📄 wpickstr.c
字号:
/* CXL - Copyright (c) 1987-1989 by Mike Smedley - All Rights Reserved */
/* WPICKSTR.C - lets user pick from an array of strings */
#include <conio.h>
#include <ctype.h>
#include <dos.h>
#include <string.h>
#include "cxldef.h"
#include "cxlkey.h"
#include "cxlmou.h"
#include "cxlvid.h"
#include "cxlwin.h"
/* define record that will hold pick window info */
struct r_t {
int numelems,lastelem,curr,first,last,strsperline,strsperwin,maxstrlen,
wwidth,wheight,fillspaces,gapspaces,xtraspaces,winattr,barattr,
scrollbar;
};
/* local function prototypes */
static int e_begline(struct r_t *r,int elem);
static int e_begwin(struct r_t *r,int lelem);
static int e_endline(struct r_t *r,int elem);
static int e_endwin(struct r_t *r,int felem);
static void goto_item(struct r_t *r,char *strarr[],int elem);
static void hide_mouse_cursor(void);
static int mouse_on_item(struct r_t *r,int mrow,int mcol);
static void page_down(char *strarr[],struct r_t *r);
static void page_up(char *strarr[],struct r_t *r);
static int read_mouse(char *strarr[],struct r_t *r);
static void scroll_down(char *strarr[],struct r_t *r,int upcurr);
static void scroll_up(char *strarr[],struct r_t *r,int upcurr);
static void show_mouse_cursor(void);
static void update_curr(char *strarr[],struct r_t *r,int bar);
static void update_line(char *strarr[],struct r_t *r,int wrow,int upcurr);
static void update_window(char *strarr[],struct r_t *r);
/*---------------------------------------------------------------------------*/
int wpickstr(int srow,int scol,int erow,int ecol,int btype,int bordattr,
int winattr,int barattr,char *strarr[],int initelem,
void (*open)(void))
{
register int i,j;
int maxlen,border,outside;
unsigned int xch;
struct r_t r;
char ch;
/* go through input array and determine the longest */
/* string, and count the number of elements in the array */
for(i=maxlen=0;strarr[i]!=NULL;i++)
if((j=strlen(strarr[i]))>maxlen) maxlen=j;
r.maxstrlen=maxlen;
r.lastelem=((r.numelems=i)-1);
r.winattr=winattr;
r.barattr=_vinfo.mapattr?revsattr(winattr):barattr;
/* see if window is to have a border */
border=((btype==5)?NO:YES);
/* if ecol == -1 then adjust it to conform to length of longest string */
if(ecol==-1) ecol=scol+border+r.maxstrlen+border-1;
/* calculate window area width and height */
r.wwidth =(ecol-border)-(scol+border)+1;
r.wheight=(erow-border)-(srow+border)+1;
/* make sure longest string can fit in window */
if(r.maxstrlen>r.wwidth) {
_winfo.errno=W_STRLONG;
return(-1);
}
/* open window which strings will reside in */
hide_mouse_cursor();
if(!wopen(srow,scol,erow,ecol,btype,bordattr,winattr)) return(-1);
/* if mouse cursor mode is on and window has a border, */
/* display scroll indicator arrows on right window border */
if((_mouse&MS_CURS)&&(btype!=5)&&((srow+2)<erow)) {
printc(srow+1,ecol,bordattr,24);
printc(erow-1,ecol,bordattr,25);
r.scrollbar=TRUE;
}
else
r.scrollbar=FALSE;
show_mouse_cursor();
/* if an open function has been specified, then call it */
if(open!=NULL) (*open)();
/* if mouse cursor mode is on, then turn on mouse cursor */
show_mouse_cursor();
/* calculate how many strings can fit into 1 window line, number of */
/* filler spaces needed per window line, number of spaces per gap in */
/* between strings, number of extra spaces to add to first gap, and */
/* number of strings that can fit inside the window */
r.strsperline=(r.wwidth-2)/(r.maxstrlen+2);
if(!r.strsperline) r.strsperline++;
r.fillspaces=r.wwidth-(r.strsperline*r.maxstrlen);
r.gapspaces=r.fillspaces/(r.strsperline+1);
r.xtraspaces=(r.fillspaces%(r.strsperline+1))/2;
r.strsperwin=r.strsperline*r.wheight;
/* initialize first, last, and current elements */
r.curr=r.first=0;
r.last=(r.numelems<r.strsperwin)?(r.lastelem):(r.strsperwin-1);
/* move selection bar to specified initial element */
goto_item(&r,strarr,initelem);
/* fill window with as many strings as can fit and display bar */
update_window(strarr,&r);
/* loop until an element is selected or Escape is pressed */
for(;;) {
/* get keystroke/mouse movement */
_kbinfo.inmenu=TRUE;
xch=read_mouse(strarr,&r);
if(!xch) xch=getxch();
_kbinfo.inmenu=FALSE;
/* test keystroke for a special key */
switch(xch) {
case 0x011b: /* Esc */
/* close window and set error to Escape press code */
if(_winfo.esc) {
hide_mouse_cursor();
wclose();
_winfo.errno=W_ESCPRESS;
return(-1);
}
break;
case 0x1c0d: /* Enter */
/* close window and return subscript of selected string */
hide_mouse_cursor();
wclose();
_winfo.errno=W_NOERROR;
return(r.curr);
case 0x4b00: /* LeftArrow */
/* move to the item to the left, scrolling if necessary */
if(r.curr) {
update_curr(strarr,&r,0);
if(r.curr==r.first) scroll_down(strarr,&r,0);
r.curr--;
update_curr(strarr,&r,1);
}
break;
case 0x4d00: /* RightArrow */
/* move to the item to the right, scrolling if necessary */
if(r.curr!=r.lastelem) {
update_curr(strarr,&r,0);
if(r.curr==r.last) scroll_up(strarr,&r,0);
r.curr++;
update_curr(strarr,&r,1);
}
break;
case 0x4800: /* UpArrow */
/* move to the item up, scrolling if necessary */
if((r.curr-r.strsperline)<r.first)
scroll_down(strarr,&r,2);
else {
update_curr(strarr,&r,0);
r.curr-=r.strsperline;
update_curr(strarr,&r,1);
}
break;
case 0x5000: /* DownArrow */
/* move to the item down, scrolling if necessary */
if((r.curr+r.strsperline)>r.last)
scroll_up(strarr,&r,((r.curr+r.strsperline)>r.lastelem)
?0:2);
else {
update_curr(strarr,&r,0);
r.curr+=r.strsperline;
update_curr(strarr,&r,1);
}
break;
case 0x4900: /* PgUp */
/* move up 1 page. adjust position if at 1st element */
page_up(strarr,&r);
break;
case 0x5100: /* PgDn */
/* move down 1 page. adjust position if at last element */
page_down(strarr,&r);
break;
case 0x4700: /* Home */
/* set position to 1st element */
if(r.curr) {
if((outside=r.first)==NO) update_curr(strarr,&r,0);
r.first=r.curr=0;
if(outside) {
r.last=e_endwin(&r,r.first);
update_window(strarr,&r);
}
else
update_curr(strarr,&r,1);
}
break;
case 0x4f00: /* End */
/* set position to last element */
if(r.curr!=r.lastelem) {
if((outside=(r.last<(r.lastelem))?YES:NO)==NO)
update_curr(strarr,&r,0);
r.last=r.curr=r.lastelem;
if(outside) {
r.first=e_begwin(&r,r.last);
update_window(strarr,&r);
}
else
update_curr(strarr,&r,1);
}
break;
default:
/* if not an extended keypress, then search from current */
/* position for the item that begins with the same ASCII */
/* character as the keypress. If not found after current */
/* position, search from the beginning for a match */
ch=toupper((char)xch);
if(!ch) break;
for(i=r.curr+1;i<r.numelems;i++)
if(ch==toupper(*(strarr[i]))) break;
if(i==r.numelems) {
for(i=0;i<r.curr;i++)
if(ch==toupper(*(strarr[i]))) break;
if(i==r.curr) continue;
}
/* a matching ASCII character was found. set position */
/* to matching element, adjusting window if necessary */
goto_item(&r,strarr,i);
}
}
}
/*---------------------------------------------------------------------------*/
/* this function will find the element number of the */
/* first element on the same line as the given element */
static int e_begline(struct r_t *r,int elem)
{
return((elem/r->strsperline)*r->strsperline);
}
/*---------------------------------------------------------------------------*/
/* this function will find the first element in a */
/* window, using a given last element as input */
static int e_begwin(struct r_t *r,int lelem)
{
register int beg;
beg=e_begline(r,lelem)+r->strsperline-r->strsperwin;
if(beg<0) beg=0;
return(beg);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -