|
|
1.1 root 1: /* scfgxtrn.c */
2:
3: /* $Id: scfgxtrn.c,v 1.33 2004/07/28 00:00:18 rswindell Exp $ */
4:
5: /****************************************************************************
6: * @format.tab-size 4 (Plain Text/Source Code File Header) *
7: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
8: * *
9: * Copyright 2002 Rob Swindell - http://www.synchro.net/copyright.html *
10: * *
11: * This program is free software; you can redistribute it and/or *
12: * modify it under the terms of the GNU General Public License *
13: * as published by the Free Software Foundation; either version 2 *
14: * of the License, or (at your option) any later version. *
15: * See the GNU General Public License for more details: gpl.txt or *
16: * http://www.fsf.org/copyleft/gpl.html *
17: * *
18: * Anonymous FTP access to the most recent released source is available at *
19: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
20: * *
21: * Anonymous CVS access to the development source and modification history *
22: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
23: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
24: * (just hit return, no password is necessary) *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
26: * *
27: * For Synchronet coding style and modification guidelines, see *
28: * http://www.synchro.net/source.html *
29: * *
30: * You are encouraged to submit any modifications (preferably in Unix diff *
31: * format) via e-mail to [email protected] *
32: * *
33: * Note: If this box doesn't appear square, then you need to fix your tabs. *
34: ****************************************************************************/
35: /****************************************************************************/
36: /* Synchronet configuration utility */
37: /****************************************************************************/
38:
39: #include "scfg.h"
40:
41: char *daystr(char days);
42: static void hotkey_cfg(void);
43:
44: static char* mdaystr(long mdays)
45: {
46: int i;
47: char tmp[16];
48: static char str[256];
49:
50: if(mdays==0 || mdays==1)
51: return("Any");
52:
53: str[0]=0;
54: for(i=1;i<32;i++) {
55: if((mdays&(1<<i))==0)
56: continue;
57: if(str[0])
58: strcat(str," ");
59: sprintf(tmp,"%u",i);
60: strcat(str,tmp);
61: }
62:
63: return(str);
64: }
65:
66: static char* dropfile(int type, ulong misc)
67: {
68: static char str[128];
69: char fname[64]="";
70:
71: switch(type) {
72: case XTRN_SBBS:
73: strcpy(fname,"XTRN.DAT");
74: break;
75: case XTRN_WWIV:
76: strcpy(fname,"CHAIN.TXT");
77: break;
78: case XTRN_GAP:
79: strcpy(fname,"DOOR.SYS");
80: break;
81: case XTRN_RBBS:
82: strcpy(fname,"DORINFO#.DEF");
83: break;
84: case XTRN_RBBS1:
85: strcpy(fname,"DORINFO1.DEF");
86: break;
87: case XTRN_WILDCAT:
88: strcpy(fname,"CALLINFO.BBS");
89: break;
90: case XTRN_PCBOARD:
91: strcpy(fname,"PCBOARD.SYS");
92: break;
93: case XTRN_SPITFIRE:
94: strcpy(fname,"SFDOORS.DAT");
95: break;
96: case XTRN_UTI:
97: strcpy(fname,"UTIDOOR.TXT");
98: break;
99: case XTRN_SR:
100: strcpy(fname,"DOORFILE.SR");
101: break;
102: case XTRN_TRIBBS:
103: strcpy(fname,"TRIBBS.SYS");
104: break;
105: case XTRN_DOOR32:
106: strcpy(fname,"DOOR32.SYS");
107: break;
108: }
109:
110: if(misc&XTRN_LWRCASE)
111: strlwr(fname);
112:
113: switch(type) {
114: case XTRN_SBBS:
115: sprintf(str,"%-15s %s","Synchronet",fname);
116: break;
117: case XTRN_WWIV:
118: sprintf(str,"%-15s %s","WWIV",fname);
119: break;
120: case XTRN_GAP:
121: sprintf(str,"%-15s %s","GAP",fname);
122: break;
123: case XTRN_RBBS:
124: sprintf(str,"%-15s %s","RBBS/QuickBBS",fname);
125: break;
126: case XTRN_RBBS1:
127: sprintf(str,"%-15s %s","RBBS/QuickBBS",fname);
128: break;
129: case XTRN_WILDCAT:
130: sprintf(str,"%-15s %s","Wildcat",fname);
131: break;
132: case XTRN_PCBOARD:
133: sprintf(str,"%-15s %s","PCBoard",fname);
134: break;
135: case XTRN_SPITFIRE:
136: sprintf(str,"%-15s %s","SpitFire",fname);
137: break;
138: case XTRN_UTI:
139: sprintf(str,"%-15s %s","MegaMail",fname);
140: break;
141: case XTRN_SR:
142: sprintf(str,"%-15s %s","Solar Realms",fname);
143: break;
144: case XTRN_TRIBBS:
145: sprintf(str,"%-15s %s","TriBBS",fname);
146: break;
147: case XTRN_DOOR32:
148: sprintf(str,"%-15s %s","Mystic",fname);
149: break;
150: default:
151: strcpy(str,"None");
152: break;
153: }
154: return(str);
155: }
156:
157: void xprogs_cfg()
158: {
159: static int xprogs_dflt;
160: int i;
161:
162: while(1) {
163: i=0;
164: strcpy(opt[i++],"Fixed Events");
165: strcpy(opt[i++],"Timed Events");
166: strcpy(opt[i++],"Native Program List");
167: strcpy(opt[i++],"External Editors");
168: strcpy(opt[i++],"Global Hot Key Events");
169: strcpy(opt[i++],"Online Programs (Doors)");
170: opt[i][0]=0;
171: SETHELP(WHERE);
172: /*
173: &Online External Programs:&
174:
175: From this menu, you can configure external events, external editors, or
176: online external programs (doors).
177: */
178: switch(uifc.list(WIN_ORG|WIN_CHE|WIN_ACT,0,0,0,&xprogs_dflt,0
179: ,"External Programs",opt)) {
180: case -1:
181: i=save_changes(WIN_MID);
182: if(i==-1)
183: break;
184: if(!i) {
185: cfg.new_install=new_install;
186: write_xtrn_cfg(&cfg,backup_level);
187: write_main_cfg(&cfg,backup_level);
188: refresh_cfg(&cfg);
189: }
190: return;
191: case 0:
192: fevents_cfg();
193: break;
194: case 1:
195: tevents_cfg();
196: break;
197: case 2:
198: natvpgm_cfg();
199: break;
200: case 3:
201: xedit_cfg();
202: break;
203: case 4:
204: hotkey_cfg();
205: break;
206: case 5:
207: xtrnsec_cfg();
208: break; } }
209: }
210:
211: void fevents_cfg()
212: {
213: static int event_dflt;
214: int i;
215:
216: while(1) {
217: i=0;
218: sprintf(opt[i++],"%-32.32s%.40s","Logon Event",cfg.sys_logon);
219: sprintf(opt[i++],"%-32.32s%.40s","Logout Event",cfg.sys_logout);
220: sprintf(opt[i++],"%-32.32s%.40s","Daily Event",cfg.sys_daily);
221: opt[i][0]=0;
222: uifc.savnum=0;
223: SETHELP(WHERE);
224: /*
225: &External Events:&
226:
227: From this menu, you can configure the logon and logout events, and the
228: system daily event.
229: */
230: switch(uifc.list(WIN_ACT|WIN_SAV|WIN_CHE|WIN_BOT|WIN_RHT,0,0,60,&event_dflt,0
231: ,"Fixed Events",opt)) {
232: case -1:
233: return;
234: case 0:
235: SETHELP(WHERE);
236: /*
237: &Logon Event:&
238:
239: This is the command line for a program that will execute during the
240: logon sequence of every user. The program cannot have user interaction.
241: The program will be executed after the LOGON message is displayed and
242: before the logon user list is displayed. If you wish to place a program
243: in the logon sequence of users that includes interaction or requires
244: account information, you probably want to use an online external
245: program configured to run as a logon event.
246: */
247: uifc.input(WIN_MID|WIN_SAV,0,0,"Logon Event"
248: ,cfg.sys_logon,sizeof(cfg.sys_logon)-1,K_EDIT);
249: break;
250: case 1:
251: SETHELP(WHERE);
252: /*
253: &Logout Event:&
254:
255: This is the command line for a program that will execute during the
256: logout sequence of every user. This program cannot have user
257: interaction because it is executed after carrier is dropped. If you
258: wish to have a program execute before carrier is dropped, you probably
259: want to use an &Online External Program& configured to run as a logoff
260: event.
261: */
262: uifc.input(WIN_MID|WIN_SAV,0,0,"Logout Event"
263: ,cfg.sys_logout,sizeof(cfg.sys_logout)-1,K_EDIT);
264: break;
265: case 2:
266: SETHELP(WHERE);
267: /*
268: &Daily Event:&
269:
270: This is the command line for a program that will run after the first
271: user that logs on after midnight, logs off (regardless of what node).
272: */
273: uifc.input(WIN_MID|WIN_SAV,0,0,"Daily Event"
274: ,cfg.sys_daily,sizeof(cfg.sys_daily)-1,K_EDIT);
275:
276: break; } }
277: }
278:
279: void tevents_cfg()
280: {
281: static int dflt,dfltopt,bar;
282: char str[81],done=0,*p;
283: int j,k;
284: uint i;
285: static event_t savevent;
286:
287: while(1) {
288: for(i=0;i<cfg.total_events && i<MAX_OPTS;i++)
289: sprintf(opt[i],"%-8.8s %.50s",cfg.event[i]->code,cfg.event[i]->cmd);
290: opt[i][0]=0;
291: j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_RHT;
292: uifc.savnum=0;
293: if(cfg.total_events)
294: j|=WIN_DEL|WIN_GET;
295: if(cfg.total_events<MAX_OPTS)
296: j|=WIN_INS|WIN_INSACT|WIN_XTR;
297: if(savevent.code[0])
298: j|=WIN_PUT;
299: SETHELP(WHERE);
300: /*
301: &Timed Events:&
302:
303: This is a list of the configured timed external events.
304:
305: To add an event hit INS .
306:
307: To delete an event, select it and hit DEL .
308:
309: To configure an event, select it and hit ENTER .
310: */
311: i=uifc.list(j,0,0,45,&dflt,&bar,"Timed Events",opt);
312: if((signed)i==-1)
313: return;
314: if((i&MSK_ON)==MSK_INS) {
315: i=cfg.total_events;
316: SETHELP(WHERE);
317: /*
318: &Timed Event Internal Code:&
319:
320: This is the internal code for the timed event.
321: */
322: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Event Internal Code",str,LEN_CODE
323: ,K_UPPER)<1)
324: continue;
325: if((cfg.event=(event_t **)REALLOC(cfg.event
326: ,sizeof(event_t *)*(cfg.total_events+1)))==NULL) {
327: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_events+1);
328: cfg.total_events=0;
329: bail(1);
330: continue; }
331: if((cfg.event[i]=(event_t *)MALLOC(sizeof(event_t)))==NULL) {
332: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(event_t));
333: continue; }
334: memset((event_t *)cfg.event[i],0,sizeof(event_t));
335: strcpy(cfg.event[i]->code,str);
336: cfg.event[i]->node=1;
337: cfg.event[i]->days=0xff;
338: cfg.total_events++;
339: uifc.changes=1;
340: continue; }
341: if((i&MSK_ON)==MSK_DEL) {
342: i&=MSK_OFF;
343: FREE(cfg.event[i]);
344: cfg.total_events--;
345: for(j=i;j<cfg.total_events;j++)
346: cfg.event[j]=cfg.event[j+1];
347: uifc.changes=1;
348: continue; }
349: if((i&MSK_ON)==MSK_GET) {
350: i&=MSK_OFF;
351: savevent=*cfg.event[i];
352: continue; }
353: if((i&MSK_ON)==MSK_PUT) {
354: i&=MSK_OFF;
355: *cfg.event[i]=savevent;
356: uifc.changes=1;
357: continue; }
358: done=0;
359: while(!done) {
360: k=0;
361: sprintf(opt[k++],"%-32.32s%s","Internal Code",cfg.event[i]->code);
362: sprintf(opt[k++],"%-32.32s%.40s","Start-up Directory",cfg.event[i]->dir);
363: sprintf(opt[k++],"%-32.32s%.40s","Command Line",cfg.event[i]->cmd);
364: sprintf(opt[k++],"%-32.32s%s","Enabled"
365: ,cfg.event[i]->misc&EVENT_DISABLED ? "No":"Yes");
366: sprintf(opt[k++],"%-32.32s%u","Execution Node",cfg.event[i]->node);
367: sprintf(opt[k++],"%-32.32s%s","Execution Days of Month"
368: ,mdaystr(cfg.event[i]->mdays));
369: sprintf(opt[k++],"%-32.32s%s","Execution Days of Week",daystr(cfg.event[i]->days));
370: if(cfg.event[i]->freq) {
371: sprintf(str,"%u times a day",1440/cfg.event[i]->freq);
372: sprintf(opt[k++],"%-32.32s%s","Execution Frequency",str);
373: } else {
374: sprintf(str,"%2.2u:%2.2u"
375: ,cfg.event[i]->time/60,cfg.event[i]->time%60);
376: sprintf(opt[k++],"%-32.32s%s","Execution Time",str);
377: }
378: sprintf(opt[k++],"%-32.32s%s","Requires Exclusive Execution"
379: ,cfg.event[i]->misc&EVENT_EXCL ? "Yes":"No");
380: sprintf(opt[k++],"%-32.32s%s","Force Users Off-line For Event"
381: ,cfg.event[i]->misc&EVENT_FORCE ? "Yes":"No");
382: sprintf(opt[k++],"%-32.32s%s","Native (32-bit) Executable"
383: ,cfg.event[i]->misc&EX_NATIVE ? "Yes" : "No");
384: sprintf(opt[k++],"%-32.32s%s","Use Shell to Execute"
385: ,cfg.event[i]->misc&XTRN_SH ? "Yes" : "No");
386: sprintf(opt[k++],"%-32.32s%s","Background Execution"
387: ,cfg.event[i]->misc&EX_BG ? "Yes" : "No");
388: sprintf(opt[k++],"%-32.32s%s","Always Run After Init/Re-init"
389: ,cfg.event[i]->misc&EVENT_INIT ? "Yes":"No");
390:
391: opt[k][0]=0;
392: SETHELP(WHERE);
393: /*
394: &Timed Event:&
395:
396: This is the configuration menu for a timed event. An event is an
397: external program that performs some type of automated function on the
398: system. Use this menu to configure how and when this event will be
399: executed.
400:
401: If you need the BBS to swap out of memory for this event (to make more
402: available memory), add the program name (first word of the command line)
403: to &Global Swap List& from the &External Programs& menu.
404: */
405: uifc.savnum=1;
406: sprintf(str,"%s Timed Event",cfg.event[i]->code);
407: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_L2R|WIN_BOT,0,0,70,&dfltopt,0
408: ,str,opt)) {
409: case -1:
410: done=1;
411: break;
412: case 0:
413: strcpy(str,cfg.event[i]->code);
414: SETHELP(WHERE);
415: /*
416: &Timed Event Internal Code:&
417:
418: Every timed event must have its own unique internal code for Synchronet
419: to reference it by. It is helpful if this code is an abreviation of the
420: command line.
421: */
422: uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
423: ,str,LEN_CODE,K_EDIT|K_UPPER);
424: if(code_ok(str))
425: strcpy(cfg.event[i]->code,str);
426: else {
427: uifc.helpbuf=invalid_code;
428: uifc.msg("Invalid Code");
429: uifc.helpbuf=0; }
430: break;
431: case 1:
432: SETHELP(WHERE);
433: /*
434: &Timed Event Start-up Directory:&
435:
436: This is the DOS drive/directory where the event program is located.
437: If a path is specified here, it will be made the current directory
438: before the event's command line is executed. This eliminates the need
439: for batch files that just change the current drive and directory before
440: executing the event.
441:
442: If this option is not used, the current NODE's directory will be the
443: current DOS drive/directory before the command line is executed.
444: */
445: uifc.input(WIN_MID|WIN_SAV,0,10,"Directory"
446: ,cfg.event[i]->dir,sizeof(cfg.event[i]->dir)-1,K_EDIT);
447: break;
448: case 2:
449: SETHELP(WHERE);
450: /*
451: &Timed Event Command Line:&
452:
453: This is the command line to execute upon this timed event.
454: */
455: uifc.input(WIN_MID|WIN_SAV,0,10,"Command"
456: ,cfg.event[i]->cmd,sizeof(cfg.event[i]->cmd)-1,K_EDIT);
457: break;
458:
459: case 3:
460: k=cfg.event[i]->misc&EVENT_DISABLED ? 1:0;
461: strcpy(opt[0],"Yes");
462: strcpy(opt[1],"No");
463: opt[2][0]=0;
464: uifc.savnum=2;
465: SETHELP(WHERE);
466: /*
467: `Event Enabled:`
468:
469: If you want disable this event from executing, set this option to ~No~.
470: */
471: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
472: ,"Enabled",opt);
473: if((k==0 && cfg.event[i]->misc&EVENT_DISABLED)
474: || (k==1 && !(cfg.event[i]->misc&EVENT_DISABLED))) {
475: cfg.event[i]->misc^=EVENT_DISABLED;
476: uifc.changes=1;
477: }
478: break;
479:
480: case 4:
481: SETHELP(WHERE);
482: /*
483: &Timed Event Node:&
484:
485: This is the node number to execute the timed event.
486: */
487: sprintf(str,"%u",cfg.event[i]->node);
488: uifc.input(WIN_MID|WIN_SAV,0,0,"Node Number"
489: ,str,3,K_EDIT|K_NUMBER);
490: cfg.event[i]->node=atoi(str);
491: break;
492: case 5:
493: SETHELP(WHERE);
494: /*
495: `Days of Month to Execute Event:`
496:
497: Specifies the days of the month (`1-31`, separated by spaces) on which
498: to execute this event, or `Any` to execute event on any and all days of
499: the month.
500: */
501: SAFECOPY(str,mdaystr(cfg.event[i]->mdays));
502: uifc.input(WIN_MID|WIN_SAV,0,0,"Days of Month to Execute Event (or Any)"
503: ,str,16,K_EDIT);
504: cfg.event[i]->mdays=0;
505: for(p=str;*p;p++) {
506: if(!isdigit(*p))
507: continue;
508: cfg.event[i]->mdays|=(1<<atoi(p));
509: while(*p && isdigit(*p))
510: p++;
511: }
512: break;
513: case 6:
514: j=0;
515: while(1) {
516: for(k=0;k<7;k++)
517: sprintf(opt[k],"%-30s %3s"
518: ,wday[k],(cfg.event[i]->days&(1<<k)) ? "Yes":"No");
519: strcpy(opt[k++],"All");
520: strcpy(opt[k++],"None");
521: opt[k][0]=0;
522: uifc.savnum=2;
523: SETHELP(WHERE);
524: /*
525: &Days of Week to Execute Event:&
526:
527: These are the days of the week that this event will be executed.
528: */
529: k=uifc.list(WIN_MID|WIN_SAV|WIN_ACT,0,0,0,&j,0
530: ,"Days of Week to Execute Event",opt);
531: if(k==-1)
532: break;
533: if(k==7)
534: cfg.event[i]->days=0xff;
535: else if(k==8)
536: cfg.event[i]->days=0;
537: else
538: cfg.event[i]->days^=(1<<k);
539: uifc.changes=1;
540: }
541: break;
542: case 7:
543: if(cfg.event[i]->freq==0)
544: k=0;
545: else
546: k=1;
547: strcpy(opt[0],"Yes");
548: strcpy(opt[1],"No");
549: opt[2][0]=0;
550: uifc.savnum=2;
551: SETHELP(WHERE);
552: /*
553: &Execute Event at a Specific Time:&
554:
555: If you want the system execute this event at a specific time, set
556: this option to &Yes&. If you want the system to execute this event more
557: than once a day at predetermined intervals, set this option to &No&.
558: */
559: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
560: ,"Execute Event at a Specific Time",opt);
561: if(k==0) {
562: sprintf(str,"%2.2u:%2.2u",cfg.event[i]->time/60
563: ,cfg.event[i]->time%60);
564: SETHELP(WHERE);
565: /*
566: &Time to Execute Event:&
567:
568: This is the time (in 24 hour HH:MM format) to execute the event.
569: */
570: if(uifc.input(WIN_MID|WIN_SAV,0,0
571: ,"Time to Execute Event (HH:MM)"
572: ,str,5,K_UPPER|K_EDIT)>0) {
573: cfg.event[i]->freq=0;
574: cfg.event[i]->time=atoi(str)*60;
575: if((p=strchr(str,':'))!=NULL)
576: cfg.event[i]->time+=atoi(p+1); } }
577: else if(k==1) {
578: sprintf(str,"%u"
579: ,cfg.event[i]->freq && cfg.event[i]->freq<=1440
580: ? 1440/cfg.event[i]->freq : 0);
581: SETHELP(WHERE);
582: /*
583: &Number of Executions Per Day:&
584:
585: This is the maximum number of times the system will execute this event
586: per day.
587: */
588: if(uifc.input(WIN_MID|WIN_SAV,0,0
589: ,"Number of Executions Per Day"
590: ,str,4,K_NUMBER|K_EDIT)>0) {
591: cfg.event[i]->time=0;
592: k=atoi(str);
593: if(k && k<=1440)
594: cfg.event[i]->freq=1440/k;
595: else
596: cfg.event[i]->freq=0;
597: }
598: }
599: break;
600: case 8:
601: k=cfg.event[i]->misc&EVENT_EXCL ? 0:1;
602: strcpy(opt[0],"Yes");
603: strcpy(opt[1],"No");
604: opt[2][0]=0;
605: uifc.savnum=2;
606: SETHELP(WHERE);
607: /*
608: &Exclusive Event Execution:&
609:
610: If this event must be run exclusively (all nodes inactive), set this
611: option to &Yes&.
612: */
613: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Exclusive Execution"
614: ,opt);
615: if(!k && !(cfg.event[i]->misc&EVENT_EXCL)) {
616: cfg.event[i]->misc|=EVENT_EXCL;
617: uifc.changes=1; }
618: else if(k==1 && cfg.event[i]->misc&EVENT_EXCL) {
619: cfg.event[i]->misc&=~EVENT_EXCL;
620: uifc.changes=1; }
621: break;
622: case 9:
623: k=cfg.event[i]->misc&EVENT_FORCE ? 0:1;
624: strcpy(opt[0],"Yes");
625: strcpy(opt[1],"No");
626: opt[2][0]=0;
627: uifc.savnum=2;
628: SETHELP(WHERE);
629: /*
630: &Force Users Off-line for Event:&
631:
632: If you want to have your users' on-line time reduced so the event can
633: execute precisely on time, set this option to &Yes&.
634: */
635: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
636: ,"Force Users Off-line for Event",opt);
637: if(!k && !(cfg.event[i]->misc&EVENT_FORCE)) {
638: cfg.event[i]->misc|=EVENT_FORCE;
639: uifc.changes=1; }
640: else if(k==1 && cfg.event[i]->misc&EVENT_FORCE) {
641: cfg.event[i]->misc&=~EVENT_FORCE;
642: uifc.changes=1; }
643: break;
644:
645: case 10:
646: k=cfg.event[i]->misc&EX_NATIVE ? 0:1;
647: strcpy(opt[0],"Yes");
648: strcpy(opt[1],"No");
649: opt[2][0]=0;
650: uifc.savnum=2;
651: SETHELP(WHERE);
652: /*
653: &Native (32-bit) Executable:&
654:
655: If this event program is a native 32-bit executable,
656: set this option to &Yes&.
657: */
658: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
659: ,"Native (32-bit)",opt);
660: if(!k && !(cfg.event[i]->misc&EX_NATIVE)) {
661: cfg.event[i]->misc|=EX_NATIVE;
662: uifc.changes=TRUE;
663: }
664: else if(k==1 && cfg.event[i]->misc&EX_NATIVE) {
665: cfg.event[i]->misc&=~EX_NATIVE;
666: uifc.changes=TRUE;
667: }
668: break;
669:
670: case 11:
671: k=cfg.event[i]->misc&XTRN_SH ? 0:1;
672: strcpy(opt[0],"Yes");
673: strcpy(opt[1],"No");
674: opt[2][0]=0;
675: uifc.savnum=2;
676: SETHELP(WHERE);
677: /*
678: `Use Shell to Execute Command:`
679:
680: If this command-line requires the system command shell to execute, (Unix
681: shell script or DOS batch file), set this option to ~Yes~.
682: */
683: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
684: ,"Use Shell",opt);
685: if(!k && !(cfg.event[i]->misc&XTRN_SH)) {
686: cfg.event[i]->misc|=XTRN_SH;
687: uifc.changes=TRUE;
688: }
689: else if(k==1 && cfg.event[i]->misc&XTRN_SH) {
690: cfg.event[i]->misc&=~XTRN_SH;
691: uifc.changes=TRUE;
692: }
693: break;
694:
695: case 12:
696: k=cfg.event[i]->misc&EX_BG ? 0:1;
697: strcpy(opt[0],"Yes");
698: strcpy(opt[1],"No");
699: opt[2][0]=0;
700: uifc.savnum=2;
701: SETHELP(WHERE);
702: /*
703: &Execute Event in Background (Asynchronously):&
704:
705: If you would like this event to run simultaneously with other events,
706: set this option to &Yes&. Exclusive events will not run in the background.
707: */
708: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
709: ,"Background (Asynchronous) Execution",opt);
710: if(!k && !(cfg.event[i]->misc&EX_BG)) {
711: cfg.event[i]->misc|=EX_BG;
712: uifc.changes=TRUE;
713: }
714: else if(k==1 && cfg.event[i]->misc&EX_BG) {
715: cfg.event[i]->misc&=~EX_BG;
716: uifc.changes=TRUE;
717: }
718: break;
719:
720: case 13:
721: k=cfg.event[i]->misc&EVENT_INIT ? 0:1;
722: strcpy(opt[0],"Yes");
723: strcpy(opt[1],"No");
724: opt[2][0]=0;
725: uifc.savnum=2;
726: SETHELP(WHERE);
727: /*
728: `Always Run After Initialization or Re-initialization:`
729:
730: If you want this event to always run after the BBS is initialized or
731: re-initialized, set this option to ~Yes~.
732: */
733: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
734: ,"Always Run After Initialization or Re-initialization",opt);
735: if(!k && !(cfg.event[i]->misc&EVENT_INIT)) {
736: cfg.event[i]->misc|=EVENT_INIT;
737: uifc.changes=1;
738: }
739: else if(k==1 && cfg.event[i]->misc&EVENT_INIT) {
740: cfg.event[i]->misc&=~EVENT_INIT;
741: uifc.changes=1;
742: }
743: break;
744: }
745: }
746: }
747: }
748:
749:
750: void xtrn_cfg(uint section)
751: {
752: static int ext_dflt,ext_bar,opt_dflt,time_dflt;
753: char str[128],code[9],done=0,*p;
754: int j,k;
755: uint i,n,xtrnnum[MAX_OPTS+1];
756: static xtrn_t savxtrn;
757:
758: while(1) {
759: for(i=0,j=0;i<cfg.total_xtrns && j<MAX_OPTS;i++)
760: if(cfg.xtrn[i]->sec==section) {
761: sprintf(opt[j],"%-25s",cfg.xtrn[i]->name);
762: xtrnnum[j++]=i; }
763: xtrnnum[j]=cfg.total_xtrns;
764: opt[j][0]=0;
765: uifc.savnum=2;
766: i=WIN_ACT|WIN_CHE|WIN_SAV|WIN_RHT;
767: if(j)
768: i|=WIN_DEL|WIN_GET;
769: if(cfg.total_xtrns<MAX_OPTS)
770: i|=WIN_INS|WIN_INSACT|WIN_XTR;
771: if(savxtrn.name[0])
772: i|=WIN_PUT;
773: SETHELP(WHERE);
774: /*
775: &Online External Programs:&
776:
777: This is a list of the configured online external programs (doors).
778:
779: To add a program, select the desired location with the arrow keys and
780: hit INS .
781:
782: To delete a program, select it with the arrow keys and hit DEL .
783:
784: To configure a program, select it with the arrow keys and hit ENTER .
785: */
786: sprintf(str,"%s Online Programs",cfg.xtrnsec[section]->name);
787: i=uifc.list(i,0,0,45,&ext_dflt,&ext_bar,str,opt);
788: if((signed)i==-1)
789: return;
790: if((i&MSK_ON)==MSK_INS) {
791: i&=MSK_OFF;
792: SETHELP(WHERE);
793: /*
794: &Online Program Name:&
795:
796: This is the name or description of the online program (door).
797: */
798: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Online Program Name",str,25
799: ,0)<1)
800: continue;
801: sprintf(code,"%.8s",str);
802: p=strchr(code,' ');
803: if(p) *p=0;
804: strupr(code);
805: SETHELP(WHERE);
806: /*
807: &Online Program Internal Code:&
808:
809: Every online program must have its own unique code for Synchronet to
810: refer to it internally. This code is usually an abreviation of the
811: online program name.
812: */
813: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Internal Code"
814: ,code,LEN_CODE,K_EDIT|K_UPPER)<1)
815: continue;
816: if(!code_ok(code)) {
817: uifc.helpbuf=invalid_code;
818: uifc.msg("Invalid Code");
819: uifc.helpbuf=0;
820: continue; }
821: if((cfg.xtrn=(xtrn_t **)REALLOC(cfg.xtrn,sizeof(xtrn_t *)*(cfg.total_xtrns+1)))
822: ==NULL) {
823: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_xtrns+1);
824: cfg.total_xtrns=0;
825: bail(1);
826: continue; }
827: if(j)
828: for(n=cfg.total_xtrns;n>xtrnnum[i];n--)
829: cfg.xtrn[n]=cfg.xtrn[n-1];
830: if((cfg.xtrn[xtrnnum[i]]=(xtrn_t *)MALLOC(sizeof(xtrn_t)))==NULL) {
831: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(xtrn_t));
832: continue; }
833: memset((xtrn_t *)cfg.xtrn[xtrnnum[i]],0,sizeof(xtrn_t));
834: strcpy(cfg.xtrn[xtrnnum[i]]->name,str);
835: strcpy(cfg.xtrn[xtrnnum[i]]->code,code);
836: cfg.xtrn[xtrnnum[i]]->sec=section;
837: cfg.total_xtrns++;
838: uifc.changes=TRUE;
839: continue; }
840: if((i&MSK_ON)==MSK_DEL) {
841: i&=MSK_OFF;
842: FREE(cfg.xtrn[xtrnnum[i]]);
843: cfg.total_xtrns--;
844: for(j=xtrnnum[i];j<cfg.total_xtrns;j++)
845: cfg.xtrn[j]=cfg.xtrn[j+1];
846: uifc.changes=TRUE;
847: continue; }
848: if((i&MSK_ON)==MSK_GET) {
849: i&=MSK_OFF;
850: savxtrn=*cfg.xtrn[xtrnnum[i]];
851: continue; }
852: if((i&MSK_ON)==MSK_PUT) {
853: i&=MSK_OFF;
854: *cfg.xtrn[xtrnnum[i]]=savxtrn;
855: cfg.xtrn[xtrnnum[i]]->sec=section;
856: uifc.changes=TRUE;
857: continue; }
858: done=0;
859: i=xtrnnum[i];
860: while(!done) {
861: k=0;
862: sprintf(opt[k++],"%-27.27s%s","Name",cfg.xtrn[i]->name);
863: sprintf(opt[k++],"%-27.27s%s","Internal Code",cfg.xtrn[i]->code);
864: sprintf(opt[k++],"%-27.27s%.40s","Start-up Directory",cfg.xtrn[i]->path);
865: sprintf(opt[k++],"%-27.27s%.40s","Command Line",cfg.xtrn[i]->cmd);
866: sprintf(opt[k++],"%-27.27s%.40s","Clean-up Command Line",cfg.xtrn[i]->clean);
867: if(cfg.xtrn[i]->cost)
868: sprintf(str,"%lu credits",cfg.xtrn[i]->cost);
869: else
870: strcpy(str,"None");
871: sprintf(opt[k++],"%-27.27s%s","Execution Cost",str);
872: sprintf(opt[k++],"%-27.27s%.40s","Access Requirements",cfg.xtrn[i]->arstr);
873: sprintf(opt[k++],"%-27.27s%.40s","Execution Requirements"
874: ,cfg.xtrn[i]->run_arstr);
875: sprintf(opt[k++],"%-27.27s%s","Multiple Concurrent Users"
876: ,cfg.xtrn[i]->misc&MULTIUSER ? "Yes" : "No");
877: sprintf(opt[k++],"%-27.27s%s%s%s","Intercept Standard I/O"
878: ,cfg.xtrn[i]->misc&IO_INTS ? "Yes" : "No"
879: ,(cfg.xtrn[i]->misc&(IO_INTS|WWIVCOLOR))
880: ==(IO_INTS|WWIVCOLOR) ? ", WWIV Color" : nulstr
881: ,(cfg.xtrn[i]->misc&(IO_INTS|XTRN_NOECHO))
882: ==(IO_INTS|XTRN_NOECHO) ? ", No Echo" : nulstr);
883: sprintf(opt[k++],"%-27.27s%s","Native (32-bit) Executable"
884: ,cfg.xtrn[i]->misc&XTRN_NATIVE ? "Yes" : "No");
885: sprintf(opt[k++],"%-27.27s%s","Use Shell to Execute"
886: ,cfg.xtrn[i]->misc&XTRN_SH ? "Yes" : "No");
887: sprintf(opt[k++],"%-27.27s%s","Modify User Data"
888: ,cfg.xtrn[i]->misc&MODUSERDAT ? "Yes" : "No");
889: switch(cfg.xtrn[i]->event) {
890: case EVENT_LOGON:
891: strcpy(str,"Logon");
892: break;
893: case EVENT_LOGOFF:
894: strcpy(str,"Logoff");
895: break;
896: case EVENT_NEWUSER:
897: strcpy(str,"New User");
898: break;
899: case EVENT_BIRTHDAY:
900: strcpy(str,"Birthday");
901: break;
902: case EVENT_POST:
903: strcpy(str,"Message Posted");
904: break;
905: case EVENT_UPLOAD:
906: strcpy(str,"File Uploaded");
907: break;
908: case EVENT_DOWNLOAD:
909: strcpy(str,"File Downloaded");
910: break;
911: default:
912: strcpy(str,"No");
913: break;
914: }
915: if(cfg.xtrn[i]->misc&EVENTONLY && cfg.xtrn[i]->event)
916: strcat(str,", Only");
917: sprintf(opt[k++],"%-27.27s%s","Execute on Event",str);
918: sprintf(opt[k++],"%-27.27s%s","Pause After Execution"
919: ,cfg.xtrn[i]->misc&XTRN_PAUSE ? "Yes" : "No");
920: sprintf(opt[k++],"%-23.23s%-4s%s","BBS Drop File Type"
921: ,cfg.xtrn[i]->misc&REALNAME ? "(R)":nulstr
922: ,dropfile(cfg.xtrn[i]->type,cfg.xtrn[i]->misc));
923: sprintf(opt[k++],"%-27.27s%s","Place Drop File In"
924: ,cfg.xtrn[i]->misc&STARTUPDIR ? "Start-Up Directory":"Node Directory");
925: sprintf(opt[k++],"Time Options...");
926: opt[k][0]=0;
927: uifc.savnum=3;
928: SETHELP(WHERE);
929: /*
930: &Online Program Configuration:&
931:
932: This menu is for configuring the selected online program.
933: */
934: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_MID,0,0,60,&opt_dflt,0,cfg.xtrn[i]->name
935: ,opt)) {
936: case -1:
937: done=1;
938: break;
939: case 0:
940: SETHELP(WHERE);
941: /*
942: &Online Program Name:&
943:
944: This is the name or description of the online program (door).
945: */
946: strcpy(str,cfg.xtrn[i]->name);
947: if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Online Program Name"
948: ,cfg.xtrn[i]->name,sizeof(cfg.xtrn[i]->name)-1,K_EDIT))
949: strcpy(cfg.xtrn[i]->name,str);
950: break;
951: case 1:
952: SETHELP(WHERE);
953: /*
954: &Online Program Internal Code:&
955:
956: Every online program must have its own unique code for Synchronet to
957: refer to it internally. This code is usually an abreviation of the
958: online program name.
959: */
960: strcpy(str,cfg.xtrn[i]->code);
961: uifc.input(WIN_MID|WIN_SAV,0,10,"Internal Code"
962: ,str,LEN_CODE,K_UPPER|K_EDIT);
963: if(code_ok(str))
964: strcpy(cfg.xtrn[i]->code,str);
965: else {
966: uifc.helpbuf=invalid_code;
967: uifc.msg("Invalid Code");
968: uifc.helpbuf=0;
969: }
970: break;
971: case 2:
972: SETHELP(WHERE);
973: /*
974: &Online Program Start-up Directory:&
975:
976: This is the DOS drive/directory where the online program is located.
977: If a path is specified here, it will be made the current directory
978: before the program's command line is executed. This eliminates the need
979: for batch files that just change the current drive and directory before
980: executing the program.
981:
982: If this option is not used, the current NODE's directory will be the
983: current DOS drive/directory before the command line is executed.
984: */
985: uifc.input(WIN_MID|WIN_SAV,0,10,""
986: ,cfg.xtrn[i]->path,sizeof(cfg.xtrn[i]->path)-1,K_EDIT);
987: break;
988: case 3:
989: SETHELP(WHERE);
990: /*
991: &Online Program Command Line:&
992:
993: This is the command line to execute to run the online program.
994: */
995: uifc.input(WIN_MID|WIN_SAV,0,10,"Command"
996: ,cfg.xtrn[i]->cmd,sizeof(cfg.xtrn[i]->cmd)-1,K_EDIT);
997: break;
998: case 4:
999: SETHELP(WHERE);
1000: /*
1001: &Online Program Clean-up Command:&
1002:
1003: This is the command line to execute after the main command line. This
1004: option is usually only used for multiuser online programs.
1005: */
1006: uifc.input(WIN_MID|WIN_SAV,0,10,"Clean-up"
1007: ,cfg.xtrn[i]->clean,sizeof(cfg.xtrn[i]->clean)-1,K_EDIT);
1008: break;
1009: case 5:
1010: ultoa(cfg.xtrn[i]->cost,str,10);
1011: SETHELP(WHERE);
1012: /*
1013: &Online Program Cost to Run:&
1014:
1015: If you want users to be charged credits to run this online program,
1016: set this value to the number of credits to charge. If you want this
1017: online program to be free, set this value to &0&.
1018: */
1019: uifc.input(WIN_MID|WIN_SAV,0,0,"Cost to Run (in Credits)"
1020: ,str,10,K_EDIT|K_NUMBER);
1021: cfg.xtrn[i]->cost=atol(str);
1022: break;
1023: case 6:
1024: uifc.savnum=4;
1025: sprintf(str,"%s Access",cfg.xtrn[i]->name);
1026: getar(str,cfg.xtrn[i]->arstr);
1027: break;
1028: case 7:
1029: uifc.savnum=4;
1030: sprintf(str,"%s Execution",cfg.xtrn[i]->name);
1031: getar(str,cfg.xtrn[i]->run_arstr);
1032: break;
1033: case 8:
1034: k=cfg.xtrn[i]->misc&MULTIUSER ? 0:1;
1035: strcpy(opt[0],"Yes");
1036: strcpy(opt[1],"No");
1037: opt[2][0]=0;
1038: SETHELP(WHERE);
1039: /*
1040: &Supports Multiple Users:&
1041:
1042: If this online program supports multiple simultaneous users (nodes),
1043: set this option to &Yes&.
1044: */
1045: uifc.savnum=4;
1046: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Supports Multiple Users"
1047: ,opt);
1048: if(!k && !(cfg.xtrn[i]->misc&MULTIUSER)) {
1049: cfg.xtrn[i]->misc|=MULTIUSER;
1050: uifc.changes=TRUE; }
1051: else if(k==1 && cfg.xtrn[i]->misc&MULTIUSER) {
1052: cfg.xtrn[i]->misc&=~MULTIUSER;
1053: uifc.changes=TRUE; }
1054: break;
1055: case 9:
1056: k=cfg.xtrn[i]->misc&IO_INTS ? 0:1;
1057: strcpy(opt[0],"Yes");
1058: strcpy(opt[1],"No");
1059: opt[2][0]=0;
1060: SETHELP(WHERE);
1061: /*
1062: &Intercept Standard I/O:&
1063:
1064: If this online program uses a FOSSIL driver or SOCKET communications,
1065: set this option to &No&.
1066: */
1067: uifc.savnum=4;
1068: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Intercept Standard I/O"
1069: ,opt);
1070: if(!k && !(cfg.xtrn[i]->misc&IO_INTS)) {
1071: cfg.xtrn[i]->misc|=IO_INTS;
1072: uifc.changes=TRUE; }
1073: else if(k==1 && cfg.xtrn[i]->misc&IO_INTS) {
1074: cfg.xtrn[i]->misc&=~(IO_INTS|WWIVCOLOR);
1075: uifc.changes=TRUE; }
1076: else if(k==-1)
1077: break;
1078: if(!(cfg.xtrn[i]->misc&IO_INTS))
1079: break;
1080: k=cfg.xtrn[i]->misc&WWIVCOLOR ? 0:1;
1081: SETHELP(WHERE);
1082: /*
1083: &Program Uses WWIV Color Codes:&
1084:
1085: If this program was written for use exclusively under WWIV, set this
1086: option to &Yes&.
1087: */
1088: uifc.savnum=4;
1089: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1090: ,"Program Uses WWIV Color Codes"
1091: ,opt);
1092: if(!k && !(cfg.xtrn[i]->misc&WWIVCOLOR)) {
1093: cfg.xtrn[i]->misc|=WWIVCOLOR;
1094: uifc.changes=TRUE; }
1095: else if(k==1 && cfg.xtrn[i]->misc&WWIVCOLOR) {
1096: cfg.xtrn[i]->misc&=~WWIVCOLOR;
1097: uifc.changes=TRUE; }
1098: k=cfg.xtrn[i]->misc&XTRN_NOECHO ? 1:0;
1099: SETHELP(WHERE);
1100: /*
1101: `Echo Input:`
1102:
1103: If you want the BBS to copy ("echo") all keyboard input to the screen
1104: output, set this option to ~Yes~ (for native Win32 programs only).
1105: */
1106: uifc.savnum=4;
1107: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1108: ,"Echo Keyboard Input"
1109: ,opt);
1110: if(!k && cfg.xtrn[i]->misc&XTRN_NOECHO) {
1111: cfg.xtrn[i]->misc&=~XTRN_NOECHO;
1112: uifc.changes=TRUE;
1113: } else if(k==1 && !(cfg.xtrn[i]->misc&XTRN_NOECHO)) {
1114: cfg.xtrn[i]->misc|=XTRN_NOECHO;
1115: uifc.changes=TRUE;
1116: }
1117: break;
1118: case 10:
1119: k=cfg.xtrn[i]->misc&XTRN_NATIVE ? 0:1;
1120: strcpy(opt[0],"Yes");
1121: strcpy(opt[1],"No");
1122: opt[2][0]=0;
1123: SETHELP(WHERE);
1124: /*
1125: &Native (32-bit) Executable:&
1126:
1127: If this online program is a native 32-bit executable,
1128: set this option to &Yes&.
1129: */
1130: uifc.savnum=4;
1131: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1132: ,"Native (32-bit)",opt);
1133: if(!k && !(cfg.xtrn[i]->misc&XTRN_NATIVE)) {
1134: cfg.xtrn[i]->misc|=XTRN_NATIVE;
1135: uifc.changes=TRUE; }
1136: else if(k==1 && cfg.xtrn[i]->misc&XTRN_NATIVE) {
1137: cfg.xtrn[i]->misc&=~XTRN_NATIVE;
1138: uifc.changes=TRUE; }
1139: break;
1140: case 11:
1141: k=cfg.xtrn[i]->misc&XTRN_SH ? 0:1;
1142: strcpy(opt[0],"Yes");
1143: strcpy(opt[1],"No");
1144: opt[2][0]=0;
1145: SETHELP(WHERE);
1146: /*
1147: `Use Shell to Execute Command:`
1148:
1149: If this command-line requires the system command shell to execute, (Unix
1150: shell script or DOS batch file), set this option to ~Yes~.
1151: */
1152: uifc.savnum=4;
1153: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1154: ,"Use Shell",opt);
1155: if(!k && !(cfg.xtrn[i]->misc&XTRN_SH)) {
1156: cfg.xtrn[i]->misc|=XTRN_SH;
1157: uifc.changes=TRUE;
1158: }
1159: else if(k==1 && cfg.xtrn[i]->misc&XTRN_SH) {
1160: cfg.xtrn[i]->misc&=~XTRN_SH;
1161: uifc.changes=TRUE;
1162: }
1163: break;
1164: case 12:
1165: k=cfg.xtrn[i]->misc&MODUSERDAT ? 0:1;
1166: strcpy(opt[0],"Yes");
1167: strcpy(opt[1],"No");
1168: opt[2][0]=0;
1169: SETHELP(WHERE);
1170: /*
1171: &Program Can Modify User Data:&
1172:
1173: If this online programs recognizes the Synchronet MODUSER.DAT format
1174: or the RBBS/QuickBBS EXITINFO.BBS format and you want it to be able to
1175: modify the data of users who run the program, set this option to &Yes&.
1176: */
1177: uifc.savnum=4;
1178: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1179: ,"Program Can Modify User Data",opt);
1180: if(!k && !(cfg.xtrn[i]->misc&MODUSERDAT)) {
1181: cfg.xtrn[i]->misc|=MODUSERDAT;
1182: uifc.changes=TRUE; }
1183: else if(k==1 && cfg.xtrn[i]->misc&MODUSERDAT) {
1184: cfg.xtrn[i]->misc&=~MODUSERDAT;
1185: uifc.changes=TRUE; }
1186: break;
1187: case 13:
1188: k=0;
1189: strcpy(opt[k++],"No");
1190: strcpy(opt[k++],"Logon");
1191: strcpy(opt[k++],"Logoff");
1192: strcpy(opt[k++],"New User");
1193: strcpy(opt[k++],"Birthday");
1194: strcpy(opt[k++],"Message Posted");
1195: strcpy(opt[k++],"File Uploaded");
1196: strcpy(opt[k++],"File Downloaded");
1197: opt[k][0]=0;
1198: k=cfg.xtrn[i]->event;
1199: SETHELP(WHERE);
1200: /*
1201: &Execute Online Program on Event:&
1202:
1203: If you would like this online program to automatically execute on a
1204: specific user event, select the event. Otherwise, select &No&.
1205: */
1206: uifc.savnum=4;
1207: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1208: ,"Execute on Event",opt);
1209: if(k==-1)
1210: break;
1211: if(cfg.xtrn[i]->event!=k) {
1212: cfg.xtrn[i]->event=k;
1213: uifc.changes=TRUE; }
1214: if(!cfg.xtrn[i]->event)
1215: break;
1216: k=cfg.xtrn[i]->misc&EVENTONLY ? 0:1;
1217: strcpy(opt[0],"Yes");
1218: strcpy(opt[1],"No");
1219: opt[2][0]=0;
1220: SETHELP(WHERE);
1221: /*
1222: &Execute Online Program as Event Only:&
1223:
1224: If you would like this online program to execute as an event only
1225: (not available to users on the online program menu), set this option
1226: to &Yes&.
1227: */
1228: uifc.savnum=4;
1229: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k
1230: ,0,"Execute as Event Only"
1231: ,opt);
1232: if(!k && !(cfg.xtrn[i]->misc&EVENTONLY)) {
1233: cfg.xtrn[i]->misc|=EVENTONLY;
1234: uifc.changes=TRUE; }
1235: else if(k==1 && cfg.xtrn[i]->misc&EVENTONLY) {
1236: cfg.xtrn[i]->misc&=~EVENTONLY;
1237: uifc.changes=TRUE; }
1238: break;
1239: case 14:
1240: k=cfg.xtrn[i]->misc&XTRN_PAUSE ? 0:1;
1241: strcpy(opt[0],"Yes");
1242: strcpy(opt[1],"No");
1243: opt[2][0]=0;
1244: SETHELP(WHERE);
1245: /*
1246: `Pause Screen After Execution:`
1247:
1248: Set this option to ~Yes~ if you would like an automatic screen pause
1249: (`[Hit a key]` prompt) to appear after the program executes.
1250:
1251: This can be useful if the program displays information just before exiting
1252: or you want to debug a program with a program not running correctly.
1253: */
1254: uifc.savnum=4;
1255: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1256: ,"Pause After Execution",opt);
1257: if((!k && !(cfg.xtrn[i]->misc&XTRN_PAUSE))
1258: || (k && cfg.xtrn[i]->misc&XTRN_PAUSE)) {
1259: cfg.xtrn[i]->misc^=XTRN_PAUSE;
1260: uifc.changes=TRUE;
1261: }
1262: break;
1263: case 15:
1264: k=0;
1265: strcpy(opt[k++],"None");
1266: sprintf(opt[k++],"%-15s %s","Synchronet","XTRN.DAT");
1267: sprintf(opt[k++],"%-15s %s","WWIV","CHAIN.TXT");
1268: sprintf(opt[k++],"%-15s %s","GAP","DOOR.SYS");
1269: sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO#.DEF");
1270: sprintf(opt[k++],"%-15s %s","Wildcat","CALLINFO.BBS");
1271: sprintf(opt[k++],"%-15s %s","PCBoard","PCBOARD.SYS");
1272: sprintf(opt[k++],"%-15s %s","SpitFire","SFDOORS.DAT");
1273: sprintf(opt[k++],"%-15s %s","MegaMail","UTIDOOR.TXT");
1274: sprintf(opt[k++],"%-15s %s","Solar Realms","DOORFILE.SR");
1275: sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO1.DEF");
1276: sprintf(opt[k++],"%-15s %s","TriBBS","TRIBBS.SYS");
1277: sprintf(opt[k++],"%-15s %s","Mystic","DOOR32.SYS");
1278: opt[k][0]=0;
1279: k=cfg.xtrn[i]->type;
1280: SETHELP(WHERE);
1281: /*
1282: &Online Program BBS Drop File Type:&
1283:
1284: If this online program requires a specific BBS data (drop) file
1285: format, select the file format from the list.
1286: */
1287: uifc.savnum=4;
1288: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1289: ,"BBS Drop File Type",opt);
1290: if(k==-1)
1291: break;
1292: if(cfg.xtrn[i]->type!=k) {
1293: cfg.xtrn[i]->type=k;
1294: if(cfg.xtrn[i]->type==XTRN_DOOR32)
1295: cfg.xtrn[i]->misc|=XTRN_NATIVE;
1296: uifc.changes=TRUE; }
1297: if(cfg.xtrn[i]->type && cfg.uq&UQ_ALIASES) {
1298: strcpy(opt[0],"Yes");
1299: strcpy(opt[1],"No");
1300: opt[2][0]=0;
1301: k=cfg.xtrn[i]->misc&REALNAME ? 0:1;
1302: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Use Real Names",opt);
1303: if(k==0 && !(cfg.xtrn[i]->misc&REALNAME)) {
1304: cfg.xtrn[i]->misc|=REALNAME;
1305: uifc.changes=TRUE; }
1306: else if(k==1 && cfg.xtrn[i]->misc&REALNAME) {
1307: cfg.xtrn[i]->misc&=~REALNAME;
1308: uifc.changes=TRUE;
1309: }
1310: }
1311: if(cfg.xtrn[i]->type) {
1312: strcpy(opt[0],"Yes");
1313: strcpy(opt[1],"No");
1314: opt[2][0]=0;
1315: k=cfg.xtrn[i]->misc&XTRN_LWRCASE ? 0:1;
1316: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Lowercase Filename",opt);
1317: if(k==0 && !(cfg.xtrn[i]->misc&XTRN_LWRCASE)) {
1318: cfg.xtrn[i]->misc|=XTRN_LWRCASE;
1319: uifc.changes=TRUE;
1320: }
1321: else if(k==1 && cfg.xtrn[i]->misc&XTRN_LWRCASE) {
1322: cfg.xtrn[i]->misc&=~XTRN_LWRCASE;
1323: uifc.changes=TRUE;
1324: }
1325: }
1326: break;
1327: case 16:
1328: k=0;
1329: strcpy(opt[0],"Node Directory");
1330: strcpy(opt[1],"Start-up Directory");
1331: opt[2][0]=0;
1332: SETHELP(WHERE);
1333: /*
1334: &Directory for Drop File:&
1335:
1336: You can have the data file created in the current &Node Directory& or the
1337: &Start-up Directory& (if one is specified).
1338: */
1339: uifc.savnum=4;
1340: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Create Drop File In"
1341: ,opt);
1342: if(!k && cfg.xtrn[i]->misc&STARTUPDIR) {
1343: cfg.xtrn[i]->misc&=~STARTUPDIR;
1344: uifc.changes=TRUE; }
1345: else if(k==1 && !(cfg.xtrn[i]->misc&STARTUPDIR)) {
1346: cfg.xtrn[i]->misc|=STARTUPDIR;
1347: uifc.changes=TRUE; }
1348: break;
1349: case 17:
1350: while(1) {
1351: k=0;
1352: if(cfg.xtrn[i]->textra)
1353: sprintf(str,"%u minutes",cfg.xtrn[i]->textra);
1354: else
1355: strcpy(str,"None");
1356: sprintf(opt[k++],"%-25.25s%s","Extra Time",str);
1357: if(cfg.xtrn[i]->maxtime)
1358: sprintf(str,"%u minutes",cfg.xtrn[i]->maxtime);
1359: else
1360: strcpy(str,"None");
1361: sprintf(opt[k++],"%-25.25s%s","Maximum Time",str);
1362: sprintf(opt[k++],"%-25.25s%s","Suspended (Free) Time"
1363: ,cfg.xtrn[i]->misc&FREETIME ? "Yes" : "No");
1364: sprintf(opt[k++],"%-25.25s%s","Monitor Time Left"
1365: ,cfg.xtrn[i]->misc&XTRN_CHKTIME ? "Yes" : "No");
1366: opt[k][0]=0;
1367: SETHELP(WHERE);
1368: /*
1369: &Online Program Time Options:&
1370:
1371: This sub-menu allows you to define specific preferences regarding the
1372: time users spend running this program.
1373: */
1374: uifc.savnum=4;
1375: k=uifc.list(WIN_SAV|WIN_ACT|WIN_RHT|WIN_BOT,0,0,40
1376: ,&time_dflt,0
1377: ,"Online Program Time Options",opt);
1378: if(k==-1)
1379: break;
1380: uifc.savnum=5;
1381: switch(k) {
1382: case 0:
1383: ultoa(cfg.xtrn[i]->textra,str,10);
1384: SETHELP(WHERE);
1385: /*
1386: &Extra Time to Give User in Program:&
1387:
1388: If you want to give users extra time while in this online program,
1389: set this value to the number of minutes to add to their current time
1390: left online.
1391: */
1392: uifc.input(WIN_MID|WIN_SAV,0,0
1393: ,"Extra Time to Give User (in minutes)"
1394: ,str,2,K_EDIT|K_NUMBER);
1395: cfg.xtrn[i]->textra=atoi(str);
1396: break;
1397: case 1:
1398: ultoa(cfg.xtrn[i]->maxtime,str,10);
1399: SETHELP(WHERE);
1400: /*
1401: &Maximum Time Allowed in Program:&
1402:
1403: If this program supports a drop file that contains the number of minutes
1404: left online for the current user, this option allows the sysop to set
1405: the maximum number of minutes that will be allowed in the drop file.
1406:
1407: Setting this option to &0&, disables this feature.
1408: */
1409: uifc.input(WIN_MID|WIN_SAV,0,0
1410: ,"Maximum Time (in minutes, 0=disabled)"
1411: ,str,2,K_EDIT|K_NUMBER);
1412: cfg.xtrn[i]->maxtime=atoi(str);
1413: break;
1414: case 2:
1415: k=cfg.xtrn[i]->misc&FREETIME ? 0:1;
1416: strcpy(opt[0],"Yes");
1417: strcpy(opt[1],"No");
1418: opt[2][0]=0;
1419: SETHELP(WHERE);
1420: /*
1421: &Suspended (Free) Time:&
1422:
1423: If you want the user's time online to be suspended while running this
1424: online program (e.g. Free Time), set this option to &Yes&.
1425: */
1426: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1427: ,"Suspended (Free) Time",opt);
1428: if(!k && !(cfg.xtrn[i]->misc&FREETIME)) {
1429: cfg.xtrn[i]->misc|=FREETIME;
1430: uifc.changes=TRUE; }
1431: else if(k==1 && cfg.xtrn[i]->misc&FREETIME) {
1432: cfg.xtrn[i]->misc&=~FREETIME;
1433: uifc.changes=TRUE; }
1434: break;
1435: case 3:
1436: k=cfg.xtrn[i]->misc&XTRN_CHKTIME ? 0:1;
1437: strcpy(opt[0],"Yes");
1438: strcpy(opt[1],"No");
1439: opt[2][0]=0;
1440: SETHELP(WHERE);
1441: /*
1442: &Monitor Time Left:&
1443:
1444: If you want Synchronet to monitor the user's time left onlnie while this
1445: program runs (and disconnect the user if their time runs out), set this
1446: option to &Yes&.
1447: */
1448: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1449: ,"Monitor Time Left",opt);
1450: if(!k && !(cfg.xtrn[i]->misc&XTRN_CHKTIME)) {
1451: cfg.xtrn[i]->misc|=XTRN_CHKTIME;
1452: uifc.changes=TRUE; }
1453: else if(k==1 && cfg.xtrn[i]->misc&XTRN_CHKTIME) {
1454: cfg.xtrn[i]->misc&=~XTRN_CHKTIME;
1455: uifc.changes=TRUE; }
1456: break;
1457: }
1458: }
1459: break;
1460:
1461: } } }
1462: }
1463:
1464: void xedit_cfg()
1465: {
1466: static int dflt,dfltopt,bar;
1467: char str[81],code[81],done=0,*p;
1468: int j,k;
1469: uint i;
1470: static xedit_t savxedit;
1471:
1472: while(1) {
1473: for(i=0;i<cfg.total_xedits && i<MAX_OPTS;i++)
1474: sprintf(opt[i],"%-8.8s %.40s",cfg.xedit[i]->code,cfg.xedit[i]->rcmd);
1475: opt[i][0]=0;
1476: j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_RHT;
1477: uifc.savnum=0;
1478: if(cfg.total_xedits)
1479: j|=WIN_DEL|WIN_GET;
1480: if(cfg.total_xedits<MAX_OPTS)
1481: j|=WIN_INS|WIN_INSACT|WIN_XTR;
1482: if(savxedit.name[0])
1483: j|=WIN_PUT;
1484: SETHELP(WHERE);
1485: /*
1486: &External Editors:&
1487:
1488: This is a list of the configured external editors.
1489:
1490: To add an editor, select the desired location and hit INS .
1491:
1492: To delete an editor, select it and hit DEL .
1493:
1494: To configure an editor, select it and hit ENTER .
1495: */
1496: i=uifc.list(j,0,0,45,&dflt,&bar,"External Editors",opt);
1497: if((signed)i==-1)
1498: return;
1499: if((i&MSK_ON)==MSK_INS) {
1500: i&=MSK_OFF;
1501: SETHELP(WHERE);
1502: /*
1503: &External Editor Name:&
1504:
1505: This is the name or description of the external editor.
1506: */
1507: if(uifc.input(WIN_MID|WIN_SAV,0,0,"External Editor Name",str,40
1508: ,0)<1)
1509: continue;
1510: sprintf(code,"%.8s",str);
1511: p=strchr(code,' ');
1512: if(p) *p=0;
1513: strupr(code);
1514: SETHELP(WHERE);
1515: /*
1516: &External Editor Internal Code:&
1517:
1518: This is the internal code for the external editor.
1519: */
1520: if(uifc.input(WIN_MID|WIN_SAV,0,0,"External Editor Internal Code",code,8
1521: ,K_UPPER|K_EDIT)<1)
1522: continue;
1523: if(!code_ok(code)) {
1524: uifc.helpbuf=invalid_code;
1525: uifc.msg("Invalid Code");
1526: uifc.helpbuf=0;
1527: continue; }
1528:
1529: if((cfg.xedit=(xedit_t **)REALLOC(cfg.xedit
1530: ,sizeof(xedit_t *)*(cfg.total_xedits+1)))==NULL) {
1531: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_xedits+1);
1532: cfg.total_xedits=0;
1533: bail(1);
1534: continue; }
1535: if(cfg.total_xedits)
1536: for(j=cfg.total_xedits;j>i;j--)
1537: cfg.xedit[j]=cfg.xedit[j-1];
1538: if((cfg.xedit[i]=(xedit_t *)MALLOC(sizeof(xedit_t)))==NULL) {
1539: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(xedit_t));
1540: continue; }
1541: memset((xedit_t *)cfg.xedit[i],0,sizeof(xedit_t));
1542: strcpy(cfg.xedit[i]->name,str);
1543: strcpy(cfg.xedit[i]->code,code);
1544: cfg.total_xedits++;
1545: uifc.changes=TRUE;
1546: continue; }
1547: if((i&MSK_ON)==MSK_DEL) {
1548: i&=MSK_OFF;
1549: FREE(cfg.xedit[i]);
1550: cfg.total_xedits--;
1551: for(j=i;j<cfg.total_xedits;j++)
1552: cfg.xedit[j]=cfg.xedit[j+1];
1553: uifc.changes=TRUE;
1554: continue; }
1555: if((i&MSK_ON)==MSK_GET) {
1556: i&=MSK_OFF;
1557: savxedit=*cfg.xedit[i];
1558: continue; }
1559: if((i&MSK_ON)==MSK_PUT) {
1560: i&=MSK_OFF;
1561: *cfg.xedit[i]=savxedit;
1562: uifc.changes=TRUE;
1563: continue; }
1564: done=0;
1565: while(!done) {
1566: k=0;
1567: sprintf(opt[k++],"%-32.32s%s","Name",cfg.xedit[i]->name);
1568: sprintf(opt[k++],"%-32.32s%s","Internal Code",cfg.xedit[i]->code);
1569: sprintf(opt[k++],"%-32.32s%.40s","Remote Command Line",cfg.xedit[i]->rcmd);
1570: sprintf(opt[k++],"%-32.32s%.40s","Access Requirements",cfg.xedit[i]->arstr);
1571: sprintf(opt[k++],"%-32.32s%s%s","Intercept Standard I/O"
1572: ,cfg.xedit[i]->misc&IO_INTS ? "Yes":"No"
1573: ,cfg.xedit[i]->misc&WWIVCOLOR ? ", WWIV" : nulstr);
1574: sprintf(opt[k++],"%-32.32s%s","Native (32-bit) Executable"
1575: ,cfg.xedit[i]->misc&XTRN_NATIVE ? "Yes" : "No");
1576: sprintf(opt[k++],"%-32.32s%s","Use Shell to Execute"
1577: ,cfg.xedit[i]->misc&XTRN_SH ? "Yes" : "No");
1578: sprintf(opt[k++],"%-32.32s%s","Quoted Text"
1579: ,cfg.xedit[i]->misc"EALL ? "All":cfg.xedit[i]->misc"ENONE
1580: ? "None" : "Prompt User");
1581: sprintf(opt[k++],"%-32.32s%s","QuickBBS Style (MSGTMP)"
1582: ,cfg.xedit[i]->misc&QUICKBBS ? "Yes":"No");
1583: sprintf(opt[k++],"%-32.32s%s","Expand Line Feeds to CRLF"
1584: ,cfg.xedit[i]->misc&EXPANDLF ? "Yes":"No");
1585: sprintf(opt[k++],"%-32.32s%s","Strip FidoNet Kludge Lines"
1586: ,cfg.xedit[i]->misc&STRIPKLUDGE ? "Yes":"No");
1587: sprintf(opt[k++],"%-32.32s%s","BBS Drop File Type"
1588: ,dropfile(cfg.xedit[i]->type,cfg.xedit[i]->misc));
1589: opt[k][0]=0;
1590: SETHELP(WHERE);
1591: /*
1592: &External Editor Configuration:&
1593:
1594: This menu allows you to change the settings for the selected external
1595: message editor. External message editors are very common on BBSs. Some
1596: popular editors include &SyncEdit&, &WWIVedit&, &FEdit&, &GEdit&, &IceEdit&,
1597: and many others.
1598: */
1599:
1600: uifc.savnum=1;
1601: sprintf(str,"%s Editor",cfg.xedit[i]->name);
1602: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_L2R|WIN_BOT,0,0,70,&dfltopt,0
1603: ,str,opt)) {
1604: case -1:
1605: done=1;
1606: break;
1607: case 0:
1608: SETHELP(WHERE);
1609: /*
1610: &External Editor Name:&
1611:
1612: This is the name or description of the external editor.
1613: */
1614: strcpy(str,cfg.xedit[i]->name);
1615: if(!uifc.input(WIN_MID|WIN_SAV,0,10,"External Editor Name"
1616: ,cfg.xedit[i]->name,sizeof(cfg.xedit[i]->name)-1,K_EDIT))
1617: strcpy(cfg.xedit[i]->name,str);
1618: break;
1619: case 1:
1620: strcpy(str,cfg.xedit[i]->code);
1621: SETHELP(WHERE);
1622: /*
1623: &External Editor Internal Code:&
1624:
1625: Every external editor must have its own unique internal code for
1626: Synchronet to reference it by. It is helpful if this code is an
1627: abreviation of the name.
1628: */
1629: uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
1630: ,str,LEN_CODE,K_EDIT|K_UPPER);
1631: if(code_ok(str))
1632: strcpy(cfg.xedit[i]->code,str);
1633: else {
1634: uifc.helpbuf=invalid_code;
1635: uifc.msg("Invalid Code");
1636: uifc.helpbuf=0; }
1637: break;
1638: case 2:
1639: SETHELP(WHERE);
1640: /*
1641: &External Editor Remote Command Line:&
1642:
1643: This is the command line to execute when using this editor remotely.
1644: */
1645: uifc.input(WIN_MID|WIN_SAV,0,10,"Remote"
1646: ,cfg.xedit[i]->rcmd,sizeof(cfg.xedit[i]->rcmd)-1,K_EDIT);
1647: break;
1648: case 3:
1649: uifc.savnum=2;
1650: sprintf(str,"%s External Editor",cfg.xedit[i]->name);
1651: getar(str,cfg.xedit[i]->arstr);
1652: break;
1653: case 4:
1654: k=cfg.xedit[i]->misc&IO_INTS ? 0:1;
1655: strcpy(opt[0],"Yes");
1656: strcpy(opt[1],"No");
1657: opt[2][0]=0;
1658: uifc.savnum=2;
1659: SETHELP(WHERE);
1660: /*
1661: &Intercept Standard I/O:&
1662:
1663: If this external editor uses a FOSSIL driver or SOCKET communications,
1664: set this option to &No&.
1665: */
1666: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Intercept Standard I/O"
1667: ,opt);
1668: if(!k && !(cfg.xedit[i]->misc&IO_INTS)) {
1669: cfg.xedit[i]->misc|=IO_INTS;
1670: uifc.changes=TRUE; }
1671: else if(k==1 && cfg.xedit[i]->misc&IO_INTS) {
1672: cfg.xedit[i]->misc&=~(IO_INTS|WWIVCOLOR);
1673: uifc.changes=TRUE; }
1674: if(!(cfg.xedit[i]->misc&IO_INTS))
1675: break;
1676: k=cfg.xedit[i]->misc&WWIVCOLOR ? 0:1;
1677: strcpy(opt[0],"Yes");
1678: strcpy(opt[1],"No");
1679: opt[2][0]=0;
1680: uifc.savnum=2;
1681: SETHELP(WHERE);
1682: /*
1683: &Editor Uses WWIV Color Codes:&
1684:
1685: If this editor was written for use exclusively under WWIV, set this
1686: option to &Yes&.
1687: */
1688: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1689: ,"Editor Uses WWIV Color Codes",opt);
1690: if(!k && !(cfg.xedit[i]->misc&WWIVCOLOR)) {
1691: cfg.xedit[i]->misc|=WWIVCOLOR;
1692: uifc.changes=TRUE; }
1693: else if(k==1 && cfg.xedit[i]->misc&WWIVCOLOR) {
1694: cfg.xedit[i]->misc&=~WWIVCOLOR;
1695: uifc.changes=TRUE; }
1696: break;
1697: case 5:
1698: k=cfg.xedit[i]->misc&XTRN_NATIVE ? 0:1;
1699: strcpy(opt[0],"Yes");
1700: strcpy(opt[1],"No");
1701: opt[2][0]=0;
1702: SETHELP(WHERE);
1703: /*
1704: &Native (32-bit) Executable:&
1705:
1706: If this editor is a native 32-bit executable, set this option to &Yes&.
1707: */
1708: uifc.savnum=2;
1709: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1710: ,"Native (32-bit)",opt);
1711: if(!k && !(cfg.xedit[i]->misc&XTRN_NATIVE)) {
1712: cfg.xedit[i]->misc|=XTRN_NATIVE;
1713: uifc.changes=TRUE; }
1714: else if(k==1 && cfg.xedit[i]->misc&XTRN_NATIVE) {
1715: cfg.xedit[i]->misc&=~XTRN_NATIVE;
1716: uifc.changes=TRUE; }
1717: break;
1718: case 6:
1719: k=cfg.xedit[i]->misc&XTRN_SH ? 0:1;
1720: strcpy(opt[0],"Yes");
1721: strcpy(opt[1],"No");
1722: opt[2][0]=0;
1723: SETHELP(WHERE);
1724: /*
1725: `Use Shell to Execute Command:`
1726:
1727: If this command-line requires the system command shell to execute, (Unix
1728: shell script or DOS batch file), set this option to ~Yes~.
1729: */
1730: uifc.savnum=2;
1731: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1732: ,"Use Shell",opt);
1733: if(!k && !(cfg.xedit[i]->misc&XTRN_SH)) {
1734: cfg.xedit[i]->misc|=XTRN_SH;
1735: uifc.changes=TRUE;
1736: } else if(k==1 && cfg.xedit[i]->misc&XTRN_SH) {
1737: cfg.xedit[i]->misc&=~XTRN_SH;
1738: uifc.changes=TRUE;
1739: }
1740: break;
1741: case 7:
1742: k=3;
1743: strcpy(opt[0],"All");
1744: strcpy(opt[1],"None");
1745: strcpy(opt[2],"Prompt User");
1746: opt[3][0]=0;
1747: uifc.savnum=2;
1748: SETHELP(WHERE);
1749: /*
1750: &Quoted Text:&
1751:
1752: If you want all the message text to be automatically entered into the
1753: message edit/quote file (&INPUT.MSG& or &MSGTMP&), select &All&.
1754:
1755: If you want the user to be prompted for which lines to quote before
1756: running the editor, select &Prompt User&.
1757:
1758: If you want none of the lines to be automatically quoted, select &None&.
1759: This option is mainly for use with editors that support the "ES.TXT&
1760: drop file (like &SyncEdit v2.x&).
1761: */
1762: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Quoted Text"
1763: ,opt);
1764: if(!k && !(cfg.xedit[i]->misc"EALL)) {
1765: cfg.xedit[i]->misc|=QUOTEALL;
1766: cfg.xedit[i]->misc&=~QUOTENONE;
1767: uifc.changes=TRUE; }
1768: else if(k==1 && !(cfg.xedit[i]->misc"ENONE)) {
1769: cfg.xedit[i]->misc|=QUOTENONE;
1770: cfg.xedit[i]->misc&=~QUOTEALL;
1771: uifc.changes=TRUE; }
1772: else if(k==2 && cfg.xedit[i]->misc&(QUOTENONE|QUOTEALL)) {
1773: cfg.xedit[i]->misc&=~(QUOTENONE|QUOTEALL);
1774: uifc.changes=TRUE; }
1775: break;
1776: case 8:
1777: k=cfg.xedit[i]->misc&QUICKBBS ? 0:1;
1778: strcpy(opt[0],"Yes");
1779: strcpy(opt[1],"No");
1780: opt[2][0]=0;
1781: uifc.savnum=2;
1782: SETHELP(WHERE);
1783: /*
1784: &QuickBBS Style (MSGTMP):&
1785:
1786: If this external editor uses the QuickBBS style MSGTMP interface, set
1787: this option to &Yes&.
1788: */
1789: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"QuickBBS Style (MSGTMP)"
1790: ,opt);
1791: if(!k && !(cfg.xedit[i]->misc&QUICKBBS)) {
1792: cfg.xedit[i]->misc|=QUICKBBS;
1793: uifc.changes=TRUE; }
1794: else if(k==1 && cfg.xedit[i]->misc&QUICKBBS) {
1795: cfg.xedit[i]->misc&=~QUICKBBS;
1796: uifc.changes=TRUE; }
1797: break;
1798: case 9:
1799: k=cfg.xedit[i]->misc&EXPANDLF ? 0:1;
1800: strcpy(opt[0],"Yes");
1801: strcpy(opt[1],"No");
1802: opt[2][0]=0;
1803: uifc.savnum=2;
1804: SETHELP(WHERE);
1805: /*
1806: &Expand Line Feeds to Carriage Return/Line Feed Pairs:&
1807:
1808: If this external editor saves new lines as a single line feed character
1809: instead of a carriage return/line feed pair, set this option to &Yes&.
1810: */
1811: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Expand LF to CRLF"
1812: ,opt);
1813: if(!k && !(cfg.xedit[i]->misc&EXPANDLF)) {
1814: cfg.xedit[i]->misc|=EXPANDLF;
1815: uifc.changes=TRUE; }
1816: else if(k==1 && cfg.xedit[i]->misc&EXPANDLF) {
1817: cfg.xedit[i]->misc&=~EXPANDLF;
1818: uifc.changes=TRUE; }
1819: break;
1820: case 10:
1821: k=cfg.xedit[i]->misc&STRIPKLUDGE ? 0:1;
1822: strcpy(opt[0],"Yes");
1823: strcpy(opt[1],"No");
1824: opt[2][0]=0;
1825: uifc.savnum=2;
1826: SETHELP(WHERE);
1827: /*
1828: &Strip FidoNet Kludge Lines From Messages:&
1829:
1830: If this external editor adds FidoNet Kludge lines to the message text,
1831: set this option to &Yes& to strip those lines from the message.
1832: */
1833: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1834: ,"Strip FidoNet Kludge Lines"
1835: ,opt);
1836: if(!k && !(cfg.xedit[i]->misc&STRIPKLUDGE)) {
1837: cfg.xedit[i]->misc|=STRIPKLUDGE;
1838: uifc.changes=TRUE; }
1839: else if(k==1 && cfg.xedit[i]->misc&STRIPKLUDGE) {
1840: cfg.xedit[i]->misc&=~STRIPKLUDGE;
1841: uifc.changes=TRUE; }
1842: break;
1843: case 11:
1844: k=0;
1845: strcpy(opt[k++],"None");
1846: sprintf(opt[k++],"%-15s %s","Synchronet","XTRN.DAT");
1847: sprintf(opt[k++],"%-15s %s","WWIV","CHAIN.TXT");
1848: sprintf(opt[k++],"%-15s %s","GAP","DOOR.SYS");
1849: sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO#.DEF");
1850: sprintf(opt[k++],"%-15s %s","Wildcat","CALLINFO.BBS");
1851: sprintf(opt[k++],"%-15s %s","PCBoard","PCBOARD.SYS");
1852: sprintf(opt[k++],"%-15s %s","SpitFire","SFDOORS.DAT");
1853: sprintf(opt[k++],"%-15s %s","MegaMail","UTIDOOR.TXT");
1854: sprintf(opt[k++],"%-15s %s","Solar Realms","DOORFILE.SR");
1855: sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO1.DEF");
1856: sprintf(opt[k++],"%-15s %s","TriBBS","TRIBBS.SYS");
1857: sprintf(opt[k++],"%-15s %s","Mystic","DOOR32.SYS");
1858: opt[k][0]=0;
1859: k=cfg.xedit[i]->type;
1860: SETHELP(WHERE);
1861: /*
1862: &External Program BBS Drop File Type:&
1863:
1864: If this external editor requires a specific BBS data (drop) file
1865: format, select the file format from the list.
1866: */
1867: uifc.savnum=2;
1868: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1869: ,"BBS Drop File Type",opt);
1870: if(k==-1)
1871: break;
1872: if(cfg.xedit[i]->type!=k) {
1873: cfg.xedit[i]->type=k;
1874: if(cfg.xedit[i]->type==XTRN_DOOR32)
1875: cfg.xedit[i]->misc|=XTRN_NATIVE;
1876: uifc.changes=TRUE;
1877: }
1878: if(cfg.xedit[i]->type) {
1879: strcpy(opt[0],"Yes");
1880: strcpy(opt[1],"No");
1881: opt[2][0]=0;
1882: k=cfg.xedit[i]->misc&XTRN_LWRCASE ? 0:1;
1883: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Lowercase Filename",opt);
1884: if(k==0 && !(cfg.xedit[i]->misc&XTRN_LWRCASE)) {
1885: cfg.xedit[i]->misc|=XTRN_LWRCASE;
1886: uifc.changes=TRUE;
1887: }
1888: else if(k==1 && cfg.xedit[i]->misc&XTRN_LWRCASE) {
1889: cfg.xedit[i]->misc&=~XTRN_LWRCASE;
1890: uifc.changes=TRUE;
1891: }
1892: }
1893: break;
1894:
1895: } } }
1896: }
1897:
1898: int natvpgm_cfg()
1899: {
1900: static int dflt,bar;
1901: char str[81];
1902: int j;
1903: uint i;
1904:
1905: while(1) {
1906: for(i=0;i<MAX_OPTS && i<cfg.total_natvpgms;i++)
1907: sprintf(opt[i],"%-12s",cfg.natvpgm[i]->name);
1908: opt[i][0]=0;
1909: j=WIN_ACT|WIN_CHE|WIN_L2R|WIN_SAV;
1910: uifc.savnum=0;
1911: if(cfg.total_natvpgms)
1912: j|=WIN_DEL;
1913: if(cfg.total_natvpgms<MAX_OPTS)
1914: j|=WIN_INS|WIN_INSACT|WIN_XTR;
1915: SETHELP(WHERE);
1916: /*
1917: &Native (32-bit) Program List:&
1918:
1919: This is a list of all native (32-bit) external program (executable file)
1920: names that you may execute under &Synchronet&. This list is not
1921: used in Synchronet for DOS. Any programs not listed here will be assumed
1922: to be DOS programs and executed accordingly.
1923:
1924: Use INS and DELETE to add and remove native program names.
1925:
1926: To change the filename of a program, hit ENTER .
1927: */
1928: i=uifc.list(j,0,0,30,&dflt,&bar,"Native (32-bit) Program List",opt);
1929: if((signed)i==-1)
1930: break;
1931: if((i&MSK_ON)==MSK_INS) {
1932: i&=MSK_OFF;
1933: SETHELP(WHERE);
1934: /*
1935: &Native (32-bit) Program Name:&
1936:
1937: This is the executable filename of the native external program.
1938: */
1939: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Native Program Name",str,12
1940: ,0)<1)
1941: continue;
1942: if((cfg.natvpgm=(natvpgm_t **)REALLOC(cfg.natvpgm
1943: ,sizeof(natvpgm_t *)*(cfg.total_natvpgms+1)))==NULL) {
1944: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_natvpgms+1);
1945: cfg.total_natvpgms=0;
1946: bail(1);
1947: continue; }
1948: if(cfg.total_natvpgms)
1949: for(j=cfg.total_natvpgms;j>i;j--)
1950: cfg.natvpgm[j]=cfg.natvpgm[j-1];
1951: if((cfg.natvpgm[i]=(natvpgm_t *)MALLOC(sizeof(natvpgm_t)))==NULL) {
1952: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(natvpgm_t));
1953: continue; }
1954: memset((natvpgm_t *)cfg.natvpgm[i],0,sizeof(natvpgm_t));
1955: strcpy(cfg.natvpgm[i]->name,str);
1956: cfg.total_natvpgms++;
1957: uifc.changes=TRUE;
1958: continue; }
1959: if((i&MSK_ON)==MSK_DEL) {
1960: i&=MSK_OFF;
1961: FREE(cfg.natvpgm[i]);
1962: cfg.total_natvpgms--;
1963: for(j=i;j<cfg.total_natvpgms;j++)
1964: cfg.natvpgm[j]=cfg.natvpgm[j+1];
1965: uifc.changes=TRUE;
1966: continue; }
1967: SETHELP(WHERE);
1968: /*
1969: &Native Program Name:&
1970:
1971: This is the executable filename of the Native external program.
1972: */
1973: strcpy(str,cfg.natvpgm[i]->name);
1974: if(uifc.input(WIN_MID|WIN_SAV,0,5,"Native (32-bit) Program Name",str,12
1975: ,K_EDIT)>0)
1976: strcpy(cfg.natvpgm[i]->name,str);
1977: }
1978: return(0);
1979: }
1980:
1981:
1982: void xtrnsec_cfg()
1983: {
1984: static int xtrnsec_dflt,xtrnsec_opt;
1985: char str[81],code[9],done=0,*p;
1986: int j,k;
1987: uint i;
1988: static xtrnsec_t savxtrnsec;
1989:
1990: while(1) {
1991: for(i=0;i<cfg.total_xtrnsecs && i<MAX_OPTS;i++)
1992: sprintf(opt[i],"%-25s",cfg.xtrnsec[i]->name);
1993: opt[i][0]=0;
1994: j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_BOT;
1995: uifc.savnum=0;
1996: if(cfg.total_xtrnsecs)
1997: j|=WIN_DEL|WIN_GET;
1998: if(cfg.total_xtrnsecs<MAX_OPTS)
1999: j|=WIN_INS|WIN_INSACT|WIN_XTR;
2000: if(savxtrnsec.name[0])
2001: j|=WIN_PUT;
2002: SETHELP(WHERE);
2003: /*
2004: &Online Program Sections:&
2005:
2006: This is a list of &Online Program Sections& configured for your system.
2007:
2008: To add an online program section, select the desired location with the
2009: arrow keys and hit INS .
2010:
2011: To delete an online program section, select it and hit DEL .
2012:
2013: To configure an online program section, select it and hit ENTER .
2014: */
2015: i=uifc.list(j,0,0,45,&xtrnsec_dflt,0,"Online Program Sections",opt);
2016: if((signed)i==-1)
2017: return;
2018: if((i&MSK_ON)==MSK_INS) {
2019: i&=MSK_OFF;
2020: SETHELP(WHERE);
2021: /*
2022: &Online Program Section Name:&
2023:
2024: This is the name of this section.
2025: */
2026: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Online Program Section Name",str,40
2027: ,0)<1)
2028: continue;
2029: sprintf(code,"%.8s",str);
2030: p=strchr(code,' ');
2031: if(p) *p=0;
2032: strupr(code);
2033: SETHELP(WHERE);
2034: /*
2035: &Online Program Section Internal Code:&
2036:
2037: Every online program section must have its own unique internal code
2038: for Synchronet to reference it by. It is helpful if this code is an
2039: abreviation of the name.
2040: */
2041: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Online Program Section Internal Code"
2042: ,code,LEN_CODE,K_EDIT|K_UPPER)<1)
2043: continue;
2044: if(!code_ok(code)) {
2045: uifc.helpbuf=invalid_code;
2046: uifc.msg("Invalid Code");
2047: uifc.helpbuf=0;
2048: continue; }
2049: if((cfg.xtrnsec=(xtrnsec_t **)REALLOC(cfg.xtrnsec
2050: ,sizeof(xtrnsec_t *)*(cfg.total_xtrnsecs+1)))==NULL) {
2051: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_xtrnsecs+1);
2052: cfg.total_xtrnsecs=0;
2053: bail(1);
2054: continue; }
2055: if(cfg.total_xtrnsecs) {
2056: for(j=cfg.total_xtrnsecs;j>i;j--)
2057: cfg.xtrnsec[j]=cfg.xtrnsec[j-1];
2058: for(j=0;j<cfg.total_xtrns;j++)
2059: if(cfg.xtrn[j]->sec>=i)
2060: cfg.xtrn[j]->sec++; }
2061:
2062:
2063: if((cfg.xtrnsec[i]=(xtrnsec_t *)MALLOC(sizeof(xtrnsec_t)))==NULL) {
2064: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(xtrnsec_t));
2065: continue; }
2066: memset((xtrnsec_t *)cfg.xtrnsec[i],0,sizeof(xtrnsec_t));
2067: strcpy(cfg.xtrnsec[i]->name,str);
2068: strcpy(cfg.xtrnsec[i]->code,code);
2069: cfg.total_xtrnsecs++;
2070: uifc.changes=TRUE;
2071: continue; }
2072: if((i&MSK_ON)==MSK_DEL) {
2073: i&=MSK_OFF;
2074: FREE(cfg.xtrnsec[i]);
2075: for(j=0;j<cfg.total_xtrns;) {
2076: if(cfg.xtrn[j]->sec==i) { /* delete xtrns of this group */
2077: FREE(cfg.xtrn[j]);
2078: cfg.total_xtrns--;
2079: k=j;
2080: while(k<cfg.total_xtrns) { /* move all xtrns down */
2081: cfg.xtrn[k]=cfg.xtrn[k+1];
2082: k++; } }
2083: else j++; }
2084: for(j=0;j<cfg.total_xtrns;j++) /* move xtrn group numbers down */
2085: if(cfg.xtrn[j]->sec>i)
2086: cfg.xtrn[j]->sec--;
2087: cfg.total_xtrnsecs--;
2088: while(i<cfg.total_xtrnsecs) {
2089: cfg.xtrnsec[i]=cfg.xtrnsec[i+1];
2090: i++; }
2091: uifc.changes=TRUE;
2092: continue; }
2093: if((i&MSK_ON)==MSK_GET) {
2094: i&=MSK_OFF;
2095: savxtrnsec=*cfg.xtrnsec[i];
2096: continue; }
2097: if((i&MSK_ON)==MSK_PUT) {
2098: i&=MSK_OFF;
2099: *cfg.xtrnsec[i]=savxtrnsec;
2100: uifc.changes=TRUE;
2101: continue; }
2102: done=0;
2103: while(!done) {
2104: k=0;
2105: sprintf(opt[k++],"%-27.27s%s","Name",cfg.xtrnsec[i]->name);
2106: sprintf(opt[k++],"%-27.27s%s","Internal Code",cfg.xtrnsec[i]->code);
2107: sprintf(opt[k++],"%-27.27s%.40s","Access Requirements"
2108: ,cfg.xtrnsec[i]->arstr);
2109: sprintf(opt[k++],"%s","Available Online Programs...");
2110: opt[k][0]=0;
2111: uifc.savnum=1;
2112: sprintf(str,"%s Program Section",cfg.xtrnsec[i]->name);
2113: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_MID,0,0,60,&xtrnsec_opt,0,str
2114: ,opt)) {
2115: case -1:
2116: done=1;
2117: break;
2118: case 0:
2119: SETHELP(WHERE);
2120: /*
2121: &Online Program Section Name:&
2122:
2123: This is the name of this section.
2124: */
2125: strcpy(str,cfg.xtrnsec[i]->name); /* save */
2126: if(!uifc.input(WIN_MID|WIN_SAV,0,10
2127: ,"Program Section Name"
2128: ,cfg.xtrnsec[i]->name,sizeof(cfg.xtrnsec[i]->name)-1,K_EDIT))
2129: strcpy(cfg.xtrnsec[i]->name,str);
2130: break;
2131: case 1:
2132: strcpy(str,cfg.xtrnsec[i]->code);
2133: SETHELP(WHERE);
2134: /*
2135: &Online Program Section Internal Code:&
2136:
2137: Every online program section must have its own unique internal code
2138: for Synchronet to reference it by. It is helpful if this code is an
2139: abreviation of the name.
2140: */
2141: uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
2142: ,str,LEN_CODE,K_EDIT|K_UPPER);
2143: if(code_ok(str))
2144: strcpy(cfg.xtrnsec[i]->code,str);
2145: else {
2146: uifc.helpbuf=invalid_code;
2147: uifc.msg("Invalid Code");
2148: uifc.helpbuf=0;
2149: }
2150: break;
2151: case 2:
2152: getar(cfg.xtrnsec[i]->name,cfg.xtrnsec[i]->arstr);
2153: break;
2154: case 3:
2155: xtrn_cfg(i);
2156: break;
2157: }
2158: }
2159: }
2160: }
2161:
2162: void hotkey_cfg(void)
2163: {
2164: static int dflt,dfltopt,bar;
2165: char str[81],done=0;
2166: int j,k;
2167: uint i;
2168: static hotkey_t savhotkey;
2169:
2170: while(1) {
2171: for(i=0;i<cfg.total_hotkeys && i<MAX_OPTS;i++)
2172: sprintf(opt[i],"Ctrl-%c %.40s"
2173: ,cfg.hotkey[i]->key+'@'
2174: ,cfg.hotkey[i]->cmd);
2175: opt[i][0]=0;
2176: j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_RHT;
2177: uifc.savnum=0;
2178: if(cfg.total_hotkeys)
2179: j|=WIN_DEL|WIN_GET;
2180: if(cfg.total_hotkeys<MAX_OPTS)
2181: j|=WIN_INS|WIN_INSACT|WIN_XTR;
2182: if(savhotkey.cmd[0])
2183: j|=WIN_PUT;
2184: SETHELP(WHERE);
2185: /*
2186: &Global Hot Key Events:&
2187:
2188: This is a list of programs or loadable modules that can be executed by
2189: anyone on the BBS at any time (while the BBS has control of user input).
2190:
2191: To add a hot key event, select the desired location and hit INS .
2192:
2193: To delete a hot key event, select it and hit DEL .
2194:
2195: To configure a hot key event, select it and hit ENTER .
2196: */
2197: i=uifc.list(j,0,0,45,&dflt,&bar,"Global Hot Key Events",opt);
2198: if((signed)i==-1)
2199: return;
2200: if((i&MSK_ON)==MSK_INS) {
2201: i&=MSK_OFF;
2202: SETHELP(WHERE);
2203: /*
2204: &Global Hot Key:&
2205:
2206: This is the control key used to trigger the hot key event. Example, A
2207: indicates a Ctrl-A hot key event.
2208: */
2209: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Control Key",str,1
2210: ,K_UPPER)<1)
2211: continue;
2212:
2213: if((cfg.hotkey=(hotkey_t **)REALLOC(cfg.hotkey
2214: ,sizeof(hotkey_t *)*(cfg.total_hotkeys+1)))==NULL) {
2215: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_hotkeys+1);
2216: cfg.total_hotkeys=0;
2217: bail(1);
2218: continue; }
2219: if(cfg.total_hotkeys)
2220: for(j=cfg.total_hotkeys;j>i;j--)
2221: cfg.hotkey[j]=cfg.hotkey[j-1];
2222: if((cfg.hotkey[i]=(hotkey_t *)MALLOC(sizeof(hotkey_t)))==NULL) {
2223: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(hotkey_t));
2224: continue; }
2225: memset((hotkey_t *)cfg.hotkey[i],0,sizeof(hotkey_t));
2226: cfg.hotkey[i]->key=str[0]-'@';
2227: cfg.total_hotkeys++;
2228: uifc.changes=TRUE;
2229: continue; }
2230: if((i&MSK_ON)==MSK_DEL) {
2231: i&=MSK_OFF;
2232: FREE(cfg.hotkey[i]);
2233: cfg.total_hotkeys--;
2234: for(j=i;j<cfg.total_hotkeys;j++)
2235: cfg.hotkey[j]=cfg.hotkey[j+1];
2236: uifc.changes=TRUE;
2237: continue; }
2238: if((i&MSK_ON)==MSK_GET) {
2239: i&=MSK_OFF;
2240: savhotkey=*cfg.hotkey[i];
2241: continue; }
2242: if((i&MSK_ON)==MSK_PUT) {
2243: i&=MSK_OFF;
2244: *cfg.hotkey[i]=savhotkey;
2245: uifc.changes=TRUE;
2246: continue; }
2247: done=0;
2248: while(!done) {
2249: k=0;
2250: sprintf(opt[k++],"%-27.27sCtrl-%c","Global Hot Key"
2251: ,cfg.hotkey[i]->key+'@');
2252: sprintf(opt[k++],"%-27.27s%.40s","Command Line",cfg.hotkey[i]->cmd);
2253: opt[k][0]=0;
2254: SETHELP(WHERE);
2255: /*
2256: &Global Hot Key Event:&
2257:
2258: This menu allows you to change the settings for the selected global
2259: hot key event. Hot key events are control characters that are used to
2260: execute an external program or module anywhere in the BBS.
2261: */
2262: uifc.savnum=1;
2263: sprintf(str,"Ctrl-%C Hot Key Event",cfg.hotkey[i]->key+'@');
2264: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_L2R|WIN_BOT,0,0,60,&dfltopt,0
2265: ,str,opt)) {
2266: case -1:
2267: done=1;
2268: break;
2269: case 0:
2270: SETHELP(WHERE);
2271: /*
2272: &Global Hot-Ctrl Key:&
2273:
2274: This is the global control key used to execute this event.
2275: */
2276: sprintf(str,"%c",cfg.hotkey[i]->key+'@');
2277: if(uifc.input(WIN_MID|WIN_SAV,0,10,"Global Hot Ctrl-Key"
2278: ,str,1,K_EDIT|K_UPPER)>0)
2279: cfg.hotkey[i]->key=str[0]-'@';
2280: break;
2281: case 1:
2282: SETHELP(WHERE);
2283: /*
2284: &Hot Key Event Command Line:&
2285:
2286: This is the command line to execute when this hot key is pressed.
2287: */
2288: uifc.input(WIN_MID|WIN_SAV,0,10,"Command Line"
2289: ,cfg.hotkey[i]->cmd,sizeof(cfg.hotkey[i]->cmd)-1,K_EDIT);
2290: break;
2291: } } }
2292:
2293: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.