--- sbbs/uifc/uifc.c 2018/04/24 16:37:52 1.1 +++ sbbs/uifc/uifc.c 2018/04/24 16:41:22 1.1.1.3 @@ -1,14 +1,59 @@ -#line 1 "UIFC.C" +/* uifc.c */ -#include "UIFC.h" +/* Original implementation of UIFC (user interface) library based on conio */ +/* $Id: uifc.c,v 1.1.1.3 2018/04/24 16:41:22 root Exp $ */ -#if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -#define MALLOC farmalloc -#define FREE farfree -#else -#define MALLOC malloc -#define FREE free +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details: lgpl.txt or * + * http://www.fsf.org/copyleft/lesser.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 +#include + +#if defined(__OS2__) + +#define INCL_BASE +#include + +void mswait(int msec) +{ +DosSleep(msec ? msec : 1); +} + +#elif defined(_WIN32) + #include + #define mswait(x) Sleep(x) +#elif defined(__FLAT__) + #define mswait(x) delay(x) #endif /* Bottom line elements */ @@ -17,97 +62,332 @@ #define BL_GET (1<<2) /* Get key */ #define BL_PUT (1<<3) /* Put key */ +static char hclr,lclr,bclr,cclr,show_free_mem=0; +static int cursor; +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; + +/* Prototypes */ +static int uprintf(int x, int y, char attr, char *fmt,...); +static void bottomline(int line); +static char *utimestr(time_t *intime); +static void help(void); +static int getstr(char *outstr, int max, long mode); + +/* 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); +static void timedisplay(void); -char hclr,lclr,bclr,cclr,scrn_len,savnum=0 - ,blk_scrn[MAX_BFLN],savdepth=0,changes=0,uifc_status=0; -win_t sav[MAX_BUFS]; -uint cursor; +#ifdef __FLAT__ +int inkey(int mode) +{ + int c; -extern int daylight=0; +if(mode) + return(kbhit()); +c=getch(); +if(!c) + c=(getch()<<8); +return(c); +} +#else +int inkey(int mode) +{ +if(mode) + return(bioskey(1)); +while(!bioskey(1)); +return(bioskey(0)); +} +#endif -void bottomline(int line); +static uint mousecursor=0x28; -void uifcini() +/****************************************************************************/ +/* Initialization function, see uifc.h for details. */ +/* Returns 0 on success. */ +/****************************************************************************/ +int uifcini(uifcapi_t* uifcapi) { int i; struct text_info txtinfo; +#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; + api->showhelp=help; + api->showbuf=NULL; + api->timedisplay=timedisplay; + + if(api->scrn_len!=0) { + switch(api->scrn_len) { + case 14: + textmode(C80X14); + break; + case 21: + textmode(C80X21); + break; + case 25: + textmode(C80); + break; + case 28: + textmode(C80X28); + break; + case 43: + textmode(C80X43); + break; + case 50: + textmode(C80X50); + break; + case 60: + textmode(C80X60); + break; + default: + textmode(C4350); + break; + } + } + + clrscr(); + gettextinfo(&txtinfo); + /* unsupported mode? */ + if(txtinfo.screenheightMAX_LINES + || txtinfo.screenwidth<80) { + textmode(C80); /* set mode to 80x25*/ + gettextinfo(&txtinfo); + } + + api->scrn_len=txtinfo.screenheight; + if(api->scrn_lenscrn_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(txtinfo.screenwidth<80) { + cprintf("\7UIFC: Screen width (%u) must be at least 80 characters\r\n" + ,txtinfo.screenwidth); + return(-3); + } + api->scrn_width=txtinfo.screenwidth; + +#ifndef __FLAT__ + + r.w.ax=0x0000; /* reset mouse and get driver status */ + INT_86(0x33,&r,&r); + + if(r.w.ax==0xffff) { /* mouse driver installed */ + uifc_status|=UIFC_MOUSE; + + + r.w.ax=0x0020; /* enable mouse driver */ + INT_86(0x33,&r,&r); + + r.w.ax=0x000a; /* set text pointer type */ + r.w.bx=0x0000; /* software cursor */ + r.w.cx=0x77ff; + r.w.dx=mousecursor<<8; + INT_86(0x33,&r,&r); + + r.w.ax=0x0013; /* set double speed threshold */ + r.w.dx=32; /* double speed threshold */ + INT_86(0x33,&r,&r); + + r.w.ax=0x0001; /* show mouse pointer */ + INT_86(0x33,&r,&r); } + + #endif + + + if(!(api->mode&UIFC_COLOR) + && (api->mode&UIFC_MONO + || txtinfo.currmode==MONO || txtinfo.currmode==BW80)) { + bclr=BLACK; + hclr=WHITE; + lclr=LIGHTGRAY; + cclr=LIGHTGRAY; + } else { + bclr=BLUE; + hclr=YELLOW; + lclr=WHITE; + cclr=CYAN; + } + for(i=0;iscrn_len,blk_scrn)) + return(-1); + gotoxy(1,api->scrn_len+1); + clreol(); + 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 - cursor=getcursortype(); -scrn_len=lclini(5<<8)-1; -lputc(FF); -if(scrn_len>50) { - lputs("\7UIFC: Can't operate in video modes beyond 80x50\r\n"); - exit(1); } -setcursortype(NO_CURSOR); -if(txtinfo.currmode==2 || txtinfo.currmode==7) { - bclr=BLACK; - hclr=WHITE; - lclr=LIGHTGRAY; - cclr=LIGHTGRAY; } -else { - bclr=BLUE; - hclr=YELLOW; - lclr=WHITE; - cclr=CYAN; } -for(i=0;i<8000;i+=2) { - blk_scrn[i]='°'; - blk_scrn[i+1]=cclr|(bclr<<4); } -} - -void uscrn(char *str) -{ -lclatr(bclr|(cclr<<4)); -lclxy(1,1); -lputc(CLREOL); -lclxy(3,1); -lputs(str); -lclini(scrn_len); -puttext(1,2,80,scrn_len,blk_scrn); -lclxy(1,scrn_len+1); -lputc(CLREOL); -} - -/**************************************************************************/ -/* General menu display function. SCRN_* macros define virtual screen */ -/* limits. *cur is a pointer to the current option. Returns option number */ -/* positive value for selected option or -1 for ESC, -2 for INS or -3 for */ -/* DEL. Menus can centered left to right and top to bottom automatically. */ -/* mode bits are set with macros WIN_* */ -/* option is an array of char arrays, first element of last char array */ -/* must be NULL. */ -/**************************************************************************/ -int ulist(int mode, char left, char top, char width, int *cur - , char *title, char option[][MAX_OPLN]) + 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(void) { - char line[160],height,y,shade[160],win[MAX_BFLN],*ptr,a,b,c,longopt - ,search[MAX_OPLN]; + 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]<=' ') 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 */ - union REGS reg; -if(mode&WIN_SAV && savnum>=MAX_BUFS-1) - lputc(7); +#ifndef __FLAT__ + union REGS reg,r; + +hidemouse(); + +r.w.ax=0x0006; /* Get button release info */ +r.w.bx=0x0000; /* Left button */ +INT_86(0x33,&r,&r); /* Clears any buffered mouse clicks */ + +r.w.ax=0x0006; /* Get button release info */ +r.w.bx=0x0001; /* Right button */ +INT_86(0x33,&r,&r); /* Clears any buffered mouse clicks */ + +#endif + +if(mode&WIN_SAV && api->savnum>=MAX_BUFS-1) + putch(7); i=0; -if(mode&WIN_INS) i|=BL_INS; -if(mode&WIN_DEL) i|=BL_DEL; -if(mode&WIN_GET) i|=BL_GET; -if(mode&WIN_PUT) i|=BL_PUT; -bottomline(i); -while(optsscrn_len-3) - height=(scrn_len-3)-top; -if(!width) { +if(top+height>api->scrn_len-3) + height=(api->scrn_len-3)-top; +if(!width || widthwidth) - width=j; } + width=j; } } if(width>(SCRN_RIGHT+1)-SCRN_LEFT) width=(SCRN_RIGHT+1)-SCRN_LEFT; if(mode&WIN_L2R) @@ -115,53 +395,57 @@ if(mode&WIN_L2R) else if(mode&WIN_RHT) left=SCRN_RIGHT-(width+4+left); if(mode&WIN_T2B) - top=(scrn_len/2)-(height/2)-2; + top=(api->scrn_len/2)-(height/2)-2; else if(mode&WIN_BOT) - top=scrn_len-height-3-top; -if(mode&WIN_SAV && savdepth==savnum) { - if((sav[savnum].buf=(char *)MALLOC((width+3)*(height+2)*2))==NULL) { - lprintf("UIFC: error allocating %u bytes.",(width+3)*(height+2)*2); + 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+2 - ,SCRN_TOP+top+height+1,sav[savnum].buf); - sav[savnum].left=SCRN_LEFT+left; - sav[savnum].top=SCRN_TOP+top; - sav[savnum].right=SCRN_LEFT+left+width+2; - sav[savnum].bot=SCRN_TOP+top+height+1; - savdepth++; } + 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[savnum].left!=SCRN_LEFT+left - || sav[savnum].top!=SCRN_TOP+top - || sav[savnum].right!=SCRN_LEFT+left+width+2 - || sav[savnum].bot!=SCRN_TOP+top+height+1)) { /* dimensions have changed */ - puttext(sav[savnum].left,sav[savnum].top,sav[savnum].right,sav[savnum].bot - ,sav[savnum].buf); /* put original window back */ - FREE(sav[savnum].buf); - if((sav[savnum].buf=(char *)MALLOC((width+3)*(height+2)*2))==NULL) { - lprintf("UIFC: error allocating %u bytes.",(width+3)*(height+2)*2); + && (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+2 - ,SCRN_TOP+top+height+1,sav[savnum].buf); /* save again */ - sav[savnum].left=SCRN_LEFT+left; - sav[savnum].top=SCRN_TOP+top; - sav[savnum].right=SCRN_LEFT+left+width+2; - sav[savnum].bot=SCRN_TOP+top+height+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; } -/*** -lclxy(58,1); /* print available memory after allocating */ -lclatr(bclr|(cclr<<4)); -#if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -lprintf("%10ld bytes free",farcoreleft()); -#else -lprintf("%10u bytes free",coreleft()); + +#ifndef __FLAT__ +if(show_free_mem) { + #if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) + uprintf(58,1,bclr|(cclr<<4),"%10ld bytes free",farcoreleft()); + #else + uprintf(58,1,bclr|(cclr<<4),"%10u bytes free",coreleft()); + #endif + } #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<=scrn_len) - puttext(SCRN_LEFT,SCRN_TOP+height+top,SCRN_RIGHT+2,scrn_len,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); @@ -171,7 +455,24 @@ if(mode&WIN_ORG) { /* Clear around menu ptr=win; *(ptr++)='É'; *(ptr++)=hclr|(bclr<<4); -for(i=0;imode&UIFC_MOUSE) { + *(ptr++)='['; + *(ptr++)=hclr|(bclr<<4); + *(ptr++)='þ'; + *(ptr++)=lclr|(bclr<<4); + *(ptr++)=']'; + *(ptr++)=hclr|(bclr<<4); + *(ptr++)='['; + *(ptr++)=hclr|(bclr<<4); + *(ptr++)='?'; + *(ptr++)=lclr|(bclr<<4); + *(ptr++)=']'; + *(ptr++)=hclr|(bclr<<4); + i=6; } +else + i=0; +for(;i=opts) - (*cur)=opts-1; -if((*cur)>height-5) - (*cur)=height-5; + (*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; -i=0; + +j=0; +if(i<0) i=0; longopt=0; -while(iheight && (*cur)!=opts-1) { - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); - lclatr(lclr|(bclr<<4)); - lputc(31); /* put down arrow */ - lclatr(hclr|(bclr<<4)); } +if(bar) + y=top+3+(*bar); +else + y=top+3+(*cur); +if(opts+4>height && ((!bar && (*cur)!=opts-1) + || (bar && ((*cur)-(*bar))+(height-4)savdepth,opts); +#endif + if(!show_free_mem) + timedisplay(); +#ifndef __FLAT__ + if(api->mode&UIFC_MOUSE) { + + r.w.ax=0x0003; /* Get button status and mouse position */ + INT_86(0x33,&r,&r); + + if(r.w.bx&1) { /* Left button down */ + + if(r.w.cx/8>=SCRN_LEFT+left + && r.w.cx/8<=SCRN_LEFT+left+width + && r.w.dx/8>=SCRN_TOP+top+2 + && r.w.dx/8<=(SCRN_TOP+top+height)-3) { + + hidemouse(); + gettext(SCRN_LEFT+3+left,SCRN_TOP+y + ,SCRN_LEFT+left+width-2,SCRN_TOP+y,line); + for(i=1;i=SCRN_LEFT+left + && r.w.cx/8<=SCRN_LEFT+left+width + && r.w.dx/8>=SCRN_TOP+top+2 + && r.w.dx/8<=(SCRN_TOP+top+height)-3) { + + (*cur)=(r.w.dx/8)-(SCRN_TOP+top+2); + if(bar) + (*bar)=(*cur); + y=top+3+((r.w.dx/8)-(SCRN_TOP+top+2)); + + if(!opts || (mode&WIN_XTR && (*cur)==opts-1)) + continue; + + 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;isavnum].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); } + else if(r.w.cx/8>=SCRN_LEFT+left+3 + && r.w.cx/8<=SCRN_LEFT+left+5 + && r.w.dx/8==(SCRN_TOP+top)-1) /* Clicked help icon */ + help(); + else + goto hitesc; } + + r.w.ax=0x0006; /* Get button release information */ + r.w.bx=0x0001; /* right button */ + INT_86(0x33,&r,&r); + + if(r.w.bx) { /* Right button down, same as ESC */ +hitesc: + 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); } + } +#endif + + if(inkey(1)) { + i=inkey(0); if(!(i&0xff)) { s=0; switch(i>>8) { @@ -275,21 +725,26 @@ while(1) { if(!opts) break; if(opts+4>height) { - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); - lclatr(lclr|(bclr<<4)); - lputc(' '); /* Delete the up arrow */ - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); - lputc(31); /* put the down arrow */ - lclxy(SCRN_LEFT+left+3,SCRN_TOP+top+3); - lclatr(bclr|(LIGHTGRAY<<4)); - lprintf("%-*.*s",width-4,width-4,option[0]); - lclatr(lclr|(bclr<<4)); - for(i=1;iheight) { - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); /* like end */ - lclatr(lclr|(bclr<<4)); - lputc(30); /* put the up arrow */ - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); - lputc(' '); /* delete the down arrow */ - for(i=(opts+4)-height,j=0;i(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;iheight) { /* Scroll mode */ - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); - lclatr(lclr|(bclr<<4)); - lputc(30); /* put the up arrow */ - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); - lputc(' '); /* delete the down arrow */ - for(i=(opts+4)-height,j=0;iheight) { /* like home */ - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); - lclatr(lclr|(bclr<<4)); - lputc(' '); /* Delete the up arrow */ - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); - lputc(31); /* put the down arrow */ - lclxy(SCRN_LEFT+left+3,SCRN_TOP+top+3); - lclatr(bclr|(LIGHTGRAY<<4)); - lprintf("%-*.*s",width-4,width-4,option[0]); - lclatr(lclr|(bclr<<4)); - for(i=1;i=longopt) { b=0; @@ -517,36 +1048,42 @@ while(1) { else s++; if(y+(j-(*cur))+2>height+top) { (*cur)=j; - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); - lclatr(lclr|(bclr<<4)); - lputc(30); /* put the up arrow */ + gotoxy(SCRN_LEFT+left+1,SCRN_TOP+top+3); + textattr(lclr|(bclr<<4)); + putch(30); /* put the up arrow */ if((*cur)==opts-1) { - lclxy(SCRN_LEFT+left+1,SCRN_TOP+top+height-2); - lputc(' '); } /* delete the down arrow */ - for(i=((*cur)+5)-height,j=0;i<(*cur)+1;i++,j++) { - if(i==(*cur)) lclatr(bclr|(LIGHTGRAY<<4)); - lclxy(SCRN_LEFT+left+3,SCRN_TOP+top+3+j); - lprintf("%-*.*s",width-4,width-4,option[i]); } + 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)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;isavnum].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 && changes) + case '\b': /* backspace */ + 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); } + +left+width-1,SCRN_TOP+top+height-1,win); + showmouse(); } else if(mode&WIN_SAV) { - puttext(sav[savnum].left,sav[savnum].top - ,sav[savnum].right,sav[savnum].bot - ,sav[savnum].buf); - FREE(sav[savnum].buf); - savdepth--; } - return(-1); } } } } + 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. */ /*************************************************************************/ -char uinput(int mode, char left, char top, char *prompt, char *str, - char max, int kmode) +int uinput(int mode, int left, int top, char *prompt, char *str, + int max, int kmode) { - unsigned char c,tmp[81],save_buf[2048],shade[160],width,height=3,lines=0; - int i,j,plen; + unsigned char c,tmp[81],save_buf[2048],in_win[2048] + ,shade[160],width,height=3; + int i,j,plen,slen; +hidemouse(); plen=strlen(prompt); -width=plen+6+max; -if(width+SCRN_LEFT>SCRN_RIGHT) { /* prompt+max is too large */ - width=max+6; - for(lines=1,i=0,j=0;iwidth) - width=j+6; - j=0; } - height=3+lines; } -if(mode&WIN_MID) { - top=(scrn_len/2)-(height/2)-2; - left=36-(width/2); } -else if(mode&WIN_L2R) +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); -lclxy(SCRN_LEFT+left,SCRN_TOP+top); -lclatr(hclr|(bclr<<4)); -lputc('É'); -for(c=1;c=SP) - lputc(prompt[i]); - i++; } - lclatr(hclr|(bclr<<4)); - i++; /* skip LF */ - lclxy(SCRN_LEFT+left+width,SCRN_TOP+top+1+j); - lputc('º'); - j++; - lclxy(SCRN_LEFT+left,SCRN_TOP+SCRN_TOP+top+1+j); - lputc('º'); } } -else { - lprintf(" %s: %*s ",prompt,max,""); - lclatr(hclr|(bclr<<4)); - lputc('º'); } -lclxy(SCRN_LEFT+left,SCRN_TOP+top+2+lines); -lputc('È'); -for(c=1;cmode&UIFC_INMSG) /* non-cursive */ return; -uifc_status|=UIFC_INMSG; -if(savdepth) savnum++; -ulist(WIN_SAV|WIN_MID,0,0,0,&i,str,ok); -if(savdepth) savnum--; -uifc_status&=~UIFC_INMSG; -} - -/****************************************************************************/ -/* Returns current cursor type as int */ -/****************************************************************************/ -uint getcursortype() -{ - struct REGPACK r; - -r.r_bx=0x0000; -r.r_ax=0x0300; -intr(0x10,&r); -return(r.r_cx); -} -/****************************************************************************/ -/* Sets current cursor - NO_CURSOR is no-cursor */ -/****************************************************************************/ -void setcursortype(uint cursor) -{ - struct REGPACK r; - -r.r_cx=cursor; -r.r_ax=0x0100; -intr(0x10,&r); -} - -/****************************************************************************/ -/* Updates time in upper left corner of screen with current time in ASCII/ */ -/* Unix format */ -/****************************************************************************/ -void timedisplay() -{ - static time_t savetime; - time_t now; - -now=time(NULL); -if(difftime(now,savetime)>=60) { - lclxy(55,1); - lclatr(bclr|(cclr<<4)); - lputs(timestr(&now)); - savetime=now; } +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; } /****************************************************************************/ @@ -759,94 +1277,143 @@ if(difftime(now,savetime)>=60) { /* Different modes - K_* macros. ESC aborts input. */ /* Cursor should be at END of where string prompt will be placed. */ /****************************************************************************/ -int getstr(char *outstr, int max, int mode) +static int getstr(char *outstr, int max, long mode) { - char str[256],ch,ins=0,buf[256],y; - int i,j,k; /* i=offset, j=length */ + uchar ch,str[256],ins=0,buf[256],y; + int i,j,k,f=0; /* i=offset, j=length */ +#ifndef __FLAT__ + union REGS r; +#endif -setcursortype(cursor); +cursor=_NORMALCURSOR; +_setcursortype(cursor); +y=wherey(); if(mode&K_EDIT) { /*** truncsp(outstr); ***/ - lclatr(bclr|(LIGHTGRAY<<4)); - lputs(outstr); - lclatr(lclr|(bclr<<4)); + outstr[max]=0; + textattr(bclr|(LIGHTGRAY<<4)); + cputs(outstr); + textattr(lclr|(bclr<<4)); strcpy(str,outstr); i=j=strlen(str); - while((k=bioskey(1))==0); - y=lclwy(); - lclxy(lclwx()-i,y); - if(!isprint(k&0xff) && k!=0x5300) - lputs(outstr); + while(inkey(1)==0) { +#ifndef __FLAT__ + if(api->mode&UIFC_MOUSE) { + r.w.ax=0x0006; /* Get button release information */ + r.w.bx=0x0000; /* Left button */ + INT_86(0x33,&r,&r); + if(r.w.bx) { /* Left button release same as CR */ + cursor=_NOCURSOR; + _setcursortype(cursor); + return(i); } + r.w.ax=0x0006; /* Get button release information */ + r.w.bx=0x0001; /* Right button */ + INT_86(0x33,&r,&r); + if(r.w.bx) { /* Right button release same as ESC */ + cursor=_NOCURSOR; + _setcursortype(cursor); + return(-1); } } +#endif + mswait(1); + } + f=inkey(0); + gotoxy(wherex()-i,y); + if(!isprint(f&0xff) && f!=0x5300) + cputs(outstr); else { - lprintf("%*s",i,""); - lclxy(lclwx()-i,y); + cprintf("%*s",i,""); + gotoxy(wherex()-i,y); i=j=0; } } else i=j=0; + + while(1) { + + if(i>j) j=i; - if(bioskey(1)) { - k=bioskey(0); +#ifndef __FLAT__ + if(api->mode&UIFC_MOUSE) { + r.w.ax=0x0006; /* Get button release information */ + r.w.bx=0x0000; /* Left button */ + INT_86(0x33,&r,&r); + if(r.w.bx) /* Left button release same as CR */ + break; + r.w.ax=0x0006; /* Get button release information */ + r.w.bx=0x0001; /* Right button */ + INT_86(0x33,&r,&r); + if(r.w.bx) { /* Right button release same as ESC */ + cursor=_NOCURSOR; + _setcursortype(cursor); + return(-1); } } +#endif + if(f || inkey(1)) { + if(f) k=f; /* First key */ + else k=inkey(0); + f=0; ch=k&0xff; if(!ch) { switch(k>>8) { + case 0x3b: /* F1 Help */ + help(); + continue; case 0x4b: /* left arrow */ if(i) { - lclxy(lclwx()-1,lclwy()); + gotoxy(wherex()-1,y); i--; } continue; case 0x4d: /* right arrow */ if(i=SP && i=' ' || (ch==1 && mode&K_MSG)) && ii;k--) str[k]=str[k-1]; } - lputc(ch); - str[i++]=ch; } } } + putch(ch); + str[i++]=ch; } } + else + mswait(1); + } str[j]=0; if(mode&K_EDIT) { truncsp(str); if(strcmp(outstr,str)) - changes=1; } + api->changes=1; } else { if(j) - changes=1; } + api->changes=1; } strcpy(outstr,str); -setcursortype(NO_CURSOR); +cursor=_NOCURSOR; +_setcursortype(cursor); return(j); } /****************************************************************************/ -/* Performs printf() through local assembly routines */ -/* Called from everywhere */ +/* Performs printf() through puttext() routine */ /****************************************************************************/ -int lprintf(char *fmat, ...) { - char sbuf[256]; - int chcount; - -chcount=vsprintf(sbuf,fmat,_va_ptr); -lputs(sbuf); -return(chcount); +static int uprintf(int x, int y, 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 */ +/* Display bottom line of screen in inverse */ /****************************************************************************/ void bottomline(int line) { - -lclxy(4,scrn_len+1); -lclatr(bclr|(cclr<<4)); -lputs("F1 "); -lclatr(BLACK|(cclr<<4)); -lputs("Help "); + 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) { - lclatr(bclr|(cclr<<4)); - lputs("F5 "); - lclatr(BLACK|(cclr<<4)); - lputs("Get Item "); } + 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) { - lclatr(bclr|(cclr<<4)); - lputs("F6 "); - lclatr(BLACK|(cclr<<4)); - lputs("Put Item "); } + 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) { - lclatr(bclr|(cclr<<4)); - lputs("INS "); - lclatr(BLACK|(cclr<<4)); - lputs("Add Item "); } + 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) { - lclatr(bclr|(cclr<<4)); - lputs("DEL "); - lclatr(BLACK|(cclr<<4)); - lputs("Delete Item "); } -lclatr(bclr|(cclr<<4)); -lputs("ESC "); -lclatr(BLACK|(cclr<<4)); -lputs("Exit"); -lputc(CLREOL); + 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)); +clreol(); } @@ -952,7 +1529,7 @@ lputc(CLREOL); /* Generates a 24 character ASCII string that represents the time_t pointer */ /* Used as a replacement for ctime() */ /*****************************************************************************/ -char *timestr(time_t *intime) +char *utimestr(time_t *intime) { static char str[25]; char wday[4],mon[4],mer[3],hour; @@ -1031,3 +1608,224 @@ sprintf(str,"%s %s %02d %4d %02d:%02d %s ,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,' ',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;jhelpbuf) { + 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;jmode&UIFC_MOUSE) { + r.w.ax=0x0006; /* Get button release information */ + r.w.bx=0x0000; /* Left button */ + INT_86(0x33,&r,&r); + if(r.w.bx) /* Left button release same as CR */ + break; + r.w.ax=0x0006; /* Get button release information */ + r.w.bx=0x0001; /* Right button */ + INT_86(0x33,&r,&r); + if(r.w.bx) /* Left button release same as CR */ + break; } + #endif + mswait(1); + } + + hidemouse(); + puttext(1,1,80,25,savscrn); + showmouse(); + FREE(savscrn); + FREE(buf); + _setcursortype(cursor); +} +