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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 char *program_name = "page";
36 DviRange *mdvi_parse_range(const char *format, DviRange *limit, int *nitems, char **endptr)
51 quoted = (*format == '{');
57 copy = mdvi_strdup(format);
61 type = MDVI_RANGE_UNBOUNDED;
65 case MDVI_RANGE_BOUNDED:
69 case MDVI_RANGE_UPPER:
73 case MDVI_RANGE_LOWER:
77 case MDVI_RANGE_UNBOUNDED:
86 type = MDVI_RANGE_UNBOUNDED;
92 for(cp = text = copy; !done; cp++) {
100 if(*cp == 0 || *cp == '.' || (*cp == '}' && quoted))
113 p = strchr(text, ':');
117 f = strtol(text, NULL, 0);
127 p = strchr(text, ':');
131 t = strtol(text, NULL, 0);
137 s = strtol(text, NULL, 0);
139 if(lower_given && upper_given)
140 this_type = MDVI_RANGE_BOUNDED;
141 else if(lower_given) {
142 if(!RANGE_HAS_UPPER(type))
143 this_type = MDVI_RANGE_LOWER;
145 this_type = MDVI_RANGE_BOUNDED;
147 } else if(upper_given) {
148 if(RANGE_HAS_UPPER(one.type)) {
150 this_type = MDVI_RANGE_BOUNDED;
153 if(!RANGE_HAS_LOWER(type))
154 this_type = MDVI_RANGE_UPPER;
156 this_type = MDVI_RANGE_BOUNDED;
164 one.type = this_type;
171 range = mdvi_realloc(range, size * sizeof(DviRange));
173 memcpy(&range[curr++], &one, sizeof(DviRange));
179 if(quoted && *cp == '}')
182 *endptr = (char *)format + (cp - copy);
183 if(curr && curr < size)
184 range = mdvi_realloc(range, curr * sizeof(DviRange));
190 DviPageSpec *mdvi_parse_page_spec(const char *format)
193 * a page specification looks like this:
194 * '{'RANGE_SPEC'}' for a DVI spec
195 * '{'RANGE_SPEC'}' '.' ... for a TeX spec
203 spec = xnalloc(struct _DviPageSpec *, 11);
204 for(i = 0; i < 11; i++)
207 /* check what kind of spec we're parsing */
209 range = mdvi_parse_range(format, NULL, &count, &ptr);
211 if(range) mdvi_free(range);
212 mdvi_error(_("invalid page specification `%s'\n"), format);
218 if(*format == 'D' || *format == 'd' || *ptr != '.')
224 spec[i] = xalloc(struct _DviPageSpec);
225 spec[i]->ranges = range;
226 spec[i]->nranges = count;
232 mdvi_warning(_("garbage after DVI page specification ignored\n"));
236 for(i++; *ptr == '.' && i <= 10; i++) {
244 range = mdvi_parse_range(ptr, NULL, &count, &end);
246 if(range) mdvi_free(range);
252 spec[i] = xalloc(struct _DviPageSpec);
253 spec[i]->ranges = range;
254 spec[i]->nranges = count;
260 mdvi_warning(_("more than 10 counters in page specification\n"));
262 mdvi_warning(_("garbage after TeX page specification ignored\n"));
267 /* returns non-zero if the given page is included by `spec' */
268 int mdvi_page_selected(DviPageSpec *spec, PageNum page, int dvipage)
276 not_found = mdvi_in_range(spec[0]->ranges,
277 spec[0]->nranges, dvipage);
281 for(i = 1; i <= 10; i++) {
284 not_found = mdvi_in_range(spec[i]->ranges,
285 spec[i]->nranges, (int)page[i]);
292 void mdvi_free_page_spec(DviPageSpec *spec)
296 for(i = 0; i < 11; i++)
298 mdvi_free(spec[i]->ranges);
304 int mdvi_in_range(DviRange *range, int nitems, int value)
308 for(r = range; r < range + nitems; r++) {
312 case MDVI_RANGE_BOUNDED:
316 cond = (value <= r->from) && (value >= r->to);
318 cond = (value <= r->to) && (value >= r->from);
319 if(cond && ((value - r->from) % r->step) == 0)
322 case MDVI_RANGE_LOWER:
326 cond = (value < r->from);
328 cond = (value > r->from);
329 if(cond && ((value - r->from) % r->step) == 0)
332 case MDVI_RANGE_UPPER:
336 cond = (value > r->to);
338 cond = (value < r->to);
339 if(cond && ((value - r->to) % r->step) == 0)
342 case MDVI_RANGE_UNBOUNDED:
343 if((value % r->step) == 0)
351 int mdvi_range_length(DviRange *range, int nitems)
356 for(r = range; r < range + nitems; r++) {
359 if(r->type != MDVI_RANGE_BOUNDED)
361 n = (r->to - r->from) / r->step;
371 void print_range(DviRange *range)
373 switch(range->type) {
374 case MDVI_RANGE_BOUNDED:
375 printf("From %d to %d, step %d\n",
376 range->from, range->to, range->step);
378 case MDVI_RANGE_LOWER:
379 printf("From %d, step %d\n",
380 range->from, range->step);
382 case MDVI_RANGE_UPPER:
383 printf("From %d, step -%d\n",
384 range->to, range->step);
386 case MDVI_RANGE_UNBOUNDED:
387 printf("From 0, step %d and %d\n",
388 range->step, -range->step);
402 limit.type = MDVI_RANGE_UNBOUNDED;
409 printf("Range> "); fflush(stdout);
410 if(fgets(buf, 256, stdin) == NULL)
412 if(buf[strlen(buf)-1] == '\n')
413 buf[strlen(buf)-1] = 0;
417 range = mdvi_parse_range(buf, &limit, &count, &end);
419 printf("range is empty\n");
423 for(i = 0; i < count; i++) {
424 printf("Range %d (%d elements):\n",
425 i, mdvi_range_length(&range[i], 1));
426 print_range(&range[i]);
429 printf("Tail: [%s]\n", end);
430 printf("range has %d elements\n",
431 mdvi_range_length(range, count));
436 printf("Value: "); fflush(stdout);
437 if(fgets(buf, 256, stdin) == NULL)
439 if(buf[strlen(buf)-1] == '\n')
440 buf[strlen(buf)-1] = 0;
444 i = mdvi_in_range(range, count, v);
446 printf("%d not in range\n", v);
448 printf("%d in range: ", v);
449 print_range(&range[i]);
453 if(range) mdvi_free(range);
460 printf("Spec> "); fflush(stdout);
461 if(fgets(buf, 256, stdin) == NULL)
463 if(buf[strlen(buf)-1] == '\n')
464 buf[strlen(buf)-1] = 0;
467 spec = mdvi_parse_page_spec(buf);
469 printf("no spec parsed\n");
474 for(i = 0; i < 11; i++) {
475 printf("Counter %d:\n", i);
479 for(k = 0; k < spec[i]->nranges; k++)
480 print_range(&spec[i]->ranges[k]);
484 mdvi_free_page_spec(spec);