[CONTACT]

[ABOUT]

[POLICY]

git clone dmenu dmenu Log gph

Found at: gopher.r-36.net:70/scm/dmenu/file/dmenu.c.gph

tdmenu.c - dmenu - Dmenu fork with xft fonts.

git clone git://r-36.net/dmenu

Log

Files

Refs

README

LICENSE

---
tdmenu.c (16967B)
---
     1 /* See LICENSE file for copyright and license details. */
     2 #include <ctype.h>
     3 #include <locale.h>
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <string.h>
     7 #include <strings.h>
     8 #include <time.h>
     9
    10 #include <X11/Xlib.h>
    11 #include <X11/Xatom.h>
    12 #include <X11/Xutil.h>
    13 #ifdef XINERAMA
    14 #include <X11/extensions/Xinerama.h>
    15 #endif
    16 #include <X11/Xft/Xft.h>
    17
    18 #include "drw.h"
    19 #include "util.h"
    20
    21 /* macros */
    22 #define INTERSECT(x,y,w,h,r)  (MAX(0, MIN((x)+(w),(r).x_org+(r).width)  - MAX((x),(r).x_org)) \
    23                              * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
    24 #define LENGTH(X)             (sizeof X / sizeof X[0])
    25 #define TEXTNW(X,N)           (drw_font_getexts_width(drw->fonts[0], (X), (N)))
    26 #define TEXTW(X)              (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h)
    27
    28 /* enums */
    29 enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */
    30
    31 struct item {
    32         char *text;
    33         struct item *left, *right;
    34         int out;
    35 };
    36
    37 static char text[BUFSIZ] = "";
    38 static int bh, mw, mh;
    39 static int sw, sh; /* X display screen geometry width, height */
    40 static int inputw, promptw;
    41 static size_t cursor;
    42 static struct item *items = NULL;
    43 static struct item *matches, *matchend;
    44 static struct item *prev, *curr, *next, *sel;
    45 static int mon = -1, screen;
    46
    47 static Atom clip, utf8;
    48 static Display *dpy;
    49 static Window root, win;
    50 static XIC xic;
    51
    52 static ClrScheme scheme[SchemeLast];
    53 static Drw *drw;
    54
    55 #include "config.h"
    56
    57 static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
    58 static char *(*fstrstr)(const char *, const char *) = strstr;
    59
    60 static void
    61 appenditem(struct item *item, struct item **list, struct item **last)
    62 {
    63         if (*last)
    64                 (*last)->right = item;
    65         else
    66                 *list = item;
    67
    68         item->left = *last;
    69         item->right = NULL;
    70         *last = item;
    71 }
    72
    73 static void
    74 calcoffsets(void)
    75 {
    76         int i, n;
    77
    78         if (lines > 0)
    79                 n = lines * bh;
    80         else
    81                 n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
    82         /* calculate which items will begin the next page and previous page */
    83         for (i = 0, next = curr; next; next = next->right)
    84                 if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n)
    85                         break;
    86         for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
    87                 if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n)
    88                         break;
    89 }
    90
    91 static void
    92 cleanup(void)
    93 {
    94         size_t i;
    95
    96         XUngrabKey(dpy, AnyKey, AnyModifier, root);
    97         for (i = 0; i < SchemeLast; i++) {
    98                 drw_clr_free(scheme[i].bg);
    99                 drw_clr_free(scheme[i].fg);
   100         }
   101         drw_free(drw);
   102         XSync(dpy, False);
   103         XCloseDisplay(dpy);
   104 }
   105
   106 static char *
   107 cistrstr(const char *s, const char *sub)
   108 {
   109         size_t len;
   110
   111         for (len = strlen(sub); *s; s++)
   112                 if (!strncasecmp(s, sub, len))
   113                         return (char *)s;
   114         return NULL;
   115 }
   116
   117 static void
   118 drawmenu(void)
   119 {
   120         int curpos;
   121         struct item *item;
   122         int x = 0, y = 0, h = bh, w;
   123
   124         drw_setscheme(drw, &scheme[SchemeNorm]);
   125         drw_rect(drw, 0, 0, mw, mh, 1, 1, 1);
   126
   127         if (prompt && *prompt) {
   128                 drw_setscheme(drw, &scheme[SchemeSel]);
   129                 drw_text(drw, x, 0, promptw, bh, prompt, 0);
   130                 x += promptw;
   131         }
   132         /* draw input field */
   133         w = (lines > 0 || !matches) ? mw - x : inputw;
   134         drw_setscheme(drw, &scheme[SchemeNorm]);
   135         drw_text(drw, x, 0, w, bh, text, 0);
   136
   137         if ((curpos = TEXTNW(text, cursor) + bh / 2 - 2) < w) {
   138                 drw_setscheme(drw, &scheme[SchemeNorm]);
   139                 drw_rect(drw, x + curpos + 2, 2, 1, bh - 4, 1, 1, 0);
   140         }
   141
   142         if (lines > 0) {
   143                 /* draw vertical list */
   144                 w = mw - x;
   145                 for (item = curr; item != next; item = item->right) {
   146                         y += h;
   147                         if (item == sel)
   148                                 drw_setscheme(drw, &scheme[SchemeSel]);
   149                         else if (item->out)
   150                                 drw_setscheme(drw, &scheme[SchemeOut]);
   151                         else
   152                                 drw_setscheme(drw, &scheme[SchemeNorm]);
   153
   154                         drw_text(drw, x, y, w, bh, item->text, 0);
   155                 }
   156         } else if (matches) {
   157                 /* draw horizontal list */
   158                 x += inputw;
   159                 w = TEXTW("<");
   160                 if (curr->left) {
   161                         drw_setscheme(drw, &scheme[SchemeNorm]);
   162                         drw_text(drw, x, 0, w, bh, "<", 0);
   163                 }
   164                 for (item = curr; item != next; item = item->right) {
   165                         x += w;
   166                         w = MIN(TEXTW(item->text), mw - x - TEXTW(">"));
   167
   168                         if (item == sel)
   169                                 drw_setscheme(drw, &scheme[SchemeSel]);
   170                         else if (item->out)
   171                                 drw_setscheme(drw, &scheme[SchemeOut]);
   172                         else
   173                                 drw_setscheme(drw, &scheme[SchemeNorm]);
   174                         drw_text(drw, x, 0, w, bh, item->text, 0);
   175                 }
   176                 w = TEXTW(">");
   177                 x = mw - w;
   178                 if (next) {
   179                         drw_setscheme(drw, &scheme[SchemeNorm]);
   180                         drw_text(drw, x, 0, w, bh, ">", 0);
   181                 }
   182         }
   183         drw_map(drw, win, 0, 0, mw, mh);
   184 }
   185
   186 static void
   187 grabkeyboard(void)
   188 {
   189         struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000  };
   190         int i;
   191
   192         /* try to grab keyboard, we may have to wait for another process to ungrab */
   193         for (i = 0; i < 1000; i++) {
   194                 if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True,
   195                                  GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess)
   196                         return;
   197                 nanosleep(&ts, NULL);
   198         }
   199         die("cannot grab keyboard\n");
   200 }
   201
   202 static void
   203 match(void)
   204 {
   205         static char **tokv = NULL;
   206         static int tokn = 0;
   207
   208         char buf[sizeof text], *s;
   209         int i, tokc = 0;
   210         size_t len, textsize;
   211         struct item *item, *lprefix, *lsubstr, *prefixend, *substrend;
   212
   213         strcpy(buf, text);
   214         /* separate input text into tokens to be matched individually */
   215         for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
   216                 if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
   217                         die("cannot realloc %u bytes\n", tokn * sizeof *tokv);
   218         len = tokc ? strlen(tokv[0]) : 0;
   219
   220         matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL;
   221         textsize = strlen(text);
   222         for (item = items; item && item->text; item++) {
   223                 for (i = 0; i < tokc; i++)
   224                         if (!fstrstr(item->text, tokv[i]))
   225                                 break;
   226                 if (i != tokc) /* not all tokens match */
   227                         continue;
   228                 /* exact matches go first, then prefixes, then substrings */
   229                 if (!tokc || !fstrncmp(text, item->text, textsize))
   230                         appenditem(item, &matches, &matchend);
   231                 else if (!fstrncmp(tokv[0], item->text, len))
   232                         appenditem(item, &lprefix, &prefixend);
   233                 else
   234                         appenditem(item, &lsubstr, &substrend);
   235         }
   236         if (lprefix) {
   237                 if (matches) {
   238                         matchend->right = lprefix;
   239                         lprefix->left = matchend;
   240                 } else
   241                         matches = lprefix;
   242                 matchend = prefixend;
   243         }
   244         if (lsubstr) {
   245                 if (matches) {
   246                         matchend->right = lsubstr;
   247                         lsubstr->left = matchend;
   248                 } else
   249                         matches = lsubstr;
   250                 matchend = substrend;
   251         }
   252         curr = sel = matches;
   253         calcoffsets();
   254 }
   255
   256 static void
   257 insert(const char *str, ssize_t n)
   258 {
   259         if (strlen(text) + n > sizeof text - 1)
   260                 return;
   261         /* move existing text out of the way, insert new text, and update cursor */
   262         memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0));
   263         if (n > 0)
   264                 memcpy(&text[cursor], str, n);
   265         cursor += n;
   266         match();
   267 }
   268
   269 static size_t
   270 nextrune(int inc)
   271 {
   272         ssize_t n;
   273
   274         /* return location of next utf8 rune in the given direction (+1 or -1) */
   275         for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc)
   276                 ;
   277         return n;
   278 }
   279
   280 static void
   281 keypress(XKeyEvent *ev)
   282 {
   283         char buf[32];
   284         int len;
   285         KeySym ksym = NoSymbol;
   286         Status status;
   287
   288         len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
   289         if (status == XBufferOverflow)
   290                 return;
   291         if (ev->state & ControlMask)
   292                 switch(ksym) {
   293                 case XK_a: ksym = XK_Home;      break;
   294                 case XK_b: ksym = XK_Left;      break;
   295                 case XK_c: ksym = XK_Escape;    break;
   296                 case XK_d: ksym = XK_Delete;    break;
   297                 case XK_e: ksym = XK_End;       break;
   298                 case XK_f: ksym = XK_Right;     break;
   299                 case XK_g: ksym = XK_Escape;    break;
   300                 case XK_h: ksym = XK_BackSpace; break;
   301                 case XK_i: ksym = XK_Tab;       break;
   302                 case XK_j: /* fallthrough */
   303                 case XK_J: /* fallthrough */
   304                 case XK_m: /* fallthrough */
   305                 case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break;
   306                 case XK_n: ksym = XK_Down;      break;
   307                 case XK_p: ksym = XK_Up;        break;
   308
   309                 case XK_k: /* delete right */
   310                         text[cursor] = '\0';
   311                         match();
   312                         break;
   313                 case XK_u: /* delete left */
   314                         insert(NULL, 0 - cursor);
   315                         break;
   316                 case XK_w: /* delete word */
   317                         while (cursor > 0 && strchr(worddelimiters,
   318                                text[nextrune(-1)]))
   319                                 insert(NULL, nextrune(-1) - cursor);
   320                         while (cursor > 0 && !strchr(worddelimiters,
   321                                text[nextrune(-1)]))
   322                                 insert(NULL, nextrune(-1) - cursor);
   323                         break;
   324                 case XK_y: /* paste selection */
   325                 case XK_Y:
   326                         XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
   327                                           utf8, utf8, win, CurrentTime);
   328                         return;
   329                 case XK_Return:
   330                 case XK_KP_Enter:
   331                         break;
   332                 case XK_bracketleft:
   333                         cleanup();
   334                         exit(1);
   335                 default:
   336                         return;
   337                 }
   338         else if (ev->state & Mod1Mask)
   339                 switch(ksym) {
   340                 case XK_g: ksym = XK_Home;  break;
   341                 case XK_G: ksym = XK_End;   break;
   342                 case XK_h: ksym = XK_Up;    break;
   343                 case XK_j: ksym = XK_Next;  break;
   344                 case XK_k: ksym = XK_Prior; break;
   345                 case XK_l: ksym = XK_Down;  break;
   346                 default:
   347                         return;
   348                 }
   349         switch(ksym) {
   350         default:
   351                 if (!iscntrl(*buf))
   352                         insert(buf, len);
   353                 break;
   354         case XK_Delete:
   355                 if (text[cursor] == '\0')
   356                         return;
   357                 cursor = nextrune(+1);
   358                 /* fallthrough */
   359         case XK_BackSpace:
   360                 if (cursor == 0)
   361                         return;
   362                 insert(NULL, nextrune(-1) - cursor);
   363                 break;
   364         case XK_End:
   365                 if (text[cursor] != '\0') {
   366                         cursor = strlen(text);
   367                         break;
   368                 }
   369                 if (next) {
   370                         /* jump to end of list and position items in reverse */
   371                         curr = matchend;
   372                         calcoffsets();
   373                         curr = prev;
   374                         calcoffsets();
   375                         while (next && (curr = curr->right))
   376                                 calcoffsets();
   377                 }
   378                 sel = matchend;
   379                 break;
   380         case XK_Escape:
   381                 cleanup();
   382                 exit(1);
   383         case XK_Home:
   384                 if (sel == matches) {
   385                         cursor = 0;
   386                         break;
   387                 }
   388                 sel = curr = matches;
   389                 calcoffsets();
   390                 break;
   391         case XK_Left:
   392                 if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
   393                         cursor = nextrune(-1);
   394                         break;
   395                 }
   396                 if (lines > 0)
   397                         return;
   398                 /* fallthrough */
   399         case XK_Up:
   400                 if (sel && sel->left && (sel = sel->left)->right == curr) {
   401                         curr = prev;
   402                         calcoffsets();
   403                 }
   404                 break;
   405         case XK_Next:
   406                 if (!next)
   407                         return;
   408                 sel = curr = next;
   409                 calcoffsets();
   410                 break;
   411         case XK_Prior:
   412                 if (!prev)
   413                         return;
   414                 sel = curr = prev;
   415                 calcoffsets();
   416                 break;
   417         case XK_Return:
   418         case XK_KP_Enter:
   419                 puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
   420                 if (!(ev->state & ControlMask)) {
   421                         cleanup();
   422                         exit(0);
   423                 }
   424                 if (sel)
   425                         sel->out = 1;
   426                 break;
   427         case XK_Right:
   428                 if (text[cursor] != '\0') {
   429                         cursor = nextrune(+1);
   430                         break;
   431                 }
   432                 if (lines > 0)
   433                         return;
   434                 /* fallthrough */
   435         case XK_Down:
   436                 if (sel && sel->right && (sel = sel->right) == next) {
   437                         curr = next;
   438                         calcoffsets();
   439                 }
   440                 break;
   441         case XK_Tab:
   442                 if (!sel)
   443                         return;
   444                 strncpy(text, sel->text, sizeof text - 1);
   445                 text[sizeof text - 1] = '\0';
   446                 cursor = strlen(text);
   447                 match();
   448                 break;
   449         }
   450         drawmenu();
   451 }
   452
   453 static void
   454 paste(void)
   455 {
   456         char *p, *q;
   457         int di;
   458         unsigned long dl;
   459         Atom da;
   460
   461         /* we have been given the current selection, now insert it into input */
   462         XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
   463                            utf8, &da, &di, &dl, &dl, (unsigned char **)&p);
   464         insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p));
   465         XFree(p);
   466         drawmenu();
   467 }
   468
   469 static void
   470 readstdin(void)
   471 {
   472         char buf[sizeof text], *p, *maxstr = NULL;
   473         size_t i, max = 0, size = 0;
   474
   475         /* read each line from stdin and add it to the item list */
   476         for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
   477                 if (i + 1 >= size / sizeof *items)
   478                         if (!(items = realloc(items, (size += BUFSIZ))))
   479                                 die("cannot realloc %u bytes:", size);
   480                 if ((p = strchr(buf, '\n')))
   481                         *p = '\0';
   482                 if (!(items[i].text = strdup(buf)))
   483                         die("cannot strdup %u bytes:", strlen(buf) + 1);
   484                 items[i].out = 0;
   485                 if (strlen(items[i].text) > max)
   486                         max = strlen(maxstr = items[i].text);
   487         }
   488         if (items)
   489                 items[i].text = NULL;
   490         inputw = maxstr ? TEXTW(maxstr) : 0;
   491         lines = MIN(lines, i);
   492 }
   493
   494 static void
   495 run(void)
   496 {
   497         XEvent ev;
   498
   499         while (!XNextEvent(dpy, &ev)) {
   500                 if (XFilterEvent(&ev, win))
   501                         continue;
   502                 switch(ev.type) {
   503                 case Expose:
   504                         if (ev.xexpose.count == 0)
   505                                 drw_map(drw, win, 0, 0, mw, mh);
   506                         break;
   507                 case KeyPress:
   508                         keypress(&ev.xkey);
   509                         break;
   510                 case SelectionNotify:
   511                         if (ev.xselection.property == utf8)
   512                                 paste();
   513                         break;
   514                 case VisibilityNotify:
   515                         if (ev.xvisibility.state != VisibilityUnobscured)
   516                                 XRaiseWindow(dpy, win);
   517                         break;
   518                 }
   519         }
   520 }
   521
   522 static void
   523 setup(void)
   524 {
   525         int x, y;
   526         XSetWindowAttributes swa;
   527         XIM xim;
   528 #ifdef XINERAMA
   529         XineramaScreenInfo *info;
   530         Window w, pw, dw, *dws;
   531         XWindowAttributes wa;
   532         int a, j, di, n, i = 0, area = 0;
   533         unsigned int du;
   534 #endif
   535
   536         /* init appearance */
   537         scheme[SchemeNorm].bg = drw_clr_create(drw, normbgcolor);
   538         scheme[SchemeNorm].fg = drw_clr_create(drw, normfgcolor);
   539         scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor);
   540         scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor);
   541         scheme[SchemeOut].bg = drw_clr_create(drw, outbgcolor);
   542         scheme[SchemeOut].fg = drw_clr_create(drw, outfgcolor);
   543
   544         clip = XInternAtom(dpy, "CLIPBOARD",   False);
   545         utf8 = XInternAtom(dpy, "UTF8_STRING", False);
   546
   547         /* calculate menu geometry */
   548         bh = drw->fonts[0]->h + 2;
   549         lines = MAX(lines, 0);
   550         mh = (lines + 1) * bh;
   551 #ifdef XINERAMA
   552         if ((info = XineramaQueryScreens(dpy, &n))) {
   553                 XGetInputFocus(dpy, &w, &di);
   554                 if (mon != -1 && mon < n)
   555                         i = mon;
   556                 else if (w != root && w != PointerRoot && w != None) {
   557                         /* find top-level window containing current input focus */
   558                         do {
   559                                 if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
   560                                         XFree(dws);
   561                         } while (w != root && w != pw);
   562                         /* find xinerama screen with which the window intersects most */
   563                         if (XGetWindowAttributes(dpy, pw, &wa))
   564                                 for (j = 0; j < n; j++)
   565                                         if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
   566                                                 area = a;
   567                                                 i = j;
   568                                         }
   569                 }
   570                 /* no focused window is on screen, so use pointer location instead */
   571                 if (mon == -1 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
   572                         for (i = 0; i < n; i++)
   573                                 if (INTERSECT(x, y, 1, 1, info[i]))
   574                                         break;
   575
   576                 x = info[i].x_org;
   577                 y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
   578                 mw = info[i].width;
   579                 XFree(info);
   580         } else
   581 #endif
   582         {
   583                 x = 0;
   584                 y = topbar ? 0 : sh - mh;
   585                 mw = sw;
   586         }
   587         promptw = (prompt && *prompt) ? TEXTW(prompt) : 0;
   588         inputw = MIN(inputw, mw/3);
   589         match();
   590
   591         /* create menu window */
   592         swa.override_redirect = True;
   593         swa.background_pixel = scheme[SchemeNorm].bg->pix;
   594         swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
   595         win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
   596                             DefaultDepth(dpy, screen), CopyFromParent,
   597                             DefaultVisual(dpy, screen),
   598                             CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
   599
   600         /* open input methods */
   601         xim = XOpenIM(dpy, NULL, NULL, NULL);
   602         xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
   603                         XNClientWindow, win, XNFocusWindow, win, NULL);
   604
   605         XMapRaised(dpy, win);
   606         drw_resize(drw, mw, mh);
   607         drawmenu();
   608 }
   609
   610 static void
   611 usage(void)
   612 {
   613         fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
   614               "             [-nb color] [-nf color] [-sb color] [-sf color] [-v]\n", stderr);
   615         exit(1);
   616 }
   617
   618 int
   619 main(int argc, char *argv[])
   620 {
   621         int i, fast = 0;
   622
   623         for (i = 1; i < argc; i++)
   624                 /* these options take no arguments */
   625                 if (!strcmp(argv[i], "-v")) {      /* prints version information */
   626                         puts("dmenu-"VERSION);
   627                         exit(0);
   628                 } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */
   629                         topbar = 0;
   630                 else if (!strcmp(argv[i], "-f"))   /* grabs keyboard before reading stdin */
   631                         fast = 1;
   632                 else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
   633                         fstrncmp = strncasecmp;
   634                         fstrstr = cistrstr;
   635                 } else if (i + 1 == argc)
   636                         usage();
   637                 /* these options take one argument */
   638                 else if (!strcmp(argv[i], "-l"))   /* number of lines in vertical list */
   639                         lines = atoi(argv[++i]);
   640                 else if (!strcmp(argv[i], "-m"))
   641                         mon = atoi(argv[++i]);
   642                 else if (!strcmp(argv[i], "-p"))   /* adds prompt to left of input field */
   643                         prompt = argv[++i];
   644                 else if (!strcmp(argv[i], "-fn"))  /* font or font set */
   645                         fonts[0] = argv[++i];
   646                 else if (!strcmp(argv[i], "-nb"))  /* normal background color */
   647                         normbgcolor = argv[++i];
   648                 else if (!strcmp(argv[i], "-nf"))  /* normal foreground color */
   649                         normfgcolor = argv[++i];
   650                 else if (!strcmp(argv[i], "-sb"))  /* selected background color */
   651                         selbgcolor = argv[++i];
   652                 else if (!strcmp(argv[i], "-sf"))  /* selected foreground color */
   653                         selfgcolor = argv[++i];
   654                 else
   655                         usage();
   656
   657         if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
   658                 fputs("warning: no locale support\n", stderr);
   659         if (!(dpy = XOpenDisplay(NULL)))
   660                 die("cannot open display\n");
   661         screen = DefaultScreen(dpy);
   662         root = RootWindow(dpy, screen);
   663         sw = DisplayWidth(dpy, screen);
   664         sh = DisplayHeight(dpy, screen);
   665         drw = drw_create(dpy, screen, root, sw, sh);
   666         drw_load_fonts(drw, fonts, LENGTH(fonts));
   667         if (!drw->fontcount)
   668                 die("no fonts could be loaded.\n");
   669         drw_setscheme(drw, &scheme[SchemeNorm]);
   670
   671         if (fast) {
   672                 grabkeyboard();
   673                 readstdin();
   674         } else {
   675                 readstdin();
   676                 grabkeyboard();
   677         }
   678         setup();
   679         run();
   680
   681         return 1; /* unreachable */
   682 }
.


AD:

NEW PAGES:

[ODDNUGGET]

[GOPHER]