The R Project SVN R

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4394 ripley 1
/*
2
 * GraphApp - Cross-Platform Graphics Programming Library.
3
 *
4
 * File: drawtext.c -- cross-platform portable drawing functions.
5
 * Platform: Neutral  Version: 2.30  Date: 1998/01/01
6
 *
7
 * Version: 1.00  Changes: Original version by Lachlan Patrick.
8
 * Version: 1.50  Changes: gprintf now has internal state.
9
 * Version: 1.60  Changes: Major bugfixes!
10
 * Version: 2.00  Changes: Update to version 2.
11
 * Version: 2.01  Changes: Changed unnecessary longs to ints.
12
 * Version: 2.20  Changes: Added underlining ability.
13
 * Version: 2.30  Changes: Now uses getheight, getdescent.
14
 */
15
 
16
/* Copyright (C) 1993-1998 Lachlan Patrick
17
 
18
   This file is part of GraphApp, a cross-platform C graphics library.
19
 
20
   GraphApp is free software; you can redistribute it and/or modify it
21
   under the terms of the GNU Library General Public License.
22
   GraphApp is distributed in the hope that it will be useful, but
23
   WITHOUT ANY WARRANTY.
24
 
25
   See the file COPYLIB.TXT for details.
26
*/
27
 
28
#include "internal.h"
29
#include <stdarg.h>
30
 
31
#define COMPRESS_WHITESPACE 0
32
 
33
static char *get_next_line(char *line, int width, char *s)
34
{
35
	char *t, *k;
36
	int	word_width, line_width;
37
	int	sp, tab, nl;
38
 
39
	line_width  = 0;
40
 
41
	for (t=s, k=line; *t!='\0'; line=k, s=t)
42
	{
43
		for (nl=tab=sp=0; (*t!='\0') && isspace(*t) && !nl; t++)
44
		{
45
#if COMPRESS_WHITESPACE
46
			if (*t == '\n') nl++;
47
			else if (*t == '\t') tab++;
48
			else sp++;
49
#else
50
			if (*t == '\n') nl++;
51
			else if (*t == '\t') { /* expand tabs */
52
				for (tab=4; tab; tab--)
53
					*k++ = ' ';
54
			}
55
			else
56
				*k++ = *t;
57
#endif
58
		}
59
 
60
		s = t;
61
 
62
		if (nl)      	{ *k++ = '\n'; break; }
63
		else if (tab)	{ *k++ = ' '; *k++ = ' '; }
64
		else if (sp) 	{ *k++ = ' ';  }
65
 
66
		/* fetch the next word to draw */
67
 
68
		for (*k='\0'; (*t!='\0') && !isspace(*t); *k='\0') {
69
			if (*t == '-') {
70
				*k++ = *t++;
71
				*k = '\0';
72
				break;
73
			}
74
			*k++ = *t++;
75
		}
76
 
77
		/* determine where the word should be drawn */
78
 
79
		while (((word_width = strwidth(current->fnt,line)) > width)
80
				&& (k>line))
81
		{
82
			*(--k) = '\0';
83
			--t;
84
		}
85
 
86
		if (word_width > (width - line_width)) {
87
			k = line;
88
			break;
89
		} else
90
			line_width += word_width;
91
	}
92
 
93
	*k = '\0';
94
 
95
	return (*s == '\0') ? NULL : s;
96
}
97
 
98
int textheight(int width, char *s)
99
{
100
	int y;
101
	char line[256];
102
	int height;
103
 
104
	height = getheight(current->fnt);
105
 
106
	for(y=0; s; y+=height)
107
	{
108
		s = get_next_line(line, width, s);
109
	}
110
 
111
	return y;
112
}
113
 
114
static char *draw_text_left(char *line, rect r, int line_height,
115
			int underline, char *s)
