1 #include <stdio.h>
2 #include <string.h>
3 #include <time.h>
4 #if HAVE_UNISTD_H
5 # include <unistd.h>
6 #endif
7 #include "dir.h"
8 #include "deco.h"
9 #include "scr.h"
10
11 #define DECOVERSION "Version 3.9"
12
13 static BOX *cbox; /* box under cursor */
14 static struct dir *cdir; /* drawed directory */
15
16 static void draw1dir (struct dir *c);
17 static void drawframe (int c, int view, int stawin);
18 static void drawcwd (int col, char *wd);
19 static void drawpat (int col, char *pat, int width);
20 static void drawsdir (struct dir *c);
21 static void drawstatus (int col, struct file *f, int view);
22 static void drawpage (int col, struct file *c, int n, struct dir *d);
23 static void drawfull (struct file *f, int tail);
24 static void drawmode (char *m, int u, int g);
25 static void drawtime (struct file *f);
26 static void drawlong (struct file *f);
27 static char *filnam (const char *p, int tail);
28 static char *filnam_wide (const char *p);
29
draw()30 void draw ()
31 {
32 if (visualwin) {
33 drawbanners ();
34 draw1dir (&left);
35 draw1dir (&right);
36 } else {
37 VClearBox (1, 0, LINES-2, 80);
38 drawbanners ();
39 }
40 }
41
drawdir(struct dir * c,int statusflag)42 void drawdir (struct dir *c, int statusflag) /* redraw window */
43 {
44 draw1dir (c);
45 if (statusflag) {
46 c = (c == &left ? &right : &left);
47 if (c->status)
48 draw1dir (c);
49 }
50 }
51
drawbanners()52 void drawbanners ()
53 {
54 register i;
55 register char *curtime;
56
57 if (visualwin)
58 if (widewin)
59 drawframe (BASECOL (cur), cur->view, cur->status);
60 else {
61 drawframe (left.basecol, left.view, left.status);
62 drawframe (right.basecol, right.view, right.status);
63 }
64 VSetDim ();
65 VStandOut ();
66 VMove (0, 0);
67 for (i=80; --i>=0; VPutChar (' '));
68 VMove (0, 1);
69 if (machine) {
70 VPutString (machine);
71 VPutChar (':');
72 }
73 if (tty)
74 VPutString (tty);
75 if (user)
76 VMPutString (0, 39 - strlen (user), user);
77 VPutChar ('.');
78 if (group)
79 VPutString (group);
80 if ((curtime = timestr (time ((long *) 0))))
81 VMPutString (0, 79 - strlen (curtime), curtime);
82 VStandEnd ();
83 VMPutString (LINES-1, 0, cmdreg ?
84 "1\16Help \17 2\16User \17 3\16 \17 4\16 \17 5\16 \
85 \17 6\16 \17 7\16 \17 8\16 \17 9\16Menu \017 10\16Quit \17" :
86 "1\16Help \17 2\16User \17 3\16View \17 4\16Edit \17 5\16Copy\
87 \17 6\16RenMov\17 7\16Mkdir \17 8\16Delete\17 9\16Menu \017 10\16Quit \17");
88 VSetNormal ();
89 }
90
draw1dir(struct dir * c)91 static void draw1dir (struct dir *c) /* redraw window */
92 {
93 register len = c->num - c->topfile;
94
95 /* check visibility in full window mode */
96 if (! visualwin || (widewin && c != cur))
97 return;
98 cdir = c;
99
100 /* if it is status window - draw status of another one */
101 if (c->status) {
102 drawsdir (c);
103 return;
104 }
105
106 /* reprint dir name */
107 VSetDim ();
108 VHorLine (1, BASECOL (c) + 1, PAGEWID-2);
109 VHorLine (H+2, BASECOL (c) + 1, PAGEWID-2);
110 VHorLine (H+4, BASECOL (c) + 1, PAGEWID-2);
111 if (widewin)
112 switch (c->view) {
113 case VIEW_BRIEF:
114 VCorner (1, 19, 2);
115 VCorner (1, 38, 2);
116 VCorner (1, 57, 2);
117 break;
118 case VIEW_LONG:
119 case VIEW_WIDE:
120 VCorner (1, 38, 2);
121 break;
122 }
123 else if (c->view == VIEW_BRIEF)
124 VCorner (H+2, BASECOL(c) + 19, 8);
125 drawcwd (c->basecol, c->shortcwd);
126 if (c->pattern [0])
127 drawpat (BASECOL (c), c->pattern, PAGEWID);
128 else {
129 char buf [80];
130
131 sprintf (buf, " %s byte%s in %d file%s ",
132 ltoac (c->nbytes), c->nbytes==1 ? "" : "s",
133 c->nfiles, c->nfiles==1 ? "" : "s");
134 mvcaddstr (H+4, BASECOL (c) + PAGEWID/2 + 1, buf);
135 if (c->tfiles) {
136 sprintf (buf, " %s byte%s in %d file%s ",
137 ltoac (c->tbytes), c->tbytes==1 ? "" : "s",
138 c->tfiles, c->tfiles==1 ? "" : "s");
139 VSetBold ();
140 mvcaddstr (H+2, BASECOL (c) + PAGEWID/2 + 1, buf);
141 }
142 }
143 VSetNormal ();
144
145 switch (c->view) {
146 case VIEW_INFO:
147 case VIEW_FULL:
148 if (widewin) {
149 VClearBox (2, 1, H, 75);
150 drawpage (1, &c->cat[c->topfile], len, c);
151 break;
152 }
153 /* Fall through... */
154 case VIEW_LONG:
155 case VIEW_WIDE:
156 VClearBox (2, BASECOL (c) + 1, H, 37);
157 drawpage (BASECOL (c) + 1, &c->cat[c->topfile], len, c);
158 if (widewin) {
159 VClearBox (2, BASECOL (c) + 39, H, 37);
160 if (len > H)
161 drawpage (BASECOL (c) + 39,
162 &c->cat[c->topfile+H], len-H, c);
163 }
164 break;
165 case VIEW_BRIEF:
166 VClearBox (2, BASECOL (c) + 1, H, 18);
167 drawpage (BASECOL (c) + 1, &c->cat[c->topfile], len, c);
168
169 VClearBox (2, BASECOL (c) + 20, H, 18);
170 if (len > H)
171 drawpage (BASECOL (c) + 20, &c->cat[c->topfile+H],
172 len -= H, c);
173 if (widewin) {
174 VClearBox (2, BASECOL (c) + 39, H, 18);
175 if (len > H)
176 drawpage (BASECOL (c) + 39,
177 &c->cat[c->topfile+H+H], len-=H, c);
178
179 VClearBox (2, BASECOL (c) + 58, H, 18);
180 if (len > H)
181 drawpage (BASECOL (c) + 58,
182 &c->cat[c->topfile+H+H+H], len-H, c);
183 }
184 break;
185 }
186 drawstatus (BASECOL (c), &c->cat[c->curfile], c->view);
187 }
188
drawcursor()189 void drawcursor ()
190 {
191 register col, line, w;
192
193 cdir = cur;
194 if (cur->status) {
195 VStandOut ();
196 drawcwd (cur->basecol, " Status ");
197 VStandEnd ();
198 return;
199 }
200 switch (cur->view) {
201 case VIEW_INFO: case VIEW_FULL: w = PAGEWID-2; break;
202 case VIEW_LONG: case VIEW_WIDE: w = 37; break;
203 default: w = 18; break;
204 }
205 line = cur->curfile - cur->topfile;
206 if (line < H)
207 col = BASECOL (cur) + 1;
208 else {
209 col = BASECOL (cur) + line/H * (w+1) + 1;
210 line %= H;
211 }
212 line += 2;
213 if (cbox)
214 VFreeBox (cbox);
215 cbox = VGetBox (line, col, 1, w);
216 if (VStandOut ())
217 if (cur->cat[cur->curfile].tag) {
218 VSetBold ();
219 VPrintBox (cbox);
220 VSetNormal ();
221 } else
222 VPrintBox (cbox);
223 else {
224 VMPutChar (line, col, '[');
225 VMPutChar (line, col+w-1, ']');
226 }
227 drawcwd (cur->basecol, cur->shortcwd);
228 VStandEnd ();
229 drawstatus (BASECOL (cur), &cur->cat[cur->curfile], cur->view);
230 }
231
undrawcursor()232 void undrawcursor ()
233 {
234 if (cbox) {
235 VUngetBox (cbox);
236 cbox = 0;
237 }
238 VSetDim ();
239 drawcwd (cur->basecol, cur->status ? " Status " : cur->shortcwd);
240 VSetNormal ();
241 }
242
243 /*
244 * Draw frame of (one) window
245 */
drawframe(int c,int view,int stawin)246 static void drawframe (int c, int view, int stawin)
247 {
248 VSetDim ();
249 if (stawin) {
250 VHorLine (4, c+1, PAGEWID-2);
251 VHorLine (11, c+1, PAGEWID-2);
252 VVertLine (c, 2, H+2);
253 VVertLine (c+PAGEWID-1, 2, H+2);
254 VCorner (1, c, 1);
255 VCorner (1, c+PAGEWID-1, 3);
256 VCorner (4, c, 4);
257 VCorner (4, c+PAGEWID-1, 6);
258 VCorner (11, c, 4);
259 VCorner (11, c+PAGEWID-1, 6);
260 VCorner (H+4, c, 7);
261 VCorner (H+4, c+PAGEWID-1, 9);
262 } else if (widewin) switch (view) {
263 case VIEW_INFO:
264 case VIEW_FULL:
265 VHorLine (H+2, 1, PAGEWID-2);
266 VVertLine (0, 2, H+2);
267 VVertLine (PAGEWID-1, 2, H+2);
268 VCorner (1, 0, 1);
269 VCorner (1, PAGEWID-1, 3);
270 VCorner (H+2, 0, 4);
271 VCorner (H+2, PAGEWID-1, 6);
272 VCorner (H+4, 0, 7);
273 VCorner (H+4, PAGEWID-1, 9);
274 break;
275 case VIEW_WIDE:
276 case VIEW_LONG:
277 VHorLine (H+2, 1, PAGEWID-2);
278 VVertLine (0, 2, H+2);
279 VVertLine (38, 2, H);
280 VVertLine (PAGEWID-1, 2, H+2);
281 VCorner (1, 0, 1);
282 VCorner (1, PAGEWID-1, 3);
283 VCorner (H+2, 0, 4);
284 VCorner (H+2, 38, 8);
285 VCorner (H+2, PAGEWID-1, 6);
286 VCorner (H+4, 0, 7);
287 VCorner (H+4, PAGEWID-1, 9);
288 break;
289 case VIEW_BRIEF:
290 VHorLine (H+2, 1, PAGEWID-2);
291 VVertLine (0, 2, H+2);
292 VVertLine (19, 2, H);
293 VVertLine (38, 2, H);
294 VVertLine (57, 2, H);
295 VVertLine (PAGEWID-1, 2, H+2);
296 VCorner (1, 0, 1);
297 VCorner (1, PAGEWID-1, 3);
298 VCorner (H+2, 0, 4);
299 VCorner (H+2, 19, 8);
300 VCorner (H+2, 38, 8);
301 VCorner (H+2, 57, 8);
302 VCorner (H+2, PAGEWID-1, 6);
303 VCorner (H+4, 0, 7);
304 VCorner (H+4, PAGEWID-1, 9);
305 break;
306 } else {
307 VHorLine (H+2, c+1, PAGEWID-2);
308 VVertLine (c, 2, H+2);
309 if (view == VIEW_BRIEF)
310 VVertLine (c+19, 2, H);
311 VVertLine (c+38, 2, H+2);
312 VCorner (1, c, 1);
313 VCorner (1, c+38, 3);
314 VCorner (H+2, c, 4);
315 VCorner (H+2, c+38, 6);
316 VCorner (H+4, c, 7);
317 if (view == VIEW_BRIEF)
318 VCorner (H+2, c+19, 8);
319 VCorner (H+4, c+38, 9);
320 }
321 VSetNormal ();
322 }
323
drawcwd(int col,char * wd)324 static void drawcwd (int col, char *wd)
325 {
326 register len;
327
328 if (! visualwin)
329 return;
330 len = strlen (wd);
331 if (widewin && col)
332 col = 38;
333 VMPutString (1, col + (39-len) / 2, wd);
334 }
335
drawpat(int col,char * pat,int width)336 static void drawpat (int col, char *pat, int width)
337 {
338 col += width - strlen (pat) - 1;
339 VMove (H+4, col);
340 VPutString (pat);
341 }
342
drawsdir(struct dir * c)343 static void drawsdir (struct dir *c) /* draw status window */
344 {
345 struct dir *d = c == &left ? &right : &left;
346 char buf [80];
347
348 /* print window name " Status " */
349 VSetDim ();
350 VHorLine (1, BASECOL (c) + 1, PAGEWID-2);
351 drawcwd (c->basecol, " Status ");
352 VHorLine (H+4, BASECOL (c) + 1, PAGEWID-2);
353 VSetNormal ();
354 VClearBox (2, BASECOL (c) + 1, 2, PAGEWID-2);
355 VClearBox (5, BASECOL (c) + 1, 6, PAGEWID-2);
356 VClearBox (12, BASECOL (c) + 1, H-8, PAGEWID-2);
357 sprintf (buf, "The Demos Commander, %s", DECOVERSION);
358 mvcaddstr (2, BASECOL (c) + PAGEWID/2 + 1, buf);
359 mvcaddstr (3, BASECOL (c) + PAGEWID/2 + 1, "Copyright (C) 1989-2000 S.Vakulenko");
360 mvcaddstr (5, BASECOL (c) + PAGEWID/2 + 1, "Directory");
361 mvcaddstr (6, BASECOL (c) + PAGEWID/2 + 1, d->shortcwd);
362 sprintf (buf, "\3%d\2 file%s", d->nfiles, d->nfiles==1 ? "" : "s");
363 mvcaddstr (7, BASECOL (c) + PAGEWID/2 + 2, buf);
364 sprintf (buf, "\3%s\2 byte%s", ltoac (d->nbytes), d->nbytes==1 ? "" : "s");
365 mvcaddstr (8, BASECOL (c) + PAGEWID/2 + 2, buf);
366 if (d->pattern [0]) {
367 sprintf (buf, "\3%s\2 byte%s in \3%d\2 matched file%s",
368 ltoac (d->mbytes), d->mbytes==1 ? "" : "s",
369 d->mfiles, d->mfiles==1 ? "" : "s");
370 mvcaddstr (9, BASECOL (c) + PAGEWID/2 + 3, buf);
371 }
372 if (d->tfiles) {
373 sprintf (buf, "\3%s\2 byte%s in \3%d\2 selected file%s",
374 ltoac (d->tbytes), d->tbytes==1 ? "" : "s",
375 d->tfiles, d->tfiles==1 ? "" : "s");
376 mvcaddstr (10, BASECOL (c) + PAGEWID/2 + 3, buf);
377 }
378 #ifdef notyet
379 mvcaddstr (13, BASECOL (c) + PAGEWID/2 + 1, "No .dirinfo file in this directory");
380 #endif
381 }
382
drawstatus(int col,struct file * f,int view)383 static void drawstatus (int col, struct file *f, int view)
384 {
385 /* draw current file status box */
386 VMove (H+3, col+2);
387 VSetDim ();
388 VPutChar (filetype (f));
389 VSetNormal ();
390 VPutChar (' ');
391 if (widewin) switch (view) {
392 case VIEW_FULL:
393 VPutString (filnam (f->name, 1));
394 drawtime (f);
395 break;
396 case VIEW_INFO:
397 case VIEW_LONG:
398 case VIEW_WIDE:
399 case VIEW_BRIEF:
400 drawfull (f, 1);
401 drawlong (f);
402 break;
403 } else
404 drawfull (f, 1);
405 }
406
407 /*
408 * Redraw file window
409 */
drawpage(int col,struct file * c,int n,struct dir * d)410 static void drawpage (int col, struct file *c, int n, struct dir *d)
411 {
412 register i;
413 char *info;
414
415 if (n > H)
416 n = H;
417 ++col;
418 for (i=0; i<n; ++i, ++c) {
419 VSetDim ();
420 VMPutChar (i+2, col, filetype (c));
421 if (c->tag) {
422 VPutChar ('>');
423 VSetBold ();
424 } else if (c->link) {
425 VPutChar ('@');
426 VSetNormal ();
427 } else {
428 VPutChar (' ');
429 VSetNormal ();
430 }
431 switch (d->view) {
432 case VIEW_INFO:
433 if (! widewin)
434 goto draw_long;
435 VPutString (filnam (c->name, 0)); /* 14 */
436 VPutChar (' '); /* 1 */
437 VPutChar (' '); /* 1 */
438 if (! c->infoflag)
439 setinfo (c, d);
440 if (! c->dateflag)
441 VSetDim ();
442 VPutString (filedate (c->infodate)); /* 8 */
443 if (! c->dateflag)
444 VSetPrev ();
445 if (c->rinfo && (lang==RUS || lang==UKR))
446 info = c->rinfo;
447 else
448 info = c->info;
449 if (info) {
450 VPutChar (' '); /* 1 */
451 VPutChar (' '); /* 1 */
452 VPutString (info); /* 48 */
453 }
454 break;
455 case VIEW_FULL:
456 drawfull (c, 0);
457 if (widewin)
458 drawlong (c);
459 break;
460 case VIEW_LONG:
461 draw_long: drawfull (c, 0);
462 break;
463 case VIEW_WIDE:
464 VPutString (filnam_wide (c->name));
465 break;
466 case VIEW_BRIEF:
467 VPutString (filnam (c->name, 0));
468 break;
469 }
470 if (c->tag)
471 VSetNormal ();
472 }
473 }
474
drawfull(struct file * f,int tail)475 static void drawfull (struct file *f, int tail)
476 {
477 VPutString (filnam (f->name, tail)); /* 14 */
478 VPutString (filesize (f)); /* 8 */
479 VPutChar (' '); /* 1 */
480 VPutChar (' '); /* 1 */
481 drawmode (filemode ((int) f->mode), (int) f->uid, (int) f->gid);
482 }
483
drawmode(char * m,int file_uid,int file_gid)484 static void drawmode (char *m, int file_uid, int file_gid)
485 {
486 int u, g;
487
488 u = (file_uid == uid);
489 g = mygroup (file_gid);
490 if (! u)
491 VSetDim ();
492 VPutChar (*m++);
493 VPutChar (*m++);
494 VPutChar (*m++);
495 if (u)
496 VSetDim ();
497 else if (g)
498 VSetPrev ();
499 VPutChar (*m++);
500 VPutChar (*m++);
501 VPutChar (*m++);
502 if (! u)
503 if (g)
504 VSetDim ();
505 else
506 VSetPrev ();
507 VPutChar (*m++);
508 VPutChar (*m++);
509 VPutChar (*m++);
510 if (u || g)
511 VSetPrev ();
512 }
513
drawtime(struct file * f)514 static void drawtime (struct file *f)
515 {
516 VPrint ("%4d/%-5d", f->dev, f->ino);
517 if (f->nlink > 1)
518 VPrint (" %-3d ", f->nlink);
519 else
520 VPutString (" ");
521 VPutString (timestr (f->atime));
522 VPutChar (' ');
523 VPutChar (' ');
524 VPutString (timestr (f->ctime));
525 }
526
drawlong(struct file * f)527 static void drawlong (struct file *f)
528 {
529 VPrint (" %8.8s.%-8.8s", username ((int) f->uid), groupname ((int) f->gid));
530 VPutString (timestr (f->mtime));
531 }
532
filnam(const char * p,int tail)533 static char *filnam (const char *p, int tail)
534 {
535 static char buf [20];
536 register char *s;
537 const char *e, *q;
538
539 if (strlen (p) > 14) {
540 if (tail) {
541 buf [0] = '~';
542 strcpy (buf+1, p + strlen(p) - 13);
543 } else {
544 strncpy (buf, p, 13);
545 buf [13] = '~';
546 }
547 return (buf);
548 }
549 for (s=buf; s<buf+14; *s++=' '); /* clear buf */
550 if (cdir->alignext) {
551 e = extension (p); /* make ptr to extension */
552 for (s=buf; p<e; *s++= *p++); /* copy file name */
553 for (q=e; *q; ++q); /* search extension end */
554 for (s=buf+13, --q; q>=e; *s--= *q--); /* copy extension */
555 } else {
556 e = p + 14; /* make ptr to end */
557 for (s=buf; *p && p<e; *s++= *p++); /* copy file name */
558 }
559 buf [14] = 0;
560 return (buf);
561 }
562
filnam_wide(const char * p)563 static char *filnam_wide (const char *p)
564 {
565 static char buf [40];
566 register char *s;
567 const char *e, *q;
568
569 #define N 33
570 if (strlen (p) > N) {
571 strncpy (buf, p, N-1);
572 buf [N-1] = '~';
573 return (buf);
574 }
575 for (s=buf; s<buf+N; *s++=' '); /* clear buf */
576 if (cdir->alignext) {
577 e = extension (p); /* make ptr to extension */
578 for (s=buf; p<e; *s++= *p++); /* copy file name */
579 for (q=e; *q; ++q); /* search extension end */
580 for (s=buf+N-1, --q; q>=e; *s--= *q--); /* copy extension */
581 } else {
582 e = p + N; /* make ptr to end */
583 for (s=buf; *p && p<e; *s++= *p++); /* copy file name */
584 }
585 buf [N] = 0;
586 return (buf);
587 }
588