scfgchat.c 23.4 KB
Newer Older
rswindell's avatar
rswindell committed
1
2
/* scfgchat.c */

3
4
5
6
7
8
/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
9
 * Copyright 2012 Rob Swindell - http://www.synchro.net/copyright.html		*
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/
rswindell's avatar
rswindell committed
35
36
37
38
39
40
41
42
43
44
45
46
47

#include "scfg.h"

void page_cfg()
{
	static int dflt,bar;
	char str[81],done=0;
	int j,k;
	uint i;
	static page_t savpage;

while(1) {
	for(i=0;i<cfg.total_pages && i<MAX_OPTS;i++)
rswindell's avatar
rswindell committed
48
		sprintf(opt[i],"%-40.40s %-.20s",cfg.page[i]->cmd,cfg.page[i]->arstr);
rswindell's avatar
rswindell committed
49
50
51
52
53
54
55
56
57
58
	opt[i][0]=0;
	j=WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT;
	if(cfg.total_pages)
		j|=WIN_DEL|WIN_GET;
	if(cfg.total_pages<MAX_OPTS)
		j|=WIN_INS|WIN_INSACT|WIN_XTR;
	if(savpage.cmd[0])
		j|=WIN_PUT;
	SETHELP(WHERE);
/*
59
`External Sysop Chat Pagers:`
rswindell's avatar
rswindell committed
60
61
62

This is a list of the configured external sysop chat pagers.

63
To add a pager, select the desired location and hit ~ INS ~.
rswindell's avatar
rswindell committed
64

65
To delete a pager, select it and hit ~ DEL ~.
rswindell's avatar
rswindell committed
66

67
To configure a pager, select it and hit ~ ENTER ~.
rswindell's avatar
rswindell committed
68
*/
69
	i=uifc.list(j,0,0,45,&dflt,&bar,"External Sysop Chat Pagers",opt);
rswindell's avatar
rswindell committed
70
71
72
73
74
75
76
	if((signed)i==-1)
		return;
	if((i&MSK_ON)==MSK_INS) {
		i&=MSK_OFF;
		sprintf(str,"%%!tone +chatpage.ton");
		SETHELP(WHERE);
/*
77
`External Chat Pager Command Line:`
rswindell's avatar
rswindell committed
78
79
80

This is the command line to execute for this external chat pager.
*/
81
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"Command Line",str,50
rswindell's avatar
rswindell committed
82
83
			,K_EDIT)<1)
            continue;
deuce's avatar
deuce committed
84
		if((cfg.page=(page_t **)realloc(cfg.page,sizeof(page_t *)*(cfg.total_pages+1)))
rswindell's avatar
rswindell committed
85
86
87
88
            ==NULL) {
            errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_pages+1);
			cfg.total_pages=0;
			bail(1);
89
90
            continue; 
		}
rswindell's avatar
rswindell committed
91
92
93
		if(cfg.total_pages)
			for(j=cfg.total_pages;j>i;j--)
				cfg.page[j]=cfg.page[j-1];
deuce's avatar
deuce committed
94
		if((cfg.page[i]=(page_t *)malloc(sizeof(page_t)))==NULL) {
rswindell's avatar
rswindell committed
95
			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(page_t));
96
97
			continue; 
		}
rswindell's avatar
rswindell committed
98
99
100
		memset((page_t *)cfg.page[i],0,sizeof(page_t));
		strcpy(cfg.page[i]->cmd,str);
		cfg.total_pages++;
101
		uifc.changes=1;
102
103
		continue; 
	}
rswindell's avatar
rswindell committed
104
105
	if((i&MSK_ON)==MSK_DEL) {
		i&=MSK_OFF;
deuce's avatar
deuce committed
106
		free(cfg.page[i]);
rswindell's avatar
rswindell committed
107
108
109
		cfg.total_pages--;
		for(j=i;j<cfg.total_pages;j++)
			cfg.page[j]=cfg.page[j+1];
110
		uifc.changes=1;
111
112
		continue; 
	}
rswindell's avatar
rswindell committed
113
114
115
	if((i&MSK_ON)==MSK_GET) {
		i&=MSK_OFF;
		savpage=*cfg.page[i];
116
117
		continue; 
	}
rswindell's avatar
rswindell committed
118
119
120
	if((i&MSK_ON)==MSK_PUT) {
		i&=MSK_OFF;
		*cfg.page[i]=savpage;
121
		uifc.changes=1;
122
123
        continue; 
	}
