Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <thread.h>
5
#include <mouse.h>
6
#include <keyboard.h>
7
#include <control.h>
8
 
9
typedef struct Entry Entry;
10
 
11
struct Entry
12
{
13
	Control;
14
	int		border;
15
	CFont	*font;
16
	CImage	*image;
17
	CImage	*textcolor;
18
	CImage	*bordercolor;
19
	Rune		*text;
20
	int		ntext;
21
	int		cursor;
22
	int		align;
23
	int		hasfocus;
24
	int		lastbut;
25
};
26
 
27
enum{
28
	EAlign,
29
	EBorder,
30
	EBordercolor,
31
	EData,
32
	EFocus,
33
	EFont,
34
	EFormat,
35
	EHide,
36
	EImage,
37
	ERect,
38
	EReveal,
39
	EShow,
40
	ESize,
41
	ETextcolor,
42
	EValue,
43
};
44
 
45
static char *cmds[] = {
46
	[EAlign] =			"align",
47
	[EBorder] =		"border",
48
	[EBordercolor] =	"bordercolor",
49
	[EData] = 			"data",
50
	[EFocus] = 		"focus",
51
	[EFont] =			"font",
52
	[EFormat] = 		"format",
53
	[EHide] =			"hide",
54
	[EImage] =		"image",
55
	[ERect] =			"rect",
56
	[EReveal] =		"reveal",
57
	[EShow] =			"show",
58
	[ESize] =			"size",
59
	[ETextcolor] =		"textcolor",
60
	[EValue] =			"value",
61
	nil
62
};
63
 
64
static void
65
entryfree(Control *c)
66
{
67
	Entry *e;
68
 
69
	e = (Entry *)c;
70
	_putctlfont(e->font);
71
	_putctlimage(e->image);
72
	_putctlimage(e->textcolor);
73
	_putctlimage(e->bordercolor);
74
	free(e->text);
75
}
76
 
77
static Point
78
entrypoint(Entry *e, int c)
79
{
80
	Point p;
81
	Rectangle r;
82
 
83
	r = e->rect;
84
	if(e->border > 0)
85
		r = insetrect(r, e->border);
86
	p = _ctlalignpoint(r,
87
		runestringnwidth(e->font->font, e->text, e->ntext),
88
		e->font->font->height, e->align);
89
	if(c > e->ntext)
90
		c = e->ntext;
91
	p.x += runestringnwidth(e->font->font, e->text, c);
92
	return p;
93
}
94
 
95
static void
96
entryshow(Entry *e)
97
{
98
	Rectangle r, dr;
99
	Point p;
100
 
101
	if (e->hidden)
102
		return;
103
	r = e->rect;
104
	draw(e->screen, r, e->image->image, nil, e->image->image->r.min);
105
	if(e->border > 0){
106
		border(e->screen, r, e->border, e->bordercolor->image, e->bordercolor->image->r.min);
107
		dr = insetrect(r, e->border);
108
	}else
109
		dr = r;
110
	p = entrypoint(e, 0);
111
	_string(e->screen, p, e->textcolor->image,
112
		ZP, e->font->font, nil, e->text, e->ntext,
113
		dr, nil, ZP, SoverD);
114
	if(e->hasfocus){
115
		p = entrypoint(e, e->cursor);
116
		r.min = p;
117
		r.max.x = p.x+1;
118
		r.max.y = p.y+e->font->font->height;
119
		if(rectclip(&r, dr))
120
			draw(e->screen, r, e->textcolor->image, nil, ZP);
121
	}
122
	flushimage(display, 1);
123
}
124
 
125
static void
126
entrysetpoint(Entry *e, Point cp)
127
{
128
	Point p;
129
	int i;
130
 
131
	if(!ptinrect(cp, insetrect(e->rect, e->border)))
132
		return;
133
	p = entrypoint(e, 0);
134
	for(i=0; i<e->ntext; i++){
135
		p.x += runestringnwidth(e->font->font, e->text+i, 1);
136
		if(p.x > cp.x)
137
			break;
138
	}
139
	e->cursor = i;
140
	entryshow(e);
141
}
142
 
143
static void
144
entrymouse(Control *c, Mouse *m)
145
{
146
	Entry *e;
147
 
148
	e = (Entry*)c;
149
	if(m->buttons==1 && e->lastbut==0)
150
		entrysetpoint(e, m->xy);
151
	e->lastbut = m->buttons;
152
}
153
 
