|
|
1.1 root 1: /* uifc32.c */
2:
3: /* Curses implementation of UIFC (user interface) library based on uifc.c */
4:
5: /* $Id: uifc32.c,v 1.107 2004/12/20 20:59:16 deuce Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This library is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU Lesser General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU Lesser General Public License for more details: lgpl.txt or *
18: * http://www.fsf.org/copyleft/lesser.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #ifdef __unix__
39: #include <stdio.h>
40: #include <unistd.h>
41: #ifdef __QNX__
42: #include <strings.h>
43: #endif
44: #define mswait(x) delay(x)
45: #elif defined(_WIN32)
46: #include <share.h>
47: #include <windows.h>
48: #define mswait(x) Sleep(x)
49: #endif
50:
51: #include "ciolib.h"
52: #include "keys.h"
53: #include "uifc.h"
54: #define MAX_GETSTR 5120
55: /* Bottom line elements */
56: #define BL_INS (1<<0) /* INS key */
57: #define BL_DEL (1<<1) /* DEL key */
58: #define BL_GET (1<<2) /* Get key */
59: #define BL_PUT (1<<3) /* Put key */
60:
61: #define BLINK 128
62:
63: static char hclr,lclr,bclr,cclr,lbclr;
64: static int cursor;
65: static char* helpfile=0;
66: static uint helpline=0;
67: static size_t blk_scrn_len;
68: static char* blk_scrn;
69: static uchar* tmp_buffer;
70: static uchar* tmp_buffer2;
71: static win_t sav[MAX_BUFS];
72: static uifcapi_t* api;
73:
74: /* Prototypes */
75: static int uprintf(int x, int y, unsigned char attr, char *fmt,...);
76: static void bottomline(int line);
77: static char *utimestr(time_t *intime);
78: static void help(void);
79: static int ugetstr(int left, int top, int width, char *outstr, int max, long mode, int *lastkey);
80: static void timedisplay(void);
81:
82: /* API routines */
83: static void uifcbail(void);
84: static int uscrn(char *str);
85: static int ulist(int mode, int left, int top, int width, int *dflt, int *bar
86: ,char *title, char **option);
87: static int uinput(int imode, int left, int top, char *prompt, char *str
88: ,int len ,int kmode);
89: static void umsg(char *str);
90: static void upop(char *str);
91: static void sethelp(int line, char* file);
92: static void showbuf(int mode, int left, int top, int width, int height, char *title
93: , char *hbuf, int *curp, int *barp);
94:
95: /* Dynamic menu support */
96: static int *last_menu_cur=NULL;
97: static int *last_menu_bar=NULL;
98: static int save_menu_cur=-1;
99: static int save_menu_bar=-1;
100:
101: static void reset_dynamic(void) {
102: last_menu_cur=NULL;
103: last_menu_bar=NULL;
104: save_menu_cur=-1;
105: save_menu_bar=-1;
106: }
107:
108: /****************************************************************************/
109: /* Initialization function, see uifc.h for details. */
110: /* Returns 0 on success. */
111: /****************************************************************************/
112:
113: void uifc_mouse_enable(void)
114: {
115: ciomouse_setevents(1<<CIOLIB_BUTTON_1_CLICK|1<<CIOLIB_BUTTON_3_CLICK);
116: showmouse();
117: }
118:
119: void uifc_mouse_disable(void)
120: {
121: ciomouse_setevents(0);
122: hidemouse();
123: }
124:
125: int kbwait(void) {
126: int timeout=0;
127: while(timeout++<50) {
128: if(kbhit())
129: return(TRUE);
130: mswait(1);
131: }
132: return(FALSE);
133: }
134:
135: int inkey(void)
136: {
137: int c;
138:
139: c=getch();
140: if(!c || c==0xff)
141: c|=(getch()<<8);
142: return(c);
143: }
144:
145: int uifcini32(uifcapi_t* uifcapi)
146: {
147: int i;
148: struct text_info txtinfo;
149:
150: if(uifcapi==NULL || uifcapi->size!=sizeof(uifcapi_t))
151: return(-1);
152:
153: api=uifcapi;
154:
155: /* install function handlers */
156: api->bail=uifcbail;
157: api->scrn=uscrn;
158: api->msg=umsg;
159: api->pop=upop;
160: api->list=ulist;
161: api->input=uinput;
162: api->sethelp=sethelp;
163: api->showhelp=help;
164: api->showbuf=showbuf;
165: api->timedisplay=timedisplay;
166: api->getstrxy=ugetstr;
167:
168: /* A esc_delay of less than 10 is stupid... silently override */
169: if(api->esc_delay < 10)
170: api->esc_delay=25;
171:
172: #ifdef NCURSES_VERSION_MAJOR
173: if(cio_api.mode==CIOLIB_MODE_CURSES) {
174: ESCDELAY=api->esc_delay;
175: #endif
176:
177: if(api->scrn_len!=0) {
178: switch(api->scrn_len) {
179: case 14:
180: textmode(C80X14);
181: break;
182: case 21:
183: textmode(C80X21);
184: break;
185: case 25:
186: textmode(C80);
187: break;
188: case 28:
189: textmode(C80X28);
190: break;
191: case 43:
192: textmode(C80X43);
193: break;
194: case 50:
195: textmode(C80X50);
196: break;
197: case 60:
198: textmode(C80X60);
199: break;
200: default:
201: textmode(C4350);
202: break;
203: }
204: }
205:
206: clrscr();
207:
208: gettextinfo(&txtinfo);
209: /* unsupported mode? */
210: if(txtinfo.screenheight<MIN_LINES
211: /* || txtinfo.screenheight>MAX_LINES */
212: || txtinfo.screenwidth<40) {
213: textmode(C80); /* set mode to 80x25*/
214: gettextinfo(&txtinfo);
215: }
216:
217:
218: api->scrn_len=txtinfo.screenheight;
219: if(api->scrn_len<MIN_LINES) {
220: cprintf("\7UIFC: Screen length (%u) must be %d lines or greater\r\n"
221: ,api->scrn_len,MIN_LINES);
222: return(-2);
223: }
224: api->scrn_len--; /* account for status line */
225:
226: if(txtinfo.screenwidth<40) {
227: cprintf("\7UIFC: Screen width (%u) must be at least 40 characters\r\n"
228: ,txtinfo.screenwidth);
229: return(-3);
230: }
231: api->scrn_width=txtinfo.screenwidth;
232:
233: if(!(api->mode&UIFC_COLOR)
234: && (api->mode&UIFC_MONO
235: || txtinfo.currmode==MONO || txtinfo.currmode==BW40 || txtinfo.currmode==BW80
236: || txtinfo.currmode==MONO14 || txtinfo.currmode==BW40X14 || txtinfo.currmode==BW80X14
237: || txtinfo.currmode==MONO21 || txtinfo.currmode==BW40X21 || txtinfo.currmode==BW80X21
238: || txtinfo.currmode==MONO28 || txtinfo.currmode==BW40X28 || txtinfo.currmode==BW80X28
239: || txtinfo.currmode==MONO43 || txtinfo.currmode==BW40X43 || txtinfo.currmode==BW80X43
240: || txtinfo.currmode==MONO50 || txtinfo.currmode==BW40X50 || txtinfo.currmode==BW80X50
241: || txtinfo.currmode==MONO60 || txtinfo.currmode==BW40X60 || txtinfo.currmode==BW80X60))
242: {
243: bclr=BLACK;
244: hclr=WHITE;
245: lclr=LIGHTGRAY;
246: cclr=LIGHTGRAY;
247: lbclr=BLACK|(LIGHTGRAY<<4); /* lightbar color */
248: } else {
249: bclr=BLUE;
250: hclr=YELLOW;
251: lclr=WHITE;
252: cclr=CYAN;
253: lbclr=BLUE|(LIGHTGRAY<<4); /* lightbar color */
254: }
255:
256: blk_scrn_len=api->scrn_width*api->scrn_len*2;
257: if((blk_scrn=(char *)MALLOC(blk_scrn_len))==NULL) {
258: cprintf("UIFC line %d: error allocating %u bytes."
259: ,__LINE__,blk_scrn_len);
260: return(-1);
261: }
262: if((tmp_buffer=(uchar *)MALLOC(blk_scrn_len))==NULL) {
263: cprintf("UIFC line %d: error allocating %u bytes."
264: ,__LINE__,blk_scrn_len);
265: return(-1);
266: }
267: if((tmp_buffer2=(uchar *)MALLOC(blk_scrn_len))==NULL) {
268: cprintf("UIFC line %d: error allocating %u bytes."
269: ,__LINE__,blk_scrn_len);
270: return(-1);
271: }
272: for(i=0;i<blk_scrn_len;i+=2) {
273: blk_scrn[i]='�';
274: blk_scrn[i+1]=cclr|(bclr<<4);
275: }
276:
277: cursor=_NOCURSOR;
278: _setcursortype(cursor);
279:
280: if(cio_api.mouse)
281: api->mode|=UIFC_MOUSE;
282:
283: return(0);
284: }
285:
286: static int uifc_getmouse(struct mouse_event *mevent)
287: {
288: mevent->startx=0;
289: mevent->starty=0;
290: mevent->event=0;
291: if(api->mode&UIFC_MOUSE) {
292: getmouse(mevent);
293: if(mevent->event==CIOLIB_BUTTON_3_CLICK)
294: return(ESC);
295: if(mevent->starty==api->buttony) {
296: if(mevent->startx>=api->exitstart
297: && mevent->startx<=api->exitend
298: && mevent->event==CIOLIB_BUTTON_1_CLICK) {
299: return(ESC);
300: }
301: if(mevent->startx>=api->helpstart
302: && mevent->startx<=api->helpend
303: && mevent->event==CIOLIB_BUTTON_1_CLICK) {
304: return(CIO_KEY_F(1));
305: }
306: }
307: return(0);
308: }
309: return(-1);
310: }
311:
312: void uifcbail(void)
313: {
314: _setcursortype(_NORMALCURSOR);
315: textattr(LIGHTGRAY);
316: uifc_mouse_disable();
317: clrscr();
318: FREE(blk_scrn);
319: FREE(tmp_buffer);
320: FREE(tmp_buffer2);
321: }
322:
323: /****************************************************************************/
324: /* Clear screen, fill with background attribute, display application title. */
325: /* Returns 0 on success. */
326: /****************************************************************************/
327: int uscrn(char *str)
328: {
329: textattr(bclr|(cclr<<4));
330: gotoxy(1,1);
331: clreol();
332: gotoxy(3,1);
333: cputs(str);
334: if(!puttext(1,2,api->scrn_width,api->scrn_len,blk_scrn))
335: return(-1);
336: gotoxy(1,api->scrn_len+1);
337: clreol();
338: reset_dynamic();
339: settitle(str);
340: return(0);
341: }
342:
343: /****************************************************************************/
344: /****************************************************************************/
345: static void scroll_text(int x1, int y1, int x2, int y2, int down)
346: {
347: gettext(x1,y1,x2,y2,tmp_buffer2);
348: if(down)
349: puttext(x1,y1+1,x2,y2,tmp_buffer2);
350: else
351: puttext(x1,y1,x2,y2-1,tmp_buffer2+(((x2-x1)+1)*2));
352: }
353:
354: /****************************************************************************/
355: /* Updates time in upper left corner of screen with current time in ASCII/ */
356: /* Unix format */
357: /****************************************************************************/
358: static void timedisplay()
359: {
360: static time_t savetime;
361: time_t now;
362:
363: now=time(NULL);
364: if(difftime(now,savetime)>=60) {
365: uprintf(api->scrn_width-25,1,bclr|(cclr<<4),utimestr(&now));
366: savetime=now;
367: }
368: }
369:
370: /****************************************************************************/
371: /* Truncates white-space chars off end of 'str' */
372: /****************************************************************************/
373: static void truncsp(char *str)
374: {
375: uint c;
376:
377: c=strlen(str);
378: while(c && (uchar)str[c-1]<=' ') c--;
379: if(str[c]!=0) /* don't write to string constants */
380: str[c]=0;
381: }
382:
383: /****************************************************************************/
384: /* General menu function, see uifc.h for details. */
385: /****************************************************************************/
386: int ulist(int mode, int left, int top, int width, int *cur, int *bar
387: , char *initial_title, char **option)
388: {
389: uchar line[256],shade[256],*ptr
390: ,search[MAX_OPLN],bline=0,*win;
391: int height,y;
392: int i,j,opts=0,s=0; /* s=search index into options */
393: int is_redraw=0;
394: uint s_top=SCRN_TOP;
395: uint s_left=SCRN_LEFT;
396: uint s_right=SCRN_RIGHT;
397: uint s_bottom=api->scrn_len-3;
398: uint title_len;
399: struct mouse_event mevnt;
400: char *title;
401: int a,b,c,longopt;
402:
403: if((title=(char *)MALLOC(strlen(initial_title)+1))==NULL) {
404: cprintf("UIFC line %d: error allocating %u bytes."
405: ,__LINE__,strlen(title)+1);
406: return(-1);
407: }
408: strcpy(title,initial_title);
409: uifc_mouse_disable();
410:
411: title_len=strlen(title);
412:
413: if(mode&WIN_FAT) {
414: s_top=1;
415: s_left=2;
416: s_right=api->scrn_width-3; /* Leave space for the shadow */
417: s_bottom=api->scrn_len-1; /* Leave one for the shadow */
418: }
419: if(mode&WIN_SAV && api->savnum>=MAX_BUFS-1)
420: putch(7);
421: if(mode&WIN_INS) bline|=BL_INS;
422: if(mode&WIN_DEL) bline|=BL_DEL;
423: if(mode&WIN_GET) bline|=BL_GET;
424: if(mode&WIN_PUT) bline|=BL_PUT;
425: bottomline(bline);
426: while(opts<MAX_OPTS)
427: if(option[opts]==NULL || option[opts][0]==0)
428: break;
429: else opts++;
430: if(mode&WIN_XTR && opts<MAX_OPTS)
431: opts++;
432: height=opts+4;
433: if(top+height>s_bottom)
434: height=(s_bottom)-top;
435: if(!width || width<title_len+6) {
436: width=title_len+6;
437: for(i=0;i<opts;i++) {
438: truncsp(option[i]);
439: if((j=strlen(option[i])+5)>width)
440: width=j;
441: }
442: }
443: if(width>(s_right+1)-s_left) {
444: width=(s_right+1)-s_left;
445: if(title_len>(width-4)) {
446: *(title+width-7)='.';
447: *(title+width-6)='.';
448: *(title+width-5)='.';
449: *(title+width-4)=0;
450: title_len=strlen(title);
451: }
452: }
453: if(mode&WIN_L2R)
454: left=(s_right-s_left-width+1)/2;
455: else if(mode&WIN_RHT)
456: left=s_right-(width+4+left);
457: if(mode&WIN_T2B)
458: top=(api->scrn_len-height+1)/2-2;
459: else if(mode&WIN_BOT)
460: top=s_bottom-height-top;
461: if(left<0)
462: left=0;
463: if(top<0)
464: top=0;
465:
466: /* Dynamic Menus */
467: if(mode&WIN_DYN
468: && cur != NULL
469: && bar != NULL
470: && last_menu_cur==cur
471: && last_menu_bar==bar
472: && save_menu_cur==*cur
473: && save_menu_bar==*bar)
474: is_redraw=1;
475: if(mode&WIN_DYN && mode&WIN_REDRAW)
476: is_redraw=1;
477: if(mode&WIN_DYN && mode&WIN_NODRAW)
478: is_redraw=0;
479:
480: if(!is_redraw) {
481: if(mode&WIN_SAV && api->savdepth==api->savnum) {
482: if((sav[api->savnum].buf=(char *)MALLOC((width+3)*(height+2)*2))==NULL) {
483: cprintf("UIFC line %d: error allocating %u bytes."
484: ,__LINE__,(width+3)*(height+2)*2);
485: free(title);
486: return(-1);
487: }
488: gettext(s_left+left,s_top+top,s_left+left+width+1
489: ,s_top+top+height,sav[api->savnum].buf);
490: sav[api->savnum].left=s_left+left;
491: sav[api->savnum].top=s_top+top;
492: sav[api->savnum].right=s_left+left+width+1;
493: sav[api->savnum].bot=s_top+top+height;
494: api->savdepth++;
495: }
496: else if(mode&WIN_SAV
497: && (sav[api->savnum].left!=s_left+left
498: || sav[api->savnum].top!=s_top+top
499: || sav[api->savnum].right!=s_left+left+width+1
500: || sav[api->savnum].bot!=s_top+top+height)) { /* dimensions have changed */
501: puttext(sav[api->savnum].left,sav[api->savnum].top,sav[api->savnum].right,sav[api->savnum].bot
502: ,sav[api->savnum].buf); /* put original window back */
503: FREE(sav[api->savnum].buf);
504: if((sav[api->savnum].buf=(char *)MALLOC((width+3)*(height+2)*2))==NULL) {
505: cprintf("UIFC line %d: error allocating %u bytes."
506: ,__LINE__,(width+3)*(height+2)*2);
507: free(title);
508: return(-1);
509: }
510: gettext(s_left+left,s_top+top,s_left+left+width+1
511: ,s_top+top+height,sav[api->savnum].buf); /* save again */
512: sav[api->savnum].left=s_left+left;
513: sav[api->savnum].top=s_top+top;
514: sav[api->savnum].right=s_left+left+width+1;
515: sav[api->savnum].bot=s_top+top+height;
516: }
517: }
518:
519: if(!is_redraw) {
520: if(mode&WIN_ORG) { /* Clear around menu */
521: if(top)
522: puttext(1,2,api->scrn_width,s_top+top-1,blk_scrn);
523: if(s_top+height+top<=api->scrn_len)
524: puttext(1,s_top+height+top,api->scrn_width,api->scrn_len,blk_scrn);
525: if(left)
526: puttext(1,s_top+top,s_left+left-1,s_top+height+top
527: ,blk_scrn);
528: if(s_left+left+width<=s_right)
529: puttext(s_left+left+width,s_top+top,/* s_right+2 */api->scrn_width
530: ,s_top+height+top,blk_scrn);
531: }
532: ptr=tmp_buffer;
533: *(ptr++)='�';
534: *(ptr++)=hclr|(bclr<<4);
535:
536: if(api->mode&UIFC_MOUSE) {
537: *(ptr++)='[';
538: *(ptr++)=hclr|(bclr<<4);
539: /* *(ptr++)='�'; */
540: *(ptr++)=0xfe;
541: *(ptr++)=lclr|(bclr<<4);
542: *(ptr++)=']';
543: *(ptr++)=hclr|(bclr<<4);
544: *(ptr++)='[';
545: *(ptr++)=hclr|(bclr<<4);
546: *(ptr++)='?';
547: *(ptr++)=lclr|(bclr<<4);
548: *(ptr++)=']';
549: *(ptr++)=hclr|(bclr<<4);
550: i=6;
551: api->buttony=s_top+top;
552: api->exitstart=s_left+left+1;
553: api->exitend=s_left+left+3;
554: api->helpstart=s_left+left+4;
555: api->helpend=s_left+left+6;
556: }
557: else
558: i=0;
559:
560: for(;i<width-2;i++) {
561: *(ptr++)='�';
562: *(ptr++)=hclr|(bclr<<4);
563: }
564: *(ptr++)='�';
565: *(ptr++)=hclr|(bclr<<4);
566: *(ptr++)='�';
567: *(ptr++)=hclr|(bclr<<4);
568: a=title_len;
569: b=(width-a-1)/2;
570: for(i=0;i<b;i++) {
571: *(ptr++)=' ';
572: *(ptr++)=hclr|(bclr<<4);
573: }
574: for(i=0;i<a;i++) {
575: *(ptr++)=title[i];
576: *(ptr++)=hclr|(bclr<<4);
577: }
578: for(i=0;i<width-(a+b)-2;i++) {
579: *(ptr++)=' ';
580: *(ptr++)=hclr|(bclr<<4);
581: }
582: *(ptr++)='�';
583: *(ptr++)=hclr|(bclr<<4);
584: *(ptr++)='�';
585: *(ptr++)=hclr|(bclr<<4);
586: for(i=0;i<width-2;i++) {
587: *(ptr++)='�';
588: *(ptr++)=hclr|(bclr<<4);
589: }
590: *(ptr++)='�';
591: *(ptr++)=hclr|(bclr<<4);
592:
593: if((*cur)>=opts)
594: (*cur)=opts-1; /* returned after scrolled */
595:
596: if(!bar) {
597: if((*cur)>height-5)
598: (*cur)=height-5;
599: i=0;
600: }
601: else {
602: if((*bar)>=opts)
603: (*bar)=opts-1;
604: if((*bar)>height-5)
605: (*bar)=height-5;
606: if((*cur)==opts-1)
607: (*bar)=height-5;
608: if((*bar)<0)
609: (*bar)=0;
610: if((*cur)<(*bar))
611: (*cur)=(*bar);
612: i=(*cur)-(*bar);
613: if(i+(height-5)>=opts) {
614: i=opts-(height-4);
615: (*cur)=i+(*bar);
616: }
617: }
618: if((*cur)<0)
619: (*cur)=0;
620:
621: j=0;
622: if(i<0) i=0;
623: longopt=0;
624: while(j<height-4 && i<opts) {
625: *(ptr++)='�';
626: *(ptr++)=hclr|(bclr<<4);
627: *(ptr++)=' ';
628: *(ptr++)=hclr|(bclr<<4);
629: *(ptr++)='�';
630: *(ptr++)=lclr|(bclr<<4);
631: if(i==(*cur))
632: a=lbclr;
633: else
634: a=lclr|(bclr<<4);
635: b=strlen(option[i]);
636: if(b>longopt)
637: longopt=b;
638: if(b+4>width)
639: b=width-4;
640: for(c=0;c<b;c++) {
641: *(ptr++)=option[i][c];
642: *(ptr++)=a;
643: }
644: while(c<width-4) {
645: *(ptr++)=' ';
646: *(ptr++)=a;
647: c++;
648: }
649: *(ptr++)='�';
650: *(ptr++)=hclr|(bclr<<4);
651: i++;
652: j++;
653: }
654: *(ptr++)='�';
655: *(ptr++)=hclr|(bclr<<4);
656: for(i=0;i<width-2;i++) {
657: *(ptr++)='�';
658: *(ptr++)=hclr|(bclr<<4);
659: }
660: *(ptr++)='�';
661: *(ptr)=hclr|(bclr<<4); /* Not incremented to shut ot BCC */
662: puttext(s_left+left,s_top+top,s_left+left+width-1
663: ,s_top+top+height-1,tmp_buffer);
664: if(bar)
665: y=top+3+(*bar);
666: else
667: y=top+3+(*cur);
668: if(opts+4>height && ((!bar && (*cur)!=opts-1)
669: || (bar && ((*cur)-(*bar))+(height-4)<opts))) {
670: gotoxy(s_left+left+1,s_top+top+height-2);
671: textattr(lclr|(bclr<<4));
672: putch(31); /* put down arrow */
673: textattr(hclr|(bclr<<4));
674: }
675:
676: if(bar && (*bar)!=(*cur)) {
677: gotoxy(s_left+left+1,s_top+top+3);
678: textattr(lclr|(bclr<<4));
679: putch(30); /* put the up arrow */
680: textattr(hclr|(bclr<<4));
681: }
682:
683: if(bclr==BLUE) {
684: gettext(s_left+left+width,s_top+top+1,s_left+left+width+1
685: ,s_top+top+height-1,shade);
686: for(i=1;i<height*4;i+=2)
687: shade[i]=DARKGRAY;
688: puttext(s_left+left+width,s_top+top+1,s_left+left+width+1
689: ,s_top+top+height-1,shade);
690: gettext(s_left+left+2,s_top+top+height,s_left+left+width+1
691: ,s_top+top+height,shade);
692: for(i=1;i<width*2;i+=2)
693: shade[i]=DARKGRAY;
694: puttext(s_left+left+2,s_top+top+height,s_left+left+width+1
695: ,s_top+top+height,shade);
696: }
697: }
698: else { /* Is a redraw */
699: i=(*cur)-(*bar);
700: j=2;
701:
702: longopt=0;
703: while(j<height-2 && i<opts) {
704: ptr=tmp_buffer;
705: if(i==(*cur))
706: a=lbclr;
707: else
708: a=lclr|(bclr<<4);
709: b=strlen(option[i]);
710: if(b>longopt)
711: longopt=b;
712: if(b+4>width)
713: b=width-4;
714: for(c=0;c<b;c++) {
715: *(ptr++)=option[i][c];
716: *(ptr++)=a;
717: }
718: while(c<width-4) {
719: *(ptr++)=' ';
720: *(ptr++)=a;
721: c++;
722: }
723: i++;
724: j++;
725: puttext(s_left+left+3,s_top+top+j,s_left+left+width-2
726: ,s_top+top+j,tmp_buffer);
727: }
728: if(bar)
729: y=top+3+(*bar);
730: else
731: y=top+3+(*cur);
732: }
733: free(title);
734:
735: last_menu_cur=cur;
736: last_menu_bar=bar;
737: if(mode&WIN_IMM)
738: return(-2);
739:
740: uifc_mouse_enable();
741:
742: while(1) {
743: #if 0 /* debug */
744: gotoxy(30,1);
745: cprintf("y=%2d h=%2d c=%2d b=%2d s=%2d o=%2d"
746: ,y,height,*cur,bar ? *bar :0xff,api->savdepth,opts);
747: #endif
748: timedisplay();
749: i=0;
750: if(kbwait()) {
751: i=inkey();
752: if(i==CIO_KEY_MOUSE) {
753: if((i=uifc_getmouse(&mevnt))==0) {
754: /* Clicked in menu */
755: if(mevnt.startx>=s_left+left+3
756: && mevnt.startx<=s_left+left+width-2
757: && mevnt.starty>=s_top+top+3
758: && mevnt.starty<=(s_top+top+height)-2
759: && mevnt.event==CIOLIB_BUTTON_1_CLICK) {
760:
761: (*cur)=(mevnt.starty)-(s_top+top+3);
762: if(bar)
763: (*bar)=(*cur);
764: y=top+3+((mevnt.starty)-(s_top+top+3));
765:
766: if(!opts)
767: continue;
768:
769: if(mode&WIN_ACT) {
770: uifc_mouse_disable();
771: if((win=(char *)MALLOC((width+3)*(height+2)*2))==NULL) {
772: cprintf("UIFC line %d: error allocating %u bytes."
773: ,__LINE__,(width+3)*(height+2)*2);
774: return(-1);
775: }
776: gettext(s_left+left,s_top+top,s_left
777: +left+width-1,s_top+top+height-1,win);
778: for(i=1;i<(width*height*2);i+=2)
779: win[i]=lclr|(cclr<<4);
780: j=(((y-top)*width)*2)+7+((width-4)*2);
781: for(i=(((y-top)*width)*2)+7;i<j;i+=2)
782: win[i]=hclr|(cclr<<4);
783:
784: puttext(s_left+left,s_top+top,s_left
785: +left+width-1,s_top+top+height-1,win);
786: free(win);
787: uifc_mouse_enable();
788: }
789: else if(mode&WIN_SAV) {
790: uifc_mouse_disable();
791: puttext(sav[api->savnum].left,sav[api->savnum].top
792: ,sav[api->savnum].right,sav[api->savnum].bot
793: ,sav[api->savnum].buf);
794: uifc_mouse_enable();
795: free(sav[api->savnum].buf);
796: api->savdepth--;
797: }
798: if(mode&WIN_XTR && (*cur)==opts-1)
799: return(MSK_INS|*cur);
800: return(*cur);
801: }
802: /* Clicked Scroll Up */
803: if(mevnt.startx==s_left+left+1
804: && mevnt.starty==s_top+top+3
805: && mevnt.event==CIOLIB_BUTTON_1_CLICK) {
806: i=CIO_KEY_PPAGE;
807: }
808: /* Clicked Scroll Down */
809: if(mevnt.startx==s_left+left+1
810: && mevnt.starty==(s_top+top+height)-2
811: && mevnt.event==CIOLIB_BUTTON_1_CLICK) {
812: i=CIO_KEY_NPAGE;
813: }
814: /* Clicked Outside of Window */
815: if(mevnt.startx<s_left+left
816: || mevnt.startx>s_left+left+width-1
817: || mevnt.starty<s_top+top
818: || mevnt.starty>s_top+top+height-1)
819: i=ESC;
820: }
821: }
822: /* For compatibility with terminals lacking special keys */
823: switch(i) {
824: case '\b':
825: i=ESC;
826: break;
827: case '+':
828: i=CIO_KEY_IC; /* insert */
829: break;
830: case '-':
831: case DEL:
832: i=CIO_KEY_DC; /* delete */
833: break;
834: case CTRL_B:
835: i=CIO_KEY_HOME;
836: break;
837: case CTRL_E:
838: i=CIO_KEY_END;
839: break;
840: case CTRL_U:
841: i=CIO_KEY_PPAGE;
842: break;
843: case CTRL_D:
844: i=CIO_KEY_NPAGE;
845: break;
846: case CTRL_Z:
847: i=CIO_KEY_F(1); /* help */
848: break;
849: case CTRL_C:
850: i=CIO_KEY_F(5); /* copy */
851: break;
852: case CTRL_V:
853: i=CIO_KEY_F(6); /* paste */
854: break;
855:
856: }
857: if(i>255) {
858: s=0;
859: switch(i) {
860: /* ToDo extended keys */
861: case CIO_KEY_HOME: /* home */
862: if(!opts)
863: break;
864: if(opts+4>height) {
865: gotoxy(s_left+left+1,s_top+top+3);
866: textattr(lclr|(bclr<<4));
867: putch(' '); /* Delete the up arrow */
868: gotoxy(s_left+left+1,s_top+top+height-2);
869: putch(31); /* put the down arrow */
870: uprintf(s_left+left+3,s_top+top+3
871: ,lbclr
872: ,"%-*.*s",width-4,width-4,option[0]);
873: for(i=1;i<height-4;i++) /* re-display options */
874: uprintf(s_left+left+3,s_top+top+3+i
875: ,lclr|(bclr<<4)
876: ,"%-*.*s",width-4,width-4,option[i]);
877: (*cur)=0;
878: if(bar)
879: (*bar)=0;
880: y=top+3;
881: break;
882: }
883: gettext(s_left+3+left,s_top+y
884: ,s_left+left+width-2,s_top+y,line);
885: for(i=1;i<width*2;i+=2)
886: line[i]=lclr|(bclr<<4);
887: puttext(s_left+3+left,s_top+y
888: ,s_left+left+width-2,s_top+y,line);
889: (*cur)=0;
890: if(bar)
891: (*bar)=0;
892: y=top+3;
893: gettext(s_left+3+left,s_top+y
894: ,s_left+left+width-2,s_top+y,line);
895: for(i=1;i<width*2;i+=2)
896: line[i]=lbclr;
897: puttext(s_left+3+left,s_top+y
898: ,s_left+left+width-2,s_top+y,line);
899: break;
900: case CIO_KEY_UP: /* up arrow */
901: if(!opts)
902: break;
903: if(!(*cur) && opts+4>height) {
904: gotoxy(s_left+left+1,s_top+top+3); /* like end */
905: textattr(lclr|(bclr<<4));
906: putch(30); /* put the up arrow */
907: gotoxy(s_left+left+1,s_top+top+height-2);
908: putch(' '); /* delete the down arrow */
909: for(i=(opts+4)-height,j=0;i<opts;i++,j++)
910: uprintf(s_left+left+3,s_top+top+3+j
911: ,i==opts-1 ? lbclr
912: : lclr|(bclr<<4)
913: ,"%-*.*s",width-4,width-4,option[i]);
914: (*cur)=opts-1;
915: if(bar)
916: (*bar)=height-5;
917: y=top+height-2;
918: break;
919: }
920: gettext(s_left+3+left,s_top+y
921: ,s_left+left+width-2,s_top+y,line);
922: for(i=1;i<width*2;i+=2)
923: line[i]=lclr|(bclr<<4);
924: puttext(s_left+3+left,s_top+y
925: ,s_left+left+width-2,s_top+y,line);
926: if(!(*cur)) {
927: y=top+height-2;
928: (*cur)=opts-1;
929: if(bar)
930: (*bar)=height-5;
931: }
932: else {
933: (*cur)--;
934: y--;
935: if(bar && *bar)
936: (*bar)--;
937: }
938: if(y<top+3) { /* scroll */
939: if(!(*cur)) {
940: gotoxy(s_left+left+1,s_top+top+3);
941: textattr(lclr|(bclr<<4));
942: putch(' '); /* delete the up arrow */
943: }
944: if((*cur)+height-4==opts-1) {
945: gotoxy(s_left+left+1,s_top+top+height-2);
946: textattr(lclr|(bclr<<4));
947: putch(31); /* put the dn arrow */
948: }
949: y++;
950: scroll_text(s_left+left+2,s_top+top+3
951: ,s_left+left+width-3,s_top+top+height-2,1);
952: uprintf(s_left+left+3,s_top+top+3
953: ,lbclr
954: ,"%-*.*s",width-4,width-4,option[*cur]);
955: }
956: else {
957: gettext(s_left+3+left,s_top+y
958: ,s_left+left+width-2,s_top+y,line);
959: for(i=1;i<width*2;i+=2)
960: line[i]=lbclr;
961: puttext(s_left+3+left,s_top+y
962: ,s_left+left+width-2,s_top+y,line);
963: }
964: break;
965: case CIO_KEY_PPAGE: /* PgUp */
966: if(!opts)
967: break;
968: *cur -= (height-5);
969: if(*cur<0)
970: *cur = 0;
971: if(bar)
972: *bar=0;
973: y=s_top+top;
974: gotoxy(s_left+left+1,s_top+top+3);
975: textattr(lclr|(bclr<<4));
976: if(*cur && opts>height-3) /* Scroll mode */
977: putch(30); /* put the up arrow */
978: else
979: putch(' '); /* delete the up arrow */
980: gotoxy(s_left+left+1,s_top+top+height-2);
981: if(opts > height-3 && *cur + height - 4 < opts)
982: putch(31); /* put the down arrow */
983: else
984: putch(' '); /* delete the down arrow */
985: for(i=*cur,j=0;i<=*cur-5+height;i++,j++)
986: uprintf(s_left+left+3,s_top+top+3+j
987: ,i==*cur ? lbclr
988: : lclr|(bclr<<4)
989: ,"%-*.*s",width-4,width-4,option[i]);
990: break;
991: case CIO_KEY_NPAGE: /* PgDn */
992: if(!opts)
993: break;
994: *cur += (height-5);
995: if(*cur>opts-1)
996: *cur = opts-1;
997: if(bar)
998: *bar = height-5;
999: y=height-5+s_top+top;
1000: gotoxy(s_left+left+1,s_top+top+3);
1001: textattr(lclr|(bclr<<4));
1002: if(*cur>height-5) /* Scroll mode */
1003: putch(30); /* put the up arrow */
1004: else
1005: putch(' '); /* delete the up arrow */
1006: gotoxy(s_left+left+1,s_top+top+height-2);
1007: if(*cur < opts-1)
1008: putch(31); /* put the down arrow */
1009: else
1010: putch(' '); /* delete the down arrow */
1011: for(i=*cur+5-height,j=0;i<=*cur;i++,j++)
1012: uprintf(s_left+left+3,s_top+top+3+j
1013: ,i==*cur ? lbclr
1014: : lclr|(bclr<<4)
1015: ,"%-*.*s",width-4,width-4,option[i]);
1016: break;
1017: case CIO_KEY_END: /* end */
1018: if(!opts)
1019: break;
1020: if(opts+4>height) { /* Scroll mode */
1021: gotoxy(s_left+left+1,s_top+top+3);
1022: textattr(lclr|(bclr<<4));
1023: putch(30); /* put the up arrow */
1024: gotoxy(s_left+left+1,s_top+top+height-2);
1025: putch(' '); /* delete the down arrow */
1026: for(i=(opts+4)-height,j=0;i<opts;i++,j++)
1027: uprintf(s_left+left+3,s_top+top+3+j
1028: ,i==opts-1 ? lbclr
1029: : lclr|(bclr<<4)
1030: ,"%-*.*s",width-4,width-4,option[i]);
1031: (*cur)=opts-1;
1032: y=top+height-2;
1033: if(bar)
1034: (*bar)=height-5;
1035: break;
1036: }
1037: gettext(s_left+3+left,s_top+y
1038: ,s_left+left+width-2,s_top+y,line);
1039: for(i=1;i<width*2;i+=2)
1040: line[i]=lclr|(bclr<<4);
1041: puttext(s_left+3+left,s_top+y
1042: ,s_left+left+width-2,s_top+y,line);
1043: (*cur)=opts-1;
1044: y=top+height-2;
1045: if(bar)
1046: (*bar)=height-5;
1047: gettext(s_left+3+left,s_top+y
1048: ,s_left+left+width-2,s_top+y,line);
1049: for(i=1;i<148;i+=2)
1050: line[i]=lbclr;
1051: puttext(s_left+3+left,s_top+y
1052: ,s_left+left+width-2,s_top+y,line);
1053: break;
1054: case CIO_KEY_DOWN: /* dn arrow */
1055: if(!opts)
1056: break;
1057: if((*cur)==opts-1 && opts+4>height) { /* like home */
1058: gotoxy(s_left+left+1,s_top+top+3);
1059: textattr(lclr|(bclr<<4));
1060: putch(' '); /* Delete the up arrow */
1061: gotoxy(s_left+left+1,s_top+top+height-2);
1062: putch(31); /* put the down arrow */
1063: uprintf(s_left+left+3,s_top+top+3
1064: ,lbclr
1065: ,"%-*.*s",width-4,width-4,option[0]);
1066: for(i=1;i<height-4;i++) /* re-display options */
1067: uprintf(s_left+left+3,s_top+top+3+i
1068: ,lclr|(bclr<<4)
1069: ,"%-*.*s",width-4,width-4,option[i]);
1070: (*cur)=0;
1071: y=top+3;
1072: if(bar)
1073: (*bar)=0;
1074: break;
1075: }
1076: gettext(s_left+3+left,s_top+y
1077: ,s_left+left+width-2,s_top+y,line);
1078: for(i=1;i<width*2;i+=2)
1079: line[i]=lclr|(bclr<<4);
1080: puttext(s_left+3+left,s_top+y
1081: ,s_left+left+width-2,s_top+y,line);
1082: if((*cur)==opts-1) {
1083: (*cur)=0;
1084: y=top+3;
1085: if(bar) {
1086: /* gotoxy(1,1); cprintf("bar=%08lX ",bar); */
1087: (*bar)=0;
1088: }
1089: }
1090: else {
1091: (*cur)++;
1092: y++;
1093: if(bar && (*bar)<height-5) {
1094: /* gotoxy(1,1); cprintf("bar=%08lX ",bar); */
1095: (*bar)++;
1096: }
1097: }
1098: if(y==top+height-1) { /* scroll */
1099: if(*cur==opts-1) {
1100: gotoxy(s_left+left+1,s_top+top+height-2);
1101: textattr(lclr|(bclr<<4));
1102: putch(' '); /* delete the down arrow */
1103: }
1104: if((*cur)+4==height) {
1105: gotoxy(s_left+left+1,s_top+top+3);
1106: textattr(lclr|(bclr<<4));
1107: putch(30); /* put the up arrow */
1108: }
1109: y--;
1110: /* gotoxy(1,1); cprintf("\rdebug: %4d ",__LINE__); */
1111: scroll_text(s_left+left+2,s_top+top+3
1112: ,s_left+left+width-3,s_top+top+height-2,0);
1113: /* gotoxy(1,1); cprintf("\rdebug: %4d ",__LINE__); */
1114: uprintf(s_left+left+3,s_top+top+height-2
1115: ,lbclr
1116: ,"%-*.*s",width-4,width-4,option[*cur]);
1117: }
1118: else {
1119: gettext(s_left+3+left,s_top+y
1120: ,s_left+left+width-2,s_top+y
1121: ,line);
1122: for(i=1;i<width*2;i+=2)
1123: line[i]=lbclr;
1124: puttext(s_left+3+left,s_top+y
1125: ,s_left+left+width-2,s_top+y
1126: ,line);
1127: }
1128: break;
1129: case CIO_KEY_F(1): /* F1 */
1130: api->showhelp();
1131: break;
1132: case CIO_KEY_F(5): /* F5 */
1133: if(mode&WIN_GET && !(mode&WIN_XTR && (*cur)==opts-1))
1134: return((*cur)|MSK_GET);
1135: break;
1136: case CIO_KEY_F(6): /* F6 */
1137: if(mode&WIN_PUT && !(mode&WIN_XTR && (*cur)==opts-1))
1138: return((*cur)|MSK_PUT);
1139: break;
1140: case CIO_KEY_IC: /* insert */
1141: if(mode&WIN_INS) {
1142: if(mode&WIN_INSACT) {
1143: gettext(s_left+left,s_top+top,s_left
1144: +left+width-1,s_top+top+height-1,tmp_buffer);
1145: for(i=1;i<(width*height*2);i+=2)
1146: tmp_buffer[i]=lclr|(cclr<<4);
1147: if(opts) {
1148: j=(((y-top)*width)*2)+7+((width-4)*2);
1149: for(i=(((y-top)*width)*2)+7;i<j;i+=2)
1150: tmp_buffer[i]=hclr|(cclr<<4);
1151: }
1152: puttext(s_left+left,s_top+top,s_left
1153: +left+width-1,s_top+top+height-1,tmp_buffer);
1154: }
1155: if(!opts) {
1156: return(MSK_INS);
1157: }
1158: return((*cur)|MSK_INS);
1159: }
1160: break;
1161: case CIO_KEY_DC: /* delete */
1162: if(mode&WIN_XTR && (*cur)==opts-1) /* can't delete */
1163: break; /* extra line */
1164: if(mode&WIN_DEL) {
1165: if(mode&WIN_DELACT) {
1166: gettext(s_left+left,s_top+top,s_left
1167: +left+width-1,s_top+top+height-1,tmp_buffer);
1168: for(i=1;i<(width*height*2);i+=2)
1169: tmp_buffer[i]=lclr|(cclr<<4);
1170: j=(((y-top)*width)*2)+7+((width-4)*2);
1171: for(i=(((y-top)*width)*2)+7;i<j;i+=2)
1172: tmp_buffer[i]=hclr|(cclr<<4);
1173: puttext(s_left+left,s_top+top,s_left
1174: +left+width-1,s_top+top+height-1,tmp_buffer);
1175: }
1176: return((*cur)|MSK_DEL);
1177: }
1178: break;
1179: default:
1180: if(mode&WIN_EXTKEYS)
1181: return(-2-i);
1182: break;
1183: }
1184: }
1185: else {
1186: i&=0xff;
1187: if(isalnum(i) && opts && option[0][0]) {
1188: search[s]=i;
1189: search[s+1]=0;
1190: for(j=(*cur)+1,a=b=0;a<2;j++) { /* a = search count */
1191: if(j==opts) { /* j = option count */
1192: j=-1; /* b = letter count */
1193: continue;
1194: }
1195: if(j==(*cur)) {
1196: b++;
1197: continue;
1198: }
1199: if(b>=longopt) {
1200: b=0;
1201: a++;
1202: }
1203: if(a==1 && !s)
1204: break;
1205: if(strlen(option[j])>b
1206: && ((!a && s && !strnicmp(option[j]+b,search,s+1))
1207: || ((a || !s) && toupper(option[j][b])==toupper(i)))) {
1208: if(a) s=0;
1209: else s++;
1210: if(y+(j-(*cur))+2>height+top) {
1211: (*cur)=j;
1212: gotoxy(s_left+left+1,s_top+top+3);
1213: textattr(lclr|(bclr<<4));
1214: putch(30); /* put the up arrow */
1215: if((*cur)==opts-1) {
1216: gotoxy(s_left+left+1,s_top+top+height-2);
1217: putch(' '); /* delete the down arrow */
1218: }
1219: for(i=((*cur)+5)-height,j=0;i<(*cur)+1;i++,j++)
1220: uprintf(s_left+left+3,s_top+top+3+j
1221: ,i==(*cur) ? lbclr
1222: : lclr|(bclr<<4)
1223: ,"%-*.*s",width-4,width-4,option[i]);
1224: y=top+height-2;
1225: if(bar)
1226: (*bar)=height-5;
1227: break;
1228: }
1229: if(y-((*cur)-j)<top+3) {
1230: (*cur)=j;
1231: gotoxy(s_left+left+1,s_top+top+3);
1232: textattr(lclr|(bclr<<4));
1233: if(!(*cur))
1234: putch(' '); /* Delete the up arrow */
1235: gotoxy(s_left+left+1,s_top+top+height-2);
1236: putch(31); /* put the down arrow */
1237: uprintf(s_left+left+3,s_top+top+3
1238: ,lbclr
1239: ,"%-*.*s",width-4,width-4,option[(*cur)]);
1240: for(i=1;i<height-4;i++) /* re-display options */
1241: uprintf(s_left+left+3,s_top+top+3+i
1242: ,lclr|(bclr<<4)
1243: ,"%-*.*s",width-4,width-4
1244: ,option[(*cur)+i]);
1245: y=top+3;
1246: if(bar)
1247: (*bar)=0;
1248: break;
1249: }
1250: gettext(s_left+3+left,s_top+y
1251: ,s_left+left+width-2,s_top+y,line);
1252: for(i=1;i<width*2;i+=2)
1253: line[i]=lclr|(bclr<<4);
1254: puttext(s_left+3+left,s_top+y
1255: ,s_left+left+width-2,s_top+y,line);
1256: if((*cur)>j)
1257: y-=(*cur)-j;
1258: else
1259: y+=j-(*cur);
1260: if(bar) {
1261: if((*cur)>j)
1262: (*bar)-=(*cur)-j;
1263: else
1264: (*bar)+=j-(*cur);
1265: }
1266: (*cur)=j;
1267: gettext(s_left+3+left,s_top+y
1268: ,s_left+left+width-2,s_top+y,line);
1269: for(i=1;i<width*2;i+=2)
1270: line[i]=lbclr;
1271: puttext(s_left+3+left,s_top+y
1272: ,s_left+left+width-2,s_top+y,line);
1273: break;
1274: }
1275: }
1276: if(a==2)
1277: s=0;
1278: }
1279: else
1280: switch(i) {
1281: case CR:
1282: if(!opts)
1283: break;
1284: if(mode&WIN_ACT) {
1285: gettext(s_left+left,s_top+top,s_left
1286: +left+width-1,s_top+top+height-1,tmp_buffer);
1287: for(i=1;i<(width*height*2);i+=2)
1288: tmp_buffer[i]=lclr|(cclr<<4);
1289: j=(((y-top)*width)*2)+7+((width-4)*2);
1290: for(i=(((y-top)*width)*2)+7;i<j;i+=2)
1291: tmp_buffer[i]=hclr|(cclr<<4);
1292:
1293: puttext(s_left+left,s_top+top,s_left
1294: +left+width-1,s_top+top+height-1,tmp_buffer);
1295: }
1296: else if(mode&WIN_SAV) {
1297: puttext(sav[api->savnum].left,sav[api->savnum].top
1298: ,sav[api->savnum].right,sav[api->savnum].bot
1299: ,sav[api->savnum].buf);
1300: FREE(sav[api->savnum].buf);
1301: api->savdepth--;
1302: }
1303: if(mode&WIN_XTR && (*cur)==opts-1)
1304: return(MSK_INS|*cur);
1305: return(*cur);
1306: case 3:
1307: case ESC:
1308: if((mode&WIN_ESC || (mode&WIN_CHE && api->changes))
1309: && !(mode&WIN_SAV)) {
1310: gettext(s_left+left,s_top+top,s_left
1311: +left+width-1,s_top+top+height-1,tmp_buffer);
1312: for(i=1;i<(width*height*2);i+=2)
1313: tmp_buffer[i]=lclr|(cclr<<4);
1314: puttext(s_left+left,s_top+top,s_left
1315: +left+width-1,s_top+top+height-1,tmp_buffer);
1316: }
1317: else if(mode&WIN_SAV) {
1318: puttext(sav[api->savnum].left,sav[api->savnum].top
1319: ,sav[api->savnum].right,sav[api->savnum].bot
1320: ,sav[api->savnum].buf);
1321: FREE(sav[api->savnum].buf);
1322: api->savdepth--;
1323: }
1324: return(-1);
1325: default:
1326: if(mode&WIN_EXTKEYS)
1327: return(-2-i);
1328: }
1329: }
1330: }
1331: else
1332: mswait(1);
1333: if(mode&WIN_DYN) {
1334: save_menu_cur=*cur;
1335: save_menu_bar=*bar;
1336: return(-2-i);
1337: }
1338: }
1339: }
1340:
1341:
1342: /*************************************************************************/
1343: /* This function is a windowed input string input routine. */
1344: /*************************************************************************/
1345: int uinput(int mode, int left, int top, char *inprompt, char *str,
1346: int max, int kmode)
1347: {
1348: unsigned char save_buf[2048],in_win[2048]
1349: ,shade[160];
1350: int width;
1351: int height=3;
1352: int i,plen,slen,j;
1353: int iwidth;
1354: char *prompt;
1355:
1356: reset_dynamic();
1357: plen=strlen(inprompt);
1358: prompt=strdup(inprompt);
1359: if(!plen)
1360: slen=4;
1361: else
1362: slen=6;
1363: width=plen+slen+max;
1364: if(width>api->scrn_width-6)
1365: width=api->scrn_width-6;
1366: if(mode&WIN_T2B)
1367: top=(api->scrn_len-height+1)/2-2;
1368: if(mode&WIN_L2R)
1369: left=(SCRN_RIGHT-SCRN_LEFT-width+1)/2;
1370: if(left<=-(SCRN_LEFT))
1371: left=-(SCRN_LEFT)+1;
1372: if(top<0)
1373: top=0;
1374: if(mode&WIN_SAV)
1375: gettext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT+left+width+1
1376: ,SCRN_TOP+top+height,save_buf);
1377: iwidth=width-plen-slen;
1378: while(iwidth<1 && plen>4) {
1379: plen=strlen(prompt);
1380: prompt[plen-1]=0;
1381: prompt[plen-2]='.';
1382: prompt[plen-3]='.';
1383: prompt[plen-4]='.';
1384: plen--;
1385: iwidth=width-plen-slen;
1386: }
1387:
1388: i=0;
1389: in_win[i++]='�';
1390: in_win[i++]=hclr|(bclr<<4);
1391: for(j=1;j<width-1;j++) {
1392: in_win[i++]='�';
1393: in_win[i++]=hclr|(bclr<<4);
1394: }
1395: if(api->mode&UIFC_MOUSE && width>6) {
1396: in_win[2]='[';
1397: in_win[3]=hclr|(bclr<<4);
1398: /* in_win[4]='�'; */
1399: in_win[4]=0xfe;
1400: in_win[5]=lclr|(bclr<<4);
1401: in_win[6]=']';
1402: in_win[7]=hclr|(bclr<<4);
1403: in_win[8]='[';
1404: in_win[9]=hclr|(bclr<<4);
1405: in_win[10]='?';
1406: in_win[11]=lclr|(bclr<<4);
1407: in_win[12]=']';
1408: in_win[13]=hclr|(bclr<<4);
1409: api->buttony=SCRN_TOP+top;
1410: api->exitstart=SCRN_LEFT+left+1;
1411: api->exitend=SCRN_LEFT+left+3;
1412: api->helpstart=SCRN_LEFT+left+4;
1413: api->helpend=SCRN_LEFT+left+6;
1414: }
1415:
1416: in_win[i++]='�';
1417: in_win[i++]=hclr|(bclr<<4);
1418: in_win[i++]='�';
1419: in_win[i++]=hclr|(bclr<<4);
1420:
1421: if(plen) {
1422: in_win[i++]=' ';
1423: in_win[i++]=lclr|(bclr<<4);
1424: }
1425:
1426: for(j=0;prompt[j];j++) {
1427: in_win[i++]=prompt[j];
1428: in_win[i++]=lclr|(bclr<<4);
1429: }
1430:
1431: if(plen) {
1432: in_win[i++]=':';
1433: in_win[i++]=lclr|(bclr<<4);
1434: }
1435:
1436: for(j=0;j<iwidth+2;j++) {
1437: in_win[i++]=' ';
1438: in_win[i++]=lclr|(bclr<<4);
1439: }
1440:
1441: in_win[i++]='�';
1442: in_win[i++]=hclr|(bclr<<4);
1443: in_win[i++]='�';
1444: in_win[i++]=hclr|(bclr<<4);
1445: for(j=1;j<width-1;j++) {
1446: in_win[i++]='�';
1447: in_win[i++]=hclr|(bclr<<4);
1448: }
1449: in_win[i++]='�';
1450: in_win[i]=hclr|(bclr<<4); /* I is not incremented to shut up BCC */
1451: puttext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT+left+width-1
1452: ,SCRN_TOP+top+height-1,in_win);
1453:
1454: if(bclr==BLUE) {
1455: gettext(SCRN_LEFT+left+width,SCRN_TOP+top+1,SCRN_LEFT+left+width+1
1456: ,SCRN_TOP+top+(height-1),shade);
1457: for(j=1;j<12;j+=2)
1458: shade[j]=DARKGRAY;
1459: puttext(SCRN_LEFT+left+width,SCRN_TOP+top+1,SCRN_LEFT+left+width+1
1460: ,SCRN_TOP+top+(height-1),shade);
1461: gettext(SCRN_LEFT+left+2,SCRN_TOP+top+3,SCRN_LEFT+left+width+1
1462: ,SCRN_TOP+top+height,shade);
1463: for(j=1;j<width*2;j+=2)
1464: shade[j]=DARKGRAY;
1465: puttext(SCRN_LEFT+left+2,SCRN_TOP+top+3,SCRN_LEFT+left+width+1
1466: ,SCRN_TOP+top+height,shade);
1467: }
1468:
1469: textattr(lclr|(bclr<<4));
1470: if(!plen)
1471: i=ugetstr(SCRN_LEFT+left+2,SCRN_TOP+top+1,iwidth,str,max,kmode,NULL);
1472: else
1473: i=ugetstr(SCRN_LEFT+left+plen+4,SCRN_TOP+top+1,iwidth,str,max,kmode,NULL);
1474: if(mode&WIN_SAV)
1475: puttext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT+left+width+1
1476: ,SCRN_TOP+top+height,save_buf);
1477: free(prompt);
1478: return(i);
1479: }
1480:
1481: /****************************************************************************/
1482: /* Displays the message 'str' and waits for the user to select "OK" */
1483: /****************************************************************************/
1484: void umsg(char *str)
1485: {
1486: int i=0;
1487: char *ok[2]={"OK",""};
1488:
1489: if(api->mode&UIFC_INMSG) /* non-cursive */
1490: return;
1491: api->mode|=UIFC_INMSG;
1492: if(api->savdepth) api->savnum++;
1493: ulist(WIN_SAV|WIN_MID,0,0,0,&i,0,str,ok);
1494: if(api->savdepth) api->savnum--;
1495: api->mode&=~UIFC_INMSG;
1496: }
1497:
1498: /***************************************/
1499: /* Private sub - updates a ugetstr box */
1500: /***************************************/
1501: void getstrupd(int left, int top, int width, char *outstr, int cursoffset, int *scrnoffset)
1502: {
1503: _setcursortype(_NOCURSOR);
1504: if(cursoffset<*scrnoffset)
1505: *scrnoffset=cursoffset;
1506:
1507: if(*scrnoffset+width < cursoffset)
1508: *scrnoffset=cursoffset-width;
1509:
1510: gotoxy(left,top);
1511: cprintf("%-*.*s",width,width,outstr+*scrnoffset);
1512: gotoxy(left+(cursoffset-*scrnoffset),top);
1513: _setcursortype(cursor);
1514: }
1515:
1516: /****************************************************************************/
1517: /* Gets a string of characters from the user. Turns cursor on. Allows */
1518: /* Different modes - K_* macros. ESC aborts input. */
1519: /****************************************************************************/
1520: int ugetstr(int left, int top, int width, char *outstr, int max, long mode, int *lastkey)
1521: {
1522: uchar *str,ins=0;
1523: int ch;
1524: int i,j,k,f=0; /* i=offset, j=length */
1525: BOOL gotdecimal=FALSE;
1526: int soffset=0;
1527: struct mouse_event mevnt;
1528:
1529: if((str=(uchar *)malloc(max+1))==NULL) {
1530: cprintf("UIFC line %d: error allocating %u bytes\r\n"
1531: ,__LINE__,(max+1));
1532: _setcursortype(cursor);
1533: return(-1);
1534: }
1535: gotoxy(left,top);
1536: cursor=_NORMALCURSOR;
1537: _setcursortype(cursor);
1538: str[0]=0;
1539: if(mode&K_EDIT && outstr[0]) {
1540: /***
1541: truncsp(outstr);
1542: ***/
1543: outstr[max]=0;
1544: i=j=strlen(outstr);
1545: textattr(lbclr);
1546: getstrupd(left, top, width, outstr, i, &soffset);
1547: textattr(lclr|(bclr<<4));
1548: if(strlen(outstr)<width) {
1549: k=wherex();
1550: f=wherey();
1551: cprintf("%*s",width-strlen(outstr),"");
1552: gotoxy(k,f);
1553: }
1554: strcpy(str,outstr);
1555: #if 0
1556: while(kbwait()==0) {
1557: mswait(1);
1558: }
1559: #endif
1560: f=inkey();
1561: if(f==CIO_KEY_MOUSE) {
1562: if((f=uifc_getmouse(&mevnt))==0) {
1563: if(mevnt.startx>=left
1564: && mevnt.startx<=left+width
1565: && mevnt.event==CIOLIB_BUTTON_1_CLICK) {
1566: i=mevnt.startx-left+soffset;
1567: if(i>j)
1568: i=j;
1569: }
1570: }
1571: }
1572:
1573: if(f == CR
1574: || (f >= 0xff && f != CIO_KEY_DC)
1575: || (f == '\t' && mode&K_TABEXIT)
1576: || (f == '%' && mode&K_SCANNING)
1577: || f==CTRL_B
1578: || f==CTRL_E
1579: || f==CTRL_V
1580: || f==CTRL_Z
1581: || f==0)
1582: {
1583: getstrupd(left, top, width, str, i, &soffset);
1584: }
1585: else
1586: {
1587: getstrupd(left, top, width, str, i, &soffset);
1588: i=j=0;
1589: }
1590: }
1591: else
1592: i=j=0;
1593:
1594: ch=0;
1595: while(ch!=CR)
1596: {
1597: if(i>j) j=i;
1598: str[j]=0;
1599: getstrupd(left, top, width, str, i, &soffset);
1600: if(f || (ch=inkey())!=0)
1601: {
1602: if(f)
1603: ch=f;
1604: f=0;
1605: if(ch==CIO_KEY_MOUSE) {
1606: if((ch=uifc_getmouse(&mevnt))==0) {
1607: if(mevnt.startx>=left
1608: && mevnt.startx<=left+width
1609: && mevnt.event==CIOLIB_BUTTON_1_CLICK) {
1610: i=mevnt.startx-left+soffset;
1611: if(i>j)
1612: i=j;
1613: }
1614: }
1615: }
1616: if(lastkey != NULL)
1617: *lastkey=ch;
1618: switch(ch)
1619: {
1620: case CTRL_Z:
1621: case CIO_KEY_F(1): /* F1 Help */
1622: api->showhelp();
1623: continue;
1624: case CIO_KEY_LEFT: /* left arrow */
1625: if(i)
1626: {
1627: i--;
1628: }
1629: continue;
1630: case CIO_KEY_RIGHT: /* right arrow */
1631: if(i<j)
1632: {
1633: i++;
1634: }
1635: continue;
1636: case CTRL_B:
1637: case CIO_KEY_HOME: /* home */
1638: if(i)
1639: {
1640: i=0;
1641: }
1642: continue;
1643: case CTRL_E:
1644: case CIO_KEY_END: /* end */
1645: if(i<j)
1646: {
1647: i=j;
1648: }
1649: continue;
1650: case CTRL_V:
1651: case CIO_KEY_IC: /* insert */
1652: ins=!ins;
1653: if(ins)
1654: cursor=_SOLIDCURSOR;
1655: else
1656: cursor=_NORMALCURSOR;
1657: _setcursortype(cursor);
1658: continue;
1659: case BS:
1660: if(i)
1661: {
1662: if(i==j)
1663: {
1664: j--;
1665: i--;
1666: }
1667: else {
1668: i--;
1669: j--;
1670: if(str[i]=='.')
1671: gotdecimal=FALSE;
1672: for(k=i;k<=j;k++)
1673: str[k]=str[k+1];
1674: }
1675: continue;
1676: }
1677: case CIO_KEY_DC: /* delete */
1678: if(i<j)
1679: {
1680: if(str[i]=='.')
1681: gotdecimal=FALSE;
1682: for(k=i;k<j;k++)
1683: str[k]=str[k+1];
1684: j--;
1685: }
1686: continue;
1687: case CTRL_C:
1688: case ESC:
1689: {
1690: cursor=_NOCURSOR;
1691: _setcursortype(cursor);
1692: return(-1);
1693: }
1694: case CR:
1695: break;
1696: case '\t': /* '%' indicates that a UPC is coming next */
1697: if(mode&K_TABEXIT)
1698: ch=CR;
1699: break;
1700: case '%': /* '%' indicates that a UPC is coming next */
1701: if(mode&K_SCANNING)
1702: ch=CR;
1703: break;
1704: case CIO_KEY_F(2):
1705: case CIO_KEY_UP:
1706: case CIO_KEY_DOWN:
1707: if(mode&K_DEUCEEXIT) {
1708: ch=CR;
1709: break;
1710: }
1711: continue;
1712: case CTRL_X:
1713: if(j)
1714: {
1715: i=j=0;
1716: }
1717: continue;
1718: case CTRL_Y:
1719: if(i<j)
1720: {
1721: j=i;
1722: }
1723: continue;
1724: }
1725: if(mode&K_NUMBER && !isdigit(ch))
1726: continue;
1727: if(mode&K_DECIMAL && !isdigit(ch)) {
1728: if(ch!='.')
1729: continue;
1730: if(gotdecimal)
1731: continue;
1732: gotdecimal=TRUE;
1733: }
1734: if(mode&K_ALPHA && !isalpha(ch))
1735: continue;
1736: #if 0
1737: /* This broke swedish chars... */
1738: if((ch>=' ' || (ch==1 && mode&K_MSG)) && i<max && (!ins || j<max) && isprint(ch))
1739: #else
1740: if((ch>=' ' || (ch==1 && mode&K_MSG)) && i<max && (!ins || j<max) && ch < 256)
1741: #endif
1742: {
1743: if(mode&K_UPPER)
1744: ch=toupper(ch);
1745: if(ins)
1746: {
1747: for(k=++j;k>i;k--)
1748: str[k]=str[k-1];
1749: }
1750: str[i++]=ch;
1751: }
1752: }
1753: }
1754:
1755:
1756: str[j]=0;
1757: if(mode&K_EDIT)
1758: {
1759: truncsp(str);
1760: if(strcmp(outstr,str))
1761: api->changes=1;
1762: }
1763: else
1764: {
1765: if(j)
1766: api->changes=1;
1767: }
1768: strcpy(outstr,str);
1769: cursor=_NOCURSOR;
1770: _setcursortype(cursor);
1771: return(j);
1772: }
1773:
1774: /****************************************************************************/
1775: /* Performs printf() through puttext() routine */
1776: /****************************************************************************/
1777: static int uprintf(int x, int y, unsigned char attr, char *fmat, ...)
1778: {
1779: va_list argptr;
1780: char str[256],buf[512];
1781: int i,j;
1782:
1783: va_start(argptr,fmat);
1784: vsprintf(str,fmat,argptr);
1785: va_end(argptr);
1786: for(i=j=0;str[i];i++) {
1787: buf[j++]=str[i];
1788: buf[j++]=attr;
1789: }
1790: puttext(x,y,x+(i-1),y,buf);
1791: return(i);
1792: }
1793:
1794:
1795: /****************************************************************************/
1796: /* Display bottom line of screen in inverse */
1797: /****************************************************************************/
1798: void bottomline(int line)
1799: {
1800: int i=4;
1801:
1802: uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"F1 ");
1803: i+=3;
1804: uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Help ");
1805: i+=6;
1806: if(line&BL_GET) {
1807: uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"F5 ");
1808: i+=3;
1809: uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Copy Item ");
1810: i+=11;
1811: }
1812: if(line&BL_PUT) {
1813: uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"F6 ");
1814: i+=3;
1815: uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Paste ");
1816: i+=7;
1817: }
1818: if(line&BL_INS) {
1819: uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"INS ");
1820: i+=4;
1821: uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Add Item ");
1822: i+=10;
1823: }
1824: if(line&BL_DEL) {
1825: uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"DEL ");
1826: i+=4;
1827: uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Delete Item ");
1828: i+=13;
1829: }
1830: uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"ESC "); /* Backspace is no good no way to abort editing */
1831: i+=4;
1832: uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Exit");
1833: i+=4;
1834: gotoxy(i,api->scrn_len+1);
1835: textattr(BLACK|(cclr<<4));
1836: clreol();
1837: }
1838:
1839:
1840: /*****************************************************************************/
1841: /* Generates a 24 character ASCII string that represents the time_t pointer */
1842: /* Used as a replacement for ctime() */
1843: /*****************************************************************************/
1844: char *utimestr(time_t *intime)
1845: {
1846: static char str[25];
1847: char wday[4],mon[4],mer[3],hour;
1848: struct tm *gm;
1849:
1850: gm=localtime(intime);
1851: switch(gm->tm_wday) {
1852: case 0:
1853: strcpy(wday,"Sun");
1854: break;
1855: case 1:
1856: strcpy(wday,"Mon");
1857: break;
1858: case 2:
1859: strcpy(wday,"Tue");
1860: break;
1861: case 3:
1862: strcpy(wday,"Wed");
1863: break;
1864: case 4:
1865: strcpy(wday,"Thu");
1866: break;
1867: case 5:
1868: strcpy(wday,"Fri");
1869: break;
1870: case 6:
1871: strcpy(wday,"Sat");
1872: break;
1873: }
1874: switch(gm->tm_mon) {
1875: case 0:
1876: strcpy(mon,"Jan");
1877: break;
1878: case 1:
1879: strcpy(mon,"Feb");
1880: break;
1881: case 2:
1882: strcpy(mon,"Mar");
1883: break;
1884: case 3:
1885: strcpy(mon,"Apr");
1886: break;
1887: case 4:
1888: strcpy(mon,"May");
1889: break;
1890: case 5:
1891: strcpy(mon,"Jun");
1892: break;
1893: case 6:
1894: strcpy(mon,"Jul");
1895: break;
1896: case 7:
1897: strcpy(mon,"Aug");
1898: break;
1899: case 8:
1900: strcpy(mon,"Sep");
1901: break;
1902: case 9:
1903: strcpy(mon,"Oct");
1904: break;
1905: case 10:
1906: strcpy(mon,"Nov");
1907: break;
1908: case 11:
1909: strcpy(mon,"Dec");
1910: break;
1911: }
1912: if(gm->tm_hour>12) {
1913: strcpy(mer,"pm");
1914: hour=gm->tm_hour-12;
1915: }
1916: else {
1917: if(!gm->tm_hour)
1918: hour=12;
1919: else
1920: hour=gm->tm_hour;
1921: strcpy(mer,"am");
1922: }
1923: sprintf(str,"%s %s %02d %4d %02d:%02d %s",wday,mon,gm->tm_mday,1900+gm->tm_year
1924: ,hour,gm->tm_min,mer);
1925: return(str);
1926: }
1927:
1928: /****************************************************************************/
1929: /* Status popup/down function, see uifc.h for details. */
1930: /****************************************************************************/
1931: void upop(char *str)
1932: {
1933: static char sav[26*3*2];
1934: char buf[26*3*2];
1935: int i,j,k;
1936:
1937: if(!str) {
1938: /* puttext(28,12,53,14,sav); */
1939: puttext((api->scrn_width-26+1)/2+1,(api->scrn_len-3+1)/2+1
1940: ,(api->scrn_width+26-1)/2+1,(api->scrn_len+3-1)/2+1,sav);
1941: return;
1942: }
1943: /* gettext(28,12,53,14,sav); */
1944: gettext((api->scrn_width-26+1)/2+1,(api->scrn_len-3+1)/2+1
1945: ,(api->scrn_width+26-1)/2+1,(api->scrn_len+3-1)/2+1,sav);
1946: memset(buf,' ',25*3*2);
1947: for(i=1;i<26*3*2;i+=2)
1948: buf[i]=(hclr|(bclr<<4));
1949: buf[0]='�';
1950: for(i=2;i<25*2;i+=2)
1951: buf[i]='�';
1952: buf[i]='�'; i+=2;
1953: buf[i]='�'; i+=2;
1954: i+=2;
1955: k=strlen(str);
1956: i+=(((23-k)/2)*2);
1957: for(j=0;j<k;j++,i+=2) {
1958: buf[i]=str[j];
1959: buf[i+1]|=BLINK;
1960: }
1961: i=((25*2)+1)*2;
1962: buf[i]='�'; i+=2;
1963: buf[i]='�'; i+=2;
1964: for(;i<((26*3)-1)*2;i+=2)
1965: buf[i]='�';
1966: buf[i]='�';
1967:
1968: /* puttext(28,12,53,14,buf); */
1969: puttext((api->scrn_width-26+1)/2+1,(api->scrn_len-3+1)/2+1
1970: ,(api->scrn_width+26-1)/2+1,(api->scrn_len+3-1)/2+1,buf);
1971: }
1972:
1973: /****************************************************************************/
1974: /* Sets the current help index by source code file and line number. */
1975: /****************************************************************************/
1976: void sethelp(int line, char* file)
1977: {
1978: helpline=line;
1979: helpfile=file;
1980: }
1981:
1982: /****************************************************************************/
1983: /* Shows a scrollable text buffer - optionally parsing "help markup codes" */
1984: /****************************************************************************/
1985: void showbuf(int mode, int left, int top, int width, int height, char *title, char *hbuf, int *curp, int *barp)
1986: {
1987: char inverse=0,high=0;
1988: char *textbuf;
1989: char *p;
1990: char *oldp=NULL;
1991: int i,j,k,len;
1992: int lines;
1993: int pad=1;
1994: int is_redraw=0;
1995: uint title_len=0;
1996: struct mouse_event mevnt;
1997:
1998: _setcursortype(_NOCURSOR);
1999:
2000: title_len=strlen(title);
2001: if(api->mode&UIFC_MOUSE)
2002: title_len+=6;
2003:
2004: if(top+height>api->scrn_len-3)
2005: height=(api->scrn_len-3)-top;
2006: if(!width || width<title_len+6)
2007: width=title_len+6;
2008: if(width>api->scrn_width)
2009: width=api->scrn_width;
2010: if(mode&WIN_L2R)
2011: left=(api->scrn_width-width+2)/2;
2012: else if(mode&WIN_RHT)
2013: left=SCRN_RIGHT-(width+4+left);
2014: if(mode&WIN_T2B)
2015: top=(api->scrn_len-height+1)/2;
2016: else if(mode&WIN_BOT)
2017: top=api->scrn_len-height-3-top;
2018: if(left<0)
2019: left=0;
2020: if(top<0)
2021: top=0;
2022:
2023: if(mode&WIN_PACK)
2024: pad=0;
2025:
2026: /* Dynamic Menus */
2027: if(mode&WIN_DYN
2028: && curp != NULL
2029: && barp != NULL
2030: && last_menu_cur==curp
2031: && last_menu_bar==barp
2032: && save_menu_cur==*curp
2033: && save_menu_bar==*barp)
2034: is_redraw=1;
2035: if(mode&WIN_DYN && mode&WIN_REDRAW)
2036: is_redraw=1;
2037: if(mode&WIN_DYN && mode&WIN_NODRAW)
2038: is_redraw=0;
2039:
2040: gettext(1,1,api->scrn_width,api->scrn_len,tmp_buffer);
2041:
2042: if(!is_redraw) {
2043: memset(tmp_buffer2,' ',width*height*2);
2044: for(i=1;i<width*height*2;i+=2)
2045: tmp_buffer2[i]=(hclr|(bclr<<4));
2046: tmp_buffer2[0]='�';
2047: j=title_len;
2048: if(j>width-6)
2049: *(title+width-6)=0;
2050: for(i=2;i<((width-6)/2-(j/2))*2;i+=2)
2051: tmp_buffer2[i]='�';
2052: if(api->mode&UIFC_MOUSE && !mode&WIN_DYN) {
2053: tmp_buffer2[2]='[';
2054: tmp_buffer2[3]=hclr|(bclr<<4);
2055: /* tmp_buffer2[4]='�'; */
2056: tmp_buffer2[4]=0xfe;
2057: tmp_buffer2[5]=lclr|(bclr<<4);
2058: tmp_buffer2[6]=']';
2059: tmp_buffer2[7]=hclr|(bclr<<4);
2060: /* Buttons are ignored - leave it this way to not confuse stuff from help() */
2061: }
2062: tmp_buffer2[i]='�'; i+=4;
2063: for(p=title;*p;p++) {
2064: tmp_buffer2[i]=*p;
2065: i+=2;
2066: }
2067: i+=2;
2068: tmp_buffer2[i]='�'; i+=2;
2069: for(j=i;j<((width-1)*2);j+=2)
2070: tmp_buffer2[j]='�';
2071: i=j;
2072: tmp_buffer2[i]='�'; i+=2;
2073: j=i; /* leave i alone */
2074: for(k=0;k<(height-2);k++) { /* the sides of the box */
2075: tmp_buffer2[j]='�'; j+=2;
2076: j+=((width-2)*2);
2077: tmp_buffer2[j]='�'; j+=2;
2078: }
2079: tmp_buffer2[j]='�'; j+=2;
2080: if(!(mode&WIN_DYN) && (width>31)) {
2081: for(k=j;k<j+(((width-4)/2-13)*2);k+=2)
2082: tmp_buffer2[k]='�';
2083: tmp_buffer2[k]='�'; k+=4;
2084: tmp_buffer2[k]='H'; k+=2;
2085: tmp_buffer2[k]='i'; k+=2;
2086: tmp_buffer2[k]='t'; k+=4;
2087: tmp_buffer2[k]='a'; k+=2;
2088: tmp_buffer2[k]='n'; k+=2;
2089: tmp_buffer2[k]='y'; k+=4;
2090: tmp_buffer2[k]='k'; k+=2;
2091: tmp_buffer2[k]='e'; k+=2;
2092: tmp_buffer2[k]='y'; k+=4;
2093: tmp_buffer2[k]='t'; k+=2;
2094: tmp_buffer2[k]='o'; k+=4;
2095: tmp_buffer2[k]='c'; k+=2;
2096: tmp_buffer2[k]='o'; k+=2;
2097: tmp_buffer2[k]='n'; k+=2;
2098: tmp_buffer2[k]='t'; k+=2;
2099: tmp_buffer2[k]='i'; k+=2;
2100: tmp_buffer2[k]='n'; k+=2;
2101: tmp_buffer2[k]='u'; k+=2;
2102: tmp_buffer2[k]='e'; k+=4;
2103: tmp_buffer2[k]='�'; k+=2;
2104: for(j=k;j<k+(((width-4)/2-12)*2);j+=2)
2105: tmp_buffer2[j]='�';
2106: }
2107: else {
2108: for(k=j;k<j+((width-2)*2);k+=2)
2109: tmp_buffer2[k]='�';
2110: j=k;
2111: }
2112: tmp_buffer2[j]='�';
2113: puttext(left,top+1,left+width-1,top+height,tmp_buffer2);
2114: }
2115: len=strlen(hbuf);
2116:
2117: lines=0;
2118: k=0;
2119: for(j=0;j<len;j++) {
2120: k++;
2121: if((hbuf[j]==LF) || (k>width-2-pad-pad && (hbuf[j+1]!='\n'))) {
2122: k=0;
2123: lines++;
2124: }
2125: }
2126: if(k)
2127: lines++;
2128: if(lines < height-2-pad-pad)
2129: lines=height-2-pad-pad;
2130:
2131: if((textbuf=(char *)MALLOC((width-2-pad-pad)*lines*2))==NULL) {
2132: cprintf("UIFC line %d: error allocating %u bytes\r\n"
2133: ,__LINE__,(width-2-pad-pad)*lines*2);
2134: _setcursortype(cursor);
2135: return;
2136: }
2137: memset(textbuf,' ',(width-2-pad-pad)*lines*2);
2138: for(i=1;i<(width-2-pad-pad)*lines*2;i+=2)
2139: textbuf[i]=(hclr|(bclr<<4));
2140:
2141: i=0;
2142:
2143: for(j=i;j<len;j++,i+=2) {
2144: if(hbuf[j]==LF) {
2145: i+=2;
2146: while(i%((width-2-pad-pad)*2)) i++; i-=2;
2147: }
2148: else if(mode&WIN_HLP && (hbuf[j]==2 || hbuf[j]=='~')) { /* Ctrl-b toggles inverse */
2149: inverse=!inverse;
2150: i-=2;
2151: }
2152: else if(mode&WIN_HLP && (hbuf[j]==1 || hbuf[j]=='`')) { /* Ctrl-a toggles high intensity */
2153: high=!high;
2154: i-=2;
2155: }
2156: else if(hbuf[j]!=CR) {
2157: textbuf[i]=hbuf[j];
2158: textbuf[i+1]=inverse ? (bclr|(cclr<<4))
2159: : high ? (hclr|(bclr<<4)) : (lclr|(bclr<<4));
2160: }
2161: }
2162: i=0;
2163: p=textbuf;
2164: if(mode&WIN_DYN) {
2165: puttext(left+1+pad,top+2+pad,left+width-2-pad,top+height-1-pad,p);
2166: }
2167: else {
2168: while(i==0) {
2169: if(p!=oldp) {
2170: if(p > textbuf+(lines-(height-2-pad-pad))*(width-4)*2)
2171: p=textbuf+(lines-(height-2-pad-pad))*(width-4)*2;
2172: if(p<textbuf)
2173: p=textbuf;
2174: if(p!=oldp) {
2175: puttext(left+1+pad,top+2+pad,left+width-2-pad,top+height-1-pad,p);
2176: oldp=p;
2177: }
2178: }
2179: if(kbwait()) {
2180: j=inkey();
2181: if(j==CIO_KEY_MOUSE) {
2182: /* Ignores return value to avoid hitting help/exit hotspots */
2183: if(uifc_getmouse(&mevnt)>=0) {
2184: /* Clicked Scroll Up */
2185: if(mevnt.startx>=left+pad
2186: && mevnt.startx<=left+pad+width-3
2187: && mevnt.starty>=top+pad+1
2188: && mevnt.starty<=top+pad+(height/2)-2
2189: && mevnt.event==CIOLIB_BUTTON_1_CLICK) {
2190: p = p-((width-4)*2*(height-5));
2191: continue;
2192: }
2193: /* Clicked Scroll Down */
2194: if(mevnt.startx>=left+pad
2195: && mevnt.startx<=left+pad+width
2196: && mevnt.starty<=top+pad+height-2
2197: && mevnt.starty>=top+pad+height-(height/2+1)-2
2198: && mevnt.event==CIOLIB_BUTTON_1_CLICK) {
2199: p=p+(width-4)*2*(height-5);
2200: continue;
2201: }
2202: i=1;
2203: }
2204: continue;
2205: }
2206: switch(j) {
2207: case CIO_KEY_HOME: /* home */
2208: p=textbuf;
2209: break;
2210:
2211: case CIO_KEY_UP: /* up arrow */
2212: p = p-((width-4)*2);
2213: break;
2214:
2215: case CIO_KEY_PPAGE: /* PgUp */
2216: p = p-((width-4)*2*(height-5));
2217: break;
2218:
2219: case CIO_KEY_NPAGE: /* PgDn */
2220: p=p+(width-4)*2*(height-5);
2221: break;
2222:
2223: case CIO_KEY_END: /* end */
2224: p=textbuf+(lines-height+1)*(width-4)*2;
2225: break;
2226:
2227: case CIO_KEY_DOWN: /* dn arrow */
2228: p = p+((width-4)*2);
2229: break;
2230:
2231: default:
2232: i=1;
2233: }
2234: }
2235: mswait(1);
2236: }
2237:
2238: puttext(1,1,api->scrn_width,api->scrn_len,tmp_buffer);
2239: }
2240: if(is_redraw) /* Force redraw of menu also. */
2241: reset_dynamic();
2242: FREE(textbuf);
2243: _setcursortype(cursor);
2244: }
2245:
2246: /************************************************************/
2247: /* Help (F1) key function. Uses helpbuf as the help input. */
2248: /************************************************************/
2249: static void help(void)
2250: {
2251: char hbuf[HELPBUF_SIZE],str[256];
2252: char *p;
2253: unsigned short line; /* This must be 16-bits */
2254: long l;
2255: FILE *fp;
2256:
2257: _setcursortype(_NOCURSOR);
2258:
2259: if(!api->helpbuf) {
2260: if((fp=fopen(api->helpixbfile,"rb"))==NULL) {
2261: sprintf(hbuf," ERROR Cannot open help index:\r\n %s"
2262: ,api->helpixbfile);
2263: }
2264: else {
2265: p=strrchr(helpfile,'/');
2266: if(p==NULL)
2267: p=strrchr(helpfile,'\\');
2268: if(p==NULL)
2269: p=helpfile;
2270: else
2271: p++;
2272: l=-1L;
2273: while(!feof(fp)) {
2274: if(!fread(str,12,1,fp))
2275: break;
2276: str[12]=0;
2277: fread(&line,sizeof(line),1,fp);
2278: if(stricmp(str,p) || line!=helpline) {
2279: fseek(fp,sizeof(l),SEEK_CUR);
2280: continue;
2281: }
2282: fread(&l,sizeof(l),1,fp);
2283: break;
2284: }
2285: fclose(fp);
2286: if(l==-1L)
2287: sprintf(hbuf," ERROR Cannot locate help key (%s:%u) in:\r\n"
2288: " %s",p,helpline,api->helpixbfile);
2289: else {
2290: if((fp=fopen(api->helpdatfile,"rb"))==NULL)
2291: sprintf(hbuf," ERROR Cannot open help file:\r\n %s"
2292: ,api->helpdatfile);
2293: else {
2294: fseek(fp,l,SEEK_SET);
2295: fread(hbuf,HELPBUF_SIZE,1,fp);
2296: fclose(fp);
2297: }
2298: }
2299: }
2300: }
2301: else
2302: strcpy(hbuf,api->helpbuf);
2303:
2304: showbuf(WIN_MID|WIN_HLP, 0, 0, 76, api->scrn_len, "Online Help", hbuf, NULL, NULL);
2305: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.