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