amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (03/25/91)
Submitted-by: peter@taronga.hackercorp.com Posting-number: Volume 91, Issue 074 Archive-name: utilities/browser-1.7/part01 Well, 1.4 is now 2.0, and it's almost here. So this is probably going to be the last revision of Browser. I'm now using Workbench 2.0 on a daily basis, and I find I'm not using Browser that much. It remains faster than workbench and cleaner for quick jobs, but not enough for me to spend much time on it. However, lots of people remain in a 1.3 environment, and with the new release of the Aztec C compiler (5.0d) I've been able to clear up several outstanding bugs in Browser. Thus, the new release. What Browser does allow you to do, easily and conveniently, is to move, copy, rename, and delete files and directories. It will also let you execute either Workbench or CLI programs, either directly by double- clicking them or by selecting them from a menu. By combining these you can set up a complete operating environment that will, to a large extent, replace both Workbench and the CLI. #!/bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 1)." # Contents: PatMatch.c browser.doc fonts.h goodies.readme menu.c # menu.h vollist.c # Wrapped by tadguy@ab20 on Mon Mar 25 10:44:32 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'PatMatch.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'PatMatch.c'\" else echo shar: Extracting \"'PatMatch.c'\" \(5837 characters\) sed "s/^X//" >'PatMatch.c' <<'END_OF_FILE' X/* PatMatch.c - Implements AmigaDos Regular Expression Pattern Matching. X** X** This program will test whether a string is an AmigaDos regular expression X** It may be used to implement wild expressions such as: X** X** "copy #?.c to <dir>" to copy any file ending in .c X** X** The program has two entry points: CmplPat, and Match. X** X** CmplPat - takes a pattern and returns an auxilliary integer vector X** which is used by Match. The pattern is not modified in X** any way. CmplPat returns 1 if no errors were detected X** while compiling the pattern; otherwise it returns 0; X** X** Match - takes the pattern, the auxilliary vector, and the string X** to be matched. It returns 1 if the string matches the X** pattern; otherwise it returns 0; X** X** Translated from BCPL by: X** Jeff Lydiatt X** Richmond B.C. Canada X** 16 May 1986. X** X** Source: "A Compact Function for Regular Expression Pattern Matching", X** Software - Practice and Experience, September 1979. X** X** Useage: X** To test if "file.c" matches the regular expression "#?.c" X** char *Pat = "#?.c"; X** char *Str = "file.c"; X** WORD Aux[128]; X** X** if ( CmplPat( Pat, Aux ) == 0 ) X** { X** printf("Bad Wildcard Expression\n"); X** exit(1); X** } X** if ( Match( Pat, Aux, Str ) == 1 ) X** printf("String matches the pattern\n"); X** else X** printf("String does NOT match the pattern\n"); X**/ X X/*--- Included files ----*/ X X#include <stdio.h> X#include <exec/types.h> X#include <ctype.h> X X#define EOS '\0' X X/*--- Global Variables ---*/ X Xstatic char Ch; /* The current character in Pattern */ Xstatic char *Pat; /* Pointer to the Pattern */ Xstatic WORD *Aux; /* Pointer to returned auxilliary vector */ Xstatic int PatP; /* Current position in Pat */ Xstatic int Patlen; /* strlen(pat) */ Xstatic BOOL Errflag; /* TRUE if error */ Xstatic WORD *Work; /* Pointer to Active work area */ Xstatic int Wp; /* Current position in work */ Xstatic BOOL Succflag;/* True if "str" matches "pat" */ X X/*----------------------------------------------------------------*/ X/* The Interpreter */ X/*----------------------------------------------------------------*/ X Xstatic void Put(int N) X{ X register WORD *ip; X register WORD *to; X X if ( N == 0 ) X Succflag = TRUE; X else X { X for ( ip = &Work[ 1 ], to = &Work[ Wp ]; ip <= to; ip++) X if ( *ip == N ) X return; X Work[ ++Wp ] = N; X } X} X Xint Match( char *Pat, WORD *Aux, char *Str ) X{ X static WORD W[ 128 ]; X int S = 0; X int I, N, Q, P, Strlength; X char K; X int strlen(); X void Put(); X X Work = W; X Wp = 0; X Succflag = FALSE; X Strlength = strlen( Str ); X Put( 1 ); X X if ( Aux[ 0 ] != 0 ) X Put( Aux[ 0 ] ); X X for(;;) X { X /* First complete the closure */ X for( N=1; N <= Wp; N++ ) X { X P = Work[ N ]; X K = Pat[ P-1 ]; X Q = Aux[ P ]; X switch( K ) X { X case '#': Put( P + 1 ); X case '%': Put( Q ); X default : break; X case '(': X case '|': Put( P + 1); X if ( Q != 0 ) X Put( Q ); X } X } X X if ( S >= Strlength ) X return Succflag; X if ( Wp == 0 ) X return FALSE; X Ch = Str[ S++ ]; X X /* Now deal with the match items */ X X N = Wp; X Wp = 0; X Succflag = FALSE; X X for ( I = 1; I <= N; I++) X { X P = Work[ I ]; X K = Pat[ P - 1 ]; X switch( K ) X { X case '#': X case '|': X case '%': X case '(': break; X case '\'': K = Pat[ P ]; X default : if ( _toupper( Ch ) != _toupper( K ) ) X break; X case '?': /* Successful match */ X Put ( Aux[ P ] ); X } /* End Switch */ X } /* End For I */ X } /* End for(;;) */ X} X X X/*----------------------------------------------------------------*/ X/* The Compiler */ X/*----------------------------------------------------------------*/ X Xstatic void Rch(void) /* Read next character from Pat */ X{ X if ( PatP >= Patlen ) X Ch = EOS; X else X Ch = Pat[ PatP++ ]; X} X Xstatic void Nextitem(void) /* Get next char from Pat; recognize the ' escape char */ X{ X if ( Ch == '\'' ) X Rch(); X Rch(); X} X Xstatic void Setexits( int List, int Val ) X{ X int A; X X do X { X A = Aux[ List ]; X Aux[ List ] = Val; X List = A; X } X while ( List != 0 ); X} X Xstatic int Join( int A, int B ) X{ X int T = A; X X if ( A == 0 ) X return B; X while ( Aux[ A ] != 0 ) X A = Aux[ A ]; X Aux[ A ] = B; X return T; X} X Xstatic int Prim(void) /* Parse a Prim symbol */ X{ X int A = PatP; X char Op = Ch; X int Exp(); X void Setexits(), Nextitem(); X X Nextitem(); X switch( Op ) X { X case EOS: X case ')': X case '|': Errflag = TRUE; X default : return A; X case '#': Setexits( Prim(), A ); return A; X case '(': A = Exp( A ); X if ( Ch != ')' ) X { X Errflag = TRUE; X } X Nextitem(); X return A; X } X} X Xstatic int Exp( int AltP ) /* Parse an expression */ X{ X int Exits = 0; X int A; X int Prim(), Exits(), Join(); X void Nextitem(), Setexits(); X X for (;;) X { X A = Prim(); X if ( Ch == '|' || Ch == ')' || Ch == EOS ) X { X Exits = Join( Exits, A ); X if ( Ch != '|' ) X return Exits; X Aux[ AltP ] = PatP; X AltP = PatP; X Nextitem(); X } X else X Setexits( A, PatP ); X } X} X Xint CmplPat( char *Pattern, WORD *CmplPattern) X{ X int i, strlen(); X void Rch(), Setexits(); X X Pat = Pattern; X Aux = CmplPattern; X PatP = 0; X Patlen = strlen( Pat ); X Errflag = FALSE; X X for ( i = 0; i <= Patlen; i++ ) X Aux[ i ] = 0; X Rch(); X Setexits( Exp(0), 0 ); X return (!Errflag); X} END_OF_FILE if test 5837 -ne `wc -c <'PatMatch.c'`; then echo shar: \"'PatMatch.c'\" unpacked with wrong size! fi # end of 'PatMatch.c' fi if test -f 'browser.doc' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'browser.doc'\" else echo shar: Extracting \"'browser.doc'\" \(12580 characters\) sed "s/^X//" >'browser.doc' <<'END_OF_FILE' XBrowser -- a programmer's "Workbench". Release 1.7 X X) 1990 Peter da Silva X XIntroduction X X In earlier versions of Browser, I opened this document with the Xsomewhat confident comment: X X The Amiga "Workbench" has some serious deficiencies as X a working environment. The most important one is that X it doesn't let you operate on just any file (this is X rumored to be fixed in 1.4, by the way), but there are X others. It's designed to be easy to learn and use, but X it just isn't very powerful. X XWell, 1.4 is now 2.0, and it's almost here. So this is probably going to Xbe the last revision of Browser. I'm now using Workbench 2.0 on a daily Xbasis, and I find I'm not using Browser that much. It remains faster than Xworkbench and cleaner for quick jobs, but not enough for me to spend much Xtime on it. However, lots of people remain in a 1.3 environment, and with Xthe new release of the Aztec C compiler (5.0d) I've been able to clear up Xseveral outstanding bugs in Browser. Thus, the new release. X X This program is an attempt to deal with limitations in earlier Xversions of the Workbench. It runs under all versions of AmigaOS, including X2.0, but is expected to be most useful for people running 1.3 and earlier. XIt is not a complete replacement for Workbench, nor is it intended to be. XThere is no attempt to support icons, and there are no disk-oriented Xfunctions (formatting, copying, etc...). X X What Browser does allow you to do, easily and conveniently, is to Xmove, copy, rename, and delete files and directories. It will also let you Xexecute either Workbench or CLI programs, either directly by double- Xclicking them or by selecting them from a menu. By combining these you can Xset up a complete operating environment that will, to a large extent, Xreplace both Workbench and the CLI. X X Browser presents you with a set of windows, representing directories, Xwith all the files and directories within each listed in alphabetical Xorder. Directories, displayed in color 2 (red/orange), are listed first, Xfollowed by the files. Selected files are displayed in inverse video. X XSelecting Files X X You can select individual files three ways. First, just click on Xa file name. This will select that file and deselect all others. If you Xhold down the shift key when you click on the file, it will be selected Xwithout deselecting other files. This way you can build a list of files Xto operate on. So far this is just like Workbench, but if you click a Xselected file while holding down the shift key, it will be deselected Xwithout affecting other selected files. This lets you take back mistakes. X X Finally, you can use the menu items "Sel All" and "Sel Match" to Xselect a group of files at once. "Sel All" will select all files in the Xactive window. "Sel Match" will allow you to enter a pattern and then Xselect only files matching that pattern in the active window. These Xnormally act as toggles... if you have any selected files in the active Xwindow they will be deselected if they match. X XActions X X There are, again, three ways to manipulate selected files. First, Xyou can drag a file or selected files to another window by holding down the Xleft mouse button while you move the mouse. When you release the button, XBrowser will attempt to move the files to the location you indicate. This Xis just like the Workbench. X X Secondly, double-clicking a file will open it. If it's a directory, Xit will be opened and files in it will be displayed. If it's a program Xwith an accompanying '.info' file, it will be launched as a Workbench task. XThis will also work with Projects, if the accompanying .info file specifies Xa tool. Finally, Browser will ask you if you want to launch it as a CLI Xprogram. X X Any other files selected will be passed to the new program, either Xon the CLI command line or in the Workbench Args structure. This is the Xnormal Workbench shift-double-click method. X X Third, you can select a menu item. X XMenus X X There are two main Browser menus. The first, "Browser", relates to Xthe browser environment itself. The second, "Actions", relates to the files Xand directories displayed in Browser's windows. Menu items act either on Xselected files or on the currently active window. There are additional Xmenus (called Tools Menus) that can be set up by the user. X XBrowser Menu X X Open X X This entry is equivalent to double-clicking the selected X file. It is included for consistency with Workbench. Strictly X speaking it should be in the Actions menu, but it seems to fit X here better. X X Close X X This entry is equivalent to clicking the active window's X close gadget. Again, it's included for consistency with the X Workbench. X X Rescan X X This entry requests Browser to re-scan the directory displayed X in the active window. This is equivalent to, but a lot more convenient X than, closing and re-opening the window. I suppose I could poll the X disk for these, but if you use floppies much this becomes slightly X inconvenient. X X Show > X X This entry selects whether files, files and sizes, or full X file information is displayed for the current window. It has been X extended since 1.6a and is now provides a full set of options. X X Sel All X X This selects all files in the active window. Actually, it X toggles the selection of each file. Currently selected files will X be deselected. X X Sel Match... X X This is the same as Sel All, except that a pattern may be X provided to further restrict the selection. X X Options X X This allows you to modify the global behaviour of Browser X to some extent: X X X Toggle Selections X X This affects whether a selection through the menu, X or a shift-click, will deselect an already selected file. X X X Move files into subdirectories X X This effects whether you can move files into a X subdirectory by dragging them to it and releasing the mouse X button when the mouse is over the directory's name. If this X is not set you have to open the directory first. X X X Ask before moving into subdirectories X X If you permit files to be moved into subdirectories, X this determines if Browser will prompt you beforehand. X X Quit X X This selection closes all windows and terminates Browser. X XActions Menu X X The entries in this menu act on files rather than changing the state Xof Browser. X X WB Tool X X The currently selected file (singular) is entered into the X Tools menu as a workbench tool. X X CLI Tool... X X The currently selected file (singular) is entered into the X Tools menu as a CLI tool. Browser will pop up a requestor and allow X you to add additional arguments. X X Rename... X X The currently selected file (singular) is renamed. Browser X will pop up a requestor and allow you to enter the new name. X X Duplicate... X X The currently selected file (singular) is duplicated. Browser X will pop up a requestor and allow you to edit the new name (generated X by BumpRevision: "file" becomes "copy of file", and so on). X X Make Dir... X X Creates a new directory in the currently active window. X Browser will pop up a requestor and allow you to specify the name of X the new directory. X X Delete X X Deletes all selected files. This will only delete directories X if they happen to be empty. X X Delete All X X Deletes all selected files AND directories, recursively. X XTools Menus X X These menus (starting with Tools) are initially empty. They are filled Xin by selecting "Add * Tool" or from the file "s:browser.inittab". When you Xselect an entry in these menus they're run (either as workbench or CLI Xprograms) with all selected files being passed to the program. If you have Xa choice, you should make a program run under the Workbench... it's MUCH Xmore reliable. X XEnvironment X X Browser can itself be run from either the Workbench or the CLI. The Xseparate "bgbrowser" program no longer exists... use "runback" or some Xequivalent program if you want to run browser in a detached mode. X X Browser uses a file, "s:browser.inittab", to pre-load the command Xmenus. Each line in the file is a separate menu item, made up of 5 fields Xseparated by semicolons: X X name;environment;command;stack;window X X The first field is the name that is to appear in the menu. This Xname can be preceded by the name of the menu to insert it in followed by Xa period. If the menu name is left off, the "Tools" menu will be used. XFor example, "Applications.Terminal Emulator" will create a menu entry Xfor "Terminal Emulator" and install it in the "Applications" menu. If the Xmenu doesn't already exist, it will be created. X X The two environments currently supported are the CLI and the XWorkbench. Project files (such as AmigaBasic programs) aren't supported Xthrough the menu system at this time, though they may be at a later date. XThey do work just fine when you double-click them. X X If our terminal emulator was to be run as a Workbench program, then Xthis field should contain "Workbench". If it can't run under the Workbench, Xthen it should contain "CLI". It is better, if possible, to run programs Xunder the Workbench. It's a cleaner environment, and you don't get extra Xwindows cluttering up your display. X X The next field is the name of the command. This should contain the Xfull path name to the program. If the command is a CLI command, additional Xarguments can be included at this point. The names of any files highlighted Xwhen this menu is selected will be added to the end. If the command is Xa Workbench command, this should just be the program name. Highlighted Xfiles will be passed to the program in the Workbench Args structure. X X The next field is the stack size. It may be left off, and will Xdefault to 8K. X X The last field is the window. For a CLI command, this is the Xwindow that will be opened to run the CLI in. For a Workbench command, Xthis is the ToolWindow that will be passed to it. If it's left off a Xdefault will be used. X X Applications.Terminal Emulator;Workbench;sys:system/Termulator X XLimitations: X X The CLI capability occasionally leaves you in an interactive CLI Xafter you exit the program. This is caused by using one of the BREAK keys Xwhile you're in the program. I had to leave this in to get finicky CLI Xprograms, such as Manx 'Z' editor, to work properly. X X If you're copying a file to disk and you get a disk error, Xoccasionally browser will appear to ignore disk errors and keep on trying Xto write. Actually, Browser handles all disk errors that get reported to Xit. For some reason AmigaDOS doesn't report errors promptly. I suspect Xthis is related to requesting writes larger than a disk buffer, but I Xdon't plan on having Browser do anything about this in the near future. X X Browser seems to run just fine with only the standard 4K stack. The Xminimum environment you need to run browser is: X X libs (dir) X icon.library X XIf you also want to run CLI programs, you also need: X X c (dir) X cd EndCLI X Failat NewCLI X Run Stack X l (dir) X Ram-Handler X XThese are needed to run the little scripts Browser builds in RAM: when you Xrun a CLI program. X XAuthor: X X Peter da Silva X X U.S.Mail: X 15770 Bellaire Blvd. #107 X Houston, TX 77083 X X Phone: X +1 713 568 0480 (data: Taronga Park) X +1 713 274 5180 (work) X X Internet: X peter@taronga.hackercorp.com X Compuserve: X >internet:peter@taronga.hackercorp.com (preferred) X 70216,1076 X X I'm currently getting a new domain name, so if your mail to Xtaronga.hackercorp.com bounces or is delayed, try taronga.com. If all Xelse fails I'm currently working at Ferranti International Controls XCorporation, so try peter@ferranti.com. X XDonations: X X If you find this program useful, you may send a donation to the Xauthor, Peter da Silva. For a donation of thirty dollars or more you will Xreceive the latest version of Browser (or, if you prefer, the next version Xif it ever comes out... as I said, 1.7 is likely to be the ultimate release). X X If you have been waiting for the next release and it hasn't got Xto you, call me or send me email. With this release I'm sending all the Xfolks who contributed the program and a copy of the source. You should get Xa copy in the mail soon. X XSponsors: X X The following people have donated money, and are willing to have Xtheir names up in lights. Thanks, folks. In no particular order... X X <CB> X Kent and Judy Polk X Burkard S. Kr|ger X D. Ballinger X Ron Harper X Steven D. Kapplin X David Allen X Glen Fullmer X Ed Vishoot X Jeff Van Epps X P. Wright X Heinz Mathalm X Blaine Gardner X Liam Healy X Johan Widin X D. Ratliff X T. J. Pagano X J|rgen Klawitter X Ulrich Denker X Rick Jones X Guenther Engelhardt X XAnd special thanks to my wife, Stephanie, who talked me into doing this Xrelease. END_OF_FILE if test 12580 -ne `wc -c <'browser.doc'`; then echo shar: \"'browser.doc'\" unpacked with wrong size! fi # end of 'browser.doc' fi if test -f 'fonts.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fonts.h'\" else echo shar: Extracting \"'fonts.h'\" \(355 characters\) sed "s/^X//" >'fonts.h' <<'END_OF_FILE' X#ifndef FONTS_H X#define FONTS_H X#ifndef GRAPHICS_GFXBASE_H X#include <graphics/gfxbase.h> X#endif X#ifndef GRAPHICS_TEXT_H X#include <graphics/text.h> X#endif X Xextern struct GfxBase *GfxBase; X X#define FONTWIDTH (GfxBase->DefaultFont->tf_XSize) X#define FONTHEIGHT (GfxBase->DefaultFont->tf_YSize) X#define FONTBASELINE (GfxBase->DefaultFont->tf_Baseline) X#endif END_OF_FILE if test 355 -ne `wc -c <'fonts.h'`; then echo shar: \"'fonts.h'\" unpacked with wrong size! fi # end of 'fonts.h' fi if test -f 'goodies.readme' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'goodies.readme'\" else echo shar: Extracting \"'goodies.readme'\" \(451 characters\) sed "s/^X//" >'goodies.readme' <<'END_OF_FILE' XThe 'goodies' are sections of the source to Browser that I have previously Xreleased into the public domain, or that I got from the public domain. I Xfigure that you folks should benefit from them: X X PatMatch.c A very nice AmigaDOS-compatible regular expression parser. X menu.c A fairly clean way of dealing with lots of silly menus. X menu.h Needed for menu.c X fonts.h Needed for menu.c X vollist.c An Examine/ExNext type interface to the device list. END_OF_FILE if test 451 -ne `wc -c <'goodies.readme'`; then echo shar: \"'goodies.readme'\" unpacked with wrong size! fi # end of 'goodies.readme' fi if test -f 'menu.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'menu.c'\" else echo shar: Extracting \"'menu.c'\" \(8280 characters\) sed "s/^X//" >'menu.c' <<'END_OF_FILE' X/* easy menus: Copyright 1987 Peter da Silva, all rights reserved. X * X * Permission is granted to use this in any application, so long as X * this notice is retained in the source. Permission is granted to X * modify the code as you like, so long as this notice (between the X * first line beginning "easy menus" and the end of this paragraph, X * inclusive) is retained intact. X * X * Usage: X * X * #include "menu.h" X * X * struct MenuPtr menudata; X * struct MenuPtr *menuptr = &menudata; X * X * init_menus(menuptr); / * Just zero menu pointer out * / X * X * for(each menu item) { X * add_menu(menuptr, menu, item, subitem, flags); X * } X * X * Flags: X * SUBITEM_NOCHECK -- subitem does not require a checkmark. X * SUBITEM_SELECTOR -- subitem is a 1 of n selector, use mutual-exclude. X * SUBITEM_TOGGLE -- subitem is a toggled flag. X * SUBITEM_SELECTED -- defaults to checked. X * X * X * SetMenuStrip(yourwindow, menuptr->MenuBar); X * X * ... X * X * ClearMenuStrip(yourwindow); X * X * trash_menus(menuptr); X * X * Notes: X * X * if you don't want any subitems, use zero for the subitem value. X * X * subitem is always initialised as a CHECKIT item with all the other X * subitems mutually excluded. X * X * it is intended that the menu be set up with all action items in X * the first level of the menu, and all toggles in the second level... X * this is a piece of blatant authoritarianism on my part. I've seen X * too many menus with no rhyme or reason. Look at AmigaTerm (the term X * program that comes with the Amiga modem) some time. Baud rate has X * an item all by itself, but word size is hidden off in a menu with X * things like bell sound. X * X * the appearance of the menus produced by this is (in my humble X * opinion) good. I took some care making text centered in menu boxes, X * for example. X */ X#include <exec/memory.h> X#include <intuition/intuition.h> X#include "menu.h" X#include "fonts.h" X X/* Forward prototypes */ Xstatic void nudge(struct MenuItem *item, int delta); Xstatic struct Menu * X new_menu(struct MenuPtr *menuptr, char *name); Xstatic struct MenuItem * X new_item(struct MenuPtr *menuptr, X struct Menu *menu, UBYTE *name); Xstatic struct MenuItem * X new_subitem(struct MenuPtr *menuptr, X struct MenuItem *item, UBYTE *name, long flags); X X/* Xstruct MenuPtr { X struct Menu *MenuBar; X struct Remember *MenuMemory; X}; X*/ X Xchar *AllocRemember(); X Xstatic struct Menu *new_menu(); Xstatic struct MenuItem *new_item(), *new_subitem(); X X#define TOMENUNUM(i,j,k) (SHIFTMENU(i)|SHIFTITEM(j)|SHIFTSUB(k)) X#define TextLen(s) (strlen(s)*FONTWIDTH) X Xvoid trash_menus(struct MenuPtr *menuptr) X{ X FreeRemember(&menuptr->MenuMemory, 1); X menuptr->MenuMemory = 0; X menuptr->MenuBar = 0; X} X Xvoid init_menus(struct MenuPtr *menuptr) X{ X menuptr->MenuMemory = 0; X menuptr->MenuBar = 0; X} X Xint add_menu( X struct MenuPtr *menuptr, X char *menuname, X char *itemname, X char *subitemname, X long flags) X{ X int i, j, k; X struct Menu *menu; X struct MenuItem *item; X struct MenuItem *subitem; X X if(menuptr->MenuBar) { X for(i = 0, menu = menuptr->MenuBar; X menu; X menu = menu->NextMenu, i++ X ) X if(strcmp(menuname, menu->MenuName)==0) X break; X if(!menu) X menu = new_menu(menuptr, menuname); X if(!menu) X return MENUNULL; X } else { X i = 0; X menu = new_menu(menuptr, menuname); X if(!menu) X return MENUNULL; X } X for(j = 0, item = menu->FirstItem; X item; X item = item->NextItem, j++ X ) { X struct IntuiText *text; X text = (struct IntuiText *)item->ItemFill; X if(strcmp(itemname, text->IText) == 0) X break; X } X if(subitemname) { X if(!item) X item = new_item(menuptr, menu, (UBYTE *)itemname); X if(!item) X return MENUNULL; X for(k = 0, subitem = item->SubItem; X subitem; X subitem = subitem->NextItem, k++ X ) { X struct IntuiText *text; X text = (struct IntuiText *)subitem->ItemFill; X if(strcmp(subitemname, text->IText) == 0) X break; X } X if(!subitem) X subitem = new_subitem(menuptr, item, (UBYTE *)subitemname, flags); X if(!subitem) X return MENUNULL; X return TOMENUNUM(i, j, k); X } else { X if(!item) X item = new_item(menuptr, menu, (UBYTE *)itemname); X if(!item) X return MENUNULL; X return TOMENUNUM(i, j, NOSUB); X } X} X Xstatic struct Menu * Xnew_menu(struct MenuPtr *menuptr, char *name) X{ X struct Menu *menu; X X menu = (struct Menu *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct Menu), X MEMF_PUBLIC); X if(!menu) X return 0; X menu->NextMenu = NULL; X menu->LeftEdge = 0; X menu->TopEdge = 0; X menu->Width = TextLen(name)+FONTWIDTH; X menu->Height = 0; X menu->Flags = MENUENABLED; X menu->MenuName = name; X menu->FirstItem = 0; X if(menuptr->MenuBar) { X struct Menu *ptr, *prev; X for(ptr = menuptr->MenuBar; ptr; ptr=ptr->NextMenu) { X menu->LeftEdge += ptr->Width; X prev = ptr; X } X prev->NextMenu = menu; X } else { X menuptr->MenuBar = menu; X } X X return menu; X} X Xstatic struct MenuItem * Xnew_item(struct MenuPtr *menuptr, struct Menu *menu, UBYTE *name) X{ X struct MenuItem *item; X struct IntuiText *text; X X item = (struct MenuItem *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct MenuItem), X MEMF_PUBLIC); X if(!item) X return 0; X text = (struct IntuiText *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct IntuiText), X MEMF_PUBLIC); X if(!text) X return 0; X X text->FrontPen = AUTOFRONTPEN; X text->BackPen = AUTOBACKPEN; X text->DrawMode = JAM2; X text->LeftEdge = 1; X text->TopEdge = 1; X text->ITextFont = NULL; X text->IText = name; X text->NextText = NULL; X X item->NextItem = NULL; X item->LeftEdge = 0; X item->TopEdge = 0; X item->Width = IntuiTextLength(text)+2; X if(item->Width <= menu->Width) X item->Width = menu->Width+1; X item->Height = FONTHEIGHT+1; X item->Flags = ITEMTEXT|HIGHCOMP|ITEMENABLED; X item->MutualExclude = 0; X item->ItemFill = (APTR)text; X item->SelectFill = NULL; X item->Command = 0; X item->SubItem = NULL; X item->NextSelect = NULL; X X if(menu->FirstItem) { X struct MenuItem *ptr, *prev; X for(ptr = menu->FirstItem; ptr; ptr=ptr->NextItem) { X if(item->Width > ptr->Width) { X if(ptr->SubItem) X nudge(ptr->SubItem, item->Width-ptr->Width); X ptr->Width = item->Width; X } else if(ptr->Width>item->Width) X item->Width = ptr->Width; X prev = ptr; X } X item->TopEdge = prev->TopEdge + prev->Height; X prev->NextItem = item; X } else { X menu->FirstItem = item; X } X X return item; X} X Xstatic void nudge(struct MenuItem *item, int delta) X{ X while(item) { X item->LeftEdge += delta; X item = item->NextItem; X } X} X Xstatic struct MenuItem * Xnew_subitem( X struct MenuPtr *menuptr, X struct MenuItem *item, X UBYTE *name, X long flags) X{ X struct MenuItem *subitem; X struct IntuiText *text; X X subitem = (struct MenuItem *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct MenuItem), X MEMF_PUBLIC); X if(!subitem) X return 0; X text = (struct IntuiText *)AllocRemember( X &menuptr->MenuMemory, X sizeof(struct IntuiText), X MEMF_PUBLIC); X if(!text) X return 0; X X text->FrontPen = AUTOFRONTPEN; X text->BackPen = AUTOBACKPEN; X text->DrawMode = JAM2; X text->LeftEdge = 1; X if(flags != SUBITEM_NOCHECK) text->LeftEdge += CHECKWIDTH; X text->TopEdge = 1; X text->ITextFont = NULL; X text->IText = name; X text->NextText = NULL; X X subitem->NextItem = NULL; X subitem->LeftEdge = item->Width; X subitem->TopEdge = 0; X subitem->Width = IntuiTextLength(text)+2; X if(flags != SUBITEM_NOCHECK) subitem->Width += CHECKWIDTH; X subitem->Height = FONTHEIGHT+1; X subitem->Flags = ITEMTEXT|ITEMENABLED|HIGHCOMP; X subitem->MutualExclude = 0; X if(flags != SUBITEM_NOCHECK) { X subitem->Flags |= CHECKIT; X if(flags & SUBITEM_TOGGLE) subitem->Flags |= MENUTOGGLE; X if(flags & SUBITEM_SELECTED) subitem->Flags |= CHECKED; X } X subitem->ItemFill = (APTR)text; X subitem->SelectFill = NULL; X subitem->Command = 0; X subitem->SubItem = NULL; X subitem->NextSelect = NULL; X X if(item->SubItem) { X struct MenuItem *ptr, *prev; X int i; X for(i=0, ptr = item->SubItem; ptr; i++, ptr=ptr->NextItem) { X if(subitem->Width > ptr->Width) X ptr->Width = subitem->Width; X else if(ptr->Width>subitem->Width) X subitem->Width = ptr->Width; X prev = ptr; X } X subitem->TopEdge = prev->TopEdge + prev->Height; X if(flags & SUBITEM_SELECTOR) X subitem->MutualExclude = ~(1<<i); X prev->NextItem = subitem; X } else { X item->SubItem = subitem; X if(flags & SUBITEM_SELECTOR) X subitem->MutualExclude = ~1; X } X X return subitem; X} END_OF_FILE if test 8280 -ne `wc -c <'menu.c'`; then echo shar: \"'menu.c'\" unpacked with wrong size! fi # end of 'menu.c' fi if test -f 'menu.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'menu.h'\" else echo shar: Extracting \"'menu.h'\" \(359 characters\) sed "s/^X//" >'menu.h' <<'END_OF_FILE' Xstruct MenuPtr { X struct Menu *MenuBar; X struct Remember *MenuMemory; X int next_id; X}; X X/* flags */ X#define SUBITEM_NOCHECK 0x0 /* subitem does not require a checkmark. */ X#define SUBITEM_SELECTOR 0x10 /* subitem is a 1 of n selector */ X#define SUBITEM_TOGGLE 0x20 /* subitem is a toggled flag. */ X#define SUBITEM_SELECTED 0x01 /* defaults to checked. */ END_OF_FILE if test 359 -ne `wc -c <'menu.h'`; then echo shar: \"'menu.h'\" unpacked with wrong size! fi # end of 'menu.h' fi if test -f 'vollist.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'vollist.c'\" else echo shar: Extracting \"'vollist.c'\" \(1578 characters\) sed "s/^X//" >'vollist.c' <<'END_OF_FILE' X#include <libraries/dosextens.h> X#include <stdio.h> X#ifdef DEBUG X#include "debug.h" X#endif X/* Fakes an Examine/ExNext interface to the device list. Call OpenVolList X * first, then ReadVolList(fib), and finally CloseVolList. This last is X * a dummy, but it's handy if you want to be safe and put a forbid/permit X * around the whole thing. X */ X X#define toAPTR(b) ((b)<<2) X#define toBPTR(a) ((a)>>2) X Xstruct DeviceList *list; X Xvoid OpenVolList(void) X{ X extern struct DosLibrary *DOSBase; X struct RootNode *root; X struct DosInfo *info; X X root = (struct RootNode *)DOSBase -> dl_Root; X info = (struct DosInfo *)toAPTR(root->rn_Info); X list = (struct DeviceList *)toAPTR(info->di_DevInfo); X} X Xint ReadVolList(struct FileInfoBlock *fib) X{ X struct DeviceList *next; X X while(list) { X next = (struct DeviceList *)toAPTR(list->dl_Next); X if(list->dl_Type == DLT_VOLUME || X list->dl_Type == DLT_DIRECTORY) { X char *ptr; X int count; X ptr = (char *)toAPTR((BPTR)list->dl_Name); X count = *ptr++; X if(count > 106) X count = 106; X strncpy(fib->fib_FileName, ptr, count); X fib->fib_FileName[count++] = ':'; X fib->fib_FileName[count] = 0; X if(strcmp(fib->fib_FileName, "RAM Disk:") == 0) X strcpy(fib->fib_FileName, "RAM:"); X fib->fib_DiskKey = 0; X fib->fib_DirEntryType = list->dl_Type; X fib->fib_Protection = 0; X fib->fib_EntryType = list->dl_Type; X fib->fib_Size = 0; X fib->fib_NumBlocks = 0; X fib->fib_Date = list->dl_VolumeDate; X fib->fib_Comment[0] = 0; X list = next; X return 1; X } X list = next; X } X return 0; X} X Xvoid CloseVolList(void) X{ X} END_OF_FILE if test 1578 -ne `wc -c <'vollist.c'`; then echo shar: \"'vollist.c'\" unpacked with wrong size! fi # end of 'vollist.c' fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have the archive. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>. Mail comments to the moderator at <amiga-request@uunet.uu.net>. Post requests for sources, and general discussion to comp.sys.amiga.misc.