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