Jabber WindowGram Client (JWGC)

Introduction Screenshots Installation Downloads
Documentation Browse Source Resources Project Site

Stable Version
-none-

Latest Version
beta5



Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

tty_filter.c

Go to the documentation of this file.
00001 /*
00002  *      Copyright (c) 1989 by the Massachusetts Institute of Technology.
00003  *      For copying and distribution information, see the file
00004  *      "mit-copyright.h".
00005  *
00006  *      Modified for jwgc by Daniel Henninger.
00007  */
00008 
00009 #include "mit-copyright.h"
00010 
00011 /****************************************************************************/
00012 /* */
00013 /* The tty & plain filters:                         */
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  * Dictionary naming convention:
00033  * 
00034  * B.xxx is the termcap sequence to begin environment xxx. E.xxx is the termcap
00035  * sequence to end environment xxx.
00036  * 
00037  */
00038 
00039 static string_dictionary termcap_dict;
00040 static char code_buf[10240], *code_buf_pos = code_buf, *code;
00041 
00042 /*
00043  * Define the following commands:
00044  * 
00045  * (Hopefully) shared with all devices:
00046  * 
00047  * @center      Guess.
00048  * 
00049  * @em          Emphasis.  User underline if available, else reverse video.
00050  * @bold        Bold letters.  If not available, reverse video, else
00051  * underline. @beep     "bl" termcap entry, else "^G"
00052  * 
00053  * Other:
00054  * 
00055  * @blink       "mb"/"me" termcap entry, else nothing. @rv              "so"/"se"
00056  * termcap entry. @u            "us"/"ue" termcap entry.
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 /* ARGSUSED */
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"))) { /* Only use termcap if $TERM.    */
00099                 if (isrealtty && !notfirst)
00100                         /*
00101                          * only complain if initializing tty mode, and would
00102                          * be first available port
00103                          */
00104                         ERROR("$TERM not set.  tty mode will be plain.\n");
00105         }
00106 #ifdef _AIX
00107         /*
00108          * This is a temporary KLUDGE to get around the problem where some
00109          * people might start jwgc in their ~/.startup.X and it hangs on the
00110          * RISC/6000. Apparently, the call to tgetent() with the Athena
00111          * console window causes the process to get stopped on tty access.
00112          * Since the terminal type is "dumb" (set by tcsh), we can pretty
00113          * much assume there isn't anything to setup from the termcap
00114          * information.
00115          */
00116         else if (!strcmp(term, "dumb")) {
00117         }
00118 #endif
00119         else {
00120                 tgetent(tc_buf, term);
00121 
00122                 /*
00123                  * Step 1: get all of {rv,bold,u,bell,blink} that are
00124                  * available.
00125                  */
00126 
00127                 /*
00128                  * We cheat here, and ignore the padding (if any) specified
00129                  * for the mode-change strings (it's a real pain to do
00130                  * "right")
00131                  */
00132 
00133                 tmp = tgetstr("pc", &p);
00134                 PC = (tmp) ? *tmp : 0;
00135                 if ((tmp = tgetstr("md", &p))) {        /* bold ? */
00136                         EXPAND("B.bold");
00137                         tmp = tgetstr("me", &p);
00138                         EXPAND("E.bold");
00139                 }
00140                 if ((tmp = tgetstr("mr", &p))) {        /* reverse video? */
00141                         EXPAND("B.rw");
00142                         tmp = tgetstr("me", &p);
00143                         EXPAND("E.rw");
00144                 }
00145                 if ((tmp = tgetstr("bl", &p))) {        /* Bell ? */
00146                         EXPAND("B.bell");
00147                         TD_SET("E.bell", NULL);
00148                 }
00149                 if ((tmp = tgetstr("mb", &p))) {        /* Blink ? */
00150                         EXPAND("B.blink");
00151                         tmp = tgetstr("me", &p);
00152                         EXPAND("E.blink");
00153                 }
00154                 if ((tmp = tgetstr("us", &p))) {        /* Underline ? */
00155                         EXPAND("B.u");
00156                         tmp = tgetstr("ue", &p);
00157                         EXPAND("E.u");
00158                 }
00159                 if ((tmp = tgetstr("so", &p))) {        /* Standout ? */
00160                         EXPAND("B.so");
00161                         tmp = tgetstr("se", &p);
00162                         EXPAND("E.so");
00163                 }
00164         }
00165         /* Step 2: alias others to the nearest substitute */
00166 
00167         /* Bold = so, else rv, else ul */
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         /* Bell = ^G */
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         /* Underline -> nothing */
00193         /* Blink -> nothing */
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;         /* 'l', 'c', 'r', or ' ' to indicate newline */
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         /* alignment commands: */
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         /* font commands: */
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         /* commands ignored in tty mode: */
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          * This is needed due to a bug in saber, and lack of pre-ANSI
00299          * support.
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                 /* Handle environments: */
00316                 if (desc->code == DT_ENV) {
00317                         /* PUSH! */
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(&current_mode, desc->str, desc->len);
00323                         if (!isbeep || did_beep)
00324                                 continue;       /* process one beep, ignore
00325                                                  * other envs */
00326                 }
00327                 else if (desc->code == DT_END) {
00328                         /* POP! */
00329                         temp = current_mode.next;
00330                         current_mode = *temp;
00331                         free(temp);
00332                         continue;
00333                 }
00334 
00335                 /* Add new block (call it temp) to result: */
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                         /* special processing: need to insert a bell */
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                                 /* shouldn't get here! */
00356                                 abort();
00357                         did_beep++;
00358                         continue;
00359                 }
00360                 if (desc->code == DT_STR) {
00361                         /* just combine string info with current mode: */
00362                         *temp = current_mode;
00363                         temp->str = desc->str;
00364                         temp->len = desc->len;
00365                 }
00366                 else if (desc->code == DT_NL) {
00367                         /*
00368                          * make the new block a ' ' alignment block with an
00369                          * empty string
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                 /* CRLF-terminate all results */
00549                 result_so_far = string_Concat2(result_so_far, "\r\n");
00550         return (result_so_far);
00551 }


Last updated at Tue Dec 18 21:07:42 PST 2007. This site and project hosted by...SourceForge.net Logo
Source Perspective by Fisheye