OVERVIEW: wIconSetter is a companion utilitiy to wIconify. It allows you to specify the icon imagery and attributes for any window that uses the default wIconify window icon, and sny screen that uses the default screen icon. You can specify windows by the program that opens them, the screen they are on and the title of the window, so very flexible identification is possible. You can specify the icon's imagery, its name, its initial position, and its attributes, and can even indicate that a window should be iconified as soon as it is openned. USING WICONSETTER: You should place the wIconSetter command in the C: directory (or somewhere in the command path), and the wIconSetter-Handler file in the L: directory. wIconSetter reads an initialization file in order to find out what icons you want to use. If you do not specify a file on the command line, wIconSetter will look for WICONIFY:WICONSETTER.INIT, and if that can not be found, it will look for S:WICONSETTER.INIT. To start wIconSetter, use the command 1> WICONSETTER [initfile] where [initfile] is the name of the initialization file to use. wIconify must be running in order for wIconSetter to work (it will exit with an error message if it is not), and the initialization file must include at least one icon specification. If you want wIconSetter to run automatically when you boot your Amiga, you must add the WICONSETTER command to your startup-sequence (found in the S: directory), usually right after the WICONIFY command. To stop wIconSetter, simply issue a WICONSETTER command while wIconSetter is running. This will remove the handler from memory, subject to some limitations. See TECHNICAL DETAILS below for more information about ending wIconSetter. WHAT WICONSETTER DOES: wIconSetter traps the OpenWindow() Intution routine and whenever a new window is openned, wIconify looks to see if you have specified an icon for the new window. If so, wIconSetter adds the icon to the window so that when you use the left-right mouse click (or whatever iconify key sequence you have specified) the window will be iconified using the given icon. wIconSetter determines whether you have specified an icon by looking at the name of the program that is openning the window, the title of the screen on which it is being openned, and the title of the window itself, and comparing these to the values you have given in the initialization file (see below). If no match is found, the window is openned unaffected by wIconSetter. The Intuition SetWindowTitles() routine also is trapped by wIconSetter. When a window's title is changed, wIconSetter checks to see if you have specified an icon for the window with the new title. This is useful for windows that have their titles added after they are openned, such as the Clock and Calculator program provided with WB 1.3. Finally, wIconSetter also traps the OpenScreen() Intuition function, and when a new screen is openned, it checks to see if you have specified a screen icon for that screen. Screens are identified by name and by the name of the program that opens them. THE WICONSETTER INITIALIZATION FILE: To specify that a certain window should have an icon, you must tell wIconSetter what program will open the window, what screen it will be on, and what the title of the window will be. The special keyword '[ANY]' can be used as a wildcard that will match any title. For example, if you specify the program 'emacs', screen '[ANY]', window '[ANY]', then the icon information you give for this specification will be used for any window openned by the program EMACS on any screen. The special keyword '[NULL]' represents a window or screen that has no title at all. To specify a blank title, use ''. To specify the desired program, screen and window, use the commands PROGRAM:, SCREEN: and WINDOW: (the colons are necessary), as in: PROGRAM: 'EMACS' SCREEN: '[ANY]' WINDOW: '[ANY]' The quote characters are optional, and if they are left out, the remainder of the line will be used as the title. If you need to specify a quote within a quote, use two quotes in a row, as in: WINDOW: 'Joe''s Window' If you are specifying more than one window title for the same screen, you do not need to repeat the PROGRAM and SCREEN commands. Similarly, if there is more that one screen title for the same program, the PROGRAM command need only be issued once. For example: Program: Workbench Screen: Workbench Window: Workbench ; the main Workbench window /* icon specification goes here, see below */ Window: 'RAM DISK' ; the Ram disk main window /* icon specification here */ Window: '[ANY]' ; any other WB window /* icon spec */ Screen: [ANY] Window: '[ANY]' ; any window on any other screen /* icon spec */ Note that you must include leading spaces if they appear in the title of a screen or window you are trying to specify; e.g., ' Title with a space'. wIconSetter does not distinguish between upper an lower case when it compares names, so 'wIconify' matches 'WICONIFY', 'WIcoNify' and 'wiconify'. Note that you can also specify PROGRAM: [ANY] if you want to spcify icons by screen or window title only. If more than one window title should get the same icon, you can use more than one WINDOW command in a row, as for example Program: 'NEWCON' Window: 'AmigaShell' Window: 'AmigaDOS' /* icon specification here */ If you omit any of the SCREEN, WINDOW or PROGRAM commands, wIconSetter will assume a value of '[ANY]'. For example, in Program: 'Emacs' Window: 'MicroEmacs' a screen of '[ANY]' is assumed. For window and screen titles, you do not need to specify the complete title, just the first word or so; wIconSetter does a prefix match against the actual window or screen title of the window being openned. That is, if you specify a screen of 'wIconify' this will match 'wIconify v3.7', 'wIconify Screen', or any other title starting with the word 'wIconify'. This is only true for screen and window titles, however; program names must be given in their entirety. Use '[NULL]' to specify a window or screen that has no title at all, and use empty-quotes, '', for a window or screen whose title is blank (i.e., it's title pointer is non-NULL, but points to a string that contains a 0-byte as its first character). These two titles are treated specially, in that they do not prefix-match any other titles (otherwise, for example, '' would match against ANY window, and there would be no way to specify a blank title). To specify a screen icon, simply place the icon specification directly after the SCREEN command, and before any WINDOW commands, as in the following: Program: 'Emacs' Screen: '[ANY]' /* screen icon goes here */ Window: '[ANY]' /* window icon goes here */ Once you have given PROGRAM, SCREEN, and WINDOW commands that specify the window or screen you want to add an icon to, you can use IMAGE, SELECT, MASK, NAME, POSITION, and FLAGS commands to specify the icon's image, select image, image mask (for dragging), name, initial position, and flags. You can include as many or as few of these commands as you like. For example: Program: 'Clock' Name: 'Clock' Position: (600,160) specifies that any window openned on any screen by the program called 'Clock' should have an icon titled 'Clock' that will appear at 600 pixels from the left of the screen and 160 down from the top of the screen when it is first iconified. INITIALIZATION FILE COMMANDS: NAME: 'name' NAME determines what title will appear under the icon when the window or screen is iconified. Usually this is the title of the window or screen itself, but some titles are quite long, and it is convenient to use wIconSetter to give them some shorter name. You can also add icon titles to windows and screens that have no titles. POSITION: (x,y) POSITION sets the initial position of the icon when it is first iconified. If the user moves the icon, however, the inital position is lost (the icon can be made un-movable by using the FLAGS command described below). The parenthesies are required, as is the comma. The x value is the number of pixels from the left of the screen and the y value is the number of pixels from the top of the screen. FLAGS: flag | flag ... The flags may be any of the following: NOSAVEPOS icon will not remember its old position when openned NOCLOSE the CLOSE menu item will not be available for this icon NOMOVE icon can not be dragged from its initial position NOORGANIZE icon will not be affected by the ORGANIZE or CLEANUP menus LOCKED icon is not allowed to move under any circumstances NOMULTISELECT multiple icons can not be selected together with this one CHANGEREFRESH a SMART_REFRESH window will be converted to SIMPLE_REFRESH window automatically when iconified (saves space, but may loose data within the window) NOICONIFY window will not be able to be iconified AUTOICONIFY window will be iconified as soon as it opens For example: Program: [ANY] Window: 'AmigaShell' FLAGS: CHANGEREFRESH | AUTOICONIFY specifies that any window called 'AmigaShell' on any screen will change from a smart to a simple refresh window when iconified, and when a new one is openned, it will be iconified automatically. IMAGE: SELECT: MASK: All three of these have the same format; it is the same format used in the wIconify.init file to specify DEFAULT_IMAGE, DEFAULT_SELECT, and DEFAULT_MASK. The lines that follow the IMAGE, SELECT or MASK command represent the pixel pen colors for the image or mask specified. Each line gives the values for one row of the image, and each character (past the initial blanks) represents one pixel of the image. The character is the pen color for that pixel; for example a '2' is pen color 2, and a '0' is the background pen (color 0). For a two bitplane screen, the colors are from 0 to 3; for 3 bitplanes they are from 0 to 7; For 4 bitplanes, they are 0 to 9 and a to f (these must be lower case letters); for 5 bitplanes, they are 0-9 and a-f for the first sixteen pen colors, and then SHIFT 0-9 and SHIFT A-F for pens from 16 to 31. I.e., ')' is pen 16, '!' is pen 17, '@' is pen 18, '#' is pen 19, up through '*' as pen 24 and '(' as pen 25. Then 'A' is pen 26, up through 'F' as pen 31. This allows you to specify a five bitplane image if you want. For a MASK, however, the only valid pen colors are 0 and 1. A '1' indicates that the bit is part of the mask (the image will show through it) and a '0' indicates that the background will show through. The standard icon size is 41 by 18, though you can specify larger or smaller icons if you want. The size of the SELECT image should match that of the IMAGE, and the MASK should match the SELECT image, if given, or the IMAGE if there is no SELECT image. As an example, the definition of the default icon is: IMAGE: 11111110111111111111111111111111111111111 11000110100000000000000000000011111100011 11000110111111111111111111111111222100011 11111110100000000000000000000011222111111 11111110111111111111111111111111111111111 10000000000000000000000000000000000000001 10000000000000000000000000000000000000001 10000000000000000000000000000000000000001 10000000000000000000000000000000000000001 10000000000000000000000000000000000000001 10000000000000000000000000000000000000001 10000000000000000000000000000000000000001 10000000000000000000000000000000000000001 10000000000000000000000000000000000000001 10000000000000000000000000000000000011111 10000000000000000000000000000000000012211 10000000000000000000000000000000000011001 11111111111111111111111111111111111111111 You may want to have more than one window use the same icon, and it would be tedious to have to include the actial bitmap for the image after each WINDOW command (it would also take up precious CHIP memory, as each image would be stored separately). For this reason, wIconSetter allows you to define common icon images and attributes so that they can be shared by more than one window. To do this you use the DEFINE command. DEFINE: 'icon-name' where 'icon-name' is the name of the icon you are defining. This name will be used later when you want to associate this icon with a specific window. Following a DEFINE command, you give the IMAGE, SELECT, MASK, NAME, POSITION, and FLAG commands that you want this icon to have. For example, Define: 'Small Icon' Name: 'Tiny' Image: 11111111111111111111 11111111111111111111 11000000011222222211 11000000011222222211 11000000011222222211 11000000011222222211 11111111111111111111 11222222211000000011 11222222211000000011 11222222211000000011 11111111111111111111 11111111111111111111 defines a small, checker-board shaped icon with the title 'Tiny'. Throughout the rest of the initialization file, it will be referred to as 'Small Icon', as in the example below. To use an icon that has been defined, use the ICON command in place of the usual icon commands: Program: 'Example' Window: '[ANY]' Icon: 'Small Icon' Flags: AUTOICONIFY You can include additional icon commands after the ICON command, if you wish, as, for example, the FLAGS command above. They can even over-ride the commands given in the DEFINE command. For instance, we could have included a NAME command that would replace the name 'Tiny' given in the definition. You can even DEFINE icons in terms of other icons. For example, if two icons have the same image but different select images, you could do the following: DEFINE: Icon1 IMAGE: /* image for both icons */ SELECT: /* select image of icon 1*/ DEFINE: Icon2 ICON: Icon1 ; use the images of icon 1 SELECT: ; but replace the select image /* select image of icon 2 */ In this case, only one copy of the IMAGE is stored in memory, and both definitions share it. It is sometimes convenient to store the definitions of the images in separate files, so that the initialization file is not so large and so that it is easier to read and modify. To do this, create a file that includes the IMAGE, SELECT, MASK, NAME, POSITION, and FLAG commands that belong to a given icon, and use the command ICON: FROM 'filename' when you want to assiciate that icon to a WINDOW, SCREEN or a DEFINE command. For example: DEFINE: 'External Icon' ICON: FROM 'Icons:Fancy.Icon' This command uses the external file FANCY.ICON in the directory associated to the ASSIGNED name ICONS: as the definition of 'External Icon'. Later, we can use ICON: 'External Icon' as many times as we want to associate this icon with different windows. Note that the DEFINE command does not go in the external file, nor do PROGRAM, SCREEN, WINDOW, or ICON commands. As with DEFINED icons, you can override the values specified in the icon file by supplying additional commands after the ICON command: Program: 'Clock' ICON: FROM 'Icons:FancyClock.Icon' FLAGS: AUTOICONIFY Comments can be included in the initialization file in two different ways. The first is to use the semi-colon (;) which indicates that the remainder of the line is a comment (this works is the same way that the semi-colon works for the CLI). All characters on the rest of the line are ignored, and processing begins at the beginning of the next line. The second way is to use a slash (/) followed by an asterisk (*) to indicate the beginning of the comment and an asterisk followed by a slash to mark the end of the comment (this is the C language comment convention). For example, /* This is a comment */ This has the advantage of being able to "comment-out" just a portion of a line, instead on all of the line. It can also be used to comment-out large sections of the initialization file at once. Any characters within these comment delimiters will be ignored, including line-breaks, and the semi-colon comment character. Comments of this type can be nested, as indicated below: /* This is a /* comment inside */ another comment */ Be sure you have the proper number of closing delimiters or your whole initialization file may be ignored! TECHNICAL DETAILS: How wIconSetter Finds a Program's Name: When a window or screen is openned, wIconSetter determines the program name by looking at the task that openned it. The name is found in one of two ways: If the task is a PROCESS, then wIconSetter checks to see if the process is a CLI process. If so, it looks in the CLI structure for the file name of the command that is running, and strips any disk or directory paths from the name. The resulting name is considered the program name. For example, if the command was 'df0:c/IconEd', then the program name would be 'IconEd'. If the task is a process that is not a CLI (e.g., it was started from the Workbench), or if the task is not a process, then wIconSetter looks for the task name in the task's node structure. This name is treated as a file name (in the case of a WB process, it is the name of the file that is being executed) and any disk and directories are removed, and the result is considered to be the program name. For example, if you click on a document whose default tool is 'C:More', then the process name will be 'C:More', and the program name found by wIconSetter will be 'More'. You can use the program wIdentify to find out what wIconSetter thinks the program names are, if you are having trouble determining the names. NEWCON:, CON: and RAW: windows: Since wIconSetter uses the task that opens a window to determine the program name of the openning task, you have to be somewhat careful if you want to specify icons for CON: or RAW: windows. When a CON: window is openned, for example, a new process is set up (the console task) which manages the IO in the newly created window. It is this task, in fact, that opens the window, not the task that requested the CON: window. The console task always has the name 'CON' ('RAW' for a RAW: window and 'NEWCON' for a NEWCON: window), regardless of the name of the program that requests the console window. For example, if you type DIR > CON:0/0/640/100/Directory in a CLI window, a new CON: window will be openned and the directory output will appear there. wIconSetter will see this window as being openned by the program 'CON', not the program 'DIR'. Similarly, NEWSHELL NEWCON:0/10/640/100/MyShell will open a new shell in a NEWCON: window, and wIconSetter will identify the program that opens this window as 'NEWCON' not as 'NEWSHELL'. This is unfortunate, but unavoidable. You will have to rely on the screen and window titles to distinguish among such windows. Windows and screens that are Open when wIcon Setter Begins: Since wIconSetter adds icons only when windows and screens are initially openned, any windows or screens that are already open when wIconSetter is first started (normally) would not be given icons by wIconSetter. It is desirable to have wIconSetter add icons to these windows and screens as well (if they match a window or screen title given in the initialization file). For this reason, when you start wIconSetter, it will look through the list of open windows to see if any should get icons. Normally, however, when wIconify checks a window to see if it should get an icon, it has a pointer to the process that is creating the window. This is not the case for windows that are pre-existing. wIconSetter does its best to find the program name of the exiting windows, but in some cases (namely CON: and RAW: windows), this is not possible, so wIconSetter may not be able to add icons to all the existing windows correctly. When wIconSetter can not determine the existing program name, it uses the name '[ANY]'. There are two approaches to solving this problem: first, be sure to start wIconSetter early in your startup sequence so that it will be running when other windows are openned. Second, use PROGRAM: [ANY] in the initialization file to include titles of NEWCON:, CON: and RAW: windows that should have icons. wIconSetter does NOT add icons to existing screens at startup, since there is no way to determine the owner of an existing screen. Windows Openned by Intuition: Since wIconSetter traps the OpenWindow() function in the Intuition library jump table, only windows that are created through this mechanism are modified by wIconSetter. Intuition itself, however, does not call its own jump table, so windows openned by Intuition (e.g., "System Request" windows, and windows created by AutoRequest() or BuildSysRequest()) do not pass through wIconSetter's trap, hence can never be modified by wIconSetter. It is pointless to specify such windows in the initialization file, since there is no way wIconSetter can add icons to them. Windows and Screen openned by wIconify itself: wIconSetter uses inter-process message passing to add icons to windows and screens, and and since it does so from within the trapped OpenWindow() and OpenScreen() routines, it is operating within the environment of the process that is openning the window or screen. This communication is done synchronously (i.e, wIconSetter calls Wait() until the reply is returned), so wIconSetter can not be used to add icons to screens (or windows) created by wIconify itself, since this would cause a deadlock situation (wIconSetter would be waiting for wIconify to reply, but wIconify would be waiting for the screen to open before it could process any icon requests). For this reason, wIconSetter ignores any requests to add icons when the calling process is wIconify, so it is safe to use '[ANY]' in situations that could possibly include wIconify screens or windows. Since the only windows openned by wIconify are the wIconify backdrop windows, this should not be a problem. If you want to have the wIconify screens to have different icons from other screens, however, you can do it by using the SCREEN_IMAGE, SCREEN_SELECT, and SCREEN_MASK commands of the wIconify initialization file to specify the icon for wIconify screens: this will be used by wIconify for its own screens (as well as all the others). Then use the commands Program: [ANY] Screen: [ANY] /* real default icon here */ to specify the icon you really want as the default icon. wIconSetter will add this icon to all new screens that are openned by processes other than wIconify itself. Window Title Changes: Some programs open their windows without titles, and then add the title once the window is open (e.g., Clock and Calculator supplied with WB 1.3). For this reason wIconSetter traps the SetWindowTitles() Intuition routine, and when a window's title changes, wIconSetter checks its list of icons again to see if the window with it's new title should receive a special icon. For example, you can specify: PROGRAM: Clock Window: Clock Flags: AUTOICONIFY Name: Clock And even though the clock window opens with no title, when the Clock program renames its window, wIconSetter will recognize it at that point, and modify the icon accordingly. A more interesting use of this feature is the following: the More program provided with WB 1.3 changes the title of the CLI window in which it was run, and wIconSetter will notice this change. The commands PROGRAM: More Window: 'AmigaShell' Window: 'AmigaDOS' Icon: FROM Icons:CLI.Icon Window: [ANY] Icon: FROM Icons:More.Icon Name: 'More' ; to avoid long names can be take advantage of this in a clever way. When MORE adds the window title, the WINDOW: [ANY] command will add the icon found in the file ICONS:MORE.ICON to the CLI window where MORE is running. When MORE removes the window title and replaces the original title, the two other WINDOW commands will change the icon back to the stnadard CLI icon found in the file ICONS:CLI.ICON (provided the original title was 'AmigaDOS' or 'AmigaShell'). Although the Shell window is owned by the NEWCON process, the PROGRAM command names MORE not NEWCON as the program since the window's title is being changed by the MORE program, not the NEWCON device. Ending wIconSetter: To stop wIconSetter once it is running, issue the wIconSetter command again. If wIconSetter is called while the wIconSetter-Handler is already installed, then wIconSetter will attempt to remove the handler from memory. Unfortunately, it's not quite that easy. It is unsafe to terminate wIconSetter while wIconify is running, since the icons set up by wIconSetter may still be in use by wIconify. Thus wIconSetter will not terminate while wIconify is still running, so if you want to remove wIconSetter, you must first end wIconify itself. Unfortunately, both wIconify and wIconSetter use the SetFunction() command to trap calls to the OpenWindow(), OpenScreen(), and SetWindowTitles() routines of the Intuition library, and since wIconify must be run first, it sets its trap before wIconSetter. The current implementation of SetFunction() requires that the traps be removed in the reverse of the order in which they were set, so wIconify may not be able to remove its traps before wIconSetter exits. This creates a "catch-22" situation, since wIconSetter can not exit before wIconify does. The upshot of all this is that, under normal circumstances, it is imposible to end wIconify or wIconSetter once they are both running together. This isn't such a bad problem since there is not usually any reason to end them once they are running. The solution to this problem is to perform a modification of the SetFunction() routine (this has advantages not just for wIconify and wIconSetter, but for any program that traps system routines) so that traps can be be removed in any order. The program PatchSetFunction, also written by the author of wIconify and available free of charge, is a program that does just that. It is highly recommended, if you use programs that trap system calls, that you install PatchSetFunction before starting those programs. AUTHOR: Davide P. Cervone Mathematics Department Brown University Providence, Rhode Island 02912 ST402523@BROWNVM