Commit a0e70b370afcb628caabb3e8610d600fea6966f3

Authored by Jay Berkenbilt
1 parent 1921e44c

Wiring for --set-page-labels: manual (non-bisectable commit)

This commit contains only the manual changes. It is separated for
clarity. This commit would not pass CI because it lacks the automated
changes, which appear in the next commit.
include/qpdf/QPDFJob.hh
... ... @@ -296,6 +296,23 @@ class QPDFJob
296 296 Config* config;
297 297 };
298 298  
  299 + class PageLabelsConfig {
  300 + friend class QPDFJob;
  301 + friend class Config;
  302 +
  303 + public:
  304 + QPDF_DLL
  305 + Config* endSetPageLabels();
  306 +
  307 +#include <qpdf/auto_job_c_set_page_labels.hh>
  308 +
  309 + private:
  310 + PageLabelsConfig(Config*);
  311 + PageLabelsConfig(PagesConfig const&) = delete;
  312 +
  313 + Config* config;
  314 + };
  315 +
299 316 class Config
300 317 {
301 318 friend class QPDFJob;
... ... @@ -313,6 +330,8 @@ class QPDFJob
313 330 Config* outputFile(std::string const& filename);
314 331 QPDF_DLL
315 332 Config* replaceInput();
  333 + QPDF_DLL
  334 + Config* setPageLabels(std::vector<std::string> const& specs);
316 335  
317 336 QPDF_DLL
318 337 std::shared_ptr<CopyAttConfig> copyAttachmentsFrom();
... ... @@ -675,6 +694,7 @@ class QPDFJob
675 694 bool json_output{false};
676 695 std::string update_from_json;
677 696 bool report_mem_usage{false};
  697 + std::vector<std::string> page_label_specs;
678 698 };
679 699 std::shared_ptr<Members> m;
680 700 };
... ...
... ... @@ -94,6 +94,7 @@ options:
94 94 - underlay
95 95 - empty
96 96 - replace-input
  97 + - set-page-labels
97 98 positional: true
98 99 bare:
99 100 - add-attachment
... ... @@ -134,6 +135,7 @@ options:
134 135 - report-memory-usage
135 136 - requires-password
136 137 - remove-restrictions
  138 + - set-page-labels
137 139 - show-encryption
138 140 - show-encryption-key
139 141 - show-linearization
... ... @@ -282,6 +284,9 @@ options:
282 284 required_parameter:
283 285 prefix: prefix
284 286 password: password
  287 + - table: set page labels
  288 + prefix: PageLabels
  289 + positional: true
285 290 json:
286 291 # The structure of this section defines what the json input to
287 292 # QPDFJob looks like. If a key starts with underscore, it does not
... ... @@ -437,6 +442,8 @@ json:
437 442 remove-page-labels:
438 443 report-memory-usage:
439 444 rotate:
  445 + set-page-labels:
  446 + - null
440 447 overlay:
441 448 _file: "source file for overlay"
442 449 UO.password:
... ...
libqpdf/QPDFJob_argv.cc
... ... @@ -409,6 +409,26 @@ ArgParser::argEndCopyAttachment()
409 409 }
410 410  
411 411 void
  412 +ArgParser::argSetPageLabels()
  413 +{
  414 + this->ap.selectOptionTable(O_SET_PAGE_LABELS);
  415 + accumulated_args.clear();
  416 +}
  417 +
  418 +void
  419 +ArgParser::argPageLabelsPositional(std::string const& arg)
  420 +{
  421 + accumulated_args.push_back(arg);
  422 +}
  423 +
  424 +void
  425 +ArgParser::argEndSetPageLabels()
  426 +{
  427 + c_main->setPageLabels(accumulated_args);
  428 + accumulated_args.clear();
  429 +}
  430 +
  431 +void
