~dannf/ubuntu/saucy/screen/lp1213278-from-debian

« back to all changes in this revision

Viewing changes to process.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathaniel McCallum
  • Date: 2004-09-03 15:15:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040903151533-px02yqlrchs4fv2t
Tags: upstream-4.0.2
ImportĀ upstreamĀ versionĀ 4.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 1993-2002
 
2
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
 
3
 *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
 
4
 * Copyright (c) 1987 Oliver Laumann
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2, or (at your option)
 
9
 * any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program (see the file COPYING); if not, write to the
 
18
 * Free Software Foundation, Inc.,
 
19
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 
20
 *
 
21
 ****************************************************************
 
22
 */
 
23
 
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>
 
26
#include <signal.h>
 
27
#include <fcntl.h>
 
28
#if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX)
 
29
# include <time.h>
 
30
#endif
 
31
#include <sys/time.h>
 
32
#ifndef sun
 
33
#include <sys/ioctl.h>
 
34
#endif
 
35
 
 
36
 
 
37
#include "config.h"
 
38
 
 
39
/* for solaris 2.1, Unixware (SVR4.2) and possibly others: */
 
40
#ifdef SVR4
 
41
# include <sys/stropts.h>
 
42
#endif
 
43
 
 
44
#include "screen.h"
 
45
#include "extern.h"
 
46
#include "logfile.h"
 
47
 
 
48
extern struct comm comms[];
 
49
extern char *rc_name;
 
50
extern char *RcFileName, *home;
 
51
extern char *BellString, *ActivityString, *ShellProg, *ShellArgs[];
 
52
extern char *hstatusstring, *captionstring, *timestring;
 
53
extern char *wliststr, *wlisttit;
 
54
extern int captionalways;
 
55
extern char *hardcopydir, *screenlogfile, *logtstamp_string;
 
56
extern int log_flush, logtstamp_on, logtstamp_after;
 
57
extern char *VisualBellString;
 
58
extern int VBellWait, MsgWait, MsgMinWait, SilenceWait;
 
59
extern char SockPath[], *SockName;
 
60
extern int TtyMode, auto_detach, use_altscreen;
 
61
extern int iflag, maxwin;
 
62
extern int use_hardstatus, visual_bell;
 
63
#ifdef COLOR
 
64
extern int attr2color[][4];
 
65
extern int nattr2color;
 
66
#endif
 
67
extern int hardstatusemu;
 
68
extern char *printcmd;
 
69
extern int default_startup;
 
70
extern int defobuflimit;
 
71
extern int defnonblock;
 
72
extern int ZombieKey_destroy;
 
73
extern int ZombieKey_resurrect;
 
74
#ifdef AUTO_NUKE
 
75
extern int defautonuke;
 
76
#endif
 
77
extern int separate_sids;
 
78
extern struct NewWindow nwin_default, nwin_undef;
 
79
#ifdef COPY_PASTE
 
80
extern int join_with_cr;
 
81
extern int compacthist;
 
82
extern int search_ic;
 
83
# ifdef FONT
 
84
extern int pastefont;
 
85
# endif
 
86
extern unsigned char mark_key_tab[];
 
87
extern char *BufferFile;
 
88
#endif
 
89
#ifdef POW_DETACH
 
90
extern char *BufferFile, *PowDetachString;
 
91
#endif
 
92
#ifdef MULTIUSER
 
93
extern struct acluser *EffectiveAclUser;        /* acl.c */
 
94
#endif
 
95
extern struct term term[];      /* terminal capabilities */
 
96
#ifdef MAPKEYS
 
97
extern char *kmapdef[];
 
98
extern char *kmapadef[];
 
99
extern char *kmapmdef[];
 
100
#endif
 
101
extern struct mchar mchar_so, mchar_null;
 
102
extern int VerboseCreate;
 
103
#ifdef UTF8
 
104
extern char *screenencodings;
 
105
#endif
 
106
 
 
107
static int  CheckArgNum __P((int, char **));
 
108
static void ClearAction __P((struct action *));
 
109
static void SaveAction __P((struct action *, int, char **, int *));
 
110
static int  NextWindow __P((void));
 
111
static int  PreviousWindow __P((void));
 
112
static int  MoreWindows __P((void));
 
113
static void LogToggle __P((int));
 
114
static void ShowInfo __P((void));
 
115
static void ShowDInfo __P((void));
 
116
static struct win *WindowByName __P((char *));
 
117
static int  WindowByNumber __P((char *));
 
118
static int  ParseOnOff __P((struct action *, int *));
 
119
static int  ParseWinNum __P((struct action *, int *));
 
120
static int  ParseBase __P((struct action *, char *, int *, int, char *));
 
121
static int  ParseNum1000 __P((struct action *, int *));
 
122
static char **SaveArgs __P((char **));
 
123
static int  IsNum __P((char *, int));
 
124
static void Colonfin __P((char *, int, char *));
 
125
static void InputSelect __P((void));
 
126
static void InputSetenv __P((char *));
 
127
static void InputAKA __P((void));
 
128
#ifdef MULTIUSER
 
129
static int  InputSu __P((struct win *, struct acluser **, char *));
 
130
static void su_fin __P((char *, int, char *));
 
131
#endif
 
132
static void AKAfin __P((char *, int, char *));
 
133
#ifdef COPY_PASTE
 
134
static void copy_reg_fn __P((char *, int, char *));
 
135
static void ins_reg_fn __P((char *, int, char *));
 
136
#endif
 
137
static void process_fn __P((char *, int, char *));
 
138
#ifdef PASSWORD
 
139
static void pass1 __P((char *, int, char *));
 
140
static void pass2 __P((char *, int, char *));
 
141
#endif
 
142
#ifdef POW_DETACH
 
143
static void pow_detach_fn __P((char *, int, char *));
 
144
#endif
 
145
static void digraph_fn __P((char *, int, char *));
 
146
static void confirm_fn __P((char *, int, char *));
 
147
static int  IsOnDisplay __P((struct win *));
 
148
static void ResizeRegions __P((char*));
 
149
static void ResizeFin __P((char *, int, char *));
 
150
static struct action *FindKtab __P((char *, int));
 
151
 
 
152
 
 
153
extern struct layer *flayer;
 
154
extern struct display *display, *displays;
 
155
extern struct win *fore, *console_window, *windows;
 
156
extern struct acluser *users;
 
157
 
 
158
extern char screenterm[], HostName[], version[];
 
159
extern struct NewWindow nwin_undef, nwin_default;
 
160
extern struct LayFuncs WinLf;
 
161
 
 
162
extern int Z0width, Z1width;
 
163
extern int real_uid, real_gid;
 
164
 
 
165
#ifdef NETHACK
 
166
extern int nethackflag;
 
167
#endif
 
168
 
 
169
 
 
170
struct win *wtab[MAXWIN];       /* window table, should be dynamic */
 
171
 
 
172
#ifdef MULTIUSER
 
173
extern char *multi;
 
174
extern int maxusercount;
 
175
#endif
 
176
char NullStr[] = "";
 
177
 
 
178
struct plop plop_tab[MAX_PLOP_DEFS];
 
179
 
 
180
#ifndef PTYMODE
 
181
# define PTYMODE 0622
 
182
#endif
 
183
 
 
184
int TtyMode = PTYMODE;
 
185
int hardcopy_append = 0;
 
186
int all_norefresh = 0;
 
187
#ifdef ZMODEM
 
188
int zmodem_mode = 0;
 
189
char *zmodem_sendcmd;
 
190
char *zmodem_recvcmd;
 
191
static char *zmodes[4] = {"off", "auto", "catch", "pass"};
 
192
#endif
 
193
 
 
194
int idletimo;
 
195
struct action idleaction;
 
196
#ifdef BLANKER_PRG
 
197
char **blankerprg;
 
198
#endif
 
199
 
 
200
struct action ktab[256];        /* command key translation table */
 
201
struct kclass {
 
202
  struct kclass *next;
 
203
  char *name;
 
204
  struct action ktab[256];
 
205
};
 
206
struct kclass *kclasses;
 
207
 
 
208
#ifdef MAPKEYS
 
209
struct action umtab[KMAP_KEYS+KMAP_AKEYS];
 
210
struct action dmtab[KMAP_KEYS+KMAP_AKEYS];
 
211
struct action mmtab[KMAP_KEYS+KMAP_AKEYS];
 
212
struct kmap_ext *kmap_exts;
 
213
int kmap_extn;
 
214
static int maptimeout = 300;
 
215
#endif
 
216
 
 
217
 
 
218
/* digraph table taken from old vim and rfc1345 */
 
219
static const unsigned char digraphs[][3] = {
 
220
    {' ', ' ', 160},    /* ļæ½ */
 
221
    {'N', 'S', 160},    /* ļæ½ */
 
222
    {'~', '!', 161},    /* ļæ½ */
 
223
    {'!', '!', 161},    /* ļæ½ */
 
224
    {'!', 'I', 161},    /* ļæ½ */
 
225
    {'c', '|', 162},    /* ļæ½ */
 
226
    {'c', 't', 162},    /* ļæ½ */
 
227
    {'$', '$', 163},    /* ļæ½ */
 
228
    {'P', 'd', 163},    /* ļæ½ */
 
229
    {'o', 'x', 164},    /* ļæ½ */
 
230
    {'C', 'u', 164},    /* ļæ½ */
 
231
    {'C', 'u', 164},    /* ļæ½ */
 
232
    {'E', 'u', 164},    /* ļæ½ */
 
233
    {'Y', '-', 165},    /* ļæ½ */
 
234
    {'Y', 'e', 165},    /* ļæ½ */
 
235
    {'|', '|', 166},    /* ļæ½ */
 
236
    {'B', 'B', 166},    /* ļæ½ */
 
237
    {'p', 'a', 167},    /* ļæ½ */
 
238
    {'S', 'E', 167},    /* ļæ½ */
 
239
    {'"', '"', 168},    /* ļæ½ */
 
240
    {'\'', ':', 168},   /* ļæ½ */
 
241
    {'c', 'O', 169},    /* ļæ½ */
 
242
    {'C', 'o', 169},    /* ļæ½ */
 
243
    {'a', '-', 170},    /* ļæ½ */
 
244
    {'<', '<', 171},    /* ļæ½ */
 
245
    {'-', ',', 172},    /* ļæ½ */
 
246
    {'N', 'O', 172},    /* ļæ½ */
 
247
    {'-', '-', 173},    /* ļæ½ */
 
248
    {'r', 'O', 174},    /* ļæ½ */
 
249
    {'R', 'g', 174},    /* ļæ½ */
 
250
    {'-', '=', 175},    /* ļæ½ */
 
251
    {'\'', 'm', 175},   /* ļæ½ */
 
252
    {'~', 'o', 176},    /* ļæ½ */
 
253
    {'D', 'G', 176},    /* ļæ½ */
 
254
    {'+', '-', 177},    /* ļæ½ */
 
255
    {'2', '2', 178},    /* ļæ½ */
 
256
    {'2', 'S', 178},    /* ļæ½ */
 
257
    {'3', '3', 179},    /* ļæ½ */
 
258
    {'3', 'S', 179},    /* ļæ½ */
 
259
    {'\'', '\'', 180},  /* ļæ½ */
 
260
    {'j', 'u', 181},    /* ļæ½ */
 
261
    {'M', 'y', 181},    /* ļæ½ */
 
262
    {'p', 'p', 182},    /* ļæ½ */
 
263
    {'P', 'I', 182},    /* ļæ½ */
 
264
    {'~', '.', 183},    /* ļæ½ */
 
265
    {'.', 'M', 183},    /* ļæ½ */
 
266
    {',', ',', 184},    /* ļæ½ */
 
267
    {'\'', ',', 184},   /* ļæ½ */
 
268
    {'1', '1', 185},    /* ļæ½ */
 
269
    {'1', 'S', 185},    /* ļæ½ */
 
270
    {'o', '-', 186},    /* ļæ½ */
 
271
    {'>', '>', 187},    /* ļæ½ */
 
272
    {'1', '4', 188},    /* ļæ½ */
 
273
    {'1', '2', 189},    /* ļæ½ */
 
274
    {'3', '4', 190},    /* ļæ½ */
 
275
    {'~', '?', 191},    /* ļæ½ */
 
276
    {'?', '?', 191},    /* ļæ½ */
 
277
    {'?', 'I', 191},    /* ļæ½ */
 
278
    {'A', '`', 192},    /* ļæ½ */
 
279
    {'A', '!', 192},    /* ļæ½ */
 
280
    {'A', '\'', 193},   /* ļæ½ */
 
281
    {'A', '^', 194},    /* ļæ½ */
 
282
    {'A', '>', 194},    /* ļæ½ */
 
283
    {'A', '~', 195},    /* ļæ½ */
 
284
    {'A', '?', 195},    /* ļæ½ */
 
285
    {'A', '"', 196},    /* ļæ½ */
 
286
    {'A', ':', 196},    /* ļæ½ */
 
287
    {'A', '@', 197},    /* ļæ½ */
 
288
    {'A', 'A', 197},    /* ļæ½ */
 
289
    {'A', 'E', 198},    /* ļæ½ */
 
290
    {'C', ',', 199},    /* ļæ½ */
 
291
    {'E', '`', 200},    /* ļæ½ */
 
292
    {'E', '!', 200},    /* ļæ½ */
 
293
    {'E', '\'', 201},   /* ļæ½ */
 
294
    {'E', '^', 202},    /* ļæ½ */
 
295
    {'E', '>', 202},    /* ļæ½ */
 
296
    {'E', '"', 203},    /* ļæ½ */
 
297
    {'E', ':', 203},    /* ļæ½ */
 
298
    {'I', '`', 204},    /* ļæ½ */
 
299
    {'I', '!', 204},    /* ļæ½ */
 
300
    {'I', '\'', 205},   /* ļæ½ */
 
301
    {'I', '^', 206},    /* ļæ½ */
 
302
    {'I', '>', 206},    /* ļæ½ */
 
303
    {'I', '"', 207},    /* ļæ½ */
 
304
    {'I', ':', 207},    /* ļæ½ */
 
305
    {'D', '-', 208},    /* ļæ½ */
 
306
    {'N', '~', 209},    /* ļæ½ */
 
307
    {'N', '?', 209},    /* ļæ½ */
 
308
    {'O', '`', 210},    /* ļæ½ */
 
309
    {'O', '!', 210},    /* ļæ½ */
 
310
    {'O', '\'', 211},   /* ļæ½ */
 
311
    {'O', '^', 212},    /* ļæ½ */
 
312
    {'O', '>', 212},    /* ļæ½ */
 
313
    {'O', '~', 213},    /* ļæ½ */
 
314
    {'O', '?', 213},    /* ļæ½ */
 
315
    {'O', '"', 214},    /* ļæ½ */
 
316
    {'O', ':', 214},    /* ļæ½ */
 
317
    {'/', '\\', 215},   /* ļæ½ */
 
318
    {'*', 'x', 215},    /* ļæ½ */
 
319
    {'O', '/', 216},    /* ļæ½ */
 
320
    {'U', '`', 217},    /* ļæ½ */
 
321
    {'U', '!', 217},    /* ļæ½ */
 
322
    {'U', '\'', 218},   /* ļæ½ */
 
323
    {'U', '^', 219},    /* ļæ½ */
 
324
    {'U', '>', 219},    /* ļæ½ */
 
325
    {'U', '"', 220},    /* ļæ½ */
 
326
    {'U', ':', 220},    /* ļæ½ */
 
327
    {'Y', '\'', 221},   /* ļæ½ */
 
328
    {'I', 'p', 222},    /* ļæ½ */
 
329
    {'T', 'H', 222},    /* ļæ½ */
 
330
    {'s', 's', 223},    /* ļæ½ */
 
331
    {'s', '"', 223},    /* ļæ½ */
 
332
    {'a', '`', 224},    /* ļæ½ */
 
333
    {'a', '!', 224},    /* ļæ½ */
 
334
    {'a', '\'', 225},   /* ļæ½ */
 
335
    {'a', '^', 226},    /* ļæ½ */
 
336
    {'a', '>', 226},    /* ļæ½ */
 
337
    {'a', '~', 227},    /* ļæ½ */
 
338
    {'a', '?', 227},    /* ļæ½ */
 
339
    {'a', '"', 228},    /* ļæ½ */
 
340
    {'a', ':', 228},    /* ļæ½ */
 
341
    {'a', 'a', 229},    /* ļæ½ */
 
342
    {'a', 'e', 230},    /* ļæ½ */
 
343
    {'c', ',', 231},    /* ļæ½ */
 
344
    {'e', '`', 232},    /* ļæ½ */
 
345
    {'e', '!', 232},    /* ļæ½ */
 
346
    {'e', '\'', 233},   /* ļæ½ */
 
347
    {'e', '^', 234},    /* ļæ½ */
 
348
    {'e', '>', 234},    /* ļæ½ */
 
349
    {'e', '"', 235},    /* ļæ½ */
 
350
    {'e', ':', 235},    /* ļæ½ */
 
351
    {'i', '`', 236},    /* ļæ½ */
 
352
    {'i', '!', 236},    /* ļæ½ */
 
353
    {'i', '\'', 237},   /* ļæ½ */
 
354
    {'i', '^', 238},    /* ļæ½ */
 
355
    {'i', '>', 238},    /* ļæ½ */
 
356
    {'i', '"', 239},    /* ļæ½ */
 
357
    {'i', ':', 239},    /* ļæ½ */
 
358
    {'d', '-', 240},    /* ļæ½ */
 
359
    {'n', '~', 241},    /* ļæ½ */
 
360
    {'n', '?', 241},    /* ļæ½ */
 
361
    {'o', '`', 242},    /* ļæ½ */
 
362
    {'o', '!', 242},    /* ļæ½ */
 
363
    {'o', '\'', 243},   /* ļæ½ */
 
364
    {'o', '^', 244},    /* ļæ½ */
 
365
    {'o', '>', 244},    /* ļæ½ */
 
366
    {'o', '~', 245},    /* ļæ½ */
 
367
    {'o', '?', 245},    /* ļæ½ */
 
368
    {'o', '"', 246},    /* ļæ½ */
 
369
    {'o', ':', 246},    /* ļæ½ */
 
370
    {':', '-', 247},    /* ļæ½ */
 
371
    {'o', '/', 248},    /* ļæ½ */
 
372
    {'u', '`', 249},    /* ļæ½ */
 
373
    {'u', '!', 249},    /* ļæ½ */
 
374
    {'u', '\'', 250},   /* ļæ½ */
 
375
    {'u', '^', 251},    /* ļæ½ */
 
376
    {'u', '>', 251},    /* ļæ½ */
 
377
    {'u', '"', 252},    /* ļæ½ */
 
378
    {'u', ':', 252},    /* ļæ½ */
 
379
    {'y', '\'', 253},   /* ļæ½ */
 
380
    {'i', 'p', 254},    /* ļæ½ */
 
381
    {'t', 'h', 254},    /* ļæ½ */
 
382
    {'y', '"', 255},    /* ļæ½ */
 
383
    {'y', ':', 255},    /* ļæ½ */
 
384
    {'"', '[', 196},    /* ļæ½ */
 
385
    {'"', '\\', 214},   /* ļæ½ */
 
386
    {'"', ']', 220},    /* ļæ½ */
 
387
    {'"', '{', 228},    /* ļæ½ */
 
388
    {'"', '|', 246},    /* ļæ½ */
 
389
    {'"', '}', 252},    /* ļæ½ */
 
390
    {'"', '~', 223}     /* ļæ½ */
 
391
};
 
392
 
 
393
 
 
394
char *noargs[1];
 
395
 
 
396
void
 
397
InitKeytab()
 
398
{
 
399
  register unsigned int i;
 
400
#ifdef MAPKEYS
 
401
  char *argarr[2];
 
402
#endif
 
403
 
 
404
  for (i = 0; i < sizeof(ktab)/sizeof(*ktab); i++)
 
405
    {
 
406
      ktab[i].nr = RC_ILLEGAL;
 
407
      ktab[i].args = noargs;
 
408
      ktab[i].argl = 0;
 
409
    }
 
410
#ifdef MAPKEYS
 
411
  for (i = 0; i < KMAP_KEYS+KMAP_AKEYS; i++)
 
412
    {
 
413
      umtab[i].nr = RC_ILLEGAL;
 
414
      umtab[i].args = noargs;
 
415
      umtab[i].argl = 0;
 
416
      dmtab[i].nr = RC_ILLEGAL;
 
417
      dmtab[i].args = noargs;
 
418
      dmtab[i].argl = 0;
 
419
      mmtab[i].nr = RC_ILLEGAL;
 
420
      mmtab[i].args = noargs;
 
421
      mmtab[i].argl = 0;
 
422
    }
 
423
  argarr[1] = 0;
 
424
  for (i = 0; i < NKMAPDEF; i++)
 
425
    {
 
426
      if (i + KMAPDEFSTART < T_CAPS)
 
427
        continue;
 
428
      if (i + KMAPDEFSTART >= T_CAPS + KMAP_KEYS)
 
429
        continue;
 
430
      if (kmapdef[i] == 0)
 
431
        continue;
 
432
      argarr[0] = kmapdef[i];
 
433
      SaveAction(dmtab + i + (KMAPDEFSTART - T_CAPS), RC_STUFF, argarr, 0);
 
434
    }
 
435
  for (i = 0; i < NKMAPADEF; i++)
 
436
    {
 
437
      if (i + KMAPADEFSTART < T_CURSOR)
 
438
        continue;
 
439
      if (i + KMAPADEFSTART >= T_CURSOR + KMAP_AKEYS)
 
440
        continue;
 
441
      if (kmapadef[i] == 0)
 
442
        continue;
 
443
      argarr[0] = kmapadef[i];
 
444
      SaveAction(dmtab + i + (KMAPADEFSTART - T_CURSOR + KMAP_KEYS), RC_STUFF, argarr, 0);
 
445
    }
 
446
  for (i = 0; i < NKMAPMDEF; i++)
 
447
    {
 
448
      if (i + KMAPMDEFSTART < T_CAPS)
 
449
        continue;
 
450
      if (i + KMAPMDEFSTART >= T_CAPS + KMAP_KEYS)
 
451
        continue;
 
452
      if (kmapmdef[i] == 0)
 
453
        continue;
 
454
      argarr[0] = kmapmdef[i];
 
455
      argarr[1] = 0;
 
456
      SaveAction(mmtab + i + (KMAPMDEFSTART - T_CAPS), RC_STUFF, argarr, 0);
 
457
    }
 
458
#endif
 
459
 
 
460
  ktab['h'].nr = RC_HARDCOPY;
 
461
#ifdef BSDJOBS
 
462
  ktab['z'].nr = ktab[Ctrl('z')].nr = RC_SUSPEND;
 
463
#endif
 
464
  ktab['c'].nr = ktab[Ctrl('c')].nr = RC_SCREEN;
 
465
  ktab[' '].nr = ktab[Ctrl(' ')].nr =
 
466
    ktab['n'].nr = ktab[Ctrl('n')].nr = RC_NEXT;
 
467
  ktab['N'].nr = RC_NUMBER;
 
468
  ktab[Ctrl('h')].nr = ktab[0177].nr = ktab['p'].nr = ktab[Ctrl('p')].nr = RC_PREV;
 
469
  ktab['k'].nr = ktab[Ctrl('k')].nr = RC_KILL;
 
470
  ktab['l'].nr = ktab[Ctrl('l')].nr = RC_REDISPLAY;
 
471
  ktab['w'].nr = ktab[Ctrl('w')].nr = RC_WINDOWS;
 
472
  ktab['v'].nr = RC_VERSION;
 
473
  ktab[Ctrl('v')].nr = RC_DIGRAPH;
 
474
  ktab['q'].nr = ktab[Ctrl('q')].nr = RC_XON;
 
475
  ktab['s'].nr = ktab[Ctrl('s')].nr = RC_XOFF;
 
476
  ktab['t'].nr = ktab[Ctrl('t')].nr = RC_TIME;
 
477
  ktab['i'].nr = ktab[Ctrl('i')].nr = RC_INFO;
 
478
  ktab['m'].nr = ktab[Ctrl('m')].nr = RC_LASTMSG;
 
479
  ktab['A'].nr = RC_TITLE;
 
480
#if defined(UTMPOK) && defined(LOGOUTOK)
 
481
  ktab['L'].nr = RC_LOGIN;
 
482
#endif
 
483
  ktab[','].nr = RC_LICENSE;
 
484
  ktab['W'].nr = RC_WIDTH;
 
485
  ktab['.'].nr = RC_DUMPTERMCAP;
 
486
  ktab[Ctrl('\\')].nr = RC_QUIT;
 
487
#ifdef DETACH
 
488
  ktab['d'].nr = ktab[Ctrl('d')].nr = RC_DETACH;
 
489
# ifdef POW_DETACH
 
490
  ktab['D'].nr = RC_POW_DETACH;
 
491
# endif
 
492
#endif
 
493
  ktab['r'].nr = ktab[Ctrl('r')].nr = RC_WRAP;
 
494
  ktab['f'].nr = ktab[Ctrl('f')].nr = RC_FLOW;
 
495
  ktab['C'].nr = RC_CLEAR;
 
496
  ktab['Z'].nr = RC_RESET;
 
497
  ktab['H'].nr = RC_LOG;
 
498
  ktab['M'].nr = RC_MONITOR;
 
499
  ktab['?'].nr = RC_HELP;
 
500
#ifdef MULTI
 
501
  ktab['*'].nr = RC_DISPLAYS;
 
502
#endif
 
503
  {
 
504
    char *args[2];
 
505
    args[0] = "-";
 
506
    args[1] = NULL;
 
507
    SaveAction(ktab + '-', RC_SELECT, args, 0);
 
508
  }
 
509
  for (i = 0; i < ((MAXWIN < 10) ? MAXWIN : 10); i++)
 
510
    {
 
511
      char *args[2], arg1[10];
 
512
      args[0] = arg1;
 
513
      args[1] = 0;
 
514
      sprintf(arg1, "%d", i);
 
515
      SaveAction(ktab + '0' + i, RC_SELECT, args, 0);
 
516
    }
 
517
  ktab['\''].nr = RC_SELECT; /* calling a window by name */
 
518
  {
 
519
    char *args[2];
 
520
    args[0] = "-b";
 
521
    args[1] = 0;
 
522
    SaveAction(ktab + '"', RC_WINDOWLIST, args, 0);
 
523
  }
 
524
  ktab[Ctrl('G')].nr = RC_VBELL;
 
525
  ktab[':'].nr = RC_COLON;
 
526
#ifdef COPY_PASTE
 
527
  ktab['['].nr = ktab[Ctrl('[')].nr = RC_COPY;
 
528
  {
 
529
    char *args[2];
 
530
    args[0] = ".";
 
531
    args[1] = 0;
 
532
    SaveAction(ktab + ']', RC_PASTE, args, 0);
 
533
    SaveAction(ktab + Ctrl(']'), RC_PASTE, args, 0);
 
534
  }
 
535
  ktab['{'].nr = RC_HISTORY;
 
536
  ktab['}'].nr = RC_HISTORY;
 
537
  ktab['>'].nr = RC_WRITEBUF;
 
538
  ktab['<'].nr = RC_READBUF;
 
539
  ktab['='].nr = RC_REMOVEBUF;
 
540
#endif
 
541
#ifdef POW_DETACH
 
542
  ktab['D'].nr = RC_POW_DETACH;
 
543
#endif
 
544
#ifdef LOCK
 
545
  ktab['x'].nr = ktab[Ctrl('x')].nr = RC_LOCKSCREEN;
 
546
#endif
 
547
  ktab['b'].nr = ktab[Ctrl('b')].nr = RC_BREAK;
 
548
  ktab['B'].nr = RC_POW_BREAK;
 
549
  ktab['_'].nr = RC_SILENCE;
 
550
  ktab['S'].nr = RC_SPLIT;
 
551
  ktab['Q'].nr = RC_ONLY;
 
552
  ktab['X'].nr = RC_REMOVE;
 
553
  ktab['F'].nr = RC_FIT;
 
554
  ktab['\t'].nr = RC_FOCUS;
 
555
  /* These come last; they may want overwrite others: */
 
556
  if (DefaultEsc >= 0)
 
557
    {
 
558
      ClearAction(&ktab[DefaultEsc]);
 
559
      ktab[DefaultEsc].nr = RC_OTHER;
 
560
    }
 
561
  if (DefaultMetaEsc >= 0)
 
562
    {
 
563
      ClearAction(&ktab[DefaultMetaEsc]);
 
564
      ktab[DefaultMetaEsc].nr = RC_META;
 
565
    }
 
566
 
 
567
  idleaction.nr = RC_BLANKER;
 
568
  idleaction.args = noargs;
 
569
  idleaction.argl = 0;
 
570
}
 
571
 
 
572
static struct action *
 
573
FindKtab(class, create)
 
574
char *class;
 
575
int create;
 
576
{
 
577
  struct kclass *kp, **kpp;
 
578
  int i;
 
579
 
 
580
  if (class == 0)
 
581
    return ktab;
 
582
  for (kpp = &kclasses; (kp = *kpp) != 0; kpp = &kp->next)
 
583
    if (!strcmp(kp->name, class))
 
584
      break;
 
585
  if (kp == 0)
 
586
    {
 
587
      if (!create)
 
588
        return 0;
 
589
      if (strlen(class) > 80)
 
590
        {
 
591
          Msg(0, "Command class name too long.");
 
592
          return 0;
 
593
        }
 
594
      kp = malloc(sizeof(*kp));
 
595
      if (kp == 0)
 
596
        {
 
597
          Msg(0, strnomem);
 
598
          return 0;
 
599
        }
 
600
      kp->name = SaveStr(class);
 
601
      for (i = 0; i < (int)(sizeof(kp->ktab)/sizeof(*kp->ktab)); i++)
 
602
        {
 
603
          kp->ktab[i].nr = RC_ILLEGAL;
 
604
          kp->ktab[i].args = noargs;
 
605
        }
 
606
      kp->next = 0;
 
607
      *kpp = kp;
 
608
    }
 
609
  return kp->ktab;
 
610
}
 
611
 
 
612
static void
 
613
ClearAction(act)
 
614
struct action *act;
 
615
{
 
616
  char **p;
 
617
 
 
618
  if (act->nr == RC_ILLEGAL)
 
619
    return;
 
620
  act->nr = RC_ILLEGAL;
 
621
  if (act->args == noargs)
 
622
    return;
 
623
  for (p = act->args; *p; p++)
 
624
    free(*p);
 
625
  free((char *)act->args);
 
626
  act->args = noargs;
 
627
  act->argl = 0;
 
628
}
 
629
 
 
630
/*
 
631
 * ProcessInput: process input from display and feed it into
 
632
 * the layer on canvas D_forecv.
 
633
 */
 
634
 
 
635
#ifdef MAPKEYS
 
636
 
 
637
/*
 
638
 *  This ProcessInput just does the keybindings and passes
 
639
 *  everything else on to ProcessInput2.
 
640
 */
 
641
 
 
642
void
 
643
ProcessInput(ibuf, ilen)
 
644
char *ibuf;
 
645
int ilen;
 