rswindell's avatar
rswindell committed
124
125
126
127
128
129
	j=0;
	done=0;
	while(!done) {
		k=0;
		sprintf(opt[k++],"%-27.27s%.40s","Command Line",cfg.page[i]->cmd);
		sprintf(opt[k++],"%-27.27s%.40s","Access Requirements",cfg.page[i]->arstr);
130
131
132
		sprintf(opt[k++],"%-27.27s%s","Intercept I/O"
			,(cfg.page[i]->misc&XTRN_STDIO) ? "Standard"
				:cfg.page[i]->misc&XTRN_CONIO ? "Console":"No");
rswindell's avatar
rswindell committed
133
134
		opt[k][0]=0;
		sprintf(str,"Sysop Chat Pager #%d",i+1);
135
		switch(uifc.list(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&j,0,str,opt)) {
rswindell's avatar
rswindell committed
136
137
138
139
140
141
			case -1:
				done=1;
				break;
			case 0:
				SETHELP(WHERE);
/*
142
`External Chat Pager Command Line:`
rswindell's avatar
rswindell committed
143
144
145
146

This is the command line to execute for this external chat pager.
*/
				strcpy(str,cfg.page[i]->cmd);
147
				if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Command Line"
148
					,cfg.page[i]->cmd,sizeof(cfg.page[i]->cmd)-1,K_EDIT))
rswindell's avatar
rswindell committed
149
150
151
152
153
154
					strcpy(cfg.page[i]->cmd,str);
				break;
			case 1:
				getar(str,cfg.page[i]->arstr);
				break;
			case 2:
155
156
157
158
159
160
161
162
163
164
165
166
167
168
				switch(cfg.page[i]->misc&(XTRN_STDIO|XTRN_CONIO)) {
					case XTRN_STDIO:
						k=0;
						break;
					case XTRN_CONIO:
						k=1;
						break;
					default:
						k=2;
				}
				strcpy(opt[0],"Standard");
				strcpy(opt[1],"Console");
				strcpy(opt[2],"No");
				opt[3][0]=0;
rswindell's avatar
rswindell committed
169
170
				SETHELP(WHERE);
/*
171
`Intercept I/O:`
rswindell's avatar
rswindell committed
172

173
174
If you wish the screen output and keyboard input to be intercepted
when running this chat pager, set this option to either `Standard` or ~Console~.
rswindell's avatar
rswindell committed
175
*/
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
				switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Intercept I/O"
					,opt)) {
				case 0:
					if((cfg.page[i]->misc&(XTRN_STDIO|XTRN_CONIO)) != XTRN_STDIO) {
						cfg.page[i]->misc|=XTRN_STDIO;
						cfg.page[i]->misc&=~XTRN_CONIO;
						uifc.changes=1; 
					}
					break;
				case 1:
					if((cfg.page[i]->misc&(XTRN_STDIO|XTRN_CONIO)) != XTRN_CONIO) {
						cfg.page[i]->misc|=XTRN_CONIO;
						cfg.page[i]->misc&=~XTRN_STDIO;
						uifc.changes=1; 
					}
					break;
				case 2:
					if((cfg.page[i]->misc&(XTRN_STDIO|XTRN_CONIO)) != 0) {
						cfg.page[i]->misc&=~(XTRN_STDIO|XTRN_CONIO);
						uifc.changes=1; 
					}
					break;
				}
rswindell's avatar
rswindell committed
199
                break;
200
201
202
			} 
		} 
	}
rswindell's avatar
rswindell committed
203
204
205
206
207
}

void chan_cfg()
{
	static int chan_dflt,chan_bar,opt_dflt;
208
	char str[128],code[128],done=0;
rswindell's avatar
rswindell committed
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
	int j,k;
	uint i;
	static chan_t savchan;

while(1) {
	for(i=0;i<cfg.total_chans && i<MAX_OPTS;i++)
		sprintf(opt[i],"%-25s",cfg.chan[i]->name);
	opt[i][0]=0;
	j=WIN_ACT|WIN_SAV|WIN_BOT|WIN_RHT;
	if(cfg.total_chans)
		j|=WIN_DEL|WIN_GET;
	if(cfg.total_chans<MAX_OPTS)
		j|=WIN_INS|WIN_INSACT|WIN_XTR;
	if(savchan.name[0])
		j|=WIN_PUT;
	SETHELP(WHERE);
/*
226
`Multinode Chat Channels:`
rswindell's avatar
rswindell committed
227
228
229
230

This is a list of the configured multinode chat channels.

To add a channel, select the desired location with the arrow keys and
231
hit ~ INS ~.
rswindell's avatar
rswindell committed
232

233
To delete a channel, select it with the arrow keys and hit ~ DEL ~.
rswindell's avatar
rswindell committed
234

235
To configure a channel, select it with the arrow keys and hit ~ ENTER ~.
rswindell's avatar
rswindell committed
236
*/
237
	i=uifc.list(j,0,0,45,&chan_dflt,&chan_bar,"Multinode Chat Channels",opt);
rswindell's avatar
rswindell committed
238
239
240
241
242
243
244
	if((signed)i==-1)
		return;
	if((i&MSK_ON)==MSK_INS) {
		i&=MSK_OFF;
		strcpy(str,"Open");
		SETHELP(WHERE);
/*
245
`Channel Name:`
rswindell's avatar
rswindell committed
246
247
248

This is the name or description of the chat channel.
*/
249
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"Chat Channel Name",str,25
rswindell's avatar
rswindell committed
250
251
			,K_EDIT)<1)
            continue;
252
253
		SAFECOPY(code,str);
		prep_code(code,/* prefix: */NULL);
rswindell's avatar
rswindell committed
254
255
		SETHELP(WHERE);
/*
256
`Chat Channel Internal Code:`
rswindell's avatar
rswindell committed
257
258
259
260
261

Every chat channel must have its own unique code for Synchronet to refer
to it internally. This code is usually an abreviation of the chat
channel name.
*/
262
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"Internal Code"
263
			,code,LEN_CODE,K_EDIT|K_UPPER)<1)