412 432 ArgParser::argJobJsonHelp()
413 433 {
414 434 *QPDFLogger::defaultLogger()->getInfo()
... ...
libqpdf/QPDFJob_config.cc
... ... @@ -1059,6 +1059,17 @@ QPDFJob::Config::encrypt(
1059 1059 return std::shared_ptr<EncConfig>(new EncConfig(this));
1060 1060 }
1061 1061  
  1062 +QPDFJob::Config*
  1063 +QPDFJob::Config::setPageLabels(const std::vector<std::string>& specs)
  1064 +{
  1065 + // XXX validate
  1066 + for (auto const& xxx: specs) {
  1067 + std::cout << "XXX config: spec: " << xxx << std::endl;
  1068 + }
  1069 + o.m->page_label_specs = specs;
  1070 + return this;
  1071 +}
  1072 +
1062 1073 QPDFJob::EncConfig::EncConfig(Config* c) :
1063 1074 config(c)
1064 1075 {
... ... @@ -1213,3 +1224,14 @@ QPDFJob::EncConfig::forceR5()
1213 1224 config->o.m->force_R5 = true;
1214 1225 return this;
1215 1226 }
  1227 +
  1228 +QPDFJob::PageLabelsConfig::PageLabelsConfig(Config* c) :
  1229 + config(c)
  1230 +{
  1231 +}
  1232 +
  1233 +QPDFJob::Config*
  1234 +QPDFJob::PageLabelsConfig::endSetPageLabels()
  1235 +{
  1236 + return this->config;
  1237 +}
... ...
libqpdf/QPDFJob_json.cc
... ... @@ -66,6 +66,7 @@ namespace
66 66 std::shared_ptr<QPDFJob::PagesConfig> c_pages;
67 67 std::shared_ptr<QPDFJob::UOConfig> c_uo;
68 68 std::shared_ptr<QPDFJob::EncConfig> c_enc;
  69 + std::vector<std::string> accumulated_args;
69 70 };
70 71 } // namespace
71 72  
... ... @@ -565,6 +566,26 @@ Handlers::setupUnderlayPassword()
565 566 }
566 567  
567 568 void
  569 +Handlers::setupSetPageLabels()
  570 +{
  571 + accumulated_args.clear();
  572 + addParameter([this](char const* p) { accumulated_args.push_back(p); });
  573 +}
  574 +
  575 +void
  576 +Handlers::endSetPageLabelsArray()
  577 +{
  578 + c_main->setPageLabels(accumulated_args);
  579 + accumulated_args.clear();
  580 +}
  581 +
  582 +void
  583 +Handlers::beginSetPageLabelsArray(JSON)
  584 +{
  585 + // nothing needed
  586 +}
  587 +
  588 +void
