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
) {
159 if (f
== 0) *fid
= (*xfonts
)->fid
;
160 *ascent
= K8T_MAX(*ascent
, (*xfonts
)->ascent
);
161 *descent
= K8T_MAX(*descent
, (*xfonts
)->descent
);
162 *lbearing
= K8T_MAX(*lbearing
, (*xfonts
)->min_bounds
.lbearing
);
163 *rbearing
= K8T_MAX(*rbearing
, (*xfonts
)->max_bounds
.rbearing
);
169 static void initfonts (const char *fontstr
, const char *bfontstr
, const char *tabfont
) {
170 if ((dc
.font
[0].set
= xinitfont(fontstr
)) == NULL
) {
171 if ((dc
.font
[0].set
= xinitfont(FONT
)) == NULL
) k8t_die("can't load font %s", fontstr
);
173 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
);
175 if ((dc
.font
[1].set
= xinitfont(bfontstr
)) == NULL
) {
176 if ((dc
.font
[1].set
= xinitfont(FONTBOLD
)) == NULL
) k8t_die("can't load font %s", bfontstr
);
178 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
);
180 if ((dc
.font
[2].set
= xinitfont(tabfont
)) == NULL
) {
181 if ((dc
.font
[2].set
= xinitfont(FONTTAB
)) == NULL
) k8t_die("can't load font %s", tabfont
);
183 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
);
187 static void xinit (void) {
188 XSetWindowAttributes attrs
;
190 XColor blackcolor
= { 0, 0, 0, 0, 0, 0 };
193 if (!(xw
.dpy
= XOpenDisplay(NULL
))) k8t_die("can't open display");
195 XA_VT_SELECTION
= XInternAtom(xw
.dpy
, "_STERM_SELECTION_", 0);
196 XA_CLIPBOARD
= XInternAtom(xw
.dpy
, "CLIPBOARD", 0);
197 XA_UTF8
= XInternAtom(xw
.dpy
, "UTF8_STRING", 0);
198 XA_NETWM_NAME
= XInternAtom(xw
.dpy
, "_NET_WM_NAME", 0);
199 XA_TARGETS
= XInternAtom(xw
.dpy
, "TARGETS", 0);
200 XA_WM_DELETE_WINDOW
= XInternAtom(xw
.dpy
, "WM_DELETE_WINDOW", 0);
201 xw
.xembed
= XInternAtom(xw
.dpy
, "_XEMBED", False
);
203 xw
.scr
= XDefaultScreen(xw
.dpy
);
205 initfonts(opt_fontnorm
, opt_fontbold
, opt_fonttab
);
206 /* XXX: Assuming same size for bold font */
207 xw
.cw
= dc
.font
[0].rbearing
-dc
.font
[0].lbearing
;
208 xw
.ch
= dc
.font
[0].ascent
+dc
.font
[0].descent
;
209 xw
.tch
= dc
.font
[2].ascent
+dc
.font
[2].descent
;
210 xw
.tabheight
= opt_disabletabs
? 0 : xw
.tch
+2;
213 xw
.cmap
= XDefaultColormap(xw
.dpy
, xw
.scr
);
215 /* window - default size */
217 K8T_DATA(curterm)->picbufh = curterm->row*xw.ch;
218 K8T_DATA(curterm)->picbufw = curterm->col*xw.cw;
220 wwdt
= curterm
->col
*xw
.cw
;
221 whgt
= curterm
->row
*xw
.ch
;
223 xw
.h
= whgt
+xw
.tabheight
;
226 attrs
.background_pixel
= getColor(defaultBG
);
227 attrs
.border_pixel
= getColor(defaultBG
);
228 attrs
.bit_gravity
= NorthWestGravity
;
230 FocusChangeMask
|KeyPressMask
|
231 ExposureMask
|VisibilityChangeMask
|StructureNotifyMask
|
232 /*ButtonMotionMask|*/PointerMotionMask
|ButtonPressMask
|ButtonReleaseMask
|
233 EnterWindowMask
|LeaveWindowMask
;
234 attrs
.colormap
= xw
.cmap
;
235 //fprintf(stderr, "oe: [%s]\n", opt_embed);
236 parent
= opt_embed
? strtol(opt_embed
, NULL
, 0) : XRootWindow(xw
.dpy
, xw
.scr
);
237 xw
.win
= XCreateWindow(xw
.dpy
, parent
, 0, 0,
238 xw
.w
, xw
.h
, 0, XDefaultDepth(xw
.dpy
, xw
.scr
), InputOutput
,
239 XDefaultVisual(xw
.dpy
, xw
.scr
),
240 CWBackPixel
|CWBorderPixel
|CWBitGravity
|CWEventMask
|CWColormap
,
244 xw
.pictab
= XCreatePixmap(xw
.dpy
, xw
.win
, xw
.w
, xw
.tabheight
>0?xw
.tabheight
:1, XDefaultDepth(xw
.dpy
, xw
.scr
));
246 if ((xw
.xim
= XOpenIM(xw
.dpy
, NULL
, NULL
, NULL
)) == NULL
) k8t_die("XOpenIM() failed");
247 xw
.xic
= XCreateIC(xw
.xim
, XNInputStyle
, XIMPreeditNothing
|XIMStatusNothing
, XNClientWindow
, xw
.win
, XNFocusWindow
, xw
.win
, NULL
);
249 dc
.gc
= XCreateGC(xw
.dpy
, xw
.win
, 0, NULL
);
251 xw
.lastcursor
= xw
.cursor
= XCreateFontCursor(xw
.dpy
, XC_xterm
);
252 //xw.cursor = XCreateFontCursor(xw.dpy, XC_arrow);
253 /* green cursor, black outline */
254 XRecolorCursor(xw
.dpy
, xw
.cursor
,
255 &(XColor
){.red
= 0x0000, .green
= 0xffff, .blue
= 0x0000},
256 &(XColor
){.red
= 0x0000, .green
= 0x0000, .blue
= 0x0000});
258 xw
.defcursor
= XCreateFontCursor(xw
.dpy
, /*XC_X_cursor*/XC_left_ptr
);
259 XRecolorCursor(xw
.dpy
, xw
.defcursor
,
260 &(XColor
){.red
= 0x0000, .green
= 0xffff, .blue
= 0x0000},
261 &(XColor
){.red
= 0x0000, .green
= 0x0000, .blue
= 0x0000});
263 XDefineCursor(xw
.dpy
, xw
.win
, xw
.lastcursor
);
264 fixWindowTitle(curterm
);
265 //XStoreName(xw.dpy, xw.win, opt_title);
267 XSetForeground(xw
.dpy
, dc
.gc
, 0);
268 if (xw
.tabheight
> 0) XFillRectangle(xw
.dpy
, xw
.pictab
, dc
.gc
, 0, 0, xw
.w
, xw
.tabheight
);
271 termCreateXPixmap(curterm
);
273 XMapWindow(xw
.dpy
, xw
.win
);
275 #if BLANKPTR_USE_GLYPH_CURSOR
276 xw
.blankPtr
= XCreateGlyphCursor(xw
.dpy
, dc
.font
[0].fid
, dc
.font
[0].fid
, ' ', ' ', &blackcolor
, &blackcolor
);
278 static const char cmbmp
[1] = {0};
281 pm
= XCreateBitmapFromData(xw
.dpy
, xw
.win
, cmbmp
, 1, 1);
282 xw
.blankPtr
= XCreatePixmapCursor(xw
.dpy
, pm
, pm
, &blackcolor
, &blackcolor
, 0, 0);
283 XFreePixmap(xw
.dpy
, pm
);