1314817Sngie/* $Id: term_ascii.c,v 1.20 2011/12/04 23:10:52 schwarze Exp $ */ 2311966Sngie/* 3311966Sngie * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4311966Sngie * 5311966Sngie * Permission to use, copy, modify, and distribute this software for any 6311966Sngie * purpose with or without fee is hereby granted, provided that the above 7311966Sngie * copyright notice and this permission notice appear in all copies. 8311966Sngie * 9311966Sngie * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10311966Sngie * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11311966Sngie * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12311966Sngie * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13311966Sngie * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14311966Sngie * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15311966Sngie * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16311966Sngie */ 17311966Sngie#ifdef HAVE_CONFIG_H 18311966Sngie#include "config.h" 19311966Sngie#endif 20311966Sngie 21311966Sngie#include <sys/types.h> 22311966Sngie 23311966Sngie#include <assert.h> 24311966Sngie#ifdef USE_WCHAR 25311966Sngie# include <locale.h> 26311966Sngie#endif 27311966Sngie#include <stdint.h> 28311966Sngie#include <stdio.h> 29311966Sngie#include <stdlib.h> 30311966Sngie#include <unistd.h> 31311966Sngie#ifdef USE_WCHAR 32311966Sngie# include <wchar.h> 33311966Sngie#endif 34311966Sngie 35311966Sngie#include "mandoc.h" 36311966Sngie#include "out.h" 37311966Sngie#include "term.h" 38311966Sngie#include "main.h" 39311966Sngie 40311966Sngie/* 41311966Sngie * Sadly, this doesn't seem to be defined on systems even when they 42311966Sngie * support it. For the time being, remove it and let those compiling 43311966Sngie * the software decide for themselves what to use. 44311966Sngie */ 45311966Sngie#if 0 46311966Sngie#if ! defined(__STDC_ISO_10646__) 47311966Sngie# undef USE_WCHAR 48311966Sngie#endif 49311966Sngie#endif 50311966Sngie 51314817Sngiestatic struct termp *ascii_init(enum termenc, char *); 52311966Sngiestatic double ascii_hspan(const struct termp *, 53311966Sngie const struct roffsu *); 54311966Sngiestatic size_t ascii_width(const struct termp *, int); 55311966Sngiestatic void ascii_advance(struct termp *, size_t); 56311966Sngiestatic void ascii_begin(struct termp *); 57311966Sngiestatic void ascii_end(struct termp *); 58311966Sngiestatic void ascii_endline(struct termp *); 59311966Sngiestatic void ascii_letter(struct termp *, int); 60311966Sngie 61311966Sngie#ifdef USE_WCHAR 62311966Sngiestatic void locale_advance(struct termp *, size_t); 63311966Sngiestatic void locale_endline(struct termp *); 64311966Sngiestatic void locale_letter(struct termp *, int); 65311966Sngiestatic size_t locale_width(const struct termp *, int); 66311966Sngie#endif 67311966Sngie 68311966Sngiestatic struct termp * 69311966Sngieascii_init(enum termenc enc, char *outopts) 70311966Sngie{ 71311966Sngie const char *toks[4]; 72311966Sngie char *v; 73311966Sngie struct termp *p; 74311966Sngie 75311966Sngie p = mandoc_calloc(1, sizeof(struct termp)); 76311966Sngie p->enc = enc; 77311966Sngie 78311966Sngie p->tabwidth = 5; 79311966Sngie p->defrmargin = 78; 80311966Sngie 81311966Sngie p->begin = ascii_begin; 82311966Sngie p->end = ascii_end; 83311966Sngie p->hspan = ascii_hspan; 84311966Sngie p->type = TERMTYPE_CHAR; 85311966Sngie 86311966Sngie p->enc = TERMENC_ASCII; 87311966Sngie p->advance = ascii_advance; 88311966Sngie p->endline = ascii_endline; 89311966Sngie p->letter = ascii_letter; 90311966Sngie p->width = ascii_width; 91311966Sngie 92311966Sngie#ifdef USE_WCHAR 93311966Sngie if (TERMENC_ASCII != enc) { 94311966Sngie v = TERMENC_LOCALE == enc ? 95311966Sngie setlocale(LC_ALL, "") : 96311966Sngie setlocale(LC_CTYPE, "UTF-8"); 97311966Sngie if (NULL != v && MB_CUR_MAX > 1) { 98311966Sngie p->enc = enc; 99311966Sngie p->advance = locale_advance; 100311966Sngie p->endline = locale_endline; 101311966Sngie p->letter = locale_letter; 102311966Sngie p->width = locale_width; 103311966Sngie } 104311966Sngie } 105311966Sngie#endif 106311966Sngie 107311966Sngie toks[0] = "indent"; 108311966Sngie toks[1] = "width"; 109311966Sngie toks[2] = "mdoc"; 110311966Sngie toks[3] = NULL; 111311966Sngie 112311966Sngie while (outopts && *outopts) 113311966Sngie switch (getsubopt(&outopts, UNCONST(toks), &v)) { 114311966Sngie case (0): 115311966Sngie p->defindent = (size_t)atoi(v); 116311966Sngie break; 117311966Sngie case (1): 118311966Sngie p->defrmargin = (size_t)atoi(v); 119311966Sngie break; 120311966Sngie case (2): 121311966Sngie /* 122311966Sngie * Temporary, undocumented mode 123311966Sngie * to imitate mdoc(7) output style. 124311966Sngie */ 125311966Sngie p->mdocstyle = 1; 126311966Sngie p->defindent = 5; 127311966Sngie break; 128311966Sngie default: 129311966Sngie break; 130311966Sngie } 131311966Sngie 132311966Sngie /* Enforce a lower boundary. */ 133311966Sngie if (p->defrmargin < 58) 134311966Sngie p->defrmargin = 58; 135311966Sngie 136311966Sngie return(p); 137311966Sngie} 138311966Sngie 139311966Sngievoid * 140311966Sngieascii_alloc(char *outopts) 141311966Sngie{ 142311966Sngie 143311966Sngie return(ascii_init(TERMENC_ASCII, outopts)); 144311966Sngie} 145311966Sngie 146311966Sngievoid * 147311966Sngieutf8_alloc(char *outopts) 148311966Sngie{ 149311966Sngie 150311966Sngie return(ascii_init(TERMENC_UTF8, outopts)); 151311966Sngie} 152311966Sngie 153311966Sngie 154311966Sngievoid * 155311966Sngielocale_alloc(char *outopts) 156311966Sngie{ 157311966Sngie 158311966Sngie return(ascii_init(TERMENC_LOCALE, outopts)); 159311966Sngie} 160311966Sngie 161311966Sngie/* ARGSUSED */ 162311966Sngiestatic size_t 163311966Sngieascii_width(const struct termp *p, int c) 164311966Sngie{ 165311966Sngie 166311966Sngie return(1); 167311966Sngie} 168311966Sngie 169311966Sngievoid 170311966Sngieascii_free(void *arg) 171311966Sngie{ 172311966Sngie 173311966Sngie term_free((struct termp *)arg); 174311966Sngie} 175311966Sngie 176311966Sngie/* ARGSUSED */ 177311966Sngiestatic void 178311966Sngieascii_letter(struct termp *p, int c) 179311966Sngie{ 180311966Sngie 181311966Sngie putchar(c); 182311966Sngie} 183311966Sngie 184311966Sngiestatic void 185311966Sngieascii_begin(struct termp *p) 186311966Sngie{ 187311966Sngie 188311966Sngie (*p->headf)(p, p->argf); 189311966Sngie} 190311966Sngie 191311966Sngiestatic void 192311966Sngieascii_end(struct termp *p) 193311966Sngie{ 194311966Sngie 195311966Sngie (*p->footf)(p, p->argf); 196311966Sngie} 197311966Sngie 198311966Sngie/* ARGSUSED */ 199311966Sngiestatic void 200311966Sngieascii_endline(struct termp *p) 201311966Sngie{ 202311966Sngie 203311966Sngie putchar('\n'); 204311966Sngie} 205311966Sngie 206311966Sngie/* ARGSUSED */ 207311966Sngiestatic void 208311966Sngieascii_advance(struct termp *p, size_t len) 209311966Sngie{ 210311966Sngie size_t i; 211311966Sngie 212311966Sngie for (i = 0; i < len; i++) 213311966Sngie putchar(' '); 214311966Sngie} 215311966Sngie 216311966Sngie/* ARGSUSED */ 217311966Sngiestatic double 218311966Sngieascii_hspan(const struct termp *p, const struct roffsu *su) 219311966Sngie{ 220311966Sngie double r; 221311966Sngie 222311966Sngie /* 223311966Sngie * Approximate based on character width. These are generated 224311966Sngie * entirely by eyeballing the screen, but appear to be correct. 225311966Sngie */ 226311966Sngie 227311966Sngie switch (su->unit) { 228311966Sngie case (SCALE_CM): 229311966Sngie r = 4 * su->scale; 230311966Sngie break; 231311966Sngie case (SCALE_IN): 232311966Sngie r = 10 * su->scale; 233311966Sngie break; 234311966Sngie case (SCALE_PC): 235311966Sngie r = (10 * su->scale) / 6; 236311966Sngie break; 237311966Sngie case (SCALE_PT): 238311966Sngie r = (10 * su->scale) / 72; 239311966Sngie break; 240311966Sngie case (SCALE_MM): 241311966Sngie r = su->scale / 1000; 242311966Sngie break; 243311966Sngie case (SCALE_VS): 244311966Sngie r = su->scale * 2 - 1; 245311966Sngie break; 246311966Sngie default: 247311966Sngie r = su->scale; 248311966Sngie break; 249311966Sngie } 250311966Sngie 251311966Sngie return(r); 252311966Sngie} 253311966Sngie 254311966Sngie#ifdef USE_WCHAR 255311966Sngie/* ARGSUSED */ 256311966Sngiestatic size_t 257311966Sngielocale_width(const struct termp *p, int c) 258311966Sngie{ 259311966Sngie int rc; 260311966Sngie 261311966Sngie return((rc = wcwidth(c)) < 0 ? 0 : rc); 262311966Sngie} 263311966Sngie 264311966Sngie/* ARGSUSED */ 265311966Sngiestatic void 266311966Sngielocale_advance(struct termp *p, size_t len) 267311966Sngie{ 268311966Sngie size_t i; 269311966Sngie 270311966Sngie for (i = 0; i < len; i++) 271311966Sngie putwchar(L' '); 272311966Sngie} 273311966Sngie 274311966Sngie/* ARGSUSED */ 275311966Sngiestatic void 276311966Sngielocale_endline(struct termp *p) 277311966Sngie{ 278311966Sngie 279311966Sngie putwchar(L'\n'); 280311966Sngie} 281311966Sngie 282311966Sngie/* ARGSUSED */ 283311966Sngiestatic void 284311966Sngielocale_letter(struct termp *p, int c) 285311966Sngie{ 286311966Sngie 287311966Sngie putwchar(c); 288311966Sngie} 289311966Sngie#endif 290311966Sngie