1319715Sbapt/* $OpenBSD: term.c,v 1.119 2017/01/08 18:08:44 schwarze Exp $ */ 2319715Sbapt/* 3319715Sbapt * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org> 4319715Sbapt * 5319715Sbapt * Permission to use, copy, modify, and distribute this software for any 6319715Sbapt * purpose with or without fee is hereby granted, provided that the above 7319715Sbapt * copyright notice and this permission notice appear in all copies. 8319715Sbapt * 9319715Sbapt * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10319715Sbapt * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11319715Sbapt * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12319715Sbapt * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13319715Sbapt * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14319715Sbapt * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15319715Sbapt * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16319715Sbapt */ 17319715Sbapt#include <sys/types.h> 18319715Sbapt 19319715Sbapt#include <stddef.h> 20319715Sbapt 21319715Sbapt#include "mandoc_aux.h" 22319715Sbapt#include "out.h" 23319715Sbapt#include "term.h" 24319715Sbapt 25319715Sbaptstruct tablist { 26319715Sbapt size_t *t; /* Allocated array of tab positions. */ 27319715Sbapt size_t s; /* Allocated number of positions. */ 28319715Sbapt size_t n; /* Currently used number of positions. */ 29319715Sbapt}; 30319715Sbapt 31319715Sbaptstatic struct { 32319715Sbapt struct tablist a; /* All tab positions for lookup. */ 33319715Sbapt struct tablist p; /* Periodic tab positions to add. */ 34319715Sbapt size_t d; /* Default tab width in units of n. */ 35319715Sbapt} tabs; 36319715Sbapt 37319715Sbapt 38319715Sbaptvoid 39319715Sbaptterm_tab_set(const struct termp *p, const char *arg) 40319715Sbapt{ 41319715Sbapt static int recording_period; 42319715Sbapt 43319715Sbapt struct roffsu su; 44319715Sbapt struct tablist *tl; 45319715Sbapt size_t pos; 46319715Sbapt int add; 47319715Sbapt 48319715Sbapt /* Special arguments: clear all tabs or switch lists. */ 49319715Sbapt 50319715Sbapt if (arg == NULL) { 51319715Sbapt tabs.a.n = tabs.p.n = 0; 52319715Sbapt recording_period = 0; 53319715Sbapt if (tabs.d == 0) { 54319715Sbapt a2roffsu(".8i", &su, SCALE_IN); 55322249Sbapt tabs.d = term_hen(p, &su); 56319715Sbapt } 57319715Sbapt return; 58319715Sbapt } 59319715Sbapt if (arg[0] == 'T' && arg[1] == '\0') { 60319715Sbapt recording_period = 1; 61319715Sbapt return; 62319715Sbapt } 63319715Sbapt 64319715Sbapt /* Parse the sign, the number, and the unit. */ 65319715Sbapt 66319715Sbapt if (*arg == '+') { 67319715Sbapt add = 1; 68319715Sbapt arg++; 69319715Sbapt } else 70319715Sbapt add = 0; 71319715Sbapt if (a2roffsu(arg, &su, SCALE_EM) == NULL) 72319715Sbapt return; 73319715Sbapt 74319715Sbapt /* Select the list, and extend it if it is full. */ 75319715Sbapt 76319715Sbapt tl = recording_period ? &tabs.p : &tabs.a; 77319715Sbapt if (tl->n >= tl->s) { 78319715Sbapt tl->s += 8; 79319715Sbapt tl->t = mandoc_reallocarray(tl->t, tl->s, sizeof(*tl->t)); 80319715Sbapt } 81319715Sbapt 82319715Sbapt /* Append the new position. */ 83319715Sbapt 84322249Sbapt pos = term_hen(p, &su); 85319715Sbapt tl->t[tl->n] = pos; 86319715Sbapt if (add && tl->n) 87319715Sbapt tl->t[tl->n] += tl->t[tl->n - 1]; 88319715Sbapt tl->n++; 89319715Sbapt} 90319715Sbapt 91322249Sbapt/* 92322249Sbapt * Simplified version without a parser, 93322249Sbapt * never incremental, never periodic, for use by tbl(7). 94322249Sbapt */ 95322249Sbaptvoid 96322249Sbaptterm_tab_iset(size_t inc) 97322249Sbapt{ 98322249Sbapt if (tabs.a.n >= tabs.a.s) { 99322249Sbapt tabs.a.s += 8; 100322249Sbapt tabs.a.t = mandoc_reallocarray(tabs.a.t, tabs.a.s, 101322249Sbapt sizeof(*tabs.a.t)); 102322249Sbapt } 103322249Sbapt tabs.a.t[tabs.a.n++] = inc; 104322249Sbapt} 105322249Sbapt 106319715Sbaptsize_t 107319715Sbaptterm_tab_next(size_t prev) 108319715Sbapt{ 109319715Sbapt size_t i, j; 110319715Sbapt 111319715Sbapt for (i = 0;; i++) { 112319715Sbapt if (i == tabs.a.n) { 113319715Sbapt if (tabs.p.n == 0) 114319715Sbapt return prev; 115319715Sbapt tabs.a.n += tabs.p.n; 116319715Sbapt if (tabs.a.s < tabs.a.n) { 117319715Sbapt tabs.a.s = tabs.a.n; 118319715Sbapt tabs.a.t = mandoc_reallocarray(tabs.a.t, 119319715Sbapt tabs.a.s, sizeof(*tabs.a.t)); 120319715Sbapt } 121319715Sbapt for (j = 0; j < tabs.p.n; j++) 122319715Sbapt tabs.a.t[i + j] = tabs.p.t[j] + 123319715Sbapt (i ? tabs.a.t[i - 1] : 0); 124319715Sbapt } 125322249Sbapt if (prev < tabs.a.t[i]) 126322249Sbapt return tabs.a.t[i]; 127319715Sbapt } 128319715Sbapt} 129