00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "mit-copyright.h"
00010
00011 #ifndef X_DISPLAY_MISSING
00012
00013 #include "X_gram.h"
00014 #include "xmark.h"
00015 #include <X11/Xutil.h>
00016 #include <X11/cursorfont.h>
00017 #include "main.h"
00018 #include "X_driver.h"
00019 #include "X_fonts.h"
00020 #include "error.h"
00021 #include "new_string.h"
00022 #include "xrevstack.h"
00023 #include "xerror.h"
00024 #include "xselect.h"
00025
00026 extern XContext desc_context;
00027 extern char *app_instance;
00028 extern unsigned long x_string_to_color();
00029 extern char *getenv();
00030
00031
00032
00033
00034
00035 int internal_border_width = 2;
00036
00037 unsigned long default_fgcolor;
00038 unsigned long default_bgcolor;
00039 unsigned long default_bordercolor;
00040 long ttl = 0;
00041 static int reset_saver;
00042 static int border_width = 1;
00043 static int cursor_code = XC_sailboat;
00044 static int set_transient;
00045 static int enable_delete;
00046 static char *title_name, *icon_name;
00047 static Cursor cursor;
00048 static Window group_leader;
00049
00050 static XClassHint classhint;
00051 static XSetWindowAttributes xattributes;
00052 static unsigned long xattributes_mask;
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 void
00078 x_set_icccm_hints(dpy, w, name, icon_name, psizehints, pwmhints, main_window)
00079 Display *dpy;
00080 Window w;
00081 char *name;
00082 char *icon_name;
00083 XSizeHints *psizehints;
00084 XWMHints *pwmhints;
00085 Window main_window;
00086 {
00087 XStoreName(dpy, w, name);
00088 XSetIconName(dpy, w, icon_name);
00089 XSetNormalHints(dpy, w, psizehints);
00090 XSetWMHints(dpy, w, pwmhints);
00091 XSetClassHint(dpy, w, &classhint);
00092
00093
00094
00095
00096 if (main_window != None) {
00097 if (set_transient)
00098 XSetTransientForHint(dpy, w, main_window);
00099 }
00100 if (enable_delete)
00101 XSetWMProtocols(dpy, w, &XA_WM_DELETE_WINDOW, 1);
00102 }
00103
00104 void
00105 x_gram_init(dpy)
00106 Display *dpy;
00107 {
00108 char *temp;
00109 XSizeHints sizehints;
00110 XWMHints wmhints;
00111 unsigned long rv, tc;
00112
00113 default_fgcolor = BlackPixelOfScreen(DefaultScreenOfDisplay(dpy));
00114 default_bgcolor = WhitePixelOfScreen(DefaultScreenOfDisplay(dpy));
00115 rv = get_bool_resource("reverseVideo", "ReverseVideo", 0);
00116 if (rv) {
00117 tc = default_fgcolor;
00118 default_fgcolor = default_bgcolor;
00119 default_bgcolor = tc;
00120 }
00121 if ((temp = get_string_resource("foreground", "Foreground")))
00122 default_fgcolor = x_string_to_color(temp, default_fgcolor);
00123 if ((temp = get_string_resource("background", "Background")))
00124 default_bgcolor = x_string_to_color(temp, default_bgcolor);
00125 default_bordercolor = default_fgcolor;
00126 if ((temp = get_string_resource("borderColor", "BorderColor")))
00127 default_bordercolor = x_string_to_color(temp, default_bordercolor);
00128
00129 temp = get_string_resource("minTimeToLive", "MinTimeToLive");
00130 if (temp && atoi(temp) >= 0)
00131 ttl = atoi(temp);
00132
00133 reverse_stack = get_bool_resource("reverseStack", "ReverseStack", 0);
00134 reset_saver = get_bool_resource("resetSaver", "ResetSaver", 1);
00135
00136 set_transient = get_bool_resource("transient", "Transient", 0);
00137 enable_delete = get_bool_resource("enableDelete", "EnableDelete", 1);
00138
00139 temp = get_string_resource("borderWidth", "BorderWidth");
00140
00141 if (temp && atoi(temp) >= 0)
00142 border_width = atoi(temp);
00143
00144 temp = get_string_resource("internalBorder", "InternalBorder");
00145
00146 if (temp && atoi(temp) >= 0)
00147 internal_border_width = atoi(temp);
00148
00149 temp = get_string_resource("cursorCode", "CursorCode");
00150
00151 if (temp && atoi(temp))
00152 cursor_code = atoi(temp);
00153
00154 cursor = XCreateFontCursor(dpy, cursor_code);
00155 if (!cursor)
00156 cursor = XCreateFontCursor(dpy, XC_sailboat);
00157
00158 temp = get_string_resource("pointerColor", "Foreground");
00159 if (temp) {
00160 char *temp2;
00161 XColor cursor_fore, cursor_back;
00162
00163
00164
00165
00166
00167 if (!(temp2 = get_string_resource("background", "Background"))) {
00168 if (default_bgcolor == WhitePixelOfScreen(DefaultScreenOfDisplay(dpy)))
00169 temp2 = "white";
00170 else
00171 temp2 = "black";
00172 }
00173 if (XParseColor(dpy,
00174 DefaultColormapOfScreen(DefaultScreenOfDisplay(dpy)),
00175 temp, &cursor_fore) &&
00176 XParseColor(dpy,
00177 DefaultColormapOfScreen(DefaultScreenOfDisplay(dpy)),
00178 temp2, &cursor_back)) {
00179 XRecolorCursor(dpy, cursor, &cursor_fore, &cursor_back);
00180 }
00181 }
00182 if (!(title_name = get_string_resource("title", "Title")))
00183 if (!(title_name = get_string_resource("name", "Name")))
00184 title_name = app_instance;
00185
00186 if (!(icon_name = get_string_resource("iconName", "IconName")))
00187 if (!(icon_name = get_string_resource("name", "Name")))
00188 icon_name = app_instance;
00189
00190 if (!(temp = get_string_resource("name", "Name")))
00191 if (!(temp = (char *) getenv("RESOURCE_NAME")))
00192 temp = app_instance;
00193 classhint.res_name = string_Copy(temp);
00194 classhint.res_class = "Jwgc";
00195
00196 if (set_transient) {
00197 group_leader = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 100, 100,
00198 0, default_bordercolor, default_bgcolor);
00199 sizehints.x = 0;
00200 sizehints.y = 0;
00201 sizehints.width = 100;
00202 sizehints.height = 100;
00203 sizehints.flags = PPosition | PSize;
00204
00205 wmhints.input = False;
00206 wmhints.initial_state = DontCareState;
00207 wmhints.flags = InputHint | StateHint;
00208
00209 x_set_icccm_hints(dpy, group_leader, "JwgcGroup", "JwgcGroup", &sizehints,
00210 &wmhints, 0);
00211 }
00212 xattributes.border_pixel = default_bordercolor;
00213 xattributes.cursor = cursor;
00214 xattributes.event_mask = (ExposureMask | ButtonReleaseMask | ButtonPressMask
00215 | LeaveWindowMask | Button1MotionMask
00216 | Button3MotionMask | StructureNotifyMask);
00217 xattributes_mask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor);
00218 temp = get_string_resource("backingStore", "BackingStore");
00219 if (!temp)
00220 return;
00221 xattributes_mask |= CWBackingStore;
00222 if (!strcasecmp(temp, "notuseful"))
00223 xattributes.backing_store = NotUseful;
00224 else if (!strcasecmp(temp, "whenmapped"))
00225 xattributes.backing_store = WhenMapped;
00226 else if (!strcasecmp(temp, "always"))
00227 xattributes.backing_store = Always;
00228 else if (!strcasecmp(temp, "default"))
00229 xattributes_mask &= ~CWBackingStore;
00230 else {
00231 switch (get_bool_resource("backingStore", "BackingStore", -1)) {
00232 case 0:
00233 xattributes.backing_store = NotUseful;
00234 break;
00235 case 1:
00236 xattributes.backing_store = WhenMapped;
00237 break;
00238 case -1:
00239 fprintf(stderr,
00240 "jwgc: Cannot interpret backing-store resource value `%s'.\n",
00241 temp);
00242 xattributes_mask &= ~CWBackingStore;
00243 break;
00244 }
00245 }
00246 }
00247
00248 void
00249 x_gram_create(dpy, gram, xalign, yalign, xpos, ypos, xsize, ysize,
00250 beepcount)
00251 Display *dpy;
00252 x_gram *gram;
00253 int xalign, yalign;
00254 int xpos, ypos;
00255 int xsize, ysize;
00256 int beepcount;
00257 {
00258 Window w;
00259 XSizeHints sizehints;
00260 XWMHints wmhints;
00261 XSetWindowAttributes attributes;
00262 extern void x_get_input();
00263
00264
00265
00266
00267 if (xalign < 0)
00268 xpos = WidthOfScreen(DefaultScreenOfDisplay(dpy)) - xpos - xsize
00269 - 2 * border_width;
00270 else if (xalign == 0)
00271 xpos = ((WidthOfScreen(DefaultScreenOfDisplay(dpy)) - xsize
00272 - 2 * border_width) >> 1) + xpos;
00273
00274 if (yalign < 0)
00275 ypos = HeightOfScreen(DefaultScreenOfDisplay(dpy)) - ypos - ysize
00276 - 2 * border_width;
00277 else if (yalign == 0)
00278 ypos = ((HeightOfScreen(DefaultScreenOfDisplay(dpy)) - ysize
00279 - 2 * border_width) >> 1) + ypos;
00280
00281
00282
00283
00284 attributes = xattributes;
00285 attributes.background_pixel = gram->bgcolor;
00286
00287 gram->w = w = XCreateWindow(dpy, DefaultRootWindow(dpy), xpos, ypos,
00288 xsize, ysize, border_width, 0,
00289 CopyFromParent, CopyFromParent,
00290 xattributes_mask, &attributes);
00291
00292 sizehints.x = xpos;
00293 sizehints.y = ypos;
00294 sizehints.width = xsize;
00295 sizehints.height = ysize;
00296 sizehints.flags = USPosition | USSize;
00297
00298 wmhints.input = True;
00299 wmhints.initial_state = NormalState;
00300 if (set_transient) {
00301 wmhints.window_group = group_leader;
00302 wmhints.flags = InputHint | StateHint | WindowGroupHint;
00303
00304 x_set_icccm_hints(dpy, w, title_name, icon_name, &sizehints, &wmhints,
00305 group_leader);
00306 }
00307 else {
00308 wmhints.flags = InputHint | StateHint;
00309
00310 x_set_icccm_hints(dpy, w, title_name, icon_name, &sizehints, &wmhints, 0);
00311 }
00312
00313
00314 XSaveContext(dpy, w, desc_context, (caddr_t) gram);
00315
00316 gram->can_die.tv_sec = 0;
00317
00318 XMapWindow(dpy, w);
00319
00320 if (beepcount)
00321 XBell(dpy, 0);
00322
00323 xerror_happened = 0;
00324 if (reverse_stack && bottom_gram) {
00325 XWindowChanges winchanges;
00326
00327 winchanges.sibling = bottom_gram->w;
00328 winchanges.stack_mode = Below;
00329 begin_xerror_trap(dpy);
00330 XReconfigureWMWindow(dpy, w, DefaultScreen(dpy),
00331 CWSibling | CWStackMode, &winchanges);
00332 end_xerror_trap(dpy);
00333 if (xerror_happened) {
00334
00335
00336
00337
00338 ERROR("Error configuring window to the bottom of the stack.\n");
00339 }
00340 }
00341
00342 add_to_bottom(gram);
00343 if (xerror_happened)
00344 pull_to_top(gram);
00345
00346 if (reset_saver)
00347 XResetScreenSaver(dpy);
00348
00349 XFlush(dpy);
00350
00351
00352
00353
00354
00355
00356 x_get_input(dpy);
00357 }
00358
00359 void
00360 x_gram_draw(dpy, w, gram, region)
00361 Display *dpy;
00362 Window w;
00363 x_gram *gram;
00364 Region region;
00365 {
00366 int i;
00367 GC gc;
00368 XGCValues gcvals;
00369 xblock *xb;
00370 XTextItem text;
00371 int startblock, endblock, startpixel, endpixel;
00372
00373 #define SetFG(fg) \
00374 gcvals.foreground=fg; \
00375 XChangeGC(dpy,gc,GCForeground,&gcvals)
00376
00377 gc = XCreateGC(dpy, w, 0, &gcvals);
00378 XSetRegion(dpy, gc, region);
00379 startpixel = endpixel = 0;
00380
00381 if ((markgram == gram) && (STARTBLOCK != -1) && (ENDBLOCK != -1)) {
00382 if (xmarkSecond() == XMARK_END_BOUND) {
00383 startblock = STARTBLOCK;
00384 endblock = ENDBLOCK;
00385 startpixel = STARTPIXEL;
00386 endpixel = ENDPIXEL;
00387 }
00388 else {
00389 startblock = ENDBLOCK;
00390 endblock = STARTBLOCK;
00391 startpixel = ENDPIXEL;
00392 endpixel = STARTPIXEL;
00393 }
00394 }
00395 else {
00396 startblock = -1;
00397 endblock = -1;
00398 }
00399
00400 for (i = 0, xb = gram->blocks; i < gram->numblocks; i++, xb++) {
00401 if (XRectInRegion(region, xb->x1, xb->y1, xb->x2 - xb->x1,
00402 xb->y2 - xb->y1) != RectangleOut) {
00403 if (i == startblock) {
00404 if (i == endblock) {
00405 SetFG(gram->bgcolor);
00406 XFillRectangle(dpy, w, gc, xb->x1, xb->y1, startpixel,
00407 (xb->y2 - xb->y1));
00408 SetFG(xb->fgcolor);
00409 XFillRectangle(dpy, w, gc, xb->x1 + startpixel, xb->y1,
00410 (endpixel - startpixel), (xb->y2 - xb->y1));
00411 SetFG(gram->bgcolor);
00412 XFillRectangle(dpy, w, gc, xb->x1 + endpixel, xb->y1,
00413 (xb->x2 - xb->x1 - endpixel), (xb->y2 - xb->y1));
00414 }
00415 else {
00416 SetFG(gram->bgcolor);
00417 XFillRectangle(dpy, w, gc, xb->x1, xb->y1, startpixel,
00418 (xb->y2 - xb->y1));
00419 SetFG(xb->fgcolor);
00420 XFillRectangle(dpy, w, gc, xb->x1 + startpixel, xb->y1,
00421 (xb->x2 - xb->x1 - startpixel), (xb->y2 - xb->y1));
00422 }
00423 }
00424 else if (i == endblock) {
00425 SetFG(xb->fgcolor);
00426 XFillRectangle(dpy, w, gc, xb->x1, xb->y1, endpixel,
00427 (xb->y2 - xb->y1));
00428 SetFG(gram->bgcolor);
00429 XFillRectangle(dpy, w, gc, xb->x1 + endpixel, xb->y1,
00430 (xb->x2 - xb->x1 - endpixel), (xb->y2 - xb->y1));
00431 }
00432 else {
00433 if ((startblock < i) && (i < endblock)) {
00434 SetFG(xb->fgcolor);
00435 }
00436 else {
00437 SetFG(gram->bgcolor);
00438 }
00439 XFillRectangle(dpy, w, gc, xb->x1, xb->y1, (xb->x2 - xb->x1),
00440 (xb->y2 - xb->y1));
00441 }
00442 }
00443 }
00444
00445 gcvals.function = GXxor;
00446 XChangeGC(dpy, gc, GCFunction, &gcvals);
00447
00448 for (i = 0, xb = gram->blocks; i < gram->numblocks; i++, xb++) {
00449 if (XRectInRegion(region, xb->x1, xb->y1, xb->x2 - xb->x1,
00450 xb->y2 - xb->y1) != RectangleOut) {
00451 SetFG(gram->bgcolor ^ xb->fgcolor);
00452 text.chars = gram->text + xb->strindex;
00453 text.nchars = xb->strlen;
00454 text.delta = 0;
00455 text.font = xb->fid;
00456 XDrawText(dpy, w, gc, xb->x, xb->y, &text, 1);
00457 }
00458 }
00459
00460 XFreeGC(dpy, gc);
00461 }
00462
00463 void
00464 x_gram_expose(dpy, w, gram, event)
00465 Display *dpy;
00466 Window w;
00467 x_gram *gram;
00468 XExposeEvent *event;
00469 {
00470 static Region region;
00471 static int partregion;
00472 XRectangle rect;
00473
00474 rect.x = (short) event->x;
00475 rect.y = (short) event->y;
00476 rect.width = (unsigned short) event->width;
00477 rect.height = (unsigned short) event->height;
00478
00479 if (!partregion) {
00480 region = XCreateRegion();
00481 partregion = 1;
00482 }
00483
00484 if (rect.width && rect.height)
00485 XUnionRectWithRegion(&rect, region, region);
00486
00487 if (event->count == 0) {
00488 x_gram_draw(dpy, w, gram, region);
00489 partregion = 0;
00490 XDestroyRegion(region);
00491 }
00492 }
00493
00494 #endif