1*61d06d6bSBaptiste Daroussin /* $OpenBSD: term.c,v 1.119 2017/01/08 18:08:44 schwarze Exp $ */ 2*61d06d6bSBaptiste Daroussin /* 3*61d06d6bSBaptiste Daroussin * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org> 4*61d06d6bSBaptiste Daroussin * 5*61d06d6bSBaptiste Daroussin * Permission to use, copy, modify, and distribute this software for any 6*61d06d6bSBaptiste Daroussin * purpose with or without fee is hereby granted, provided that the above 7*61d06d6bSBaptiste Daroussin * copyright notice and this permission notice appear in all copies. 8*61d06d6bSBaptiste Daroussin * 9*61d06d6bSBaptiste Daroussin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*61d06d6bSBaptiste Daroussin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*61d06d6bSBaptiste Daroussin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*61d06d6bSBaptiste Daroussin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*61d06d6bSBaptiste Daroussin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*61d06d6bSBaptiste Daroussin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*61d06d6bSBaptiste Daroussin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*61d06d6bSBaptiste Daroussin */ 17*61d06d6bSBaptiste Daroussin #include <sys/types.h> 18*61d06d6bSBaptiste Daroussin 19*61d06d6bSBaptiste Daroussin #include <stddef.h> 20*61d06d6bSBaptiste Daroussin 21*61d06d6bSBaptiste Daroussin #include "mandoc_aux.h" 22*61d06d6bSBaptiste Daroussin #include "out.h" 23*61d06d6bSBaptiste Daroussin #include "term.h" 24*61d06d6bSBaptiste Daroussin 25*61d06d6bSBaptiste Daroussin struct tablist { 26*61d06d6bSBaptiste Daroussin size_t *t; /* Allocated array of tab positions. */ 27*61d06d6bSBaptiste Daroussin size_t s; /* Allocated number of positions. */ 28*61d06d6bSBaptiste Daroussin size_t n; /* Currently used number of positions. */ 29*61d06d6bSBaptiste Daroussin }; 30*61d06d6bSBaptiste Daroussin 31*61d06d6bSBaptiste Daroussin static struct { 32*61d06d6bSBaptiste Daroussin struct tablist a; /* All tab positions for lookup. */ 33*61d06d6bSBaptiste Daroussin struct tablist p; /* Periodic tab positions to add. */ 34*61d06d6bSBaptiste Daroussin size_t d; /* Default tab width in units of n. */ 35*61d06d6bSBaptiste Daroussin } tabs; 36*61d06d6bSBaptiste Daroussin 37*61d06d6bSBaptiste Daroussin 38*61d06d6bSBaptiste Daroussin void 39*61d06d6bSBaptiste Daroussin term_tab_set(const struct termp *p, const char *arg) 40*61d06d6bSBaptiste Daroussin { 41*61d06d6bSBaptiste Daroussin static int recording_period; 42*61d06d6bSBaptiste Daroussin 43*61d06d6bSBaptiste Daroussin struct roffsu su; 44*61d06d6bSBaptiste Daroussin struct tablist *tl; 45*61d06d6bSBaptiste Daroussin size_t pos; 46*61d06d6bSBaptiste Daroussin int add; 47*61d06d6bSBaptiste Daroussin 48*61d06d6bSBaptiste Daroussin /* Special arguments: clear all tabs or switch lists. */ 49*61d06d6bSBaptiste Daroussin 50*61d06d6bSBaptiste Daroussin if (arg == NULL) { 51*61d06d6bSBaptiste Daroussin tabs.a.n = tabs.p.n = 0; 52*61d06d6bSBaptiste Daroussin recording_period = 0; 53*61d06d6bSBaptiste Daroussin if (tabs.d == 0) { 54*61d06d6bSBaptiste Daroussin a2roffsu(".8i", &su, SCALE_IN); 55*61d06d6bSBaptiste Daroussin tabs.d = term_hen(p, &su); 56*61d06d6bSBaptiste Daroussin } 57*61d06d6bSBaptiste Daroussin return; 58*61d06d6bSBaptiste Daroussin } 59*61d06d6bSBaptiste Daroussin if (arg[0] == 'T' && arg[1] == '\0') { 60*61d06d6bSBaptiste Daroussin recording_period = 1; 61*61d06d6bSBaptiste Daroussin return; 62*61d06d6bSBaptiste Daroussin } 63*61d06d6bSBaptiste Daroussin 64*61d06d6bSBaptiste Daroussin /* Parse the sign, the number, and the unit. */ 65*61d06d6bSBaptiste Daroussin 66*61d06d6bSBaptiste Daroussin if (*arg == '+') { 67*61d06d6bSBaptiste Daroussin add = 1; 68*61d06d6bSBaptiste Daroussin arg++; 69*61d06d6bSBaptiste Daroussin } else 70*61d06d6bSBaptiste Daroussin add = 0; 71*61d06d6bSBaptiste Daroussin if (a2roffsu(arg, &su, SCALE_EM) == NULL) 72*61d06d6bSBaptiste Daroussin return; 73*61d06d6bSBaptiste Daroussin 74*61d06d6bSBaptiste Daroussin /* Select the list, and extend it if it is full. */ 75*61d06d6bSBaptiste Daroussin 76*61d06d6bSBaptiste Daroussin tl = recording_period ? &tabs.p : &tabs.a; 77*61d06d6bSBaptiste Daroussin if (tl->n >= tl->s) { 78*61d06d6bSBaptiste Daroussin tl->s += 8; 79*61d06d6bSBaptiste Daroussin tl->t = mandoc_reallocarray(tl->t, tl->s, sizeof(*tl->t)); 80*61d06d6bSBaptiste Daroussin } 81*61d06d6bSBaptiste Daroussin 82*61d06d6bSBaptiste Daroussin /* Append the new position. */ 83*61d06d6bSBaptiste Daroussin 84*61d06d6bSBaptiste Daroussin pos = term_hen(p, &su); 85*61d06d6bSBaptiste Daroussin tl->t[tl->n] = pos; 86*61d06d6bSBaptiste Daroussin if (add && tl->n) 87*61d06d6bSBaptiste Daroussin tl->t[tl->n] += tl->t[tl->n - 1]; 88*61d06d6bSBaptiste Daroussin tl->n++; 89*61d06d6bSBaptiste Daroussin } 90*61d06d6bSBaptiste Daroussin 91*61d06d6bSBaptiste Daroussin /* 92*61d06d6bSBaptiste Daroussin * Simplified version without a parser, 93*61d06d6bSBaptiste Daroussin * never incremental, never periodic, for use by tbl(7). 94*61d06d6bSBaptiste Daroussin */ 95*61d06d6bSBaptiste Daroussin void 96*61d06d6bSBaptiste Daroussin term_tab_iset(size_t inc) 97*61d06d6bSBaptiste Daroussin { 98*61d06d6bSBaptiste Daroussin if (tabs.a.n >= tabs.a.s) { 99*61d06d6bSBaptiste Daroussin tabs.a.s += 8; 100*61d06d6bSBaptiste Daroussin tabs.a.t = mandoc_reallocarray(tabs.a.t, tabs.a.s, 101*61d06d6bSBaptiste Daroussin sizeof(*tabs.a.t)); 102*61d06d6bSBaptiste Daroussin } 103*61d06d6bSBaptiste Daroussin tabs.a.t[tabs.a.n++] = inc; 104*61d06d6bSBaptiste Daroussin } 105*61d06d6bSBaptiste Daroussin 106*61d06d6bSBaptiste Daroussin size_t 107*61d06d6bSBaptiste Daroussin term_tab_next(size_t prev) 108*61d06d6bSBaptiste Daroussin { 109*61d06d6bSBaptiste Daroussin size_t i, j; 110*61d06d6bSBaptiste Daroussin 111*61d06d6bSBaptiste Daroussin for (i = 0;; i++) { 112*61d06d6bSBaptiste Daroussin if (i == tabs.a.n) { 113*61d06d6bSBaptiste Daroussin if (tabs.p.n == 0) 114*61d06d6bSBaptiste Daroussin return prev; 115*61d06d6bSBaptiste Daroussin tabs.a.n += tabs.p.n; 116*61d06d6bSBaptiste Daroussin if (tabs.a.s < tabs.a.n) { 117*61d06d6bSBaptiste Daroussin tabs.a.s = tabs.a.n; 118*61d06d6bSBaptiste Daroussin tabs.a.t = mandoc_reallocarray(tabs.a.t, 119*61d06d6bSBaptiste Daroussin tabs.a.s, sizeof(*tabs.a.t)); 120*61d06d6bSBaptiste Daroussin } 121*61d06d6bSBaptiste Daroussin for (j = 0; j < tabs.p.n; j++) 122*61d06d6bSBaptiste Daroussin tabs.a.t[i + j] = tabs.p.t[j] + 123*61d06d6bSBaptiste Daroussin (i ? tabs.a.t[i - 1] : 0); 124*61d06d6bSBaptiste Daroussin } 125*61d06d6bSBaptiste Daroussin if (prev < tabs.a.t[i]) 126*61d06d6bSBaptiste Daroussin return tabs.a.t[i]; 127*61d06d6bSBaptiste Daroussin } 128*61d06d6bSBaptiste Daroussin } 129