rswindell's avatar
rswindell committed
264
265
			continue;
		if(!code_ok(code)) {
266
267
268
			uifc.helpbuf=invalid_code;
			uifc.msg("Invalid Code");
			uifc.helpbuf=0;
269
270
            continue; 
		}
deuce's avatar
deuce committed
271
		if((cfg.chan=(chan_t **)realloc(cfg.chan,sizeof(chan_t *)*(cfg.total_chans+1)))
rswindell's avatar
rswindell committed
272
273
274
275
            ==NULL) {
            errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_chans+1);
			cfg.total_chans=0;
			bail(1);
276
277
            continue; 
		}
rswindell's avatar
rswindell committed
278
279
280
		if(cfg.total_chans)
			for(j=cfg.total_chans;j>i;j--)
				cfg.chan[j]=cfg.chan[j-1];
deuce's avatar
deuce committed
281
		if((cfg.chan[i]=(chan_t *)malloc(sizeof(chan_t)))==NULL) {
rswindell's avatar
rswindell committed
282
			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(chan_t));
283
284
			continue; 
		}
rswindell's avatar
rswindell committed
285
286
287
288
		memset((chan_t *)cfg.chan[i],0,sizeof(chan_t));
		strcpy(cfg.chan[i]->name,str);
		strcpy(cfg.chan[i]->code,code);
		cfg.total_chans++;
289
		uifc.changes=1;
290
291
		continue; 
	}
rswindell's avatar
rswindell committed
292
293
	if((i&MSK_ON)==MSK_DEL) {
		i&=MSK_OFF;
deuce's avatar
deuce committed
294
		free(cfg.chan[i]);
rswindell's avatar
rswindell committed
295
296
297
		cfg.total_chans--;
		for(j=i;j<cfg.total_chans;j++)
			cfg.chan[j]=cfg.chan[j+1];
298
		uifc.changes=1;
299
300
		continue; 
	}
rswindell's avatar
rswindell committed
301
302
303
	if((i&MSK_ON)==MSK_GET) {
		i&=MSK_OFF;
		savchan=*cfg.chan[i];
304
305
		continue; 
	}
rswindell's avatar
rswindell committed
306
307
308
	if((i&MSK_ON)==MSK_PUT) {
		i&=MSK_OFF;
		*cfg.chan[i]=savchan;
309
		uifc.changes=1;
310
311
        continue; 
	}
rswindell's avatar
rswindell committed
312
313
314
315
316
317
    j=0;
	done=0;
	while(!done) {
		k=0;
		sprintf(opt[k++],"%-27.27s%s","Name",cfg.chan[i]->name);
		sprintf(opt[k++],"%-27.27s%s","Internal Code",cfg.chan[i]->code);
deuce's avatar
deuce committed
318
		sprintf(opt[k++],"%-27.27s%"PRIu32,"Cost in Credits",cfg.chan[i]->cost);
rswindell's avatar
rswindell committed
319
320
321
322
323
324
325
326
327
328
329
330
331
		sprintf(opt[k++],"%-27.27s%.40s","Access Requirements"
			,cfg.chan[i]->arstr);
		sprintf(opt[k++],"%-27.27s%s","Password Protection"
			,cfg.chan[i]->misc&CHAN_PW ? "Yes" : "No");
		sprintf(opt[k++],"%-27.27s%s","Guru Joins When Empty"
			,cfg.chan[i]->misc&CHAN_GURU ? "Yes" : "No");
		sprintf(opt[k++],"%-27.27s%s","Channel Guru"
			,cfg.chan[i]->guru<cfg.total_gurus ? cfg.guru[cfg.chan[i]->guru]->name : "");
        sprintf(opt[k++],"%-27.27s%s","Channel Action Set"
            ,cfg.actset[cfg.chan[i]->actset]->name);
		opt[k][0]=0;
		SETHELP(WHERE);
/*
332
`Chat Channel Configuration:`
rswindell's avatar
rswindell committed
333
334
335
336

This menu is for configuring the selected chat channel.
*/
		sprintf(str,"%s Chat Channel",cfg.chan[i]->name);
337
		switch(uifc.list(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&opt_dflt,0,str,opt)) {
rswindell's avatar
rswindell committed
338
339
340
341
342
343
			case -1:
				done=1;
				break;
			case 0:
				SETHELP(WHERE);
/*
344
`Chat Channel Name:`
rswindell's avatar
rswindell committed
345
346
347
348

This is the name or description of the chat channel.
*/
				strcpy(str,cfg.chan[i]->name);
349
				if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Chat Channel Name"
350
					,cfg.chan[i]->name,sizeof(cfg.chan[i]->name)-1,K_EDIT))
rswindell's avatar
rswindell committed
351
352
353
354
355
					strcpy(cfg.chan[i]->name,str);
				break;
			case 1:
				SETHELP(WHERE);
