aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/qpdf/QPDFJob.hh20
-rw-r--r--job.yml7
-rw-r--r--libqpdf/QPDFJob_argv.cc20
-rw-r--r--libqpdf/QPDFJob_config.cc22
-rw-r--r--libqpdf/QPDFJob_json.cc21
-rw-r--r--manual/cli.rst110
-rw-r--r--qpdf/sizes.cc1
7 files changed, 201 insertions, 0 deletions
diff --git a/include/qpdf/QPDFJob.hh b/include/qpdf/QPDFJob.hh
index 01fe35ae..9a7afb0f 100644
--- a/include/qpdf/QPDFJob.hh
+++ b/include/qpdf/QPDFJob.hh
@@ -296,6 +296,23 @@ class QPDFJob
Config* config;
};
+ class PageLabelsConfig {
+ friend class QPDFJob;
+ friend class Config;
+
+ public:
+ QPDF_DLL
+ Config* endSetPageLabels();
+
+#include <qpdf/auto_job_c_set_page_labels.hh>
+
+ private:
+ PageLabelsConfig(Config*);
+ PageLabelsConfig(PagesConfig const&) = delete;
+
+ Config* config;
+ };
+
class Config
{
friend class QPDFJob;
@@ -313,6 +330,8 @@ class QPDFJob
Config* outputFile(std::string const& filename);
QPDF_DLL
Config* replaceInput();
+ QPDF_DLL
+ Config* setPageLabels(std::vector<std::string> const& specs);
QPDF_DLL
std::shared_ptr<CopyAttConfig> copyAttachmentsFrom();
@@ -675,6 +694,7 @@ class QPDFJob
bool json_output{false};
std::string update_from_json;
bool report_mem_usage{false};
+ std::vector<std::string> page_label_specs;
};
std::shared_ptr<Members> m;
};
diff --git a/job.yml b/job.yml
index d342e7a2..3d918385 100644
--- a/job.yml
+++ b/job.yml
@@ -94,6 +94,7 @@ options:
- underlay
- empty
- replace-input
+ - set-page-labels
positional: true
bare:
- add-attachment
@@ -134,6 +135,7 @@ options:
- report-memory-usage
- requires-password
- remove-restrictions
+ - set-page-labels
- show-encryption
- show-encryption-key
- show-linearization
@@ -282,6 +284,9 @@ options:
required_parameter:
prefix: prefix
password: password
+ - table: set page labels
+ prefix: PageLabels
+ positional: true
json:
# The structure of this section defines what the json input to
# QPDFJob looks like. If a key starts with underscore, it does not
@@ -437,6 +442,8 @@ json:
remove-page-labels:
report-memory-usage:
rotate:
+ set-page-labels:
+ - null
overlay:
_file: "source file for overlay"
UO.password:
diff --git a/libqpdf/QPDFJob_argv.cc b/libqpdf/QPDFJob_argv.cc
index eadf9a33..737059f0 100644
--- a/libqpdf/QPDFJob_argv.cc
+++ b/libqpdf/QPDFJob_argv.cc
@@ -409,6 +409,26 @@ ArgParser::argEndCopyAttachment()
}
void
+ArgParser::argSetPageLabels()
+{
+ this->ap.selectOptionTable(O_SET_PAGE_LABELS);
+ accumulated_args.clear();
+}
+
+void
+ArgParser::argPageLabelsPositional(std::string const& arg)
+{
+ accumulated_args.push_back(arg);
+}
+
+void
+ArgParser::argEndSetPageLabels()
+{
+ c_main->setPageLabels(accumulated_args);
+ accumulated_args.clear();
+}
+
+void
ArgParser::argJobJsonHelp()
{
*QPDFLogger::defaultLogger()->getInfo()
diff --git a/libqpdf/QPDFJob_config.cc b/libqpdf/QPDFJob_config.cc
index a0dc10f6..9651c3b9 100644
--- a/libqpdf/QPDFJob_config.cc
+++ b/libqpdf/QPDFJob_config.cc
@@ -1059,6 +1059,17 @@ QPDFJob::Config::encrypt(
return std::shared_ptr<EncConfig>(new EncConfig(this));
}
+QPDFJob::Config*
+QPDFJob::Config::setPageLabels(const std::vector<std::string>& specs)
+{
+ // XXX validate
+ for (auto const& xxx: specs) {
+ std::cout << "XXX config: spec: " << xxx << std::endl;
+ }
+ o.m->page_label_specs = specs;
+ return this;
+}
+
QPDFJob::EncConfig::EncConfig(Config* c) :
config(c)
{
@@ -1213,3 +1224,14 @@ QPDFJob::EncConfig::forceR5()
config->o.m->force_R5 = true;
return this;
}
+
+QPDFJob::PageLabelsConfig::PageLabelsConfig(Config* c) :
+ config(c)
+{
+}
+
+QPDFJob::Config*
+QPDFJob::PageLabelsConfig::endSetPageLabels()
+{
+ return this->config;
+}
diff --git a/libqpdf/QPDFJob_json.cc b/libqpdf/QPDFJob_json.cc
index d44652f4..754cb81b 100644
--- a/libqpdf/QPDFJob_json.cc
+++ b/libqpdf/QPDFJob_json.cc
@@ -66,6 +66,7 @@ namespace
std::shared_ptr<QPDFJob::PagesConfig> c_pages;
std::shared_ptr<QPDFJob::UOConfig> c_uo;
std::shared_ptr<QPDFJob::EncConfig> c_enc;
+ std::vector<std::string> accumulated_args;
};
} // namespace
@@ -565,6 +566,26 @@ Handlers::setupUnderlayPassword()
}
void
+Handlers::setupSetPageLabels()
+{
+ accumulated_args.clear();
+ addParameter([this](char const* p) { accumulated_args.push_back(p); });
+}
+
+void
+Handlers::endSetPageLabelsArray()
+{
+ c_main->setPageLabels(accumulated_args);
+ accumulated_args.clear();
+}
+
+void
+Handlers::beginSetPageLabelsArray(JSON)
+{
+ // nothing needed
+}
+
+void
QPDFJob::initializeFromJson(std::string const& json, bool partial)
{
std::list<std::string> errors;
diff --git a/manual/cli.rst b/manual/cli.rst
index 1d530641..6495829f 100644
--- a/manual/cli.rst
+++ b/manual/cli.rst
@@ -1748,6 +1748,116 @@ Related Options
Exclude page labels (explicit page numbers) from the output file.
Exclude page labels (explicit page numbers) from the output file.
+ See also :qpdf:ref:`--set-page-labels`.
+
+.. qpdf:option:: --set-page-labels label-spec ... --
+
+ .. help: number pages for the entire document
+
+ Set page labels (explicit page numbers) for the entire file.
+ Each label-spec has the form
+
+ first-page:[type][/start[/prefix]]
+
+ where
+
+ - "first-page" represents a sequential page number using the
+ same format as page ranges: a number, a number preceded by "r"
+ to indicate counting from the end, or "z" indicating the last
+ page
+ - "type" is one of
+ - D: Arabic numerals (digits)
+ - A: Upper-case alphabetic characters
+ - a: Lower-case alphabetic characters
+ - R: Upper-case Roman numerals
+ - r: Lower-case Roman numerals
+ - omitted: the page number does not appear, though the prefix,
+ if specified will still appear
+ - "prefix"` may be any string and is prepended to each page
+ label
+
+ A given page label spec causes pages to be numbered according to
+ that scheme starting with first-page and continuing until the
+ next label spec or the end of the document. If you want to omit
+ numbering starting at a certain page, you can use first-page: as
+ the spec.
+
+ Example: "1:r 5:D" would number the first four pages i through
+ iv, then the remaining pages with Arabic numerals starting with
+ 1 and continuing sequentially until the end of the document. For
+ additional examples, please consult the manual.
+
+ Set page labels (explicit page numbers) for the entire file. A PDF
+ file's pages can be explicitly numbered using page labels. Page
+ labels in a PDF file have an optional type (Arabic numerals,
+ upper/lower-case alphabetic characters, upper/lower-case Roman
+ numerals), an optional prefix, and an optional starting value,
+ which defaults to 1. A qpdf page label spec has the form
+
+ :samp:`{first-page}:[{type}][/{start}[/{prefix}]]`
+
+ where
+
+ - :samp:`{first-page}` represents a sequential page number using
+ the same format as page ranges (see :ref:`page-ranges`): a
+ number, a number preceded by ``r`` to indicate counting from the
+ end, or ``z`` indicating the last page
+
+ - :samp:`{type}` may be one of
+
+ - ``D``: Arabic numerals (digits)
+
+ - ``A``: Upper-case alphabetic characters
+
+ - ``a``: Lower-case alphabetic characters
+
+ - ``R``: Upper-case Roman numerals
+
+ - ``r``: Lower-case Roman numerals
+
+ - omitted: the page number does not appear, though the prefix, if
+ specified will still appear
+
+ - :samp:`{prefix}` may be any string and is prepended to each page
+ label
+
+ A given page label spec causes pages to be numbered according to
+ that scheme starting with :samp:`{first-page}` and continuing until
+ the next label spec or the end of the document. If you want to omit
+ numbering starting at a certain page, you can use
+ :samp:`{first-page}:` as the spec.
+
+ Here are some example page labeling schemes. First these examples,
+ assume a 50-page document.
+
+ - ``1:a 5:D``
+
+ - The first four pages will be numbered ``a`` through ``d``, then
+ the remaining pages will numbered ``1`` through ``46``.
+
+ - ``1:r 5:D 12: 14:D/10 r5:D//A- z://"end note"``:
+
+ - The first four pages are numbered ``i`` through ``iv``
+
+ - The 5th page is numbered ``1``, and pages are numbered
+ sequentially through the 11th page, which will be numbered
+ ``7``
+
+ - The 12th and 13th pages will not have labels
+
+ - The 14th page is numbered ``10``. Pages will be numered
+ sequentially up through the 45th page, which will be numbered
+ ``41``
+
+ - Starting with the 46th page (the fifth to last page) and going
+ to the 49th page, pages will be labeled ``A-1`` through ``A-4``
+
+ - The 50th page (the last page) will be labeled ``end note``.
+
+ The limitations on the range of formats for page labels are as
+ specified in Section 12.4.2 of the PDF spec, ISO 32000.
+
+ See also :qpdf:ref:`--remove-page-labels`.
.. _encryption-options:
diff --git a/qpdf/sizes.cc b/qpdf/sizes.cc
index cbec5cd5..65121872 100644
--- a/qpdf/sizes.cc
+++ b/qpdf/sizes.cc
@@ -101,6 +101,7 @@ main()
print_size(QPDFJob::EncConfig);
print_size(QPDFJob::PagesConfig);
print_size(QPDFJob::UOConfig);
+ print_size(QPDFJob::PageLabelsConfig);
print_size(QPDFLogger);
print_size(QPDFMatrix);
print_size(QPDFNameTreeObjectHelper);