646
{
 
647
  int ch, slen;
 
648
  unsigned char *s, *q;
 
649
  int i, l;
 
650
  char *p;
 
651
 
 
652
  debug1("ProcessInput: %d bytes\n", ilen);
 
653
  if (display == 0 || ilen == 0)
 
654
    return;
 
655
  if (D_seql)
 
656
    evdeq(&D_mapev);
 
657
  slen = ilen;
 
658
  s = (unsigned char *)ibuf;
 
659
  while (ilen-- > 0)
 
660
    {
 
661
      ch = *s++;
 
662
      if (D_dontmap || !D_nseqs)
 
663
        {
 
664
          D_dontmap = 0;
 
665
          continue;
 
666
        }
 
667
      for (;;)
 
668
        {
 
669
          debug3("cmp %c %c[%d]\n", ch, *D_seqp, D_seqp - D_kmaps);
 
670
          if (*D_seqp != ch)
 
671
            {
 
672
              l = D_seqp[D_seqp[-D_seql-1] + 1];
 
673
              if (l)
 
674
                {
 
675
                  D_seqp += l * 2 + 4;
 
676
                  debug1("miss %d\n", D_seqp - D_kmaps);
 
677
                  continue;
 
678
                }
 
679
              debug("complete miss\n");
 
680
              D_mapdefault = 0;
 
681
              l = D_seql;
 
682
              p = (char *)D_seqp - l;
 
683
              D_seql = 0;
 
684
              D_seqp = D_kmaps + 3;
 
685
              if (l == 0)
 
686
                break;
 
687
              if ((q = D_seqh) != 0)
 
688
                {
 
689
                  D_seqh = 0;
 
690
                  i = q[0] << 8 | q[1];
 
691
                  i &= ~KMAP_NOTIMEOUT;
 
692
                  debug1("Mapping former hit #%d - ", i);
 
693
                  debug2("%d(%s) - ", q[2], q + 3);
 
694
                  if (StuffKey(i))
 
695
                    ProcessInput2((char *)q + 3, q[2]);
 
696
                  if (display == 0)
 
697
                    return;
 
698
                  l -= q[2];
 
699
                  p += q[2];
 
700
                }
 
701
              else
 
702
                D_dontmap = 1;
 
703
              debug1("flush old %d\n", l);
 
704
              ProcessInput(p, l);
 
705
              if (display == 0)
 
706
                return;
 
707
              evdeq(&D_mapev);
 
708
              continue;
 
709
            }
 
710
          if (D_seql++ == 0)
 
711
            {
 
712
              /* Finish old stuff */
 
713
              slen -= ilen + 1;
 
714
              debug1("finish old %d\n", slen);
 
715
              if (slen)
 
716
                ProcessInput2(ibuf, slen);
 
717
              if (display == 0)
 
718
                return;
 
719
              D_seqh = 0;
 
720
            }
 
721
          ibuf = (char *)s;
 
722
          slen = ilen;
 
723
          D_seqp++;
 
724
          l = D_seql;
 
725
          debug2("length am %d, want %d\n", l, D_seqp[-l - 1]);
 
726
          if (l == D_seqp[-l - 1])
 
727
            {
 
728
              if (D_seqp[l] != l)
 
729
                {
 
730
                  q = D_seqp + 1 + l;
 
731
                  if (D_kmaps + D_nseqs > q && q[2] > l && !bcmp(D_seqp - l, q + 3, l))
 
732
                    {
 
733
                      debug1("have another mapping (%s), delay execution\n", q + 3);
 
734
                      D_seqh = D_seqp - 3 - l;
 
735
                      D_seqp = q + 3 + l;
 
736
                      break;
 
737
                    }
 
738
                }
 
739
              i = D_seqp[-l - 3] << 8 | D_seqp[-l - 2];
 
740
              i &= ~KMAP_NOTIMEOUT;
 
741
              debug1("Mapping #%d - ", i);
 
742
              p = (char *)D_seqp - l;
 
743
              debug2("%d(%s) - ", l, p);
 
744
              D_seql = 0;
 
745
              D_seqp = D_kmaps + 3;
 
746
              D_seqh = 0;
 
747
              if (StuffKey(i))
 
748
                ProcessInput2(p, l);
 
749
              if (display == 0)
 
750
                return;
 
751
            }
 
752
          break;
 
753
        }
 
754
    }
 
755
  if (D_seql)
 
756
    {
 
757
      debug("am in sequence -> check for timeout\n");
 
758
      l = D_seql;
 
759
      for (s = D_seqp; ; s += i * 2 + 4)
 
760
        {
 
761
          if (s[-l-3] & KMAP_NOTIMEOUT >> 8)
 
762
            break;
 
763
          if ((i = s[s[-l-1] + 1]) == 0)
 
764
            {
 
765
              SetTimeout(&D_mapev, maptimeout);
 
766
              evenq(&D_mapev);
 
767
              break;
 
768
            }
 
769
        }
 
770
    }
 
771
  ProcessInput2(ibuf, slen);
 
772
}
 
773
 
 
774
#else
 
775
# define ProcessInput2 ProcessInput
 
776
#endif
 
777
 
 
778
 
 
779
/*
 
780
 *  Here only the screen escape commands are handled.
 
781
 */
 
782
 
 
783
void
 
784
ProcessInput2(ibuf, ilen)
 
785
char *ibuf;
 
786
int ilen;
 
787
{
 
788
  char *s;
 
789
  int ch, slen;
 
790
  struct action *ktabp;
 
791
 
 
792
  debug1("ProcessInput2: %d bytes\n", ilen);
 
793
  while (ilen && display)
 
794
    {
 
795
      debug1(" - ilen now %d bytes\n", ilen);
 
796
      flayer = D_forecv->c_layer;
 
797
      fore = D_fore;
 
798
      slen = ilen;
 
799
      s = ibuf;
 
800
      if (!D_ESCseen)
 
801
        {
 
802
          while (ilen > 0)
 
803
            {
 
804
              if ((unsigned char)*s++ == D_user->u_Esc)
 
805
                break;
 
806
              ilen--;
 
807
            }
 
808
          slen -= ilen;
 
809
          if (slen)
 
810
            DoProcess(fore, &ibuf, &slen, 0);
 
811
          if (--ilen == 0)
 
812
            D_ESCseen = ktab;
 
813
        }
 
814
      if (ilen <= 0)
 
815
        return;
 
816
      ktabp = D_ESCseen ? D_ESCseen : ktab;
 
817
      D_ESCseen = 0;
 
818
      ch = (unsigned char)*s;
 
819
 
 
820
      /* 
 
821
       * As users have different esc characters, but a common ktab[],
 
822
       * we fold back the users esc and meta-esc key to the Default keys
 
823
       * that can be looked up in the ktab[]. grmbl. jw.
 
824
       * XXX: make ktab[] a per user thing.
 
825
       */
 
826
      if (ch == D_user->u_Esc) 
 
827
        ch = DefaultEsc;
 
828
      else if (ch == D_user->u_MetaEsc) 
 
829
        ch = DefaultMetaEsc;
 
830
 
 
831
      if (ch >= 0)
 
832
        DoAction(&ktabp[ch], ch);
 
833
      ibuf = (char *)(s + 1);
 
834
      ilen--;
 
835
    }
 
836
}
 
837
 
 
838
void
 
839
DoProcess(p, bufp, lenp, pa)
 
840
struct win *p;
 
841
char **bufp;
 
842
int *lenp;
 
843
struct paster *pa;
 
844
{
 
845
  int oldlen;
 
846
  struct display *d = display;
 
847
 
 
848
#ifdef COPY_PASTE
 
849
  /* XXX -> PasteStart */
 
850
  if (pa && *lenp > 1 && p && p->w_slowpaste)
 
851
    {
 
852
      /* schedule slowpaste event */
 
853
      SetTimeout(&p->w_paster.pa_slowev, p->w_slowpaste);
 
854
      evenq(&p->w_paster.pa_slowev);
 
855
      return;
 
856
    }
 
857
#endif
 
858
  while (flayer && *lenp)
 
859
    {
 
860
#ifdef COPY_PASTE
 
861
      if (!pa && p && p->w_paster.pa_pastelen && flayer == p->w_paster.pa_pastelayer)
 
862
        {
 
863
          debug("layer is busy - beep!\n");
 
864
          WBell(p, visual_bell);
 
865
          *bufp += *lenp;
 
866
          *lenp = 0;
 
867
          display = d;
 
868
          return;
 
869
        }
 
870
#endif
 
871
      oldlen = *lenp;
 
872
      LayProcess(bufp, lenp);
 
873
#ifdef COPY_PASTE
 
874
      if (pa && !pa->pa_pastelayer)
 
875
        break;          /* flush rest of paste */
 
876
#endif
 
877
      if (*lenp == oldlen)
 
878
        {
 
879
          if (pa)
 
880
            {
 
881
              display = d;
 
882
              return;
 
883
            }
 
884
          /* We're full, let's beep */
 
885
          debug("layer is full - beep!\n");
 
886
          WBell(p, visual_bell);
 
887
          break;
 
888
        }
 
889
    }
 
890
  *bufp += *lenp;
 
891
  *lenp = 0;
 
892
  display = d;
 
893
#ifdef COPY_PASTE
 
894
  if (pa && pa->pa_pastelen == 0)
 
895
    FreePaster(pa);
 
896
#endif
 
897
}
 
898
 
 
899
int
 
900
FindCommnr(str)
 
901
char *str;
 
902
{
 
903
  int x, m, l = 0, r = RC_LAST;
 
904
  while (l <= r)
 
905
    {
 
906
      m = (l + r) / 2;
 
907
      x = strcmp(str, comms[m].name);
 
908
      if (x > 0)
 
909
        l = m + 1;
 
910
      else if (x < 0)
 
911
        r = m - 1;
 
912
      else
 
913
        return m;
 
914
    }
 
915
  return RC_ILLEGAL;
 
916
}
 
917
 
 
918
static int
 
919
CheckArgNum(nr, args)
 
920
int nr;
 
921
char **args;
 
922
{
 
923
  int i, n;
 
924
  static char *argss[] = {"no", "one", "two", "three", "four", "OOPS"};
 
925
  static char *orformat[] = 
 
926
    {
 
927
      "%s: %s: %s argument%s required",
 
928
      "%s: %s: %s or %s argument%s required",
 
929
      "%s: %s: %s, %s or %s argument%s required",
 
930
      "%s: %s: %s, %s, %s or %s argument%s required"
 
931
    };
 
932
 
 
933
  n = comms[nr].flags & ARGS_MASK;
 
934
  for (i = 0; args[i]; i++)
 
935
    ;
 
936
  if (comms[nr].flags & ARGS_ORMORE)
 
937
    {
 
938
      if (i < n)
 
939
        {
 
940
          Msg(0, "%s: %s: at least %s argument%s required", 
 
941
              rc_name, comms[nr].name, argss[n], n != 1 ? "s" : "");
 
942
          return -1;
 
943
        }
 
944
    }
 
945
  else if ((comms[nr].flags & ARGS_PLUS1) && 
 
946
           (comms[nr].flags & ARGS_PLUS2) &&
 
947
           (comms[nr].flags & ARGS_PLUS3))
 
948
    {
 
949
      if (i != n && i != n + 1 && i != n + 2 && i != n + 3)
 
950
        {
 
951
          Msg(0, orformat[3], rc_name, comms[nr].name, argss[n], 
 
952
              argss[n + 1], argss[n + 2], argss[n + 3], "");
 
953
          return -1;
 
954
        }
 
955
    }
 
956
  else if ((comms[nr].flags & ARGS_PLUS1) &&
 
957
           (comms[nr].flags & ARGS_PLUS2))
 
958
    {
 
959
      if (i != n && i != n + 1 && i != n + 2)
 
960
        {
 
961
          Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], 
 
962
              argss[n + 1], argss[n + 2], "");
 
963
          return -1;
 
964
        }
 
965
    }
 
966
  else if ((comms[nr].flags & ARGS_PLUS1) &&
 
967
           (comms[nr].flags & ARGS_PLUS3))
 
968
    {
 
969
      if (i != n && i != n + 1 && i != n + 3)
 
970
        {
 
971
          Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], 
 
972
              argss[n + 1], argss[n + 3], "");
 
973
          return -1;
 
974
        }
 
975
    }
 
976
  else if ((comms[nr].flags & ARGS_PLUS2) &&
 
977
           (comms[nr].flags & ARGS_PLUS3))
 
978
    {
 
979
      if (i != n && i != n + 2 && i != n + 3)
 
980
        {
 
981
          Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], 
 
982
              argss[n + 2], argss[n + 3], "");
 
983
          return -1;
 
984
        }
 
985
    }
 
986
  else if (comms[nr].flags & ARGS_PLUS1)
 
987
    {
 
988
      if (i != n && i != n + 1)
 
989
        {
 
990
          Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], 
 
991
              argss[n + 1], n != 0 ? "s" : "");
 
992
          return -1;
 
993
        }
 
994
    }
 
995
  else if (comms[nr].flags & ARGS_PLUS2)
 
996
    {
 
997
      if (i != n && i != n + 2)
 
998
        {
 
999
          Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], 
 
1000
              argss[n + 2], "s");
 
1001
          return -1;
 
1002
        }
 
1003
    }
 
1004
  else if (comms[nr].flags & ARGS_PLUS3)
 
1005
    {
 
1006
      if (i != n && i != n + 3)
 
1007
        {
 
1008
          Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], 
 
1009
              argss[n + 3], "");
 
1010
          return -1;
 
1011
        }
 
1012
    }
 
1013
  else if (i != n)
 
1014
    {
 
1015
      Msg(0, orformat[0], rc_name, comms[nr].name, argss[n], n != 1 ? "s" : "");
 
1016
      return -1;
 
1017
    }
 
1018
  return i;
 
1019
}
 
1020
 
 
1021
/*ARGSUSED*/
 
1022
void
 
1023
DoAction(act, key)
 
1024
struct action *act;
 
1025
int key;
 