/*
356
`Chat Channel Internal Code:`
rswindell's avatar
rswindell committed
357
358
359
360
361
362

Every chat channel must have its own unique code for Synchronet to refer
to it internally. This code is usually an abreviation of the chat
channel name.
*/
				strcpy(str,cfg.chan[i]->code);
363
				if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Internal Code"
364
					,str,LEN_CODE,K_UPPER|K_EDIT))
rswindell's avatar
rswindell committed
365
366
367
368
					break;
				if(code_ok(str))
					strcpy(cfg.chan[i]->code,str);
				else {
369
370
					uifc.helpbuf=invalid_code;
					uifc.msg("Invalid Code");
371
372
                    uifc.helpbuf=0; 
				}
rswindell's avatar
rswindell committed
373
374
375
376
377
                break;
			case 2:
				ultoa(cfg.chan[i]->cost,str,10);
                SETHELP(WHERE);
/*
378
`Chat Channel Cost to Join:`
rswindell's avatar
rswindell committed
379
380
381

If you want users to be charged credits to join this chat channel, set
this value to the number of credits to charge. If you want this channel
382
to be free, set this value to `0`.
rswindell's avatar
rswindell committed
383
*/
384
				uifc.input(WIN_MID|WIN_SAV,0,0,"Cost to Join (in Credits)"
rswindell's avatar
rswindell committed
385
386
387
388
389
390
391
392
393
394
395
                    ,str,10,K_EDIT|K_NUMBER);
				cfg.chan[i]->cost=atol(str);
                break;
			case 3:
				sprintf(str,"%s Chat Channel",cfg.chan[i]->name);
				getar(str,cfg.chan[i]->arstr);
				break;
			case 4:
				k=1;
				SETHELP(WHERE);
/*
396
`Allow Channel to be Password Protected:`
rswindell's avatar
rswindell committed
397
398

If you want to allow the first user to join this channel to password
399
protect it, set this option to `Yes`.
rswindell's avatar
rswindell committed
400
*/
401
				k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
rswindell's avatar
rswindell committed
402
					,"Allow Channel to be Password Protected"
403
					,uifcYesNoOpts);
rswindell's avatar
rswindell committed
404
405
				if(!k && !(cfg.chan[i]->misc&CHAN_PW)) {
					cfg.chan[i]->misc|=CHAN_PW;
406
407
					uifc.changes=1; 
				}
rswindell's avatar
rswindell committed
408
409
				else if(k==1 && cfg.chan[i]->misc&CHAN_PW) {
					cfg.chan[i]->misc&=~CHAN_PW;
410
411
					uifc.changes=1; 
				}
rswindell's avatar
rswindell committed
412
413
414
415
416
				break;
			case 5:
				k=1;
				SETHELP(WHERE);
/*
417
`Guru Joins This Channel When Empty:`
rswindell's avatar
rswindell committed
418
419

If you want the system guru to join this chat channel when there is
420
only one user, set this option to `Yes`.
rswindell's avatar
rswindell committed
421
*/
422
				k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
rswindell's avatar
rswindell committed
423
					,"Guru Joins This Channel When Empty"
424
					,uifcYesNoOpts);
rswindell's avatar
rswindell committed
425
426
				if(!k && !(cfg.chan[i]->misc&CHAN_GURU)) {
					cfg.chan[i]->misc|=CHAN_GURU;
427
428
					uifc.changes=1; 
				}
rswindell's avatar
rswindell committed
429
430
				else if(k==1 && cfg.chan[i]->misc&CHAN_GURU) {
					cfg.chan[i]->misc&=~CHAN_GURU;
431
432
					uifc.changes=1; 
				}
rswindell's avatar
rswindell committed
433
434
435
436
				break;
			case 6:
SETHELP(WHERE);
/*
437
`Channel Guru:`
rswindell's avatar
rswindell committed
438
439
440
441
442
443
444
445

This is a list of available chat Gurus.  Select the one that you wish
to have available in this channel.
*/
				k=0;
				for(j=0;j<cfg.total_gurus && j<MAX_OPTS;j++)
					sprintf(opt[j],"%-25s",cfg.guru[j]->name);
				opt[j][0]=0;
446
				k=uifc.list(WIN_SAV|WIN_RHT,0,0,25,&j,0
rswindell's avatar
rswindell committed
447
448
449
450
451
452
453
454
					,"Available Chat Gurus",opt);
				if(k==-1)
					break;
				cfg.chan[i]->guru=k;
				break;
			case 7:
SETHELP(WHERE);
/*
455
`Channel Action Set:`
rswindell's avatar
rswindell committed
456

rswindell's avatar
rswindell committed
457
458
This is a list of available chat action sets.  Select the one that you
wish to have available in this channel.
rswindell's avatar
rswindell committed
459
460
461
462
463
*/
				k=0;
				for(j=0;j<cfg.total_actsets && j<MAX_OPTS;j++)
					sprintf(opt[j],"%-25s",cfg.actset[j]->name);
				opt[j][0]=0;