568 589 QPDFJob::initializeFromJson(std::string const& json, bool partial)
569 590 {
570 591 std::list<std::string> errors;
... ...
manual/cli.rst
... ... @@ -1748,6 +1748,116 @@ Related Options
1748 1748 Exclude page labels (explicit page numbers) from the output file.
1749 1749  
1750 1750 Exclude page labels (explicit page numbers) from the output file.
  1751 + See also :qpdf:ref:`--set-page-labels`.
  1752 +
  1753 +.. qpdf:option:: --set-page-labels label-spec ... --
  1754 +
  1755 + .. help: number pages for the entire document
  1756 +
  1757 + Set page labels (explicit page numbers) for the entire file.
  1758 + Each label-spec has the form
  1759 +
  1760 + first-page:[type][/start[/prefix]]
  1761 +
  1762 + where
  1763 +
  1764 + - "first-page" represents a sequential page number using the
  1765 + same format as page ranges: a number, a number preceded by "r"
  1766 + to indicate counting from the end, or "z" indicating the last
  1767 + page
  1768 + - "type" is one of
  1769 + - D: Arabic numerals (digits)
  1770 + - A: Upper-case alphabetic characters
  1771 + - a: Lower-case alphabetic characters
  1772 + - R: Upper-case Roman numerals
  1773 + - r: Lower-case Roman numerals
  1774 + - omitted: the page number does not appear, though the prefix,
  1775 + if specified will still appear
  1776 + - "prefix"` may be any string and is prepended to each page
  1777 + label
  1778 +
  1779 + A given page label spec causes pages to be numbered according to
  1780 + that scheme starting with first-page and continuing until the
  1781 + next label spec or the end of the document. If you want to omit
  1782 + numbering starting at a certain page, you can use first-page: as
  1783 + the spec.
  1784 +
  1785 + Example: "1:r 5:D" would number the first four pages i through
  1786 + iv, then the remaining pages with Arabic numerals starting with
  1787 + 1 and continuing sequentially until the end of the document. For
  1788 + additional examples, please consult the manual.
  1789 +
  1790 + Set page labels (explicit page numbers) for the entire file. A PDF
  1791 + file's pages can be explicitly numbered using page labels. Page
  1792 + labels in a PDF file have an optional type (Arabic numerals,
  1793 + upper/lower-case alphabetic characters, upper/lower-case Roman
  1794 + numerals), an optional prefix, and an optional starting value,
  1795 + which defaults to 1. A qpdf page label spec has the form
  1796 +
  1797 + :samp:`{first-page}:[{type}][/{start}[/{prefix}]]`
  1798 +
  1799 + where
  1800 +
  1801 + - :samp:`{first-page}` represents a sequential page number using
  1802 + the same format as page ranges (see :ref:`page-ranges`): a
  1803 + number, a number preceded by ``r`` to indicate counting from the
  1804 + end, or ``z`` indicating the last page
  1805 +
  1806 + - :samp:`{type}` may be one of
  1807 +
  1808 + - ``D``: Arabic numerals (digits)
  1809 +
  1810 + - ``A``: Upper-case alphabetic characters
  1811 +
  1812 + - ``a``: Lower-case alphabetic characters
  1813 +
  1814 + - ``R``: Upper-case Roman numerals
  1815 +
  1816 + - ``r``: Lower-case Roman numerals
  1817 +
  1818 + - omitted: the page number does not appear, though the prefix, if
  1819 + specified will still appear
  1820 +
  1821 + - :samp:`{prefix}` may be any string and is prepended to each page
  1822 + label
  1823 +
  1824 + A given page label spec causes pages to be numbered according to
  1825 + that scheme starting with :samp:`{first-page}` and continuing until
  1826 + the next label spec or the end of the document. If you want to omit
  1827 + numbering starting at a certain page, you can use
  1828 + :samp:`{first-page}:` as the spec.
  1829 +
  1830 + Here are some example page labeling schemes. First these examples,
  1831 + assume a 50-page document.
  1832 +
  1833 + - ``1:a 5:D``
  1834 +
  1835 + - The first four pages will be numbered ``a`` through ``d``, then
  1836 + the remaining pages will numbered ``1`` through ``46``.
  1837 +
  1838 + - ``1:r 5:D 12: 14:D/10 r5:D//A- z://"end note"``:
  1839 +
  1840 + - The first four pages are numbered ``i`` through ``iv``
  1841 +
  1842 + - The 5th page is numbered ``1``, and pages are numbered
  1843 + sequentially through the 11th page, which will be numbered
  1844 + ``7``
  1845 +
  1846 + - The 12th and 13th pages will not have labels
  1847 +
  1848 + - The 14th page is numbered ``10``. Pages will be numered
  1849 + sequentially up through the 45th page, which will be numbered
  1850 + ``41``
  1851 +
  1852 + - Starting with the 46th page (the fifth to last page) and going
  1853 + to the 49th page, pages will be labeled ``A-1`` through ``A-4``
  1854 +
  1855 + - The 50th page (the last page) will be labeled ``end note``.
  1856 +
  1857 + The limitations on the range of formats for page labels are as
  1858 + specified in Section 12.4.2 of the PDF spec, ISO 32000.
  1859 +
  1860 + See also :qpdf:ref:`--remove-page-labels`.
1751 1861  
1752 1862 .. _encryption-options:
1753 1863  
... ...
qpdf/sizes.cc
... ... @@ -101,6 +101,7 @@ main()
101 101 print_size(QPDFJob::EncConfig);
102 102 print_size(QPDFJob::PagesConfig);
103 103 print_size(QPDFJob::UOConfig);
  104 + print_size(QPDFJob::PageLabelsConfig);
104 105 print_size(QPDFLogger);
105 106 print_size(QPDFMatrix);
106 107 print_size(QPDFNameTreeObjectHelper);
... ...