/ / / You shouldn't be reading these lines! Start the program USER_DOC.PRG / instead to be presented with menu-driven documentation. / / / / #:help Use the arrow keys or the mouse to navigate the menus. Right-arrow or left mousebutton pops in a menu, left-arrow or right mousebutton pops out again. At any time 'ClrHome' brings you back to the first menu. You may also use 'Return' to pop in a menu, or 'Undo' to pop out. 'Escape' quits the program altogether. 'Help' brings you to this menu. Now press the left-arrow/right mousebutton/Undo to go back to where you came from. / / #:main U| A users guide to README.PRG T:ÿ +: 1. Introducing README.PRG =:ch1 +: 2. What's it about? =:ch2 +: 3. Menufile format =:ch3 +: 4. Normalized Key Codes =:ch4 +: 5. Foolproofness =:ch5 +: 6. Who did it? =:ch6 +: 7. Tips 'n Tricks =:ch7 / / #:ch1 Y:1 U|1. Introducing README.PRG T:ÿ If you want to be able to write your own menu-driven documentation, README.PRG is *the thing* for you. It was written with the help of the library 'HELP.LIB' (somewhere else on this disk). If you're not a C- programmer this lib might be of no interest to you, but the application you started to read these lines sure is! A short note on how to move around. You may use the mouse to select menu-entries - left-clicking pops in a menu, right-clicking pops out again. You may also use the cursor keys: right-arrow to pop-in, left to pop-out. Furthermore selects a menu-entry (pops in), pos-out and brings you back to the first menu. quits the program altogether. Pressing the right mousebutton in the top menu als quits the program Now press to go to the next page... +:Chapter 2... =:ch2 / / #:ch2 Y:1 U|2. What's it about? T:ÿ The original program was written by Tod Burkey. We liked the idea, but not so much the coding style and the lack of flexibility, so eventually we ended up rewriting the entire program. README.PRG now makes it fairly easy to write your own menu-driven documentation. The program basically does three things: 1 - It tries to read the file COVER.MNU and, when found, displays this file on the screen as a so-called cover-page. 2 - It tries to read the file DEFAULT.MNU. This is a so-called menufile which contains both text (like you're reading now) and additional information, so the program is able to make menus out of this file. 3 - When the menus have been created internally, two things can happen: If step 1 was successful, you are asked to press the -key. If you do so, you'll see the first menu pop-up. If step 1 was not successful, the program will immediately show the first menu, after having completed step 2. The program now will handle all the menu-actions for you. So, summarizing: show COVER.MNU, read and analyze DEFAULT.MNU, make a menu-tree in memory and finally handle all the popup-menu stuff. +:Next page... =:ch21 +:Home... =:main / / #:ch21 Y:1 So in principle the only thing you need to know is how to make a menufile. We'll explain that in chapter 3. There are however still other ways you can use README.PRG. In the foregoing we supposed you just simply started the program by e.g. double clicking on it from the desktop. But it is also possible to supply the program with a commandline. The first argument is taken to be the menufile the program should read. This way you can force the program to load some other menufile, instead of DEFAULT.MNU. If you supply a second argument -which is optional- then this is taken to be the name of the alternate 'cover-page-file' (?) - i.e. the file that will replace COVER.MNU. If no second argument is provided, the program won't draw a cover page and after reading the menufile will immediately show the first menu, without first clearing the screen. This last fact is important if you want to call README.PRG from within another program. How do you pass a commandline to a program? Read on... +:Next page... =:ch22 +:Home... =:main / / #:ch22 Y:1 There are 5 ways to pass a commandline to README.PRG: 1 - Rename the program to README.TTP. When starting it, you'll get a dialog in which you can type a commandline. In this case however the screen *will* be cleared - GEM does this, so don't blame us... 2 - Install the program as an application. in the desktop, select the program icon, move to the 'Options'-menu and select 'Install Application'. Type 'MNU' in the dialog that now appears and press 'Install'. Don't forget to save the desktop ('Save Desktop' in the 'Options'-menu). If you now double-click a MNU-file, the name of that file will be passed as an argument to README.PRG. 3 - If you use an alternate desktop like Gemini: put the README.PRG-icon on the desktop. If you now drag a MNU-file to it and drop it on the icon, README.PRG will be started, loading the MNU-file you dropped. 4 - If you are a programmer and want to call README.PRG from within your own program, just 'Pexec' README.PRG, while providing it with a commandline. This way you can easily incorporate online-help in your programs. You could even maintain different menufiles and Pexec README.PRG with different arguments, depending on where in your program the user is: context-sensitive help! +:Next page... =:ch23 +:Home... =:main / / #:ch23 Y:1 5 - The easiest way: the program SELFREAD.PRG calls the README.PRG program, with a commandline that consists of *its own name*, except that the extension PRG has been replaced by MNU. So make a menufile, e.g. MY_MENU.MNU. Now rename the program SELFREAD.PRG (or a copy of it) to MY_MENU.PRG. If you start this program, it will look for README.PRG and give it the argument 'MY_MENU.MNU' on the commandline. Easy, eh? Note that SELFREAD.PRG expects README.PRG to be in the same folder. The program you started to read these menus, USERS.PRG,is nothing but a copy of SELFREAD.PRG. Well, we've covered everything now: cover-pages, menufiles, commandlines, online-help possibilities. The only thing left is to describe the format of a menufile. For the programmers among you, we've included a small example of how to Pexec README.PRG. We also included some notes on the key-bindings. +:Chapter 3... =:ch3 +:Key bindings... =:ch24 +:Pexec example... =:ch26 +:Home... =:main / / #:ch24 Y:1 The key bindings are as follows: Helpmenu (called 'help') ------------- HELP Move down in the menu list ----------- DOWN ARROW Mouse down Move up in the menu list ------------- UP ARROW Mouse up Select the hilited menu item --------- RIGHT ARROW RETURN ENTER Left mousebutton Go back to previous menu ------------- LEFT ARROW UNDO Right mousebutton Go to the first menu (called 'main') - CLR HOME Quit menu-level ---------------------- ESC Quit program ------------------------- ESC +:More... =:ch25 +:Previous page... =:ch23 / / #:ch25 Y:1 The mouse works as is to be expected. Note that the helpmenu is also shown when a user has made four or more wrong key- strokes. It is therefore a good idea to put the key-bindings info in the helpmenu. Note also that menus wrap top-to-bottom and v.v. When in the top level menu ('main'), the right mouse- button and the key quit the menu-level. If there is no cover-page, this means you quit the program altogether. If there is one, pressing the -key brings you back again to the menus. *always* quits the menu-level, no matter where you are in the menutree. If there is a cover-page, an additional is needed to quit the program. +:Previous page... =:ch24 / / #:ch26 Y:1 This is the complete C-source for SELFREAD.PRG, showing how to Pexec README.PRG, using the commandline to pass the name of an alternate menufile. The program looks for a menufile with the same name as the program. So just rename the program to use it with other menufiles and take care README.PRG is in the same directory. Simple, isn't it? :-) ========================================================================= T:#include T:#include char _PrgName[128]; /* imported by the startup-module that puts the program-name in the array */ main() { char cmdline[128], *p; p=strrchr(_PrgName, '.'); strcpy(p+1, "MNU"); strcpy(cmdline+1, _PrgName); /* Pascal-type string with the */ cmdline[0]=(char)strlen(&cmdline[1]); /*length in the first byte */ return((int)Pexec(0,"README.PRG",cmdline,"")); } +:Previous page... =:ch23 / / #:ch3 Y:1 U|3. Menufile format T:ÿ A menufile is a normal ASCII file and can thus be created and edited with any text editor. It consists of menublocks, each describing a particular menu. A menublock consists of a name, menu-coordinates, text-lines and selectable entries. Menublocks may be in any order. The format is as follows: Each line in a menufile starts with either #, X, Y, T, U, +, &, =, <, 0, 1, 2 or 3. These are the so-called 'opcodes' and they determine the meaning/function of what follows on that line. The opcodes are followed by either : or |, the so-called modifiers. ':' modifies nothing and is there for purely syntactical reasons. '|' causes subsequent text to be centered. Note that opcodes are *not* case-sensitive - so you may either use e.g 'T' or 't'. In the examples we'll use uppercase though (for historical reasons :-). +:Meaning of the opcodes... =:ch31 +:Home... =:main / / #:ch31 Y:1 Each menublock *must* begin with a line T:#: where can be any name you want to give this menu. The first menu (the menu that shows up first when starting the program - this need not be the first menu in the menufile) *must* be called "main" (without quotes). The helpmenu (the one that shows up when you press ) *must* be called "help" (again no quotes). Menunames are not case-sensitive, so "The next menu" is the same as "the NeXT menu" :-). Menunames may contain spaces, etc., so 'this is a %&*^ silly name for a menu' is a legal menuname. Next there are two lines: T:X: T:Y: They specify the location -in characters, not pixels!- of the upper-left corner of the menu. In fact those two need not follow immediately after the '#:name' line - they may be located somewhere in the middle of a menu- block, although that doesn't seem to be very logical... They also may be in any order of course. +:Next page... =:ch31a +:Home... =:main / / #:ch31a Y:1 When using the menus/program on a color monitor, it is possible to override the default color settings by including lines of the form: :rgb in the definition of a menu. The line starts with a number between 0 and 3, so 4 colors can be specified. Color 0 determines the color of selectable text and the menu-border, color 1 determines the color of non-selectable text, color 2 determines the color of the desktop and finally color 3 determines the background color of the menus themselves. After the ':' you must specify *three* numbers - no more or less - between 0 en 7. They determine the red, green and blue components of the color. So e.g a line '0:777' sets the... color for this menu to black. When overriding the default colors be very careful not to render the menus unusable for monochrome-monitor users! Like the X and Y opcodes, the color-opcodes 0, 1, 2 and 3 may be located anywhere in a menu block, although placing them somewhere on top is probably the most logical... +:Next page... =:ch32 +:Home... =:main / / #:ch32 Y:1 The rest of the menublock consists of (non-selectable) text and (selectable) entries. Lines of text are of one of the forms: T:T: T:U: Lines starting with 'T' are displayed the way you have written them. Lines starting with 'U' are automagically converted to uppercase (nice for menu titles). Selectable entries consist of two lines: T:+: T:=: or T:&: T:=: +:Next page... =:ch32a +:Home... =:main / / #:ch32a Y:1 The first line contains the text of the entry (e.g. '+:Back to the table of contents'), while the second contains the name of the menu to jump to when this entry is selected (eg '=:main'). Using '+' in the first line displays the text exactly as you have written it. Using '&' converts the entry-text to uppercase. The last opcode reads text from a file and shows it in a menu: T:<: This kind of entry should always have a separate menu! So it should be of used like this: T:#:filemenu T:X:1 T:Y:1 T:<:somefile.txt +:Next page... =:ch33 +:Home... =:main / / #:ch33 Y:1 A small example of a possible menufile: T:#:main T:X:1 T:Y:1 T:T:This is the main menu T:+:Goto menu 2 T:=:menu 2 T:+:Display a file T:=:menu 3 T:#:menu 2 T:X:1 T:Y:1 T:U:The second menu contains only uppercase text... T:#:menu 3 T:X:1 T:Y:1 T:<:somefile.txt +:Next page... =:ch34 +:Home... =:main / / #:ch34 Y:1 As we already said, it is possible to replace the ':' by a '|' in order to have text be centered automatically. Of course this only works with textual entries: T, U, +, &. If this was al there was to know, it would be a rather tedious job to make a menufile - and it would be rather hard to read or edit one. But we've implemented various features to make life a bit easier: 1 - Lines starting with "/" (slash - without quotes) are regarded as comments and skipped when parsing the menufile. Use these to e.g. separate the various menublocks. 2 - Lines not starting with ":" or "|" are considered to be of type "T:". So the text of the menu you're currently reading was typed just as you see it now - no opcodes or other syntactical fuzz. 3 - Coordinates may be omitted. Whenever a coordinate is omitted, the menu will be centered in the corresponding direction. 4 - Lines starting with an overstrike ('ÿ') are completely filled with overstrikes, thus underlining the line above. Use this to have your menu-titles automatically underlined. Everything after the overstrike will be ignored. +:Next page... =:ch35 +:Home... =:main / / #:ch35 Y:1 So a 'stripped bare' version of a menu file could be something like: T:#:main T:The first line of the main menu T:Note that this menu is centered, since the coordinates fail. T:+:The first entry T:=:menu 2 T:+:And the second entry T:=:menu 3 T:/ and a line with some comment T:#:menu 2 T:Just another one-liner menu - and centered also T:/ T:#:menu 3 T:Y:1 T:This one is only centered in the X-direction T:Let's make another entry: T:+:To two T:=:menu 2 T:/ and just some more comment +:Chapter 4... =:ch4 +:Home... =:main / / #:ch4 Y:1 U|4. Normalized Key Codes T:ÿ The program uses the so-called Normalized Key Code Converter (Release 2.71 Copyright (c) 1989-1991 Harald Siegmund). This makes it independant of the specific keyboard you use - your HELP-key will always be interpreted as a HELP-key, even if it happens to send a code which *my* keyboard sends when pressing the CTRL-ALT-RSHIFT-DEL key :-) +:Chapter 5... =:ch5 +:Home... =:main / / #:ch5 Y:1 U|5. Foolproofness T:ÿ We tried to make the program as foolproof as possible. It is always possible to mess up things by supplying nonsensical menufiles, but *that* is your responsibility. Anyhow: - No coordinates are specified for a given menu: the menu is automagically centered when drawn. - An illegal coordinate (<1 or >screenwidth) is specified: This also causes the menu to be centered in that direction. So when e.g. you've specified an X of 1 and a Y of -1, the menu will be centered in the Y direction. Specifying only an X of 10 and not specifying a Y at all has the same effect. +:Next page... =:ch51 +:Home... =:main / / #:ch51 Y:1 - Lines that are too long to fit the current screen: If the line is too long, given the specified X-coordinate, the program wil try to adjust (=decrement) this coordinate, to show as much of the string as possible. If the string is longer than the current screenwidth, the line is truncated. - Menus that are too high to fit the current screen: the menu is automatically truncated, so only the first XX lines are shown, where XX is the screenheight (in lines) - 2. - Right margin: a menu is always drawn one character wider than the longest menu-entry. This gives a one-char right margin. - Empty menu: if a menu is empty (i.e. only a '#:' line is specified in the menufile), it won't show up when you select it. - If a menu is missing, you'll be notified about that as soon as you try to select this menu. - If an entry in a menu tries to jump to *the same* menu, no action is performed. - If an entry points to a file ('<:') and the file can't be found, you'll be notified about this. +:Let's do some error testing... =:ch52 +:Home... / / #:ch52 Y:1 U|Some error testing T:ÿ +:Look at non-existant file =:1 +:Menu Doesn't exist =:I don't exist +:Goto myself (loop) =:ch52 This line is far too long to fit on the screen, so let's see what will happen if we try to print it. +:F!#%ed up menu =:2 +:An empty menu =:3 +:Menu that is too big... =:4 +:Chapter 6... =:ch6 +:Back to the contents... =:main / #:1 <:ytrewq.txt / / #:2 X:789 Y:4 The X-coordinate of this menu is 789... The Y-coordinate is 4 / / #:3 / / #:4 T:This menu is far too big to fit on a normal monochrome screen and thus should be T:truncated T:so T:it T:is T:made T:to T:fit T:in T:a T:normal T:menu T:box. T:Works T:well, T:doesn't T:it? T:Well, T:this T:should T:be T:enough, T:don't T:you T:think? / / #:ch6 Y:1 U|6. Who did it? T:ÿ T| Original concept, design & first-versions-programming: T| Todd Burkey (trb@stag.UUCP) (C)opyright 1988 T| T| Ported to Pure-C, LINEA-replacement, wrapping menus, first T| cosmetic changes and first improved error-checking: T| Hendrik Jan Veenstra, May-01-1992 T| T| All the rest... (which is quite a lot %->): T| Jeroen Scheerder Hendrik Jan Veenstra T| (Jeroen.Scheerder@let.ruu.nl) (HendrikJan.Veenstra@phil.ruu.nl) T| May - September '92/March '93, Utrecht, the Netherlands T| +:More about us and copyrights... =:ch61 +:A short history... =:ch62 +:Home... =:main / / #:ch61 Y:1 U|More about us and copyrights T:ÿ The programs, lib and source are Public Domain. Feel free to use it, modify it and improve it. If you make any improvements, it would be nice to send us (all 3 authors) a copy of your source-code, and a small note on what was actualy improved. If you use the programs, lib or source, modified or not, you should at least mention the authors and give them some credits... You could for example make a menu-entry 'Who did it' <...> None of the authors is responsible for any damage, real or imagined, done to you, your family or your system, due to using or not using these programs, lib or the accompanying source-code, modified or not. As far as we know, the program is bug-free. We can be reached at: Jeroen Scheerder Internet: Jeroen.Scheerder@let.ruu.nl Hendrik Jan Veenstra: Internet: HendrikJan.Veenstra@phil.ruu.nl STer BBS: 01880-40035 (Holland), User-ID 'HJV' T|* Murphy's law: bug-free programs tend to crash. * +:A short history... =:ch62 +:Chapter 7... =:ch7 / / #:ch62 Y:1 U|A short history T:ÿ It all started when we found the original program (Todd Burkey's) on the net. We liked the concept, but not so much the coding style :). So the following happened... May-01-92: HJV - Ported to Turbo-C, LINEA-replacement, wrapping menus, first cosmetic changes and first improved error-checking. May-02: JS&HJV - lots of other improvements. The program now runs as a full fledged stand-alone application. Program renamed to README (instead of the original POPHELP.PRG). May-03-5: HJV - commandline support and extensive debugging (VDI, cosmetics and resolution independance). May-04/5: JS - Library concept and design. Got the first on-line help system running! More debugging... VDI & IKBD troubles. May-05: The programs (both our versions) can now safely be Pexec'ed without f***ing up the VDI settings anymore. May-06: HJV - The renamable SELFREAD.PRG... May-11: Integration of both our versions and improvements into a library + 'stand-alone-shell'. Together this replaces the original May-2 README.PRG-version. Added full mouse support...! +:More history... =:ch63 / / #:ch63 y:1 May-17: JS - removed unnecessary recursion. Added 'short circuit' feature: jumping forward to a previously visited menu jumps back, instead of adding it at the end of the 'visited menus'-list. May-18: JS&HJV - ...debugging (of course). Sept-24: HJV - After a long holiday :-) removed the last (?) bugs, cleaned up the ugliest parts of the code (=rewriting big chunks) and started writing the documentation you're now reading. Sept-25-7: HJV - More rewriting. All the ugly arrays are replaced by decent structs. Introduced some new bugs and fixed them. Sept-28: HJV - The lib now uses malloc/realloc in order to consume as little memory as possible. Menu-syntax (i.e. opcodes) is no longer case-sensitive. Removed some redundant code. Finally got the lib < 10k! Is it ready for release now...? Sept-29: HJV - Very nasty bug with long menunames fixed. More static allocation replaced by dynamic allocation, so the thing uses even less memory... Sept-30: HJV - removed the weirdest bug I've ever seen... October: HJV - last fixes... Unfortunately the lib again is > 10k...(sigh) March '93: JS&HJV - the absolute final fix... %-> Never mind. +:Chapter 7... =:ch7 +:Home... =:main / / #:ch7 Y:1 U|Tips 'n tricks T:ÿ - Always think twice about the menu-structure before beginning to write the actual menufile. It is very important for the user/reader that your menus have a logical structure and are easy to navigate. It's very easy to make a menufile in which the reader will immediately get lost, having no other solution than popping all the way back, or pressing . - If there is a 'next page' entry in a menu, take care it's the *first* entry in the menu. When popping in a menu, the program always selects the first selectable entry, so by putting the 'next page' on top, one only needs to press to move through the document. - Menu-structures that are too shallow don't use the full advantage of menu-driven systems. It's no good -and very confusing- to have e.g. 20 selectable entries in one menu. - Menu-structures that are to deep also don't use the full power of menu- driven systems. Having only one selectable entry on each page driving you deeper and deeper in the menutree is a very bad practice. +:More... =:ch72 +:Home... =:main / / #:ch72 Y:1 - Menus should contain a reasonable amount of information. One full page of text is reasonable. A full page of selectable entries isn't. Also a menu consisting of only two selectable entries (and no text) is bad practice. - Care about the layout of your menus. It's very annoying when menus pop up and down on random locations. You could e.g. have all your menus centered, or have them all located at the same Y-position, while centering in the X-direction (by omitting the X-coordinate). We used this last method when writing the menufile you're currently reading. - Give the user some feedback on where in the menutree s/he is. Do this by using menutitles, which e.g. repeat the menu-entry the user choose to enter this menu. E.g.: T:... T:+: 7. Tips 'n Tricks T:=:chapter7 T:... T:#:chapter7 T:U| 7. Tips 'n tricks T:T:ÿ ... +:More... =:ch73 +:Home... =:main / / #:ch73 Y:1 - Don't forget a textual entry (selectable or not) can be capitalized (U, &), centered (|) and underlined (T:ÿ) automatically. Use these features! (see the example on the previous page) - Be nice to yourself: give menus logical names. While writing a menufile, e.g. 'chapter 7' is a lot easier to understand and remember than 'menu 25'. - Probably it's easiest to first write a normal document, without thinking about menus too much. After it's finished, you can divide it in chunks and put the chunks in menus. - And so on... Well, what more can we say? Now it's up to you! We think we gave you a nice piece of software, absolutely free, and now you're the one that should prove all our long and sleepless nights have had there use. In case you're a C-programmer, don't forget to read the additional docs for programmers... T|Enjoy it! T|Jeroen & Hendrik Jan +:Home... =:main