1026
{
 
1027
  int nr = act->nr;
 
1028
  char **args = act->args;
 
1029
  int *argl = act->argl;
 
1030
  struct win *p;
 
1031
  int argc, i, n, msgok;
 
1032
  char *s;
 
1033
  char ch;
 
1034
  struct display *odisplay = display;
 
1035
  struct acluser *user;
 
1036
 
 
1037
  user = display ? D_user : users;
 
1038
  if (nr == RC_ILLEGAL)
 
1039
    {
 
1040
      debug1("key '%c': No action\n", key);
 
1041
      return;
 
1042
    }
 
1043
  n = comms[nr].flags;
 
1044
  if ((n & NEED_DISPLAY) && display == 0)
 
1045
    {
 
1046
      Msg(0, "%s: %s: display required", rc_name, comms[nr].name);
 
1047
      return;
 
1048
    }
 
1049
  if ((n & NEED_FORE) && fore == 0)
 
1050
    {
 
1051
      Msg(0, "%s: %s: window required", rc_name, comms[nr].name);
 
1052
      return;
 
1053
    }
 
1054
  if ((n & NEED_LAYER) && flayer == 0)
 
1055
    {
 
1056
      Msg(0, "%s: %s: display or window required", rc_name, comms[nr].name);
 
1057
      return;
 
1058
    }
 
1059
  if ((argc = CheckArgNum(nr, args)) < 0)
 
1060
    return;
 
1061
#ifdef MULTIUSER
 
1062
  if (display)
 
1063
    {
 
1064
      if (AclCheckPermCmd(D_user, ACL_EXEC, &comms[nr]))
 
1065
        {
 
1066
          Msg(0, "%s: %s: permission denied (user %s)", 
 
1067
              rc_name, comms[nr].name, (EffectiveAclUser ? EffectiveAclUser : D_user)->u_name);
 
1068
          return;
 
1069
        }
 
1070
    }
 
1071
#endif /* MULTIUSER */
 
1072
 
 
1073
  msgok = display && !*rc_name;
 
1074
  switch(nr)
 
1075
    {
 
1076
    case RC_SELECT:
 
1077
      if (!*args)
 
1078
        InputSelect();
 
1079
      else if (args[0][0] == '-' && !args[0][1])
 
1080
        {
 
1081
          SetForeWindow((struct win *)0);
 
1082
          Activate(0);
 
1083
        }
 
1084
      else if (args[0][0] == '.' && !args[0][1])
 
1085
        {
 
1086
          if (!fore)
 
1087
            Msg(0, "select . needs a window");
 
1088
          else
 
1089
            {
 
1090
              SetForeWindow(fore);
 
1091
              Activate(0);
 
1092
            }
 
1093
        }
 
1094
      else if (ParseWinNum(act, &n) == 0)
 
1095
        SwitchWindow(n);
 
1096
      break;
 
1097
#ifdef AUTO_NUKE
 
1098
    case RC_DEFAUTONUKE:
 
1099
      if (ParseOnOff(act, &defautonuke) == 0 && msgok)
 
1100
        Msg(0, "Default autonuke turned %s", defautonuke ? "on" : "off");
 
1101
      if (display && *rc_name)
 
1102
        D_auto_nuke = defautonuke;
 
1103
      break;
 
1104
    case RC_AUTONUKE:
 
1105
      if (ParseOnOff(act, &D_auto_nuke) == 0 && msgok)
 
1106
        Msg(0, "Autonuke turned %s", D_auto_nuke ? "on" : "off");
 
1107
      break;
 
1108
#endif
 
1109
    case RC_DEFOBUFLIMIT:
 
1110
      if (ParseNum(act, &defobuflimit) == 0 && msgok)
 
1111
        Msg(0, "Default limit set to %d", defobuflimit);
 
1112
      if (display && *rc_name)
 
1113
        {
 
1114
          D_obufmax = defobuflimit;
 
1115
          D_obuflenmax = D_obuflen - D_obufmax;
 
1116
        }
 
1117
      break;
 
1118
    case RC_OBUFLIMIT:
 
1119
      if (*args == 0)
 
1120
        Msg(0, "Limit is %d, current buffer size is %d", D_obufmax, D_obuflen);
 
1121
      else if (ParseNum(act, &D_obufmax) == 0 && msgok)
 
1122
        Msg(0, "Limit set to %d", D_obufmax);
 
1123
      D_obuflenmax = D_obuflen - D_obufmax;
 
1124
      break;
 
1125
    case RC_DUMPTERMCAP:
 
1126
      WriteFile(user, (char *)0, DUMP_TERMCAP);
 
1127
      break;
 
1128
    case RC_HARDCOPY:
 
1129
      {
 
1130
        int mode = DUMP_HARDCOPY;
 
1131
 
 
1132
        if (argc > 1 && !strcmp(*args, "-h"))
 
1133
          {
 
1134
            mode = DUMP_SCROLLBACK;
 
1135
            args++;
 
1136
            argc--;
 
1137
          }
 
1138
        if (*args && args[1])
 
1139
          {
 
1140
            Msg(0, "%s: hardcopy: too many arguments", rc_name);
 
1141
            break;
 
1142
          }
 
1143
        if (fore == 0 && *args == 0)
 
1144
          Msg(0, "%s: hardcopy: window required", rc_name);
 
1145
        else
 
1146
          WriteFile(user, *args, mode);
 
1147
      }
 
1148
      break;
 
1149
    case RC_DEFLOG:
 
1150
      (void)ParseOnOff(act, &nwin_default.Lflag);
 
1151
      break;
 
1152
    case RC_LOG:
 
1153
      n = fore->w_log ? 1 : 0;
 
1154
      ParseSwitch(act, &n);
 
1155
      LogToggle(n);
 
1156
      break;
 
1157
#ifdef BSDJOBS
 
1158
    case RC_SUSPEND:
 
1159
      Detach(D_STOP);
 
1160
      break;
 
1161
#endif
 
1162
    case RC_NEXT:
 
1163
      if (MoreWindows())
 
1164
        SwitchWindow(NextWindow());
 
1165
      break;
 
1166
    case RC_PREV:
 
1167
      if (MoreWindows())
 
1168
        SwitchWindow(PreviousWindow());
 
1169
      break;
 
1170
    case RC_KILL:
 
1171
      {
 
1172
        char *name;
 
1173
 
 
1174
        if (key >= 0)
 
1175
          {
 
1176
#ifdef PSEUDOS
 
1177
            Input(fore->w_pwin ? "Really kill this filter [y/n]" : "Really kill this window [y/n]", 1, INP_RAW, confirm_fn, (char *)RC_KILL);
 
1178
#else
 
1179
            Input("Really kill this window [y/n]", 1, INP_RAW, confirm_fn, (char *)RC_KILL);
 
1180
#endif
 
1181
            break;
 
1182
          }
 
1183
        n = fore->w_number;
 
1184
#ifdef PSEUDOS
 
1185
        if (fore->w_pwin)
 
1186
          {
 
1187
            FreePseudowin(fore);
 
1188
            Msg(0, "Filter removed.");
 
1189
            break;
 
1190
          }
 
1191
#endif
 
1192
        name = SaveStr(fore->w_title);
 
1193
        KillWindow(fore);
 
1194
        Msg(0, "Window %d (%s) killed.", n, name);
 
1195
        if (name)
 
1196
          free(name);
 
1197
        break;
 
1198
      }
 
1199
    case RC_QUIT:
 
1200
      if (key >= 0)
 
1201
        {
 
1202
          Input("Really quit and kill all your windows [y/n]", 1, INP_RAW, confirm_fn, (char *)RC_QUIT);
 
1203
          break;
 
1204
        }
 
1205
      Finit(0);
 
1206
      /* NOTREACHED */
 
1207
#ifdef DETACH
 
1208
    case RC_DETACH:
 
1209
      if (*args && !strcmp(*args, "-h"))
 
1210
        Hangup();
 
1211
      else
 
1212
        Detach(D_DETACH);
 
1213
      break;
 
1214
# ifdef POW_DETACH
 
1215
    case RC_POW_DETACH:
 
1216
      if (key >= 0)
 
1217
        {
 
1218
          static char buf[2];
 
1219
 
 
1220
          buf[0] = key;
 
1221
          Input(buf, 1, INP_RAW, pow_detach_fn, NULL);
 
1222
        }
 
1223
      else
 
1224
        Detach(D_POWER); /* detach and kill Attacher's parent */
 
1225
      break;
 
1226
# endif
 
1227
#endif
 
1228
    case RC_DEBUG:
 
1229
#ifdef DEBUG
 
1230
      if (!*args)
 
1231
        {
 
1232
          if (dfp)
 
1233
            Msg(0, "debugging info is written to %s/", DEBUGDIR);
 
1234
          else
 
1235
            Msg(0, "debugging is currently off. Use 'debug on' to enable.");
 
1236
          break;
 
1237
        }
 
1238
      if (dfp)
 
1239
        {
 
1240
          debug("debug: closing debug file.\n");
 
1241
          fflush(dfp);
 
1242
          fclose(dfp);
 
1243
          dfp = NULL;
 
1244
        }
 
1245
      if (strcmp("off", *args))
 
1246
        opendebug(0, 1);
 
1247
# ifdef SIG_NODEBUG
 
1248
      else if (display)
 
1249
        kill(D_userpid, SIG_NODEBUG);   /* a one shot item, but hey... */
 
1250
# endif /* SIG_NODEBUG */
 
1251
#else
 
1252
      if (*args == 0 || strcmp("off", *args))
 
1253
        Msg(0, "Sorry, screen was compiled without -DDEBUG option.");
 
1254
#endif
 
1255
      break;
 
1256
#ifdef ZMODEM
 
1257
    case RC_ZMODEM:
 
1258
      if (*args && !strcmp(*args, "sendcmd"))
 
1259
        {
 
1260
          if (args[1])
 
1261
            {
 
1262
              free(zmodem_sendcmd);
 
1263
              zmodem_sendcmd = SaveStr(args[1]);
 
1264
            }
 
1265
          if (msgok)
 
1266
            Msg(0, "zmodem sendcmd: %s", zmodem_sendcmd);
 
1267
          break;
 
1268
        }
 
1269
      if (*args && !strcmp(*args, "recvcmd"))
 
1270
        {
 
1271
          if (args[1])
 
1272
            {
 
1273
              free(zmodem_recvcmd);
 
1274
              zmodem_recvcmd = SaveStr(args[1]);
 
1275
            }
 
1276
          if (msgok)
 
1277
            Msg(0, "zmodem recvcmd: %s", zmodem_recvcmd);
 
1278
          break;
 
1279
        }
 
1280
      if (*args)
 
1281
        {
 
1282
          for (i = 0; i < 4; i++)
 
1283
            if (!strcmp(zmodes[i], *args))
 
1284
              break;
 
1285
          if (i == 4 && !strcmp(*args, "on"))
 
1286
            i = 1;
 
1287
          if (i == 4)
 
1288
            {
 
1289
              Msg(0, "usage: zmodem off|auto|catch|pass");
 
1290
              break;
 
1291
            }
 
1292
          zmodem_mode = i;
 
1293
        }
 
1294
      if (msgok)
 
1295
        Msg(0, "zmodem mode is %s", zmodes[zmodem_mode]);
 
1296
      break;
 
1297
#endif
 
1298
    case RC_ZOMBIE:
 
1299
      {
 
1300
        if (!(s = *args))
 
1301
          {
 
1302
            ZombieKey_destroy = 0;
 
1303
            break;
 
1304
          }
 
1305
        if (*argl == 0 || *argl > 2)
 
1306
          {
 
1307
            Msg(0, "%s:zombie: one or two characters expected.", rc_name);
 
1308
            break;
 
1309
          }
 
1310
        ZombieKey_destroy = args[0][0];
 
1311
        ZombieKey_resurrect = *argl == 2 ? args[0][1] : 0;
 
1312
      }
 
1313
      break;
 
1314
    case RC_WALL:
 
1315
#ifdef MULTIUSER
 
1316
      s = D_user->u_name;
 
1317
#else
 
1318
      s = D_usertty;
 
1319
#endif
 
1320
        {
 
1321
          struct display *olddisplay = display;
 
1322
          display = 0;          /* no display will cause a broadcast */
 
1323
          Msg(0, "%s: %s", s, *args);
 
1324
          display = olddisplay;
 
1325
        }
 
1326
      break;
 
1327
    case RC_AT:
 
1328
      /* where this AT command comes from: */
 
1329
#ifdef MULTIUSER
 
1330
      s = SaveStr(D_user->u_name);
 
1331
      /* DO NOT RETURN FROM HERE WITHOUT RESETTING THIS: */
 
1332
      EffectiveAclUser = D_user;
 
1333
#else
 
1334
      s = SaveStr(D_usertty);
 
1335
#endif
 
1336
      n = strlen(args[0]);
 
1337
      if (n) n--;
 
1338
      /*
 
1339
       * the windows/displays loops are quite dangerous here, take extra
 
1340
       * care not to trigger landmines. Things may appear/disappear while
 
1341
       * we are walking along.
 
1342
       */
 
1343
      switch (args[0][n])
 
1344
        {
 
1345
        case '*':               /* user */
 
1346
          {
 
1347
            struct display *nd;
 
1348
            struct acluser *u;
 
1349
 
 
1350
            if (!n)
 
1351
              u = D_user;
 
1352
            else
 
1353
              for (u = users; u; u = u->u_next)
 
1354
                {
 
1355
                  debug3("strncmp('%s', '%s', %d)\n", *args, u->u_name, n);
 
1356
                  if (!strncmp(*args, u->u_name, n))
 
1357
                    break;
 
1358
                }
 
1359
            debug1("at all displays of user %s\n", u->u_name);
 
1360
            for (display = displays; display; display = nd)
 
1361
              {
 
1362
                nd = display->d_next;
 
1363
                if (D_forecv == 0)
 
1364
                  continue;
 
1365
                flayer = D_forecv->c_layer;
 
1366
                fore = D_fore;
 
1367
                if (D_user != u)
 
1368
                  continue;
 
1369
                debug1("AT display %s\n", D_usertty);
 
1370
                DoCommand(args + 1, argl + 1);
 
1371
                if (display)
 
1372
                  Msg(0, "command from %s: %s %s", 
 
1373
                      s, args[1], args[2] ? args[2] : "");
 
1374
                display = NULL;
 
1375
                flayer = 0;
 
1376
                fore = NULL;
 
1377
              }
 
1378
            break;
 
1379
          }
 
1380
        case '%':               /* display */
 
1381
          {
 
1382
            struct display *nd;
 
1383
 
 
1384
            debug1("at display matching '%s'\n", args[0]);
 
1385
            for (display = displays; display; display = nd)
 
1386
              {
 
1387
                nd = display->d_next;
 
1388
                if (D_forecv == 0)
 
1389
                  continue;
 
1390
                fore = D_fore;
 
1391
                flayer = D_forecv->c_layer;
 
1392
                if (strncmp(args[0], D_usertty, n) && 
 
1393
                    (strncmp("/dev/", D_usertty, 5) || 
 
1394
                     strncmp(args[0], D_usertty + 5, n)) &&
 
1395
                    (strncmp("/dev/tty", D_usertty, 8) ||
 
1396
                     strncmp(args[0], D_usertty + 8, n)))
 
1397
                  continue;
 
1398
                debug1("AT display %s\n", D_usertty);
 
1399
                DoCommand(args + 1, argl + 1);
 
1400
                if (display)
 
1401
                  Msg(0, "command from %s: %s %s", 
 
1402
                      s, args[1], args[2] ? args[2] : "");
 
1403
                display = NULL;
 
1404
                fore = NULL;
 
1405
                flayer = 0;
 
1406
              }
 
1407
            break;
 
1408
          }
 
1409
        case '#':               /* window */
 
1410
          n--;
 
1411
          /* FALLTHROUGH */
 
1412
        default:
 
1413
          {
 
1414
            struct win *nw;
 
1415
            int ch;
 
1416
 
 
1417
            n++; 
 
1418
            ch = args[0][n];
 
1419
            args[0][n] = '\0';
 
1420
            if (!*args[0] || (i = WindowByNumber(args[0])) < 0)
 
1421
              {
 
1422
                args[0][n] = ch;      /* must restore string in case of bind */
 
1423
                /* try looping over titles */
 
1424
                for (fore = windows; fore; fore = nw)
 
1425
                  {
 
1426
                    nw = fore->w_next;
 
1427
                    if (strncmp(args[0], fore->w_title, n))
 
1428
                      continue;
 
1429
                    debug2("AT window %d(%s)\n", fore->w_number, fore->w_title);
 
1430
                    /*
 
1431
                     * consider this a bug or a feature: 
 
1432
                     * while looping through windows, we have fore AND
 
1433
                     * display context. This will confuse users who try to 
 
1434
                     * set up loops inside of loops, but often allows to do 
 
1435
                     * what you mean, even when you adress your context wrong.
 
1436
                     */
 
1437
                    i = 0;
 
1438
                    /* XXX: other displays? */
 
1439
                    if (fore->w_layer.l_cvlist)
 
1440
                      display = fore->w_layer.l_cvlist->c_display;
 
1441
                    flayer = fore->w_savelayer ? fore->w_savelayer : &fore->w_layer;
 
1442
                    DoCommand(args + 1, argl + 1);      /* may destroy our display */
 
1443
                    if (fore && fore->w_layer.l_cvlist)
 
1444
                      {
 
1445
                        display = fore->w_layer.l_cvlist->c_display;
 
1446
                        Msg(0, "command from %s: %s %s", 
 
1447
                            s, args[1], args[2] ? args[2] : "");
 
1448
                      }
 
1449
                  }
 
1450
                display = NULL;
 
1451
                fore = NULL;
 
1452
                if (i < 0)
 
1453
                  Msg(0, "%s: at '%s': no such window.\n", rc_name, args[0]);
 
1454
                break;
 
1455
              }
 
1456
            else if (i < MAXWIN && (fore = wtab[i]))
 
1457
              {
 
1458
                args[0][n] = ch;      /* must restore string in case of bind */
 
1459
                debug2("AT window %d (%s)\n", fore->w_number, fore->w_title);
 
1460
                if (fore->w_layer.l_cvlist)
 
1461
                  display = fore->w_layer.l_cvlist->c_display;
 
1462
                flayer = fore->w_savelayer ? fore->w_savelayer : &fore->w_layer;
 
1463
                DoCommand(args + 1, argl + 1);
 
1464
                if (fore && fore->w_layer.l_cvlist)
 
1465
                  {
 
1466
                    display = fore->w_layer.l_cvlist->c_display;
 
1467
                    Msg(0, "command from %s: %s %s", 
 
1468
                        s, args[1], args[2] ? args[2] : "");
 
1469
                  }
 
1470
                display = NULL;
 
1471
                fore = NULL;
 
1472
              }
 
1473
            else
 
1474
              Msg(0, "%s: at [identifier][%%|*|#] command [args]", rc_name);
 
1475
            break;
 
1476
          }
 
1477
        }
 
1478
      free(s);
 
1479
#ifdef MULTIUSER
 
1480
      EffectiveAclUser = NULL;
 
1481
#endif
 
1482
      break;
 
1483
 
 
1484
#ifdef COPY_PASTE
 
1485
    case RC_READREG:
 
1486
#ifdef ENCODINGS
 
1487
      i = fore ? fore->w_encoding : display ? display->d_encoding : 0;
 
1488
      if (args[0] && args[1] && !strcmp(args[0], "-e"))
 
1489
        {
 
1490
          i = FindEncoding(args[1]);
 
1491
          if (i == -1)
 
1492
            {
 
1493
              Msg(0, "%s: readreg: unknown encoding", rc_name);
 
1494
              break;
 
1495
            }
 
1496
          args += 2;
 
1497
        }
 
1498
#endif
 
1499
      /* 
 
1500
       * Without arguments we prompt for a destination register.
 
1501
       * It will receive the copybuffer contents.
 
1502
       * This is not done by RC_PASTE, as we prompt for source
 
1503
       * (not dest) there.
 
1504
       */
 
1505
      if ((s = *args) == NULL)
 
1506
        {
 
1507
          Input("Copy to register:", 1, INP_RAW, copy_reg_fn, NULL);
 
1508
          break;
 
1509
        }
 
1510
      if (*argl != 1)
 
1511
        {
 
1512
          Msg(0, "%s: copyreg: character, ^x, or (octal) \\032 expected.", rc_name);
 
1513
          break;
 
1514
        }
 
1515
      ch = args[0][0];
 
1516
      /* 
 
1517
       * With two arguments we *really* read register contents from file
 
1518
       */
 
1519
      if (args[1])
 
1520
        {
 
1521
          if (args[2])
 
1522
            {
 
1523
              Msg(0, "%s: readreg: too many arguments", rc_name);
 
1524
              break;
 
1525
            }
 
1526
          if ((s = ReadFile(args[1], &n)))
 
1527
            {
 
1528
              struct plop *pp = plop_tab + (int)(unsigned char)ch;
 
1529
 
 
1530
              if (pp->buf)
 
1531
                free(pp->buf);
 
1532
              pp->buf = s;
 
1533
              pp->len = n;
 
1534
#ifdef ENCODINGS
 
1535
              pp->enc = i;
 
1536
#endif
 
1537
            }
 
1538
        }
 
1539
      else
 
1540
        /*
 
1541
         * with one argument we copy the copybuffer into a specified register
 
1542
         * This could be done with RC_PASTE too, but is here to be consistent
 
1543
         * with the zero argument call.
 
1544
         */
 
1545
        copy_reg_fn(&ch, 0, NULL);
 
1546
      break;
 
1547
#endif
 
1548
    case RC_REGISTER:
 
1549
#ifdef ENCODINGS
 
1550
      i = fore ? fore->w_encoding : display ? display->d_encoding : 0;
 
1551
      if (args[0] && args[1] && !strcmp(args[0], "-e"))
 
1552
        {
 
1553
          i = FindEncoding(args[1]);
 
1554
          if (i == -1)
 
1555
            {
 
1556
              Msg(0, "%s: register: unknown encoding", rc_name);
 
1557
              break;
 
1558
            }
 
1559
          args += 2;
 
1560
          argc -= 2;
 
1561
        }
 
1562
#endif
 
1563
      if (argc != 2)
 
1564
        {
 
1565
          Msg(0, "%s: register: illegal number of arguments.", rc_name);
 
1566
          break;
 
1567
        }
 
1568
      if (*argl != 1)
 
1569
        {
 
1570
          Msg(0, "%s: register: character, ^x, or (octal) \\032 expected.", rc_name);
 
1571
          break;
 
1572
        }
 
1573
      ch = args[0][0];
 
1574
#ifdef COPY_PASTE
 
1575
      if (ch == '.')
 
1576
        {
 
1577
          if (user->u_plop.buf != NULL)
 
1578
            UserFreeCopyBuffer(user);
 
1579
          if (args[1] && args[1][0])
 
1580
            {
 
1581
              user->u_plop.buf = SaveStrn(args[1], argl[1]);
 
1582
              user->u_plop.len = argl[1];
 
1583
#ifdef ENCODINGS
 
1584
              user->u_plop.enc = i;
 
1585
#endif
 
1586
            }
 
1587
        }
 
1588
#endif
 
1589
      else
 
1590
        {
 
1591
          struct plop *plp = plop_tab + (int)(unsigned char)ch;
 
1592
 
 
1593
          if (plp->buf)
 
1594
            free(plp->buf);
 
1595
          plp->buf = SaveStrn(args[1], argl[1]);
 
1596
          plp->len = argl[1];
 
1597
#ifdef ENCODINGS
 
1598
          plp->enc = i;
 
1599
#endif
 
1600
        }
 
1601
      break;
 
1602
    case RC_PROCESS:
 
1603
      if ((s = *args) == NULL)
 
1604
        {
 
1605
          Input("Process register:", 1, INP_RAW, process_fn, NULL);
 
1606
          break;
 
1607
        }
 
1608
      if (*argl != 1)
 
1609
        {
 
1610
          Msg(0, "%s: process: character, ^x, or (octal) \\032 expected.", rc_name);
 
1611
          break;
 
1612
        }
 
1613
      ch = args[0][0];
 
1614
      process_fn(&ch, 0, NULL);
 
1615
      break;
 
1616
    case RC_STUFF:
 
1617
      s = *args;
 
1618
      n = *argl;
 
1619
      if (args[1])
 
1620
        {
 
1621
          if (strcmp(s, "-k"))
 
1622
            {
 
1623
              Msg(0, "%s: stuff: invalid option %s", rc_name, s);
 
1624
              break;
 
1625
            }
 
1626
          s = args[1];
 
1627
          for (i = T_CAPS; i < T_OCAPS; i++)
 
1628
            if (strcmp(term[i].tcname, s) == 0)
 
1629
              break;
 
1630
          if (i == T_OCAPS)
 
1631
            {
 
1632
              Msg(0, "%s: stuff: unknown key '%s'", rc_name, s);
 
1633
              break;
 
1634
            }
 
1635
#ifdef MAPKEYS
 
1636
          if (StuffKey(i - T_CAPS) == 0)
 
1637
            break;
 
1638
#endif
 
1639
          s = display ? D_tcs[i].str : 0;
 
1640
          if (s == 0)
 
1641
            break;
 
1642
          n = strlen(s);
 
1643
        }
 
1644
      while(n)
 
1645
        LayProcess(&s, &n);
 
1646
      break;
 
1647
    case RC_REDISPLAY:
 
1648
      Activate(-1);
 
1649
      break;
 
1650
    case RC_WINDOWS:
 
1651
      ShowWindows(-1);
 
1652
      break;
 
1653
    case RC_VERSION:
 
1654
      Msg(0, "screen %s", version);
 
1655
      break;
 
1656
    case RC_TIME:
 
1657
      if (*args)
 
1658
        {
 
1659
          timestring = SaveStr(*args);
 
1660
          break;
 
1661
        }
 
1662
      Msg(0, "%s", MakeWinMsg(timestring, fore, '%'));
 
1663
      break;
 
1664
    case RC_INFO:
 
1665
      ShowInfo();
 
1666
      break;
 
1667
    case RC_DINFO:
 
1668
      ShowDInfo();
 
1669
      break;
 
1670
    case RC_COMMAND:
 
1671
        {
 
1672
          struct action *ktabp = ktab;
 
1673
          if (argc == 2 && !strcmp(*args, "-c"))
 
1674
            {
 
1675
              if ((ktabp = FindKtab(args[1], 0)) == 0)
 
1676
                {
 
1677
                  Msg(0, "Unknown command class '%s'", args[1]);
 
1678
                  break;
 
1679
                }
 
1680
            }
 
1681
          if (D_ESCseen != ktab || ktabp != ktab)
 
1682
            {
 
1683
              D_ESCseen = ktabp;
 
1684
              break;
 
1685
            }
 
1686
          D_ESCseen = 0;
 
1687
        }
 
1688
      /* FALLTHROUGH */
 
1689
    case RC_OTHER:
 
1690
      if (MoreWindows())
 
1691
        SwitchWindow(display && D_other ? D_other->w_number : NextWindow());
 
1692
      break;
 
1693
    case RC_META:
 
1694
      if (user->u_Esc == -1)
 
1695
        break;
 
1696
      ch = user->u_Esc;
 
1697
      s = &ch;
 
1698
      n = 1;
 
1699
      LayProcess(&s, &n);
 
1700
      break;
 
1701
    case RC_XON:
 
1702
      ch = Ctrl('q');
 
1703
      s = &ch;
 
1704
      n = 1;
 
1705
      LayProcess(&s, &n);
 
1706
      break;
 
1707
    case RC_XOFF:
 
1708
      ch = Ctrl('s');
 
1709
      s = &ch;
 
1710
      n = 1;
 
1711
      LayProcess(&s, &n);
 
1712
      break;
 
1713
    case RC_DEFBREAKTYPE:
 
1714
    case RC_BREAKTYPE:
 
1715
        {
 
1716
          static char *types[] = { "TIOCSBRK", "TCSBRK", "tcsendbreak", NULL };
 
1717
          extern int breaktype;
 
1718
 
 
1719
          if (*args)
 
1720
            {
 
1721
              if (ParseNum(act, &n))
 
1722
                for (n = 0; n < (int)(sizeof(types)/sizeof(*types)); n++)
 
1723
                  {
 
1724
                    for (i = 0; i < 4; i++)
 
1725
                      {
 
1726
                        ch = args[0][i];
 
1727
                        if (ch >= 'a' && ch <= 'z')
 
1728
                          ch -= 'a' - 'A';
 
1729
                        if (ch != types[n][i] && (ch + ('a' - 'A')) != types[n][i])
 
1730
                          break;
 
1731
                      }
 
1732
                    if (i == 4)
 
1733
                      break;
 
1734
                  }
 
1735
              if (n < 0 || n >= (int)(sizeof(types)/sizeof(*types)))
 
1736
                Msg(0, "%s invalid, chose one of %s, %s or %s", *args, types[0], types[1], types[2]);
 
1737
              else
 
1738
                {
 
1739
                  breaktype = n;
 
1740
                  Msg(0, "breaktype set to (%d) %s", n, types[n]);
 
1741
                }
 
1742
            }
 
1743
          else
 
1744
            Msg(0, "breaktype is (%d) %s", breaktype, types[breaktype]);
 
1745
        }
 
1746
      break;
 
1747
    case RC_POW_BREAK:
 
1748
    case RC_BREAK:
 
1749
      n = 0;
 
1750
      if (*args && ParseNum(act, &n))
 
1751
        break;
 
1752
      SendBreak(fore, n, nr == RC_POW_BREAK);
 
1753
      break;
 
1754
#ifdef LOCK
 
1755
    case RC_LOCKSCREEN:
 
1756
      Detach(D_LOCK);
 
1757
      break;
 
1758
#endif
 
1759
    case RC_WIDTH:
 
1760
    case RC_HEIGHT:
 
1761
      {
 
1762
        int w, h;
 
1763
        int what = 0;
 
1764
        
 
1765
        i = 1;
 
1766
        if (*args && !strcmp(*args, "-w"))
 
1767
          what = 1;
 
1768
        else if (*args && !strcmp(*args, "-d"))
 
1769
          what = 2;
 
1770
        if (what)
 
1771
          args++;
 
1772
        if (what == 0 && flayer && !display)
 
1773
          what = 1;
 
1774
        if (what == 1)
 
1775
          {
 
1776
            if (!flayer)
 
1777
              {
 
1778
                Msg(0, "%s: %s: window required", rc_name, comms[nr].name);
 
1779
                break;
 
1780
              }
 
1781
            w = flayer->l_width;
 
1782
            h = flayer->l_height;
 
1783
          }
 
1784
        else
 
1785
          {
 
1786
            if (!display)
 
1787
              {
 
1788
                Msg(0, "%s: %s: display required", rc_name, comms[nr].name);
 
1789
                break;
 
1790
              }
 
1791
            w = D_width;
 
1792
            h = D_height;
 
1793
          }
 
1794
        if (*args && args[0][0] == '-')
 
1795
          {
 
1796
            Msg(0, "%s: %s: unknown option %s", rc_name, comms[nr].name, *args);
 
1797
            break;
 
1798
          }
 
1799
        if (nr == RC_HEIGHT)
 
1800
          {
 
1801
            if (!*args)
 
1802
              {
 
1803
#define H0height 42
 
1804
#define H1height 24
 
1805
                if (h == H0height)
 
1806
                  h = H1height;
 
1807
                else if (h == H1height)
 
1808
                  h = H0height;
 
1809
                else if (h > (H0height + H1height) / 2)
 
1810
                  h = H0height;
 
1811
                else
 
1812
                  h = H1height;
 
1813
              }
 
1814
            else
 
1815
              {
 
1816
                h = atoi(*args);
 
1817
                if (args[1])
 
1818
                  w = atoi(args[1]);
 
1819
              }
 
1820
          }
 
1821
        else
 
1822
          {
 
1823
            if (!*args)
 
1824
              {
 
1825
                if (w == Z0width)
 
1826
                  w = Z1width;
 
1827
                else if (w == Z1width)
 
1828
                  w = Z0width;
 
1829
                else if (w > (Z0width + Z1width) / 2)
 
1830
                  w = Z0width;
 
1831
                else
 
1832
                  w = Z1width;
 
1833
              }
 
1834
            else
 
1835
              {
 
1836
                w = atoi(*args);
 
1837
                if (args[1])
 
1838
                  h = atoi(args[1]);
 
1839
              }
 
1840
          }
 
1841
        if (*args && args[1] && args[2])
 
1842
          {
 
1843
            Msg(0, "%s: %s: too many arguments", rc_name, comms[nr].name);
 
1844
            break;
 
1845
          }
 
1846
        if (w <= 0)
 
1847
          {
 
1848
            Msg(0, "Illegal width");
 
1849
            break;
 
1850
          }
 
1851
        if (h <= 0)
 
1852
          {
 
1853
            Msg(0, "Illegal height");
 
1854
            break;
 
1855
          }
 
1856
        if (what == 1)
 
1857
          {
 
1858
            if (flayer->l_width == w && flayer->l_height == h)
 
1859
              break;
 
1860
            ResizeLayer(flayer, w, h, (struct display *)0);
 
1861
            break;
 
1862
          }
 
1863
        if (D_width == w && D_height == h)
 
1864
          break;
 
1865
        if (what == 2)
 
1866
          {
 
1867
            ChangeScreenSize(w, h, 1);
 
1868
          }
 
1869
        else
 
1870
          {
 
1871
            if (ResizeDisplay(w, h) == 0)
 
1872
              {
 
1873
                Activate(D_fore ? D_fore->w_norefresh : 0);
 
1874
                /* autofit */
 
1875
                ResizeLayer(D_forecv->c_layer, D_forecv->c_xe - D_forecv->c_xs + 1, D_forecv->c_ye - D_forecv->c_ys + 1, 0);
 
1876
                break;
 
1877
              }
 
1878
            if (h == D_height)
 
1879
              Msg(0, "Your termcap does not specify how to change the terminal's width to %d.", w);
 
1880
            else if (w == D_width)
 
1881
              Msg(0, "Your termcap does not specify how to change the terminal's height to %d.", h);
 
1882
            else
 
1883
              Msg(0, "Your termcap does not specify how to change the terminal's resolution to %dx%d.", w, h);
 
1884
          }
 
1885
      }
 
1886
      break;
 
1887
    case RC_TITLE:
 
1888
      if (*args == 0)
 
1889
        InputAKA();
 
1890
      else
 
1891
        ChangeAKA(fore, *args, strlen(*args));
 
1892
      break;
 
1893
    case RC_COLON:
 
1894
      Input(":", 100, INP_COOKED, Colonfin, NULL);
 
1895
      if (*args && **args)
 
1896
        {
 
1897
          s = *args;
 
1898
          n = strlen(s);
 
1899
          LayProcess(&s, &n);
 
1900
        }
 
1901
      break;
 
1902
    case RC_LASTMSG:
 
1903
      if (D_status_lastmsg)
 
1904
        Msg(0, "%s", D_status_lastmsg);
 
1905
      break;
 
1906
    case RC_SCREEN:
 
1907
      DoScreen("key", args);
 
1908
      break;
 
1909
    case RC_WRAP:
 
1910
      if (ParseSwitch(act, &fore->w_wrap) == 0 && msgok)
 
1911
        Msg(0, "%cwrap", fore->w_wrap ? '+' : '-');
 
1912
      break;
 
1913
    case RC_FLOW:
 
1914
      if (*args)
 
1915
        {
 
1916
          if (args[0][0] == 'a')
 
1917
            {
 
1918
              fore->w_flow = (fore->w_flow & FLOW_AUTO) ? FLOW_AUTOFLAG |FLOW_AUTO|FLOW_NOW : FLOW_AUTOFLAG;
 
1919
            }
 
1920
          else
 
1921
            {
 
1922
              if (ParseOnOff(act, &n))
 
1923
                break;
 
1924
              fore->w_flow = (fore->w_flow & FLOW_AUTO) | n;
 
1925
            }
 
1926
        }
 
1927
      else
 
1928
        {
 
1929
          if (fore->w_flow & FLOW_AUTOFLAG)
 
1930
            fore->w_flow = (fore->w_flow & FLOW_AUTO) | FLOW_NOW;
 
1931
          else if (fore->w_flow & FLOW_NOW)
 
1932
            fore->w_flow &= ~FLOW_NOW;
 
1933
          else
 
1934
            fore->w_flow = fore->w_flow ? FLOW_AUTOFLAG|FLOW_AUTO|FLOW_NOW : FLOW_AUTOFLAG;
 
1935
        }
 
1936
      SetFlow(fore->w_flow & FLOW_NOW);
 
1937
      if (msgok)
 
1938
        Msg(0, "%cflow%s", (fore->w_flow & FLOW_NOW) ? '+' : '-',
 
1939
            (fore->w_flow & FLOW_AUTOFLAG) ? "(auto)" : "");
 
1940
      break;
 
1941
#ifdef MULTIUSER
 
1942
    case RC_DEFWRITELOCK:
 
1943
      if (args[0][0] == 'a')
 
1944
        nwin_default.wlock = WLOCK_AUTO;
 
1945
      else
 
1946
        {
 
1947
          if (ParseOnOff(act, &n))
 
1948
            break;
 
1949
          nwin_default.wlock = n ? WLOCK_ON : WLOCK_OFF;
 
1950
        }
 
1951
      break;
 
1952
    case RC_WRITELOCK:
 
1953
      if (*args)
 
1954
        {
 
1955
          if (args[0][0] == 'a')
 
1956
            {
 
1957
              fore->w_wlock = WLOCK_AUTO;
 
1958
            }
 
1959
          else
 
1960
            {
 
1961
              if (ParseOnOff(act, &n))
 
1962
                break;
 
1963
              fore->w_wlock = n ? WLOCK_ON : WLOCK_OFF;
 
1964
            }
 
1965
          /* 
 
1966
           * user may have permission to change the writelock setting, 
 
1967
           * but he may never aquire the lock himself without write permission
 
1968
           */
 
1969
          if (!AclCheckPermWin(D_user, ACL_WRITE, fore))
 
1970
            fore->w_wlockuser = D_user;
 
1971
        }
 
1972
      Msg(0, "writelock %s", (fore->w_wlock == WLOCK_AUTO) ? "auto" :
 
1973
          ((fore->w_wlock == WLOCK_OFF) ? "off" : "on"));
 
1974
      break;
 
1975
#endif
 
1976
    case RC_CLEAR:
 
1977
      ResetAnsiState(fore);
 
1978
      WriteString(fore, "\033[H\033[J", 6);
 
1979
      break;
 
1980
    case RC_RESET:
 
1981
      ResetAnsiState(fore);
 
1982
#ifdef ZMODEM
 
1983
      if (fore->w_zdisplay)
 
1984
        zmodem_abort(fore, fore->w_zdisplay);
 
1985
#endif
 
1986
      WriteString(fore, "\033c", 2);
 
1987
      break;
 
1988
    case RC_MONITOR:
 
1989
      n = fore->w_monitor != MON_OFF;
 
1990
      if (ParseSwitch(act, &n))
 
1991
        break;
 
1992
      if (n)
 
1993
        {
 
1994
#ifdef MULTIUSER
 
1995
          if (display)  /* we tell only this user */
 
1996
            ACLBYTE(fore->w_mon_notify, D_user->u_id) |= ACLBIT(D_user->u_id);
 
1997
          else
 
1998
            for (i = 0; i < maxusercount; i++)
 
1999
              ACLBYTE(fore->w_mon_notify, i) |= ACLBIT(i);
 
2000
#endif
 
2001
          if (fore->w_monitor == MON_OFF)
 
2002
            fore->w_monitor = MON_ON;
 
2003
          Msg(0, "Window %d (%s) is now being monitored for all activity.", fore->w_number, fore->w_title);
 
2004
        }
 
2005
      else
 
2006
        {
 
2007
#ifdef MULTIUSER
 
2008
          if (display) /* we remove only this user */
 
2009
            ACLBYTE(fore->w_mon_notify, D_user->u_id) 
 
2010
              &= ~ACLBIT(D_user->u_id);
 
2011
          else
 
2012
            for (i = 0; i < maxusercount; i++)
 
2013
              ACLBYTE(fore->w_mon_notify, i) &= ~ACLBIT(i);
 
2014
          for (i = maxusercount - 1; i >= 0; i--)
 
2015
            if (ACLBYTE(fore->w_mon_notify, i))
 
2016
              break;
 
2017
          if (i < 0)
 
2018
#endif
 
2019
            fore->w_monitor = MON_OFF;
 
2020
          Msg(0, "Window %d (%s) is no longer being monitored for activity.", fore->w_number, fore->w_title);
 
2021
        }
 
2022
      break;
 
2023
#ifdef MULTI
 
2024
    case RC_DISPLAYS:
 
2025
      display_displays();
 
2026
      break;
 
2027
#endif
 
2028
    case RC_WINDOWLIST:
 
2029
      if (!*args)
 
2030
        display_wlist(0, WLIST_NUM);
 
2031
      else if (!strcmp(*args, "-m") && !args[1])
 
2032
        display_wlist(0, WLIST_MRU);
 
2033
      else if (!strcmp(*args, "-b") && !args[1])
 
2034
        display_wlist(1, WLIST_NUM);
 
2035
      else if (!strcmp(*args, "-b") && !strcmp(args[1], "-m") && !args[2])
 
2036
        display_wlist(1, WLIST_MRU);
 
2037
      else if (!strcmp(*args, "-m") && !strcmp(args[1], "-b") && !args[2])
 
2038
        display_wlist(1, WLIST_MRU);
 
2039
      else if (!strcmp(*args, "string"))
 
2040
        {
 
2041
          if (args[1])
 
2042
            {
 
2043
              if (wliststr)
 
2044
                free(wliststr);
 
2045
              wliststr = SaveStr(args[1]);
 
2046
            }
 
2047
          if (msgok)
 
2048
            Msg(0, "windowlist string is '%s'", wliststr);
 
2049
        }
 
2050
      else if (!strcmp(*args, "title"))
 
2051
        {
 
2052
          if (args[1])
 
2053
            {
 
2054
              if (wlisttit)
 
2055
                free(wlisttit);
 
2056
              wlisttit = SaveStr(args[1]);
 
2057
            }
 
2058
          if (msgok)
 
2059
            Msg(0, "windowlist title is '%s'", wlisttit);
 
2060
        }
 
2061
      else
 
2062
        Msg(0, "usage: windowlist [-b] [string [string] | title [title]]");
 
2063
      break;
 
2064
    case RC_HELP:
 
2065
      if (argc == 2 && !strcmp(*args, "-c"))
 
2066
        {
 
2067
          struct action *ktabp;
 
2068
          if ((ktabp = FindKtab(args[1], 0)) == 0)
 
2069
            {
 
2070
              Msg(0, "Unknown command class '%s'", args[1]);
 
2071
              break;
 
2072
            }
 
2073
          display_help(args[1], ktabp);
 
2074
        }
 
2075
      else
 
2076
        display_help((char *)0, ktab);
 
2077
      break;
 
2078
    case RC_LICENSE:
 
2079
      display_copyright();
 
2080
      break;
 
2081
#ifdef COPY_PASTE
 
2082
    case RC_COPY:
 
2083
      if (flayer->l_layfn != &WinLf)
 
2084
        {
 
2085
          Msg(0, "Must be on a window layer");
 
2086
          break;
 
2087
        }
 
2088
      MarkRoutine();
 
2089
      break;
 
2090
    case RC_HISTORY:
 
2091
      {
 
2092
        static char *pasteargs[] = {".", 0};
 
2093
        static int pasteargl[] = {1};
 
2094
 
 
2095
        if (flayer->l_layfn != &WinLf)
 
2096
          {
 
2097
            Msg(0, "Must be on a window layer");
 
2098
            break;
 
2099
          }
 
2100
        if (GetHistory() == 0)
 
2101
          break;
 
2102
        if (user->u_plop.buf == NULL)
 
2103
          break;
 
2104
        args = pasteargs;
 
2105
        argl = pasteargl;
 
2106
      }
 
2107
      /*FALLTHROUGH*/
 
2108
    case RC_PASTE:
 
2109
      {
 
2110
        char *ss, *dbuf, dch;
 
2111
        int l = 0;
 
2112
# ifdef ENCODINGS
 
2113
        int enc = -1;
 
2114
# endif
 
2115
 
 
2116
        /*
 
2117
         * without args we prompt for one(!) register to be pasted in the window
 
2118
         */
 
2119
        if ((s = *args) == NULL)
 
2120
          {
 
2121
            Input("Paste from register:", 1, INP_RAW, ins_reg_fn, NULL);
 
2122
            break;
 
2123
          }
 
2124
        if (args[1] == 0 && !fore)      /* no window? */
 
2125
          break;
 
2126
        /*      
 
2127
         * with two arguments we paste into a destination register
 
2128
         * (no window needed here).
 
2129
         */
 
2130
        if (args[1] && argl[1] != 1)
 
2131
          {
 
2132
            Msg(0, "%s: paste destination: character, ^x, or (octal) \\032 expected.",
 
2133
                rc_name);
 
2134
            break;
 
2135
          }
 
2136
# ifdef ENCODINGS
 
2137
        else if (fore)
 
2138
          enc = fore->w_encoding;
 
2139
# endif
 
2140
 
 
2141
        /*
 
2142
         * measure length of needed buffer 
 
2143
         */
 
2144
        for (ss = s = *args; (ch = *ss); ss++)
 
2145
          {
 
2146
            if (ch == '.')
 
2147
              {
 
2148
# ifdef ENCODINGS
 
2149
                if (enc == -1)
 
2150
                  enc = user->u_plop.enc;
 
2151
                if (enc != user->u_plop.enc)
 
2152
                  l += RecodeBuf((unsigned char *)user->u_plop.buf, user->u_plop.len, user->u_plop.enc, enc, (unsigned char *)0);
 
2153
                else
 
2154
# endif
 
2155
                  l += user->u_plop.len;
 
2156
              }
 
2157
            else
 
2158
              {
 
2159
# ifdef ENCODINGS
 
2160
                if (enc == -1)
 
2161
                  enc = plop_tab[(int)(unsigned char)ch].enc;
 
2162
                if (enc != plop_tab[(int)(unsigned char)ch].enc)
 
2163
                  l += RecodeBuf((unsigned char *)plop_tab[(int)(unsigned char)ch].buf, plop_tab[(int)(unsigned char)ch].len, plop_tab[(int)(unsigned char)ch].enc, enc, (unsigned char *)0);
 
2164
                else
 
2165
# endif
 
2166
                  l += plop_tab[(int)(unsigned char)ch].len;
 
2167
              }
 
2168
          }
 
2169
        if (l == 0)
 
2170
          {
 
2171
            Msg(0, "empty buffer");
 
2172
            break;
 
2173
          }
 
2174
        /*
 
2175
         * shortcut: 
 
2176
         * if there is only one source and the destination is a window, then
 
2177
         * pass a pointer rather than duplicating the buffer.
 
2178
         */
 
2179
        if (s[1] == 0 && args[1] == 0)
 
2180
# ifdef ENCODINGS
 
2181
          if (enc == (*s == '.' ? user->u_plop.enc : plop_tab[(int)(unsigned char)*s].enc))
 
2182
# endif
 
2183
            {
 
2184
              MakePaster(&fore->w_paster, *s == '.' ? user->u_plop.buf : plop_tab[(int)(unsigned char)*s].buf, l, 0);
 
2185
              break;
 
2186
            }
 
2187
        /*
 
2188
         * if no shortcut, we construct a buffer
 
2189
         */
 
2190
        if ((dbuf = (char *)malloc(l)) == 0)
 
2191
          {
 
2192
            Msg(0, strnomem);
 
2193
            break;
 
2194
          }
 
2195
        l = 0;
 
2196
        /*
 
2197
         * concatenate all sources into our own buffer, copy buffer is
 
2198
         * special and is skipped if no display exists.
 
2199
         */
 
2200
        for (ss = s; (ch = *ss); ss++)
 
2201
          {
 
2202
            struct plop *pp = (ch == '.' ? &user->u_plop : &plop_tab[(int)(unsigned char)ch]);
 
2203
#ifdef ENCODINGS
 
2204
            if (pp->enc != enc)
 
2205
              {
 
2206
                l += RecodeBuf((unsigned char *)pp->buf, pp->len, pp->enc, enc, (unsigned char *)dbuf + l);
 
2207
                continue;
 
2208
              }
 
2209
#endif
 
2210
            bcopy(pp->buf, dbuf + l, pp->len);
 
2211
            l += pp->len;
 
2212
          }
 
2213
        /*
 
2214
         * when called with one argument we paste our buffer into the window 
 
2215
         */
 
2216
        if (args[1] == 0)
 
2217
          {
 
2218
            MakePaster(&fore->w_paster, dbuf, l, 1);
 
2219
          }
 
2220
        else
 
2221
          {
 
2222
            /*
 
2223
             * we have two arguments, the second is already in dch.
 
2224
             * use this as destination rather than the window.
 
2225
             */
 
2226
            dch = args[1][0];
 
2227
            if (dch == '.')
 
2228
              {
 
2229
                if (user->u_plop.buf != NULL)
 
2230
                  UserFreeCopyBuffer(user);
 
2231
                user->u_plop.buf = dbuf;
 
2232
                user->u_plop.len = l;
 
2233
#ifdef ENCODINGS
 
2234
                user->u_plop.enc = enc;
 
2235
#endif
 
2236
              }
 
2237
            else
 
2238
              {
 
2239
                struct plop *pp = plop_tab + (int)(unsigned char)dch;
 
2240
                if (pp->buf)
 
2241
                  free(pp->buf);
 
2242
                pp->buf = dbuf;
 
2243
                pp->len = l;
 
2244
#ifdef ENCODINGS
 
2245
                pp->enc = enc;
 
2246
#endif
 
2247
              }
 
2248
          }
 
2249
        break;
 
2250
      }
 
2251
    case RC_WRITEBUF:
 
2252
      if (!user->u_plop.buf)
 
2253
        {
 
2254
          Msg(0, "empty buffer");
 
2255
          break;
 
2256
        }
 
2257
#ifdef ENCODINGS
 
2258
        {
 
2259
          struct plop oldplop;
 
2260
 
 
2261
          oldplop = user->u_plop;
 
2262
          if (args[0] && args[1] && !strcmp(args[0], "-e"))
 
2263
            {
 
2264
              int enc, l;
 
2265
              char *newbuf;
 
2266
 
 
2267
              enc = FindEncoding(args[1]);
 
2268
              if (enc == -1)
 
2269
                {
 
2270
                  Msg(0, "%s: writebuf: unknown encoding", rc_name);
 
2271
                  break;
 
2272
                }
 
2273
              if (enc != oldplop.enc)
 
2274
                {
 
2275
                  l = RecodeBuf((unsigned char *)oldplop.buf, oldplop.len, oldplop.enc, enc, (unsigned char *)0);
 
2276
                  newbuf = malloc(l + 1);
 
2277
                  if (!newbuf)
 
2278
                    {
 
2279
                      Msg(0, strnomem);
 
2280
                      break;
 
2281
                    }
 
2282
                  user->u_plop.len = RecodeBuf((unsigned char *)oldplop.buf, oldplop.len, oldplop.enc, enc, (unsigned char *)newbuf);
 
2283
                  user->u_plop.buf = newbuf;
 
2284
                  user->u_plop.enc = enc;
 
2285
                }
 
2286
              args += 2;
 
2287
            }
 
2288
#endif
 
2289
          if (args[0] && args[1])
 
2290
            Msg(0, "%s: writebuf: too many arguments", rc_name);
 
2291
          else
 
2292
            WriteFile(user, args[0], DUMP_EXCHANGE);
 
2293
#ifdef ENCODINGS
 
2294
          if (user->u_plop.buf != oldplop.buf)
 
2295
            free(user->u_plop.buf);
 
2296
          user->u_plop = oldplop;
 
2297
        }
 
2298
#endif
 
2299
      break;
 
2300
    case RC_READBUF:
 
2301
#ifdef ENCODINGS
 
2302
      i = fore ? fore->w_encoding : display ? display->d_encoding : 0;
 
2303
      if (args[0] && args[1] && !strcmp(args[0], "-e"))
 
2304
        {
 
2305
          i = FindEncoding(args[1]);
 
2306
          if (i == -1)
 
2307
            {
 
2308
              Msg(0, "%s: readbuf: unknown encoding", rc_name);
 
2309
              break;
 
2310
            }
 
2311
          args += 2;
 
2312
        }
 
2313
#endif
 
2314
      if (args[0] && args[1])
 
2315
        {
 
2316
          Msg(0, "%s: readbuf: too many arguments", rc_name);
 
2317
          break;
 
2318
        }
 
2319
      if ((s = ReadFile(args[0] ? args[0] : BufferFile, &n)))
 
2320
        {
 
2321
          if (user->u_plop.buf)
 
2322
            UserFreeCopyBuffer(user);
 
2323
          user->u_plop.len = n;
 
2324
          user->u_plop.buf = s;
 
2325
#ifdef ENCODINGS
 
2326
          user->u_plop.enc = i;
 
2327
#endif
 
2328
        }
 
2329
      break;
 
2330
    case RC_REMOVEBUF:
 
2331
      KillBuffers();
 
2332
      break;
 
2333
    case RC_IGNORECASE:
 
2334
      (void)ParseSwitch(act, &search_ic);
 
2335
      if (msgok)
 
2336
        Msg(0, "Will %signore case in searches", search_ic ? "" : "not ");
 
2337
      break;
 
2338
#endif                          /* COPY_PASTE */
 
2339
    case RC_ESCAPE:
 
2340
      if (*argl == 0)
 
2341
        SetEscape(user, -1, -1);
 
2342
      else if (*argl == 2)
 
2343
        SetEscape(user, (int)(unsigned char)args[0][0], (int)(unsigned char)args[0][1]);
 
2344
      else
 
2345
        {
 
2346
          Msg(0, "%s: two characters required after escape.", rc_name);
 
2347
          break;
 
2348
        }
 
2349
      /* Change defescape if master user. This is because we only
 
2350
       * have one ktab.
 
2351
       */
 
2352
      if (display && user != users)
 
2353
        break;
 
2354
      /* FALLTHROUGH */
 
2355
    case RC_DEFESCAPE:
 
2356
      if (*argl == 0)
 
2357
        SetEscape(NULL, -1, -1);
 
2358
      else if (*argl == 2)
 
2359
        SetEscape(NULL, (int)(unsigned char)args[0][0], (int)(unsigned char)args[0][1]);
 
2360
      else
 
2361
        {
 
2362
          Msg(0, "%s: two characters required after defescape.", rc_name);
 
2363
          break;
 
2364
        }
 
2365
#ifdef MAPKEYS
 
2366
      CheckEscape();
 
2367
#endif
 
2368
      break;
 
2369
    case RC_CHDIR:
 
2370
      s = *args ? *args : home;
 
2371
      if (chdir(s) == -1)
 
2372
        Msg(errno, "%s", s);
 
2373
      break;
 
2374
    case RC_SHELL:
 
2375
    case RC_DEFSHELL:
 
2376
      if (ParseSaveStr(act, &ShellProg) == 0)
 
2377
        ShellArgs[0] = ShellProg;
 
2378
      break;
 
2379
    case RC_HARDCOPYDIR:
 
2380
      if (*args)
 
2381
        (void)ParseSaveStr(act, &hardcopydir);
 
2382
      if (msgok)
 
2383
        Msg(0, "hardcopydir is %s\n", hardcopydir && *hardcopydir ? hardcopydir : "<cwd>");
 
2384
      break;
 
2385
    case RC_LOGFILE:
 
2386
      if (*args)
 
2387
        {
 
2388
          if (args[1] && !(strcmp(*args, "flush")))
 
2389
            {
 
2390
              log_flush = atoi(args[1]);
 
2391
              if (msgok)
 
2392
                Msg(0, "log flush timeout set to %ds\n", log_flush);
 
2393
              break;
 
2394
            }
 
2395
          if (ParseSaveStr(act, &screenlogfile) || !msgok)
 
2396
            break;
 
2397
        }
 
2398
      Msg(0, "logfile is '%s'", screenlogfile);
 
2399
      break;
 
2400
    case RC_LOGTSTAMP:
 
2401
      if (!*args || !strcmp(*args, "on") || !strcmp(*args, "off"))
 
2402
        {
 
2403
          if (ParseSwitch(act, &logtstamp_on) == 0 && msgok)
 
2404
            Msg(0, "timestamps turned %s", logtstamp_on ? "on" : "off");
 
2405
        }
 
2406
      else if (!strcmp(*args, "string"))
 
2407
        {
 
2408
          if (args[1])
 
2409
            {
 
2410
              if (logtstamp_string)
 
2411
                free(logtstamp_string);
 
2412
              logtstamp_string = SaveStr(args[1]);
 
2413
            }
 
2414
          if (msgok)
 
2415
            Msg(0, "logfile timestamp is '%s'", logtstamp_string);
 
2416
        }
 
2417
      else if (!strcmp(*args, "after"))
 
2418
        {
 
2419
          if (args[1])
 
2420
            {
 
2421
              logtstamp_after = atoi(args[1]);
 
2422
              if (!msgok)
 
2423
                break;
 
2424
            }
 
2425
          Msg(0, "timestamp printed after %ds\n", logtstamp_after);
 
2426
        }
 
2427
      else
 
2428
        Msg(0, "usage: logtstamp [after [n]|string [str]|on|off]");
 
2429
      break;
 
2430
    case RC_SHELLTITLE:
 
2431
      (void)ParseSaveStr(act, &nwin_default.aka);
 
2432
      break;
 
2433
    case RC_TERMCAP:
 
2434
    case RC_TERMCAPINFO:
 
2435
    case RC_TERMINFO:
 
2436
      if (!rc_name || !*rc_name)
 
2437
        Msg(0, "Sorry, too late now. Place that in your .screenrc file.");
 
2438
      break;
 
2439
    case RC_SLEEP:
 
2440
      break;                    /* Already handled */
 
2441
    case RC_TERM:
 
2442
      s = NULL;
 
2443
      if (ParseSaveStr(act, &s))
 
2444
        break;
 
2445
      if (strlen(s) >= 20)
 
2446
        {
 
2447
          Msg(0, "%s: term: argument too long ( < 20)", rc_name);
 
2448
          free(s);
 
2449
          break;
 
2450
        }
 
2451
      strcpy(screenterm, s);
 
2452
      free(s);
 
2453
      debug1("screenterm set to %s\n", screenterm);
 
2454
      MakeTermcap((display == 0));
 
2455
      debug("new termcap made\n");
 
2456
      break;
 
2457
    case RC_ECHO:
 
2458
      if (!msgok && (!rc_name || strcmp(rc_name, "-X")))
 
2459
        break;
 
2460
      /*
 
2461
       * user typed ^A:echo... well, echo isn't FinishRc's job,
 
2462
       * but as he wanted to test us, we show good will
 
2463
       */
 
2464
      if (argc > 1 && !strcmp(*args, "-n"))
 
2465
        {
 
2466
          args++;
 
2467
          argc--;
 
2468
        }
 
2469
      s = *args;
 
2470
      if (argc > 1 && !strcmp(*args, "-p"))
 
2471
        {
 
2472
          args++;
 
2473
          argc--;
 
2474
          s = *args;
 
2475
          if (s)
 
2476
            s = MakeWinMsg(s, fore, '%');
 
2477
        }
 
2478
      if (s)
 
2479
        Msg(0, "%s", s);
 
2480
      else
 
2481
        Msg(0, "%s: 'echo [-n] [-p] \"string\"' expected.", rc_name);
 
2482
      break;
 
2483
    case RC_BELL:
 
2484
    case RC_BELL_MSG:
 
2485
      if (*args == 0)
 
2486
        {
 
2487
          char buf[256];
 
2488
          AddXChars(buf, sizeof(buf), BellString);
 
2489
          Msg(0, "bell_msg is '%s'", buf);
 
2490
          break;
 
2491
        }
 
2492
      (void)ParseSaveStr(act, &BellString);
 
2493
      break;
 
2494
#ifdef COPY_PASTE
 
2495
    case RC_BUFFERFILE:
 
2496
      if (*args == 0)
 
2497
        BufferFile = SaveStr(DEFAULT_BUFFERFILE);
 
2498
      else if (ParseSaveStr(act, &BufferFile))
 
2499
        break;
 
2500
      if (msgok)
 
2501
        Msg(0, "Bufferfile is now '%s'", BufferFile);
 
2502
      break;
 
2503
#endif
 
2504
    case RC_ACTIVITY:
 
2505
      (void)ParseSaveStr(act, &ActivityString);
 
2506
      break;
 
2507
#if defined(DETACH) && defined(POW_DETACH)
 
2508
    case RC_POW_DETACH_MSG:
 
2509
      if (*args == 0)
 
2510
        {
 
2511
          char buf[256];
 
2512
          AddXChars(buf, sizeof(buf), PowDetachString);
 
2513
          Msg(0, "pow_detach_msg is '%s'", buf);
 
2514
          break;
 
2515
        }
 
2516
      (void)ParseSaveStr(act, &PowDetachString);
 
2517
      break;
 
2518
#endif
 
2519
#if defined(UTMPOK) && defined(LOGOUTOK)
 
2520
    case RC_LOGIN:
 
2521
      n = fore->w_slot != (slot_t)-1;
 
2522
      if (*args && !strcmp(*args, "always"))
 
2523
        {
 
2524
          fore->w_lflag = 3;
 
2525
          if (!displays && n)
 
2526
            SlotToggle(n);
 
2527
          break;
 
2528
        }
 
2529
      if (*args && !strcmp(*args, "attached"))
 
2530
        {
 
2531
          fore->w_lflag = 1;
 
2532
          if (!displays && n)
 
2533
            SlotToggle(0);
 
2534
          break;
 
2535
        }
 
2536
      if (ParseSwitch(act, &n) == 0)
 
2537
        SlotToggle(n);
 
2538
      break;
 
2539
    case RC_DEFLOGIN:
 
2540
      if (!strcmp(*args, "always"))
 
2541
        nwin_default.lflag |= 2;
 
2542
      else if (!strcmp(*args, "attached"))
 
2543
        nwin_default.lflag &= ~2;
 
2544
      else
 
2545
        (void)ParseOnOff(act, &nwin_default.lflag);
 
2546
      break;
 
2547
#endif
 
2548
    case RC_DEFFLOW:
 
2549
      if (args[0] && args[1] && args[1][0] == 'i')
 
2550
        {
 
2551
          iflag = 1;
 
2552
          for (display = displays; display; display = display->d_next)
 
2553
            {
 
2554
              if (!D_flow)
 
2555
                continue;
 
2556
#if defined(TERMIO) || defined(POSIX)
 
2557
              D_NewMode.tio.c_cc[VINTR] = D_OldMode.tio.c_cc[VINTR];
 
2558
              D_NewMode.tio.c_lflag |= ISIG;
 
2559
#else /* TERMIO || POSIX */
 
2560
              D_NewMode.m_tchars.t_intrc = D_OldMode.m_tchars.t_intrc;
 
2561
#endif /* TERMIO || POSIX */
 
2562
              SetTTY(D_userfd, &D_NewMode);
 
2563
            }
 
2564
        }
 
2565
      if (args[0] && args[0][0] == 'a')
 
2566
        nwin_default.flowflag = FLOW_AUTOFLAG;
 
2567
      else
 
2568
        (void)ParseOnOff(act, &nwin_default.flowflag);
 
2569
      break;
 
2570
    case RC_DEFWRAP:
 
2571
      (void)ParseOnOff(act, &nwin_default.wrap);
 
2572
      break;
 
2573
    case RC_DEFC1:
 
2574
      (void)ParseOnOff(act, &nwin_default.c1);
 
2575
      break;
 
2576
#ifdef COLOR
 
2577
    case RC_DEFBCE:
 
2578
      (void)ParseOnOff(act, &nwin_default.bce);
 
2579
      break;
 
2580
#endif
 
2581
    case RC_DEFGR:
 
2582
      (void)ParseOnOff(act, &nwin_default.gr);
 
2583
      break;
 
2584
    case RC_DEFMONITOR:
 
2585
      if (ParseOnOff(act, &n) == 0)
 
2586
        nwin_default.monitor = (n == 0) ? MON_OFF : MON_ON;
 
2587
      break;
 
2588
    case RC_DEFSILENCE:
 
2589
      if (ParseOnOff(act, &n) == 0)
 
2590
        nwin_default.silence = (n == 0) ? SILENCE_OFF : SILENCE_ON;
 
2591
      break;
 
2592
    case RC_VERBOSE:
 
2593
      if (!*args)
 
2594
        Msg(0, "W%s echo command when creating windows.", 
 
2595
          VerboseCreate ? "ill" : "on't");
 
2596
      else if (ParseOnOff(act, &n) == 0)
 
2597
        VerboseCreate = n;
 
2598
      break;
 
2599
    case RC_HARDSTATUS:
 
2600
      if (display)
 
2601
        {
 
2602
          Msg(0, "%s", "");     /* wait till mintime (keep gcc quiet) */
 
2603
          RemoveStatus();
 
2604
        }
 
2605
      if (args[0] && strcmp(args[0], "on") && strcmp(args[0], "off"))
 
2606
        {
 
2607
          struct display *olddisplay = display;
 
2608
          int old_use, new_use = -1;
 
2609
 
 
2610
          s = args[0];
 
2611
          if (!strncmp(s, "always", 6))
 
2612
            s += 6;
 
2613
          if (!strcmp(s, "lastline"))
 
2614
            new_use = HSTATUS_LASTLINE;
 
2615
          else if (!strcmp(s, "ignore"))
 
2616
            new_use = HSTATUS_IGNORE;
 
2617
          else if (!strcmp(s, "message"))
 
2618
            new_use = HSTATUS_MESSAGE;
 
2619
          else if (!strcmp(args[0], "string"))
 
2620
            {
 
2621
              if (!args[1])
 
2622
                {
 
2623
                  char buf[256];
 
2624
                  AddXChars(buf, sizeof(buf), hstatusstring);
 
2625
                  Msg(0, "hardstatus string is '%s'", buf);
 
2626
                  break;
 
2627
                }
 
2628
            }
 
2629
          else
 
2630
            {
 
2631
              Msg(0, "%s: usage: hardstatus [always]lastline|ignore|message|string [string]", rc_name);
 
2632
              break;
 
2633
            }
 
2634
          if (new_use != -1)
 
2635
            {
 
2636
              hardstatusemu = new_use | (s == args[0] ? 0 : HSTATUS_ALWAYS);
 
2637
              for (display = displays; display; display = display->d_next)
 
2638
                {
 
2639
                  RemoveStatus();
 
2640
                  new_use = hardstatusemu & ~HSTATUS_ALWAYS;
 
2641
                  if (D_HS && s == args[0])
 
2642
                    new_use = HSTATUS_HS;
 
2643
                  ShowHStatus((char *)0);
 
2644
                  old_use = D_has_hstatus;
 
2645
                  D_has_hstatus = new_use;
 
2646
                  if ((new_use == HSTATUS_LASTLINE && old_use != HSTATUS_LASTLINE) || (new_use != HSTATUS_LASTLINE && old_use == HSTATUS_LASTLINE))
 
2647
                    ChangeScreenSize(D_width, D_height, 1);
 
2648
                  RefreshHStatus();
 
2649
                }
 
2650
            }
 
2651
          if (args[1])
 
2652
            {
 
2653
              if (hstatusstring)
 
2654
                free(hstatusstring);
 
2655
              hstatusstring = SaveStr(args[1]);
 
2656
              for (display = displays; display; display = display->d_next)
 
2657
                RefreshHStatus();
 
2658
            }
 
2659
          display = olddisplay;
 
2660
          break;
 
2661
        }
 
2662
      (void)ParseSwitch(act, &use_hardstatus);
 
2663
      if (msgok)
 
2664
        Msg(0, "messages displayed on %s", use_hardstatus ? "hardstatus line" : "window");
 
2665
      break;
 
2666
    case RC_CAPTION:
 
2667
      if (strcmp(args[0], "always") == 0 || strcmp(args[0], "splitonly") == 0)
 
2668
        {
 
2669
          struct display *olddisplay = display;
 
2670
 
 
2671
          captionalways = args[0][0] == 'a';
 
2672
          for (display = displays; display; display = display->d_next)
 
2673
            ChangeScreenSize(D_width, D_height, 1);
 
2674
          display = olddisplay;
 
2675
        }
 
2676
      else if (strcmp(args[0], "string") == 0)
 
2677
        {
 
2678
          if (!args[1])
 
2679
            {
 
2680
              char buf[256];
 
2681
              AddXChars(buf, sizeof(buf), captionstring);
 
2682
              Msg(0, "caption string is '%s'", buf);
 
2683
              break;
 
2684
            }
 
2685
        }
 
2686
      else
 
2687
        {
 
2688
          Msg(0, "%s: usage: caption always|splitonly|string <string>", rc_name);
 
2689
          break;
 
2690
        }
 
2691
      if (!args[1])
 
2692
        break;
 
2693
      if (captionstring)
 
2694
        free(captionstring);
 
2695
      captionstring = SaveStr(args[1]);
 
2696
      RedisplayDisplays(0);
 
2697
      break;
 
2698
    case RC_CONSOLE:
 
2699
      n = (console_window != 0);
 
2700
      if (ParseSwitch(act, &n))
 
2701
        break;
 
2702
      if (TtyGrabConsole(fore->w_ptyfd, n, rc_name))
 
2703
        break;
 
2704
      if (n == 0)
 
2705
          Msg(0, "%s: releasing console %s", rc_name, HostName);
 
2706
      else if (console_window)
 
2707
          Msg(0, "%s: stealing console %s from window %d (%s)", rc_name, 
 
2708
              HostName, console_window->w_number, console_window->w_title);
 
2709
      else
 
2710
          Msg(0, "%s: grabbing console %s", rc_name, HostName);
 
2711
      console_window = n ? fore : 0;
 
2712
      break;
 
2713
    case RC_ALLPARTIAL:
 
2714
      if (ParseOnOff(act, &all_norefresh))
 
2715
        break;
 
2716
      if (!all_norefresh && fore)
 
2717
        Activate(-1);
 
2718
      if (msgok)
 
2719
        Msg(0, all_norefresh ? "No refresh on window change!\n" :
 
2720
                               "Window specific refresh\n");
 
2721
      break;
 
2722
    case RC_PARTIAL:
 
2723
      (void)ParseSwitch(act, &n);
 
2724
      fore->w_norefresh = n;
 
2725
      break;
 
2726
    case RC_VBELL:
 
2727
      if (ParseSwitch(act, &visual_bell) || !msgok)
 
2728
        break;
 
2729
      if (visual_bell == 0)
 
2730
        Msg(0, "switched to audible bell.");
 
2731
      else
 
2732
        Msg(0, "switched to visual bell.");
 
2733
      break;
 
2734
    case RC_VBELLWAIT:
 
2735
      if (ParseNum1000(act, &VBellWait) == 0 && msgok)
 
2736
        Msg(0, "vbellwait set to %.10g seconds", VBellWait/1000.);
 
2737
      break;
 
2738
    case RC_MSGWAIT:
 
2739
      if (ParseNum1000(act, &MsgWait) == 0 && msgok)
 
2740
        Msg(0, "msgwait set to %.10g seconds", MsgWait/1000.);
 
2741
      break;
 
2742
    case RC_MSGMINWAIT:
 
2743
      if (ParseNum1000(act, &MsgMinWait) == 0 && msgok)
 
2744
        Msg(0, "msgminwait set to %.10g seconds", MsgMinWait/1000.);
 
2745
      break;
 
2746
    case RC_SILENCEWAIT:
 
2747
      if (ParseNum(act, &SilenceWait))
 
2748
        break;
 
2749
      if (SilenceWait < 1)
 
2750
        SilenceWait = 1;
 
2751
      for (p = windows; p; p = p->w_next)
 
2752
        p->w_silencewait = SilenceWait;
 
2753
      if (msgok)
 
2754
        Msg(0, "silencewait set to %d seconds", SilenceWait);
 
2755
      break;
 
2756
    case RC_NUMBER:
 
2757
      if (*args == 0)
 
2758
        Msg(0, "This is window %d (%s).\n", fore->w_number, fore->w_title);
 
2759
      else
 
2760
        {
 
2761
          int old = fore->w_number;
 
2762
 
 
2763
          if (ParseNum(act, &n) || n >= maxwin)
 
2764
            break;
 
2765
          p = wtab[n];
 
2766
          wtab[n] = fore;
 
2767
          fore->w_number = n;
 
2768
          wtab[old] = p;
 
2769
          if (p)
 
2770
            p->w_number = old;
 
2771
#ifdef MULTIUSER
 
2772
          /* exchange the acls for these windows. */
 
2773
          AclWinSwap(old, n);
 
2774
#endif
 
2775
#ifdef UTMPOK
 
2776
          /* exchange the utmp-slots for these windows */
 
2777
          if ((fore->w_slot != (slot_t) -1) && (fore->w_slot != (slot_t) 0))
 
2778
            {
 
2779
              RemoveUtmp(fore);
 
2780
              SetUtmp(fore);
 
2781
            }
 
2782
          if (p && (p->w_slot != (slot_t) -1) && (p->w_slot != (slot_t) 0))
 
2783
            {
 
2784
              /* XXX: first display wins? */
 
2785
              display = fore->w_layer.l_cvlist ? fore->w_layer.l_cvlist->c_display : 0;
 
2786
              RemoveUtmp(p);
 
2787
              SetUtmp(p);
 
2788
            }
 
2789
#endif
 
2790
 
 
2791
          WindowChanged(fore, 'n');
 
2792
          WindowChanged((struct win *)0, 'w');
 
2793
          WindowChanged((struct win *)0, 'W');
 
2794
          WindowChanged((struct win *)0, 0);
 
2795
        }
 
2796
      break;
 
2797
    case RC_SILENCE:
 
2798
      n = fore->w_silence != 0;
 
2799
      i = fore->w_silencewait;
 
2800
      if (args[0] && (args[0][0] == '-' || (args[0][0] >= '0' && args[0][0] <= '9')))
 
2801
        {
 
2802
          if (ParseNum(act, &i))
 
2803
            break;
 
2804
          n = i > 0;
 
2805
        }
 
2806
      else if (ParseSwitch(act, &n))
 
2807
        break;
 
2808
      if (n)
 
2809
        {
 
2810
#ifdef MULTIUSER
 
2811
          if (display)  /* we tell only this user */
 
2812
            ACLBYTE(fore->w_lio_notify, D_user->u_id) |= ACLBIT(D_user->u_id);
 
2813
          else
 
2814
            for (n = 0; n < maxusercount; n++)
 
2815
              ACLBYTE(fore->w_lio_notify, n) |= ACLBIT(n);
 
2816
#endif
 
2817
          fore->w_silencewait = i;
 
2818
          fore->w_silence = SILENCE_ON;
 
2819
          SetTimeout(&fore->w_silenceev, fore->w_silencewait * 1000);
 
2820
          evenq(&fore->w_silenceev);
 
2821
 
 
2822
          if (!msgok)
 
2823
            break;
 
2824
          Msg(0, "The window is now being monitored for %d sec. silence.", fore->w_silencewait);
 
2825
        }
 
2826
      else
 
2827
        {
 
2828
#ifdef MULTIUSER
 
2829
          if (display) /* we remove only this user */
 
2830
            ACLBYTE(fore->w_lio_notify, D_user->u_id) 
 
2831
              &= ~ACLBIT(D_user->u_id);
 
2832
          else
 
2833
            for (n = 0; n < maxusercount; n++)
 
2834
              ACLBYTE(fore->w_lio_notify, n) &= ~ACLBIT(n);
 
2835
          for (i = maxusercount - 1; i >= 0; i--)
 
2836
            if (ACLBYTE(fore->w_lio_notify, i))
 
2837
              break;
 
2838
          if (i < 0)
 
2839
#endif
 
2840
            {
 
2841
              fore->w_silence = SILENCE_OFF;
 
2842
              evdeq(&fore->w_silenceev);
 
2843
            }
 
2844
          if (!msgok)
 
2845
            break;
 
2846
          Msg(0, "The window is no longer being monitored for silence.");
 
2847
        }
 
2848
      break;
 
2849
#ifdef COPY_PASTE
 
2850
    case RC_DEFSCROLLBACK:
 
2851
      (void)ParseNum(act, &nwin_default.histheight);
 
2852
      break;
 
2853
    case RC_SCROLLBACK:
 
2854
      (void)ParseNum(act, &n);
 
2855
      ChangeWindowSize(fore, fore->w_width, fore->w_height, n);
 
2856
      if (msgok)
 
2857
        Msg(0, "scrollback set to %d", fore->w_histheight);
 
2858
      break;
 
2859
#endif
 
2860
    case RC_SESSIONNAME:
 
2861
      if (*args == 0)
 
2862
        Msg(0, "This session is named '%s'\n", SockName);
 
2863
      else
 
2864
        {
 
2865
          char buf[MAXPATHLEN];
 
2866
 
 
2867
          s = 0;
 
2868
          if (ParseSaveStr(act, &s))
 
2869
            break;
 
2870
          if (!*s || strlen(s) + (SockName - SockPath) > MAXPATHLEN - 13 || index(s, '/'))
 
2871
            {
 
2872
              Msg(0, "%s: bad session name '%s'\n", rc_name, s);
 
2873
              free(s);
 
2874
              break;
 
2875
            }
 
2876
          strncpy(buf, SockPath, SockName - SockPath);
 
2877
          sprintf(buf + (SockName - SockPath), "%d.%s", (int)getpid(), s); 
 
2878
          free(s);
 
2879
          if ((access(buf, F_OK) == 0) || (errno != ENOENT))
 
2880
            {
 
2881
              Msg(0, "%s: inappropriate path: '%s'.", rc_name, buf);
 
2882
              break;
 
2883
            }
 
2884
          if (rename(SockPath, buf))
 
2885
            {
 
2886
              Msg(errno, "%s: failed to rename(%s, %s)", rc_name, SockPath, buf);
 
2887
              break;
 
2888
            }
 
2889
          debug2("rename(%s, %s) done\n", SockPath, buf);
 
2890
          strcpy(SockPath, buf);
 
2891
          MakeNewEnv();
 
2892
        }
 
2893
      break;
 
2894
    case RC_SETENV:
 
2895
      if (!args[0] || !args[1])
 
2896
        {
 
2897
          debug1("RC_SETENV arguments missing: %s\n", args[0] ? args[0] : "");
 
2898
          InputSetenv(args[0]);
 
2899
        }
 
2900
      else
 
2901
        {
 
2902
          xsetenv(args[0], args[1]);
 
2903
          MakeNewEnv();
 
2904
        }
 
2905
      break;
 
2906
    case RC_UNSETENV:
 
2907
      unsetenv(*args);
 
2908
      MakeNewEnv();
 
2909
      break;
 
2910
#ifdef COPY_PASTE
 
2911
    case RC_DEFSLOWPASTE:
 
2912
      (void)ParseNum(act, &nwin_default.slow);
 
2913
      break;
 
2914
    case RC_SLOWPASTE:
 
2915
      if (*args == 0)
 
2916
        Msg(0, fore->w_slowpaste ? 
 
2917
               "Slowpaste in window %d is %d milliseconds." :
 
2918
               "Slowpaste in window %d is unset.", 
 
2919
            fore->w_number, fore->w_slowpaste);
 
2920
      else if (ParseNum(act, &fore->w_slowpaste) == 0 && msgok)
 
2921
        Msg(0, fore->w_slowpaste ?
 
2922
               "Slowpaste in window %d set to %d milliseconds." :
 
2923
               "Slowpaste in window %d now unset.", 
 
2924
            fore->w_number, fore->w_slowpaste);
 
2925
      break;
 
2926
    case RC_MARKKEYS:
 
2927
      if (CompileKeys(*args, *argl, mark_key_tab))
 
2928
        {
 
2929
          Msg(0, "%s: markkeys: syntax error.", rc_name);
 
2930
          break;
 
2931
        }
 
2932
      debug1("markkeys %s\n", *args);
 
2933
      break;
 
2934
# ifdef FONT
 
2935
    case RC_PASTEFONT:
 
2936
      if (ParseSwitch(act, &pastefont) == 0 && msgok)
 
2937
        Msg(0, "Will %spaste font settings", pastefont ? "" : "not ");
 
2938
      break;
 
2939
# endif
 
2940
    case RC_CRLF:
 
2941
      (void)ParseSwitch(act, &join_with_cr);
 
2942
      break;
 
2943
    case RC_COMPACTHIST:
 
2944
      if (ParseSwitch(act, &compacthist) == 0 && msgok)
 
2945
        Msg(0, "%scompacting history lines", compacthist ? "" : "not ");
 
2946
      break;
 
2947
#endif
 
2948
#ifdef NETHACK
 
2949
    case RC_NETHACK:
 
2950
      (void)ParseOnOff(act, &nethackflag);
 
2951
      break;
 
2952
#endif
 
2953
    case RC_HARDCOPY_APPEND:
 
2954
      (void)ParseOnOff(act, &hardcopy_append);
 
2955
      break;
 
2956
    case RC_VBELL_MSG:
 
2957
      if (*args == 0) 
 
2958
        { 
 
2959
          char buf[256];
 
2960
          AddXChars(buf, sizeof(buf), VisualBellString);
 
2961
          Msg(0, "vbell_msg is '%s'", buf);
 
2962
          break; 
 
2963
        }
 
2964
      (void)ParseSaveStr(act, &VisualBellString);
 
2965
      debug1(" new vbellstr '%s'\n", VisualBellString);
 
2966
      break;
 
2967
    case RC_DEFMODE:
 
2968
      if (ParseBase(act, *args, &n, 8, "octal"))
 
2969
        break;
 
2970
      if (n < 0 || n > 0777)
 
2971
        {
 
2972
          Msg(0, "%s: mode: Invalid tty mode %o", rc_name, n);
 
2973
          break;
 
2974
        }
 
2975
      TtyMode = n;
 
2976
      if (msgok)
 
2977
        Msg(0, "Ttymode set to %03o", TtyMode);
 
2978
      break;
 
2979
    case RC_AUTODETACH:
 
2980
      (void)ParseOnOff(act, &auto_detach);
 
2981
      break;
 
2982
    case RC_STARTUP_MESSAGE:
 
2983
      (void)ParseOnOff(act, &default_startup);
 
2984
      break;
 
2985
#ifdef PASSWORD
 
2986
    case RC_PASSWORD:
 
2987
      if (*args)
 
2988
        {
 
2989
          n = (*user->u_password) ? 1 : 0;
 
2990
          if (user->u_password != NullStr) free((char *)user->u_password);
 
2991
          user->u_password = SaveStr(*args);
 
2992
          if (!strcmp(user->u_password, "none"))
 
2993
            {
 
2994
              if (n)
 
2995
                Msg(0, "Password checking disabled");
 
2996
              free(user->u_password);
 
2997
              user->u_password = NullStr;
 
2998
            }
 
2999
        }
 
3000
      else
 
3001
        {
 
3002
          if (!fore)
 
3003
            {
 
3004
              Msg(0, "%s: password: window required", rc_name);
 
3005
              break;
 
3006
            }
 
3007
          Input("New screen password:", 100, INP_NOECHO, pass1, display ? (char *)D_user : (char *)users);
 
3008
        }
 
3009
      break;
 
3010
#endif                          /* PASSWORD */
 
3011
    case RC_BIND:
 
3012
        {
 
3013
          struct action *ktabp = ktab;
 
3014
 
 
3015
          if (argc > 2 && !strcmp(*args, "-c"))
 
3016
            {
 
3017
              ktabp = FindKtab(args[1], 1);
 
3018
              if (ktabp == 0)
 
3019
                break;
 
3020
              args += 2;
 
3021
              argl += 2;
 
3022
            }
 
3023
          if (*argl != 1)
 
3024
            {
 
3025
              Msg(0, "%s: bind: character, ^x, or (octal) \\032 expected.", rc_name);
 
3026
              break;
 
3027
            }
 
3028
          n = (unsigned char)args[0][0];
 
3029
          if (args[1])
 
3030
            {
 
3031
              if ((i = FindCommnr(args[1])) == RC_ILLEGAL)
 
3032
                {
 
3033
                  Msg(0, "%s: bind: unknown command '%s'", rc_name, args[1]);
 
3034
                  break;
 
3035
                }
 
3036
              if (CheckArgNum(i, args + 2) < 0)
 
3037
                break;
 
3038
              ClearAction(&ktabp[n]);
 
3039
              SaveAction(ktabp + n, i, args + 2, argl + 2);
 
3040
            }
 
3041
          else
 
3042
            ClearAction(&ktabp[n]);
 
3043
        }
 
3044
      break;
 
3045
#ifdef MAPKEYS
 
3046
    case RC_BINDKEY:
 
3047
        {
 
3048
          struct action *newact;
 
3049
          int newnr, fl = 0, kf = 0, af = 0, df = 0, mf = 0;
 
3050
          struct display *odisp = display;
 
3051
          int used = 0;
 
3052
          struct kmap_ext *kme;
 
3053
 
 
3054
          for (; *args && **args == '-'; args++, argl++)
 
3055
            {
 
3056
              if (strcmp(*args, "-t") == 0)
 
3057
                fl = KMAP_NOTIMEOUT;
 
3058
              else if (strcmp(*args, "-k") == 0)
 
3059
                kf = 1;
 
3060
              else if (strcmp(*args, "-a") == 0)
 
3061
                af = 1;
 
3062
              else if (strcmp(*args, "-d") == 0)
 
3063
                df = 1;
 
3064
              else if (strcmp(*args, "-m") == 0)
 
3065
                mf = 1;
 
3066
              else if (strcmp(*args, "--") == 0)
 
3067
                {
 
3068
                  args++;
 
3069
                  argl++;
 
3070
                  break;
 
3071
                }
 
3072
              else
 
3073
                {
 
3074
                  Msg(0, "%s: bindkey: invalid option %s", rc_name, *args);
 
3075
                  return;
 
3076
                }
 
3077
            }
 
3078
          if (df && mf)
 
3079
            {
 
3080
              Msg(0, "%s: bindkey: -d does not work with -m", rc_name);
 
3081
              break;
 
3082
            }
 
3083
          if (*args == 0)
 
3084
            {
 
3085
              if (mf)
 
3086
                display_bindkey("Edit mode", mmtab);
 
3087
              else if (df)
 
3088
                display_bindkey("Default", dmtab);
 
3089
              else
 
3090
                display_bindkey("User", umtab);
 
3091
              break;
 
3092
            }
 
3093
          if (kf == 0)
 
3094
            {
 
3095
              if (af)
 
3096
                {
 
3097
                  Msg(0, "%s: bindkey: -a only works with -k", rc_name);
 
3098
                  break;
 
3099
                }
 
3100
              if (*argl == 0)
 
3101
                {
 
3102
                  Msg(0, "%s: bindkey: empty string makes no sense", rc_name);
 
3103
                  break;
 
3104
                }
 
3105
              for (i = 0, kme = kmap_exts; i < kmap_extn; i++, kme++)
 
3106
                if (kme->str == 0)
 
3107
                  {
 
3108
                    if (args[1])
 
3109
                      break;
 
3110
                  }
 
3111
                else
 
3112
                  if (*argl == (kme->fl & ~KMAP_NOTIMEOUT) && bcmp(kme->str, *args, *argl) == 0)
 
3113
                      break;
 
3114
              if (i == kmap_extn)
 
3115
                {
 
3116
                  if (!args[1])
 
3117
                    {
 
3118
                      Msg(0, "%s: bindkey: keybinding not found", rc_name);
 
3119
                      break;
 
3120
                    }
 
3121
                  kmap_extn += 8;
 
3122
                  kmap_exts = (struct kmap_ext *)xrealloc((char *)kmap_exts, kmap_extn * sizeof(*kmap_exts));
 
3123
                  kme = kmap_exts + i;
 
3124
                  bzero((char *)kme, 8 * sizeof(*kmap_exts));
 
3125
                  for (; i < kmap_extn; i++, kme++)
 
3126
                    {
 
3127
                      kme->str = 0;
 
3128
                      kme->dm.nr = kme->mm.nr = kme->um.nr = RC_ILLEGAL;
 
3129
                      kme->dm.args = kme->mm.args = kme->um.args = noargs;
 
3130
                    }
 
3131
                  i -= 8;
 
3132
                  kme -= 8;
 
3133
                }
 
3134
              if (df == 0 && kme->dm.nr != RC_ILLEGAL)
 
3135
                used = 1;
 
3136
              if (mf == 0 && kme->mm.nr != RC_ILLEGAL)
 
3137
                used = 1;
 
3138
              if ((df || mf) && kme->um.nr != RC_ILLEGAL)
 
3139
                used = 1;
 
3140
              i += KMAP_KEYS + KMAP_AKEYS;
 
3141
              newact = df ? &kme->dm : mf ? &kme->mm : &kme->um;
 
3142
            }
 
3143
          else
 
3144
            {
 
3145
              for (i = T_CAPS; i < T_OCAPS; i++)
 
3146
                if (strcmp(term[i].tcname, *args) == 0)
 
3147
                  break;
 
3148
              if (i == T_OCAPS)
 
3149
                {
 
3150
                  Msg(0, "%s: bindkey: unknown key '%s'", rc_name, *args);
 
3151
                  break;
 
3152
                }
 
3153
              if (af && i >= T_CURSOR && i < T_OCAPS)
 
3154
                i -=  T_CURSOR - KMAP_KEYS;
 
3155
              else
 
3156
                i -=  T_CAPS;
 
3157
              newact = df ? &dmtab[i] : mf ? &mmtab[i] : &umtab[i];
 
3158
            }
 
3159
          if (args[1])
 
3160
            {
 
3161
              if ((newnr = FindCommnr(args[1])) == RC_ILLEGAL)
 
3162
                {
 
3163
                  Msg(0, "%s: bindkey: unknown command '%s'", rc_name, args[1]);
 
3164
                  break;
 
3165
                }
 
3166
              if (CheckArgNum(newnr, args + 2) < 0)
 
3167
                break;
 
3168
              ClearAction(newact);
 
3169
              SaveAction(newact, newnr, args + 2, argl + 2);
 
3170
              if (kf == 0 && args[1])
 
3171
                {
 
3172
                  if (kme->str)
 
3173
                    free(kme->str);
 
3174
                  kme->str = SaveStrn(*args, *argl);
 
3175
                  kme->fl = fl | *argl;
 
3176
                }
 
3177
            }
 
3178
          else
 
3179
            ClearAction(newact);
 
3180
          for (display = displays; display; display = display->d_next)
 
3181
            remap(i, args[1] ? 1 : 0);
 
3182
          if (kf == 0 && !args[1])
 
3183
            {
 
3184
              if (!used && kme->str)
 
3185
                {
 
3186
                  free(kme->str);
 
3187
                  kme->str = 0;
 
3188
                  kme->fl = 0;
 
3189
                }
 
3190
            }
 
3191
          display = odisp;
 
3192
        }
 
3193
      break;
 
3194
    case RC_MAPTIMEOUT:
 
3195
      if (*args)
 
3196
        {
 
3197
          if (ParseNum(act, &n))
 
3198
            break;
 
3199
          if (n < 0)
 
3200
            {
 
3201
              Msg(0, "%s: maptimeout: illegal time %d", rc_name, n);
 
3202
              break;
 
3203
            }
 
3204
          maptimeout = n;
 
3205
        }
 
3206
      if (*args == 0 || msgok)
 
3207
        Msg(0, "maptimeout is %dms", maptimeout);
 
3208
      break;
 
3209
    case RC_MAPNOTNEXT:
 
3210
      D_dontmap = 1;
 
3211
      break;
 
3212
    case RC_MAPDEFAULT:
 
3213
      D_mapdefault = 1;
 
3214
      break;
 
3215
#endif
 
3216
#ifdef MULTIUSER
 
3217
    case RC_ACLCHG:
 
3218
    case RC_ACLADD:
 
3219
    case RC_ADDACL:
 
3220
    case RC_CHACL:
 
3221
      UsersAcl(NULL, argc, args);
 
3222
      break;
 
3223
    case RC_ACLDEL:
 
3224
      if (UserDel(args[0], NULL))
 
3225
        break;
 
3226
      if (msgok)
 
3227
        Msg(0, "%s removed from acl database", args[0]);
 
3228
      break;
 
3229
    case RC_ACLGRP:
 
3230
      /*
 
3231
       * modify a user to gain or lose rights granted to a group.
 
3232
       * This group is actually a normal user whose rights were defined
 
3233
       * with chacl in the usual way.
 
3234
       */
 
3235
      if (args[1])
 
3236
        {
 
3237
          if (strcmp(args[1], "none"))  /* link a user to another user */
 
3238
            {
 
3239
              if (AclLinkUser(args[0], args[1]))
 
3240
                break;
 
3241
              if (msgok)
 
3242
                Msg(0, "User %s joined acl-group %s", args[0], args[1]);
 
3243
            }
 
3244
          else                          /* remove all groups from user */
 
3245
            {
 
3246
              struct acluser *u;
 
3247
              struct aclusergroup *g;
 
3248
 
 
3249
              if (!(u = *FindUserPtr(args[0])))
 
3250
                break;
 
3251
              while ((g = u->u_group))
 
3252
                {
 
3253
                  u->u_group = g->next;
 
3254
                  free((char *)g);
 
3255
                }
 
3256
            }
 
3257
        }
 
3258
      else                              /* show all groups of user */
 
3259
        {
 
3260
          char buf[256], *p = buf;
 
3261
          int ngroups = 0;
 
3262
          struct acluser *u;
 
3263
          struct aclusergroup *g;
 
3264
 
 
3265
          if (!(u = *FindUserPtr(args[0])))
 
3266
            {
 
3267
              if (msgok)
 
3268
                Msg(0, "User %s does not exist.", args[0]);
 
3269
              break;
 
3270
            }
 
3271
          g = u->u_group;
 
3272
          while (g)
 
3273
            {
 
3274
              ngroups++;
 
3275
              sprintf(p, "%s ", g->u->u_name);
 
3276
              p += strlen(p);
 
3277
              if (p > buf+200)
 
3278
                break;
 
3279
              g = g->next;
 
3280
            }
 
3281
          if (ngroups)
 
3282
            *(--p) = '\0';
 
3283
          Msg(0, "%s's group%s: %s.", args[0], (ngroups == 1) ? "" : "s",
 
3284
              (ngroups == 0) ? "none" : buf);
 
3285
        }
 
3286
      break;
 
3287
    case RC_ACLUMASK:
 
3288
    case RC_UMASK:
 
3289
      while ((s = *args++))
 
3290
        {
 
3291
          char *err = 0;
 
3292
 
 
3293
          if (AclUmask(display ? D_user : users, s, &err))
 
3294
            Msg(0, "umask: %s\n", err);
 
3295
        }
 
3296
      break;
 
3297
    case RC_MULTIUSER:
 
3298
      if (ParseOnOff(act, &n))
 
3299
        break;
 
3300
      multi = n ? "" : 0;
 
3301
      chsock();
 
3302
      if (msgok)
 
3303
        Msg(0, "Multiuser mode %s", multi ? "enabled" : "disabled");
 
3304
      break;
 
3305
#endif /* MULTIUSER */
 
3306
#ifdef PSEUDOS
 
3307
    case RC_EXEC:
 
3308
      winexec(args);
 
3309
      break;
 
3310
#endif
 
3311
#ifdef MULTI
 
3312
    case RC_NONBLOCK:
 
3313
      i = D_nonblock >= 0;
 
3314
      if (*args && ((args[0][0] >= '0' && args[0][0] <= '9') || args[0][0] == '.'))
 
3315
        {
 
3316
          if (ParseNum1000(act, &i))
 
3317
            break;
 
3318
        }
 
3319
      else if (!ParseSwitch(act, &i))
 
3320
        i = i == 0 ? -1 : 1000;
 
3321
      else
 
3322
        break;
 
3323
      if (msgok && i == -1)
 
3324
        Msg(0, "display set to blocking mode");
 
3325
      else if (msgok && i == 0)
 
3326
        Msg(0, "display set to nonblocking mode, no timeout");
 
3327
      else if (msgok)
 
3328
        Msg(0, "display set to nonblocking mode, %.10gs timeout", i/1000.);
 
3329
      D_nonblock = i;
 
3330
      if (D_nonblock <= 0)
 
3331
        evdeq(&D_blockedev);
 
3332
      break;
 
3333
    case RC_DEFNONBLOCK:
 
3334
      if (*args && ((args[0][0] >= '0' && args[0][0] <= '9') || args[0][0] == '.'))
 
3335
        {
 
3336
          if (ParseNum1000(act, &defnonblock))
 
3337
            break;
 
3338
        }
 
3339
      else if (!ParseOnOff(act, &defnonblock))
 
3340
        defnonblock = defnonblock == 0 ? -1 : 1000;
 
3341
      else
 
3342
        break;
 
3343
      if (display && *rc_name)
 
3344
        {
 
3345
          D_nonblock = defnonblock;
 
3346
          if (D_nonblock <= 0)
 
3347
            evdeq(&D_blockedev);
 
3348
        }
 
3349
      break;
 
3350
#endif
 
3351
    case RC_GR:
 
3352
#ifdef ENCODINGS
 
3353
      if (fore->w_gr == 2)
 
3354
        fore->w_gr = 0;
 
3355
#endif
 
3356
      if (ParseSwitch(act, &fore->w_gr) == 0 && msgok)
 
3357
        Msg(0, "Will %suse GR", fore->w_gr ? "" : "not ");
 
3358
#ifdef ENCODINGS
 
3359
      if (fore->w_gr == 0 && fore->w_FontE)
 
3360
        fore->w_gr = 2;
 
3361
#endif
 
3362
      break;
 
3363
    case RC_C1:
 
3364
      if (ParseSwitch(act, &fore->w_c1) == 0 && msgok)
 
3365
        Msg(0, "Will %suse C1", fore->w_c1 ? "" : "not ");
 
3366
      break;
 
3367
#ifdef COLOR
 
3368
    case RC_BCE:
 
3369
      if (ParseSwitch(act, &fore->w_bce) == 0 && msgok)
 
3370
        Msg(0, "Will %serase with background color", fore->w_bce ? "" : "not ");
 
3371
      break;
 
3372
#endif
 
3373
#ifdef ENCODINGS
 
3374
    case RC_KANJI:
 
3375
    case RC_ENCODING:
 
3376
#ifdef UTF8
 
3377
      if (*args && !strcmp(args[0], "-d"))
 
3378
        {
 
3379
          if (!args[1])
 
3380
            Msg(0, "encodings directory is %s", screenencodings ? screenencodings : "<unset>");
 
3381
          else
 
3382
            {
 
3383
              free(screenencodings);
 
3384
              screenencodings = SaveStr(args[1]);
 
3385
            }
 
3386
          break;
 
3387
        }
 
3388
      if (*args && !strcmp(args[0], "-l"))
 
3389
        {
 
3390
          if (!args[1])
 
3391
            Msg(0, "encoding: -l: argument required");
 
3392
          else if (LoadFontTranslation(-1, args[1]))
 
3393
            Msg(0, "encoding: could not load utf8 encoding file");
 
3394
          else if (msgok)
 
3395
            Msg(0, "encoding: utf8 encoding file loaded");
 
3396
          break;
 
3397
        }
 
3398
#else
 
3399
      if (*args && (!strcmp(args[0], "-l") || !strcmp(args[0], "-d")))
 
3400
        {
 
3401
          if (msgok)
 
3402
            Msg(0, "encoding: screen is not compiled for UTF-8.");
 
3403
          break;
 
3404
        }
 
3405
#endif
 
3406
      for (i = 0; i < 2; i++)
 
3407
        {
 
3408
          if (args[i] == 0)
 
3409
            break;
 
3410
          if (!strcmp(args[i], "."))
 
3411
            continue;
 
3412
          n = FindEncoding(args[i]);
 
3413
          if (n == -1)
 
3414
            {
 
3415
              Msg(0, "encoding: unknown encoding '%s'", args[i]);
 
3416
              break;
 
3417
            }
 
3418
          if (i == 0 && fore)
 
3419
            {
 
3420
              WinSwitchEncoding(fore, n);
 
3421
              ResetCharsets(fore);
 
3422
            }
 
3423
          else if (i && display)
 
3424
            D_encoding  = n;
 
3425
        }
 
3426
      break;
 
3427
    case RC_DEFKANJI:
 
3428
    case RC_DEFENCODING:
 
3429
      n = FindEncoding(*args);
 
3430
      if (n == -1)
 
3431
        {
 
3432
          Msg(0, "defencoding: unknown encoding '%s'", *args);
 
3433
          break;
 
3434
        }
 
3435
      nwin_default.encoding = n;
 
3436
      break;
 
3437
#endif
 
3438
 
 
3439
#ifdef UTF8
 
3440
    case RC_DEFUTF8:
 
3441
      n = nwin_default.encoding == UTF8;
 
3442
      if (ParseSwitch(act, &n) == 0)
 
3443
        {
 
3444
          nwin_default.encoding = n ? UTF8 : 0;
 
3445
          if (msgok)
 
3446
            Msg(0, "Will %suse UTF-8 encoding for new windows", n ? "" : "not ");
 
3447
        }
 
3448
      break;
 
3449
    case RC_UTF8:
 
3450
      for (i = 0; i < 2; i++)
 
3451
        {
 
3452
          if (i && args[i] == 0)
 
3453
            break;
 
3454
          if (args[i] == 0)
 
3455
            n = fore->w_encoding != UTF8;
 
3456
          else if (strcmp(args[i], "off") == 0)
 
3457
            n = 0;
 
3458
          else if (strcmp(args[i], "on") == 0)
 
3459
            n = 1;
 
3460
          else
 
3461
            {
 
3462
              Msg(0, "utf8: illegal argument (%s)", args[i]);
 
3463
              break;
 
3464
            }
 
3465
          if (i == 0)
 
3466
            {
 
3467
              WinSwitchEncoding(fore, n ? UTF8 : 0);
 
3468
              if (msgok)
 
3469
                Msg(0, "Will %suse UTF-8 encoding", n ? "" : "not ");
 
3470
            }
 
3471
          else if (display)
 
3472
            D_encoding = n ? UTF8 : 0;
 
3473
          if (args[i] == 0)
 
3474
            break;
 
3475
        }
 
3476
      break;
 
3477
#endif
 
3478
 
 
3479
    case RC_PRINTCMD:
 
3480
      if (*args)
 
3481
        {
 
3482
          if (printcmd)
 
3483
            free(printcmd);
 
3484
          printcmd = 0;
 
3485
          if (**args)
 
3486
            printcmd = SaveStr(*args);
 
3487
        }
 
3488
      if (*args == 0 || msgok)
 
3489
        {
 
3490
          if (printcmd)
 
3491
            Msg(0, "using '%s' as print command", printcmd);
 
3492
          else
 
3493
            Msg(0, "using termcap entries for printing");
 
3494
            break;
 
3495
        }
 
3496
      break;
 
3497
 
 
3498
    case RC_DIGRAPH:
 
3499
      Input("Enter digraph: ", 10, INP_EVERY, digraph_fn, NULL);
 
3500
      if (*args && **args)
 
3501
        {
 
3502
          s = *args;
 
3503
          n = strlen(s);
 
3504
          LayProcess(&s, &n);
 
3505
        }
 
3506
      break;
 
3507
 
 
3508
    case RC_DEFHSTATUS:
 
3509
      if (*args == 0)
 
3510
        {
 
3511
          char buf[256];
 
3512
          *buf = 0;
 
3513
          if (nwin_default.hstatus)
 
3514
            AddXChars(buf, sizeof(buf), nwin_default.hstatus);
 
3515
          Msg(0, "default hstatus is '%s'", buf);
 
3516
          break;
 
3517
        }
 
3518
      (void)ParseSaveStr(act, &nwin_default.hstatus);
 
3519
      if (*nwin_default.hstatus == 0)
 
3520
        {
 
3521
          free(nwin_default.hstatus);
 
3522
          nwin_default.hstatus = 0;
 
3523
        }
 
3524
      break;
 
3525
    case RC_HSTATUS:
 
3526
      (void)ParseSaveStr(act, &fore->w_hstatus);
 
3527
      if (*fore->w_hstatus == 0)
 
3528
        {
 
3529
          free(fore->w_hstatus);
 
3530
          fore->w_hstatus = 0;
 
3531
        }
 
3532
      WindowChanged(fore, 'h');
 
3533
      break;
 
3534
 
 
3535
#ifdef FONT
 
3536
    case RC_DEFCHARSET:
 
3537
    case RC_CHARSET:
 
3538
      if (*args == 0)
 
3539
        {
 
3540
          char buf[256];
 
3541
          *buf = 0;
 
3542
          if (nwin_default.charset)
 
3543
            AddXChars(buf, sizeof(buf), nwin_default.charset);
 
3544
          Msg(0, "default charset is '%s'", buf);
 
3545
          break;
 
3546
        }
 
3547
      n = strlen(*args);
 
3548
      if (n == 0 || n > 6)
 
3549
        {
 
3550
          Msg(0, "%s: %s: string has illegal size.", rc_name, comms[nr].name);
 
3551
          break;
 
3552
        }
 
3553
      if (n > 4 && (
 
3554
        ((args[0][4] < '0' || args[0][4] > '3') && args[0][4] != '.') ||
 
3555
        ((args[0][5] < '0' || args[0][5] > '3') && args[0][5] && args[0][5] != '.')))
 
3556
        {
 
3557
          Msg(0, "%s: %s: illegal mapping number.", rc_name, comms[nr].name);
 
3558
          break;
 
3559
        }
 
3560
      if (nr == RC_CHARSET)
 
3561
        {
 
3562
          SetCharsets(fore, *args);
 
3563
          break;
 
3564
        }
 
3565
      if (nwin_default.charset)
 
3566
        free(nwin_default.charset);
 
3567
      nwin_default.charset = SaveStr(*args);
 
3568
      break;
 
3569
#endif
 
3570
#ifdef COLOR
 
3571
    case RC_ATTRCOLOR:
 
3572
      s = args[0];
 
3573
      if (*s >= '0' && *s <= '9')
 
3574
        i = *s - '0';
 
3575
      else
 
3576
        for (i = 0; i < 8; i++)
 
3577
          if (*s == "dubrsBiI"[i])
 
3578
            break;
 
3579
      s++;
 
3580
      nr = 0;
 
3581
      if (*s && s[1] && !s[2])
 
3582
        {
 
3583
          if (*s == 'd' && s[1] == 'd')
 
3584
            nr = 3;
 
3585
          else if (*s == '.' && s[1] == 'd')
 
3586
            nr = 2;
 
3587
          else if (*s == 'd' && s[1] == '.')
 
3588
            nr = 1;
 
3589
          else if (*s != '.' || s[1] != '.')
 
3590
            s--;
 
3591
          s += 2;
 
3592
        }
 
3593
      if (*s || i < 0 || i >= 8)
 
3594
        {
 
3595
          Msg(0, "%s: attrcolor: unknown attribute '%s'.", rc_name, args[0]);
 
3596
          break;
 
3597
        }
 
3598
      n = 0;
 
3599
      if (args[1])
 
3600
        n = ParseAttrColor(args[1], args[2], 1);
 
3601
      if (n == -1)
 
3602
        break;
 
3603
      attr2color[i][nr] = n;
 
3604
      n = 0;
 
3605
      for (i = 0; i < 8; i++)
 
3606
        if (attr2color[i][0] || attr2color[i][1] || attr2color[i][2] || attr2color[i][3])
 
3607
          n |= 1 << i;
 
3608
      nattr2color = n;
 
3609
      break;
 
3610
#endif
 
3611
    case RC_SORENDITION:
 
3612
      i = 0;
 
3613
      if (*args)
 
3614
        {
 
3615
          i = ParseAttrColor(*args, args[1], 1);
 
3616
          if (i == -1)
 
3617
            break;
 
3618
          ApplyAttrColor(i, &mchar_so);
 
3619
          debug2("--> %x %x\n", mchar_so.attr, mchar_so.color);
 
3620
        }
 
3621
      if (msgok)
 
3622
#ifdef COLOR
 
3623
        Msg(0, "Standout attributes 0x%02x  color 0x%02x", (unsigned char)mchar_so.attr, 0x99 ^ (unsigned char)mchar_so.color);
 
3624
#else
 
3625
        Msg(0, "Standout attributes 0x%02x ", (unsigned char)mchar_so.attr);
 
3626
#endif
 
3627
      break;
 
3628
 
 
3629
      case RC_SOURCE:
 
3630
        do_source(*args);
 
3631
        break;
 
3632
 
 
3633
#ifdef MULTIUSER
 
3634
    case RC_SU:
 
3635
      s = NULL;
 
3636
      if (!*args)
 
3637
        {
 
3638
          Msg(0, "%s:%s screen login", HostName, SockPath);
 
3639
          InputSu(D_fore, &D_user, NULL);
 
3640
        }
 
3641
      else if (!args[1])
 
3642
        InputSu(D_fore, &D_user, args[0]);
 
3643
      else if (!args[2])
 
3644
        s = DoSu(&D_user, args[0], args[1], "\377");
 
3645
      else
 
3646
        s = DoSu(&D_user, args[0], args[1], args[2]);
 
3647
      if (s)
 
3648
        Msg(0, "%s", s);
 
3649
      break;
 
3650
#endif /* MULTIUSER */
 
3651
    case RC_SPLIT:
 
3652
      AddCanvas();
 
3653
      Activate(-1);
 
3654
      break;
 
3655
    case RC_REMOVE:
 
3656
      RemCanvas();
 
3657
      Activate(-1);
 
3658
      break;
 
3659
    case RC_ONLY:
 
3660
      OneCanvas();
 
3661
      Activate(-1);
 
3662
      break;
 
3663
    case RC_FIT:
 
3664
      D_forecv->c_xoff = D_forecv->c_xs;
 
3665
      D_forecv->c_yoff = D_forecv->c_ys;
 
3666
      RethinkViewportOffsets(D_forecv);
 
3667
      ResizeLayer(D_forecv->c_layer, D_forecv->c_xe - D_forecv->c_xs + 1, D_forecv->c_ye - D_forecv->c_ys + 1, 0);
 
3668
      flayer = D_forecv->c_layer;
 
3669
      LaySetCursor();
 
3670
      break;
 
3671
    case RC_FOCUS:
 
3672
      if (!*args || !strcmp(*args, "down"))
 
3673
        D_forecv = D_forecv->c_next ? D_forecv->c_next : D_cvlist;
 
3674
      else if (!strcmp(*args, "up"))
 
3675
        {
 
3676
          struct canvas *cv;
 
3677
          for (cv = D_cvlist; cv->c_next && cv->c_next != D_forecv; cv = cv->c_next)
 
3678
            ;
 
3679
          D_forecv = cv;
 
3680
        }
 
3681
      else if (!strcmp(*args, "top"))
 
3682
        D_forecv = D_cvlist;
 
3683
      else if (!strcmp(*args, "bottom"))
 
3684
        {
 
3685
          struct canvas *cv;
 
3686
          for (cv = D_cvlist; cv->c_next; cv = cv->c_next)
 
3687
            ;
 
3688
          D_forecv = cv;
 
3689
        }
 
3690
      else
 
3691
        {
 
3692
          Msg(0, "%s: usage: focus [up|down|top|bottom]", rc_name);
 
3693
          break;
 
3694
        }
 
3695
      fore = D_fore = Layer2Window(D_forecv->c_layer);
 
3696
      flayer = D_forecv->c_layer;
 
3697
#ifdef RXVT_OSC
 
3698
      if (D_xtermosc[2] || D_xtermosc[3])
 
3699
        {
 
3700
          Activate(-1);
 
3701
          break;
 
3702
        }
 
3703
#endif
 
3704
      RefreshHStatus();
 
3705
#ifdef RXVT_OSC
 
3706
      RefreshXtermOSC();
 
3707
#endif
 
3708
      flayer = D_forecv->c_layer;
 
3709
      CV_CALL(D_forecv, LayRestore();LaySetCursor());
 
3710
      WindowChanged(0, 'F');
 
3711
      break;
 
3712
    case RC_RESIZE:
 
3713
      if (*args)
 
3714
        ResizeRegions(*args);
 
3715
      else
 
3716
        Input("resize # lines: ", 20, INP_COOKED, ResizeFin, (char*)0);
 
3717
      break;
 
3718
    case RC_SETSID:
 
3719
      (void)ParseSwitch(act, &separate_sids);
 
3720
      break;
 
3721
    case RC_EVAL:
 
3722
      for (; *args; args++)
 
3723
        {
 
3724
          char *ss = SaveStr(*args);
 
3725
          if (*ss)
 
3726
            Colonfin(ss, strlen(ss), (char *)0);
 
3727
          free(ss);
 
3728
        }
 
3729
      break;
 
3730
    case RC_ALTSCREEN:
 
3731
      (void)ParseSwitch(act, &use_altscreen);
 
3732
      if (msgok)
 
3733
        Msg(0, "Will %sdo alternate screen switching", use_altscreen ? "" : "not ");
 
3734
      break;
 
3735
    case RC_MAXWIN:
 
3736
      if (ParseNum(act, &n))
 
3737
        break;
 
3738
      if (n < 1)
 
3739
        Msg(0, "illegal maxwin number specified");
 
3740
      else if (n > maxwin)
 
3741
        Msg(0, "may only decrease maxwin number");
 
3742
      else
 
3743
        maxwin = n;
 
3744
      break;
 
3745
    case RC_BACKTICK:
 
3746
      if (ParseBase(act, *args, &n, 10, "decimal"))
 
3747
        break;
 
3748
      if (!args[1])
 
3749
        setbacktick(n, 0, 0, (char **)0);
 
3750
      else
 
3751
        {
 
3752
          int lifespan, tick;
 
3753
          if (argc < 4)
 
3754
            {
 
3755
              Msg(0, "%s: usage: backtick num [lifespan tick cmd args...]", rc_name);
 
3756
              break;
 
3757
            }
 
3758
          if (ParseBase(act, args[1], &lifespan, 10, "decimal"))
 
3759
            break;
 
3760
          if (ParseBase(act, args[2], &tick, 10, "decimal"))
 
3761
            break;
 
3762
          setbacktick(n, lifespan, tick, SaveArgs(args + 3));
 
3763
        }
 
3764
      WindowChanged(0, '`');
 
3765
      break;
 
3766
    case RC_BLANKER:
 
3767
#ifdef BLANKER_PRG
 
3768
      if (blankerprg)
 
3769
        {
 
3770
          RunBlanker(blankerprg);
 
3771
          break;
 
3772
        }
 
3773
#endif
 
3774
      ClearAll();
 
3775
      CursorVisibility(-1);
 
3776
      D_blocked = 4;
 
3777
      break;
 
3778
#ifdef BLANKER_PRG
 
3779
    case RC_BLANKERPRG:
 
3780
      if (blankerprg)
 
3781
        {
 
3782
          char **pp;
 
3783
          for (pp = blankerprg; *pp; pp++)
 
3784
            free(*pp);
 
3785
          free(blankerprg);
 
3786
          blankerprg = 0;
 
3787
        }
 
3788
      if (args[0][0])
 
3789
        blankerprg = SaveArgs(args);
 
3790
      break;
 
3791
#endif
 
3792
    case RC_IDLE:
 
3793
      if (*args)
 
3794
        {
 
3795
          struct display *olddisplay = display;
 
3796
          if (!strcmp(*args, "off"))
 
3797
            idletimo = 0;
 
3798
          else if (args[0][0])
 
3799
            idletimo = atoi(*args) * 1000;
 
3800
          if (argc > 1)
 
3801
            {
 
3802
              if ((i = FindCommnr(args[1])) == RC_ILLEGAL)
 
3803
                {
 
3804
                  Msg(0, "%s: idle: unknown command '%s'", rc_name, args[1]);
 
3805
                  break;
 
3806
                }
 
3807
              if (CheckArgNum(i, args + 2) < 0)
 
3808
                break;
 
3809
              ClearAction(&idleaction);
 
3810
              SaveAction(&idleaction, i, args + 2, argl + 2);
 
3811
            }
 
3812
          for (display = displays; display; display = display->d_next)
 
3813
            ResetIdle();
 
3814
          display = olddisplay;
 
3815
        }
 
3816
      if (msgok)
 
3817
        {
 
3818
          if (idletimo)
 
3819
            Msg(0, "idle timeout %ds, %s", idletimo / 1000, comms[idleaction.nr].name);
 
3820
          else
 
3821
            Msg(0, "idle off");
 
3822
        }
 
3823
      break;
 
3824
    default:
 
3825
#ifdef HAVE_BRAILLE
 
3826
      /* key == -2: input from braille keybord, msgok always 0 */
 
3827
      DoBrailleAction(act, key == -2 ? 0 : msgok);
 
3828
#endif
 
3829
      break;
 
3830
    }
 
3831
  if (display != odisplay)
 
3832
    {
 
3833
      for (display = displays; display; display = display->d_next)
 
3834
        if (display == odisplay)
 
3835
          break;
 
3836
    }
 
3837
}
 
