1 #include <stdlib.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <sys/ioctl.h>
5 #if HAVE_UNISTD_H
6 # include <unistd.h>
7 #endif
8 #include "scr.h"
9 #include "dir.h"
10 #include "deco.h"
11 #include "env.h"
12
13 struct dir left, right; /* left and right directories */
14 struct dir *cur; /* current directory */
15 int H; /* file window height */
16 int uid; /* real user id */
17 int main_pid; /* our process id */
18 int ppid; /* parent process id */
19 int widewin; /* full window mode */
20 char *user;
21 char *group;
22 char *tty = 0;
23 char *machine;
24 int cpos; /* position of command line cursor */
25 int cmdreg; /* cursor in command line */
26 int visualwin = 1; /* cursor in command line */
27 int lang;
28
29 #ifndef GETGROUPS_T
30 #define GETGROUPS_T int
31 #endif
32
33 GETGROUPS_T gidlist [128]; /* groups list */
34 int gidnum; /* number of groups in list */
35
36 struct palette dflt_palette = { 7, 0, 7, 6, 15, 0, 15, 6, 3, 0, 0, 7, };
37 struct palette palette;
38
39 static struct KeyMap keymap [] = {
40 { "kl", 0, meta ('l') },
41 { "kr", 0, meta ('r') },
42 { "ku", 0, meta ('u') },
43 { "kd", 0, meta ('d') },
44 { "kN", 0, meta ('n') },
45 { "kP", 0, meta ('p') },
46 { "kh", 0, meta ('h') },
47 { "kH", 0, meta ('e') },
48 { "@7", 0, meta ('e') },
49 { "kI", 0, cntrl ('T') },
50 { "k.", 0, cntrl ('G') },
51 { "kD", 0, cntrl ('G') },
52 { "kE", 0, meta ('h') },
53 { "kS", 0, meta ('e') },
54 { "k1", 0, meta ('A') },
55 { "k2", 0, meta ('B') },
56 { "k3", 0, meta ('C') },
57 { "k4", 0, meta ('D') },
58 { "k5", 0, meta ('E') },
59 { "k6", 0, meta ('F') },
60 { "k7", 0, meta ('G') },
61 { "k8", 0, meta ('H') },
62 { "k9", 0, meta ('I') },
63 { "k0", 0, meta ('J') },
64 { "k;", 0, meta ('J') },
65 { "f1", 0, meta ('A') },
66 { "f2", 0, meta ('B') },
67 { "f3", 0, meta ('C') },
68 { "f4", 0, meta ('D') },
69 { "f5", 0, meta ('E') },
70 { "f6", 0, meta ('F') },
71 { "f7", 0, meta ('G') },
72 { "f8", 0, meta ('H') },
73 { "f9", 0, meta ('I') },
74 { "f0", 0, meta ('J') },
75 { "kb", "\b", meta ('b') },
76 { 0, "\0331", meta ('A') },
77 { 0, "\0332", meta ('B') },
78 { 0, "\0333", meta ('C') },
79 { 0, "\0334", meta ('D') },
80 { 0, "\0335", meta ('E') },
81 { 0, "\0336", meta ('F') },
82 { 0, "\0337", meta ('G') },
83 { 0, "\0338", meta ('H') },
84 { 0, "\0339", meta ('I') },
85 { 0, "\0330", meta ('J') },
86
87 { 0, "\033l", meta ('l') },
88 { 0, "\033r", meta ('r') },
89 { 0, "\033u", meta ('u') },
90 { 0, "\033d", meta ('d') },
91 { 0, "\033n", meta ('n') },
92 { 0, "\033p", meta ('p') },
93 { 0, "\033h", meta ('h') },
94 { 0, "\033e", meta ('e') },
95
96 { 0, "\033\033", cntrl ('C') },
97 { 0, 0, 0 },
98 };
99
100 static void init (void);
101 static void inithome (void);
102 static void initlang (void);
103 static void execute (void);
104 static void docmdreg (int c);
105 static void doscrreg (int c);
106
main(int argc,char ** argv,char ** envp)107 int main (int argc, char **argv, char **envp)
108 {
109 register c;
110
111 if (argc > 2) {
112 outerr ("Usage: deco [dirname]\n");
113 exit (1);
114 }
115 #ifdef GC
116 /*GC_set_warn_proc (outerr);*/
117 #endif
118 outerr ("Demos Commander, Copyright (C) 1989-1997 Serge Vakulenko\n");
119 palette = dflt_palette;
120 if (argc > 1)
121 chdir (argv [1]);
122 EnvInit (envp);
123 initlang ();
124 uid = getuid ();
125 #ifdef HAVE_GETGROUPS
126 gidnum = getgroups (sizeof(gidlist)/sizeof(gidlist[0]), gidlist);
127 #else
128 gidlist[0] = getgid ();
129 gidnum = 1;
130 #endif
131 main_pid = getpid ();
132 ppid = getppid ();
133 user = username (uid);
134 group = groupname (gidlist[0]);
135 tty = ttyname (0);
136 machine = getmachine ();
137 sigign ();
138 tcsetpgrp (2, main_pid);
139
140 init ();
141 inithome ();
142 VClear ();
143 right.sort = SORTEXT;
144 left.sort = SORTEXT;
145 right.typesort = 1;
146 left.typesort = 1;
147 right.alignext = 1;
148 left.alignext = 1;
149 readinitfile ();
150 if (uid == 0)
151 palette.dimfg = 6;
152 VSetPalette (palette.fg, palette.bg, palette.revfg, palette.revbg,
153 palette.boldfg, palette.boldbg, palette.boldrevfg, palette.boldrevbg,
154 palette.dimfg, palette.dimbg, palette.dimrevfg, palette.dimrevbg);
155 setdir (&left, ".");
156 setdir (&right, home);
157 chdir (left.cwd);
158 cur = &left;
159 draw ();
160 for (;;) {
161 if (! cmdreg)
162 drawcursor ();
163 drawcmd ();
164 VSync ();
165 c = KeyGet ();
166 if (! cmdreg)
167 undrawcursor ();
168 switch (c) {
169 case '+': /* select */
170 case '-': /* unselect */
171 if (! cpos && ! cmdreg && ! cur->status) {
172 if (c == '+')
173 tagall ();
174 else
175 untagall ();
176 draw ();
177 continue;
178 }
179 default:
180 if ((c>=' ' && c<='~') || (c>=0300 && c<=0377)) {
181 if (cpos || c!=' ')
182 inscmd (c);
183 continue;
184 }
185 VBeep ();
186 continue;
187 case cntrl ('V'): /* quote next char */
188 inscmd (quote ());
189 continue;
190 case cntrl ('J'): /* insert file name */
191 if (! cmdreg && ! cur->status)
192 namecmd ();
193 continue;
194 case cntrl ('G'):
195 delcmd ();
196 continue;
197 case meta ('b'): /* backspace */
198 if (cpos) {
199 leftcmd ();
200 delcmd ();
201 }
202 continue;
203 case cntrl ('O'): /* set/unset command mode */
204 case cntrl ('P'): /* set/unset command mode */
205 switchcmdreg ();
206 if (! cmdreg)
207 visualwin = 1;
208 draw ();
209 continue;
210 case cntrl ('M'): /* return */
211 if (command [0]) {
212 execmd (1, 1);
213 draw ();
214 continue;
215 }
216 if (cmdreg) {
217 cmdreg = 0;
218 if (! visualwin) {
219 visualwin = 1;
220 setdir (cur==&left ? &right : &left, 0);
221 setdir (cur, 0);
222 }
223 draw ();
224 continue;
225 }
226 execute ();
227 continue;
228 case cntrl (']'): /* redraw screen */
229 VRedraw ();
230 continue;
231 case cntrl ('B'): /* history */
232 if (! visualwin)
233 VClearBox (1, 0, LINES-2, 80);
234 histmenu ();
235 draw ();
236 continue;
237 case meta ('A'): /* f1 */
238 genhelp ();
239 draw ();
240 continue;
241 case meta ('B'): /* f2 */
242 usermenu ();
243 draw ();
244 continue;
245 case meta ('I'): /* f9 */
246 runmenu (cur==&left ? 'l' : 'r');
247 draw ();
248 continue;
249 case meta ('J'): /* f0 */
250 case cntrl ('C'): /* quit */
251 quit ();
252 continue;
253 case cntrl ('U'): /* swap panels */
254 swappanels ();
255 draw ();
256 continue;
257 case cntrl ('F'): /* full screen */
258 fullscreen (0, 0);
259 draw ();
260 continue;
261 case cntrl ('^'): /* cd / */
262 directory (0, 'r');
263 if (! cur->status)
264 drawdir (cur, 1);
265 continue;
266 case cntrl ('\\'): /* cd $HOME */
267 directory (0, 'o');
268 if (! cur->status)
269 drawdir (cur, 1);
270 continue;
271 case cntrl ('Y'): /* clear line */
272 command [cpos = 0] = 0;
273 continue;
274 case cntrl ('X'): /* next history */
275 nextcmd ();
276 continue;
277 case cntrl ('E'): /* prev history */
278 prevcmd ();
279 continue;
280 case cntrl ('S'): /* char left */
281 case cntrl ('A'): /* char left */
282 leftcmd ();
283 continue;
284 case cntrl ('D'): /* char right */
285 rightcmd ();
286 continue;
287 case cntrl ('I'): /* tab */
288 if (cmdreg)
289 if (command [cpos])
290 endcmd ();
291 else
292 homecmd ();
293 else {
294 switchpanels ();
295 if (widewin) {
296 drawbanners ();
297 drawdir (cur, 0);
298 break;
299 }
300 }
301 continue;
302 case cntrl ('W'): /* double width */
303 if (! cmdreg) {
304 setdwid ();
305 draw ();
306 }
307 continue;
308 case meta ('G'): /* f7 */
309 makedir ();
310 draw ();
311 continue;
312 case meta ('h'): /* home */
313 case meta ('e'): /* end */
314 case meta ('u'): /* up */
315 case meta ('d'): /* down */
316 case meta ('l'): /* left */
317 case meta ('r'): /* right */
318 case meta ('n'): /* next page */
319 case meta ('p'): /* prev page */
320 case cntrl ('K'): /* find file */
321 case cntrl ('R'): /* reread catalog */
322 case cntrl ('T'): /* tag file */
323 case meta ('C'): /* f3 */
324 case meta ('D'): /* f4 */
325 case meta ('E'): /* f5 */
326 case meta ('F'): /* f6 */
327 case meta ('H'): /* f8 */
328 case cntrl ('L'): /* status */
329 if (cmdreg || cur->status)
330 docmdreg (c);
331 else
332 doscrreg (c);
333 continue;
334 }
335 }
336 }
337
doscrreg(int c)338 static void doscrreg (int c)
339 {
340 switch (c) {
341 case meta ('h'): /* home */
342 cur->curfile = cur->topfile = 0;
343 break;
344 case meta ('e'): /* end */
345 cur->curfile = cur->num - 1;
346 cur->topfile = cur->num - PAGELEN (cur);
347 if (cur->topfile < 0)
348 cur->topfile = 0;
349 break;
350 case meta ('u'): /* up */
351 if (cur->curfile <= 0)
352 return;
353 if (cur->curfile > cur->topfile) {
354 --cur->curfile;
355 return;
356 }
357 cur->topfile = --cur->curfile;
358 break;
359 case meta ('d'): /* down */
360 if (cur->curfile >= cur->num-1)
361 return;
362 if (cur->topfile + PAGELEN (cur) - 1 > cur->curfile) {
363 ++cur->curfile;
364 return;
365 }
366 cur->topfile = ++cur->curfile - PAGELEN (cur) + 1;
367 break;
368 case meta ('l'): /* left */
369 if (cur->curfile < H) {
370 if (cur->topfile <= 0)
371 return;
372 cur->curfile -= cur->topfile;
373 cur->topfile = 0;
374 break;
375 }
376 cur->curfile -= H;
377 if (cur->topfile <= cur->curfile)
378 return;
379 cur->topfile -= H;
380 if (cur->topfile <= 0) {
381 cur->curfile -= cur->topfile;
382 cur->topfile = 0;
383 }
384 break;
385 case meta ('r'): /* right */
386 if (cur->curfile + H < cur->num) {
387 cur->curfile += H;
388 if (cur->topfile + PAGELEN (cur) > cur->curfile)
389 return;
390 cur->topfile += H;
391 break;
392 }
393 if (cur->topfile + PAGELEN (cur) < cur->num) {
394 cur->curfile = cur->num-1;
395 cur->topfile += H;
396 break;
397 }
398 if ((cur->curfile - cur->topfile) / H <
399 (cur->num - cur->topfile - 1) / H)
400 cur->curfile = cur->num-1;
401 return;
402 case meta ('n'): /* next page */
403 if (cur->topfile + PAGELEN (cur) >= cur->num) {
404 cur->curfile = cur->num-1;
405 } else if (cur->topfile + 2 * PAGELEN (cur) >= cur->num) {
406 cur->curfile = cur->num-1;
407 cur->topfile = cur->num - PAGELEN (cur);
408 } else {
409 cur->curfile += PAGELEN (cur);
410 cur->topfile += PAGELEN (cur);
411 }
412 break;
413 case meta ('p'): /* prev page */
414 if (cur->topfile == 0) {
415 cur->curfile = 0;
416 } else {
417 cur->curfile -= PAGELEN (cur);
418 if (cur->topfile > cur->curfile)
419 cur->topfile -= PAGELEN (cur);
420 if (cur->topfile < 0) {
421 cur->curfile -= cur->topfile;
422 cur->topfile = 0;
423 }
424 }
425 break;
426 case cntrl ('K'): /* find file */
427 findname ();
428 break;
429 case cntrl ('R'): /* reread catalog */
430 reread (cur==&left ? 'l' : 'r', 0);
431 break;
432 case cntrl ('T'): /* tag file */
433 if ((cur->cat[cur->curfile].mode & S_IFMT) == (unsigned) S_IFREG) {
434 cur->cat[cur->curfile].tag ^= 1;
435 counttag (cur);
436 }
437 if (cur->curfile < cur->num-1) {
438 /* move down */
439 ++cur->curfile;
440 if (cur->topfile + PAGELEN (cur) - 1 < cur->curfile)
441 cur->topfile = cur->curfile - PAGELEN (cur) + 1;
442 }
443 break;
444 case meta ('C'): /* f3 */
445 if ((cur->cat[cur->curfile].mode & S_IFMT) != (unsigned) S_IFREG)
446 return;
447 view ();
448 draw ();
449 return;
450 case meta ('D'): /* f4 */
451 edit ();
452 setdir (cur==&left ? &right : &left, 0);
453 setdir (cur, 0);
454 draw ();
455 return;
456 case meta ('E'): /* f5 */
457 copy ();
458 draw ();
459 return;
460 case meta ('F'): /* f6 */
461 renmove ();
462 draw ();
463 return;
464 case meta ('H'): /* f8 */
465 delete ();
466 draw ();
467 return;
468 case cntrl ('L'): /* status */
469 setstatus ();
470 draw ();
471 return;
472 }
473 drawdir (cur, 1);
474 }
475
docmdreg(int c)476 static void docmdreg (int c)
477 {
478 switch (c) {
479 case meta ('h'): /* home */
480 homecmd ();
481 return;
482 case meta ('e'): /* end */
483 endcmd ();
484 return;
485 case meta ('l'): /* left */
486 leftcmd ();
487 return;
488 case meta ('r'): /* right */
489 rightcmd ();
490 return;
491 case meta ('u'): /* up */
492 upcmd ();
493 return;
494 case meta ('d'): /* down */
495 downcmd ();
496 return;
497 case meta ('n'): /* next page */
498 nextcmd ();
499 return;
500 case meta ('p'): /* prev page */
501 prevcmd ();
502 return;
503 }
504 }
505
execute()506 static void execute ()
507 {
508 register struct file *file = &cur->cat[cur->curfile];
509 register char *name = file->name;
510 int updir, dev = 0, ino = 0;
511
512 switch (file->mode & S_IFMT) {
513 case S_IFDIR:
514 if (! strcmp (name, ".")) {
515 setdir (cur, 0);
516 break;
517 }
518 if ((updir = !strcmp (name, ".."))) {
519 dev = cur->dev;
520 ino = cur->ino;
521 }
522 if (chdir (name) < 0)
523 break;
524 setdir (cur, ".");
525 if (updir) {
526 for (cur->curfile=0; cur->curfile<cur->num; ++cur->curfile) {
527 if (cur->cat[cur->curfile].dev == dev &&
528 cur->cat[cur->curfile].ino == ino)
529 break;
530 }
531 if (cur->curfile >= cur->num)
532 cur->curfile = 0;
533 if (cur->topfile + PAGELEN (cur) <= cur->curfile)
534 cur->topfile = cur->curfile - PAGELEN (cur) + 1;
535 }
536 if (visualwin) {
537 drawdir (&left, 0);
538 drawdir (&right, 0);
539 }
540 break;
541 case S_IFREG:
542 if (file->execable)
543 strcpy (command, file->name);
544 else
545 excommand (command, file->name);
546 cpos = strlen (command);
547 if (! command [0])
548 break;
549 execmd (file->execable ? 1 : 0, 1);
550 draw ();
551 break;
552 }
553 }
554
init()555 static void init ()
556 {
557 char *buf;
558
559 buf = malloc (2048);
560 if (! CapInit (buf)) {
561 outerr ("Cannot read termcap\n");
562 exit (1);
563 }
564 if (! VInit ()) {
565 outerr ("Cannot initialize video device\n");
566 exit (1);
567 }
568 if (COLS < 80) {
569 outerr ("The screen must have at least 80 columns\n");
570 exit (1);
571 }
572 KeyInit (keymap, VFlush);
573 VOpen ();
574 free (buf);
575
576 /* H is the number of lines at file window */
577
578 H = LINES/2-1;
579
580 left.basecol = 0;
581 right.basecol = 40;
582 }
583
pagelen(int view)584 int pagelen (int view)
585 {
586 register h = H;
587
588 if (! widewin)
589 return (view == VIEW_BRIEF ? h+h : h);
590 switch (view) {
591 case VIEW_BRIEF:
592 h += h;
593 case VIEW_LONG:
594 case VIEW_WIDE:
595 return (h+h);
596 default:
597 return (h);
598 }
599 }
600
inithome()601 static void inithome ()
602 {
603 register char *s;
604
605 if ((s = EnvGet ("HOME")))
606 home = s;
607 }
608
initlang()609 static void initlang ()
610 {
611 register char *s = EnvGet ("MSG");
612
613 if (! s)
614 s = "e";
615 switch (*s) {
616 default: lang = ENG; break;
617 case 'r': lang = RUS; break;
618 case 'u': lang = UKR; break;
619 case 'd': lang = DEU; break;
620 case 'f': lang = FRA; break;
621 }
622 }
623
setlang()624 void setlang ()
625 {
626 char *s, *altlang;
627
628 s = EnvGet ("MSG");
629 if (! s)
630 s = "l";
631 switch (*s) {
632 default: altlang = " Russian "; break;
633 case 'u': altlang = " Ukrainian "; break;
634 case 'd': altlang = " Deutch "; break;
635 case 'f': altlang = " Francais "; break;
636 }
637 switch (getchoice (0, " Language ", "Select language to use:",
638 0, " English ", altlang, 0)) {
639 case 0:
640 lang = ENG;
641 break;
642 case 1:
643 switch (*s) {
644 default: lang = RUS; break;
645 case 'u': lang = UKR; break;
646 case 'd': lang = DEU; break;
647 case 'f': lang = FRA; break;
648 }
649 break;
650 }
651 }
652
hidecursor()653 void hidecursor ()
654 {
655 VMove (LINES-1, COLS-2);
656 }
657
mvcaddstr(int r,int c,char * s)658 void mvcaddstr (int r, int c, char *s)
659 {
660 VMPutString (r, c - (strlen (s) + 1) / 2, s);
661 }
662
quote()663 int quote ()
664 {
665 register c, i;
666
667 c = KeyGet ();
668 if (c<'0' || c>'3')
669 return (c);
670 i = c & 3;
671 c = KeyGet ();
672 if (c<'0' || c>'7') {
673 KeyUnget (c);
674 return (i);
675 }
676 i = i << 3 | (c & 7);
677 c = KeyGet ();
678 if (c<'0' || c>'7') {
679 KeyUnget (c);
680 return (i);
681 }
682 return (i << 3 | (c & 7));
683 }
684
mygroup(int gid)685 int mygroup (int gid)
686 {
687 int i;
688
689 for (i=0; i<gidnum; ++i)
690 if (gid == gidlist[i])
691 return 1;
692 return 0;
693 }
694