1<!-- 2 PPD API introduction for CUPS. 3 4 Copyright 2007-2018 by Apple Inc. 5 Copyright 1997-2006 by Easy Software Products, all rights reserved. 6 7 These coded instructions, statements, and computer programs are the 8 property of Apple Inc. and are protected by Federal copyright 9 law. Distribution and use rights are outlined in the file "LICENSE.txt" 10 which should have been included with this file. If this file is 11 file is missing or damaged, see the license at "http://www.cups.org/". 12--> 13 14<h2 class='title'><a name='OVERVIEW'>Overview</a></h2> 15 16<blockquote>The PPD API is deprecated starting in CUPS 1.6/macOS 10.8. Please use the new Job Ticket APIs in the <a href="cupspm.html">CUPS API</a> documentation. These functions will be removed in a future release of CUPS.</blockquote> 17 18<p>The CUPS PPD API provides read-only access the data in PostScript Printer 19Description ("PPD") files which are used for all printers with a driver. With 20it you can obtain the data necessary to display printer options to users, mark 21option choices and check for conflicting choices, and output marked choices in 22PostScript output. The <a href="#ppd_file_t"><code>ppd_file_t</code></a> 23structure contains all of the information in a PPD file.</p> 24 25<blockquote><b>Note:</b> 26 27<p>The CUPS PPD API uses the terms "option" and "choice" instead of the Adobe 28terms "MainKeyword" and "OptionKeyword" to refer to specific printer options and 29features. CUPS also treats option ("MainKeyword") and choice ("OptionKeyword") 30values as case-insensitive strings, so option "InputSlot" and choice "Upper" 31are equivalent to "inputslot" and "upper", respectively.</p> 32</blockquote> 33 34<h3><a name="LOADING">Loading a PPD File</a></h3> 35 36<p>The <a href="#ppdOpenFile"><code>ppdOpenFile</code></a> function "opens" a 37PPD file and loads it into memory. For example, the following code opens the 38current printer's PPD file in a CUPS filter:</p> 39 40<pre class="example"> 41#include <cups/ppd.h> 42 43<a href="#ppd_file_t">ppd_file_t</a> *ppd = <a href="#ppdOpenFile">ppdOpenFile</a>(getenv("PPD")); 44</pre> 45 46<p>The return value is a pointer to a new 47<a href="#ppd_file_t"><code>ppd_file_t</code></a> structure or <code>NULL</code> 48if the PPD file does not exist or cannot be loaded. The 49<a href="#ppdClose"><code>ppdClose</code></a> function frees the memory used 50by the structure:</p> 51 52<pre class="example"> 53#include <cups/ppd.h> 54 55<a href="#ppd_file_t">ppd_file_t</a> *ppd; 56 57<a href="#ppdClose">ppdClose</a>(ppd); 58</pre> 59 60<p>Once closed, pointers to the <a href="#ppd_file_t"><code>ppd_file_t</code></a> 61structure and any data in it will no longer be valid.</p> 62 63<h3><a name="OPTIONS_AND_GROUPS">Options and Groups</a></h3> 64 65<p>PPD files support multiple options, which are stored in arrays of 66<a href="#ppd_option_t"><code>ppd_option_t</code></a> and 67<a href="#ppd_choice_t"><code>ppd_choice_t</code></a> structures.</p> 68 69<p>Each option in turn is associated with a group stored in a 70<a href="#ppd_group_t"><code>ppd_group_t</code></a> structure. Groups can be 71specified in the PPD file; if an option is not associated with a group 72then it is put in an automatically-generated "General" group. Groups can also 73have sub-groups, however CUPS currently ignores sub-groups because of past 74abuses of this functionality.</p> 75 76<p>Option choices are selected by marking them using one of three functions. The 77first is <a href="#ppdMarkDefaults"><code>ppdMarkDefaults</code></a> which 78selects all of the default options in the PPD file:</p> 79 80<pre class="example"> 81#include <cups/ppd.h> 82 83<a href="#ppd_file_t">ppd_file_t</a> *ppd; 84 85<a href="#ppdMarkDefaults">ppdMarkDefaults</a>(ppd); 86</pre> 87 88<p>The second is <a href="#ppdMarkOption"><code>ppdMarkOption</code></a> 89which selects a single option choice in the PPD file. For example, the following 90code selects the upper paper tray:</p> 91 92<pre class="example"> 93#include <cups/ppd.h> 94 95<a href="#ppd_file_t">ppd_file_t</a> *ppd; 96 97<a href="#ppdMarkOption">ppdMarkOption</a>(ppd, "InputSlot", "Upper"); 98</pre> 99 100<p>The last function is 101<a href="#cupsMarkOptions"><code>cupsMarkOptions</code></a> which selects 102multiple option choices in the PPD file from an array of CUPS options, mapping 103IPP attributes like "media" and "sides" to their corresponding PPD options. You 104typically use this function in a print filter with 105<code>cupsParseOptions</code> and 106<a href="#ppdMarkDefaults"><code>ppdMarkDefaults</code></a> to select all of 107the option choices needed for the job, for example:</p> 108 109<pre class="example"> 110#include <cups/ppd.h> 111 112<a href="#ppd_file_t">ppd_file_t</a> *ppd = <a href="#ppdOpenFile">ppdOpenFile</a>(getenv("PPD")); 113cups_option_t *options = NULL; 114int num_options = cupsParseOptions(argv[5], 0, &options); 115 116<a href="#ppdMarkDefaults">ppdMarkDefaults</a>(ppd); 117<a href="#cupsMarkOptions">cupsMarkOptions</a>(ppd, num_options, options); 118cupsFreeOptions(num_options, options); 119</pre> 120 121<h3><a name="CONSTRAINTS">Constraints</a></h3> 122 123<p>PPD files support specification of conflict conditions, called 124constraints, between different options. Constraints are stored in an array of 125<a href="#ppd_const_t"><code>ppd_const_t</code></a> structures which specify 126the options and choices that conflict with each other. The 127<a href="#ppdConflicts"><code>ppdConflicts</code></a> function tells you 128how many of the selected options are incompatible. Since constraints are 129normally specified in pairs, the returned value is typically an even number.</p> 130 131<h3><a name="PAGE_SIZES">Page Sizes</a></h3> 132 133<p>Page sizes are special options which have physical dimensions and margins 134associated with them. The size information is stored in 135<a href="#ppd_size_t"><code>ppd_size_t</code></a> structures and is available 136by looking up the named size with the 137<a href="#ppdPageSize"><code>ppdPageSize</code></a> function. The page size and 138margins are returned in units called points; there are 72 points per inch. If 139you pass <code>NULL</code> for the size, the currently selected size is 140returned:</p> 141 142<pre class="example"> 143#include <cups/ppd.h> 144 145<a href="#ppd_file_t">ppd_file_t</a> *ppd; 146<a href="#ppd_size_t">ppd_size_t</a> *size = <a href="#ppdPageSize">ppdPageSize</a>(ppd, NULL); 147</pre> 148 149<p>Besides the standard page sizes listed in a PPD file, some printers 150support variable or custom page sizes. Custom page sizes are supported if the 151<code>variables_sizes</code> member of the 152<a href="#ppd_file_t"><code>ppd_file_t</code></a> structure is non-zero. 153The <code>custom_min</code>, <code>custom_max</code>, and 154<code>custom_margins</code> members of the 155<a href="#ppd_file_t"><code>ppd_file_t</code></a> structure define the limits 156of the printable area. To get the resulting media size, use a page size string 157of the form "Custom.<I>width</I>x<I>length</I>", where "width" and "length" are 158in points. Custom page size names can also be specified in inches 159("Custom.<i>width</i>x<i>height</i>in"), centimeters 160("Custom.<i>width</i>x<i>height</i>cm"), or millimeters 161("Custom.<i>width</i>x<i>height</i>mm"):</p> 162 163<pre class="example"> 164#include <cups/ppd.h> 165 166<a href="#ppd_file_t">ppd_file_t</a> *ppd; 167 168/* Get an 576x720 point custom page size */ 169<a href="#ppd_size_t">ppd_size_t</a> *size = <a href="#ppdPageSize">ppdPageSize</a>(ppd, "Custom.576x720"); 170 171/* Get an 8x10 inch custom page size */ 172<a href="#ppd_size_t">ppd_size_t</a> *size = <a href="#ppdPageSize">ppdPageSize</a>(ppd, "Custom.8x10in"); 173 174/* Get a 100x200 millimeter custom page size */ 175<a href="#ppd_size_t">ppd_size_t</a> *size = <a href="#ppdPageSize">ppdPageSize</a>(ppd, "Custom.100x200mm"); 176 177/* Get a 12.7x34.5 centimeter custom page size */ 178<a href="#ppd_size_t">ppd_size_t</a> *size = <a href="#ppdPageSize">ppdPageSize</a>(ppd, "Custom.12.7x34.5cm"); 179</pre> 180 181<p>If the PPD does not support variable page sizes, the 182<a href="#ppdPageSize"><code>ppdPageSize</code></a> function will return 183<code>NULL</code>.</p> 184 185<h3><a name="ATTRIBUTES">Attributes</a></h3> 186 187<p>Every PPD file is composed of one or more attributes. Most of these 188attributes are used to define groups, options, choices, and page sizes, 189however several informational attributes may be present which you can access 190in your program or filter. Attributes normally look like one of the following 191examples in a PPD file:</p> 192 193<pre class="example"> 194*name: "value" 195*name spec: "value" 196*name spec/text: "value" 197</pre> 198 199<p>The <a href="#ppdFindAttr"><code>ppdFindAttr</code></a> and 200<a href="#ppdFindNextAttr"><code>ppdFindNextAttr</code></a> functions find the 201first and next instances, respectively, of the named attribute with the given 202"spec" string and return a <a href="#ppd_attr_t"><code>ppd_attr_t</code></a> 203structure. If you provide a NULL specifier string, all attributes with the 204given name will be returned. For example, the following code lists all of the 205<code>Product</code> attributes in a PPD file:</p> 206 207<pre class="example"> 208#include <cups/ppd.h> 209 210<a href="#ppd_file_t">ppd_file_t</a> *ppd; 211<a href="#ppd_attr_t">ppd_attr_t</a> *attr; 212 213for (attr = <a href="#ppdFindAttr">ppdFindAttr</a>(ppd, "Product", NULL); 214 attr != NULL; 215 attr = <a href="#ppdFindNextAttr">ppdFindNextAttr</a>(ppd, "Product", NULL)) 216 puts(attr->value); 217</pre> 218