116
{
117
	char *k;
118
	point p;
119
	int width, height;
120
	font f;
121
 
122
	f = current->fnt;
123
 
124
	for(p=pt(r.x,r.y); (p.y<=r.y+r.height) && (s); p.y+=line_height)
125
	{
126
		s = get_next_line(line, r.width, s);
127
 
128
		for (k=line; *k!='\0'; k++)
129
			continue;
130
		for (--k; (k>=line) && isspace(*k); k--)
131
			*k = '\0';
132
 
133
		drawstr(p, line);
134
 
135
		if (underline) {
136
			width = strwidth(f, line);
137
			height = p.y+getheight(f)-getdescent(f)+2;
138
			drawline(pt(p.x+1, height), pt(p.x+width-1, height));
139
		}
140
	}
141
 
142
	return s;
143
}
144
 
145
static char *draw_text_right(char *line, rect r, int line_height,
146
			int underline, char *s)
147
{
148
	char *k;
149
	int w;
150
	point p;
151
	int width, height;
152
	font f;
153
 
154
	f = current->fnt;
155
 
156
	for(p=pt(r.x,r.y); (p.y<=r.y+r.height) && (s); p.y+=line_height)
157
	{
158
		s = get_next_line(line, r.width, s);
159
 
160
		for (k=line; *k!='\0'; k++)
161
			continue;
162
		for (--k; (k>=line) && isspace(*k); k--)
163
			*k = '\0';
164
		for (k=line; (*k!='\0') && isspace(*k); k++)
165
			continue;
166
 
167
		w = strwidth(current->fnt, k);
168
		p.x = r.x+r.width - w;
169
 
170
		drawstr(p, k);
171
 
172
		if (underline) {
173
			width = strwidth(f, k);
174
			height = p.y+getheight(f)-getdescent(f)+2;
175
			drawline(pt(p.x+1, height), pt(p.x+width-1, height));
176
		}
177
	}
178
 
179
	return s;
180
}
181
 
182
static char *draw_text_centered(char *line, rect r, int line_height,
183
			int underline, char *s)
184
{
185
	char *k;
186
	int w;
187
	point p;
188
	int width, height;
189
	font f;
190
 
191
	f = current->fnt;
192
 
193
	for(p=pt(r.x,r.y); (p.y<=r.y+r.height) && (s); p.y+=line_height)
194
	{
195
		s = get_next_line(line, r.width, s);
196
 
197
		for (k=line; *k!='\0'; k++)
198
			continue;
199
		for (--k; (k>=line) && isspace(*k); k--)
200
			*k = '\0';
201
		for(k=line; (*k!='\0') && isspace(*k); k++)
202
			continue;
203
 
204
		w = strwidth(current->fnt, k);
205
		p.x = r.x + (r.width-w)/2;
206
 
207
		drawstr(p, k);
208
 
209
		if (underline) {
210
			width = strwidth(f, k);
211
			height = p.y+getheight(f)-getdescent(f)+2;
212
			drawline(pt(p.x+1, height), pt(p.x+width-1, height));
213
		}
214
	}
215
 
216
	return s;
217
}
218
 
219
static char *draw_text_justified(char *line, rect r, int line_height,
220
			int underline, char *s)
