Xinqi Bao's Git
15f5e26c762f16fb332e6a0bf4b9530ff79e4f0a
   1 /* See LICENSE file for copyright and license details. */ 
  10 #include <X11/keysym.h> 
  12 #include <X11/Xutil.h> 
  14 #include <X11/extensions/Xinerama.h> 
  18 #define CLEANMASK(mask)         (mask & ~(numlockmask | LockMask)) 
  19 #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) 
  20 #define MIN(a, b)               ((a) < (b) ? (a) : (b)) 
  21 #define MAX(a, b)               ((a) > (b) ? (a) : (b)) 
  22 #define IS_UTF8_1ST_CHAR(c)     ((((c) & 0xc0) == 0xc0) || !((c) & 0x80)) 
  24 /* forward declarations */ 
  25 static void cleanup(void); 
  26 static void drawcursor(void); 
  27 static void drawinput(void); 
  28 static Bool 
grabkeyboard(void); 
  29 static void kpress(XKeyEvent 
* e
); 
  30 static void run(void); 
  31 static void setup(Bool topbar
); 
  37 static char *prompt 
= NULL
; 
  38 static char text
[4096]; 
  39 static int promptw 
= 0; 
  41 static unsigned int cursor 
= 0; 
  42 static unsigned int numlockmask 
= 0; 
  43 static Bool running 
= True
; 
  55         XDestroyWindow(dpy
, win
); 
  56         XUngrabKeyboard(dpy
, CurrentTime
); 
  61         XRectangle r 
= { dc
.x
, dc
.y 
+ 2, 1, dc
.font
.height 
- 2 }; 
  63         r
