1 ////////////////////////////////////////////////////////////////////////////////
2 // x11 drawing and utils
3 static void k8t_DrawClear (K8Term
*term
, int x1
, int y1
, int x2
, int y2
) {
4 XSetForeground(xw
.dpy
, dc
.gc
, getColor(K8T_ISSET(term
, K8T_MODE_REVERSE
) ? term
->deffg
: term
->defbg
));
5 XFillRectangle(xw
.dpy
, term
->picbuf
, dc
.gc
, x1
*xw
.cw
, y1
*xw
.ch
, (x2
-x1
+1)*xw
.cw
, (y2
-y1
+1)*xw
.ch
);
9 /* copy buffer pixmap to screen pixmap */
10 static void k8t_DrawCopy (K8Term
*term
, int x
, int y
, int cols
, int rows
) {
12 int src_x
= x
*xw
.cw
, src_y
= y
*xw
.ch
, src_w
= cols
*xw
.cw
, src_h
= rows
*xw
.ch
;
13 int dst_x
= src_x
, dst_y
= src_y
;
15 if (opt_tabposition
== 1) { dst_y
+= xw
.tabheight
; }
16 XCopyArea(xw
.dpy
, term
->picbuf
, xw
.win
, dc
.gc
, src_x
, src_y
, src_w
, src_h
, dst_x
, dst_y
);
22 static void xcreatebw (void) {
23 if ((dc.bcol = calloc(MAX_COLOR+1, sizeof(dc.bcol[0]))) == NULL) die("out of memory");
25 for (int f = 0; f <= MAX_COLOR; ++f) {
28 nclr = dc.ncol[f].pixel;
29 XQueryColor(xw.dpy, xw.cmap, &nclr);
30 fprintf(stderr, "%d: r=%u; g=%u; b=%u\n", f, nclr.red, nclr.green, nclr.blue);
36 static void xallocbwclr (int idx
, XColor
*color
) {
39 XQueryColor(xw
.dpy
, xw
.cmap
, color
);
40 //fprintf(stderr, "%d: r=%u; g=%u; b=%u\n", idx, color->red, color->green, color->blue);
42 lumi
= 0.3*((double)color
->red
/65535.0)+0.59*((double)color
->green
/65535.0)+0.11*((double)color
->blue
/65535.0);
43 color
->red
= color
->green
= color
->blue
= (int)(lumi
*65535.0);
44 if (!XAllocColor(xw
.dpy
, xw
.cmap
, color
)) {
45 fprintf(stderr
, "WARNING: could not allocate b/w color #%d\n", idx
);
48 dc
.bcol
[idx
] = color
->pixel
;
49 color
->red
= color
->blue
= 0;
50 if (!XAllocColor(xw
.dpy
, xw
.cmap
, color
)) {
51 fprintf(stderr
, "WARNING: could not allocate b/w color #%d\n", idx
);
54 dc
.gcol
[idx
] = color
->pixel
;
58 static void xallocnamedclr (int idx
, const char *cname
) {
61 if (!XAllocNamedColor(xw
.dpy
, xw
.cmap
, cname
, &color
, &color
)) {
62 fprintf(stderr
, "WARNING: could not allocate color #%d: '%s'\n", idx
, cname
);
65 dc
.ncol
[idx
] = color
.pixel
;
66 xallocbwclr(idx
, &color
);
70 static void xloadcols (void) {
73 uint32_t white
= WhitePixel(xw
.dpy
, xw
.scr
);
75 if ((dc
.clrs
[0] = dc
.ncol
= calloc(MAX_COLOR
+1, sizeof(dc
.ncol
[0]))) == NULL
) die("out of memory");
76 if ((dc
.clrs
[1] = dc
.bcol
= calloc(MAX_COLOR
+1, sizeof(dc
.bcol
[0]))) == NULL
) die("out of memory");
77 if ((dc
.clrs
[2] = dc
.gcol
= calloc(MAX_COLOR
+1, sizeof(dc
.gcol
[0]))) == NULL
) die("out of memory");
79 for (f
= 0; f
<= MAX_COLOR
; ++f
) dc
.ncol
[f
] = dc
.bcol
[f
] = white
;
80 /* load colors [0-15] */
81 for (f
= 0; f
<= 15; ++f
) {
82 const char *cname
= opt_colornames
[f
]!=NULL
?opt_colornames
[f
]:defcolornames
[f
];
84 xallocnamedclr(f
, cname
);
86 /* load colors [256-...] */
87 for (f
= 256; f
<= MAX_COLOR
; ++f
) {
88 const char *cname
= opt_colornames
[f
];
91 if (K8T_ARRLEN(defextcolornames
) <= f
-256) continue;
92 cname
= defextcolornames
[f
-256];
94 if (cname
== NULL
) continue;
95 xallocnamedclr(f
, cname
);
97 /* load colors [16-255] ; same colors as xterm */
98 for (f
= 16, r
= 0; r
< 6; ++r
) {
99 for (g
= 0; g
< 6; ++g
) {
100 for (b
= 0; b
< 6; ++b
) {
101 if (opt_colornames
[f
] != NULL
) {
102 xallocnamedclr(f
, opt_colornames
[f
]);
104 color
.red
= r
== 0 ? 0 : 0x3737+0x2828*r
;
105 color
.green
= g
== 0 ? 0 : 0x3737+0x2828*g
;
106 color
.blue
= b
== 0 ? 0 : 0x3737+0x2828*b
;
107 if (!XAllocColor(xw
.dpy
, xw
.cmap
, &color
)) {
108 fprintf(stderr
, "WARNING: could not allocate color #%d\n", f
);
110 dc
.ncol
[f
] = color
.pixel
;
111 xallocbwclr(f
, &color
);
118 for (r
= 0; r
< 24; ++r
, ++f
) {
119 if (opt_colornames
[f
] != NULL
) {
120 xallocnamedclr(f
, opt_colornames
[f
]);
122 color
.red
= color
.green
= color
.blue
= 0x0808+0x0a0a*r
;
123 if (!XAllocColor(xw
.dpy
, xw
.cmap
, &color
)) {
124 fprintf(stderr
, "WARNING: could not allocate color #%d\n", f
);
126 dc
.ncol
[f
] = color
.pixel
;
127 xallocbwclr(f
, &color
);
132 for (int f
= 0; f
< K8T_ARRLEN(opt_colornames
); ++f
) if (opt_colornames
[f
]) free(opt_colornames
[f
]);
136 static void xhints (void) {
137 XClassHint
class = {opt_class
, opt_title
};
138 XWMHints wm
= {.flags
= InputHint
, .input
= 1};
140 .flags
= PSize
|PResizeInc
|PBaseSize
,
145 .base_height
= xw
.h
/*xw.tabheight*/,
148 //XSetWMNormalHints(xw.dpy, xw.win, &size);
149 XSetWMProperties(xw
.dpy
, xw
.win
, NULL
, NULL
, NULL
, 0, &size
, &wm
, &class);
150 XSetWMProtocols(xw
.dpy
, xw
.win
, &XA_WM_DELETE_WINDOW
, 1);
154 static XFontSet
xinitfont (const char *fontstr
) {
156 char *def
, **missing
;
160 set
= XCreateFontSet(xw
.dpy
, fontstr
, &missing
, &n
, &def
);
162 while (n
--) fprintf(stderr
, "sterm: missing fontset: %s\n", missing
[n
]);
163 XFreeStringList(missing
);
169 static void xgetfontinfo (XFontSet set
, int *ascent
, int *descent
, short *lbearing
, short *rbearing
, Font
*fid
) {
170 XFontStruct
**xfonts
;
174 *ascent
= *descent
= *lbearing
= *rbearing
= 0;
175 n
= XFontsOfFontSet(set
, &xfonts
, &font_names
);
176 for (int f
= 0; f
< n
; ++f
) {
177 if (f
== 0) *fid
= (*xfonts
)->fid
;
178 *ascent
= K8T_MAX(*ascent
, (*xfonts
)->ascent
);
179 *descent
= K8T_MAX(*descent
, (*xfonts
)->descent
);
180 *lbearing
= K8T_MAX(*lbearing
, (*xfonts
)->min_bounds
.lbearing
);
181 *rbearing
= K8T_MAX(*rbearing
, (*xfonts
)->max_bounds
.rbearing
);
187 static void initfonts (const char *fontstr
, const char *bfontstr
, const char *tabfont
) {
188 if ((dc
.font
[0].set
= xinitfont(fontstr
)) == NULL
) {
189 if ((dc
.font
[0].set
= xinitfont(FONT
)) == NULL
) die("can't load font %s", fontstr
);
191 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
);
193 if ((dc
.font
[1].set
= xinitfont(bfontstr
)) == NULL
) {
194 if ((dc
.font
[1].set
= xinitfont(FONTBOLD
)) == NULL
) die("can't load font %s", bfontstr
);
196 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
);
198 if ((dc
.font
[2].set
= xinitfont(tabfont
)) == NULL
) {
199 if ((dc
.font
[2].set
= xinitfont(FONTTAB
)) == NULL
) die("can't load font %s", tabfont
);
201 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
);
205 static void xinit (void) {
206 XSetWindowAttributes attrs
;
208 XColor blackcolor
= { 0, 0, 0, 0, 0, 0 };
210 if (!(xw
.dpy
= XOpenDisplay(NULL
))) die("can't open display");
212 XA_VT_SELECTION
= XInternAtom(xw
.dpy
, "_STERM_SELECTION_", 0);
213 XA_CLIPBOARD
= XInternAtom(xw
.dpy
, "CLIPBOARD", 0);
214 XA_UTF8
= XInternAtom(xw
.dpy
, "UTF8_STRING", 0);
215 XA_NETWM_NAME
= XInternAtom(xw
.dpy
, "_NET_WM_NAME", 0);
216 XA_TARGETS
= XInternAtom(xw
.dpy
, "TARGETS", 0);
217 XA_WM_DELETE_WINDOW
= XInternAtom(xw
.dpy
, "WM_DELETE_WINDOW", 0);
218 xw
.xembed
= XInternAtom(xw
.dpy
, "_XEMBED", False
);
220 xw
.scr
= XDefaultScreen(xw
.dpy
);
222 initfonts(opt_fontnorm
, opt_fontbold
, opt_fonttab
);
223 /* XXX: Assuming same size for bold font */
224 xw
.cw
= dc
.font
[0].rbearing
-dc
.font
[0].lbearing
;
225 xw
.ch
= dc
.font
[0].ascent
+dc
.font
[0].descent
;
226 xw
.tch
= dc
.font
[2].ascent
+dc
.font
[2].descent
;
227 xw
.tabheight
= opt_disabletabs
? 0 : xw
.tch
+2;
230 xw
.cmap
= XDefaultColormap(xw
.dpy
, xw
.scr
);
232 /* window - default size */
233 curterm
->picbufh
= curterm
->row
*xw
.ch
;
234 curterm
->picbufw
= curterm
->col
*xw
.cw
;
236 xw
.h
= curterm
->picbufh
+xw
.tabheight
;
237 xw
.w
= curterm
->picbufw
;
239 attrs
.background_pixel
= getColor(defaultBG
);
240 attrs
.border_pixel
= getColor(defaultBG
);
241 attrs
.bit_gravity
= NorthWestGravity
;
243 FocusChangeMask
|KeyPressMask
|
244 ExposureMask
|VisibilityChangeMask
|StructureNotifyMask
|
245 /*ButtonMotionMask|*/PointerMotionMask
|ButtonPressMask
|ButtonReleaseMask
|
246 EnterWindowMask
|LeaveWindowMask
;
247 attrs
.colormap
= xw
.cmap
;
248 //fprintf(stderr, "oe: [%s]\n", opt_embed);
249 parent
= opt_embed
? strtol(opt_embed
, NULL
, 0) : XRootWindow(xw
.dpy
, xw
.scr
);
250 xw
.win
= XCreateWindow(xw
.dpy
, parent
, 0, 0,
251 xw
.w
, xw
.h
, 0, XDefaultDepth(xw
.dpy
, xw
.scr
), InputOutput
,
252 XDefaultVisual(xw
.dpy
, xw
.scr
),
253 CWBackPixel
|CWBorderPixel
|CWBitGravity
|CWEventMask
|CWColormap
,
256 curterm
->picbuf
= XCreatePixmap(xw
.dpy
, xw
.win
, curterm
->picbufw
, curterm
->picbufh
, XDefaultDepth(xw
.dpy
, xw
.scr
));
257 xw
.pictab
= XCreatePixmap(xw
.dpy
, xw
.win
, xw
.w
, xw
.tabheight
>0?xw
.tabheight
:1, XDefaultDepth(xw
.dpy
, xw
.scr
));
259 if ((xw
.xim
= XOpenIM(xw
.dpy
, NULL
, NULL
, NULL
)) == NULL
) die("XOpenIM() failed");
260 xw
.xic
= XCreateIC(xw
.xim
, XNInputStyle
, XIMPreeditNothing
|XIMStatusNothing
, XNClientWindow
, xw
.win
, XNFocusWindow
, xw
.win
, NULL
);
262 dc
.gc
= XCreateGC(xw
.dpy
, xw
.win
, 0, NULL
);
263 /* white cursor, black outline */
264 xw
.cursor
= XCreateFontCursor(xw
.dpy
, XC_xterm
);
265 XDefineCursor(xw
.dpy
, xw
.win
, xw
.cursor
);
266 XRecolorCursor(xw
.dpy
, xw
.cursor
,
267 &(XColor
){.red
= 0xffff, .green
= 0xffff, .blue
= 0xffff},
268 &(XColor
){.red
= 0x0000, .green
= 0x0000, .blue
= 0x0000});
269 fixWindowTitle(curterm
);
270 //XStoreName(xw.dpy, xw.win, opt_title);
272 XSetForeground(xw
.dpy
, dc
.gc
, 0);
273 XFillRectangle(xw
.dpy
, curterm
->picbuf
, dc
.gc
, 0, 0, curterm
->picbufw
, curterm
->picbufh
);
274 if (xw
.tabheight
> 0) XFillRectangle(xw
.dpy
, xw
.pictab
, dc
.gc
, 0, 0, xw
.w
, xw
.tabheight
);
276 XMapWindow(xw
.dpy
, xw
.win
);
278 #if BLANKPTR_USE_GLYPH_CURSOR
279 xw
.blankPtr
= XCreateGlyphCursor(xw
.dpy
, dc
.font
[0].fid
, dc
.font
[0].fid
, ' ', ' ', &blackcolor
, &blackcolor
);
281 static const char cmbmp
[1] = {0};
284 pm
= XCreateBitmapFromData(xw
.dpy
, xw
.win
, cmbmp
, 1, 1);
285 xw
.blankPtr
= XCreatePixmapCursor(xw
.dpy
, pm
, pm
, &blackcolor
, &blackcolor
, 0, 0);
286 XFreePixmap(xw
.dpy
, pm
);
293 static void xblankPointer (void) {
294 if (!ptrBlanked
&& xw
.blankPtr
!= None
) {
296 XDefineCursor(xw
.dpy
, xw
.win
, xw
.blankPtr
);
302 static void xunblankPointer (void) {
303 if (ptrBlanked
&& xw
.cursor
!= None
) {
305 XDefineCursor(xw
.dpy
, xw
.win
, xw
.cursor
);
307 ptrLastMove
= mclock_ticks();
313 static int xisyinunused (int y) {
314 if (xw.tabheight > 0 && curterm != NULL) {
315 int unh = xw.h-(curterm->row*xw.ch)-xw.tabheight;
318 switch (opt_tabposition) {
320 return (y >= xw.h-xw.tabheight-unh && y < xw.h-xw.tabheight);
323 return (y >= xw.tabheight+(curterm->row*xw.ch)t);
333 static void xclearunused (void) {
334 if (xw
.tabheight
> 0 && curterm
!= NULL
) {
335 int unh
= xw
.h
-(curterm
->row
*xw
.ch
)-xw
.tabheight
;
338 switch (opt_tabposition
) {
340 XClearArea(xw
.dpy
, xw
.win
, 0, xw
.h
-xw
.tabheight
-unh
, xw
.w
, unh
, False
);
343 XClearArea(xw
.dpy
, xw
.win
, 0, xw
.tabheight
+(curterm
->row
*xw
.ch
), xw
.w
, unh
, False
);