1 ////////////////////////////////////////////////////////////////////////////////
2 // x11 drawing and utils
4 static void xcreatebw (void) {
5 if ((dc.bcol = calloc(MAX_COLOR+1, sizeof(dc.bcol[0]))) == NULL) k8t_die("out of memory");
7 for (int f = 0; f <= MAX_COLOR; ++f) {
10 nclr = dc.ncol[f].pixel;
11 XQueryColor(xw.dpy, xw.cmap, &nclr);
12 fprintf(stderr, "%d: r=%u; g=%u; b=%u\n", f, nclr.red, nclr.green, nclr.blue);
18 static void xallocbwclr (int idx
, XColor
*color
) {
21 XQueryColor(xw
.dpy
, xw
.cmap
, color
);
22 //fprintf(stderr, "%d: r=%u; g=%u; b=%u\n", idx, color->red, color->green, color->blue);
24 lumi
= 0.3*((double)color
->red
/65535.0)+0.59*((double)color
->green
/65535.0)+0.11*((double)color
->blue
/65535.0);
25 color
->red
= color
->green
= color
->blue
= (int)(lumi
*65535.0);
26 if (!XAllocColor(xw
.dpy
, xw
.cmap
, color
)) {
27 fprintf(stderr
, "WARNING: could not allocate b/w color #%d\n", idx
);
30 dc
.bcol
[idx
] = color
->pixel
;
31 color
->red
= color
->blue
= 0;
32 if (!XAllocColor(xw
.dpy
, xw
.cmap
, color
)) {
33 fprintf(stderr
, "WARNING: could not allocate b/w color #%d\n", idx
);
36 dc
.gcol
[idx
] = color
->pixel
;
40 static void xallocnamedclr (int idx
, const char *cname
) {
43 if (!XAllocNamedColor(xw
.dpy
, xw
.cmap
, cname
, &color
, &color
)) {
44 fprintf(stderr
, "WARNING: could not allocate color #%d: '%s'\n", idx
, cname
);
47 dc
.ncol
[idx
] = color
.pixel
;
48 xallocbwclr(idx
, &color
);
52 static void xloadcols (void) {
55 uint32_t white
= WhitePixel(xw
.dpy
, xw
.scr
);
57 if ((dc
.clrs
[0] = dc
.ncol
= calloc(MAX_COLOR
+1, sizeof(dc
.ncol
[0]))) == NULL
) k8t_die("out of memory");
58 if ((dc
.clrs
[1] = dc
.bcol
= calloc(MAX_COLOR
+1, sizeof(dc
.bcol
[0]))) == NULL
) k8t_die("out of memory");
59 if ((dc
.clrs
[2] = dc
.gcol
= calloc(MAX_COLOR
+1, sizeof(dc
.gcol
[0]))) == NULL
) k8t_die("out of memory");
61 for (f
= 0; f
<= MAX_COLOR
; ++f
) dc
.ncol
[f
] = dc
.bcol
[f
] = white
;
62 /* load colors [0-15] */
63 for (f
= 0; f
<= 15; ++f
) {
64 const char *cname
= opt_colornames
[f
]!=NULL
?opt_colornames
[f
]:defcolornames
[f
];
66 xallocnamedclr(f
, cname
);
68 /* load colors [256-...] */
69 for (f
= 256; f
<= MAX_COLOR
; ++f
) {
70 const char *cname
= opt_colornames
[f
];
73 if (K8T_ARRLEN(defextcolornames
) <= f
-256) continue;
74 cname
= defextcolornames
[f
-256];
76 if (cname
== NULL
) continue;
77 xallocnamedclr(f
, cname
);
79 /* load colors [16-255] ; same colors as xterm */
80 for (f
= 16, r
= 0; r
< 6; ++r
) {
81 for (g
= 0; g
< 6; ++g
) {
82 for (b
= 0; b
< 6; ++b
) {
83 if (opt_colornames
[f
] != NULL
) {
84 xallocnamedclr(f
, opt_colornames
[f
]);
86 color
.red
= r
== 0 ? 0 : 0x3737+0x2828*r
;
87 color
.green
= g
== 0 ? 0 : 0x3737+0x2828*g
;
88 color
.blue
= b
== 0 ? 0 : 0x3737+0x2828*b
;
89 if (!XAllocColor(xw
.dpy
, xw
.cmap
, &color
)) {
90 fprintf(stderr
, "WARNING: could not allocate color #%d\n", f
);
92 dc
.ncol
[f
] = color
.pixel
;
93 xallocbwclr(f
, &color
);
100 for (r
= 0; r
< 24; ++r
, ++f
) {
101 if (opt_colornames
[f
] != NULL
) {
102 xallocnamedclr(f
, opt_colornames
[f
]);
104 color
.red
= color
.green
= color
.blue
= 0x0808+0x0a0a*r
;
105 if (!XAllocColor(xw
.dpy
, xw
.cmap
, &color
)) {
106 fprintf(stderr
, "WARNING: could not allocate color #%d\n", f
);
108 dc
.ncol
[f
] = color
.pixel
;
109 xallocbwclr(f
, &color
);
114 for (int f
= 0; f
< K8T_ARRLEN(opt_colornames
); ++f
) if (opt_colornames
[f
]) free(opt_colornames
[f
]);
118 static void xhints (void) {
119 XClassHint
class = {opt_class
, opt_title
};
120 XWMHints wm
= {.flags
= InputHint
, .input
= 1};
122 .flags
= PSize
|PResizeInc
|PBaseSize
,
127 .base_height
= xw
.h
/*xw.tabheight*/,
130 //XSetWMNormalHints(xw.dpy, xw.win, &size);
131 XSetWMProperties(xw
.dpy
, xw
.win
, NULL
, NULL
, NULL
, 0, &size
, &wm
, &class);
132 XSetWMProtocols(xw
.dpy
, xw
.win
, &XA_WM_DELETE_WINDOW
, 1);
136 static XFontSet
xinitfont (const char *fontstr
) {
138 char *def
, **missing
;
142 set
= XCreateFontSet(xw
.dpy
, fontstr
, &missing
, &n
, &def
);
144 while (n
--) fprintf(stderr
, "sterm: missing fontset: %s\n", missing
[n
]);
145 XFreeStringList(missing
);
151 static void xgetfontinfo (XFontSet set
, int *ascent
, int *descent
, short *lbearing
, short *rbearing
, Font
*fid
) {
152 XFontStruct
**xfonts
;
156 *ascent
= *descent
= *lbearing
= *rbearing
= 0;
157 n
= XFontsOfFontSet(set
, &xfonts
, &font_names
);
158 for (int f
= 0; f
< n
; ++f
, ++xfonts
) {
159 //fprintf(stderr, "--%d-- [%s] a=%d; d=%d\n", f, font_names[f], (*xfonts)->ascent, (*xfonts)->descent);
160 if (f
== 0) *fid
= (*xfonts
)->fid
;
161 //if (*rbearing != 0 && (*xfonts)->max_bounds.rbearing > (*rbearing)*2-(*rbearing)/2) continue; /*HACK: skip too wide fonts*/
162 *ascent
= K8T_MAX(*ascent
, (*xfonts
)->ascent
);
163 *descent
= K8T_MAX(*descent
, (*xfonts
)->descent
);
166 fprintf(stderr, "--%d-- [%s]\n", f, font_names[f]);
167 fprintf(stderr, " ib: l=%d; r=%d\n", (*xfonts)->min_bounds.lbearing, (*xfonts)->min_bounds.rbearing);
168 fprintf(stderr, " ab: l=%d; r=%d\n", (*xfonts)->max_bounds.lbearing, (*xfonts)->max_bounds.rbearing);
170 *lbearing
= K8T_MAX(*lbearing
, (*xfonts
)->min_bounds
.lbearing
);
171 *rbearing
= K8T_MAX(*rbearing
, (*xfonts
)->max_bounds
.rbearing
);
174 memset(&r
, 0, sizeof(r
));
175 XmbTextExtents(set
, "W", 1, &r
, NULL
);
176 fprintf(stderr
, "x=%d; w=%d\n", r
.x
, r
.width
);
177 fprintf(stderr
, " ib: l=%d; r=%d\n", (*xfonts
)->min_bounds
.lbearing
, (*xfonts
)->min_bounds
.rbearing
);
178 fprintf(stderr
, " ab: l=%d; r=%d\n", (*xfonts
)->max_bounds
.lbearing
, (*xfonts
)->max_bounds
.rbearing
);
179 *lbearing
= K8T_MAX(*lbearing
, r
.x
);
180 *rbearing
= K8T_MAX(*rbearing
, r
.width
);
182 break; /*HACK: use first font in set*/
187 static void initfonts (const char *fontstr
, const char *bfontstr
, const char *tabfont
) {
189 /* X Core Fonts fix */
190 /* sorry, we HAVE to do this shit here!
191 * braindamaged X11 will not work with utf-8 in Xmb*() correctly if we have, for example,
192 * koi8 as system locale unless we first create font set in system locale. don't even ask
193 * me why X.Org is so fuckin' broken. */
197 olocale
= strdup(setlocale(LC_ALL
, NULL
)); /*FIXME: this can fail if we have no memory; fuck it*/
198 setlocale(LC_ALL
, "");
199 tmp_fs
= XCreateFontSet(xw
.dpy
, "-*-*-*-*-*-*-*-*-*-*-*-*-*", &missing
, &missing_count
, NULL
);
201 fprintf(stderr
, "FATAL: can't apply workarount for X Core FontSets!\n");
204 if (missing
) XFreeStringList(missing
);
205 /* throw out unused fontset */
206 XFreeFontSet(xw
.dpy
, tmp_fs
);
207 //setlocale(LC_ALL, "ru_RU.utf-8");
208 /*TODO: find suitable utf-8 encoding */
209 setlocale(LC_ALL
, "en_US.UTF-8");
210 /* create fonts for utf-8 locale */
211 if ((dc
.font
[0].set
= xinitfont(fontstr
)) == NULL
) {
212 if ((dc
.font
[0].set
= xinitfont(FONT
)) == NULL
) k8t_die("can't load font %s", fontstr
);
214 xgetfontinfo(dc
.font
[0].set
, &dc
.font
[0].ascent
, &dc
.font
[0].descent
, &dc
.font
[0].lbearing
, &dc
.font
[0].rbearing
, &dc
.font
[0].fid
);
215 if ((dc
.font
[1].set
= xinitfont(bfontstr
)) == NULL
) {
216 if ((dc
.font
[1].set
= xinitfont(FONTBOLD
)) == NULL
) k8t_die("can't load font %s", bfontstr
);
218 xgetfontinfo(dc
.font
[1].set
, &dc
.font
[1].ascent
, &dc
.font
[1].descent
, &dc
.font
[1].lbearing
, &dc
.font
[1].rbearing
, &dc
.font
[1].fid
);
219 if ((dc
.font
[2].set
= xinitfont(tabfont
)) == NULL
) {
220 if ((dc
.font
[2].set
= xinitfont(FONTTAB
)) == NULL
) k8t_die("can't load font %s", tabfont
);
222 xgetfontinfo(dc
.font
[2].set
, &dc
.font
[2].ascent
, &dc
.font
[2].descent
, &dc
.font
[2].lbearing
, &dc
.font
[2].rbearing
, &dc
.font
[2].fid
);
224 setlocale(LC_ALL
, olocale
);
229 static void xinit (void) {
230 XSetWindowAttributes attrs
;
232 XColor blackcolor
= { 0, 0, 0, 0, 0, 0 };
235 if (!(xw
.dpy
= XOpenDisplay(NULL
))) k8t_die("can't open display");
237 XA_VT_SELECTION
= XInternAtom(xw
.dpy
, "_STERM_SELECTION_", 0);
238 XA_CLIPBOARD
= XInternAtom(xw
.dpy
, "CLIPBOARD", 0);
239 XA_UTF8
= XInternAtom(xw
.dpy
, "UTF8_STRING", 0);
240 XA_NETWM_NAME
= XInternAtom(xw
.dpy
, "_NET_WM_NAME", 0);
241 XA_TARGETS
= XInternAtom(xw
.dpy
, "TARGETS", 0);
242 XA_WM_DELETE_WINDOW
= XInternAtom(xw
.dpy
, "WM_DELETE_WINDOW", 0);
243 xw
.xembed
= XInternAtom(xw
.dpy
, "_XEMBED", False
);
245 xw
.scr
= XDefaultScreen(xw
.dpy
);
247 initfonts(opt_fontnorm
, opt_fontbold
, opt_fonttab
);
248 /* XXX: Assuming same size for bold font */
249 xw
.cw
= dc
.font
[0].rbearing
-dc
.font
[0].lbearing
;
250 xw
.ch
= dc
.font
[0].ascent
+dc
.font
[0].descent
;
251 xw
.tch
= dc
.font
[2].ascent
+dc
.font
[2].descent
;
252 xw
.tabheight
= opt_disabletabs
? 0 : xw
.tch
+2;
255 xw
.cmap
= XDefaultColormap(xw
.dpy
, xw
.scr
);
257 /* window - default size */
259 K8T_DATA(curterm)->picbufh = curterm->row*xw.ch;
260 K8T_DATA(curterm)->picbufw = curterm->col*xw.cw;
262 wwdt
= curterm
->col
*xw
.cw
;
263 whgt
= curterm
->row
*xw
.ch
;
265 xw
.h
= whgt
+xw
.tabheight
;
268 attrs
.background_pixel
= getColor(defaultBG
);
269 attrs
.border_pixel
= getColor(defaultBG
);
270 attrs
.bit_gravity
= NorthWestGravity
;
272 FocusChangeMask
|KeyPressMask
|
273 ExposureMask
|VisibilityChangeMask
|StructureNotifyMask
|
274 /*ButtonMotionMask|*/PointerMotionMask
|ButtonPressMask
|ButtonReleaseMask
|
275 EnterWindowMask
|LeaveWindowMask
;
276 attrs
.colormap
= xw
.cmap
;
277 //fprintf(stderr, "oe: [%s]\n", opt_embed);
278 parent
= opt_embed
? strtol(opt_embed
, NULL
, 0) : XRootWindow(xw
.dpy
, xw
.scr
);
279 xw
.win
= XCreateWindow(xw
.dpy
, parent
, 0, 0,
280 xw
.w
, xw
.h
, 0, XDefaultDepth(xw
.dpy
, xw
.scr
), InputOutput
,
281 XDefaultVisual(xw
.dpy
, xw
.scr
),
282 CWBackPixel
|CWBorderPixel
|CWBitGravity
|CWEventMask
|CWColormap
,
286 xw
.pictab
= XCreatePixmap(xw
.dpy
, xw
.win
, xw
.w
, xw
.tabheight
>0?xw
.tabheight
:1, XDefaultDepth(xw
.dpy
, xw
.scr
));
288 if ((xw
.xim
= XOpenIM(xw
.dpy
, NULL
, NULL
, NULL
)) == NULL
) k8t_die("XOpenIM() failed");
289 xw
.xic
= XCreateIC(xw
.xim
, XNInputStyle
, XIMPreeditNothing
|XIMStatusNothing
, XNClientWindow
, xw
.win
, XNFocusWindow
, xw
.win
, NULL
);
291 dc
.gc
= XCreateGC(xw
.dpy
, xw
.win
, 0, NULL
);
293 xw
.lastcursor
= xw
.cursor
= XCreateFontCursor(xw
.dpy
, XC_xterm
);
294 //xw.cursor = XCreateFontCursor(xw.dpy, XC_arrow);
295 /* green cursor, black outline */
296 XRecolorCursor(xw
.dpy
, xw
.cursor
,
297 &(XColor
){.red
= 0x0000, .green
= 0xffff, .blue
= 0x0000},
298 &(XColor
){.red
= 0x0000, .green
= 0x0000, .blue
= 0x0000});
300 xw
.defcursor
= XCreateFontCursor(xw
.dpy
, /*XC_X_cursor*/XC_left_ptr
);
301 XRecolorCursor(xw
.dpy
, xw
.defcursor
,
302 &(XColor
){.red
= 0x0000, .green
= 0xffff, .blue
= 0x0000},
303 &(XColor
){.red
= 0x0000, .green
= 0x0000, .blue
= 0x0000});
305 XDefineCursor(xw
.dpy
, xw
.win
, xw
.lastcursor
);
306 fixWindowTitle(curterm
);
307 //XStoreName(xw.dpy, xw.win, opt_title);
309 XSetForeground(xw
.dpy
, dc
.gc
, 0);
310 if (xw
.tabheight
> 0) XFillRectangle(xw
.dpy
, xw
.pictab
, dc
.gc
, 0, 0, xw
.w
, xw
.tabheight
);
313 termCreateXPixmap(curterm
);
315 XMapWindow(xw
.dpy
, xw
.win
);
317 #if BLANKPTR_USE_GLYPH_CURSOR
318 xw
.blankPtr
= XCreateGlyphCursor(xw
.dpy
, dc
.font
[0].fid
, dc
.font
[0].fid
, ' ', ' ', &blackcolor
, &blackcolor
);
320 static const char cmbmp
[1] = {0};
323 pm
= XCreateBitmapFromData(xw
.dpy
, xw
.win
, cmbmp
, 1, 1);
324 xw
.blankPtr
= XCreatePixmapCursor(xw
.dpy
, pm
, pm
, &blackcolor
, &blackcolor
, 0, 0);
325 XFreePixmap(xw
.dpy
, pm
);