464
				k=uifc.list(WIN_SAV|WIN_RHT,0,0,25,&j,0
rswindell's avatar
rswindell committed
465
466
467
					,"Available Chat Action Sets",opt);
				if(k==-1)
					break;
468
				uifc.changes=1;
rswindell's avatar
rswindell committed
469
				cfg.chan[i]->actset=k;
470
471
472
473
				break; 
			} 
		} 
	}
rswindell's avatar
rswindell committed
474
475
476
477
478
479
}

void chatact_cfg(uint setnum)
{
	static int chatact_dflt,chatact_bar;
	char str[128],cmd[128],out[128];
rswindell's avatar
rswindell committed
480
	int j;
rswindell's avatar
rswindell committed
481
482
483
484
485
486
487
488
	uint i,n,chatnum[MAX_OPTS+1];
	static chatact_t savchatact;

while(1) {
	for(i=0,j=0;i<cfg.total_chatacts && j<MAX_OPTS;i++)
		if(cfg.chatact[i]->actset==setnum) {
			sprintf(opt[j],"%-*.*s %s",LEN_CHATACTCMD,LEN_CHATACTCMD
				,cfg.chatact[i]->cmd,cfg.chatact[i]->out);
489
490
			chatnum[j++]=i; 
		}
rswindell's avatar
rswindell committed
491
492
493
494
495
496
497
498
499
500
501
	chatnum[j]=cfg.total_chatacts;
	opt[j][0]=0;
	i=WIN_ACT|WIN_SAV;
	if(j)
		i|=WIN_DEL|WIN_GET;
	if(j<MAX_OPTS)
		i|=WIN_INS|WIN_INSACT|WIN_XTR;
	if(savchatact.cmd[0])
		i|=WIN_PUT;
	SETHELP(WHERE);
/*
502
`Multinode Chat Actions:`
rswindell's avatar
rswindell committed
503
504
505

This is a list of the configured multinode chat actions.  The users can
use these actions in multinode chat by turning on action commands with
506
507
the `/A` command in multinode chat.  Then if a line is typed which
begins with a valid `action command` and has a user name, chat handle,
rswindell's avatar
rswindell committed
508
or node number following, the output string will be displayed replacing
509
the `%s` symbols with the sending user's name and the receiving user's
rswindell's avatar
rswindell committed
510
511
512
name (in that order).

To add an action, select the desired location with the arrow keys and
513
hit ~ INS ~.
rswindell's avatar
rswindell committed
514

515
To delete an action, select it with the arrow keys and hit ~ DEL ~.
rswindell's avatar
rswindell committed
516

517
To configure an action, select it with the arrow keys and hit ~ ENTER ~.
rswindell's avatar
rswindell committed
518
519
*/
	sprintf(str,"%s Chat Actions",cfg.actset[setnum]->name);
520
	i=uifc.list(i,0,0,70,&chatact_dflt,&chatact_bar,str,opt);
rswindell's avatar
rswindell committed
521
522
523
524
525
526
	if((signed)i==-1)
		return;
	if((i&MSK_ON)==MSK_INS) {
		i&=MSK_OFF;
		SETHELP(WHERE);
/*
527
`Chat Action Command:`
rswindell's avatar
rswindell committed
528
529
530

This is the command word (normally a verb) to trigger the action output.
*/
531
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"Action Command",cmd,LEN_CHATACTCMD
rswindell's avatar
rswindell committed
532
533
534
535
			,K_UPPER)<1)
            continue;
		SETHELP(WHERE);
/*
536
`Chat Action Output String:`
rswindell's avatar
rswindell committed
537
538
539

This is the output string displayed with this action output.
*/
540
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"",out,LEN_CHATACTOUT
rswindell's avatar
rswindell committed
541
542
			,K_MSG)<1)
            continue;
deuce's avatar
deuce committed
543
		if((cfg.chatact=(chatact_t **)realloc(cfg.chatact
rswindell's avatar
rswindell committed
544
545
546
547
            ,sizeof(chatact_t *)*(cfg.total_chatacts+1)))==NULL) {
            errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_chatacts+1);
			cfg.total_chatacts=0;
			bail(1);
548
549
            continue; 
		}
rswindell's avatar
rswindell committed
550
551
552
		if(j)
			for(n=cfg.total_chatacts;n>chatnum[i];n--)
				cfg.chatact[n]=cfg.chatact[n-1];
deuce's avatar
deuce committed
553
		if((cfg.chatact[chatnum[i]]=(chatact_t *)malloc(sizeof(chatact_t)))==NULL) {
rswindell's avatar
rswindell committed
554
			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(chatact_t));
555
556
			continue; 
		}
rswindell's avatar
rswindell committed
557
558
559
560
561
		memset((chatact_t *)cfg.chatact[chatnum[i]],0,sizeof(chatact_t));
		strcpy(cfg.chatact[chatnum[i]]->cmd,cmd);
		strcpy(cfg.chatact[chatnum[i]]->out,out);
		cfg.chatact[chatnum[i]]->actset=setnum;
		cfg.total_chatacts++;
562
		uifc.changes=1;
563
564
		continue; 
	}
rswindell's avatar
rswindell committed
565
566
	if((i&MSK_ON)==MSK_DEL) {
		i&=MSK_OFF;
deuce's avatar
deuce committed
567
		free(cfg.chatact[chatnum[i]]);
rswindell's avatar
rswindell committed
568
569
570
		cfg.total_chatacts--;
		for(j=chatnum[i];j<cfg.total_chatacts && j<MAX_OPTS;j++)
			cfg.chatact[j]=cfg.chatact[j+1];
571
		uifc.changes=1;
572
573
		continue; 
	}
rswindell's avatar
rswindell committed
574
575
576
	if((i&MSK_ON)==MSK_GET) {
		i&=MSK_OFF;
		savchatact=*cfg.chatact[chatnum[i]];
577
578
		continue; 
	}
rswindell's avatar
rswindell committed
579
580
581
582
	if((i&MSK_ON)==MSK_PUT) {
		i&=MSK_OFF;
		*cfg.chatact[chatnum[i]]=savchatact;
		cfg.chatact[chatnum[i]]->actset=setnum;
583
		uifc.changes=1;
584
585
        continue; 
	}
rswindell's avatar
rswindell committed
586
587
	SETHELP(WHERE);
/*
588
`Chat Action Command:`
rswindell's avatar
rswindell committed
589
590
591
592

This is the command that triggers this chat action.
*/
	strcpy(str,cfg.chatact[chatnum[i]]->cmd);
593
	if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Chat Action Command"
rswindell's avatar
rswindell committed
594
595
		,cfg.chatact[chatnum[i]]->cmd,LEN_CHATACTCMD,K_EDIT|K_UPPER)) {
		strcpy(cfg.chatact[chatnum[i]]->cmd,str);
596
597
		continue; 
	}
rswindell's avatar
rswindell committed
598
599
	SETHELP(WHERE);
/*
600
`Chat Action Output String:`
rswindell's avatar
rswindell committed
601
602
603
604

This is the output string that results from this chat action.
*/
	strcpy(str,cfg.chatact[chatnum[i]]->out);
605
	if(!uifc.input(WIN_MID|WIN_SAV,0,10,""
rswindell's avatar
rswindell committed
606
		,cfg.chatact[chatnum[i]]->out,LEN_CHATACTOUT,K_EDIT|K_MSG))
607
608
		strcpy(cfg.chatact[chatnum[i]]->out,str); 
}
rswindell's avatar
rswindell committed
609
610
611
612
613
}

void guru_cfg()
{
	static int guru_dflt,guru_bar,opt_dflt;
614
	char str[128],code[128],done=0;
rswindell's avatar
rswindell committed
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
	int j,k;
	uint i;
	static guru_t savguru;

while(1) {
	for(i=0;i<cfg.total_gurus && i<MAX_OPTS;i++)
		sprintf(opt[i],"%-25s",cfg.guru[i]->name);
	opt[i][0]=0;
	j=WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT;
	if(cfg.total_gurus)
		j|=WIN_DEL|WIN_GET;
	if(cfg.total_gurus<MAX_OPTS)
		j|=WIN_INS|WIN_INSACT|WIN_XTR;
	if(savguru.name[0])
		j|=WIN_PUT;
	SETHELP(WHERE);
/*
632
`Gurus:`
rswindell's avatar
rswindell committed
633
634
635
636

This is a list of the configured Gurus.

To add a Guru, select the desired location with the arrow keys and
637
hit ~ INS ~.
rswindell's avatar
rswindell committed
638

639
To delete a Guru, select it with the arrow keys and hit ~ DEL ~.
rswindell's avatar
rswindell committed
640

641
To configure a Guru, select it with the arrow keys and hit ~ ENTER ~.
rswindell's avatar
rswindell committed
642
*/
643
	i=uifc.list(j,0,0,45,&guru_dflt,&guru_bar,"Artificial Gurus",opt);
rswindell's avatar
rswindell committed
644
645
646
647
648
649
	if((signed)i==-1)
		return;
	if((i&MSK_ON)==MSK_INS) {
		i&=MSK_OFF;
		SETHELP(WHERE);
/*
650
`Guru Name:`
rswindell's avatar
rswindell committed
651
652
653

This is the name of the selected Guru.
*/
654
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"Guru Name",str,25
rswindell's avatar
rswindell committed
655
656
			,0)<1)
            continue;
657
658
		SAFECOPY(code,str);
		prep_code(code,/* prefix: */NULL);
rswindell's avatar
rswindell committed
659
660
		SETHELP(WHERE);
/*
661
`Guru Internal Code:`
rswindell's avatar
rswindell committed
662
663
664
665

Every Guru must have its own unique code for Synchronet to refer to
it internally. This code is usually an abreviation of the Guru name.
*/
666
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"Internal Code"
667
			,code,LEN_CODE,K_EDIT|K_UPPER)<1)
rswindell's avatar
rswindell committed
668
669
			continue;
		if(!code_ok(code)) {
670
671
672
			uifc.helpbuf=invalid_code;
			uifc.msg("Invalid Code");
			uifc.helpbuf=0;
673
674
            continue; 
		}
