1*6d38604fSBaptiste Daroussin /* $Id: term_tab.c,v 1.6 2020/06/22 19:20:40 schwarze Exp $ */ 261d06d6bSBaptiste Daroussin /* 361d06d6bSBaptiste Daroussin * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org> 461d06d6bSBaptiste Daroussin * 561d06d6bSBaptiste Daroussin * Permission to use, copy, modify, and distribute this software for any 661d06d6bSBaptiste Daroussin * purpose with or without fee is hereby granted, provided that the above 761d06d6bSBaptiste Daroussin * copyright notice and this permission notice appear in all copies. 861d06d6bSBaptiste Daroussin * 961d06d6bSBaptiste Daroussin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1061d06d6bSBaptiste Daroussin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1161d06d6bSBaptiste Daroussin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1261d06d6bSBaptiste Daroussin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1361d06d6bSBaptiste Daroussin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1461d06d6bSBaptiste Daroussin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1561d06d6bSBaptiste Daroussin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1661d06d6bSBaptiste Daroussin */ 17*6d38604fSBaptiste Daroussin #include "config.h" 18*6d38604fSBaptiste Daroussin 1961d06d6bSBaptiste Daroussin #include <sys/types.h> 2061d06d6bSBaptiste Daroussin 2161d06d6bSBaptiste Daroussin #include <stddef.h> 2261d06d6bSBaptiste Daroussin 2361d06d6bSBaptiste Daroussin #include "mandoc_aux.h" 2461d06d6bSBaptiste Daroussin #include "out.h" 2561d06d6bSBaptiste Daroussin #include "term.h" 2661d06d6bSBaptiste Daroussin 2761d06d6bSBaptiste Daroussin struct tablist { 2861d06d6bSBaptiste Daroussin size_t *t; /* Allocated array of tab positions. */ 2961d06d6bSBaptiste Daroussin size_t s; /* Allocated number of positions. */ 3061d06d6bSBaptiste Daroussin size_t n; /* Currently used number of positions. */ 3161d06d6bSBaptiste Daroussin }; 3261d06d6bSBaptiste Daroussin 3361d06d6bSBaptiste Daroussin static struct { 3461d06d6bSBaptiste Daroussin struct tablist a; /* All tab positions for lookup. */ 3561d06d6bSBaptiste Daroussin struct tablist p; /* Periodic tab positions to add. */ 3661d06d6bSBaptiste Daroussin size_t d; /* Default tab width in units of n. */ 3761d06d6bSBaptiste Daroussin } tabs; 3861d06d6bSBaptiste Daroussin 3961d06d6bSBaptiste Daroussin 4061d06d6bSBaptiste Daroussin void 4161d06d6bSBaptiste Daroussin term_tab_set(const struct termp *p, const char *arg) 4261d06d6bSBaptiste Daroussin { 4361d06d6bSBaptiste Daroussin static int recording_period; 4461d06d6bSBaptiste Daroussin 4561d06d6bSBaptiste Daroussin struct roffsu su; 4661d06d6bSBaptiste Daroussin struct tablist *tl; 4761d06d6bSBaptiste Daroussin size_t pos; 4861d06d6bSBaptiste Daroussin int add; 4961d06d6bSBaptiste Daroussin 5061d06d6bSBaptiste Daroussin /* Special arguments: clear all tabs or switch lists. */ 5161d06d6bSBaptiste Daroussin 5261d06d6bSBaptiste Daroussin if (arg == NULL) { 5361d06d6bSBaptiste Daroussin tabs.a.n = tabs.p.n = 0; 5461d06d6bSBaptiste Daroussin recording_period = 0; 5561d06d6bSBaptiste Daroussin if (tabs.d == 0) { 5661d06d6bSBaptiste Daroussin a2roffsu(".8i", &su, SCALE_IN); 5761d06d6bSBaptiste Daroussin tabs.d = term_hen(p, &su); 5861d06d6bSBaptiste Daroussin } 5961d06d6bSBaptiste Daroussin return; 6061d06d6bSBaptiste Daroussin } 6161d06d6bSBaptiste Daroussin if (arg[0] == 'T' && arg[1] == '\0') { 6261d06d6bSBaptiste Daroussin recording_period = 1; 6361d06d6bSBaptiste Daroussin return; 6461d06d6bSBaptiste Daroussin } 6561d06d6bSBaptiste Daroussin 6661d06d6bSBaptiste Daroussin /* Parse the sign, the number, and the unit. */ 6761d06d6bSBaptiste Daroussin 6861d06d6bSBaptiste Daroussin if (*arg == '+') { 6961d06d6bSBaptiste Daroussin add = 1; 7061d06d6bSBaptiste Daroussin arg++; 7161d06d6bSBaptiste Daroussin } else 7261d06d6bSBaptiste Daroussin add = 0; 7361d06d6bSBaptiste Daroussin if (a2roffsu(arg, &su, SCALE_EM) == NULL) 7461d06d6bSBaptiste Daroussin return; 7561d06d6bSBaptiste Daroussin 7661d06d6bSBaptiste Daroussin /* Select the list, and extend it if it is full. */ 7761d06d6bSBaptiste Daroussin 7861d06d6bSBaptiste Daroussin tl = recording_period ? &tabs.p : &tabs.a; 7961d06d6bSBaptiste Daroussin if (tl->n >= tl->s) { 8061d06d6bSBaptiste Daroussin tl->s += 8; 8161d06d6bSBaptiste Daroussin tl->t = mandoc_reallocarray(tl->t, tl->s, sizeof(*tl->t)); 8261d06d6bSBaptiste Daroussin } 8361d06d6bSBaptiste Daroussin 8461d06d6bSBaptiste Daroussin /* Append the new position. */ 8561d06d6bSBaptiste Daroussin 8661d06d6bSBaptiste Daroussin pos = term_hen(p, &su); 8761d06d6bSBaptiste Daroussin tl->t[tl->n] = pos; 8861d06d6bSBaptiste Daroussin if (add && tl->n) 8961d06d6bSBaptiste Daroussin tl->t[tl->n] += tl->t[tl->n - 1]; 9061d06d6bSBaptiste Daroussin tl->n++; 9161d06d6bSBaptiste Daroussin } 9261d06d6bSBaptiste Daroussin 9361d06d6bSBaptiste Daroussin /* 9461d06d6bSBaptiste Daroussin * Simplified version without a parser, 9561d06d6bSBaptiste Daroussin * never incremental, never periodic, for use by tbl(7). 9661d06d6bSBaptiste Daroussin */ 9761d06d6bSBaptiste Daroussin void 9861d06d6bSBaptiste Daroussin term_tab_iset(size_t inc) 9961d06d6bSBaptiste Daroussin { 10061d06d6bSBaptiste Daroussin if (tabs.a.n >= tabs.a.s) { 10161d06d6bSBaptiste Daroussin tabs.a.s += 8; 10261d06d6bSBaptiste Daroussin tabs.a.t = mandoc_reallocarray(tabs.a.t, tabs.a.s, 10361d06d6bSBaptiste Daroussin sizeof(*tabs.a.t)); 10461d06d6bSBaptiste Daroussin } 10561d06d6bSBaptiste Daroussin tabs.a.t[tabs.a.n++] = inc; 10661d06d6bSBaptiste Daroussin } 10761d06d6bSBaptiste Daroussin 10861d06d6bSBaptiste Daroussin size_t 10961d06d6bSBaptiste Daroussin term_tab_next(size_t prev) 11061d06d6bSBaptiste Daroussin { 11161d06d6bSBaptiste Daroussin size_t i, j; 11261d06d6bSBaptiste Daroussin 11361d06d6bSBaptiste Daroussin for (i = 0;; i++) { 11461d06d6bSBaptiste Daroussin if (i == tabs.a.n) { 11561d06d6bSBaptiste Daroussin if (tabs.p.n == 0) 11661d06d6bSBaptiste Daroussin return prev; 11761d06d6bSBaptiste Daroussin tabs.a.n += tabs.p.n; 11861d06d6bSBaptiste Daroussin if (tabs.a.s < tabs.a.n) { 11961d06d6bSBaptiste Daroussin tabs.a.s = tabs.a.n; 12061d06d6bSBaptiste Daroussin tabs.a.t = mandoc_reallocarray(tabs.a.t, 12161d06d6bSBaptiste Daroussin tabs.a.s, sizeof(*tabs.a.t)); 12261d06d6bSBaptiste Daroussin } 12361d06d6bSBaptiste Daroussin for (j = 0; j < tabs.p.n; j++) 12461d06d6bSBaptiste Daroussin tabs.a.t[i + j] = tabs.p.t[j] + 12561d06d6bSBaptiste Daroussin (i ? tabs.a.t[i - 1] : 0); 12661d06d6bSBaptiste Daroussin } 12761d06d6bSBaptiste Daroussin if (prev < tabs.a.t[i]) 12861d06d6bSBaptiste Daroussin return tabs.a.t[i]; 12961d06d6bSBaptiste Daroussin } 13061d06d6bSBaptiste Daroussin } 131