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
) {
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*/) {
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);
54 k8t_drawCopy(term
, scrx
, scry
, 1, 1);
56 term->line[term->oldcy][scrx].state |= K8T_GLYPH_DIRTY;
57 k8t_tmDirtyMark(term, term->oldcy, 1);
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 */
68 scry
= term
->c
.y
+term
->topline
;
70 if (scry
>= 0 && scry
< term
->row
&& !term
->isUnderOverlay(term
, scrx
, scry
, 1)) {
73 //fprintf(stderr, "cx=%d; cy=%d\n", scrx, scry);
75 if (term
->defcurinactivebg
< 0) {
76 term
->drawSetFG(term
, (term
->defcurbg1
< 0 ? term
->defcurbg
: term
->defcurbg1
));
77 term
->drawRect(term
, scrx
, scry
, 1, 1);
80 g
.bg
= term
->defcurinactivebg
;
81 g
.fg
= term
->defcurinactivefg
;
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
);
91 g
.uc
= term
->line
[term
->c
.y
][scrx
].uc
;
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
);
99 term
->oldcy
= term
->c
.y
;
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
) {
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
;
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;
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
) {
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;
148 ovr
= term
->isUnderOverlay(term
, x1
, scry
, x2
-x1
);
152 if (term
->drawOverlay(term
, x1
, x2
, scry
, lineno
, dontcopy
)) return;
153 } else if (ovr
< 0) {
155 int sx
= x1
, sw
= x2
-x1
, ex
;
157 term
->clipToOverlay(term
, &sx
, scry
, &sw
);
159 // draw string part and overlay part
163 k8t_drawLine(term
, x1
, sx
-x1
, scry
, lineno
, dontcopy
);
167 k8t_drawLine(term
, ex
, x2
, scry
, lineno
, dontcopy
);
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);
183 K8TLine l
= term
->line
[lineno
];
185 if (lineno
< term
->row
&& term
->topline
== 0) {
186 if (!term
->dirty
[lineno
]) return;
188 // fix 'dirty' flag for line
189 if (term
->dirty
[lineno
]&0x02) {
190 // mark full line as dirty
193 term
->dirty
[lineno
] = 0;
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; }
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
205 // 'dontcopy' means that the whole screen is dirty
208 term
->dirty
[lineno
] = 0;
211 //if (lineno < term->row) term->dirty[lineno] = 0;
217 if (term
->sel
.bx
!= -1 && k8t_isSelected(term
, stx
, lineno
)) base
.attr
^= K8T_ATTR_REVERSE
;
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
) {
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
)) {
227 k8t_drawString(term
, term
->drawbuf
, &base
, ox
, scry
, ic
, ib
);
230 if (ib
== 0) { ox
= x
; base
= new; }
231 sl
= k8t_UTF8Size(new.c
);
232 memcpy(term
->drawbuf
+ib
, new.c
, sl
);
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
) {
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;
258 if (y1
== 0 && y2
== term
->row
) {
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
;
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);
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
) {
287 //fprintf(stderr, "k8t_drawTerm(%d) (%d)\n", forced, term->clockTicks(term));
288 k8t_drawRegion(term
, 0, 0, term
->col
, term
->row
, forced
);