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 *
ascii_init(enum termenc enc,char * outopts)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 *
ascii_alloc(char * outopts)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 *
utf8_alloc(char * outopts)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 *
locale_alloc(char * outopts)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
ascii_width(const struct termp * p,int c)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
ascii_free(void * arg)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
ascii_letter(struct termp * p,int c)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
ascii_begin(struct termp * p)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
ascii_end(struct termp * p)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
ascii_endline(struct termp * p)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
ascii_advance(struct termp * p,size_t len)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
ascii_hspan(const struct termp * p,const struct roffsu * su)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
locale_width(const struct termp * p,int c)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
locale_advance(struct termp * p,size_t len)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
locale_endline(struct termp * p)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
locale_letter(struct termp * p,int c)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