diff --git a/src/uifc/uifcc.c b/src/uifc/uifcc.c new file mode 100644 index 0000000000000000000000000000000000000000..90e553ef3ba309fead89efdad1685b40629d035c --- /dev/null +++ b/src/uifc/uifcc.c @@ -0,0 +1,1881 @@ +/* uifcc.c */ + +/* Curses implementation of UIFC (user interface) library based on uifc.c */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2002 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU General Public License for more details: gpl.txt or * + * http://www.fsf.org/copyleft/gpl.html * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#include "uifc.h" +#include <curses.h> +#include <unistd.h> +#include <sys/time.h> + +#if defined(__OS2__) + +#define INCL_BASE +#include <os2.h> + +void mswait(int msec) +{ +DosSleep(msec ? msec : 1); +} + +#elif defined(_WIN32) + #include <windows.h> + #define mswait(x) Sleep(x) +#elif defined(__FLAT__) + #define mswait(x) delay(x) +#endif + + /* Bottom line elements */ +#define BL_INS (1<<0) /* INS key */ +#define BL_DEL (1<<1) /* DEL key */ +#define BL_GET (1<<2) /* Get key */ +#define BL_PUT (1<<3) /* Put key */ + +#define BLACK 0 +#define BLUE 1 +#define GREEN 2 +#define CYAN 3 +#define RED 4 +#define MAGENTA 5 +#define BROWN 6 +#define LIGHTGRAY 7 +#define DARKGRAY 8 +#define LIGHTBLUE 9 +#define LIGHTGREEN 10 +#define LIGHTCYAN 11 +#define LIGHTRED 12 +#define LIGHTMAGENTA 13 +#define YELLOW 14 +#define WHITE 15 +#define BLINK 128 +#define SH_DENYWR 1 +#define SH_DENYRW 2 +#define O_BINARY 0 + +static char hclr,lclr,bclr,cclr,show_free_mem=0; +static char* helpfile=0; +static uint helpline=0; +static char blk_scrn[MAX_BFLN]; +static win_t sav[MAX_BUFS]; +static uint max_opts=MAX_OPTS; +static uifcapi_t* api; +static int lastattr=0; + +/* Prototypes */ +static int uprintf(int x, int y, unsigned char attr, char *fmt,...); +static void bottomline(int line); +static char *utimestr(time_t *intime); +static void help(); +static int puttext(int sx, int sy, int ex, int ey, unsigned char *fill); +static int gettext(int sx, int sy, int ex, int ey, unsigned char *fill); +static short curses_color(short color); +static void textattr(unsigned char attr); +static int kbhit(void); +static void delay(int msec); +static int ugetstr(char *outstr, int max, long mode); +static int wherey(void); +static int wherex(void); +static FILE * _fsopen(char *pathname, char *mode, int flags); +static int cprintf(char *fmat, ...); +static void putch(unsigned char ch); +static void cputs(char *str); +static void gotoxy(int x, int y); + +/* API routines */ +static void uifcbail(void); +static int uscrn(char *str); +static int ulist(int mode, int left, int top, int width, int *dflt, int *bar + ,char *title, char **option); +static int uinput(int imode, int left, int top, char *prompt, char *str + ,int len ,int kmode); +static void umsg(char *str); +static void upop(char *str); +static void sethelp(int line, char* file); + +int inkey(int mode) +{ + if(mode) + return(kbhit()); + return(getch()); +} + +/****************************************************************************/ +/* Initialization function, see uifc.h for details. */ +/* Returns 0 on success. */ +/****************************************************************************/ +int uifcinic(uifcapi_t* uifcapi) +{ + int i; + int height, width; + short fg, bg, pair=0; +#ifndef __FLAT__ + union REGS r; +#endif + + if(uifcapi==NULL || uifcapi->size!=sizeof(uifcapi_t)) + return(-1); + + api=uifcapi; + + /* install function handlers */ + api->bail=uifcbail; + api->scrn=uscrn; + api->msg=umsg; + api->pop=upop; + api->list=ulist; + api->input=uinput; + api->sethelp=sethelp; + + initscr(); + start_color(); + cbreak(); + noecho(); + nonl(); +// intrflush(stdscr, FALSE); + keypad(stdscr, TRUE); + scrollok(stdscr,FALSE); + + // Set up color pairs + for(bg=0;bg<8;bg++) { + for(fg=0;fg<8;fg++) { + init_pair(++pair,curses_color(fg),curses_color(bg)); + } + } +// resizeterm(25,80); /* set mode to 80x25 if possible */ + clear(); + getmaxyx(stdscr,height,width); + /* unsupported mode? */ + if(height<MIN_LINES + || height>MAX_LINES + || width<80) { + } + + api->scrn_len=height; + if(api->scrn_len<MIN_LINES || api->scrn_len>MAX_LINES) { + cprintf("\7UIFC: Screen length (%u) must be between %d and %d lines\r\n" + ,api->scrn_len,MIN_LINES,MAX_LINES); + return(-2); + } + api->scrn_len--; /* account for status line */ + + if(width<80) { + cprintf("\7UIFC: Screen width (%u) must be at least 80 characters\r\n" + ,width); + return(-3); + } + + +/* ToDo - Set up mousemask() here */ + + if(!has_colors()) { + bclr=BLACK; + hclr=WHITE; + lclr=LIGHTGRAY; + cclr=LIGHTGRAY; + } else { + bclr=BLUE; + hclr=YELLOW; + lclr=WHITE; + cclr=CYAN; + } + for(i=0;i<MAX_BFLN;i+=2) { + blk_scrn[i]='°'; + blk_scrn[i+1]=cclr|(bclr<<4); + } + + curs_set(0); + refresh(); + + return(0); +} + +short curses_color(short color) +{ + switch(color) + { + case 0 : + return(COLOR_BLACK); + case 1 : + return(COLOR_BLUE); + case 2 : + return(COLOR_GREEN); + case 3 : + return(COLOR_CYAN); + case 4 : + return(COLOR_RED); + case 5 : + return(COLOR_MAGENTA); + case 6 : + return(COLOR_YELLOW); + case 7 : + return(COLOR_WHITE); + case 8 : + return(COLOR_BLACK); + case 9 : + return(COLOR_BLUE); + case 10 : + return(COLOR_GREEN); + case 11 : + return(COLOR_CYAN); + case 12 : + return(COLOR_RED); + case 13 : + return(COLOR_MAGENTA); + case 14 : + return(COLOR_YELLOW); + case 15 : + return(COLOR_WHITE); + } + return(0); +} + +static void hidemouse(void) +{ +/* ToDo - Mouse stuff here */ +} + +static void showmouse(void) +{ +/* ToDo - Mouse stuff here */ +} + + +void uifcbail(void) +{ +curs_set(1); +clear(); +refresh(); +} + +/****************************************************************************/ +/* Clear screen, fill with background attribute, display application title. */ +/* Returns 0 on success. */ +/****************************************************************************/ +int uscrn(char *str) +{ + textattr(bclr|(cclr<<4)); + gotoxy(1,1); + clrtoeol(); + gotoxy(3,1); + cputs(str); + if(!puttext(1,2,80,api->scrn_len,blk_scrn)) + return(-1); + gotoxy(1,api->scrn_len+1); + clrtoeol(); + refresh(); + return(0); +} + +/****************************************************************************/ +/****************************************************************************/ +static void scroll_text(int x1, int y1, int x2, int y2, int down) +{ + uchar buf[MAX_BFLN]; + +gettext(x1,y1,x2,y2,buf); +if(down) + puttext(x1,y1+1,x2,y2,buf); +else + puttext(x1,y1,x2,y2-1,buf+(((x2-x1)+1)*2)); +} + +/****************************************************************************/ +/* Updates time in upper left corner of screen with current time in ASCII/ */ +/* Unix format */ +/****************************************************************************/ +static void timedisplay() +{ + static time_t savetime; + time_t now; + +now=time(NULL); +if(difftime(now,savetime)>=60) { + uprintf(55,1,bclr|(cclr<<4),utimestr(&now)); + savetime=now; } +} + +/****************************************************************************/ +/* Truncates white-space chars off end of 'str' */ +/****************************************************************************/ +static void truncsp(char *str) +{ + uint c; + + c=strlen(str); + while(c && (uchar)str[c-1]<=SP) c--; + str[c]=0; +} + +/****************************************************************************/ +/* General menu function, see uifc.h for details. */ +/****************************************************************************/ +int ulist(int mode, int left, int top, int width, int *cur, int *bar + , char *title, char **option) +{ + uchar line[256],shade[256],win[MAX_BFLN],*ptr,a,b,c,longopt + ,search[MAX_OPLN],bline=0; + int height,y; + int i,j,opts=0,s=0; /* s=search index into options */ + +#ifndef __FLAT__ +/* ToDo Mouse stuff */ +#endif + +if(mode&WIN_SAV && api->savnum>=MAX_BUFS-1) + putch(7); +i=0; +if(mode&WIN_INS) bline|=BL_INS; +if(mode&WIN_DEL) bline|=BL_DEL; +if(mode&WIN_GET) bline|=BL_GET; +if(mode&WIN_PUT) bline|=BL_PUT; +bottomline(bline); +while(opts<max_opts && opts<MAX_OPTS) + if(option[opts][0]==0) + break; + else opts++; +if(mode&WIN_XTR && opts<max_opts && opts<MAX_OPTS) + option[opts++][0]=0; +height=opts+4; +if(top+height>api->scrn_len-3) + height=(api->scrn_len-3)-top; +if(!width || width<strlen(title)+6) { + width=strlen(title)+6; + for(i=0;i<opts;i++) { + truncsp(option[i]); + if((j=strlen(option[i])+5)>width) + width=j; } } +if(width>(SCRN_RIGHT+1)-SCRN_LEFT) + width=(SCRN_RIGHT+1)-SCRN_LEFT; +if(mode&WIN_L2R) + left=36-(width/2); +else if(mode&WIN_RHT) + left=SCRN_RIGHT-(width+4+left); +if(mode&WIN_T2B) + top=(api->scrn_len/2)-(height/2)-2; +else if(mode&WIN_BOT) + top=api->scrn_len-height-3-top; +if(mode&WIN_SAV && api->savdepth==api->savnum) { + if((sav[api->savnum].buf=(char *)MALLOC((width+3)*(height+2)*2))==NULL) { + cprintf("UIFC line %d: error allocating %u bytes." + ,__LINE__,(width+3)*(height+2)*2); + return(-1); } + gettext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height,sav[api->savnum].buf); + sav[api->savnum].left=SCRN_LEFT+left; + sav[api->savnum].top=SCRN_TOP+top; + sav[api->savnum].right=SCRN_LEFT+left+width+1; + sav[api->savnum].bot=SCRN_TOP+top+height; + api->savdepth++; } +else if(mode&WIN_SAV + && (sav[api->savnum].left!=SCRN_LEFT+left + || sav[api->savnum].top!=SCRN_TOP+top + || sav[api->savnum].right!=SCRN_LEFT+left+width+1 + || sav[api->savnum].bot!=SCRN_TOP+top+height)) { /* dimensions have changed */ + puttext(sav[api->savnum].left,sav[api->savnum].top,sav[api->savnum].right,sav[api->savnum].bot + ,sav[api->savnum].buf); /* put original window back */ + FREE(sav[api->savnum].buf); + if((sav[api->savnum].buf=(char *)MALLOC((width+3)*(height+2)*2))==NULL) { + cprintf("UIFC line %d: error allocating %u bytes." + ,__LINE__,(width+3)*(height+2)*2); + return(-1); } + gettext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height,sav[api->savnum].buf); /* save again */ + sav[api->savnum].left=SCRN_LEFT+left; + sav[api->savnum].top=SCRN_TOP+top; + sav[api->savnum].right=SCRN_LEFT+left+width+1; + sav[api->savnum].bot=SCRN_TOP+top+height; } + + +#ifndef __FLAT__ +if(show_free_mem) { +/* ToDo Show free memory */ +// uprintf(58,1,bclr|(cclr<<4),"%10u bytes free",coreleft()); + } +#endif + + +if(mode&WIN_ORG) { /* Clear around menu */ + if(top) + puttext(SCRN_LEFT,SCRN_TOP,SCRN_RIGHT+2,SCRN_TOP+top-1,blk_scrn); + if(SCRN_TOP+height+top<=api->scrn_len) + puttext(SCRN_LEFT,SCRN_TOP+height+top,SCRN_RIGHT+2,api->scrn_len,blk_scrn); + if(left) + puttext(SCRN_LEFT,SCRN_TOP+top,SCRN_LEFT+left-1,SCRN_TOP+height+top + ,blk_scrn); + if(SCRN_LEFT+left+width<=SCRN_RIGHT) + puttext(SCRN_LEFT+left+width,SCRN_TOP+top,SCRN_RIGHT+2 + ,SCRN_TOP+height+top,blk_scrn); } +ptr=win; +*(ptr++)='É'; +*(ptr++)=hclr|(bclr<<4); + +if(api->mode&UIFC_MOUSE) { + /* ToDo Mouse stuff */ + i=0; +} +else + i=0; +for(;i<width-2;i++) { + *(ptr++)='Í'; + *(ptr++)=hclr|(bclr<<4); } +*(ptr++)='»'; +*(ptr++)=hclr|(bclr<<4); +*(ptr++)='º'; +*(ptr++)=hclr|(bclr<<4); +a=strlen(title); +b=(width-a-1)/2; +for(i=0;i<b;i++) { + *(ptr++)=' '; + *(ptr++)=hclr|(bclr<<4); } +for(i=0;i<a;i++) { + *(ptr++)=title[i]; + *(ptr++)=hclr|(bclr<<4); } +for(i=0;i<width-(a+b)-2;i++) { + *(ptr++)=' '; + *(ptr++)=hclr|(bclr<<4); } +*(ptr++)='º'; +*(ptr++)=hclr|(bclr<<4); +*(ptr++)='Ì'; +*(ptr++)=hclr|(bclr<<4); +for(i=0;i<width-2;i++) { + *(ptr++)='Í'; + *(ptr++)=hclr|(bclr<<4); } +*(ptr++)='¹'; +*(ptr++)=hclr|(bclr<<4); + +if((*cur)>=opts) + (*cur)=opts-1; /* returned after scrolled */ + +if(!bar) { + if((*cur)>height-5) + (*cur)=height-5; + i=0; } +else { + if((*bar)>=opts) + (*bar)=opts-1; + if((*bar)>height-5) + (*bar)=height-5; + if((*cur)==opts-1) + (*bar)=height-5; + if((*bar)<0) + (*bar)=0; + if((*cur)<(*bar)) + (*cur)=(*bar); + i=(*cur)-(*bar); +// + if(i+(height-5)>=opts) { + i=opts-(height-4); + (*cur)=i+(*bar); + } + } +if((*cur)<0) + (*cur)=0; + +j=0; +if(i<0) i=0; +longopt=0; +while(j<height-4 && i<opts) { + *(ptr++)='º'; + *(ptr++)=hclr|(bclr<<4); + *(ptr++)=' '; + *(ptr++)=hclr|(bclr<<4); + *(ptr++)='³'; + *(ptr++)=lclr|(bclr<<4); + if(i==(*cur)) + a=bclr|(LIGHTGRAY<<4); + else + a=lclr|(bclr<<4); + b=strlen(option[i]); + if(b>longopt) + longopt=b; + if(b+4>width) + b=width-4; + for(c=0;c<b;c++) { + *(ptr++)=option[i][c]; + *(ptr++)=a; } + while(c<width-4) { + *(ptr++)=' '; + *(ptr++)=a; + c++; } + *(ptr++)='º'; + *(ptr++)=hclr|(bclr<<4); + i++; + j++; } +*(ptr++)='È'; +*(ptr++)=hclr|(bclr<<4); +for(i=0;i<width-2;i++) { + *(ptr++)='Í'; + *(ptr++)=hclr|(bclr<<4); } +*(ptr++)='¼'; +*(ptr++)=hclr|(bclr<<4); +puttext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT+left+width-1 + ,SCRN_TOP+top+height-1,win); +if(bar) + y=top+3+(*bar); +else + y=top+3+(*cur); +if(opts+4>height && ((!bar && (*cur)!=opts-1) + || (bar && ((*cur)-(*bar))+(height-4)<opts))) { + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); + textattr(lclr|(bclr<<4)); + putch(31); /* put down arrow */ + textattr(hclr|(bclr<<4)); } + +if(bar && (*bar)!=(*cur)) { + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); + textattr(lclr|(bclr<<4)); + putch(30); /* put the up arrow */ + textattr(hclr|(bclr<<4)); } + +if(bclr==BLUE) { + gettext(SCRN_LEFT+left+width,SCRN_TOP+top+1,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height-1,shade); + for(i=1;i<height*4;i+=2) + shade[i]=DARKGRAY; + puttext(SCRN_LEFT+left+width,SCRN_TOP+top+1,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height-1,shade); + gettext(SCRN_LEFT+left+2,SCRN_TOP+top+height,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height,shade); + for(i=1;i<width*2;i+=2) + shade[i]=DARKGRAY; + puttext(SCRN_LEFT+left+2,SCRN_TOP+top+height,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height,shade); } +showmouse(); +while(1) { +#if 0 /* debug */ + gotoxy(30,1); + cprintf("y=%2d h=%2d c=%2d b=%2d s=%2d o=%2d" + ,y,height,*cur,bar ? *bar :0xff,api->savdepth,opts); +#endif + if(!show_free_mem) + timedisplay(); +#ifndef __FLAT__ + if(api->mode&UIFC_MOUSE) { + /* ToDo Serious mouse stuff here */ + } +#endif + + if(inkey(1)) { + i=inkey(0); + if(i>255) { + s=0; + switch(i) { + /* ToDo extended keys */ + case KEY_HOME: /* home */ + if(!opts) + break; + if(opts+4>height) { + hidemouse(); + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); + textattr(lclr|(bclr<<4)); + putch(' '); /* Delete the up arrow */ + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); + putch(31); /* put the down arrow */ + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3 + ,bclr|(LIGHTGRAY<<4) + ,"%-*.*s",width-4,width-4,option[0]); + for(i=1;i<height-4;i++) /* re-display options */ + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3+i + ,lclr|(bclr<<4) + ,"%-*.*s",width-4,width-4,option[i]); + (*cur)=0; + if(bar) + (*bar)=0; + y=top+3; + showmouse(); + break; } + hidemouse(); + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<width*2;i+=2) + line[i]=lclr|(bclr<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + (*cur)=0; + if(bar) + (*bar)=0; + y=top+3; + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<width*2;i+=2) + line[i]=bclr|(LIGHTGRAY<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + showmouse(); + break; + case KEY_UP: /* up arrow */ + if(!opts) + break; + if(!(*cur) && opts+4>height) { + hidemouse(); + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); /* like end */ + textattr(lclr|(bclr<<4)); + putch(30); /* put the up arrow */ + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); + putch(' '); /* delete the down arrow */ + for(i=(opts+4)-height,j=0;i<opts;i++,j++) + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3+j + ,i==opts-1 ? bclr|(LIGHTGRAY<<4) + : lclr|(bclr<<4) + ,"%-*.*s",width-4,width-4,option[i]); + (*cur)=opts-1; + if(bar) + (*bar)=height-5; + y=top+height-2; + showmouse(); + break; } + hidemouse(); + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<width*2;i+=2) + line[i]=lclr|(bclr<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + showmouse(); + if(!(*cur)) { + y=top+height-2; + (*cur)=opts-1; + if(bar) + (*bar)=height-5; } + else { + (*cur)--; + y--; + if(bar && *bar) + (*bar)--; } + if(y<top+3) { /* scroll */ + hidemouse(); + if(!(*cur)) { + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); + textattr(lclr|(bclr<<4)); + putch(' '); } /* delete the up arrow */ + if((*cur)+height-4==opts-1) { + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); + textattr(lclr|(bclr<<4)); + putch(31); } /* put the dn arrow */ + y++; + scroll_text(SCRN_LEFT+left+2,SCRN_TOP+top+3 + ,SCRN_LEFT+left+width-3,SCRN_TOP+top+height-2,1); + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3 + ,bclr|(LIGHTGRAY<<4) + ,"%-*.*s",width-4,width-4,option[*cur]); + showmouse(); } + else { + hidemouse(); + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<width*2;i+=2) + line[i]=bclr|(LIGHTGRAY<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + showmouse(); } + break; +#if 0 + case KEY_PPAGE; /* PgUp */ + case KEY_NPAGE; /* PgDn */ + if(!opts || (*cur)==(opts-1)) + break; + (*cur)+=(height-4); + if((*cur)>(opts-1)) + (*cur)=(opts-1); + + hidemouse(); + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<width*2;i+=2) + line[i]=lclr|(bclr<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + + for(i=(opts+4)-height,j=0;i<opts;i++,j++) + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3+j + ,i==(*cur) bclr|(LIGHTGRAY<<4) : lclr|(bclr<<4) + ,"%-*.*s",width-4,width-4,option[i]); + y=top+height-2; + if(bar) + (*bar)=height-5; + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<148;i+=2) + line[i]=bclr|(LIGHTGRAY<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + showmouse(); + break; +#endif + case KEY_END: /* end */ + if(!opts) + break; + if(opts+4>height) { /* Scroll mode */ + hidemouse(); + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); + textattr(lclr|(bclr<<4)); + putch(30); /* put the up arrow */ + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); + putch(' '); /* delete the down arrow */ + for(i=(opts+4)-height,j=0;i<opts;i++,j++) + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3+j + ,i==opts-1 ? bclr|(LIGHTGRAY<<4) + : lclr|(bclr<<4) + ,"%-*.*s",width-4,width-4,option[i]); + (*cur)=opts-1; + y=top+height-2; + if(bar) + (*bar)=height-5; + showmouse(); + break; } + hidemouse(); + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<width*2;i+=2) + line[i]=lclr|(bclr<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + (*cur)=opts-1; + y=top+height-2; + if(bar) + (*bar)=height-5; + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<148;i+=2) + line[i]=bclr|(LIGHTGRAY<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + showmouse(); + break; + case KEY_DOWN: /* dn arrow */ + if(!opts) + break; + if((*cur)==opts-1 && opts+4>height) { /* like home */ + hidemouse(); + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); + textattr(lclr|(bclr<<4)); + putch(' '); /* Delete the up arrow */ + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); + putch(31); /* put the down arrow */ + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3 + ,bclr|(LIGHTGRAY<<4) + ,"%-*.*s",width-4,width-4,option[0]); + for(i=1;i<height-4;i++) /* re-display options */ + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3+i + ,lclr|(bclr<<4) + ,"%-*.*s",width-4,width-4,option[i]); + (*cur)=0; + y=top+3; + if(bar) + (*bar)=0; + showmouse(); + break; } + hidemouse(); + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<width*2;i+=2) + line[i]=lclr|(bclr<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + showmouse(); + if((*cur)==opts-1) { + (*cur)=0; + y=top+3; + if(bar) { + /* gotoxy(1,1); cprintf("bar=%08lX ",bar); */ + (*bar)=0; } } + else { + (*cur)++; + y++; + if(bar && (*bar)<height-5) { + /* gotoxy(1,1); cprintf("bar=%08lX ",bar); */ + (*bar)++; } } + if(y==top+height-1) { /* scroll */ + hidemouse(); + if(*cur==opts-1) { + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); + textattr(lclr|(bclr<<4)); + putch(' '); } /* delete the down arrow */ + if((*cur)+4==height) { + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); + textattr(lclr|(bclr<<4)); + putch(30); } /* put the up arrow */ + y--; + /* gotoxy(1,1); cprintf("\rdebug: %4d ",__LINE__); */ + scroll_text(SCRN_LEFT+left+2,SCRN_TOP+top+3 + ,SCRN_LEFT+left+width-3,SCRN_TOP+top+height-2,0); + /* gotoxy(1,1); cprintf("\rdebug: %4d ",__LINE__); */ + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+height-2 + ,bclr|(LIGHTGRAY<<4) + ,"%-*.*s",width-4,width-4,option[*cur]); + showmouse(); } + else { + hidemouse(); + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y + ,line); + for(i=1;i<width*2;i+=2) + line[i]=bclr|(LIGHTGRAY<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y + ,line); + showmouse(); } + break; + case KEY_F(1): /* F1 */ + help(); + break; + case KEY_F(5): /* F5 */ + if(mode&WIN_GET && !(mode&WIN_XTR && (*cur)==opts-1)) + return((*cur)|MSK_GET); + break; + case KEY_F(6): /* F6 */ + if(mode&WIN_PUT && !(mode&WIN_XTR && (*cur)==opts-1)) + return((*cur)|MSK_PUT); + break; + case KEY_IC: /* insert */ + if(mode&WIN_INS) { + if(mode&WIN_INSACT) { + hidemouse(); + gettext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT + +left+width-1,SCRN_TOP+top+height-1,win); + for(i=1;i<(width*height*2);i+=2) + win[i]=lclr|(cclr<<4); + if(opts) { + j=(((y-top)*width)*2)+7+((width-4)*2); + for(i=(((y-top)*width)*2)+7;i<j;i+=2) + win[i]=hclr|(cclr<<4); } + puttext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT + +left+width-1,SCRN_TOP+top+height-1,win); + showmouse(); } + if(!opts) + return(MSK_INS); + return((*cur)|MSK_INS); } + break; + case KEY_DC: /* delete */ + if(mode&WIN_XTR && (*cur)==opts-1) /* can't delete */ + break; /* extra line */ + if(mode&WIN_DEL) { + if(mode&WIN_DELACT) { + hidemouse(); + gettext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT + +left+width-1,SCRN_TOP+top+height-1,win); + for(i=1;i<(width*height*2);i+=2) + win[i]=lclr|(cclr<<4); + j=(((y-top)*width)*2)+7+((width-4)*2); + for(i=(((y-top)*width)*2)+7;i<j;i+=2) + win[i]=hclr|(cclr<<4); + puttext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT + +left+width-1,SCRN_TOP+top+height-1,win); + showmouse(); } + return((*cur)|MSK_DEL); } + break; } } + else { + i&=0xff; + if(isalnum(i) && opts && option[0][0]) { + search[s]=i; + search[s+1]=0; + for(j=(*cur)+1,a=b=0;a<2;j++) { /* a = search count */ + if(j==opts) { /* j = option count */ + j=-1; /* b = letter count */ + continue; } + if(j==(*cur)) { + b++; + continue; } + if(b>=longopt) { + b=0; + a++; } + if(a==1 && !s) + break; + if(strlen(option[j])>b + && ((!a && s && !strncasecmp(option[j]+b,search,s+1)) + || ((a || !s) && toupper(option[j][b])==toupper(i)))) { + if(a) s=0; + else s++; + if(y+(j-(*cur))+2>height+top) { + (*cur)=j; + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); + textattr(lclr|(bclr<<4)); + putch(30); /* put the up arrow */ + if((*cur)==opts-1) { + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); + putch(' '); } /* delete the down arrow */ + for(i=((*cur)+5)-height,j=0;i<(*cur)+1;i++,j++) + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3+j + ,i==(*cur) ? bclr|(LIGHTGRAY<<4) + : lclr|(bclr<<4) + ,"%-*.*s",width-4,width-4,option[i]); + y=top+height-2; + if(bar) + (*bar)=height-5; + break; } + if(y-((*cur)-j)<top+3) { + (*cur)=j; + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); + textattr(lclr|(bclr<<4)); + if(!(*cur)) + putch(' '); /* Delete the up arrow */ + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); + putch(31); /* put the down arrow */ + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3 + ,bclr|(LIGHTGRAY<<4) + ,"%-*.*s",width-4,width-4,option[(*cur)]); + for(i=1;i<height-4;i++) /* re-display options */ + uprintf(SCRN_LEFT+left+3,SCRN_TOP+top+3+i + ,lclr|(bclr<<4) + ,"%-*.*s",width-4,width-4 + ,option[(*cur)+i]); + y=top+3; + if(bar) + (*bar)=0; + break; } + hidemouse(); + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<width*2;i+=2) + line[i]=lclr|(bclr<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + if((*cur)>j) + y-=(*cur)-j; + else + y+=j-(*cur); + if(bar) { + if((*cur)>j) + (*bar)-=(*cur)-j; + else + (*bar)+=j-(*cur); } + (*cur)=j; + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i<width*2;i+=2) + line[i]=bclr|(LIGHTGRAY<<4); + puttext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + showmouse(); + break; } } + if(a==2) + s=0; } + else + switch(i) { + case CR: + if(!opts || (mode&WIN_XTR && (*cur)==opts-1)) + break; + if(mode&WIN_ACT) { + hidemouse(); + gettext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT + +left+width-1,SCRN_TOP+top+height-1,win); + for(i=1;i<(width*height*2);i+=2) + win[i]=lclr|(cclr<<4); + j=(((y-top)*width)*2)+7+((width-4)*2); + for(i=(((y-top)*width)*2)+7;i<j;i+=2) + win[i]=hclr|(cclr<<4); + + puttext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT + +left+width-1,SCRN_TOP+top+height-1,win); + showmouse(); } + else if(mode&WIN_SAV) { + hidemouse(); + puttext(sav[api->savnum].left,sav[api->savnum].top + ,sav[api->savnum].right,sav[api->savnum].bot + ,sav[api->savnum].buf); + showmouse(); + FREE(sav[api->savnum].buf); + api->savdepth--; } + return(*cur); + case ESC: + if((mode&WIN_ESC || (mode&WIN_CHE && api->changes)) + && !(mode&WIN_SAV)) { + hidemouse(); + gettext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT + +left+width-1,SCRN_TOP+top+height-1,win); + for(i=1;i<(width*height*2);i+=2) + win[i]=lclr|(cclr<<4); + puttext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT + +left+width-1,SCRN_TOP+top+height-1,win); + showmouse(); } + else if(mode&WIN_SAV) { + hidemouse(); + puttext(sav[api->savnum].left,sav[api->savnum].top + ,sav[api->savnum].right,sav[api->savnum].bot + ,sav[api->savnum].buf); + showmouse(); + FREE(sav[api->savnum].buf); + api->savdepth--; } + return(-1); } } } + else + mswait(1); + } +} + + +/*************************************************************************/ +/* This function is a windowed input string input routine. */ +/*************************************************************************/ +int uinput(int mode, int left, int top, char *prompt, char *str, + int max, int kmode) +{ + unsigned char c,save_buf[2048],in_win[2048] + ,shade[160],width,height=3; + int i,plen,slen; + +hidemouse(); +plen=strlen(prompt); +if(!plen) + slen=4; +else + slen=6; +width=plen+slen+max; +if(mode&WIN_T2B) + top=(api->scrn_len/2)-(height/2)-2; +if(mode&WIN_L2R) + left=36-(width/2); +if(mode&WIN_SAV) + gettext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height,save_buf); +i=0; +in_win[i++]='É'; +in_win[i++]=hclr|(bclr<<4); +for(c=1;c<width-1;c++) { + in_win[i++]='Í'; + in_win[i++]=hclr|(bclr<<4); } +in_win[i++]='»'; +in_win[i++]=hclr|(bclr<<4); +in_win[i++]='º'; +in_win[i++]=hclr|(bclr<<4); + +if(plen) { + in_win[i++]=SP; + in_win[i++]=lclr|(bclr<<4); } + +for(c=0;prompt[c];c++) { + in_win[i++]=prompt[c]; + in_win[i++]=lclr|(bclr<<4); } + +if(plen) { + in_win[i++]=':'; + in_win[i++]=lclr|(bclr<<4); + c++; } + +for(c=0;c<max+2;c++) { + in_win[i++]=SP; + in_win[i++]=lclr|(bclr<<4); } + +in_win[i++]='º'; +in_win[i++]=hclr|(bclr<<4); +in_win[i++]='È'; +in_win[i++]=hclr|(bclr<<4); +for(c=1;c<width-1;c++) { + in_win[i++]='Í'; + in_win[i++]=hclr|(bclr<<4); } +in_win[i++]='¼'; +in_win[i++]=hclr|(bclr<<4); +puttext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT+left+width-1 + ,SCRN_TOP+top+height-1,in_win); + +if(bclr==BLUE) { + gettext(SCRN_LEFT+left+width,SCRN_TOP+top+1,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+(height-1),shade); + for(c=1;c<12;c+=2) + shade[c]=DARKGRAY; + puttext(SCRN_LEFT+left+width,SCRN_TOP+top+1,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+(height-1),shade); + gettext(SCRN_LEFT+left+2,SCRN_TOP+top+3,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height,shade); + for(c=1;c<width*2;c+=2) + shade[c]=DARKGRAY; + puttext(SCRN_LEFT+left+2,SCRN_TOP+top+3,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height,shade); } + +textattr(lclr|(bclr<<4)); +if(!plen) + gotoxy(SCRN_LEFT+left+2,SCRN_TOP+top+1); +else + gotoxy(SCRN_LEFT+left+plen+4,SCRN_TOP+top+1); +i=ugetstr(str,max,kmode); +if(mode&WIN_SAV) + puttext(SCRN_LEFT+left,SCRN_TOP+top,SCRN_LEFT+left+width+1 + ,SCRN_TOP+top+height,save_buf); +showmouse(); +return(i); +} + +/****************************************************************************/ +/* Displays the message 'str' and waits for the user to select "OK" */ +/****************************************************************************/ +void umsg(char *str) +{ + int i=0; + char *ok[2]={"OK",""}; + +if(api->mode&UIFC_INMSG) /* non-cursive */ + return; +api->mode|=UIFC_INMSG; +if(api->savdepth) api->savnum++; +ulist(WIN_SAV|WIN_MID,0,0,0,&i,0,str,ok); +if(api->savdepth) api->savnum--; +api->mode&=~UIFC_INMSG; +} + +/****************************************************************************/ +/* Gets a string of characters from the user. Turns cursor on. Allows */ +/* Different modes - K_* macros. ESC aborts input. */ +/* Cursor should be at END of where string prompt will be placed. */ +/****************************************************************************/ +static int ugetstr(char *outstr, int max, long mode) +{ + uchar str[256],ins=0,buf[256],y; + int ch; + int i,j,k,f=0; /* i=offset, j=length */ +#ifndef __FLAT__ + union REGS r; +#endif + +curs_set(1); +y=wherey(); +if(mode&K_EDIT) { +/*** + truncsp(outstr); +***/ + outstr[max]=0; + textattr(bclr|(LIGHTGRAY<<4)); + cputs(outstr); + textattr(lclr|(bclr<<4)); + strcpy(str,outstr); + i=j=strlen(str); + while(inkey(1)==0) { +#ifndef __FLAT__ + if(api->mode&UIFC_MOUSE) { + /* ToDo More mouse stuff */ + } +#endif + mswait(1); + } + f=inkey(0); + gotoxy(wherex()-i,y); + if(f != KEY_DC && f != KEY_BACKSPACE) + { + cputs(outstr); + if(isprint(f)) + { + putch(f); + i++; + j++; + } + } + else + { + cprintf("%*s",i,""); + gotoxy(wherex()-i,y); + i=j=0; + } +} +else + i=j=0; + +ch=0; +while(ch!=CR) +{ + if(i>j) j=i; +#ifndef __FLAT__ + if(api->mode&UIFC_MOUSE) + { + /* ToDo More Mouse Stuff */ + } +#endif + if(inkey(1)) + { + ch=inkey(0); + switch(ch) + { + case KEY_F(1): /* F1 Help */ + help(); + continue; + case KEY_LEFT: /* left arrow */ + if(i) + { + gotoxy(wherex()-1,y); + i--; + } + continue; + case KEY_RIGHT: /* right arrow */ + if(i<j) + { + gotoxy(wherex()+1,y); + i++; + } + continue; + case KEY_HOME: /* home */ + if(i) + { + gotoxy(wherex()-i,y); + i=0; + } + continue; + case KEY_END: /* end */ + if(i<j) + { + gotoxy(wherex()+(j-i),y); + i=j; + } + continue; + case KEY_IC: /* insert */ + ins=!ins; + if(ins) + { + curs_set(2); + refresh(); + } + else + { + curs_set(1); + refresh(); + } + continue; + case BS: + case KEY_BACKSPACE: + if(i) + { + if(i==j) + { + cputs("\b \b"); + j--; + i--; + } + else { + gettext(wherex(),y,wherex()+(j-i),y,buf); + puttext(wherex()-1,y,wherex()+(j-i)-1,y,buf); + gotoxy(wherex()+(j-i),y); + putch(SP); + gotoxy(wherex()-((j-i)+2),y); + i--; + j--; + for(k=i;k<j;k++) + str[k]=str[k+1]; + } + continue; + } + case KEY_DC: /* delete */ + if(i<j) + { + gettext(wherex()+1,y,wherex()+(j-i),y,buf); + puttext(wherex(),y,wherex()+(j-i)-1,y,buf); + gotoxy(wherex()+(j-i),y); + putch(SP); + gotoxy(wherex()-((j-i)+1),y); + for(k=i;k<j;k++) + str[k]=str[k+1]; + j--; + } + continue; + case 03: + case ESC: + { + curs_set(0); + refresh(); + return(-1); + } + case CR: + break; + case 24: /* ctrl-x */ + if(j) + { + gotoxy(wherex()-i,y); + cprintf("%*s",j,""); + gotoxy(wherex()-j,y); + i=j=0; + } + continue; + case 25: /* ctrl-y */ + if(i<j) + { + cprintf("%*s",(j-i),""); + gotoxy(wherex()-(j-i),y); + j=i; + } + continue; + } + if(mode&K_NUMBER && !isdigit(ch)) + continue; + if(mode&K_ALPHA && !isalpha(ch)) + continue; + if((ch>=SP || (ch==1 && mode&K_MSG)) && i<max && (!ins || j<max)) + { + if(mode&K_UPPER) + ch=toupper(ch); + if(ins) + { + gettext(wherex(),y,wherex()+(j-i),y,buf); + puttext(wherex()+1,y,wherex()+(j-i)+1,y,buf); + for(k=++j;k>i;k--) + str[k]=str[k-1]; + } + putch(ch); + str[i++]=ch; + } + } + else + mswait(1); +} + + + str[j]=0; + if(mode&K_EDIT) + { + truncsp(str); + if(strcmp(outstr,str)) + api->changes=1; + } + else + { + if(j) + api->changes=1; + } + strcpy(outstr,str); + curs_set(0); + refresh(); + return(j); +} + +/****************************************************************************/ +/* Performs printf() through puttext() routine */ +/****************************************************************************/ +static int uprintf(int x, int y, unsigned char attr, char *fmat, ...) +{ + va_list argptr; + char str[256],buf[512]; + int i,j; + + va_start(argptr,fmat); + vsprintf(str,fmat,argptr); + va_end(argptr); + for(i=j=0;str[i];i++) { + buf[j++]=str[i]; + buf[j++]=attr; } + puttext(x,y,x+(i-1),y,buf); + return(i); +} + + +/****************************************************************************/ +/* Display bottom line of screen in inverse */ +/****************************************************************************/ +void bottomline(int line) +{ + int i=4; +uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"F1 "); +i+=3; +uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Help "); +i+=6; +if(line&BL_GET) { + uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"F5 "); + i+=3; + uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Copy Item "); + i+=11; } +if(line&BL_PUT) { + uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"F6 "); + i+=3; + uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Paste "); + i+=7; } +if(line&BL_INS) { + uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"INS "); + i+=4; + uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Add Item "); + i+=10; } +if(line&BL_DEL) { + uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"DEL "); + i+=4; + uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Delete Item "); + i+=13; } +uprintf(i,api->scrn_len+1,bclr|(cclr<<4),"ESC "); +i+=4; +uprintf(i,api->scrn_len+1,BLACK|(cclr<<4),"Exit"); +i+=4; +gotoxy(i,api->scrn_len+1); +textattr(BLACK|(cclr<<4)); +clrtoeol(); +} + + +/*****************************************************************************/ +/* Generates a 24 character ASCII string that represents the time_t pointer */ +/* Used as a replacement for ctime() */ +/*****************************************************************************/ +char *utimestr(time_t *intime) +{ + static char str[25]; + char wday[4],mon[4],mer[3],hour; + struct tm *gm; + +gm=localtime(intime); +switch(gm->tm_wday) { + case 0: + strcpy(wday,"Sun"); + break; + case 1: + strcpy(wday,"Mon"); + break; + case 2: + strcpy(wday,"Tue"); + break; + case 3: + strcpy(wday,"Wed"); + break; + case 4: + strcpy(wday,"Thu"); + break; + case 5: + strcpy(wday,"Fri"); + break; + case 6: + strcpy(wday,"Sat"); + break; } +switch(gm->tm_mon) { + case 0: + strcpy(mon,"Jan"); + break; + case 1: + strcpy(mon,"Feb"); + break; + case 2: + strcpy(mon,"Mar"); + break; + case 3: + strcpy(mon,"Apr"); + break; + case 4: + strcpy(mon,"May"); + break; + case 5: + strcpy(mon,"Jun"); + break; + case 6: + strcpy(mon,"Jul"); + break; + case 7: + strcpy(mon,"Aug"); + break; + case 8: + strcpy(mon,"Sep"); + break; + case 9: + strcpy(mon,"Oct"); + break; + case 10: + strcpy(mon,"Nov"); + break; + case 11: + strcpy(mon,"Dec"); + break; } +if(gm->tm_hour>12) { + strcpy(mer,"pm"); + hour=gm->tm_hour-12; } +else { + if(!gm->tm_hour) + hour=12; + else + hour=gm->tm_hour; + strcpy(mer,"am"); } +sprintf(str,"%s %s %02d %4d %02d:%02d %s",wday,mon,gm->tm_mday,1900+gm->tm_year + ,hour,gm->tm_min,mer); +return(str); +} + +/****************************************************************************/ +/* Status popup/down function, see uifc.h for details. */ +/****************************************************************************/ +void upop(char *str) +{ + static char sav[26*3*2]; + char buf[26*3*2]; + int i,j,k; + + hidemouse(); + if(!str) { + puttext(28,12,53,14,sav); + showmouse(); + return; } + gettext(28,12,53,14,sav); + memset(buf,SP,25*3*2); + for(i=1;i<26*3*2;i+=2) + buf[i]=(hclr|(bclr<<4)); + buf[0]='Ú'; + for(i=2;i<25*2;i+=2) + buf[i]='Ä'; + buf[i]='¿'; i+=2; + buf[i]='³'; i+=2; + i+=2; + k=strlen(str); + i+=(((23-k)/2)*2); + for(j=0;j<k;j++,i+=2) { + buf[i]=str[j]; + buf[i+1]|=BLINK; } + i=((25*2)+1)*2; + buf[i]='³'; i+=2; + buf[i]='À'; i+=2; + for(;i<((26*3)-1)*2;i+=2) + buf[i]='Ä'; + buf[i]='Ù'; + + puttext(28,12,53,14,buf); + showmouse(); +} + +/****************************************************************************/ +/* Sets the current help index by source code file and line number. */ +/****************************************************************************/ +void sethelp(int line, char* file) +{ + helpline=line; + helpfile=file; +} + +/************************************************************/ +/* Help (F1) key function. Uses helpbuf as the help input. */ +/************************************************************/ +void help() +{ + char *savscrn,*buf,inverse=0,high=0 + ,hbuf[HELPBUF_SIZE],str[256]; + char *p; + uint i,j,k,len; + unsigned short line; + long l; + FILE *fp; +#ifndef __FLAT__ + union REGS r; +#endif + + curs_set(0); + + if((savscrn=(char *)MALLOC(80*25*2))==NULL) { + cprintf("UIFC line %d: error allocating %u bytes\r\n" + ,__LINE__,80*25*2); + curs_set(1); + return; } + if((buf=(char *)MALLOC(76*21*2))==NULL) { + cprintf("UIFC line %d: error allocating %u bytes\r\n" + ,__LINE__,76*21*2); + FREE(savscrn); + curs_set(1); + return; } + hidemouse(); + gettext(1,1,80,25,savscrn); + memset(buf,SP,76*21*2); + for(i=1;i<76*21*2;i+=2) + buf[i]=(hclr|(bclr<<4)); + buf[0]='Ú'; + for(i=2;i<30*2;i+=2) + buf[i]='Ä'; + buf[i]='´'; i+=4; + buf[i]='O'; i+=2; + buf[i]='n'; i+=2; + buf[i]='l'; i+=2; + buf[i]='i'; i+=2; + buf[i]='n'; i+=2; + buf[i]='e'; i+=4; + buf[i]='H'; i+=2; + buf[i]='e'; i+=2; + buf[i]='l'; i+=2; + buf[i]='p'; i+=4; + buf[i]='Ã'; i+=2; + for(j=i;j<i+(30*2);j+=2) + buf[j]='Ä'; + i=j; + buf[i]='¿'; i+=2; + j=i; /* leave i alone */ + for(k=0;k<19;k++) { /* the sides of the box */ + buf[j]='³'; j+=2; + j+=(74*2); + buf[j]='³'; j+=2; } + buf[j]='À'; j+=2; + for(k=j;k<j+(23*2);k+=2) + buf[k]='Ä'; + buf[k]='´'; k+=4; + buf[k]='H'; k+=2; + buf[k]='i'; k+=2; + buf[k]='t'; k+=4; + buf[k]='a'; k+=2; + buf[k]='n'; k+=2; + buf[k]='y'; k+=4; + buf[k]='k'; k+=2; + buf[k]='e'; k+=2; + buf[k]='y'; k+=4; + buf[k]='t'; k+=2; + buf[k]='o'; k+=4; + buf[k]='c'; k+=2; + buf[k]='o'; k+=2; + buf[k]='n'; k+=2; + buf[k]='t'; k+=2; + buf[k]='i'; k+=2; + buf[k]='n'; k+=2; + buf[k]='u'; k+=2; + buf[k]='e'; k+=4; + buf[k]='Ã'; k+=2; + for(j=k;j<k+(24*2);j+=2) + buf[j]='Ä'; + buf[j]='Ù'; + + if(!api->helpbuf) { + if((fp=_fsopen(api->helpixbfile,"rb",SH_DENYWR))==NULL) + sprintf(hbuf," ERROR Cannot open help index:\r\n %s" + ,api->helpixbfile); + else { + p=strrchr(helpfile,'/'); + if(p==NULL) + p=strrchr(helpfile,'\\'); + if(p==NULL) + p=helpfile; + else + p++; + l=-1L; + while(!feof(fp)) { + if(!fread(str,12,1,fp)) + break; + str[12]=0; + fread(&line,2,1,fp); + if(stricmp(str,p) || line!=helpline) { + fseek(fp,4,SEEK_CUR); + continue; } + fread(&l,4,1,fp); + break; } + fclose(fp); + if(l==-1L) + sprintf(hbuf," ERROR Cannot locate help key (%s:%u) in:\r\n" + " %s",p,helpline,api->helpixbfile); + else { + if((fp=_fsopen(api->helpdatfile,"rb",SH_DENYWR))==NULL) + sprintf(hbuf," ERROR Cannot open help file:\r\n %s" + ,api->helpdatfile); + else { + fseek(fp,l,SEEK_SET); + fread(hbuf,HELPBUF_SIZE,1,fp); + fclose(fp); } } } } + else + strcpy(hbuf,api->helpbuf); + + len=strlen(hbuf); + + i+=78*2; + for(j=0;j<len;j++,i+=2) { + if(hbuf[j]==LF) { + while(i%(76*2)) i++; + i+=2; } + else if(hbuf[j]==2) { /* Ctrl-b toggles inverse */ + inverse=!inverse; + i-=2; } + else if(hbuf[j]==1) { /* Ctrl-a toggles high intensity */ + high=!high; + i-=2; } + else if(hbuf[j]!=CR) { + buf[i]=hbuf[j]; + buf[i+1]=inverse ? (bclr|(cclr<<4)) + : high ? (hclr|(bclr<<4)) : (lclr|(bclr<<4)); } } + puttext(3,3,78,23,buf); + showmouse(); + while(1) { + if(inkey(1)) { + inkey(0); + break; } + #ifndef __FLAT__ + if(api->mode&UIFC_MOUSE) { + /* ToDo more mouse stiff */ + } + #endif + mswait(1); + } + + hidemouse(); + puttext(1,1,80,25,savscrn); + showmouse(); + FREE(savscrn); + FREE(buf); + curs_set(1); +} + +static int puttext(int sx, int sy, int ex, int ey, unsigned char *fill) +{ + int x,y; + int fillpos=0; + unsigned char attr; + unsigned char fill_char; + unsigned char orig_attr; + int oldx, oldy; + + getyx(stdscr,oldy,oldx); + orig_attr=lastattr; + for(y=sy-1;y<=ey-1;y++) + { + for(x=sx-1;x<=ex-1;x++) + { + fill_char=fill[fillpos++]; + attr=fill[fillpos++]; + textattr(attr); + mvaddch(y, x, fill_char); + } + } + textattr(orig_attr); + move(oldy, oldx); + refresh(); + return(1); +} + +static int gettext(int sx, int sy, int ex, int ey, unsigned char *fill) +{ + int x,y; + int fillpos=0; + chtype attr; + unsigned char attrib; + unsigned char colour; + int oldx, oldy; + + getyx(stdscr,oldy,oldx); + for(y=sy-1;y<=ey-1;y++) + { + for(x=sx-1;x<=ex-1;x++) + { + attr=mvinch(y, x); + fill[fillpos++]=(unsigned char)(attr&255); + attrib=0; + if (attr & A_BOLD) + { + attrib |= 8; + } + if (attr & A_BLINK) + { + attrib |= 128; + } + colour=PAIR_NUMBER(attr&A_COLOR)-1; + colour=((colour&56)<<1)|(colour&7); + fill[fillpos++]=colour|attrib; + } + } + move(oldy, oldx); + return(1); +} + +static void textattr(unsigned char attr) +{ + int attrs=A_NORMAL; + short colour; + + if (lastattr==attr) + return; + + lastattr=attr; + + if (attr & 8) { + attrs |= A_BOLD; + } + if (attr & 128) + { + attrs |= A_BLINK; + } + attrset(attrs); + colour = COLOR_PAIR( ((attr&7)|((attr>>1)&56))+1 ); + color_set(colour,NULL); + bkgdset(colour); +} + +static int kbhit(void) +{ + struct timeval timeout; + fd_set rfds; + + timeout.tv_sec=5; + timeout.tv_usec=0; + FD_ZERO(&rfds); + FD_SET(fileno(stdin),&rfds); + + return(select(fileno(stdin)+1,&rfds,NULL,NULL,&timeout)); +} + +static void delay(msec) +{ + usleep(msec*1000); +} + +static int wherey(void) +{ + int x,y; + getyx(stdscr,y,x); + return(y+1); +} + +static int wherex(void) +{ + int x,y; + getyx(stdscr,y,x); + return(x+1); +} + +static FILE * _fsopen(char *pathname, char *mode, int flags) +{ + FILE *thefile; + + thefile = fopen(pathname, mode); + if (thefile != NULL) { + if (flags&SH_DENYWR) { + flock(fileno(thefile), LOCK_SH); + return(thefile); + } + if (flags&SH_DENYRW) { + flock(fileno(thefile), LOCK_EX); + return(thefile); + } + } + return(thefile); +} + +static void putch(unsigned char ch) +{ + addch(ch); + refresh(); +} + +static int cprintf(char *fmat, ...) +{ + va_list argptr; + + va_start(argptr,fmat); + vwprintw(stdscr,fmat,argptr); + va_end(argptr); + refresh(); + return(1); +} + +static void cputs(char *str) +{ + addstr(str); + refresh(); +} + +static void gotoxy(int x, int y) +{ + move(y-1,x-1); + refresh(); +}