deuce's avatar
deuce committed
675
		if((cfg.guru=(guru_t **)realloc(cfg.guru,sizeof(guru_t *)*(cfg.total_gurus+1)))
rswindell's avatar
rswindell committed
676
677
678
679
            ==NULL) {
			errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_gurus+1);
			cfg.total_gurus=0;
			bail(1);
680
681
            continue; 
		}
rswindell's avatar
rswindell committed
682
683
684
		if(cfg.total_gurus)
			for(j=cfg.total_gurus;j>i;j--)
				cfg.guru[j]=cfg.guru[j-1];
deuce's avatar
deuce committed
685
		if((cfg.guru[i]=(guru_t *)malloc(sizeof(guru_t)))==NULL) {
rswindell's avatar
rswindell committed
686
			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(guru_t));
687
688
			continue; 
		}
rswindell's avatar
rswindell committed
689
690
691
692
		memset((guru_t *)cfg.guru[i],0,sizeof(guru_t));
		strcpy(cfg.guru[i]->name,str);
		strcpy(cfg.guru[i]->code,code);
		cfg.total_gurus++;
693
		uifc.changes=1;
694
695
		continue; 
	}
rswindell's avatar
rswindell committed
696
697
	if((i&MSK_ON)==MSK_DEL) {
		i&=MSK_OFF;
deuce's avatar
deuce committed
698
		free(cfg.guru[i]);
rswindell's avatar
rswindell committed
699
700
701
		cfg.total_gurus--;
		for(j=i;j<cfg.total_gurus;j++)
			cfg.guru[j]=cfg.guru[j+1];
702
		uifc.changes=1;
703
704
		continue; 
	}
rswindell's avatar
rswindell committed
705
706
707
	if((i&MSK_ON)==MSK_GET) {
		i&=MSK_OFF;
		savguru=*cfg.guru[i];
708
709
		continue; 
	}
rswindell's avatar
rswindell committed
710
711
712
	if((i&MSK_ON)==MSK_PUT) {
		i&=MSK_OFF;
		*cfg.guru[i]=savguru;
713
		uifc.changes=1;
714
715
        continue; 
	}
rswindell's avatar
rswindell committed
716
717
718
719
720
721
722
723
724
725
    j=0;
	done=0;
	while(!done) {
		k=0;
		sprintf(opt[k++],"%-27.27s%s","Guru Name",cfg.guru[i]->name);
		sprintf(opt[k++],"%-27.27s%s","Guru Internal Code",cfg.guru[i]->code);
		sprintf(opt[k++],"%-27.27s%.40s","Access Requirements",cfg.guru[i]->arstr);
		opt[k][0]=0;
		SETHELP(WHERE);
/*
726
`Guru Configuration:`
rswindell's avatar
rswindell committed
727
728
729

This menu is for configuring the selected Guru.
*/
730
		switch(uifc.list(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&opt_dflt,0,cfg.guru[i]->name
rswindell's avatar
rswindell committed
731
732
733
734
735
736
737
			,opt)) {
			case -1:
				done=1;
				break;
			case 0:
				SETHELP(WHERE);
/*
738
`Guru Name:`
rswindell's avatar
rswindell committed
739
740
741
742

This is the name of the selected Guru.
*/
				strcpy(str,cfg.guru[i]->name);
743
				if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Guru Name"
744
					,cfg.guru[i]->name,sizeof(cfg.guru[i]->name)-1,K_EDIT))
rswindell's avatar
rswindell committed
745
746
747
748
749
					strcpy(cfg.guru[i]->name,str);
				break;
			case 1:
SETHELP(WHERE);
/*
750
`Guru Internal Code:`
rswindell's avatar
rswindell committed
751
752
753
754
755

Every Guru must have its own unique code for Synchronet to refer to
it internally. This code is usually an abreviation of the Guru name.
*/
				strcpy(str,cfg.guru[i]->code);
756
				if(!uifc.input(WIN_MID|WIN_SAV,0,0,"Guru Internal Code"
757
					,str,LEN_CODE,K_EDIT|K_UPPER))
rswindell's avatar
rswindell committed
758
759
760
761
					break;
				if(code_ok(str))
					strcpy(cfg.guru[i]->code,str);
				else {
762
763
					uifc.helpbuf=invalid_code;
					uifc.msg("Invalid Code");
764
765
                    uifc.helpbuf=0; 
				}
rswindell's avatar
rswindell committed
766
767
768
				break;
			case 2:
				getar(cfg.guru[i]->name,cfg.guru[i]->arstr);
769
770
771
772
				break; 
			} 
		} 
	}
rswindell's avatar
rswindell committed
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
}

