1 /* OpenCP Module Player
2  * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3  *
4  * CPIFace text modes master mode and window handler
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * revision history: (please note changes here)
21  *  -nb980510   Niklas Beisert <nbeisert@physik.tu-muenchen.de>
22  *    -first release
23  *  -fd981119   Felix Domke <tmbinc@gmx.net>
24  *    -added the really important 'NO_CPIFACE_IMPORT'
25  *  -ss040825   Stian Skjelstad <stian@nixia.no>
26  *    -upgraded the IQ of cpiTextRecalc to make it try fill more of the screen
27  */
28 
29 #include "config.h"
30 #include <string.h>
31 #include "types.h"
32 #include "stuff/poutput.h"
33 #include "filesel/pfilesel.h"
34 #include "cpiface.h"
35 #include "boot/psetting.h"
36 #include "boot/plinkman.h"
37 
38 static struct cpitextmoderegstruct *cpiTextActModes;
39 static struct cpitextmoderegstruct *cpiTextModes = 0;
40 static struct cpitextmoderegstruct *cpiTextDefModes = 0;
41 static struct cpitextmoderegstruct *cpiFocus;
42 static char cpiFocusHandle[9];
43 static int modeactive;
44 
45 static unsigned int LastWidth, LastHeight;
46 
cpiTextRegisterMode(struct cpitextmoderegstruct * mode)47 void cpiTextRegisterMode(struct cpitextmoderegstruct *mode)
48 {
49 	if (mode->Event&&!mode->Event(cpievInit))
50 		return;
51 	mode->next=cpiTextModes;
52 	cpiTextModes=mode;
53 }
54 
cpiTextUnregisterMode(struct cpitextmoderegstruct * m)55 void cpiTextUnregisterMode(struct cpitextmoderegstruct *m)
56 {
57 	if (cpiTextModes==m)
58 	{
59 		cpiTextModes=m->next;
60 		return;
61 	} else {
62 		struct cpitextmoderegstruct *p = cpiTextModes;
63 		while (p)
64 		{
65 			if (p->next==m)
66 			{
67 				p->next=m->next;
68 				return;
69 			}
70 			p=p->next;
71 		}
72 	}
73 }
74 
cpiTextRegisterDefMode(struct cpitextmoderegstruct * mode)75 void cpiTextRegisterDefMode(struct cpitextmoderegstruct *mode)
76 {
77 	mode->nextdef=cpiTextDefModes;
78 	cpiTextDefModes=mode;
79 }
80 
cpiTextVerifyDefModes(void)81 static void cpiTextVerifyDefModes(void)
82 {
83 	struct cpitextmoderegstruct *p;
84 
85 	while (cpiTextDefModes)
86 	{
87 		if (cpiTextDefModes->Event&&!cpiTextDefModes->Event(cpievInitAll))
88 			cpiTextDefModes=cpiTextDefModes->nextdef;
89 		else
90 			break;
91 	}
92 	p = cpiTextDefModes;
93 	while (p)
94 	{
95 		if (p->nextdef)
96 		{
97 			if (p->nextdef->Event&&!p->nextdef->Event(cpievInitAll))
98 				p->nextdef=p->nextdef->nextdef;
99 			else
100 				p=p->nextdef;
101 		} else
102 			break;
103 	}
104 }
105 
cpiTextUnregisterDefMode(struct cpitextmoderegstruct * m)106 void cpiTextUnregisterDefMode(struct cpitextmoderegstruct *m)
107 {
108 	if (cpiTextDefModes==m)
109 	{
110 		cpiTextDefModes=m->next;
111 		return;
112 	} else {
113 		struct cpitextmoderegstruct *p = cpiTextDefModes;
114 		while (p)
115 		{
116 			if (p->nextdef==m)
117 			{
118 				p->nextdef=m->nextdef;
119 				return;
120 			}
121 			p=p->nextdef;
122 		}
123 	}
124 }
125 
cpiSetFocus(const char * name)126 static void cpiSetFocus(const char *name)
127 {
128 	struct cpitextmoderegstruct *mode;
129 
130 	if (cpiFocus&&cpiFocus->Event)
131 		cpiFocus->Event(cpievLoseFocus);
132 	cpiFocus=0;
133 	if (!name)
134 	{
135 		*cpiFocusHandle=0;
136 		return;
137 	}
138 	for (mode=cpiTextActModes; mode; mode=mode->nextact)
139 		if (!strcasecmp(name, mode->handle))
140 			break;
141 	*cpiFocusHandle=0;
142 	if (!mode||(mode->Event&&!mode->Event(cpievGetFocus)))
143 		return;
144 	cpiFocus=mode;
145 	mode->active=1;
146 	strcpy(cpiFocusHandle, cpiFocus->handle);
147 	cpiTextRecalc();
148 }
149 
cpiTextSetMode(const char * name)150 void cpiTextSetMode(const char *name)
151 {
152 	if (!name)
153 		name=cpiFocusHandle;
154 	if (!modeactive)
155 	{
156 		strcpy(cpiFocusHandle, name);
157 		cpiSetMode("text");
158 	} else
159 		cpiSetFocus(name);
160 }
161 
cpiTextRecalc(void)162 void cpiTextRecalc(void)
163 {
164 	unsigned int i;
165 	int winfirst=5;
166 	int winheight=plScrHeight-winfirst;
167 	int sidefirst=5;
168 	int sideheight=plScrHeight-sidefirst;
169 	struct cpitextmodequerystruct win[10];
170 	unsigned int nwin=0;
171 	struct cpitextmoderegstruct *mode;
172 
173 	int sidemin,sidemax,sidesize;
174 	int winmin,winmax,winsize;
175 
176 	plChanChanged=1;
177 
178 	LastWidth=plScrWidth;
179 	LastHeight=plScrHeight;
180 
181 	for (mode=cpiTextActModes; mode; mode=mode->nextact)
182 	{
183 		mode->active=0;
184 		if (mode->GetWin(&win[nwin]))
185 			win[nwin++].owner=mode;
186 	}
187 #ifdef CPIFACE_DEBUG
188 	fprintf (stderr, "cpiTextRecalc\n");
189 	fprintf (stderr, "step 1, found all active modes\n");
190 	for (i=0; i<nwin; i++)
191 	{
192 		fprintf (stderr, "[%d] %-8s xmode=%d\n", i, win[i].owner->handle, win[i].xmode);
193 	};
194 #endif
195 
196 	/* xmode bit0 = left column request
197 	 *       bit1 = right column request
198 	 */
199 	if (plScrWidth<132)
200 		for (i=0; i<nwin; i++)
201 			win[i].xmode&=1;
202 
203 #ifdef CPIFACE_DEBUG
204 	fprintf (stderr, "step 2, masked away xmode bit1 if display can not fit 132 width\n");
205 	for (i=0; i<nwin; i++)
206 	{
207 		fprintf (stderr, "[%d] %-8s xmode=%d\n", i, win[i].owner->handle, win[i].xmode);
208 	}
209 #endif
210 
211 	/* can we fit all the columned windows (not checking the header ones)? */
212 	while (1)
213 	{
214 		/* initialize all the probes back to zero */
215 		sidemin=sidemax=sidesize=0;
216 		winmin=winmax=winsize=0;
217 		/* sum all the left and right windows */
218 		for (i=0; i<nwin; i++)
219 		{
220 			if (win[i].xmode&1)
221 			{
222 				winmin+=win[i].hgtmin;
223 				winmax+=win[i].hgtmax;
224 				winsize+=win[i].size;
225 			}
226 			if (win[i].xmode&2)
227 			{
228 				sidemin+=win[i].hgtmin;
229 				sidemax+=win[i].hgtmax;
230 				sidesize+=win[i].size;
231 			}
232 		}
233 		if ((winmin<=winheight)&&(sidemin<=sideheight))
234 			break;
235 		/* if we were too heigh, hide windows by setting the xmode to 0 */
236 		if (sidemin>sideheight)
237 		{
238 			int worst=0;
239 			for (i=0; i<nwin; i++)
240 				if (win[i].xmode&2)
241 					if (win[i].killprio>win[worst].killprio)
242 						worst=i;
243 			win[i].xmode=0;
244 			continue;
245 		}
246 		if (winmin>winheight)
247 		{
248 			int worst=0;
249 			for (i=0; i<nwin; i++)
250 				if (win[i].xmode&1)
251 					if (win[i].killprio>win[worst].killprio)
252 						worst=i;
253 			win[i].xmode=0;
254 			continue;
255 		}
256 	}
257 
258 	/* Disable all windows. We are about to actually pick out one and one window until the screen is full */
259 	for (i=0; i<nwin; i++)
260 		win[i].owner->active=0;
261 
262 	/* first we want to fill the screen with all the windows that requested both left and right column, starting with the highest priority ones */
263 #ifdef CPIFACE_DEBUG
264 	fprintf (stderr, "step 3, place all xmode==3 windows\n");
265 #endif
266 	while (1)
267 	{
268 		int best=-1;
269 		int whgt,shgt,hgt;
270 
271 		for (i=0; i<nwin; i++)
272 			if ((win[i].xmode==3)&&!win[i].owner->active)
273 				if ((best==-1)||(win[i].viewprio>win[best].viewprio))
274 					best=i;
275 		if (best==-1)
276 			break;
277 		if (!win[best].size)
278 			hgt=win[best].hgtmin;
279 		else {
280 			whgt=win[best].hgtmin+(winheight-winmin)*win[best].size/winsize;
281 			if ((winheight-whgt)>(winmax-win[best].hgtmax))
282 				whgt=winheight-(winmax-win[best].hgtmax);
283 			shgt=win[best].hgtmin+(sideheight-sidemin)*win[best].size/sidesize;
284 			if ((sideheight-shgt)>(sidemax-win[best].hgtmax))
285 				shgt=sideheight-(sidemax-win[best].hgtmax);
286 			hgt=(whgt<shgt)?whgt:shgt;
287 		}
288 		if (hgt>win[best].hgtmax)
289 			hgt=win[best].hgtmax;
290 		if (win[best].top)
291 		{
292 #ifdef CPIFACE_DEBUG
293 			fprintf (stderr, "Placing window %-8s top %d %d %d %d\n", win[best].owner->handle, 0, plScrWidth, winfirst, hgt);
294 #endif
295 			win[best].owner->SetWin(0, plScrWidth, winfirst, hgt);
296 			winfirst+=hgt;
297 			sidefirst+=hgt;
298 		} else {
299 #ifdef CPIFACE_DEBUG
300 			fprintf (stderr, "Placing window %-8s bot %d %d %d %d\n", win[best].owner->handle, 0, plScrWidth, winfirst+winheight-hgt, hgt);
301 #endif
302 			win[best].owner->SetWin(0, plScrWidth, winfirst+winheight-hgt, hgt);
303 		}
304 		win[best].owner->active=1;
305 		winheight-=hgt;
306 		sideheight-=hgt;
307 		winmin-=win[best].hgtmin;
308 		winsize-=win[best].size;
309 		sidemin-=win[best].hgtmin;
310 		sidesize-=win[best].size;
311 
312 		winmax-=win[best].hgtmax;
313 		sidemax-=win[best].hgtmax;
314 	}
315 #ifdef CPIFACE_DEBUG
316 	fprintf (stderr, "step 4, place all xmode==2 windows (right column)\n");
317 #endif
318 
319 	while (1)
320 	{
321 		int best=-1;
322 		int hgt;
323 
324 		for (i=0; i<nwin; i++)
325 			if ((win[i].xmode==2)&&!win[i].owner->active)
326 				if ((best==-1)||(win[i].viewprio>win[best].viewprio)) /* can crash in theory, TODO */
327 					best=i;
328 		if (best==-1)
329 			break;
330 		hgt=win[best].hgtmin;
331 		if (win[best].size)
332 		{
333 			hgt+=(sideheight-sidemin)*win[best].size/sidesize;
334 			if ((sideheight-hgt)>(sidemax-win[best].hgtmax))
335 				hgt=sideheight-(sidemax-win[best].hgtmax);
336 		}
337 		if (hgt>win[best].hgtmax)
338 			hgt=win[best].hgtmax;
339 		if (win[best].top)
340 		{
341 #ifdef CPIFACE_DEBUG
342 			fprintf (stderr, "Placing window %-8s top %d %d %d %d\n", win[best].owner->handle, plScrWidth-52, 52, sidefirst, hgt);
343 #endif
344 			win[best].owner->SetWin(plScrWidth-52, 52, sidefirst, hgt);
345 			sidefirst+=hgt;
346 		} else {
347 #ifdef CPIFACE_DEBUG
348 			fprintf (stderr, "Placing window %-8s bot %d %d %d %d\n", win[best].owner->handle, plScrWidth-52, 52, sidefirst+sideheight-hgt, hgt);
349 #endif
350 			win[best].owner->SetWin(plScrWidth-52, 52, sidefirst+sideheight-hgt, hgt);
351 		}
352 		win[best].owner->active=1;
353 		sideheight-=hgt;
354 		sidemin-=win[best].hgtmin;
355 		sidesize-=win[best].size;
356 		sidemax-=win[best].hgtmax;
357 	}
358 
359 #ifdef CPIFACE_DEBUG
360 	fprintf (stderr, "step 5, place all xmode==1 windows (left column)\n");
361 #endif
362 
363 	while (1)
364 	{
365 		int best=-1;
366 		int hgt;
367 		int wid;
368 
369 		for (i=0; i<nwin; i++)
370 			if ((win[i].xmode==1)&&!win[i].owner->active)
371 				if ((best==-1)||(win[i].viewprio>win[best].viewprio))
372 					best=i;
373 		if (best==-1)
374 			break;
375 		if (winmax<=winheight)
376 			hgt=win[best].hgtmax;
377 		else {
378 			hgt=win[best].hgtmin;
379 			if (win[best].size) /* if size were requested, we try to adjust up from minsize */
380 			{
381 /*
382 				        / free space left
383 				        |         / min space that has to be used
384 				        |         |                / size requested
385 				        |         |                |     / total size requested
386 */
387 				hgt+=(winheight-winmin)*win[best].size/winsize;
388 				if ((winheight-hgt)>(winmax-win[best].hgtmax))
389 					hgt=winheight-(winmax-win[best].hgtmax);
390 			}
391 			if (hgt>win[best].hgtmax)
392 				hgt=win[best].hgtmax;
393 		}
394 		if (win[best].top)
395 		{
396 
397 			if (plScrWidth < 132)
398 			{
399 				wid=plScrWidth;
400 			} else {
401 /*
402 				              /-------------- does our new window start below (the last used) sidewindow?
403 				              |                            /-- does our new window stop before the sidewindow have anything to display?
404 				              |                            |                             /-- then use the hole width
405 				              |                            |                             |           /-- or make room for the sidewindow
406 */
407 				wid=((winfirst>=sidefirst)&&((winfirst+hgt)<=(sidefirst+sideheight)))?plScrWidth:plScrWidth-52;
408 			}
409 #ifdef CPIFACE_DEBUG
410 			fprintf (stderr, "Placing window %-8s top %d %d %d %d\n", win[best].owner->handle, 0, wid, winfirst, hgt);
411 #endif
412 
413 			win[best].owner->SetWin(0, wid, winfirst, hgt);
414 			winfirst+=hgt;
415 		} else {
416 			if (plScrWidth < 132)
417 			{
418 				wid=plScrWidth;
419 			} else {
420 				wid=(((winfirst+winheight)<=(sidefirst+sideheight))&&((winfirst+winheight-hgt)>=sidefirst))?plScrWidth:plScrWidth-52;
421 			}
422 #ifdef CPIFACE_DEBUG
423 			fprintf (stderr, "Placing window %-8s bot %d %d %d %d\n", win[best].owner->handle, 0, wid, winfirst+winheight-hgt, hgt);
424 #endif
425 
426 			win[best].owner->SetWin(0, wid, winfirst+winheight-hgt, hgt);
427 		}
428 		win[best].owner->active=1;
429 		winheight-=hgt;
430 		winmin-=win[best].hgtmin;
431 		winsize-=win[best].size;
432 		winmax-=win[best].hgtmax;
433 
434 /*
435 	Old code for filling the void. It does not work well with dynamic resolutions
436 		if (wid>=132)
437 		{
438 			if (win[best].top)
439 			{
440 				for (i=sidefirst; i<winfirst; i++)
441 					displayvoid(i, plScrWidth-52, 52);
442 				sideheight=sidefirst+sideheight-winfirst;
443 				sidefirst=winfirst;
444 			} else {
445 				for (i=winfirst+hgt; i<(sidefirst+sideheight); i++)
446 					displayvoid(i, plScrWidth-52, 52);
447 				sideheight=winfirst+winheight-sidefirst;
448 			}
449 		}*/
450 	}
451 #if 0
452 	for (i=0; i<winheight; i++)
453 		displayvoid(winfirst+i, 0, plScrWidth-52);
454 	for (i=0; i<sideheight; i++)
455 		displayvoid(sidefirst+i, plScrWidth-52, 52);
456 	if (!nwin)
457 		for (i=0;i<plScrHeight;i++)
458 			displayvoid(i, 0, plScrWidth);
459 #else
460 	for (i=0;i<plScrHeight;i++)
461 		displayvoid(i, 0, plScrWidth);
462 #endif
463 }
464 
txtSetMode(void)465 static void txtSetMode(void)
466 {
467 	struct cpitextmoderegstruct *mode;
468 	plSetTextMode(fsScrType);
469 	fsScrType=plScrType;
470 	for (mode=cpiTextActModes; mode; mode=mode->nextact)
471 		if (mode->Event)
472 			mode->Event(cpievSetMode);
473 	cpiTextRecalc();
474 }
475 
txtDraw(void)476 static void txtDraw(void)
477 {
478 	struct cpitextmoderegstruct *mode;
479 
480 	if ((LastWidth!=plScrWidth)||(LastHeight!=plScrHeight)) /* xterms as so fun */
481 		cpiTextRecalc();
482 
483 	cpiDrawGStrings();
484 	for (mode=cpiTextActModes; mode; mode=mode->nextact)
485 		if (mode->active)
486 			mode->Draw(mode==cpiFocus);
487 	for (mode=cpiTextModes; mode; mode=mode->next)
488 		mode->Event(cpievKeepalive);
489 }
490 
txtIProcessKey(uint16_t key)491 static int txtIProcessKey(uint16_t key)
492 {
493 	struct cpitextmoderegstruct *mode;
494 #ifdef KEYBOARDTEXT_DEBUG
495 	fprintf(stderr, "txtIProcessKey:START\n");
496 #endif
497 	for (mode=cpiTextModes; mode; mode=mode->next)
498 	{
499 #ifdef KEYBOARDTEXT_DEBUG
500 		fprintf(stderr, "Checking mode %s\n", mode->handle);
501 #endif
502 		if (mode->IProcessKey(key))
503 		{
504 #ifdef KEYBOARDTEXT_DEBUG
505 			fprintf(stderr, "Mode swallowed event\ntxtIProcessKey:STOP\n");
506 #endif
507 			return 1;
508 		}
509 	}
510 #ifdef KEYBOARDTEXT_DEBUG
511 	fprintf(stderr, "txtIProcessKey:STOP\n");
512 #endif
513 	switch (key)
514 	{
515 		case 'x': case 'X':
516 			fsScrType=7;
517 			cpiTextSetMode(cpiFocusHandle);
518 			return 1;
519 		case KEY_ALT_X:
520 			fsScrType=0;
521 			cpiTextSetMode(cpiFocusHandle);
522 			return 1;
523 		case 'z': case 'Z':
524 			cpiTextSetMode(cpiFocusHandle);
525 			break;
526 		default:
527 			return 0;
528 	}
529 	return 1;
530 }
531 
txtAProcessKey(uint16_t key)532 static int txtAProcessKey(uint16_t key)
533 {
534 #ifdef KEYBOARDTEXT_DEBUG
535 	fprintf(stderr, "txtAProcessKey:START\ncpiFocus is %s\n", cpiFocus?"set":"unset");
536 #endif
537 	if (cpiFocus)
538 		if (cpiFocus->active)
539 			if (cpiFocus->AProcessKey(key))
540 			{
541 #ifdef KEYBOARDTEXT_DEBUG
542 				fprintf(stderr, "cpiFocus %s swallowed event\ntxtAProcessKey:STOP\n", cpiFocus->handle);
543 #endif
544 				return 1;
545 			}
546 #ifdef KEYBOARDTEXT_DEBUG
547 	fprintf(stderr, "nobody swallowed the event\ntxtAProcessKey:STOP\n");
548 #endif
549 	switch (key)
550 	{
551 		case KEY_ALT_K:
552 			cpiKeyHelp('x', "Set screen text mode (set mode 7)");
553 			cpiKeyHelp('X', "Set screen text mode (set mode 7)");
554 			cpiKeyHelp('z', "Set screen text mode (toggle bit 1)");
555 			cpiKeyHelp('Z', "Set screen text mode (toggle bit 1)");
556 			cpiKeyHelp(KEY_ALT_X, "Set screen text screen mode (set mode 0)");
557 			cpiKeyHelp(KEY_ALT_Z, "Set screen text screen mode (toggle bit 2)");
558 			cpiKeyHelp(KEY_CTRL_Z, "Set screen text screen mode (toggle bit 1)");
559 			return 0;
560 		case 'x': case 'X':
561 			fsScrType=7;
562 			cpiForwardIProcessKey (key);
563 			cpiResetScreen();
564 			return 1;
565 		case KEY_ALT_X:
566 			fsScrType=0;
567 			cpiForwardIProcessKey (key);
568 			cpiResetScreen();
569 			return 1;
570 		case 'z': case 'Z':
571 			fsScrType^=2;
572 			cpiForwardIProcessKey (key);
573 			cpiResetScreen();
574 			break;
575 		case KEY_ALT_Z:
576 			fsScrType^=4;
577 			cpiForwardIProcessKey (key);
578 			cpiResetScreen();
579 			break;
580 		case KEY_CTRL_Z:
581 			fsScrType^=1;
582 			cpiForwardIProcessKey (key);
583 			cpiResetScreen();
584 			break;
585 		default:
586 			return 0;
587 	}
588 	return 1;
589 }
590 
txtInit(void)591 static int txtInit(void)
592 {
593 	struct cpitextmoderegstruct *mode;
594 	for (mode=cpiTextDefModes; mode; mode=mode->nextdef)
595 		cpiTextRegisterMode(mode);
596 	cpiSetFocus(cpiFocusHandle);
597 	return 1;
598 }
599 
txtClose(void)600 static void txtClose(void)
601 {
602 	struct cpitextmoderegstruct *mode;
603 	for (mode=cpiTextModes; mode; mode=mode->next)
604 		if (mode->Event)
605 			 mode->Event(cpievDone);
606 	cpiTextModes=0;
607 }
608 
txtInitAll(void)609 static int txtInitAll(void)
610 {
611 	cpiTextVerifyDefModes();
612 	return 1;
613 }
614 
txtCloseAll(void)615 static void txtCloseAll(void)
616 {
617 	struct cpitextmoderegstruct *mode;
618 	for (mode=cpiTextDefModes; mode; mode=mode->nextdef)
619 		if (mode->Event)
620 			mode->Event(cpievDoneAll);
621 	cpiTextDefModes=0;
622 }
623 
txtOpenMode(void)624 static int txtOpenMode(void)
625 {
626 	struct cpitextmoderegstruct *mode;
627 
628 	modeactive=1;
629 	cpiTextActModes=0;
630 	for (mode=cpiTextModes; mode; mode=mode->next)
631 	{
632 		if (mode->Event&&!mode->Event(cpievOpen))
633 			continue;
634 		mode->nextact=cpiTextActModes;
635 		cpiTextActModes=mode;
636 	}
637 	cpiSetFocus(cpiFocusHandle);
638 
639 	return 1;
640 }
641 
txtCloseMode(void)642 static void txtCloseMode(void)
643 {
644 	struct cpitextmoderegstruct *mode;
645 
646 	cpiSetFocus(0);
647 	for (mode=cpiTextActModes; mode; mode=mode->nextact)
648 		if (mode->Event)
649 			mode->Event(cpievClose);
650 	cpiTextActModes=0;
651 	modeactive=0;
652 }
653 
txtEvent(int ev)654 static int txtEvent(int ev)
655 {
656 	switch (ev)
657 	{
658 		case cpievOpen:
659 			return txtOpenMode();
660 		case cpievClose:
661 			txtCloseMode();
662 			return 1;
663 		case cpievInit:
664 			return txtInit();
665 		case cpievDone:
666 			txtClose();
667 			return 1;
668 		case cpievInitAll:
669 			return txtInitAll();
670 		case cpievDoneAll:
671 			txtCloseAll();
672 			return 1;
673 	}
674 	return 1;
675 }
676 
677 struct cpimoderegstruct cpiModeText = {"text", txtSetMode, txtDraw, txtIProcessKey, txtAProcessKey, txtEvent CPIMODEREGSTRUCT_TAIL};
678