uifcx.c 11.9 KB
Newer Older
1
2
/* uifcx.c */

3
4
/* Standard I/O Implementation of UIFC (user interface) library */

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* $Id$ */

/****************************************************************************
 * @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"

40
41
42
43
44
45
46
#include <sys/types.h>

#ifdef __unix__
/*	#include <sys/time.h> why? */
	#include <unistd.h>
#endif

47
48
49
50
51
52
53
54
55
56
static char *helpfile=0;
static uint helpline=0;
static uifcapi_t* api;

/* Prototypes */
static void help();

/* API routines */
static void uifcbail(void);
static int uscrn(char *str);
57
static int ulist(int mode, int left, int top, int width, int *dflt, int *bar
58
	,char *title, char **option);
59
60
static int uinput(int imode, int left, int top, char *prompt, char *str
	,int len ,int kmode);
61
62
63
64
static void umsg(char *str);
static void upop(char *str);
static void sethelp(int line, char* file);

65
66
67
68
/****************************************************************************/
/* Initialization function, see uifc.h for details.							*/
/* Returns 0 on success.													*/
/****************************************************************************/
69
int uifcinix(uifcapi_t* uifcapi)
70
{
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

    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;

86
    setvbuf(stdin,NULL,_IONBF,0);
rswindell's avatar
rswindell committed
87
    setvbuf(stdout,NULL,_IONBF,0);
88
89
90
    api->scrn_len=24;

    return(0);
91
92
}

93
94
95
/****************************************************************************/
/* Exit/uninitialize UIFC implementation.									*/
/****************************************************************************/
96
97
98
99
void uifcbail(void)
{
}

100
101
102
103
/****************************************************************************/
/* Clear screen, fill with background attribute, display application title.	*/
/* Returns 0 on success.													*/
/****************************************************************************/
104
105
106
107
108
int uscrn(char *str)
{
    return(0);
}

109
110
111
112
static int getstr(char* str, int maxlen)
{
	char 	ch;
    int		len=0;
113
#ifdef __unix__
114
115
116
	int		istty;

	istty=isatty(fileno(stdin));
117
#endif
118
119
    while(1) {
		fread(&ch,1,1,stdin);
120
#ifdef __unix__
121
122
123
124
		if(!istty)  {
			printf("%c",ch);
			fflush(stdout);
		}
125
#endif
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
        if(ch=='\r' || ch=='\n')	/* enter */
        	break;
        if(ch=='\b') {				/* backspace */
        	if(len) len--;
            continue;
    	}
        if(len<maxlen)
			str[len++]=ch;
	}
    str[len]=0;	/* we need The Terminator */
    
	return(len);
}
	

141
142
143
/****************************************************************************/
/* Local utility function.													*/
/****************************************************************************/
144
145
146
147
148
149
150
151
static int which(char* prompt, int max)
{
    char    str[41];
    int     i;

    while(1) {
        printf("%s which (1-%d): ",prompt,max);
        str[0]=0;
152
		getstr(str,sizeof(str)-1);
153
154
155
156
157
158
        i=atoi(str);
        if(i>0 && i<=max)
            return(i-1);
    }
}

159
160
161
162
163
164
165
166
167
168
169
/****************************************************************************/
/* 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;
}
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

/****************************************************************************/
/* Convert ASCIIZ string to upper case										*/
/****************************************************************************/
#if defined(__unix__)
static char* strupr(char* str)
{
	char*	p=str;

	while(*p) {
		*p=toupper(*p);
		p++;
	}
	return(str);
}
#endif

