00001
00002
00003
00004
00005
00006
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;
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
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
00143
00144
00145
00146 for (line = 0; line < numlines; line++) {
00147 lsize = csize = rsize = 0;
00148 maxascent = maxdescent = 0;
00149
00150
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
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
00190
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
00209
00210
00211
00212
00213
00214
00215
00216
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
00243
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;
00255
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
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
00436
00437
00438
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
00447
00448
00449
00450
00451
00452 free(curmode.substyle);
00453 curmode = xmode_stack_top(modes);
00454 xmode_stack_pop(modes);
00455
00456
00457 curmode.size = SPECIAL_SIZE;
00458 curmode.font = string_CreateFromData(desc->next->str,
00459 desc->next->len);
00460
00461
00462
00463
00464 desc = desc->next->next;
00465 }
00466 }
00467 else if (envmatch("color", 5)) {
00468
00469
00470
00471
00472
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
00482
00483
00484
00485
00486
00487 free(curmode.substyle);
00488 curmode = xmode_stack_top(modes);
00489 xmode_stack_pop(modes);
00490
00491
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
00499
00500
00501 desc = desc->next->next;
00502 }
00503 }
00504 else if (desc->len > 0) {
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
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
00595
00596
00597
00598
00599
00600 if (XPending(dpy) == 0)
00601 XNoOp(dpy);
00602
00603 while (XPending(dpy)) {
00604 XNextEvent(dpy, &event);
00605 xhandleevent(dpy, event.xany.window, &event);
00606 }
00607 }
00608
00609 #endif