.x 
+= textnw(text
, cursor
) + dc
.font
.height 
/ 2; 
  65         XSetForeground(dpy
, dc
.gc
, dc
.norm
[ColFG
]); 
  66         XFillRectangles(dpy
, dc
.drawable
, dc
.gc
, &r
, 1); 
  76         drawtext(NULL
, dc
.norm
); 
  80                 drawtext(prompt
, dc
.sel
); 
  84         drawtext(*text 
? text 
: NULL
, dc
.norm
); 
  86         XCopyArea(dpy
, dc
.drawable
, win
, dc
.gc
, 0, 0, mw
, mh
, 0, 0); 
  94         for(len 
= 1000; len
; len
--) { 
  95                 if(XGrabKeyboard(dpy
, parent
, True
, GrabModeAsync
, GrabModeAsync
, CurrentTime
) 
 104 kpress(XKeyEvent 
* e
) { 
 105         char buf
[sizeof text
]; 
 111         num 
= XLookupString(e
, buf
, sizeof buf
, &ksym
, NULL
); 
 112         if(ksym 
== XK_KP_Enter
) 
 114         else if(ksym 
>= XK_KP_0 
&& ksym 
<= XK_KP_9
) 
 115                 ksym 
= (ksym 
- XK_KP_0
) + XK_0
; 
 116         else if(IsFunctionKey(ksym
) || IsKeypadKey(ksym
) 
 117         || IsMiscFunctionKey(ksym
) || IsPFKey(ksym
) 
 118         || IsPrivateKeypadKey(ksym
)) 
 120         /* first check if a control mask is omitted */ 
 121         if(e
->state 
& ControlMask
) { 
 122                 switch(tolower(ksym
)) { 
 150                         memmove(text
, text 
+ cursor
, sizeof text 
- cursor 
+ 1); 
 156                                 while(i
-- > 0 && text
[i
] == ' '); 
 157                                 while(i
-- > 0 && text
[i
] != ' '); 
 158                                 memmove(text 
+ i 
+ 1, text 
+ cursor
, sizeof text 
- cursor 
+ 1); 
 166                                 if(!(fp 
= popen("sselp", "r"))) 
 167                                         eprint("cannot popen sselp\n"); 
 168                                 s 
= fgets(buf
, sizeof buf
, fp
); 
 174                         if(num 
&& buf
[num
-1] == '\n') 
 181                 num 
= MIN(num
, sizeof text 
- cursor
); 
 182                 if(num 
&& !iscntrl((int) buf
[0])) { 
 183                         memmove(text 
+ cursor 
+ num
, text 
+ cursor
, sizeof text 
- cursor 
- num
); 
 184                         memcpy(text 
+ cursor
, buf
, num
); 
 191                 for(i 
= 1; cursor 
- i 
> 0 && !IS_UTF8_1ST_CHAR(text
[cursor 
- i
]); i
++); 
 192                 memmove(text 
+ cursor 
- i
, text 
+ cursor
, sizeof text 
- cursor 
+ i
); 
 198                 for(i 
= 1; cursor 
+ i 
< len 
&& !IS_UTF8_1ST_CHAR(text
[cursor 
+ i
]); i
++); 
 199                 memmove(text 
+ cursor
, text 
+ cursor 
+ i
, sizeof text 
- cursor
); 
 214                 while(cursor
-- > 0 && !IS_UTF8_1ST_CHAR(text
[cursor
])); 
 217                 fprintf(stdout
, "%s", text
); 
 224                 while(cursor
++ < len 
&& !IS_UTF8_1ST_CHAR(text
[cursor
])); 
 234         /* main event loop */ 
 235         while(running 
&& !XNextEvent(dpy
, &ev
)) 
 241                         if(ev
.xexpose
.count 
== 0) 
 244                 case VisibilityNotify
: 
 245                         if (ev
.xvisibility
.state 
!= VisibilityUnobscured
) 
 246                                 XRaiseWindow(dpy
, win
); 
 256         XineramaScreenInfo 
*info 
= NULL
; 
 258         XModifierKeymap 
*modmap
; 
 259         XSetWindowAttributes wa
; 
 260         XWindowAttributes pwa
; 
 262         /* init modifier map */ 
 263         modmap 
= XGetModifierMapping(dpy
); 
 264         for(i 
= 0; i 
< 8; i
++) 
 265                 for(j 
= 0; j 
< modmap
->max_keypermod
; j
++) { 
 266                         if(modmap
->modifiermap
[i 
* modmap
->max_keypermod 
+ j
] 
 267                         == XKeysymToKeycode(dpy
, XK_Num_Lock
)) 
 268                                 numlockmask 
= (1 << i
); 
 270         XFreeModifiermap(modmap
); 
 275         wa
.override_redirect 
= True
; 
 276         wa
.background_pixmap 
= ParentRelative
; 
 277         wa
.event_mask 
= ExposureMask 
| ButtonPressMask 
| KeyPressMask 
| VisibilityChangeMask
; 
 279         /* menu window geometry */ 
 280         mh 
= (dc
.font
.height 
+ 2); 
 282         if(parent 
== RootWindow(dpy
, screen
) && XineramaIsActive(dpy
) && (info 
= XineramaQueryScreens(dpy
, &n
))) { 
 288                         if(XQueryPointer(dpy
, parent
, &dummy
, &dummy
, &x
, &y
, &di
, &di
, &dui
)) 
 289                                 for(i 
= 0; i 
< n
; i
++) 
 290                                         if(INRECT(x
, y
, info
[i
].x_org
, info
[i
].y_org
, info
[i
].width
, info
[i
].height
)) 
 294                 y 
= topbar 
? info
[i
].y_org 
: info
[i
].y_org 
+ info
[i
].height 
- mh
; 
 301                 XGetWindowAttributes(dpy
, parent
, &pwa
); 
 303                 y 
= topbar 
? 0 : pwa
.height 
- mh
; 
 307         win 
= XCreateWindow(dpy
, parent
, x
, y
, mw
, mh
, 0, 
 308                         DefaultDepth(dpy
, screen
), CopyFromParent
, 
 309                         DefaultVisual(dpy
, screen
), 
 310                         CWOverrideRedirect 
| CWBackPixmap 
| CWEventMask
, &wa
); 
 314                 promptw 
= MIN(textw(prompt
), mw 
/ 5); 
 315         cursor 
= strlen(text
); 
 316         XMapRaised(dpy
, win
); 
 320 main(int argc
, char *argv
[]) { 
 324         /* command line args */ 
 326         for(i 
= 1; i 
< argc
; i
++) 
 327                 if(!strcmp(argv
[i
], "-b")) 
 329                 else if(!strcmp(argv
[i
], "-e")) { 
 330                         if(++i 
< argc
) parent 
= atoi(argv
[i
]); 
 332                 else if(!strcmp(argv
[i
], "-fn")) { 
 333                         if(++i 
< argc
) font 
= argv
[i
]; 
 335                 else if(!strcmp(argv
[i
], "-nb")) { 
 336                         if(++i 
< argc
) normbgcolor 
= argv
[i
]; 
 338                 else if(!strcmp(argv
[i
], "-nf")) { 
 339                         if(++i 
< argc
) normfgcolor 
= argv
[i
]; 
 341                 else if(!strcmp(argv
[i
], "-p")) { 
 342                         if(++i 
< argc
) prompt 
= argv
[i
]; 
 344                 else if(!strcmp(argv
[i
], "-sb")) { 
 345                         if(++i 
< argc
) selbgcolor 
= argv
[i
]; 
 347                 else if(!strcmp(argv
[i
], "-sf")) { 
 348                         if(++i 
< argc
) selfgcolor 
= argv
[i
]; 
 350                 else if(!strcmp(argv
[i
], "-v")) 
 351                         eprint("dinput-"VERSION
", © 2006-2010 dinput engineers, see LICENSE for details\n"); 
 353                         strncpy(text
, argv
[i
], sizeof text
); 
 355                         eprint("usage: dinput [-b] [-e <xid>] [-fn <font>] [-nb <color>] [-nf <color>]\n" 
 356                                "              [-p <prompt>] [-sb <color>] [-sf <color>] [-v] [<text>]\n"); 
 357         if(!setlocale(LC_CTYPE
, "") || !XSupportsLocale()) 
 358                 fprintf(stderr
, "dinput: warning: no locale support\n"); 
 359         if(!(dpy 
= XOpenDisplay(NULL
))) 
 360                 eprint("cannot open display\n"); 
 361         screen 
= DefaultScreen(dpy
); 
 363                 parent 
= RootWindow(dpy
, screen
); 
 365         running 
= grabkeyboard();