1 /* pagesel.c -- Page selection mechanism */
3 * Copyright (C) 2000, Matias Atria
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 char *program_name = "page";
35 DviRange *mdvi_parse_range(const char *format, DviRange *limit, int *nitems, char **endptr)
50 quoted = (*format == '{');
56 copy = mdvi_strdup(format);
60 type = MDVI_RANGE_UNBOUNDED;
64 case MDVI_RANGE_BOUNDED:
68 case MDVI_RANGE_UPPER:
72 case MDVI_RANGE_LOWER:
76 case MDVI_RANGE_UNBOUNDED:
85 type = MDVI_RANGE_UNBOUNDED;
91 for(cp = text = copy; !done; cp++) {
99 if(*cp == 0 || *cp == '.' || (*cp == '}' && quoted))
112 p = strchr(text, ':');
116 f = strtol(text, NULL, 0);
126 p = strchr(text, ':');
130 t = strtol(text, NULL, 0);
136 s = strtol(text, NULL, 0);
138 if(lower_given && upper_given)
139 this_type = MDVI_RANGE_BOUNDED;
140 else if(lower_given) {
141 if(!RANGE_HAS_UPPER(type))
142 this_type = MDVI_RANGE_LOWER;
144 this_type = MDVI_RANGE_BOUNDED;
146 } else if(upper_given) {
147 if(RANGE_HAS_UPPER(one.type)) {
149 this_type = MDVI_RANGE_BOUNDED;
152 if(!RANGE_HAS_LOWER(type))
153 this_type = MDVI_RANGE_UPPER;
155 this_type = MDVI_RANGE_BOUNDED;
163 one.type = this_type;
170 range = mdvi_realloc(range, size * sizeof(DviRange));
172 memcpy(&range[curr++], &one, sizeof(DviRange));
178 if(quoted && *cp == '}')
181 *endptr = (char *)format + (cp - copy);
182 if(curr && curr < size)
183 range = mdvi_realloc(range, curr * sizeof(DviRange));
189 DviPageSpec *mdvi_parse_page_spec(const char *format)
192 * a page specification looks like this:
193 * '{'RANGE_SPEC'}' for a DVI spec
194 * '{'RANGE_SPEC'}' '.' ... for a TeX spec
202 spec = xnalloc(struct _DviPageSpec *, 11);
203 for(i = 0; i < 11; i++)
206 /* check what kind of spec we're parsing */
208 range = mdvi_parse_range(format, NULL, &count, &ptr);
210 if(range) mdvi_free(range);
211 error(_("invalid page specification `%s'\n"), format);
217 if(*format == 'D' || *format == 'd' || *ptr != '.')
223 spec[i] = xalloc(struct _DviPageSpec);
224 spec[i]->ranges = range;
225 spec[i]->nranges = count;
231 warning(_("garbage after DVI page specification ignored\n"));
235 for(i++; *ptr == '.' && i <= 10; i++) {
243 range = mdvi_parse_range(ptr, NULL, &count, &end);
245 if(range) mdvi_free(range);
251 spec[i] = xalloc(struct _DviPageSpec);
252 spec[i]->ranges = range;
253 spec[i]->nranges = count;
259 warning(_("more than 10 counters in page specification\n"));
261 warning(_("garbage after TeX page specification ignored\n"));
266 /* returns non-zero if the given page is included by `spec' */
267 int mdvi_page_selected(DviPageSpec *spec, PageNum page, int dvipage)
275 not_found = mdvi_in_range(spec[0]->ranges,
276 spec[0]->nranges, dvipage);
280 for(i = 1; i <= 10; i++) {
283 not_found = mdvi_in_range(spec[i]->ranges,
284 spec[i]->nranges, (int)page[i]);
291 void mdvi_free_page_spec(DviPageSpec *spec)
295 for(i = 0; i < 11; i++)
297 mdvi_free(spec[i]->ranges);
303 int mdvi_in_range(DviRange *range, int nitems, int value)
307 for(r = range; r < range + nitems; r++) {
311 case MDVI_RANGE_BOUNDED:
315 cond = (value <= r->from) && (value >= r->to);
317 cond = (value <= r->to) && (value >= r->from);
318 if(cond && ((value - r->from) % r->step) == 0)
321 case MDVI_RANGE_LOWER:
325 cond = (value < r->from);
327 cond = (value > r->from);
328 if(cond && ((value - r->from) % r->step) == 0)
331 case MDVI_RANGE_UPPER:
335 cond = (value > r->to);
337 cond = (value < r->to);
338 if(cond && ((value - r->to) % r->step) == 0)
341 case MDVI_RANGE_UNBOUNDED:
342 if((value % r->step) == 0)
350 int mdvi_range_length(DviRange *range, int nitems)
355 for(r = range; r < range + nitems; r++) {
358 if(r->type != MDVI_RANGE_BOUNDED)
360 n = (r->to - r->from) / r->step;
370 void print_range(DviRange *range)
372 switch(range->type) {
373 case MDVI_RANGE_BOUNDED:
374 printf("From %d to %d, step %d\n",
375 range->from, range->to, range->step);
377 case MDVI_RANGE_LOWER:
378 printf("From %d, step %d\n",
379 range->from, range->step);
381 case MDVI_RANGE_UPPER:
382 printf("From %d, step -%d\n",
383 range->to, range->step);
385 case MDVI_RANGE_UNBOUNDED:
386 printf("From 0, step %d and %d\n",
387 range->step, -range->step);
401 limit.type = MDVI_RANGE_UNBOUNDED;
408 printf("Range> "); fflush(stdout);
409 if(fgets(buf, 256, stdin) == NULL)
411 if(buf[strlen(buf)-1] == '\n')
412 buf[strlen(buf)-1] = 0;
416 range = mdvi_parse_range(buf, &limit, &count, &end);
418 printf("range is empty\n");
422 for(i = 0; i < count; i++) {
423 printf("Range %d (%d elements):\n",
424 i, mdvi_range_length(&range[i], 1));
425 print_range(&range[i]);
428 printf("Tail: [%s]\n", end);
429 printf("range has %d elements\n",
430 mdvi_range_length(range, count));
435 printf("Value: "); fflush(stdout);
436 if(fgets(buf, 256, stdin) == NULL)
438 if(buf[strlen(buf)-1] == '\n')
439 buf[strlen(buf)-1] = 0;
443 i = mdvi_in_range(range, count, v);
445 printf("%d not in range\n", v);
447 printf("%d in range: ", v);
448 print_range(&range[i]);
452 if(range) mdvi_free(range);
459 printf("Spec> "); fflush(stdout);
460 if(fgets(buf, 256, stdin) == NULL)
462 if(buf[strlen(buf)-1] == '\n')
463 buf[strlen(buf)-1] = 0;
466 spec = mdvi_parse_page_spec(buf);
468 printf("no spec parsed\n");
473 for(i = 0; i < 11; i++) {
474 printf("Counter %d:\n", i);
478 for(k = 0; k < spec[i]->nranges; k++)
479 print_range(&spec[i]->ranges[k]);
483 mdvi_free_page_spec(spec);