1 /*
2 * MISC.C
3 *
4 * Written on 30-Jul-90 by jim nutt. Changes on 10-Jul-94 by John Dennis.
5 * Released to the public domain.
6 *
7 * Miscellaneous functions for Msged.
8 */
9
10 #define TEXTLEN 80
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <time.h>
17 #include "addr.h"
18 #include "nedit.h"
19 #include "msged.h"
20 #include "memextra.h"
21 #include "winsys.h"
22 #include "menu.h"
23 #include "nshow.h"
24 #include "main.h"
25 #include "dialogs.h"
26 #include "help.h"
27 #include "misc.h"
28 #include "charset.h"
29 #include "group.h"
30
change_curr_addr(void)31 void change_curr_addr(void)
32 {
33 int ch, num;
34 int x1, y1, x2, y2;
35 static char line[TEXTLEN];
36 char **addrch;
37
38 if (SW->aliascount < 2)
39 {
40 return;
41 }
42 addrch = xcalloc(SW->aliascount + 2, sizeof(char *));
43
44 for (num = 0; num < SW->aliascount; num++)
45 {
46 sprintf(line, "%-20.20s", show_address(&alias[num]));
47 addrch[num] = xstrdup(line);
48 }
49
50 addrch[num] = NULL;
51
52 x1 = (maxx / 2) - 11;
53 x2 = (maxx / 2) + 11;
54 y1 = 8;
55
56 if (num > maxy - 1)
57 {
58 y2 = maxy - 1;
59 }
60 else
61 {
62 y2 = y1 + num + 1;
63 }
64
65 ch = DoMenu(x1 + 1, y1 + 1, x2 - 1, y2 - 1, addrch, 0, SELBOX_ADDRESS, "");
66
67 switch (ch)
68 {
69 case -1:
70 break;
71
72 default:
73 CurArea.addr = alias[ch];
74 ShowNewArea();
75 ShowMsgHeader(message);
76 break;
77 }
78
79 for (num = 0; num < SW->aliascount; num++)
80 {
81 xfree(addrch[num]);
82 }
83 xfree(addrch);
84 }
85
change_nodelist(void)86 void change_nodelist(void)
87 {
88 int ch, num;
89 int x1, y1, x2, y2;
90 static char line[TEXTLEN];
91 char **nodls;
92
93 if (SW->nodelists < 2)
94 {
95 return;
96 }
97 nodls = xcalloc(SW->nodelists + 2, sizeof(char *));
98
99 for (num = 0; num < SW->nodelists; num++)
100 {
101 sprintf(line, "%-20.20s", node_lists[num].name);
102 nodls[num] = xstrdup(line);
103 }
104
105 nodls[num] = NULL;
106
107 x1 = (maxx / 2) - 11;
108 x2 = (maxx / 2) + 11;
109 y1 = 8;
110
111 if (num > maxy - 1)
112 {
113 y2 = maxy - 1;
114 }
115 else
116 {
117 y2 = y1 + num + 1;
118 }
119
120 ch = DoMenu(x1 + 1, y1 + 1, x2 - 1, y2 - 1, nodls, 0, SELBOX_NODELIST, "");
121
122 switch (ch)
123 {
124 case -1:
125 break;
126
127 default:
128 ST->nodebase = node_lists[ch].base_name;
129 ST->sysop = node_lists[ch].sysop;
130 break;
131 }
132
133 for (num = 0; num < SW->nodelists; num++)
134 {
135 xfree(nodls[num]);
136 }
137 xfree(nodls);
138 }
139
change_username(void)140 void change_username(void)
141 {
142 int x1, y1, x2, y2, len = 0;
143 int i, j, ch;
144 char *list[MAXUSERS];
145
146 if (user_list[1].name == NULL)
147 {
148 return;
149 }
150
151 for (i = 0; i < MAXUSERS; i++)
152 {
153 if (user_list[i].name == NULL)
154 {
155 break;
156 }
157
158 list[i] = xstrdup(user_list[i].name);
159
160 j = strlen(list[i]);
161 if (j >= len)
162 {
163 len = j;
164 }
165 if (j >= maxx - 2)
166 {
167 *(list[i] + maxx - 4) = '\0';
168 }
169 }
170
171 list[i] = NULL;
172
173 if (len >= maxx - 2)
174 {
175 len = maxx - 4;
176 }
177
178 x1 = (maxx / 2) - (len / 2) - 1;
179 x2 = (maxx / 2) + (len / 2) + 1;
180 y1 = 7;
181 y2 = y1 + i + 1;
182
183 ch = DoMenu(x1 + 1, y1 + 1, x2 - 1, y2 - 1, list, 0, SELBOX_USERNAME, "");
184
185 switch (ch)
186 {
187 case -1:
188 break;
189
190 default:
191 release(ST->username);
192 ST->username = xstrdup(user_list[ch].name);
193
194 release(ST->lastread);
195
196 if (user_list[ch].lastread != NULL)
197 {
198 ST->lastread = xstrdup(user_list[ch].lastread);
199 }
200 else
201 {
202 ST->lastread = xstrdup(user_list[0].lastread);
203 }
204
205 SW->useroffset = user_list[ch].offset;
206 break;
207 }
208 i = 0;
209 while (list[i])
210 {
211 xfree(list[i++]);
212 }
213 }
214
set_switch(void)215 void set_switch(void)
216 {
217 WND *hCurr, *hWnd;
218 int ret;
219
220 ReadSettings();
221
222 hCurr = WndTop();
223 hWnd = WndPopUp(52, 20, INSBDR | SHADOW, cm[DL_BTXT], cm[DL_WTXT]);
224
225 ret = DoDialog(&settings, 1);
226
227 WndClose(hWnd);
228 WndCurr(hCurr);
229
230 if (ret == ID_OK)
231 {
232 WriteSettings();
233 ShowNewArea();
234 ShowMsgHeader(message);
235 message = KillMsg(message);
236 }
237 }
238
show_help(void)239 void show_help(void)
240 {
241 if (ST->helpfile != NULL)
242 {
243 DoHelp(0);
244 }
245 }
246
handle_rot(int c)247 int handle_rot(int c)
248 {
249 if (rot13 == 1)
250 {
251 if (isalpha((unsigned char)c))
252 {
253 if (toupper(c) >= 'A' && toupper(c) <= 'M')
254 {
255 c += 13;
256 }
257 else
258 {
259 c -= 13;
260 }
261 }
262 }
263 else
264 {
265 if ((unsigned char)c > '!')
266 {
267 if ((unsigned char)c + 47 > '~')
268 {
269 c = (unsigned char)c - 47;
270 }
271 else
272 {
273 c = (unsigned char) + 47;
274 }
275 }
276 }
277 return c;
278 }
279
280 /*
281 * This function is used when uudecoding is required using the
282 * built-in editor as GetString used in uudecode() leaves the cursor
283 * invisible when it returns.
284 */
285
286 #define UUDECODE(c) (char)(((c) - ' ') & 077)
287
uudecode(void)288 void uudecode(void)
289 {
290 unsigned char temp[4], bin[3];
291 static char buff[PATHLEN];
292 int len, i, bytes;
293 FILE *ofp;
294 LINE *cur;
295
296 if (message == NULL)
297 {
298 return;
299 }
300
301 *buff = '\0';
302
303 cur = message->text;
304
305 while (cur != NULL)
306 {
307 if (sscanf(cur->text, "begin %o %s", &i, buff) > 0)
308 {
309 break;
310 }
311 cur = cur->next;
312 }
313
314 if (cur == NULL)
315 {
316 return;
317 }
318
319 if (!GetString("UUdecode", "Enter filename", buff, sizeof buff))
320 {
321 return;
322 }
323
324 ofp = fopen(buff, "wb");
325
326 if (ofp == NULL)
327 {
328 return;
329 }
330
331 if (cur != NULL)
332 {
333 cur = cur->next;
334
335 while (cur != NULL && *cur->text != '\n' && *cur->text != '`' &&
336 strncmp(cur->text, "end", 3))
337 {
338 len = UUDECODE(*(cur->text));
339
340 if (!len)
341 {
342 break;
343 }
344
345 i = 0;
346 while (len > 0)
347 {
348 temp[0] = UUDECODE(*(cur->text + i + 1));
349 temp[1] = UUDECODE(*(cur->text + i + 2));
350 temp[2] = UUDECODE(*(cur->text + i + 3));
351 temp[3] = UUDECODE(*(cur->text + i + 4));
352
353 bytes = 0;
354 if (len > 0)
355 {
356 *bin = (unsigned char)
357 ((*temp << 2) | (*(temp + 1) >> 4));
358 bytes++;
359 len--;
360 if (len > 0)
361 {
362 *(bin + 1) = (unsigned char)
363 ((*(temp + 1) << 4) | (*(temp + 2) >> 2));
364 bytes++;
365 len--;
366 if (len > 0)
367 {
368 *(bin + 2) = (unsigned char)
369 ((*(temp + 2) << 6) | (*(temp + 3)));
370 bytes++;
371 len--;
372 }
373 }
374 }
375
376 if (fwrite(bin, 1, bytes, ofp) != bytes)
377 {
378 ChoiceBox("", "WARNING: Could not write to file", " Ok ", NULL, NULL);
379 fclose(ofp);
380 return;
381 }
382
383 i += 4;
384 }
385
386 cur = cur->next;
387 }
388 }
389 fclose(ofp);
390 }
391
e_uudecode(void)392 void e_uudecode(void)
393 {
394 uudecode();
395 TTCurSet(1);
396 }
397
hex_dump(void)398 void hex_dump(void)
399 {
400 static char buff[PATHLEN];
401 static char prtln[100];
402 int c, i, pos1 = 0, pos2 = 0;
403 FILE *ofp;
404 LINE *cur;
405 long x;
406
407 if (message == NULL)
408 {
409 return;
410 }
411
412 x = 0L;
413 *buff = '\0';
414
415 cur = message->text;
416 if (cur == NULL)
417 {
418 return;
419 }
420
421 if (!GetString("", "Enter filename", buff, sizeof buff))
422 {
423 return;
424 }
425
426 ofp = fopen(buff, "w");
427
428 if (ofp == NULL)
429 {
430 ChoiceBox("", "WARNING: Could not write to file", " Ok ", NULL, NULL);
431 return;
432 }
433
434 while (cur != NULL)
435 {
436 i = 0;
437 c = cur->text[i++];
438 while (c != '\0')
439 {
440 if (x % 16 == 0)
441 {
442 memset(prtln, ' ', sizeof prtln);
443 sprintf(prtln, "%0.6lX ", x);
444 pos1 = 8;
445 pos2 = 45;
446 }
447 sprintf(prtln + pos1, "%0.2X", c);
448 if (isprint(c))
449 {
450 sprintf(prtln + pos2, "%c", c);
451 }
452 else
453 {
454 sprintf(prtln + pos2, ".");
455 }
456 pos1 += 2;
457 *(prtln + pos1) = ' ';
458 pos2++;
459 if (x % 4 == 3)
460 {
461 *(prtln + pos1) = ' ';
462 pos1++;
463 }
464 if (x % 16 == 15)
465 {
466 fprintf(ofp, "%s\n", prtln);
467 }
468 x++;
469 c = cur->text[i];
470 i++;
471 }
472
473 cur = cur->next;
474 }
475
476 if (x % 16 != 0)
477 {
478 fprintf(ofp, "%s\n", prtln);
479 }
480 fclose(ofp);
481 }
482
483 /* select the charset to use */
484
sel_chs(void)485 void sel_chs(void)
486 {
487 static char *stdrecode = "Use @CHRS kludge (recommended!)";
488 static char *norecode = "Don't do any translation at all";
489 char *kludgelist;
490 int kn, ksz;
491 int num, ch = -1;
492 int x1, y1, x2, y2;
493 char **kludgemenu;
494
495 kludgelist = get_known_charset_table(&kn, &ksz);
496 if (kludgelist == NULL)
497 {
498 return;
499 }
500
501 kludgemenu = xcalloc(kn + 4, sizeof(char *));
502
503 kludgemenu[0] = stdrecode;
504 kludgemenu[1] = norecode;
505
506 for (num = 0; num < kn; num++)
507 {
508 kludgemenu[num + 2] = kludgelist + num * ksz;
509 }
510
511 kludgemenu[num + 2] = NULL;
512
513 x1 = (maxx / 2) - 17;
514 x2 = (maxx / 2) + 17;
515 y1 = 8;
516
517 if (y1 + num + 3 > maxy - 2)
518 {
519 y2 = maxy - 2;
520 }
521 else
522 {
523 y2 = y1 + num + 3;
524 }
525
526 while (ch < 0)
527 ch = DoMenu(x1 + 1, y1 + 1, x2 - 1, y2 - 1, kludgemenu, 0,
528 SELBOX_CHARSET, "Override Character Set");
529
530 switch (ch)
531 {
532 case 0:
533 release(ST->enforced_charset);
534 break;
535
536 case 1:
537 release(ST->enforced_charset);
538 ST->enforced_charset = xstrdup(get_local_charset());
539 break;
540
541 default:
542 release(ST->enforced_charset);
543 ST->enforced_charset = xstrdup(kludgemenu[ch]);
544 break;
545 }
546
547 message = KillMsg(message); /* force message re-read */
548
549 xfree(kludgemenu);
550 }
551
552 /* select the active group */
553
sel_group(void)554 int sel_group(void)
555 {
556 static char *firstentry = "Show all areas in all groups";
557 int num, ch = -1, i;
558 int x1, y1, x2, y2;
559 char **kludgemenu;
560
561 kludgemenu = group_buildlist(firstentry);
562
563 for (num = 0; kludgemenu[num] != NULL; num++);
564
565 x1 = (maxx / 2) - 22;
566 x2 = (maxx / 2) + 22;
567 y1 = 4;
568
569 if (y1 + num + 1 > maxy - 4)
570 {
571 y2 = maxy - 4;
572 }
573 else
574 {
575 y2 = y1 + num + 1;
576 }
577
578 ch = DoMenu(x1 + 1, y1 + 1, x2 - 1, y2 - 1, kludgemenu, SW->group,
579 SELBOX_GROUP, "Select Message Area Group");
580
581 switch (ch)
582 {
583 case -1: break;
584 default:
585 group_set_group(ch);
586 }
587
588 for (i = 0; i < num; i++)
589 {
590 xfree(kludgemenu[i]);
591 }
592 xfree(kludgemenu);
593
594 return (ch != -1);
595 }
596