1 #include <string.h>
2 #include <X11/Xlib.h>
3 #include <X11/Xutil.h>
4 #include "handwave.h"
5 #include "spelllist.h"
6 #include "xspell.h"
7 
8 #define TEXT_WID (400)
9 #define TEXT_HGT (512)
10 #define TEXT_X (32)
11 #define TEXT_Y (32)
12 
13 #define MAXLINESIZE (512) /* maximum number of chars that could possibly fit
14 			     in a line. If the player uses bits1, this will
15 			     probably crash. Tough. */
16 
17 static void redraw_text_only();
18 void redraw_scrollbar();
19 
init_xtext(pnum)20 void init_xtext(pnum)
21 int pnum;
22 {
23     struct player *py = &(players[pnum]);
24     static XCharStruct overall;
25     int direction, ascent, descent;
26 
27     py->cursx = 0;
28     py->sitext.nlines = 0;
29 
30     XTextExtents(py->font, "pl", 2, &direction, &ascent, &descent, &overall);
31     py->lineheight = ascent+descent;
32     if (py->lineheight <= 12)
33 	py->lineheight += 2;
34     else
35 	py->lineheight = (int)((double)(py->lineheight)*1.17);
36 
37     py->texty = TEXT_Y + ascent + 1;
38     py->textx = TEXT_X;
39     py->sitext.visible = (TEXT_HGT-2) / py->lineheight;
40 
41     py->ascent = ascent;
42     py->totalheight = ascent+descent;
43 
44     py->lineindex_size = 10;
45     py->lineindex = (struct line *)malloc(sizeof(struct line)*py->lineindex_size);
46     py->linebuf_size = 2*MAXLINESIZE;
47     py->linebuf = (char *)malloc(py->linebuf_size);
48     strcpy(py->linebuf, "");
49     py->addpoint = 0;
50     py->lineindex[0].start = 0;
51 
52     py->sitext.py = py;
53     py->sitext.top = 0;
54     py->sitext.lineheight = py->lineheight;
55     py->sitext.x = TEXT_X;
56     py->sitext.y = TEXT_Y;
57     py->sitext.h = TEXT_HGT;
58     py->sitext.redraw = redraw_text_only;
59 }
60 
redraw_text_only(py,baronly)61 static void redraw_text_only(py, baronly)
62 struct player *py;
63 int baronly;
64 {
65     int ix, sline;
66     int len, width;
67 
68     if (!baronly) {
69 	/* draw text */
70 	for (ix=py->sitext.top; ix<=py->sitext.nlines; ix++) {
71 	    sline = ix - py->sitext.top;
72 	    if (sline>=py->sitext.visible)
73 		break;
74 	    if (ix==py->sitext.nlines) {
75 		len = strlen(py->linebuf+py->lineindex[ix].start);
76 	    }
77 	    else {
78 		len = py->lineindex[ix].len;
79 	    }
80 	    width = py->lineindex[ix].width;
81 	    XDrawImageString(py->dpy, py->win, py->blackgc, py->textx,
82 			py->texty + py->lineheight*sline,
83 			py->linebuf+py->lineindex[ix].start, len);
84 	    XClearArea(py->dpy, py->win, py->textx+width, py->texty +
85 			py->lineheight*sline - py->ascent, TEXT_WID-width,
86 			py->totalheight, 0);
87 	}
88     }
89 
90     redraw_scrollbar(&(py->sitext));
91 }
92 
complete_line(py)93 void complete_line(py)
94 struct player *py;
95 {
96     int ln = py->sitext.nlines;
97     int jump;
98     static XCharStruct overall;
99     int direction, ascent, descent;
100     char *start;
101 
102     if (ln+2 >= py->lineindex_size) {
103 	py->lineindex_size *= 2;
104 	py->lineindex = (struct line *)realloc(py->lineindex,
105 			sizeof(struct line)*py->lineindex_size);
106     }
107     start = py->linebuf+py->lineindex[ln].start;
108     py->lineindex[ln].len = strlen(start);
109     XTextExtents(py->font, start, py->lineindex[ln].len, &direction, &ascent,
110 		&descent, &overall);
111     py->lineindex[ln].width = overall.width;
112 
113     /* set up new incomplete line */
114     py->lineindex[ln+1].start = py->lineindex[ln].start+py->lineindex[ln].len + 1;
115     /* len will not be computed until line is finished */
116     py->lineindex[ln+1].width = 0;
117     start = NULL;
118     if (py->lineindex[ln+1].start+MAXLINESIZE >= py->linebuf_size) {
119 	py->linebuf_size *= 2;
120 	py->linebuf = (char *)realloc(py->linebuf, py->linebuf_size);
121     }
122     strcpy(py->linebuf+py->lineindex[ln+1].start, "");
123     py->addpoint = py->lineindex[ln+1].start;
124 
125     py->cursx = 0;
126     py->sitext.nlines++;
127 
128     if (py->sitext.nlines-py->sitext.top == py->sitext.visible) {
129 	jump = ((py->sitext.nlines-py->sitext.top) - py->sitext.visible) + 1;
130 	py->sitext.top += jump;
131 	if (!py->backstore)
132 	    redraw_text_only(py, 0);
133     }
134     else {
135 	if (!py->backstore)
136 	    redraw_text_only(py, 1);
137     }
138 }
139 
redraw_text(py)140 void redraw_text(py)
141 struct player *py;
142 {
143     XDrawRectangle(py->dpy, py->win, py->blackgc, TEXT_X-3, TEXT_Y-2,
144 		TEXT_WID+4, TEXT_HGT+3);
145     XDrawRectangle(py->dpy, py->win, py->blackgc, TEXT_X-SCROLL_W, TEXT_Y-2,
146 		SCROLL_W-3, TEXT_HGT+3);
147     redraw_text_only(py, 0);
148 }
149 
dump_text(pnum,str)150 void dump_text(pnum, str)
151 int pnum;
152 char *str;
153 {
154     struct player *py = &(players[pnum]);
155     char *cx, *cy;
156     int tmp;
157     char *chtmp;
158     int len, width, sline;
159     static XCharStruct overall;
160     int direction, ascent, descent;
161 
162     if (!str) return;
163 
164     cx = str;
165 
166     while (*cx) {
167 	for (cy=cx;
168 	     !(*cy=='\0' || *cy=='\n' || (*cy==' ' && cy>cx && *(cy-1)!=' '));
169 	     cy++);
170 	len = (cy-cx);
171 	XTextExtents(py->font, cx, len, &direction, &ascent, &descent, &overall);
172 	width = overall.width;
173 	if (width >= TEXT_WID - py->cursx) {
174 	    complete_line(py);
175 	}
176 	sline = py->sitext.nlines - py->sitext.top;
177 	if (sline>=0 && sline<py->sitext.visible) {
178 	    py->gotexpose = 1;
179 	    if (!py->backstore)
180 		XDrawImageString(py->dpy, py->win, py->blackgc, py->textx+py->cursx,
181 				py->texty + py->lineheight*sline, cx, len);
182 	}
183 	chtmp = py->linebuf+py->addpoint;
184 	for (tmp=0; tmp<len; tmp++)
185 	    chtmp[tmp] = cx[tmp];
186 	chtmp[tmp] = '\0';
187 	py->addpoint += len;
188 	py->cursx += width;
189 	py->lineindex[py->sitext.nlines].width = py->cursx;
190 
191 	if (*cy=='\n') {
192 	    complete_line(py);
193 	    cy++;
194 	}
195 
196 	cx = cy;
197     }
198 }
199 
in_scrollbar_box(si,xpos,ypos)200 int in_scrollbar_box(si, xpos, ypos)
201 struct scroll_interface *si;
202 int xpos, ypos;
203 {
204     return (xpos >= si->x-SCROLL_W
205 	    && xpos < si->x
206 	    && ypos >= si->y
207 	    && ypos < si->y+si->h);
208 }
209 
redraw_scrollbar(si)210 void redraw_scrollbar(si)
211 struct scroll_interface *si;
212 {
213     struct player *py = si->py;
214     int sbeg, send;
215 
216     /* draw scrollbar */
217     if (si->nlines) {
218 	sbeg = (si->top)*si->h / si->nlines;
219 	send = (si->top+si->visible)*si->h / si->nlines;
220 	if (send>si->h)
221 	    send = si->h;
222     }
223     else {
224 	sbeg = 0;
225 	send = si->h;
226     }
227 
228     if (sbeg>0) {
229 	XFillRectangle(py->dpy, py->win, py->whitegc, si->x-SCROLL_W+2, si->y,
230 			SCROLL_W-6, sbeg);
231     }
232     XFillRectangle(py->dpy, py->win, py->blackgc, si->x-SCROLL_W+2, si->y+sbeg,
233 		SCROLL_W-6, send-sbeg);
234     if (send<si->h) {
235 	XFillRectangle(py->dpy, py->win, py->whitegc, si->x-SCROLL_W+2,
236 			si->y+send, SCROLL_W-6, si->h-send);
237     }
238 }
239 
scrollbar_hit(si,xpos,ypos,button)240 int scrollbar_hit(si, xpos, ypos, button)
241 struct scroll_interface *si;
242 int xpos, ypos;
243 int button;
244 {
245     int sbeg, send;
246 
247     if (si->nlines) {
248 	sbeg = (si->top)*si->h / si->nlines;
249 	send = (si->top+si->visible)*si->h / si->nlines;
250 	if (send>si->h)
251 	    send = si->h;
252     }
253     else {
254 	sbeg = 0;
255 	send = si->h;
256     }
257 
258     if (ypos>=si->y+sbeg && ypos<si->y+send) {
259 	si->grip = ypos - (si->y+sbeg);
260     }
261     else {
262 	si->grip = (-1);
263     }
264     si->moved = 0;
265 
266     si->py->scroll_active = si;
267     return ms_Scroll;
268 }
269 
scrollbar_motion(si,xpos,ypos,button)270 int scrollbar_motion(si, xpos, ypos, button)
271 struct scroll_interface *si;
272 int xpos, ypos;
273 int button;
274 {
275     int newtop;
276 
277     si->moved = 1;
278 
279     if (si->grip != (-1)) {
280 	newtop = (ypos-si->grip-si->y)*si->nlines / si->h;
281 	if (newtop > si->nlines - si->visible + 1)
282 	    newtop = si->nlines - si->visible + 1;
283 	if (newtop<0)
284 	    newtop = 0;
285 
286 	if (si->top != newtop) {
287 	    si->top = newtop;
288 	    (*(si->redraw))(si->py, 0);
289 	}
290     }
291 }
292 
scrollbar_release(si,xpos,ypos,button)293 int scrollbar_release(si, xpos, ypos, button)
294 struct scroll_interface *si;
295 int xpos, ypos;
296 int button;
297 {
298     int ln;
299     int newtop;
300 
301     if (!si->moved) {
302 	ln = (ypos-si->y) / si->lineheight;
303 	if (ln<=0)
304 	    ln = 1;
305 	newtop = si->top;
306 	if (button==1)
307 	    newtop += (ln);
308 	else if (button==3)
309 	    newtop -= (ln);
310 
311 	if (newtop > si->nlines - si->visible + 1)
312 	    newtop = si->nlines - si->visible + 1;
313 	if (newtop<0)
314 	    newtop = 0;
315 
316 	if (si->top != newtop) {
317 	    si->top = newtop;
318 	    (*(si->redraw))(si->py, 0);
319 	}
320     }
321 }
322