void actsets_cfg()
{
    static int actset_dflt,actset_bar,opt_dflt;
    char str[81];
    int j,k,done;
    uint i;
    static actset_t savactset;

while(1) {
	for(i=0;i<cfg.total_actsets && i<MAX_OPTS;i++)
		sprintf(opt[i],"%-25s",cfg.actset[i]->name);
	opt[i][0]=0;
	j=WIN_ACT|WIN_RHT|WIN_BOT|WIN_SAV;
    if(cfg.total_actsets)
        j|=WIN_DEL|WIN_GET;
	if(cfg.total_actsets<MAX_OPTS)
        j|=WIN_INS|WIN_INSACT|WIN_XTR;
    if(savactset.name[0])
        j|=WIN_PUT;
    SETHELP(WHERE);
/*
796
`Chat Action Sets:`
rswindell's avatar
rswindell committed
797
798
799
800

This is a list of the configured action sets.

To add an action set, select the desired location with the arrow keys and
801
hit ~ INS ~.
rswindell's avatar
rswindell committed
802

803
To delete an action set, select it with the arrow keys and hit ~ DEL ~.
rswindell's avatar
rswindell committed
804

rswindell's avatar
rswindell committed
805
To configure an action set, select it with the arrow keys and hit
806
~ ENTER ~.
rswindell's avatar
rswindell committed
807
*/
808
	i=uifc.list(j,0,0,45,&actset_dflt,&actset_bar,"Chat Action Sets",opt);
rswindell's avatar
rswindell committed
809
810
811
812
813
814
	if((signed)i==-1)
		return;
	if((i&MSK_ON)==MSK_INS) {
		i&=MSK_OFF;
        SETHELP(WHERE);
/*
815
`Chat Action Set Name:`
rswindell's avatar
rswindell committed
816
817
818

This is the name of the selected chat action set.
*/
819
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"Chat Action Set Name",str,25
rswindell's avatar
rswindell committed
820
821
			,0)<1)
            continue;
deuce's avatar
deuce committed
822
        if((cfg.actset=(actset_t **)realloc(cfg.actset,sizeof(actset_t *)*(cfg.total_actsets+1)))
rswindell's avatar
rswindell committed
823
824
825
826
            ==NULL) {
            errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_actsets+1);
			cfg.total_actsets=0;
			bail(1);
827
828
            continue; 
		}
rswindell's avatar
rswindell committed
829
830
831
        if(cfg.total_actsets)
            for(j=cfg.total_actsets;j>i;j--)
                cfg.actset[j]=cfg.actset[j-1];
deuce's avatar
deuce committed
832
        if((cfg.actset[i]=(actset_t *)malloc(sizeof(actset_t)))==NULL) {
rswindell's avatar
rswindell committed
833
            errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(actset_t));
834
835
            continue; 
		}
rswindell's avatar
rswindell committed
836
837
838
		memset((actset_t *)cfg.actset[i],0,sizeof(actset_t));
        strcpy(cfg.actset[i]->name,str);
        cfg.total_actsets++;
839
        uifc.changes=1;
840
841
        continue; 
	}
rswindell's avatar
rswindell committed
842
843
	if((i&MSK_ON)==MSK_DEL) {
		i&=MSK_OFF;
deuce's avatar
deuce committed
844
        free(cfg.actset[i]);
rswindell's avatar
rswindell committed
845
846
847
        cfg.total_actsets--;
        for(j=i;j<cfg.total_actsets;j++)
            cfg.actset[j]=cfg.actset[j+1];
848
        uifc.changes=1;
849
850
        continue; 
	}
rswindell's avatar
rswindell committed
851
852
853
	if((i&MSK_ON)==MSK_GET) {
		i&=MSK_OFF;
        savactset=*cfg.actset[i];
854
855
        continue; 
	}
rswindell's avatar
rswindell committed
856
857
858
	if((i&MSK_ON)==MSK_PUT) {
		i&=MSK_OFF;
        *cfg.actset[i]=savactset;
859
        uifc.changes=1;
860
861
        continue; 
	}
rswindell's avatar
rswindell committed
862
863
864
865
866
867
868
869
870
    j=0;
    done=0;
    while(!done) {
        k=0;
        sprintf(opt[k++],"%-27.27s%s","Action Set Name",cfg.actset[i]->name);
        sprintf(opt[k++],"%-27.27s","Configure Chat Actions...");
		opt[k][0]=0;
        SETHELP(WHERE);
/*
871
`Chat Action Set Configuration:`
rswindell's avatar
rswindell committed
872
873
874
875

This menu is for configuring the selected chat action set.
*/
		sprintf(str,"%s Chat Action Set",cfg.actset[i]->name);
876
		switch(uifc.list(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&opt_dflt,0,str
rswindell's avatar
rswindell committed
877
878
879
880
881
882
883
            ,opt)) {
            case -1:
                done=1;
                break;
            case 0:
                SETHELP(WHERE);
/*
884
`Chat Action Set Name:`
rswindell's avatar
rswindell committed
885
886
887
888

This is the name of the selected action set.
*/
                strcpy(str,cfg.actset[i]->name);
889
				if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Action Set Name"
890
                    ,cfg.actset[i]->name,sizeof(cfg.actset[i]->name)-1,K_EDIT))
rswindell's avatar
rswindell committed
891
892
893
894
                    strcpy(cfg.actset[i]->name,str);
                break;
            case 1:
                chatact_cfg(i);
895
896
897
898
                break; 
			} 
		} 
	}
rswindell's avatar
rswindell committed
899
900
}