|
|
1.1 root 1: #include "contents.h"
2: #include <stdio.h>
3: #include <curses.h>
4:
5: char selection[15];
6: char filenames [MAXRECORDS][15];
7: char workfile[15];
8: char workstring[80];
9: char getfiles[26][115];
10: char open_mode;
11: int place[MAXRECORDS];
12: int limit, screen_num;
13:
14: void show_files(); /* this should display the filenames on a curses screen */
15: int lite(); /* inverse/normal video display of a filename */
16: int rfile(); /* read records from a given file */
17: void write_win(); /*does the actual work of writing filenames to a window */
18: void display_form(); /* for for displaying selected filename */
19: void display_record(); /* display selected filename */
20: void menu(); /* menu printed at bottom of screen */
21: void build_uucp(); /* this will build multiple uucp requests */
22:
23: struct entry{
24: char filename [15];
25: char filesize [10];
26: char date[7];
27: char description [78];
28: char requires [60];
29: char notes [78];
30: char pathname [60];
31: int noparts;
32: }
33:
34:
35: main(argc, argv)
36: int argc;
37: char *argv[];
38: {
39:
40: int x;
41:
42:
43: if(argc < 1)
44: {
45: printf("Usage: mwcbbs filename\n");
46: exit(1);
47: }
48:
49:
50: if(strlen(argv[1]) == 0)
51: {
52: printf("filename not specified. Please enter a filename: ");
53: gets (workfile);
54: }
55: else
56:
57: strcpy(workfile, argv[1]);
58:
59: open_mode = 'd';
60:
61: screen_num = 0;
62:
63: x = rfile();
64: show_files (x);
65:
66: }
67:
68:
69:
70:
71: /* show_files()
72: * This function will display the filenames read to a curses
73: * screen.
74: */
75:
76:
77: void show_files(EOF_FLAG)
78: int EOF_FLAG;
79:
80: {
81: char arrow;
82: int prevcol =1;
83: int prevrow =0; /* prevcol = column before arrow */
84: int newrow =0; /* prevrow = row before arrow */
85: int newcol =1; /* newrow = row after arrow */
86: int counter = 0; /* newcol = column after arrow */
87:
88:
89: WINDOW *win1, *win2;
90:
91: initscr();
92: noecho();
93: raw();
94:
95: /* allocate memory for window. print message on failure. */
96:
97: if((win1=newwin(20, 79, 0,0)) == NULL)
98: {
99: printf("\007Window Memroy allocation for win1 failed!\n");
100: exit(1);
101: }
102:
103: if((win2=newwin(20, 79, 0,0)) == NULL)
104: {
105: printf("\007Window Memroy allocation for win2 failed!\n");
106: exit(1);
107: }
108:
109: write_win(win1);
110: menu();
111:
112:
113: /* highlite a filename. This is accomplished by going to a designated
114: * row and column, as determined by the row and counter nested loops.
115: * The innermost loop gets the character found, copies the retrieved
116: * character into a string and deletes the character from the screen.
117: * When the filename has been deleted from the screen, it is reprinted
118: * to the screen with highliting turned on. Padding for spaces must be
119: * accounted for since deleting chars shifts everything on the line one
120: * space to the left.
121: */
122:
123: /* print the first file in inverse video */
124:
125: lite (win1, prevrow, prevcol, 1);
126:
127: do
128: {
129:
130: /* now we need to get a key (preferably an arrow) */
131:
132:
133:
134: arrow = getch(); /* This stupid code should allow to use arrows keys */
135: if (arrow == 27) /* that looks more frendly than hjkl. Vlad 8/15/91 */
136: {
137: getch();
138: arrow = getch(); /* When an arrow key is pressed, an escape */
139: if (arrow == 68) /* sequence is returned. The value '27' */
140: arrow = 'h'; /* begins the sequence and the relevant */
141: if (arrow == 67) /* values needed end the sequence. The */
142: arrow = 'l'; /* middle value is not needed, so it is */
143: if (arrow == 66) /* skipped over with a getch() statement */
144: arrow = 'j';
145: if (arrow == 65)
146: arrow = 'k';
147: }
148:
149:
150: /* each movement case in the following switch...case will test to see if the
151: * new position returns a space. If a space is returned, then we will hit
152: * an empty field, which we don't want to do. If we hit an empty space,
153: * then don't move the cursor.
154: */
155:
156: switch(arrow)
157: {
158: case 'h': /* move left */
159: newcol = prevcol - 15;
160: if (newcol < 1)
161: newcol = 61;
162: if (' ' == mvwinch(win1,newrow,newcol))
163: newcol = 1;
164: break;
165:
166:
167: case 'l': /* move right */
168: newcol = prevcol + 15;
169: if (newcol > 61)
170: newcol = 1;
171: if (' ' == mvwinch(win1,newrow,newcol))
172: newcol = 1;
173: break;
174:
175:
176: case 'j': /* move down */
177: newrow = prevrow + 1;
178: if (newrow == 20)
179: newrow = 0;
180: if (' ' == mvwinch(win1,newrow,newcol))
181: newrow = 0;
182: break;
183:
184:
185: case 'k': /* move up */
186: newrow = prevrow -1;
187: if (newrow == -1)
188: newrow = 19;
189: if (' ' == mvwinch(win1,newrow,newcol))
190: newrow = 0;
191: break;
192:
193:
194: case 'p':
195: screen_num --;
196: newrow = 0;
197: newcol = 1;
198: if (screen_num < 0)
199: screen_num = 0;
200: else
201: {
202: EOF_FLAG = rfile();
203: write_win(win1);
204: }
205: break;
206:
207:
208: case 'n':
209: newrow = 0;
210: newcol = 1;
211: if (EOF_FLAG == -1)
212: break;
213: else
214: {
215: screen_num ++;
216: EOF_FLAG = rfile();
217: write_win(win1);
218: }
219: break;
220:
221:
222: case 'q':
223: break;
224:
225: case 'Q':
226: break;
227:
228: case 'S':
229: case 's':
230: wclear(win1);
231: wrefresh(win1);
232: wclear(win2);
233: display_form(win2);
234: display_record(win2,prevrow, prevcol, screen_num);
235: clear();
236: menu();
237: write_win(win1);
238: wclear(win2);
239: wrefresh(win2);
240: refresh();
241: wrefresh(win1);
242: break;
243:
244: default:
245: newcol = prevcol;
246: newrow = prevrow;
247: break;
248:
249: }
250:
251: /* print previous file highlited in normal video */
252: lite (win1, prevrow, prevcol, 0);
253:
254: /* print new filename selection in inverse video */
255:
256: lite (win1, newrow, newcol, 1);
257:
258: /* set our previous coordinates so that we can go back
259: * and unlite a field when the next directin is given.
260: */
261:
262: prevrow = newrow;
263: prevcol = newcol;
264:
265:
266: }
267: while (arrow != 'q');
268:
269: echo();
270: noraw();
271: endwin();
272: }
273:
274:
275:
276:
277: /* this routine will take a pointer to a window and row/col
278: * coordinates and print a filename found at the coordinates
279: * in INVERSE video.
280: */
281:
282: int lite(win1, row, col, liteflag)
283:
284: WINDOW *win1;
285: int row, col, liteflag;
286:
287: {
288:
289: int x,y;
290: char litestring[15];
291:
292: wmove(win1, row,col);
293:
294: /* get existing filename char by char, deleting each
295: * char as it is read into a string variable.
296: */
297:
298: for(x=0; x<15; x++)
299: {
300: litestring[x] = winch(win1);
301: /* if we hit a space, we've hit the end of the filename */
302: if(litestring[x] == ' ')
303: break;
304: wdelch(win1);
305: }
306:
307: litestring[x] = '\0';
308:
309:
310: /* repad the spaces to keep the remaning filenames
311: * on this row in their proper columns.
312: */
313:
314: for(y=0;y<x;y++)
315: winsch(win1,' ');
316:
317: if (liteflag == 1)
318: wstandout(win1);
319:
320: waddstr(win1, litestring);
321: wmove(win1, row, col);
322:
323: if (liteflag == 1)
324: wstandend(win1);
325:
326:
327: /* copy filename to a string to be displayed on stdscr.
328: * as a filename is highlited, it is also displayed on
329: * stdscr. 'selection' will be used in case the user
330: * hits return to locate the filename's entry in the
331: * Contents file.
332: */
333:
334: strcpy(selection, litestring);
335: move (23,0);
336: printw("Selected filename is: %14s", selection);
337:
338: refresh();
339: wrefresh(win1);
340:
341: return(0);
342:
343: }
344:
345:
346:
347:
348:
349: int rfile()
350:
351: {
352: struct entry record;
353: FILE *infp;
354: int EOF_FLAG;
355:
356: /* open file, abort on error */
357:
358: if ((infp = fopen(workfile,"r")) == NULL)
359: {
360: printf("\007ERROR opening file for input!\n");
361: exit(1);
362: }
363:
364: /* open a file then go to a an offset calculated by a
365: * value passed from the calling program. Once we hit
366: * the max number of records that can be held by a screen,
367: * terminate the read and set a flag to show that we did
368: * not hit EOF. If we did hit EOF, terminate the loop
369: * and set a flag to show that we did hit EOF.
370: */
371:
372: /* start reading from a specified point in the file */
373: fseek(infp, (sizeof (struct entry) * (screen_num * 100)), 0l);
374:
375: limit = 0;
376: while((fread(&record, sizeof(struct entry),1, infp)) != 0)
377: {
378: strcpy(filenames[limit], record.filename);
379: place[limit] = limit;
380: limit++;
381: if (limit == 100)
382: break;
383: }
384:
385: /* if x made it to 100, then we did NOT hit EOF */
386:
387: if ( (limit == 100) && (fread (&record,sizeof(struct entry),1,infp)) != 0)
388: EOF_FLAG = 0;
389: else
390: EOF_FLAG = -1;
391:
392: fclose(infp);
393: return (EOF_FLAG);
394:
395: }
396:
397:
398:
399: /*
400: * writewin();
401: * this routine does the actual work of writing filenames to a window
402: */
403:
404: void write_win(win1)
405:
406: WINDOW *win1;
407:
408: {
409:
410: int r,c; /* these are our rows and columns */
411: int counter = 0; /* this counts the number of files written */
412:
413:
414:
415: /* clear the window */
416: wclear(win1);
417:
418: /* the following loop will write the filenames to the window.
419: * 15 characters per screen field are allowed, since a filename
420: * can only be 14 chars in length. This will leave at least one
421: * space between filenames.
422: */
423:
424: for (r = 0; r < 20; r++)
425: {
426:
427: /* if we've run out of files, terminate loop */
428:
429: if (counter == limit)
430: break;
431:
432: /* increment column by 15 positions. This
433: * will cause the filenames to line up
434: * on the window.
435: */
436:
437: for (c = 1; c < 75; c+= 15)
438: {
439: wmove(win1, r, c);
440: waddstr(win1, filenames[counter]);
441:
442: /* increment counter. When it equals the number of
443: * records, passed as 'limit', the loop should
444: * terminate.
445: */
446:
447: counter ++;
448: if (counter == limit)
449: break;
450: }
451: }
452:
453:
454: }
455:
456: /* this function will draw a template for the selected record */
457:
458: void display_form(win2)
459: WINDOW *win2;
460:
461:
462: {
463: int x;
464:
465: clear();
466: wclear(win2);
467:
468: /* print field labels */
469:
470: wmove (win2, NAMELOCATE );
471: waddstr (win2,"Filename:");
472:
473: wmove (win2, DESCLOCATE);
474: waddstr(win2,"Description:");
475:
476: wmove(win2, DATELOCATE );
477: waddstr(win2,"Date added/modified:");
478:
479: wmove(win2, SIZELOCATE);
480: waddstr(win2,"File size:");
481:
482: if(open_mode != 'd')
483: {
484: wmove(win2, PARTLOCATE);;
485: waddstr(win2,"Number of parts to download:");
486: }
487:
488: wmove(win2, REQLOCATE );
489: waddstr(win2,"Requires these other files:");
490:
491: wmove(win2, NOTELOCATE);
492: waddstr(win2,"Other notes:");
493:
494: if(open_mode != 'd')
495: {
496: wmove(win2, PATHLOCATE);
497: waddstr(win2, "Path to download file... Must give complete path including filename.");
498: wmove (win2, PATHLOCATE2);
499: waddstr(win2,"If a file is split into several parts, enter the first filename part");
500: wmove (win2, PATHLOCATE3);
501: waddstr(win2,"leaving the LAST character off of the filename:");
502: }
503:
504:
505: /* highlite available fields */
506:
507: wstandout(win2);
508:
509: wmove (win2, NAMEHI);
510: waddstr(win2," ");
511:
512: wmove (win2,DESCHI);
513: for (x=1;x<79;x++)
514: waddstr(win2," ");
515:
516: wmove(win2, DATEHI);
517: waddstr(win2," ");
518:
519: wmove(win2, SIZEHI);
520: waddstr(win2," ");
521:
522: if (open_mode != 'd')
523: {
524: wmove(win2,PARTHI);
525: waddstr(win2," ");
526: }
527:
528: wmove (win2,REQHI);
529: for (x=1;x<61;x++)
530: waddstr(win2," ");
531:
532: wmove (win2,NOTEHI);
533: for (x=1;x<69;x++)
534: waddstr(win2," ");
535:
536: if(open_mode != 'd')
537: {
538: wmove (win2, PATHHI);
539: waddstr(win2,PATHNAME);
540: for (x=23;x<61;x++)
541: waddstr(win2," ");
542: }
543:
544: wstandend(win2);
545: refresh();
546: wrefresh(win2);
547:
548:
549:
550: }
551:
552: /* following function prints the menu at the bottom of stdscr */
553:
554: void menu()
555:
556: {
557: /* print a menu of options to stdscr. They will appear at the bottom of
558: * the screen with the first letter highlited as an indication to
559: * the user that pressing the highlited key will result in the indicated
560: * action.
561: */
562:
563:
564:
565: if(open_mode == 'd')
566: {
567: move (21,0);
568: printw("Select file to download.");
569: refresh();
570: }
571:
572: move(21, 50);
573: standout();
574: printw("Options:");
575: move(22,46);
576: printw("n");
577: move(23,46);
578: printw("p");
579: move(22,60);
580: printw("q");
581: move(23,60);
582: printw("s");
583: standend();
584: move(22,47);
585: addstr("ext page");
586: move(23,47);
587: addstr("rev. page");
588: move(22,61);
589: addstr("uit");
590: move(23,61);
591: addstr("elect file");
592:
593:
594: }
595:
596:
597: /* this function will open the file and read the appropriate record,
598: * then display it on the window in the approp. positions.
599: */
600:
601: void display_record (win2, row, col, screen_num)
602: WINDOW *win2;
603: int row, col, screen_num;
604:
605: {
606: WINDOW *win3;
607: struct entry record;
608: char choice;
609: FILE *infp;
610: int x;
611:
612: if ((infp = fopen(workfile,"r")) == NULL)
613: {
614: printf("\007ERROR opening file for input!\n");
615: exit(1);
616: }
617:
618: fseek(infp,REC_FORMULA, 0l);
619: fread(&record, sizeof (struct entry),1,infp);
620: fclose (infp);
621:
622: wstandout(win2);
623:
624: wmove(win2,NAMEHI);
625: waddstr(win2,record.filename);
626:
627: wmove(win2,DESCHI);
628: waddstr(win2,record.description);
629:
630: wmove(win2,DATEHI);
631: wprintw(win2,"%.6s",record.date);
632:
633: wmove(win2,SIZEHI);
634: waddstr(win2,record.filesize);
635:
636: if(open_mode != 'd')
637: {
638: wmove(win2,PARTHI);
639: wprintw(win2,"%.2d",record.noparts);
640: }
641:
642: wmove(win2,REQHI);
643: waddstr(win2,record.requires);
644:
645: wmove(win2,NOTEHI);
646: waddstr(win2,record.notes);
647:
648: if(open_mode != 'd')
649: {
650: wmove(win2,PATHHI);
651: waddstr(win2,record.pathname);
652: }
653:
654: wrefresh(win2);
655: wstandend(win2);
656:
657:
658: /* allocate another window as a message area */
659:
660: if ( (win3=newwin(2,40,20,0)) == NULL)
661: {
662: printf("Memory allocation for win3 failed!\n");
663: exit(1);
664: }
665:
666:
667: wclear(win3);
668: wmove(win3,0,0);
669: waddstr(win3,"Press <RETURN> for next screen.");
670: wrefresh(win3);
671: while(13 != wgetch(win3))
672: ;
673:
674: /* the following will display an extended screen of download information
675: * and ask the user if he/she wants to download the file */
676:
677: wclear(win2);
678: wmove(win2,1,0);
679: waddstr(win2,"Size of file is: ");
680: wmove(win2,1,40);
681: waddstr(win2,"Number of parts to download: ");
682: wstandout(win2);
683: wmove(win2,1,18);
684: waddstr(win2,record.filesize);
685: wmove(win2,1,69);
686: record.noparts = (record.noparts == 0) ? 1 : record.noparts;
687: wprintw(win2,"%d",record.noparts);
688: wstandend(win2);
689: wmove(win2,3,5);
690: wprintw(win2,"The following commands will be needed to download ");
691: wstandout(win2);
692: waddstr(win2,record.filename);
693: wstandend(win2);
694:
695: /* if there is more than one part to download, call a function to generate
696: * the multiple uucp requests necessary to grab each piece from mwcbbs.
697: */
698:
699: if (record.noparts >1)
700: {
701: build_uucp(record);
702: for (x=0;x<record.noparts;x++)
703: {
704: /* limit ourselves to 10 displayed commands */
705: if (x==10)
706: {
707: wmove(win2,16,0);
708: wprintw(win2,"There are %d more parts to download which do not appear on ths screen.", (record.noparts - x));
709: break;
710: }
711: wmove(win2,5+x,0);
712: waddstr(win2,getfiles[x]);
713: }
714: }
715: else
716: {
717: strcpy(getfiles[0],HOST);
718: strcat(getfiles[0],record.pathname);
719: strcat(getfiles[0],RECEIVER);
720: wmove(win2,5,0);
721: waddstr(win2,getfiles);
722: wrefresh(win2);
723: }
724:
725: wclear(win3);
726: wmove(win3,0,0);
727: waddstr(win3,"Do you wish to download this file?");
728: wmove(win3,1,0);
729: waddstr(win3,"[y] yes or any other key to abort.");
730: wrefresh(win2);
731: wrefresh(win3);
732: choice = '\0';
733: while(choice == '\0')
734: choice = wgetch(win3);
735:
736: if(choice == 'y' || choice == 'Y')
737: {
738: wclear(win3);
739: wmove(win3,0,0);
740: waddstr(win3,"Processing requests...");
741: wrefresh(win3);
742: for(x = 0; x < record.noparts; x++)
743: system(getfiles[x]);
744: wclear(win3);
745: wmove(win3,0,0);
746: waddstr(win3,"Press <RETURN> to continue.");
747: wrefresh(win3);
748: while(13 != wgetch(win3))
749: ;
750:
751: wclear(win2);
752: wmove(win2,5,15);
753: waddstr(win2,"The following file(s) will be recevied by your system:");
754: wmove(win2,7,1);
755: if (record.noparts <2)
756: {
757: waddstr(win2,record.pathname);
758: wrefresh(win2);
759: }
760: else
761: {
762: record.pathname[strlen(record.pathname)] = 'a';
763: waddstr(win2,record.pathname);
764: record.pathname[(strlen(record.pathname) -1) ] = 97 + record.noparts-1;
765: wmove(win2,8,15);
766: waddstr(win2,"-thru-");
767: wmove(win2,9,1);
768: waddstr(win2,record.pathname);
769: wmove(win2,11,1);
770: waddstr(win2,"When you receive these files, concatenate them into one file");
771: wmove(win2,12,1);
772: waddstr(win2,"named: ");
773: wstandout(win2);
774: wmove(win2,12,9);
775: waddstr(win2,record.filename);
776: wstandend(win2);
777: wrefresh(win2);
778: }
779: wclear(win3);
780: wmove(win3,0,0);
781: waddstr(win3,"Press <RETURN> to continue.");
782: wrefresh(win3);
783: while(13 != wgetch(win3))
784: ;
785: }
786:
787: }
788:
789:
790: /* this function will take the pathname and append the necessary
791: * character(s) to generate the multiple requests necessary to
792: * download multipart files.
793: */
794:
795: void build_uucp(record)
796: struct entry *record;
797:
798: {
799: int x,y;
800:
801: y = strlen(record.pathname);
802:
803: for(x=0;x< record.noparts;x++)
804: {
805: strcpy(getfiles[x],HOST);
806: record.pathname[y] = 97 + x;
807: strcat(getfiles[x],record.pathname);
808: strcat(getfiles[x],RECEIVER);
809: }
810: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.