home *** CD-ROM | disk | FTP | other *** search
- /*
- * browser - Rummage around on disks.
- *
- * copyright (c) 1986, Mike Meyer
- *
- * Permission is hereby granted to distribute this program, so long as this
- * source file is distributed with it, and this copyright notice is not
- * removed from the file.
- *
- * modified Mark Schretlen 86-10-04
- * last update 87-01-11
- *
- */
-
- #include <exec/types.h>
- #include <graphics/gfxbase.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <intuition/intuition.h>
- #include <stdio.h>
- #define INTUITION_REV 1L
- #define GRAPHICS_REV 1L
-
- #define LONGEST_NAME 80 /* Longest file name we can deal with */
- #define LONGEST_LINE 256 /* Longest line we will deal with */
- #define AVG_LINE_LENGTH 62 /* A guess, tune it if you need to */
- #define FILEINFOBLOCKSIZE 256 /* m.e.s. for memory allocation in Add_Dir */
- #define FUDGE 6L /* A fudge factor for the scroll bar */
-
- #define UP_GADGET 0 /* switch flags for Gadget ID */
- #define DOWN_GADGET 1
- #define SCROLL_GADGET 2
- #define NEW_FILE 3
-
- #define GWIDTH 14 /* Width of gadget */
- #define GHEIGHT 9
- struct SpriteImage {
- UWORD posctl[2];
- UWORD sprdata[2][15];
- UWORD reserved[2];
- };
-
- #define FIRST 18L
-
- /*
- * Gadget structures put in browser.h
- */
-
- #include "browser.h"
-
- /*
- * doggy sprite (M.E.S. 86-10-01)
- */
- struct SpriteImage Doggy[34] = {
- 0x0002, 0x0002, /* VStart, VStop */
- 0x0002, 0x0,
- 0x3A02, 0x0,
- 0x2A02, 0x1000,
- 0xFA02, 0x8000,
- 0xF9FE, 0x0,
- 0xFFFE, 0x0,
- 0x1FFE, 0x0,
- 0x1FFE, 0x0,
- 0x1FFC, 0x0,
- 0x1FFC, 0x0,
- 0x0A14, 0x0,
- 0x0A14, 0x0,
- 0x0A14, 0x0,
- 0x0A14, 0x0,
- 0x0A14, 0x0,
- 0x0000, 0x0000 }; /* End of Sprite */
- /*
- * Now, the window for it all
- */
- struct NewWindow New_Window = {
- 0, 0, 640, 200, /* Full screen */
- -1L, -1L, /* Default pens */
- MENUPICK | CLOSEWINDOW /* I want to know about menupicks */
- | GADGETUP, /* Window closes and gadgets */
- ACTIVATE /* Standard window */
- | SMART_REFRESH | NOCAREREFRESH | SIZEBBOTTOM
- | WINDOWSIZING | WINDOWDEPTH | WINDOWCLOSE | WINDOWDRAG,
- &Down_Gadget, /* Add scroll gadget */
- /*(struct Image *)*/ NULL,
- "Browser 1.2 by Mark Schretlen ;original-Mike Meyer;scroll-B.Leivian", /* Title */
- /*(struct Screen *)*/NULL,
- /*(struct BitMap *)*/NULL,
- 100, 57, /* Minimum sizes */
- 640, 200, /* Maximum sizes */
- WBENCHSCREEN /* and put it on the workbench */
- } ;
-
- /*
- * My very own variables (mostly for done)
- */
- struct Window *My_Window = NULL ;
- static FILE *infile = NULL ; /* Current input file */
- static void Page_File(unsigned short) ;
-
- /* file statistics M.E.S. 87-01-11 */
- struct FStatistics *stats;
- struct FStatistics fileInformation = { 0L,0L,0L };
-
- /*
- * And someone else's variables
- */
- struct IntuitionBase *IntuitionBase ;
- struct GfxBase *GfxBase ;
- extern struct Menu *AutoMenu ;
-
- /*
- * Finally, declare the string twiddling functions as voids
- */
- void strcat(char *, char *), strcpy(char *, char *) ,
- strncat(char *, char *, int) ;
-
- main() {
- register struct IntuiMessage *message,*GetMsg(struct MsgPort *);
- register unsigned short class, code ;
- APTR address;
- USHORT gadID;
-
- /* Set up the world this lives in */
- if ((IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", INTUITION_REV)) == NULL)
- done(20, "can't open intuition library") ;
-
- if ((GfxBase = (struct GfxBase *)
- OpenLibrary("graphics.library", GRAPHICS_REV)) == NULL)
- done(20, "can't open graphics library") ;
-
- /* set up the scroll bar */
- prop.Flags = FREEVERT | AUTOKNOB | KNOBHIT ;
- prop.VertBody = 0x1000;
-
- if ((My_Window = (struct Window *) OpenWindow(&New_Window)) == NULL)
- done(20, "can't open the window") ;
-
- SetAPen(My_Window -> RPort,3) ; /* Should be default! */
-
- show_message("Pick Disk with Menu Button ");
-
- /* Set up the first menu level */
- Menu_Init() ;
- Menu_Add("disks ", 1L) ;
- Menu_Item_Add("df0:", ITEMENABLED, 0L, 0) ;
- Menu_Item_Add("df1:", ITEMENABLED, 0L, 0) ;
- Menu_Item_Add("df2:", ITEMENABLED, 0L, 0) ;
- Menu_Item_Add("DH0:", ITEMENABLED, 0L, 0) ;
- Menu_Item_Add("RAM:", ITEMENABLED, 0L, 0) ;
- Menu_Item_Add("VDK:", ITEMENABLED, 0L, 0) ;
- SetMenuStrip(My_Window, AutoMenu) ;
-
- SetPointer(My_Window, Doggy,15,16,0,-4);
-
- /* Now spin on messages, handling them as they arrive */
- for (;;) {
- Wait(1L << (long) My_Window -> UserPort -> mp_SigBit) ;
- while (message = GetMsg(My_Window -> UserPort)) {
- class = message -> Class ;
- code = message -> Code ;
- address = message -> IAddress;
- ReplyMsg(message) ;
- switch (class) {
- case CLOSEWINDOW:
- done(0, NULL) ;
-
- case MENUPICK:
- if (code != MENUNULL)
- Examine_Menu_Pick(code) ;
- break ;
-
- case GADGETUP:
- gadID = ((struct Gadget *)address) -> GadgetID;
- Page_File(gadID);
- break ;
-
- default:
- printf("browser: intuition event 0x%x\n", class) ;
- done(20, "unexpected intution event") ;
- break ;
- }
- }
- }
- done(20, "broke out of never-breaking loop!") ;
- }
-
-
- /*
- * Examine_Menu_Pick - takes a menu pick, and twiddles the state variables
- * to match that pick.
- */
- static
- Examine_Menu_Pick(Menu_Number)
- unsigned short Menu_Number;
- {
- register unsigned short level, i, dirp ;
- register char *cp ;
- char *name, *strchr(char *,int) ;
- struct MenuItem *ItemAddress(struct Menu *, unsigned short) ;
- /* State variables that describe the current directory */
- static char Dir_Name[LONGEST_NAME] ;
- static unsigned short Menu_Level = 0 ;
-
- name = ((struct IntuiText *)
- (ItemAddress(AutoMenu,Menu_Number) -> ItemFill)) -> IText ;
- level = MENUNUM(Menu_Number) ;
-
- /* Got what we want, so clear the menu to avoid confusing the user */
- ClearMenuStrip(My_Window);
- OffGadget((APTR)&Scroll_Gadget, My_Window, NULL);
- OffGadget((APTR)&Up_Gadget, My_Window,NULL);
- OffGadget((APTR)&Down_Gadget, My_Window,NULL);
-
- SetWindowTitles(My_Window,"Browser 1.2 by Mark Schretlen (original by Mike Meyer) ",-1);
-
- /* set dirp to FALSE if the name is not a directory or disk */
- dirp = (strchr(name, '/') != NULL || strchr(name, ':') != NULL) ;
-
- /* First, set the directory name right */
- if (level > Menu_Level) /* Not possible, die */
- done(20, "impossible menu value returned") ;
- else if (level == 0) /* picked a new disk */
- Dir_Name[0] = '\0' ;
- else if (level < Menu_Level) { /* Throw away some levels */
- for (i = 1, cp = strchr(Dir_Name, ':'); i < level; i++) {
- if (cp == NULL) done(20, "broken file name") ;
- cp = strchr(cp, '/') ;
- }
- if (cp == NULL) done(20, "broken file name") ;
- *++cp = '\0' ;
- }
- /* else Menu_Level == level, chose a file at current level */
-
- /* Now, fix up the menu and it's state variable */
- while (Menu_Level > level) {
- Menu_Level-- ;
- Menu_Pop() ;
- }
-
- /* If we added a directory, tack it onto the name */
- if (dirp) {
- Menu_Level++ ;
- strncat(Dir_Name, name, LONGEST_NAME - strlen(Dir_Name) - 1) ;
- }
-
- /* Now, tell the user all about it */
- if (dirp)
- Add_Dir(Dir_Name, name) ;
- else
- Display_File(Dir_Name, name) ;
- SetMenuStrip(My_Window, AutoMenu) ;
- }
-
- /*
- * Add_Dir - given a dir and a name, add the menu name with the files in
- * dir as entries.
- */
- static
- Add_Dir(dir, name) char *dir, *name; {
- struct FileInfoBlock *File_Info ;
- register char *last_char ;
- register struct FileLock *my_lock, *Lock(char *, int) ;
- unsigned short count ;
- static char Name_Buf[LONGEST_NAME] ;
-
- File_Info = (struct FileInfoBlock *)AllocMem(FILEINFOBLOCKSIZE,0);
-
- /* Fix up the trailing / if it needs it */
- last_char = &dir[strlen(dir) - 1] ;
- if (*last_char == '/') *last_char = '\0' ;
-
- /* Now, start on the directory */
- if ((my_lock = Lock(dir, ACCESS_READ)) == NULL) {
- done(20, "can't get lock on file") ;
- }
-
- if (!Examine(my_lock, File_Info)) done(20, "can't examine file") ;
- if (File_Info -> fib_DirEntryType < 0)
- done(20, "Add_Dir called with a non-directory") ;
-
- Menu_Add(name, TRUE) ;
-
- SetAPen(My_Window -> RPort,3) ;
- show_message("Loading Directory ");
-
- for (ExNext(my_lock, File_Info), count = 0;
- IoErr() != ERROR_NO_MORE_ENTRIES;
- ExNext(my_lock, File_Info), count++)
- if (File_Info -> fib_DirEntryType < 0)
- /* file */
- Menu_Item_Add(File_Info -> fib_FileName, ITEMENABLED, 0L, 0) ;
- else {
- /* directory */
- strcpy(Name_Buf, File_Info -> fib_FileName) ;
- strcat(Name_Buf, "/");
- Menu_Item_Add(Name_Buf, ITEMENABLED, 0L, 0) ;
- }
- if (count == 0) Menu_Item_Add("EMPTY", 0L, 0L, 0) ;
-
- show_message("Directory Available ");
-
- /* Put everything back */
- if (*last_char == '\0') *last_char = '/' ;
- FreeMem(File_Info,FILEINFOBLOCKSIZE);
- UnLock(my_lock) ;
- }
-
- /*
- * Display_File - given a directory path and file name, put the first page of
- * the file in the window.
- */
-
- long aprox_lines,file_size;
- static long Page_Length = 22L;
-
- static
- Display_File(dir, name)
- char *dir, *name;
- {
- static char File_Name[LONGEST_NAME];
- FILE *fopen();
- long ftell();
- long i,pages;
- extern char *ChangeToString();
- extern FILE *parsefile();
- extern struct FStatistics *stats,fileInformation;
- char *num_of_lines,*num_of_bites;
-
- stats = &fileInformation;
- /* Get the file name */
- strcpy(File_Name, dir);
- strcat(File_Name, name);
-
- if (infile != NULL)
- fclose(infile);
-
- if ((infile = fopen(File_Name, "r")) == NULL) {
- #ifdef DEBUG
- printf("Can't open File: %s\n", File_Name) ;
- #endif
- done(20, "can't open file") ;
- }
-
- /* set up the prop gadget for scrolling */
- infile = parsefile(infile);
- aprox_lines = stats->lines;
- file_size = stats->bites;
-
- prop.Flags = FREEVERT | AUTOKNOB;
- if (Page_Length >= aprox_lines)
- i = 0xFFFF;
- else
- {
- pages = aprox_lines/Page_Length;
- if (aprox_lines%Page_Length != 0) pages++;
- i = 0xFFFF / pages; /* FFFF=100% - 0000=0% */
- }
- prop.VertBody = i;
- prop.VertPot = 0L;
- fseek(infile, 0L, 0);
-
-
- if (Page_Length < aprox_lines)
- {
- OnGadget((APTR)&Down_Gadget,My_Window,NULL);
- OnGadget((APTR)&Up_Gadget,My_Window,NULL);
- /* enable the scroll bar */
- OnGadget((APTR)&Scroll_Gadget, My_Window, NULL);
- }
-
- SetWindowTitles(My_Window,"Browser 1.2 **** To page, hit appropriate arrow gadget. ****",-1);
- Move(My_Window->RPort,FIRST + 5L ,(long)(My_Window->Height - 5L));
- Text(My_Window->RPort," ",45L);
- Move(My_Window->RPort,FIRST + 5L ,(long)(My_Window->Height - 5L));
- SetAPen(My_Window->RPort,3);
- /* SetSoftStyle(My_Window->RPort, FSF_UNDERLINED,255); */
- Text(My_Window->RPort,name,(long)strlen(name));
- Text(My_Window->RPort," ",3L);
- num_of_bites = ChangeToString(file_size);
- Text(My_Window->RPort,num_of_bites,(long)strlen(num_of_bites));
- Text(My_Window->RPort," bytes",6L);
- Text(My_Window->RPort," ",3L);
- num_of_lines = ChangeToString(aprox_lines);
- Text(My_Window->RPort,num_of_lines,(long)strlen(num_of_lines));
- Text(My_Window->RPort," lines",6L);
-
- SetAPen(My_Window->RPort,1);
- /* SetSoftStyle(My_Window->RPort, FS_NORMAL,255); */
-
- Move(My_Window->RPort,FIRST,17L);
-
- Page_File((USHORT)NEW_FILE); /* Down from page 0 */
- }
-
- /*
- * Page_File - move the file up or down one "page"
- */
- static void
- Page_File(direction)
- USHORT direction;
- {
- long where;
- static char buffer[LONGEST_LINE];
- static char edited[84]; /* allow room for a tab at end */
- static long old_pos;
- static long bites_this_page;
- static long next_page;
- static long size;
- int end_flag = 0;
- long Line_Length;
- int i,j;
- long new_pos;
- char *p;
-
- if (infile == NULL) return ;
-
- Page_Length = ((My_Window -> Height) - 20) / 8 ;
- Line_Length = (My_Window -> Width - (3+FIRST)) / 8;
-
- switch(direction)
- {
- case UP_GADGET:
- new_pos = old_pos;
- old_pos = 1L;
- break;
- case DOWN_GADGET:
- new_pos = next_page;
- break;
- case SCROLL_GADGET:
- /* compute new position based on the users scroll bar pot */
- new_pos = (file_size * prop.VertPot) / 0xFFFF;
- break;
- case NEW_FILE:
- bites_this_page = 0L;
- next_page = 0L;
- new_pos = 0L;
- old_pos = 1L;
- size = 0L;
- break;
- }
-
-
-
- if (new_pos < 0) new_pos = 0L;
-
- /* if past end of file, back up approx 1/2 page */
- if (new_pos > file_size)
- new_pos = file_size - (bites_this_page / 2);
-
- if ( new_pos == old_pos ) return; /* no change */
-
- where = (new_pos * 0xFFFF)/file_size ;
- ModifyProp(&Scroll_Gadget,My_Window,NULL,prop.Flags,0,where,0,prop.VertBody);
-
- old_pos = (new_pos + (size +2)) - bites_this_page ; /* backup one page */
- bites_this_page = 0L;
-
- fseek(infile, new_pos, 0);
-
- /* discard a partial line */
- if (new_pos)
- fgets(buffer, LONGEST_LINE, infile);
-
- /* now put out one page's worth of the file's data */
-
-
- for (where = 17L, j = Page_Length; j--; where = where + 8L)
- {
- Move(My_Window -> RPort,FIRST,where ) ;
-
- /* blank the buffer first */
- for (i = 0; i < 80; i++)
- edited[i] = ' ';
-
- if (!end_flag)
- {
- if (fgets(buffer, LONGEST_LINE, infile) == NULL)
- end_flag = TRUE;
- else
- {
- size = strlen(buffer);
- bites_this_page = size + bites_this_page;
-
- /* remove the newline */
- buffer[size-1] = '\0';
- size--;
-
- p = buffer;
- size = 0;
-
- /* edit the buffer for tabs and non-printables */
- while(*p)
- {
- if (*p == '\t')
- {
- do {
- edited[size++] = ' ';
- } while(size&3);
- }
- else if(*p < ' ')
- {
- edited[size++] = '^';
- edited[size++] = *p + '@';
- } else
- edited[size++] = *p;
-
- p++;
-
- /* mark the line as longer than the window */
- if (size >= Line_Length)
- {
- edited[size-1] = '>';
- break;
- }
- }
- }
- }
- Text(My_Window -> RPort, edited, Line_Length);
- } /* for 1 page to size of window */
- next_page = (bites_this_page + new_pos) - (size + 2);
- return;
- }
-
- /*
- * done - just close everything that's open, and exit.
- */
- static
- done(how, why)
- int how;
- char *why;
- {
-
- if (My_Window) {
- ClearMenuStrip(My_Window) ;
- Menu_Clear() ;
- CloseWindow(My_Window) ;
- }
- if (GfxBase) CloseLibrary(GfxBase) ;
- if (IntuitionBase) CloseLibrary(IntuitionBase) ;
- if (infile) fclose(infile) ;
-
- if (why)
- printf("browser: %s\n", why) ;
- (void) OpenWorkBench() ;
- exit(how) ;
- }
-
- show_message(s)
- char *s;
- {
- Move(My_Window -> RPort, FIRST, 17L);
- Text(My_Window -> RPort, s, (long) strlen(s));
- Move(My_Window -> RPort, FIRST, 25L);
- Text(My_Window -> RPort, " ", 20L);
- }
-