NibList - 
This is intended to be a utility for documenting the contents of nib files.  This should be considered a beta release, since there's a great deal of room for making the output format prettier and more informative.   I'm hoping to get a lot of ideas about improving it, so don't be shy!  Send comments & suggestions to ...uunet.uu.net!oceania!rselph.  (I think  oceania!rselph@uunet.uu.net  works.)

Legality stuff -
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program, in a file called COPYING; if not, write to
    the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Installing -
If you do a 'make install'  NibList will become one of the tools for nib files.  (For more information on using alternate tools on a file type, read /NextLibrary/Documentation/NextUser/WMgrCommands.rtfd, and search for 'tools inspector')  You can open and examine as many nib's at once as you like.   This is definitely a 2.0 application.  I don't think it will even compile under 1.0, and I have no idea what the differences in nib file format might be.

The output produced will look like this:

NIBFileName: /Net/southern/Users/rselph/Development/NibList/Info.nib
Contains 12 objects with 1 connections,
0 icons, and 0 sounds.

-----------OBJECTS------------
<File's Owner>NibbleApp(000935cc)CustomObject:
    Connections:
        outlet infoPanel to <Info>Panel(000935fc)
    Owns:
        <Info>Panel(000935fc)WindowTemplate:
            Owns:
                <Button1>Button(00093858)Button:{45,69,48,48}
                <Field1>TextField(000936ec)TextField:{172,125,73,26}
                <VersionNumber>TextField(000937a0)TextField:{9,11,62,13}
                <Field>TextField(000938f8)TextField:{74,11,326,13}
                <Box>Box(000939e8)Box:{6,30,402,2}
                <Box1>Box(00093af8)Box:{130,44,151,74}
                    Owns:
                        <Field2>TextField(00093c14)TextField:{50,21,40,18}
                        <Field3>TextField(00093cc8)TextField:{17,0,94,18}
                        <Field4>TextField(00093d84)TextField:{13,42,107,18}
                <Button>Button(00093e68)Button:{318,71,48,48}

-----------ICONS------------
List:    Contains 0 entries

-----------SOUNDS------------
List:    Contains 0 entries

Explanation of output format -
There are four sections in the output.  The first section briefly describes the nib.  The three remaining sections describe the objects, icons and sounds in the file.  Icons and sounds are simply listed by their names.

The object section  contains all the nitty-gritty of the nib file.  Each object in a nib file is 'owned' by another object.  I'm not sure exactly what this ownership relation means at run-time, but while you're working in Interface Builder, it seems to indicate which objects should be grouped together for deletion.  For instance, in the file above, <Box1> owns <Field2>, so if <Box1> gets deleted, <Field2> should also.

Each object has a name associated with it.  For windows, this is the name you see below the window icon in IB's file window.  This name is shown in angle brackets '<aName>'.  This is followed by the object's actual class, and an address in parentheses '(000xxxx)'.  This address will be different each time the file is printed, but it is included because it's the only thing gauranteed to identify the object uniquely.  This is followed by the object's nib class - the class of the object's place holder in the nib file.  This is the same as the objects actual class, unless the object is a custom object, or a sub-class of Window or Menu.  Custom objects are represented by a class called (of course) CustomObject.  Windows are represented by WindowTemplate, and Menus by MenuTemplate.  These are lightweight objects that just store the bare essentials of their 'real' counterparts.

For objects that are a subclass of View, the nib class name will be followed by the View's frame rectangle.  (There's no reason not to print information about other types of objects, except that I haven't come up with a good format yet.)

If there are any connections from this object, they will be listed next.  Connections come in two flavors: target/action and outlet.  Following this is the list of objects owned by the original object.  In this way, all objects are listed heirarchically.

File List -
Categories.[hm]		Categories for dumping appkit classes
Controller.[hm]		Main object for coordinating windows
COPYING			The GNU General Public License
IB.proj
Info.nib
Makefile
Makefile.postamble
Makefile.preamble		Establish dependency on /usr/lib/nib/libnib.o
NibFile.[hm]			Object to parse and print nibfile
NibIcon.tiff			Icon for nib files
NibList.iconheader
NibList.nib
NibList.strings
NibList.tiff			Icon for the application
NibList_main.m
Notes				Some notes on what I think is going on in a nib file
README.rtf			This file
libnib.h			Hand-rolled and incomplete header for /usr/lib/nib/libnib.o

How it works -
There were two key discoveries that helped get this program off the ground.  The first was that the Interface Builder's nib file manipulation code is in /usr/lib/nib/libnib.o.  This file contains code for several object types, the most important ones being HeaderClass, NibData, and CustomObject.  The second discovery was that you can use the AppInspector to discover what methods and instance variables these classes have.  (It's especially fun to turn the AppInspector on the Interface Builder.)

What NibList does is load the nib file as a TypedStream.  This gets the basic data into memory, and allows sifting and sorting of the objects.  See the Notes file for details of the data format.  NibList then cross-indexes the objects to establish the ownership heirarchy.  This is needed because in the nib file, the objects are simply listed in order, each with a pointer to it's owner.  Once the ownership heirarchy is figured out the program recursively descends it, printing out details of the objects on the way.  All of the important code for doing this is in NibFile.m.

Burning Questions -
Should a utility of this type print ALL of the information needed to rebuild the objects EXACTLY, or should it produce a concise, human readable summary?  (or both?)

How can I print oodles of information about each object without cluttering things up?  I'm only printing info about views now.

Have you found any nib files that crash NibList, or cause funny behavior?