Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!utcsri!utegc!utai!garfield!john13 From: john13@garfield.UUCP Newsgroups: comp.sys.amiga Subject: Re: ADD (new) and UNTIL Message-ID: <3615@garfield.UUCP> Date: Sun, 26-Apr-87 14:38:41 EDT Article-I.D.: garfield.3615 Posted: Sun Apr 26 14:38:41 1987 Date-Received: Mon, 27-Apr-87 02:39:48 EDT References: <3297@jade.BERKELEY.EDU> Organization: CS Dept., Memorial U. of Newfoundland, St. John's Lines: 393 Summary: new source + repost of docs In article <3297@jade.BERKELEY.EDU>, spencer@eris.BERKELEY.EDU (Randy Spencer) writes: > I am sorry, did I miss the source for these? Where can I look for more > information about how they work. I didn't get it all from the poster. > > (If you didn't get it, this is another plea from Randy not to start > posting UUencoded stuff to a net that is hacker oriented, without > the source code.) > Sorry if you missed ADD the first time around; you are the second person to ask about this, although I know the original posting got to ".Berkeley.edu". I was kind of leery about posting the only-slightly-modified source to add again, and if you have the source to add, then the source to until becomes kind of redundant. And add.doc - I just got to editing it and it seems to have grown into 100+ lines! Geez, a long posting by itself. To tell you the truth, I was more worried about responses saying "my grandmother had the same idea the second day I had my Amiga home...and she hand-coded it in assembler to make it more challenging!" :-) There are a million different things you can do using the same basic loop (for all screens, for all windows in each screen {..........} ). Someday I hope to have done all of them; but I gotta warn ya, ya seen one of these sources, ya seen them all! Exception #1: Expose, which had a major bug as posted, and major limitations also. These are fixed and I will post today or tomorrow source and executable. Exception #2: Menutext (it has a shorter name on my disk) & Restore, whose method of execution may not be immediately obvious from add.c, until.c, and expose.c. But I want to include a lot of extra features...aw, what the heck, they work as is so I will post them too and see what kind of feedback I get. The rest of this posting is ADD.C, ADD.DOC, and UNTIL.C. ADD.C (final): /* * ADD (add keyboard shortcuts to menus) * * Copyright ((c)) 1987, John Russell * This program is freely redistributable. Nobody may impose extra * limitations on its distribution. * * Please distribute at least documentation with the executable. The * source is straightforward, but could be informative for those who get * blurred vision from reading those structure definitions in intuition.h. * * This program is shareware, and if you feel that it is useful to you * (I *know* it is to me :-) a small contribution would be appreciated * (see documentation). */ /* Manx users compile with "+l" just in case */ #include #include /* include all the standard stuff for _intuition_ */ struct IntuitionBase *IntuitionBase; main(argc,argv) int argc; char *argv[]; { struct Screen *screen; struct Window *window; struct MenuItem *item; struct Menu *menu,*main_menu; char answer,*gets(); int x,cut; cut = argc-1; /* *argv[cut] == key to assign */ if ((IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",0L))==NULL) { puts("Where is Intuition gone???\n"); exit(0); } Forbid(); /* the following line was outside the Forbid-Permit loop in the posted executable, but should be inside */ screen = IntuitionBase->FirstScreen; /* address of Workbench screen structure */ while (screen != NULL) { /* do all screens */ window = screen->FirstWindow; while (window != NULL) { /* do all windows */ if (compare(argv[1],window->Title)==0) { /* search for name */ x=atoi(argv[2]); /* menu # */ menu = window->MenuStrip; main_menu = menu; /* main menu of window for SetMenuStrip */ while (--x > 0) { /* scan menu list */ if ((menu = menu->NextMenu) == NULL) goto quit; } x = atoi(argv[3]); /* item # */ item = menu->FirstItem; submenu: while (--x > 0) { /* scan item list */ if ((item = item->NextItem) == NULL) goto quit; } if (argc==6) { /* descend into sub-menu? */ argc=0; item=item->SubItem; x=atoi(argv[4]); /* sub-item # */ goto submenu; } ClearMenuStrip(window); /* disable menu structure */ if (!compare(argv[cut],"-kill")) { item->Flags &= -(COMMSEQ+1); /* turn off bit */ puts("Deleted shortcut."); } else { item->Flags |= COMMSEQ; /* add shortcut flag */ item->Command = *argv[cut]; /* which key */ puts("Added shortcut."); /* took out stray newline */ } SetMenuStrip(window,main_menu); /* give it back */ } window = window->NextWindow; } screen = screen->NextScreen; } quit: Permit(); CloseLibrary(IntuitionBase); } compare(string1,string2) /* if spaces in windowname, only check first word */ char *string1,*string2; { while ((*string1 != '\0') && (*string1 != ' ')) { if (*string1 != *string2) /* space and null both end conditions */ return(1); string1++; string2++; } return(0); /* return weird values like strcmp() */ } ---------------------------------- ADD.DOC: ADD - create keyboard shortcuts where no keyboard shortcuts have gone before. Copyright ((c)) 1987, John Russell This is a small Intuition hack, which I'm surprised not to have seen anywhere before. It lets you take other people's menus, and customize them (at least with regards to keyboard equivalents, ie right-Amiga + combinations). The idea was brought into my consciousness when I saw how MWB let you circumvent the assumptions made by other programmers in a transparent way, although it had probably been fermenting back there for a while :-). Syntax: add [ ] Windowname is the name of the window (no matter what screen it is on) to which the menu you want to alter is attached. I ran into hassles with long window titles and those with spaces, so you only need specify the first word (eg VT100 instead of VT100 (2.4 861214... etc). Note that names *are* case sensitive. All numbers are from 1 upwards, so "add window 1 1 X" is the upper-left-hand position in the menu list. If you have 5 parameters it assumes the 4th is the position of a sub-item, not the shortcut itself. Otherwise, the 2nd and 3rd supply the position info and the 4th is the key to use. The shortcut can be specified as upper or lower case; they are treated the same. Note that there is nothing to prevent you from creating duplicate shortcuts. Since I didn't want to get over-fancy, the size of the menu hitbox is unaltered and this may cause some (non-harmful) overlapping. The "-kill" option is position-dependent (it must go last) and just turns off an existing shortcut. -------------- Sample uses - Install this file as s:loadwb (instead of "loadwb", "execute loadwb") loadwb until Workbench 60 -m ; wait until window opens and sets menu (also posted) addbuffers df0: 15 add Workbench 1 1 O add Workbench 1 2 C add Workbench 1 3 D add Workbench 1 4 R add Workbench 1 5 I add Workbench 1 6 K ;for kill add Workbench 2 1 E add Workbench 2 2 F ;for format add Workbench 3 4 S add Workbench 3 5 V If you use VT100 and don't have a compiler, you might want to install s:vt100 ("run vt100", then "execute vt100") until VT100 60 -m ;wait 'til VT100 opens window, sets menu strip addbuffers df0: 15 ;if none added before add VT100 1 1 C add VT100 1 2 A add VT100 2 1 1 L ;I only use 3/1200 baud add VT100 2 1 2 H add VT100 2 1 3 -kill ;because this one was originally "H" -------------- Bugs/problems: Using 0 or negative numbers for menu positions is *not* recommended. Before I added the checks for end-of-menu, I would experience strange screen displays trying to access menu # 1000, etc. even though it was just de-referencing the pointers. Anyone know why? Programs with a space as the first character in the window title (eg PageSetter) need to be filezapped (change the space to, say, a _). Programs that re-use parts of the menu structure (eg Ahost); well, it doesn't hurt, but you can only specify 1 shortcut which shows up several times. Programs that disable menu operations at various times (eg DPaint and Workbench) need to be taken case-by-case. I was disappointed about DPaint, although menu operations *are* allowed once the mouse is above the drawing area. For Workbench, just allow disk activity to cease before using add. This was originally interactive, and I just hacked it into "expert" mode at someone's request. If I ever get more than 10 minutes at a time with it, I'll combine the two, and hopefully get to use some of the neato features like ItemAddress and the MenuNumber macro. Be warned, I fully intend to steal menus away from programs and let you select them in *mine*! I can't accept responsibility for any damages that may occur as a result of using this program (although I highly doubt any will happen). -------------- This program is made available as shareware. Anyone may give it to anyone, but not impose any conditions in doing so. If you feel that any and/or all programs you have from me have been worth $5 or so to you, you might want to send a small donation to: John Russell 5 Alderdice Place St. John's, NF, Canada A1B 2P8 (709) 726-7847 If I get favourable response, I may expand the idea into a general screen/ window/menu management program, allowing you to customize the Intuition-based features of other people's programs. Hmmm, I wonder what kind of copyright conundrums *that* might create? "But officer, the spreadsheet I wrote has *none* of these filthy messages in it..." ------------------------------ UNTIL.C: /* * This is a short program which will wait until a particular window * is opened, or until a certain amount of time has passed. * * Specify -m at the end to wait until the window has finished setting * its menu structure. * * Usage : until [ <-m> ] * * NB: Window name is case sensitive; for multi-word names, only the first * is checked, so if name is "My Window" use "My" when invoking "until". */ /* * Use of this program? Anytime you run one application that opens windows, * and then want to start another, but not until the first has opened its * window (and optionally constructed a menulist). Could also be used to * reduce disk grinding (hey, this is a neat idea I just thought of!): * * run Scribble! ;fine and dandy * until Scribble! 20 ;wait till loaded, or 20 secs if load fails * run Pagesetter ;I'll imagine I have lots of ram * * This works well as a companion to ADD, so you can construct script files * that run a program like Scribble or Pagesetter, wait until they have * finished loading, and then do an addbuffers and add some keyboard * shortcuts: * * run df1:vt100 ;start it up * until VT100 20 -m ;wait until it loads, gets ser: device, and * ;constructs menu * addbuffers df0: 20 * add VT100 1 1 C ;create keyboard shortcuts * etc. * * Copyright ((c)) 1987, John Russell. Unlimited distribution. */ #include struct IntuitionBase *IntuitionBase; /* actually has a use! */ struct Window *findwindow(); main(argc, argv) int argc; char *argv[]; { struct Window *open; int seconds,x; if (!(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L))) { puts("No intuition library.\n"); exit(0); } if ((argc < 3) || (argc > 4)) { /* instructions */ puts("Usage: until [ <-m> ]\n"); CloseLibrary(IntuitionBase); exit(0); } seconds = atoi(argv[2]); for (x=0; x<2*seconds; x++) { /* check every 1/2 second */ if (open = findwindow(argv[1])) { /* if window open yet */ /* now is menu bar set (or doesn't user care)? */ if (open->MenuStrip || (argc==3) || compare(argv[3],"-m")) { goto end; } } Delay(25); /* half a second or so */ } puts("Timeout - window did not open."); end: CloseLibrary(IntuitionBase); } struct Window *findwindow(title) char *title; { struct Screen *Screen; struct Window *Window; Forbid(); /* just to be safe, disable interrupts */ /* now loop through all screens/windows */ for (Screen=IntuitionBase->FirstScreen; Screen; Screen=Screen->NextScreen) { for (Window=Screen->FirstWindow; Window; Window=Window->NextWindow) { /* if found, return window pointer so we can check menu status */ if (!compare(Window->Title,title)) { Permit(); /* what happens if I don't do this, hm? */ return(Window); } } } Permit(); return(0L); } compare(string1,string2) /* compare strings that end with nulls or spaces */ char *string1,*string2; { while ((*string1 != '\0') && (*string1 != ' ')) { if (*string1 != *string2) return(1); string1++; string2++; } return(0); /* return reverse of intuitive value, as strcmp does */ } ------------------------------- John