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

xshow.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 #ifndef X_DISPLAY_MISSING
00012 
00013 #include <X11/Xlib.h>
00014 #include <X11/Xutil.h>
00015 #include <X11/Xresource.h>
00016 #include "pointer_dictionary.h"
00017 #include "formatter.h"
00018 #include "variables.h"
00019 #include "main.h"
00020 #include "X_fonts.h"
00021 #include "X_gram.h"
00022 #include "xmode_stack.h"
00023 
00024 #define max(a,b)   ((a)>(b)?(a):(b))
00025 
00026 XContext desc_context;
00027 
00028 extern int internal_border_width;
00029 extern unsigned long default_bgcolor;
00030 extern unsigned long default_fgcolor;
00031 extern unsigned long x_string_to_color();
00032 
00033 void 
00034 xshowinit()
00035 {
00036         desc_context = XUniqueContext();
00037 }
00038 
00039 struct res_dict_type {
00040         pointer_dictionary dict;
00041         char *resname_suffix;
00042         char *resclass;
00043 };
00044 
00045 static char *
00046 xres_get_resource(restype, style)
00047         struct res_dict_type *restype;
00048         char *style;
00049 {
00050         char *desc;
00051         pointer_dictionary_binding *binding;
00052         int exists;
00053         char *value;
00054 
00055         desc = string_Concat("style.", style);
00056         desc = string_Concat2(desc, restype->resname_suffix);
00057 
00058         if (!restype->dict)
00059                 restype->dict = pointer_dictionary_Create(37);
00060         binding = pointer_dictionary_Define(restype->dict, desc, &exists);
00061 
00062         if (exists) {
00063                 free(desc);
00064                 return ((string) binding->value);
00065         }
00066         else {
00067                 value = get_string_resource(desc, restype->resclass);
00068                 free(desc);
00069                 if (value == NULL)
00070                         pointer_dictionary_Delete(restype->dict, binding);
00071                 else
00072                         binding->value = (pointer) value;
00073                 return value;   /* If resource returns NULL, return NULL also */
00074         }
00075 }
00076 
00077 static struct res_dict_type geometry_resources = {
00078         NULL, ".geometry", "StyleKey.Style1.Style2.Style3.Style4.GeometryKey",
00079 };
00080 
00081 static struct res_dict_type bgcolor_resources = {
00082         NULL, ".background", "StyleKey.Style1.Style2.Style3.Style4.BackgroundKey",
00083 };
00084 
00085 #define xres_get_geometry(style) xres_get_resource(&geometry_resources,style)
00086 #define xres_get_bgcolor(style)  xres_get_resource(&bgcolor_resources,style)
00087 
00088 static struct res_dict_type fgcolor_resources = {
00089         NULL, ".foreground",
00090         "StyleKey.Style1.Style2.Style3.Style4.SubstyleKey.Substyle.ForegroundKey",
00091 };
00092 
00093 /* ARGSUSED */
00094 char *
00095 mode_to_colorname(dpy, style, mode)
00096         Display *dpy;
00097         char *style;
00098         xmode *mode;
00099 {
00100         char *desc, *result;
00101 
00102         desc = string_Concat(style, ".substyle.");
00103         desc = string_Concat2(desc, mode->substyle);
00104         result = xres_get_resource(&fgcolor_resources, desc);
00105         free(desc);
00106         return result;
00107 }
00108 
00109 void 
00110 fixup_and_draw(dpy, style, auxblocks, blocks, num, lines, numlines,
00111                beepcount)
00112         Display *dpy;
00113         char *style;
00114         xblock *blocks;
00115         xauxblock *auxblocks;
00116         int num;
00117         xlinedesc *lines;
00118         int numlines;
00119         int beepcount;
00120 {
00121         int gram_xalign = 1;
00122         int gram_yalign = 1;
00123         int gram_xpos, gram_ypos, gram_xsize, gram_ysize;
00124 
00125         x_gram *gram;
00126         int strindex = 0;
00127 
00128         int line, block = 0;
00129         int maxwidth = 0, chars = 0, maxascent, maxdescent;
00130         int ssize, lsize, csize, rsize, width = 0;
00131         int i, ascent, descent;
00132 
00133         int yofs = internal_border_width;
00134         int lofs, cofs, rofs;
00135         int ystart, yend;
00136 
00137         char *bgstr, *geometry, xpos[10], ypos[10], xfrom, yfrom;
00138 
00139         gram = (x_gram *) malloc(sizeof(x_gram));
00140 
00141         /*
00142          * Find total lengths of left, center, and right parts.  Also find
00143          * the length of the longest line and the total number of characters.
00144          */
00145 
00146         for (line = 0; line < numlines; line++) {
00147                 lsize = csize = rsize = 0;
00148                 maxascent = maxdescent = 0;
00149 
00150                 /* add up sizes for each block, get max ascent and descent */
00151 
00152                 for (i = 0; i < lines[line].numblock; i++, block++) {
00153                         chars += auxblocks[block].len;
00154                         ssize = XTextWidth(auxblocks[block].font, auxblocks[block].str,
00155                                            auxblocks[block].len);
00156                         auxblocks[block].width = ssize;
00157                         ascent = auxblocks[block].font->ascent;
00158                         descent = auxblocks[block].font->descent;
00159                         if (ascent > maxascent)
00160                                 maxascent = ascent;
00161                         if (descent > maxdescent)
00162                                 maxdescent = descent;
00163                         switch (auxblocks[block].align) {
00164                                 case LEFTALIGN:
00165                                         lsize += ssize;
00166                                         break;
00167 
00168                                 case CENTERALIGN:
00169                                         csize += ssize;
00170                                         break;
00171 
00172                                 case RIGHTALIGN:
00173                                         rsize += ssize;
00174                                         break;
00175                         }
00176                 }
00177 
00178                 /* save what we need to do size fixups */
00179 
00180                 if (maxascent > lines[line].ascent)
00181                         lines[line].ascent = maxascent;
00182                 if (maxdescent > lines[line].descent)
00183                         lines[line].descent = maxdescent;
00184                 lines[line].lsize = lsize;
00185                 lines[line].csize = csize;
00186                 lines[line].rsize = rsize;
00187 
00188                 /*
00189                  * get width of line and see if it is bigger than the max
00190                  * width
00191                  */
00192 
00193                 switch ((lsize ? 1 : 0) + (csize ? 2 : 0) + (rsize ? 4 : 0)) {
00194                         case 0:
00195                                 width = 0;
00196                                 break;
00197 
00198                         case 1:
00199                                 width = lsize;
00200                                 break;
00201 
00202                         case 2:
00203                                 width = csize;
00204                                 break;
00205 
00206                         case 3:
00207                                 /*
00208                                  * in all these cases, we just want to add
00209                                  * the width of *any* space, so the first
00210                                  * font will do just fine.
00211                                  */
00212                                 /*
00213                                  * XXX implicit assumption that a line must
00214                                  * have at least one block, so that there is
00215                                  * indeed a reasonable font in
00216                                  * auxblocks[0].font
00217                                  */
00218                                 width = lsize * 2 + csize + XTextWidth(auxblocks[0].font, " ", 1);
00219                                 break;
00220 
00221                         case 4:
00222                                 width = rsize;
00223                                 break;
00224 
00225                         case 5:
00226                                 width = lsize + rsize + XTextWidth(auxblocks[0].font, " ", 1);
00227                                 break;
00228 
00229                         case 6:
00230                                 width = csize + rsize * 2 + XTextWidth(auxblocks[0].font, " ", 1);
00231                                 break;
00232 
00233                         case 7:
00234                                 width = max(lsize, rsize) * 2 + csize +
00235                                         XTextWidth(auxblocks[0].font, " ", 1) * 2;
00236                                 break;
00237                 }
00238                 if (width > maxwidth)
00239                         maxwidth = width;
00240         }
00241 
00242         /* fixup x,y for each block, create big string and indices into it */
00243         /* set x1,y1,x2,y2 of each block also. */
00244 
00245         gram->text = (char *) malloc(chars);
00246         block = 0;
00247 
00248         for (line = 0; line < numlines; line++) {
00249                 lofs = internal_border_width;
00250                 cofs = ((maxwidth - lines[line].csize) >> 1) + internal_border_width;
00251                 rofs = maxwidth - lines[line].rsize + internal_border_width;
00252                 ystart = yofs;
00253                 yofs += lines[line].ascent;
00254                 yend = yofs + lines[line].descent + 1;  /* +1 because lines look
00255                                                          * scrunched without it. */
00256 
00257                 for (i = 0; i < lines[line].numblock; i++, block++) {
00258                         blocks[block].fid = auxblocks[block].font->fid;
00259                         switch (auxblocks[block].align) {
00260                                 case LEFTALIGN:
00261                                         blocks[block].x = lofs;
00262                                         blocks[block].x1 = lofs;
00263                                         lofs += auxblocks[block].width;
00264                                         blocks[block].x2 = lofs;
00265                                         break;
00266 
00267                                 case CENTERALIGN:
00268                                         blocks[block].x = cofs;
00269                                         blocks[block].x1 = cofs;
00270                                         cofs += auxblocks[block].width;
00271                                         blocks[block].x2 = cofs;
00272                                         break;
00273 
00274                                 case RIGHTALIGN:
00275                                         blocks[block].x = rofs;
00276                                         blocks[block].x1 = rofs;
00277                                         rofs += auxblocks[block].width;
00278                                         blocks[block].x2 = rofs;
00279                                         break;
00280                         }
00281                         blocks[block].y = yofs;
00282                         blocks[block].y1 = ystart;
00283                         blocks[block].y2 = yend;
00284                         blocks[block].strindex = strindex;
00285                         blocks[block].strlen = auxblocks[block].len;
00286                         strncpy(gram->text + strindex, auxblocks[block].str,
00287                                 auxblocks[block].len);
00288                         strindex += blocks[block].strlen;
00289                 }
00290 
00291                 yofs = yend;
00292 
00293         }
00294 
00295         if ((geometry = var_get_variable("X_geometry")), (geometry[0] == '\0'))
00296                 if ((geometry = xres_get_geometry(style)) == NULL)
00297                         if ((geometry = var_get_variable("default_X_geometry")),
00298                             (geometry[0] == '\0'))
00299                                 geometry = "+0+0";
00300         sscanf(geometry, "%c%[0123456789c]%c%[0123456789c]", &xfrom, xpos,
00301                &yfrom, ypos);
00302 
00303         if (xpos[0] == 'c') {
00304                 gram_xalign = 0;
00305                 gram_xpos = 0;
00306         }
00307         else
00308                 gram_xpos = atoi(xpos);
00309         if (xfrom == '-')
00310                 gram_xalign *= -1;
00311 
00312         if (ypos[0] == 'c') {
00313                 gram_yalign = 0;
00314                 gram_ypos = 0;
00315         }
00316         else
00317                 gram_ypos = atoi(ypos);
00318         if (yfrom == '-')
00319                 gram_yalign *= -1;
00320 
00321         if ((bgstr = var_get_variable("X_background")), (bgstr[0] == '\0'))
00322                 if ((bgstr = xres_get_bgcolor(style)) == NULL)
00323                         if ((bgstr = var_get_variable("default_X_background")),
00324                             (bgstr[0] == '\0'))
00325                                 gram->bgcolor = default_bgcolor;
00326         if (bgstr && bgstr[0])
00327                 gram->bgcolor = x_string_to_color(bgstr, default_bgcolor);
00328 
00329 
00330         gram_xsize = maxwidth + (internal_border_width << 1);
00331         gram_ysize = yofs + internal_border_width;
00332         gram->numblocks = num;
00333         gram->blocks = blocks;
00334 
00335         x_gram_create(dpy, gram, gram_xalign, gram_yalign, gram_xpos,
00336                       gram_ypos, gram_xsize, gram_ysize, beepcount);
00337 }
00338 
00339 /* Silly almost-but-not-quite-useless helper function */
00340 char *
00341 no_dots_downcase_var(str)
00342         char *str;
00343 {
00344         register char *var, *var2;
00345 
00346         var = string_Downcase(var_get_variable(str));
00347         var2 = var;
00348         while (*var++)
00349                 if (*var == '.')
00350                         *var = '_';
00351         return (var2);
00352 }
00353 
00354 #define MODE_TO_FONT(dpy,style,mode) \
00355   get_font((dpy),(style),(mode)->font?(mode)->font:(mode)->substyle, \
00356            (mode)->size, (mode)->bold+(mode)->italic*2)
00357 void 
00358 xshow(dpy, desc, numstr, numnl)
00359         Display *dpy;
00360         desctype *desc;
00361         int numstr;
00362         int numnl;
00363 {
00364         XFontStruct *font;
00365         xmode_stack modes = xmode_stack_create();
00366         xmode curmode;
00367         xlinedesc *lines;
00368         xblock *blocks;
00369         xauxblock *auxblocks;
00370         int nextblock = 0;
00371         int line = 0, linestart = 0;
00372         char *style;
00373         int free_style = 0;
00374         int beepcount = 0;
00375 
00376         lines = (xlinedesc *) malloc(sizeof(xlinedesc) * (numnl + 1));
00377 
00378         blocks = (xblock *) malloc(sizeof(xblock) * numstr);
00379         auxblocks = (xauxblock *) malloc(sizeof(xauxblock) * numstr);
00380 
00381         curmode.bold = 0;
00382         curmode.italic = 0;
00383         curmode.size = MEDIUM_SIZE;
00384         curmode.align = LEFTALIGN;
00385         curmode.expcolor = 0;
00386         curmode.substyle = string_Copy("default");
00387         curmode.font = NULL;
00388 
00389         style = var_get_variable("style");
00390         if (style[0] == '\0') {
00391                 style = string_Concat(no_dots_downcase_var("type"), ".");
00392                 style = string_Concat2(style, no_dots_downcase_var("subtype"));
00393                 style = string_Concat2(style, ".");
00394                 style = string_Concat2(style, no_dots_downcase_var("msgtype"));
00395                 style = string_Concat2(style, ".");
00396                 style = string_Concat2(style, no_dots_downcase_var("from"));
00397                 string_Downcase(style);
00398                 free_style = 1;
00399         }
00400 
00401         for (; desc->code != DT_EOF; desc = desc->next) {
00402                 switch (desc->code) {
00403                         case DT_ENV:
00404                                 xmode_stack_push(modes, curmode);
00405                                 curmode.substyle = string_Copy(curmode.substyle);
00406                                 if (curmode.font)
00407                                         curmode.font = string_Copy(curmode.font);
00408 
00409 #define envmatch(string,length) ((desc->len==(length)) && (strncasecmp(desc->str,(string),(length))==0))
00410 
00411                                 if (envmatch("roman", 5)) {
00412                                         curmode.bold = 0;
00413                                         curmode.italic = 0;
00414                                 }
00415                                 else if (envmatch("bold", 4) || envmatch("b", 1))
00416                                         curmode.bold = 1;
00417                                 else if (envmatch("italic", 6) || envmatch("i", 1))
00418                                         curmode.italic = 1;
00419                                 else if (envmatch("large", 5))
00420                                         curmode.size = LARGE_SIZE;
00421                                 else if (envmatch("medium", 6))
00422                                         curmode.size = MEDIUM_SIZE;
00423                                 else if (envmatch("small", 5))
00424                                         curmode.size = SMALL_SIZE;
00425                                 else if (envmatch("left", 4) || envmatch("l", 1))
00426                                         curmode.align = LEFTALIGN;
00427                                 else if (envmatch("center", 6) || envmatch("c", 1))
00428                                         curmode.align = CENTERALIGN;
00429                                 else if (envmatch("right", 5) || envmatch("r", 1))
00430                                         curmode.align = RIGHTALIGN;
00431                                 else if (envmatch("beep", 4))
00432                                         beepcount++;
00433                                 else if (envmatch("font", 4)) {
00434                                         /*
00435                                          * lookahead needed.  desc->next->str
00436                                          * should be the font name, and
00437                                          * desc->next->next->code should be a
00438                                          * DT_END
00439                                          */
00440                                         if ((desc->next) &&
00441                                             (desc->next->next) &&
00442                                             (desc->next->code == DT_STR) &&
00443                                         (desc->next->next->code == DT_END)) {
00444 
00445                                                 /*
00446                                                  * Since @font mutates the
00447                                                  * current environment, we
00448                                                  * have to pop the
00449                                                  * environment that this case
00450                                                  * usually pushes
00451                                                  */
00452                                                 free(curmode.substyle);
00453                                                 curmode = xmode_stack_top(modes);
00454                                                 xmode_stack_pop(modes);
00455 
00456                                                 /* mutating... */
00457                                                 curmode.size = SPECIAL_SIZE;    /* This is an @font() */
00458                                                 curmode.font = string_CreateFromData(desc->next->str,
00459                                                            desc->next->len);
00460                                                 /*
00461                                                  * skip over the rest of the
00462                                                  * @font
00463                                                  */
00464                                                 desc = desc->next->next;
00465                                         }
00466                                 }
00467                                 else if (envmatch("color", 5)) {
00468                                         /*
00469                                          * lookahead needed.  desc->next->str
00470                                          * should be the font name, and
00471                                          * desc->next->next->code should be a
00472                                          * DT_END
00473                                          */
00474                                         if ((desc->next) &&
00475                                             (desc->next->next) &&
00476                                             (desc->next->code == DT_STR) &&
00477                                         (desc->next->next->code == DT_END)) {
00478                                                 char *colorname;
00479 
00480                                                 /*
00481                                                  * Since @font mutates the
00482                                                  * current environment, we
00483                                                  * have to pop the
00484                                                  * environment that this case
00485                                                  * usually pushes
00486                                                  */
00487                                                 free(curmode.substyle);
00488                                                 curmode = xmode_stack_top(modes);
00489                                                 xmode_stack_pop(modes);
00490 
00491                                                 /* mutating... */
00492                                                 colorname = string_CreateFromData(desc->next->str,
00493                                                            desc->next->len);
00494                                                 curmode.color = x_string_to_color(colorname, default_fgcolor);
00495                                                 free(colorname);
00496                                                 curmode.expcolor = 1;
00497                                                 /*
00498                                                  * skip over the rest of the
00499                                                  * @font
00500                                                  */
00501                                                 desc = desc->next->next;
00502                                         }
00503                                 }
00504                                 else if (desc->len > 0) {       /* avoid @{...} */
00505                                         free(curmode.substyle);
00506                                         if (curmode.font) {
00507                                                 free(curmode.font);
00508                                                 curmode.font = NULL;
00509                                         }
00510                                         curmode.substyle = string_CreateFromData(desc->str, desc->len);
00511                                 }
00512                                 break;
00513 
00514                         case DT_STR:
00515                                 auxblocks[nextblock].align = curmode.align;
00516                                 auxblocks[nextblock].font = MODE_TO_FONT(dpy, style, &curmode);
00517                                 auxblocks[nextblock].str = desc->str;
00518                                 auxblocks[nextblock].len = desc->len;
00519                                 if (curmode.expcolor)
00520                                         blocks[nextblock].fgcolor = curmode.color;
00521                                 else
00522                                         blocks[nextblock].fgcolor =
00523                                                 x_string_to_color(mode_to_colorname(dpy, style, &curmode),
00524                                                            default_fgcolor);
00525                                 nextblock++;
00526                                 break;
00527 
00528                         case DT_END:
00529                                 free(curmode.substyle);
00530                                 curmode = xmode_stack_top(modes);
00531                                 xmode_stack_pop(modes);
00532                                 break;
00533 
00534                         case DT_NL:
00535                                 lines[line].startblock = linestart;
00536                                 lines[line].numblock = nextblock - linestart;
00537                                 font = MODE_TO_FONT(dpy, style, &curmode);
00538                                 lines[line].ascent = font->ascent;
00539                                 lines[line].descent = font->descent;
00540                                 line++;
00541                                 linestart = nextblock;
00542                                 break;
00543                 }
00544         }
00545 
00546         /* case DT_EOF:    will drop through to here. */
00547 
00548         if (linestart != nextblock) {
00549                 lines[line].startblock = linestart;
00550                 lines[line].numblock = nextblock - linestart;
00551                 font = MODE_TO_FONT(dpy, style, &curmode);
00552                 lines[line].ascent = 0;
00553                 lines[line].descent = 0;
00554                 line++;
00555         }
00556 
00557         free(curmode.substyle);
00558         fixup_and_draw(dpy, style, auxblocks, blocks, nextblock, lines, line,
00559                        beepcount);
00560         free(lines);
00561         free(auxblocks);
00562         if (free_style)
00563                 free(style);
00564 }
00565 
00566 static void 
00567 xhandleevent(dpy, w, event)
00568         Display *dpy;
00569         Window w;
00570         XEvent *event;
00571 {
00572         x_gram *gram;
00573 
00574         if (XFindContext(dpy, w, desc_context, (caddr_t *) & gram))
00575                 return;
00576 
00577         if (event->type == Expose)
00578                 x_gram_expose(dpy, w, gram, &(event->xexpose));
00579         else
00580                 xcut(dpy, event, desc_context);
00581 
00582         XFlush(dpy);
00583 }
00584 
00585 void 
00586 x_get_input(dpy)
00587         Display *dpy;
00588 {
00589         XEvent event;
00590 
00591         dprintf(dOutput, "Entering x_get_input(%x).\n", (unsigned int) dpy);
00592 
00593         /*
00594          * Kludge to get around lossage in XPending:
00595          *
00596          * (the problem: XPending on a partial packet returns 0 without
00597          *  reading in the packet.  This causes a problem when the X server
00598          *  dies in the middle of sending a packet.)
00599          */
00600         if (XPending(dpy) == 0)
00601                 XNoOp(dpy);     /* Ensure server is still with us... */
00602 
00603         while (XPending(dpy)) {
00604                 XNextEvent(dpy, &event);
00605                 xhandleevent(dpy, event.xany.window, &event);
00606         }
00607 }
00608 
00609 #endif                          /* X_DISPLAY_MISSING */


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