|
|
1.1 root 1: /* uifcx.c */
2:
3: /* Standard I/O Implementation of UIFC (user interface) library */
4:
1.1.1.2 ! root 5: /* $Id: uifcx.c,v 1.25 2010/02/27 04:02:25 rswindell Exp $ */
1.1 root 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: * *
1.1.1.2 ! root 11: * Copyright 2010 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 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: api->initialized=TRUE;
93:
94: return(0);
95: }
96:
97: /****************************************************************************/
98: /* Exit/uninitialize UIFC implementation. */
99: /****************************************************************************/
100: void uifcbail(void)
101: {
102: api->initialized=FALSE;
103: }
104:
105: /****************************************************************************/
106: /* Clear screen, fill with background attribute, display application title. */
107: /* Returns 0 on success. */
108: /****************************************************************************/
109: int uscrn(char *str)
110: {
111: return(0);
112: }
113:
114: static int getstr(char* str, int maxlen)
115: {
116: char ch;
117: int len=0;
118: #ifdef __unix__
119: int istty;
120:
121: istty=isatty(fileno(stdin));
122: #endif
123: while(1) {
124: fread(&ch,1,1,stdin);
125: #ifdef __unix__
126: if(!istty) {
127: printf("%c",ch);
128: fflush(stdout);
129: }
130: #endif
131: if(ch=='\r' || ch=='\n') /* enter */
132: break;
133: if(ch=='\b' || ch==DEL) { /* backspace */
134: if(len) len--;
135: continue;
136: }
137: if(len<maxlen)
138: str[len++]=ch;
139: }
140: str[len]=0; /* we need The Terminator */
141:
142: return(len);
143: }
144:
145:
146: /****************************************************************************/
147: /* Local utility function. */
148: /****************************************************************************/
149: static int which(char* prompt, int max)
150: {
151: char str[41];
152: int i;
153:
154: while(1) {
155: printf("%s which (1-%d): ",prompt,max);
156: str[0]=0;
157: getstr(str,sizeof(str)-1);
158: i=atoi(str);
159: if(i>0 && i<=max)
160: return(i-1);
161: }
162: }
163:
164: /****************************************************************************/
165: /* Truncates white-space chars off end of 'str' */
166: /****************************************************************************/
167: static void truncsp(char *str)
168: {
169: uint c;
170:
171: c=strlen(str);
172: while(c && (uchar)str[c-1]<=' ') c--;
173: str[c]=0;
174: }
175:
176: /****************************************************************************/
177: /* Convert ASCIIZ string to upper case */
178: /****************************************************************************/
179: #if defined(__unix__)
180: static char* strupr(char* str)
181: {
182: char* p=str;
183:
184: while(*p) {
185: *p=toupper(*p);
186: p++;
187: }
188: return(str);
189: }
190: #endif
191:
192: /****************************************************************************/
193: /* General menu function, see uifc.h for details. */
194: /****************************************************************************/
195: int ulist(int mode, int left, int top, int width, int *cur, int *bar
196: , char *title, char **option)
197: {
198: char str[128];
199: int i,opts;
200: int optnumlen;
201: int yesno=0;
202: int lines;
203:
204: for(opts=0;opts<MAX_OPTS;opts++)
205: if(option[opts]==NULL || option[opts][0]==0)
206: break;
207:
208: if((*cur)>=opts)
209: (*cur)=opts-1; /* returned after scrolled */
210:
211: if((*cur)<0)
212: (*cur)=0;
213:
214: if(opts>999)
215: optnumlen=4;
216: else if(opts>99)
217: optnumlen=3;
218: else if(opts>9)
219: optnumlen=2;
220: else
221: optnumlen=1;
222: while(1) {
223: if(opts==2 && !stricmp(option[0],"Yes") && !stricmp(option[1],"No")) {
224: yesno=1;
225: printf("%s? ",title);
226: } else {
227: printf("\n[%s]\n",title);
228: lines=2;
229: for(i=0;i<opts;i++) {
230: printf("%*d: %s\n",optnumlen,i+1,option[i]);
231: lines++;
232: if(!(lines%api->scrn_len)) {
233: printf("More? ");
234: str[0]=0;
235: getstr(str,sizeof(str)-1);
236: if(toupper(*str)=='N')
237: break;
238: }
239: }
240: str[0]=0;
241: if(mode&WIN_GET)
242: strcat(str,", Copy");
243: if(mode&WIN_PUT)
244: strcat(str,", Paste");
245: if(mode&WIN_INS)
246: strcat(str,", Add");
247: if(mode&WIN_DEL)
248: strcat(str,", Delete");
249: printf("\nWhich (Help%s or Quit): ",str);
250: }
251: str[0]=0;
252: getstr(str,sizeof(str)-1);
253:
254: truncsp(str);
255: i=atoi(str);
256: if(i>0 && i<=opts) {
257: *cur=--i;
258: return(*cur);
259: }
260: i=atoi(str+1);
261: switch(toupper(*str)) {
262: case 0:
263: case ESC:
264: case 'Q':
265: printf("Quit\n");
266: return(-1);
267: case 'Y':
268: if(!yesno)
269: break;
270: printf("Yes\n");
271: return(0);
272: case 'N':
273: if(!yesno)
274: break;
275: printf("No\n");
276: return(1);
277: case 'H':
278: case '?':
279: printf("Help\n");
280: help();
281: break;
282: case 'A': /* Add/Insert */
283: if(!(mode&WIN_INS))
284: break;
285: if(!opts)
286: return(MSK_INS);
287: if(i>0 && i<=opts+1)
288: return((i-1)|MSK_INS);
289: return(which("Add before",opts+1)|MSK_INS);
290: case 'D': /* Delete */
291: if(!(mode&WIN_DEL))
292: break;
293: if(!opts)
294: break;
295: if(i>0 && i<=opts)
296: return((i-1)|MSK_DEL);
297: if(opts==1)
298: return(MSK_DEL);
299: return(which("Delete",opts)|MSK_DEL);
300: case 'C': /* Copy/Get */
301: if(!(mode&WIN_GET))
302: break;
303: if(!opts)
304: break;
305: if(i>0 && i<=opts)
306: return((i-1)|MSK_GET);
307: if(opts==1)
308: return(MSK_GET);
309: return(which("Copy",opts)|MSK_GET);
310: case 'P': /* Paste/Put */
311: if(!(mode&WIN_PUT))
312: break;
313: if(!opts)
314: break;
315: if(i>0 && i<=opts)
316: return((i-1)|MSK_PUT);
317: if(opts==1)
318: return(MSK_PUT);
319: return(which("Paste",opts)|MSK_PUT);
320: }
321: }
322: }
323:
324:
325: /*************************************************************************/
326: /* This function is a windowed input string input routine. */
327: /*************************************************************************/
328: int uinput(int mode, int left, int top, char *prompt, char *outstr,
329: int max, int kmode)
330: {
331: char str[256];
332:
333: while(1) {
334: printf("%s (maxlen=%u): ",prompt,max);
335:
336: getstr(str,max);
337: truncsp(str);
338: if(strcmp(str,"?"))
339: break;
340: help();
341: }
342: if(strcmp(outstr,str))
343: api->changes=1;
344: if(kmode&K_UPPER) /* convert to uppercase? */
345: strupr(str);
346: strcpy(outstr,str);
347: return(strlen(outstr));
348: }
349:
350: /****************************************************************************/
351: /* Displays the message 'str' and waits for the user to select "OK" */
352: /****************************************************************************/
353: void umsg(char *str)
354: {
355: printf("%s\n",str);
356: }
357:
358: /****************************************************************************/
359: /* Status popup/down function, see uifc.h for details. */
360: /****************************************************************************/
361: void upop(char *str)
362: {
363: if(str==NULL)
364: printf("\n");
365: else
366: printf("\r%-79s",str);
367: }
368:
369: /****************************************************************************/
370: /* Sets the current help index by source code file and line number. */
371: /****************************************************************************/
372: void sethelp(int line, char* file)
373: {
374: helpline=line;
375: helpfile=file;
376: }
377:
1.1.1.2 ! root 378: static void uputs(char* ptr)
! 379: {
! 380: while(*ptr) {
! 381: if(*ptr>2)
! 382: putchar(*ptr);
! 383: ptr++;
! 384: }
! 385: putchar('\n');
! 386: }
! 387:
1.1 root 388: /****************************************************************************/
389: /* Help function. */
390: /****************************************************************************/
391: void help()
392: {
393: char hbuf[HELPBUF_SIZE],str[256];
394: char *p;
395: unsigned short line;
396: long l;
397: FILE *fp;
398:
399: printf("\n");
400: if(!api->helpbuf) {
401: if((fp=fopen(api->helpixbfile,"rb"))==NULL)
402: sprintf(hbuf,"ERROR: Cannot open help index: %s"
403: ,api->helpixbfile);
404: else {
405: p=strrchr(helpfile,'/');
406: if(p==NULL)
407: p=strrchr(helpfile,'\\');
408: if(p==NULL)
409: p=helpfile;
410: else
411: p++;
412: l=-1L;
413: while(!feof(fp)) {
414: if(!fread(str,12,1,fp))
415: break;
416: str[12]=0;
417: fread(&line,2,1,fp);
418: if(stricmp(str,p) || line!=helpline) {
419: fseek(fp,4,SEEK_CUR);
420: continue; }
421: fread(&l,4,1,fp);
422: break; }
423: fclose(fp);
424: if(l==-1L)
425: sprintf(hbuf,"ERROR: Cannot locate help key (%s:%u) in: %s"
426: ,p,helpline,api->helpixbfile);
427: else {
428: if((fp=fopen(api->helpdatfile,"rb"))==NULL)
429: sprintf(hbuf,"ERROR: Cannot open help file: %s"
430: ,api->helpdatfile);
431: else {
432: fseek(fp,l,SEEK_SET);
433: fread(hbuf,HELPBUF_SIZE,1,fp);
434: fclose(fp);
435: }
436: }
437: }
438: }
439: else
440: strcpy(hbuf,api->helpbuf);
441:
1.1.1.2 ! root 442: uputs(hbuf);
1.1 root 443: if(strlen(hbuf)>200) {
444: printf("Hit enter");
445: getstr(str,sizeof(str)-1);
446: }
447: }
448:
449:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.