|
|
1.1 root 1: /* uifcx.c */
2:
3: /* Standard I/O Implementation of UIFC (user interface) library */
4:
5: /* $Id: uifcx.c,v 1.23 2004/07/27 22:36:54 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This library is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU Lesser General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU Lesser General Public License for more details: lgpl.txt or *
18: * http://www.fsf.org/copyleft/lesser.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "uifc.h"
39:
40: #include <sys/types.h>
41:
42: #ifdef __unix__
43: /* #include <sys/time.h> why? */
44: #include <unistd.h>
45: #endif
46:
47: static char *helpfile=0;
48: static uint helpline=0;
49: static uifcapi_t* api;
50:
51: /* Prototypes */
52: static void help(void);
53:
54: /* API routines */
55: static void uifcbail(void);
56: 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: static int uinput(int imode, int left, int top, char *prompt, char *str
60: ,int len ,int kmode);
61: static void umsg(char *str);
62: static void upop(char *str);
63: static void sethelp(int line, char* file);
64:
65: /****************************************************************************/
66: /* Initialization function, see uifc.h for details. */
67: /* Returns 0 on success. */
68: /****************************************************************************/
69: int uifcinix(uifcapi_t* uifcapi)
70: {
71:
72: if(uifcapi==NULL || uifcapi->size!=sizeof(uifcapi_t))
73: return(-1);
74:
75: api=uifcapi;
76:
77: /* install function handlers */
78: api->bail=uifcbail;
79: api->scrn=uscrn;
80: api->msg=umsg;
81: api->pop=upop;
82: api->list=ulist;
83: api->input=uinput;
84: api->sethelp=sethelp;
85: api->showhelp=help;
86: api->showbuf=NULL;
87: api->timedisplay=NULL;
88:
89: setvbuf(stdin,NULL,_IONBF,0);
90: setvbuf(stdout,NULL,_IONBF,0);
91: api->scrn_len=24;
92:
93: return(0);
94: }
95:
96: /****************************************************************************/
97: /* Exit/uninitialize UIFC implementation. */
98: /****************************************************************************/
99: void uifcbail(void)
100: {
101: }
102:
103: /****************************************************************************/
104: /* Clear screen, fill with background attribute, display application title. */
105: /* Returns 0 on success. */
106: /****************************************************************************/
107: int uscrn(char *str)
108: {
109: return(0);
110: }
111:
112: static int getstr(char* str, int maxlen)
113: {
114: char ch;
115: int len=0;
116: #ifdef __unix__
117: int istty;
118:
119: istty=isatty(fileno(stdin));
120: #endif
121: while(1) {
122: fread(&ch,1,1,stdin);
123: #ifdef __unix__
124: if(!istty) {
125: printf("%c",ch);
126: fflush(stdout);
127: }
128: #endif
129: if(ch=='\r' || ch=='\n') /* enter */
130: break;
131: if(ch=='\b' || ch==DEL) { /* backspace */
132: if(len) len--;
133: continue;
134: }
135: if(len<maxlen)
136: str[len++]=ch;
137: }
138: str[len]=0; /* we need The Terminator */
139:
140: return(len);
141: }
142:
143:
144: /****************************************************************************/
145: /* Local utility function. */
146: /****************************************************************************/
147: static int which(char* prompt, int max)
148: {
149: char str[41];
150: int i;
151:
152: while(1) {
153: printf("%s which (1-%d): ",prompt,max);
154: str[0]=0;
155: getstr(str,sizeof(str)-1);
156: i=atoi(str);
157: if(i>0 && i<=max)
158: return(i-1);
159: }
160: }
161:
162: /****************************************************************************/
163: /* Truncates white-space chars off end of 'str' */
164: /****************************************************************************/
165: static void truncsp(char *str)
166: {
167: uint c;
168:
169: c=strlen(str);
170: while(c && (uchar)str[c-1]<=' ') c--;
171: str[c]=0;
172: }
173:
174: /****************************************************************************/
175: /* Convert ASCIIZ string to upper case */
176: /****************************************************************************/
177: #if defined(__unix__)
178: static char* strupr(char* str)
179: {
180: char* p=str;
181:
182: while(*p) {
183: *p=toupper(*p);
184: p++;
185: }
186: return(str);
187: }
188: #endif
189:
190: /****************************************************************************/
191: /* General menu function, see uifc.h for details. */
192: /****************************************************************************/
193: int ulist(int mode, int left, int top, int width, int *cur, int *bar
194: , char *title, char **option)
195: {
196: char str[128];
197: int i,opts;
198: int optnumlen;
199: int yesno=0;
200: int lines;
201:
202: for(opts=0;opts<MAX_OPTS;opts++)
203: if(option[opts]==NULL || option[opts][0]==0)
204: break;
205:
206: if((*cur)>=opts)
207: (*cur)=opts-1; /* returned after scrolled */
208:
209: if((*cur)<0)
210: (*cur)=0;
211:
212: if(opts>999)
213: optnumlen=4;
214: else if(opts>99)
215: optnumlen=3;
216: else if(opts>9)
217: optnumlen=2;
218: else
219: optnumlen=1;
220: while(1) {
221: if(opts==2 && !stricmp(option[0],"Yes") && !stricmp(option[1],"No")) {
222: yesno=1;
223: printf("%s? ",title);
224: } else {
225: printf("\n[%s]\n",title);
226: lines=2;
227: for(i=0;i<opts;i++) {
228: printf("%*d: %s\n",optnumlen,i+1,option[i]);
229: lines++;
230: if(!(lines%api->scrn_len)) {
231: printf("More? ");
232: str[0]=0;
233: getstr(str,sizeof(str)-1);
234: if(toupper(*str)=='N')
235: break;
236: }
237: }
238: str[0]=0;
239: if(mode&WIN_GET)
240: strcat(str,", Copy");
241: if(mode&WIN_PUT)
242: strcat(str,", Paste");
243: if(mode&WIN_INS)
244: strcat(str,", Add");
245: if(mode&WIN_DEL)
246: strcat(str,", Delete");
247: printf("\nWhich (Help%s or Quit): ",str);
248: }
249: str[0]=0;
250: getstr(str,sizeof(str)-1);
251:
252: truncsp(str);
253: i=atoi(str);
254: if(i>0 && i<=opts) {
255: *cur=--i;
256: return(*cur);
257: }
258: i=atoi(str+1);
259: switch(toupper(*str)) {
260: case 0:
261: case ESC:
262: case 'Q':
263: printf("Quit\n");
264: return(-1);
265: case 'Y':
266: if(!yesno)
267: break;
268: printf("Yes\n");
269: return(0);
270: case 'N':
271: if(!yesno)
272: break;
273: printf("No\n");
274: return(1);
275: case 'H':
276: case '?':
277: printf("Help\n");
278: help();
279: break;
280: case 'A': /* Add/Insert */
281: if(!(mode&WIN_INS))
282: break;
283: if(!opts)
284: return(MSK_INS);
285: if(i>0 && i<=opts+1)
286: return((i-1)|MSK_INS);
287: return(which("Add before",opts+1)|MSK_INS);
288: case 'D': /* Delete */
289: if(!(mode&WIN_DEL))
290: break;
291: if(!opts)
292: break;
293: if(i>0 && i<=opts)
294: return((i-1)|MSK_DEL);
295: if(opts==1)
296: return(MSK_DEL);
297: return(which("Delete",opts)|MSK_DEL);
298: case 'C': /* Copy/Get */
299: if(!(mode&WIN_GET))
300: break;
301: if(!opts)
302: break;
303: if(i>0 && i<=opts)
304: return((i-1)|MSK_GET);
305: if(opts==1)
306: return(MSK_GET);
307: return(which("Copy",opts)|MSK_GET);
308: case 'P': /* Paste/Put */
309: if(!(mode&WIN_PUT))
310: break;
311: if(!opts)
312: break;
313: if(i>0 && i<=opts)
314: return((i-1)|MSK_PUT);
315: if(opts==1)
316: return(MSK_PUT);
317: return(which("Paste",opts)|MSK_PUT);
318: }
319: }
320: }
321:
322:
323: /*************************************************************************/
324: /* This function is a windowed input string input routine. */
325: /*************************************************************************/
326: int uinput(int mode, int left, int top, char *prompt, char *outstr,
327: int max, int kmode)
328: {
329: char str[256];
330:
331: while(1) {
332: printf("%s (maxlen=%u): ",prompt,max);
333:
334: getstr(str,max);
335: truncsp(str);
336: if(strcmp(str,"?"))
337: break;
338: help();
339: }
340: if(strcmp(outstr,str))
341: api->changes=1;
342: if(kmode&K_UPPER) /* convert to uppercase? */
343: strupr(str);
344: strcpy(outstr,str);
345: return(strlen(outstr));
346: }
347:
348: /****************************************************************************/
349: /* Displays the message 'str' and waits for the user to select "OK" */
350: /****************************************************************************/
351: void umsg(char *str)
352: {
353: printf("%s\n",str);
354: }
355:
356: /****************************************************************************/
357: /* Status popup/down function, see uifc.h for details. */
358: /****************************************************************************/
359: void upop(char *str)
360: {
361: if(str==NULL)
362: printf("\n");
363: else
364: printf("\r%-79s",str);
365: }
366:
367: /****************************************************************************/
368: /* Sets the current help index by source code file and line number. */
369: /****************************************************************************/
370: void sethelp(int line, char* file)
371: {
372: helpline=line;
373: helpfile=file;
374: }
375:
376: /****************************************************************************/
377: /* Help function. */
378: /****************************************************************************/
379: void help()
380: {
381: char hbuf[HELPBUF_SIZE],str[256];
382: char *p;
383: unsigned short line;
384: long l;
385: FILE *fp;
386:
387: printf("\n");
388: if(!api->helpbuf) {
389: if((fp=fopen(api->helpixbfile,"rb"))==NULL)
390: sprintf(hbuf,"ERROR: Cannot open help index: %s"
391: ,api->helpixbfile);
392: else {
393: p=strrchr(helpfile,'/');
394: if(p==NULL)
395: p=strrchr(helpfile,'\\');
396: if(p==NULL)
397: p=helpfile;
398: else
399: p++;
400: l=-1L;
401: while(!feof(fp)) {
402: if(!fread(str,12,1,fp))
403: break;
404: str[12]=0;
405: fread(&line,2,1,fp);
406: if(stricmp(str,p) || line!=helpline) {
407: fseek(fp,4,SEEK_CUR);
408: continue; }
409: fread(&l,4,1,fp);
410: break; }
411: fclose(fp);
412: if(l==-1L)
413: sprintf(hbuf,"ERROR: Cannot locate help key (%s:%u) in: %s"
414: ,p,helpline,api->helpixbfile);
415: else {
416: if((fp=fopen(api->helpdatfile,"rb"))==NULL)
417: sprintf(hbuf,"ERROR: Cannot open help file: %s"
418: ,api->helpdatfile);
419: else {
420: fseek(fp,l,SEEK_SET);
421: fread(hbuf,HELPBUF_SIZE,1,fp);
422: fclose(fp);
423: }
424: }
425: }
426: }
427: else
428: strcpy(hbuf,api->helpbuf);
429:
430: puts(hbuf);
431: if(strlen(hbuf)>200) {
432: printf("Hit enter");
433: getstr(str,sizeof(str)-1);
434: }
435: }
436:
437:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.