3838
 
 
3839
void
 
3840
DoCommand(argv, argl) 
 
3841
char **argv;
 
3842
int *argl;
 
3843
{
 
3844
  struct action act;
 
3845
 
 
3846
  if ((act.nr = FindCommnr(*argv)) == RC_ILLEGAL)  
 
3847
    {
 
3848
      Msg(0, "%s: unknown command '%s'", rc_name, *argv);
 
3849
      return;
 
3850
    }
 
3851
  act.args = argv + 1;
 
3852
  act.argl = argl + 1;
 
3853
  DoAction(&act, -1);
 
3854
}
 
3855
 
 
3856
static void
 
3857
SaveAction(act, nr, args, argl)
 
3858
struct action *act;
 
3859
int nr;
 
3860
char **args;
 
3861
int *argl;
 
3862
{
 
3863
  register int argc = 0;
 
3864
  char **pp;
 
3865
  int *lp;
 
3866
 
 
3867
  if (args)
 
3868
    while (args[argc])
 
3869
      argc++;
 
3870
  if (argc == 0)
 
3871
    {
 
3872
      act->nr = nr;
 
3873
      act->args = noargs;
 
3874
      act->argl = 0;
 
3875
      return;
 
3876
    }
 
3877
  if ((pp = (char **)malloc((unsigned)(argc + 1) * sizeof(char **))) == 0)
 
3878
    Panic(0, strnomem);
 
3879
  if ((lp = (int *)malloc((unsigned)(argc) * sizeof(int *))) == 0)
 
3880
    Panic(0, strnomem);
 
3881
  act->nr = nr;
 
3882
  act->args = pp;
 
3883
  act->argl = lp;
 
3884
  while (argc--)
 
3885
    {
 
3886
      *lp = argl ? *argl++ : (int)strlen(*args);
 
3887
      *pp++ = SaveStrn(*args++, *lp++);
 
3888
    }
 
3889
  *pp = 0;
 
3890
}
 
