fixed some warnings
[k8sterm.git] / src / libk8sterm / tdraw.c
blobe02453a64c47ac29b2789c99b577a166a2487ed6
1 #include "k8sterm.h"
4 ////////////////////////////////////////////////////////////////////////////////
5 K8TERM_API void k8t_drawClear (K8Term *term, int x1, int y1, int x2, int y2) {
6 term->drawSetFG(term, K8T_ISSET(term, K8T_MODE_REVERSE) ? term->deffg : term->defbg);
7 term->drawFillRect(term, x1, y1, x2-x1+1, y2-y1+1);
11 /* copy buffer pixmap to screen pixmap */
12 K8TERM_API void k8t_drawCopy (K8Term *term, int x, int y, int cols, int rows) {
13 if (term != NULL) term->drawCopyArea(term, x, y, cols, rows);
17 K8TERM_API void k8t_drawCursor (K8Term *term, int forceblit) {
18 (void)forceblit;
19 K8TGlyph g;
20 int sl, scrx, scry;
21 //int cmy;
22 int focused;
24 if (term == NULL) return;
26 K8T_LIMIT(term->oldcx, 0, term->col-1);
27 K8T_LIMIT(term->oldcy, 0, term->row-1);
29 focused = term->isFocused(term);
30 //cmy = term->row-term->topline-1;
32 //fprintf(stderr, "cur: cx=%d; cy=%d; sy=%d; cmy=%d\n", term->c.x, term->c.y, term->c.y+term->topline, cmy);
33 if (!focused && !term->curblinkinactive) term->curbhidden = 0;
35 if (1/*term->oldcy != cmy*/) {
36 scrx = term->oldcx;
37 scry = term->oldcy+term->topline;
39 //FIXME: avoid unnecessary cursor erase when window is not focused
40 if (scry >= 0 && scry < term->row) {
41 if (term->curbhidden < 0 ||
42 (term->c.state&K8T_CURSOR_HIDE) ||
43 (!focused && term->defcurinactivebg) ||
44 term->oldcy != term->c.y || term->oldcx != term->c.x) {
45 /* remove the old cursor */
46 if (!term->isUnderOverlay(term, scrx, scry, 1)) {
47 sl = k8t_UTF8Size(term->line[term->oldcy][scrx].c);
48 g = term->line[term->oldcy][scrx];
49 if (k8t_isSelected(term, scrx, scry)) g.attr ^= K8T_ATTR_REVERSE;
50 k8t_drawString(term, g.c, &g, scrx, scry, 1, sl);
51 //k8t_drawClear(term, scrx, term->oldcy, scrx, term->oldcy);
52 //TODO
53 /*if (forceblit)*/ {
54 k8t_drawCopy(term, scrx, scry, 1, 1);
55 }/* else {
56 term->line[term->oldcy][scrx].state |= K8T_GLYPH_DIRTY;
57 k8t_tmDirtyMark(term, term->oldcy, 1);
58 }*/
61 if (term->curbhidden) term->curbhidden = 1;
65 if (/*term->oldcy == cmy ||*/ (term->c.state&K8T_CURSOR_HIDE) || (term->curbhidden && term->defcurbg < 0)) return;
66 /* draw the new one */
67 scrx = term->c.x;
68 scry = term->c.y+term->topline;
70 if (scry >= 0 && scry < term->row && !term->isUnderOverlay(term, scrx, scry, 1)) {
71 int nodraw = 0;
73 //fprintf(stderr, "cx=%d; cy=%d\n", scrx, scry);
74 if (!focused) {
75 if (term->defcurinactivebg < 0) {
76 term->drawSetFG(term, (term->defcurbg1 < 0 ? term->defcurbg : term->defcurbg1));
77 term->drawRect(term, scrx, scry, 1, 1);
78 nodraw = 1;
79 } else {
80 g.bg = term->defcurinactivebg;
81 g.fg = term->defcurinactivefg;
83 } else {
84 if (term->curbhidden) term->curbhidden = 1;
85 if (term->curbhidden && term->defcurbg1 < 0) return;
86 g.bg = (term->curbhidden ? term->defcurbg1 : term->defcurbg);
87 g.fg = (term->curbhidden && term->defcurfg1 < 0 ? term->defcurfg : term->defcurfg1);
90 if (!nodraw) {
91 g.uc = term->line[term->c.y][scrx].uc;
92 g.state = 0;
93 g.attr = K8T_ATTR_NORMAL|K8T_ATTR_FGSET|K8T_ATTR_BGSET;
94 if (K8T_ISSET(term, K8T_MODE_REVERSE)) g.attr |= K8T_ATTR_REVERSE;
95 sl = k8t_UTF8Size(g.c);
96 k8t_drawString(term, g.c, &g, scrx, scry, 1, sl);
98 term->oldcx = scrx;
99 term->oldcy = term->c.y;
100 //TODO
101 /*if (forceblit)*/ {
102 k8t_drawCopy(term, scrx, scry, 1, 1);
108 K8TERM_API void k8t_drawString (K8Term *term, const char *s, const K8TGlyph *base, int x, int y, int charlen, int bytelen) {
109 if (term != NULL) {
110 int fg = base->fg, bg = base->bg, temp;
111 int defF = ((base->attr&K8T_ATTR_FGSET) == 0), defB = ((base->attr&K8T_ATTR_BGSET) == 0);
112 int fontset = 0; /* 0: normal; 1: bold */
114 /* only switch default fg/bg if term is in RV mode */
115 if (K8T_ISSET(term, K8T_MODE_REVERSE)) {
116 if (defF) fg = term->defbg;
117 if (defB) bg = term->deffg;
118 } else {
119 if (defF) fg = term->deffg;
120 if (defB) bg = term->defbg;
122 if (base->attr&K8T_ATTR_REVERSE) defF = defB = 0;
123 if (base->attr&K8T_ATTR_BOLD) {
124 if (defF && defB && term->defboldfg >= 0) fg = term->defboldfg;
125 else if (fg < 8) fg += 8;
126 fontset = 1;
128 if ((base->attr&K8T_ATTR_UNDERLINE) && term->defunderfg >= 0) {
129 if (defF && defB) fg = term->defunderfg;
132 if (base->attr&K8T_ATTR_REVERSE) { temp = fg; fg = bg; bg = temp; }
134 term->drawSetBG(term, bg);
135 term->drawSetFG(term, fg);
136 term->drawString(term, x, y, charlen, base, fontset, s, bytelen);
141 K8TERM_API void k8t_drawLine (K8Term *term, int x1, int x2, int scry, int lineno, int dontcopy) {
142 int ovr;
144 //fprintf(stderr, "%d: k8t_drawLine: x1=%d; x2=%d; scry=%d; row:%d; lineno=%d\n", term->clockTicks(term), x1, x2, scry, term->row, lineno);
145 if (term == NULL || scry < 0 || scry >= term->row || x2 <= x1) return;
147 // draw overlays
148 ovr = term->isUnderOverlay(term, x1, scry, x2-x1);
150 if (ovr > 0) {
151 // fully inside
152 if (term->drawOverlay(term, x1, x2, scry, lineno, dontcopy)) return;
153 } else if (ovr < 0) {
154 // partially inside
155 int sx = x1, sw = x2-x1, ex;
157 term->clipToOverlay(term, &sx, scry, &sw);
158 if (sw != 0) {
159 // draw string part and overlay part
160 ex = sx+sw;
161 // left string part
162 if (sx > x1) {
163 k8t_drawLine(term, x1, sx-x1, scry, lineno, dontcopy);
165 // right string part
166 if (ex < x2) {
167 k8t_drawLine(term, ex, x2, scry, lineno, dontcopy);
169 // overlay
170 x1 = sx;
171 x2 = ex;
172 if (term->drawOverlay(term, x1, x2, scry, lineno, dontcopy)) return;
176 if (lineno < 0 || lineno >= term->linecount) {
177 k8t_drawClear(term, 0, scry, term->col-1, scry);
178 k8t_drawCopy(term, 0, scry, term->col, 1);
179 } else {
180 int ic, ib, ox, sl;
181 int stx, ex;
182 K8TGlyph base, new;
183 K8TLine l = term->line[lineno];
185 if (lineno < term->row && term->topline == 0) {
186 if (!term->dirty[lineno]) return;
187 if (!dontcopy) {
188 // fix 'dirty' flag for line
189 if (term->dirty[lineno]&0x02) {
190 // mark full line as dirty
191 stx = 0;
192 ex = term->col;
193 term->dirty[lineno] = 0;
194 } else {
195 term->dirty[lineno] = 0;
196 if (x1 > 0) for (int x = 0; x < x1; ++x) if (l[x].state&K8T_GLYPH_DIRTY) { term->dirty[lineno] = 1; break; }
197 if (!term->dirty[lineno] && x2 < term->col) for (int x = x2; x < term->col; ++x) if (l[x].state&K8T_GLYPH_DIRTY) { term->dirty[lineno] = 1; break; }
199 // find dirty region
200 for (stx = x1; stx < x2; ++stx) if (l[stx].state&K8T_GLYPH_DIRTY) break;
201 for (ex = x2; ex > stx; --ex) if (l[ex-1].state&K8T_GLYPH_DIRTY) break;
202 if (stx >= x2 || ex <= stx) return; // nothing to do
204 } else {
205 // 'dontcopy' means that the whole screen is dirty
206 stx = 0;
207 ex = term->col;
208 term->dirty[lineno] = 0;
210 } else {
211 //if (lineno < term->row) term->dirty[lineno] = 0;
212 stx = 0;
213 ex = term->col;
216 base = l[stx];
217 if (term->sel.bx != -1 && k8t_isSelected(term, stx, lineno)) base.attr ^= K8T_ATTR_REVERSE;
218 ic = ib = 0;
219 ox = stx;
220 //k8t_drawClear(term, stx, scry, ex-1, scry); //k8: actually, we don't need this for good monospace fonts, so...
221 for (int x = stx; x < ex; ++x) {
222 new = l[x];
223 l[x].state &= ~K8T_GLYPH_DIRTY; //!
224 if (term->sel.bx != -1 && k8t_isSelected(term, x, lineno)) new.attr ^= K8T_ATTR_REVERSE;
225 if (ib > 0 && (K8T_ATTRCMP(base, new) || ib >= K8T_DRAW_BUF_SIZ-K8T_UTF_SIZ)) {
226 // flush draw buffer
227 k8t_drawString(term, term->drawbuf, &base, ox, scry, ic, ib);
228 ic = ib = 0;
230 if (ib == 0) { ox = x; base = new; }
231 sl = k8t_UTF8Size(new.c);
232 memcpy(term->drawbuf+ib, new.c, sl);
233 ib += sl;
234 ++ic;
236 if (ib > 0) k8t_drawString(term, term->drawbuf, &base, ox, scry, ic, ib);
237 //k8t_drawCopy(term, 0, scry, term->col, 1);
238 //if (term->c.y == lineno && term->c.x >= stx && term->c.x < ex) k8t_drawCursor(term, 0);
239 if (!dontcopy) k8t_drawCopy(term, stx, scry, ex-stx, 1);
244 K8TERM_API void k8t_drawRegion (K8Term *term, int x1, int y1, int x2, int y2, int forced) {
245 if (term != NULL) {
246 int fulldirty = 0;
248 //term->justSwapped = 0;
250 if (!forced && !term->isVisible(term)) {
251 //dlogf("invisible");
252 term->lastDrawTime = 1;
253 if (term->setLastDrawTime) term->setLastDrawTime(term, term->lastDrawTime);
254 term->wantRedraw = 1;
255 return;
258 if (y1 == 0 && y2 == term->row) {
259 fulldirty = 1;
260 for (int y = 0; y < y2; ++y) if (!(term->dirty[y]&0x02)) { fulldirty = 0; break; }
263 if (term->topline < term->row) {
264 for (int y = y1; y < y2; ++y) k8t_drawLine(term, x1, x2, y+term->topline, y, fulldirty);
266 if (term->topline > 0) {
267 int scry = K8T_MIN(term->topline, term->row), y = term->row;
269 fulldirty = 1;
270 if (term->topline >= term->row) y += term->topline-term->row;
271 while (--scry >= 0) {
272 k8t_drawLine(term, 0, term->col, scry, y, 0);
273 ++y;
276 if (fulldirty) k8t_drawCopy(term, 0, 0, term->col, term->row);
277 k8t_drawCursor(term, 0);
278 term->lastDrawTime = term->clockTicks(term);
279 if (term->setLastDrawTime) term->setLastDrawTime(term, term->lastDrawTime);
280 term->wantRedraw = 0;
285 K8TERM_API void k8t_drawTerm (K8Term *term, int forced) {
286 if (term != NULL) {
287 //fprintf(stderr, "k8t_drawTerm(%d) (%d)\n", forced, term->clockTicks(term));
288 k8t_drawRegion(term, 0, 0, term->col, term->row, forced);