00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "mit-copyright.h"
00010
00011
00012
00013
00014
00015
00016
00017 #include "main.h"
00018 #include "new_string.h"
00019 #include "string_dictionary_aux.h"
00020 #include "formatter.h"
00021 #include "error.h"
00022
00023
00024
00025 extern int tgetent();
00026 extern char *tgetstr(), *getenv();
00027 extern void tputs();
00028 short ospeed;
00029 char PC;
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 static string_dictionary termcap_dict;
00040 static char code_buf[10240], *code_buf_pos = code_buf, *code;
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #define TD_SET(k,v) (string_dictionary_Define(termcap_dict, (k), &ex)->value \
00060 = (v))
00061 #define EXPAND(k) (code = code_buf_pos, tputs(tmp, 1, tty_outc), \
00062 *code_buf_pos++ = 0, TD_SET(k, code))
00063
00064 static int
00065 tty_outc(c)
00066 int c;
00067 {
00068 *code_buf_pos++ = c;
00069 return 0;
00070 }
00071
00072
00073 int
00074 tty_filter_init(drivername, notfirst, pargc, argv)
00075 char *drivername;
00076 char notfirst;
00077 int *pargc;
00078 char **argv;
00079 {
00080 static char st_buf[128];
00081 char tc_buf[1024], *p = st_buf, *tmp, *term;
00082 int ex;
00083 string_dictionary_binding *b;
00084 int isrealtty = string_Eq(drivername, "tty");
00085 #ifdef HAVE_TERMIOS_H
00086 struct termios tbuf;
00087
00088 ospeed = (tcgetattr(STDIN_FILENO, &tbuf) == 0) ? cfgetospeed(&tbuf) : 2400;
00089 #else
00090 struct sgttyb sgttyb;
00091
00092 ospeed = (ioctl(0, TIOCGETP, &sgttyb) == 0) ? sgttyb.sg_ospeed : 2400;
00093 #endif
00094
00095 if (termcap_dict == (string_dictionary) NULL)
00096 termcap_dict = string_dictionary_Create(7);
00097
00098 if (!(term = getenv("TERM"))) {
00099 if (isrealtty && !notfirst)
00100
00101
00102
00103
00104 ERROR("$TERM not set. tty mode will be plain.\n");
00105 }
00106 #ifdef _AIX
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 else if (!strcmp(term, "dumb")) {
00117 }
00118 #endif
00119 else {
00120 tgetent(tc_buf, term);
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 tmp = tgetstr("pc", &p);
00134 PC = (tmp) ? *tmp : 0;
00135 if ((tmp = tgetstr("md", &p))) {
00136 EXPAND("B.bold");
00137 tmp = tgetstr("me", &p);
00138 EXPAND("E.bold");
00139 }
00140 if ((tmp = tgetstr("mr", &p))) {
00141 EXPAND("B.rw");
00142 tmp = tgetstr("me", &p);
00143 EXPAND("E.rw");
00144 }
00145 if ((tmp = tgetstr("bl", &p))) {
00146 EXPAND("B.bell");
00147 TD_SET("E.bell", NULL);
00148 }
00149 if ((tmp = tgetstr("mb", &p))) {
00150 EXPAND("B.blink");
00151 tmp = tgetstr("me", &p);
00152 EXPAND("E.blink");
00153 }
00154 if ((tmp = tgetstr("us", &p))) {
00155 EXPAND("B.u");
00156 tmp = tgetstr("ue", &p);
00157 EXPAND("E.u");
00158 }
00159 if ((tmp = tgetstr("so", &p))) {
00160 EXPAND("B.so");
00161 tmp = tgetstr("se", &p);
00162 EXPAND("E.so");
00163 }
00164 }
00165
00166
00167
00168 if (NULL == string_dictionary_Lookup(termcap_dict, "B.bold")) {
00169 if ((b = string_dictionary_Lookup(termcap_dict, "B.so"))) {
00170 TD_SET("B.bold", b->value);
00171 TD_SET("E.bold",
00172 string_dictionary_Lookup(termcap_dict, "E.so")->value);
00173 }
00174 else if ((b = string_dictionary_Lookup(termcap_dict, "B.rv"))) {
00175 TD_SET("B.bold", b->value);
00176 TD_SET("E.bold",
00177 string_dictionary_Lookup(termcap_dict, "E.rv")->value);
00178 }
00179 else if ((b = string_dictionary_Lookup(termcap_dict, "B.u"))) {
00180 TD_SET("B.bold", b->value);
00181 TD_SET("E.bold",
00182 string_dictionary_Lookup(termcap_dict, "E.u")->value);
00183 }
00184 }
00185
00186
00187 if (NULL == string_dictionary_Lookup(termcap_dict, "B.bell")) {
00188 TD_SET("B.bell", "\007");
00189 TD_SET("E.bell", NULL);
00190 }
00191
00192
00193
00194
00195 return (0);
00196 }
00197
00198
00199
00200
00201
00202
00203 static int
00204 fixed_string_eq(pattern, text, text_length)
00205 string pattern;
00206 char *text;
00207 int text_length;
00208 {
00209 while (*pattern && text_length > 0 && *pattern == *text) {
00210 pattern++;
00211 text++;
00212 text_length--;
00213 }
00214
00215 return (!*pattern && !text_length);
00216 }
00217
00218 typedef struct _tty_str_info {
00219 struct _tty_str_info *next;
00220
00221 char *str;
00222 int len;
00223
00224 char alignment;
00225 int bold_p:1;
00226 int italic_p:1;
00227 int bell_p:1;
00228 int ignore:1;
00229 } tty_str_info;
00230
00231 static void
00232 free_info(info)
00233 tty_str_info *info;
00234 {
00235 tty_str_info *next_info;
00236
00237 while (info) {
00238 next_info = info->next;
00239 free(info);
00240 info = next_info;
00241 }
00242 }
00243
00244 static int
00245 do_mode_change(current_mode_p, text, text_length)
00246 tty_str_info *current_mode_p;
00247 char *text;
00248 int text_length;
00249 {
00250
00251 if (fixed_string_eq("left", text, text_length) ||
00252 fixed_string_eq("l", text, text_length))
00253 current_mode_p->alignment = 'l';
00254 else if (fixed_string_eq("center", text, text_length) ||
00255 fixed_string_eq("c", text, text_length))
00256 current_mode_p->alignment = 'c';
00257 else if (fixed_string_eq("right", text, text_length) ||
00258 fixed_string_eq("r", text, text_length))
00259 current_mode_p->alignment = 'r';
00260
00261
00262 else if (fixed_string_eq("bold", text, text_length) ||
00263 fixed_string_eq("b", text, text_length))
00264 current_mode_p->bold_p = 1;
00265 else if (fixed_string_eq("italic", text, text_length) ||
00266 fixed_string_eq("i", text, text_length))
00267 current_mode_p->italic_p = 1;
00268 else if (fixed_string_eq("roman", text, text_length)) {
00269 current_mode_p->bold_p = 0;
00270 current_mode_p->italic_p = 0;
00271 }
00272 else if (fixed_string_eq("beep", text, text_length)) {
00273 current_mode_p->bell_p = 1;
00274 return 1;
00275 }
00276
00277
00278 else if (fixed_string_eq("color", text, text_length) ||
00279 fixed_string_eq("font", text, text_length)) {
00280 current_mode_p->ignore = 1;
00281 }
00282 return 0;
00283 }
00284
00285 static tty_str_info *
00286 convert_desc_to_tty_str_info(desc)
00287 desctype *desc;
00288 {
00289 tty_str_info *temp;
00290 tty_str_info *result = NULL;
00291 tty_str_info *last_result_block = NULL;
00292 int isbeep, did_beep = 0;
00293
00294 #if !defined(SABER) && defined(__STDC__)
00295 tty_str_info current_mode = {NULL, "", 0, 'l', 0, 0, 0, 0};
00296 #else
00297
00298
00299
00300
00301 tty_str_info current_mode;
00302
00303 current_mode.next = NULL;
00304 current_mode.str = "";
00305 current_mode.len = 0;
00306 current_mode.alignment = 'l';
00307 current_mode.bold_p = 0;
00308 current_mode.italic_p = 0;
00309 current_mode.bell_p = 0;
00310 current_mode.ignore = 0;
00311 #endif
00312
00313 for (; desc->code != DT_EOF; desc = desc->next) {
00314 isbeep = 0;
00315
00316 if (desc->code == DT_ENV) {
00317
00318 temp = (tty_str_info *) malloc(sizeof(struct _tty_str_info));
00319 *temp = current_mode;
00320 current_mode.next = temp;
00321
00322 isbeep = do_mode_change(¤t_mode, desc->str, desc->len);
00323 if (!isbeep || did_beep)
00324 continue;
00325
00326 }
00327 else if (desc->code == DT_END) {
00328
00329 temp = current_mode.next;
00330 current_mode = *temp;
00331 free(temp);
00332 continue;
00333 }
00334
00335
00336 temp = (tty_str_info *) malloc(sizeof(struct _tty_str_info));
00337 if (last_result_block) {
00338 last_result_block->next = temp;
00339 last_result_block = temp;
00340 }
00341 else {
00342 result = temp;
00343 last_result_block = temp;
00344 }
00345
00346 if (isbeep) {
00347
00348 string_dictionary_binding *b;
00349 b = string_dictionary_Lookup(termcap_dict, "B.bell");
00350 if (b) {
00351 temp->str = b->value;
00352 temp->len = string_Length(temp->str);
00353 }
00354 else
00355
00356 abort();
00357 did_beep++;
00358 continue;
00359 }
00360 if (desc->code == DT_STR) {
00361
00362 *temp = current_mode;
00363 temp->str = desc->str;
00364 temp->len = desc->len;
00365 }
00366 else if (desc->code == DT_NL) {
00367
00368
00369
00370
00371 temp->alignment = ' ';
00372 temp->len = 0;
00373 }
00374 }
00375
00376 if (last_result_block)
00377 last_result_block->next = NULL;
00378
00379 return (result);
00380 }
00381
00382 #define max(a,b) ((a)>(b)?(a):(b))
00383
00384 static int
00385 line_width(left_width, center_width, right_width)
00386 int left_width;
00387 int center_width;
00388 int right_width;
00389 {
00390 if (center_width > 0) {
00391 if (left_width == 0 && right_width == 0)
00392 return (center_width);
00393 return (center_width + 2 + max(left_width, right_width) * 2);
00394 }
00395 else {
00396 if (left_width && right_width)
00397 return (1 + left_width + right_width);
00398 else
00399 return (left_width + right_width);
00400 }
00401 }
00402
00403 static int
00404 calc_max_line_width(info)
00405 tty_str_info *info;
00406 {
00407 int max_line_width = 0;
00408 int left = 0;
00409 int center = 0;
00410 int right = 0;
00411
00412 for (; info; info = info->next) {
00413 switch (info->alignment) {
00414 case 'l':
00415 left += info->len;
00416 break;
00417
00418 case 'c':
00419 center += info->len;
00420 break;
00421
00422 case 'r':
00423 right += info->len;
00424 break;
00425
00426 case ' ':
00427 max_line_width = max(max_line_width,
00428 line_width(left, center, right));
00429 left = center = right = 0;
00430 break;
00431 }
00432 }
00433
00434 max_line_width = max(max_line_width,
00435 line_width(left, center, right));
00436
00437 return (max_line_width);
00438 }
00439
00440 string
00441 tty_filter(text, use_fonts)
00442 string text;
00443 int use_fonts;
00444 {
00445 string text_copy = string_Copy(text);
00446 string result_so_far = string_Copy("");
00447 desctype *desc;
00448 int number_of_strs;
00449 int number_of_lines;
00450 tty_str_info *info;
00451 int max_line_width;
00452
00453 desc = disp_get_cmds(text_copy, &number_of_strs, &number_of_lines);
00454 info = convert_desc_to_tty_str_info(desc);
00455 free_desc(desc);
00456
00457 max_line_width = calc_max_line_width(info);
00458 dprintf(dOutput, "max width = %d\n", max_line_width);
00459
00460 while (info) {
00461 string left, center, right;
00462 int left_width, center_width, right_width;
00463 char *temp;
00464
00465 left_width = center_width = right_width = 0;
00466 left = string_Copy("");
00467 center = string_Copy("");
00468 right = string_Copy("");
00469
00470 for (; info && info->alignment != ' '; info = info->next) {
00471 string item;
00472
00473 if (info->ignore)
00474 continue;
00475
00476 item = string_Copy("");
00477
00478 if (info->bold_p && use_fonts) {
00479 if ((temp = string_dictionary_Fetch(termcap_dict, "B.bold")))
00480 item = string_Concat2(item, temp);
00481 }
00482 else if (info->italic_p && use_fonts) {
00483 if ((temp = string_dictionary_Fetch(termcap_dict, "B.u")))
00484 item = string_Concat2(item, temp);
00485 }
00486 temp = string_CreateFromData(info->str, info->len);
00487 item = string_Concat2(item, temp);
00488 free(temp);
00489
00490 if (info->bold_p && use_fonts) {
00491 if ((temp = string_dictionary_Fetch(termcap_dict, "E.bold")))
00492 item = string_Concat2(item, temp);
00493 }
00494 else if (info->italic_p && use_fonts) {
00495 if ((temp = string_dictionary_Fetch(termcap_dict, "E.u")))
00496 item = string_Concat2(item, temp);
00497 }
00498
00499 switch (info->alignment) {
00500 default:
00501 case 'l':
00502 left = string_Concat2(left, item);
00503 left_width += info->len;
00504 break;
00505
00506 case 'c':
00507 center = string_Concat2(center, item);
00508 center_width += info->len;
00509 break;
00510
00511 case 'r':
00512 right = string_Concat2(right, item);
00513 right_width += info->len;
00514 break;
00515 }
00516 free(item);
00517 }
00518
00519 result_so_far = string_Concat2(result_so_far, left);
00520 if (center_width)
00521 while (left_width < (max_line_width - center_width) / 2) {
00522 result_so_far = string_Concat2(result_so_far, " ");
00523 left_width++;
00524 }
00525 result_so_far = string_Concat2(result_so_far, center);
00526 left_width += center_width;
00527
00528 if (right_width)
00529 while (left_width < max_line_width - right_width) {
00530 result_so_far = string_Concat2(result_so_far, " ");
00531 left_width++;
00532 }
00533 result_so_far = string_Concat2(result_so_far, right);
00534 free(left);
00535 free(center);
00536 free(right);
00537
00538 if (info && info->alignment == ' ') {
00539 info = info->next;
00540 result_so_far = string_Concat2(result_so_far, "\r\n");
00541 }
00542 }
00543
00544 free_info(info);
00545 free(text_copy);
00546 if (number_of_lines &&
00547 (result_so_far[string_Length(result_so_far) - 1] != '\n'))
00548
00549 result_so_far = string_Concat2(result_so_far, "\r\n");
00550 return (result_so_far);
00551 }