From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- dviware/dvi2bitmap/PageRange.cc | 227 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 dviware/dvi2bitmap/PageRange.cc (limited to 'dviware/dvi2bitmap/PageRange.cc') diff --git a/dviware/dvi2bitmap/PageRange.cc b/dviware/dvi2bitmap/PageRange.cc new file mode 100644 index 0000000000..12d8f9b985 --- /dev/null +++ b/dviware/dvi2bitmap/PageRange.cc @@ -0,0 +1,227 @@ +/* This file is part of dvi2bitmap; see README for copyrights and licence */ + +#include + +#include "PageRange.h" +#include + +#ifdef HAVE_CSTD_INCLUDE +#include +#include +#else +#include +#include +#endif + +verbosities PageRange::verbosity_ = normal; + +/** + * Constructs a new PageRange object. This represents a selection of + * selected pages. When created, the PageRange object + * represents all pages, but this set can be constrained in a variety + * of ways using the {@link #addSpec} method. The resulting object + * can be queried, to ask whether a particular page would be included + * in the set, using the {@link #isSelected} method. + */ +PageRange::PageRange() + : useCounts_(true), useCountNo_(0), + first_(0), last_(0), rangeType_(unset) +{ +} + +/** + * Add a constraint to the set of selected pages represented by this + * PageRange object. The arguments are a selector, which is one of + * the characters `l', `p', or `P', and a string representing one or + * more numbers. The meanings of the three selectors are as follows. + * + *
+ *
'l' pagenum
+ *
The last page printed will be the first one num- + * bered num Default is the last page in the document. + * If the num is prefixed by an equals sign, then it + * (and any argument to the -p option) is treated as a + * sequence number, rather than a value to compare + * with \\count0 values. Thus, using -l =9 will end + * with the ninth page of the document, no matter what + * the pages are actually numbered.
+ * + *
'p' pagenum
+ *
The first page printed will be the first one num- + * bered num. Default is the first page in the docu- + * ment. If the num is prefixed by an equals sign, + * then it (and any argument to the -l option) is + * treated as a sequence number, rather than a value + * to compare with \\count0 values. Thus, using -p =3 + * will start with the third page of the document, no + * matter what the pages are actually numbered.
+ * + *
'P' pagelist
+ *
A comma-separated list of pages and ranges (a-b) + * may be given, which will be interpreted as \\count0 + * values. Pages not specified will not be printed. + * Multiple -pp options may be specified or all pages + * and page ranges can be specified with one -pp + * option.
+ *
+ * + *

Any of these specifications may be prefixed by either + * = or :n: + * In the former case, DVI page numbers are used rather than TeX + * \\count registers; in the latter case, the program examines the + * \\countn register rather than the default \\count0 + * + *

Thus, the syntax of pagelist is extended to satisfy: + *

+ *    pagenum:  prefix* number
+ *    pagelist: prefix* page-or-range [',' page-or-range]*
+ *    prefix: '=' | ':' number ':'
+ *    page-or-range: number | number-number
+ * 
+ * + * @param type one of the letters `l', `p', `P'. + * @param spec a page specification conforming to the grammar above + */ +bool PageRange::addSpec (const char type, const char *spec) +{ + bool parseOK = true; + + // prefix* + for (bool readPrefix = true; readPrefix; ) + switch (*spec) + { + case '=': + useCounts_ = false; + spec++; + break; + case ':': + { + spec++; + char *endp; + int countnum = static_cast(STD::strtol (spec, &endp, 10)); + spec = endp; + if (*spec != ':') + { + parseOK = false; + readPrefix = false; + } + else + { + if (countnum < 0 || countnum > 9) parseOK = false; + useCountNo_ = countnum; + spec++; + } + break; + } + default: + readPrefix = false; + } + // now have spec pointing at first page-or-range or pagenum + + switch (type) + { + case 'p': + if (rangeType_ == ranges) + { + if (verbosity_ >= normal) + std::cerr << "Inconsistent range specs\n"; + parseOK = false; + } + else + { + first_ = STD::atoi (spec); + rangeType_ = oneRange; + } + break; + + case 'P': + { + if (rangeType_ == oneRange) + parseOK = false; + else + rangeType_ = ranges; + + char *endp; + int p1=0, p2; + endp = const_cast(spec); + char lastsep = ','; + while (*endp != '\0' && parseOK) + { + p2 = static_cast(STD::strtol (spec, &endp, 10)); + if (endp == spec) // no digits found + { + parseOK = false; + continue; + } + + switch (lastsep) + { + case ',': // single page or start of range + setPages_[p2] = true; + p1 = p2; + break; + case '-': // end of range + if (p1 > p2) + parseOK = false; + else + for (int i=p1; i<=p2; i++) + setPages_[i] = true; + break; + default: + parseOK = false; + break; + } + lastsep = *endp; + spec = endp+1; + // now have endp pointing at a separator or \0, + // spec at next char + } + } + break; + + case 'l': + if (rangeType_ == ranges) + { + if (verbosity_ >= normal) + std::cerr << "Inconsistent range specs\n"; + parseOK = false; + } + else + { + last_ = STD::atoi (spec); + rangeType_ = oneRange; + } + break; + + default: + parseOK = false; + } + + return parseOK; +} + +/** + * Returns true if the specified page is to be included. We test + * either the page-sequence number or the TeX \\count0-9 + * registers, depending on how the page range was specified. + * + * @param pagenum a page-sequence number, counting pages from the + * beginning of the DVI file + * @param count is the array of TeX \\count0-9 register + * @return true if the current settings of this PageRange object + * would indicate that the specified page is to be printed + */ +bool PageRange::isSelected (const int pagenum, const int* count) +{ + bool rval; + if (rangeType_ == unset) + return true; + + int testval = (useCounts_ ? count[useCountNo_] : pagenum); + if (rangeType_ == oneRange) + rval = testval >= first_ && (last_ == 0 || testval <= last_); + else + rval = setPages_[testval]; + + return rval; +} -- cgit v1.2.3