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