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

formatter.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 #include "char_stack.h"
00012 #include "string_dictionary.h"
00013 #include "formatter.h"
00014 #include "text_operations.h"
00015 
00016 #if !defined(__STDC__) && !defined(const)
00017 #define const
00018 #endif
00019 
00020 static int pure_text_length(), env_length();
00021 
00022 static const character_class paren_set = {      /* '(' = 0x28, ')' = 0x29 */
00023         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00024         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00025         0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
00026         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00027         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00028         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00029         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00030         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00031         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00032         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00033         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00034         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00035         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00036         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00037         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00038         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00039 };
00040 
00041 static const character_class sbracket_set = {   /* '[' = 0x5b, ']' = 0x5d */
00042         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00043         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00044         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00045         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00046         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00047         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00048         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00049         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00050         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00051         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00052         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00053         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00054         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00055         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00056         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00057         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00058 };
00059 
00060 static const character_class abracket_set = {   /* '<' = 0x3c, '>' = 0x3e */
00061         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00062         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00063         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00064         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
00065         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00066         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00067         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00068         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00069         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00070         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00071         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00072         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00073         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00074         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00075         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00076         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00077 };
00078 
00079 static const character_class cbracket_set = {   /* '{' = 0x7b, '}' = 0x7d */
00080         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00081         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00082         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00083         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00084         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00085         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00086         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00087         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00088         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00089         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00090         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00091         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00092         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00093         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00094         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00095         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00096 };
00097 
00098 static const character_class allbracket_set = {
00099         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00100         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00101         0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
00102         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
00103         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00104         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00105         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00106         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00107         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00108         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00109         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00110         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00111         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00112         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00113         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00114         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00115 };
00116 
00117 static const character_class allmaskable_set = {
00118         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00119         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00120         0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
00121         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
00122         1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00123         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00124         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00125         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00126         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00127         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00128         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00129         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00130         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00131         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00132         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00133         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00134 };
00135 
00136 static char brackets[] = "()<>[]{}@";
00137 static char *openbracket[] = {"@<", "@<", "@[", "@[", "@{", "@{", "@(", "@(", "@("};
00138 static char *closebracket[] = {">", ">", "]", "]", "}", "}", ")", ")", ")"};
00139 
00140 static int 
00141 not_contains(str, set)
00142         string str;
00143         const character_class set;
00144 {
00145         while (*str && !set[(int) *str])
00146                 str++;
00147         return (!*str);
00148 }
00149 
00150 static int 
00151 pure_text_length(text, terminator)
00152         char *text;
00153         char terminator;
00154 {
00155         int len = 0;
00156 
00157         while (1) {
00158                 while (*text != '@' && *text != terminator && *text) {
00159                         text++;
00160                         len++;
00161                 }
00162 
00163                 if (*text != '@')
00164                         return (len);
00165 
00166                 if (*(text + 1) == '@') {
00167                         text++;
00168                         len++;
00169                 }
00170                 else if (env_length(text + 1) != -1)
00171                         return (len);
00172 
00173                 text++;
00174                 len++;
00175         }
00176 }
00177 
00178 static char 
00179 otherside(opener)
00180         char opener;
00181 {
00182         switch (opener) {
00183                 case '(':
00184                         return (')');
00185                 case '{':
00186                         return ('}');
00187                 case '[':
00188                         return (']');
00189                 case '<':
00190                         return ('>');
00191         }
00192 
00193         return (0);
00194 }
00195 
00196 /*
00197  * the char * that str points to is free'd by this function. if you want to
00198  * keep it, save it yourself
00199  */
00200 string 
00201 verbatim(str, bracketsonly)
00202         string str;
00203         int bracketsonly;
00204 {
00205         char *temp, *temp2;
00206         int bracketnum, len;
00207 
00208         if (strlen(str) == pure_text_length(str, 0)) {
00209                 /* No environments, so consider the fast-and-easy methods */
00210 
00211                 if (not_contains(str, allbracket_set)) {
00212                         temp = string_Copy(str);
00213                         free(str);
00214                         return (temp);
00215                 }
00216 
00217                 if (not_contains(str, abracket_set)) {
00218                         temp = (char *) malloc((len = strlen(str)) + 4);
00219                         temp[0] = '@';
00220                         temp[1] = '<';
00221                         (void) memcpy(temp + 2, str, len);
00222                         temp[len + 2] = '>';
00223                         temp[len + 3] = '\0';
00224                         free(str);
00225                         return (temp);
00226                 }
00227                 if (not_contains(str, sbracket_set)) {
00228                         temp = (char *) malloc((len = strlen(str)) + 4);
00229                         temp[0] = '@';
00230                         temp[1] = '[';
00231                         (void) memcpy(temp + 2, str, len);
00232                         temp[len + 2] = ']';
00233                         temp[len + 3] = '\0';
00234                         free(str);
00235                         return (temp);
00236                 }
00237                 if (not_contains(str, cbracket_set)) {
00238                         temp = (char *) malloc((len = strlen(str)) + 4);
00239                         temp[0] = '@';
00240                         temp[1] = '{';
00241                         (void) memcpy(temp + 2, str, len);
00242                         temp[len + 2] = '}';
00243                         temp[len + 3] = '\0';
00244                         free(str);
00245                         return (temp);
00246                 }
00247                 if (not_contains(str, paren_set)) {
00248                         temp = (char *) malloc((len = strlen(str)) + 4);
00249                         temp[0] = '@';
00250                         temp[1] = '(';
00251                         (void) memcpy(temp + 2, str, len);
00252                         temp[len + 2] = ')';
00253                         temp[len + 3] = '\0';
00254                         free(str);
00255                         return (temp);
00256                 }
00257         }
00258 
00259         temp = lbreak(&str, bracketsonly ? allbracket_set : allmaskable_set);
00260         while (*str) {
00261                 bracketnum = (int) (strchr(brackets, str[0]) - brackets);
00262                 temp = string_Concat2(temp, openbracket[bracketnum]);
00263                 temp = string_Concat2(temp, temp2 = lany(&str, " "));
00264                 free(temp2);
00265                 temp = string_Concat2(temp, closebracket[bracketnum]);
00266                 temp = string_Concat2(temp, temp2 = lbreak(&str, bracketsonly ?
00267                                          allbracket_set : allmaskable_set));
00268                 free(temp2);
00269         }
00270         free(str);              /* str is "" at this point, anyway */
00271 
00272         return (temp);
00273 }
00274 
00275 /*
00276  * text points to beginning of text string.  return value is length of
00277  * string, up to but not including the passed terminator or the default
00278  * terminator \0.  The text will not be modified, and @@ will be counted
00279  * twice
00280  */
00281 
00282 string 
00283 protect(str)
00284         string str;
00285 {
00286         string temp, temp2, temp3;
00287         int len, templen;
00288         char_stack chs;
00289         char tos;
00290 
00291         temp = string_Copy("");
00292         templen = 1;
00293         chs = char_stack_create();
00294 
00295         while (*str) {
00296                 tos = (char_stack_empty(chs) ? 0 : char_stack_top(chs));
00297 
00298                 if (*str == tos) {
00299                         /* if the character is the next terminator */
00300 
00301                         temp = (char *) realloc(temp, ++templen);
00302                         temp[templen - 2] = *str++;
00303                         char_stack_pop(chs);
00304                         temp[templen - 1] = '\0';
00305                 }
00306                 else if ((len = pure_text_length(str, tos))) {
00307                         if (tos) {
00308                                 /*
00309                                  * if the block is text in an environment,
00310                                  * just copy it
00311                                  */
00312 
00313                                 temp2 = string_CreateFromData(str, len);
00314                                 str += len;
00315                                 temp = string_Concat2(temp, temp2);
00316                                 templen += len;
00317                                 free(temp2);
00318                         }
00319                         else {
00320                                 /*
00321                                  * if the block is top level text, verbatim
00322                                  * brackets only (not @'s) and add text to
00323                                  * temp
00324                                  */
00325 
00326                                 temp2 = string_CreateFromData(str, len);
00327                                 str += len;
00328                                 temp3 = verbatim(temp2, 1);
00329                                 temp = string_Concat2(temp, temp3);
00330                                 templen += strlen(temp3);
00331                                 free(temp3);
00332                         }
00333                 }
00334                 else {
00335                         /*
00336                          * if the block is an environment, copy it, push
00337                          * delimiter
00338                          */
00339 
00340                         len = env_length(str + 1);
00341                         char_stack_push(chs, otherside(str[len + 1]));
00342                         len += 2;
00343                         temp2 = string_CreateFromData(str, len);
00344                         str += len;
00345                         temp = string_Concat2(temp, temp2);
00346                         templen += len;
00347                         free(temp2);
00348                 }
00349         }
00350         /* all blocks have been copied. */
00351 
00352         while (!char_stack_empty(chs)) {
00353                 temp = (char *) realloc(temp, ++templen);
00354                 temp[templen - 2] = char_stack_top(chs);
00355                 char_stack_pop(chs);
00356         }
00357         temp[templen - 1] = '\0';
00358 
00359         return (temp);
00360 }
00361 
00362 void 
00363 free_desc(desc)
00364         desctype *desc;
00365 {
00366         desctype *next_desc;
00367 
00368         while (desc->code != DT_EOF) {
00369                 next_desc = desc->next;
00370                 free(desc);
00371                 desc = next_desc;
00372         }
00373         free(desc);
00374 }
00375 
00376 /*
00377  * text points to beginning of possible env name.  return value is length of
00378  * env name, not including @ or opener, or -1 if not a possible env name.
00379  */
00380 static int 
00381 env_length(text)
00382         char *text;
00383 {
00384         int len = 0;
00385 
00386         while (*text && (isalnum(*text) || *text == '_')) {
00387                 text++;
00388                 len++;
00389         }
00390 
00391         if ((*text == '(') || (*text == '{') || (*text == '[') || (*text == '<'))
00392                 return (len);
00393         else
00394                 return (-1);
00395 }
00396 
00397 /*
00398  * text points to beginning of text string.  return value is length of
00399  * string, up to but not including the passed terminator or the default
00400  * terminators \0 \n @.  This can modify text, and 0 is a valid return value.
00401  */
00402 static int 
00403 text_length(text, terminator)
00404         char *text;
00405         char terminator;
00406 {
00407         int len = 0;
00408 
00409         while (1) {
00410                 while (*text != '@' && *text != '\n' && *text != terminator && *text) {
00411                         text++;
00412                         len++;
00413                 }
00414 
00415                 if (*text != '@')
00416                         return (len);
00417 
00418                 if (*(text + 1) == '@')
00419                         (void) memmove(text + 1, text + 2, strlen(text + 1));
00420                 else if (env_length(text + 1) != -1)
00421                         return (len);
00422 
00423                 text++;
00424                 len++;
00425         }
00426 }
00427 
00428 /*
00429  * parses str into a desc linked list.  Returns number of strings and
00430  * newlines in *pstr and *pnl
00431  */
00432 
00433 desctype *
00434 disp_get_cmds(str, pstr, pnl)
00435         char *str;
00436         int *pstr, *pnl;
00437 {
00438         desctype *desc, *here;
00439         int len;
00440         char_stack terminators = char_stack_create();
00441         char terminator;
00442         int nstr = 0, nnl = 0;
00443         char *curstr;
00444 
00445         desc = (desctype *) malloc(sizeof(desctype));
00446         here = desc;
00447         curstr = str;
00448         terminator = '\0';
00449 
00450         while (*curstr) {
00451                 if (*curstr == '\n') {
00452                         here->code = DT_NL;
00453                         curstr++;
00454                         nnl++;
00455                 }
00456                 else if (*curstr == terminator) {       /* if this is the end of
00457                                                          * an env */
00458                         here->code = DT_END;
00459                         terminator = char_stack_top(terminators);
00460                         char_stack_pop(terminators);
00461                         curstr++;
00462                 }
00463                 else if ((len = text_length(curstr, terminator))) {     /* if there is a text
00464                                                                          * block here */
00465                         here->code = DT_STR;
00466                         here->str = curstr;
00467                         here->len = len;
00468                         curstr += len;
00469                         nstr++;
00470                 }
00471                 else if (*curstr == '@') {      /* if this is the beginning
00472                                                  * of an env */
00473                         len = env_length(curstr + 1);
00474                         here->code = DT_ENV;
00475                         here->str = curstr + 1;
00476                         here->len = len;
00477                         char_stack_push(terminators, terminator);
00478                         terminator = otherside(*(curstr + 1 + len));
00479                         curstr += (len + 2);    /* jump over @, env name, and
00480                                                  * opener */
00481                 }
00482 
00483                 here->next = (desctype *) malloc(sizeof(desctype));
00484                 here = here->next;
00485         }
00486 
00487         while (!char_stack_empty(terminators)) {
00488                 here->code = DT_END;
00489                 terminator = char_stack_top(terminators);
00490                 char_stack_pop(terminators);
00491                 here->next = (desctype *) malloc(sizeof(desctype));
00492                 here = here->next;
00493         }
00494         here->code = DT_EOF;
00495         *pstr = nstr;
00496         *pnl = nnl;
00497 
00498         return (desc);
00499 }


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