221
{
222
	char *j, *k;
223
	int w, xw, nl, sc, sw, space_width;
224
	point p;
225
	int width, height;
226
	font f;
227
 
228
	space_width = strwidth(current->fnt, " ");
229
	f = current->fnt;
230
 
231
	for(p=pt(r.x,r.y); (p.y<=r.y+r.height) && (s); p.y+=line_height)
232
	{
233
		s = get_next_line(line, r.width, s);
234
 
235
		p.x = r.x;
236
 
237
		for(j=line; (*j!='\0') && isspace(*j); j++)
238
			p.x += space_width;
239
		for (sc=0, k=j; *k!='\0'; k++)
240
			if (isspace(*k))
241
				sc++;
242
		for (nl=0, --k; (k>=j) && isspace(*k); k--) {
243
			if (*k == '\n')
244
				nl++;
245
			*k = '\0';
246
			sc--;
247
		}
248
 
249
		if ((sc==0) || nl || (! s)) {
250
			drawstr(p, j);
251
			width = strwidth(f, j);
252
		}
253
		else {
254
			w = strwidth(f, j);
255
			sw = space_width + (r.x+r.width-p.x-w)/sc;
256
			xw = (r.x+r.width-p.x-w)%sc;
257
 
258
			for(j=strtok(j," "); j; j=strtok(NULL," "))
259
			{
260
				drawstr(p, j);
261
				p.x += sw + strwidth(f, j);
262
				if (xw) {
263
					p.x++;
264
					xw--;
265
				}
266
			}
267
			width = r.width;
268
		}
269
		if (underline) {
270
			height = p.y+getheight(f)-getdescent(f)+2;
271
			drawline(pt(p.x+1, height), pt(p.x+width-1, height));
272
		}
273
	}
274
 
275
	return s;
276
}
277
 
278
char *drawtext(rect r, int alignment, char *s)
279
{
280
	int h;
281
	int nlines;
282
	int line_height;
283
	int u = 0;
284
	rect clip;
285
	char *remains;
286
	char line[256];
287
 
288
	initapp(0,0);
289
	if (! s)
290
		return s;
291
	if (! current->fnt)
292
		current->fnt = SystemFont;
293
 
294
	clip = getcliprect();
295
	setcliprect(r);
296
 
297
	line_height = getheight(current->fnt);
298
 
299
	if ((alignment & VCenter) == VCenter) {
300
		h = textheight(r.width, s);
301
		if (h < r.height)
302
			r.y += (r.height-h)/2;
303
	}
304
	else if ((alignment & VJustify) == VJustify) {
305
		h = textheight(r.width, s);
306
		if (h < r.height) {
307
			nlines = h / line_height;
308
			if (nlines > 1)
309
				line_height += ((r.height-h) / (nlines-1));
310
		}
311
	}
312
	else if ((alignment & AlignBottom) == AlignBottom) {
313
		h = textheight(r.width, s);
314
		if (h < r.height)
315
			r.y += (r.height-h);
316
	}
317
 
318
	u = (alignment & Underline);
319
 
320
	if ((alignment & Center) == Center)
321
		remains = draw_text_centered(line, r, line_height, u, s);
322
	else if ((alignment & Justify) == Justify)
323
		remains = draw_text_justified(line, r, line_height, u, s);
324
	else if ((alignment & AlignRight) == AlignRight)
325
		remains = draw_text_right(line, r, line_height, u, s);
326
	else
327
		remains = draw_text_left(line, r, line_height, u, s);
328
 
329
	setcliprect(clip);
330
	return remains;
331
}
332
 
333
int gprintf(char *fmt, ...)
334
{
335
	static point p = {0,0};
336
	int count;
337
	int line_height;
338
	char *s, *t;
339
	va_list argptr;
340
	char str[256];
341
 
342
	va_start(argptr, fmt);
343
	count = vsprintf(str, fmt, argptr);
344
 
345
	initapp(0,0);
346
	if (! current->fnt)
347
		current->fnt = SystemFont;
348
	line_height = getheight(current->fnt);
349
 
350
	for (s=t=str; *s!='\0'; t++) {
351
		if (current->p.y != p.y) {
352
			/* typewriter ping! */
353
			p = current->p;
354
		}
355
		if (*t == '\n') {
356
		/* print everything from s to t and move point down */
357
			*t = '\0';
358
			drawstr(p, s);
359
			current->p.y += line_height;
360
			/* go past the substring just printed */
361
			s = t+1;
362
		}
363
		else if (*t == '\0') {
364
			/* print final string without newline */
365
			p.x += drawstr(p, s);
366
			/* go to end of string, signal termination */
367
			s = t;
368
		}
369
	}
370
 
371
	va_end(argptr);
372
 
373
	return count;
374
}