187
188
189
/****************************************************************************/
/* General menu function, see uifc.h for details.							*/
/****************************************************************************/
190
int ulist(int mode, int left, int top, int width, int *cur, int *bar
191
192
193
	, char *title, char **option)
{
    char str[128];
194
	int i,opts;
195
196
    int optnumlen;
    int yesno=0;
rswindell's avatar
rswindell committed
197
    int lines;
198

199
    for(opts=0;opts<MAX_OPTS;opts++)
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    	if(option[opts][0]==0)
    		break;

    if((*cur)>=opts)
        (*cur)=opts-1;			/* returned after scrolled */

    if((*cur)<0)
        (*cur)=0;

    if(opts>999)
        optnumlen=4;
    else if(opts>99)
        optnumlen=3;
    else if(opts>9)
        optnumlen=2;
    else
        optnumlen=1;
    while(1) {
        if(opts==2 && !stricmp(option[0],"Yes") && !stricmp(option[1],"No")) {
            yesno=1;
            printf("%s? ",title);
        } else {
            printf("\n[%s]\n",title);
rswindell's avatar
rswindell committed
223
            lines=2;
224
225
            for(i=0;i<opts;i++) {
                printf("%*d: %s\n",optnumlen,i+1,option[i]);
rswindell's avatar
rswindell committed
226
227
                lines++;
                if(!(lines%api->scrn_len)) {
228
229
                    printf("More? ");
                    str[0]=0;
230
                    getstr(str,sizeof(str)-1);
231
232
233
234
235
236
237
238
239
240
241
242
243
                    if(toupper(*str)=='N')
                        break;
                }
            }
            str[0]=0;
            if(mode&WIN_GET)
                strcat(str,", Copy");
            if(mode&WIN_PUT)
                strcat(str,", Paste");
            if(mode&WIN_INS)
                strcat(str,", Add");
            if(mode&WIN_DEL)
                strcat(str,", Delete");
rswindell's avatar
rswindell committed
244
            printf("\nWhich (Help%s or Quit): ",str);
245
246
        }
        str[0]=0;
247
        getstr(str,sizeof(str)-1);
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
        
        truncsp(str);
        i=atoi(str);
        if(i>0) {
            *cur=--i;
            return(*cur);
        }
        i=atoi(str+1);
        switch(toupper(*str)) {
            case 0:
            case ESC:
            case 'Q':
                printf("Quit\n");
                return(-1);
            case 'Y':
                if(!yesno)
                    break;
                printf("Yes\n");
                return(0);
            case 'N':
                if(!yesno)
                    break;
                printf("No\n");
                return(1);
            case 'H':
            case '?':
                printf("Help\n");
                help();
                break;
rswindell's avatar
rswindell committed
277
            case 'A':   /* Add/Insert */
278
279
280
281
282
				if(!opts)
    				return(MSK_INS);
                if(i>0 && i<=opts+1)
        			return((i-1)|MSK_INS);
                return(which("Add before",opts+1)|MSK_INS);
rswindell's avatar
rswindell committed
283
            case 'D':   /* Delete */
284
285
286
287
				if(!opts)
    				break;
                if(i>0 && i<=opts)
        			return((i-1)|MSK_DEL);
rswindell's avatar
rswindell committed
288
289
290
291
                if(opts==1)
                    return(MSK_DEL);
                return(which("Delete",opts)|MSK_DEL);
            case 'C':   /* Copy/Get */
292
293
294
295
				if(!opts)
    				break;
                if(i>0 && i<=opts)
        			return((i-1)|MSK_GET);
rswindell's avatar
rswindell committed
296
297
                if(opts==1)
                    return(MSK_GET);
298
                return(which("Copy",opts)|MSK_GET);
rswindell's avatar
rswindell committed
299
            case 'P':   /* Paste/Put */
300
301
302
303
				if(!opts)
    				break;
                if(i>0 && i<=opts)
        			return((i-1)|MSK_PUT);
rswindell's avatar
rswindell committed
304
305
                if(opts==1)
                    return(MSK_PUT);
306
307
308
309
310
311
312
313
314
                return(which("Paste",opts)|MSK_PUT);
        }
    }
}


/*************************************************************************/
/* This function is a windowed input string input routine.               */
/*************************************************************************/
315
316
int uinput(int mode, int left, int top, char *prompt, char *outstr,
	int max, int kmode)
317
{
318
319
320
321
    char str[256];
    
    while(1) {
        printf("%s (maxlen=%u): ",prompt,max);
322
323

        getstr(str,max);
324
325
326
327
328
329
330
        truncsp(str);
        if(strcmp(str,"?"))
            break;
        help();
    }
	if(strcmp(outstr,str))
		api->changes=1;
331
332
    if(kmode&K_UPPER)	/* convert to uppercase? */
    	strupr(str);
333
334
    strcpy(outstr,str);    
    return(strlen(outstr));
335
336
337
338
339
340
341
342
343
344
345
}

/****************************************************************************/
/* Displays the message 'str' and waits for the user to select "OK"         */
/****************************************************************************/
void umsg(char *str)
{
    printf("%s\n",str);
}

/****************************************************************************/
346
/* Status popup/down function, see uifc.h for details.						*/
347
348
349
350
351
352
353
354
355
/****************************************************************************/
void upop(char *str)
{
    if(str==NULL)
        printf("\n");
    else
        printf("\r%-79s",str);
}

356
357
358
/****************************************************************************/
/* Sets the current help index by source code file and line number.			*/
/****************************************************************************/
359
360
361
362
363
364
void sethelp(int line, char* file)
{
    helpline=line;
    helpfile=file;
}

365
366
367
/****************************************************************************/
/* Help function.															*/
/****************************************************************************/
368
369
370
371
void help()
{
	char hbuf[HELPBUF_SIZE],str[256];
    char *p;
372
	unsigned short line;
373
374
375
376
	long l;
	FILE *fp;

    printf("\n");
377
    if(!api->helpbuf) {
378
        if((fp=fopen(api->helpixbfile,"rb"))==NULL)
379
            sprintf(hbuf,"ERROR: Cannot open help index: %s"
380
                ,api->helpixbfile);
381
382
383
384
385
386
387
388
389
390
391
392
393
        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;
rswindell's avatar
rswindell committed
394
395
                fread(&line,2,1,fp);
                if(stricmp(str,p) || line!=helpline) {
396
397
398
399
400
401
402
                    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: %s"
403
                    ,p,helpline,api->helpixbfile);
404
            else {
405
                if((fp=fopen(api->helpdatfile,"rb"))==NULL)
406
                    sprintf(hbuf,"ERROR: Cannot open help file: %s"
407
                        ,api->helpdatfile);
408
409
410
                else {
                    fseek(fp,l,SEEK_SET);
                    fread(hbuf,HELPBUF_SIZE,1,fp);
rswindell's avatar
rswindell committed
411
412
413
414
415
                    fclose(fp); 
				} 
			} 
		} 
	}
416
    else
417
        strcpy(hbuf,api->helpbuf);
418
419

    puts(hbuf);
420
421
    if(strlen(hbuf)>200) {
        printf("Hit enter");
422
        getstr(str,sizeof(str)-1);
423
    }
424
425
}

426