154
static void
155
entryctl(Control *c, CParse *cp)
156
{
157
	int cmd;
158
	Rectangle r;
159
	Entry *e;
160
	Rune *rp;
161
 
162
	e = (Entry*)c;
163
	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
164
	switch(cmd){
165
	default:
166
		ctlerror("%q: unrecognized message '%s'", e->name, cp->str);
167
		break;
168
	case EAlign:
169
		_ctlargcount(e, cp, 2);
170
		e->align = _ctlalignment(cp->args[1]);
171
		break;
172
	case EBorder:
173
		_ctlargcount(e, cp, 2);
174
		if(cp->iargs[1] < 0)
175
			ctlerror("%q: bad border: %c", e->name, cp->str);
176
		e->border = cp->iargs[1];
177
		break;
178
	case EBordercolor:
179
		_ctlargcount(e, cp, 2);
180
		_setctlimage(e, &e->bordercolor, cp->args[1]);
181
		break;
182
	case EData:
183
		_ctlargcount(e, cp, 1);
184
		chanprint(e->data, "%S", e->text);
185
		break;
186
	case EFocus:
187
		_ctlargcount(e, cp, 2);
188
		e->hasfocus = cp->iargs[1];
189
		e->lastbut = 0;
190
		entryshow(e);
191
		break;
192
	case EFont:
193
		_ctlargcount(e, cp, 2);
194
		_setctlfont(e, &e->font, cp->args[1]);
195
		break;
196
	case EFormat:
197
		_ctlargcount(e, cp, 2);
198
		e->format = ctlstrdup(cp->args[1]);
199
		break;
200
	case EHide:
201
		_ctlargcount(e, cp, 1);
202
		e->hidden = 1;
203
		break;
204
	case EImage:
205
		_ctlargcount(e, cp, 2);
206
		_setctlimage(e, &e->image, cp->args[1]);
207
		break;
208
	case ERect:
209
		_ctlargcount(e, cp, 5);
210
		r.min.x = cp->iargs[1];
211
		r.min.y = cp->iargs[2];
212
		r.max.x = cp->iargs[3];
213
		r.max.y = cp->iargs[4];
214
		if(Dx(r)<=0 || Dy(r)<=0)
215
			ctlerror("%q: bad rectangle: %s", e->name, cp->str);
216
		e->rect = r;
217
		break;
218
	case EReveal:
219
		_ctlargcount(e, cp, 1);
220
		e->hidden = 0;
221
		entryshow(e);
222
		break;
223
	case EShow:
224
		_ctlargcount(e, cp, 1);
225
		entryshow(e);
226
		break;
227
	case ESize:
228
		if (cp->nargs == 3)
229
			r.max = Pt(0x7fffffff, 0x7fffffff);
230
		else{
231
			_ctlargcount(e, cp, 5);
232
			r.max.x = cp->iargs[3];
233
			r.max.y = cp->iargs[4];
234
		}
235
		r.min.x = cp->iargs[1];
236
		r.min.y = cp->iargs[2];
237
		if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y)
238
			ctlerror("%q: bad sizes: %s", e->name, cp->str);
239
		e->size.min = r.min;
240
		e->size.max = r.max;
241
		break;
242
	case ETextcolor:
243
		_ctlargcount(e, cp, 2);
244
		_setctlimage(e, &e->textcolor, cp->args[1]);
245
		break;
246
	case EValue:
247
		_ctlargcount(e, cp, 2);
248
		rp = _ctlrunestr(cp->args[1]);
249
		if(runestrcmp(rp, e->text) != 0){
250
			free(e->text);
251
			e->text = rp;
252
			e->ntext = runestrlen(e->text);
253
			e->cursor = e->ntext;
254
			entryshow(e);
255
		}else
256
			free(rp);
257
		break;
258
	}
259
}
260
 
261
static void
262
entrykey(Entry *e, Rune r)
263
{
264
	Rune *s;
265
	int n;
266
	char *p;
267
 
268
	switch(r){
269
	default:
270
		e->text = ctlrealloc(e->text, (e->ntext+1+1)*sizeof(Rune));
271
		memmove(e->text+e->cursor+1, e->text+e->cursor,
272
			(e->ntext+1-e->cursor)*sizeof(Rune));
273
		e->text[e->cursor++] = r;
274
		e->ntext++;
275
		break;
276
	case L'\n':	/* newline: return value */
277
		p = _ctlstrrune(e->text);
278
		chanprint(e->event, e->format, e->name, p);
279
		free(p);
280
		return;
281
	case L'\b':
282
		if(e->cursor > 0){
283
			memmove(e->text+e->cursor-1, e->text+e->cursor,
284
				(e->ntext+1-e->cursor)*sizeof(Rune));
285
			e->cursor--;
286
			e->ntext--;
287
		}
288
		break;
289
	case Kright:
290
		if(e->cursor < e->ntext)
291
			e->cursor++;
292
		break;
293
	case Kleft:
294
		if(e->cursor > 0)
295
			e->cursor--;
296
		break;
297
	case 0x01:	/* control A: beginning of line */
298
		e->cursor = 0;
299
		break;
300
	case 0x05:	/* control E: end of line */
301
		e->cursor = e->ntext;
302
		break;
303
	case 0x15:	/* control U: kill line */
304
		e->cursor = 0;
305
		e->ntext = 0;
306
		break;
307
	case 0x16:	/* control V: paste (append snarf buffer) */
308
		s = _ctlgetsnarf();
309
		if(s != nil){
310
			n = runestrlen(s);
311
			e->text = ctlrealloc(e->text, (e->ntext+n+1)*sizeof(Rune));
312
			memmove(e->text+e->cursor+n, e->text+e->cursor,
313
				(e->ntext+1-e->cursor)*sizeof(Rune));
314
			memmove(e->text+e->cursor, s, n*sizeof(Rune));
315
			e->cursor += n;
316
			e->ntext += n;
317
		}
318
		break;
319
	}
320
	e->text[e->ntext] = L'\0';
321
}
322
 
323
static void
324
entrykeys(Control *c, Rune *rp)
325
{
326
	Entry *e;
327
	int i;
328
 
329
	e = (Entry *)c;
330
	for(i=0; rp[i]!=L'\0'; i++)
331
		entrykey(e, rp[i]);
332
	entryshow(e);
333
}
334
 
335
Control*
336
createentry(Controlset *cs, char *name)
337
{
338
	Entry *e;
339
 
340
	e = (Entry*) _createctl(cs, "entry", sizeof(Entry), name);
341
	e->text = ctlmalloc(sizeof(Rune));
342
	e->ntext = 0;
343
	e->image = _getctlimage("white");
344
	e->textcolor = _getctlimage("black");
345
	e->bordercolor = _getctlimage("black");
346
	e->font = _getctlfont("font");
347
	e->format = ctlstrdup("%q: value %q");
348
	e->border = 0;
349
	e->ctl = entryctl;
350
	e->mouse = entrymouse;
351
	e->key = entrykeys;
352
	e->exit = entryfree;
353
	return (Control *)e;
354
}