fixed some warnings
[k8sterm.git] / src / x11init.c
blobd0348f95d495e1355bff059d57b71fabfaef384c
1 ////////////////////////////////////////////////////////////////////////////////
2 // x11 drawing and utils
3 /*
4 static void xcreatebw (void) {
5 if ((dc.bcol = calloc(MAX_COLOR+1, sizeof(dc.bcol[0]))) == NULL) k8t_die("out of memory");
6 //
7 for (int f = 0; f <= MAX_COLOR; ++f) {
8 XColor nclr;
9 //
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) {
19 double lumi;
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);
28 return;
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);
34 return;
36 dc.gcol[idx] = color->pixel;
40 static void xallocnamedclr (int idx, const char *cname) {
41 XColor color;
43 if (!XAllocNamedColor(xw.dpy, xw.cmap, cname, &color, &color)) {
44 fprintf(stderr, "WARNING: could not allocate color #%d: '%s'\n", idx, cname);
45 return;
47 dc.ncol[idx] = color.pixel;
48 xallocbwclr(idx, &color);
52 static void xloadcols (void) {
53 int f, r, g, b;
54 XColor color;
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];
72 if (cname == NULL) {
73 if (K8T_ARRLEN(defextcolornames) <= (unsigned)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]);
85 } else {
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);
91 } else {
92 dc.ncol[f] = color.pixel;
93 xallocbwclr(f, &color);
96 ++f;
100 for (r = 0; r < 24; ++r, ++f) {
101 if (opt_colornames[f] != NULL) {
102 xallocnamedclr(f, opt_colornames[f]);
103 } else {
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);
107 } else {
108 dc.ncol[f] = color.pixel;
109 xallocbwclr(f, &color);
114 for (size_t f = 0; f < K8T_ARRLEN(opt_colornames); ++f) {
115 if (opt_colornames[f]) free(opt_colornames[f]);
120 static void xhints (void) {
121 XClassHint class = {opt_class, opt_title};
122 XWMHints wm = {.flags = InputHint, .input = 1};
123 XSizeHints size = {
124 .flags = PSize|PResizeInc|PBaseSize,
125 .height = xw.h,
126 .width = xw.w,
127 .height_inc = xw.ch,
128 .width_inc = xw.cw,
129 .base_height = xw.h/*xw.tabheight*/,
130 .base_width = xw.w,
132 //XSetWMNormalHints(xw.dpy, xw.win, &size);
133 XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, &size, &wm, &class);
134 XSetWMProtocols(xw.dpy, xw.win, &XA_WM_DELETE_WINDOW, 1);
138 #ifdef X11_USE_FUCKED_FONTSETS
139 static XFontSet xinitfont (const char *fontstr) {
140 XFontSet set;
141 char *def, **missing;
142 int n;
144 missing = NULL;
145 set = XCreateFontSet(xw.dpy, fontstr, &missing, &n, &def);
146 if (missing) {
147 while (n--) fprintf(stderr, "sterm: missing fontset: %s\n", missing[n]);
148 XFreeStringList(missing);
150 return set;
152 #else
153 static XFontStruct *xinitfont (const char *fontstr) {
154 XFontStruct *fst = NULL;
155 int fcount = 0;
156 char **flist = XListFonts(xw.dpy, (char *)fontstr, 32700/*maxnames*/, &fcount);
157 if (flist) {
158 //for (int f = 0; f < fcount; ++f) fprintf(stderr, "F#%d: <%s>\n", f, flist[f]);
159 for (int f = 0; f < fcount; ++f) {
160 if (strstr(flist[f], "-iso10646-1")) {
161 fst = XLoadQueryFont(xw.dpy, flist[f]);
162 if (fst) {
163 int dir, ascent, descent;
164 XCharStruct cs;
165 XQueryTextExtents(xw.dpy, fst->fid, "W", 1, &dir, &ascent, &descent, &cs);
166 if (ascent+descent > 0 && cs.rbearing-cs.lbearing > 0 && cs.width > 0) {
167 fprintf(stderr, "X11: loaded font '%s' (hgt=%d; wdt=%d)\n", flist[f], (int)(ascent+descent), (int)cs.width);
168 break;
169 } else {
170 fprintf(stderr, "X11: rejected font '%s'\n", flist[f]);
171 XFreeFont(xw.dpy, fst);
176 XFreeFontNames(flist);
178 if (!fst) {
179 fst = XLoadQueryFont(xw.dpy, (char *)fontstr);
181 return fst;
183 #endif
186 #ifdef X11_USE_FUCKED_FONTSETS
187 static void xgetfontinfo (XFontSet set, int *ascent, int *descent, int *width, Font *fid, int monocheck) {
188 XFontStruct **xfonts;
189 char **font_names;
190 int n;
192 *ascent = *descent = 0;
193 int lbearing = 0, rbearing = 0;
194 n = XFontsOfFontSet(set, &xfonts, &font_names);
195 for (int f = 0; f < n; ++f, ++xfonts) {
196 //fprintf(stderr, "--%d-- [%s] a=%d; d=%d\n", f, font_names[f], (*xfonts)->ascent, (*xfonts)->descent);
197 if (f == 0) *fid = (*xfonts)->fid;
198 //if (*rbearing != 0 && (*xfonts)->max_bounds.rbearing > (*rbearing)*2-(*rbearing)/2) continue; /*HACK: skip too wide fonts*/
199 *ascent = K8T_MAX(*ascent, (*xfonts)->ascent);
200 *descent = K8T_MAX(*descent, (*xfonts)->descent);
201 #if 1
203 fprintf(stderr, "--%d-- [%s]\n", f, font_names[f]);
204 fprintf(stderr, " ib: l=%d; r=%d\n", (*xfonts)->min_bounds.lbearing, (*xfonts)->min_bounds.rbearing);
205 fprintf(stderr, " ab: l=%d; r=%d\n", (*xfonts)->max_bounds.lbearing, (*xfonts)->max_bounds.rbearing);
207 lbearing = K8T_MAX(lbearing, (*xfonts)->min_bounds.lbearing);
208 rbearing = K8T_MAX(rbearing, (*xfonts)->max_bounds.rbearing);
209 #else
210 XRectangle r;
211 memset(&r, 0, sizeof(r));
212 XmbTextExtents(set, "W", 1, &r, NULL);
213 fprintf(stderr, "x=%d; w=%d\n", r.x, r.width);
214 fprintf(stderr, " ib: l=%d; r=%d\n", (*xfonts)->min_bounds.lbearing, (*xfonts)->min_bounds.rbearing);
215 fprintf(stderr, " ab: l=%d; r=%d\n", (*xfonts)->max_bounds.lbearing, (*xfonts)->max_bounds.rbearing);
216 lbearing = K8T_MAX(lbearing, r.x);
217 rbearing = K8T_MAX(rbearing, r.width);
218 #endif
219 *width = rbearing-lbearing;
220 break; /*HACK: use first font in set*/
223 #else
224 static void xgetfontinfo (XFontStruct *set, int *ascent, int *descent, int *width, Font *fid, int monocheck) {
225 int dir;
226 XCharStruct cs;
227 *fid = set->fid;
228 XQueryTextExtents(xw.dpy, set->fid, "W", 1, &dir, ascent, descent, &cs);
229 *width = cs.width;
230 if (!(cs.width > 0 && *ascent+*descent > 0)) {
231 k8t_die("X11: specified X font has invalid dimensions");
232 return;
234 //fprintf(stderr, "ASCENT: %d; DESCENT: %d; lb=%d; rb=%d\n", font->ascent, font->descent, font->lbearing, font->rbearing);
236 if (monocheck) {
237 // rough check for monospaced font
238 const char *wcs[9] = {"A", "W", "I", "i", "0", "1", "-", "g", "b"};
239 int wdt[9] = {0};
241 for (unsigned f = 0; f < 9; ++f) {
242 wdt[f] = XTextWidth(set, wcs[f], 1);
245 for (unsigned f = 0; f < 9; ++f) {
246 for (unsigned c = 0; c < 9; ++c) {
247 if (wdt[f] != wdt[c]) {
248 k8t_die("X11: specified X font is not monospaced");
249 return;
255 #endif
259 static int isUTF8LocaleName (const char *lang) {
260 if (!lang) return 0;
261 while (*lang) {
262 if ((lang[0]|0x20) == 'u' && (lang[1]|0x20) == 't' && (lang[2]|0x20) == 'f') return 1;
263 ++lang;
265 return 0;
270 static void initfonts (const char *fontstr, const char *bfontstr, const char *tabfont) {
271 #ifdef X11_USE_FUCKED_FONTSETS
272 char *olocale;
273 /* X Core Fonts fix */
274 /* sorry, we HAVE to do this shit here!
275 * braindamaged X11 will not work with utf-8 in Xmb*() correctly if we have, for example,
276 * koi8 as system locale unless we first create font set in system locale. don't even ask
277 * me why X.Org is so fuckin' broken. */
278 XFontSet tmp_fs;
279 char **missing;
280 int missing_count;
281 olocale = strdup(setlocale(LC_ALL, NULL)); /*FIXME: this can fail if we have no memory; fuck it*/
282 setlocale(LC_ALL, "");
283 tmp_fs = XCreateFontSet(xw.dpy, "-*-*-*-*-*-*-*-*-*-*-*-*-*", &missing, &missing_count, NULL);
284 if (!tmp_fs) {
285 fprintf(stderr, "FATAL: can't apply workarount for X Core FontSets!\n");
286 exit(1);
288 if (missing) XFreeStringList(missing);
289 /* throw out unused fontset */
290 XFreeFontSet(xw.dpy, tmp_fs);
291 //setlocale(LC_ALL, "ru_RU.utf-8");
292 /*TODO: find suitable utf-8 encoding */
293 if (!isUTF8LocaleName(setlocale(LC_ALL, NULL)) {
294 //setlocale(LC_ALL, "en_US.UTF-8");
295 if (!setlocale(LC_ALL, "en_US.UTF-8") && !setlocale(LC_ALL, "en_US.UTF8") && !setlocale(LC_ALL, "en_US.utf8")) {
296 fprintf(stderr, "FATAL: can't set UTF locale!\n");
297 exit(1);
300 /* create fonts for utf-8 locale */
301 #endif
302 if ((dc.font[0].set = xinitfont(fontstr)) == NULL) {
303 if ((dc.font[0].set = xinitfont(FONT)) == NULL) k8t_die("can't load font '%s'", fontstr);
305 xgetfontinfo(dc.font[0].set, &dc.font[0].ascent, &dc.font[0].descent, &dc.font[0].width, &dc.font[0].fid, 1);
306 if ((dc.font[1].set = xinitfont(bfontstr)) == NULL) {
307 if ((dc.font[1].set = xinitfont(FONTBOLD)) == NULL) k8t_die("can't load font '%s'", bfontstr);
309 xgetfontinfo(dc.font[1].set, &dc.font[1].ascent, &dc.font[1].descent, &dc.font[1].width, &dc.font[1].fid, 1);
310 if ((dc.font[2].set = xinitfont(tabfont)) == NULL) {
311 if ((dc.font[2].set = xinitfont(FONTTAB)) == NULL) k8t_die("can't load font '%s'", tabfont);
313 xgetfontinfo(dc.font[2].set, &dc.font[2].ascent, &dc.font[2].descent, &dc.font[2].width, &dc.font[2].fid, 0);
314 /* restore locale */
315 #ifdef X11_USE_FUCKED_FONTSETS
316 setlocale(LC_ALL, olocale);
317 free(olocale);
318 #endif
322 static void xinit (void) {
323 XSetWindowAttributes attrs;
324 Window parent;
325 XColor blackcolor = { 0, 0, 0, 0, 0, 0 };
326 int wwdt, whgt;
328 if (!(xw.dpy = XOpenDisplay(NULL))) k8t_die("can't open display");
330 XA_VT_SELECTION = XInternAtom(xw.dpy, "_K8STERM_SELECTION_PROP_", 0);
331 XA_CLIPBOARD = XInternAtom(xw.dpy, "CLIPBOARD", 0);
332 XA_UTF8 = XInternAtom(xw.dpy, "UTF8_STRING", 0);
333 XA_NETWM_NAME = XInternAtom(xw.dpy, "_NET_WM_NAME", 0);
334 XA_TARGETS = XInternAtom(xw.dpy, "TARGETS", 0);
335 XA_WM_DELETE_WINDOW = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", 0);
336 XA_INCR = XInternAtom(xw.dpy, "INCR", 0);
337 XA_CSTRING = XInternAtom(xw.dpy, "C_STRING", 0);
338 xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
340 xw.paste_term = NULL;
342 xw.scr = XDefaultScreen(xw.dpy);
343 /* font */
344 initfonts(opt_fontnorm, opt_fontbold, opt_fonttab);
345 /* XXX: Assuming same size for bold font */
346 xw.cw = dc.font[0].width;
347 xw.ch = dc.font[0].ascent+dc.font[0].descent;
348 xw.tch = dc.font[2].ascent+dc.font[2].descent;
349 xw.tabheight = opt_disabletabs ? 0 : xw.tch+2;
350 //xw.tabheight = 0;
351 /* colors */
352 xw.cmap = XDefaultColormap(xw.dpy, xw.scr);
353 xloadcols();
354 /* window - default size */
356 K8T_DATA(curterm)->picbufh = curterm->row*xw.ch;
357 K8T_DATA(curterm)->picbufw = curterm->col*xw.cw;
359 wwdt = curterm->col*xw.cw;
360 whgt = curterm->row*xw.ch;
362 xw.h = whgt+xw.tabheight;
363 xw.w = wwdt;
365 attrs.background_pixel = getColor(defaultBG);
366 attrs.border_pixel = getColor(defaultBG);
367 attrs.bit_gravity = NorthWestGravity;
368 attrs.event_mask =
369 FocusChangeMask|KeyPressMask|
370 ExposureMask|VisibilityChangeMask|StructureNotifyMask|
371 /*ButtonMotionMask|*/PointerMotionMask|ButtonPressMask|ButtonReleaseMask|
372 EnterWindowMask|LeaveWindowMask|
373 PropertyChangeMask; // for selection pasting
374 attrs.colormap = xw.cmap;
375 //fprintf(stderr, "oe: [%s]\n", opt_embed);
376 parent = opt_embed ? (Window)strtol(opt_embed, NULL, 0) : XRootWindow(xw.dpy, xw.scr);
377 xw.win = XCreateWindow(xw.dpy, parent, 0, 0,
378 xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
379 XDefaultVisual(xw.dpy, xw.scr),
380 CWBackPixel|CWBorderPixel|CWBitGravity|CWEventMask|CWColormap,
381 &attrs);
382 xhints();
384 xw.pictab = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.tabheight>0?xw.tabheight:1, XDefaultDepth(xw.dpy, xw.scr));
385 /* input methods */
386 if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) k8t_die("XOpenIM() failed");
387 xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL);
388 /* gc */
389 dc.gc = XCreateGC(xw.dpy, xw.win, 0, NULL);
390 #ifdef X11_USE_FUCKED_FONTSETS
391 // nothing
392 #else
393 XSetFont(xw.dpy, dc.gc, dc.font[0].fid);
394 dc.gcfid = dc.font[0].fid;
395 #endif
397 xw.lastcursor = xw.cursor = XCreateFontCursor(xw.dpy, XC_xterm);
398 //xw.cursor = XCreateFontCursor(xw.dpy, XC_arrow);
399 /* green cursor, black outline */
400 XRecolorCursor(xw.dpy, xw.cursor,
401 &(XColor){.red = 0x0000, .green = 0xffff, .blue = 0x0000},
402 &(XColor){.red = 0x0000, .green = 0x0000, .blue = 0x0000});
404 xw.defcursor = XCreateFontCursor(xw.dpy, /*XC_X_cursor*/XC_left_ptr);
405 XRecolorCursor(xw.dpy, xw.defcursor,
406 &(XColor){.red = 0x0000, .green = 0xffff, .blue = 0x0000},
407 &(XColor){.red = 0x0000, .green = 0x0000, .blue = 0x0000});
409 XDefineCursor(xw.dpy, xw.win, xw.lastcursor);
410 fixWindowTitle(curterm);
411 //XStoreName(xw.dpy, xw.win, opt_title);
413 XSetForeground(xw.dpy, dc.gc, 0);
414 if (xw.tabheight > 0) XFillRectangle(xw.dpy, xw.pictab, dc.gc, 0, 0, xw.w, xw.tabheight);
416 xw.picscrhere = 0;
417 termCreateXPixmap(curterm);
419 XMapWindow(xw.dpy, xw.win);
421 #if BLANKPTR_USE_GLYPH_CURSOR
422 xw.blankPtr = XCreateGlyphCursor(xw.dpy, dc.font[0].fid, dc.font[0].fid, ' ', ' ', &blackcolor, &blackcolor);
423 #else
424 static const char cmbmp[1] = {0};
425 Pixmap pm;
427 pm = XCreateBitmapFromData(xw.dpy, xw.win, cmbmp, 1, 1);
428 xw.blankPtr = XCreatePixmapCursor(xw.dpy, pm, pm, &blackcolor, &blackcolor, 0, 0);
429 XFreePixmap(xw.dpy, pm);
430 #endif
432 XSync(xw.dpy, 0);
436 void xdone (void) {
437 if (xw.xim) XCloseIM(xw.xim);
438 if (xw.dpy) XCloseDisplay(xw.dpy);