3891
 
 
3892
static char **
 
3893
SaveArgs(args)
 
3894
char **args;
 
3895
{
 
3896
  register char **ap, **pp;
 
3897
  register int argc = 0;
 
3898
 
 
3899
  while (args[argc])
 
3900
    argc++;
 
3901
  if ((pp = ap = (char **)malloc((unsigned)(argc + 1) * sizeof(char **))) == 0)
 
3902
    Panic(0, strnomem);
 
3903
  while (argc--)
 
3904
    *pp++ = SaveStr(*args++);
 
3905
  *pp = 0;
 
3906
  return ap;
 
3907
}
 
3908
 
 
3909
 
 
3910
/*
 
3911
 * buf is split into argument vector args.
 
3912
 * leading whitespace is removed.
 
3913
 * @!| abbreviations are expanded.
 
3914
 * the end of buffer is recognized by '\0' or an un-escaped '#'.
 
3915
 * " and ' are interpreted.
 
3916
 *
 
3917
 * argc is returned.
 
3918
 */
 
3919
int 
 
3920
Parse(buf, bufl, args, argl)
 
3921
char *buf, **args;
 
3922
int bufl, *argl;
 
3923
{
 
3924
  register char *p = buf, **ap = args, *pp;
 
3925
  register int delim, argc;
 
3926
  int *lp = argl;
 
3927
 
 
3928
  debug2("Parse %d %s\n", bufl, buf);
 
3929
  argc = 0;
 
3930
  pp = buf;
 
3931
  delim = 0;
 
3932
  for (;;)
 
3933
    {
 
3934
      while (*p && (*p == ' ' || *p == '\t'))
 
3935
        ++p;
 
3936
#ifdef PSEUDOS
 
3937
      if (argc == 0 && *p == '!')
 
3938
        {
 
3939
          *ap++ = "exec";
 
3940
          *lp++ = 4;
 
3941
          p++;
 
3942
          argc++;
 
3943
          continue;
 
3944
        }
 
3945
#endif
 
3946
      if (*p == '\0' || *p == '#' || *p == '\n')
 
3947
        {
 
3948
          *p = '\0';
 
3949
          for (delim = 0; delim < argc; delim++)
 
3950
            debug1("-- %s\n", args[delim]);
 
3951
          args[argc] = 0;
 
3952
          return argc;
 
3953
        }
 
3954
      if (++argc >= MAXARGS)
 
3955
        {
 
3956
          Msg(0, "%s: too many tokens.", rc_name);
 
3957
          return 0;
 
3958
        }
 
3959
      *ap++ = pp;
 
3960
 
 
3961
      debug1("- new arg %s\n", p);
 
3962
      while (*p)
 
3963
        {
 
3964
          if (*p == delim)
 
3965
            delim = 0;
 
3966
          else if (delim != '\'' && *p == '\\' && (p[1] == '\'' || p[1] == '"' || p[1] == '\\' || p[1] == '$' || p[1] == '#' || p[1] == '^' || (p[1] >= '0' && p[1] <= '7')))
 
3967
            {
 
3968
              p++;
 
3969
              if (*p >= '0' && *p <= '7')
 
3970
                {
 
3971
                  *pp = *p - '0';
 
3972
                  if (p[1] >= '0' && p[1] <= '7')
 
3973
                    {
 
3974
                      p++;
 
3975
                      *pp = (*pp << 3) | (*p - '0');
 
3976
                      if (p[1] >= '0' && p[1] <= '7')
 
3977
                        {
 
3978
                          p++;
 
3979
                          *pp = (*pp << 3) | (*p - '0');
 
3980
                        }
 
3981
                    }
 
3982
                  pp++;
 
3983
                }
 
3984
              else
 
3985
                *pp++ = *p;
 
3986
            }
 
3987
          else if (delim != '\'' && *p == '$' && (p[1] == '{' || p[1] == ':' || (p[1] >= 'a' && p[1] <= 'z') || (p[1] >= 'A' && p[1] <= 'Z') || (p[1] >= '0' && p[1] <= '9') || p[1] == '_'))
 
3988
 
 
3989
            {
 
3990
              char *ps, *pe, op, *v, xbuf[11];
 
3991
              int vl;
 
3992
 
 
3993
              ps = ++p;
 
3994
              debug1("- var %s\n", ps);
 
3995
              p++;
 
3996
              while (*p)
 
3997
                {
 
3998
                  if (*ps == '{' && *p == '}')
 
3999
                    break;
 
4000
                  if (*ps == ':' && *p == ':')
 
4001
                    break;
 
4002
                  if (*ps != '{' && *ps != ':' && (*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z') && (*p < '0' || *p > '9') && *p != '_')
 
4003
                    break;
 
4004
                  p++;
 
4005
                }
 
4006
              pe = p;
 
4007
              if (*ps == '{' || *ps == ':')
 
4008
                {
 
4009
                  if (!*p)
 
4010
                    {
 
4011
                      Msg(0, "%s: bad variable name.", rc_name);
 
4012
                      return 0;
 
4013
                    }
 
4014
                  p++;
 
4015
                }
 
4016
              op = *pe;
 
4017
              *pe = 0;
 
4018
              debug1("- var is '%s'\n", ps);
 
4019
              if (*ps == ':')
 
4020
                v = gettermcapstring(ps + 1);
 
4021
              else
 
4022
                {
 
4023
                  if (*ps == '{')
 
4024
                    ps++;
 
4025
                  v = xbuf;
 
4026
                  if (!strcmp(ps, "TERM"))
 
4027
                    v = display ? D_termname : "unknown";
 
4028
                  else if (!strcmp(ps, "COLUMNS"))
 
4029
                    sprintf(xbuf, "%d", display ? D_width : -1);
 
4030
                  else if (!strcmp(ps, "LINES"))
 
4031
                    sprintf(xbuf, "%d", display ? D_height : -1);
 
4032
                  else
 
4033
                    v = getenv(ps);
 
4034
                }
 
4035
              *pe = op;
 
4036
              vl = v ? strlen(v) : 0;
 
4037
              if (vl)
 
4038
                {
 
4039
                  debug1("- sub is '%s'\n", v);
 
4040
                  if (p - pp < vl)
 
4041
                    {
 
4042
                      int right = buf + bufl - (p + strlen(p) + 1);
 
4043
                      if (right > 0)
 
4044
                        {
 
4045
                          bcopy(p, p + right, strlen(p) + 1);
 
4046
                          p += right;
 
4047
                        }
 
4048
                    }
 
4049
                  if (p - pp < vl)
 
4050
                    {
 
4051
                      Msg(0, "%s: no space left for variable expansion.", rc_name);
 
4052
                      return 0;
 
4053
                    }
 
4054
                  bcopy(v, pp, vl);
 
4055
                  pp += vl;
 
4056
                }
 
4057
              continue;
 
4058
            }
 
4059
          else if (delim != '\'' && *p == '^' && p[1])
 
4060
            {
 
4061
              p++;
 
4062
              *pp++ = *p == '?' ? '\177' : *p & 0x1f;
 
4063
            }
 
4064
          else if (delim == 0 && (*p == '\'' || *p == '"'))
 
4065
            delim = *p;
 
4066
          else if (delim == 0 && (*p == ' ' || *p == '\t' || *p == '\n'))
 
4067
            break;
 
4068
          else
 
4069
            *pp++ = *p;
 
4070
          p++;
 
4071
        }
 
4072
      if (delim)
 
4073
        {
 
4074
          Msg(0, "%s: Missing %c quote.", rc_name, delim);
 
4075
          return 0;
 
4076
        }
 
4077
      if (*p)
 
4078
        p++;
 
4079
      *pp = 0;
 
4080
      debug2("- arg done, '%s' rest %s\n", ap[-1], p);
 
4081
      *lp++ = pp - ap[-1];
 
4082
      pp++;
 
4083
    }
 
4084
}
 
4085
 
 
4086
void
 
4087
SetEscape(u, e, me)
 
4088
struct acluser *u;
 
4089
int e, me;
 
4090
{
 
4091
  if (u)
 
4092
    {
 
4093
      u->u_Esc = e;
 
4094
      u->u_MetaEsc = me;
 
4095
    }
 
4096
  else
 
4097
    {
 
4098
      if (users)
 
4099
        {
 
4100
          if (DefaultEsc >= 0)
 
4101
            ClearAction(&ktab[DefaultEsc]);
 
4102
          if (DefaultMetaEsc >= 0)
 
4103
            ClearAction(&ktab[DefaultMetaEsc]);
 
4104
        }
 
4105
      DefaultEsc = e;
 
4106
      DefaultMetaEsc = me;
 
4107
      if (users)
 
4108
        {
 
4109
          if (DefaultEsc >= 0)
 
4110
            {
 
4111
              ClearAction(&ktab[DefaultEsc]);
 
4112
              ktab[DefaultEsc].nr = RC_OTHER;
 
4113
            }
 
4114
          if (DefaultMetaEsc >= 0)
 
4115
            {
 
4116
              ClearAction(&ktab[DefaultMetaEsc]);
 
4117
              ktab[DefaultMetaEsc].nr = RC_META;
 
4118
            }
 
4119
        }
 
4120
    }
 
4121
}
 
4122
 
 
4123
int
 
4124
ParseSwitch(act, var)
 
4125
struct action *act;
 
4126
int *var;
 
4127
{
 
4128
  if (*act->args == 0)
 
4129
    {
 
4130
      *var ^= 1;
 
4131
      return 0;
 
4132
    }
 
4133
  return ParseOnOff(act, var);
 
4134
}
 
4135
 
 
4136
static int
 
4137
ParseOnOff(act, var)
 
4138
struct action *act;
 
4139
int *var;
 
4140
{
 
4141
  register int num = -1;
 
4142
  char **args = act->args;
 
4143
 
 
4144
  if (args[1] == 0)
 
4145
    {
 
4146
      if (strcmp(args[0], "on") == 0)
 
4147
        num = 1;
 
4148
      else if (strcmp(args[0], "off") == 0)
 
4149
        num = 0;
 
4150
    }
 
4151
  if (num < 0)
 
4152
    {
 
4153
      Msg(0, "%s: %s: invalid argument. Give 'on' or 'off'", rc_name, comms[act->nr].name);
 
4154
      return -1;
 
4155
    }
 
4156
  *var = num;
 
4157
  return 0;
 
4158
}
 
4159
 
 
4160
int
 
4161
ParseSaveStr(act, var)
 
4162
struct action *act;
 
4163
char **var;
 
4164
{
 
4165
  char **args = act->args;
 
4166
  if (*args == 0 || args[1])
 
4167
    {
 
4168
      Msg(0, "%s: %s: one argument required.", rc_name, comms[act->nr].name);
 
4169
      return -1;
 
4170
    }
 
4171
  if (*var)
 
4172
    free(*var);
 
4173
  *var = SaveStr(*args);
 
4174
  return 0;
 
4175
}
 
4176
 
 
4177
int
 
4178
ParseNum(act, var)
 
4179
struct action *act;
 
4180
int *var;
 
4181
{
 
4182
  int i;
 
4183
  char *p, **args = act->args;
 
4184
 
 
4185
  p = *args;
 
4186
  if (p == 0 || *p == 0 || args[1])
 
4187
    {
 
4188
      Msg(0, "%s: %s: invalid argument. Give one argument.",
 
4189
          rc_name, comms[act->nr].name);
 
4190
      return -1;
 
4191
    }
 
4192
  i = 0; 
 
4193
  while (*p)
 
4194
    {
 
4195
      if (*p >= '0' && *p <= '9')
 
4196
        i = 10 * i + (*p - '0');
 
4197
      else
 
4198
        {
 
4199
          Msg(0, "%s: %s: invalid argument. Give numeric argument.",
 
4200
              rc_name, comms[act->nr].name);
 
4201
          return -1;
 
4202
        }    
 
4203
      p++;
 
4204
    }
 
4205
  debug1("ParseNum got %d\n", i);
 
4206
  *var = i;
 
4207
  return 0;
 
4208
}
 
4209
 
 
4210
static int
 
4211
ParseNum1000(act, var)
 
4212
struct action *act;
 
4213
int *var;
 
4214
{
 
4215
  int i;
 
4216
  char *p, **args = act->args;
 
4217
  int dig = 0;
 
4218
 
 
4219
  p = *args;
 
4220
  if (p == 0 || *p == 0 || args[1])
 
4221
    {
 
4222
      Msg(0, "%s: %s: invalid argument. Give one argument.",
 
4223
          rc_name, comms[act->nr].name);
 
4224
      return -1;
 
4225
    }
 
4226
  i = 0; 
 
4227
  while (*p)
 
4228
    {
 
4229
      if (*p >= '0' && *p <= '9')
 
4230
        {
 
4231
          if (dig < 4)
 
4232
            i = 10 * i + (*p - '0');
 
4233
          else if (dig == 4 && *p >= '5')
 
4234
            i++;
 
4235
          if (dig)
 
4236
            dig++;
 
4237
        }
 
4238
      else if (*p == '.' && !dig)
 
4239
        dig++;
 
4240
      else
 
4241
        {
 
4242
          Msg(0, "%s: %s: invalid argument. Give floating point argument.",
 
4243
              rc_name, comms[act->nr].name);
 
4244
          return -1;
 
4245
        }    
 
4246
      p++;
 
4247
    }
 
4248
  if (dig == 0)
 
4249
    i *= 1000;
 
4250
  else
 
4251
    while (dig++ < 4)
 
4252
      i *= 10;
 
4253
  if (i < 0)
 
4254
    i = (int)((unsigned int)~0 >> 1);
 
4255
  debug1("ParseNum1000 got %d\n", i);
 
4256
  *var = i;
 
4257
  return 0;
 
4258
}
 
4259
 
 
4260
static struct win *
 
4261
WindowByName(s)
 
4262
char *s;
 
4263
{
 
4264
  struct win *p;
 
4265
 
 
4266
  for (p = windows; p; p = p->w_next)
 
4267
    if (!strcmp(p->w_title, s))
 
4268
      return p;
 
4269
  for (p = windows; p; p = p->w_next)
 
4270
    if (!strncmp(p->w_title, s, strlen(s)))
 
4271
      return p;
 
4272
  return 0;
 
4273
}
 
4274
 
 
4275
static int
 
4276
WindowByNumber(str)
 
4277
char *str;
 
4278
{
 
4279
  int i;
 
4280
  char *s;
 
4281
 
 
4282
  for (i = 0, s = str; *s; s++)
 
4283
    {
 
4284
      if (*s < '0' || *s > '9')
 
4285
        break;
 
4286
      i = i * 10 + (*s - '0');
 
4287
    }
 
4288
  return *s ? -1 : i;
 
4289
}
 
4290
 
 
4291
/* 
 
4292
 * Get window number from Name or Number string.
 
4293
 * Numbers are tried first, then names, a prefix match suffices.
 
4294
 * Be careful when assigning numeric strings as WindowTitles.
 
4295
 */
 
4296
int
 
4297
WindowByNoN(str)
 
4298
char *str;
 
4299
{
 
4300
  int i;
 
4301
  struct win *p;
 
4302
  
 
4303
  if ((i = WindowByNumber(str)) < 0 || i >= MAXWIN)
 
4304
    {
 
4305
      if ((p = WindowByName(str)))
 
4306
        return p->w_number;
 
4307
      return -1;
 
4308
    }
 
4309
  return i;
 
4310
}
 
4311
 
 
4312
static int
 
4313
ParseWinNum(act, var)
 
4314
struct action *act;
 
4315
int *var;
 
4316
{
 
4317
  char **args = act->args;
 
4318
  int i = 0;
 
4319
 
 
4320
  if (*args == 0 || args[1])
 
4321
    {
 
4322
      Msg(0, "%s: %s: one argument required.", rc_name, comms[act->nr].name);
 
4323
      return -1;
 
4324
    }
 
4325
  
 
4326
  i = WindowByNoN(*args);
 
4327
  if (i < 0)
 
4328
    {
 
4329
      Msg(0, "%s: %s: invalid argument. Give window number or name.",
 
4330
          rc_name, comms[act->nr].name);
 
4331
      return -1;
 
4332
    }
 
4333
  debug1("ParseWinNum got %d\n", i);
 
4334
  *var = i;
 
4335
  return 0;
 
4336
}
 
4337
 
 
4338
static int
 
4339
ParseBase(act, p, var, base, bname)
 
4340
struct action *act;
 
4341
char *p;
 
4342
int *var;
 
4343
int base;
 
4344
char *bname;
 
4345
{
 
4346
  int i = 0;
 
4347
  int c;
 
4348
 
 
4349
  if (*p == 0)
 
4350
    {
 
4351
      Msg(0, "%s: %s: empty argument.", rc_name, comms[act->nr].name);
 
4352
      return -1;
 
4353
    }
 
4354
  while ((c = *p++))
 
4355
    {
 
4356
      if (c >= 'a' && c <= 'z')
 
4357
        c -= 'a' - 'A';
 
4358
      if (c >= 'A' && c <= 'Z')
 
4359
        c -= 'A' - ('0' + 10);
 
4360
      c -= '0';
 
4361
      if (c < 0 || c >= base)
 
4362
        {
 
4363
          Msg(0, "%s: %s: argument is not %s.", rc_name, comms[act->nr].name, bname);
 
4364
          return -1;
 
4365
        }    
 
4366
      i = base * i + c;
 
4367
    }
 
4368
  debug1("ParseBase got %d\n", i);
 
4369
  *var = i;
 
4370
  return 0;
 
4371
}
 
4372
 
 
4373
static int
 
4374
IsNum(s, base)
 
4375
register char *s;
 
4376
register int base;
 
4377
{
 
4378
  for (base += '0'; *s; ++s)
 
4379
    if (*s < '0' || *s > base)
 
4380
      return 0;
 
4381
  return 1;
 
4382
}
 
4383
 
 
4384
int
 
4385
IsNumColon(s, base, p, psize)
 
4386
int base, psize;
 
4387
char *s, *p;
 
4388
{
 
4389
  char *q;
 
4390
  if ((q = rindex(s, ':')) != 0)
 
4391
    {
 
4392
      strncpy(p, q + 1, psize - 1);
 
4393
      p[psize - 1] = '\0';
 
4394
      *q = '\0';
 
4395
    }
 
4396
  else
 
4397
    *p = '\0';
 
4398
  return IsNum(s, base);
 
4399
}
 
4400
 
 
4401
void
 
4402
SwitchWindow(n)
 
4403
int n;
 
4404
{
 
4405
  struct win *p;
 
4406
 
 
4407
  debug1("SwitchWindow %d\n", n);
 
4408
  if (n < 0 || n >= MAXWIN)
 
4409
    {
 
4410
      ShowWindows(-1);
 
4411
      return;
 
4412
    }
 
4413
  if ((p = wtab[n]) == 0)
 
4414
    {
 
4415
      ShowWindows(n);
 
4416
      return;
 
4417
    }
 
4418
  if (display == 0)
 
4419
    {
 
4420
      fore = p;
 
4421
      return;
 
4422
    }
 
4423
  if (p == D_fore)
 
4424
    {
 
4425
      Msg(0, "This IS window %d (%s).", n, p->w_title);
 
4426
      return;
 
4427
    }
 
4428
#ifdef MULTIUSER
 
4429
  if (AclCheckPermWin(D_user, ACL_READ, p))
 
4430
    {
 
4431
      Msg(0, "Access to window %d denied.", p->w_number);
 
4432
      return;
 
4433
    }
 
4434
#endif
 
4435
  SetForeWindow(p);
 
4436
  Activate(fore->w_norefresh);  
 
4437
}
 
4438
 
 
4439
 
 
4440
void
 
4441
SetCanvasWindow(cv, wi)
 
4442
struct canvas *cv;
 
4443
struct win *wi;
 
4444
{
 
4445
  struct win *p = 0, **pp;
 
4446
  struct layer *l;
 
4447
  struct canvas *cvp, **cvpp;
 
4448
 
 
4449
  l = cv->c_layer;
 
4450
  display = cv->c_display;
 
4451
 
 
4452
  if (l)
 
4453
    {
 
4454
      /* remove old layer */
 
4455
      for (cvpp = &l->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
 
4456
        if (cvp == cv)
 
4457
          break;
 
4458
      ASSERT(cvp);
 
4459
      *cvpp = cvp->c_lnext;
 
4460
 
 
4461
      p = Layer2Window(l);
 
4462
      l = cv->c_layer;
 
4463
      cv->c_layer = 0;
 
4464
 
 
4465
      if (p && cv == D_forecv)
 
4466
        {
 
4467
#ifdef MULTIUSER
 
4468
          ReleaseAutoWritelock(display, p);
 
4469
#endif
 
4470
          if (p->w_silence)
 
4471
            {
 
4472
              SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
 
4473
              evenq(&p->w_silenceev);
 
4474
            }
 
4475
          D_other = fore;
 
4476
          D_fore = 0;
 
4477
        }
 
4478
      if (l->l_cvlist == 0 && (p == 0 || l != p->w_savelayer))
 
4479
        KillLayerChain(l);
 
4480
    }
 
4481
 
 
4482
  /* find right layer to display on canvas */
 
4483
  if (wi)
 
4484
    {
 
4485
      l = &wi->w_layer;
 
4486
      if (wi->w_savelayer && (wi->w_blocked || wi->w_savelayer->l_cvlist == 0))
 
4487
        l = wi->w_savelayer;
 
4488
    }
 
4489
  else
 
4490
    l = &cv->c_blank;
 
4491
 
 
4492
  /* add our canvas to the layer's canvaslist */
 
4493
  cv->c_lnext = l->l_cvlist;
 
4494
  l->l_cvlist = cv;
 
4495
  cv->c_layer = l;
 
4496
  cv->c_xoff = cv->c_xs;
 
4497
  cv->c_yoff = cv->c_ys;
 
4498
  RethinkViewportOffsets(cv);
 
4499
 
 
4500
  if (flayer == 0)
 
4501
    flayer = l;
 
4502
 
 
4503
  if (wi && D_other == wi)
 
4504
    D_other = wi->w_next;       /* Might be 0, but that's OK. */
 
4505
  if (cv == D_forecv)
 
4506
    {
 
4507
      D_fore = wi;
 
4508
      fore = D_fore;    /* XXX ? */
 
4509
      if (wi)
 
4510
        {
 
4511
#ifdef MULTIUSER
 
4512
          ObtainAutoWritelock(display, wi);
 
4513
#endif
 
4514
          /*
 
4515
           * Place the window at the head of the most-recently-used list
 
4516
           */
 
4517
          if (windows != wi)
 
4518
            {
 
4519
              for (pp = &windows; (p = *pp); pp = &p->w_next)
 
4520
                if (p == wi)
 
4521
                  break;
 
4522
              ASSERT(p);
 
4523
              *pp = p->w_next;
 
4524
              p->w_next = windows;
 
4525
              windows = p;
 
4526
              WListLinkChanged();
 
4527
            }
 
4528
        }
 
4529
    }
 
4530
}
 
4531
 
 
4532
 
 
4533
/*
 
4534
 * SetForeWindow changes the window in the input focus of the display.
 
4535
 * Puts window wi in canvas display->d_forecv.
 
4536
 */
 
4537
void
 
4538
SetForeWindow(wi)
 
4539
struct win *wi;
 
4540
{
 
4541
  struct win *p;
 
4542
  if (display == 0)
 
4543
    {
 
4544
      fore = wi;
 
4545
      return;
 
4546
    }
 
4547
  p = Layer2Window(D_forecv->c_layer);
 
4548
  SetCanvasWindow(D_forecv, wi);
 
4549
  if (p)
 
4550
    WindowChanged(p, 'u');
 
4551
  if (wi)
 
4552
    WindowChanged(wi, 'u');
 
4553
  flayer = D_forecv->c_layer;
 
4554
  /* Activate called afterwards, so no RefreshHStatus needed */
 
4555
}
 
4556
 
 
4557
 
 
4558
/*****************************************************************/
 
4559
 
 
4560
/* 
 
4561
 *  Activate - make fore window active
 
4562
 *  norefresh = -1 forces a refresh, disregard all_norefresh then.
 
4563
 */
 
4564
void
 
4565
Activate(norefresh)
 
4566
int norefresh;
 
4567
{
 
4568
  debug1("Activate(%d)\n", norefresh);
 
4569
  if (display == 0)
 
4570
    return;
 
4571
  if (D_status)
 
4572
    {
 
4573
      Msg(0, "%s", ""); /* wait till mintime (keep gcc quiet) */
 
4574
      RemoveStatus();
 
4575
    }
 
4576
 
 
4577
  if (MayResizeLayer(D_forecv->c_layer))
 
4578
    ResizeLayer(D_forecv->c_layer, D_forecv->c_xe - D_forecv->c_xs + 1, D_forecv->c_ye - D_forecv->c_ys + 1, display);
 
4579
 
 
4580
  fore = D_fore;
 
4581
  if (fore)
 
4582
    {
 
4583
      /* XXX ? */
 
4584
      if (fore->w_monitor != MON_OFF)
 
4585
        fore->w_monitor = MON_ON;
 
4586
      fore->w_bell = BELL_ON;
 
4587
      WindowChanged(fore, 'f');
 
4588
 
 
4589
#if 0
 
4590
      if (ResizeDisplay(fore->w_width, fore->w_height))
 
4591
        {
 
4592
          debug2("Cannot resize from (%d,%d)", D_width, D_height);
 
4593
          debug2(" to (%d,%d) -> resize window\n", fore->w_width, fore->w_height);
 
4594
          DoResize(D_width, D_height);
 
4595
        }
 
4596
#endif
 
4597
    }
 
4598
  Redisplay(norefresh + all_norefresh);
 
4599
}
 
4600
 
 
4601
 
 
4602
static int
 
4603
NextWindow()
 
4604
{
 
4605
  register struct win **pp;
 
4606
  int n = fore ? fore->w_number : -1;
 
4607
 
 
4608
  for (pp = wtab + n + 1; pp != wtab + n; pp++)
 
4609
    {
 
4610
      if (pp == wtab + MAXWIN)
 
4611
        pp = wtab;
 
4612
      if (*pp)
 
4613
        break;
 
4614
    }
 
4615
  return pp - wtab;
 
4616
}
 
4617
 
 
4618
static int
 
4619
PreviousWindow()
 
4620
{
 
4621
  register struct win **pp;
 
4622
  int n = fore ? fore->w_number : MAXWIN - 1;
 
4623
 
 
4624
  for (pp = wtab + n - 1; pp != wtab + n; pp--)
 
4625
    {
 
4626
      if (pp < wtab)
 
4627
        pp = wtab + MAXWIN - 1;
 
4628
      if (*pp)
 
4629
        break;
 
4630
    }
 
4631
  return pp - wtab;
 
4632
}
 
4633
 
 
4634
static int
 
4635
MoreWindows()
 
4636
{
 
4637
  char *m = "No other window.";
 
4638
  if (windows && (fore == 0 || windows->w_next))
 
4639
    return 1;
 
4640
  if (fore == 0)
 
4641
    {
 
4642
      Msg(0, "No window available");
 
4643
      return 0;
 
4644
    }
 
4645
  Msg(0, m, fore->w_number);    /* other arg for nethack */
 
4646
  return 0;
 
4647
}
 
4648
 
 
4649
void
 
4650
KillWindow(wi)
 
4651
struct win *wi;
 
4652
{
 
4653
  struct win **pp, *p;
 
4654
  struct canvas *cv;
 
4655
  int gotone;
 
4656
 
 
4657
  /*
 
4658
   * Remove window from linked list.
 
4659
   */
 
4660
  for (pp = &windows; (p = *pp); pp = &p->w_next)
 
4661
    if (p == wi)
 
4662
      break;
 
4663
  ASSERT(p);
 
4664
  *pp = p->w_next;
 
4665
  wi->w_inlen = 0;
 
4666
  wtab[wi->w_number] = 0;
 
4667
 
 
4668
  if (windows == 0)
 
4669
    {
 
4670
      FreeWindow(wi);
 
4671
      Finit(0);
 
4672
    }
 
4673
 
 
4674
  /*
 
4675
   * switch to different window on all canvases
 
4676
   */
 
4677
  for (display = displays; display; display = display->d_next)
 
4678
    {
 
4679
      gotone = 0;
 
4680
      for (cv = D_cvlist; cv; cv = cv->c_next)
 
4681
        {
 
4682
          if (Layer2Window(cv->c_layer) != wi)
 
4683
            continue;
 
4684
          /* switch to other window */
 
4685
          SetCanvasWindow(cv, FindNiceWindow(D_other, 0));
 
4686
          gotone = 1;
 
4687
        }
 
4688
      if (gotone)
 
4689
        {
 
4690
#ifdef ZMODEM
 
4691
          if (wi->w_zdisplay == display)
 
4692
            {
 
4693
              D_blocked = 0;
 
4694
              D_readev.condpos = D_readev.condneg = 0;
 
4695
            }
 
4696
#endif
 
4697
          Activate(-1);
 
4698
        }
 
4699
    }
 
4700
  FreeWindow(wi);
 
4701
  WindowChanged((struct win *)0, 'w');
 
4702
  WindowChanged((struct win *)0, 'W');
 
4703
  WindowChanged((struct win *)0, 0);
 
4704
}
 
4705
 
 
4706
static void
 
4707
LogToggle(on)
 
4708
int on;
 
4709
{
 
4710
  char buf[1024];
 
4711
 
 
4712
  if ((fore->w_log != 0) == on)
 
4713
    {
 
4714
      if (display && !*rc_name)
 
4715
        Msg(0, "You are %s logging.", on ? "already" : "not");
 
4716
      return;
 
4717
    }
 
4718
  if (fore->w_log != 0)
 
4719
    {
 
4720
      Msg(0, "Logfile \"%s\" closed.", fore->w_log->name);
 
4721
      logfclose(fore->w_log);
 
4722
      fore->w_log = 0;
 
4723
      WindowChanged(fore, 'f');
 
4724
      return;
 
4725
    }
 
4726
  if (DoStartLog(fore, buf, sizeof(buf)))
 
4727
    {
 
4728
      Msg(errno, "Error opening logfile \"%s\"", buf);
 
4729
      return;
 
4730
    }
 
4731
  if (ftell(fore->w_log->fp) == 0)
 
4732
    Msg(0, "Creating logfile \"%s\".", fore->w_log->name);
 
4733
  else
 
4734
    Msg(0, "Appending to logfile \"%s\".", fore->w_log->name);
 
4735
  WindowChanged(fore, 'f');
 
4736
}
 
4737
 
 
4738
char *
 
4739
AddWindows(buf, len, flags, where)
 
4740
char *buf;
 
4741
int len;
 
4742
int flags;
 
4743
int where;
 
4744
{
 
4745
  register char *s, *ss;
 
4746
  register struct win **pp, *p;
 
4747
  register char *cmd;
 
4748
  int l;
 
4749
 
 
4750
  s = ss = buf;
 
4751
  for (pp = ((flags & 4) && where >= 0) ? wtab + where + 1: wtab; pp < wtab + MAXWIN; pp++)
 
4752
    {
 
4753
      if (pp - wtab == where && ss == buf)
 
4754
        ss = s;
 
4755
      if ((p = *pp) == 0)
 
4756
        continue;
 
4757
      if ((flags & 1) && display && p == D_fore)
 
4758
        continue;
 
4759
 
 
4760
      cmd = p->w_title;
 
4761
      l = strlen(cmd);
 
4762
      if (l > 20)
 
4763
        l = 20;
 
4764
      if (s - buf + l > len - 24)
 
4765
        break;
 
4766
      if (s > buf || (flags & 4))
 
4767
        {
 
4768
          *s++ = ' ';
 
4769
          *s++ = ' ';
 
4770
        }
 
4771
      sprintf(s, "%d", p->w_number);
 
4772
      if (p->w_number == where)
 
4773
        ss = s;
 
4774
      s += strlen(s);
 
4775
      if (display && p == D_fore)
 
4776
        *s++ = '*';
 
4777
      if (!(flags & 2))
 
4778
        {
 
4779
          if (display && p == D_other)
 
4780
            *s++ = '-';
 
4781
          s = AddWindowFlags(s, len, p);
 
4782
        }
 
4783
      *s++ = ' ';
 
4784
      strncpy(s, cmd, l);
 
4785
      s += l;
 
4786
    }
 
4787
  *s = 0;
 
4788
  return ss;
 
4789
}
 
4790
 
 
4791
char *
 
4792
AddWindowFlags(buf, len, p)
 
4793
char *buf;
 
4794
int len;
 
4795
struct win *p;
 
4796
{
 
4797
  char *s = buf;
 
4798
  if (p == 0 || len < 12)
 
4799
    {
 
4800
      *s = 0;
 
4801
      return s;
 
4802
    }
 
4803
#if 0
 
4804
  if (display && p == D_fore)
 
4805
    *s++ = '*';
 
4806
  if (display && p == D_other)
 
4807
    *s++ = '-';
 
4808
#endif
 
4809
  if (p->w_layer.l_cvlist && p->w_layer.l_cvlist->c_lnext)
 
4810
    *s++ = '&';
 
4811
  if (p->w_monitor == MON_DONE)
 
4812
    *s++ = '@';
 
4813
  if (p->w_bell == BELL_DONE)
 
4814
    *s++ = '!';
 
4815
#ifdef UTMPOK
 
4816
  if (p->w_slot != (slot_t) 0 && p->w_slot != (slot_t) -1)
 
4817
    *s++ = '$';
 
4818
#endif
 
4819
  if (p->w_log != 0)
 
4820
    {
 
4821
      strcpy(s, "(L)");
 
4822
      s += 3;
 
4823
    }
 
4824
  if (p->w_ptyfd < 0)
 
4825
    *s++ = 'Z';
 
4826
  *s = 0;
 
4827
  return s;
 
4828
}
 
4829
 
 
4830
char *
 
4831
AddOtherUsers(buf, len, p)
 
4832
char *buf;
 
4833
int len;
 
4834
struct win *p;
 
4835
{
 
4836
  struct display *d, *olddisplay = display;
 
4837
  struct canvas *cv;
 
4838
  char *s;
 
4839
  int l;
 
4840
 
 
4841
  s = buf;
 
4842
  for (display = displays; display; display = display->d_next)
 
4843
    {
 
4844
      if (D_user == olddisplay->d_user)
 
4845
        continue;
 
4846
      for (cv = D_cvlist; cv; cv = cv->c_next)
 
4847
        if (Layer2Window(cv->c_layer) == p)
 
4848
          break;
 
4849
      if (!cv)
 
4850
        continue;
 
4851
      for (d = displays; d && d != display; d = d->d_next)
 
4852
        if (D_user == d->d_user)
 
4853
          break;
 
4854
      if (d && d != display)
 
4855
        continue;
 
4856
      if (len > 1 && s != buf)
 
4857
        {
 
4858
          *s++ = ',';
 
4859
          len--;
 
4860
        }
 
4861
      l = strlen(D_user->u_name);
 
4862
      if (l + 1 > len)
 
4863
        break;
 
4864
      strcpy(s, D_user->u_name);
 
4865
      s += l;
 
4866
      len -= l;
 
4867
    }
 
4868
  *s = 0;
 
4869
  display = olddisplay;
 
4870
  return s;
 
4871
}
 
4872
 
 
4873
void
 
4874
ShowWindows(where)
 
4875
int where;
 
4876
{
 
4877
  char buf[1024];
 
4878
  char *s, *ss;
 
4879
 
 
4880
  if (!display)
 
4881
    return;
 
4882
  if (where == -1 && D_fore)
 
4883
    where = D_fore->w_number;
 
4884
  ss = AddWindows(buf, sizeof(buf), 0, where);
 
4885
  s = buf + strlen(buf);
 
4886
  if (ss - buf > D_width / 2)
 
4887
    {
 
4888
      ss -= D_width / 2;
 
4889
      if (s - ss < D_width)
 
4890
        {
 
4891
          ss = s - D_width;
 
4892
          if (ss < buf)
 
4893
            ss = buf;
 
4894
        }
 
4895
    }
 
4896
  else
 
4897
    ss = buf;
 
4898
  Msg(0, "%s", ss);
 
4899
}
 
4900
 
 
4901
static void
 
4902
ShowInfo()
 
4903
{
 
4904
  char buf[512], *p;
 
4905
  register struct win *wp = fore;
 
4906
  register int i;
 
4907
 
 
4908
  if (wp == 0)
 
4909
    {
 
4910
      Msg(0, "(%d,%d)/(%d,%d) no window", D_x + 1, D_y + 1, D_width, D_height);
 
4911
      return;
 
4912
    }
 
4913
  p = buf;
 
4914
  if (buf < (p += GetAnsiStatus(wp, p)))
 
4915
    *p++ = ' ';
 
4916
  sprintf(p, "(%d,%d)/(%d,%d)",
 
4917
    wp->w_x + 1, wp->w_y + 1, wp->w_width, wp->w_height);
 
4918
#ifdef COPY_PASTE
 
4919
  sprintf(p += strlen(p), "+%d", wp->w_histheight);
 
4920
#endif
 
4921
  sprintf(p += strlen(p), " %c%sflow",
 
4922
          (wp->w_flow & FLOW_NOW) ? '+' : '-',
 
4923
          (wp->w_flow & FLOW_AUTOFLAG) ? "" : 
 
4924
           ((wp->w_flow & FLOW_AUTO) ? "(+)" : "(-)"));
 
4925
  if (!wp->w_wrap) sprintf(p += strlen(p), " -wrap");
 
4926
  if (wp->w_insert) sprintf(p += strlen(p), " ins");
 
4927
  if (wp->w_origin) sprintf(p += strlen(p), " org");
 
4928
  if (wp->w_keypad) sprintf(p += strlen(p), " app");
 
4929
  if (wp->w_log)    sprintf(p += strlen(p), " log");
 
4930
  if (wp->w_monitor != MON_OFF) sprintf(p += strlen(p), " mon");
 
4931
  if (wp->w_mouse) sprintf(p += strlen(p), " mouse");
 
4932
#ifdef COLOR
 
4933
  if (wp->w_bce) sprintf(p += strlen(p), " bce");
 
4934
#endif
 
4935
  if (!wp->w_c1) sprintf(p += strlen(p), " -c1");
 
4936
  if (wp->w_norefresh) sprintf(p += strlen(p), " nored");
 
4937
 
 
4938
  p += strlen(p);
 
4939
#ifdef FONT
 
4940
# ifdef ENCODINGS
 
4941
  if (wp->w_encoding && (display == 0 || D_encoding != wp->w_encoding || EncodingDefFont(wp->w_encoding) <= 0))
 
4942
    {
 
4943
      *p++ = ' ';
 
4944
      strcpy(p, EncodingName(wp->w_encoding));
 
4945
      p += strlen(p);
 
4946
    }
 
4947
#  ifdef UTF8
 
4948
  if (wp->w_encoding != UTF8)
 
4949
#  endif
 
4950
# endif
 
4951
    if (D_CC0 || (D_CS0 && *D_CS0))
 
4952
      {
 
4953
        if (wp->w_gr == 2)
 
4954
          {
 
4955
            sprintf(p, " G%c", wp->w_Charset + '0');
 
4956
            if (wp->w_FontE >= ' ')
 
4957
              p[3] = wp->w_FontE;
 
4958
            else
 
4959
              {
 
4960
                p[3] = '^';
 
4961
                p[4] = wp->w_FontE ^ 0x40;
 
4962
                p++;
 
4963
              }
 
4964
            p[4] = '[';
 
4965
            p++;
 
4966
          }
 
4967
        else if (wp->w_gr)
 
4968
          sprintf(p++, " G%c%c[", wp->w_Charset + '0', wp->w_CharsetR + '0');
 
4969
        else
 
4970
          sprintf(p, " G%c[", wp->w_Charset + '0');
 
4971
        p += 4;
 
4972
        for (i = 0; i < 4; i++)
 
4973
          {
 
4974
            if (wp->w_charsets[i] == ASCII)
 
4975
              *p++ = 'B';
 
4976
            else if (wp->w_charsets[i] >= ' ')
 
4977
              *p++ = wp->w_charsets[i];
 
4978
            else
 
4979
              {
 
4980
                *p++ = '^';
 
4981
                *p++ = wp->w_charsets[i] ^ 0x40;
 
4982
              }
 
4983
          }
 
4984
        *p++ = ']';
 
4985
        *p = 0;
 
4986
      }
 
4987
#endif
 
4988
 
 
4989
  if (wp->w_type == W_TYPE_PLAIN)
 
4990
    {
 
4991
      /* add info about modem control lines */
 
4992
      *p++ = ' ';
 
4993
      TtyGetModemStatus(wp->w_ptyfd, p);
 
4994
    }
 
4995
#ifdef BUILTIN_TELNET
 
4996
  else if (wp->w_type == W_TYPE_TELNET)
 
4997
    {
 
4998
      *p++ = ' ';
 
4999
      TelStatus(wp, p, sizeof(buf) - 1 - (p - buf));
 
5000
    }
 
5001
#endif
 
5002
  Msg(0, "%s %d(%s)", buf, wp->w_number, wp->w_title);
 
5003
}
 
5004
 
 
5005
static void
 
5006
ShowDInfo()
 
5007
{
 
5008
  char buf[512], *p;
 
5009
  if (display == 0)
 
5010
    return;
 
5011
  p = buf;
 
5012
  sprintf(p, "(%d,%d)", D_width, D_height),
 
5013
  p += strlen(p);
 
5014
#ifdef ENCODINGS
 
5015
  if (D_encoding)
 
5016
    {
 
5017
      *p++ = ' ';
 
5018
      strcpy(p, EncodingName(D_encoding));
 
5019
      p += strlen(p);
 
5020
    }
 
5021
#endif
 
5022
  if (D_CXT)
 
5023
    {
 
5024
      strcpy(p, " xterm");
 
5025
      p += strlen(p);
 
5026
    }
 
5027
#ifdef COLOR
 
5028
  if (D_hascolor)
 
5029
    {
 
5030
      strcpy(p, " color");
 
5031
      p += strlen(p);
 
5032
    }
 
5033
#endif
 
5034
#ifdef FONT
 
5035
  if (D_CG0)
 
5036
    {
 
5037
      strcpy(p, " iso2022");
 
5038
      p += strlen(p);
 
5039
    }
 
5040
  else if (D_CS0 && *D_CS0)
 
5041
    {
 
5042
      strcpy(p, " altchar");
 
5043
      p += strlen(p);
 
5044
    }
 
5045
#endif
 
5046
  Msg(0, "%s", buf);
 
5047
}
 
5048
 
 
5049
static void
 
5050
AKAfin(buf, len, data)
 
5051
char *buf;
 
5052
int len;
 
5053
char *data;     /* dummy */
 
5054
{
 
5055
  ASSERT(display);
 
5056
  if (len && fore)
 
5057
    ChangeAKA(fore, buf, strlen(buf));
 
5058
}
 
5059
 
 
5060
static void
 
5061
InputAKA()
 
5062
{
 
5063
  char *s, *ss;
 
5064
  int n;
 
5065
  Input("Set window's title to: ", sizeof(fore->w_akabuf) - 1, INP_COOKED, AKAfin, NULL);
 
5066
  s = fore->w_title;
 
5067
  if (!s)
 
5068
    return;
 
5069
  for (; *s; s++)
 
5070
    {
 
5071
      if ((*(unsigned char *)s & 0x7f) < 0x20 || *s == 0x7f)
 
5072
        continue;
 
5073
      ss = s;
 
5074
      n = 1;
 
5075
      LayProcess(&ss, &n);
 
5076
    }
 
5077
}
 
5078
 
 
5079
static void
 
5080
Colonfin(buf, len, data)
 
5081
char *buf;
 
5082
int len;
 
5083
char *data;     /* dummy */
 
5084
{
 
5085
  char mbuf[256];
 
5086
  if (len)
 
5087
    {
 
5088
      len = strlen(buf) + 1;
 
5089
      if (len > (int)sizeof(mbuf))
 
5090
        RcLine(buf, len);
 
5091
      else
 
5092
        {
 
5093
          bcopy(buf, mbuf, len);
 
5094
          RcLine(mbuf, sizeof mbuf);
 
5095
        }
 
5096
    }
 
5097
}
 
5098
 
 
5099
static void
 
5100
SelectFin(buf, len, data)
 
5101
char *buf;
 
5102
int len;
 
5103
char *data;     /* dummy */
 
5104
{
 
5105
  int n;
 
5106
 
 
5107
  if (!len || !display)
 
5108
    return;
 
5109
  if (len == 1 && *buf == '-')
 
5110
    {
 
5111
      SetForeWindow((struct win *)0);
 
5112
      Activate(0);
 
5113
      return;
 
5114
    }
 
5115
  if ((n = WindowByNoN(buf)) < 0)
 
5116
    return;
 
5117
  SwitchWindow(n);
 
5118
}
 
5119
    
 
5120
static void
 
5121
InputSelect()
 
5122
{
 
5123
  Input("Switch to window: ", 20, INP_COOKED, SelectFin, NULL);
 
5124
}
 
5125
 
 
5126
static char setenv_var[31];
 
5127
 
 
5128
 
 
5129
static void
 
5130
SetenvFin1(buf, len, data)
 
5131
char *buf;
 
5132
int len;
 
5133
char *data;     /* dummy */
 
5134
{
 
5135
  if (!len || !display)
 
5136
    return;
 
5137
  InputSetenv(buf);
 
5138
}
 
5139
  
 
5140
static void
 
5141
SetenvFin2(buf, len, data)
 
5142
char *buf;
 
5143
int len;
 
5144
char *data;     /* dummy */
 
5145
{
 
5146
  if (!len || !display)
 
5147
    return;
 
5148
  debug2("SetenvFin2: setenv '%s' '%s'\n", setenv_var, buf);
 
5149
  xsetenv(setenv_var, buf);
 
5150
  MakeNewEnv();
 
5151
}
 
5152
 
 
5153
static void
 
5154
InputSetenv(arg)
 
5155
char *arg;
 
5156
{
 
5157
  static char setenv_buf[50 + sizeof(setenv_var)];      /* need to be static here, cannot be freed */
 
5158
 
 
5159
  if (arg)
 
5160
    {
 
5161
      strncpy(setenv_var, arg, sizeof(setenv_var) - 1);
 
5162
      sprintf(setenv_buf, "Enter value for %s: ", setenv_var);
 
5163
      Input(setenv_buf, 30, INP_COOKED, SetenvFin2, NULL);
 
5164
    }
 
5165
  else
 
5166
    Input("Setenv: Enter variable name: ", 30, INP_COOKED, SetenvFin1, NULL);
 
5167
}
 
5168
 
 
5169
/*
 
5170
 * the following options are understood by this parser:
 
5171
 * -f, -f0, -f1, -fy, -fa
 
5172
 * -t title, -T terminal-type, -h height-of-scrollback, 
 
5173
 * -ln, -l0, -ly, -l1, -l
 
5174
 * -a, -M, -L
 
5175
 */
 
5176
void
 
5177
DoScreen(fn, av)
 
5178
char *fn, **av;
 
5179
{
 
5180
  struct NewWindow nwin;
 
5181
  register int num;
 
5182
  char buf[20];
 
5183
 
 
5184
  nwin = nwin_undef;
 
5185
  while (av && *av && av[0][0] == '-')
 
5186
    {
 
5187
      if (av[0][1] == '-')
 
5188
        {
 
5189
          av++;
 
5190
          break;
 
5191
        }
 
5192
      switch (av[0][1])
 
5193
        {
 
5194
        case 'f':
 
5195
          switch (av[0][2])
 
5196
            {
 
5197
            case 'n':
 
5198
            case '0':
 
5199
              nwin.flowflag = FLOW_NOW * 0;
 
5200
              break;
 
5201
            case 'y':
 
5202
            case '1':
 
5203
            case '\0':
 
5204
              nwin.flowflag = FLOW_NOW * 1;
 
5205
              break;
 
5206
            case 'a':
 
5207
              nwin.flowflag = FLOW_AUTOFLAG;
 
5208
              break;
 
5209
            default:
 
5210
              break;
 
5211
            }
 
5212
          break;
 
5213
        case 't':       /* no more -k */
 
5214
          if (av[0][2])
 
5215
            nwin.aka = &av[0][2];
 
5216
          else if (*++av)
 
5217
            nwin.aka = *av;
 
5218
          else
 
5219
            --av;
 
5220
          break;
 
5221
        case 'T':
 
5222
          if (av[0][2])
 
5223
            nwin.term = &av[0][2];
 
5224
          else if (*++av)
 
5225
            nwin.term = *av;
 
5226
          else
 
5227
            --av;
 
5228
          break;
 
5229
        case 'h':
 
5230
          if (av[0][2])
 
5231
            nwin.histheight = atoi(av[0] + 2);
 
5232
          else if (*++av)
 
5233
            nwin.histheight = atoi(*av);
 
5234
          else 
 
5235
            --av;
 
5236
          break;
 
5237
#ifdef LOGOUTOK
 
5238
        case 'l':
 
5239
          switch (av[0][2])
 
5240
            {
 
5241
            case 'n':
 
5242
            case '0':
 
5243
              nwin.lflag = 0;
 
5244
              break;
 
5245
            case 'y':
 
5246
            case '1':
 
5247
            case '\0':
 
5248
              nwin.lflag = 1;
 
5249
              break;
 
5250
            case 'a':
 
5251
              nwin.lflag = 3;
 
5252
              break;
 
5253
            default:
 
5254
              break;
 
5255
            }
 
5256
          break;
 
5257
#endif
 
5258
        case 'a':
 
5259
          nwin.aflag = 1;
 
5260
          break;
 
5261
        case 'M':
 
5262
          nwin.monitor = MON_ON;
 
5263
          break;
 
5264
        case 'L':
 
5265
          nwin.Lflag = 1;
 
5266
          break;
 
5267
        default:
 
5268
          Msg(0, "%s: screen: invalid option -%c.", fn, av[0][1]);
 
5269
          break;
 
5270
        }
 
5271
      ++av;
 
5272
    }
 
5273
  num = 0;
 
5274
  if (av && *av && IsNumColon(*av, 10, buf, sizeof(buf)))
 
5275
    {
 
5276
      if (*buf != '\0')
 
5277
        nwin.aka = buf;
 
5278
      num = atoi(*av);
 
5279
      if (num < 0 || num > MAXWIN - 1)
 
5280
        {
 
5281
          Msg(0, "%s: illegal screen number %d.", fn, num);
 
5282
          num = 0;
 
5283
        }
 
5284
      nwin.StartAt = num;
 
5285
      ++av;
 
5286
    }
 
5287
  if (av && *av)
 
5288
    {
 
5289
      nwin.args = av;
 
5290
      if (!nwin.aka)
 
5291
        nwin.aka = Filename(*av);
 
5292
    }
 
5293
  MakeWindow(&nwin);
 
5294
}
 
5295
 
 
5296
#ifdef COPY_PASTE
 
5297
/*
 
5298
 * CompileKeys must be called before Markroutine is first used.
 
5299
 * to initialise the keys with defaults, call CompileKeys(NULL, mark_key_tab);
 
5300
 *
 
5301
 * s is an ascii string in a termcap-like syntax. It looks like
 
5302
 *   "j=u:k=d:l=r:h=l: =.:" and so on...
 
5303
 * this example rebinds the cursormovement to the keys u (up), d (down),
 
5304
 * l (left), r (right). placing a mark will now be done with ".".
 
5305
 */
 
5306
int
 
5307
CompileKeys(s, sl, array)
 
5308
char *s;
 
5309
int sl;
 
5310
unsigned char *array;
 
5311
{
 
5312
  int i;
 
5313
  unsigned char key, value;
 
5314
 
 
5315
  if (sl == 0)
 
5316
    {
 
5317
      for (i = 0; i < 256; i++)
 
5318
        array[i] = i;
 
5319
      return 0;
 
5320
    }
 
5321
  debug1("CompileKeys: '%s'\n", s);
 
5322
  while (sl)
 
5323
    {
 
5324
      key = *(unsigned char *)s++;
 
5325
      if (*s != '=' || sl < 3)
 
5326
        return -1;
 
5327
      sl--;
 
5328
      do 
 
5329
        {
 
5330
          s++;
 
5331
          sl -= 2;
 
5332
          value = *(unsigned char *)s++;
 
5333
          array[value] = key;
 
5334
        }
 
5335
      while (*s == '=' && sl >= 2);
 
5336
      if (sl == 0) 
 
5337
        break;
 
5338
      if (*s++ != ':')
 
5339
        return -1;
 
5340
      sl--;
 
5341
    }
 
5342
  return 0;
 
5343
}
 
5344
#endif /* COPY_PASTE */
 
5345
 
 
5346
/*
 
5347
 *  Asynchronous input functions
 
5348
 */
 
5349
 
 
5350
#if defined(DETACH) && defined(POW_DETACH)
 
5351
static void
 
5352
pow_detach_fn(buf, len, data)
 
5353
char *buf;
 
5354
int len;
 
5355
char *data;     /* dummy */
 
5356
{
 
5357
  debug("pow_detach_fn called\n");
 
5358
  if (len)
 
5359
    {
 
5360
      *buf = 0;
 
5361
      return;
 
5362
    }
 
5363
  if (ktab[(int)(unsigned char)*buf].nr != RC_POW_DETACH)
 
5364
    {
 
5365
      if (display)
 
5366
        write(D_userfd, "\007", 1);
 
5367
      Msg(0, "Detach aborted.");
 
5368
    }
 
5369
  else
 
5370
    Detach(D_POWER);
 
5371
}
 
5372
#endif /* POW_DETACH */
 
5373
 
 
5374
#ifdef COPY_PASTE
 
5375
static void
 
5376
copy_reg_fn(buf, len, data)
 
5377
char *buf;
 
5378
int len;
 
5379
char *data;     /* dummy */
 
5380
{
 
5381
  struct plop *pp = plop_tab + (int)(unsigned char)*buf;
 
5382
 
 
5383
  if (len)
 
5384
    {
 
5385
      *buf = 0;
 
5386
      return;
 
5387
    }
 
5388
  if (pp->buf)
 
5389
    free(pp->buf);
 
5390
  pp->buf = 0;
 
5391
  pp->len = 0;
 
5392
  if (D_user->u_plop.len)
 
5393
    {
 
5394
      if ((pp->buf = (char *)malloc(D_user->u_plop.len)) == NULL)
 
5395
        {
 
5396
          Msg(0, strnomem);
 
5397
          return;
 
5398
        }
 
5399
      bcopy(D_user->u_plop.buf, pp->buf, D_user->u_plop.len);
 
5400
    }
 
5401
  pp->len = D_user->u_plop.len;
 
5402
#ifdef ENCODINGS
 
5403
  pp->enc = D_user->u_plop.enc;
 
5404
#endif
 
5405
  Msg(0, "Copied %d characters into register %c", D_user->u_plop.len, *buf);
 
5406
}
 
5407
 
 
5408
static void
 
5409
ins_reg_fn(buf, len, data)
 
5410
char *buf;
 
5411
int len;
 
5412
char *data;     /* dummy */
 
5413
{
 
5414
  struct plop *pp = plop_tab + (int)(unsigned char)*buf;
 
5415
 
 
5416
 
 
5417
  if (!fore)
 
5418
    return;     /* Input() should not call us w/o fore, but you never know... */
 
5419
  if (*buf == '.')
 
5420
    Msg(0, "ins_reg_fn: Warning: pasting real register '.'!");
 
5421
  if (len)
 
5422
    {
 
5423
      *buf = 0;
 
5424
      return;
 
5425
    }
 
5426
  if (pp->buf)
 
5427
    {
 
5428
      MakePaster(&fore->w_paster, pp->buf, pp->len, 0);
 
5429
      return;
 
5430
    }
 
5431
  Msg(0, "Empty register.");
 
5432
}
 
5433
#endif /* COPY_PASTE */
 
5434
 
 
5435
static void
 
5436
process_fn(buf, len, data)
 
5437
char *buf;
 
5438
int len;
 
5439
char *data;     /* dummy */
 
5440
{
 
5441
  struct plop *pp = plop_tab + (int)(unsigned char)*buf;
 
5442
 
 
5443
  if (len)
 
5444
    {
 
5445
      *buf = 0;
 
5446
      return;
 
5447
    }
 
5448
  if (pp->buf)
 
5449
    {
 
5450
      ProcessInput(pp->buf, pp->len);
 
5451
      return;
 
5452
    }
 
5453
  Msg(0, "Empty register.");
 
5454
}
 
5455
 
 
5456
static void
 
5457
confirm_fn(buf, len, data)
 
5458
char *buf;
 
5459
int len;
 
5460
char *data;     /* dummy */
 
5461
{
 
5462
  struct action act;
 
5463
 
 
5464
  if (len || (*buf != 'y' && *buf != 'Y'))
 
5465
    {
 
5466
      *buf = 0;
 
5467
      return;
 
5468
    }
 
5469
  act.nr = (int)data;
 
5470
  act.args = noargs;
 
5471
  act.argl = 0;
 
5472
  DoAction(&act, -1);
 
5473
}
 
5474
 
 
5475
#ifdef MULTIUSER
 
5476
struct inputsu
 
5477
{
 
5478
  struct acluser **up;
 
5479
  char name[24];
 
5480
  char pw1[130];        /* FreeBSD crypts to 128 bytes */
 
5481
  char pw2[130];
 
5482
};
 
5483
 
 
5484
static void
 
5485
su_fin(buf, len, data)
 
5486
char *buf;
 
5487
int len;
 
5488
char *data;
 
5489
{
 
5490
  struct inputsu *i = (struct inputsu *)data;
 
5491
  char *p;
 
5492
  int l;
 
5493
 
 
5494
  if (!*i->name)
 
5495
    { p = i->name; l = sizeof(i->name) - 1; }
 
5496
  else if (!*i->pw1)
 
5497
    { strcpy(p = i->pw1, "\377"); l = sizeof(i->pw1) - 1; }
 
5498
  else
 
5499
    { strcpy(p = i->pw2, "\377"); l = sizeof(i->pw2) - 1; }
 
5500
  if (buf && len)
 
5501
    strncpy(p, buf, 1 + (l < len) ? l : len);
 
5502
  if (!*i->name)
 
5503
    Input("Screen User: ", sizeof(i->name) - 1, INP_COOKED, su_fin, (char *)i);
 
5504
  else if (!*i->pw1)
 
5505
    Input("User's UNIX Password: ", sizeof(i->pw1)-1, INP_COOKED|INP_NOECHO, su_fin, (char *)i);
 
5506
  else if (!*i->pw2)
 
5507
    Input("User's Screen Password: ", sizeof(i->pw2)-1, INP_COOKED|INP_NOECHO, su_fin, (char *)i);
 
5508
  else
 
5509
    {
 
5510
      if ((p = DoSu(i->up, i->name, i->pw2, i->pw1)))
 
5511
        Msg(0, "%s", p);
 
5512
      free((char *)i);
 
5513
    }
 
5514
}
 
5515
 
 
5516
static int
 
5517
InputSu(w, up, name)
 
5518
struct win *w;
 
5519
struct acluser **up;
 
5520
char *name;
 
5521
{
 
5522
  struct inputsu *i;
 
5523
 
 
5524
  if (!(i = (struct inputsu *)calloc(1, sizeof(struct inputsu))))
 
5525
    return -1;
 
5526
 
 
5527
  i->up = up;
 
5528
  if (name && *name)
 
5529
    su_fin(name, (int)strlen(name), (char *)i); /* can also initialise stuff */
 
5530
  else
 
5531
    su_fin((char *)0, 0, (char *)i);
 
5532
  return 0;
 
5533
}
 
5534
#endif  /* MULTIUSER */
 
5535
 
 
5536
#ifdef PASSWORD
 
5537
 
 
5538
static void
 
5539
pass1(buf, len, data)
 
5540
char *buf;
 
5541
int len;
 
5542
char *data;
 
5543
{
 
5544
  struct acluser *u = (struct acluser *)data;
 
5545
 
 
5546
  if (!*buf)
 
5547
    return;
 
5548
  ASSERT(u);
 
5549
  if (u->u_password != NullStr)
 
5550
    free((char *)u->u_password);
 
5551
  u->u_password = SaveStr(buf);
 
5552
  bzero(buf, strlen(buf));
 
5553
  Input("Retype new password:", 100, INP_NOECHO, pass2, data);
 
5554
}
 
5555
 
 
5556
static void
 
5557
pass2(buf, len, data)
 
5558
char *buf;
 
5559
int len;
 
5560
char *data;
 
5561
{
 
5562
  int st;
 
5563
  char salt[3];
 
5564
  struct acluser *u = (struct acluser *)data;
 
5565
 
 
5566
  ASSERT(u);
 
5567
  if (!buf || strcmp(u->u_password, buf))
 
5568
    {
 
5569
      Msg(0, "[ Passwords don't match - checking turned off ]");
 
5570
      if (u->u_password != NullStr)
 
5571
        {
 
5572
          bzero(u->u_password, strlen(u->u_password));
 
5573
          free((char *)u->u_password);
 
5574
        }
 
5575
      u->u_password = NullStr;
 
5576
    }
 
5577
  else if (u->u_password[0] == '\0')
 
5578
    {
 
5579
      Msg(0, "[ No password - no secure ]");
 
5580
      if (buf)
 
5581
        bzero(buf, strlen(buf));
 
5582
    }
 
5583
  
 
5584
  if (u->u_password != NullStr)
 
5585
    {
 
5586
      for (st = 0; st < 2; st++)
 
5587
        salt[st] = 'A' + (int)((time(0) >> 6 * st) % 26);
 
5588
      salt[2] = 0;
 
5589
      buf = crypt(u->u_password, salt);
 
5590
      bzero(u->u_password, strlen(u->u_password));
 
5591
      free((char *)u->u_password);
 
5592
      u->u_password = SaveStr(buf);
 
5593
      bzero(buf, strlen(buf));
 
5594
#ifdef COPY_PASTE
 
5595
      if (u->u_plop.buf)
 
5596
        UserFreeCopyBuffer(u);
 
5597
      u->u_plop.len = strlen(u->u_password);
 
5598
# ifdef ENCODINGS
 
5599
      u->u_plop.enc = 0;
 
5600
#endif
 
5601
      if (!(u->u_plop.buf = SaveStr(u->u_password)))
 
5602
        {
 
5603
          Msg(0, strnomem);
 
5604
          D_user->u_plop.len = 0;
 
5605
        }
 
5606
      else
 
5607
        Msg(0, "[ Password moved into copybuffer ]");
 
5608
#else                           /* COPY_PASTE */
 
5609
      Msg(0, "[ Crypted password is \"%s\" ]", u->u_password);
 
5610
#endif                          /* COPY_PASTE */
 
5611
    }
 
5612
}
 
5613
#endif /* PASSWORD */
 
5614
 
 
5615
static void
 
5616
digraph_fn(buf, len, data)
 
5617
char *buf;
 
5618
int len;
 
5619
char *data;     /* dummy */
 
5620
{
 
5621
  int ch, i, x;
 
5622
 
 
5623
  ch = buf[len];
 
5624
  if (ch)
 
5625
    {
 
5626
      if (ch < ' ' || ch == '\177')
 
5627
        return;
 
5628
      if (len >= 1 && ((*buf == 'U' && buf[1] == '+') || (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X'))))
 
5629
        {
 
5630
          if (len == 1)
 
5631
            return;
 
5632
          if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f') && (ch < 'A' || ch > 'F'))
 
5633
            {
 
5634
              buf[len] = '\034';        /* ^] is ignored by Input() */
 
5635
              return;
 
5636
            }
 
5637
          if (len == (*buf == 'U' ? 5 : 3))
 
5638
            buf[len] = '\n';
 
5639
          return;
 
5640
        }
 
5641
      if (len && *buf == '0')
 
5642
        {
 
5643
          if (ch < '0' || ch > '7')
 
5644
            {
 
5645
              buf[len] = '\034';        /* ^] is ignored by Input() */
 
5646
              return;
 
5647
            }
 
5648
          if (len == 3)
 
5649
            buf[len] = '\n';
 
5650
          return;
 
5651
        }
 
5652
      if (len == 1)
 
5653
        buf[len] = '\n';
 
5654
      return;
 
5655
    }
 
5656
  buf[len] = buf[len + 1];      /* gross */
 
5657
  len++;
 
5658
  if (len < 2)
 
5659
    return;
 
5660
  if (len >= 1 && ((*buf == 'U' && buf[1] == '+') || (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X'))))
 
5661
    {
 
5662
      x = 0;
 
5663
      for (i = 2; i < len; i++)
 
5664
        {
 
5665
          if (buf[i] >= '0' && buf[i] <= '9')
 
5666
            x = x * 16 | (buf[i] - '0');
 
5667
          else if (buf[i] >= 'a' && buf[i] <= 'f')
 
5668
            x = x * 16 | (buf[i] - ('a' - 10));
 
5669
          else if (buf[i] >= 'A' && buf[i] <= 'F')
 
5670
            x = x * 16 | (buf[i] - ('A' - 10));
 
5671
          else
 
5672
            break;
 
5673
        }
 
5674
    }
 
5675
  else if (buf[0] == '0')
 
5676
    {
 
5677
      x = 0;
 
5678
      for (i = 1; i < len; i++)
 
5679
        {
 
5680
          if (buf[i] < '0' || buf[i] > '7')
 
5681
            break;
 
5682
          x = x * 8 | (buf[i] - '0');
 
5683
        }
 
5684
    }
 
5685
  else
 
5686
    {
 
5687
      for (i = 0; i < (int)(sizeof(digraphs)/sizeof(*digraphs)); i++)
 
5688
        if ((digraphs[i][0] == (unsigned char)buf[0] && digraphs[i][1] == (unsigned char)buf[1]) ||
 
5689
            (digraphs[i][0] == (unsigned char)buf[1] && digraphs[i][1] == (unsigned char)buf[0]))
 
5690
          break;
 
5691
      if (i == (int)(sizeof(digraphs)/sizeof(*digraphs)))
 
5692
        {
 
5693
          Msg(0, "Unknown digraph");
 
5694
          return;
 
5695
        }
 
5696
      x = digraphs[i][2];
 
5697
    }
 
5698
  i = 1;
 
5699
  *buf = x;
 
5700
#ifdef UTF8
 
5701
  if (flayer->l_encoding == UTF8)
 
5702
    i = ToUtf8(buf, x); /* buf is big enough for all UTF-8 codes */
 
5703
#endif
 
5704
  while(i)
 
5705
    LayProcess(&buf, &i);
 
5706
}
 
5707
 
 
5708
#ifdef MAPKEYS
 
5709
int
 
5710
StuffKey(i)
 
5711
int i;
 
5712
{
 
5713
  struct action *act;
 
5714
 
 
5715
  debug1("StuffKey #%d", i);
 
5716
#ifdef DEBUG
 
5717
  if (i < KMAP_KEYS)
 
5718
    debug1(" - %s", term[i + T_CAPS].tcname);
 
5719
#endif
 
5720
  if (i >= T_CURSOR - T_CAPS && i < T_KEYPAD - T_CAPS && D_cursorkeys)
 
5721
    i += T_OCAPS - T_CURSOR;
 
5722
  else if (i >= T_KEYPAD - T_CAPS && i < T_OCAPS - T_CAPS && D_keypad)
 
5723
    i += T_OCAPS - T_CURSOR;
 
5724
  debug1(" - action %d\n", i);
 
5725
  flayer = D_forecv->c_layer;
 
5726
  fore = D_fore;
 
5727
  act = 0;
 
5728
#ifdef COPY_PASTE
 
5729
  if (InMark() || InInput() || InWList())
 
5730
    act = i < KMAP_KEYS+KMAP_AKEYS ? &mmtab[i] : &kmap_exts[i - (KMAP_KEYS+KMAP_AKEYS)].mm;
 
5731
#endif
 
5732
  if ((!act || act->nr == RC_ILLEGAL) && !D_mapdefault)
 
5733
    act = i < KMAP_KEYS+KMAP_AKEYS ? &umtab[i] : &kmap_exts[i - (KMAP_KEYS+KMAP_AKEYS)].um;
 
5734
  D_mapdefault = 0;
 
5735
  if (!act || act->nr == RC_ILLEGAL)
 
5736
    act = i < KMAP_KEYS+KMAP_AKEYS ? &dmtab[i] : &kmap_exts[i - (KMAP_KEYS+KMAP_AKEYS)].dm;
 
5737
  if (act == 0 || act->nr == RC_ILLEGAL)
 
5738
    return -1;
 
5739
  DoAction(act, 0);
 
5740
  return 0;
 
5741
}
 
5742
#endif
 
5743
 
 
5744
 
 
5745
static int
 
5746
IsOnDisplay(wi)
 
5747
struct win *wi;
 
5748
{
 
5749
  struct canvas *cv;
 
5750
  ASSERT(display);
 
5751
  for (cv = D_cvlist; cv; cv = cv->c_next)
 
5752
    if (Layer2Window(cv->c_layer) == wi)
 
5753
      return 1;
 
5754
  return 0;
 
5755
}
 
5756
 
 
5757
struct win *
 
5758
FindNiceWindow(wi, presel)
 
5759
struct win *wi;
 
5760
char *presel;
 
5761
{
 
5762
  int i;
 
5763
 
 
5764
  debug2("FindNiceWindow %d %s\n", wi ? wi->w_number : -1 , presel ? presel : "NULL");
 
5765
  if (presel)
 
5766
    {
 
5767
      i = WindowByNoN(presel);
 
5768
      if (i >= 0)
 
5769
        wi = wtab[i];
 
5770
    }
 
5771
  if (!display)
 
5772
    return wi;
 
5773
#ifdef MULTIUSER
 
5774
  if (wi && AclCheckPermWin(D_user, ACL_READ, wi))
 
5775
    wi = 0;
 
5776
#endif
 
5777
  if (!wi || (IsOnDisplay(wi) && !presel))
 
5778
    {
 
5779
      /* try to get another window */
 
5780
      wi = 0;
 
5781
#ifdef MULTIUSER
 
5782
      for (wi = windows; wi; wi = wi->w_next)
 
5783
        if (!wi->w_layer.l_cvlist && !AclCheckPermWin(D_user, ACL_WRITE, wi))
 
5784
          break;
 
5785
      if (!wi)
 
5786
        for (wi = windows; wi; wi = wi->w_next)
 
5787
          if (wi->w_layer.l_cvlist && !IsOnDisplay(wi) && !AclCheckPermWin(D_user, ACL_WRITE, wi))
 
5788
            break;
 
5789
      if (!wi)
 
5790
        for (wi = windows; wi; wi = wi->w_next)
 
5791
          if (!wi->w_layer.l_cvlist && !AclCheckPermWin(D_user, ACL_READ, wi))
 
5792
            break;
 
5793
      if (!wi)
 
5794
        for (wi = windows; wi; wi = wi->w_next)
 
5795
          if (wi->w_layer.l_cvlist && !IsOnDisplay(wi) && !AclCheckPermWin(D_user, ACL_READ, wi))
 
5796
            break;
 
5797
#endif
 
5798
      if (!wi)
 
5799
        for (wi = windows; wi; wi = wi->w_next)
 
5800
          if (!wi->w_layer.l_cvlist)
 
5801
            break;
 
5802
      if (!wi)
 
5803
        for (wi = windows; wi; wi = wi->w_next)
 
5804
          if (wi->w_layer.l_cvlist && !IsOnDisplay(wi))
 
5805
            break;
 
5806
    }
 
5807
#ifdef MULTIUSER
 
5808
  if (wi && AclCheckPermWin(D_user, ACL_READ, wi))
 
5809
    wi = 0;
 
5810
#endif
 
5811
  return wi;
 
5812
}
 
5813
 
 
5814
#if 0
 
5815
 
 
5816
/* sorted list of all commands */
 
5817
static struct comm **commtab;
 
5818
static int ncommtab;
 
5819
 
 
5820
void
 
5821
AddComms(cos, hand)
 
5822
struct comm *cos;
 
5823
void (*hand) __P((struct comm *, char **, int));
 
5824
{
 
5825
  int n, i, j, r;
 
5826
  for (n = 0; cos[n].name; n++)
 
5827
    ;
 
5828
  if (n == 0)
 
5829
    return;
 
5830
  if (commtab)
 
5831
    commtab = (struct commt *)realloc(commtab, sizeof(*commtab) * (ncommtab + n));
 
5832
  else
 
5833
    commtab = (struct commt *)malloc(sizeof(*commtab) * (ncommtab + n));
 
5834
  if (!commtab)
 
5835
    Panic(0, strnomem);
 
5836
  for (i = 0; i < n; i++)
 
5837
    {
 
5838
      for (j = 0; j < ncommtab; j++)
 
5839
        {
 
5840
          r = strcmp(cos[i].name, commtab[j]->name);
 
5841
          if (r == 0)
 
5842
            Panic(0, "Duplicate command: %s\n", cos[i].name);
 
5843
          if (r < 0)
 
5844
            break;
 
5845
        }
 
5846
      for (r = ncommtab; r > j; r--)
 
5847
        commtab[r] = commtab[r - 1];
 
5848
      commtab[j] = cos + i;
 
5849
      cos[i].handler = hand;
 
5850
      bzero(cos[i].userbits, sizeof(cos[i].userbits));
 
5851
      ncommtab++;
 
5852
    }
 
5853
}
 
5854
 
 
5855
struct comm *
 
5856
FindComm(str)
 
5857
char *str;
 
5858
{
 
5859
  int x, m, l = 0, r = ncommtab - 1;
 
5860
  while (l <= r)
 
5861
    {
 
5862
      m = (l + r) / 2;
 
5863
      x = strcmp(str, commtab[m]->name);
 
5864
      if (x > 0)
 
5865
        l = m + 1;
 
5866
      else if (x < 0)
 
5867
        r = m - 1;
 
5868
      else
 
5869
        return commtab[m];
 
5870
    }
 
5871
  return 0;
 
5872
}
 
5873
 
 
5874
#endif
 
5875
 
 
5876
static void
 
5877
ResizeRegions(arg)
 
5878
char *arg;
 
5879
{
 
5880
  struct canvas *cv;
 
5881
  int nreg, dsize, diff, siz;
 
5882
 
 
5883
  ASSERT(display);
 
5884
  for (nreg = 0, cv = D_cvlist; cv; cv = cv->c_next)
 
5885
    nreg++;
 
5886
  if (nreg < 2)
 
5887
    {
 
5888
      Msg(0, "resize: need more than one region");
 
5889
      return;
 
5890
    }
 
5891
  dsize = D_height - (D_has_hstatus == HSTATUS_LASTLINE);
 
5892
  if (*arg == '=')
 
5893
    {
 
5894
      /* make all regions the same height */
 
5895
      int h = dsize;
 
5896
      int hh, i = 0;
 
5897
      for (cv = D_cvlist; cv; cv = cv->c_next)
 
5898
        {
 
5899
          hh = h / nreg-- - 1;
 
5900
          cv->c_ys = i;
 
5901
          cv->c_ye = i + hh - 1;
 
5902
          cv->c_yoff = i;
 
5903
          i += hh + 1;
 
5904
          h -= hh + 1;
 
5905
        }
 
5906
      RethinkDisplayViewports();
 
5907
      ResizeLayersToCanvases();
 
5908
      return;
 
5909
    }
 
5910
  siz = D_forecv->c_ye - D_forecv->c_ys + 1;
 
5911
  if (*arg == '+')
 
5912
    diff = atoi(arg + 1);
 
5913
  else if (*arg == '-')
 
5914
    diff = -atoi(arg + 1);
 
5915
  else if (!strcmp(arg, "min"))
 
5916
    diff = 1 - siz;
 
5917
  else if (!strcmp(arg, "max"))
 
5918
    diff = dsize - (nreg - 1) * 2 - 1 - siz;
 
5919
  else
 
5920
    diff = atoi(arg) - siz;
 
5921
  if (diff == 0)
 
5922
    return;
 
5923
  if (siz + diff < 1)
 
5924
    diff = 1 - siz;
 
5925
  if (siz + diff > dsize - (nreg - 1) * 2 - 1)
 
5926
    diff = dsize - (nreg - 1) * 2 - 1 - siz;
 
5927
  if (diff == 0 || siz + diff < 1)
 
5928
    return;
 
5929
 
 
5930
  if (diff < 0)
 
5931
    {
 
5932
      if (D_forecv->c_next)
 
5933
        {
 
5934
          D_forecv->c_ye += diff;
 
5935
          D_forecv->c_next->c_ys += diff;
 
5936
          D_forecv->c_next->c_yoff += diff;
 
5937
        }
 
5938
      else
 
5939
        {
 
5940
          for (cv = D_cvlist; cv; cv = cv->c_next)
 
5941
            if (cv->c_next == D_forecv)
 
5942
              break;
 
5943
          ASSERT(cv);
 
5944
          cv->c_ye -= diff;
 
5945
          D_forecv->c_ys -= diff;
 
5946
          D_forecv->c_yoff -= diff;
 
5947
        }
 
5948
    }
 
5949
  else
 
5950
    {
 
5951
      int s, i = 0, found = 0, di = diff, d2;
 
5952
      s = dsize - (nreg - 1) * 2 - 1 - siz;
 
5953
      for (cv = D_cvlist; cv; i = cv->c_ye + 2, cv = cv->c_next)
 
5954
        {
 
5955
          if (cv == D_forecv)
 
5956
            {
 
5957
              cv->c_ye = i + (cv->c_ye - cv->c_ys) + diff;
 
5958
              cv->c_yoff -= cv->c_ys - i;
 
5959
              cv->c_ys = i;
 
5960
              found = 1;
 
5961
              continue;
 
5962
            }
 
5963
          s -= cv->c_ye - cv->c_ys;
 
5964
          if (!found)
 
5965
            {
 
5966
              if (s >= di)
 
5967
                continue;
 
5968
              d2 = di - s;
 
5969
            }
 
5970
          else
 
5971
            d2 = di > cv->c_ye - cv->c_ys ? cv->c_ye - cv->c_ys : di;
 
5972
          di -= d2;
 
5973
          cv->c_ye = i + (cv->c_ye - cv->c_ys) - d2;
 
5974
          cv->c_yoff -= cv->c_ys - i;
 
5975
          cv->c_ys = i;
 
5976
        }
 
5977
    }
 
5978
  RethinkDisplayViewports();
 
5979
  ResizeLayersToCanvases();
 
5980
}
 
5981
 
 
5982
static void
 
5983
ResizeFin(buf, len, data)
 
5984
char *buf;
 
5985
int len;
 
5986
char *data;
 
5987
{
 
5988
  ResizeRegions(buf);
 
5989
}
 
5990
 
 
5991
#ifdef RXVT_OSC
 
5992
void
 
5993
RefreshXtermOSC()
 
5994
{
 
5995
  int i;
 
5996
  struct win *p;
 
5997
 
 
5998
  p = Layer2Window(D_forecv->c_layer);
 
5999
  for (i = 3; i >=0; i--)
 
6000
    SetXtermOSC(i, p ? p->w_xtermosc[i] : 0);
 
6001
}
 
6002
#endif
 
6003
 
 
6004
int
 
6005
ParseAttrColor(s1, s2, msgok)
 
6006
char *s1, *s2;
 
6007
int msgok;
 
6008
{
 
6009
  int i, n;
 
6010
  char *s, *ss;
 
6011
  int r = 0;
 
6012
 
 
6013
  s = s1;
 
6014
  while (*s == ' ')
 
6015
    s++;
 
6016
  ss = s;
 
6017
  while (*ss && *ss != ' ')
 
6018
    ss++;
 
6019
  while (*ss == ' ')
 
6020
    ss++;
 
6021
  if (*s && (s2 || *ss || !((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') || *s == '.')))
 
6022
    {
 
6023
      int mode = 0, n = 0;
 
6024
      if (*s == '+')
 
6025
        {
 
6026
          mode = 1;
 
6027
          s++;
 
6028
        }
 
6029
      else if (*s == '-')
 
6030
        {
 
6031
          mode = -1;
 
6032
          s++;
 
6033
        }
 
6034
      else if (*s == '!')
 
6035
        {
 
6036
          mode = 2;
 
6037
          s++;
 
6038
        }
 
6039
      else if (*s == '=')
 
6040
        s++;
 
6041
      if (*s >= '0' && *s <= '9')
 
6042
        {
 
6043
          n = *s++ - '0';
 
6044
          if (*s >= '0' && *s <= '9')
 
6045
            n = n * 16 + (*s++ - '0');
 
6046
          else if (*s >= 'a' && *s <= 'f')
 
6047
            n = n * 16 + (*s++ - ('a' - 10));
 
6048
          else if (*s >= 'A' && *s <= 'F')
 
6049
            n = n * 16 + (*s++ - ('A' - 10));
 
6050
          else if (*s && *s != ' ')
 
6051
            {
 
6052
              if (msgok)
 
6053
                Msg(0, "Illegal attribute hexchar '%c'", *s);
 
6054
              return -1;
 
6055
            }
 
6056
        }
 
6057
      else
 
6058
        {
 
6059
          while (*s && *s != ' ')
 
6060
            {
 
6061
              if (*s == 'd')
 
6062
                n |= A_DI;
 
6063
              else if (*s == 'u')
 
6064
                n |= A_US;
 
6065
              else if (*s == 'b')
 
6066
                n |= A_BD;
 
6067
              else if (*s == 'r')
 
6068
                n |= A_RV;
 
6069
              else if (*s == 's')
 
6070
                n |= A_SO;
 
6071
              else if (*s == 'B')
 
6072
                n |= A_BL;
 
6073
              else
 
6074
                {
 
6075
                  if (msgok)
 
6076
                    Msg(0, "Illegal attribute specifier '%c'", *s);
 
6077
                  return -1;
 
6078
                }
 
6079
              s++;
 
6080
            }
 
6081
        }
 
6082
      if (*s && *s != ' ')
 
6083
        {
 
6084
          if (msgok)
 
6085
            Msg(0, "junk after attribute description: '%c'", *s);
 
6086
          return -1;
 
6087
        }
 
6088
      if (mode == -1)
 
6089
        r = n << 8 | n;
 
6090
      else if (mode == 1)
 
6091
        r = n << 8;
 
6092
      else if (mode == 2)
 
6093
        r = n;
 
6094
      else if (mode == 0)
 
6095
        r = 0xffff ^ n;
 
6096
    }
 
6097
  while (*s && *s == ' ')
 
6098
    s++;
 
6099
 
 
6100
  if (s2)
 
6101
    {
 
6102
      if (*s)
 
6103
        {
 
6104
          if (msgok)
 
6105
            Msg(0, "junk after description: '%c'", *s);
 
6106
          return -1;
 
6107
        }
 
6108
      s = s2;
 
6109
      while (*s && *s == ' ')
 
6110
        s++;
 
6111
    }
 
6112
 
 
6113
#ifdef COLOR
 
6114
  if (*s)
 
6115
    {
 
6116
      static char costr[] = "krgybmcw d    i.01234567 9     f               FKRGYBMCW      I ";
 
6117
      int numco = 0, j;
 
6118
 
 
6119
      n = 0;
 
6120
      if (*s == '.')
 
6121
        {
 
6122
          numco++;
 
6123
          n = 0x0f;
 
6124
          s++;
 
6125
        }
 
6126
      for (j = 0; j < 2 && *s && *s != ' '; j++)
 
6127
        {
 
6128
          for (i = 0; costr[i]; i++)
 
6129
            if (*s == costr[i])
 
6130
              break;
 
6131
          if (!costr[i])
 
6132
            {
 
6133
              if (msgok)
 
6134
                Msg(0, "illegal color descriptor: '%c'", *s);
 
6135
              return -1;
 
6136
            }
 
6137
          numco++;
 
6138
          n = n << 4 | (i & 15);
 
6139
#ifdef COLORS16
 
6140
          if (i >= 48)
 
6141
            n = (n & 0x20ff) | 0x200;
 
6142
#endif
 
6143
          s++;
 
6144
        }
 
6145
      if ((n & 0xf00) == 0xf00)
 
6146
        n ^= 0xf00;     /* clear superflous bits */
 
6147
#ifdef COLORS16
 
6148
      if (n & 0x2000)
 
6149
        n ^= 0x2400;    /* shift bit into right position */
 
6150
#endif
 
6151
      if (numco == 1)
 
6152
        n |= 0xf0;      /* don't change bg color */
 
6153
      if (numco != 2 && n != 0xff)
 
6154
        n |= 0x100;     /* special invert mode */
 
6155
      if (*s && *s != ' ')
 
6156
        {
 
6157
          if (msgok)
 
6158
            Msg(0, "junk after color description: '%c'", *s);
 
6159
          return -1;
 
6160
        }
 
6161
      n ^= 0xff;
 
6162
      r |= n << 16;
 
6163
    }
 
6164
#endif
 
6165
 
 
6166
  while (*s && *s == ' ')
 
6167
    s++;
 
6168
  if (*s)
 
6169
    {
 
6170
      if (msgok)
 
6171
        Msg(0, "junk after description: '%c'", *s);
 
6172
      return -1;
 
6173
    }
 
6174
  debug1("ParseAttrColor %06x\n", r);
 
6175
  return r;
 
6176
}
 
6177
 
 
6178
/*
 
6179
 *  Color coding:
 
6180
 *    0-7 normal colors
 
6181
 *    9   default color
 
6182
 *    e   just set intensity
 
6183
 *    f   don't change anything
 
6184
 *  Intensity is encoded into bits 17(fg) and 18(bg).
 
6185
 */
 
6186
void
 
6187
ApplyAttrColor(i, mc)
 
6188
int i;
 
6189
struct mchar *mc;
 
6190
{
 
6191
  debug1("ApplyAttrColor %06x\n", i);
 
6192
  mc->attr |= i >> 8 & 255;
 
6193
  mc->attr ^= i & 255;
 
6194
#ifdef COLOR
 
6195
  i = (i >> 16) ^ 0xff;
 
6196
  if ((i & 0x100) != 0)
 
6197
    {
 
6198
      i &= 0xeff;
 
6199
      if (mc->attr & (A_SO|A_RV))
 
6200
# ifdef COLORS16
 
6201
        i = ((i & 0x0f) << 4) | ((i & 0xf0) >> 4) | ((i & 0x200) << 1) | ((i & 0x400) >> 1);
 
6202
# else
 
6203
        i = ((i & 0x0f) << 4) | ((i & 0xf0) >> 4);
 
6204
# endif
 
6205
    }
 
6206
# ifdef COLORS16
 
6207
  if ((i & 0x0f) != 0x0f)
 
6208
    mc->attr = (mc->attr & 0xbf) | ((i >> 3) & 0x40);
 
6209
  if ((i & 0xf0) != 0xf0)
 
6210
    mc->attr = (mc->attr & 0x7f) | ((i >> 3) & 0x80);
 
6211
# endif
 
6212
  mc->color = 0x99 ^ mc->color;
 
6213
  if ((i & 0x0e) == 0x0e)
 
6214
    i = (i & 0xf0) | (mc->color & 0x0f);
 
6215
  if ((i & 0xe0) == 0xe0)
 
6216
    i = (i & 0x0f) | (mc->color & 0xf0);
 
6217
  mc->color = 0x99 ^ i;
 
6218
  debug2("ApplyAttrColor - %02x %02x\n", mc->attr, i);
 
6219
#endif
 
6220
}