1*698f87a4SGarrett D'Amore /* $Id: term_ascii.c,v 1.21 2013/06/01 14:27:20 schwarze Exp $ */ 295c635efSGarrett D'Amore /* 395c635efSGarrett D'Amore * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 495c635efSGarrett D'Amore * 595c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 695c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 795c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 895c635efSGarrett D'Amore * 995c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1095c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1195c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1295c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1395c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1495c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1595c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1695c635efSGarrett D'Amore */ 1795c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H 1895c635efSGarrett D'Amore #include "config.h" 1995c635efSGarrett D'Amore #endif 2095c635efSGarrett D'Amore 2195c635efSGarrett D'Amore #include <sys/types.h> 2295c635efSGarrett D'Amore 2395c635efSGarrett D'Amore #include <assert.h> 2495c635efSGarrett D'Amore #ifdef USE_WCHAR 2595c635efSGarrett D'Amore # include <locale.h> 2695c635efSGarrett D'Amore #endif 2795c635efSGarrett D'Amore #include <stdint.h> 2895c635efSGarrett D'Amore #include <stdio.h> 2995c635efSGarrett D'Amore #include <stdlib.h> 3095c635efSGarrett D'Amore #include <unistd.h> 3195c635efSGarrett D'Amore #ifdef USE_WCHAR 3295c635efSGarrett D'Amore # include <wchar.h> 3395c635efSGarrett D'Amore #endif 3495c635efSGarrett D'Amore 3595c635efSGarrett D'Amore #include "mandoc.h" 3695c635efSGarrett D'Amore #include "out.h" 3795c635efSGarrett D'Amore #include "term.h" 3895c635efSGarrett D'Amore #include "main.h" 3995c635efSGarrett D'Amore 4095c635efSGarrett D'Amore /* 4195c635efSGarrett D'Amore * Sadly, this doesn't seem to be defined on systems even when they 4295c635efSGarrett D'Amore * support it. For the time being, remove it and let those compiling 4395c635efSGarrett D'Amore * the software decide for themselves what to use. 4495c635efSGarrett D'Amore */ 4595c635efSGarrett D'Amore #if 0 4695c635efSGarrett D'Amore #if ! defined(__STDC_ISO_10646__) 4795c635efSGarrett D'Amore # undef USE_WCHAR 4895c635efSGarrett D'Amore #endif 4995c635efSGarrett D'Amore #endif 5095c635efSGarrett D'Amore 5195c635efSGarrett D'Amore static struct termp *ascii_init(enum termenc, char *); 5295c635efSGarrett D'Amore static double ascii_hspan(const struct termp *, 5395c635efSGarrett D'Amore const struct roffsu *); 5495c635efSGarrett D'Amore static size_t ascii_width(const struct termp *, int); 5595c635efSGarrett D'Amore static void ascii_advance(struct termp *, size_t); 5695c635efSGarrett D'Amore static void ascii_begin(struct termp *); 5795c635efSGarrett D'Amore static void ascii_end(struct termp *); 5895c635efSGarrett D'Amore static void ascii_endline(struct termp *); 5995c635efSGarrett D'Amore static void ascii_letter(struct termp *, int); 6095c635efSGarrett D'Amore 6195c635efSGarrett D'Amore #ifdef USE_WCHAR 6295c635efSGarrett D'Amore static void locale_advance(struct termp *, size_t); 6395c635efSGarrett D'Amore static void locale_endline(struct termp *); 6495c635efSGarrett D'Amore static void locale_letter(struct termp *, int); 6595c635efSGarrett D'Amore static size_t locale_width(const struct termp *, int); 6695c635efSGarrett D'Amore #endif 6795c635efSGarrett D'Amore 6895c635efSGarrett D'Amore static struct termp * 6995c635efSGarrett D'Amore ascii_init(enum termenc enc, char *outopts) 7095c635efSGarrett D'Amore { 7195c635efSGarrett D'Amore const char *toks[4]; 7295c635efSGarrett D'Amore char *v; 7395c635efSGarrett D'Amore struct termp *p; 7495c635efSGarrett D'Amore 7595c635efSGarrett D'Amore p = mandoc_calloc(1, sizeof(struct termp)); 7695c635efSGarrett D'Amore 7795c635efSGarrett D'Amore p->tabwidth = 5; 7895c635efSGarrett D'Amore p->defrmargin = 78; 7995c635efSGarrett D'Amore 8095c635efSGarrett D'Amore p->begin = ascii_begin; 8195c635efSGarrett D'Amore p->end = ascii_end; 8295c635efSGarrett D'Amore p->hspan = ascii_hspan; 8395c635efSGarrett D'Amore p->type = TERMTYPE_CHAR; 8495c635efSGarrett D'Amore 8595c635efSGarrett D'Amore p->enc = TERMENC_ASCII; 8695c635efSGarrett D'Amore p->advance = ascii_advance; 8795c635efSGarrett D'Amore p->endline = ascii_endline; 8895c635efSGarrett D'Amore p->letter = ascii_letter; 8995c635efSGarrett D'Amore p->width = ascii_width; 9095c635efSGarrett D'Amore 9195c635efSGarrett D'Amore #ifdef USE_WCHAR 9295c635efSGarrett D'Amore if (TERMENC_ASCII != enc) { 9395c635efSGarrett D'Amore v = TERMENC_LOCALE == enc ? 9495c635efSGarrett D'Amore setlocale(LC_ALL, "") : 95*698f87a4SGarrett D'Amore setlocale(LC_CTYPE, "en_US.UTF-8"); 9695c635efSGarrett D'Amore if (NULL != v && MB_CUR_MAX > 1) { 9795c635efSGarrett D'Amore p->enc = enc; 9895c635efSGarrett D'Amore p->advance = locale_advance; 9995c635efSGarrett D'Amore p->endline = locale_endline; 10095c635efSGarrett D'Amore p->letter = locale_letter; 10195c635efSGarrett D'Amore p->width = locale_width; 10295c635efSGarrett D'Amore } 10395c635efSGarrett D'Amore } 10495c635efSGarrett D'Amore #endif 10595c635efSGarrett D'Amore 10695c635efSGarrett D'Amore toks[0] = "indent"; 10795c635efSGarrett D'Amore toks[1] = "width"; 10895c635efSGarrett D'Amore toks[2] = "mdoc"; 10995c635efSGarrett D'Amore toks[3] = NULL; 11095c635efSGarrett D'Amore 11195c635efSGarrett D'Amore while (outopts && *outopts) 11295c635efSGarrett D'Amore switch (getsubopt(&outopts, UNCONST(toks), &v)) { 11395c635efSGarrett D'Amore case (0): 11495c635efSGarrett D'Amore p->defindent = (size_t)atoi(v); 11595c635efSGarrett D'Amore break; 11695c635efSGarrett D'Amore case (1): 11795c635efSGarrett D'Amore p->defrmargin = (size_t)atoi(v); 11895c635efSGarrett D'Amore break; 11995c635efSGarrett D'Amore case (2): 12095c635efSGarrett D'Amore /* 12195c635efSGarrett D'Amore * Temporary, undocumented mode 12295c635efSGarrett D'Amore * to imitate mdoc(7) output style. 12395c635efSGarrett D'Amore */ 12495c635efSGarrett D'Amore p->mdocstyle = 1; 12595c635efSGarrett D'Amore p->defindent = 5; 12695c635efSGarrett D'Amore break; 12795c635efSGarrett D'Amore default: 12895c635efSGarrett D'Amore break; 12995c635efSGarrett D'Amore } 13095c635efSGarrett D'Amore 13195c635efSGarrett D'Amore /* Enforce a lower boundary. */ 13295c635efSGarrett D'Amore if (p->defrmargin < 58) 13395c635efSGarrett D'Amore p->defrmargin = 58; 13495c635efSGarrett D'Amore 13595c635efSGarrett D'Amore return(p); 13695c635efSGarrett D'Amore } 13795c635efSGarrett D'Amore 13895c635efSGarrett D'Amore void * 13995c635efSGarrett D'Amore ascii_alloc(char *outopts) 14095c635efSGarrett D'Amore { 14195c635efSGarrett D'Amore 14295c635efSGarrett D'Amore return(ascii_init(TERMENC_ASCII, outopts)); 14395c635efSGarrett D'Amore } 14495c635efSGarrett D'Amore 14595c635efSGarrett D'Amore void * 14695c635efSGarrett D'Amore utf8_alloc(char *outopts) 14795c635efSGarrett D'Amore { 14895c635efSGarrett D'Amore 14995c635efSGarrett D'Amore return(ascii_init(TERMENC_UTF8, outopts)); 15095c635efSGarrett D'Amore } 15195c635efSGarrett D'Amore 15295c635efSGarrett D'Amore 15395c635efSGarrett D'Amore void * 15495c635efSGarrett D'Amore locale_alloc(char *outopts) 15595c635efSGarrett D'Amore { 15695c635efSGarrett D'Amore 15795c635efSGarrett D'Amore return(ascii_init(TERMENC_LOCALE, outopts)); 15895c635efSGarrett D'Amore } 15995c635efSGarrett D'Amore 16095c635efSGarrett D'Amore /* ARGSUSED */ 16195c635efSGarrett D'Amore static size_t 16295c635efSGarrett D'Amore ascii_width(const struct termp *p, int c) 16395c635efSGarrett D'Amore { 16495c635efSGarrett D'Amore 16595c635efSGarrett D'Amore return(1); 16695c635efSGarrett D'Amore } 16795c635efSGarrett D'Amore 16895c635efSGarrett D'Amore void 16995c635efSGarrett D'Amore ascii_free(void *arg) 17095c635efSGarrett D'Amore { 17195c635efSGarrett D'Amore 17295c635efSGarrett D'Amore term_free((struct termp *)arg); 17395c635efSGarrett D'Amore } 17495c635efSGarrett D'Amore 17595c635efSGarrett D'Amore /* ARGSUSED */ 17695c635efSGarrett D'Amore static void 17795c635efSGarrett D'Amore ascii_letter(struct termp *p, int c) 17895c635efSGarrett D'Amore { 17995c635efSGarrett D'Amore 18095c635efSGarrett D'Amore putchar(c); 18195c635efSGarrett D'Amore } 18295c635efSGarrett D'Amore 18395c635efSGarrett D'Amore static void 18495c635efSGarrett D'Amore ascii_begin(struct termp *p) 18595c635efSGarrett D'Amore { 18695c635efSGarrett D'Amore 18795c635efSGarrett D'Amore (*p->headf)(p, p->argf); 18895c635efSGarrett D'Amore } 18995c635efSGarrett D'Amore 19095c635efSGarrett D'Amore static void 19195c635efSGarrett D'Amore ascii_end(struct termp *p) 19295c635efSGarrett D'Amore { 19395c635efSGarrett D'Amore 19495c635efSGarrett D'Amore (*p->footf)(p, p->argf); 19595c635efSGarrett D'Amore } 19695c635efSGarrett D'Amore 19795c635efSGarrett D'Amore /* ARGSUSED */ 19895c635efSGarrett D'Amore static void 19995c635efSGarrett D'Amore ascii_endline(struct termp *p) 20095c635efSGarrett D'Amore { 20195c635efSGarrett D'Amore 20295c635efSGarrett D'Amore putchar('\n'); 20395c635efSGarrett D'Amore } 20495c635efSGarrett D'Amore 20595c635efSGarrett D'Amore /* ARGSUSED */ 20695c635efSGarrett D'Amore static void 20795c635efSGarrett D'Amore ascii_advance(struct termp *p, size_t len) 20895c635efSGarrett D'Amore { 20995c635efSGarrett D'Amore size_t i; 21095c635efSGarrett D'Amore 21195c635efSGarrett D'Amore for (i = 0; i < len; i++) 21295c635efSGarrett D'Amore putchar(' '); 21395c635efSGarrett D'Amore } 21495c635efSGarrett D'Amore 21595c635efSGarrett D'Amore /* ARGSUSED */ 21695c635efSGarrett D'Amore static double 21795c635efSGarrett D'Amore ascii_hspan(const struct termp *p, const struct roffsu *su) 21895c635efSGarrett D'Amore { 21995c635efSGarrett D'Amore double r; 22095c635efSGarrett D'Amore 22195c635efSGarrett D'Amore /* 22295c635efSGarrett D'Amore * Approximate based on character width. These are generated 22395c635efSGarrett D'Amore * entirely by eyeballing the screen, but appear to be correct. 22495c635efSGarrett D'Amore */ 22595c635efSGarrett D'Amore 22695c635efSGarrett D'Amore switch (su->unit) { 22795c635efSGarrett D'Amore case (SCALE_CM): 22895c635efSGarrett D'Amore r = 4 * su->scale; 22995c635efSGarrett D'Amore break; 23095c635efSGarrett D'Amore case (SCALE_IN): 23195c635efSGarrett D'Amore r = 10 * su->scale; 23295c635efSGarrett D'Amore break; 23395c635efSGarrett D'Amore case (SCALE_PC): 23495c635efSGarrett D'Amore r = (10 * su->scale) / 6; 23595c635efSGarrett D'Amore break; 23695c635efSGarrett D'Amore case (SCALE_PT): 23795c635efSGarrett D'Amore r = (10 * su->scale) / 72; 23895c635efSGarrett D'Amore break; 23995c635efSGarrett D'Amore case (SCALE_MM): 24095c635efSGarrett D'Amore r = su->scale / 1000; 24195c635efSGarrett D'Amore break; 24295c635efSGarrett D'Amore case (SCALE_VS): 24395c635efSGarrett D'Amore r = su->scale * 2 - 1; 24495c635efSGarrett D'Amore break; 24595c635efSGarrett D'Amore default: 24695c635efSGarrett D'Amore r = su->scale; 24795c635efSGarrett D'Amore break; 24895c635efSGarrett D'Amore } 24995c635efSGarrett D'Amore 25095c635efSGarrett D'Amore return(r); 25195c635efSGarrett D'Amore } 25295c635efSGarrett D'Amore 25395c635efSGarrett D'Amore #ifdef USE_WCHAR 25495c635efSGarrett D'Amore /* ARGSUSED */ 25595c635efSGarrett D'Amore static size_t 25695c635efSGarrett D'Amore locale_width(const struct termp *p, int c) 25795c635efSGarrett D'Amore { 25895c635efSGarrett D'Amore int rc; 25995c635efSGarrett D'Amore 26095c635efSGarrett D'Amore return((rc = wcwidth(c)) < 0 ? 0 : rc); 26195c635efSGarrett D'Amore } 26295c635efSGarrett D'Amore 26395c635efSGarrett D'Amore /* ARGSUSED */ 26495c635efSGarrett D'Amore static void 26595c635efSGarrett D'Amore locale_advance(struct termp *p, size_t len) 26695c635efSGarrett D'Amore { 26795c635efSGarrett D'Amore size_t i; 26895c635efSGarrett D'Amore 26995c635efSGarrett D'Amore for (i = 0; i < len; i++) 27095c635efSGarrett D'Amore putwchar(L' '); 27195c635efSGarrett D'Amore } 27295c635efSGarrett D'Amore 27395c635efSGarrett D'Amore /* ARGSUSED */ 27495c635efSGarrett D'Amore static void 27595c635efSGarrett D'Amore locale_endline(struct termp *p) 27695c635efSGarrett D'Amore { 27795c635efSGarrett D'Amore 27895c635efSGarrett D'Amore putwchar(L'\n'); 27995c635efSGarrett D'Amore } 28095c635efSGarrett D'Amore 28195c635efSGarrett D'Amore /* ARGSUSED */ 28295c635efSGarrett D'Amore static void 28395c635efSGarrett D'Amore locale_letter(struct termp *p, int c) 28495c635efSGarrett D'Amore { 28595c635efSGarrett D'Amore 28695c635efSGarrett D'Amore putwchar(c); 28795c635efSGarrett D'Amore } 28895c635efSGarrett D'Amore #endif 289