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

X_gram.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 "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;     /* In order to have transient windows, I need
00049                                  * a top-level window to always exist */
00050 static XClassHint classhint;
00051 static XSetWindowAttributes xattributes;
00052 static unsigned long xattributes_mask;
00053 
00054 /*
00055  * ICCCM note:
00056  * 
00057  * the following properties must be set on all top-level windows:
00058  * 
00059  * WM_NAME                  XStoreName(dpy,w,name); WM_ICON_NAME
00060  * XSetIconName(dpy,w,name); WM_NORMAL_HINTS
00061  * XSetNormalHints(dpy,w,sizehints); WM_HINTS
00062  * XSetWMHints(dpy,w,wmhints); WM_CLASS
00063  * XSetClassHint(dpy,w,classhint);
00064  * 
00065  * and for individual zgrams:
00066  * 
00067  * WM_TRANSIENT_FOR         XSetTransientForHint(dpy,w,main_window);
00068  * WM_PROTOCOLS             XSetWMProtocols(dpy,w,protocols,cnt);
00069  */
00070 
00071 /*
00072  * set all properties defined in ICCCM.  If main_window == 0, per-zgram
00073  * initialization is not done.
00074  */
00075 
00076 /* ARGSUSED */
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          * in order for some wm's to iconify, the window shouldn't be
00094          * transient. e.g. Motif wm
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         /* The default here should be 1, but mwm sucks */
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                  * XXX need to do our own parsing here, since the
00164                  * RecolorCursor routine requires an XColor, not an unsigned
00165                  * long (pixel)
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          * Adjust xpos, ypos based on the alignments xalign, yalign and the sizes:
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          * Create the window:
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                          * The event didn't go.  Print an error message, and
00336                          * continue.
00337                          */
00338                         ERROR("Error configuring window to the bottom of the stack.\n");
00339                 }
00340         }
00341         /* we always need to keep a linked list of windows */
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          * Because the flushing/syncing/etc with the error trapping can cause
00352          * events to be read into the Xlib queue, we need to go through the
00353          * queue here before exiting so that any pending events get
00354          * processed.
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                          /* 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