/* 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; }