SGI File Typing Rule Tutorial
This was originally published on my old SGI website, archived here.
To avoid any confusion, FTRs apply to the vector, scaleable icons which you see in the Icon Catalog and in the file manager windows. Icons for minimised applications are a different thing. Those icons are bitmapped and are stored in a different place and are linked to the application by it’s X resource name.
The IRIX Interactive Desktop is incredibly powerful in the way it handles file types. The desktop can automatically identify files and launch the correct application without the need for file extensions or a “resource fork” like Apple’s HFS filesystem. Have you ever noticed that you can change the file extension on a file and it still maintains the same icon, eg: mv file.xyz file.xyz.backup
. It does this by two main methods:
- Firstly, an executable can be “tagged” by the tag utility. This embeds a unique number into the executable. Blocks of numbers can be allocated to software developers by SGI (Email:desktoptags@sgi.com).
- Alternatively, you can write a set of rules to identify the file, based on it’s name, location, size and contents. This is very powerful.
The procedure for creating a new filetype, complete with icon is:
- Create the icon in IconSmith.
- Consider the actions you would like to take place.
- Create the file type with a text editor.
- Recompile the icon type libraries (easier than it sounds!).
- Restart the desktop.
- Creating The Icon
Most of the icons in the Icon Catalog change their appearance when the application is opened. This, howeved, doesn’t mean that you have to design two different icons, the icon you draw is simply combined with the standard “magic carpet” background image. I’m not going to provide much detail on how to use IconSmith, since it’s a fairly self explanatory application. Have a look at some existing icons to get a feel for how things work. As stated before, you don’t have to worry about drawing the “magic carpet”. The only slightly confusing piece of terminology is the idea of a Template. Unlike most programs where a template is just a starting point which you can modify to suit you needs, a template in IconSmith is for you to trace over for easy of alignment and won’t be included when you save your file. There is an online manual for IconSmith on SGI’s Techpubs Library.
Once you have created your icon with IconSmith, save it in /usr/lib/filetype/install/iconlib
.
Tagging Your Application
Firstly, you need to get a block of tags from SGI. I’ve never done this, so I don’t know how easily they’re persueded to give them out. Maybe you have to be on their Developer Plus programme. On the other hand, they tag numbers are 32 bit hex values, so it’s not like they’re going to run out. The important thing to realise it the tag is placed in the actual executable itself, so you need write-access to the executable. The app doesn’t get fingerprinted and placed in some registry in the local machine. You should tag the application before you package the software up, if you’re going to distribute it. There are also implications with the packaging process when executables get tagged.
You can only tag executables and shell scripts. Data files don’t get tagged. Obviously.
The syntax for the tag command is:
% tag
For example:
% tag 0x12345678 foowriter
For ad-hoc local filetypes, it’s better to match the files with a set of rules though, which is more complicated, but better suited for many situations.
An example of a matching rule is:
MATCH glob("*.c") && ascii;
…which matches text files ending in .c (Only the first 512 characters are checked though).
Programming a FTR Rule
As a rule, user created or third party FTRs should go in:
/usr/lib/filetype/install
There are several FTR directories, which are listed here in order of priority. It is quite acceptable to have a FTR in two places, so a rule in local would override an identical rule in system. A single FTR file can have several rules in it.
/usr/lib/filetype/local
/usr/lib/filetype/install
/usr/lib/filetype/system
/usr/lib/filetype/default
It is conventional to name your FTR file like vendor-name[.application-name].ftr
. You should place all the rules which relate to the application in one file.
A Simple Example
TYPE FooWriter
MATCH tag == 0x00002739;
LEGEND FooWriter Document Mangler
SUPERTYPE Executable
CMD OPEN $LEADER
ICON {
if (opened) {
include("../iconlib/generic.exec.open.fti");
} else {
include("../iconlib/generic.exec.closed.fti");
}
include("/iconlib/fooware-foowriter.fti");
}
This rule only covers the actual executable itself. You could define further rules to handle the application’s data files. This is about as simple as it gets. Hopefully it should look fairly self explanatory to anybody who’s edited a config file bofore. The individual parts are explained below.
TYPE Keyword
The TYPE keyword gives a name to the type and opens the type definition. Type names must follow the C variable conventions and must be a single word with no spaces. All statements following a TYPE statement are considered to be part of it, until the next TYPE statement is encountered. There isn’t an ENDTYPE keyword.
Example:
TYPE FooWriter
SUPERTYPE Keyword
The SUPERTYPE keyword is kind of an include. You can use an existing type as a starting point, then override the pre-existing definitions for the actions and icon rules. The one exception is the Directory type, the rules of which cannot be overridden. It makes sense to use the Executable type as a basis for your own executable rules, since it includes some sensible defaults. Any existing type can be specified as a supertype. Multiple supertypes can be specified with multiple supertype statements (rather than a comma separated list, for example).
You can list existing types using the following command:
% grep TYPE /usr/lib/filetype//.ftr
Note: This will make a very long list!
LEGEND Keyword
The LEGEND keyword allows a textual description to be specified. This is shown in the list view mode.
Example:
LEGEND FooWriter Document Mangler
MATCH Keyword
The MATCH keyword uses C-like operators and expressions to determine whether a particular file is of this type. The expression should evaluate to TRUE if the file is of the required type. There is only one MATCH allowed per rule. Be careful not to make your rule too relaxed, otherwise you may accidentally include files you didn’t mean to, and break existing applications!
Some examples:
MATCH tag == 0x182012F8;
Will match the executable which has been tagged with tag number 0x182012F8
.
MATCH glob("foowriter");
Will match any file named foowriter, executable or otherwise.
The following operators are available:
- * / & | ^ ! % ( )
The following conditionals are also available:
&& || == != < > <= >=
The comparison (==
) operator works for strings as well as integers.
true and false are defined as constants.
Integers can be specifed as decimal, octal (by placing a leading zero in front), or hexadecimal (precede with 0x).
MATCH Function List
ascii | true if first 512 bytes are printable ascii chars |
char(n) | Returns the nth byte as a single signed character |
dircontains(“string”) | Returns true if the icon is a directory and it contains a file which is matched by the specified string |
linkcount | Returns the number of hard links to the file |
long(n) | Returns the nth byte as a signed long, eg -2^31 to (2^31)-1 |
mode | Returns the mode bits of the file (see chmod manpage) |
print(expr || “string”) | Prints the specified string or expression to the console for debugging purposes |
short(n) | Returns the nth byte of the file as a short integer (-32768 to 32767) |
size | Returns the size of the file in bytes |
string(n,m) | Returns a string of m bytes beginning at the nth character |
tag | Returns the tag on the application, returns -1 if file is not tagged |
ushort(n) | Returns the nth byte as an unsigned short. 0 to 65535 |
Example:
MATCH (string(1,2) == "MZ") && !ascii;
…identifies a MS-DOS executable.
MATCH (string(7,4) == "JFIF") && !ascii;
…identifies a JPEG file.
Note that these are probably not the best way of doing this!
SPECIALFILE Keyword
When used in conjuction with SUPERTYPE SpecialFile directive, this indicates that the file should not be touched. eg: a tape drive – don’t want to read from the device since the tape would be repositioned.
CMD OPEN sh-expression[; sh-expression; … ; sh-expression]
This is where you actually specify the action for when you double-click the icon. Any number of bourne shell expressions, separated by semicolons can be specified here. Do not end the last one with a semicolon. The command can span multiple lines.
There are several variables which can also be used to refer to the selected icons:
$LEADER
– The currently selected icon.$REST
– The rest of the currently selected icon.$LEADERTYPE
– The matching TYPE of the current icon.$RESTTYPE
– Type of the other selected icons, so long as the type is the same for all. Null if not.$RESTTYPELIST
– A list of the types corresponding to the icons in $REST.$ARGC
– The number of selected icons.$TARGET
– The drop target, if being dragged and dropped.$SELECTED
– All the names of selected icons.$SELECTEDTYPE
– If all selected icons are the same type, the type of the icons.$SELECTEDTYPELIST
– Corresponding type list for $SELECTED if they are different types.$WINTERM
– The name of the window manager terminal program, eg winterm.
User variables:
$WINEDITOR
– Default editor, eg: nedit$WEBBROWSER
– Default WWW browser.$IMGVIEWER
– Default image viewer.$MAILBOXPROG
– Default mail client.$BOOKVIEWER
– Default insight book viewer.$PSVIEWER
– Default ps viewer, eg showps.
Example:
CMD OPEN $WINEDITOR $SELECTED
…simple rule for text files.
Don’t forget, any bourne shell commands are valid. eg:
TYPE JPGFile
MATCH (string(1,4) == "JFIF") && !ascii;
CMD OPEN if test -x /usr/freeware/bin/gimp
then
/usr/freeware/bin/gimp $LEADER
else
$IMGVIEWER $SELECTED
fi
In addition to CMD OPEN, there is also CMD ALTOPEN. This performs a similar function, with the exception that it defines the action which takes place when the Alt button is held down simumtaneosly.
DROP Commands
Along the same vein, is the CMD DROP command, which is executed when the icon is dropped. The $TARGET
variable indicates which icon the icon was dropped onto.
Example:
CMD DROP $TARGET $SELECTED
DROPIF Keyword
When this keyword is specified, it limits an icon to only accept the specified file types as drop candidates. This can be used so that only data files produced by your application can be dropped onto the application icon.
Example:
DROPIF MyAppDataFile
CMD DROP $TARGET $SELECTED
In this case, the CMD DROP rule is followed only when the file being dropped is a MyAppDataFile.
CMD PRINT Keyword
CMD PRINT sh-expression[; sh-expression; … ; sh-expression]
This is similar to the CMD OPEN file type rule, but is executed when the file is printed via the desktop print application. It is recommended to use routeprint to handle the printing. Routeprint can automatically determine the best way to print a file using it’s own set of rules.
MENUCMD Keyword
MENUCMD "string" sh-expression;…..
The MENUCMD keyword can be used to add commands to the desktop menu, which is available when the right-mouse button is clicked. All the usual variables are still available. You could use this to add an action to edit an image file in The Gimp, for example.
ICON Keyword
The icon keyword is normally given last of all. It specifies what .fti files are to be combined in order to give the correct appearance to the icon. An example is given below:
ICON { if (opened) {
include("../iconlib/generic.exec.open.fti");
} else {
include("../iconlib/generic.exec.closed.fti");
}
include("iconlib/foowriter.fti");
}
This is fairly self-explanatory. Just make sure that the generic icon is included first, otherwise it will cover your application icon.
Compiling The Rules
This is easier than it sounds, thanks to a handy makefile.
% cd /usr/lib/filetype
% su
# make -u
# exit
% /usr/lib/desktop/telldesktop quit
…then select “In my Home Directory” in the Access Files menu on the toolchest.
Once this is done, your new rules are ready for action. Don’t forget to create a rule for your executable, and a rule for your data files. Tie the two together by using a DROPIF keyword to make sure that only your application’s own data files can be dropped onto it.