% CWEB source for FrontPubScreen % 12 Apr 1992 john fieber (jfieber@sophia.smith.edu)
\nocon % omit table of contents \datethis % print date on listing \def\progname{\.{FrontPubScreen
\N1. FrontPubScreen. This program is for AmigaDOS 2.0 or later. It does one simple and useful thing when you are working with public screens: if the frontmost screen is a public screen, it returns the name of that screen. Since the the front screen is generally the one you are working on, it effectively returns the name of the screen you are working on.
A good example of how this can be used is with a “hotkey” program for opening pop-up utilities, command shells, editors or whatever. To illustrate, in this CLI command: $$\hbox{\tt NewCLI CON:20/50/540/180/AmigaShell/AUTO/SCREEN‘\progname‘$$ \.{‘\progname‘ will be replaced by the output of \progname. Since \progname\ displays the name of the front screen, the result the above command is a CLI window opening up on whatever screen you happen to be working on. This command attached to a hot-key provides an instant CLI on whatever screen you happen to be working on. Other programs that allow you to specify a screen to open on can use the same technique. For TurboText users, try: $$\hbox{\tt ttx screen ‘progname‘$$ attached to a hotkey.
Unfortunately this nifty feature only works if the front screen is indeed a public screen. Fortunately there are a growing number of programs that do open public screens. Also, you can create your own using one of the various public screen managers roaming around the “net”.
\fi
\M2. {\bf Copying. Feel free to copy and distribute this program but please don’t distribute the executable without this source code. Also, feel free to make changes but please make and document the changes in a cweb change file, not the original. Also, I encourage people who are writing little pop-up type applications to stick this little bit of code in. Public screens are nifty things so use them and make them useful!
If you do make a change file, use the code in your own program, or otherwise find this program useful I would like to hear about it. Send email to John Fieber at \.{jfieber@sophia.smith.edu.
\fi
\M3. Okay, enough description, now on to the program, starting with a little thing to teach \.{cweave about one of the special Amiga types\dots
\Y\P\F\.{ULONG \5 \\{int\par \fi
\M4. All good AmigaDOS programs should have string such as the following embedded somewhere in the program. The CLI command \.{Version will look for this string and display it if found. This approach is much easier than writing in code to provide a command line switch and to display the version and much more consistant from the user’s point of view.
\Y\P\&{char \\{version${[\,]\K\.{"\\0\$VER:\ FrontPubScr\)\.{een\ 1.0\ (4.12.92)"{$;\par \fi
\M5. Here is the general layout of the program. We first check the value of \\{argc to determine if the program was run from a command shell or from the Workbench. If $\\{argc\S\O{0$ then \progname\ was started from the Workbench. Since it has no useful function in that context, we just exit. If $\\{argc\G\O{1$ then we move on and try the name of a useful public screen.
\Y\P\X6:Include files\X\6 \X7:Function prototypes\X\6 \X8:Global variables\X\6 $\\{main(\\{argc,\39\\{argv){$\1\1\6 \&{int \\{argc;\6 \&{char ${{*\\{argv[\,];\2\2{$\6 ${\{{$\1\6 \&{if (\\{argc)\5 ${\{{$\1\6 \X9:Open system libraries\X;\6 \X13:Get screen name\X;\6 \X11:Output screen name\X;\6 \X10:Close system libraries\X\6 \4${\{$\2\6 \4${\{$\2\par \fi
\M6. We don’t really need to include the extra baggage of \.{stdio.h either during compilation or linking since AmigaDOS provides for writing things out to the console. But we {\it do\/ need to include the headers to get at those system functions.
\Y\P\4\X6:Include files\X${\S{$\6 \8\#\&{include \.{<exec/types.h>\6 \8\#\&{include \.{<intuition/intuition\)\.{.h>\6 \8\#\&{include \.{<intuition/intuition\)\.{base.h>\6 \8\#\&{include \.{<dos/dos.h>\par \U5.\fi
\M7. We also want to include the the Commodore function prototypes to be ANSI compliant and the \#{\bf pragma’s to bypass the library access functions in \.{amiga.lib that make the code unnecessairly large and slow.
\Y\P\4\X7:Function prototypes\X${\S{$\6 \8\#\&{include \.{<proto/intuition.h>\6 \8\#\&{include \.{<proto/dos.h>\6 \8\#\&{include \.{<proto/exec.h>\par \U5.\fi
\M8. The variable \\{IntuitionBase is a pointer to base address of the Intuition Library. The value returned by the $\\{OpenLibrary(\,)$ call will be placed here. Also needed is a place to store the name of the public screen that the program will return. The value for \.{MAXPUBSCREENNAME is defined in \.{screens.h (which is included with \.{intuition.h). Finally, we have a pointer to a screen structure.
\Y\P\4\X8:Global variables\X${\S{$\6 \&{struct \\{IntuitionBase ${{*\\{IntuitionBase;{$\6 \&{char \\{public\_screen\_name[\.{MAXPUBSCREENNAME];\6 \&{struct \\{Screen ${{*\\{public\_screen\_address{$;\par \A12. \U5.\fi
\M9. Now we must open the Intuition library so we can get at the nifty system functions for twiddling with screens. If the call to $\\{OpenLibrary(\,)$ fails, it will return $\NULL$. We must exit gracefully in the event that this occurs.
Notice that since Intuition has its own non-standard library structure we must typecast the $\\{OpenLibrary(\,)$ function which by definition returns a pointer to a standard library structure.
\Y\P\4\X9:Open system libraries\X${\S{$\6 ${\\{IntuitionBase\K{$(\&{struct \\{IntuitionBase ${{*){$ % \\{OpenLibrary${(\.{"intuition.library",\39\O{36\$);{$\6 \&{if ${(\R\\{IntuitionBase){$\5 ${\{{$\1\6 \\{exit(\O{20\$);\6 \4${\{$\2\par \U5.\fi
\M10. To clean up at the end of the program, the Intuition library must be closed. Again since Intuition has a non-standard library structure we need to typecast it so that the use of $\\{CloseLibrary(\,)$ matches its definition.
\Y\P\4\X10:Close system libraries\X${\S{$\6 \\{CloseLibrary((\&{struct \\{Library ${{*){$ \\{IntuitionBase);\par \U5.\fi
\M11. Moving right along, here is the code that prints out the (hopefully) useful information regarding a public screen name. The variable \\{public\_screen\_name is assumed to contain the screen name of the front public screen, or the default public screen. Just to check its validity, we try to lock the screen. In the event that fails we just return \.{Workbench which should always work in some way shape or form.
\Y\P\4\X11:Output screen name\X${\S{$\6 ${\\{public\_screen\_address\K\\{LockPubScreen(\\{public\_screen\_name);{$% \6 \&{if (\\{public\_screen\_address)\5 ${\{{$\1\6 (\&{void) \\{PutStr(\\{public\_screen\_name);\6 (\&{void) \\{PutStr(\.{"\\n");\6 ${\\{UnlockPubScreen(\NULL,\39\\{public\_screen\_address);{$\6 \4${\{$\2\6 \&{else ${\{{$\1\6 (\&{void) \\{PutStr(\.{"Workbench\\n");\6 \4${\{$\2\par \U5.\fi
\M12. Now we must figure out some useful information for the previous section to display. A couple more variables must be defined to aid in the search for the name of the front public screen.
\Y\P\4\X8:Global variables\X${\mathrel+\S{$\6 \&{ULONG \\{intuition\_lock;\6 \&{struct \\{Screen ${{*\\{front\_screen\_address;{$\6 \&{struct \\{List ${{*\\{public\_screen\_list;{$\6 \&{struct \\{PubScreenNode ${{*\\{public\_screen\_node{$;\par \fi
\M13. The address of the front screen is easily found in the \\{IntuitionBase structure. However, since this is a system structure that we are not normally at liberty to examine, we must first get permission from Intuition to examine it. This is accomplished with the $\\{LockIBase(\,)$ function which sets up a semaphore. This is much friendlier than simply locking the whole system with $\\{forbid(\,)$ and $\\{permit(\,)$ while we look at the structure.
With the address of the frontmost screen in hand, we check to see if it is a public or Workbench screen. If so, we search the public screen list for a match. The variable \\{public\_screen\_name is set to a $\NULL$ string at the start and then checked at the end. If it is still $\NULL$, then the front screen was not found in the public screen list so we ask the system for the name of the default public screen.
\Y\P\4\X13:Get screen name\X${\S{$\6 ${\\{public\_screen\_name[\O{0]\K\.{’\\0’;{$\6 ${\\{intuition\_lock\K\\{LockIBase(\O{0\$);{$\6 ${\\{front\_screen\_address\K\\{IntuitionBase\MG\\{FirstScreen;{$\6 \&{if ${((\\{front\_screen\_address\MG\\{Flags\AND\.{PUBLICSCREEN)\V(% \\{front\_screen\_address\MG\\{Flags\AND\.{WBENCHSCREEN)){$\5 ${\{{$\1\6 \\{UnlockIBase(\\{intuition\_lock);\6 \X14:Search public screen list\X;\6 \4${\{$\2\6 \&{else ${\{{$\1\6 \\{UnlockIBase(\\{intuition\_lock);\6 \4${\{$\2\6 \&{if ${(\\{public\_screen\_name[\O{0]\S\.{’\\0’){$\5 ${\{{$\1\6 \\{GetDefaultPubScreen(\\{public\_screen\_name);\6 \4${\{$\2\par \U5.\fi
\M14. Here we lock the public screen list and examine it looking for a match to \\{front\_screen\_address. If one is found, we then copy the name of the screen into \\{public\_screen\_name for later use. Note that the AutoDocs mention that the screen pointer in the \\{PubScreenNode structure is not trustworthy. However, in this case nothing catastrophic will happen though if it is wrong—the program won’t work right but it should not affect anything else.
\Y\P\4\X14:Search public screen list\X${\S{$\6 ${\\{public\_screen\_list\K\\{LockPubScreenList(\,);{$\6 ${\\{public\_screen\_node\K{$(\&{struct \\{PubScreenNode ${{*){$ % \\{public\_screen\_list${\MG\\{lh\_Head;{$\6 \&{while (\\{public\_screen\_node)\5 ${\{{$\1\6 \&{if ${(\\{public\_screen\_node\MG\\{psn\_Screen\S\\{front\_screen% \_address){$\5 ${\{{$\1\6 ${\\{strcpy(\\{public\_screen\_name,\39\\{public\_screen\_node\MG\\{psn% \_Node.\\{ln\_Name);{$\6 \&{break;\6 \4${\{$\2\6 ${\\{public\_screen\_node\K{$(\&{struct \\{PubScreenNode ${{*){$ % \\{public\_screen\_node${\MG\\{psn\_Node.\\{ln\_Succ;{$\6 \4${\{$\2\6 ${\\{UnlockPubScreenList(\,){$;\par \U13.\fi
\M15. And thus we are finished!
\fi
\M16. {\bf Other notes. There are still a few problems that hopefully won’t be too problematic. Basically, although a public screen may be available when \progname\ runs, there is no guarantee that it will still be around later when that screen is used by whatever called \progname. In order to ensure this we would have to maintain a lock on the screen until the caller has locked the screen, either with $\\{LockPubScreen(\,)$ or by having a window open on it.
To do this properly would require communication between the applications so you might as well just build the \progname\ right in and not bother with this silly utility. Alternately \progname\ could start another process to hold the lock for a while and possibly monitor the visitor count on the screen. This might help but the payoff would probably be much smaller than the effort involved to implement it.
Also, if the comments and explainations of this program seem a bit excessive it is because I’m just learning how to use this nifty invention of D.~Knuth called \.{CWEB. \medskip\rightline{–john fieber
\fi
\N17. Index. \fi
\inx \:\\{argc, \[5]. \:\\{argv, \[5]. \:\\{CloseLibrary, 10. \:\\{exit, 9. \:\\{FirstScreen, 13. \:\\{Flags, 13. \:\\{forbid, 13. \:\\{front\_screen\_address, \[12], 13, 14. \:\\{GetDefaultPubScreen, 13. \:\&{int, 3. \:\\{intuition\_lock, \[12], 13. \:\\{IntuitionBase, \[8], 9, 10, 13. \:\\{lh\_Head, 14. \:\\{Library, 10. \:\\{List, 12. \:\\{ln\_Name, 14. \:\\{ln\_Succ, 14. \:\\{LockIBase, 13. \:\\{LockPubScreen, 11, 16. \:\\{LockPubScreenList, 14. \:\\{main, \[5]. \:\.{MAXPUBSCREENNAME, \[8]. \:\\{OpenLibrary, 8, 9. \:\\{permit, 13. \:\\{psn\_Node, 14. \:\\{psn\_Screen, 14. \:\\{public\_screen\_address, \[8], 11. \:\\{public\_screen\_list, \[12], 14. \:\\{public\_screen\_name, \[8], 11, 13, 14. \:\\{public\_screen\_node, \[12], 14. \:\.{PUBLICSCREEN, 13. \:\\{PubScreenNode, 12, 14. \:\\{PutStr, 11. \:\\{Screen, 8, 12. \:\\{strcpy, 14. \:\&{ULONG, \[3]. \:\\{UnlockIBase, 13. \:\\{UnlockPubScreen, 11. \:\\{UnlockPubScreenList, 14. \:\\{version, \[4]. \:\.{WBENCHSCREEN, 13. \fin \:\X10:Close system libraries\X \U5. \:\X7:Function prototypes\X \U5. \:\X13:Get screen name\X \U5. \:\X8, 12:Global variables\X \U5. \:\X6:Include files\X \U5. \:\X9:Open system libraries\X \U5. \:\X11:Output screen name\X \U5. \:\X14:Search public screen list\X \U13. \con
This document was generated on November 8, 2024 using texi2html 5.0.