1 #include <stdio.h>
2 #include <X11/Xlib.h>
3 #include <X11/Xutil.h>
4 
5 #include "ztypes.h"
6 #include "xio.h"
7 
8 #define BLANKATTR (-1)
9 #define SPACEWIDTH (spacewidth[FIXED_FONT])
10 
11 typedef struct sline_t {
12     int dirtybeg, dirtyend; /* [) protocol; -1,-1 for non-dirty */
13     int isclear; /* TRUE if text is all blank */
14     char *text; /* pointer to array of stat_wid chars */
15     int *attr; /* pointer to array of stat_wid ints */
16 } sline;
17 
18 /*static int stat_xpos, stat_ypos;*/ /* in pixels */
19 static int stat_realwid, stat_realhgt; /* in pixels */
20 static int stat_wid, stat_hgt; /* in chars */
21 static sline *linelist; /* array of stat_hgt slines */
22 
23 static int linesused; /* z-machine's idea of the status line size */
24 static int maxlinesused; /* lines currently visible -- reset only by hitting return. */
25 static int curlines; /* actual window size */
26 
27 static int cursorx, cursory;
28 static int cursorattr;
29 
30 static int dotactive; /* is there an insertion mark? */
31 static int dotdrawn; /* is the insertion mark currently drawn? */
32 static int dotdrawnx, dotdrawny;
33 static XPoint polydot[3];
34 
35 #ifdef __STDC__
36 static void resizewindow(int lines);
37 static void clearlines(int beg, int end);
38 static void flipdot();
39 #else
40 static void resizewindow();
41 static void clearlines();
42 static void flipdot();
43 #endif
44 
45 #ifdef __STDC__
xstat_init(int cols,int rows,int xpos,int ypos)46 void xstat_init(int cols, int rows, int xpos, int ypos)
47 #else
48 void xstat_init(cols, rows, xpos, ypos)
49 int cols;
50 int rows;
51 int xpos;
52 int ypos;
53 #endif
54 {
55     int ix;
56 
57     stat_wid = cols;
58     stat_hgt = rows;
59 
60     /*stat_xpos = xpos;
61     stat_ypos = ypos;*/
62     stat_realwid = cols * SPACEWIDTH;
63     stat_realhgt = rows * lineheight;
64 
65     polydot[0].x = 0;
66     polydot[0].y = 0;
67     polydot[1].x = 4;
68     polydot[1].y = 5;
69     polydot[2].x = -8;
70     polydot[2].y = 0;
71 
72     dotactive = FALSE;
73     dotdrawn = FALSE;
74     dotdrawnx = 0;
75     dotdrawny = 0;
76 
77     linelist = (sline *)malloc(sizeof(sline) * stat_hgt);
78 
79     for (ix=0; ix<stat_hgt; ix++) {
80 	linelist[ix].text = (char *)malloc(sizeof(char) * stat_wid);
81 	linelist[ix].attr = (int *)malloc(sizeof(int) * stat_wid);
82 	linelist[ix].isclear = FALSE;
83     }
84 
85     linesused = 0;
86     maxlinesused = 0;
87     curlines = rows;
88 
89     cursorx = 0;
90     cursory = 0;
91     cursorattr = FIXED_FONT;
92 
93 #ifndef TESTING
94     /* export to ZIP code */
95     screen_cols = cols;
96     screen_rows = rows;
97 #endif
98 
99     xstat_clear_window();
100 }
101 
102 #ifdef __STDC__
xstat_newgeometry(int newx,int newy,int newwid,int newhgt)103 void xstat_newgeometry(int newx, int newy, int newwid, int newhgt)
104 #else
105 void xstat_newgeometry(newx, newy, newwid, newhgt)
106 int newx;
107 int newy;
108 int newwid;
109 int newhgt;
110 #endif
111 {
112     stat_realwid = newwid;
113     stat_realhgt = newhgt;
114 }
115 
116 #ifdef __STDC__
xstat_redraw()117 void xstat_redraw()
118 #else
119 void xstat_redraw()
120 #endif
121 {
122     int ix;
123     sline *curline;
124 
125     for (ix=0; ix<stat_hgt; ix++) {
126 	curline = (&linelist[ix]);
127 	if (!curline->isclear) {
128 	    curline->dirtybeg = 0;
129 	    curline->dirtyend = stat_wid;
130 	}
131     }
132 
133     dotdrawn = FALSE;
134     xstat_layout();
135 }
136 
137 #ifdef __STDC__
xstat_insert(int ch)138 void xstat_insert(int ch)
139 #else
140 void xstat_insert(ch)
141 int ch;
142 #endif
143 {
144     sline *curline;
145 
146     if (cursory<0 || cursory>=stat_hgt || cursorx<0 || cursorx>=stat_wid)
147 	return;
148 
149     if (cursory+1 > linesused) {
150 	xstat_set_window_size(cursory+1);
151     }
152 
153     curline = (&linelist[cursory]);
154     if (curline->text[cursorx] != (char)ch || curline->attr[cursorx] != cursorattr) {
155 	curline->text[cursorx] = (char)ch;
156 	curline->attr[cursorx] = cursorattr;
157 	curline->isclear = FALSE;
158 	if (curline->dirtybeg == (-1) || cursorx < curline->dirtybeg)
159 	    curline->dirtybeg = cursorx;
160 	if (curline->dirtyend == (-1) || cursorx+1 > curline->dirtyend)
161 	    curline->dirtyend = cursorx+1;
162     }
163 
164     cursorx++;
165     if (cursorx == stat_wid) {
166 	cursorx = 0;
167 	cursory++;
168     }
169 }
170 
171 #ifdef __STDC__
xstat_newline()172 void xstat_newline()
173 #else
174 void xstat_newline()
175 #endif
176 {
177     cursorx = 0;
178     cursory++;
179 }
180 
181 #ifdef __STDC__
xstat_getpos(int * row,int * col)182 void xstat_getpos(int *row, int *col)
183 #else
184 void xstat_getpos(row, col)
185 int *row;
186 int *col;
187 #endif
188 {
189     *col = cursorx+1;
190     *row = cursory+1;
191 }
192 
193 #ifdef __STDC__
xstat_setpos(int row,int col)194 void xstat_setpos(int row, int col)
195 #else
196 void xstat_setpos(row, col)
197 int row;
198 int col;
199 #endif
200 {
201     cursorx = col-1;
202     cursory = row-1;
203 }
204 
205 #ifdef __STDC__
xstat_setattr(int attr)206 void xstat_setattr(int attr)
207 #else
208 void xstat_setattr(attr)
209 int attr;
210 #endif
211 {
212     cursorattr = attr | FIXED_FONT;
213 }
214 
215 #ifdef __STDC__
xstat_set_window_size(int lines)216 void xstat_set_window_size(int lines)
217 #else
218 void xstat_set_window_size(lines)
219 int lines;
220 #endif
221 {
222     linesused = lines;
223     if (lines > maxlinesused)
224 	maxlinesused = lines;
225 }
226 
227 #ifdef __STDC__
xstat_set_dot_active(int visible)228 void xstat_set_dot_active(int visible)
229 #else
230 void xstat_set_dot_active(visible)
231 int visible;
232 #endif
233 {
234     if (visible) {
235 	/* turn it on */
236 	if (dotactive)
237 	    return;
238 	dotactive = TRUE;
239     }
240     else {
241 	/* turn it off */
242 	if (!dotactive)
243 	    return;
244 	dotactive = FALSE;
245     }
246 }
247 
248 /* clear to blankness */
249 #ifdef __STDC__
xstat_clear_window()250 void xstat_clear_window()
251 #else
252 void xstat_clear_window()
253 #endif
254 {
255     clearlines(0, stat_hgt);
256 
257     linesused = 0;
258     maxlinesused = linesused; /* because anything below the status window has been cleared */
259 }
260 
261 #ifdef __STDC__
clearlines(int beg,int end)262 static void clearlines(int beg, int end)
263 #else
264 static void clearlines(beg, end)
265 int beg;
266 int end;
267 #endif
268 {
269     int ix;
270     int jx;
271     char *cx;
272     int *ax;
273 
274     for (ix=beg; ix<end; ix++) {
275 	if (!linelist[ix].isclear) {
276 	    linelist[ix].isclear = TRUE;
277 	    linelist[ix].dirtybeg = 0;
278 	    linelist[ix].dirtyend = stat_wid;
279 	    for (cx=linelist[ix].text, jx=stat_wid; jx; cx++, jx--)
280 		*cx = ' ';
281 	    for (ax=linelist[ix].attr, jx=stat_wid; jx; ax++, jx--)
282 		*ax = BLANKATTR;
283 	}
284     }
285 }
286 
287 /* redraw the dirty stuff */
288 #ifdef __STDC__
xstat_layout()289 void xstat_layout()
290 #else
291 void xstat_layout()
292 #endif
293 {
294     int ix;
295     int beg, end, pos, px;
296     int attr;
297     int newsize;
298     sline *curline;
299 
300     if (dotdrawn) {
301 	flipdot();
302 	dotdrawn = FALSE;
303     }
304 
305     newsize = maxlinesused;
306     if (prefs.autoclear && newsize != curlines) {
307 	clearlines(newsize, stat_hgt);
308     }
309 
310     for (ix=0; ix<stat_hgt; ix++) {
311 	curline = (&linelist[ix]);
312 	if (curline->dirtybeg == (-1))
313 	    continue;
314 	beg = curline->dirtybeg;
315 	end = curline->dirtyend;
316 	pos = beg;
317 	while (pos < end) {
318 	    attr = curline->attr[pos];
319 	    for (px=pos; px<end && curline->attr[px]==attr; px++);
320 	    if (attr==BLANKATTR) {
321 		XClearArea(xiodpy, xioswin, pos*SPACEWIDTH, ix*lineheight, (px-pos)*SPACEWIDTH, lineheight, FALSE);
322 	    }
323 	    else if (attr & REVERSE) {
324 		XFillRectangle(xiodpy, xioswin, gcsfont[attr], pos*SPACEWIDTH, ix*lineheight, (px-pos)*SPACEWIDTH, lineheight);
325 		XDrawString(xiodpy, xioswin, gcsnegfont[attr], pos*SPACEWIDTH, ix*lineheight+lineheightoff, curline->text+pos, (px-pos));
326 	    }
327 	    else {
328 		XClearArea(xiodpy, xioswin, pos*SPACEWIDTH, ix*lineheight, (px-pos)*SPACEWIDTH, lineheight, FALSE);
329 		XDrawString(xiodpy, xioswin, gcsfont[attr], pos*SPACEWIDTH, ix*lineheight+lineheightoff, curline->text+pos, (px-pos));
330 	    }
331 	    pos = px;
332 	}
333 	curline->dirtybeg = (-1);
334 	curline->dirtyend = (-1);
335     }
336 
337     if (dotactive) {
338 	dotdrawnx = cursorx * SPACEWIDTH;
339 	dotdrawny = cursory * lineheight + lineheightoff;
340 	flipdot();
341 	dotdrawn = TRUE;
342     }
343 
344     if (prefs.autoresize && newsize != curlines) {
345 	resizewindow(newsize);
346     }
347 }
348 
349 /* reset the window size to linesused (if max==FALSE) or temporarily to stat_hgt (if max==TRUE) */
350 #ifdef __STDC__
xstat_reset_window_size(int op)351 void xstat_reset_window_size(int op)
352 #else
353 void xstat_reset_window_size(op)
354 int op;
355 #endif
356 {
357     int newsize;
358 
359     if (op==op_Clear) {
360 	clearlines(linesused, stat_hgt);
361 	xstat_layout();
362 	return;
363     }
364     else if (op==op_Zoom)
365 	newsize = stat_hgt;
366     else if (op==op_Shrink)
367 	newsize = linesused;
368     else {
369 	return;
370     }
371 
372     if (prefs.autoclear && newsize != curlines) {
373 	clearlines(newsize, stat_hgt);
374     }
375     if (prefs.autoresize && newsize != curlines) {
376 	resizewindow(newsize);
377     }
378     maxlinesused = newsize;
379 }
380 
381 #ifdef __STDC__
resizewindow(int lines)382 static void resizewindow(int lines)
383 #else
384 static void resizewindow(lines)
385 int lines;
386 #endif
387 {
388     XSizeHints szhints;
389     int xp, yp;
390     int newheight;
391     Window child;
392 
393     curlines = lines;
394     newheight = curlines*lineheight;
395     if (newheight==0)
396 	newheight++;
397 
398     if (!prefs.resizeupward) {
399 	szhints.flags = USSize;
400 	szhints.width = stat_wid*SPACEWIDTH;
401 	szhints.height = newheight;
402 	XResizeWindow(xiodpy, xioswin, szhints.width, szhints.height);
403 	XSetNormalHints(xiodpy, xioswin, &szhints);
404     }
405     else {
406 	XTranslateCoordinates(xiodpy, xioswin, RootWindow(xiodpy, xioscn), 0, 0, &xp, &yp, &child);
407 	yp -= (newheight - stat_realhgt);
408 
409 	szhints.flags = PMinSize|PResizeInc|USPosition|USSize;
410 	szhints.width = stat_wid*SPACEWIDTH;
411 	szhints.height = newheight;
412 	szhints.x = xp;
413 	szhints.y = yp;
414 	szhints.width_inc = spacewidth[FIXED_FONT];
415 	szhints.height_inc = lineheight;
416 	szhints.min_width = 1 * szhints.width_inc;
417 	szhints.min_height = 1 * szhints.height_inc;
418 	XMoveResizeWindow(xiodpy, xioswin, xp, yp, szhints.width, szhints.height);
419 	XSetNormalHints(xiodpy, xioswin, &szhints);
420     }
421 }
422 
423 #ifdef __STDC__
flipdot()424 static void flipdot()
425 #else
426 static void flipdot()
427 #endif
428 {
429     polydot[0].x = dotdrawnx;
430     polydot[0].y = dotdrawny;
431     XFillPolygon(xiodpy, xioswin, gcsflip, polydot, 3, Convex, CoordModePrevious);
432 }
433