1 /* $Id: term_ascii.c,v 1.5 2011/01/31 02:36:55 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <sys/types.h> 18 19 #include <assert.h> 20 #include <stdint.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <unistd.h> 24 25 #include "mandoc.h" 26 #include "out.h" 27 #include "term.h" 28 #include "main.h" 29 30 static double ascii_hspan(const struct termp *, 31 const struct roffsu *); 32 static size_t ascii_width(const struct termp *, char); 33 static void ascii_advance(struct termp *, size_t); 34 static void ascii_begin(struct termp *); 35 static void ascii_end(struct termp *); 36 static void ascii_endline(struct termp *); 37 static void ascii_letter(struct termp *, char); 38 39 40 void * 41 ascii_alloc(char *outopts) 42 { 43 struct termp *p; 44 const char *toks[2]; 45 char *v; 46 47 p = term_alloc(TERMENC_ASCII); 48 49 p->tabwidth = 5; 50 p->defrmargin = 78; 51 52 p->advance = ascii_advance; 53 p->begin = ascii_begin; 54 p->end = ascii_end; 55 p->endline = ascii_endline; 56 p->hspan = ascii_hspan; 57 p->letter = ascii_letter; 58 p->type = TERMTYPE_CHAR; 59 p->width = ascii_width; 60 61 toks[0] = "width"; 62 toks[1] = NULL; 63 64 while (outopts && *outopts) 65 switch (getsubopt(&outopts, UNCONST(toks), &v)) { 66 case (0): 67 p->defrmargin = (size_t)atoi(v); 68 break; 69 default: 70 break; 71 } 72 73 /* Enforce a lower boundary. */ 74 if (p->defrmargin < 58) 75 p->defrmargin = 58; 76 77 return(p); 78 } 79 80 81 /* ARGSUSED */ 82 static size_t 83 ascii_width(const struct termp *p, char c) 84 { 85 86 return(1); 87 } 88 89 90 void 91 ascii_free(void *arg) 92 { 93 94 term_free((struct termp *)arg); 95 } 96 97 98 /* ARGSUSED */ 99 static void 100 ascii_letter(struct termp *p, char c) 101 { 102 103 putchar(c); 104 } 105 106 107 static void 108 ascii_begin(struct termp *p) 109 { 110 111 (*p->headf)(p, p->argf); 112 } 113 114 115 static void 116 ascii_end(struct termp *p) 117 { 118 119 (*p->footf)(p, p->argf); 120 } 121 122 123 /* ARGSUSED */ 124 static void 125 ascii_endline(struct termp *p) 126 { 127 128 putchar('\n'); 129 } 130 131 132 /* ARGSUSED */ 133 static void 134 ascii_advance(struct termp *p, size_t len) 135 { 136 size_t i; 137 138 /* Just print whitespace on the terminal. */ 139 for (i = 0; i < len; i++) 140 putchar(' '); 141 } 142 143 144 /* ARGSUSED */ 145 static double 146 ascii_hspan(const struct termp *p, const struct roffsu *su) 147 { 148 double r; 149 150 /* 151 * Approximate based on character width. These are generated 152 * entirely by eyeballing the screen, but appear to be correct. 153 */ 154 155 switch (su->unit) { 156 case (SCALE_CM): 157 r = 4 * su->scale; 158 break; 159 case (SCALE_IN): 160 r = 10 * su->scale; 161 break; 162 case (SCALE_PC): 163 r = (10 * su->scale) / 6; 164 break; 165 case (SCALE_PT): 166 r = (10 * su->scale) / 72; 167 break; 168 case (SCALE_MM): 169 r = su->scale / 1000; 170 break; 171 case (SCALE_VS): 172 r = su->scale * 2 - 1; 173 break; 174 default: 175 r = su->scale; 176 break; 177 } 178 179 return(r); 180 } 181 182