Initial commit master
authorBernie Innocenti <bernie@codewiz.org>
Fri, 11 Mar 2011 06:13:43 +0000 (01:13 -0500)
committerBernie Innocenti <bernie@codewiz.org>
Fri, 11 Mar 2011 06:13:43 +0000 (01:13 -0500)
83 files changed:
.gitignore [new file with mode: 0644]
BUGS [new file with mode: 0755]
ChangeLog [new file with mode: 0755]
GUIDELINES [new file with mode: 0644]
INSTALL [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
STYLE [new file with mode: 0644]
TODO [new file with mode: 0755]
classes/ExtRequesterClass/Makefile [new file with mode: 0644]
classes/Makefile [new file with mode: 0644]
common/ClassLib.s [new file with mode: 0755]
common/GetGadgetBox.c [new file with mode: 0644]
common/Makefile [new file with mode: 0644]
common/OpenClass.c [new file with mode: 0644]
common/general.mk [new file with mode: 0644]
common/gst.c [new file with mode: 0644]
common/startup_gcc.s [new file with mode: 0644]
common/startup_sc.s [new file with mode: 0644]
common/startup_storm.s [new file with mode: 0644]
config.mk [new file with mode: 0644]
docs/ExtFrameIClass.doc [new file with mode: 0644]
docs/Intuition [new file with mode: 0644]
docs/LabelTextIClass.doc [new file with mode: 0755]
docs/NoteBOOPSI [new file with mode: 0644]
docs/empty_Makefile [new file with mode: 0644]
docs/empty_config.mk [new file with mode: 0644]
gadgets/ClockGClass/Makefile [new file with mode: 0644]
gadgets/LauncherGClass/Makefile [new file with mode: 0644]
gadgets/ListBox/ListBoxClass.c [new file with mode: 0644]
gadgets/ListBox/Makefile [new file with mode: 0644]
gadgets/ListView/BoopsiLV.readme [new file with mode: 0644]
gadgets/ListView/LVDemo.c [new file with mode: 0644]
gadgets/ListView/ListViewClass.c [new file with mode: 0644]
gadgets/ListView/ListViewClass_static.newinline.s [new file with mode: 0644]
gadgets/ListView/ListViewClass_static.oldinline.s [new file with mode: 0644]
gadgets/ListView/ListViewHooks.c [new file with mode: 0644]
gadgets/ListView/Makefile [new file with mode: 0644]
gadgets/Makefile [new file with mode: 0644]
gadgets/MeterGClass/Makefile [new file with mode: 0644]
gadgets/PIPWin/GNUmakefile.nothanks [new file with mode: 0644]
gadgets/PIPWin/Makefile [new file with mode: 0644]
gadgets/PIPWin/PIPClass.c [new file with mode: 0644]
gadgets/PIPWin/PIPClass.h [new file with mode: 0644]
gadgets/PIPWin/PIPWin.c [new file with mode: 0644]
gadgets/PIPWin/PIPWin.mdbi [new file with mode: 0755]
gadgets/PIPWin/PIPWin.project [new file with mode: 0755]
gadgets/PIPWin/PIPWin.readme [new file with mode: 0644]
gadgets/PIPWin/PIPWin.sas [new file with mode: 0755]
gadgets/PIPWin/SMakefile [new file with mode: 0644]
gadgets/ResizeGClass/Makefile [new file with mode: 0644]
gadgets/ResizeGClass/config.mk [new file with mode: 0644]
gadgets/ScrollButton/Makefile [new file with mode: 0644]
gadgets/ScrollButton/ScrollButtonClass.c [new file with mode: 0644]
gadgets/SliderBar/FrPropGClass.c [new file with mode: 0644]
gadgets/SliderBar/Makefile [new file with mode: 0644]
gadgets/SliderBar/SliderBarDemo.c [new file with mode: 0644]
gadgets/SliderBar/SliderBarGClass.c [new file with mode: 0644]
gadgets/SmartGroup/Makefile [new file with mode: 0644]
gadgets/SmartGroup/SmartGroupGClass.c [new file with mode: 0644]
gadgets/ToolManagerGClass/Makefile [new file with mode: 0644]
include/BoopsiLib.h [new file with mode: 0644]
include/BoopsiStubs.h [new file with mode: 0644]
include/CompilerSpecific.h [new file with mode: 0644]
include/DebugMacros.h [new file with mode: 0644]
include/DiagnosticMacros.h [new file with mode: 0644]
include/ListMacros.h [new file with mode: 0644]
include/README [new file with mode: 0644]
include/gadgets/FrPropGClass.h [new file with mode: 0644]
include/gadgets/ListBoxClass.h [new file with mode: 0644]
include/gadgets/ListViewClass.h [new file with mode: 0644]
include/gadgets/PIPClass.h [new file with mode: 0644]
include/gadgets/ResizeGClass.h [new file with mode: 0644]
include/gadgets/ScrollButtonClass.h [new file with mode: 0644]
include/gadgets/SliderBarGClass.h [new file with mode: 0644]
include/gadgets/SmartGroupGClass.h [new file with mode: 0644]
include/images/CVS/Entries [new file with mode: 0644]
include/images/CVS/Repository [new file with mode: 0644]
include/images/CVS/Root [new file with mode: 0644]
include/images/ExtFrameIClass.h [new file with mode: 0644]
include/images/LabelTextIClass.h [new file with mode: 0644]
include/images/VectorGlyphIClass.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c01d83f
--- /dev/null
@@ -0,0 +1,2 @@
+*.o
+*.gadget
diff --git a/BUGS b/BUGS
new file mode 100755 (executable)
index 0000000..897dad9
--- /dev/null
+++ b/BUGS
@@ -0,0 +1,38 @@
+Known bugs in the provided classes
+==================================
+
+ Common:
+
+ - Some of the demo programs will exit silently when they fail
+   to open any of the required classes. In this case you must
+   copy them to your SYS:Classes/[images|gadgets]/ directory
+   in order to avoid the problem. You can also solve this
+   problem by adding The dist/classes directory to the LIBS:
+   multi-assign:
+   
+     > Assign LIBS: dist/classes/ ADD
+
+   When you are done, you can cleanup by typing:
+   
+     > Assign LIBS: dist/classes/ REMOVE
+
+
+
+ ListViewClass specific:
+
+ - The clipping mode appears to work well with the original
+   layers routines and also with CyberGraphX's "SUPERLAYERS"
+   option. When using Picasso 96, the clipped window will
+   draw incorrectly and scrolling will sometimes hang the system.
+
+ - In some cases the clipped listview with big font size calls
+   Text() with a slightly negative Y coordinate in the RastPort.
+   This shows a OS bug which corrupts the item displayed on the
+   top of the list. This problem would need further investigation.
+   It happens on AGA, CyberGraphX and Picasso96.
+
+
+Known bugs in Intuition's builtin classes
+=========================================
+
+ TODO
diff --git a/ChangeLog b/ChangeLog
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/GUIDELINES b/GUIDELINES
new file mode 100644 (file)
index 0000000..71a9cbd
--- /dev/null
@@ -0,0 +1,129 @@
+$Id: GUIDELINES,v 1.1 2000/01/12 20:37:03 bernie Exp $
+
+
+OpenBoopsi Guidelines
+=====================
+
+ This is a brief guideline to explain you how the OpenBoopsi root is
+ organized, how the makefiles system work, etc. so that you can add
+ your own class without problems and even without writing your own
+ Makefile! (more or less ;-)
+
+ The OpenBoopsi tree is structured in this way:
+
+   OpenBoopsi root/
+      Makefile
+      config.mk
+
+      images/
+          Makefile
+          class1/
+              Makefile
+              config.mk
+              Class1.c
+              Class1Demo.c
+          class2/
+              etc.
+       gadgets/
+          Makefile
+          class1/
+              Makefile
+              config.mk
+              etc.
+       include/
+          common/
+              general.mk
+              BoopsiStubs.h
+              etc.
+          images/
+              Class1.h
+              etc.
+        etc.
+
+
+These are things you should know:
+
+Makefiles
+=========
+
+1) There is a global "config.mk" files where are defined all the compiler
+ specific variables, like command line options, tools, paths, etc. It is
+ divided in two sections and you usually should need to modify only the
+ first one. This file is placed in the OpenBoosi root. Run 'make help' for
+ a listing of the current configuration.
+
+2) There are different local "config.mk" files. They contain classes
+ specific informations, i.e. class name, class version, etc. They are
+ placed in every classes' directory and are required, so if you add a
+ new class to the OpenBoopsi project you must write one of this file.
+ An empty config.mk file is provided in the docs/ drawer with all the
+ explanations you will need.
+
+3) The top level Makefile will call all the makefiles in the other
+ subdirectories to build the complete distribution, as usual. However,
+ this Makefile also has a special target which sets up your build
+ environment. Without this preliminar step you won't be able to compile
+ anything. Read the INSTALL file or just run 'make help-setup' for a
+ more detailed explanation of this required step.
+
+4) The makefiles present in every classes' directory are simple dummy
+ makefiles. They just include the local "config.mk" file and the real
+ Makefile, so you just need to copy it in your class' directory without
+ any modifications.
+
+5) It is possibleto customize the local makefiles to pass custom "arguments"
+ to the true Makefile, so if e.g. your class need to link a specific object
+ you don't need to modify the general Makefile. Read the docs/empty_Makefile
+ file for a detailed explanation.
+
+6) You can obviously add to the local Makefile your own targets, e.g. for
+ creating a custom object that need to be linked to the demo program
+ (and that you will need to pass to the general Makefile via the argument
+ system described above).
+
+7) The "general.mk" file in the common/ directory is the Makefile used to
+ compile all the classes. It is included by the various local makefiles.
+ This method has three great advantages: 1) if the Makefile is changed or
+ improved it does not need to be copied in every subdirectories and 2)
+ you don't need to write your own custom Makefile, just the config.mk
+ 3) if you write a better/different Makefile other user can take
+ advantages of this just by including your Makefile instead of the
+ standard one.
+
+8) Remember that custom makefiles must support the defined targets or it
+ will be impossible to build all the distribution calling the top level
+ Makefile. You can find a list of the required targets and their purposes
+ in the general.mk file.
+
+9) If you want your own custom Makefile we suggest you to put it in the
+ common/ directory (so don't call it Makefile, give it a different name)
+ and then change your class' local Makefile to include your custom true
+ Makefile instead of the default one. In this way other people can use your
+ Makefile without the need to copy it to their subdirectories.
+
+
+Includes
+========
+
+1) All the includes must be placed in the appropriate include/ subdirectories.
+ You must leave includes in the classes subdirectories only if they e.g. contain
+ private definitions needed by the class only, i.e. no other programs or classes
+ can include it.
+
+2) The makefiles already know where they should search for the needed
+ includes and how to tell the compiler to find them, so you should not
+ worry about this.
+
+3) To include the required headers in your programs or classes just follow
+ this example:
+
+#include "common/BoopsiStubs.h"
+#include "images/VectorGlyph.h"
+#include "gadgets/ListView.h"
+#include "RequesterClass.h"
+#include "MyPrivateInclude.h"
+
+4) IMPORTANT: in the example above the last two includes look identical,
+ however the first should be placed in the include/ dir (and not
+ in one of its subdirectories!) while the latter should go in the class
+ own directory.
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..583664b
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,15 @@
+$Id: INSTALL,v 1.1 2000/01/12 20:36:51 bernie Exp $
+
+How to build the project
+========================
+
+ Run "make setup". It will create an env variable with the name of the dir
+where you have unpacked the OpenBoopsi distribution. This variable is
+required, so don't remove it! It will also be copied in ENVARC:, so you
+will need to do the setup only once. Running 'make help-setup' will
+print a brief explanation and the value that will be assigned to the
+environment variable when you do the setup.
+
+ It is also advisable to read the GUIDELINES file for a detailed
+description of the distribution structure and how the makefiles
+are organized.
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..161a3d1
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,482 @@
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+     Appendix: How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+    MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..222061b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+##
+## $Id: Makefile,v 1.1 2000/01/12 20:37:38 bernie Exp $
+##
+##     This Makefile must be processed with GNU make 3.76.1
+##     which is available on Aminet: dev/c/make_bin.lha
+##
+## Copyright (C) 1999 by B. Innocenti & M. Cavalleri
+##
+
+SUBDIRS := common classes images gadgets
+
+include config.mk
+
+ifeq ($(COMPILER),gcc)
+       TOP := $(shell pwd)
+else
+       TOP := $(shell cd)
+endif
+
+include common/general.mk
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..b551e92
--- /dev/null
+++ b/README
@@ -0,0 +1,82 @@
+$Id: README,v 1.1 2000/01/12 20:32:09 bernie Exp $
+
+
+About `boopsi'
+==============
+
+ The achronim `boopsi' stands for Basic Object Oriented Programming System
+for Intuition. This facility is available in AmigaOS since Kickstart V36.
+boopsi is primary meant as an OOP framework for GUI components such as
+gadgets, images, texts and so on.
+
+ The system provides several boopsi classes which are the OOP counterparts
+of the plain Intuition gadgets and other important structures such as Image
+and IntuiText. There are also classes that allow building a network of
+interconnected boopsi objects so that each object can notify the others
+about its attributes. This boopsi communication system enables the gadgets
+to talk each other so they can react to user input in complex ways, freeing
+the application from most of the GUI administration duties.
+
+
+Other GUI systems
+=================
+
+ Unfortunately, the built-in Intuition classes are not very powerful,
+nor flexible enough for todays applications. That's why so many
+alternative GUI systems have appeared during the past years. Some
+of these systems are also based on boopsi, while others provide
+their own API through a shared library.
+
+ The main disadvantage with these GUI systems mentioned above is
+none of them is free. In this case we are referring to the GNU meaning
+of the word `free'. It means that the users and the developers are
+not given enough freedom. Some GUI systems are shareware, some others
+come with a license that forbids or limits their use for commercial
+applications. Few of them come with their source code and in most
+cases they don't give you the freedom to change it. On the technical
+side, the major limit of the current GUI systems is that they are
+usually mutually exclusive. You can't mix objects from two different
+systems to take advantage of the features of both.
+
+
+About the boopsi OSS project
+============================
+
+ The goal of this project is providing a comprehensive set of
+boopsi classes for general application developement. The main
+developemnt guidelines are:
+
+  - providing a pure boopsi API for GUI construction. There
+    are no additional libraries.
+
+  - integration with the system built-in classes, whenever
+    possible.
+
+  - support the current V39/V40 OS along with the current
+    RTG systems.
+
+  - Sticking to clean AmigaOS programming, except when it is
+    absolutely impossible to do so to workaround known
+    OS bugs.
+
+  - Adopting a distributed developement model. Source code
+    is freely available and anyone is allowed to improve or
+    add new functionality.
+
+  - Leave the choice to the application developer.
+    The classes will be available in several flavours,
+    including shared class libraries, linker library and
+    a monolithic shared library.
+
+  - Find the best trade-off beteen efficiency, portability
+    and configurability
+
+
+DISCLAIMER
+==========
+
+ This software is provided AS-IS, without any explicit or implied warranty.
+
+ This software is to be considered PRELIMINARY and SUBJECT TO CHANGE.
+It has not been tested accurately and it may contain BUGS that could
+easily CRASH YOUR SYSTEM.
diff --git a/STYLE b/STYLE
new file mode 100644 (file)
index 0000000..4f153d4
--- /dev/null
+++ b/STYLE
@@ -0,0 +1,185 @@
+$VER OpenBOOPSI Project Style Guide 1.1 (4.5.99)
+
+
+                         OpenBOOPSI Project Style Guide
+
+----
+
+
+0. SUMMARY
+
+    1. Introduction
+    2. Comments
+        2.1 General Rules
+        2.2 Language
+        2.3 Single line comments
+        2.4 Multi line comments
+    3. Blank Spaces
+        3.1 Tabs
+        3.2 Spaces
+        3.3 Empty lines
+    4. Naming Conventions
+        4.1 General Rules
+        4.2 Functions
+        4.3 Variables
+
+
+1. INTRODUCTION
+
+    This is a brief guide on recommended source code formatting style
+    for the OpenBOOPSI Project classes. Every source file added to this
+    project should conform as close as possible to the rules given in
+    this document to mantain consistency within the source tree.
+
+    It might happen that you're already used to a different coding
+    style. Yes, we all understand well that changing your style can be
+    frustrating for any programmer. But the need to keep the source
+    code style consistent is more important than each one's habits.
+    No one will blame you if you don't strictly follow these
+    guidelines, but we will be glad if you do.
+
+
+2. COMMENTS
+
+    2.1 GENERAL RULES
+
+        Comment as much as you can. Other programmers will read your
+        sources and since most of them will have different knowledge of
+        Amiga programming and/or different ways to do a certain thing they
+        may not understand the purpose or the inner working of some of your
+        code, so try to explain what you are doing. Obviously avoid comments
+        such as "now open a window" right above a OpenWindow() function call.
+
+    2.2 LANGUAGE
+
+        Comments must be written in english.
+
+    2.3 SINGLE LINE COMMENTS
+
+        Single line comments should follow the ANSI C syntax, i.e.
+        using the "/* */" construct. C++ comments must not be used
+        because not all C compilers do support them.
+
+    2.4 MULTI LINE COMMENTS
+
+        Comments spanning over multiple lines should be formatted this way:
+
+        /* This is a very very very
+         * very very long comment!
+         */
+
+
+3. BLANK SPACES
+
+    3.1 TABS
+
+        Tabs are four spaces wide.
+
+    3.2 SPACES
+
+        There should be a space after commas.
+
+        There should never be a space after a * when it's used with pointers,
+        e.g.:
+
+        ULONG *pointer = NULL;
+        *pointer = 45 * y;
+
+        There should be a blank space around operators, e.g.:
+
+            var1 + var2;
+            var1 & var2;
+            etc.
+
+        the only exceptions are prefix and postfix ++ and -- operators,
+        i.e.:
+
+            var--;
+            ++var;
+
+        Before a parenthesis there should never be blank spaces if
+        it follow a keyword or a function name. e.g.
+
+            if()              /* good */
+            DoMethod();       /* also good */
+            while ()          /* wrong! */
+            yourfunction ();  /* also wrong! */
+
+    3.3 EMPTY LINES
+
+        After the #include block and after the #define one there should be
+        two empty lines.
+
+        Between the declaration of the global variables and the beginning of
+        the code there should be two empty lines.
+
+        Between the end of a function and the next one there should be three
+        empty lines.
+
+        Any code block enclosed in braces should be preceded by an empty line.
+        An open brace should be on a line by itself. After a closing brace there
+        should be one empty line, except when another closing brace follows. e.g.
+
+            if(z == 1)
+            {
+                z++;
+            }
+
+            y += z + 3;
+
+            if(y > 8)
+            {
+                f = do_some_stuff();
+
+                if(f == TRUE)
+                {
+                    printf("ok!\n");
+                }
+            }
+
+            /* the following is wrong! */
+
+            if(y==1) {
+                z++;
+            }
+            y+=z +3;
+            if (y >8)
+            { etc. }
+
+
+4. NAMING CONVENTIONS
+
+    4.3 GENERAL RULES
+
+        Everything related to the classes (methods, functions, etc.) should
+        have a prefix (two or three letter maximum) that recalls the name of
+        the class. i.e. if your class is called "BananaSplit" its methods
+        should be called something like BSM_SHAKE, its attributes should look
+        like BSA_SugarSpuns, etc.
+
+    4.2 FUNCTIONS
+
+        Method functions should obviously follow the general rule and have
+        the above mentioned prefix, e.g.:
+
+        BS_GoActive();
+
+        Function names should have the first letters of each word
+        forming their names capitalized, like system's one. e.g.:
+
+        MyWonderfulFunction()
+
+    4.3 VARIABLES
+
+        Variables name must be in english and must have a meaning! Please
+        avoid names such as "foobar" or "dummy"! We hate them!
+        Some examples:
+
+        struct Window *win;       /* these are good */
+        ULONG  result;
+
+        struct BitMap *dummy1;    /* these are wrong! */
+        struct RastPort *dummy2;
+
+        Names of local variables should be all in lowercase. Global
+        variables should have their initials uppercase.
diff --git a/TODO b/TODO
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/classes/ExtRequesterClass/Makefile b/classes/ExtRequesterClass/Makefile
new file mode 100644 (file)
index 0000000..92449a0
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# $Id: Makefile,v 1.1 2000/01/12 20:40:56 bernie Exp $
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(TOP)/config.mk
+
+ARG_COMMON :=
+ARG_ALL := $(ARG_COMMON)
+ARG_LIB := $(ARG_COMMON)
+ARG_DEBUG := $(ARG_COMMON)
+ARG_PRIVATE := $(ARG_COMMON)
+ARG_OBJ := $(ARG_COMMON)
+
+DEP_COMMON :=
+DEP_ALL := $(DEP_COMMON)
+DEP_LIB := $(DEP_COMMON)
+DEP_DEBUG := $(DEP_COMMON)
+DEP_PRIVATE := $(DEP_COMMON)
+DEP_OBJ := $(DEP_COMMON)
+
+include $(TOP)/common/general.mk
diff --git a/classes/Makefile b/classes/Makefile
new file mode 100644 (file)
index 0000000..54b2e11
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# $Id: Makefile,v 1.1 2000/01/12 20:40:06 bernie Exp $
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+SUBDIRS := ExtRequesterClass
+
+include $(TOP)/common/general.mk
diff --git a/common/ClassLib.s b/common/ClassLib.s
new file mode 100755 (executable)
index 0000000..d9bc8c2
--- /dev/null
@@ -0,0 +1,298 @@
+******************************************************************************
+*
+* $VER: ClassLib.asm (5.9.97)
+*
+* Copyright (C) 1995,96,97 by Bernardo Innocenti
+*
+******************************************************************************
+*
+* This source is based on the RomTag.asm source I've found somewhere :-)
+*
+*
+       INCLUDE "exec/types.i"
+       INCLUDE "exec/macros.i"
+       INCLUDE "exec/libraries.i"
+       INCLUDE "exec/lists.i"
+       INCLUDE "exec/alerts.i"
+       INCLUDE "exec/initializers.i"
+       INCLUDE "exec/resident.i"
+       INCLUDE "exec/execbase.i"
+       INCLUDE "libraries/dos.i"
+
+       INCLUDE "exec/funcdef.i"
+       INCLUDE "exec/exec_lib.i"
+
+
+; BOOPSI class libraries should use this structure as the base for their
+; library data.  This allows developers to obtain the class pointer for
+; performing object-less inquiries.
+
+       STRUCTURE ClassBase,0
+       STRUCT   cl_Lib,LIB_SIZE        ; Embedded library
+       UWORD    cl_Pad                 ; Align the structure
+       APTR     cl_Class               ; Class pointer
+       APTR     cl_SegList             ; SegList pointer
+       LABEL    ClassLibrary_SIZEOF
+
+;---------------------------------------------------------------------------
+
+       XDEF    _LibFuncTable
+       XDEF    _LibDataTable
+
+       XREF    _LibName
+       XREF    _LibId
+       XREF    __UserLibInit
+       XREF    __UserLibCleanup
+
+       XREF    __GetEngine
+
+;---------------------------------------------------------------------------
+
+       SECTION Code
+
+; First executable location, must return an error to the caller
+
+       moveq   #-1,d0
+       rts
+
+;---------------------------------------------------------------------------
+
+_ROMTAG:
+       DC.W    RTC_MATCHWORD   ; UWORD RT_MATCHWORD
+       DC.L    _ROMTAG         ; APTR  RT_MATCHTAG
+       DC.L    _ENDCODE        ; APTR  RT_ENDSKIP
+       DC.B    RTF_AUTOINIT    ; UBYTE RT_FLAGS
+       DC.B    LIBVERSION      ; UBYTE RT_VERSION
+       DC.B    NT_LIBRARY      ; UBYTE RT_TYPE
+       DC.B    0               ; BYTE  RT_PRI  <--- WARNING: Using negative values here will cause trouble!
+       DC.L    _LibName        ; APTR  RT_NAME
+       DC.L    _LibId          ; APTR  RT_IDSTRING
+       DC.L    _LibInitTable   ; APTR  RT_INIT
+
+
+* The RomTag specified that we were RTF_AUTOINIT. This means that rt_Init
+* points to the table below. (Without RTF_AUTOINIT it would point to a
+* routine to run.)
+*
+* Our library base is a standard struct Library, followed by a WORD
+* pad, a pointer to the boopsi Class structure of the external
+* boopsi class and a pointer to our SegList.  The SegList pointer
+* will be returned by LibExpunge() in order to have our code UnloadSeg()'ed
+* The Class pointer will be initialized by UserLibInit().
+
+_LibInitTable:
+       dc.l    ClassLibrary_SIZEOF
+       dc.l    _LibFuncTable
+       dc.l    _LibDataTable
+       dc.l    _LibInit
+
+
+
+* Table of functions included in this library; the first 4 are the same
+* for any library and for internal Exec use only.
+
+
+_LibFuncTable:
+       dc.l    _LibOpen
+       dc.l    _LibClose
+       dc.l    _LibExpunge
+       dc.l    _LibExtFunc
+       dc.l    __GetEngine
+       dc.l    -1
+
+;V_DEF MACRO
+;      dc.w    \1 + (* - _LibFuncTable)
+;      ENDM
+;
+;_LibFuncTable:
+;      dc.w    -1              ; It's weird: the cool way didn't work for me :-(
+;      V_DEF   _LibOpen
+;      V_DEF   _LibClose
+;      V_DEF   _LibExpunge
+;      V_DEF   _LibExtFunc
+;      V_DEF   __GetEngine
+;      dc.w    -1
+
+
+
+_LibDataTable
+       INITBYTE        LN_TYPE,NT_LIBRARY
+       INITLONG        LN_NAME,_LibName
+       INITBYTE        LN_PRI,-5
+       INITBYTE        LIB_FLAGS,(LIBF_SUMUSED!LIBF_CHANGED)
+       INITWORD        LIB_VERSION,LIBVERSION
+       INITWORD        LIB_REVISION,LIBREVISION
+       INITLONG        LIB_IDSTRING,_LibId
+       dc.w            0
+
+
+       CNOP    0,4
+
+
+* The following function will be called at startup time.
+*
+* Inputs:
+*      LibPtr (d0) - Pointer to the library base, initialized due to the
+*                      specifications in DataTable
+*      SegList (a0) - BPTR to the segment list
+*      _SysBase (a6) - The usual ExecBase pointer
+*
+* Result:
+*      LibPtr, if all was okay and the library may be linked into the
+*      system library list. NULL otherwise.
+*
+_LibInit:
+       move.l  d0,a1
+       move.l  a0,cl_SegList(a1)               ; Save SegList
+
+; Check CPU for 68020 or better
+       IFD             _MC68020_
+       move.w  AttnFlags(a6),d1
+       btst.w  #AFB_68020,d1
+       beq.s   fail$
+       ENDC
+
+       move.l  a6,-(sp)                        ; Save SysBase
+       move.l  d0,a6                           ; Put our base in a6
+       jsr     __UserLibInit                   ; Call user init
+       move.l  a6,a1                           ; save our base to a1
+       move.l  (sp)+,a6                        ; Retrieve SysBase
+       tst.l   d0
+       beq.s   fail$
+       rts
+
+fail$
+       bsr     FreeBase                        ; Free library base
+       moveq   #0,d0
+       rts
+
+
+* The following functions are called from exec.library/OpenLibrary(),
+* exec.library/CloseLibrary() and exec.library/ExpungeLibrary(),
+* respectively. Exec passes our library base pointer in A6.
+*
+* Task switching will be turned off while these functions are being
+* executed, so they must be as short as possible.  As the data inside
+* the library base is protected with Forbid(), these functions must
+* not make calls which would explicitly or implicitly turn on multitasking.
+* This includes opening other disk based libraries.  The problem may be
+* overcame by protecting the library base with a SignalSemaphore.
+*
+
+
+* This function is called from exec.library/OpenLibrary().
+*
+* Inputs:
+*      LibPtr (a6) - Pointer to the library base
+*      Version (d0) - The suggested version number
+*
+* Result:
+*      LibPtr, if successful, NULL otherwise
+*
+
+_LibOpen:
+       addq.w  #1,LIB_OPENCNT(a6)
+       bclr.b  #LIBB_DELEXP,LIB_FLAGS(a6)      ; Prevent delayed expunge
+       move.l  a6,d0
+       rts
+
+
+
+* This function is called from exec/CloseLibrary().
+*
+* Inputs:
+*      LibPtr (A6) - pointer to the library base as returned from OpenLibrary().
+*
+* Result:
+*      Segment list of the library (see arguments of _LibInit), if there
+*      was a delayed expunge and the library is no longer open, NULL
+*      otherwise.
+*
+_LibClose:
+       subq.w  #1,LIB_OPENCNT(a6)
+       tst.w   LIB_OPENCNT(a6)
+       bne.s   .NoExpunge
+       btst.b  #LIBB_DELEXP,LIB_FLAGS(a6)
+       beq.s   .NoExpunge
+
+       bra.s   _LibExpunge
+
+.NoExpunge
+       moveq.l #0,d0
+       rts
+
+
+
+* This function is called from exec.library/RemoveLibrary().
+*
+* Inputs:
+*      LibPtr (A6) - pointer to the library base.
+*
+* Result:
+*      Segment list of the library (see arguments of _LibInit()),
+*      if the library isn't opened currently, NULL otherwise.
+*
+
+_LibExpunge:
+
+       ; Flag library base for delayed expunge
+       bset.b  #LIBB_DELEXP,LIB_FLAGS(a6)
+       tst.w   LIB_OPENCNT(a6)         ; Only expunge if OpenCnt == 0
+       bne.s   .DoNotExpunge
+
+.NotOpen
+
+       jsr     __UserLibCleanup        ; Call user cleanup code
+       tst.l   d0
+       beq.s   .DoNotExpunge
+
+       move.l  cl_SegList(a6),-(sp)    ; Save SegList pointer
+
+       move.l  a6,a1
+       REMOVE                          ; Remove us from Exec library list.
+
+
+; Free the library base
+
+       move.l  a6,a1                   ; LibBase
+       move.l  a6,-(sp)                ; Save A6
+       move.l  4.w,a6                  ; Load SysBase
+       bsr             FreeBase                ; Free our library base
+       move.l  (sp)+,a6                ; Restore A6
+
+       move.l  (sp)+,d0                ; Return our SegList
+       rts
+
+.DoNotExpunge
+
+; NOTE: I'm falling in _LibExtFunc from here!
+
+
+
+* Dummy function to return 0
+
+_LibExtFunc:
+       moveq   #0,d0
+       rts
+
+
+* Frees our library base
+*
+* Inputs:
+*      LibBase (a1) - Pointer to Library structure.
+*      SysBase (a6) - Pointer to SysBase
+*
+FreeBase:
+       moveq.l #0,d0
+       move.l  a1,a0
+       move.w  LIB_NEGSIZE(a0),d0
+       suba.l  d0,a1                   ; Get pointer to real start of library base
+       add.w   LIB_POSSIZE(a0),d0      ; Total library size (LIB_POSSIZE + LIB_NEGSIZE)
+       jsr             _LVOFreeMem(a6)
+       rts
+
+;-----------------------------------------------------------------------
+
+_ENDCODE
+
+       END
diff --git a/common/GetGadgetBox.c b/common/GetGadgetBox.c
new file mode 100644 (file)
index 0000000..e9192f6
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+**     $Id:$
+**
+**     Copyright (C) 1999 Bernardo Innocenti
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     GetGadgetBox() computes the actual IBox where a gadget exists in a window.
+**     The special cases it handles are all the REL#? (relative positioning flags).
+**
+**     This function returns the gadget size in the provided
+**     IBox structure, computing the values from the coordinates
+**     in the gadget structure and the container (window or requester)
+**     where it lives.
+*/
+
+#include <intuition/intuition.h>
+
+#include <CompilerSpecific.h>
+#include <DebugMacros.h>
+#include <BoopsiLib.h>
+
+
+void GetGadgetBox(struct GadgetInfo *ginfo, struct ExtGadget *g, struct IBox *box)
+{
+       ASSERT_VALID_PTR(g)
+       ASSERT_VALID_PTR(ginfo)
+       ASSERT_VALID_PTR(box)
+
+       DB2(if (g->Flags & GFLG_EXTENDED)
+               DBPRINTF("GetGadgetBox(): GFLG_EXTENDED is set\n");)
+       DB2(if ((g->Flags & GFLG_EXTENDED) && (g->MoreFlags & GMORE_BOUNDS))
+               DBPRINTF("GetGadgetBox(): Gadget has valid bounds\n");)
+
+
+       box->Left = g->LeftEdge;
+       if (g->Flags & GFLG_RELRIGHT)
+               box->Left += ginfo->gi_Domain.Width - 1;
+
+       box->Top = g->TopEdge;
+       if (g->Flags & GFLG_RELBOTTOM)
+               box->Top += ginfo->gi_Domain.Height - 1;
+
+       box->Width = g->Width;
+       if (g->Flags & GFLG_RELWIDTH)
+               box->Width += ginfo->gi_Domain.Width;
+
+       box->Height = g->Height;
+       if (g->Flags & GFLG_RELHEIGHT)
+               box->Height += ginfo->gi_Domain.Height;
+
+       DB2(DBPRINTF("GetGadgetBox(): Left = %ld, Top = %ld, Width = %ld, Height = %ld\n",
+               box->Left, box->Top, box->Width, box->Height);)
+}
+
+
+
+/* Useful macro missing in <intuition/imageclass.h> */
+#define GADGET_BOUNDS(g) ((struct IBox *)&((struct ExtGadget *)(g))->BoundsLeftEdge)
+
+
+void GetGadgetBounds(struct GadgetInfo *ginfo, struct ExtGadget *g, struct IBox *bounds)
+{
+       struct IBox *box;
+
+       ASSERT_VALID_PTR(g)
+       ASSERT_VALID_PTR(ginfo)
+       ASSERT_VALID_PTR(bounds)
+
+
+       box = ((g->Flags & GFLG_EXTENDED) && (g->MoreFlags & GMORE_BOUNDS)) ?
+               GADGET_BOUNDS(g) : GADGET_BOX(g);
+
+       memcpy(bounds, box, sizeof(struct IBox));
+
+       if (g->Flags & GFLG_RELRIGHT)
+               bounds->Left += ginfo->gi_Domain.Width - 1;
+
+       if (g->Flags & GFLG_RELBOTTOM)
+               bounds->Top += ginfo->gi_Domain.Height - 1;
+
+       if (g->Flags & GFLG_RELWIDTH)
+               bounds->Width += ginfo->gi_Domain.Width;
+
+       if (g->Flags & GFLG_RELHEIGHT)
+               bounds->Height += ginfo->gi_Domain.Height;
+}
diff --git a/common/Makefile b/common/Makefile
new file mode 100644 (file)
index 0000000..8e6fbd6
--- /dev/null
@@ -0,0 +1,90 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(TOP)/config.mk
+
+COMMON_OBJS = GetGadgetBox.o
+
+all: $(GST) $(APP_STARTUP) $(COMMON_OBJS)
+
+help-all:
+       @echo "This target compile the custom startup code and place it"
+       @echo "in the obj/ directory, create the GST (Global Symbol Table)"
+       @echo "for SAS/C users."
+       @echo
+
+lib:
+       $(NOP)
+
+help-lib:
+       @echo "This target does nothing."; echo
+
+debug:
+       $(NOP)
+
+help-debug:
+       @echo "This target does nothing."; echo
+
+private:
+       $(NOP)
+
+help-private:
+       @echo "This target does nothing."; echo
+
+obj: $(APP_STARTUP)
+
+help-obj:
+       @echo "This target compile the custom startup code and place it"
+       @echo "in the obj/ directory."
+       @echo
+
+clean:
+       $(RM) $(APP_STARTUP) $(GST)
+
+help-clean:
+       @echo "This target deletes the custom startup code object and the GST."
+       @echo
+
+install:
+       $(NOP)
+
+help-install:
+       @echo "This target does nothing."; echo
+
+
+###########################################################
+# Compile custom startup code for applications
+###########################################################
+
+$(APP_STARTUP): $(APP_STARTUP_SRC)
+       $(AS) $< $(TO) $@
+
+###########################################################
+# Compile common objects
+###########################################################
+
+$(COMMON_OBJS): %.o : %.c
+       $(CC) $< $(TO) $@ $(O_CFLAGS)
+
+
+###########################################################
+# Make Global Symbol Table to speed up compiling
+###########################################################
+#
+# We must define some symbols here because defining them
+# inside GST.c won't work as expected. (SAS/C bug?)
+#
+# NOTE:        The GST file does not depend on any headers because
+#      otherwise all objects would be remade each time you edit
+#      one of the header files.
+#
+
+$(GST): GST.c
+       ifeq ($(strip $(COMPILER)),sc)
+               $(CC) FROM gst.c MAKEGST $(GST) NOOBJNAME $(O_CFLAGS) \
+                DEF=INTUI_V36_NAMES_ONLY DEF=__USE_SYSBASE \
+                DEF=CLIB_ALIB_PROTOS_H
+       endif
diff --git a/common/OpenClass.c b/common/OpenClass.c
new file mode 100644 (file)
index 0000000..305f498
--- /dev/null
@@ -0,0 +1,44 @@
+struct ClassLibrary *OpenClass(CONST_STRPTR name, CONST_STRPTR prefix, ULONG version)
+
+/* Open named class. Look both in current and images/ directory
+ */
+{
+       static struct EasyStruct OpenClassES =
+       {
+               sizeof(struct EasyStruct),
+               0,
+               versiontag + 6,
+               "Couldn't open %s version %ld or greater",
+               "Ok"
+       };
+
+       struct ClassLibrary *classbase;
+       char buf[256];
+       int i;
+
+
+       if (!(classbase = (struct ClassLibrary *)OpenLibrary(name, version)))
+       {
+               /* We can't use AddPart() here because we didn't open dos.library */
+
+               /* Copy the prefix in the buffer */
+               for (i = 0; buf[i] = prefix[i]; i++);
+
+               /* Insert trailing character if missing */
+               if(buf[i] != '/')
+                       buf[++i] = '/';
+
+               /* Append the name */
+               while (buf[i++] = *name++);
+
+               /* Try again */
+               classbase = (struct ClassLibrary *)OpenLibrary(buf, version);
+
+               if (!classbase)
+               {
+                       /* Report an error */
+                       EasyRequest(NULL, &OpenClassES, NULL, buf, version);
+               }
+       }
+       return classbase;
+}
diff --git a/common/general.mk b/common/general.mk
new file mode 100644 (file)
index 0000000..edf4ea9
--- /dev/null
@@ -0,0 +1,277 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+# This makefile is flexible enough to be used for every
+# class of the OpenBoopsi project. You should not need to
+# modify anything
+#
+# all: create the demo program and the class library
+#      with no debugging information and code
+#
+# lib: create just the library of the public class
+#      with no debugging information and code
+#
+# private: create the demo program linked with optimized version of the class
+#
+# debug: create the demo program linked with debug version of the class
+#
+# obj: create just the class object ready to be linked
+#      to a program, with no debugging information and code
+#
+# install: copy the demos and classes to the appropriate
+#      directories
+#
+
+###########################################################
+# some variables...
+#
+BOOPSI_DEPS    := $(INCDIR)/BoopsiStubs.h $(INCDIR)/CompilerSpecific.h $(INCDIR)/DebugMacros.h
+CLASSOBJ_SHARED        := $(subst .c,_shared.o,$(CLASSSRC))
+CLASSOBJ_STATIC        := $(subst .c,_static.o,$(CLASSSRC))
+CLASSOBJ_DEBUG := $(subst .c,_dbg.o,$(CLASSSRC))
+CLASSINC       := $(subst .c,.h,$(CLASSRC))
+DEMOOBJ_STATIC := $(subst .c,_static.o,$(DEMOSRC))
+DEMOOBJ_SHARED := $(subst .c,_shared.o,$(DEMOSRC))
+DEMOOBJ_DEBUG  := $(subst .c,_dbg.o,$(DEMOSRC))
+
+# Provide a default name for the demo program
+ifeq ($(strip $(DEMOPROG)),)
+       ifneq ($(strip $(DEMOSRC)),)
+               DEMOPROG := $(subst .c,,$(DEMOSRC))
+       endif
+endif
+
+# Generate the name of the debug demo
+ifneq ($(strip $(DEMOPROG)),)
+       DEMOPROG_DEBUG := $(DEMOPROG)_debug
+endif
+
+###########################################################
+# additional compiler flags
+#
+ifeq ($(strip $(COMPILER)),gcc)
+       LIB_CFLAGS := -DDATE="\"$(CLASSDATE)"\" -DNAME="\"$(CLASSLIB)"\" \
+                       -DVERSION="\"$(CLASSVER).$(CLASSREV)"\"
+else
+       LIB_CFLAGS := $(DEF) DATE=$(CLASSDATE) $(DEF) NAME="$(CLASSLIB)" \
+                       $(DEF) VERSION="$(CLASSVER).$(CLASSREV)"
+endif
+
+O_CFLAGS += $(LIB_CFLAGS)
+D_CFLAGS += $(LIB_CFLAGS)
+
+
+###########################################################
+# additional assembler flags
+# do not modify the spaces in the lines below!
+#
+O_SFLAGS += SET "LIBVERSION=$(CLASSVER),LIBREVISION=$(CLASSREV) "
+D_SFLAGS += SET "LIBVERSION=$(CLASSVER),LIBREVISION=$(CLASSREV) "
+
+
+###########################################################
+# Main targets
+###########################################################
+#
+
+all: $(DEMOPROG) $(CLASSLIB)
+ifneq ($(strip $(SUBDIRS)),)
+       for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) ; done
+endif
+
+help-all:
+       @echo "This target will build all the classes and demo programs."; echo
+
+
+lib: $(CLASSLIB)
+ifneq ($(strip $(SUBDIRS)),)
+       for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) lib ; done
+endif
+
+help-lib:
+       @echo "This target will build all the classes (but not the demo programs)."; echo
+
+
+obj: $(CLASSOBJ_STATIC)
+ifneq ($(strip $(SUBDIRS)),)
+       for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) obj ; done
+endif
+
+help-obj:
+       @echo "This target create the classes object ready to be linked as a static"
+       @echo "library, with no debugging code."; echo
+
+
+private: $(DEMOPROG)
+ifneq ($(strip $(SUBDIRS)),)
+       for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) private ; done
+endif
+
+help-private:
+       @echo "This target will build all the demo programs with the classes linked"
+       @echo "as static libraries. No debug code and symbols are added."
+       @echo
+       @echo "This may be useful to let other users test new versions of the classes"
+       @echo "without the need to install them or without overwriting old versions"
+       @echo "that may have been installed."; echo
+
+
+debug: $(DEMOPROG_DEBUG)
+ifneq ($(strip $(SUBDIRS)),)
+       for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) debug ; done
+endif
+
+help-debug:
+       @echo "This target will build all the demo programs with the classes linked"
+       @echo "as static libraries. Debug code and symbols are added."; echo
+
+
+install:
+ifneq ($(strip $(SUBDIRS)),)
+       for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) install ; done
+endif
+ifneq ($(strip $(DEMOPROG)),)
+       $(CP) $(DEMOPROG) $(PREFIX)/demos/
+endif
+ifneq ($(strip $(CLASSLIB)),)
+       $(CP) $(CLASSLIB) $(PREFIX)/classes/$(INSTALLDIR)/
+endif
+
+help-install:
+       @echo "This target copy all the classes and the demos in the dist/ directory,"
+       @echo "placing the classes in the correct subdirectories."; echo
+
+
+clean:
+ifneq ($(strip $(SUBDIRS)),)
+       for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) clean ; done
+endif
+       $(RM) $(DEMOPROG) $(CLASSLIB) $(CLASSOBJ_STATIC)
+
+help-clean:
+       @echo "This target delete all the demoprograms, all the classes and all"
+       @echo "the objects in the sources subdirectories."; echo
+
+
+help:
+       @echo "Type 'make help-(targetname) (e.g. 'make help-all') to get"
+       @echo "a detailed help for each target"; echo
+       @echo "Current package configuration:"
+       @echo "------------------------------"
+       @echo "Defined targets: all; lib; debug; private; obj; install; clean; setup;"
+       @echo "Defined subdirs: $(patsubst %,%;,$(SUBDIRS))"; echo
+       @echo "Your OpenBoopsi root directory: $(TOP)."; echo
+       @echo "Configured compiler: $(COMPILER)."
+       @echo "Configured cpu: $(CPU)."
+ifeq ($(strip $(NOSTDLIB)),0)
+       @echo "Configured demo linking method: standard startup code."
+else
+       @echo "Configured demo linking method: custom startup code."
+endif
+       @echo; echo "Happy compiling!"; echo
+
+
+###########################################################
+# build the class library
+###########################################################
+#
+$(CLASSLIB): ClassLib.o $(CLASSOBJ_SHARED) $(CLASSOBJ)
+       @$(ECHO) "Building class library..."
+       $(LDNOLIB) ClassLib.o $(CLASSOBJ_SHARED) $(CLASSOBJ) $(TO) $@ $(O_LFLAGS) $(ARG_LIB)
+       $(FLUSHLIBS)
+
+
+###########################################################
+# compile class source
+###########################################################
+#
+
+# All objects depend on their headers
+$(CLASSOBJ_SHARED) $(CLASSOBJ_STATIC) $(CLASSOBJ_DEBUG): $(CLASSINC) $(BOOPSI_DEPS)
+
+$(CLASSOBJ_SHARED): %_shared.o : %.c
+       $(CC) $< $(TO) $@ $(O_CFLAGS) -DCLASS_FLAVOUR=3
+
+$(CLASSOBJ_STATIC): %_static.o : %.c
+       $(CC) $< $(TO) $@ $(O_CFLAGS) -DCLASS_FLAVOUR=0
+
+$(CLASSOBJ_DEBUG): %_dbg.o : %.c
+       $(CC) $< $(TO) $@ $(D_CFLAGS) -DCLASS_FLAVOUR=0
+
+###########################################################
+# assemble the class library init code
+###########################################################
+#
+# All this mess is required since PhxAss can't handle
+# UNIX paths. It would also be possible to link this
+# object without converting it, but it seems that
+# this leads to a bigger executable...
+#
+ClassLib.o: $(TOP)/common/ClassLib.s Makefile
+ifeq ($(strip $(COMPILER)),gcc)
+       $(CP) $< /t
+       $(ASM) T:ClassLib.s TO T:temp.o $(O_SFLAGS)
+       $(HUNK2AOUT) /t/temp.o >NIL:
+       $(REN) obj.* $@
+       $(RM) /t/ClassLib.s /t/temp.o
+else
+       $(ASM) $< $(TO) $@ $(O_SFLAGS)
+endif
+
+
+###########################################################
+# build the demo program
+###########################################################
+#
+ifneq ($(strip $(DEMOPROG)),)
+
+$(DEMOPROG): $(DEMOOBJ_STATIC) $(DEMOOBJ) $(CLASSOBJ_STATIC) $(CLASSOBJ)
+       @$(ECHO) "Linking demo..."
+ifeq ($(strip $(NOSTDLIB)),0)
+       $(LD) $(TO) $@ $(DEMOOBJ_STATIC) $(DEMOOBJ) $(CLASSOBJ_STATIC) $(CLASSOBJ) $(O_LIBS) $(O_LFLAGS)
+else
+       $(LDNOLIB) $(TO) $@ $(APP_STARTUP) $(DEMOOBJ_STATIC) $(DEMOOBJ) $(CLASSOBJ_STATIC) $(CLASSOBJ) $(O_LIBS) $(O_LFLAGS)
+endif
+
+$(DEMOPROG_DEBUG): $(DEMOOBJ_DEBUG) $(DEMOOBJ) $(CLASSOBJ_DEBUG) $(CLASSOBJ)
+ifeq ($(strip $(NOSTDLIB)),0)
+       $(CC) $(TO) $@ $(DEMOOBJ_DEBUG) $(DEMOOBJ) $(CLASSOBJ_DEBUG) $(CLASSOBJ) $(D_LIBS) $(D_LFLAGS)
+else
+       $(LDNOLIB) $(TO) $@ $(APP_STARTUP) $(DEMOOBJ_DEBUG) $(DEMOOBJ) $(CLASSOBJ_DEBUG) $(CLASSOBJ) $(D_LIBS) $(D_LFLAGS)
+endif
+
+endif
+
+
+###########################################################
+# compile demo source
+###########################################################
+#
+
+# All objects depend on their headers
+$(DEMOOBJ_SHARED) $(DEMOOBJ_DEBUG) $(DEMOOBJ_STATIC): $(CLASSINC)
+
+$(DEMOOBJ_SHARED): %_shared.o : %.c
+       $(CC) $< $(TO) $@ $(O_CFLAGS) -DCLASS_FLAVOUR=3
+
+$(DEMOOBJ_STATIC): %_static.o : %.c
+       $(CC) $< $(TO) $@ $(O_CFLAGS) -DCLASS_FLAVOUR=0
+
+$(DEMOOBJ_DEBUG): %_dbg.o : %.c
+       $(CC) $< $(TO) $@ $(D_CFLAGS) -DCLASS_FLAVOUR=0
+
+
+###########################################################
+# GNU make quirks
+###########################################################
+
+# disable all implicit rules for suffixes known to GNU make such as .c and .o
+.SUFFIXES:
+
+# Explicitly declare standard targets as phony
+.PHONY: all lib debug private obj install clean help \
+       help-all help-lib help-debug help-private help-obj \
+       help-install help-clean
diff --git a/common/gst.c b/common/gst.c
new file mode 100644 (file)
index 0000000..ba73e8f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+**     $Id:$
+**
+**     Copyright (C) 1997,99 by Bernardo Innocenti
+**
+**     This is a dummy source file used to make the Global Symbol Table
+**     for the boopsi classes.
+*/
+
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <exec/execbase.h>
+#include <dos/dos.h>
+#include <graphics/gfxbase.h>
+#include <intuition/intuition.h>
+#include <intuition/intuitionbase.h>
+#include <intuition/screens.h>
+#include <intuition/classes.h>
+#include <intuition/classusr.h>
+#include <intuition/gadgetclass.h>
+#include <intuition/imageclass.h>
+#include <intuition/icclass.h>
+#include <graphics/gfxbase.h>
+#include <graphics/gfxmacros.h>
+#include <utility/tagitem.h>
+
+#include <proto/dos.h>
+#include <proto/exec.h>
+#include <proto/graphics.h>
+#include <proto/intuition.h>
+#include <proto/layers.h>
+#include <proto/utility.h>
+#include <clib/alib_stdio_protos.h>
+
+#include "CompilerSpecific.h"
+#include "DebugMacros.h"
+
+/* Can't include these in GST because they define some inline stuff
+ *
+ * #include "BoopsiStubs.h"
+ * #include "ListMacros.h"
+ */
+
+/* Can't include these because otherwise the GST would need to be
+ * remade each time you edit one of the headers.
+ *
+ * #define LV_GADTOOLS_STUFF
+ * #include "ScrollButtonClass.h"
+ * #include "ListViewClass.h"
+ * #include "VectorGlyphIClass.h"
+ * #include "ListBoxClass.h"
+ */
diff --git a/common/startup_gcc.s b/common/startup_gcc.s
new file mode 100644 (file)
index 0000000..ca4a05d
--- /dev/null
@@ -0,0 +1,2 @@
+.text
+       jmp     __main
diff --git a/common/startup_sc.s b/common/startup_sc.s
new file mode 100644 (file)
index 0000000..a37c6b0
--- /dev/null
@@ -0,0 +1,9 @@
+
+       XREF @_main
+
+       SECTION CODE,code
+
+_start:
+       jmp     @_main
+
+       END
diff --git a/common/startup_storm.s b/common/startup_storm.s
new file mode 100644 (file)
index 0000000..912a205
--- /dev/null
@@ -0,0 +1,9 @@
+
+       XREF __main
+
+       SECTION CODE,code
+
+_start:
+       bra     __main
+
+       END
diff --git a/config.mk b/config.mk
new file mode 100644 (file)
index 0000000..6156aa7
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,214 @@
+##
+## $Id: config.mk,v 1.1 2000/01/12 20:34:26 bernie Exp $
+##
+## Build environment configuration parameters
+## Copyright (C) 1999 by B. Innocenti & M. Cavalleri
+
+
+###########################################################
+# Package configuration
+###########################################################
+
+# CPU to compile for (eg: "68020").
+#
+CPU := 68020
+
+# Compiler to use. Possible options are:
+# sc     - SAS/C 6.58 or better
+# gcc    - gcc 2.7.2 or EGCS 1.1b
+# vbcc   - Not yet supported
+# stormc - Not yet supported
+#
+COMPILER := gcc
+
+# Additional include directories (e.g.: system headers)
+#
+C_INCLUDE_PATH := -I/gg/include -I/include
+
+# compiling options: set this variable to
+# 0 to link the demo programs with the standard
+# startup libraries, se to other values to
+# link to obj/app_startup.o
+#
+NOSTDLIB := 0
+
+
+###########################################################
+# Tools used in the Makefiles
+###########################################################
+
+NOP                    := echo
+ECHO           := echo
+FLUSHLIBS      := Avail FLUSH >NIL:
+MAKEINFO       := GG:bin/makeinfo
+FD2PRAGMA      := fd2pragma
+HUNK2AOUT      := hunk2aout
+FLEXCAT                := FlexCat
+ARCHIVER       := LZX -3 -e -r a
+
+
+###########################################################
+# Compiler, linker and assembler flags
+###########################################################
+
+# Flags for SAS/C
+#
+ifeq ($(strip $(COMPILER)),sc)
+
+       APP_STARTUP_SRC := $(TOP)/common/startup_sc.s
+
+       CC      := sc
+       AS      := PhxAss
+       ASM     := $(AS)
+       LD      := PhxLnk
+       LDNOLIB := PhxLnk
+       CP      := copy CLONE
+       REN := rename
+       RM      := delete
+
+       # GST usage must sometimes be disabled due to bugs in SAS/C 6.58
+       GST     := $(OBJDIR)/$(PROJNAME).gst
+
+       # Note: Using the "STRCONST" compiler option requires
+       #       patched versions of the OS headers to work correctly
+
+       # compiler flags
+       #
+       OPT_CFLAGS := OPTIMIZE OPTTIME OPTSCHEDULER OPTINLINELOCAL \
+                               OPTRDEPTH=4 OPTDEPTH=4 OPTCOMP=8 DATA=NEAR CODE=NEAR
+       DBG_CFLAGS := NOOPTIMIZE DEBUG=FULLFLUSH ONERROR=CONTINUE CODE=FAR \
+                               DATA=FAR DEF DEBUG=1
+       CMN_CFLAGS := PARAMS=REGISTERS STRMERGE AFP UTILLIB INCDIR=$(INCDIR) \
+                               NOSTKCHK NOCHKABORT NOICONS STRSECT=CODE GST $(GST) CPU=$(CPU)
+
+       # assembler flags
+       #
+       OPT_SFLAGS := SMALLDATA SMALLCODE ALIGN MACHINE=$(CPU) OPT !
+       DBG_SFLAGS := SYMDEBUG LINEDEBUG SET "_DEBUG=1"
+       CMN_SFLAGS := INCPATH=INCLUDE:,$(INCDIR) NOEXE QUIET
+
+       # linker flags
+       #
+       # Use the utility.library for 32bit multiplication and division.
+       #
+       # The C runtime library is never used but it's still needed because
+       # SAS/C sometimes generates code that referencess symbols such as
+       # _CXAMEMSET or _CXAMEMCPY
+       #
+       OPT_LFLAGS := NODEBUG
+       DBG_LFLAGS := NOSHORTRELOCS ADDSYM
+       CMN_LFLAGS := SMALLCODE SMALLDATA NOALVS NOICONS BATCH DEFINE \
+                               "__CXM33=__UCXM33,__CXD33=__UCXD33,__CXM22=__UCXM22,__CXD22=__UCXD22"
+
+       OPT_LIBS   :=
+       DBG_LIBS   := LIB:debug.lib LIB:small.lib
+       CMN_LIBS   := LIB:sc.lib
+
+       # misc flags
+       #
+       TO  := TO
+       OBJ := NOLINK
+       DEF := DEFINE
+
+       # Additional flags for SAS/C GST support
+       #
+       ifneq ($(strip $(GST)),)
+               CMN_CFLAGS += GST=$(GST)
+       endif
+endif
+
+#
+# Flags for gcc or egcs
+#
+ifeq ($(strip $(COMPILER)),gcc)
+
+       APP_STARTUP_SRC := $(TOP)/common/startup_gcc.s
+
+       CC      := gcc -c
+       AS      := as
+       ASM     := PhxAss
+       LD      := gcc -noixemul
+       LDNOLIB := gcc -nostartfiles -noixemul
+       CP      := cp
+       MV  := mv
+       REN := $(MV)
+       RM      := rm
+
+       # compiler flags
+       #
+       # if you have some custom include directory we suggest you to
+       # use the variable C_INCLUDE_PATH instead of adding it to
+       # the directories list below via tha argument -I
+       #
+       OPT_CFLAGS := -O2 -msmall-code -fomit-frame-pointer -mregparm -funroll-loops \
+                               -finline-functions -fno-implement-inlines
+       DBG_CFLAGS := -D_DEBUG=1 -g
+       CMN_CFLAGS := -m$(CPU) -Wundef -Wimplicit -Winline -Wreturn-type \
+                               -I$(TOP)/include/ $(C_INCLUDE_PATH)
+
+       # assembler flags (for PhxAss, not as. these are needed
+       # to compile the library startup code).
+       #
+       OPT_SFLAGS := SMALLDATA SMALLCODE ALIGN MACHINE=$(CPU) OPT !
+       DBG_SFLAGS := SYMDEBUG LINEDEBUG SET "DEBUG"
+       CMN_SFLAGS := INCPATH=INCLUDE:,$(INCDIR) NOEXE QUIET
+
+       # linker flags
+       #
+       OPT_LFLAGS := -s
+       DBG_LFLAGS :=
+       CMN_LFLAGS :=
+
+       OPT_LIBS   :=
+       DBG_LIBS   := -lamiga_debug
+       CMN_LIBS   :=
+
+       # misc flags
+       #
+       TO  := -o
+       OBJ := -c
+       DEF := -D
+endif
+
+
+
+###########################################################
+###########################################################
+# You shouldn't need to modify anything below this line
+###########################################################
+###########################################################
+
+
+
+# distribution version is compiled with these flags
+#
+O_CFLAGS := $(CMN_CFLAGS) $(OPT_CFLAGS)
+O_SFLAGS := $(CMN_SFLAGS) $(OPT_SFLAGS)
+O_LFLAGS := $(CMN_LFLAGS) $(OPT_LFLAGS)
+O_LIBS   := $(CMN_LIBS) $(OPT_LIBS)
+
+
+# debug version is compiled with these flags
+#
+D_CFLAGS := $(CMN_CFLAGS) $(DBG_CFLAGS)
+D_SFLAGS := $(CMN_SFLAGS) $(DBG_SFLAGS)
+D_LFLAGS := $(CMN_LFLAGS) $(DBG_LFLAGS)
+D_LIBS   := $(CMN_LIBS) $(DBG_LIBS)
+
+
+###########################################################
+# Paths
+###########################################################
+
+OBJDIR         := $(TOP)/obj
+INCDIR         := $(TOP)/include
+PREFIX         := $(TOP)/dist
+
+PROJNAME       := OpenBoopsi
+ARCNAME                := $(PREFIX)/$(PROJNAME).lzx
+SRCARCNAME     := $(PREFIX)/$(PROJNAME)_src.lzx
+
+# APP_STARTUP_SRC is defined in the
+# compiler specific sections
+#
+APP_STARTUP    := $(OBJDIR)/app_startup.o
diff --git a/docs/ExtFrameIClass.doc b/docs/ExtFrameIClass.doc
new file mode 100644 (file)
index 0000000..76523fb
--- /dev/null
@@ -0,0 +1,96 @@
+TABLE OF CONTENTS
+
+extframe.image/extframe.image
+\fextframe.image/extframe.image           extframe.image/extframe.image
+
+    NAME
+        extframe.image -- extended frame BBOPSI image (V1)
+
+    FUNCTION
+        The extframe class is a complete replacement of the built in
+        frameiclass provided by Intuition. It can render itself using the
+        pens specified by the application, or can use the standard DrawInfo
+        pens (like the original frameiclass) when the needed pens have not
+        been supplied. It offers some new frame type, like the well known
+        XEN frame. It offers an improved configurability (quite every aspect
+        of the frame can be configured), an extended IM_FRAMEBOX method and
+        some OS3 specific optimizations.
+        It is made to be as fast as possible and offer the possibility to
+        programmers to add new frame types with little or no changes at all
+        at the GM_RENDER method.
+        This class is a subclass of the imageclass, and support all the
+        attributes of the frameiclass class (at least it should), so you
+        must read their doc to learn the supported tags and their meaning.
+        Here I will list only the class specific tags or methods.
+
+    METHODS
+        IM_FRAMEBOX -- Ask the frame information on its size according to
+            its content. It is identical to the frameiclass method, but
+            offers a new flag beside the standard FRAMEF_SPECIFY. If you
+            specify the new FRAMEF_QUERY flag, you supply the FrameBox
+            (instead of the ContentsBox) and the frame will fill the
+            ContentsBox with the appropriate size/position value taking
+            into consideration the frame thickness, the space between the
+            frame and its contents, etc.
+
+    TAGS
+
+        IA_FrameDistance -- Space between the frame and the gadget in pixel.
+            Negative values are allowed.
+
+            Applicability is (ISG)
+
+        IA_InnerDistance -- Space between the two 'side' of a frame. For
+            example a inner distance of 0 pixel will make a FRAME_ICONDROPBOX
+            frame look like a FRAME_RIDGE frame. Currently this tag has
+            effect only on the FRAME_ICONDROPBOX frame.
+
+            Applicability is (ISG)
+
+        IA_PenBackground -- Specify the background pen. Used only if
+            you did not specify the IA_EdgesOnly attribute. If this
+            tag is not specified or is set to -1 the standard BACKGROUNDPEN
+            pen will be used.
+
+            Applicability is (ISG)
+
+        IA_PenSelBackground -- Specify the pen used to fill the frame
+            when it's in the selected state. Ignored if the frame is a
+            IA_EdgesOnly one. If it is not specified or is set to -1
+            the FILLPEN pen will be used.
+
+            Applicability is (ISG)
+
+        IA_PenShine -- Specify the pen number used for the shine pen (i.e.
+            for raised borders). If it is not specified or set to -1 the
+            standard SHINEPEN will be used.
+
+            Applicability is (ISG)
+
+        IA_PenShadow -- Specify the pen number used for the shadow pen.
+            (i.e. for recessed borders). If it is not specified or set to -1
+            the standard SHADOWPEN will be used.
+
+            Applicability is (ISG)
+
+        IA_PenHalfShine -- Specify the halfshine pen. If it is not specified
+            or set to -1 the standard SHINEPEN will be used. It's usually a
+            bit darker than the shine pen and is commonly used in the xen
+            frame.
+
+            Applicability is (ISG)
+
+        IA_PenHalfShadow -- Specify the halfshadow pen. If it is not
+            specified or set to -1 the standard SHADOWPEN will be used. It's
+            usually a bit brighter than the shadow pen and is commonly used
+            for the xen frame.
+
+            Applicability is (ISG)
+
+    BUGS
+        The tags supported by the frameiclass are not very well documented,
+        so this class may not support all the needed tags.
+
+    SEE ALSO
+        The "Image Subclasses" chapter of the Intuition Reference Manual.
+
diff --git a/docs/Intuition b/docs/Intuition
new file mode 100644 (file)
index 0000000..db7096a
--- /dev/null
@@ -0,0 +1,523 @@
+
+INDICE
+
+Introduzione
+   Come si comporta Intuition
+   Come si comporta MUI
+
+Problemi
+   Problema n. 1 (input.device bloccato; Intuition)
+   Problema n. 2 (refresh della GUI bloccato; MUI)
+
+Ipotesi di soluzioni
+   Possibile soluzione per il problema n. 1 (sotto-task IDCMP in parallelo)
+   Possibile soluzione per il problema n. 2 (classe MUI con task asincrono)
+
+Considerazioni finali
+   Funzionamento seriale dell'input.device
+   Fattibilità di un patch per Intuition
+
+
+INTRODUZIONE
+
+Come si comporta Intuition
+--------------------------
+
+L'input dell'utente viene letto, comunicando direttamente con l'hardware,
+da keyboard.device e gameport.device, che lo trasmettono all'input.device.
+
+Quest'ultimo unisce le diverse informazioni sull'input in un unico stream
+(flusso) di "eventi di input", omogeneo e sequenziale, rappresentato con
+una lista di strutture InputEvent.
+
+L'input.device passa poi tale lista ad una serie di "input handler", secondo
+un ordine basato sulla loro priorità.
+
+Ciascun handler può intraprendere delle azioni in base al contenuto della
+lista ricevuta in ingresso; può inoltre apporre modifiche alla lista stessa
+aggiungendo, rimuovendo o alterando eventi. In uscita l'handler restituisce
+la lista modificata, la quale diventerà l'ingresso per l'handler successivo.
+
+Il codice di un handler viene eseguito come una normale chiamata a funzione:
+di conseguenza esso gira sempre nel contesto del task dell'input.device.
+
+Normalmente l'handler con priorità massima è quello della commodities.library
+(che quindi intercetta gli eventi prima di chiunque altro), tranne che nel
+caso in cui essa non sia stata ancora aperta.
+
+L'handler immediatamente successivo è tipicamente quello di Intuition; la
+sua funzione è "interpretare", ed eventualmente filtrare, tutti quegli eventi
+che possono influire sullo stato della GUI o sulle attività dei programmi che
+ne fanno uso.
+
+Questo handler fondamentalmente si limita a chiamare la funzione Intuition()
+della intuition.library, passandole come unico argomento il puntatore alla
+lista di eventi ricevuto in ingresso.
+
+Intuition() verifica la natura di ogni singolo evento e, se necessario,
+reagisce ad esso eseguendo opportune azioni, come ad esempio attivare una
+finestra, modificare l'aspetto e lo stato di un gadget o inviare un messaggio
+ad un applicativo.
+
+La casistica più comune comprende:
+
+· Refresh automatico di una componente della GUI (bordo di una finestra,
+  gadget non BOOPSI, barra del titolo di uno schermo).
+
+· Visualizzazione di menu
+
+· Invocazione dell'opportuno metodo di un gadget BOOPSI
+
+· Nessuna azione visibile (es.: click all'interno di una finestra, ma non
+  su un gadget)
+
+A ciascuna di queste azioni può essere associato l'invio di un particolare
+messaggio, rappresentato da una struttura IntuiMessage, all'applicativo
+"proprietario" della finestra correntemente attiva (normalmente il task che
+l'ha aperta).
+
+Gli IntuiMessage hanno spesso una corrispondenza stretta con gli InputEvent
+da cui derivano.
+
+Al termine di queste azioni gli eventi che non possono essere utili agli
+handler successivi vengono rimossi dalla lista, altri (generalmente utili
+a console.device) vengono aggiunti, e la funzione Intuition() termina
+restituendo all'handler il puntatore alla nuova lista.
+
+Infine l'handler di Intuition restituisce a sua volta il puntatore
+all'input.device che può quindi passarlo all'handler successivo, solitamente
+quello di console.device.
+                                                               _ _ _ _ _ _
+                                                              | \ \ \ \ \ |
+                                                              |Applicativo|
+                                                              |_\_\_\_\_\_|
+                               InputEvent stream                   /|\
+                             .····················.            _ _ _|_ _ __
+                             :                    :           |            |
+ _ _ _ _ _ _ _ _        _ _ _: _ _ _     _ __ _ _ V _ _ __ _  |Messaggio ad|
+|               |      |            |   |                   | |applicativo |
+|keyboard.device|-.    |            |==>|Input handler (CX) | |__ _ _ _ _ _|
+|_ _ _ _ _ _ _ _|  \   |            |   |_ _ _ _ _ _ _ _ _ _|      /\
+ _ _ _ _ _ _ _ _    \  |            |    _ __ _ _ V _ _ __ _     _ ||_ _ _ _
+|               |    \ |input.device|   |                   |   |           |
+|gameport.device|----->|    task    |==>|Input handler (I)  |==>|Intuition()|
+|_ _ _ _ _ _ _ _|    / |            |   |_ _ _ _ _ _ _ _ _ _|   |_ _ _ _ _ _|
+ _ _ _ _ _ _ _ _    /  |            |    _ __ _ _ V _ _ __ _       ||
+|               |  /   |            |   |                   |  _ _ \/_ _
+| timer.device  |-'    |            |==>|Input handler (c.d)| |         |
+|_ _ _ _ _ _ _ _|      |__ _ _ _ _ _|   |_ _ _ _ _ _ _ _ _ _| |Refresh  |
+                                                  :           |della GUI|
+                                                 _:           |_ _ _ _ _|
+                                                / \_/              ||
+                                                  :        _ _ _ _ \/_ _ _ _
+                                                  :       |                 |
+                                                  V       |Esecuzione metodo|
+                                                /////     |_ _ _ _ _ _ _ _ _|
+
+Questo meccanismo comporta che l'unico codice eseguito nel contesto di un
+applicativo che faccia uso di Intuition è quello che si occupa di rispondere
+agli IntuiMessage ed intraprendere eventuali azioni in base al loro contenuto
+(generalmente finalizzate a svolgere il compito richiesto dall'utente più
+che a gestire l'interfaccia; tuttavia nel caso di GadTools alcune operazioni
+di gestione della GUI vengono affidate al task dell'applicativo mediante le
+funzioni GT_GetIMsg() e GT_ReplyIMsg()).
+
+In particolare, nel caso dei gadget BOOPSI, la risposta della GUI risulta
+sempre immediata e "in tempo reale", indipendentemente dalle operazioni che
+l'applicativo sta svolgendo nello stesso momento, poiché di fatto se ne
+occupa asincronamente un altro task (quello dell'input.device).
+
+
+Come si comporta MUI
+--------------------
+
+La differenza fondamentale tra MUI ed Intuition è che i suoi gadget, pur
+essendo oggetti BOOPSI, sono sottoclassi di "rootclass" piuttosto che di
+"gadgetclass". Di conseguenza non sono riconosciuti da Intuition come dei
+normali gadget e non vengono quindi gestiti automaticamente dalla funzione
+Intuition(). Tutto ciò che quest'ultima rileva quando l'utente interagisce
+con i gadget MUI è una serie di eventi IDCMP_MOUSEBUTTONS e IDCMP_MOUSEMOVE
+che essa trasmette, invariati, al task proprietario della finestra.
+
+Quest'ultimo tipicamente si trova in uno stato di attesa degli eventi.
+Per ogni evento ricevuto chiama una funzione MUI di gestione dell'input
+(per l'esattezza invoca un metodo di una particolare classe) la quale
+è poi in grado di determinare a quale gadget MUI va passato, mediante
+l'invocazione di un suo opportuno metodo, l'evento appena letto.
+                                                        _ _ _ _ _ _ _ _ _ __
+                                                       | \ \ \ \ \ \ \ \ \ \|
+                                                       |Operazioni programma|
+                                                       |_\_\_\_\_\_\_\_\_\_\|
+                 _ _ _ _ _ _ _ _ __                               /\
+ _ _ _ _ _ _    |                  |      _ _ _ _ _ _      _ _ _ _|| _ _ _ _
+|           |   |Semplice messaggio|     | \ \ \ \ \ |    | \ \ \ \ \ \ \ \ |
+|Intuition()|==>| all'applicativo  |---->|Applicativo|    |Refresh della GUI|
+|_ _ _ _ _ _|   | (IDCMP_MOUSE#?)  |     |_\_\_\_\_\_|    |_\_\_\_\_\_\_\_\_|
+                |__ _ _ _ _ _ _ _ _|          ||                  /\
+                                        _ _ _ \/_ _ __     _ _ _ _|| _ _ _ _
+                                       | \ \ \ \ \ \ \|   | \ \ \ \ \ \ \ \ |
+                                       |Gestione input|==>|Esecuzione metodo|
+                                       |_\_\_\_\_\_\_\|   |_\_\_\_\_\_\_\_\_|
+
+Con MUI, di conseguenza, la risposta della GUI (almeno con le classi di
+gadget standard fornite con il pacchetto) risulta sincrona alle operazioni
+del task dell'applicativo, in quanto avviene nel suo stesso contesto.
+
+
+PROBLEMI
+
+Problema n. 1 (input.device bloccato; Intuition)
+------------------------------------------------
+
+La gestione dell'input secondo il modello di Intuition, cioè tramite un
+handler, ha il vantaggio di garantire pressoché sempre una risposta immediata
+da parte della GUI, anche nel caso in cui l'applicativo non fosse pronto a
+reagire all'input ricevuto.
+
+Tuttavia, poiché l'handler di Intuition opera sempre, come già illustrato,
+nel contesto dell'input.device, qualsiasi trasmissione di eventi di input
+nel sistema risulta completamente bloccata fino alla conclusione delle sue
+operazioni.
+
+Il problema si manifesta in modo evidente soprattutto con i gadget BOOPSI;
+infatti l'handler invoca opportuni metodi di tali gadget quando l'input
+dell'utente è diretto a loro o comporta una modifica del loro stato. Nel
+caso di metodi particolarmente complessi, come quelli dei gadget associati
+ai DataType, il tempo di esecuzione può essere elevato, e di conseguenza
+la trasmissione dell'input nell'intero sistema può subire una sospensione di
+durata non trascurabile.
+
+Il sintomo più tipico è il blocco del puntatore del mouse, ma anche altre
+attività del sistema operativo che si basino su una regolare ricezione di
+eventi di input (ad esempio quelli generati dal timer.device) rischiano di
+venire ostacolate con conseguenze imprevedibili.
+
+
+Problema n. 2 (refresh della GUI bloccato; MUI)
+-----------------------------------------------
+
+Il sistema MUI presenta un problema per certi versi opposto, ma ugualmente
+fastidioso per l'utente. Con i gadget di MUI le operazioni svolte nel
+contesto del task dell'input.device sono sempre molto limitate e di breve
+durata; si tratta per lo più di comunicare una serie di click dei pulsanti
+del mouse (e spostamenti di quest'ultimo) all'applicativo associato al canale
+IDCMP della finestra attiva.
+
+Ogni operazione relativa alla GUI viene poi effettuata nel contesto del task
+che riceve i messaggi in questione. Nel caso esso sia occupato in qualche
+elaborazione e quindi non si trovi in attesa di segnali dalla porta IDCMP,
+come è facile immaginare, nessun tipo di aggiornamento della GUI verrà
+attuato fino alla conclusione delle operazioni.
+
+L'utente, in questo caso, non osservando alcuna risposta dai gadget con cui
+tenta di interagire, può avere l'impressione che l'intero programma sia
+bloccato e non semplicemente impegnato in altre attività.
+
+Nel caso migliore l'utente si fa una cattiva opinione del programma; inoltre
+l'incertezza sul da farsi può portare l'utente a danneggiare inavvertitamente
+il lavoro che sta svolgendo mediante l'applicativo. Ad esempio, un tentativo
+di selezione ripetuta dello stesso gadget (nella speranza di una ripresa del
+funzionamento del programma) può provocare effetti collaterali indesiderati
+nell'istante in cui l'applicativo ricomincia a gestire l'input e si occupa di
+quello nel frattempo ricevuto.
+
+
+IPOTESI DI SOLUZIONI
+
+Possibile soluzione per il problema n. 1 (sotto-task IDCMP in parallelo)
+------------------------------------------------------------------------
+
+Una possibile soluzione al primo problema, attuabile al livello di Intuition,
+è la gestione multithreaded degli eventi di input trasmessi al suo handler
+dall'input.device, che in tal modo si libererebbe molto rapidamente dopo
+la chiamata alla funzione Intuition(). Come realizzare questo nella pratica?
+
+Un'idea potrebbe essere associare ad ogni schermo e finestra un task
+dedicato, creato all'apertura ed eliminato alla chiusura. Ciascuno di questi
+task riceverebbe solo gli eventi che lo riguardano e potrebbe gestirli del
+tutto asincronamente al resto del sistema e in particolare all'input.device.
+
+Per rendere possibile ciò sarebbe necessario apportare alcune modifiche alla
+funzione Intuition():
+
+1. Essa dovrebbe, preliminarmente, esaminare la lista di InputEvent ricevuta
+   dall'input.device e in base ad essa costruire una seconda lista privata
+   copiando tutti gli eventi che riguardano la GUI.
+
+2. Fatto ciò, tutti gli eventi che non devono essere rilevati dagli altri
+   handler dovrebbero essere rimossi dalla lista principale.
+
+3. La lista privata di eventi dovrebbe poi essere separata in sottoliste,
+   ognuna indirizzata all'opportuna finestra (o all'opportuno schermo).
+
+4. Ogni sottolista dovrebbe essere spedita, tramite un opportuno messaggio,
+   al task associato alla finestra (o schermo) destinazione.
+
+5. A questo punto Intuition() potrebbe terminare subito la sua esecuzione,
+   senza aspettare alcuna risposta dai task a cui ha spedito i messaggi;
+   in questo modo l'input.device sarebbe subito libero di proseguire la
+   sua attività.
+
+Una possibile variante è il passaggio (subito dopo il punto 2) della lista
+privata ad un task "intermedio" che si occupi di eseguire le operazioni
+rimanenti; in questo caso Intuition() potrebbe terminare prima del punto 3.
+Questo ipotetico task intermedio potrebbe ad esempio venire creato in modo
+automatico all'apertura della intuition.library.
+
+Occorre prestare molta attenzione all'implementazione del punto 2, in quanto
+è necessario stabilire delle regole precise in base alle quali si possa
+determinare IN ANTICIPO e senza ambiguità se un evento riguarda o no la GUI e
+se esso debba venire trasmesso o no ai successivi handler. Questo potrebbe,
+oggettivamente, non essere un compito facile.
+
+In particolare, se un evento deve essere modificato da Intuition e poi
+trasmesso al resto degli handler, bisogna che:
+
+- Si sappia già come modificarlo PRIMA di passarlo al task destinatario,
+  per non dover aspettare che questo termini fornendo informazioni sulla
+  modifica da effettuare (soluzione non sempre applicabile), oppure
+
+- Il task destinatario, dopo avere modificato personalmente l'evento, si
+  occupi di REINSERIRLO nella catena di InputEvent a monte dell'handler di
+  Intuition. Questo si può realizzare ad esempio aggiungendolo ad una coda
+  di eventi globale periodicamente letta dall'handler, oppure sfruttando
+  la commodities.library. Non basta chiamare direttamente Intuition() con
+  l'evento in questione poiché si rimarrebbe nel contesto del task.
+  Le regole per realizzare ciò potrebbero risultare abbastanza complicate.
+
+Ammettendo di risolvere questi problemi, restano da esaminare i compiti dei
+singoli task destinatari.
+
+Quelli associati alle finestre svolgerebbero esattamente gli stessi compiti
+che attualmente sono svolti dalla funzione Intuition(), cioè aggiornare lo
+stato della GUI, invocare opportuni metodi di eventuali gadget BOOPSI
+selezionati e spedire IntuiMessage all'applicativo che "possiede" la finestra
+(con l'unica avvertenza, ovvia del resto, di assicurarsi che il task sia
+completamente rientrante ed esegua una corretta arbitrazione sui dati globali
+di IntuitionBase).
+
+I task associati agli schermi non dovrebbero fare altro che gestire la
+selezione degli unici due possibili gadget, quello di trascinamento e quello
+di profondità, nonché la disattivazione di tutte le finestre in caso di
+click del mouse su una zona libera dello schermo, l'autoscrolling e lo screen
+dragging tramite Amiga sinistro + mouse.
+
+Si potrebbe anche pensare ad un ulteriore task indipendente che gestisca
+semplicemente il movimento del puntatore, ma questo è un compito talmente
+banale che potrebbe essere svolto direttamente (e più rapidamente) dalla
+funzione Intuition().
+                                                           _ _ _ _ _ _
+                                                          | \ \ \ \ \ |
+                                                          |Applicativo|
+                                                          |_\_\_\_\_\_|
+        InputEvent stream                                      /|\
+      .····················.                                    |
+      :                    :                             ::::::::::::::::
+ _ _ _: _ _ _     _ __ _ _ V _ _ __ _                    ::Messaggio ad::
+|            |   |                   |                   ::applicativo:::
+|            |==>|Input handler (CX) |                   ::::::::::::::::
+|            |   |_ _ _ _ _ _ _ _ _ _|                          /\
+|            |    _ __ _ _ V _ _ __ _     _ _ _ _ _ _           ||
+|input.device|   |                   |   |           |   :::::::::::::::::
+|    task    |==>|Input handler (I)  |==>|Intuition()|-->::Task finestra::
+|            |   |_ _ _ _ _ _ _ _ _ _|   |_ _ _ _ _ _|   :::::::::::::::::
+|            |    _ __ _ _ V _ _ __ _                           ||
+|            |   |                   |                          \/
+|            |==>|Input handler (c.d)|                     :::::::::::::
+|__ _ _ _ _ _|   |_ _ _ _ _ _ _ _ _ _|                     ::Refresh::::
+                           :                               ::della GUI::
+                          _:                               :::::::::::::
+                         / \_/                                  ||
+                           :                                    \/
+                           :                           :::::::::::::::::::::
+                           V                           ::Esecuzione metodo::
+                         /////                         :::::::::::::::::::::
+
+
+Per concludere, si può osservare che in realtà sarebbe abbastanza raro che
+la stessa lista contenga eventi indirizzati a finestre diverse; l'utente,
+in circostanze normali, non dovrebbe essere più veloce dell'elaborazione
+dell'input da parte del sistema. Un'eccezione sono gli eventi di timer (che
+non sono generati dall'utente e sono sempre diretti a tutte le finestre).
+
+Alla luce di questa considerazione si potrebbe pensare di lasciare al
+programmatore (o addirittura all'utente) la facoltà di decidere quali
+finestre debbano essere dotate di un task IDCMP dedicato, e quali invece
+possano semplicemente appoggiarsi ad un task IDCMP globale.
+
+
+Possibile soluzione per il problema n. 2 (classe MUI con task asincrono)
+------------------------------------------------------------------------
+
+Il problema di MUI potrebbe risolversi molto facilmente con una riscrittura
+delle classi di base del sistema.
+
+L'idea è che il dispatcher di un gadget MUI non dovrebbe eseguire in sequenza
+(e nel contesto dell'applicativo) il refresh della GUI e poi la chiamata alla
+funzione di callback associata al gadget.
+
+Ogni istanza di una classe di gadget MUI dovrebbe avere un proprio task
+privato a cui affidare la chiamata alla funzione di callback, rendendola
+così asincrona rispetto al refresh grafico. Tale task potrebbe essere creato
+dal metodo OM_NEW della classe e distrutto in seguito da OM_DISPOSE.
+Eventuali valori di ritorno diretti all'applicativo potrebbero essere
+comunicati mediante messaggi (gestiti automaticamente dal task del gadget).
+
+Il refresh grafico dei gadget, invece, essendo generalmente un'operazione
+abbastanza rapida, potrebbe essere affidato ad un unico task globale; una
+possibilità sarebbe quella di creare questo task all'apertura della libreria
+MUIMaster.
+
+                               ::::::::::::::::::::::::   :::::::::::::::::::
+                               ::Operazioni programma::<==::Task del gadget::
+                               ::::::::::::::::::::::::   :::::::::::::::::::
+                 _ _ _ _ _ _ _ _ __                               /|\
+ _ _ _ _ _ _    |                  |    _ _ _   _ _ __     _ _ _ _ | _ _ _ _
+|           |   |Semplice messaggio|   | \ \ \ \ \ \ \|   | \ \ \ \ \ \ \ \ |
+|Intuition()|==>| all'applicativo  |-+ |Gestione input|==>|Esecuzione metodo|
+|_ _ _ _ _ _|   | (IDCMP_MOUSE#?)  | | |_\_\_\_\_\_\_\|   |_\_\_\_\_\_\_\_\_|
+                |__ _ _ _ _ _ _ _ _| |        /\                   |
+                                     |    _ _ ||_ _ _             \|/
+                                     |   | \ \ \ \ \ |  ;;;;;;;;;;;;;;;;;;;;;
+                                     +-->|Applicativo|  ;;Refresh della GUI;;
+                                         |_\_\_\_\_\_|  ;;;;;;;;;;;;;;;;;;;;;
+
+Se le operazioni di refresh non necessitano di restituire alcun valore al
+dispatcher dell'oggetto (oppure alla funzione di MUI che gestisce l'input)
+quest'ultimo verrebbe disimpegnato immediatamente; in caso contrario sarebbe
+sufficiente che il task preposto al refresh svolgesse tutte le sue operazioni
+prima di rispondere al dispatcher con ReplyMsg(), e copiasse il valore di
+ritorno in un apposito campo del messaggio "restituito" al mittente.
+
+Questo ovviamente terrebbe impegnato il task dell'applicativo per un tempo
+leggermente superiore, ma le operazioni di refresh grafico puro e semplice
+non dovrebbero, nella maggior parte dei casi, richiedere più di qualche
+millisecondo (come del resto accade per Intuition nel caso di gadget non
+troppo complicati). Chiaramente se tale comportamento fosse richiesto per
+TUTTI i gadget sarebbe più conveniente evitare del tutto l'uso di un task
+separato per il refresh, mantenendo però quello dedicato al callback.
+
+Sarebbero possibili diverse variazioni sul tema: ad esempio, l'ordine in cui
+vengono "richiamati" i due task potrebbe influenzare, sia pure di poco, la
+prontezza del refresh e quindi della risposta all'utente da parte della GUI;
+oppure in certi casi potrebbe essere conveniente creare "al volo" il task
+preposto al callback in modo che l'applicativo possa eseguire più volte
+contemporaneamente la stessa funzione (se la sua natura lo consente).
+
+In ogni caso questa soluzione eliminerebbe alla radice il problema del
+"blocco" apparente della risposta della GUI durante un'intensa attività
+dell'applicativo, senza per questo tornare al modello "mono-threaded"
+adottato attualmente da Intuition. L'alternativa proposta per quest'ultimo
+(vedi paragrafo precedente) risolverebbe in teoria anche il problema di MUI,
+ma solo se i gadget MUI fossero istanze di "gadgetclass", cosa che al
+momento, in pratica, non accade.
+
+
+CONSIDERAZIONI FINALI
+
+Funzionamento seriale dell'input.device
+---------------------------------------
+
+Come già detto, l'input.device propaga lo stream di eventi di input
+attraverso i vari handler in cascata. Gli handler non sono altro che
+funzioni chiamate, una dopo l'altra, dal task dell'input.device; ogni
+handler riceve in ingresso il valore di uscita del precedente (e cioè
+il puntatore ad una particolare lista di InputEvent).
+
+Questo è un meccanismo intrinsecamente seriale; inoltre esso implica che gli
+handler di priorità più alta (come quello di Intuition) debbano esaminare,
+tra gli altri, molti eventi che non li riguardano direttamente e che vanno
+semplicemente trasmessi agli handler successivi.
+
+Come aumentare il parallelismo nelle operazioni dell'input.device?
+
+Ingenuamente si potrebbe pensare di avere diverse code, ognuna gestita da
+un task indipendente, tra cui suddividere gli eventi in base al tipo degli
+handler che tali code alimentano; ovviamente occorrerebbe che gli handler
+di una coda non abbiano mai la necessità di trasmettere eventi a quelli di
+un'altra coda.
+
+Purtroppo in pratica questo non è una soluzione, dato che porterebbe a
+ricreare la situazione corrente. Infatti normalmente gli handler esistenti
+nel sistema sono pochi (per lo più Commodities, Intuition e console.device)
+ed è difficile individuare tipi di eventi che non interessino, anche solo
+potenzialmente, almeno due di essi.
+
+In particolare, la quasi totalità degli eventi di input generati dall'utente
+interessa in qualche modo Intuition, che viene ad essere un vero e proprio
+"collo di bottiglia".
+
+Più vantaggioso risulterebbe applicare questa soluzione al livello dei
+singoli handler; ciascuno di essi, a meno che il suo funzionamento sia
+molto semplice, potrebbe gestire l'input in arrivo ripartendolo in modo
+opportuno tra diversi task paralleli (come illustrato riguardo al problema
+di Intuition).
+
+In questo modo sorgerebbe però il problema della trasmissione del flusso
+di input lungo la catena di handler. Ognuno di essi potrebbe trasmettere
+al successivo solo gli eventi che può scartare immediatamente come "non
+rilevanti" per le sue attività, ma gli sarebbe preclusa la possibilità di
+modificare gli eventi utilizzati, o crearne di nuovi in base ai risultati
+della loro elaborazione, e reinserirli nella posizione originale: questa
+operazione generalmente richiederebbe la conoscenza di dati non disponibili
+a priori e, d'altra parte, una sincronizzazione con i suoi task per ottenere
+da essi tali dati annullerebbe ovviamente tutti i vantaggi del parallelismo.
+
+E` dunque necessario, volendo impiegare un simile modello:
+
+· Stabilire delle regole estremamente precise per decidere quando l'ordine
+  relativo di due eventi vada mantenuto oppure sia ininfluente;
+
+· Limitare al massimo la necessità di trasmettere informazioni tra un
+  handler e il successivo (nel caso di entità strettamente connesse, come
+  Intuition e console.device, questo potrebbe rivelarsi un problema serio);
+
+· Assicurarsi, ad esempio mediante semafori, che venga sempre mantenuta la
+  consistenza interna dei valori che definiscono lo stato di un handler (e
+  quindi dell'entità software che si appoggia ad esso) anche in presenza
+  di numerosi sotto-task che possono accedere a tali valori.
+
+Ad esempio, se l'utente attiva una finestra di Shell e poi preme un tasto
+sulla tastiera, è necessario che il console.device riceva l'evento "finestra
+attiva" PRIMA di quello "tasto premuto", nonostante il fatto che il secondo
+potrebbe venire trasmesso immediatamente mentre il primo richiederebbe una
+più lunga elaborazione da parte di Intuition.
+
+Ancora, quando l'utente trascina un gadget proporzionale sarebbe auspicabile
+che la posizione relativa di knob e puntatore del mouse rimanesse costante,
+anche se gli spostamenti dei due oggetti vengono gestiti da due diversi task.
+
+La trasmissione di eventi agli handler successivi potrebbe ad esempio essere
+implementata mediante una coda ausiliaria globale svuotata periodicamente,
+accessibile a tutti i sotto-task di un handler, purché si presti la massima
+attenzione a mantenerla sempre perfettamente ordinata e ad inserire in essa
+anche quegli eventi (e solo quelli) che, pur non dovendo essere elaborati
+dall'handler corrente, possono risentire dell'ordine in cui vengono trasmessi
+rispetto a certi altri eventi.
+
+Queste considerazioni non pretendono certamente di costituire una soluzione
+completa, preferibile ad altre o facilmente realizzabile; si tratta solo di
+riflessioni su alcuni aspetti del problema di cui probabilmente converrebbe
+tenere conto.
+
+
+Fattibilità di un patch per Intuition
+-------------------------------------
+
+E` possibile, tramite un patch, applicare all'attuale versione di Intuition
+i criteri appena esposti?
+
+Probabilmente no.
+
+L'idea sarebbe di applicare un patch alla funzione Intuition() per forzare
+il passaggio dell'input ad un task separato che se ne occupi, permettendo
+all'handler di Intuition di terminare subito la sua esecuzione. Ma anche
+immaginando di risolvere quasi tutti i problemi prima descritti, resta sempre
+l'impossibilità di garantire la consistenza dei dati PRIVATI contenuti nella
+struttura IntuitionBase, a cui sarebbe facile, in questo modo, effettuare
+un accesso asincrono.
+
+Non è escluso che si possa trovare una soluzione anche a questo problema, ma
+con ogni probabilità a questo punto conviene aspettare che sia Amiga Inc. ad
+implementare nel sistema operativo una gestione dell'input più efficiente.
+
diff --git a/docs/LabelTextIClass.doc b/docs/LabelTextIClass.doc
new file mode 100755 (executable)
index 0000000..669699c
--- /dev/null
@@ -0,0 +1,181 @@
+TABLE OF CONTENTS
+
+labeltext.image/labeltext.image
+\flabeltext.image/labeltext.image           labeltext.image/labeltext.image
+
+    NAME
+        labeltext.image -- label BBOPSI image (V1)
+
+    FUNCTION
+        The labeltext class is a little BOOPSI class that provides a complete
+        label handling. A label can be placed inside or outside a gadget
+        (above, below, left, right or inside) with different alignments
+        (centered, left aligned, right aligned, etc.) with a couple of
+        different rendering methods (normal, hilighted, 3d). It is able to
+        use the standard DrawInfo pens when no custom pens are supplied and
+        the system default font when no custom font is supplied.
+        It supports various image states (i.e. normal, selected, disabled,
+        etc.) This class has also a nice API for easy layer clipping when it
+        is necessary.
+
+    METHODS
+        IM_DRAW -- Tell the class to render itself. Before calling this
+            method for the first time you should first invoke the IM_FRAMEBOX
+            method and then the IM_DRAW one using the FrameBox Left and Top
+            field or the Image LeftEdge and TopEdge fields. Note that these
+            coordinates are NOT exactly the ones the label will use, i.e.
+            if you do a Text() call using that coordinates you'll get a text
+            slightly shifted. In other words if you calculate yourself the
+            coordinates of the label you won't be able to draw it in the right
+            place. This is required for an easy layer clipping support.
+            NB: You must alway supply the imp_Offset coordinates, even if the
+            Image->LeftEdge and Image->TopEdge field already contain the right
+            values.
+
+        IM_FRAMEBOX -- This method tell the class to calculate its position
+            relative to the ContentsBox coordinates and according to its
+            alignment attributes. For this reason the ContenstBox is usually
+            filled with the gadgets coordinates. Moreover the FrameBox structure
+            is filled with the coordinates of the rectangle required by the
+            label to draw itself. In this way the gadget can easily perform
+            the correct layer clipping if necessary. Example:
+
+
+            struct IBox cbox, fbox;
+            struct Rectangle rect;
+
+            DoMethod((Object *)gad->GadgetText, IM_FRAMEBOX, (ULONG)&(cbox), (ULONG)&fbox, NULL);
+
+            rect.MinX = MAX(msg->gpr_GInfo->gi_Window->BorderLeft, fbox.Left);
+            rect.MinY = MAX(msg->gpr_GInfo->gi_Window->BorderTop, fbox.Top);
+            rect.MaxX = MIN(msg->gpr_GInfo->gi_Window->Width - msg->gpr_GInfo->gi_Window->BorderRight,
+                            fbox.Left + fbox.Width - 1);
+            rect.MaxY = MIN(msg->gpr_GInfo->gi_Window->Height - msg->gpr_GInfo->gi_Window->BorderBottom,
+                            fbox.Top + fbox.Height - 1);
+
+            OrRectRegion(new_region, &rect);
+            old_region = InstallClipRegion(msg->gpr_GInfo->gi_Layer, new_region);
+
+
+            The same rectangle is then usually used to tell the label to draw
+            or erase itself (using the Left and Top field) but it is not
+            required, since the class modifies its coordinates with the values
+            it calculated the last time IM_FRAMEBOX was invoked (i.e. you may
+            alternatively supply the img->LeftEdge and img->TopEdge values).
+
+            If you specify the FRAMEF_SPECIFY flag the label will check if it
+            fit in the ContentsBox rectangle. If not the FrameBox Left and
+            Top fields will be set to -1. You can blindly pass this values
+            to the IM_DRAW or IM_ERASE method, since the class knows that it
+            has not to render itself. The FrameBox Width and Height fields
+            are set to an arbitrary value to avoid problems if the gadget do
+            layer clipping without checking the result of the IM_FRAMEBOX
+            method.
+
+            NOTE: If you change some attributes (e.g. the font) you should call
+            the IM_FRAMEBOX method again, so that the label can recalculate
+            its position and size.
+
+    TAGS
+
+        ELA_Label -- Pointer to the string the class will print. You MUST
+            supply this tag when you create an object. The label will not
+            deallocate the string when disposed.
+
+            Applicability is (ISG)
+
+        ELA_LabelType -- Specify the way the label should render itself. See
+            the include file for the currently supported values.
+
+            Applicability is (ISG)
+
+        ELA_Distance -- The distance from the gadget borders. Note that the
+            label does not know about frame thickness. e.g. if you draw a
+            label inside a gadget, left aligned with a distance of 0 pixel,
+            the label will likely draw itself over the left border of the
+            frame. If you want to avoid this you must set this attribute to
+            a value at least equal to the frame thickness.
+
+            Applicability is (ISG)
+
+        ELA_Position -- Tell the label where it should draw itself, i.e.
+            above the gadget, below, to the left, etc. Note that 'gadget'
+            is somewhat misleading, since the label calculates its position
+            relative to any rectangle. i.e. when you call the IM_FRAMEBOX
+            method, you usually pass as the ContentsBox the gadget
+            coordinates, but if you want you could, e.g. tell the label
+            to center itself in the window titlebar.
+            See the include file for the values of this tag.
+
+            Applicability is (ISG)
+
+        ELA_Align -- Set the alignment of the label. If the label is placed
+            above or below the gadget the label can be centered, left aligned
+            or right aligned. If placed to the side of the gadget it can be
+            vertically centered or aligned to the top or to the bottom of the
+            gadget. If it is placed inside it can be centered, aligned to the
+            top or bottom (always horizontally centered) or aligned to the
+            left or right (vertically centered).
+
+            Applicability is (ISG)
+
+        ELA_Font -- Specify the font the label will use to draw itself.
+            It must be a TextFont pointer, i.e. the one you'll get with
+            the OpenFont() function. The label will not close the font
+            when disposed.
+
+            Applicability is (ISG)
+
+        ELA_PenBackgound -- Specify the pen number used for the background
+            pen. If it is not specified or set to -1 the standard DrawInfo
+            BACKGROUNDPEN will be used. Currently it is used only to erase
+            the label.
+
+            Applicability is (ISG)
+
+        ELA_PenShine -- Specify the pen number used for the shine pen.
+            If it is not specified or set to -1 the standard SHINEPEN will
+            be used. Currently this is used for the 'hilight' and '3d' labels.
+
+            Applicability is (ISG)
+
+        ELA_PenShadow -- Specify the pen number used for the shadow pen.
+             If it is not specified or set to -1 the standard SHADOWPEN will
+             be used. This is the pen used for 'normal' and '3d' labels.
+
+            Applicability is (ISG)
+
+        ELA_PenHalfShine -- Specify the halfshine pen. If it is not specified
+            or set to -1 the standard SHINEPEN will be used. It's usually a
+            bit darker than the shine pen and is currently used for the
+            disabled state.
+
+            Applicability is (ISG)
+
+        ELA_PenHalfShadow -- Specify the halfshadow pen. If it is not
+            specified or set to -1 the standard SHADOWPEN will be used.
+            It'susually a bit brighter than the shadow pen and is currently
+            used for the disabled state.
+
+            Applicability is (ISG)
+
+    NOTE
+        Usually a single BOOPSI image (e.g. a frame) may be used by different
+        gadgets at the same time. This is true even for the textlabel class,
+        but there are a couple of little "problem" or side effects that may
+        be encountered. First every time the IM_FRAMEBOX method is called the
+        image LeftEdge and TopEdge fields are changed, so the gadgets should
+        take care of storing the result of this method by their own (i.e. they
+        should save the FrameBox Left and top fields somewhere), since if they
+        call the IM_DRAW method using the image coordinates they may use the
+        result of another gadget's IM_FRAMEBOX call. Second the text to be
+        printed (and maybe even the font) should be set every time before a
+        IM_DRAW method since it's very unlikely that different gadgets need to
+        display the same string.
+        Currently I don't know if there's some nice and elegant way to solve
+        this, so you should create a different instance of this class for every
+        gadget that will use a lebeltext object.
+
+    SEE ALSO
+        The "Image Subclasses" chapter of the Intuition Reference Manual.
+
diff --git a/docs/NoteBOOPSI b/docs/NoteBOOPSI
new file mode 100644 (file)
index 0000000..b227ff8
--- /dev/null
@@ -0,0 +1,149 @@
+
+Alcune note sulla struttura GadgetInfo
+--------------------------------------
+
+Apparentemente l'input handler di Intuition riutilizza sempre, quando ciò è
+possibile, la stessa struttura GadgetInfo quando invoca un metodo di un
+gadget custom. Del resto il singolo task dell'input.device può solo invocare
+un metodo dopo l'altro in sequenza e nella maggioranza dei casi non necessita
+di avere contemporaneamente più di una struttura GadgetInfo.
+
+Nella struttura GadgetInfo un gadget custom riceve nel campo gi_Layer il
+puntatore al layer associato al "contenitore logico" in cui si trova il
+gadget stesso.
+
+· Un gadget custom situato in una finestra normale, oppure nella zona interna
+  di una finestra GIMMEZEROZERO riceve in gi_Layer il puntatore al layer di
+  Window.RPort. Il "contenitore logico" è l'area dell'intera finestra, oppure
+  l'area della sua zona interna.
+
+· Un gadget custom situato nella zona esterna di una finestra GIMMEZEROZERO
+  (GZZGADGET) riceve in gi_Layer il puntatore al layer di Window.BorderRPort.
+  Il "contenitore logico" è l'area dell'intera finestra.
+
+· Un gadget custom situato in un requester (REQGADGET) riceve in gi_Layer il
+  puntatore al layer del requester (Requester.ReqLayer).
+  Il "contenitore logico" è l'area del requester.
+
+· Un gadget custom situato nella titlebar di uno schermo (SCRGADGET) riceve
+  in gi_Layer il puntatore al layer della titlebar (Screen.BarLayer).
+  Il "contenitore logico" è l'area della titlebar.
+
+· Un gadget custom situato in un gruppo (cioè appartenente alla lista interna
+  di un gadget "groupgclass") riceve in gi_Layer un valore che dipende dal
+  "contenitore logico" del gruppo stesso, ricadendo così in uno dei quattro
+  casi precedenti.
+
+Il campo gi_RastPort è uguale a gi_Screen->BarLayer->rp quando il gadget
+appartiene ad una finestra o ad un requester, e punta a gi_Screen.RastPort
+quando invece il gadget appartiene alla titlebar dello schermo.
+Ignoro le ragioni di questo fatto; in ogni caso questa RastPort per
+qualche motivo non deve venire utilizzata per il rendering (nel caso di
+un gadget SCRGADGET essa non ha nemmeno un layer).
+
+Chiamando ObtainGIRPort() si ottiene un clone della RastPort di gi_Layer, che
+punta allo stesso layer, il quale punta alla RastPort originale (quella della
+finestra interna, o quella del bordo per le finestre GIMMEZEROZERO, ecc.).
+
+Inoltre ObtainGIRPort() esegue un LockLayer() su gi_Layer. Apparentemente
+gi_Layer ha già tre lock quando Intuition invoca il metodo GM_RENDER (solo due
+nel caso di un gadget SCRGADGET) mentre non è bloccato nel caso di tutti gli
+altri metodi.
+
+Per il metodo GM_RENDER il valore di gpr_RPort è esattamente lo stesso che
+si otterrebbe chiamando ObtainGIRPort(), il che suggerisce che tale RastPort
+clonata sia unica e conservata da qualche parte. In effetti a quanto ho visto
+finora ObtainGIRPort() restituisce sempre lo stesso indirizzo, qualunque sia
+il contesto.
+
+I valori di gi_Screen, gi_Window e gi_Requester sono inizializzati in modo
+opportuno (oppure nulli se non applicabili, a parte gi_Screen).
+
+Tabella di esempio per un gadget in una finestra non GZZ:
+
+ +-------------------------------------------------------------------------+
+ |                                              gi_Window: W               |
+ |                                  gi_Layer: RL, LWindow: W, LRastPort: R |
+ | gi_RastPort:         S, BitMap: bm, Layer: SL, LWindow: 0, LRastPort: S |
+ | gi_Window->RPort:    R, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R |
+ | gi_Window->BorderRP: 0, BitMap: --, Layer: --, LWindow: -, LRastPort: - |
+ | gpr_RPort:           C, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R |
+ | ObtainGIRPort():     C, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R |
+ +-------------------------------------------------------------------------+
+
+Tabella di esempio per un gadget non GZZ in una finestra GZZ:
+
+ +-------------------------------------------------------------------------+
+ |                                              gi_Window: W               |
+ |                                  gi_Layer: RL, LWindow: W, LRastPort: R |
+ | gi_RastPort:         S, BitMap: bm, Layer: SL, LWindow: 0, LRastPort: S |
+ | gi_Window->RPort:    R, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R |
+ | gi_Window->BorderRP: B, BitMap: bm, Layer: BL, LWindow: W, LRastPort: B |
+ | gpr_RPort:           C, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R |
+ | ObtainGIRPort():     C, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R |
+ +-------------------------------------------------------------------------+
+
+Tabella di esempio per un gadget GZZ in una finestra GZZ:
+
+ +-------------------------------------------------------------------------+
+ |                                              gi_Window: W               |
+ |                                  gi_Layer: BL, LWindow: W, LRastPort: B |
+ | gi_RastPort:         S, BitMap: bm, Layer: SL, LWindow: 0, LRastPort: S |
+ | gi_Window->RPort:    R, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R |
+ | gi_Window->BorderRP: B, BitMap: bm, Layer: BL, LWindow: W, LRastPort: B |
+ | gpr_RPort:           C, BitMap: bm, Layer: BL, LWindow: W, LRastPort: B |
+ | ObtainGIRPort():     C, BitMap: bm, Layer: BL, LWindow: W, LRastPort: B |
+ +-------------------------------------------------------------------------+
+
+Il campo gi_Domain contiene larghezza e altezza del "contenitore logico" del
+gadget. Nel caso di un gadget SCRGADGET, l'altezza è stranamente quella dello
+schermo, mentre sarebbe più corretto se fosse quella della titlebar. Inoltre
+un gadget che appartenga ad un gruppo ha come "contenitore logico" quello che
+contiene il gruppo, e non il gruppo stesso (probabilmente in quanto il gruppo
+non ha un layer proprio).
+Gli offset contenuti in gi_Domain sono la distanza della posizione (espressa
+in coordinate di schermo) del layer associato al "contenitore logico" del
+gadget dalla posizione (sempre in coordinate di schermo) del suo "contenitore
+fisico primario" (cioè lo schermo per i gadget SCRGADGET e la finestra per
+tutti gli altri, anche se REQGADGET oppure appartenenti ad un gruppo).
+
+La funzione DoGadgetMethodA() crea una struttura GadgetInfo appropriata
+in base al tipo di gadget di cui viene invocato il metodo. Se è di tipo
+GZZGADGET, REQGADGET o SCRGADGET viene scelto il layer corretto, e anche
+gi_Domain viene inizializzato adeguatamente.
+
+Un problema è che "gadgetclass" e "icclass" nell'implementare il metodo
+OM_NOTIFY non chiamano DoGadgetMethodA() per invocare il metodo OM_UPDATE
+dell'oggetto ICA_TARGET, bensì gli passano direttamente il puntatore a
+GadgetInfo ricevuto, che fa riferimento al contesto dell'oggetto notificante
+e non, come sarebbe corretto, a quello dell'oggetto notificato!
+
+Non si devono annidare chiamate a ObtainGIRPort(), altrimenti la RastPort
+clonata (sempre la stessa) può venire modificata ad ogni chiamata. In
+realtà probabilmente se si rimane nello stesso contesto la RastPort clonata
+viene reinizializzata ogni volta con gli stessi valori, per cui non cambia
+niente. Il vero pericolo sta nell'invocare un metodo di un altro gadget che
+chiami ObtainGIRPort() mentre si è ancora all'interno del proprio blocco
+ObtainGIRPort().
+In entrambi i casi comunque può verificarsi un errore 01000008 (Semaphore
+in illegal state).
+Del resto chiamare tanto ObtainGIRPort() quanto DoGadgetMethodA() all'interno
+di un blocco ObtainGIRPort() dovrebbe essere scorretto comunque (sono due
+funzioni di Intuition).
+
+
+Note varie
+----------
+
+GACT_IMMEDIATE viene sempre rispettato anche per i gadget custom o BOOPSI.
+Il valore di Code del messaggio IDCMP_GADGETDOWN è sempre zero e non può
+essere impostato dal dispatcher in alcun metodo (GM_HITTEST/GM_GOACTIVE).
+
+GACT_RELVERIFY è necessario affinché l'uso di GMR_VERIFY + gpi_Termination
+generi effettivamente un messaggio IDCMP_GADGETUP; in sua assenza esso non
+viene generato. Viceversa la sua presenza non garantisce l'invio di tali
+messaggi; ciò è deciso dal dispatcher nei metodi GM_GOACTIVE e GM_HANDLEINPUT.
+
+La documentazione del metodo IM_FRAMEBOX sul RKM è sbagliata! Viene invertito
+il ruolo di imp_ContentsBox e imp_FrameBox.
+
diff --git a/docs/empty_Makefile b/docs/empty_Makefile
new file mode 100644 (file)
index 0000000..c17c250
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+## This is the 'local' makefile, i.e. the makefile
+## that is placed in very classes' directory.
+## You can simply copy it in your class' directory
+## and rename it to 'Makefile', or, if you want, you
+## can customize it.
+##
+## We also suggest you to delete the lines beginning
+## with two '##' like the ones you are reading now.
+## This will make the processing of this file faster
+## since make won't have to strip tons of comments.
+##
+include $(BOOPSITOP)/config.mk
+##
+## This include the local configuration
+## for your class, i.e. the file with
+## the class name, version, etc.
+## It must be present and properly
+## customized. Read the Empty_config.mk
+## file in the docs/ directory for a more
+## detailed explanation.
+##
+include config.mk
+
+##
+## These variables will be used by the general.mk
+## files, so you may use them to pass "arguments"
+## to it, e.g. if you need to link a specific object
+## to your demo program or class.
+##
+## the ARG_COMMON is the arguments that will be used
+## for all the targets, the other variables will be
+## used only for the specific target
+##
+## example
+##
+## ARG_ALL := $(ARG_COMMON) MyObj.o
+##
+ARG_COMMON :=
+ARG_ALL := $(ARG_COMMON)
+ARG_LIB := $(ARG_COMMON)
+ARG_DEBUG := $(ARG_COMMON)
+ARG_PRIVATE := $(ARG_COMMON)
+ARG_OBJ := $(ARG_COMMON)
+ARG_INSTALL := $(ARG_COMMON)
+
+##
+## These variables will be used by the general.mk
+## files, so you may use them to pass "arguments"
+## to it, e.g. if you need to add new dependencies
+## to the various targets
+##
+## the DEP_COMMON is the arguments that will be used
+## for all the targets, the other variables will be
+## used only for the specific target
+##
+## example
+##
+## DEP_ALL := $(DEP_COMMON) MyObj.o
+##
+DEP_COMMON :=
+DEP_ALL := $(DEP_COMMON)
+DEP_LIB := $(DEP_COMMON)
+DEP_DEBUG := $(DEP_COMMON)
+DEP_PRIVATE := $(DEP_COMMON)
+DEP_OBJ := $(DEP_COMMON)
+
+##
+## This is the real makefile. If you
+## don't like it you can include your
+## own makefile. We suggest you to put it
+## in the common/ directory (with a name
+## different from 'general.mk') and to include
+## it rather than writing it here, so that
+## other user can use it for their classes.
+##
+## example
+##
+## include $(BOOPSITOP)/common/mycustommakefile.mk
+##
+include $(BOOPSITOP)/common/general.mk
+
+##
+## Below you can add your own custom targets that are
+## needed for your class.
+##
+## example
+##
+## MyObj.o: MyObj.c
+##    $(CC) $^ $(O) $@
+##
diff --git a/docs/empty_config.mk b/docs/empty_config.mk
new file mode 100644 (file)
index 0000000..6f9a513
--- /dev/null
@@ -0,0 +1,137 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+## This is an empty local config.mk file. You should fill
+## the required fields, copy it to your class directory
+## and rename it to "config.mk".
+## Detailed explanations of the various variables are
+## given below. Please be sure to give the right value
+## to all the variables, or you may get unpredictable
+## results!!
+##
+## We also suggest you to delete the lines beginning with
+## two '##' like the ones you are reading now. This will
+## make the processing of this file faster since make 
+## won't have to strip tons of comments.
+
+###########################################################
+# your stuff
+#
+
+##
+## CLASSLIB is the name of the compiled class, like
+## "label.image" or "listview.gadget", etc.
+## This is required by the makefile. It will also
+## define the symbol "NAME" with this variable's
+## value so that it can be used in your source.
+##
+## example:
+##
+## CLASSLIB := button.gadget
+##
+CLASSLIB :=
+##
+## CLASSSRC is the name of the source code of
+## your class, extension included.
+## This is required by the Makefile.
+##
+## example
+##
+## CLASSSRC := ButtonGClass.c
+##
+CLASSSRC :=
+##
+## DEMOSRC is the name of the source code
+## of your demo program, extension included.
+## This is required by the Makefile.
+##
+## example
+##
+## DEMOSRC := ButtonGDemo.c
+##
+DEMOSRC  :=
+##
+## SUBDIR is the directory name where your class
+## will be copied when you will execute the
+## 'install' target. It must be "images" if your
+## class is a BOOPSI image, "gadgets" if your class
+## is a BOOPSI gadget or just an empty string if
+## your class is a general BOOPSI object.
+##
+## example
+##
+## SUBDIR := gadgets
+##
+SUBDIR   :=
+
+
+###########################################################
+# class version information
+#
+
+##
+## CLASSVER is the version number of your class library
+## e.g. if your library is version 1.2 CLASSVER is 1.
+## It is required to compile the library startup code,
+## and will also be used to define a symbol named VERSION,
+## so that you can use it in your source code.
+##
+## example
+##
+## CLASSVER := 1
+##
+CLASSVER  :=
+##
+## CLASSREV is the revision number of your class library
+## e.g. if your library is version 1.2 CLASSREV is 2.
+## It is required to compile the library startup code,
+## and will also be used to define a symbol named VERSION,
+## so that you can use it in your source code.
+##
+## example
+##
+## CLASSREV := 2
+##
+CLASSREV  :=
+##
+## CLASSDATE is the date of your class library. It follow
+## the standard AmigaOS rules, so it must be enclosed in
+## parenthesis and have the following format: Day.Month.Year
+## It is used to define a symbol named DATE so that you can
+## use it in your source code.
+##
+## example
+##
+## CLASSDATE := (6.4.99)
+##
+CLASSDATE :=
+
+
+###########################################################
+# variable to make the linked library version
+#
+
+##
+## PRV variables is used to compile the class as a linked
+## library instead of the shared version. It is simply
+## used to define a preprocessor simbol with the name
+## you give here.
+## It's up to you to create a class that can be compiled
+## as a shared or static library depending on the
+## definition of this symbol. The current makefile
+## define it for a couple of targets, like 'debug', so
+## we suggest you to implement this features. It's very
+## easy and in most cases requires just some copy & paste
+## from existing classes. Look at them or ask in the
+## OpenBoopsi mailing list if you need a more detailed
+## explanation.
+##
+## example
+##
+## PRV := PRIVATE_GADGETCLASS
+##
+PRV :=
+
diff --git a/gadgets/ClockGClass/Makefile b/gadgets/ClockGClass/Makefile
new file mode 100644 (file)
index 0000000..eb79630
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(BOOPSITOP)/config.mk
+include config.mk
+
+ARG_COMMON :=
+ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o
+ARG_LIB := $(ARG_COMMON)
+ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV)
+ARG_PRIVATE := $(ARG_COMMON)
+ARG_OBJ := $(ARG_COMMON)
+
+DEP_COMMON :=
+DEP_ALL := $(DEP_COMMON) OpenClass.o
+DEP_LIB := $(DEP_COMMON)
+DEP_DEBUG := $(DEP_COMMON) OpenClass.o
+DEP_PRIVATE := $(DEP_COMMON)
+DEP_OBJ := $(DEP_COMMON)
+
+include $(BOOPSITOP)/common/general.mk
+
+OpenClass.o: OpenClass.c
+       $(MAKE) -C $(BOOPSITOP)/common/ $@
diff --git a/gadgets/LauncherGClass/Makefile b/gadgets/LauncherGClass/Makefile
new file mode 100644 (file)
index 0000000..95064ba
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(BOOPSITOP)/config.mk
+include config.mk
+
+ARG_COMMON :=
+ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o
+ARG_LIB := $(ARG_COMMON)
+ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV)
+ARG_PRIVATE := $(ARG_COMMON)
+ARG_OBJ := $(ARG_COMMON)
+
+DEP_COMMON :=
+DEP_ALL := $(DEP_COMMON) OpenClass.o
+DEP_LIB := $(DEP_COMMON)
+DEP_DEBUG := $(DEP_COMMON) OpenClass.o
+DEP_PRIVATE := $(DEP_COMMON)
+DEP_OBJ := $(DEP_COMMON)
+
+include config.mk
+include $(BOOPSITOP)/common/general.mk
+
+OpenClass.o: OpenClass.c
+       $(MAKE) -C $(BOOPSITOP)/common/ $@
diff --git a/gadgets/ListBox/ListBoxClass.c b/gadgets/ListBox/ListBoxClass.c
new file mode 100644 (file)
index 0000000..e0c2ddf
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+**     $Id: ListBoxClass.c,v 1.3 1999/01/30 13:25:03 bernie Exp $
+**
+**     Copyright (C) 1997,98,99 Bernardo Innocenti (<bernardo.innocenti@usa.net>)
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     GadTools-like `boopsi' ListView group class
+*/
+
+#define USE_BUILTIN_MATH
+#define INTUI_V36_NAMES_ONLY
+#define INTUITION_IOBSOLETE_H
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H            /* Avoid dupe defines of boopsi funcs */
+
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <intuition/intuition.h>
+#include <intuition/intuitionbase.h>
+#include <intuition/classes.h>
+#include <intuition/gadgetclass.h>
+#include <intuition/icclass.h>
+#include <intuition/imageclass.h>
+
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <proto/utility.h>
+
+#ifdef __STORM__
+       #pragma header
+#endif
+
+#define LV_GADTOOLS_STUFF
+#include <gadgets/ListBoxClass.h>
+
+#include <CompilerSpecific.h>
+#include <DebugMacros.h>
+#include <BoopsiStubs.h>
+#include <BoopsiLib.h>
+
+
+
+/* Sliders dimensions
+ */
+#define VSLIDER_WIDTH  18
+#define HSLIDER_HEIGHT 18
+
+
+/* Per-object instance data */
+struct LBData
+{
+       /* struct Gadget *ThisGadget; (not used) */
+
+       /* Group children */
+       Object *ListView;
+       Object *HSlider;
+       Object *VSlider;
+       Object *LVToVSliderIC;
+       Object *LVToHSliderIC;
+
+       Object *Model;                  /* The ic object that makes our children talk to each other */
+       Object *Frame;                  /* The frame to put around the child objects */
+
+       /* Frame size */
+       LONG    FrameWidth, FrameHeight;
+
+       /* These two have the same meaning, but we keep both updated
+        * because the Rectangle structure (MinX, MinY, MaxX, MaxY)
+        * is more handy in some cases, while the IBox structure
+        * (Left/Top/Width/Height) is best for other cases.
+        */
+       struct IBox              GBox;
+       struct Rectangle GRect;
+};
+
+
+/* Global class data */
+struct LBClassData
+{
+       Class                           *SliderBarGClass;
+       struct ClassLibrary     *SliderBarBase;
+};
+
+
+
+#define SLIDERBARGCLASS_PTR ( ((struct LBClassData *)(cl->cl_UserData))->SliderBarGClass )
+
+
+
+extern Class *ListViewClass;
+
+
+/* Local function prototypes */
+static void            LB_GMLayout             (Class *cl, struct Gadget *g, struct gpLayout *msg);
+static ULONG   LB_OMSet                (Class *cl, struct Gadget *g, struct opUpdate *msg);
+static ULONG   LB_OMGet                (Class *cl, struct Gadget *g, struct opGet *msg);
+static ULONG   LB_OMNew                (Class *cl, struct Gadget *g, struct opSet *msg);
+static void            LB_OMDispose    (Class *cl, struct Gadget *g, Msg msg);
+
+static void            CreateVSlider   (Class *cl, struct Gadget *g, struct LBData *lb, struct DrawInfo *dri);
+static void            CreateHSlider   (Class *cl, struct Gadget *g, struct LBData *lb, struct DrawInfo *dri);
+static void            DeleteVSlider   (struct Gadget *g, struct LBData *lb);
+static void            DeleteHSlider   (struct Gadget *g, struct LBData *lb);
+
+
+
+
+/* Attribute translations for object interconnections */
+
+static LONG MapLVToHSlider[] =
+{
+       LVA_PixelLeft,          PGA_Top,
+       LVA_PixelWidth,         PGA_Total,
+       LVA_PixelHVisible,      PGA_Visible,
+       TAG_DONE
+};
+
+static LONG MapHSliderToLV[] =
+{
+       PGA_Top,                        LVA_PixelLeft,
+       TAG_DONE
+};
+
+static LONG MapLVToVSlider[] =
+{
+       LVA_PixelTop,           PGA_Top,
+       LVA_PixelHeight,        PGA_Total,
+       LVA_PixelVVisible,      PGA_Visible,
+       TAG_DONE
+};
+
+static LONG MapVSliderToLV[] =
+{
+       PGA_Top,        LVA_PixelTop,
+       TAG_DONE
+};
+
+
+
+static ULONG HOOKCALL LBDispatcher(
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, Msg msg))
+{
+       ASSERT_VALID_PTR(cl)
+       ASSERT_VALID_PTR(g)
+       ASSERT_VALID_PTR(msg)
+
+       switch (msg->MethodID)
+       {
+               case GM_LAYOUT:
+                       /* This method is only supported on V39 and above */
+                       LB_GMLayout(cl, g, (struct gpLayout *)msg);
+                       return TRUE;
+
+               case OM_SET:
+               case OM_UPDATE:
+                       return LB_OMSet(cl, g, (struct opUpdate *)msg);
+
+               case OM_GET:
+                       return LB_OMGet(cl, g, (struct opGet *)msg);
+
+               case OM_NEW:
+                       return LB_OMNew(cl, g, (struct opSet *)msg);
+
+               case OM_DISPOSE:
+                       LB_OMDispose(cl, g, msg);
+                       return TRUE;
+
+               default:
+                       /* Unsupported method: let our superclass's dispatcher take
+                        * a look at it. This includes all gadget methods sent
+                        * by Intuition: GM_RENDER, GM_HANDLEINPUT, GM_GOACTIVE and
+                        * GM_GOINACTIVE. These methods are automatically forwarded
+                        * to our child gadgets by the groupgclass.
+                        */
+                       DB2 (DBPRINTF("ListBoxClass: passing unknown method 0x%lx to superclass\n", msg->MethodID);)
+                       return DoSuperMethodA (cl, (Object *)g, msg);
+       }
+}
+
+
+
+static void LB_GMLayout(Class *cl, struct Gadget *g, struct gpLayout *msg)
+{
+       struct LBData *lb = (struct LBData *) INST_DATA(cl, (Object *)g);
+
+       DB(DBPRINTF("ListBoxClass: GM_LAYOUT\n");)
+       ASSERT_VALID_PTR(lb)
+
+
+       /* Collect new gadget size */
+       GetGadgetBox(msg->gpl_GInfo, (struct ExtGadget *)g, &lv->GBox);
+       IBoxToRect(&lv->GBox, &lv->GRect);
+
+
+       /* Size our children accordingly */
+       SetAttrs(lb->ListView,
+               GA_Left,        lb->GBox.Left + lb->FrameWidth / 2,
+               GA_Top,         lb->GBox.Top + lb->FrameHeight / 2,
+               GA_Width,       lb->GBox.Width - lb->FrameWidth - VSLIDER_WIDTH,
+               GA_Height,      lb->GBox.Height - lb->FrameHeight - HSLIDER_HEIGHT,
+               TAG_DONE);
+
+       if (lb->VSlider)
+               SetAttrs(lb->VSlider,
+                       GA_Left,        lb->GRect.MaxX - VSLIDER_WIDTH + 1,
+                       GA_Top,         lb->GBox.Top,
+                       GA_Width,       VSLIDER_WIDTH,
+                       GA_Height,      lb->GBox.Height,
+                       TAG_DONE);
+
+
+       /* NOTE: it seems that the groupgclass does not forward GM_LAYOUT
+        * to its children, so we must handle this here.
+        */
+       DoMethodA(lb->ListView, (Msg)msg);
+       if (lb->VSlider)        DoMethodA(lb->VSlider, (Msg)msg);
+}
+
+
+
+static ULONG LB_OMSet(Class *cl, struct Gadget *g, struct opUpdate *msg)
+{
+       struct LBData *lb = (struct LBData *) INST_DATA(cl, (Object *)g);
+
+       DB2(DBPRINTF("ListBoxClass: OM_SET\n");)
+       ASSERT_VALID_PTR(lb)
+
+       if (lb->ListView)
+               /* Forward attributes to our listview */
+               DoMethodA (lb->ListView, (Msg)msg);
+
+       /* Also forward to our superclass */
+       return DoSuperMethodA (cl, (Object *)g, (Msg) msg);
+}
+
+
+
+static ULONG LB_OMGet(Class *cl, struct Gadget *g, struct opGet *msg)
+{
+       struct LBData *lb = (struct LBData *) INST_DATA(cl, (Object *)g);
+
+       DB2(DBPRINTF("ListBoxClass: OM_GET\n");)
+       ASSERT_VALID_PTR(lb)
+
+       /* Forward this method to our listview */
+       return DoMethodA(lb->ListView, (Msg)msg);
+}
+
+
+
+static ULONG LB_OMNew(Class *cl, struct Gadget *g, struct opSet *msg)
+{
+       struct LBData   *lb;
+       struct DrawInfo *dri;
+
+
+       DB2(DBPRINTF("ListBoxClass: OM_NEW\n");)
+
+       if (g = (struct Gadget *)DoSuperMethodA(cl, (Object *)g, (Msg)msg))
+       {
+               /* Set the GMORE_SCROLLRASTER flag */
+               if (g->Flags & GFLG_EXTENDED)
+               {
+                       DB(DBPRINTF("ListBoxClass: OM_NEW: Setting GMORE_SCROLLRASTER\n");)
+                       ((struct ExtGadget *)g)->MoreFlags |= GMORE_SCROLLRASTER;
+               }
+
+               lb = (struct LBData *) INST_DATA(cl, (Object *)g);
+               ASSERT_VALID_PTR(lb)
+
+
+               /* Clear the object instance */
+               memset(lb, 0, sizeof (struct LBData));
+
+
+               /* Store a pointer to this object (a Gadget) in the class private
+                * instance. This way we can avoid passing it along to all functions.
+                */
+               /* lb->ThisGadget = g; (not used) */
+
+
+               /* May be NULL */
+               dri = (struct DrawInfo *) GetTagData(GA_DrawInfo, NULL, msg->ops_AttrList);
+
+
+               /* Create a frame to put around us */
+               if (lb->Frame = NewObject(NULL, FRAMEICLASS,
+                       IA_EdgesOnly,   TRUE,
+                       IA_FrameType,   FRAME_BUTTON,
+                       TAG_DONE))
+               {
+                       struct IBox FrameBox, ContentsBox = { 0, 0, 0, 0 };
+
+                       /* Ask the frame about its nominal frame width and height */
+                       DoMethod((Object *)lb->Frame, IM_FRAMEBOX, &ContentsBox, &FrameBox, dri, 0);
+
+                       /* Remember it later */
+                       lb->FrameWidth = FrameBox.Width;
+                       lb->FrameHeight = FrameBox.Height;
+               }
+
+               /* Create a model object. This will be the core of the boopsi attributes
+                * network used by the sub-objects to talk each other. We pass our
+                * initalization tags to the model so it will pick up the correct
+                * ICA_TARGET and ICA_MAP, if specified with NewObject().
+                */
+               if (lb->Model = NewObjectA(NULL, MODELCLASS, NULL))
+               {
+                       /* Create the ListView and pass all creation time attributes to it.
+                        * Note that any GA_#? attributes are also passed to the listview,
+                        * so it will have the same size of its container.
+                        */
+                       if (lb->ListView = NewObject(ListViewClass, NULL,
+                               GA_Image,               lb->Frame,
+                               TAG_MORE,               msg->ops_AttrList))
+                       {
+                               /* From now on, the groupgclass will dispose this object for us */
+                               DoMethod((Object *)g, OM_ADDMEMBER, lb->ListView);
+
+                               /* Connect Model to ListView */
+                               {
+                                       APTR icobject;
+
+                                       if (icobject = NewObject(NULL, ICCLASS,
+                                               ICA_TARGET,     lb->ListView,
+                                               TAG_DONE))
+                                               if (!DoMethod(lb->Model, OM_ADDMEMBER, icobject))
+                                                       DisposeObject(icobject);
+                               }
+
+                               /* Connect ListView to Model */
+                               SetAttrs(lb->ListView,
+                                       ICA_TARGET, lb->Model,
+                                       TAG_DONE);
+
+                               /* Add sliders */
+                               CreateVSlider(cl, g, lb, dri);
+                               CreateHSlider(cl, g, lb, dri);
+
+                               /* Set the gadget width and height because the groupgclass
+                                * always forces them to 0 on creation.
+                                */
+                               {
+                                       struct TagItem *tag;
+
+                                       if (tag = FindTagItem(GA_RelWidth, msg->ops_AttrList))
+                                               SetAttrs(g,
+                                                       GA_RelWidth, tag->ti_Data,
+                                                       TAG_DONE);
+                                       else
+                                               SetAttrs (g,
+                                                       GA_Width, GetTagData(GA_Width, g->Width, msg->ops_AttrList),
+                                                       TAG_DONE);
+
+                                       if (tag = FindTagItem(GA_RelHeight, msg->ops_AttrList))
+                                               SetAttrs(g,
+                                                       GA_RelHeight, tag->ti_Data,
+                                                       TAG_DONE);
+                                       else
+                                               SetAttrs(g,
+                                                       GA_Height, GetTagData (GA_Height, g->Height, msg->ops_AttrList),
+                                                       TAG_DONE);
+
+                                       DB2(DBPRINTF("ListBoxClass: OM_NEW: size set to L=%ld T=%ld W=%ld H=%ld\n",
+                                               g->LeftEdge, g->TopEdge, g->Width, g->Height);)
+                               }
+
+                               /* TODO: Handle creation-time attributes */
+
+                               return (ULONG)g;        /* Return newly created istance */
+                       }
+               }
+
+
+               /* Dispose object without disturbing the dispatchers of our sub-classes, if any */
+               CoerceMethod(cl, (Object *)g, OM_DISPOSE);
+       }
+
+       return 0;       /* Fail */
+}
+
+
+
+static void LB_OMDispose(Class *cl, struct Gadget *g, Msg msg)
+{
+       struct LBData   *lb = (struct LBData *) INST_DATA(cl, (Object *)g);
+
+       DB(DBPRINTF("ListBoxClass: OM_DISPOSE\n");)
+       ASSERT_VALID_PTR(lb)
+
+
+       DeleteHSlider(g, lb);
+       DeleteVSlider(g, lb);
+
+       /* Dispose the child objects that aren't freed automatically by the modelclass.
+        * Note that here we are disposing the Frame before we dispose the gadgets that
+        * may be still using it. Everything will go well unless those classes will
+        * access the frame within their OM_DISPOSE methods (very silly).
+        */
+       DisposeObject(lb->Model);
+       DisposeObject(lb->Frame);
+
+       /* Our superclass will cleanup everything else now */
+       DoSuperMethodA(cl, (Object *)g, (Msg) msg);
+
+       /* From now on, our instance data is no longer available */
+}
+
+
+
+static void CreateVSlider(Class *cl, struct Gadget *g, struct LBData *lb, struct DrawInfo *dri)
+{
+       if (lb->VSlider = NewObject(SLIDERBARGCLASS_PTR, NULL,
+               GA_ID,                  g->GadgetID,    /* Same as our ID */
+               GA_DrawInfo,    dri,
+               GA_LabelImage,  lb->Frame,
+               PGA_Freedom,    FREEVERT,
+               PGA_NewLook,    TRUE,
+               PGA_Borderless, TRUE,
+               LAYOUTA_Orientation, LORIENT_VERT,
+               ICA_TARGET,             lb->Model,
+               ICA_MAP,                MapVSliderToLV,
+               TAG_DONE))
+       {
+               /* From now on, the groupgclass will dispose this object for us */
+               DoMethod((Object *)g, OM_ADDMEMBER, lb->VSlider);
+
+               /* Connect Model to ListView */
+               SetAttrs(lb->Model,
+                       ICA_TARGET, lb->ListView,
+                       TAG_DONE);
+
+               /* Connect VSlider to Model */
+               if (lb->LVToVSliderIC = NewObject(NULL, ICCLASS,
+                       ICA_TARGET,     lb->VSlider,
+                       ICA_MAP,        MapLVToVSlider,
+                       TAG_DONE))
+                       if (!DoMethod(lb->Model, OM_ADDMEMBER, lb->LVToVSliderIC))
+                               DisposeObject(lb->LVToVSliderIC);
+       }
+}
+
+
+
+static void CreateHSlider(Class *cl, struct Gadget *g, struct LBData *lb, struct DrawInfo *dri)
+{
+       /* TODO */
+}
+
+
+static void DeleteVSlider(struct Gadget *g, struct LBData *lb)
+{
+       if (lb->LVToVSliderIC)
+       {
+               ASSERT_VALID_PTR(lb->LVToVSliderIC)
+               ASSERT_VALID_PTR(lb->Model)
+
+               DoMethod (lb->Model, OM_REMMEMBER, lb->LVToVSliderIC);
+               DisposeObject (lb->LVToVSliderIC);
+               lb->LVToVSliderIC = NULL;
+       }
+
+       if (lb->VSlider)
+       {
+               ASSERT_VALID_PTR(lb->VSlider)
+
+               DoMethod ((Object *)g, OM_REMMEMBER, lb->VSlider);
+               DisposeObject (lb->VSlider);
+               lb->VSlider = NULL;
+       }
+}
+
+
+
+static void DeleteHSlider(struct Gadget *g, struct LBData *lb)
+{
+       /* TODO */
+}
+
+
+
+Class *MakeListBoxClass(void)
+{
+       Class *class;
+       struct LBClassData *classdata;
+
+       if (class = MakeClass(NULL, GROUPGCLASS, NULL, sizeof (struct LBData), 0))
+       {
+               class->cl_Dispatcher.h_Entry = (ULONG (*)()) LBDispatcher;
+
+               /* Allocate storage for global class data */
+               if (classdata = AllocMem(sizeof (struct LBClassData), MEMF_PUBLIC | MEMF_CLEAR))
+               {
+                       class->cl_UserData = (ULONG) classdata;
+
+                       if (classdata->SliderBarBase = (struct ClassLibrary *)
+                               OpenLibrary("gadgets/sliderbar.gadget", 0))
+                       {
+                               classdata->SliderBarGClass = classdata->SliderBarBase->cl_Class;
+                               ASSERT_VALID_PTR(classdata->SliderBarGClass);
+
+                               return class;
+                       }
+               }
+
+               FreeListBoxClass(class);
+       }
+
+       return NULL;
+}
+
+
+
+BOOL FreeListBoxClass(Class *class)
+{
+       struct LBClassData *classdata;
+
+       if (class)
+       {
+               ASSERT_VALID_PTR(class)
+
+               classdata = (struct LBClassData *)class->cl_UserData;
+
+               /* Try to remove the class */
+               if (FreeClass(class))
+               {
+                       if (classdata)
+                       {
+                               ASSERT_VALID_PTR(classdata)
+                               ASSERT_VALID_PTR_OR_NULL(classdata->SliderBarBase)
+
+                               /* Cleanup global class data */
+
+                               /* NULL is safe in CloseLibrary() since V36 */
+                               CloseLibrary((struct Library *)classdata->SliderBarBase);
+                               FreeMem(classdata, sizeof (struct LBClassData));
+                       }
+                       return TRUE;
+               }
+               return FALSE;
+       }
+       return TRUE;
+}
diff --git a/gadgets/ListBox/Makefile b/gadgets/ListBox/Makefile
new file mode 100644 (file)
index 0000000..4b80f8e
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(TOP)/config.mk
+
+#
+# Class specific information
+#
+CLASSLIB       := listbox.gadget
+CLASSSRC       := ListBoxClass.c
+DEMOSRC                :=
+INSTALLDIR     := gadgets
+
+#
+# Class version information
+#
+CLASSVER       := 1
+CLASSREV       := 7
+CLASSDATE      := (22.8.99)
+
+#
+# variable to make the linked library version
+#
+PRV :=
+
+include $(TOP)/common/general.mk
diff --git a/gadgets/ListView/BoopsiLV.readme b/gadgets/ListView/BoopsiLV.readme
new file mode 100644 (file)
index 0000000..1b1ad8d
--- /dev/null
@@ -0,0 +1,81 @@
+Short:    Fast boopsi ListView class with many features (w/ src)
+Author:   bernardo.innocenti@usa.net (Bernardo Innocenti)
+Uploader: bernardo.innocenti@usa.net (Bernardo Innocenti)
+Type:     dev/src
+Version:  2.0
+
+ The ListBoxClass is a flexible and efficient boopsi gadget class which
+replaces the original GadTools LISTVIEW_KIND gadget and offers a lot
+more functionality. It's a subclass of the groupgclass and incorporates
+several other gadgets to build a full featured listview with vertical
+and horizontal scroll bars, a surrounding border and, of course, a
+ListView object.
+
+ The ListViewClass is a subclass of Intuition's gadgetclass which
+builds a plain listview gadget without any border or scroll bars.
+It handles selection of multiple items and it can be resized on the fly.
+The GFLG_REL#? attributes are fully supported and you can even display
+a list of images and other boopsi objects. Lists with multiple columns
+are possible but not yet implemented. Horizontal scrolling would also
+be easy to add. Usually you don't need to create objects from this class
+directly because the ListBoxClass will do it for you.
+
+ The LVDemo program demonstrates the usage of both classes. The
+ListViewClass is attached to scroll bars in the window borders.
+The demo is also a useful source of information on several
+Intuition and boopsi topics.
+
+ Three different binary versions are provided:
+
+       LVDemo_Generic
+               Works even on plain 68000 and includes OS 2.0 support
+
+       LVDemo_020_OS30
+               Optimized for 68020, no OS 2.0 support
+
+       LVDemo_Trace
+               Outputs debug messages with kprintf(), view them with
+               serial terminal or sushi
+
+
+ Some features:
+
+       + Easy to use (almost a drop-in replacement for LISTVIEW_KIND)
+       + Can be resized and supports GREL_#? flags
+       + Multiple selection of items
+       + Notifies your `boopsi' sliders
+       + Multiple columns (TODO)
+       + Redraws quickly without clearing
+         (which is good for solid window sizing)
+       + Horizontal scrolling (TODO)
+       + Items can be `boopsi' images as well as texts
+       + Using arrays instead of exec lists
+       + You can use `boopsi' label images instead of plain text
+       + You can use your own custom rendering hook
+       + You can use your own item-retriving callback hook
+       + List titles (TODO)
+       + Full Keyboard control (shift, alt and control key combos
+         are supported)
+       + Asynchronous scrolling with inertia (TODO)
+       + OS 3.0 optimized (V39-only version also available)
+       + RTG friendly and optimized (no planar stuff in chunky bitmaps)
+       + Small code size! (less then 10KB)
+       + Written in C to be highly portable across compilers and CPUs
+       + Comes with source code with detailed comments
+       + Source code compiles with SAS/C, StormC and GCC
+       + Subclasses can be easlily derived from the base listview class
+
+
+The source code shows how to:
+
+       * Build a `boopsi' class on top of the gadgetclass
+       * Build a `boopsi' class on top of the groupgclass
+       * Write a `boopsi' gadget dispatcher with complex GM_DRAW
+         and GM_HANDLEINPUT
+       * Use the `boopsi' sysiclass images
+       * Connect `boopsi' objects together using the icclass
+       * Overlay the buttongclass to make a scroll button
+       * Create a sizeable window with sliders
+       * Make a C program without startup
+       * Correctly opening/closing libraries, windows and other
+         system resources
diff --git a/gadgets/ListView/LVDemo.c b/gadgets/ListView/LVDemo.c
new file mode 100644 (file)
index 0000000..6b5c2e4
--- /dev/null
@@ -0,0 +1,1004 @@
+/*
+**     $Id: LVDemo.c,v 1.3 2000/01/12 21:17:25 bernie Exp $
+**
+**     Introduction
+**     ============
+**
+**     This program demonstrates how to use the `boopsi' ListView gadget.
+**
+**     The source code shows how to create a resizable window with sliders
+**     and how to write a custom `boopsi' class on top of the gadgetclass.
+**
+**
+**     Compiling
+**     =========
+**
+**     This project can be compiled with SAS/C 6.58 or better and
+**     GeekGadget's GCC 2.95.2 or better.
+**     You get the smallest executable with SAS/C. GCC will give
+**     you quite a lot of warnings with the tag calls. Don't worry about them.
+**
+**
+**     History
+**     =======
+**
+**     0.1 (23.6.96)   First try
+**     1.0 (21.1.97)   First alpha release
+**     1.1 (24.5.97)   Lotsa bugs fixed, implemented LVA_DoubleClick
+**     1.2 (31.8.97)   Lotsa bugs fixed, implemented LVA_Clipped
+**                                     Fixed memory leak with the test list
+**     1.3 (5.9.97)    Improved initial sliders notification
+**                                     Added multiple selection (LVA_DoMultiselect)
+**                                     Fixed scrolling problems in some unusual conditions
+**     1.4     (8.9.97)        Sets GMORE_SCROLLRASTER in OM_NEW
+**                                     Multiple demo windows showing the features of the class
+**     1.5 (14.9.97)   Added LVA_ItemSpacing
+**                                     Finally fixed the LVA_Clipped mode!
+**
+**     1.6 (2.10.97)   Added StormC support
+**                                     Implemented pixel-wise vertical scrolling for clipped mode
+**                                     Reworked the class istance data and some code
+**
+**     1.7 (15.12.98)  Added ListBoxClass
+**                                     Moved ScrollButtonClass in its own file
+**                                     Removed function OpenClass()
+**                                     Updated to latest version of VectorGlyphIClass
+**
+**
+**     Known Bugs
+**     ==========
+**
+**             - This code has never been tested on V37.
+**
+**             - Middle mouse button scrolling does not work because
+**               of a bug in input.device V40.
+**
+**
+**     Copyright Notice
+**     ================
+**
+**     Copyright © 1996,97,98,00 by Bernardo Innocenti <bernie@cosmos.it>.
+**     Freely Distributable, as long as source code, documentation and
+**     executable are kept together. Permission is granted to release
+**     modified versions of this program as long as all existing copyright
+**     notices are left intact.
+**
+*/
+
+#define USE_BUILTIN_MATH
+#define INTUI_V36_NAMES_ONLY
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H    /* Avoid including this header file because of
+                                                        * conflicting definitions in BoopsiStubs.h
+                                                        */
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <exec/execbase.h>
+
+#include <dos/dos.h>
+
+#include <intuition/intuition.h>
+#include <intuition/intuitionbase.h>
+#include <intuition/screens.h>
+#include <intuition/classes.h>
+#include <intuition/gadgetclass.h>
+#include <intuition/imageclass.h>
+#include <intuition/icclass.h>
+#include <devices/timer.h>
+
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <proto/dos.h>
+#include <proto/utility.h>
+#include <proto/graphics.h>
+#include <proto/diskfont.h>
+
+#ifdef __STORM__
+       #pragma header
+#endif
+
+#include <gadgets/ScrollButtonClass.h>
+#include <gadgets/ListViewClass.h>
+//#include <gadgets/ListBoxClass.h>
+#include <images/VectorGlyphIClass.h>
+
+#include "CompilerSpecific.h"
+#include "DebugMacros.h"
+#include "BoopsiStubs.h"
+#include "ListMacros.h"
+
+
+/* Local function prototypes */
+
+LONG SAVEDS                                     main                           (void);
+static struct MsgPort          *OpenDemoWindows        (struct List *winlist);
+static void                                     CloseDemoWindows       (struct List *winlist);
+static struct LVHandle         *OpenLVWin                      (CONST_STRPTR pubscreen,
+       struct MsgPort *winport, CONST_STRPTR title, ULONG mode, BOOL useListBox,
+       ULONG left, ULONG top, ULONG width, ULONG height, ULONG moreTags, ...);
+static void                                     CloseLVWin                     (struct LVHandle *lvhandle);
+static struct Gadget           *CreateLVGadgets        (struct LVHandle *lvhandle,
+       struct TagItem *moreTags);
+static void                                     DisposeGadgets         (struct LVHandle *lvhandle);
+static void                                     CreateItems            (struct LVHandle *lvhandle);
+static void                                     CreateImages           (struct DrawInfo *dri);
+static void                                     FreeImages                     (void);
+
+
+/* Width and height for the demo vector images */
+#define IMAGES_WIDTH   56
+#define IMAGES_HEIGHT  48
+
+
+/* Gadgets IDs */
+enum
+{
+       GAD_LV, GAD_VSLIDER, GAD_HSLIDER,
+       GAD_UPBUTTON, GAD_DOWNBUTTON, GAD_LEFTBUTTON, GAD_RIGHTBUTTON,
+       GAD_COUNT
+};
+
+
+/* Images IDs */
+enum
+{
+       IMG_UP, IMG_DOWN, IMG_LEFT, IMG_RIGHT, IMG_COUNT
+};
+
+
+
+
+/* This structure describes an open ListView window */
+struct LVHandle
+{
+       struct MinNode   Link;                  /* Link LVHandle in a list of all windows       */
+       struct Window   *Win;                   /* Pointer to our window                                        */
+       struct Screen   *Scr;                   /* The screen we are opening our windows on     */
+       struct DrawInfo *DrawInfo;              /* DrawInfo for this screen                             */
+       ULONG                    Mode;                  /* ListView operating mode                                      */
+       APTR                     Items;                 /* Items attached to the ListView                       */
+       ULONG                    Total;                 /* Number of items or -1 if unknown                     */
+       struct Gadget   *Gad[GAD_COUNT];/* All our gadgets                                                      */
+       APTR                     Model;                 /* Make boopsi gadgets talk to each other       */
+       struct List              TestList;              /* Items list for LVA_#?List modes                      */
+       ULONG                   *SelectArray;   /* Array for storing multiple selections        */
+       BOOL                     UseListBox;    /* If TRUE, window uses the ListBox class       */
+};
+
+
+
+/* Version tag */
+
+UBYTE versiontag[] = "$VER: ListViewDemo 1.7 (15.12.98) by Bernardo Innocenti"
+       " (compiled with " _COMPILED_WITH ")";
+
+
+
+/* Workaround a bug in StormC header file <proto/utility.h> */
+
+#ifdef __STORM__
+       #define UTILITYBASETYPE struct Library
+#else
+       #define UTILITYBASETYPE struct UtilityBase
+#endif
+
+/* Library bases */
+struct ExecBase                                *SysBase;
+UTILITYBASETYPE                                *UtilityBase;
+struct IntuitionBase           *IntuitionBase;
+struct GfxBase                         *GfxBase;
+struct Library                         *LayersBase;
+struct Library                         *DiskfontBase;
+
+
+/* Our private `boopsi' classes */
+Class                                          *ListViewClass;
+//static Class                         *ListBoxClass;
+static Class                           *ScrollButtonClass;
+
+
+/* `boopsi' images for all windows
+ *
+ * These variables must be NULL at startup time. We are not
+ * going to explicitly initialize them because otherwise
+ * Storm C 2.0 would generate a C++-style constructor to do it :-).
+ * LoasSeg() will clear the BSS data section for us, so these
+ * variables are guaranteed to be NULL anyway.
+ */
+static struct Image            *Img[IMG_COUNT];
+static ULONG                    ImgWidth[IMG_COUNT];
+static ULONG                    ImgHeight[IMG_COUNT];
+static struct TextFont *CustomFont;
+
+
+
+/* Attribute translations for object interconnections */
+
+static LONG MapLVToHSlider[] =
+{
+       LVA_PixelLeft,          PGA_Top,
+       LVA_PixelWidth,         PGA_Total,
+       LVA_PixelHVisible,      PGA_Visible,
+       TAG_DONE
+};
+
+static LONG MapHSliderToLV[] =
+{
+       PGA_Top,                        LVA_PixelLeft,
+       TAG_DONE
+};
+
+/*
+static LONG MapLVToVSlider[] =
+{
+       LVA_Top,                        PGA_Top,
+       LVA_Total,                      PGA_Total,
+       LVA_Visible,            PGA_Visible,
+       TAG_DONE
+};
+*/
+
+static LONG MapLVToVSlider[] =
+{
+       LVA_PixelTop,           PGA_Top,
+       LVA_PixelHeight,        PGA_Total,
+       LVA_PixelVVisible,      PGA_Visible,
+       TAG_DONE
+};
+
+
+/*
+static LONG MapVSliderToLV[] =
+{
+       PGA_Top,        LVA_Top,
+       TAG_DONE
+};
+*/
+
+static LONG MapVSliderToLV[] =
+{
+       PGA_Top,        LVA_PixelTop,
+       TAG_DONE
+};
+
+
+
+static LONG MapUpButtonToLV[] =
+{
+       GA_ID,          LVA_MoveUp,
+       TAG_DONE
+};
+
+static LONG MapDownButtonToLV[] =
+{
+       GA_ID,          LVA_MoveDown,
+       TAG_DONE
+};
+
+static LONG MapLeftButtonToLV[] =
+{
+       GA_ID,          LVA_MoveLeft,
+       TAG_DONE
+};
+
+static LONG MapRightButtonToLV[] =
+{
+       GA_ID,          LVA_MoveRight,
+       TAG_DONE
+};
+
+
+
+/* Test Strings */
+
+/* StormC does not see that the expression "versiontag + 6" is constant
+ * and generates an initializer for it. The following definition
+ * works around this problem.
+ */
+#ifdef __STORM__
+       #define VERSIONTAG "ListViewDemo 1.7 by Bernardo Innocenti (compiled with " _COMPILED_WITH ")"
+#else
+       #define VERSIONTAG versiontag + 6
+#endif
+
+static STRPTR TestStrings[] =
+{
+       VERSIONTAG,
+       NULL,
+       "This `boopsi' ListView class supports all the features",
+       "of the Gadtools LISTVIEW_KIND, plus more stuff:",
+       NULL,
+       " + Easy to use (almost a drop-in replacement for LISTVIEW_KIND)",
+       " + Can be resized and supports GREL_#? flags",
+       " + Multiple selection of items",
+       " + Notifies your `boopsi' sliders",
+       " + Multiple columns (TODO)",
+       " + Redraws quickly without clearing (which is good for solid window sizing)",
+       " + Horizontal scrolling (TODO)",
+       " + Items with `boopsi' images",
+       " + Using arrays instead of exec lists",
+       " + You can use `boopsi' label images instead of plain text",
+       " + You can use your own custom rendering hook",
+       " + You can use your own item item-retriving callback hook",
+       " + List title (TODO)",
+       " + Full Keyboard control (all control, alt and shift key combinations supported)",
+       " + Asynchronous scrolling with inertia (TODO)",
+       " + OS 3.0 optimized (V39-only version also available)",
+       " + RTG friendly and optimized (no planar stuff in chunky bitmaps)",
+       " + Small code! (<10K)",
+       " + Written in C to be highly portable across compilers and CPUs",
+       " + Full commented source code included",
+       " + Source code compiles with SAS/C, StormC and GCC",
+       " + Subclasses can be easlily derived from the base listview class",
+       NULL,
+       "Please send comments to <bernardo.innocenti@usa.net>."
+};
+
+#define TESTSTRINGS_CNT (sizeof (TestStrings) / sizeof (CONST_STRPTR))
+
+
+
+LONG SAVEDS _main(void)
+
+/* Main program entry point.  When linking without startup code, this
+ * must be the first function in the first object module listed on the
+ * linker command line.  We also need to initialize SysBase and open
+ * all needed libraries manually.
+ */
+{
+       struct MinList   winlist;
+       struct MsgPort  *winport;
+       struct Library  *VectorGlyphBase = NULL;
+       LONG                     sigwait, sigrcvd;
+       LONG                     retval = RETURN_FAIL;  /* = RETURN_FAIL */
+       BOOL                     quit   = FALSE;
+
+
+       /* Initialize SysBase */
+       SysBase = *((struct ExecBase **)4UL);
+
+       /* Open system libraries */
+
+       if ((UtilityBase = (UTILITYBASETYPE *) OpenLibrary("utility.library", 37L)) &&
+               (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39L)) &&
+               (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39L)) &&
+               (LayersBase = OpenLibrary("layers.library", 39L)))
+       {
+               if ((ListViewClass = MakeListViewClass()) &&
+//                     (ListBoxClass = MakeListBoxClass()) &&
+                       (ScrollButtonClass = MakeScrollButtonClass()) &&
+                       (VectorGlyphBase = OpenLibrary("images/vectorglyph.image", 0)))
+               {
+                       NEWLIST((struct List *)&winlist);
+
+                       if (winport = OpenDemoWindows((struct List *)&winlist))
+                       {
+                               /* Pre-calculate the signal mask for Wait() */
+                               sigwait = (1 << winport->mp_SigBit) |
+                                       SIGBREAKF_CTRL_C;
+
+                               /* Now for the main loop.  As you can see, it is really
+                                * very compact.  That's the magic of boopsi! :-)
+                                */
+                               while (!quit)
+                               {
+                                       /* Sleep until something interesting occurs */
+                                       sigrcvd = Wait(sigwait);
+
+                                       /* Now handle received signals */
+
+                                       /* Break signal? */
+                                       if (sigrcvd & SIGBREAKF_CTRL_C)
+                                               quit = TRUE;
+
+                                       /* IDCMP message? */
+                                       if (sigrcvd & (1 << winport->mp_SigBit))
+                                       {
+                                               struct IntuiMessage     *msg;
+
+                                               while (msg = (struct IntuiMessage *) GetMsg(winport))
+                                               {
+                                                       switch (msg->Class)
+                                                       {
+                                                               case IDCMP_CLOSEWINDOW:
+                                                                       quit = TRUE;
+                                                                       break;
+
+                                                               default:
+                                                                       break;
+                                                       }
+                                                       ReplyMsg((struct Message *) msg);
+                                               }
+                                       }
+                               } /* End while (!quit) */
+
+                               retval = 0;     /* RETURN_OK */
+
+                               CloseDemoWindows((struct List *)&winlist);
+                       }
+
+                       FreeImages ();
+               }
+
+               /* These cannot fail. Passing NULL is ok. */
+               CloseLibrary((struct Library *)VectorGlyphBase);
+               FreeScrollButtonClass(ScrollButtonClass);
+//             FreeListBoxClass(ListBoxClass);
+               FreeListViewClass(ListViewClass);
+       }
+
+       /* Passing NULL to CloseLibrary() was illegal in pre-V37 Exec.
+        * To avoid crashing when someone attempts to run this program
+        * on an old OS, we need to test the first library base we tried
+        * to open.
+        */
+       if (UtilityBase)
+       {
+               CloseLibrary((struct Library *)LayersBase);
+               CloseLibrary((struct Library *)GfxBase);
+               CloseLibrary((struct Library *)IntuitionBase);
+               CloseLibrary((struct Library *)UtilityBase);
+       }
+
+       return retval;
+}
+
+
+
+static struct MsgPort *OpenDemoWindows(struct List *winlist)
+{
+       struct LVHandle *lvhandle;
+       struct MsgPort  *winport;
+
+       if (DiskfontBase = OpenLibrary("diskfont.library", 0L))
+       {
+               static struct TextAttr attr =
+               {
+                       "times.font",
+                       24,
+                       FSB_ITALIC,
+                       0
+               };
+
+               CustomFont = OpenDiskFont(&attr);
+               CloseLibrary(DiskfontBase);
+       }
+
+       /* Setup windows shared Message Port */
+       if (winport = CreateMsgPort())
+       {
+/*             if (lvhandle = OpenLVWin(NULL, winport,
+                       "ListBox test",
+                       LVA_StringList,         TRUE, 600, 20, 320, 128,
+                       TAG_DONE))
+                       ADDTAIL(winlist, (struct Node *)lvhandle);
+*/
+/*             if (lvhandle = OpenLVWin(NULL, winport,
+                       "LVA_TextFont = times/24/italic, LVA_Clipped = TRUE",
+                       LVA_StringList,         FALSE, 320, 320, 320, 64,
+                       LVA_TextFont,           CustomFont,
+                       LVA_Clipped,            TRUE,
+                       TAG_DONE))
+                       ADDTAIL(winlist, (struct Node *)lvhandle);
+*/
+/*             if (lvhandle = OpenLVWin(NULL, winport,
+                       "LAYOUTA_Spacing = 4",
+                       LVA_StringList,         FALSE, 256, 256, 320, 64,
+                       LAYOUTA_Spacing,        4,
+                       TAG_DONE))
+                       ADDTAIL(winlist, (struct Node *)lvhandle);
+*/
+/*             if (lvhandle = OpenLVWin(NULL, winport,
+                       "GA_ReadOnly = TRUE; LVA_Selected = 3",
+                       LVA_StringList, FALSE, 192, 192, 320, 64,
+                       GA_ReadOnly,            TRUE,
+                       LVA_Selected,           3,
+                       TAG_DONE))
+                       ADDTAIL(winlist, (struct Node *)lvhandle);
+*/
+               if (lvhandle = OpenLVWin(NULL, winport,
+                       "Single selection image list, LVA_Clipped = TRUE",
+                       LVA_ImageList, FALSE, 128, 128, 320, 128,
+                       LVA_ItemHeight,         IMAGES_HEIGHT,
+                       LVA_Clipped,            TRUE,
+                       TAG_DONE))
+                       ADDTAIL(winlist, (struct Node *)lvhandle);
+/*
+               if (lvhandle = OpenLVWin(NULL, winport,
+                       "LVA_DoMultiSelect = TRUE; LVA_StringArray",
+                       LVA_StringArray,        FALSE, 64, 64, 320, 128,
+                       LVA_DoMultiSelect,      TRUE,
+                       TAG_DONE))
+                       ADDTAIL(winlist, (struct Node *)lvhandle);
+*/
+/*             if (lvhandle = OpenLVWin(NULL, winport,
+                       "Plain, single selection string list",
+                       LVA_StringList,         FALSE, 0, 20, 320, 128,
+                       TAG_DONE))
+                       ADDTAIL(winlist, (struct Node *)lvhandle);
+*/
+               /* Abort only if no windows could be opened */
+               if (IsListEmpty(winlist))
+               {
+                       DeleteMsgPort(winport);
+                       CloseFont (CustomFont);
+                       return NULL;
+               }
+       }
+
+       return winport;
+}
+
+
+
+static void CloseDemoWindows(struct List *winlist)
+{
+       struct MsgPort  *winport = NULL;
+       struct LVHandle *lvhandle;
+
+       while (lvhandle = (struct LVHandle *) REMHEAD(winlist))
+       {
+               /* Safe way to close a shared IDCMP port window */
+
+               Forbid();
+               {
+                       struct Node *succ;
+                       struct Message *msg;
+
+                       winport = lvhandle->Win->UserPort;
+                       msg = (struct Message *) winport->mp_MsgList.lh_Head;
+
+                       /* Now remove any pending message from the shared IDCMP port */
+                       while (succ = msg->mn_Node.ln_Succ)
+                       {
+                               /* Since we are closing all our windows at once,
+                                * we don't need to check to which window this
+                                * message was addressed.
+                                */
+                               REMOVE((struct Node *)msg);
+                               ReplyMsg (msg);
+                               msg = (struct Message *) succ;
+                       }
+
+                       /* Keep intuition from freeing our port... */
+                       lvhandle->Win->UserPort = NULL;
+
+                       /* ...and from sending us any more messages. */
+                       ModifyIDCMP(lvhandle->Win, 0L);
+               }
+               Permit();
+
+               CloseLVWin(lvhandle);
+       }
+
+       DeleteMsgPort(winport); /* NULL is ok */
+
+       if (CustomFont)
+               CloseFont(CustomFont);
+}
+
+
+
+
+static struct LVHandle *OpenLVWin(CONST_STRPTR pubscreen,
+       struct MsgPort *winport, CONST_STRPTR title, ULONG mode, BOOL useListBox,
+       ULONG left, ULONG top, ULONG width, ULONG height, ULONG moreTags, ...)
+{
+       struct LVHandle *lvhandle;
+       struct Gadget   *glist;
+
+       if (lvhandle = AllocMem(sizeof (struct LVHandle), MEMF_ANY | MEMF_CLEAR))
+       {
+               if (lvhandle->Scr = LockPubScreen(pubscreen))
+               {
+                       /* GetScreenDrawInfo() never fails */
+                       lvhandle->DrawInfo = GetScreenDrawInfo(lvhandle->Scr);
+
+                       /* Set listview operating mode and ListBox flag */
+                       lvhandle->Mode                  = mode;
+                       lvhandle->UseListBox    = useListBox;
+
+                       CreateItems (lvhandle);
+
+                       if (glist = CreateLVGadgets(lvhandle, (struct TagItem *)&moreTags))
+                       {
+                               if (lvhandle->Win = OpenWindowTags(NULL,
+                                       WA_Top,                         top,
+                                       WA_Left,                        left,
+                                       WA_InnerWidth,          width,
+                                       WA_InnerHeight,         height,
+                                       WA_PubScreen,           lvhandle->Scr,
+                                       WA_Gadgets,                     glist,
+                                       WA_Title,                       title,
+                                       /* Since we are going to redraw the whole window anyway,
+                                        * we can disable backfilling to avoid flashes while
+                                        * resizing or revealing the window.
+                                        */
+                                       WA_BackFill,            useListBox ? NULL : LAYERS_NOBACKFILL,
+                                       WA_ScreenTitle,         versiontag + 6,
+                                       WA_Flags,                       WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM |
+                                                                               WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH | WFLG_NOCAREREFRESH,
+                                       WA_PubScreenFallBack, TRUE,
+                                       WA_AutoAdjust,          TRUE,
+                                       WA_MinWidth,            64,
+                                       WA_MinHeight,           64,
+                                       WA_MaxWidth,            -1,
+                                       WA_MaxHeight,           -1,
+                                       TAG_DONE))
+                               {
+                                       lvhandle->Win->UserPort = winport;
+                                       ModifyIDCMP(lvhandle->Win, IDCMP_CLOSEWINDOW);
+
+                                       /* We need to keep our screen locked all the time
+                                        * because we want to free the associated DrawInfo
+                                        * *after* the window has been closed and
+                                        * FreeScreenDrawInfo() wants a pointer to a *valid*
+                                        * Screen.
+                                        */
+                                       return lvhandle;
+                               }
+
+                               DisposeGadgets(lvhandle);
+                       }
+
+                       FreeScreenDrawInfo(lvhandle->Scr, lvhandle->DrawInfo);
+                       /* lvhandle->DrawInfo = NULL */
+
+                       UnlockPubScreen(NULL, lvhandle->Scr);
+               }
+               FreeMem(lvhandle, sizeof(struct LVHandle));
+       }
+       return NULL;
+}
+
+
+
+static void CloseLVWin(struct LVHandle *lvhandle)
+{
+       /* Close our window. No need to reply queued messages,
+        * Intuition is clever enough to care about this for us.
+        */
+       CloseWindow(lvhandle->Win);
+       DisposeGadgets(lvhandle);
+       UnlockPubScreen(NULL, lvhandle->Scr);
+
+       FreeVec(lvhandle->SelectArray); /* NULL is ok */
+
+       if ((lvhandle->Mode == LVA_StringList) || (lvhandle->Mode == LVA_ImageList))
+       {
+               struct Node *node;
+
+               /* Free the test list */
+               while (node = REMHEAD (&lvhandle->TestList))
+               {
+                       if (lvhandle->Mode == LVA_ImageList)
+                               DisposeObject ((Object *)node->ln_Name);
+                       FreeMem (node, sizeof (struct Node));
+               }
+       }
+
+       FreeMem (lvhandle, sizeof (struct LVHandle));
+}
+
+
+
+/*     Diagram of object interconnections for the ListView window
+ *     ==========================================================
+ *
+ *                ScrollButtonClass objects
+ *     +----------+ +------------+ +------------+ +-------------+
+ *     | UpButton | | DownButton | | LeftButton | | RightButton |
+ *     +----------+ +------------+ +------------+ +-------------+
+ *      | GA_ID =     | GA_ID =       | GA_ID =       | GA_ID =
+ *      | LVA_MoveUp  | LVA_MoveDown  | LVA_MoveLeft  | LVA_MoveRight
+ *      |             |               |               |
+ *      |  +----------+               |               |
+ *      |  |  +-----------------------+               |
+ *      |  |  |  +------------------------------------+
+ *      |  |  |  |        propgclass object     icclass object
+ *      |  |  |  |          +-----------+      +--------------+
+ *      |  |  |  |          |  HSlider  |<-----| PIPToHSlider |
+ *      |  |  |  |          +-----------+      +--------------+
+ *      |  |  |  |     PGA_Top =  |                 ^ LVA_Top  = PGA_Top
+ *      |  |  |  |     LVA_Left   |                 | LVA_Visible = PGA_Visible
+ *      |  |  |  |                |                 |
+ *      V  V  V  V                V                 |
+ *     +-----------+         ***********            |
+ *     |           |-------->*         *------------+
+ *     | ListView  |         *  Model  *
+ *     |           |<--------*         *------------+
+ *     +-----------+         ***********            |
+ *                                ^                 |
+ *                    PGA_Top =   |                 |
+ *                    LVA_Top     |                 V  icclass object
+ *                          +-----------+      +--------------+
+ *                          |  VSlider  |<-----| PIPToVSlider |
+ *                          +-----------+      +--------------+
+ *                        propgclass object     LVA_Top     = PGA_Top
+ *                                              LVA_Visible = PGA_Visible
+ */
+
+static struct Gadget *CreateLVGadgets(struct LVHandle *lvhandle,
+       struct TagItem *moreTags)
+{
+       struct Screen   *scr = lvhandle->Scr;
+       ULONG SizeWidth = 18, SizeHeight = 11;  /* Default size */
+       struct Image    *SizeImage;
+
+       /* Create a size image to get its... uhm... size */
+       if (SizeImage = NewObject(NULL, SYSICLASS,
+               SYSIA_Which,    SIZEIMAGE,
+               SYSIA_DrawInfo, lvhandle->DrawInfo,
+               TAG_DONE))
+       {
+               /* Get size gadget geometry */
+               GetAttr(IA_Width, SizeImage, &SizeWidth);
+               GetAttr(IA_Height, SizeImage, &SizeHeight);
+
+               /* And then get rid of it... */
+               DisposeObject(SizeImage);
+       }
+
+
+/*     if (lvhandle->UseListBox)
+       {
+               lvhandle->Gad[GAD_LV] = NewObject(ListBoxClass, NULL,
+                       GA_ID,                          GAD_LV,
+                       GA_Left,                        scr->WBorLeft,
+                       GA_Top,                         scr->WBorTop + scr->Font->ta_YSize + 1,
+                       GA_RelWidth,            - SizeWidth - scr->WBorLeft,
+                       GA_RelHeight,           - (scr->WBorTop + scr->Font->ta_YSize + SizeHeight + 1),
+                       GA_DrawInfo,            lvhandle->DrawInfo,
+                       lvhandle->Mode,         lvhandle->Items,
+                       LVA_Total,                      lvhandle->Total,
+                       LVA_SelectArray,        lvhandle->SelectArray,
+                       TAG_MORE,                       moreTags);
+
+               return lvhandle->Gad[GAD_LV];
+       }
+*/
+
+       /* Code to create normal ListView class and its gadgets */
+
+
+       /* No need to check this: in case of failure we would just
+        * get no images in the scroll buttons, but we can still try
+        * to open our window anyway.
+        */
+       CreateImages(lvhandle->DrawInfo);
+
+       if (lvhandle->Model = NewObjectA(NULL, MODELCLASS, NULL))
+               if (lvhandle->Gad[GAD_LV] = NewObject(ListViewClass, NULL,
+                       GA_ID,                          GAD_LV,
+                       GA_Left,                        scr->WBorLeft,
+                       GA_Top,                         scr->WBorTop + scr->Font->ta_YSize + 1,
+                       GA_RelWidth,            - SizeWidth - scr->WBorLeft,
+                       GA_RelHeight,           - (scr->WBorTop + scr->Font->ta_YSize + SizeHeight + 1),
+                       GA_DrawInfo,            lvhandle->DrawInfo,
+                       ICA_TARGET,                     lvhandle->Model,
+                       lvhandle->Mode,         lvhandle->Items,
+                       LVA_Total,                      lvhandle->Total,
+                       LVA_SelectArray,        lvhandle->SelectArray,
+                       TAG_MORE,                       moreTags))
+                       if (lvhandle->Gad[GAD_VSLIDER] = NewObject(NULL, PROPGCLASS,
+                               GA_ID,                  GAD_VSLIDER,
+                               GA_Previous,    lvhandle->Gad[GAD_LV],
+                               GA_RelRight,    - SizeWidth + 5,
+                               GA_Top,                 scr->WBorTop + scr->Font->ta_YSize + 2,
+                               GA_Width,               SizeWidth - 8,
+                               GA_RelHeight,   - (scr->WBorTop + scr->Font->ta_YSize +
+                                                               SizeHeight + ImgHeight[IMG_DOWN] + ImgHeight[IMG_UP] + 4),
+                               GA_RightBorder, TRUE,
+                               GA_DrawInfo,    lvhandle->DrawInfo,
+                               PGA_Freedom,    FREEVERT,
+                               PGA_Borderless, ((lvhandle->DrawInfo->dri_Flags & DRIF_NEWLOOK) &&
+                                                                (lvhandle->DrawInfo->dri_Depth != 1)),
+                               PGA_NewLook,    TRUE,
+                               ICA_TARGET,             lvhandle->Model,
+                               ICA_MAP,                MapVSliderToLV,
+                               TAG_DONE))
+                               if (lvhandle->Gad[GAD_HSLIDER] = NewObject(NULL, PROPGCLASS,
+                                       GA_ID,                  GAD_HSLIDER,
+                                       GA_Previous,    lvhandle->Gad[GAD_VSLIDER],
+                                       GA_RelBottom,   - SizeHeight + ((SizeHeight > 15) ? 4 : 3),
+                                       GA_Left,                scr->WBorLeft,
+                                       GA_Height,              SizeHeight - ((SizeHeight > 15)  ? 6 : 4),
+                                       GA_RelWidth,    - (SizeWidth + ImgWidth[IMG_RIGHT] + ImgWidth[IMG_LEFT] + scr->WBorLeft + 2),
+                                       GA_BottomBorder,TRUE,
+                                       GA_DrawInfo,    lvhandle->DrawInfo,
+                                       PGA_Freedom,    FREEHORIZ,
+                                       PGA_Borderless, ((lvhandle->DrawInfo->dri_Flags & DRIF_NEWLOOK) &&
+                                                                        (lvhandle->DrawInfo->dri_Depth != 1)),
+                                       PGA_NewLook,    TRUE,
+                                       ICA_TARGET,             lvhandle->Model,
+                                       ICA_MAP,                MapHSliderToLV,
+                                       TAG_DONE))
+                                       if (lvhandle->Gad[GAD_UPBUTTON] = NewObject(ScrollButtonClass, NULL,
+                                               GA_ID,                  GAD_UPBUTTON,
+                                               GA_Previous,    lvhandle->Gad[GAD_HSLIDER],
+                                               GA_RelBottom,   - SizeHeight - ImgHeight[IMG_DOWN] - ImgHeight[IMG_UP] + 1,
+                                               GA_RelRight,    - ImgWidth[IMG_DOWN] + 1,
+                                               GA_RightBorder, TRUE,
+                                               GA_DrawInfo,    lvhandle->DrawInfo,
+                                               GA_Image,               Img[IMG_UP],
+                                               ICA_TARGET,             lvhandle->Gad[GAD_LV],
+                                               ICA_MAP,                MapUpButtonToLV,
+                                               TAG_DONE))
+                                               if (lvhandle->Gad[GAD_DOWNBUTTON] = NewObject(ScrollButtonClass, NULL,
+                                                       GA_ID,                  GAD_DOWNBUTTON,
+                                                       GA_Previous,    lvhandle->Gad[GAD_UPBUTTON],
+                                                       GA_RelBottom,   - SizeHeight - ImgHeight[IMG_DOWN] + 1,
+                                                       GA_RelRight,    - ImgWidth[IMG_DOWN] + 1,
+                                                       GA_RightBorder, TRUE,
+                                                       GA_DrawInfo,    lvhandle->DrawInfo,
+                                                       GA_Image,               Img[IMG_DOWN],
+                                                       ICA_TARGET,             lvhandle->Gad[GAD_LV],
+                                                       ICA_MAP,                MapDownButtonToLV,
+                                                       TAG_DONE))
+                                                       if (lvhandle->Gad[GAD_LEFTBUTTON] = NewObject(ScrollButtonClass, NULL,
+                                                               GA_ID,                  GAD_LEFTBUTTON,
+                                                               GA_Previous,    lvhandle->Gad[GAD_DOWNBUTTON],
+                                                               GA_RelBottom,   - ImgHeight[IMG_LEFT] + 1,
+                                                               GA_RelRight,    - SizeWidth - ImgWidth[IMG_RIGHT] - ImgWidth[IMG_LEFT] + 1,
+                                                               GA_BottomBorder,TRUE,
+                                                               GA_DrawInfo,    lvhandle->DrawInfo,
+                                                               GA_Image,               Img[IMG_LEFT],
+                                                               ICA_TARGET,             lvhandle->Gad[GAD_LV],
+                                                               ICA_MAP,                MapLeftButtonToLV,
+                                                               TAG_DONE))
+                                                               if (lvhandle->Gad[GAD_RIGHTBUTTON] = NewObject(ScrollButtonClass, NULL,
+                                                                       GA_ID,                  GAD_RIGHTBUTTON,
+                                                                       GA_Previous,    lvhandle->Gad[GAD_LEFTBUTTON],
+                                                                       GA_RelBottom,   - ImgHeight[IMG_RIGHT] + 1,
+                                                                       GA_RelRight,    - SizeWidth - ImgWidth[IMG_RIGHT] + 1,
+                                                                       GA_BottomBorder,TRUE,
+                                                                       GA_DrawInfo,    lvhandle->DrawInfo,
+                                                                       GA_Image,               Img[IMG_RIGHT],
+                                                                       ICA_TARGET,             lvhandle->Gad[GAD_LV],
+                                                                       ICA_MAP,                MapRightButtonToLV,
+                                                                       TAG_DONE))
+                                                                       {
+                                                                               APTR icobject;
+
+                                                                               /* Connect VSlider to Model */
+
+                                                                               if (icobject = NewObject(NULL, ICCLASS,
+                                                                                       ICA_TARGET,     lvhandle->Gad[GAD_VSLIDER],
+                                                                                       ICA_MAP,        MapLVToVSlider,
+                                                                                       TAG_DONE))
+                                                                                       if (!DoMethod(lvhandle->Model, OM_ADDMEMBER, icobject))
+                                                                                               DisposeObject (icobject);
+
+                                                                               /* Connect HSlider to Model */
+
+                                                                               if (icobject = NewObject(NULL, ICCLASS,
+                                                                                       ICA_TARGET,     lvhandle->Gad[GAD_HSLIDER],
+                                                                                       ICA_MAP,        MapLVToHSlider,
+                                                                                       TAG_DONE))
+                                                                                       if (!DoMethod(lvhandle->Model, OM_ADDMEMBER, icobject))
+                                                                                               DisposeObject (icobject);
+
+                                                                               /* Connect Model to ListView */
+
+                                                                               SetAttrs(lvhandle->Model,
+                                                                                       ICA_TARGET, lvhandle->Gad[GAD_LV],
+                                                                                       TAG_DONE);
+
+                                                                               return lvhandle->Gad[GAD_LV];
+                                                                       }
+       DisposeGadgets(lvhandle);
+
+       return NULL;
+}
+
+
+
+static void DisposeGadgets(struct LVHandle *lvhandle)
+{
+       ULONG i;
+
+       for (i = 0; i < GAD_COUNT; i++)
+       {
+               DisposeObject(lvhandle->Gad[i]);
+               /* lvhandle->Gad[i] = NULL; */
+       }
+
+       /* Freeing the Model will also free its two targets */
+       DisposeObject(lvhandle->Model);
+       /* lvhandle->Model = NULL */
+}
+
+
+
+static void CreateItems(struct LVHandle *lvhandle)
+{
+       if ((lvhandle->Mode == LVA_StringList) || (lvhandle->Mode == LVA_ImageList))
+       {
+               struct Node             *node;
+               ULONG                    i, cnt;
+
+
+               if (lvhandle->Mode == LVA_StringList)
+                       cnt = TESTSTRINGS_CNT;
+               else /* LVA_ImageList */
+                       cnt = VG_IMGCOUNT * 8;
+
+
+               /* Build a list of nodes to test the list */
+
+               NEWLIST(&lvhandle->TestList);
+
+               for (i = 0; i < cnt; i++)
+               {
+                       if (node = AllocMem(sizeof (struct Node), MEMF_PUBLIC))
+                       {
+                               if (lvhandle->Mode == LVA_StringList)
+                                       node->ln_Name = TestStrings[i];
+                               else
+                                       node->ln_Name = (STRPTR) NewObject(NULL, VECTORGLYPHCLASS,
+                                               SYSIA_Which,    i % VG_IMGCOUNT,
+                                               SYSIA_DrawInfo, lvhandle->DrawInfo,
+                                               IA_Width,               IMAGES_WIDTH,
+                                               IA_Height,              IMAGES_HEIGHT,
+                                               TAG_DONE);
+
+                               /* Unselect all items */
+                               node->ln_Type = 0;
+
+                               ADDTAIL (&lvhandle->TestList, node);
+
+                               lvhandle->Total++;
+                       }
+               }
+
+               lvhandle->Items = &lvhandle->TestList;
+       }
+       else if (lvhandle->Mode == LVA_StringArray)
+       {
+               lvhandle->Items = TestStrings;
+               lvhandle->Total = TESTSTRINGS_CNT;
+               lvhandle->SelectArray = AllocVec (TESTSTRINGS_CNT * sizeof (ULONG),
+                       MEMF_CLEAR | MEMF_PUBLIC);
+       }
+       else /* (lvhandle->Mode == LVA_ImageArray) */
+       {
+               lvhandle->Items = NULL; /* No items     */
+               lvhandle->Total = -1;   /* Unknown      */
+       }
+}
+
+
+
+static void CreateImages(struct DrawInfo *dri)
+
+/* Create 4 arrow images for the window scroll buttons.
+ *
+ * Why bother checking for failure? The arrow images are not
+ * life critical in our program...
+ */
+{
+       static ULONG imagetypes[IMG_COUNT] = { UPIMAGE, DOWNIMAGE, LEFTIMAGE, RIGHTIMAGE };
+       ULONG i;
+
+       for (i = 0; i < IMG_COUNT; i++)
+               if (!Img[i])
+                       if (Img[i] = (struct Image *)NewObject (NULL, SYSICLASS,
+                               SYSIA_Which,    imagetypes[i],
+                               SYSIA_DrawInfo, dri,
+                               TAG_DONE))
+                       {
+                               /* Ask image width and height */
+                               GetAttr(IA_Width, Img[i], &ImgWidth[i]);
+                               GetAttr(IA_Height, Img[i], &ImgHeight[i]);
+                       }
+}
+
+
+
+static void FreeImages (void)
+{
+       ULONG i;
+
+       for (i = 0; i < IMG_COUNT; i++)
+               DisposeObject((APTR)Img[i]);    /* DisposeObject(NULL) is safe */
+}
diff --git a/gadgets/ListView/ListViewClass.c b/gadgets/ListView/ListViewClass.c
new file mode 100644 (file)
index 0000000..5a1b51f
--- /dev/null
@@ -0,0 +1,2238 @@
+/*
+**     $Id: ListViewClass.c,v 1.4 2000/01/12 21:18:06 bernie Exp $
+**
+**     Copyright (C) 1996,97,99 Bernardo Innocenti <bernie@cosmos.it>
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     GadTools-like `boopsi' ListView gadget class
+*/
+
+/* Definitions for system headers */
+#define USE_BUILTIN_MATH
+#define INTUI_V36_NAMES_ONLY
+#define INTUITION_IOBSOLETE_H
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H            /* Avoid dupe defines of boopsi funcs */
+
+#include <exec/types.h>
+#include <exec/libraries.h>
+#include <intuition/intuition.h>
+#include <intuition/intuitionbase.h>
+#include <intuition/classes.h>
+#include <intuition/gadgetclass.h>
+#include <intuition/imageclass.h>
+#include <graphics/gfxbase.h>
+#include <graphics/gfxmacros.h>
+
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <proto/graphics.h>
+#include <proto/layers.h>
+#include <proto/utility.h>
+
+#include <CompilerSpecific.h>
+#include <DebugMacros.h>
+#include <DiagnosticMacros.h>
+#include <BoopsiStubs.h>
+#include <BoopsiLib.h>
+
+#define LV_GADTOOLS_STUFF
+#include <gadgets/ListViewClass.h>
+
+#ifdef __STORM__
+       #pragma header
+#endif
+
+
+
+/* ListView private instance data */
+
+
+/* Type of a listview hook function */
+typedef        ASMCALL APTR    LVHook(
+       REG(a0, struct Hook     *hook), REG(a1, APTR item), REG(a2, struct lvGetItem *lvg));
+typedef        ASMCALL APTR    LVDrawHook(
+       REG(a0, struct Hook     *hook), REG(a1, APTR item), REG(a2, struct lvDrawItem *lvdi));
+
+struct LVData
+{
+       APTR                     Items;                         /* The list/array of items                              */
+       LONG                     Top;                           /* Ordinal nr. of the top visible item  */
+       APTR                     TopPtr;                        /* Pointer to the top visible item              */
+       LONG                     Total;                         /* Total nr. of items in the list               */
+       LONG                     Visible;                       /* Number of items visible in the list  */
+       LONG                     PixelTop;                      /* Pixel-wise offset from the top               */
+       LONG                     Selected;                      /* Ordinal nr. of the selected item             */
+       APTR                     SelectedPtr;           /* Pointer to the selected item                 */
+       ULONG                    SelectCount;           /* Number of items currently selected   */
+       ULONG                    MaxSelect;                     /* Maximum nr. of selections to allow   */
+
+       /* Old values used to track scrolling amount in GM_RENDER */
+       LONG                     OldTop;
+       LONG                     OldPixelTop;
+       LONG                     OldSelected;
+       APTR                     OldSelectedPtr;
+
+       ULONG                    DragSelect;            /* Status of drag selection                             */
+       LONG                     ItemHeight;            /* Height of one item in pixels                 */
+       LONG                     Spacing;                       /* Spacing between items in pixels              */
+       LONG                     MaxScroll;                     /* Redraw all when scrolling too much   */
+       LONG                     ScrollRatio;           /* max visible/scrolled ratio                   */
+       ULONG                   *SelectArray;           /* Array of selected items. May be NULL */
+       LONG                     BackupSelected;        /* Used by RMB undo                                     */
+       LONG                     BackupPixelTop;        /* Used by RMB undo                                             */
+       WORD                     MiddleMouseY;          /* Initial Y position for MMB scrolling */
+       ULONG                    Flags;                         /* See <listviewclass.h>                                */
+       ULONG                    MaxPen;                        /* Highest pen number used                              */
+       ULONG                    DoubleClickSecs, DoubleClickMicros;
+
+       /* User or internal hooks */
+       LVHook                  *GetItemFunc;
+       LVHook                  *GetNextFunc;
+       LVHook                  *GetPrevFunc;
+       LVHook                  *DrawBeginFunc;
+       LVHook                  *DrawEndFunc;
+       LVDrawHook              *DrawItemFunc;
+       struct Hook             *CallBack;                      /* Callback hook provided by user       */
+
+       struct TextFont *Font;                          /* Font used to render text labels      */
+       struct Region   *ClipRegion;            /* Used in LVA_Clipped mode                     */
+
+
+       /* These two have the same meaning, but we keep both updated
+        * because the Rectangle structure (MinX, MinY, MaxX, MaxY)
+        * is more handy in some cases, while the IBox structure
+        * (Left/Top/Width/Height) is best for other cases.
+        */
+       struct IBox              GBox;
+       struct Rectangle GRect;
+
+       struct IBox              FrameBox;                      /* The size of our surrounding frame */
+};
+
+
+
+/* Local function prototypes */
+
+static void            LV_GMRender             (Class *cl, struct Gadget *g, struct gpRender *msg);
+static ULONG   LV_GMGoActive   (Class *cl, struct Gadget *g, struct gpInput *msg);
+static ULONG   LV_GMHandleInput(Class *cl, struct Gadget *g, struct gpInput *msg);
+static void            LV_GMGoInactive (Class *cl, struct Gadget *g, struct gpGoInactive *msg);
+static void            LV_GMLayout             (Class *cl, struct Gadget *g, struct gpLayout *msg);
+static ULONG   LV_OMSet                (Class *cl, struct Gadget *g, struct opUpdate *msg);
+static ULONG   LV_OMGet                (Class *cl, struct Gadget *g, struct opGet *msg);
+static ULONG   LV_OMNew                (Class *cl, struct Gadget *g, struct opSet *msg);
+static void            LV_OMDispose    (Class *cl, struct Gadget *g, Msg msg);
+
+static void            RedrawItems             (struct LVData *lv, struct gpRender *msg, LONG first, LONG last, APTR item);
+INLINE LONG            ItemHit                 (struct LVData *lv, WORD x, WORD y);
+INLINE APTR    GetItem                 (struct LVData *lv, LONG num);
+INLINE APTR    GetNext                 (struct LVData *lv, APTR item, LONG num);
+INLINE APTR    GetPrev                 (struct LVData *lv, APTR item, LONG num);
+INLINE ULONG   CountNodes              (struct List *list);
+static ULONG   CountSelections (struct LVData *lv);
+INLINE ULONG   IsItemSelected  (struct LVData *lv, APTR item, LONG num);
+
+/* Definitions for the builtin List hooks */
+LVHook         ListGetItem;
+LVHook         ListGetNext;
+LVHook         ListGetPrev;
+LVDrawHook     ListStringDrawItem;
+LVDrawHook     ListImageDrawItem;
+
+/* Definitions for the builtin Array hooks */
+LVHook         ArrayGetItem;
+LVDrawHook     StringDrawItem;
+LVDrawHook     ImageDrawItem;
+
+
+
+#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB)
+
+       /* Class library support functions */
+       struct ClassLibrary     *       HOOKCALL _UserLibInit           (REG(a6, struct ClassLibrary *mybase));
+       struct ClassLibrary     *       HOOKCALL _UserLibCleanup        (REG(a6, struct ClassLibrary *mybase));
+       Class *                                 HOOKCALL _GetEngine                     (REG(a6, struct ClassLibrary *mybase));
+
+       /* Library data */
+       const UBYTE LibName[] = "listview.gadget";
+       const UBYTE LibVer[] = { '$', 'V', 'E', 'R', ':', ' ' };
+       const UBYTE LibId[] = "listview.gadget 1.0 (28.8.99) © 1997-1999 Bernardo Innocenti\n";
+
+       /* Workaround a bug in StormC header file <proto/utility.h> */
+       #ifdef __STORM__
+               #define UTILITYBASETYPE struct Library
+       #else
+               #define UTILITYBASETYPE struct UtilityBase
+       #endif
+
+       /* Library bases */
+       struct ExecBase                 *SysBase                = NULL;
+       struct IntuitionBase    *IntuitionBase  = NULL;
+       UTILITYBASETYPE                 *UtilityBase    = NULL;
+       struct GfxBase                  *GfxBase                = NULL;
+       struct Library                  *LayersBase             = NULL;
+#endif
+
+
+
+/* ListView class dispatcher - Handles all supported methods
+ */
+static ULONG HOOKCALL LVDispatcher (
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, Msg msg))
+{
+       ASSERT_VALID_PTR(cl)
+       ASSERT_VALID_PTR(g)
+       ASSERT_VALID_PTR(msg)
+
+       switch (msg->MethodID)
+       {
+               case GM_RENDER:
+                       LV_GMRender(cl, g, (struct gpRender *)msg);
+                       return TRUE;
+
+               case GM_GOACTIVE:
+                       return LV_GMGoActive(cl, g, (struct gpInput *)msg);
+
+               case GM_HANDLEINPUT:
+                       return LV_GMHandleInput(cl, g, (struct gpInput *)msg);
+
+               case GM_GOINACTIVE:
+                       LV_GMGoInactive(cl, g, (struct gpGoInactive *)msg);
+                       return TRUE;
+
+               case GM_LAYOUT:
+                       /* This method is only supported on V39 and above */
+                       LV_GMLayout(cl, g, (struct gpLayout *)msg);
+                       return TRUE;
+
+               case OM_SET:
+               case OM_UPDATE:
+                       return LV_OMSet(cl, g, (struct opUpdate *)msg);
+
+               case OM_GET:
+                       return LV_OMGet(cl, g, (struct opGet *)msg);
+
+               case OM_NEW:
+                       return LV_OMNew(cl, g, (struct opSet *)msg);
+
+               case OM_DISPOSE:
+                       LV_OMDispose(cl, g, msg);
+                       return TRUE;
+
+               default:
+                       /* Unsupported method: let our superclass's
+                        * dispatcher take a look at it.
+                        */
+                       return DoSuperMethodA(cl, (Object *)g, msg);
+       }
+}
+
+
+
+/* Stub for LV_GETITEM hook method
+ */
+INLINE APTR GetItem(struct LVData *lv, LONG num)
+{
+       struct lvGetItem lvgi;
+
+
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR(lv->Items)
+       ASSERT_VALID_PTR(lv->GetItemFunc)
+       ASSERT(num >= 0)
+       ASSERT(num < lv->Total)
+
+
+       lvgi.lvgi_MethodID      = LV_GETITEM;
+       lvgi.lvgi_Number        = num;
+       lvgi.lvgi_Items         = lv->Items;
+
+       return (lv->GetItemFunc(lv->CallBack, NULL, &lvgi));
+}
+
+
+
+/* Stub for LV_GETNEXT hook method
+ */
+INLINE APTR GetNext(struct LVData *lv, APTR item, LONG num)
+{
+       struct lvGetItem lvgi;
+
+
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR(lv->GetNextFunc)
+       ASSERT_VALID_PTR_OR_NULL(item)
+       ASSERT(num >= 0)
+       ASSERT(num < lv->Total)
+
+
+       lvgi.lvgi_MethodID      = LV_GETNEXT;
+       lvgi.lvgi_Number        = num;
+       lvgi.lvgi_Items         = lv->Items;
+
+       return (lv->GetNextFunc (lv->CallBack, item, &lvgi));
+}
+
+
+
+/* Stub for LV_GETPREV hook method
+ */
+INLINE APTR GetPrev(struct LVData *lv, APTR item, LONG num)
+{
+       struct lvGetItem lvgi;
+
+
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR(lv->GetPrevFunc)
+       ASSERT_VALID_PTR_OR_NULL(item)
+       ASSERT(num >= 0)
+       ASSERT(num < lv->Total)
+
+
+       lvgi.lvgi_MethodID      = LV_GETPREV;
+       lvgi.lvgi_Number        = num;
+       lvgi.lvgi_Items         = lv->Items;
+
+       return (lv->GetPrevFunc (lv->CallBack, item, &lvgi));
+}
+
+
+
+INLINE void GetItemBounds(struct LVData *lv, struct Rectangle *rect, LONG item)
+
+/* Compute the bounding box to render the given item and store it in the passed
+ * Rectangle structure.
+ */
+{
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR(rect)
+       ASSERT(item < lv->Total)
+       ASSERT(item >= 0)
+
+       rect->MinX = lv->GRect.MinX;
+       rect->MaxX = lv->GRect.MaxX;
+       rect->MinY = lv->ClipRegion ?
+               (lv->GRect.MinY + item * (lv->ItemHeight + lv->Spacing) - lv->PixelTop) :
+               (lv->GRect.MinY + (item - lv->Top) * (lv->ItemHeight + lv->Spacing));
+       rect->MaxY = rect->MinY + lv->ItemHeight - 1;
+}
+
+
+
+/* Checks if the given item is selected
+ */
+INLINE ULONG IsItemSelected(struct LVData *lv, APTR item, LONG num)
+{
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR_OR_NULL(item)
+       ASSERT(num >= 0)
+       ASSERT(num < lv->Total)
+
+
+       if (lv->Flags & LVF_DOMULTISELECT)
+       {
+               if (lv->SelectArray)
+               {
+                       ASSERT(num < lv->Total)
+
+                       return lv->SelectArray[num];
+               }
+               else if (lv->Flags & LVF_LIST)
+               {
+                       if (!item)
+                               item = GetItem(lv, num);
+
+                       ASSERT_VALID_PTR(item)
+
+                       return item ? (ULONG)(((struct Node *)item)->ln_Type) : 0;
+               }
+
+               return 0;
+       }
+       else
+               return ((ULONG)(num == lv->Selected));
+}
+
+
+
+/* Return the number of nodes in a list
+ */
+INLINE ULONG CountNodes(struct List *list)
+{
+       struct Node *node;
+       ULONG count = 0;
+
+       if (list)
+       {
+               ASSERT_VALID_PTR(list)
+
+               for (node = list->lh_Head; (node = node->ln_Succ); count++)
+                       ASSERT_VALID_PTR_OR_NULL(node);
+       }
+
+       return count;
+}
+
+
+
+/* Count the number of selections in a multiselect listview
+ */
+static ULONG CountSelections(struct LVData *lv)
+{
+       ULONG count = 0;
+
+       ASSERT_VALID_PTR(lv)
+
+
+       if (lv->Flags & LVF_DOMULTISELECT)
+       {
+               if (lv->SelectArray)
+               {
+                       int i;
+
+                       ASSERT_VALID_PTR(lv->SelectArray)
+
+                       for (i = 0; i < lv->Total; i++)
+                               if (lv->SelectArray[i])
+                                       count++;
+               }
+               else if ((lv->Flags & LVF_LIST) && lv->Items)
+               {
+                       struct Node *node;
+
+                       ASSERT_VALID_PTR(lv->Items)
+
+                       for (node = ((struct List *)lv->Items)->lh_Head; (node = node->ln_Succ); count++)
+                               ASSERT_VALID_PTR_OR_NULL(node);
+               }
+       }
+
+       return count;
+}
+
+
+
+static void RedrawItems(struct LVData *lv, struct gpRender *msg, LONG first, LONG last, APTR item)
+
+/* Redraw items from <min> to <max>.  No sanity checks are performed
+ * to ensure that all items between <min> and <max> are really visible.
+ */
+{
+       struct lvDrawItem lvdi;
+       LONG selected;
+
+
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR(msg)
+       ASSERT(first <= last)
+       ASSERT(last < lv->Total)
+
+       DB2( DBPRINTF ("  RedrawItems (first = %ld, last = %ld)\n", first, last);)
+
+
+       lvdi.lvdi_Current       = first;
+       lvdi.lvdi_Items         = lv->Items;
+       lvdi.lvdi_RastPort      = msg->gpr_RPort;
+       lvdi.lvdi_DrawInfo      = msg->gpr_GInfo->gi_DrInfo;
+       lvdi.lvdi_Flags         = lv->Flags;
+
+       GetItemBounds (lv, &lvdi.lvdi_Bounds, first);
+
+       if (!item)
+       {
+               lvdi.lvdi_MethodID = LV_GETITEM;
+               item = lv->GetItemFunc (lv->CallBack, NULL, (struct lvGetItem *)&lvdi);
+       }
+
+       if (lv->DrawBeginFunc)
+       {
+               lvdi.lvdi_MethodID      = LV_DRAWBEGIN;
+               lv->DrawBeginFunc (lv->CallBack, item, (struct lvDrawBegin *)&lvdi);
+       }
+
+       for (;;)
+       {
+               if (lv->Flags & LVF_DOMULTISELECT)
+               {
+                       if (lv->SelectArray)
+                               /* Array selection */
+                               selected = lv->SelectArray[lvdi.lvdi_Current];
+                       else
+                               if (lv->Flags & LVF_LIST)
+                                       /* Node selection */
+                                       selected = (((struct Node *)item)->ln_Type);
+                               else
+                                       selected = 0;
+               }
+               else
+                       /* Single selection */
+                       selected = (lvdi.lvdi_Current == lv->Selected);
+
+               lvdi.lvdi_State = selected ? LVR_SELECTED : LVR_NORMAL;
+
+               lvdi.lvdi_MethodID      = LV_DRAW;
+               lv->DrawItemFunc (lv->CallBack, item, &lvdi);
+
+               if (++lvdi.lvdi_Current > last)
+                       break;
+
+               lvdi.lvdi_MethodID      = LV_GETNEXT;
+               item = lv->GetNextFunc (lv->CallBack, item, (struct lvGetNext *)&lvdi);
+
+               lvdi.lvdi_Bounds.MinY += lv->ItemHeight + lv->Spacing;
+               lvdi.lvdi_Bounds.MaxY += lv->ItemHeight + lv->Spacing;
+       }
+
+       if (lv->DrawEndFunc)
+       {
+               lvdi.lvdi_MethodID      = LV_DRAWEND;
+               lv->DrawEndFunc (lv->CallBack, item, (struct lvDrawEnd *)&lvdi);
+       }
+}
+
+
+
+static void LV_GMRender(Class *cl, struct Gadget *g, struct gpRender *msg)
+{
+       struct LVData   *lv = INST_DATA (cl, g);
+       struct RastPort *rp = msg->gpr_RPort;
+
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR(rp)
+
+       DB2 (DBPRINTF ("GM_RENDER: msg->gpr_Redraw = %s\n",
+               (msg->gpr_Redraw == GREDRAW_TOGGLE) ? "GREDRAW_TOGGLE" :
+               ((msg->gpr_Redraw == GREDRAW_REDRAW) ? "GREDRAW_REDRAW" :
+               ((msg->gpr_Redraw == GREDRAW_UPDATE) ? "GREDRAW_UPDATE" :
+               "*** Unknown GREDRAW mode ***")) );)
+
+
+       if (lv->Flags & LVF_DONTDRAW)
+               return;
+
+       if (lv->Items && lv->Visible)
+       {
+               struct TextFont *oldfont = NULL;
+               struct Region *oldregion;
+               BOOL layerupdating = FALSE;
+
+               if (rp->Font != lv->Font)
+               {
+                       oldfont = rp->Font;
+                       SetFont (rp, lv->Font);
+               }
+
+               if (lv->ClipRegion)
+               {
+                       ASSERT_VALID_PTR(lv->ClipRegion)
+                       ASSERT_VALID_PTR(msg->gpr_RPort->Layer)
+                       DB2(DBPRINTF ("Calling InstallClipRegion()...\n");)
+
+                       /* Workaround for installing clip regions in
+                        * updating layers within a boopsi gadget dispatcher,
+                        * as suggested by Jochen Bechen.
+                        */
+//                     if (msg->gpr_RPort->Layer->Flags & LAYERUPDATING)
+//                     {
+//                             layerupdating = TRUE;
+//                             EndUpdate(msg->gpr_RPort->Layer, FALSE);
+//                     }
+                       oldregion = InstallClipRegion(rp->Layer, lv->ClipRegion);
+               }
+
+               switch (msg->gpr_Redraw)
+               {
+                       case GREDRAW_TOGGLE:    /* Toggle selected item */
+                       {
+                               BOOL    drawnew = (lv->Selected >= lv->Top) && (lv->Selected < lv->Top + lv->Visible),
+                                               drawold = (lv->OldSelected >= lv->Top) && (lv->OldSelected < lv->Top + lv->Visible);
+
+                               if (drawold || drawnew)
+                               {
+                                       struct lvDrawItem        lvdi;
+                                       lvdi.lvdi_Items         = lv->Items;
+                                       lvdi.lvdi_RastPort      = rp;
+                                       lvdi.lvdi_DrawInfo      = msg->gpr_GInfo->gi_DrInfo;
+                                       lvdi.lvdi_Flags         = lv->Flags;
+
+
+                                       if (lv->DrawBeginFunc)
+                                       {
+                                               lvdi.lvdi_MethodID      = LV_DRAWBEGIN;
+                                               lv->DrawBeginFunc(lv->CallBack, NULL, (struct lvDrawBegin *)&lvdi);
+                                       }
+
+                                       lvdi.lvdi_MethodID      = LV_DRAW;
+
+                                       if (drawnew)
+                                       {
+                                               GetItemBounds (lv, &lvdi.lvdi_Bounds, lv->Selected);
+                                               lvdi.lvdi_State = IsItemSelected (lv, lv->SelectedPtr, lv->Selected) ?
+                                                       LVR_SELECTED : LVR_NORMAL;
+                                               lvdi.lvdi_Current = lv->Selected;
+
+                                               lv->DrawItemFunc (lv->CallBack, lv->SelectedPtr, &lvdi);
+                                       }
+
+                                       if (drawold)
+                                       {
+                                               GetItemBounds (lv, &lvdi.lvdi_Bounds, lv->OldSelected);
+                                               lvdi.lvdi_State = IsItemSelected (lv, lv->OldSelectedPtr, lv->OldSelected) ?
+                                                       LVR_SELECTED : LVR_NORMAL;
+                                               lvdi.lvdi_Current = lv->OldSelected;
+
+                                               lv->DrawItemFunc (lv->CallBack, lv->OldSelectedPtr, &lvdi);
+                                       }
+
+                                       if (lv->DrawEndFunc)
+                                       {
+                                               lvdi.lvdi_MethodID      = LV_DRAWEND;
+                                               lv->DrawEndFunc (lv->CallBack, NULL, (struct lvDrawEnd *)&lvdi);
+                                       }
+                               }
+
+                               lv->OldSelected = lv->Selected;
+                               lv->OldSelectedPtr = lv->SelectedPtr;
+
+                               break;
+                       }
+
+                       case GREDRAW_REDRAW:    /* Redraw everything */
+                       {
+                               LONG    ycoord;
+
+                               /* Set the background pen */
+                               SetAPen (rp, msg->gpr_GInfo->gi_DrInfo->dri_Pens[BACKGROUNDPEN]);
+                               /* SetAPen (rp, -1); Used to debug clearing code */
+
+                               /* Now clear the spacing between the items */
+                               if (lv->Spacing && lv->Items && lv->Visible)
+                               {
+                                       LONG i, lastitem;
+
+                                       ycoord = lv->GRect.MinY + lv->ItemHeight;
+                                       lastitem = min (lv->Visible, lv->Total - lv->Top) - 1;
+
+                                       for (i = 0 ; i < lastitem; i++)
+                                       {
+                                               RectFill (rp, lv->GRect.MinX, ycoord,
+                                                       lv->GRect.MaxX, ycoord + lv->Spacing - 1);
+
+                                               ycoord += lv->ItemHeight + lv->Spacing;
+                                       }
+                               }
+                               else
+                                       ycoord = lv->GRect.MinY + min (lv->Visible, lv->Total - lv->Top)
+                                               * lv->ItemHeight;
+
+                               /* Now let's clear bottom part of gadget */
+                               RectFill (rp, lv->GRect.MinX, ycoord,
+                                       lv->GRect.MaxX, lv->GRect.MaxY);
+
+                               /* Finally, draw the items */
+                               RedrawItems (lv, msg, lv->Top,
+                                       min (lv->Top + lv->Visible, lv->Total) - 1, lv->TopPtr);
+
+                               break;
+                       }
+
+                       case GREDRAW_UPDATE:    /* Scroll ListView */
+                       {
+                               LONG scroll_dy, scroll_height;
+
+                               if (lv->ClipRegion)
+                               {
+                                       /* Calculate scrolling amount in pixels */
+                                       if (!(scroll_dy = lv->PixelTop - lv->OldPixelTop))
+                                               /* Do nothing if called improperly */
+                                               break;
+
+                                       /* Scroll everything */
+                                       scroll_height = lv->GBox.Height;
+                               }
+                               else
+                               {
+                                       if (!(lv->Top - lv->OldTop))
+                                               /* Do nothing if called improperly */
+                                               break;
+
+                                       /* Calculate scrolling amount in pixels */
+                                       scroll_dy = (lv->Top - lv->OldTop) * (lv->ItemHeight + lv->Spacing);
+
+                                       /* Only scroll upto last visible item */
+                                       scroll_height = lv->Visible * (lv->ItemHeight + lv->Spacing) - lv->Spacing;
+                               }
+
+                               if (abs(scroll_dy) > lv->MaxScroll)
+                               {
+                                       /* Redraw everything when listview has been scrolled too much */
+                                       RedrawItems (lv, msg, lv->Top,
+                                               min (lv->Top + lv->Visible, lv->Total) - 1, lv->TopPtr);
+                               }
+                               else
+                               {
+                                       /* Optimize scrolling on planar displays if possible */
+                                       SetMaxPen (rp, lv->MaxPen);
+
+                                       /* We use ClipBlit() to scroll the listview because it doesn't clear
+                                        * the scrolled region like ScrollRaster() would do.  Unfortunately,
+                                        * ClipBlit() does not scroll along the damage regions, so we also
+                                        * call ScrollRaster() with the mask set to 0, which will scroll the
+                                        * layer damage regions without actually modifying the display.
+                                        */
+
+                                       if (scroll_dy > 0)      /* Scroll Down */
+                                       {
+                                               ClipBlit (rp, lv->GBox.Left, lv->GBox.Top + scroll_dy,
+                                                       rp, lv->GBox.Left, lv->GBox.Top,
+                                                       lv->GBox.Width, scroll_height - scroll_dy,
+                                                       0x0C0);
+
+                                                       if (lv->ClipRegion)
+                                                       {
+                                                               /* NOTE: We subtract 1 pixel to avoid an exact division which would
+                                                                *       render one item beyond the end when the slider is dragged
+                                                                *       all the way down.
+                                                                */
+                                                               RedrawItems(lv, msg,
+                                                                       (lv->OldPixelTop + lv->GBox.Height) / (lv->ItemHeight + lv->Spacing),
+                                                                       (lv->PixelTop + lv->GBox.Height - 1) / (lv->ItemHeight + lv->Spacing),
+                                                                       NULL);
+                                                       }
+                                                       else
+                                                               RedrawItems(lv, msg,
+                                                                       lv->Visible + lv->OldTop,
+                                                                       lv->Visible + lv->Top - 1,
+                                                                       NULL);
+                                       }
+                                       else                            /* Scroll Up */
+                                       {
+                                               ClipBlit(rp, lv->GBox.Left, lv->GBox.Top,
+                                                       rp, lv->GBox.Left, lv->GBox.Top - scroll_dy,
+                                                       lv->GBox.Width, scroll_height + scroll_dy,
+                                                       0x0C0);
+
+
+                                                       if (lv->ClipRegion)
+                                                               RedrawItems(lv, msg,
+                                                                       lv->PixelTop / (lv->ItemHeight + lv->Spacing),
+                                                                       lv->OldPixelTop / (lv->ItemHeight + lv->Spacing),
+                                                                       NULL);
+                                                       else
+                                                               RedrawItems(lv, msg,
+                                                                       lv->Top,
+                                                                       lv->OldTop - 1,
+                                                                       lv->TopPtr);
+                                       }
+
+                                       /* This will scroll the layer damage regions without actually
+                                        * scrolling the display, but only if our layer really needs it.
+                                        */
+                                       if (NeedZeroScrollRaster(rp->Layer))
+                                       {
+                                               UBYTE oldmask = rp->Mask; /* Would GetRPAttr() be better? */
+
+                                               DB2 (DBPRINTF ("  Calling ScrollRaster()\n");)
+                                               SetWriteMask(rp, 0);
+                                               ScrollRaster(rp, 0, scroll_dy,
+                                                       lv->GRect.MinX, lv->GRect.MinY,
+                                                       lv->GRect.MaxX,
+                                                       lv->GRect.MaxY);
+
+                                               SetWriteMask(rp, oldmask);
+                                       }
+
+                                       /* Restore MaxPen in our RastPort */
+                                       SetMaxPen(rp, -1);
+                               }
+
+                               /* Update OldTop to the current Top item and
+                                * OldPixelTop to the current PixelTop position.
+                                */
+                               lv->OldTop = lv->Top;
+                               lv->OldPixelTop = lv->PixelTop;
+
+                               break;
+                       }
+
+                       default:
+                               break;
+               }
+
+               if (lv->ClipRegion)
+               {
+                       /* Restore old clipping region in our layer */
+                       DB2 (DBPRINTF ("GM_RENDER: Resoring old ClipRegion\n");)
+                       ASSERT_VALID_PTR_OR_NULL(oldregion)
+                       InstallClipRegion (rp->Layer, oldregion);
+                       if (layerupdating)
+                               BeginUpdate(msg->gpr_RPort->Layer);
+               }
+
+               if (oldfont)
+                       SetFont (rp, oldfont);
+       }
+       else if (msg->gpr_Redraw == GREDRAW_REDRAW)
+       {
+               /* Clear all gadget contents */
+               SetAPen (rp, msg->gpr_GInfo->gi_DrInfo->dri_Pens[BACKGROUNDPEN]);
+               RectFill (rp, lv->GRect.MinX, lv->GRect.MinY, lv->GRect.MaxX, lv->GRect.MaxY);
+       }
+
+
+       /* Last but not least, draw the frame if we have one associated */
+
+       if ((msg->gpr_Redraw == GREDRAW_REDRAW) && GadgetHasFrame(g))
+       {
+               DB2 (DBPRINTF("ListViewClass: Rendering my own frame\n");)
+
+               DoMethod((Object *)g->GadgetRender, IM_DRAWFRAME,
+                       msg->gpr_RPort,                                                                         /* imp_RPort            */
+                       (lv->FrameBox.Left << 16) | (lv->FrameBox.Top),         /* imp_Offset           */
+                       IDS_NORMAL,                                                                                     /* imp_State            */
+                       msg->gpr_GInfo->gi_DrInfo,                                                      /* imp_DrInfo           */
+                       (lv->FrameBox.Width << 16) | (lv->FrameBox.Height));/* imp_Dimensions   */
+       }
+}
+
+
+
+static ULONG LV_GMGoActive(Class *cl, struct Gadget *g, struct gpInput *msg)
+{
+       struct LVData *lv = INST_DATA (cl, g);
+
+       ASSERT_VALID_PTR(lv)
+       DB2 (DBPRINTF ("GM_GOACTIVE: gpi_IEvent = $%lx\n", msg->gpi_IEvent);)
+
+
+       if (!lv->Items)
+               return GMR_NOREUSE;
+
+       g->Flags |= GFLG_SELECTED;
+
+       /* Do not process InputEvent when the gadget has been
+        * activated by ActivateGadget().
+        */
+       if (!msg->gpi_IEvent)
+               return GMR_MEACTIVE;
+
+       /* Note: The input event that triggered the gadget
+        * activation (usually a mouse click) should be passed
+        * to the GM_HANDLEINPUT method, so we fall down to it.
+        */
+       return LV_GMHandleInput (cl, g, msg);
+}
+
+
+
+INLINE LONG ItemHit (struct LVData *lv, UNUSED(WORD x), WORD y)
+
+/* Determine which item has been hit with gadget relative
+ * coordinates x and y.
+ */
+{
+       return ((y + lv->PixelTop) / (lv->ItemHeight + lv->Spacing));
+}
+
+
+
+static ULONG LV_GMHandleInput (Class *cl, struct Gadget *g, struct gpInput *msg)
+{
+       struct LVData           *lv = INST_DATA (cl, g);
+       struct InputEvent       *ie = msg->gpi_IEvent;
+       ULONG                            result = GMR_MEACTIVE;
+
+       ASSERT_VALID_PTR(lv)
+/*     DB2 (DBPRINTF ("GM_HANDLEINPUT: ie_Class = $%lx, ie->ie_Code = $%lx, "
+               "gpi_Mouse.X = %ld, gpi_Mouse.Y = %ld\n",
+               ie->ie_Class, ie->ie_Code, msg->gpi_Mouse.X, msg->gpi_Mouse.Y);)
+*/
+       switch (ie->ie_Class)
+       {
+               case IECLASS_RAWKEY:
+               {
+                       LONG tags[5];
+                       LONG pos;
+
+                       switch (ie->ie_Code)
+                       {
+                               case CURSORUP:
+                                       if ((lv->Flags & LVF_READONLY) || (ie->ie_Qualifier & IEQUALIFIER_CONTROL))
+                                       {
+                                               if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
+                                                       pos = lv->Top - lv->Visible / 2;
+                                               else
+                                                       pos = lv->Top - 1;
+
+                                               if (pos < 0) pos = 0;
+
+                                               tags[0] = LVA_Top;
+                                               tags[1] = pos;
+                                               tags[2] = TAG_DONE;
+                                       }
+                                       else
+                                       {
+                                               if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
+                                                       pos = 0;
+                                               else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
+                                                       pos = lv->Selected - lv->Visible + 1;
+                                               else
+                                                       pos = lv->Selected - 1;
+
+                                               if (pos < 0) pos = 0;
+
+                                               tags[0] = LVA_Selected;
+                                               tags[1] = pos;
+                                               tags[2] = LVA_MakeVisible;
+                                               tags[3] = pos;
+                                               tags[4] = TAG_DONE;
+                                       }
+                                       break;
+
+                               case CURSORDOWN:
+                                       if ((lv->Flags & LVF_READONLY) || (ie->ie_Qualifier & IEQUALIFIER_CONTROL))
+                                       {
+                                               if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
+                                                       pos = lv->Top + lv->Visible / 2;
+                                               else
+                                                       pos = lv->Top + 1;
+
+                                               tags[0] = LVA_Top;
+                                               tags[1] = pos;
+                                               tags[2] = TAG_DONE;
+                                       }
+                                       else
+                                       {
+                                               if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
+                                                       pos = lv->Total - 1;
+                                               else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
+                                                       pos = lv->Selected + lv->Visible - 1;
+                                               else
+                                                       pos = lv->Selected + 1;
+
+                                               tags[0] = LVA_Selected;
+                                               tags[1] = pos;
+                                               tags[2] = LVA_MakeVisible;
+                                               tags[3] = pos;
+                                               tags[4] = TAG_DONE;
+                                       }
+                                       break;
+
+                               default:
+                                       tags[0] = TAG_DONE;
+
+                       } /* End switch (ie->ie_Code) */
+
+                       if (tags[0] != TAG_DONE)
+                               DoMethod ((Object *)g, OM_UPDATE, tags, msg->gpi_GInfo,
+                                       (ie->ie_Qualifier & IEQUALIFIERB_REPEAT) ? OPUF_INTERIM : 0);
+
+                       break;
+               }
+
+               case IECLASS_RAWMOUSE:
+               {
+                       LONG selected;
+
+                       switch (ie->ie_Code)
+                       {
+                               case SELECTDOWN:
+
+                                       /* Check for click outside gadget box */
+
+                                       if ((msg->gpi_Mouse.X < 0) ||
+                                               (msg->gpi_Mouse.X >= lv->GBox.Width) ||
+                                               (msg->gpi_Mouse.Y < 0) ||
+                                               (msg->gpi_Mouse.Y >= lv->GBox.Height))
+                                       {
+                                               result = GMR_REUSE;
+                                               break;
+                                       }
+
+                                       /* Start dragging mode */
+                                       lv->Flags |= LVF_DRAGGING;
+
+                                       if (lv->Flags & LVF_READONLY)
+                                               break;
+
+                                       /* Select an item */
+                                       selected = ItemHit (lv, msg->gpi_Mouse.X, msg->gpi_Mouse.Y);
+
+                                       /* No action when selecting over blank space in the bottom */
+                                       if ((selected < 0) || (selected >= lv->Total))
+                                               break;
+
+                                       /* Backup current selection for RMB undo */
+                                       lv->BackupSelected = lv->Selected;
+                                       lv->BackupPixelTop = lv->PixelTop;
+
+                                       if (selected == lv->Selected)
+                                       {
+                                               /* Check for double click */
+                                               if (DoubleClick (lv->DoubleClickSecs, lv->DoubleClickMicros,
+                                                       ie->ie_TimeStamp.tv_secs, ie->ie_TimeStamp.tv_micro))
+                                                       UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0,
+                                                               LVA_DoubleClick, selected,
+                                                               TAG_DONE);
+                                       }
+
+                                       if (lv->Flags & LVF_DOMULTISELECT)
+                                               /* Setup for multiple items drag selection */
+                                               lv->DragSelect = IsItemSelected (lv, NULL, selected) ?
+                                                       LVA_DeselectItem : LVA_SelectItem;
+                                       else if (g->Activation & GACT_TOGGLESELECT)
+                                       {
+                                               /* Setup for single item toggle */
+                                               lv->DragSelect = LVA_Selected;
+                                               if (selected == lv->Selected)
+                                                       selected = ~0;
+                                       }
+                                       else /* Single selection */
+                                               /* Setup for single item drag selection */
+                                               lv->DragSelect = LVA_Selected;
+
+                                       UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0,
+                                               lv->DragSelect, selected,
+                                               TAG_DONE);
+
+                                       /* Save double click info */
+                                       lv->DoubleClickSecs = ie->ie_TimeStamp.tv_secs;
+                                       lv->DoubleClickMicros = ie->ie_TimeStamp.tv_micro;
+                                       break;
+
+                               case MENUDOWN:
+                                       /* Undo selection & position when RMB is pressed */
+                                       if (lv->Flags & (LVF_DRAGGING | LVF_SCROLLING))
+                                       {
+                                               /* Stop dragging and scrolling modes */
+                                               lv->Flags &= ~(LVF_DRAGGING | LVF_SCROLLING);
+
+                                               if ((lv->BackupSelected != lv->Selected) ||
+                                                       (lv->BackupPixelTop != lv->PixelTop))
+                                               {
+                                                       UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0,
+                                                               (lv->Flags & LVF_READONLY) ?
+                                                                       TAG_IGNORE : LVA_Selected, lv->BackupSelected,
+                                                               LVA_PixelTop, lv->BackupPixelTop,
+                                                               TAG_DONE);
+                                               }
+                                       }
+                                       else
+                                               /* Deactivate gadget on menu button press */
+                                               result = GMR_REUSE;
+
+                                       break;
+
+                               case MIDDLEDOWN:
+                                       /* Argh, input.device never sends this event in V40! */
+                                       DB1 (DBPRINTF ("MIDDLEDOWN received\n");)
+
+                                       /* Start MMB scrolling */
+                                       lv->BackupPixelTop = lv->PixelTop;
+                                       lv->BackupSelected = lv->Selected;
+                                       lv->MiddleMouseY = msg->gpi_Mouse.Y;
+                                       lv->Flags |= LVF_DRAGGING;
+                                       break;
+
+                               case SELECTUP:
+
+                                       /* Stop dragging mode */
+                                       lv->Flags &= ~LVF_DRAGGING;
+
+                                       if (g->Activation & GACT_RELVERIFY)
+                                       {
+                                               /* Send IDCMP_GADGETUP message to our parent window */
+                                               msg->gpi_Termination = &lv->Selected;
+                                               result = GMR_NOREUSE | GMR_VERIFY;
+                                       }
+                                       break;
+
+                               case MIDDLEUP:
+                                       /* Argh, input.device never sends this event in V40! */
+                                       DB1 (DBPRINTF ("scrolling off\n");)
+
+                                       /* Stop MMB scrolling */
+                                       lv->Flags &= ~LVF_SCROLLING;
+                                       break;
+
+                               default: /* Mouse moved */
+
+                                       /* Holding LMB? */
+                                       if (lv->Flags & LVF_DRAGGING)
+                                       {
+                                               /* Select an item */
+                                               selected = ItemHit (lv, msg->gpi_Mouse.X, msg->gpi_Mouse.Y);
+
+                                               /* Moved over another item inside the currently displayed list? */
+                                               if ((selected != lv->Selected) && !(lv->Flags & LVF_READONLY)
+                                                       && (selected >= lv->Top) && (selected < lv->Top + lv->Visible))
+                                               {
+                                                       /* Single selection */
+
+                                                       /* Call our OM_UPDATE method to change the attributes.
+                                                        * This will also send notification to targets and
+                                                        * update the contents of the gadget.
+                                                        */
+                                                       UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0,
+                                                               lv->DragSelect, selected,
+                                                               TAG_DONE);
+                                               }
+                                       }
+
+                                       /* Holding MMB? */
+                                       if (lv->Flags & LVF_SCROLLING)
+                                       {
+                                               DB1 (DBPRINTF ("  scrolling\n");)
+                                               selected = (msg->gpi_Mouse.Y - lv->MiddleMouseY)
+                                                       + lv->BackupPixelTop;
+
+                                               UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0,
+                                                       LVA_PixelTop, selected < 0 ? 0 : selected,
+                                                       TAG_DONE);
+                                       }
+
+                       } /* End switch (ie->ie_Code) */
+
+                       break;
+               }
+
+               case IECLASS_TIMER:
+
+                       /* Holding LMB? */
+                       if (lv->Flags & LVF_DRAGGING)
+                       {
+                               /* Mouse above the upper item? */
+                               if ((msg->gpi_Mouse.Y < 0) && lv->Top)
+                               {
+                                       /* Scroll up */
+                                       UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0,
+                                               LVA_MoveUp,     1,
+                                               (lv->Flags & LVF_READONLY) ? TAG_IGNORE : LVA_Selected, lv->Top - 1,
+                                               TAG_DONE);
+                               }
+                               /* Mouse below the bottom item? */
+                               else if (msg->gpi_Mouse.Y / (lv->ItemHeight + lv->Spacing) >= lv->Visible)
+                               {
+                                       /* Scroll down */
+                                       UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0,
+                                               LVA_MoveDown,           1,
+                                               (lv->Flags & LVF_READONLY) ? TAG_IGNORE : LVA_Selected, lv->Top + lv->Visible,
+                                               TAG_DONE);
+                               }
+                       }
+                       break;
+
+               default:
+                       ;
+
+       } /* End switch (ie->ie_Class) */
+
+       return result;
+}
+
+
+
+static void LV_GMGoInactive (Class *cl, struct Gadget *g, UNUSED(struct gpGoInactive *msg))
+{
+       struct LVData *lv = INST_DATA (cl, g);
+       ASSERT_VALID_PTR(lv)
+
+       DB1 (DBPRINTF ("ListViewClass: GM_GOINACTIVE\n");)
+
+       /* Stop dragging and scrolling modes */
+       lv->Flags &= ~(LVF_DRAGGING | LVF_SCROLLING);
+
+       /* Mark gadget inactive */
+       g->Flags &= ~GFLG_SELECTED;
+}
+
+
+
+static void LV_GMLayout(Class *cl, struct Gadget *g, struct gpLayout *msg)
+{
+       struct LVData *lv = INST_DATA (cl, g);
+       LONG visible;
+
+       DB2 (DBPRINTF ("ListViewClass: GM_LAYOUT\n");)
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR(msg->gpl_GInfo)
+       ASSERT_VALID_PTR(msg->gpl_GInfo->gi_DrInfo)
+       ASSERT_VALID_PTR(msg->gpl_GInfo->gi_DrInfo->dri_Font)
+
+
+       /* We shouldn't draw inside the GM_LAYOUT method: the
+        * GM_REDRAW method will be called by Intuition shortly after.
+        */
+       lv->Flags |= LVF_DONTDRAW;
+
+       /* Collect new gadget size */
+       GetGadgetBox(msg->gpl_GInfo, (struct ExtGadget *)g, &lv->GBox);
+       IBoxToRect(&lv->GBox, &lv->GRect);
+
+       if (GadgetHasFrame(g))
+               /* Calculate dimensions of our framing image */
+               DoMethod((Object *)g->GadgetRender,
+                       IM_FRAMEBOX, &lv->GBox, &lv->FrameBox, msg->gpl_GInfo->gi_DrInfo, 0);
+
+       /* Calculate clipping region for gadget LVA_Clipped mode */
+       if (lv->ClipRegion)
+       {
+               /* Remove previous clipping rectangle, if any */
+               ClearRegion (lv->ClipRegion);
+
+               /* Install a clipping rectangle around the gadget box.
+                * We don't check for failure because we couldn't do
+                * anything otherwise.
+                */
+               OrRectRegion (lv->ClipRegion, &lv->GRect);
+       }
+
+       /* Setup Font if not yet done */
+       if (!lv->Font)
+       {
+               lv->Font = msg->gpl_GInfo->gi_DrInfo->dri_Font;
+               if (!lv->ItemHeight)
+                       lv->ItemHeight = lv->Font->tf_YSize;
+       }
+
+       if (lv->ItemHeight)
+       {
+               if (lv->ClipRegion)
+                       /* Allow displaying an incomplete item at the bottom of the listview,
+                        * plus one incomplete item at the top.
+                        */
+                       visible = (lv->GBox.Height + lv->ItemHeight + lv->Spacing - 1) /
+                               (lv->ItemHeight + lv->Spacing);
+               else
+                       /* get maximum number of items fitting in the listview height.
+                        * Ignore spacing for the last visible item.
+                        */
+                       visible = (lv->GBox.Height + lv->Spacing) / (lv->ItemHeight + lv->Spacing);
+       }
+       else
+               visible = 0;
+
+       lv->MaxScroll = lv->GBox.Height / lv->ScrollRatio;
+
+
+       /* Send initial notification to our sliders, or update them to
+        * the new values. The slieders will get the correct size also
+        * in the special case where the list is attached at creation
+        * time and the sliders are attached later using a model object.
+        *
+        * The private class attribute LVA_Visible will handle everything for us.
+        */
+       UpdateAttrs ((Object *)g, msg->gpl_GInfo, 0,
+               LVA_Visible,    visible,
+               TAG_DONE);
+
+       /* Re-enable drawing */
+       lv->Flags &= ~LVF_DONTDRAW;
+}
+
+
+
+static ULONG LV_OMSet(Class *cl, struct Gadget *g, struct opUpdate *msg)
+{
+       struct LVData   *lv = INST_DATA (cl, g);
+       struct TagItem  *ti,
+                                       *tstate = msg->opu_AttrList;
+       ULONG   result;
+       UWORD   action = 0;     /* See flag definitions below */
+
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR_OR_NULL(tstate)
+
+       DB2 (DBPRINTF ((msg->MethodID == OM_SET) ?
+               "ListViewClass: OM_SET\n" :
+               "ListViewClass: OM_UPDATE:\n");)
+
+
+       /* Definitions for the ations to be taken right after
+        * scanning the attributes list in OM_SET/OM_UPDATE.
+        * For speed reasons we pack them together in a single variable,
+        * so we can set and test multiple flags in once.
+        */
+       #define LVF_DO_SUPER_METHOD     (1<<0)
+       #define LVF_REDRAW                      (1<<1)
+       #define LVF_SCROLL                      (1<<2)
+       #define LVF_TOGGLESELECT        (1<<3)
+       #define LVF_NOTIFY                      (1<<4)
+       #define LVF_NOTIFYALL           (1<<5)
+
+
+       while ((ti = NextTagItem (&tstate)))
+               switch (ti->ti_Tag)
+               {
+                       case GA_ID:
+                               if (msg->MethodID == OM_SET)
+                               {
+                                       DB2 (DBPRINTF ("  GA_ID, %ld\n", ti->ti_Data);)
+
+                                       /* Avoid forwarding all taglists to superclass because of GA_ID */
+                                       g->GadgetID = ti->ti_Data;
+                               }
+                               break;
+
+                       case LVA_Selected:
+                               DB2 (DBPRINTF ("  LVA_Selected, %ld\n", ti->ti_Data);)
+
+                               if (lv->Items)
+                               {
+                                       LONG newselected = ti->ti_Data;
+
+                                       if (newselected != ~0)
+                                               newselected = (newselected >= lv->Total) ?
+                                                       (lv->Total - 1) : newselected;
+
+                                       if (lv->Selected != newselected)
+                                       {
+                                               if (((lv->Selected >= lv->Top) &&
+                                                       (lv->Selected < lv->Top + lv->Visible)) ||
+                                                       ((newselected >= lv->Top) &&
+                                                       (newselected < lv->Top + lv->Visible)))
+                                                       action |= LVF_TOGGLESELECT;
+
+                                               lv->Selected = newselected;
+
+                                               if (newselected == ~0)
+                                                       lv->SelectedPtr = NULL;
+                                               else
+                                                       lv->SelectedPtr = GetItem(lv, newselected);
+
+                                               action |= LVF_NOTIFY;
+                                       }
+                               }
+                               break;
+
+                       case LVA_Top:
+                               DB2 (DBPRINTF ("  LVA_Top, %ld\n", ti->ti_Data);)
+
+                               if ((lv->Top != (LONG)ti->ti_Data) && lv->Items)
+                               {
+                                       /* This will scroll the listview contents when needed */
+
+                                       lv->Top = (((LONG)ti->ti_Data + lv->Visible) >= lv->Total) ?
+                                               ((lv->Total <= lv->Visible) ? 0 : (lv->Total - lv->Visible))
+                                               : (LONG)ti->ti_Data;
+                                       lv->PixelTop = lv->Top * (lv->ItemHeight + lv->Spacing);
+
+                                       /* TODO: optimize for some special cases:
+                                        * Top == oldtop + 1 and Top == oldtop - 1
+                                        */
+                                       lv->TopPtr = GetItem(lv, lv->Top);
+                                       action |= LVF_SCROLL | LVF_NOTIFY;
+                               }
+                               break;
+
+                       case LVA_Total:
+                               DB2 (DBPRINTF ("  LVA_Total, %ld\n", ti->ti_Data);)
+
+                               /* We don't hhandle LVA_Total except when setting a new
+                                * list or array of items.
+                                */
+                               break;
+
+                       case LVA_SelectItem:
+                               DB2 (DBPRINTF ("  LVA_SelectItem, %ld\n", ti->ti_Data);)
+
+                               /* Check LVA_MaxSelect */
+                               if (lv->SelectCount >= lv->MaxSelect)
+                                       DisplayBeep (msg->opu_GInfo ? msg->opu_GInfo->gi_Screen : NULL);
+                               else if (lv->Items)
+                               {
+                                       LONG newselected = ((LONG)ti->ti_Data >= lv->Total) ?
+                                               (lv->Total - 1) : (LONG)ti->ti_Data;
+
+                                       if (((lv->Selected >= lv->Top) &&
+                                               (lv->Selected < lv->Top + lv->Visible)) ||
+                                               ((newselected >= lv->Top) &&
+                                               (newselected < lv->Top + lv->Visible)))
+                                               action |= LVF_TOGGLESELECT;
+
+                                       lv->Selected = newselected;
+                                       lv->SelectedPtr = GetItem(lv, newselected);
+
+                                       if (!IsItemSelected(lv, lv->SelectedPtr, newselected))
+                                       {
+                                               lv->SelectCount++;
+
+                                               if (lv->SelectArray)
+                                                       lv->SelectArray[newselected] = lv->SelectCount;
+                                               else if (lv->Flags & LVF_LIST)
+                                                       ((struct Node *)lv->SelectedPtr)->ln_Type = lv->SelectCount;
+                                       }
+                                       action |= LVF_NOTIFY;
+                               }
+                               break;
+
+                       case LVA_DeselectItem:
+                               DB2 (DBPRINTF ("  LVA_DeselectItem, %ld\n", ti->ti_Data);)
+
+                               if (lv->Items)
+                               {
+                                       LONG newselected = ((LONG)ti->ti_Data >= lv->Total) ?
+                                               (lv->Total - 1) : (LONG)ti->ti_Data;
+
+                                       if (((lv->Selected >= lv->Top) &&
+                                               (lv->Selected < lv->Top + lv->Visible)) ||
+                                               ((newselected >= lv->Top) &&
+                                               (newselected < lv->Top + lv->Visible)))
+                                               action |= LVF_TOGGLESELECT;
+
+                                       lv->Selected = newselected;
+                                       lv->SelectedPtr = GetItem(lv, newselected);
+
+                                       if (IsItemSelected(lv, lv->SelectedPtr, newselected))
+                                       {
+                                               lv->SelectCount--;
+
+                                               if (lv->SelectArray)
+                                                       lv->SelectArray[lv->Selected] = 0;
+                                               else if (lv->Flags & LVF_LIST)
+                                                       ((struct Node *)lv->SelectedPtr)->ln_Type = 0;
+
+                                               action |= LVF_NOTIFY;
+                                       }
+                               }
+                               break;
+
+                       case LVA_ToggleItem:
+                               DB2 (DBPRINTF ("  LVA_ToggleItem, %ld\n", ti->ti_Data);)
+
+                               if (lv->Items)
+                               {
+                                       LONG newselected = ((LONG)ti->ti_Data >= lv->Total) ?
+                                               (lv->Total - 1) : (LONG)ti->ti_Data;
+
+                                       if (((lv->Selected >= lv->Top) &&
+                                               (lv->Selected < lv->Top + lv->Visible)) ||
+                                               ((newselected >= lv->Top) &&
+                                               (newselected < lv->Top + lv->Visible)))
+                                               action |= LVF_TOGGLESELECT;
+
+                                       lv->Selected = newselected;
+                                       lv->SelectedPtr = GetItem(lv, newselected);
+
+                                       if (IsItemSelected(lv, lv->SelectedPtr, lv->Selected))
+                                       {
+                                               /* Deselect */
+                                               lv->SelectCount--;
+
+                                               if (lv->SelectArray)
+                                                       lv->SelectArray[lv->Selected] = 0;
+                                               else if (lv->Flags & LVF_LIST)
+                                                       ((struct Node *)lv->SelectedPtr)->ln_Type = 0;
+                                       }
+                                       else
+                                       {
+                                               /* Check LVA_MaxSelect */
+                                               if (lv->SelectCount >= lv->MaxSelect)
+                                                       DisplayBeep (msg->opu_GInfo ? msg->opu_GInfo->gi_Screen : NULL);
+                                               else
+                                               {
+                                                       /* Select */
+                                                       lv->SelectCount++;
+
+                                                       if (lv->SelectArray)
+                                                               lv->SelectArray[lv->Selected] = lv->SelectCount;
+                                                       else if (lv->Flags & LVF_LIST)
+                                                               ((struct Node *)lv->SelectedPtr)->ln_Type = lv->SelectCount;
+                                               }
+                                       }
+
+                                       action |= LVF_NOTIFY;
+                               }
+                               break;
+
+                       case LVA_ClearSelected:
+                               DB2 (DBPRINTF ("  LVA_ClearSelected, %ld\n", ti->ti_Data);)
+
+                               if (lv->Items)
+                               {
+                                       LONG newselected = (LONG)ti->ti_Data;
+                                       LONG i;
+
+                                       if (((lv->Selected >= lv->Top) &&
+                                               (lv->Selected < lv->Top + lv->Visible)) ||
+                                               ((newselected >= lv->Top) &&
+                                               (newselected < lv->Top + lv->Visible)))
+                                               action |= LVF_TOGGLESELECT;
+
+                                       lv->Selected = ~0;
+                                       lv->SelectedPtr = NULL;
+                                       lv->SelectCount = 0;
+
+
+                                       /* Clear the selections */
+
+                                       if (lv->SelectArray)
+                                               for (i = 0; i < lv->Total; i++)
+                                                       lv->SelectArray[i] = 0;
+                                       else if (lv->Flags & LVF_LIST)
+                                       {
+                                               struct Node *node;
+
+                                               for (node = ((struct List *)lv->Items)->lh_Head;
+                                                       node->ln_Succ;
+                                                       node = node->ln_Succ)
+                                               {
+                                                       node->ln_Type = 0;
+                                                       ASSERT_VALID_PTR_OR_NULL(node);
+                                               }
+                                       }
+
+                                       /* TODO: check if total redraw is really needed */
+                                       action |= LVF_REDRAW | LVF_NOTIFY;
+                               }
+                               break;
+
+                       case LVA_MakeVisible:
+                       {
+                               LONG itemnum = (LONG)ti->ti_Data;
+
+                               DB2 (DBPRINTF ("  LVA_MakeVisible, %ld\n", ti->ti_Data);)
+
+                               if (itemnum < 0)
+                                       itemnum = 0;
+
+                               if (itemnum >= lv->Total)
+                                       itemnum = lv->Total - 1;
+
+                               if (itemnum < lv->Top)
+                               {
+                                       /* Scroll up */
+
+                                       lv->Top = itemnum;
+                                       lv->TopPtr = GetItem(lv, lv->Top);
+                                       action |= LVF_SCROLL | LVF_NOTIFY;
+                               }
+                               else if (itemnum >= lv->Top + lv->Visible)
+                               {
+                                       /* Scroll down */
+
+                                       lv->Top = itemnum - lv->Visible + 1;
+                                       lv->TopPtr = GetItem(lv, lv->Top);
+                                       action |= LVF_SCROLL | LVF_NOTIFY;
+                               }
+                               break;
+                       }
+
+                       case LVA_MoveUp:
+                               DB2 (DBPRINTF ("  LVA_MoveUp, %ld\n", ti->ti_Data);)
+
+                               if ((lv->Top > 0) && lv->Items)
+                               {
+                                       lv->Top--;
+                                       lv->TopPtr = GetPrev (lv, lv->TopPtr, lv->Top);
+                                       action |= LVF_SCROLL | LVF_NOTIFY;
+                               }
+                               break;
+
+                       case LVA_MoveDown:
+                               DB2 (DBPRINTF ("  LVA_MoveDown, %ld\n", ti->ti_Data);)
+
+                               if ((lv->Top + lv->Visible < lv->Total) && lv->Items)
+                               {
+                                       lv->Top++;
+                                       lv->TopPtr = GetNext (lv, lv->TopPtr, lv->Top);
+                                       action |= LVF_SCROLL | LVF_NOTIFY;
+                               }
+                               break;
+
+                       case LVA_MoveLeft:
+                               DB2 (DBPRINTF ("  Unimplemented attr: LVA_MoveLeft\n");)
+                               break;
+
+                       case LVA_MoveRight:
+                               DB2 (DBPRINTF ("  Unimplemented attr: LVA_MoveRight\n");)
+                               break;
+
+                       case LVA_StringList:
+                               DB2 (DBPRINTF ("  LVA_StringList, $%lx\n", ti->ti_Data);)
+
+                               if (ti->ti_Data == (ULONG)~0L)
+                                       lv->Items = NULL;
+                               else
+                               {
+                                       ASSERT_VALID_PTR_OR_NULL(ti->ti_Data)
+
+                                       lv->Items = (void *)ti->ti_Data;
+                                       lv->GetItemFunc         = ListGetItem;
+                                       lv->GetNextFunc         = ListGetNext;
+                                       lv->GetPrevFunc         = ListGetPrev;
+                                       lv->DrawItemFunc        = ListStringDrawItem;
+                                       lv->Flags |= LVF_LIST;
+
+                                       lv->Total = GetTagData (LVA_Total, ~0, msg->opu_AttrList);
+                                       if (lv->Total == ~0)
+                                               lv->Total = CountNodes(lv->Items);
+
+                                       lv->SelectCount = CountSelections (lv);
+
+                                       action |= LVF_REDRAW | LVF_NOTIFYALL;
+                               }
+                               break;
+
+                       case LVA_StringArray:
+                               DB2 (DBPRINTF ("  LVA_StringArray, $%lx\n", ti->ti_Data);)
+
+                               if (ti->ti_Data == (ULONG)~0L)
+                                       lv->Items = NULL;
+                               else
+                               {
+                                       ASSERT_VALID_PTR_OR_NULL(ti->ti_Data)
+
+                                       lv->Items = (void *)ti->ti_Data;
+                                       lv->GetItemFunc         = ArrayGetItem;
+                                       lv->GetNextFunc         = ArrayGetItem;
+                                       lv->GetPrevFunc         = ArrayGetItem;
+                                       lv->DrawItemFunc        = StringDrawItem;
+                                       lv->Flags &= ~LVF_LIST;
+
+                                       lv->Total = GetTagData (LVA_Total, ~0, msg->opu_AttrList);
+                                       if ((lv->Total == ~0) && lv->Items)
+                                       {
+                                               /* Count items */
+                                               ULONG i = 0;
+                                               while (((APTR *)lv->Items)[i]) i++;
+                                               lv->Total = i;
+                                       }
+
+                                       lv->SelectCount = CountSelections(lv);
+
+                                       action |= LVF_REDRAW | LVF_NOTIFYALL;
+                               }
+                               break;
+
+                       case LVA_ImageList:
+                               DB2 (DBPRINTF ("  LVA_ImageList, $%lx\n", ti->ti_Data);)
+
+                               if (ti->ti_Data == (ULONG)~0L)
+                                       lv->Items = NULL;
+                               else
+                               {
+                                       ASSERT_VALID_PTR_OR_NULL(ti->ti_Data)
+
+                                       lv->Items = (void *) ti->ti_Data;
+                                       lv->GetItemFunc         = ListGetItem;
+                                       lv->GetNextFunc         = ListGetNext;
+                                       lv->GetPrevFunc         = ListGetPrev;
+                                       lv->DrawItemFunc        = ListImageDrawItem;
+                                       lv->Flags |= LVF_LIST;
+
+                                       lv->Total = GetTagData (LVA_Total, ~0, msg->opu_AttrList);
+                                       if (lv->Total == ~0)
+                                               lv->Total = CountNodes(lv->Items);
+
+                                       lv->SelectCount = CountSelections(lv);
+
+                                       action |= LVF_REDRAW | LVF_NOTIFYALL;
+                               }
+                               break;
+
+                       case LVA_ImageArray:
+                               DB2 (DBPRINTF ("  LVA_ImageArray, $%lx\n", ti->ti_Data);)
+
+                               if (ti->ti_Data == (ULONG)~0L)
+                                       lv->Items = NULL;
+                               else
+                               {
+                                       ASSERT_VALID_PTR_OR_NULL(ti->ti_Data)
+
+                                       lv->Items = (void *) ti->ti_Data;
+                                       lv->GetItemFunc         = ArrayGetItem;
+                                       lv->GetNextFunc         = ArrayGetItem;
+                                       lv->GetPrevFunc         = ArrayGetItem;
+                                       lv->DrawItemFunc        = ImageDrawItem;
+                                       lv->Flags &= ~LVF_LIST;
+
+                                       lv->Total = GetTagData (LVA_Total, ~0, msg->opu_AttrList);
+                                       if ((lv->Total == ~0) && lv->Items)
+                                       {
+                                               /* Count items */
+                                               ULONG i = 0;
+                                               while (((APTR *)lv->Items)[i]) i++;
+                                               lv->Total = i;
+                                       }
+
+                                       action |= LVF_REDRAW | LVF_NOTIFYALL;
+                               }
+                               break;
+
+                       case LVA_CustomList:
+                               DB2 (DBPRINTF ("  LVA_CustomList, $%lx\n", ti->ti_Data);)
+
+                               if (ti->ti_Data == (ULONG)~0L)
+                                       lv->Items = NULL;
+                               else
+                               {
+                                       ASSERT_VALID_PTR_OR_NULL(ti->ti_Data)
+
+                                       lv->Items = (void *) ti->ti_Data;
+                                       lv->SelectCount = CountSelections (lv);
+
+                                       action |= LVF_REDRAW | LVF_NOTIFYALL;
+                               }
+                               break;
+
+                       case LVA_Visible:
+                               DB2 (DBPRINTF ("  LVA_Visible, %ld\n", ti->ti_Data);)
+
+                               /* This attribute can only be set internally, and will
+                                * trigger a full slider notification.
+                                */
+                               lv->Visible = (LONG)ti->ti_Data;
+                               action |= LVF_NOTIFYALL;
+
+
+                               /* Also scroll the ListView if needed. */
+                               if (lv->ClipRegion)
+                               {
+                                       LONG height = lv->Total * (lv->ItemHeight + lv->Spacing);
+                                       LONG newtop;
+
+                                       if (lv->PixelTop + lv->GBox.Height >= height)
+                                       {
+                                               lv->PixelTop = height - lv->GBox.Height;
+                                               if (lv->PixelTop < 0)
+                                                       lv->PixelTop = 0;
+
+                                               newtop = lv->PixelTop / (lv->ItemHeight + lv->Spacing);
+                                               if (newtop != lv->Top)
+                                               {
+                                                       lv->Top = newtop;
+                                                       lv->TopPtr = GetItem(lv, newtop);
+                                               }
+                                               action |= LVF_SCROLL;
+                                       }
+                               }
+                               else if (lv->Top + lv->Visible >= lv->Total)
+                               {
+                                       lv->Top = (lv->Total <= lv->Visible) ? 0 : (lv->Total - lv->Visible);
+                                       lv->TopPtr = GetItem(lv, lv->Top);
+                                       lv->PixelTop = lv->Top * (lv->ItemHeight + lv->Spacing);
+                                       action |= LVF_SCROLL;
+                               }
+                               break;
+
+                       case LVA_SelectArray:
+                               DB2 (DBPRINTF ("  LVA_SelectArray, $%lx\n", ti->ti_Data);)
+                               ASSERT_VALID_PTR_OR_NULL(ti->ti_Data)
+
+                               lv->SelectArray = (ULONG *)ti->ti_Data;
+                               lv->SelectCount = CountSelections (lv);
+                               action |= LVF_REDRAW;
+                               break;
+
+                       case LVA_MaxSelect:
+                               DB2(DBPRINTF("  LVA_MaxSelect, %ld\n", ti->ti_Data);)
+
+                               lv->MaxSelect = ti->ti_Data;
+                               /* NOTE: We are not checking lv->SelectCount */
+                               break;
+
+                       case LVA_PixelTop:      /* Handle pixel-wise scrolling */
+                               DB2(DBPRINTF("  LVA_PixelTop, %ld\n", ti->ti_Data);)
+
+                               if (((LONG)ti->ti_Data != lv->PixelTop) && lv->Items && lv->ItemHeight)
+                               {
+                                       LONG newtop;
+
+                                       lv->PixelTop = (LONG)ti->ti_Data;
+                                       action |= LVF_SCROLL;
+
+                                       newtop = lv->PixelTop / (lv->ItemHeight + lv->Spacing);
+                                       newtop = ((newtop + lv->Visible) >= lv->Total) ?
+                                               ((lv->Total <= lv->Visible) ? 0 : (lv->Total - lv->Visible))
+                                               : newtop;
+
+                                       if (newtop != lv->Top)
+                                       {
+                                               /* TODO: optimize GetItem() for some special cases:
+                                                * Top = oldtop + 1 and Top = oldtop - 1
+                                                */
+                                               lv->Top = newtop;
+                                               lv->TopPtr = GetItem(lv, newtop);
+                                               action |= LVF_NOTIFY | LVF_SCROLL;
+                                       }
+                               }
+                               break;
+
+                       case LVA_ScrollRatio:
+                               DB2 (DBPRINTF ("  LVA_ScrollRatio, %ld\n", ti->ti_Data);)
+                               ASSERT(ti->ti_Data != 0)
+
+                               lv->ScrollRatio = (LONG)ti->ti_Data;
+                               lv->MaxScroll = lv->GBox.Height / lv->ScrollRatio;
+                               break;
+
+                       default:
+                               DB2 (DBPRINTF ("  Passing unknown tag to superclass: $%lx, %ld\n",
+                                       ti->ti_Tag, ti->ti_Data);)
+
+                               /* This little optimization avoids forwarding the
+                                * OM_SET method to our superclass then there are
+                                * no unknown tags.
+                                */
+                               action |= LVF_DO_SUPER_METHOD;
+                               break;
+               }
+
+       DB2 (DBPRINTF ("  TAG_DONE\n");)
+
+       /* Forward method to our superclass dispatcher, only if needed */
+
+       if (action & LVF_DO_SUPER_METHOD)
+               result = (DoSuperMethodA (cl, (Object *)g, (Msg) msg));
+       else
+               result = TRUE;
+
+
+       /* Update gadget imagery, only when needed */
+
+       if ((action & (LVF_REDRAW | LVF_SCROLL | LVF_TOGGLESELECT))
+               && msg->opu_GInfo && !(lv->Flags & LVF_DONTDRAW))
+       {
+               struct RastPort *rp;
+
+               if ((rp = ObtainGIRPort (msg->opu_GInfo)))
+               {
+                       /* Just redraw everything */
+                       if (action & LVF_REDRAW)
+                               DoMethod ((Object *)g, GM_RENDER, msg->opu_GInfo, rp, GREDRAW_REDRAW);
+                       else
+                       {
+                               /* Both these may happen at the same time */
+
+                               if (action & LVF_SCROLL)
+                                       DoMethod ((Object *)g, GM_RENDER, msg->opu_GInfo, rp,
+                                               GREDRAW_UPDATE);
+
+                               if (action & LVF_TOGGLESELECT)
+                                       DoMethod ((Object *)g, GM_RENDER, msg->opu_GInfo, rp,
+                                               GREDRAW_TOGGLE);
+                       }
+
+                       ReleaseGIRPort (rp);
+               }
+               DB1(else DBPRINTF ("*** ObtainGIRPort() failed!\n");)
+       }
+
+
+       /* Notify our targets about changed attributes */
+
+       if (action & LVF_NOTIFYALL)
+       {
+               DB2(DBPRINTF("ListViewClass: OM_NOTIFY ALL\n");)
+               DB2(DBPRINTF("  LVA_Top,           %ld\n", lv->Top);)
+               DB2(DBPRINTF("  LVA_Total,         %ld\n", lv->Total);)
+               DB2(DBPRINTF("  LVA_Visible,       %ld\n", lv->Visible);)
+               DB2(DBPRINTF("  LVA_Selected,      %ld\n", lv->Selected);)
+               DB2(DBPRINTF("  LVA_PixelTop,      %ld\n", lv->PixelTop);)
+               DB2(DBPRINTF("  LVA_PixelHeight,   %ld\n", lv->Total * (lv->ItemHeight + lv->Spacing));)
+               DB2(DBPRINTF("  LVA_PixelVVisible, %ld\n", lv->GBox.Height);)
+               DB2(DBPRINTF("  TAG_DONE\n");)
+
+               NotifyAttrs((Object *)g, msg->opu_GInfo,
+                       (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0,
+                       LVA_Top,                        lv->Top,
+                       LVA_Total,                      lv->Total,
+                       LVA_Visible,            lv->Visible,
+                       LVA_Selected,           lv->Selected,
+                       LVA_PixelTop,           lv->PixelTop,
+                       LVA_PixelHeight,        lv->Total * (lv->ItemHeight + lv->Spacing),
+                       LVA_PixelVVisible,      lv->ClipRegion ?
+                                                                       lv->GBox.Height :
+                                                                       lv->Visible * (lv->ItemHeight + lv->Spacing),
+                       GA_ID,                          g->GadgetID,
+                       TAG_DONE);
+       }
+       else if (action & LVF_NOTIFY)
+       {
+               IPTR tags[9];
+               int cnt = 0;
+
+               if (action & LVF_SCROLL)
+               {
+                       tags[0] = LVA_Top;                      tags[1] = lv->Top;
+                       tags[2] = LVA_PixelTop;         tags[3] = lv->Top * (lv->ItemHeight + lv->Spacing);
+                       cnt = 4;
+               }
+
+               if (action & LVF_TOGGLESELECT)
+               {
+                       tags[cnt++] = LVA_Selected;     tags[cnt++] = lv->Selected;
+               }
+
+               tags[cnt++]     = GA_ID;                        tags[cnt++]     = g->GadgetID;
+               tags[cnt]       = TAG_DONE;
+
+               DoMethod((Object *)g, OM_NOTIFY, tags, msg->opu_GInfo,
+                       (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0);
+       }
+
+       return result;
+}
+
+
+
+static ULONG LV_OMGet(Class *cl, struct Gadget *g, struct opGet *msg)
+{
+       struct LVData *lv = INST_DATA (cl, g);
+
+       ASSERT_VALID_PTR(lv)
+       ASSERT_VALID_PTR(msg->opg_Storage)
+
+       DB2 (DBPRINTF("ListViewClass: OM_GET\n");)
+
+
+       switch (msg->opg_AttrID)
+       {
+               case LVA_Selected:
+                       *msg->opg_Storage = (ULONG) lv->Selected;
+                       return TRUE;
+
+               case LVA_Top:
+                       *msg->opg_Storage = (ULONG) lv->Top;
+                       return TRUE;
+
+               case LVA_Total:
+                       *msg->opg_Storage = (ULONG) lv->Total;
+                       return TRUE;
+
+               case LVA_StringList:
+               case LVA_StringArray:
+               case LVA_ImageList:
+               case LVA_ImageArray:
+               case LVA_CustomList:
+                       *msg->opg_Storage = (ULONG) lv->Items;
+                       return TRUE;
+
+               case LVA_Visible:
+                       *msg->opg_Storage = (ULONG) lv->Visible;
+                       return TRUE;
+
+               case LVA_SelectedPtr:
+                       *msg->opg_Storage = (ULONG) lv->SelectedPtr;
+                       return TRUE;
+
+               case LVA_SelectArray:
+                       *msg->opg_Storage = (ULONG) lv->SelectArray;
+                       return TRUE;
+
+               default:
+                       return DoSuperMethodA (cl, (Object *)g, (Msg) msg);
+       }
+}
+
+
+
+static ULONG LV_OMNew(Class *cl, struct Gadget *g, struct opSet *msg)
+{
+       struct LVData   *lv;
+       struct TagItem  *tag;
+       struct DrawInfo *drawinfo;
+
+
+       DB2(DBPRINTF("ListViewClass: OM_NEW\n");)
+
+       if ((g = (struct Gadget *)DoSuperMethodA(cl, (Object *)g, (Msg)msg)))
+       {
+               /* Set the GMORE_SCROLLRASTER flag */
+               if (g->Flags & GFLG_EXTENDED)
+               {
+                       DB(DBPRINTF("  Setting GMORE_SCROLLRASTER\n");)
+                       ((struct ExtGadget *)g)->MoreFlags |= GMORE_SCROLLRASTER;
+               }
+
+               lv = (struct LVData *) INST_DATA (cl, (Object *)g);
+               ASSERT_VALID_PTR(lv)
+
+               /* Handle creation-time attributes */
+
+               /* Map boolean attributes */
+               {
+                       static IPTR boolMap[] =
+                       {
+                               GA_ReadOnly,            LVF_READONLY,
+                               LVA_Clipped,            LVF_CLIPPED,
+                               LVA_ShowSelected,       LVF_SHOWSELECTED,
+                               LVA_DoMultiSelect,      LVF_DOMULTISELECT,
+                               TAG_DONE
+                       };
+
+                       lv->Flags = PackBoolTags (
+                               LVF_SHOWSELECTED,
+                               msg->ops_AttrList,
+                               (struct TagItem *)boolMap);
+               }
+
+
+               /* Select font to use when drawing the Listview labels */
+
+               /* First, try to get the font from our DrawInfo... */
+
+               if ((drawinfo = (struct DrawInfo *)
+                       GetTagData (GA_DrawInfo, NULL, msg->ops_AttrList)))
+               {
+                       ASSERT_VALID_PTR(drawinfo)
+                       lv->Font = drawinfo->dri_Font;
+               }
+               else
+                       lv->Font = NULL;
+
+
+               /* ...then override it with LVA_TextFont */
+
+               if ((tag = FindTagItem (LVA_TextFont, msg->ops_AttrList)))
+               {
+                       if (tag->ti_Data)
+                       {
+                               lv->Font = (struct TextFont *)tag->ti_Data;
+                               ASSERT_VALID_PTR_OR_NULL(lv->Font)
+                       }
+               }
+               else    /* Otherwise, try GA_TextAttr */
+               {
+                       struct TextAttr *attr;
+                       struct TextFont *font;
+
+                       if ((attr = (struct TextAttr *)GetTagData (GA_TextAttr,
+                               NULL, msg->ops_AttrList)))
+                       {
+                               if ((font = OpenFont(attr)))
+                               {
+                                       /* Must remember to close this font later */
+                                       lv->Flags |= LVF_CLOSEFONT;
+                                       lv->Font = font;
+                               }
+                       }
+               }
+
+               /* Calculate ItemHeight */
+
+               if (lv->Font)
+                       /* Get height from font Y size */
+                       lv->ItemHeight = lv->Font->tf_YSize;
+               else
+                       lv->ItemHeight = 0;
+
+               lv->ItemHeight = GetTagData(LVA_ItemHeight, lv->ItemHeight, msg->ops_AttrList);
+               lv->Spacing = GetTagData(LAYOUTA_Spacing, 0, msg->ops_AttrList);
+
+               if ((tag = FindTagItem(LVA_MaxPen, msg->ops_AttrList)))
+                       lv->MaxPen = tag->ti_Data;
+               else
+               {
+                       if (drawinfo)
+                               lv->MaxPen = max (
+                                       max (drawinfo->dri_Pens[BACKGROUNDPEN],
+                                               drawinfo->dri_Pens[TEXTPEN]),
+                                       max (drawinfo->dri_Pens[FILLPEN],
+                                               drawinfo->dri_Pens[FILLTEXTPEN]));
+                       else
+                               lv->MaxPen = (ULONG)-1;
+               }
+
+
+               lv->Total = GetTagData (LVA_Total, ~0, msg->ops_AttrList);
+
+               if ((lv->Items = (APTR) GetTagData (LVA_StringList, NULL, msg->ops_AttrList)))
+               {
+                       ASSERT_VALID_PTR_OR_NULL(lv->Items)
+                       lv->GetItemFunc = ListGetItem;
+                       lv->GetNextFunc = ListGetNext;
+                       lv->GetPrevFunc = ListGetPrev;
+                       lv->DrawItemFunc = ListStringDrawItem;
+                       lv->Flags |= LVF_LIST;
+
+                       if (lv->Total == ~0)
+                               lv->Total = CountNodes(lv->Items);
+               }
+               else if ((lv->Items = (APTR) GetTagData (LVA_StringArray, NULL, msg->ops_AttrList)))
+               {
+                       ASSERT_VALID_PTR_OR_NULL(lv->Items)
+                       lv->GetItemFunc = ArrayGetItem;
+                       lv->GetNextFunc = ArrayGetItem;
+                       lv->GetPrevFunc = ArrayGetItem;
+                       lv->DrawItemFunc = StringDrawItem;
+
+                       if (lv->Total == ~0)
+                       {
+                               /* Count items */
+                               ULONG i = 0;
+                               while (((APTR *)lv->Items)[i]) i++;
+                               lv->Total = i;
+                       }
+               }
+               else if ((lv->Items = (APTR)GetTagData(LVA_ImageList, NULL, msg->ops_AttrList)))
+               {
+                       ASSERT_VALID_PTR_OR_NULL(lv->Items)
+                       lv->GetItemFunc = ListGetItem;
+                       lv->GetNextFunc = ListGetNext;
+                       lv->GetPrevFunc = ListGetPrev;
+                       lv->DrawItemFunc = ListImageDrawItem;
+                       lv->Flags |= LVF_LIST;
+
+                       if (lv->Total == ~0)
+                               lv->Total = CountNodes(lv->Items);
+               }
+               else if ((lv->Items = (APTR) GetTagData (LVA_ImageArray, NULL, msg->ops_AttrList)))
+               {
+                       ASSERT_VALID_PTR_OR_NULL(lv->Items)
+                       lv->GetItemFunc = ArrayGetItem;
+                       lv->GetNextFunc = ArrayGetItem;
+                       lv->GetPrevFunc = ArrayGetItem;
+                       lv->DrawItemFunc = ImageDrawItem;
+
+                       if (lv->Total == ~0)
+                       {
+                               /* Count items */
+                               ULONG i = 0;
+                               while (((APTR *)lv->Items)[i]) i++;
+                               lv->Total = i;
+                       }
+               }
+
+               lv->SelectArray = (ULONG *)GetTagData (LVA_SelectArray, NULL, msg->ops_AttrList);
+               lv->MaxSelect = GetTagData (LVA_MaxSelect, -1, msg->ops_AttrList);
+               lv->SelectCount = CountSelections(lv);
+
+               if ((lv->Visible = GetTagData(LVA_Visible, 0, msg->ops_AttrList)))
+               {
+                       SetAttrs (g,
+                               GA_Height, lv->Visible * (lv->ItemHeight + lv->Spacing),
+                               TAG_DONE);
+               }
+
+               /* Initialize Top and all related values */
+
+               lv->OldTop = lv->Top = GetTagData(LVA_MakeVisible,
+                       GetTagData (LVA_Top, 0, msg->ops_AttrList), msg->ops_AttrList);
+               lv->OldPixelTop = lv->PixelTop = lv->Top * (lv->ItemHeight + lv->Spacing);
+
+               if (lv->Items)
+                       lv->TopPtr = GetItem(lv, lv->Top);
+
+               lv->ScrollRatio = GetTagData(LVA_ScrollRatio, 2, msg->ops_AttrList);
+               ASSERT(lv->ScrollRatio != 0)
+
+               if ((lv->OldSelected =
+                       lv->Selected = GetTagData(LVA_Selected, ~0, msg->ops_AttrList)) != ~0)
+                       lv->SelectedPtr = GetItem(lv, lv->Selected);
+
+               if ((lv->CallBack = (struct Hook *)GetTagData (LVA_CallBack, NULL,
+                       msg->ops_AttrList)))
+               {
+                       ASSERT_VALID_PTR_OR_NULL(lv->CallBack->h_Entry)
+                       lv->DrawItemFunc = (LVDrawHook *) lv->CallBack->h_Entry;
+               }
+
+               if (lv->Flags & LVF_CLIPPED)
+                       lv->ClipRegion = NewRegion ();
+       }
+       return (ULONG)g;
+}
+
+
+
+static void LV_OMDispose(Class *cl, struct Gadget *g, Msg msg)
+{
+       struct LVData   *lv;
+
+       lv = (struct LVData *) INST_DATA (cl, (Object *)g);
+
+       DB2 (DBPRINTF ("ListViewClass: OM_DISPOSE\n");)
+       ASSERT_VALID_PTR(lv)
+
+       if (lv->ClipRegion)
+               DisposeRegion (lv->ClipRegion);
+
+       if (lv->Flags & LVF_CLOSEFONT)
+               CloseFont(lv->Font);
+
+       /* Our superclass will cleanup everything else now */
+       DoSuperMethodA (cl, (Object *)g, (Msg) msg);
+
+       /* From now on, our instance data is no longer available */
+}
+
+
+
+/* Class support functions */
+
+
+Class *MakeListViewClass(void)
+{
+       Class *LVClass;
+
+       if ((LVClass = MakeClass(NULL, GADGETCLASS, NULL, sizeof (struct LVData), 0)))
+               LVClass->cl_Dispatcher.h_Entry = (ULONG (*)()) LVDispatcher;
+
+       return LVClass;
+}
+
+
+
+BOOL FreeListViewClass(Class *LVClass)
+{
+       ASSERT_VALID_PTR_OR_NULL(LVClass)
+       return FreeClass(LVClass);
+}
+
+
+#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB)
+/*
+ * Class library support functions
+ */
+
+struct ClassLibrary * HOOKCALL _UserLibInit(REG(a6, struct ClassLibrary *mybase))
+{
+       /* Initialize SysBase */
+       SysBase = *((struct ExecBase **)4UL);
+
+       if (!((UtilityBase = (UTILITYBASETYPE *) OpenLibrary("utility.library", 39)) &&
+               (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39)) &&
+               (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39)) &&
+               (LayersBase = OpenLibrary("layers.library", 39))))
+       {
+               _UserLibCleanup(mybase);
+               return NULL;
+       }
+
+       if (!(mybase->cl_Class = MakeListViewClass()))
+       {
+               _UserLibCleanup(mybase);
+               return NULL;
+       }
+
+       AddClass(mybase->cl_Class);
+       return mybase;
+}
+
+struct ClassLibrary * HOOKCALL _UserLibCleanup(REG(a6, struct ClassLibrary *mybase))
+{
+       if (mybase->cl_Class)
+               if (!FreeListViewClass(mybase->cl_Class))
+                       return NULL;
+
+       CloseLibrary((struct Library *)LayersBase);
+       CloseLibrary((struct Library *)GfxBase);
+       CloseLibrary((struct Library *)IntuitionBase);
+       CloseLibrary((struct Library *)UtilityBase);
+
+       return mybase;
+}
+
+Class * HOOKCALL _GetEngine(REG(a6, struct ClassLibrary *mybase))
+{
+       return mybase->cl_Class;
+}
+
+#endif /* (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) */
diff --git a/gadgets/ListView/ListViewClass_static.newinline.s b/gadgets/ListView/ListViewClass_static.newinline.s
new file mode 100644 (file)
index 0000000..aa2c682
--- /dev/null
@@ -0,0 +1,4072 @@
+#NO_APP
+gcc2_compiled.:
+___gnu_compiled_c:
+.text
+       .even
+_LVDispatcher:
+       moveml #0x2030,sp@-
+       movel a2,d1
+       movel a1@,d0
+       moveq #6,d2
+       cmpl d0,d2
+       jeq L14
+       jcs L23
+       moveq #2,d2
+       cmpl d0,d2
+       jeq L11
+       jcs L24
+       moveq #1,d2
+       cmpl d0,d2
+       jeq L10
+       jra L20
+       .even
+L24:
+       moveq #3,d2
+       cmpl d0,d2
+       jeq L12
+       moveq #4,d2
+       cmpl d0,d2
+       jeq L13
+       jra L20
+       .even
+L23:
+       cmpl #259,d0
+       jeq L16
+       jhi L25
+       cmpl #257,d0
+       jeq L18
+       cmpl #258,d0
+       jeq L19
+       jra L20
+       .even
+L25:
+       cmpl #260,d0
+       jeq L17
+       cmpl #264,d0
+       jeq L16
+       jra L20
+       .even
+L10:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMRender
+       moveq #1,d0
+       jra L26
+       .even
+L11:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMGoActive
+       jra L27
+       .even
+L12:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMHandleInput
+       jra L27
+       .even
+L13:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMGoInactive
+       moveq #1,d0
+       jra L26
+       .even
+L14:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMLayout
+       moveq #1,d0
+       jra L26
+       .even
+L16:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_OMSet
+       jra L27
+       .even
+L17:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_OMGet
+       jra L27
+       .even
+L18:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_OMNew
+       jra L27
+       .even
+L19:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_OMDispose
+       moveq #1,d0
+       jra L26
+       .even
+L20:
+       movel a0@(24),a0
+       movel a0@(8),a3
+       movel d1,a2
+       jbsr a3@
+L27:
+L26:
+       moveml sp@+,#0xc04
+       rts
+       .even
+_RedrawItems:
+       lea sp@(-40),sp
+       moveml #0x303c,sp@-
+       movel a0,a4
+       movel d0,d2
+       movel d1,d3
+       movel sp@(68),a5
+       movel d2,sp@(28)
+       movel a4@,sp@(32)
+       movel a1@(8),sp@(36)
+       movel a1@(4),a0
+       movel a0@(30),sp@(40)
+       movel a4@(90),sp@(56)
+       movew a4@(150),sp@(44)
+       movew a4@(154),sp@(48)
+       tstl a4@(138)
+       jeq L68
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d2,d0
+       addw a4@(152),d0
+       subw a4@(22),d0
+       jra L69
+       .even
+L68:
+       subl a4@(4),d2
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d2,d0
+       addw a4@(152),d0
+L69:
+       movew d0,sp@(46)
+       addw a4@(62),d0
+       subqw #1,d0
+       movew d0,sp@(50)
+       moveq #24,d2
+       addl sp,d2
+       tstl a5
+       jne L71
+       movel #517,sp@(24)
+       movel a4@(106),a3
+       movel d2,a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a5
+L71:
+       movel a4@(118),a3
+       tstl a3
+       jeq L73
+       movel #518,sp@(24)
+       movel d2,a2
+       movel a5,a1
+       movel a4@(130),a0
+       jbsr a3@
+       jra L73
+       .even
+L82:
+       movel #515,sp@(24)
+       movel a4@(110),a3
+       movel d2,a2
+       movel a5,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a5
+       movew a4@(62),d0
+       addw a4@(66),d0
+       addw d0,sp@(46)
+       addw d0,sp@(50)
+L73:
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L76
+       movel a4@(76),a0
+       tstl a0
+       jeq L77
+       movel sp@(28),d0
+       movel a0@(d0:l:4),d0
+       jra L81
+       .even
+L77:
+       btst #28,d0
+       jeq L79
+       clrl d0
+       moveb a5@(8),d0
+       jra L81
+       .even
+L79:
+       clrl d0
+       jra L81
+       .even
+L76:
+       movel sp@(28),d0
+       cmpl a4@(24),d0
+       seq d0
+       extbl d0
+       negl d0
+L81:
+       tstl d0
+       sne d0
+       extbl d0
+       negl d0
+       movel d0,sp@(52)
+       movel #514,sp@(24)
+       movel a4@(126),a3
+       movel d2,a2
+       movel a5,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel sp@(28),d0
+       movel d0,d1
+       addql #1,d1
+       movel d1,sp@(28)
+       addql #1,d0
+       cmpl d0,d3
+       jge L82
+       movel a4@(122),a3
+       tstl a3
+       jeq L84
+       movel #519,sp@(24)
+       movel a5,a1
+       movel a4@(130),a0
+       jbsr a3@
+L84:
+       moveml sp@+,#0x3c0c
+       lea sp@(40),sp
+       rts
+       .even
+_LV_GMRender:
+       lea sp@(-72),sp
+       moveml #0x3f3e,sp@-
+       movel a1,sp@(60)
+       movel d0,sp@(56)
+       clrl d0
+       movew a0@(32),d0
+       movel a1,a4
+       addl d0,a4
+       movel sp@(56),a0
+       movel a0@(8),a5
+       btst #5,a4@(90)
+       jne L85
+       tstl a4@
+       jeq L87
+       tstl a4@(16)
+       jeq L87
+       clrl sp@(52)
+       clrw sp@(46)
+       movel a5@(52),d0
+       movel a4@(134),d1
+       cmpl d0,d1
+       jeq L88
+       movel d0,sp@(52)
+       movel _GfxBase,a2
+       movel a2,a6
+       movel d1,a0
+       movel a5,a1
+       jbsr a2@(-66)
+L88:
+       tstl a4@(138)
+       jeq L89
+       movel sp@(56),a1
+       movel a1@(8),a0
+       movel a0@,a0
+       btst #4,a0@(31)
+       jeq L90
+       movew #1,sp@(46)
+       movel _LayersBase,a1
+       movel a1,a6
+       clrl d0
+       jbsr a1@(-84)
+L90:
+       movel _LayersBase,a2
+       movel a2,a6
+       movel a4@(138),a1
+       movel a5@,a0
+       jbsr a2@(-174)
+       movel d0,sp@(48)
+L89:
+       movel sp@(56),a2
+       movel a2@(12),d0
+       moveq #1,d1
+       cmpl d0,d1
+       jeq L127
+       jlt L157
+       tstl d0
+       jeq L92
+       jra L91
+       .even
+L157:
+       moveq #2,d3
+       cmpl d0,d3
+       jeq L138
+       jra L91
+       .even
+L92:
+       clrw d3
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L93
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       sgt d0
+       moveb d0,d3
+       extw d3
+       negw d3
+L93:
+       clrw d4
+       movel a4@(48),d2
+       cmpl d2,d1
+       jgt L94
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       sgt d0
+       moveb d0,d4
+       extw d4
+       negw d4
+L94:
+       tstw d4
+       jne L96
+       tstw d3
+       jeq L95
+L96:
+       movel a4@,sp@(84)
+       movel a5,sp@(88)
+       movel sp@(56),a1
+       movel a1@(4),a0
+       movel a0@(30),sp@(92)
+       movel a4@(90),sp@(108)
+       movel a4@(118),a3
+       tstl a3
+       jeq L97
+       movel #518,sp@(76)
+       lea sp@(76),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+L97:
+       movel #514,sp@(76)
+       tstw d3
+       jeq L98
+       movel a4@(24),d1
+       movew a4@(150),sp@(96)
+       movew a4@(154),sp@(100)
+       tstl a4@(138)
+       jeq L99
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d0,d1
+       movew d1,d0
+       addw a4@(152),d0
+       subw a4@(22),d0
+       jra L100
+       .even
+L99:
+       subl a4@(4),d1
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d0,d1
+       movew d1,d0
+       addw a4@(152),d0
+L100:
+       movew d0,sp@(98)
+       addw a4@(62),d0
+       subqw #1,d0
+       movew d0,sp@(102)
+       movel a4@(28),a1
+       movel a4@(24),d1
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L102
+       movel a4@(76),a0
+       tstl a0
+       jeq L103
+       movel a0@(d1:l:4),d0
+       jra L104
+       .even
+L103:
+       btst #28,d0
+       jeq L105
+       tstl a1
+       jne L166
+       movel #517,sp@(64)
+       movel d1,sp@(68)
+       movel a4@,sp@(72)
+       movel a4@(106),a3
+       lea sp@(64),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L108
+L166:
+       clrl d0
+       moveb a1@(8),d0
+       jra L104
+       .even
+L108:
+L105:
+       clrl d0
+       jra L104
+       .even
+L102:
+       moveq #1,d0
+L104:
+       tstl d0
+       sne d0
+       extbl d0
+       negl d0
+       movel d0,sp@(104)
+       movel a4@(24),sp@(80)
+       movel a4@(126),a3
+       lea sp@(76),a2
+       movel a4@(28),a1
+       movel a4@(130),a0
+       jbsr a3@
+L98:
+       tstw d4
+       jeq L112
+       movel a4@(48),d1
+       movew a4@(150),sp@(96)
+       movew a4@(154),sp@(100)
+       tstl a4@(138)
+       jeq L113
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d0,d1
+       movew d1,d0
+       addw a4@(152),d0
+       subw a4@(22),d0
+       jra L114
+       .even
+L113:
+       subl a4@(4),d1
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d0,d1
+       movew d1,d0
+       addw a4@(152),d0
+L114:
+       movew d0,sp@(98)
+       addw a4@(62),d0
+       subqw #1,d0
+       movew d0,sp@(102)
+       movel a4@(52),a1
+       movel a4@(48),d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L116
+       movel a4@(76),a0
+       tstl a0
+       jeq L117
+       movel a0@(d0:l:4),d0
+       jra L118
+       .even
+L117:
+       btst #28,d1
+       jeq L119
+       tstl a1
+       jne L167
+       movel #517,sp@(64)
+       movel d0,sp@(68)
+       movel a4@,sp@(72)
+       movel a4@(106),a3
+       lea sp@(64),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L122
+L167:
+       clrl d0
+       moveb a1@(8),d0
+       jra L118
+       .even
+L122:
+L119:
+       clrl d0
+       jra L118
+       .even
+L116:
+       cmpl a4@(24),d0
+       seq d0
+       extbl d0
+       negl d0
+L118:
+       tstl d0
+       sne d0
+       extbl d0
+       negl d0
+       movel d0,sp@(104)
+       movel a4@(48),sp@(80)
+       movel a4@(126),a3
+       lea sp@(76),a2
+       movel a4@(52),a1
+       movel a4@(130),a0
+       jbsr a3@
+L112:
+       movel a4@(122),a3
+       tstl a3
+       jeq L95
+       movel #519,sp@(76)
+       lea sp@(76),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+L95:
+       movel a4@(24),a4@(48)
+       movel a4@(28),a4@(52)
+       jra L91
+       .even
+L127:
+       movel _GfxBase,a2
+       movel sp@(56),a1
+       movel a1@(4),a0
+       movel a0@(30),a0
+       movel a0@(4),a0
+       movel a2,a6
+       clrl d0
+       movew a0@(14),d0
+       movel a5,a1
+       jbsr a2@(-342)
+       movel a4@(64),a1
+       tstl a1
+       jeq L128
+       tstl a4@
+       jeq L128
+       movel a4@(16),d1
+       jeq L128
+       movew a4@(152),a0
+       movel a0,a3
+       addl a4@(60),a3
+       movel a4@(12),d0
+       subl a4@(4),d0
+       cmpl d0,d1
+       jge L129
+       movel d1,d0
+L129:
+       subql #1,d0
+       tstl d0
+       jle L135
+       movel d0,d4
+       negl d0
+       moveq #3,d1
+       andl d1,d0
+       jeq L133
+       cmpl d0,d1
+       jle L170
+       moveq #2,d3
+       cmpl d0,d3
+       jle L171
+       movel _GfxBase,a0
+       movel a0,a6
+       lea a1@(-1,a3:l),a1
+       movel a1,d3
+       movew a4@(154),d2
+       extl d2
+       movel a3,d1
+       movew a4@(150),d0
+       extl d0
+       movel a5,a1
+       jbsr a0@(-306)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       addl d0,a3
+       subql #1,d4
+L171:
+       movel _GfxBase,a0
+       movel a3,d3
+       addl a4@(64),d3
+       movel a0,a6
+       subql #1,d3
+       movew a4@(154),d2
+       extl d2
+       movel a3,d1
+       movew a4@(150),d0
+       extl d0
+       movel a5,a1
+       jbsr a0@(-306)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       addl d0,a3
+       subql #1,d4
+L170:
+       movel _GfxBase,a0
+       movel a3,d3
+       addl a4@(64),d3
+       movel a0,a6
+       subql #1,d3
+       movew a4@(154),d2
+       extl d2
+       movel a3,d1
+       movew a4@(150),d0
+       extl d0
+       movel a5,a1
+       jbsr a0@(-306)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       addl d0,a3
+       subql #1,d4
+       jeq L135
+       .even
+L133:
+       movel _GfxBase,a0
+       movel a3,d3
+       addl a4@(64),d3
+       movel a0,a6
+       subql #1,d3
+       movew a4@(154),d2
+       extl d2
+       movel a3,d1
+       movew a4@(150),d0
+       extl d0
+       movel a5,a1
+       jbsr a0@(-306)
+       movel a4@(64),a0
+       movel a4@(60),d0
+       addl a0,d0
+       addl d0,a3
+       movel _GfxBase,a2
+       movel a2,a6
+       lea a0@(-1,a3:l),a0
+       movel a0,d3
+       movew a4@(154),d2
+       extl d2
+       movel a3,d1
+       movew a4@(150),d0
+       extl d0
+       movel a5,a1
+       jbsr a2@(-306)
+       movel a4@(64),a0
+       movel a4@(60),d0
+       addl a0,d0
+       addl d0,a3
+       movel _GfxBase,a2
+       movel a2,a6
+       lea a0@(-1,a3:l),a0
+       movel a0,d3
+       movew a4@(154),d2
+       extl d2
+       movel a3,d1
+       movew a4@(150),d0
+       extl d0
+       movel a5,a1
+       jbsr a2@(-306)
+       movel a4@(64),a0
+       movel a4@(60),d0
+       addl a0,d0
+       addl d0,a3
+       movel _GfxBase,a2
+       movel a2,a6
+       lea a0@(-1,a3:l),a0
+       movel a0,d3
+       movew a4@(154),d2
+       extl d2
+       movel a3,d1
+       movew a4@(150),d0
+       extl d0
+       movel a5,a1
+       jbsr a2@(-306)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       addl d0,a3
+       subql #4,d4
+       jne L133
+       jra L135
+       .even
+L128:
+       movew a4@(152),a0
+       movel a4@(12),d1
+       subl a4@(4),d1
+       movel a4@(16),d0
+       cmpl d1,d0
+       jge L136
+       movel d0,d1
+L136:
+       mulsl a4@(60),d1
+       lea a0@(0,d1:l),a3
+L135:
+       movel _GfxBase,a0
+       movel a0,a6
+       movew a4@(156),d3
+       extl d3
+       movew a4@(154),d2
+       extl d2
+       movel a3,d1
+       movew a4@(150),d0
+       extl d0
+       movel a5,a1
+       jbsr a0@(-306)
+       movel a4@(4),d0
+       movel d0,d2
+       addl a4@(16),d2
+       movel a4@(12),d1
+       cmpl d1,d2
+       jge L137
+       movel d2,d1
+L137:
+       movel a4@(8),sp@-
+       subql #1,d1
+       movel sp@(60),a1
+       movel a4,a0
+       jbsr _RedrawItems
+       addql #4,sp
+       jra L91
+       .even
+L138:
+       tstl a4@(138)
+       jeq L139
+       movel a4@(20),d7
+       subl a4@(44),d7
+       jeq L91
+       movew a4@(148),d5
+       extl d5
+       jra L141
+       .even
+L139:
+       movel a4@(4),d0
+       movel a4@(40),d1
+       cmpl d0,d1
+       jeq L91
+       movel d0,d7
+       subl d1,d7
+       movel a4@(64),d1
+       movel a4@(60),d0
+       addl d1,d0
+       mulsl d0,d7
+       movel a4@(16),d5
+       mulsl d0,d5
+       subl d1,d5
+L141:
+       movel d7,d0
+       jge L144
+       negl d0
+L144:
+       cmpl a4@(68),d0
+       jle L143
+       movel a4@(4),d0
+       movel d0,d2
+       addl a4@(16),d2
+       movel a4@(12),d1
+       cmpl d1,d2
+       jge L145
+       movel d2,d1
+L145:
+       movel a4@(8),sp@-
+       subql #1,d1
+       movel sp@(60),a1
+       movel a4,a0
+       jbsr _RedrawItems
+       addql #4,sp
+       jra L146
+       .even
+L143:
+       movel _GfxBase,a1
+       movel a1,a6
+       movel a4@(94),d0
+       movel a5,a0
+       jbsr a1@(-990)
+       tstl d7
+       jle L147
+       movel _GfxBase,a2
+       movew a4@(144),a0
+       movew a4@(142),a1
+       movel a2,a6
+       moveq #63,d6
+       notb d6
+       subl d7,d5
+       movew a4@(146),d4
+       extl d4
+       movel a0,d3
+       movel a1,d2
+       movel a5,a1
+       movel d3,d1
+       addl d7,d1
+       movel d2,d0
+       movel a5,a0
+       jbsr a2@(-552)
+       tstl a4@(138)
+       jeq L148
+       movew a4@(148),a0
+       movel a4@(20),d1
+       addl a0,d1
+       subql #1,d1
+       movel a4@(60),d2
+       addl a4@(64),d2
+       divsl d2,d1
+       movel a4@(44),d0
+       addl a0,d0
+       divsl d2,d0
+       clrl sp@-
+       jra L187
+       .even
+L148:
+       movel a4@(16),d0
+       movel d0,d1
+       addl a4@(4),d1
+       clrl sp@-
+       subql #1,d1
+       addl a4@(40),d0
+       jra L187
+       .even
+L147:
+       movel _GfxBase,a2
+       movew a4@(144),a0
+       movew a4@(142),a1
+       movel a2,a6
+       moveq #63,d6
+       notb d6
+       addl d7,d5
+       movew a4@(146),d4
+       extl d4
+       movel a0,d3
+       subl d7,d3
+       movel a1,d2
+       movel a5,a1
+       movel a0,d1
+       movel d2,d0
+       movel a5,a0
+       jbsr a2@(-552)
+       tstl a4@(138)
+       jeq L151
+       movel a4@(60),d0
+       addl a4@(64),d0
+       movel a4@(44),d1
+       divsl d0,d1
+       movel a4@(20),d3
+       divsl d0,d3
+       movel d3,d0
+       clrl sp@-
+       jra L187
+       .even
+L151:
+       movel a4@(8),sp@-
+       movel a4@(40),d1
+       subql #1,d1
+       movel a4@(4),d0
+L187:
+       movel sp@(60),a1
+       movel a4,a0
+       jbsr _RedrawItems
+       addql #4,sp
+       movel a5@,a1
+       btst #0,a1@(31)
+       jeq L153
+       movel a1@(8),a0
+       tstl a0
+       jeq L154
+       movel a1@(16),d1
+       movel a0@(16),d0
+       cmpl d1,d0
+       jne L154
+       movel a1@(20),d1
+       movel a0@(20),d0
+       cmpl d1,d0
+       jne L154
+       movel a1@(156),a0
+       tstl a0
+       jeq L153
+       tstl a0@(8)
+       jeq L153
+L154:
+       moveb a5@(24),d6
+       movel _GfxBase,a1
+       movel a1,a6
+       clrl d0
+       movel a5,a0
+       jbsr a1@(-984)
+       movel _GfxBase,a0
+       movel a0,a6
+       movew a4@(156),d5
+       extl d5
+       movew a4@(154),d4
+       extl d4
+       movew a4@(152),d3
+       extl d3
+       movew a4@(150),d2
+       extl d2
+       movel d7,d1
+       clrl d0
+       movel a5,a1
+       jbsr a0@(-396)
+       movel _GfxBase,a1
+       movel a1,a6
+       clrl d0
+       moveb d6,d0
+       movel a5,a0
+       jbsr a1@(-984)
+L153:
+       movel _GfxBase,a1
+       movel a1,a6
+       moveq #-1,d0
+       movel a5,a0
+       jbsr a1@(-990)
+L146:
+       movel a4@(4),a4@(40)
+       movel a4@(20),a4@(44)
+L91:
+       tstl a4@(138)
+       jeq L158
+       movel _LayersBase,a2
+       movel a2,a6
+       movel sp@(48),a1
+       movel a5@,a0
+       jbsr a2@(-174)
+       tstw sp@(46)
+       jeq L158
+       movel _LayersBase,a1
+       movel sp@(56),a2
+       movel a2@(8),a0
+       movel a1,a6
+       movel a0@,a0
+       jbsr a1@(-78)
+L158:
+       tstl sp@(52)
+       jeq L161
+       movel _GfxBase,a2
+       movel a2,a6
+       movel sp@(52),a0
+       movel a5,a1
+       jbsr a2@(-66)
+       jra L161
+       .even
+L87:
+       moveq #1,d0
+       movel sp@(56),a0
+       cmpl a0@(12),d0
+       jne L85
+       movel _GfxBase,a2
+       movel a0@(4),a0
+       movel a0@(30),a0
+       movel a0@(4),a0
+       movel a2,a6
+       clrl d0
+       movew a0@(14),d0
+       movel a5,a1
+       jbsr a2@(-342)
+       movel _GfxBase,a0
+       movel a0,a6
+       movew a4@(156),d3
+       extl d3
+       movew a4@(154),d2
+       extl d2
+       movew a4@(152),d1
+       extl d1
+       movew a4@(150),d0
+       extl d0
+       movel a5,a1
+       jbsr a0@(-306)
+L161:
+       moveq #1,d0
+       movel sp@(56),a0
+       cmpl a0@(12),d0
+       jne L85
+       clrl d0
+       movel sp@(60),a1
+       movel a1@(18),a0
+       tstl a0
+       jeq L164
+       btst #2,a1@(13)
+       jeq L164
+       cmpw #-1,a0@(8)
+       seq d0
+       extbl d0
+       negl d0
+L164:
+       tstw d0
+       jeq L85
+       movel #518,sp@(88)
+       movel sp@(56),a2
+       movel a2@(8),sp@(92)
+       movew a4@(158),d1
+       swap d1
+       clrw d1
+       movew a4@(160),d0
+       extl d0
+       orl d0,d1
+       movel d1,sp@(96)
+       clrl sp@(100)
+       movel a2@(4),a0
+       movel a0@(30),sp@(104)
+       movew a4@(162),d1
+       swap d1
+       clrw d1
+       movew a4@(164),d0
+       extl d0
+       orl d0,d1
+       movel d1,sp@(108)
+       movel sp@(88),sp@(64)
+       movel sp@(92),sp@(68)
+       movel sp@(96),sp@(72)
+       movel sp@(100),sp@(76)
+       movel sp@(104),sp@(80)
+       movel d1,sp@(84)
+       movel sp@(60),a0
+       movel a0@(18),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       lea sp@(64),a1
+       jbsr a3@
+L85:
+       moveml sp@+,#0x7cfc
+       lea sp@(72),sp
+       rts
+       .even
+_LV_GMHandleInput:
+       lea sp@(-140),sp
+       moveml #0x3f3e,sp@-
+       movel a1,sp@(76)
+       movel d0,d6
+       clrl d0
+       movew a0@(32),d0
+       movel a1,a4
+       addl d0,a4
+       movel d6,a0
+       movel a0@(8),sp@(72)
+       clrl sp@(68)
+       movel sp@(72),a1
+       clrl d0
+       moveb a1@(4),d0
+       moveq #2,d1
+       cmpl d0,d1
+       jeq L221
+       jlt L279
+       moveq #1,d1
+       cmpl d0,d1
+       jeq L194
+       jra L193
+       .even
+L279:
+       moveq #6,d1
+       cmpl d0,d1
+       jeq L268
+       jra L193
+       .even
+L194:
+       movel sp@(72),a0
+       clrl d0
+       movew a0@(6),d0
+       moveq #76,d1
+       cmpl d0,d1
+       jeq L196
+       moveq #77,d1
+       cmpl d0,d1
+       jeq L208
+       jra L218
+       .even
+L196:
+       movel sp@(72),a0
+       movew a0@(8),d1
+       btst #0,a4@(93)
+       jne L198
+       btst #3,d1
+       jeq L197
+L198:
+       bftst d1{#30:#2}
+       jeq L199
+       movel a4@(16),d0
+       jpl L283
+       addql #1,d0
+L283:
+       asrl #1,d0
+       movel a4@(4),a4
+       subl d0,a4
+       movel a4,d0
+       jra L200
+       .even
+L199:
+       movel a4@(4),d0
+       subql #1,d0
+L200:
+       tstl d0
+       jge L212
+       clrl d0
+       jra L212
+       .even
+L197:
+       movew d1,d0
+       andw #48,d0
+       jne L281
+       bftst d1{#30:#2}
+       jeq L205
+       movel a4@(24),d0
+       subl a4@(16),d0
+       addql #1,d0
+       jra L204
+       .even
+L205:
+       movel a4@(24),d0
+       subql #1,d0
+L204:
+       tstl d0
+       jge L215
+L281:
+       clrl d0
+       jra L215
+       .even
+L208:
+       movel sp@(72),a1
+       movew a1@(8),d1
+       btst #0,a4@(93)
+       jne L210
+       movew d1,d2
+       btst #3,d2
+       jeq L209
+L210:
+       bftst d1{#30:#2}
+       jeq L211
+       movel a4@(16),d0
+       jpl L284
+       addql #1,d0
+L284:
+       asrl #1,d0
+       addl a4@(4),d0
+       jra L212
+       .even
+L211:
+       movel a4@(4),d0
+       addql #1,d0
+L212:
+       movel #-2142480894,sp@(160)
+       movel d0,sp@(164)
+       clrl sp@(168)
+       jra L195
+       .even
+L209:
+       movew d2,d0
+       andw #48,d0
+       jeq L214
+       movel a4@(12),d0
+       subql #1,d0
+       jra L215
+       .even
+L214:
+       bftst d2{#30:#2}
+       jeq L216
+       movel a4@(24),d0
+       addl a4@(16),d0
+       subql #1,d0
+       jra L215
+       .even
+L216:
+       movel a4@(24),d0
+       addql #1,d0
+L215:
+       movel #-2142480895,sp@(160)
+       movel d0,sp@(164)
+       movel #-2142480888,sp@(168)
+       movel d0,sp@(172)
+       clrl sp@(176)
+       jra L195
+       .even
+L218:
+       clrl sp@(160)
+L195:
+       tstl sp@(160)
+       jeq L193
+       movel #264,sp@(128)
+       lea sp@(160),a2
+       movel a2,sp@(132)
+       movel d6,a0
+       movel a0@(4),sp@(136)
+       movel sp@(72),a1
+       movew a1@(8),d0
+       andw #9,d0
+       sne d0
+       extbl d0
+       negl d0
+       movel d0,sp@(140)
+       movel sp@(128),sp@(144)
+       movel a2,sp@(148)
+       movel sp@(136),sp@(152)
+       movel d0,sp@(156)
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       lea sp@(144),a1
+       jbsr a3@
+       jra L193
+       .even
+L221:
+       movel sp@(72),a0
+       clrl d0
+       movew a0@(6),d0
+       moveq #106,d1
+       cmpl d0,d1
+       jeq L256
+       jlt L267
+       moveq #104,d1
+       cmpl d0,d1
+       jeq L223
+       moveq #105,d1
+       cmpl d0,d1
+       jeq L249
+       jra L260
+       .even
+L267:
+       cmpl #232,d0
+       jeq L257
+       cmpl #234,d0
+       jeq L259
+       jra L260
+       .even
+L223:
+       movel d6,a0
+       movew a0@(16),d0
+       jlt L225
+       cmpw a4@(146),d0
+       jge L225
+       movew a0@(18),d1
+       jlt L225
+       cmpw a4@(148),d1
+       jlt L224
+L225:
+       movew #4,a1
+       movel a1,sp@(68)
+       jra L193
+       .even
+L224:
+       movel a4@(90),d0
+       bset #31,d0
+       movel d0,a4@(90)
+       btst #0,d0
+       jne L193
+       movel a4@(20),a0
+       lea a0@(d1:w),a2
+       movel a2,d5
+       movel a4@(60),d0
+       addl a4@(64),d0
+       divsl d0,d5
+       movel d5,d4
+       jlt L193
+       cmpl a4@(12),d4
+       jge L193
+       movel a4@(24),a4@(80)
+       movel a0,a4@(84)
+       lea sp@(128),a0
+       movel a0,sp@(52)
+       lea sp@(144),a1
+       movel a1,sp@(48)
+       lea sp@(148),a2
+       movel a2,sp@(44)
+       lea sp@(152),a2
+       lea sp@(140),a5
+       lea sp@(112),a0
+       movel a0,sp@(64)
+       lea sp@(116),a1
+       movel a1,sp@(60)
+       lea sp@(120),a0
+       movel a0,sp@(56)
+       moveq #124,d7
+       addl sp,d7
+       cmpl a4@(24),d4
+       jne L230
+       movel _IntuitionBase,a0
+       movel a0,a6
+       movel sp@(72),a1
+       movel a1@(18),d3
+       movel a1@(14),d2
+       movel a4@(102),d1
+       movel a4@(98),d0
+       jbsr a0@(-102)
+       tstw d0
+       jeq L230
+       movel #-2142480866,sp@(128)
+       movel d4,sp@(132)
+       clrl sp@(136)
+       movel #264,sp@(112)
+       movel sp@(52),sp@(116)
+       movel d6,a0
+       movel a0@(4),sp@(120)
+       clrl sp@(124)
+       movel sp@(64),a1
+       movel a1@,a5@
+       movel sp@(48),a0
+       movel sp@(60),a1
+       movel a1@,a0@
+       movel sp@(44),a0
+       movel sp@(56),a1
+       movel a1@,a0@
+       movel d7,a0
+       movel a0@,a2@
+       movel sp@(76),a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       movel a5,a1
+       movel sp@(76),a2
+       jbsr a3@
+L230:
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L232
+       movel a4@(76),a0
+       tstl a0
+       jeq L236
+       movel a0@(d5:l:4),d0
+       jra L237
+       .even
+L236:
+       btst #28,d0
+       jeq L233
+       movel #517,sp@(112)
+       movel d5,sp@(116)
+       movel a4@,sp@(120)
+       movel a4@(106),a3
+       lea sp@(112),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a0
+       clrl d0
+       tstl a0
+       jeq L241
+       clrl d0
+       moveb a0@(8),d0
+L241:
+L237:
+       movel #-2142480891,d1
+       tstl d0
+       jne L234
+L233:
+       movel #-2142480892,d1
+L234:
+       movel d1,a4@(56)
+       jra L245
+       .even
+L232:
+       movel sp@(76),a2
+       btst #0,a2@(14)
+       jeq L246
+       movel #-2142480895,a4@(56)
+       cmpl a4@(24),d5
+       jne L245
+       moveq #-1,d4
+       jra L245
+       .even
+L246:
+       movel #-2142480895,a4@(56)
+L245:
+       movel a4@(56),sp@(124)
+       movel d4,sp@(128)
+       clrl sp@(132)
+       movel sp@(64),a0
+       movel d7,a1
+       movel a1@,a0@
+       movel sp@(60),a2
+       movel sp@(52),a0
+       movel a0@,a2@
+       movel sp@(56),a1
+       movel sp@(132),a1@
+       lea sp@(136),a1
+       movel #264,sp@(96)
+       lea sp@(112),a2
+       movel a2,sp@(100)
+       movel d6,a0
+       movel a0@(4),sp@(104)
+       clrl sp@(108)
+       movel sp@(96),a1@
+       movel sp@(100),a5@
+       movel sp@(48),a2
+       movel sp@(104),a2@
+       movel sp@(44),a0
+       movel sp@(108),a0@
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       jbsr a3@
+       movel sp@(72),a0
+       movel a0@(14),a4@(98)
+       movel a0@(18),a4@(102)
+       jra L193
+       .even
+L249:
+       movel a4@(90),d1
+       movel d1,d0
+       andl #-1073741824,d0
+       jeq L250
+       movel d1,d0
+       andl #1073741823,d0
+       movel d0,a4@(90)
+       movel a4@(80),d2
+       cmpl a4@(24),d2
+       jne L252
+       movel a4@(84),a0
+       cmpl a4@(20),a0
+       jeq L193
+L252:
+       movel #-2142480895,d0
+       btst #0,d1
+       jeq L253
+       moveq #1,d0
+L253:
+       movel d0,sp@(116)
+       movel d2,sp@(120)
+       movel #-2142480864,sp@(124)
+       movel a4@(84),sp@(128)
+       clrl sp@(132)
+       movel d0,sp@(96)
+       movel d2,sp@(100)
+       movel sp@(124),sp@(104)
+       movel sp@(128),sp@(108)
+       movel sp@(132),sp@(112)
+       lea sp@(136),a1
+       movel #264,sp@(80)
+       lea sp@(96),a2
+       movel a2,sp@(84)
+       movel d6,a0
+       movel a0@(4),sp@(88)
+       clrl sp@(92)
+       movel sp@(80),a1@
+       movel sp@(84),sp@(140)
+       movel sp@(88),sp@(144)
+       movel sp@(92),sp@(148)
+       jra L282
+       .even
+L250:
+       moveq #4,d0
+       movel d0,sp@(68)
+       jra L193
+       .even
+L256:
+       movel a4@(20),a4@(84)
+       movel a4@(24),a4@(80)
+       movel d6,a0
+       movew a0@(18),a4@(88)
+       bset #7,a4@(90)
+       jra L193
+       .even
+L257:
+       bclr #7,a4@(90)
+       movel sp@(76),a1
+       btst #0,a1@(15)
+       jeq L193
+       lea a4@(24),a4
+       movel d6,a2
+       movel a4,a2@(12)
+       moveq #10,d0
+       movel d0,sp@(68)
+       jra L193
+       .even
+L259:
+       bclr #6,a4@(90)
+       jra L193
+       .even
+L260:
+       movel a4@(90),d1
+       jge L261
+       movel d6,a1
+       movew a1@(18),a0
+       movel a0,d4
+       addl a4@(20),d4
+       movel a4@(60),d0
+       addl a4@(64),d0
+       divsl d0,d4
+       cmpl a4@(24),d4
+       jeq L261
+       btst #0,d1
+       jne L261
+       movel a4@(4),d0
+       cmpl d4,d0
+       jgt L261
+       addl a4@(16),d0
+       cmpl d4,d0
+       jle L261
+       movel a4@(56),sp@(92)
+       movel d4,sp@(96)
+       clrl sp@(100)
+       movel sp@(92),sp@(80)
+       movel d4,sp@(84)
+       movel sp@(100),sp@(88)
+       lea sp@(104),a1
+       movel #264,sp@(120)
+       lea sp@(80),a2
+       movel a2,sp@(124)
+       movel d6,a0
+       movel a0@(4),sp@(128)
+       clrl sp@(132)
+       movel sp@(120),a1@
+       movel sp@(124),sp@(108)
+       movel sp@(128),sp@(112)
+       movel sp@(132),sp@(116)
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       jbsr a3@
+L261:
+       btst #6,a4@(90)
+       jeq L193
+       movel d6,a1
+       movew a1@(18),a0
+       subw a4@(88),a0
+       movel a0,d4
+       addl a4@(84),d4
+       movel #-2142480864,sp@(80)
+       movel d4,d0
+       jge L265
+       clrl d0
+L265:
+       movel d0,sp@(84)
+       clrl sp@(88)
+       movel #264,sp@(108)
+       lea sp@(80),a2
+       movel a2,sp@(112)
+       movel d6,a0
+       movel a0@(4),sp@(116)
+       clrl sp@(120)
+       movel sp@(108),sp@(92)
+       movel a2,sp@(96)
+       movel sp@(116),sp@(100)
+       movel sp@(120),sp@(104)
+       movel sp@(76),a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea sp@(92),a1
+       movel sp@(76),a2
+       jbsr a3@
+       jra L193
+       .even
+L268:
+       movel a4@(90),d2
+       jge L193
+       movel d6,a2
+       tstw a2@(18)
+       jge L270
+       movel a4@(4),d1
+       jeq L270
+       movel #-2142480887,sp@(100)
+       moveq #1,d0
+       movel d0,sp@(104)
+       movel #-2142480895,d0
+       btst #0,d2
+       jeq L271
+       moveq #1,d0
+L271:
+       movel d0,sp@(108)
+       subql #1,d1
+       movel d1,sp@(112)
+       clrl sp@(116)
+       movel sp@(100),sp@(80)
+       movel sp@(104),sp@(84)
+       movel d0,sp@(88)
+       movel d1,sp@(92)
+       movel sp@(116),sp@(96)
+       lea sp@(120),a1
+       movel #264,sp@(136)
+       lea sp@(80),a0
+       movel a0,sp@(140)
+       movel d6,a2
+       movel a2@(4),sp@(144)
+       clrl sp@(148)
+       movel sp@(136),a1@
+       movel sp@(140),sp@(124)
+       movel sp@(144),sp@(128)
+       movel sp@(148),sp@(132)
+L282:
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       jbsr a3@
+       jra L193
+       .even
+L270:
+       movel d6,a0
+       movew a0@(18),d0
+       extl d0
+       movel a4@(60),d1
+       addl a4@(64),d1
+       divsl d1,d0
+       movel a4@(16),d1
+       cmpl d0,d1
+       jgt L193
+       movel #-2142480886,sp@(100)
+       moveq #1,d0
+       movel d0,sp@(104)
+       movel #-2142480895,d0
+       btst #0,a4@(93)
+       jeq L275
+       moveq #1,d0
+L275:
+       movel d0,sp@(108)
+       addl a4@(4),d1
+       movel d1,sp@(112)
+       clrl sp@(116)
+       movel sp@(100),sp@(80)
+       movel sp@(104),sp@(84)
+       movel d0,sp@(88)
+       movel d1,sp@(92)
+       movel sp@(116),sp@(96)
+       lea sp@(120),a1
+       movel #264,sp@(136)
+       lea sp@(80),a0
+       movel a0,sp@(140)
+       movel d6,a2
+       movel a2@(4),sp@(144)
+       clrl sp@(148)
+       movel sp@(136),a1@
+       movel sp@(140),sp@(124)
+       movel sp@(144),sp@(128)
+       movel sp@(148),sp@(132)
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       jbsr a3@
+L193:
+       movel sp@(68),d0
+       moveml sp@+,#0x7cfc
+       lea sp@(140),sp
+       rts
+       .even
+_LV_GMLayout:
+       lea sp@(-64),sp
+       moveml #0x3f3e,sp@-
+       movel a1,a5
+       movel d0,sp@(44)
+       clrl d0
+       movew a0@(32),d0
+       lea a5@(0,d0:l),a4
+       bset #5,a4@(90)
+       lea a4@(142),a2
+       movel a2,d0
+       movel sp@(44),a3
+       movel a3@(4),a0
+       jbsr _GetGadgetBox
+       lea a4@(150),a0
+       movew a2@,a0@
+       movew a2@(2),a0@(2)
+       movew a2@,d0
+       addw a2@(4),d0
+       subqw #1,d0
+       movew d0,a0@(4)
+       movew a2@(2),d0
+       addw a2@(6),d0
+       subqw #1,d0
+       movew d0,a0@(6)
+       clrl d0
+       movel a5@(18),a0
+       tstl a0
+       jeq L289
+       btst #2,a5@(13)
+       jeq L289
+       cmpw #-1,a0@(8)
+       seq d0
+       extbl d0
+       negl d0
+L289:
+       moveq #64,d3
+       addl sp,d3
+       moveq #84,d2
+       addl sp,d2
+       moveq #88,d6
+       addl sp,d6
+       lea sp@(92),a1
+       moveq #76,d4
+       addl sp,d4
+       moveq #80,d5
+       addl sp,d5
+       tstw d0
+       jeq L288
+       movel #519,sp@(64)
+       lea a4@(142),a0
+       movel a0,sp@(68)
+       lea a4@(158),a2
+       movel a2,sp@(72)
+       movel sp@(44),a3
+       movel a3@(4),a0
+       movel a0@(30),sp@(76)
+       clrl sp@(80)
+       movel d2,a0
+       movel d3,a2
+       movel a2@,a0@
+       movel d6,a3
+       movel sp@(68),a3@
+       movel sp@(72),a1@
+       movel d4,a0
+       movel a0@,sp@(96)
+       movel d5,a1
+       movel a1@,sp@(100)
+       movel a5@(18),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       movel d2,a1
+       jbsr a3@
+L288:
+       movel a4@(138),d0
+       jeq L291
+       movel _GfxBase,a1
+       movel a1,a6
+       movel d0,a0
+       jbsr a1@(-528)
+       movel _GfxBase,a2
+       movel a2,a6
+       lea a4@(150),a1
+       movel a4@(138),a0
+       jbsr a2@(-510)
+L291:
+       tstl a4@(134)
+       jne L292
+       movel sp@(44),a2
+       movel a2@(4),a0
+       movel a0@(30),a0
+       movel a0@(8),a4@(134)
+       tstl a4@(60)
+       jne L298
+       movel a4@(134),a0
+       clrl d0
+       movew a0@(20),d0
+       movel d0,a4@(60)
+L292:
+       tstl a4@(60)
+       jeq L294
+L298:
+       tstl a4@(138)
+       jeq L295
+       movew a4@(148),a2
+       movel a4@(60),d0
+       lea a2@(0,d0:l),a1
+       movel a4@(64),a0
+       lea a0@(-1,a1:l),a1
+       movel a1,d1
+       addl a0,d0
+       divsl d0,d1
+       movel a2,d0
+       jra L297
+       .even
+L295:
+       movew a4@(148),a0
+       movel a4@(64),d0
+       movel a0,d1
+       addl d0,d1
+       addl a4@(60),d0
+       divsl d0,d1
+       movel a0,d0
+       jra L297
+       .even
+L294:
+       clrl d1
+       movew a4@(148),d0
+       extl d0
+L297:
+       movel d0,d7
+       divsl a4@(72),d7
+       movel d7,a4@(68)
+       movel #-2142480878,sp@(64)
+       movel d1,sp@(68)
+       clrl sp@(72)
+       movel #264,sp@(48)
+       movel d3,sp@(52)
+       movel sp@(44),a0
+       movel a0@(4),sp@(56)
+       clrl sp@(60)
+       movel d4,a1
+       movel sp@(48),a1@
+       movel d5,a2
+       movel sp@(52),a2@
+       movel d2,a3
+       movel sp@(56),a3@
+       movel d6,a0
+       movel sp@(60),a0@
+       movel a5@(-4),a0
+       movel a0@(8),a3
+       lea sp@(76),a1
+       movel a5,a2
+       jbsr a3@
+       bclr #5,a4@(90)
+       moveml sp@+,#0x7cfc
+       lea sp@(64),sp
+       rts
+       .even
+_LV_OMSet:
+       link a5,#-188
+       moveml #0x3f3a,sp@-
+       movel a0,d7
+       movel a1,d5
+       movel d0,a5@(-188)
+       clrl d0
+       movew a0@(32),d0
+       movel d5,a4
+       addl d0,a4
+       movel a5@(-188),a0
+       movel a0@(4),a5@(-184)
+       clrw d4
+       movel a5,d6
+       addl #-184,d6
+       jra L300
+       .even
+L302:
+       movel a0@,d0
+       cmpl #-2142480884,d0
+       jhi L583
+       cmpl #-2142480885,d0
+       jcc L300
+       cmpl #-2142480891,d0
+       jeq L352
+       jhi L584
+       cmpl #-2142480894,d0
+       jeq L318
+       jhi L585
+       cmpl #-2147287024,d0
+       jeq L304
+       cmpl #-2142480895,d0
+       jeq L306
+       jra L581
+       .even
+L585:
+       cmpl #-2142480893,d0
+       jeq L300
+       cmpl #-2142480892,d0
+       jeq L326
+       jra L581
+       .even
+L584:
+       cmpl #-2142480888,d0
+       jeq L422
+       jhi L586
+       cmpl #-2142480890,d0
+       jeq L374
+       cmpl #-2142480889,d0
+       jeq L404
+       jra L581
+       .even
+L586:
+       cmpl #-2142480887,d0
+       jeq L430
+       cmpl #-2142480886,d0
+       jeq L433
+       jra L581
+       .even
+L583:
+       cmpl #-2142480879,d0
+       jeq L524
+       jhi L587
+       cmpl #-2142480882,d0
+       jeq L465
+       jcs L438
+       cmpl #-2142480881,d0
+       jeq L489
+       cmpl #-2142480880,d0
+       jeq L516
+       jra L581
+       .even
+L587:
+       cmpl #-2142480865,d0
+       jeq L571
+       jhi L588
+       cmpl #-2142480878,d0
+       jeq L543
+       cmpl #-2142480876,d0
+       jeq L554
+       jra L581
+       .even
+L588:
+       cmpl #-2142480864,d0
+       jeq L572
+       cmpl #-2142480850,d0
+       jeq L580
+       jra L581
+       .even
+L304:
+       movel a5@(-188),a1
+       cmpl #259,a1@
+       jne L300
+       movel d5,a2
+       movew a0@(6),a2@(38)
+       jra L300
+       .even
+L306:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d1
+       moveq #-1,d0
+       cmpl d1,d0
+       jeq L308
+       movel a4@(12),d2
+       movel d1,d0
+       cmpl d0,d2
+       jgt L309
+       movel d2,d0
+       subql #1,d0
+L309:
+       movel d0,d1
+L308:
+       movel a4@(24),a0
+       cmpl a0,d1
+       jeq L300
+       movel a4@(4),d2
+       cmpl a0,d2
+       jgt L314
+       movel d2,d0
+       addl a4@(16),d0
+       cmpl a0,d0
+       jgt L313
+L314:
+       cmpl d1,d2
+       jgt L312
+       movel d2,d0
+       addl a4@(16),d0
+       cmpl d1,d0
+       jle L312
+L313:
+       orw #8,d4
+L312:
+       movel d1,a4@(24)
+       moveq #-1,d0
+       cmpl d1,d0
+       jne L315
+       clrl a4@(28)
+       jra L396
+       .even
+L315:
+       movel #517,a5@(-12)
+       movel d1,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+       jra L396
+       .even
+L318:
+       movel a0@(4),d2
+       cmpl a4@(4),d2
+       jeq L300
+       tstl a4@
+       jeq L300
+       movel a4@(16),a0
+       movel d2,d0
+       addl a0,d0
+       movel a4@(12),d1
+       cmpl d0,d1
+       jgt L321
+       cmpl d1,a0
+       slt d0
+       moveb d0,d2
+       extbl d2
+       subl a0,d1
+       andl d1,d2
+L321:
+       movel d2,a4@(4)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d2,d0
+       movel d0,a4@(20)
+       movel #517,a5@(-12)
+       movel d2,a5@(-8)
+       jra L755
+       .even
+L326:
+       movel a4@(32),d1
+       cmpl a4@(36),d1
+       jcs L327
+       movel _IntuitionBase,d0
+       movel d0,a0
+       lea a0@(-96),a2
+       movel a5@(-188),a0
+       movel a0@(8),a1
+       clrl d1
+       tstl a1
+       jeq L328
+       movel a1@,d1
+L328:
+       movel d0,a6
+       movel d1,a0
+       jbsr a2@
+       jra L300
+       .even
+L327:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d1
+       movel a4@(12),d0
+       movel d0,d3
+       subql #1,d3
+       cmpl d1,d0
+       jle L332
+       movel d1,d3
+L332:
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L336
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       jgt L335
+L336:
+       cmpl d3,d1
+       jgt L334
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d3,d0
+       jle L334
+L335:
+       orw #8,d4
+L334:
+       movel d3,a4@(24)
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+       movel d0,a1
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L339
+       movel a4@(76),a0
+       tstl a0
+       jeq L340
+       movel a0@(d3:l:4),d0
+       jra L341
+       .even
+L340:
+       btst #28,d0
+       jeq L610
+       tstl a1
+       jne L611
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L345
+L611:
+       clrl d0
+       moveb a1@(8),d0
+       jra L341
+       .even
+L345:
+       clrl d0
+       jra L341
+       .even
+L339:
+       cmpl a4@(24),d3
+       seq d0
+       extbl d0
+       negl d0
+L341:
+       tstl d0
+       jne L396
+L610:
+       movel a4@(32),d0
+       movel d0,a1
+       addql #1,a1
+       movel a1,a4@(32)
+       movel a4@(76),a0
+       tstl a0
+       jeq L401
+       addql #1,d0
+       movel d0,a0@(d3:l:4)
+       jra L396
+       .even
+L352:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d1
+       movel a4@(12),d0
+       movel d0,d3
+       subql #1,d3
+       cmpl d1,d0
+       jle L354
+       movel d1,d3
+L354:
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L358
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       jgt L357
+L358:
+       cmpl d3,d1
+       jgt L356
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d3,d0
+       jle L356
+L357:
+       orw #8,d4
+L356:
+       movel d3,a4@(24)
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+       movel d0,a1
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L361
+       movel a4@(76),a0
+       tstl a0
+       jeq L362
+       movel a0@(d3:l:4),d0
+       jra L363
+       .even
+L362:
+       btst #28,d0
+       jeq L300
+       tstl a1
+       jne L612
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L367
+L612:
+       clrl d0
+       moveb a1@(8),d0
+       jra L363
+       .even
+L367:
+       clrl d0
+       jra L363
+       .even
+L361:
+       cmpl a4@(24),d3
+       seq d0
+       extbl d0
+       negl d0
+L363:
+       tstl d0
+       jeq L300
+L771:
+       subql #1,a4@(32)
+       movel a4@(76),a0
+       tstl a0
+       jne L770
+       btst #4,a4@(90)
+       jeq L396
+       movel a4@(28),a0
+       clrb a0@(8)
+       jra L396
+       .even
+L374:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d1
+       movel a4@(12),d0
+       movel d0,d3
+       subql #1,d3
+       cmpl d1,d0
+       jle L376
+       movel d1,d3
+L376:
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L380
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       jgt L379
+L380:
+       cmpl d3,d1
+       jgt L378
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d3,d0
+       jle L378
+L379:
+       orw #8,d4
+L378:
+       movel d3,a4@(24)
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+       movel d0,a1
+       movel a4@(24),d1
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L383
+       movel a4@(76),a0
+       tstl a0
+       jeq L384
+       movel a0@(d1:l:4),d0
+       jra L385
+       .even
+L384:
+       btst #28,d0
+       jeq L382
+       tstl a1
+       jne L613
+       movel #517,a5@(-12)
+       movel d1,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L389
+L613:
+       clrl d0
+       moveb a1@(8),d0
+       jra L385
+       .even
+L389:
+       clrl d0
+       jra L385
+       .even
+L383:
+       moveq #1,d0
+L385:
+       tstl d0
+       jeq L382
+       jra L771
+       .even
+L770:
+       movel a4@(24),d0
+       clrl a0@(d0:l:4)
+       jra L396
+       .even
+L382:
+       movel a4@(32),d1
+       cmpl a4@(36),d1
+       jcs L397
+       movel _IntuitionBase,d0
+       movel d0,a0
+       lea a0@(-96),a2
+       movel a5@(-188),a0
+       movel a0@(8),a1
+       clrl d1
+       tstl a1
+       jeq L398
+       movel a1@,d1
+L398:
+       movel d0,a6
+       movel d1,a0
+       jbsr a2@
+       jra L396
+       .even
+L397:
+       movel d1,a1
+       addql #1,a1
+       movel a1,a4@(32)
+       movel a4@(76),a0
+       tstl a0
+       jeq L401
+       movel a4@(24),d0
+       addql #1,d1
+       movel d1,a0@(d0:l:4)
+       jra L396
+       .even
+L401:
+       btst #4,a4@(90)
+       jeq L396
+       movel a4@(28),a0
+       moveb a4@(35),a0@(8)
+L396:
+       orw #16,d4
+       jra L300
+       .even
+L404:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d3
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L408
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       jgt L407
+L408:
+       cmpl d3,d1
+       jgt L406
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d3,d0
+       jle L406
+L407:
+       orw #8,d4
+L406:
+       moveq #-1,d0
+       movel d0,a4@(24)
+       clrl a4@(28)
+       clrl a4@(32)
+       tstl a4@(76)
+       jeq L409
+       clrl d1
+       movew d4,d0
+       orw #18,d0
+       cmpl a4@(12),d1
+       jge L415
+       .even
+L413:
+       movel a4@(76),a0
+       clrl a0@(d1:l:4)
+       addql #1,d1
+       cmpl a4@(12),d1
+       jlt L413
+       jra L415
+       .even
+L409:
+       movew d4,d0
+       orw #18,d0
+       btst #4,a4@(90)
+       jeq L415
+       movel a4@,a0
+       jra L757
+       .even
+L420:
+       clrb a0@(8)
+L757:
+       movel a0@,a0
+       tstl a0@
+       jne L420
+L415:
+       movew d0,d4
+       jra L300
+       .even
+L422:
+       movel a0@(4),d1
+       jge L423
+       clrl d1
+L423:
+       movel a4@(12),d0
+       cmpl d1,d0
+       jgt L424
+       movel d0,d1
+       subql #1,d1
+L424:
+       movel a4@(4),d0
+       cmpl d1,d0
+       jle L425
+       movel d1,a4@(4)
+       movel #517,a5@(-12)
+       movel d1,a5@(-8)
+       jra L755
+       .even
+L425:
+       movel a4@(16),d2
+       addl d2,d0
+       cmpl d1,d0
+       jgt L300
+       subl d2,d1
+       movel d1,d0
+       addql #1,d0
+       jra L758
+       .even
+L430:
+       movel a4@(4),d0
+       jle L300
+       movel a4@,d1
+       jeq L300
+       movel d0,a0
+       subql #1,a0
+       movel a0,a4@(4)
+       movel a4@(8),a1
+       movel #516,a5@(-12)
+       subql #1,d0
+       movel d0,a5@(-8)
+       movel d1,a5@(-4)
+       movel a4@(114),a3
+       lea a5@(-12),a2
+       jra L759
+       .even
+L433:
+       movel a4@(4),d1
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl a4@(12),d0
+       jge L300
+       movel a4@,d0
+       jeq L300
+       movel d1,a1
+       addql #1,a1
+       movel a1,a4@(4)
+       movel a4@(8),a1
+       movel #515,a5@(-12)
+       addql #1,d1
+       movel d1,a5@(-8)
+       movel d0,a5@(-4)
+       movel a4@(110),a3
+       lea a5@(-12),a2
+       jra L759
+       .even
+L438:
+       movel a0@(4),d0
+       moveq #-1,d1
+       cmpl d0,d1
+       jeq L760
+       movel d0,a4@
+       movel #_ListGetItem,a4@(106)
+       movel #_ListGetNext,a4@(110)
+       movel #_ListGetPrev,a4@(114)
+       movel #_ListStringDrawItem,a4@(126)
+       bset #4,a4@(90)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(-188),a2
+       movel a2@(4),a0
+       moveq #-1,d1
+       movel #-2142480893,d0
+       jbsr a1@(-36)
+       movel d0,a4@(12)
+       movew d4,d3
+       orw #34,d3
+       moveq #-1,d1
+       cmpl d0,d1
+       jne L441
+       movel a4@,a0
+       clrl d0
+       tstl a0
+       jeq L442
+       movel a0@,a0
+       jra L761
+       .even
+L446:
+       addql #1,d0
+L761:
+       movel a0@,a0
+       tstl a0
+       jne L446
+L442:
+       movel d0,a4@(12)
+L441:
+       clrl d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L450
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L453
+       cmpl d1,d4
+       jle L728
+       moveq #2,d4
+       cmpl d1,d4
+       jle L729
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L729:
+       tstl a3@+
+       jeq L735
+       addql #1,d0
+L735:
+       subql #1,a2
+L728:
+       tstl a3@+
+       jeq L738
+       addql #1,d0
+L738:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L453:
+       movel a3,a0
+       tstl a0@+
+       jeq L741
+       addql #1,d0
+L741:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L744
+       addql #1,d0
+L744:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L747
+       addql #1,d0
+L747:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L750
+       addql #1,d0
+L750:
+       subql #4,a2
+       tstl a2
+       jne L453
+       jra L555
+       .even
+L450:
+       btst #28,d1
+       jeq L555
+       movel a4@,a0
+       tstl a0
+       jeq L555
+       movel a0@,a0
+       jra L762
+       .even
+L460:
+       addql #1,d0
+L762:
+       movel a0@,a0
+       tstl a0
+       jne L460
+       jra L555
+       .even
+L465:
+       movel a0@(4),d0
+       moveq #-1,d1
+       cmpl d0,d1
+       jeq L760
+       movel d0,a4@
+       movel #_ArrayGetItem,a4@(106)
+       movel #_ArrayGetItem,a4@(110)
+       movel #_ArrayGetItem,a4@(114)
+       movel #_StringDrawItem,a4@(126)
+       bclr #4,a4@(90)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(-188),a2
+       movel a2@(4),a0
+       moveq #-1,d1
+       movel #-2142480893,d0
+       jbsr a1@(-36)
+       movel d0,a4@(12)
+       movew d4,d3
+       orw #34,d3
+       moveq #-1,d1
+       cmpl d0,d1
+       jne L468
+       movel a4@,a0
+       tstl a0
+       jeq L468
+       clrl d0
+       tstl a0@
+       jeq L470
+       .even
+L471:
+       addql #1,d0
+       addql #4,a0
+       tstl a0@
+       jne L471
+L470:
+       movel d0,a4@(12)
+L468:
+       clrl d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L474
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L477
+       cmpl d1,d4
+       jle L700
+       moveq #2,d4
+       cmpl d1,d4
+       jle L701
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L701:
+       tstl a3@+
+       jeq L707
+       addql #1,d0
+L707:
+       subql #1,a2
+L700:
+       tstl a3@+
+       jeq L710
+       addql #1,d0
+L710:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L477:
+       movel a3,a0
+       tstl a0@+
+       jeq L713
+       addql #1,d0
+L713:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L716
+       addql #1,d0
+L716:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L719
+       addql #1,d0
+L719:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L722
+       addql #1,d0
+L722:
+       subql #4,a2
+       tstl a2
+       jne L477
+       jra L555
+       .even
+L474:
+       btst #28,d1
+       jeq L555
+       movel a4@,a0
+       tstl a0
+       jeq L555
+       movel a0@,a0
+       jra L763
+       .even
+L484:
+       addql #1,d0
+L763:
+       movel a0@,a0
+       tstl a0
+       jne L484
+       jra L555
+       .even
+L489:
+       movel a0@(4),d0
+       moveq #-1,d1
+       cmpl d0,d1
+       jeq L760
+       movel d0,a4@
+       movel #_ListGetItem,a4@(106)
+       movel #_ListGetNext,a4@(110)
+       movel #_ListGetPrev,a4@(114)
+       movel #_ListImageDrawItem,a4@(126)
+       bset #4,a4@(90)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(-188),a2
+       movel a2@(4),a0
+       moveq #-1,d1
+       movel #-2142480893,d0
+       jbsr a1@(-36)
+       movel d0,a4@(12)
+       movew d4,d3
+       orw #34,d3
+       moveq #-1,d1
+       cmpl d0,d1
+       jne L492
+       movel a4@,a0
+       clrl d0
+       tstl a0
+       jeq L493
+       movel a0@,a0
+       jra L764
+       .even
+L497:
+       addql #1,d0
+L764:
+       movel a0@,a0
+       tstl a0
+       jne L497
+L493:
+       movel d0,a4@(12)
+L492:
+       clrl d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L501
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L504
+       cmpl d1,d4
+       jle L672
+       moveq #2,d4
+       cmpl d1,d4
+       jle L673
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L673:
+       tstl a3@+
+       jeq L679
+       addql #1,d0
+L679:
+       subql #1,a2
+L672:
+       tstl a3@+
+       jeq L682
+       addql #1,d0
+L682:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L504:
+       movel a3,a0
+       tstl a0@+
+       jeq L685
+       addql #1,d0
+L685:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L688
+       addql #1,d0
+L688:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L691
+       addql #1,d0
+L691:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L694
+       addql #1,d0
+L694:
+       subql #4,a2
+       tstl a2
+       jne L504
+       jra L555
+       .even
+L501:
+       btst #28,d1
+       jeq L555
+       movel a4@,a0
+       tstl a0
+       jeq L555
+       movel a0@,a0
+       jra L765
+       .even
+L511:
+       addql #1,d0
+L765:
+       movel a0@,a0
+       tstl a0
+       jne L511
+       jra L555
+       .even
+L516:
+       movel a0@(4),d0
+       moveq #-1,d1
+       cmpl d0,d1
+       jeq L760
+       movel d0,a4@
+       movel #_ArrayGetItem,a4@(106)
+       movel #_ArrayGetItem,a4@(110)
+       movel #_ArrayGetItem,a4@(114)
+       movel #_ImageDrawItem,a4@(126)
+       bclr #4,a4@(90)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(-188),a2
+       movel a2@(4),a0
+       moveq #-1,d1
+       movel #-2142480893,d0
+       jbsr a1@(-36)
+       movel d0,a4@(12)
+       movew d4,d3
+       orw #34,d3
+       moveq #-1,d1
+       cmpl d0,d1
+       jne L766
+       movel a4@,a0
+       tstl a0
+       jeq L766
+       clrl d0
+       tstl a0@
+       jeq L521
+       .even
+L522:
+       addql #1,d0
+       addql #4,a0
+       tstl a0@
+       jne L522
+L521:
+       movel d0,a4@(12)
+       jra L766
+       .even
+L524:
+       movel a0@(4),a1
+       moveq #-1,d0
+       cmpl a1,d0
+       jne L525
+L760:
+       clrl a4@
+       jra L300
+       .even
+L525:
+       movel a1,a4@
+       clrl d0
+       movel a4@(90),d1
+       movew d4,d3
+       orw #34,d3
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L528
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L531
+       cmpl d1,d4
+       jle L644
+       moveq #2,d4
+       cmpl d1,d4
+       jle L645
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L645:
+       tstl a3@+
+       jeq L651
+       addql #1,d0
+L651:
+       subql #1,a2
+L644:
+       tstl a3@+
+       jeq L654
+       addql #1,d0
+L654:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L531:
+       movel a3,a0
+       tstl a0@+
+       jeq L657
+       addql #1,d0
+L657:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L660
+       addql #1,d0
+L660:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L663
+       addql #1,d0
+L663:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L666
+       addql #1,d0
+L666:
+       subql #4,a2
+       tstl a2
+       jne L531
+       jra L555
+       .even
+L528:
+       btst #28,d1
+       jeq L555
+       tstl a1
+       jeq L555
+       movel a1@,a0
+       jra L767
+       .even
+L538:
+       addql #1,d0
+L767:
+       movel a0@,a0
+       tstl a0
+       jne L538
+       jra L555
+       .even
+L543:
+       movel a0@(4),a4@(16)
+       orw #32,d4
+       tstl a4@(138)
+       jeq L544
+       movel a4@(60),d1
+       addl a4@(64),d1
+       mulsl a4@(12),d1
+       movew a4@(148),a0
+       movel a4@(20),d0
+       addl a0,d0
+       cmpl d0,d1
+       jgt L300
+       movel d1,d0
+       subl a0,d0
+       movel d0,a4@(20)
+       jge L546
+       clrl a4@(20)
+L546:
+       movel a4@(60),d0
+       addl a4@(64),d0
+       movel a4@(20),d1
+       divsl d0,d1
+       cmpl a4@(4),d1
+       jeq L768
+       movel d1,a4@(4)
+       movel #517,a5@(-12)
+       movel d1,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(8)
+       jra L768
+       .even
+L544:
+       movel a4@(16),d2
+       movel a4@(4),d0
+       addl d2,d0
+       movel a4@(12),d1
+       cmpl d0,d1
+       jgt L300
+       cmpl d1,d2
+       slt d0
+       extbl d0
+       subl d2,d1
+       andl d1,d0
+       movel d0,a4@(4)
+       movel #517,a5@(-12)
+       movel d0,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(8)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl a4@(4),d0
+       movel d0,a4@(20)
+L768:
+       orw #4,d4
+       jra L300
+       .even
+L554:
+       movel a0@(4),a4@(76)
+       clrl d0
+       movel a4@(90),d1
+       movew d4,d3
+       orw #2,d3
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L556
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L559
+       cmpl d1,d4
+       jle L617
+       moveq #2,d4
+       cmpl d1,d4
+       jle L618
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L618:
+       tstl a3@+
+       jeq L624
+       addql #1,d0
+L624:
+       subql #1,a2
+L617:
+       tstl a3@+
+       jeq L627
+       addql #1,d0
+L627:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L559:
+       movel a3,a0
+       tstl a0@+
+       jeq L630
+       addql #1,d0
+L630:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L633
+       addql #1,d0
+L633:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L636
+       addql #1,d0
+L636:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L639
+       addql #1,d0
+L639:
+       subql #4,a2
+       tstl a2
+       jne L559
+       jra L555
+       .even
+L556:
+       btst #28,d1
+       jeq L555
+       movel a4@,a0
+       tstl a0
+       jeq L555
+       movel a0@,a0
+       jra L769
+       .even
+L566:
+       addql #1,d0
+L769:
+       movel a0@,a0
+       tstl a0
+       jne L566
+L555:
+       movel d0,a4@(32)
+L766:
+       movew d3,d4
+       jra L300
+       .even
+L571:
+       movel a0@(4),a4@(36)
+       jra L300
+       .even
+L572:
+       movel a0@(4),d1
+       cmpl a4@(20),d1
+       jeq L300
+       tstl a4@
+       jeq L300
+       movel a4@(60),d0
+       jeq L300
+       movel d1,a4@(20)
+       orw #4,d4
+       addl a4@(64),d0
+       movel d1,d3
+       divsl d0,d3
+       movel a4@(16),d2
+       movel d3,d0
+       addl d2,d0
+       movel a4@(12),d1
+       cmpl d0,d1
+       jgt L574
+       cmpl d1,d2
+       slt d0
+       extbl d0
+       subl d2,d1
+       andl d1,d0
+       jra L575
+       .even
+L574:
+       movel d3,d0
+L575:
+       cmpl a4@(4),d0
+       jeq L300
+L758:
+       movel d0,a4@(4)
+       movel #517,a5@(-12)
+       movel d0,a5@(-8)
+L755:
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+L759:
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(8)
+       orw #20,d4
+       jra L300
+       .even
+L580:
+       movel a0@(4),a4@(72)
+       movew a4@(148),d0
+       extl d0
+       movel d0,d1
+       divsl a4@(72),d1
+       movel d1,a4@(68)
+       jra L300
+       .even
+L581:
+       orw #1,d4
+L300:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel d6,a0
+       jbsr a1@(-48)
+       movel d0,a0
+       tstl a0
+       jne L302
+       btst #0,d4
+       jeq L590
+       movel d7,a1
+       movel a1@(24),a0
+       movel a0@(8),a3
+       movel a5@(-188),a1
+       movel d5,a2
+       jbsr a3@
+       movel d0,d3
+       jra L592
+       .even
+L590:
+       moveq #1,d3
+L592:
+       movew d4,d0
+       andw #14,d0
+       jeq L593
+       movel a5@(-188),a2
+       movel a2@(8),d0
+       jeq L593
+       btst #5,a4@(90)
+       jne L593
+       movel _IntuitionBase,a1
+       movel a1,a6
+       movel d0,a0
+       jbsr a1@(-558)
+       movel d0,d2
+       jeq L593
+       btst #1,d4
+       jeq L595
+       moveq #1,d0
+       movel d0,a5@(-44)
+       movel a2@(8),a5@(-40)
+       movel d2,a5@(-36)
+       movel d0,a5@(-32)
+       movel d0,a5@(-28)
+       movel a5@(-40),a5@(-24)
+       movel d2,a5@(-20)
+       movel d0,a5@(-16)
+       movel d5,a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-28),a1
+       movel d5,a2
+       jbsr a3@
+       jra L596
+       .even
+L595:
+       btst #2,d4
+       jeq L597
+       moveq #1,d0
+       movel d0,a5@(-28)
+       movel a5@(-188),a0
+       movel a0@(8),a5@(-24)
+       movel d2,a5@(-20)
+       moveq #2,d0
+       movel d0,a5@(-16)
+       movel a5@(-28),a5@(-44)
+       movel a5@(-24),a5@(-40)
+       movel d2,a5@(-36)
+       movel d0,a5@(-32)
+       movel d5,a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-44),a1
+       movel d5,a2
+       jbsr a3@
+L597:
+       btst #3,d4
+       jeq L596
+       moveq #1,d0
+       movel d0,a5@(-28)
+       movel a5@(-188),a0
+       movel a0@(8),a5@(-24)
+       movel d2,a5@(-20)
+       clrl a5@(-16)
+       movel d0,a5@(-44)
+       movel a5@(-24),a5@(-40)
+       movel d2,a5@(-36)
+       movel a5@(-16),a5@(-32)
+       movel d5,a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-44),a1
+       movel d5,a2
+       jbsr a3@
+L596:
+       movel _IntuitionBase,a1
+       movel a1,a6
+       movel d2,a0
+       jbsr a1@(-564)
+L593:
+       btst #5,d4
+       jeq L599
+       movel #-2142480894,a5@(-180)
+       movel a4@(4),a5@(-176)
+       movel #-2142480893,a5@(-172)
+       movel a4@(12),a5@(-168)
+       movel #-2142480878,a5@(-164)
+       movel a4@(16),a5@(-160)
+       movel #-2142480895,a5@(-156)
+       movel a4@(24),a5@(-152)
+       movel #-2142480864,a5@(-148)
+       movel a4@(20),a5@(-144)
+       movel #-2142480863,a5@(-140)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       movel a4@(12),d1
+       mulsl d0,d1
+       movel d1,a5@(-136)
+       movel #-2142480862,a5@(-132)
+       tstl a4@(138)
+       jeq L600
+       movew a4@(148),d0
+       extl d0
+       jra L601
+       .even
+L600:
+       mulsl a4@(16),d0
+L601:
+       movel d0,a5@(-128)
+       movel #-2147287024,a5@(-124)
+       movel d5,a0
+       clrl d0
+       movew a0@(38),d0
+       movel d0,a5@(-120)
+       clrl a5@(-116)
+       moveq #-112,d2
+       addl a5,d2
+       pea 68:w
+       movel d2,sp@-
+       pea a5@(-180)
+       jbsr _bcopy
+       lea sp@(12),sp
+       movel #263,a5@(-28)
+       movel d2,a5@(-24)
+       movel a5@(-188),a1
+       movel a1@(8),a5@(-20)
+       clrl d0
+       cmpl #264,a1@
+       jne L602
+       movel a1@(12),d0
+L602:
+       movel d0,a5@(-16)
+       movel a5@(-28),a5@(-44)
+       movel a5@(-24),a5@(-40)
+       movel a5@(-20),a5@(-36)
+       movel d0,a5@(-32)
+       movel d5,a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-44),a1
+       jbsr a3@
+       jra L604
+       .even
+L599:
+       btst #4,d4
+       jeq L604
+       clrl d1
+       btst #2,d4
+       jeq L606
+       movel #-2142480894,a5@(-180)
+       movel a4@(4),a5@(-176)
+       movel #-2142480864,a5@(-172)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl a4@(4),d0
+       movel d0,a5@(-168)
+       moveq #4,d1
+L606:
+       lea a5@(-180),a0
+       btst #3,d4
+       jeq L607
+       movel #-2142480895,a0@(d1:l:4)
+       addql #1,d1
+       movel a4@(24),a0@(d1:l:4)
+       addql #1,d1
+L607:
+       movel #-2147287024,a0@(d1:l:4)
+       addql #1,d1
+       movel d5,a1
+       clrl d0
+       movew a1@(38),d0
+       movel d0,a0@(d1:l:4)
+       clrl a0@(4,d1:l:4)
+       movel #263,a5@(-128)
+       movel a0,a5@(-124)
+       movel a5@(-188),a2
+       movel a2@(8),a5@(-120)
+       clrl d0
+       cmpl #264,a2@
+       jne L608
+       movel a2@(12),d0
+L608:
+       movel d0,a5@(-116)
+       movel a5@(-128),a5@(-144)
+       movel a5@(-124),a5@(-140)
+       movel a5@(-120),a5@(-136)
+       movel d0,a5@(-132)
+       movel d5,a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-144),a1
+       movel d5,a2
+       jbsr a3@
+L604:
+       movel d3,d0
+       moveml a5@(-228),#0x5cfc
+       unlk a5
+       rts
+.data
+       .even
+_boolMap.69:
+       .long -2147286999
+       .long 1
+       .long -2142480872
+       .long 2
+       .long -2142480873
+       .long 4
+       .long -2142480871
+       .long 8
+       .long 0
+.text
+       .even
+_LV_OMNew:
+       lea sp@(-28),sp
+       moveml #0x383e,sp@-
+       movel a0,a4
+       movel a1,d4
+       movel d0,a5
+       movel a4@(24),a0
+       movel a0@(8),a3
+       movel a5,a1
+       movel d4,a2
+       jbsr a3@
+       movel d0,d4
+       jeq L789
+       movel d4,a0
+       tstw a0@(12)
+       jge L791
+       moveq #4,d0
+       orl d0,a0@(44)
+L791:
+       clrl d0
+       movew a4@(32),d0
+       movel d4,a4
+       addl d0,a4
+       movel _UtilityBase,a2
+       movel a2,a6
+       lea _boolMap.69,a1
+       movel a5@(4),a0
+       moveq #4,d0
+       jbsr a2@(-42)
+       movel d0,a4@(90)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2147287007,d0
+       jbsr a1@(-36)
+       movel d0,a2
+       tstl a2
+       jeq L792
+       movel a2@(8),a4@(134)
+       jra L793
+       .even
+L792:
+       clrl a4@(134)
+L793:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       movel #-2142480867,d0
+       jbsr a1@(-30)
+       movel d0,a0
+       tstl a0
+       jeq L794
+       movel a0@(4),d0
+       jeq L796
+       jra L902
+       .even
+L794:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2147287000,d0
+       jbsr a1@(-36)
+       tstl d0
+       jeq L796
+       movel _GfxBase,a1
+       movel a1,a6
+       movel d0,a0
+       jbsr a1@(-72)
+       tstl d0
+       jeq L796
+       bset #3,a4@(90)
+L902:
+       movel d0,a4@(134)
+L796:
+       movel a4@(134),a0
+       tstl a0
+       jeq L799
+       clrl d0
+       movew a0@(20),d0
+       movel d0,a4@(60)
+       jra L800
+       .even
+L799:
+       clrl a4@(60)
+L800:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       movel a4@(60),d1
+       movel #-2142480869,d0
+       jbsr a1@(-36)
+       movel d0,a4@(60)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2147254270,d0
+       jbsr a1@(-36)
+       movel d0,a4@(64)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       movel #-2142480868,d0
+       jbsr a1@(-30)
+       movel d0,a0
+       tstl a0
+       jeq L801
+       movel a0@(4),a4@(94)
+       jra L802
+       .even
+L801:
+       tstl a2
+       jeq L803
+       movel a2@(4),a0
+       movew a0@(14),d1
+       movew a0@(4),d0
+       cmpw d1,d0
+       jcc L806
+       clrl d2
+       movew d1,d2
+       jra L807
+       .even
+L806:
+       clrl d2
+       movew d0,d2
+L807:
+       movew a0@(10),d1
+       movew a0@(12),d0
+       cmpw d1,d0
+       jcc L808
+       clrl d0
+       movew d1,d0
+       cmpl d2,d0
+       jlt L809
+       jra L804
+       .even
+L808:
+       andl #0xFFFF,d0
+       cmpl d2,d0
+       jge L804
+L809:
+       movew a0@(14),d1
+       movew a0@(4),d0
+       cmpw d1,d0
+       jcs L903
+       jra L812
+       .even
+L804:
+       movew a0@(10),d1
+       movew a0@(12),d0
+       cmpw d1,d0
+       jcc L812
+L903:
+       clrl d0
+       movew d1,d0
+       jra L805
+       .even
+L812:
+       andl #0xFFFF,d0
+L805:
+       movel d0,a4@(94)
+       jra L802
+       .even
+L803:
+       moveq #-1,d1
+       movel d1,a4@(94)
+L802:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       moveq #-1,d1
+       movel #-2142480893,d0
+       jbsr a1@(-36)
+       movel d0,a4@(12)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2142480883,d0
+       jbsr a1@(-36)
+       movel d0,a0
+       movel a0,a4@
+       jeq L815
+       movel #_ListGetItem,a4@(106)
+       movel #_ListGetNext,a4@(110)
+       movel #_ListGetPrev,a4@(114)
+       movel #_ListStringDrawItem,a4@(126)
+       bset #4,a4@(90)
+       moveq #-1,d3
+       cmpl a4@(12),d3
+       jne L824
+       clrl d0
+       movel a0@,a0
+       jra L904
+       .even
+L821:
+       addql #1,d0
+L904:
+       movel a0@,a0
+       tstl a0
+       jne L821
+       jra L845
+       .even
+L815:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2142480882,d0
+       jbsr a1@(-36)
+       movel d0,a0
+       movel a0,a4@
+       jeq L825
+       movel #_ArrayGetItem,a4@(106)
+       movel #_ArrayGetItem,a4@(110)
+       movel #_ArrayGetItem,a4@(114)
+       movel #_StringDrawItem,a4@(126)
+       moveq #-1,d0
+       cmpl a4@(12),d0
+       jne L824
+       clrl d0
+       tstl a0@
+       jeq L845
+       .even
+L829:
+       addql #1,d0
+       addql #4,a0
+       tstl a0@
+       jne L829
+       jra L845
+       .even
+L825:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2142480881,d0
+       jbsr a1@(-36)
+       movel d0,a0
+       movel a0,a4@
+       jeq L832
+       movel #_ListGetItem,a4@(106)
+       movel #_ListGetNext,a4@(110)
+       movel #_ListGetPrev,a4@(114)
+       movel #_ListImageDrawItem,a4@(126)
+       bset #4,a4@(90)
+       moveq #-1,d1
+       cmpl a4@(12),d1
+       jne L824
+       clrl d0
+       movel a0@,a0
+       jra L905
+       .even
+L838:
+       addql #1,d0
+L905:
+       movel a0@,a0
+       tstl a0
+       jne L838
+       jra L845
+       .even
+L832:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2142480880,d0
+       jbsr a1@(-36)
+       movel d0,a0
+       movel a0,a4@
+       jeq L824
+       movel #_ArrayGetItem,a4@(106)
+       movel #_ArrayGetItem,a4@(110)
+       movel #_ArrayGetItem,a4@(114)
+       movel #_ImageDrawItem,a4@(126)
+       moveq #-1,d3
+       cmpl a4@(12),d3
+       jne L824
+       clrl d0
+       tstl a0@
+       jeq L845
+       .even
+L846:
+       addql #1,d0
+       addql #4,a0
+       tstl a0@
+       jne L846
+L845:
+       movel d0,a4@(12)
+L824:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2142480876,d0
+       jbsr a1@(-36)
+       movel d0,a4@(76)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       moveq #-1,d1
+       movel #-2142480865,d0
+       jbsr a1@(-36)
+       movel d0,a4@(36)
+       clrl d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L848
+       movel a4@(76),d2
+       jeq L849
+       movel a4@(12),d1
+       cmpl d0,d1
+       jle L848
+       movel d2,a2
+       movel d1,d2
+       negl d1
+       moveq #3,d3
+       andl d3,d1
+       jeq L852
+       cmpl d1,d3
+       jle L874
+       moveq #2,d3
+       cmpl d1,d3
+       jle L875
+       tstl a2@+
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,d2
+L875:
+       tstl a2@+
+       jeq L881
+       addql #1,d0
+L881:
+       subql #1,d2
+L874:
+       tstl a2@+
+       jeq L884
+       addql #1,d0
+L884:
+       subql #1,d2
+       jeq L848
+       .even
+L852:
+       movel a2,a0
+       tstl a0@+
+       jeq L887
+       addql #1,d0
+L887:
+       lea a2@(8),a1
+       tstl a0@
+       jeq L890
+       addql #1,d0
+L890:
+       lea a2@(12),a0
+       tstl a1@
+       jeq L893
+       addql #1,d0
+L893:
+       lea a2@(16),a2
+       tstl a0@
+       jeq L896
+       addql #1,d0
+L896:
+       subql #4,d2
+       jne L852
+       jra L848
+       .even
+L849:
+       btst #28,d1
+       jeq L848
+       movel a4@,a0
+       tstl a0
+       jeq L848
+       movel a0@,a0
+       jra L906
+       .even
+L859:
+       addql #1,d0
+L906:
+       movel a0@,a0
+       tstl a0
+       jne L859
+L848:
+       movel d0,a4@(32)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2142480878,d0
+       jbsr a1@(-36)
+       movel d0,a4@(16)
+       jeq L864
+       movel #-2147287033,sp@(32)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl a4@(16),d0
+       movel d0,sp@(36)
+       clrl sp@(40)
+       movel sp@(32),sp@(44)
+       movel d0,sp@(48)
+       movel sp@(40),sp@(52)
+       movel _IntuitionBase,a2
+       movel a2,a6
+       lea sp@(44),a1
+       movel d4,a0
+       jbsr a2@(-648)
+L864:
+       movel _UtilityBase,d2
+       movel d2,a0
+       lea a0@(-36),a2
+       movel a5@(4),d3
+       movel d2,a6
+       movel d3,a0
+       clrl d1
+       movel #-2142480894,d0
+       jbsr a2@
+       movel d3,a0
+       movel d0,d1
+       movel #-2142480888,d0
+       jbsr a2@
+       movel d0,d1
+       movel d1,a4@(4)
+       movel d1,a4@(40)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d1,d0
+       movel d0,a4@(20)
+       movel d0,a4@(44)
+       tstl a4@
+       jeq L865
+       movel #517,sp@(32)
+       movel d1,sp@(36)
+       movel a4@,sp@(40)
+       movel a4@(106),a3
+       lea sp@(32),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(8)
+L865:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       moveq #2,d1
+       movel #-2142480850,d0
+       jbsr a1@(-36)
+       movel d0,a4@(72)
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       moveq #-1,d1
+       movel #-2142480895,d0
+       jbsr a1@(-36)
+       movel d0,a4@(24)
+       movel d0,a4@(48)
+       moveq #-1,d1
+       cmpl d0,d1
+       jeq L867
+       movel #517,sp@(32)
+       movel d0,sp@(36)
+       movel a4@,sp@(40)
+       movel a4@(106),a3
+       lea sp@(32),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+L867:
+       movel _UtilityBase,a1
+       movel a1,a6
+       movel a5@(4),a0
+       clrl d1
+       movel #-2142480875,d0
+       jbsr a1@(-36)
+       movel d0,a0
+       movel a0,a4@(130)
+       jeq L869
+       movel a0@(8),a4@(126)
+L869:
+       btst #1,a4@(93)
+       jeq L789
+       movel _GfxBase,a0
+       movel a0,a6
+       jbsr a0@(-516)
+       movel d0,a4@(138)
+L789:
+       movel d4,d0
+       moveml sp@+,#0x7c1c
+       lea sp@(28),sp
+       rts
+LC0:
+       .ascii "gadgetclass\0"
+       .even
+.globl _MakeListViewClass
+_MakeListViewClass:
+       moveml #0x32,sp@-
+       movel _IntuitionBase,a3
+       movel a3,a6
+       clrl d1
+       moveq #89,d0
+       notb d0
+       subl a2,a2
+       lea LC0,a1
+       subl a0,a0
+       jbsr a3@(-678)
+       movel d0,a0
+       tstl a0
+       jeq L912
+       movel #_LVDispatcher,a0@(8)
+L912:
+       movel a0,d0
+       moveml sp@+,#0x4c00
+       rts
+       .even
+.globl _FreeListViewClass
+_FreeListViewClass:
+       movel a6,sp@-
+       movel _IntuitionBase,a1
+       movel a1,a6
+       jbsr a1@(-714)
+       extl d0
+       movel sp@+,a6
+       rts
+       .even
+_LV_GMGoActive:
+       movel a2,sp@-
+       movel a0,a2
+       movel d0,a0
+       clrl d0
+       movew a2@(32),d0
+       tstl a1@(d0:l)
+       jeq L189
+       orw #128,a1@(12)
+       clrl d0
+       tstl a0@(8)
+       jeq L914
+       movel a0,d0
+       movel a2,a0
+       jbsr _LV_GMHandleInput
+       jra L914
+       .even
+L189:
+       moveq #2,d0
+L914:
+       movel sp@+,a2
+       rts
+       .even
+_LV_GMGoInactive:
+       clrl d0
+       movew a0@(32),d0
+       andl #1073741823,a1@(90,d0:l)
+       andw #65407,a1@(12)
+       rts
+       nop
+       .even
+_LV_OMGet:
+       moveml #0x2030,sp@-
+       movel a1,d1
+       movel d0,a1
+       clrl d0
+       movew a0@(32),d0
+       movel d1,a3
+       addl d0,a3
+       movel a1@(4),d0
+       addl #2142480895,d0
+       moveq #19,d2
+       cmpl d0,d2
+       jcs L785
+LI787:
+       movew pc@(L787-LI787-2:b,d0:l:2),d0
+       jmp pc@(2,d0:w)
+       .even
+L787:
+       .word L774-L787
+       .word L775-L787
+       .word L776-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L781-L787
+       .word L781-L787
+       .word L781-L787
+       .word L781-L787
+       .word L781-L787
+       .word L782-L787
+       .word L783-L787
+       .word L784-L787
+       .even
+L774:
+       movel a1@(8),a0
+       movel a3@(24),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L775:
+       movel a1@(8),a0
+       movel a3@(4),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L776:
+       movel a1@(8),a0
+       movel a3@(12),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L781:
+       movel a1@(8),a0
+       movel a3@,a0@
+       moveq #1,d0
+       jra L915
+       .even
+L782:
+       movel a1@(8),a0
+       movel a3@(16),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L783:
+       movel a1@(8),a0
+       movel a3@(28),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L784:
+       movel a1@(8),a0
+       movel a3@(76),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L785:
+       movel a0@(24),a0
+       movel a0@(8),a3
+       movel d1,a2
+       jbsr a3@
+L915:
+       moveml sp@+,#0xc04
+       rts
+       .even
+_LV_OMDispose:
+       moveml #0x3032,sp@-
+       movel a0,a2
+       movel a1,d2
+       movel d0,d3
+       clrl d0
+       movew a2@(32),d0
+       movel d2,a3
+       addl d0,a3
+       movel a3@(138),d0
+       jeq L908
+       movel _GfxBase,a1
+       movel a1,a6
+       movel d0,a0
+       jbsr a1@(-534)
+L908:
+       btst #3,a3@(90)
+       jeq L909
+       movel _GfxBase,a0
+       movel a0,a6
+       movel a3@(134),a1
+       jbsr a0@(-78)
+L909:
+       movel a2@(24),a0
+       movel a0@(8),a3
+       movel d3,a1
+       movel d2,a2
+       jbsr a3@
+       moveml sp@+,#0x4c0c
+       rts
diff --git a/gadgets/ListView/ListViewClass_static.oldinline.s b/gadgets/ListView/ListViewClass_static.oldinline.s
new file mode 100644 (file)
index 0000000..92a4766
--- /dev/null
@@ -0,0 +1,4136 @@
+#NO_APP
+gcc2_compiled.:
+___gnu_compiled_c:
+.text
+       .even
+_LVDispatcher:
+       moveml #0x2030,sp@-
+       movel a2,d1
+       movel a1@,d0
+       moveq #6,d2
+       cmpl d0,d2
+       jeq L14
+       jcs L23
+       moveq #2,d2
+       cmpl d0,d2
+       jeq L11
+       jcs L24
+       moveq #1,d2
+       cmpl d0,d2
+       jeq L10
+       jra L20
+       .even
+L24:
+       moveq #3,d2
+       cmpl d0,d2
+       jeq L12
+       moveq #4,d2
+       cmpl d0,d2
+       jeq L13
+       jra L20
+       .even
+L23:
+       cmpl #259,d0
+       jeq L16
+       jhi L25
+       cmpl #257,d0
+       jeq L18
+       cmpl #258,d0
+       jeq L19
+       jra L20
+       .even
+L25:
+       cmpl #260,d0
+       jeq L17
+       cmpl #264,d0
+       jeq L16
+       jra L20
+       .even
+L10:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMRender
+       moveq #1,d0
+       jra L26
+       .even
+L11:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMGoActive
+       jra L27
+       .even
+L12:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMHandleInput
+       jra L27
+       .even
+L13:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMGoInactive
+       moveq #1,d0
+       jra L26
+       .even
+L14:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_GMLayout
+       moveq #1,d0
+       jra L26
+       .even
+L16:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_OMSet
+       jra L27
+       .even
+L17:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_OMGet
+       jra L27
+       .even
+L18:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_OMNew
+       jra L27
+       .even
+L19:
+       movel a1,d0
+       movel d1,a1
+       jbsr _LV_OMDispose
+       moveq #1,d0
+       jra L26
+       .even
+L20:
+       movel a0@(24),a0
+       movel a0@(8),a3
+       movel d1,a2
+       jbsr a3@
+L27:
+L26:
+       moveml sp@+,#0xc04
+       rts
+       .even
+_RedrawItems:
+       lea sp@(-40),sp
+       moveml #0x303c,sp@-
+       movel a0,a4
+       movel d0,d2
+       movel d1,d3
+       movel sp@(68),a5
+       movel d2,sp@(28)
+       movel a4@,sp@(32)
+       movel a1@(8),sp@(36)
+       movel a1@(4),a0
+       movel a0@(30),sp@(40)
+       movel a4@(90),sp@(56)
+       movew a4@(150),sp@(44)
+       movew a4@(154),sp@(48)
+       tstl a4@(138)
+       jeq L68
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d2,d0
+       addw a4@(152),d0
+       subw a4@(22),d0
+       jra L69
+       .even
+L68:
+       subl a4@(4),d2
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d2,d0
+       addw a4@(152),d0
+L69:
+       movew d0,sp@(46)
+       addw a4@(62),d0
+       subqw #1,d0
+       movew d0,sp@(50)
+       moveq #24,d2
+       addl sp,d2
+       tstl a5
+       jne L71
+       movel #517,sp@(24)
+       movel a4@(106),a3
+       movel d2,a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a5
+L71:
+       movel a4@(118),a3
+       tstl a3
+       jeq L73
+       movel #518,sp@(24)
+       movel d2,a2
+       movel a5,a1
+       movel a4@(130),a0
+       jbsr a3@
+       jra L73
+       .even
+L82:
+       movel #515,sp@(24)
+       movel a4@(110),a3
+       movel d2,a2
+       movel a5,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a5
+       movew a4@(62),d0
+       addw a4@(66),d0
+       addw d0,sp@(46)
+       addw d0,sp@(50)
+L73:
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L76
+       movel a4@(76),a0
+       tstl a0
+       jeq L77
+       movel sp@(28),d0
+       movel a0@(d0:l:4),d0
+       jra L81
+       .even
+L77:
+       btst #28,d0
+       jeq L79
+       clrl d0
+       moveb a5@(8),d0
+       jra L81
+       .even
+L79:
+       clrl d0
+       jra L81
+       .even
+L76:
+       movel sp@(28),d0
+       cmpl a4@(24),d0
+       seq d0
+       extbl d0
+       negl d0
+L81:
+       tstl d0
+       sne d0
+       extbl d0
+       negl d0
+       movel d0,sp@(52)
+       movel #514,sp@(24)
+       movel a4@(126),a3
+       movel d2,a2
+       movel a5,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel sp@(28),d0
+       movel d0,d1
+       addql #1,d1
+       movel d1,sp@(28)
+       addql #1,d0
+       cmpl d0,d3
+       jge L82
+       movel a4@(122),a3
+       tstl a3
+       jeq L84
+       movel #519,sp@(24)
+       movel a5,a1
+       movel a4@(130),a0
+       jbsr a3@
+L84:
+       moveml sp@+,#0x3c0c
+       lea sp@(40),sp
+       rts
+       .even
+_LV_GMRender:
+       lea sp@(-72),sp
+       moveml #0x3f3e,sp@-
+       movel a1,sp@(60)
+       movel d0,sp@(56)
+       clrl d0
+       movew a0@(32),d0
+       movel a1,a4
+       addl d0,a4
+       movel sp@(56),a0
+       movel a0@(8),a5
+       btst #5,a4@(90)
+       jne L85
+       tstl a4@
+       jeq L87
+       tstl a4@(16)
+       jeq L87
+       clrl sp@(52)
+       clrw sp@(46)
+       movel a5@(52),d0
+       movel a4@(134),d1
+       cmpl d0,d1
+       jeq L88
+       movel d0,sp@(52)
+       movel _GfxBase,a6
+       movel a5,a1
+       movel d1,a0
+#APP
+       jsr a6@(-0x42:W)
+#NO_APP
+L88:
+       tstl a4@(138)
+       jeq L89
+       movel sp@(56),a1
+       movel a1@(8),a0
+       movel a0@,a0
+       btst #4,a0@(31)
+       jeq L90
+       movew #1,sp@(46)
+       movel _LayersBase,a6
+       clrl d0
+#APP
+       jsr a6@(-0x54:W)
+#NO_APP
+L90:
+       movel _LayersBase,a6
+       movel a5@,a0
+       movel a4@(138),a1
+#APP
+       jsr a6@(-0xae:W)
+#NO_APP
+       movel d0,sp@(48)
+L89:
+       movel sp@(56),a0
+       movel a0@(12),d0
+       moveq #1,d1
+       cmpl d0,d1
+       jeq L127
+       jlt L157
+       tstl d0
+       jeq L92
+       jra L91
+       .even
+L157:
+       moveq #2,d3
+       cmpl d0,d3
+       jeq L138
+       jra L91
+       .even
+L92:
+       clrw d3
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L93
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       sgt d0
+       moveb d0,d3
+       extw d3
+       negw d3
+L93:
+       clrw d4
+       movel a4@(48),d2
+       cmpl d2,d1
+       jgt L94
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       sgt d0
+       moveb d0,d4
+       extw d4
+       negw d4
+L94:
+       tstw d4
+       jne L96
+       tstw d3
+       jeq L95
+L96:
+       movel a4@,sp@(84)
+       movel a5,sp@(88)
+       movel sp@(56),a1
+       movel a1@(4),a0
+       movel a0@(30),sp@(92)
+       movel a4@(90),sp@(108)
+       movel a4@(118),a3
+       tstl a3
+       jeq L97
+       movel #518,sp@(76)
+       lea sp@(76),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+L97:
+       movel #514,sp@(76)
+       tstw d3
+       jeq L98
+       movel a4@(24),d1
+       movew a4@(150),sp@(96)
+       movew a4@(154),sp@(100)
+       tstl a4@(138)
+       jeq L99
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d0,d1
+       movew d1,d0
+       addw a4@(152),d0
+       subw a4@(22),d0
+       jra L100
+       .even
+L99:
+       subl a4@(4),d1
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d0,d1
+       movew d1,d0
+       addw a4@(152),d0
+L100:
+       movew d0,sp@(98)
+       addw a4@(62),d0
+       subqw #1,d0
+       movew d0,sp@(102)
+       movel a4@(28),a1
+       movel a4@(24),d1
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L102
+       movel a4@(76),a0
+       tstl a0
+       jeq L103
+       movel a0@(d1:l:4),d0
+       jra L104
+       .even
+L103:
+       btst #28,d0
+       jeq L105
+       tstl a1
+       jne L166
+       movel #517,sp@(64)
+       movel d1,sp@(68)
+       movel a4@,sp@(72)
+       movel a4@(106),a3
+       lea sp@(64),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L108
+L166:
+       clrl d0
+       moveb a1@(8),d0
+       jra L104
+       .even
+L108:
+L105:
+       clrl d0
+       jra L104
+       .even
+L102:
+       moveq #1,d0
+L104:
+       tstl d0
+       sne d0
+       extbl d0
+       negl d0
+       movel d0,sp@(104)
+       movel a4@(24),sp@(80)
+       movel a4@(126),a3
+       lea sp@(76),a2
+       movel a4@(28),a1
+       movel a4@(130),a0
+       jbsr a3@
+L98:
+       tstw d4
+       jeq L112
+       movel a4@(48),d1
+       movew a4@(150),sp@(96)
+       movew a4@(154),sp@(100)
+       tstl a4@(138)
+       jeq L113
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d0,d1
+       movew d1,d0
+       addw a4@(152),d0
+       subw a4@(22),d0
+       jra L114
+       .even
+L113:
+       subl a4@(4),d1
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d0,d1
+       movew d1,d0
+       addw a4@(152),d0
+L114:
+       movew d0,sp@(98)
+       addw a4@(62),d0
+       subqw #1,d0
+       movew d0,sp@(102)
+       movel a4@(52),a1
+       movel a4@(48),d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L116
+       movel a4@(76),a0
+       tstl a0
+       jeq L117
+       movel a0@(d0:l:4),d0
+       jra L118
+       .even
+L117:
+       btst #28,d1
+       jeq L119
+       tstl a1
+       jne L167
+       movel #517,sp@(64)
+       movel d0,sp@(68)
+       movel a4@,sp@(72)
+       movel a4@(106),a3
+       lea sp@(64),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L122
+L167:
+       clrl d0
+       moveb a1@(8),d0
+       jra L118
+       .even
+L122:
+L119:
+       clrl d0
+       jra L118
+       .even
+L116:
+       cmpl a4@(24),d0
+       seq d0
+       extbl d0
+       negl d0
+L118:
+       tstl d0
+       sne d0
+       extbl d0
+       negl d0
+       movel d0,sp@(104)
+       movel a4@(48),sp@(80)
+       movel a4@(126),a3
+       lea sp@(76),a2
+       movel a4@(52),a1
+       movel a4@(130),a0
+       jbsr a3@
+L112:
+       movel a4@(122),a3
+       tstl a3
+       jeq L95
+       movel #519,sp@(76)
+       lea sp@(76),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+L95:
+       movel a4@(24),a4@(48)
+       movel a4@(28),a4@(52)
+       jra L91
+       .even
+L127:
+       movel sp@(56),a1
+       movel a1@(4),a0
+       movel a0@(30),a0
+       movel a0@(4),a0
+       movel _GfxBase,a6
+       movel a5,a1
+       clrl d0
+       movew a0@(14),d0
+#APP
+       jsr a6@(-0x156:W)
+#NO_APP
+       movel a4@(64),a3
+       tstl a3
+       jeq L128
+       tstl a4@
+       jeq L128
+       movel a4@(16),d1
+       jeq L128
+       movew a4@(152),a0
+       movel a0,a2
+       addl a4@(60),a2
+       movel a4@(12),d0
+       subl a4@(4),d0
+       cmpl d0,d1
+       jge L129
+       movel d1,d0
+L129:
+       subql #1,d0
+       tstl d0
+       jle L135
+       movel d0,d4
+       negl d0
+       moveq #3,d1
+       andl d1,d0
+       jeq L133
+       cmpl d0,d1
+       jle L170
+       moveq #2,d3
+       cmpl d0,d3
+       jle L171
+       movel _GfxBase,a6
+       movel a5,a1
+       movew a4@(150),d0
+       extl d0
+       movel a2,d1
+       movew a4@(154),d2
+       extl d2
+       lea a3@(-1,a2:l),a3
+       movel a3,d3
+#APP
+       jsr a6@(-0x132:W)
+#NO_APP
+       movel a4@(60),d0
+       addl a4@(64),d0
+       addl d0,a2
+       subql #1,d4
+L171:
+       movel a2,d3
+       addl a4@(64),d3
+       movel _GfxBase,a6
+       movel a5,a1
+       movew a4@(150),d0
+       extl d0
+       movel a2,d1
+       movew a4@(154),d2
+       extl d2
+       subql #1,d3
+#APP
+       jsr a6@(-0x132:W)
+#NO_APP
+       movel a4@(60),d0
+       addl a4@(64),d0
+       addl d0,a2
+       subql #1,d4
+L170:
+       movel a2,d3
+       addl a4@(64),d3
+       movel _GfxBase,a6
+       movel a5,a1
+       movew a4@(150),d0
+       extl d0
+       movel a2,d1
+       movew a4@(154),d2
+       extl d2
+       subql #1,d3
+#APP
+       jsr a6@(-0x132:W)
+#NO_APP
+       movel a4@(60),d0
+       addl a4@(64),d0
+       addl d0,a2
+       subql #1,d4
+       jeq L135
+       .even
+L133:
+       movel a2,d3
+       addl a4@(64),d3
+       movel _GfxBase,a6
+       movel a5,a1
+       movew a4@(150),d0
+       extl d0
+       movel a2,d1
+       movew a4@(154),d2
+       extl d2
+       subql #1,d3
+#APP
+       jsr a6@(-0x132:W)
+#NO_APP
+       movel a4@(64),a0
+       movel a4@(60),d0
+       addl a0,d0
+       addl d0,a2
+       movel _GfxBase,a6
+       movel a5,a1
+       movew a4@(150),d0
+       extl d0
+       movel a2,d1
+       movew a4@(154),d2
+       extl d2
+       lea a0@(-1,a2:l),a0
+       movel a0,d3
+#APP
+       jsr a6@(-0x132:W)
+#NO_APP
+       movel a4@(64),a0
+       movel a4@(60),d0
+       addl a0,d0
+       addl d0,a2
+       movel _GfxBase,a6
+       movel a5,a1
+       movew a4@(150),d0
+       extl d0
+       movel a2,d1
+       movew a4@(154),d2
+       extl d2
+       lea a0@(-1,a2:l),a0
+       movel a0,d3
+#APP
+       jsr a6@(-0x132:W)
+#NO_APP
+       movel a4@(64),a0
+       movel a4@(60),d0
+       addl a0,d0
+       addl d0,a2
+       movel _GfxBase,a6
+       movel a5,a1
+       movew a4@(150),d0
+       extl d0
+       movel a2,d1
+       movew a4@(154),d2
+       extl d2
+       lea a0@(-1,a2:l),a0
+       movel a0,d3
+#APP
+       jsr a6@(-0x132:W)
+#NO_APP
+       movel a4@(60),d0
+       addl a4@(64),d0
+       addl d0,a2
+       subql #4,d4
+       jne L133
+       jra L135
+       .even
+L128:
+       movew a4@(152),a0
+       movel a4@(12),d1
+       subl a4@(4),d1
+       movel a4@(16),d0
+       cmpl d1,d0
+       jge L136
+       movel d0,d1
+L136:
+       mulsl a4@(60),d1
+       lea a0@(0,d1:l),a2
+L135:
+       movel _GfxBase,a6
+       movel a5,a1
+       movew a4@(150),d0
+       extl d0
+       movel a2,d1
+       movew a4@(154),d2
+       extl d2
+       movew a4@(156),d3
+       extl d3
+#APP
+       jsr a6@(-0x132:W)
+#NO_APP
+       movel a4@(4),d0
+       movel d0,d2
+       addl a4@(16),d2
+       movel a4@(12),d1
+       cmpl d1,d2
+       jge L137
+       movel d2,d1
+L137:
+       movel a4@(8),sp@-
+       subql #1,d1
+       movel sp@(60),a1
+       movel a4,a0
+       jbsr _RedrawItems
+       addql #4,sp
+       jra L91
+       .even
+L138:
+       tstl a4@(138)
+       jeq L139
+       movel a4@(20),d7
+       subl a4@(44),d7
+       jeq L91
+       movew a4@(148),d5
+       extl d5
+       jra L141
+       .even
+L139:
+       movel a4@(4),d0
+       movel a4@(40),d1
+       cmpl d0,d1
+       jeq L91
+       movel d0,d7
+       subl d1,d7
+       movel a4@(64),d1
+       movel a4@(60),d0
+       addl d1,d0
+       mulsl d0,d7
+       movel a4@(16),d5
+       mulsl d0,d5
+       subl d1,d5
+L141:
+       movel d7,d0
+       jge L144
+       negl d0
+L144:
+       cmpl a4@(68),d0
+       jle L143
+       movel a4@(4),d0
+       movel d0,d2
+       addl a4@(16),d2
+       movel a4@(12),d1
+       cmpl d1,d2
+       jge L145
+       movel d2,d1
+L145:
+       movel a4@(8),sp@-
+       subql #1,d1
+       movel sp@(60),a1
+       movel a4,a0
+       jbsr _RedrawItems
+       addql #4,sp
+       jra L146
+       .even
+L143:
+       movel _GfxBase,a6
+       movel a5,a0
+       movel a4@(94),d0
+#APP
+       jsr a6@(-0x3de:W)
+#NO_APP
+       tstl d7
+       jle L147
+       movew a4@(144),a2
+       movel _GfxBase,a6
+       movel a5,a0
+       movew a4@(142),d0
+       extl d0
+       movel a2,d1
+       addl d7,d1
+       movel a0,a1
+       movel d0,d2
+       movel a2,d3
+       movew a4@(146),d4
+       extl d4
+       subl d7,d5
+       moveq #63,d6
+       notb d6
+#APP
+       jsr a6@(-0x228:W)
+#NO_APP
+       tstl a4@(138)
+       jeq L148
+       movew a4@(148),a0
+       movel a4@(20),d1
+       addl a0,d1
+       subql #1,d1
+       movel a4@(60),d2
+       addl a4@(64),d2
+       divsl d2,d1
+       movel a4@(44),d0
+       addl a0,d0
+       divsl d2,d0
+       clrl sp@-
+       jra L187
+       .even
+L148:
+       movel a4@(16),d0
+       movel d0,d1
+       addl a4@(4),d1
+       clrl sp@-
+       subql #1,d1
+       addl a4@(40),d0
+       jra L187
+       .even
+L147:
+       movew a4@(144),a1
+       movel _GfxBase,a6
+       movel a5,a0
+       movew a4@(142),d0
+       extl d0
+       movel a1,d1
+       movel a0,a1
+       movel d0,d2
+       movel d1,d3
+       subl d7,d3
+       movew a4@(146),d4
+       extl d4
+       addl d7,d5
+       moveq #63,d6
+       notb d6
+#APP
+       jsr a6@(-0x228:W)
+#NO_APP
+       tstl a4@(138)
+       jeq L151
+       movel a4@(60),d0
+       addl a4@(64),d0
+       movel a4@(44),d1
+       divsl d0,d1
+       movel a4@(20),d3
+       divsl d0,d3
+       movel d3,d0
+       clrl sp@-
+       jra L187
+       .even
+L151:
+       movel a4@(8),sp@-
+       movel a4@(40),d1
+       subql #1,d1
+       movel a4@(4),d0
+L187:
+       movel sp@(60),a1
+       movel a4,a0
+       jbsr _RedrawItems
+       addql #4,sp
+       movel a5@,a1
+       btst #0,a1@(31)
+       jeq L153
+       movel a1@(8),a0
+       tstl a0
+       jeq L154
+       movel a1@(16),d1
+       movel a0@(16),d0
+       cmpl d1,d0
+       jne L154
+       movel a1@(20),d1
+       movel a0@(20),d0
+       cmpl d1,d0
+       jne L154
+       movel a1@(156),a0
+       tstl a0
+       jeq L153
+       tstl a0@(8)
+       jeq L153
+L154:
+       moveb a5@(24),d6
+       movel _GfxBase,a6
+       movel a5,a0
+       clrl d0
+#APP
+       jsr a6@(-0x3d8:W)
+#NO_APP
+       movel _GfxBase,a6
+       movel a5,a1
+       clrl d0
+       movel d7,d1
+       movew a4@(150),d2
+       extl d2
+       movew a4@(152),d3
+       extl d3
+       movew a4@(154),d4
+       extl d4
+       movew a4@(156),d5
+       extl d5
+#APP
+       jsr a6@(-0x18c:W)
+#NO_APP
+       movel _GfxBase,a6
+       movel a5,a0
+       clrl d0
+       moveb d6,d0
+#APP
+       jsr a6@(-0x3d8:W)
+#NO_APP
+L153:
+       movel _GfxBase,a6
+       movel a5,a0
+       moveq #-1,d0
+#APP
+       jsr a6@(-0x3de:W)
+#NO_APP
+L146:
+       movel a4@(4),a4@(40)
+       movel a4@(20),a4@(44)
+L91:
+       tstl a4@(138)
+       jeq L158
+       movel _LayersBase,a6
+       movel a5@,a0
+       movel sp@(48),a1
+#APP
+       jsr a6@(-0xae:W)
+#NO_APP
+       tstw sp@(46)
+       jeq L158
+       movel sp@(56),a1
+       movel a1@(8),a0
+       movel _LayersBase,a6
+       movel a0@,a0
+#APP
+       jsr a6@(-0x4e:W)
+#NO_APP
+L158:
+       tstl sp@(52)
+       jeq L161
+       movel _GfxBase,a6
+       movel a5,a1
+       movel sp@(52),a0
+#APP
+       jsr a6@(-0x42:W)
+#NO_APP
+       jra L161
+       .even
+L87:
+       moveq #1,d0
+       movel sp@(56),a0
+       cmpl a0@(12),d0
+       jne L85
+       movel a0@(4),a0
+       movel a0@(30),a0
+       movel a0@(4),a0
+       movel _GfxBase,a6
+       movel a5,a1
+       clrl d0
+       movew a0@(14),d0
+#APP
+       jsr a6@(-0x156:W)
+#NO_APP
+       movel _GfxBase,a6
+       movel a5,a1
+       movew a4@(150),d0
+       extl d0
+       movew a4@(152),d1
+       extl d1
+       movew a4@(154),d2
+       extl d2
+       movew a4@(156),d3
+       extl d3
+#APP
+       jsr a6@(-0x132:W)
+#NO_APP
+L161:
+       moveq #1,d0
+       movel sp@(56),a0
+       cmpl a0@(12),d0
+       jne L85
+       clrl d0
+       movel sp@(60),a1
+       movel a1@(18),a0
+       tstl a0
+       jeq L164
+       btst #2,a1@(13)
+       jeq L164
+       cmpw #-1,a0@(8)
+       seq d0
+       extbl d0
+       negl d0
+L164:
+       tstw d0
+       jeq L85
+       movel #518,sp@(88)
+       movel sp@(56),a0
+       movel a0@(8),sp@(92)
+       movew a4@(158),d1
+       swap d1
+       clrw d1
+       movew a4@(160),d0
+       extl d0
+       orl d0,d1
+       movel d1,sp@(96)
+       clrl sp@(100)
+       movel a0@(4),a0
+       movel a0@(30),sp@(104)
+       movew a4@(162),d1
+       swap d1
+       clrw d1
+       movew a4@(164),d0
+       extl d0
+       orl d0,d1
+       movel d1,sp@(108)
+       movel sp@(88),sp@(64)
+       movel sp@(92),sp@(68)
+       movel sp@(96),sp@(72)
+       movel sp@(100),sp@(76)
+       movel sp@(104),sp@(80)
+       movel d1,sp@(84)
+       movel sp@(60),a1
+       movel a1@(18),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       lea sp@(64),a1
+       jbsr a3@
+L85:
+       moveml sp@+,#0x7cfc
+       lea sp@(72),sp
+       rts
+       .even
+_LV_GMHandleInput:
+       lea sp@(-140),sp
+       moveml #0x3f3e,sp@-
+       movel a1,sp@(76)
+       movel d0,d6
+       clrl d0
+       movew a0@(32),d0
+       movel a1,a4
+       addl d0,a4
+       movel d6,a0
+       movel a0@(8),sp@(72)
+       clrl sp@(68)
+       movel sp@(72),a1
+       clrl d0
+       moveb a1@(4),d0
+       moveq #2,d1
+       cmpl d0,d1
+       jeq L221
+       jlt L279
+       moveq #1,d1
+       cmpl d0,d1
+       jeq L194
+       jra L193
+       .even
+L279:
+       moveq #6,d1
+       cmpl d0,d1
+       jeq L268
+       jra L193
+       .even
+L194:
+       movel sp@(72),a0
+       clrl d0
+       movew a0@(6),d0
+       moveq #76,d1
+       cmpl d0,d1
+       jeq L196
+       moveq #77,d1
+       cmpl d0,d1
+       jeq L208
+       jra L218
+       .even
+L196:
+       movel sp@(72),a0
+       movew a0@(8),d1
+       btst #0,a4@(93)
+       jne L198
+       btst #3,d1
+       jeq L197
+L198:
+       bftst d1{#30:#2}
+       jeq L199
+       movel a4@(16),d0
+       jpl L283
+       addql #1,d0
+L283:
+       asrl #1,d0
+       movel a4@(4),a4
+       subl d0,a4
+       movel a4,d0
+       jra L200
+       .even
+L199:
+       movel a4@(4),d0
+       subql #1,d0
+L200:
+       tstl d0
+       jge L212
+       clrl d0
+       jra L212
+       .even
+L197:
+       movew d1,d0
+       andw #48,d0
+       jne L281
+       bftst d1{#30:#2}
+       jeq L205
+       movel a4@(24),d0
+       subl a4@(16),d0
+       addql #1,d0
+       jra L204
+       .even
+L205:
+       movel a4@(24),d0
+       subql #1,d0
+L204:
+       tstl d0
+       jge L215
+L281:
+       clrl d0
+       jra L215
+       .even
+L208:
+       movel sp@(72),a1
+       movew a1@(8),d1
+       btst #0,a4@(93)
+       jne L210
+       movew d1,d2
+       btst #3,d2
+       jeq L209
+L210:
+       bftst d1{#30:#2}
+       jeq L211
+       movel a4@(16),d0
+       jpl L284
+       addql #1,d0
+L284:
+       asrl #1,d0
+       addl a4@(4),d0
+       jra L212
+       .even
+L211:
+       movel a4@(4),d0
+       addql #1,d0
+L212:
+       movel #-2142480894,sp@(160)
+       movel d0,sp@(164)
+       clrl sp@(168)
+       jra L195
+       .even
+L209:
+       movew d2,d0
+       andw #48,d0
+       jeq L214
+       movel a4@(12),d0
+       subql #1,d0
+       jra L215
+       .even
+L214:
+       bftst d2{#30:#2}
+       jeq L216
+       movel a4@(24),d0
+       addl a4@(16),d0
+       subql #1,d0
+       jra L215
+       .even
+L216:
+       movel a4@(24),d0
+       addql #1,d0
+L215:
+       movel #-2142480895,sp@(160)
+       movel d0,sp@(164)
+       movel #-2142480888,sp@(168)
+       movel d0,sp@(172)
+       clrl sp@(176)
+       jra L195
+       .even
+L218:
+       clrl sp@(160)
+L195:
+       tstl sp@(160)
+       jeq L193
+       movel #264,sp@(128)
+       lea sp@(160),a2
+       movel a2,sp@(132)
+       movel d6,a0
+       movel a0@(4),sp@(136)
+       movel sp@(72),a1
+       movew a1@(8),d0
+       andw #9,d0
+       sne d0
+       extbl d0
+       negl d0
+       movel d0,sp@(140)
+       movel sp@(128),sp@(144)
+       movel a2,sp@(148)
+       movel sp@(136),sp@(152)
+       movel d0,sp@(156)
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       lea sp@(144),a1
+       jbsr a3@
+       jra L193
+       .even
+L221:
+       movel sp@(72),a0
+       clrl d0
+       movew a0@(6),d0
+       moveq #106,d1
+       cmpl d0,d1
+       jeq L256
+       jlt L267
+       moveq #104,d1
+       cmpl d0,d1
+       jeq L223
+       moveq #105,d1
+       cmpl d0,d1
+       jeq L249
+       jra L260
+       .even
+L267:
+       cmpl #232,d0
+       jeq L257
+       cmpl #234,d0
+       jeq L259
+       jra L260
+       .even
+L223:
+       movel d6,a0
+       movew a0@(16),d0
+       jlt L225
+       cmpw a4@(146),d0
+       jge L225
+       movew a0@(18),d1
+       jlt L225
+       cmpw a4@(148),d1
+       jlt L224
+L225:
+       movew #4,a1
+       movel a1,sp@(68)
+       jra L193
+       .even
+L224:
+       movel a4@(90),d0
+       bset #31,d0
+       movel d0,a4@(90)
+       btst #0,d0
+       jne L193
+       movel a4@(20),a0
+       lea a0@(d1:w),a2
+       movel a2,d5
+       movel a4@(60),d0
+       addl a4@(64),d0
+       divsl d0,d5
+       movel d5,d4
+       jlt L193
+       cmpl a4@(12),d4
+       jge L193
+       movel a4@(24),a4@(80)
+       movel a0,a4@(84)
+       lea sp@(128),a0
+       movel a0,sp@(52)
+       lea sp@(144),a1
+       movel a1,sp@(48)
+       lea sp@(148),a2
+       movel a2,sp@(44)
+       lea sp@(152),a2
+       lea sp@(140),a5
+       lea sp@(112),a0
+       movel a0,sp@(64)
+       lea sp@(116),a1
+       movel a1,sp@(60)
+       lea sp@(120),a0
+       movel a0,sp@(56)
+       moveq #124,d7
+       addl sp,d7
+       cmpl a4@(24),d4
+       jne L230
+       movel _IntuitionBase,a6
+       movel a4@(98),d0
+       movel a4@(102),d1
+       movel sp@(72),a1
+       movel a1@(14),d2
+       movel a1@(18),d3
+#APP
+       jsr a6@(-0x66:W)
+#NO_APP
+       tstw d0
+       jeq L230
+       movel #-2142480866,sp@(128)
+       movel d4,sp@(132)
+       clrl sp@(136)
+       movel #264,sp@(112)
+       movel sp@(52),sp@(116)
+       movel d6,a0
+       movel a0@(4),sp@(120)
+       clrl sp@(124)
+       movel sp@(64),a1
+       movel a1@,a5@
+       movel sp@(48),a0
+       movel sp@(60),a1
+       movel a1@,a0@
+       movel sp@(44),a0
+       movel sp@(56),a1
+       movel a1@,a0@
+       movel d7,a0
+       movel a0@,a2@
+       movel sp@(76),a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       movel a5,a1
+       movel sp@(76),a2
+       jbsr a3@
+L230:
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L232
+       movel a4@(76),a0
+       tstl a0
+       jeq L236
+       movel a0@(d5:l:4),d0
+       jra L237
+       .even
+L236:
+       btst #28,d0
+       jeq L233
+       movel #517,sp@(112)
+       movel d5,sp@(116)
+       movel a4@,sp@(120)
+       movel a4@(106),a3
+       lea sp@(112),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a0
+       clrl d0
+       tstl a0
+       jeq L241
+       clrl d0
+       moveb a0@(8),d0
+L241:
+L237:
+       movel #-2142480891,d1
+       tstl d0
+       jne L234
+L233:
+       movel #-2142480892,d1
+L234:
+       movel d1,a4@(56)
+       jra L245
+       .even
+L232:
+       movel sp@(76),a2
+       btst #0,a2@(14)
+       jeq L246
+       movel #-2142480895,a4@(56)
+       cmpl a4@(24),d5
+       jne L245
+       moveq #-1,d4
+       jra L245
+       .even
+L246:
+       movel #-2142480895,a4@(56)
+L245:
+       movel a4@(56),sp@(124)
+       movel d4,sp@(128)
+       clrl sp@(132)
+       movel sp@(64),a0
+       movel d7,a1
+       movel a1@,a0@
+       movel sp@(60),a2
+       movel sp@(52),a0
+       movel a0@,a2@
+       movel sp@(56),a1
+       movel sp@(132),a1@
+       lea sp@(136),a1
+       movel #264,sp@(96)
+       lea sp@(112),a2
+       movel a2,sp@(100)
+       movel d6,a0
+       movel a0@(4),sp@(104)
+       clrl sp@(108)
+       movel sp@(96),a1@
+       movel sp@(100),a5@
+       movel sp@(48),a2
+       movel sp@(104),a2@
+       movel sp@(44),a0
+       movel sp@(108),a0@
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       jbsr a3@
+       movel sp@(72),a0
+       movel a0@(14),a4@(98)
+       movel a0@(18),a4@(102)
+       jra L193
+       .even
+L249:
+       movel a4@(90),d1
+       movel d1,d0
+       andl #-1073741824,d0
+       jeq L250
+       movel d1,d0
+       andl #1073741823,d0
+       movel d0,a4@(90)
+       movel a4@(80),d2
+       cmpl a4@(24),d2
+       jne L252
+       movel a4@(84),a0
+       cmpl a4@(20),a0
+       jeq L193
+L252:
+       movel #-2142480895,d0
+       btst #0,d1
+       jeq L253
+       moveq #1,d0
+L253:
+       movel d0,sp@(116)
+       movel d2,sp@(120)
+       movel #-2142480864,sp@(124)
+       movel a4@(84),sp@(128)
+       clrl sp@(132)
+       movel d0,sp@(96)
+       movel d2,sp@(100)
+       movel sp@(124),sp@(104)
+       movel sp@(128),sp@(108)
+       movel sp@(132),sp@(112)
+       lea sp@(136),a1
+       movel #264,sp@(80)
+       lea sp@(96),a2
+       movel a2,sp@(84)
+       movel d6,a0
+       movel a0@(4),sp@(88)
+       clrl sp@(92)
+       movel sp@(80),a1@
+       movel sp@(84),sp@(140)
+       movel sp@(88),sp@(144)
+       movel sp@(92),sp@(148)
+       jra L282
+       .even
+L250:
+       moveq #4,d0
+       movel d0,sp@(68)
+       jra L193
+       .even
+L256:
+       movel a4@(20),a4@(84)
+       movel a4@(24),a4@(80)
+       movel d6,a0
+       movew a0@(18),a4@(88)
+       bset #7,a4@(90)
+       jra L193
+       .even
+L257:
+       bclr #7,a4@(90)
+       movel sp@(76),a1
+       btst #0,a1@(15)
+       jeq L193
+       lea a4@(24),a4
+       movel d6,a2
+       movel a4,a2@(12)
+       moveq #10,d0
+       movel d0,sp@(68)
+       jra L193
+       .even
+L259:
+       bclr #6,a4@(90)
+       jra L193
+       .even
+L260:
+       movel a4@(90),d1
+       jge L261
+       movel d6,a1
+       movew a1@(18),a0
+       movel a0,d4
+       addl a4@(20),d4
+       movel a4@(60),d0
+       addl a4@(64),d0
+       divsl d0,d4
+       cmpl a4@(24),d4
+       jeq L261
+       btst #0,d1
+       jne L261
+       movel a4@(4),d0
+       cmpl d4,d0
+       jgt L261
+       addl a4@(16),d0
+       cmpl d4,d0
+       jle L261
+       movel a4@(56),sp@(92)
+       movel d4,sp@(96)
+       clrl sp@(100)
+       movel sp@(92),sp@(80)
+       movel d4,sp@(84)
+       movel sp@(100),sp@(88)
+       lea sp@(104),a1
+       movel #264,sp@(120)
+       lea sp@(80),a2
+       movel a2,sp@(124)
+       movel d6,a0
+       movel a0@(4),sp@(128)
+       clrl sp@(132)
+       movel sp@(120),a1@
+       movel sp@(124),sp@(108)
+       movel sp@(128),sp@(112)
+       movel sp@(132),sp@(116)
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       jbsr a3@
+L261:
+       btst #6,a4@(90)
+       jeq L193
+       movel d6,a1
+       movew a1@(18),a0
+       subw a4@(88),a0
+       movel a0,d4
+       addl a4@(84),d4
+       movel #-2142480864,sp@(80)
+       movel d4,d0
+       jge L265
+       clrl d0
+L265:
+       movel d0,sp@(84)
+       clrl sp@(88)
+       movel #264,sp@(108)
+       lea sp@(80),a2
+       movel a2,sp@(112)
+       movel d6,a0
+       movel a0@(4),sp@(116)
+       clrl sp@(120)
+       movel sp@(108),sp@(92)
+       movel a2,sp@(96)
+       movel sp@(116),sp@(100)
+       movel sp@(120),sp@(104)
+       movel sp@(76),a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea sp@(92),a1
+       movel sp@(76),a2
+       jbsr a3@
+       jra L193
+       .even
+L268:
+       movel a4@(90),d2
+       jge L193
+       movel d6,a2
+       tstw a2@(18)
+       jge L270
+       movel a4@(4),d1
+       jeq L270
+       movel #-2142480887,sp@(100)
+       moveq #1,d0
+       movel d0,sp@(104)
+       movel #-2142480895,d0
+       btst #0,d2
+       jeq L271
+       moveq #1,d0
+L271:
+       movel d0,sp@(108)
+       subql #1,d1
+       movel d1,sp@(112)
+       clrl sp@(116)
+       movel sp@(100),sp@(80)
+       movel sp@(104),sp@(84)
+       movel d0,sp@(88)
+       movel d1,sp@(92)
+       movel sp@(116),sp@(96)
+       lea sp@(120),a1
+       movel #264,sp@(136)
+       lea sp@(80),a0
+       movel a0,sp@(140)
+       movel d6,a2
+       movel a2@(4),sp@(144)
+       clrl sp@(148)
+       movel sp@(136),a1@
+       movel sp@(140),sp@(124)
+       movel sp@(144),sp@(128)
+       movel sp@(148),sp@(132)
+L282:
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       jbsr a3@
+       jra L193
+       .even
+L270:
+       movel d6,a0
+       movew a0@(18),d0
+       extl d0
+       movel a4@(60),d1
+       addl a4@(64),d1
+       divsl d1,d0
+       movel a4@(16),d1
+       cmpl d0,d1
+       jgt L193
+       movel #-2142480886,sp@(100)
+       moveq #1,d0
+       movel d0,sp@(104)
+       movel #-2142480895,d0
+       btst #0,a4@(93)
+       jeq L275
+       moveq #1,d0
+L275:
+       movel d0,sp@(108)
+       addl a4@(4),d1
+       movel d1,sp@(112)
+       clrl sp@(116)
+       movel sp@(100),sp@(80)
+       movel sp@(104),sp@(84)
+       movel d0,sp@(88)
+       movel d1,sp@(92)
+       movel sp@(116),sp@(96)
+       lea sp@(120),a1
+       movel #264,sp@(136)
+       lea sp@(80),a0
+       movel a0,sp@(140)
+       movel d6,a2
+       movel a2@(4),sp@(144)
+       clrl sp@(148)
+       movel sp@(136),a1@
+       movel sp@(140),sp@(124)
+       movel sp@(144),sp@(128)
+       movel sp@(148),sp@(132)
+       movel sp@(76),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       jbsr a3@
+L193:
+       movel sp@(68),d0
+       moveml sp@+,#0x7cfc
+       lea sp@(140),sp
+       rts
+       .even
+_LV_GMLayout:
+       lea sp@(-64),sp
+       moveml #0x3f3e,sp@-
+       movel a1,a5
+       movel d0,sp@(44)
+       clrl d0
+       movew a0@(32),d0
+       lea a5@(0,d0:l),a4
+       bset #5,a4@(90)
+       lea a4@(142),a2
+       movel a2,d0
+       movel sp@(44),a3
+       movel a3@(4),a0
+       jbsr _GetGadgetBox
+       lea a4@(150),a0
+       movew a2@,a0@
+       movew a2@(2),a0@(2)
+       movew a2@,d0
+       addw a2@(4),d0
+       subqw #1,d0
+       movew d0,a0@(4)
+       movew a2@(2),d0
+       addw a2@(6),d0
+       subqw #1,d0
+       movew d0,a0@(6)
+       clrl d0
+       movel a5@(18),a0
+       tstl a0
+       jeq L289
+       btst #2,a5@(13)
+       jeq L289
+       cmpw #-1,a0@(8)
+       seq d0
+       extbl d0
+       negl d0
+L289:
+       moveq #64,d3
+       addl sp,d3
+       moveq #84,d2
+       addl sp,d2
+       moveq #88,d6
+       addl sp,d6
+       lea sp@(92),a1
+       moveq #76,d4
+       addl sp,d4
+       moveq #80,d5
+       addl sp,d5
+       tstw d0
+       jeq L288
+       movel #519,sp@(64)
+       lea a4@(142),a0
+       movel a0,sp@(68)
+       lea a4@(158),a2
+       movel a2,sp@(72)
+       movel sp@(44),a3
+       movel a3@(4),a0
+       movel a0@(30),sp@(76)
+       clrl sp@(80)
+       movel d2,a0
+       movel d3,a2
+       movel a2@,a0@
+       movel d6,a3
+       movel sp@(68),a3@
+       movel sp@(72),a1@
+       movel d4,a0
+       movel a0@,sp@(96)
+       movel d5,a1
+       movel a1@,sp@(100)
+       movel a5@(18),a2
+       movel a2@(-4),a0
+       movel a0@(8),a3
+       movel d2,a1
+       jbsr a3@
+L288:
+       movel a4@(138),d0
+       jeq L291
+       movel _GfxBase,a6
+       movel d0,a0
+#APP
+       jsr a6@(-0x210:W)
+#NO_APP
+       movel _GfxBase,a6
+       movel a4@(138),a0
+       lea a4@(150),a1
+#APP
+       jsr a6@(-0x1fe:W)
+#NO_APP
+L291:
+       tstl a4@(134)
+       jne L292
+       movel sp@(44),a2
+       movel a2@(4),a0
+       movel a0@(30),a0
+       movel a0@(8),a4@(134)
+       tstl a4@(60)
+       jne L298
+       movel a4@(134),a0
+       clrl d0
+       movew a0@(20),d0
+       movel d0,a4@(60)
+L292:
+       tstl a4@(60)
+       jeq L294
+L298:
+       tstl a4@(138)
+       jeq L295
+       movew a4@(148),a2
+       movel a4@(60),d0
+       lea a2@(0,d0:l),a1
+       movel a4@(64),a0
+       lea a0@(-1,a1:l),a1
+       movel a1,d1
+       addl a0,d0
+       divsl d0,d1
+       movel a2,d0
+       jra L297
+       .even
+L295:
+       movew a4@(148),a0
+       movel a4@(64),d0
+       movel a0,d1
+       addl d0,d1
+       addl a4@(60),d0
+       divsl d0,d1
+       movel a0,d0
+       jra L297
+       .even
+L294:
+       clrl d1
+       movew a4@(148),d0
+       extl d0
+L297:
+       movel d0,d7
+       divsl a4@(72),d7
+       movel d7,a4@(68)
+       movel #-2142480878,sp@(64)
+       movel d1,sp@(68)
+       clrl sp@(72)
+       movel #264,sp@(48)
+       movel d3,sp@(52)
+       movel sp@(44),a0
+       movel a0@(4),sp@(56)
+       clrl sp@(60)
+       movel d4,a1
+       movel sp@(48),a1@
+       movel d5,a2
+       movel sp@(52),a2@
+       movel d2,a3
+       movel sp@(56),a3@
+       movel d6,a0
+       movel sp@(60),a0@
+       movel a5@(-4),a0
+       movel a0@(8),a3
+       lea sp@(76),a1
+       movel a5,a2
+       jbsr a3@
+       bclr #5,a4@(90)
+       moveml sp@+,#0x7cfc
+       lea sp@(64),sp
+       rts
+       .even
+_LV_OMSet:
+       link a5,#-188
+       moveml #0x3f3a,sp@-
+       movel a0,d7
+       movel a1,d5
+       movel d0,a5@(-188)
+       clrl d0
+       movew a0@(32),d0
+       movel d5,a4
+       addl d0,a4
+       movel a5@(-188),a0
+       movel a0@(4),a5@(-184)
+       clrw d4
+       movel a5,d6
+       addl #-184,d6
+       jra L300
+       .even
+L302:
+       movel a0@,d0
+       cmpl #-2142480884,d0
+       jhi L583
+       cmpl #-2142480885,d0
+       jcc L300
+       cmpl #-2142480891,d0
+       jeq L352
+       jhi L584
+       cmpl #-2142480894,d0
+       jeq L318
+       jhi L585
+       cmpl #-2147287024,d0
+       jeq L304
+       cmpl #-2142480895,d0
+       jeq L306
+       jra L581
+       .even
+L585:
+       cmpl #-2142480893,d0
+       jeq L300
+       cmpl #-2142480892,d0
+       jeq L326
+       jra L581
+       .even
+L584:
+       cmpl #-2142480888,d0
+       jeq L422
+       jhi L586
+       cmpl #-2142480890,d0
+       jeq L374
+       cmpl #-2142480889,d0
+       jeq L404
+       jra L581
+       .even
+L586:
+       cmpl #-2142480887,d0
+       jeq L430
+       cmpl #-2142480886,d0
+       jeq L433
+       jra L581
+       .even
+L583:
+       cmpl #-2142480879,d0
+       jeq L524
+       jhi L587
+       cmpl #-2142480882,d0
+       jeq L465
+       jcs L438
+       cmpl #-2142480881,d0
+       jeq L489
+       cmpl #-2142480880,d0
+       jeq L516
+       jra L581
+       .even
+L587:
+       cmpl #-2142480865,d0
+       jeq L571
+       jhi L588
+       cmpl #-2142480878,d0
+       jeq L543
+       cmpl #-2142480876,d0
+       jeq L554
+       jra L581
+       .even
+L588:
+       cmpl #-2142480864,d0
+       jeq L572
+       cmpl #-2142480850,d0
+       jeq L580
+       jra L581
+       .even
+L304:
+       movel a5@(-188),a1
+       cmpl #259,a1@
+       jne L300
+       movel d5,a1
+       movew a0@(6),a1@(38)
+       jra L300
+       .even
+L306:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d1
+       moveq #-1,d0
+       cmpl d1,d0
+       jeq L308
+       movel a4@(12),d2
+       movel d1,d0
+       cmpl d0,d2
+       jgt L309
+       movel d2,d0
+       subql #1,d0
+L309:
+       movel d0,d1
+L308:
+       movel a4@(24),a0
+       cmpl a0,d1
+       jeq L300
+       movel a4@(4),d2
+       cmpl a0,d2
+       jgt L314
+       movel d2,d0
+       addl a4@(16),d0
+       cmpl a0,d0
+       jgt L313
+L314:
+       cmpl d1,d2
+       jgt L312
+       movel d2,d0
+       addl a4@(16),d0
+       cmpl d1,d0
+       jle L312
+L313:
+       orw #8,d4
+L312:
+       movel d1,a4@(24)
+       moveq #-1,d0
+       cmpl d1,d0
+       jne L315
+       clrl a4@(28)
+       jra L396
+       .even
+L315:
+       movel #517,a5@(-12)
+       movel d1,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+       jra L396
+       .even
+L318:
+       movel a0@(4),d2
+       cmpl a4@(4),d2
+       jeq L300
+       tstl a4@
+       jeq L300
+       movel a4@(16),a0
+       movel d2,d0
+       addl a0,d0
+       movel a4@(12),d1
+       cmpl d0,d1
+       jgt L321
+       cmpl d1,a0
+       slt d0
+       moveb d0,d2
+       extbl d2
+       subl a0,d1
+       andl d1,d2
+L321:
+       movel d2,a4@(4)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl d2,d0
+       movel d0,a4@(20)
+       movel #517,a5@(-12)
+       movel d2,a5@(-8)
+       jra L755
+       .even
+L326:
+       movel a4@(32),d1
+       cmpl a4@(36),d1
+       jcs L327
+       movel a5@(-188),a0
+       movel a0@(8),a1
+       clrl d0
+       tstl a1
+       jeq L328
+       movel a1@,d0
+L328:
+       movel _IntuitionBase,a6
+       movel d0,a0
+#APP
+       jsr a6@(-0x60:W)
+#NO_APP
+       jra L300
+       .even
+L327:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d1
+       movel a4@(12),d0
+       movel d0,d3
+       subql #1,d3
+       cmpl d1,d0
+       jle L332
+       movel d1,d3
+L332:
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L336
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       jgt L335
+L336:
+       cmpl d3,d1
+       jgt L334
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d3,d0
+       jle L334
+L335:
+       orw #8,d4
+L334:
+       movel d3,a4@(24)
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+       movel d0,a1
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L339
+       movel a4@(76),a0
+       tstl a0
+       jeq L340
+       movel a0@(d3:l:4),d0
+       jra L341
+       .even
+L340:
+       btst #28,d0
+       jeq L610
+       tstl a1
+       jne L611
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L345
+L611:
+       clrl d0
+       moveb a1@(8),d0
+       jra L341
+       .even
+L345:
+       clrl d0
+       jra L341
+       .even
+L339:
+       cmpl a4@(24),d3
+       seq d0
+       extbl d0
+       negl d0
+L341:
+       tstl d0
+       jne L396
+L610:
+       movel a4@(32),d0
+       movel d0,a1
+       addql #1,a1
+       movel a1,a4@(32)
+       movel a4@(76),a0
+       tstl a0
+       jeq L401
+       addql #1,d0
+       movel d0,a0@(d3:l:4)
+       jra L396
+       .even
+L352:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d1
+       movel a4@(12),d0
+       movel d0,d3
+       subql #1,d3
+       cmpl d1,d0
+       jle L354
+       movel d1,d3
+L354:
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L358
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       jgt L357
+L358:
+       cmpl d3,d1
+       jgt L356
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d3,d0
+       jle L356
+L357:
+       orw #8,d4
+L356:
+       movel d3,a4@(24)
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+       movel d0,a1
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L361
+       movel a4@(76),a0
+       tstl a0
+       jeq L362
+       movel a0@(d3:l:4),d0
+       jra L363
+       .even
+L362:
+       btst #28,d0
+       jeq L300
+       tstl a1
+       jne L612
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L367
+L612:
+       clrl d0
+       moveb a1@(8),d0
+       jra L363
+       .even
+L367:
+       clrl d0
+       jra L363
+       .even
+L361:
+       cmpl a4@(24),d3
+       seq d0
+       extbl d0
+       negl d0
+L363:
+       tstl d0
+       jeq L300
+L771:
+       subql #1,a4@(32)
+       movel a4@(76),a0
+       tstl a0
+       jne L770
+       btst #4,a4@(90)
+       jeq L396
+       movel a4@(28),a0
+       clrb a0@(8)
+       jra L396
+       .even
+L374:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d1
+       movel a4@(12),d0
+       movel d0,d3
+       subql #1,d3
+       cmpl d1,d0
+       jle L376
+       movel d1,d3
+L376:
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L380
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       jgt L379
+L380:
+       cmpl d3,d1
+       jgt L378
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d3,d0
+       jle L378
+L379:
+       orw #8,d4
+L378:
+       movel d3,a4@(24)
+       movel #517,a5@(-12)
+       movel d3,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+       movel d0,a1
+       movel a4@(24),d1
+       movel a4@(90),d0
+       btst #3,d0
+       jeq L383
+       movel a4@(76),a0
+       tstl a0
+       jeq L384
+       movel a0@(d1:l:4),d0
+       jra L385
+       .even
+L384:
+       btst #28,d0
+       jeq L382
+       tstl a1
+       jne L613
+       movel #517,a5@(-12)
+       movel d1,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a1
+       tstl a1
+       jeq L389
+L613:
+       clrl d0
+       moveb a1@(8),d0
+       jra L385
+       .even
+L389:
+       clrl d0
+       jra L385
+       .even
+L383:
+       moveq #1,d0
+L385:
+       tstl d0
+       jeq L382
+       jra L771
+       .even
+L770:
+       movel a4@(24),d0
+       clrl a0@(d0:l:4)
+       jra L396
+       .even
+L382:
+       movel a4@(32),d1
+       cmpl a4@(36),d1
+       jcs L397
+       movel a5@(-188),a0
+       movel a0@(8),a1
+       clrl d0
+       tstl a1
+       jeq L398
+       movel a1@,d0
+L398:
+       movel _IntuitionBase,a6
+       movel d0,a0
+#APP
+       jsr a6@(-0x60:W)
+#NO_APP
+       jra L396
+       .even
+L397:
+       movel d1,a1
+       addql #1,a1
+       movel a1,a4@(32)
+       movel a4@(76),a0
+       tstl a0
+       jeq L401
+       movel a4@(24),d0
+       addql #1,d1
+       movel d1,a0@(d0:l:4)
+       jra L396
+       .even
+L401:
+       btst #4,a4@(90)
+       jeq L396
+       movel a4@(28),a0
+       moveb a4@(35),a0@(8)
+L396:
+       orw #16,d4
+       jra L300
+       .even
+L404:
+       tstl a4@
+       jeq L300
+       movel a0@(4),d3
+       movel a4@(24),d2
+       movel a4@(4),d1
+       cmpl d2,d1
+       jgt L408
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d2,d0
+       jgt L407
+L408:
+       cmpl d3,d1
+       jgt L406
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl d3,d0
+       jle L406
+L407:
+       orw #8,d4
+L406:
+       moveq #-1,d0
+       movel d0,a4@(24)
+       clrl a4@(28)
+       clrl a4@(32)
+       tstl a4@(76)
+       jeq L409
+       clrl d1
+       movew d4,d0
+       orw #18,d0
+       cmpl a4@(12),d1
+       jge L415
+       .even
+L413:
+       movel a4@(76),a0
+       clrl a0@(d1:l:4)
+       addql #1,d1
+       cmpl a4@(12),d1
+       jlt L413
+       jra L415
+       .even
+L409:
+       movew d4,d0
+       orw #18,d0
+       btst #4,a4@(90)
+       jeq L415
+       movel a4@,a0
+       jra L757
+       .even
+L420:
+       clrb a0@(8)
+L757:
+       movel a0@,a0
+       tstl a0@
+       jne L420
+L415:
+       movew d0,d4
+       jra L300
+       .even
+L422:
+       movel a0@(4),d1
+       jge L423
+       clrl d1
+L423:
+       movel a4@(12),d0
+       cmpl d1,d0
+       jgt L424
+       movel d0,d1
+       subql #1,d1
+L424:
+       movel a4@(4),d0
+       cmpl d1,d0
+       jle L425
+       movel d1,a4@(4)
+       movel #517,a5@(-12)
+       movel d1,a5@(-8)
+       jra L755
+       .even
+L425:
+       movel a4@(16),d2
+       addl d2,d0
+       cmpl d1,d0
+       jgt L300
+       subl d2,d1
+       movel d1,d0
+       addql #1,d0
+       jra L758
+       .even
+L430:
+       movel a4@(4),d0
+       jle L300
+       movel a4@,d1
+       jeq L300
+       movel d0,a0
+       subql #1,a0
+       movel a0,a4@(4)
+       movel a4@(8),a1
+       movel #516,a5@(-12)
+       subql #1,d0
+       movel d0,a5@(-8)
+       movel d1,a5@(-4)
+       movel a4@(114),a3
+       lea a5@(-12),a2
+       jra L759
+       .even
+L433:
+       movel a4@(4),d1
+       movel d1,d0
+       addl a4@(16),d0
+       cmpl a4@(12),d0
+       jge L300
+       movel a4@,d0
+       jeq L300
+       movel d1,a1
+       addql #1,a1
+       movel a1,a4@(4)
+       movel a4@(8),a1
+       movel #515,a5@(-12)
+       addql #1,d1
+       movel d1,a5@(-8)
+       movel d0,a5@(-4)
+       movel a4@(110),a3
+       lea a5@(-12),a2
+       jra L759
+       .even
+L438:
+       movel a0@(4),d0
+       moveq #-1,d1
+       cmpl d0,d1
+       jeq L760
+       movel d0,a4@
+       movel #_ListGetItem,a4@(106)
+       movel #_ListGetNext,a4@(110)
+       movel #_ListGetPrev,a4@(114)
+       movel #_ListStringDrawItem,a4@(126)
+       bset #4,a4@(90)
+       movel _UtilityBase,a6
+       movel #-2142480893,d0
+       moveq #-1,d1
+       movel a5@(-188),a1
+       movel a1@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(12)
+       movew d4,d3
+       orw #34,d3
+       moveq #-1,d1
+       cmpl d0,d1
+       jne L441
+       movel a4@,a0
+       clrl d0
+       tstl a0
+       jeq L442
+       movel a0@,a0
+       jra L761
+       .even
+L446:
+       addql #1,d0
+L761:
+       movel a0@,a0
+       tstl a0
+       jne L446
+L442:
+       movel d0,a4@(12)
+L441:
+       clrl d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L450
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L453
+       cmpl d1,d4
+       jle L728
+       moveq #2,d4
+       cmpl d1,d4
+       jle L729
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L729:
+       tstl a3@+
+       jeq L735
+       addql #1,d0
+L735:
+       subql #1,a2
+L728:
+       tstl a3@+
+       jeq L738
+       addql #1,d0
+L738:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L453:
+       movel a3,a0
+       tstl a0@+
+       jeq L741
+       addql #1,d0
+L741:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L744
+       addql #1,d0
+L744:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L747
+       addql #1,d0
+L747:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L750
+       addql #1,d0
+L750:
+       subql #4,a2
+       tstl a2
+       jne L453
+       jra L555
+       .even
+L450:
+       btst #28,d1
+       jeq L555
+       movel a4@,a0
+       tstl a0
+       jeq L555
+       movel a0@,a0
+       jra L762
+       .even
+L460:
+       addql #1,d0
+L762:
+       movel a0@,a0
+       tstl a0
+       jne L460
+       jra L555
+       .even
+L465:
+       movel a0@(4),d0
+       moveq #-1,d1
+       cmpl d0,d1
+       jeq L760
+       movel d0,a4@
+       movel #_ArrayGetItem,a4@(106)
+       movel #_ArrayGetItem,a4@(110)
+       movel #_ArrayGetItem,a4@(114)
+       movel #_StringDrawItem,a4@(126)
+       bclr #4,a4@(90)
+       movel _UtilityBase,a6
+       movel #-2142480893,d0
+       moveq #-1,d1
+       movel a5@(-188),a1
+       movel a1@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(12)
+       movew d4,d3
+       orw #34,d3
+       moveq #-1,d1
+       cmpl d0,d1
+       jne L468
+       movel a4@,a0
+       tstl a0
+       jeq L468
+       clrl d0
+       tstl a0@
+       jeq L470
+       .even
+L471:
+       addql #1,d0
+       addql #4,a0
+       tstl a0@
+       jne L471
+L470:
+       movel d0,a4@(12)
+L468:
+       clrl d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L474
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L477
+       cmpl d1,d4
+       jle L700
+       moveq #2,d4
+       cmpl d1,d4
+       jle L701
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L701:
+       tstl a3@+
+       jeq L707
+       addql #1,d0
+L707:
+       subql #1,a2
+L700:
+       tstl a3@+
+       jeq L710
+       addql #1,d0
+L710:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L477:
+       movel a3,a0
+       tstl a0@+
+       jeq L713
+       addql #1,d0
+L713:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L716
+       addql #1,d0
+L716:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L719
+       addql #1,d0
+L719:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L722
+       addql #1,d0
+L722:
+       subql #4,a2
+       tstl a2
+       jne L477
+       jra L555
+       .even
+L474:
+       btst #28,d1
+       jeq L555
+       movel a4@,a0
+       tstl a0
+       jeq L555
+       movel a0@,a0
+       jra L763
+       .even
+L484:
+       addql #1,d0
+L763:
+       movel a0@,a0
+       tstl a0
+       jne L484
+       jra L555
+       .even
+L489:
+       movel a0@(4),d0
+       moveq #-1,d1
+       cmpl d0,d1
+       jeq L760
+       movel d0,a4@
+       movel #_ListGetItem,a4@(106)
+       movel #_ListGetNext,a4@(110)
+       movel #_ListGetPrev,a4@(114)
+       movel #_ListImageDrawItem,a4@(126)
+       bset #4,a4@(90)
+       movel _UtilityBase,a6
+       movel #-2142480893,d0
+       moveq #-1,d1
+       movel a5@(-188),a1
+       movel a1@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(12)
+       movew d4,d3
+       orw #34,d3
+       moveq #-1,d1
+       cmpl d0,d1
+       jne L492
+       movel a4@,a0
+       clrl d0
+       tstl a0
+       jeq L493
+       movel a0@,a0
+       jra L764
+       .even
+L497:
+       addql #1,d0
+L764:
+       movel a0@,a0
+       tstl a0
+       jne L497
+L493:
+       movel d0,a4@(12)
+L492:
+       clrl d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L501
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L504
+       cmpl d1,d4
+       jle L672
+       moveq #2,d4
+       cmpl d1,d4
+       jle L673
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L673:
+       tstl a3@+
+       jeq L679
+       addql #1,d0
+L679:
+       subql #1,a2
+L672:
+       tstl a3@+
+       jeq L682
+       addql #1,d0
+L682:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L504:
+       movel a3,a0
+       tstl a0@+
+       jeq L685
+       addql #1,d0
+L685:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L688
+       addql #1,d0
+L688:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L691
+       addql #1,d0
+L691:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L694
+       addql #1,d0
+L694:
+       subql #4,a2
+       tstl a2
+       jne L504
+       jra L555
+       .even
+L501:
+       btst #28,d1
+       jeq L555
+       movel a4@,a0
+       tstl a0
+       jeq L555
+       movel a0@,a0
+       jra L765
+       .even
+L511:
+       addql #1,d0
+L765:
+       movel a0@,a0
+       tstl a0
+       jne L511
+       jra L555
+       .even
+L516:
+       movel a0@(4),d0
+       moveq #-1,d1
+       cmpl d0,d1
+       jeq L760
+       movel d0,a4@
+       movel #_ArrayGetItem,a4@(106)
+       movel #_ArrayGetItem,a4@(110)
+       movel #_ArrayGetItem,a4@(114)
+       movel #_ImageDrawItem,a4@(126)
+       bclr #4,a4@(90)
+       movel _UtilityBase,a6
+       movel #-2142480893,d0
+       moveq #-1,d1
+       movel a5@(-188),a1
+       movel a1@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(12)
+       movew d4,d3
+       orw #34,d3
+       moveq #-1,d1
+       cmpl d0,d1
+       jne L766
+       movel a4@,a0
+       tstl a0
+       jeq L766
+       clrl d0
+       tstl a0@
+       jeq L521
+       .even
+L522:
+       addql #1,d0
+       addql #4,a0
+       tstl a0@
+       jne L522
+L521:
+       movel d0,a4@(12)
+       jra L766
+       .even
+L524:
+       movel a0@(4),a1
+       moveq #-1,d0
+       cmpl a1,d0
+       jne L525
+L760:
+       clrl a4@
+       jra L300
+       .even
+L525:
+       movel a1,a4@
+       clrl d0
+       movel a4@(90),d1
+       movew d4,d3
+       orw #34,d3
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L528
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L531
+       cmpl d1,d4
+       jle L644
+       moveq #2,d4
+       cmpl d1,d4
+       jle L645
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L645:
+       tstl a3@+
+       jeq L651
+       addql #1,d0
+L651:
+       subql #1,a2
+L644:
+       tstl a3@+
+       jeq L654
+       addql #1,d0
+L654:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L531:
+       movel a3,a0
+       tstl a0@+
+       jeq L657
+       addql #1,d0
+L657:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L660
+       addql #1,d0
+L660:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L663
+       addql #1,d0
+L663:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L666
+       addql #1,d0
+L666:
+       subql #4,a2
+       tstl a2
+       jne L531
+       jra L555
+       .even
+L528:
+       btst #28,d1
+       jeq L555
+       tstl a1
+       jeq L555
+       movel a1@,a0
+       jra L767
+       .even
+L538:
+       addql #1,d0
+L767:
+       movel a0@,a0
+       tstl a0
+       jne L538
+       jra L555
+       .even
+L543:
+       movel a0@(4),a4@(16)
+       orw #32,d4
+       tstl a4@(138)
+       jeq L544
+       movel a4@(60),d1
+       addl a4@(64),d1
+       mulsl a4@(12),d1
+       movew a4@(148),a0
+       movel a4@(20),d0
+       addl a0,d0
+       cmpl d0,d1
+       jgt L300
+       movel d1,d0
+       subl a0,d0
+       movel d0,a4@(20)
+       jge L546
+       clrl a4@(20)
+L546:
+       movel a4@(60),d0
+       addl a4@(64),d0
+       movel a4@(20),d1
+       divsl d0,d1
+       cmpl a4@(4),d1
+       jeq L768
+       movel d1,a4@(4)
+       movel #517,a5@(-12)
+       movel d1,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(8)
+       jra L768
+       .even
+L544:
+       movel a4@(16),d2
+       movel a4@(4),d0
+       addl d2,d0
+       movel a4@(12),d1
+       cmpl d0,d1
+       jgt L300
+       cmpl d1,d2
+       slt d0
+       extbl d0
+       subl d2,d1
+       andl d1,d0
+       movel d0,a4@(4)
+       movel #517,a5@(-12)
+       movel d0,a5@(-8)
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(8)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl a4@(4),d0
+       movel d0,a4@(20)
+L768:
+       orw #4,d4
+       jra L300
+       .even
+L554:
+       movel a0@(4),a4@(76)
+       clrl d0
+       movel a4@(90),d1
+       movew d4,d3
+       orw #2,d3
+       btst #3,d1
+       jeq L555
+       movel a4@(76),a0
+       tstl a0
+       jeq L556
+       movel a4@(12),d2
+       cmpl d0,d2
+       jle L555
+       movel a0,a3
+       movel d2,a2
+       movel d2,d1
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L559
+       cmpl d1,d4
+       jle L617
+       moveq #2,d4
+       cmpl d1,d4
+       jle L618
+       movel a0@+,d0
+       movel a0,a3
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,a2
+L618:
+       tstl a3@+
+       jeq L624
+       addql #1,d0
+L624:
+       subql #1,a2
+L617:
+       tstl a3@+
+       jeq L627
+       addql #1,d0
+L627:
+       subql #1,a2
+       tstl a2
+       jeq L555
+       .even
+L559:
+       movel a3,a0
+       tstl a0@+
+       jeq L630
+       addql #1,d0
+L630:
+       lea a3@(8),a1
+       tstl a0@
+       jeq L633
+       addql #1,d0
+L633:
+       lea a3@(12),a0
+       tstl a1@
+       jeq L636
+       addql #1,d0
+L636:
+       lea a3@(16),a3
+       tstl a0@
+       jeq L639
+       addql #1,d0
+L639:
+       subql #4,a2
+       tstl a2
+       jne L559
+       jra L555
+       .even
+L556:
+       btst #28,d1
+       jeq L555
+       movel a4@,a0
+       tstl a0
+       jeq L555
+       movel a0@,a0
+       jra L769
+       .even
+L566:
+       addql #1,d0
+L769:
+       movel a0@,a0
+       tstl a0
+       jne L566
+L555:
+       movel d0,a4@(32)
+L766:
+       movew d3,d4
+       jra L300
+       .even
+L571:
+       movel a0@(4),a4@(36)
+       jra L300
+       .even
+L572:
+       movel a0@(4),d1
+       cmpl a4@(20),d1
+       jeq L300
+       tstl a4@
+       jeq L300
+       movel a4@(60),d0
+       jeq L300
+       movel d1,a4@(20)
+       orw #4,d4
+       addl a4@(64),d0
+       movel d1,d3
+       divsl d0,d3
+       movel a4@(16),d2
+       movel d3,d0
+       addl d2,d0
+       movel a4@(12),d1
+       cmpl d0,d1
+       jgt L574
+       cmpl d1,d2
+       slt d0
+       extbl d0
+       subl d2,d1
+       andl d1,d0
+       jra L575
+       .even
+L574:
+       movel d3,d0
+L575:
+       cmpl a4@(4),d0
+       jeq L300
+L758:
+       movel d0,a4@(4)
+       movel #517,a5@(-12)
+       movel d0,a5@(-8)
+L755:
+       movel a4@,a5@(-4)
+       movel a4@(106),a3
+       lea a5@(-12),a2
+       subl a1,a1
+L759:
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(8)
+       orw #20,d4
+       jra L300
+       .even
+L580:
+       movel a0@(4),a4@(72)
+       movew a4@(148),d0
+       extl d0
+       movel d0,d1
+       divsl a4@(72),d1
+       movel d1,a4@(68)
+       jra L300
+       .even
+L581:
+       orw #1,d4
+L300:
+       movel _UtilityBase,a6
+       movel d6,a0
+#APP
+       jsr a6@(-0x30:W)
+#NO_APP
+       movel d0,a0
+       tstl a0
+       jne L302
+       btst #0,d4
+       jeq L590
+       movel d7,a1
+       movel a1@(24),a0
+       movel a0@(8),a3
+       movel a5@(-188),a1
+       movel d5,a2
+       jbsr a3@
+       movel d0,d3
+       jra L592
+       .even
+L590:
+       moveq #1,d3
+L592:
+       movew d4,d0
+       andw #14,d0
+       jeq L593
+       movel a5@(-188),a0
+       movel a0@(8),d0
+       jeq L593
+       btst #5,a4@(90)
+       jne L593
+       movel _IntuitionBase,a6
+       movel d0,a0
+#APP
+       jsr a6@(-0x22e:W)
+#NO_APP
+       movel d0,d2
+       jeq L593
+       btst #1,d4
+       jeq L595
+       moveq #1,d1
+       movel d1,a5@(-44)
+       movel a5@(-188),a0
+       movel a0@(8),a5@(-40)
+       movel d0,a5@(-36)
+       movel d1,a5@(-32)
+       movel d1,a5@(-28)
+       movel a5@(-40),a5@(-24)
+       movel d0,a5@(-20)
+       movel d1,a5@(-16)
+       movel d5,a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-28),a1
+       movel d5,a2
+       jbsr a3@
+       jra L596
+       .even
+L595:
+       btst #2,d4
+       jeq L597
+       moveq #1,d1
+       movel d1,a5@(-28)
+       movel a5@(-188),a0
+       movel a0@(8),a5@(-24)
+       movel d0,a5@(-20)
+       moveq #2,d0
+       movel d0,a5@(-16)
+       movel d1,a5@(-44)
+       movel a5@(-24),a5@(-40)
+       movel a5@(-20),a5@(-36)
+       movel d0,a5@(-32)
+       movel d5,a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-44),a1
+       movel d5,a2
+       jbsr a3@
+L597:
+       btst #3,d4
+       jeq L596
+       moveq #1,d0
+       movel d0,a5@(-28)
+       movel a5@(-188),a0
+       movel a0@(8),a5@(-24)
+       movel d2,a5@(-20)
+       clrl a5@(-16)
+       movel d0,a5@(-44)
+       movel a5@(-24),a5@(-40)
+       movel d2,a5@(-36)
+       movel a5@(-16),a5@(-32)
+       movel d5,a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-44),a1
+       movel d5,a2
+       jbsr a3@
+L596:
+       movel _IntuitionBase,a6
+       movel d2,a0
+#APP
+       jsr a6@(-0x234:W)
+#NO_APP
+L593:
+       btst #5,d4
+       jeq L599
+       movel #-2142480894,a5@(-180)
+       movel a4@(4),a5@(-176)
+       movel #-2142480893,a5@(-172)
+       movel a4@(12),a5@(-168)
+       movel #-2142480878,a5@(-164)
+       movel a4@(16),a5@(-160)
+       movel #-2142480895,a5@(-156)
+       movel a4@(24),a5@(-152)
+       movel #-2142480864,a5@(-148)
+       movel a4@(20),a5@(-144)
+       movel #-2142480863,a5@(-140)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       movel a4@(12),d1
+       mulsl d0,d1
+       movel d1,a5@(-136)
+       movel #-2142480862,a5@(-132)
+       tstl a4@(138)
+       jeq L600
+       movew a4@(148),d0
+       extl d0
+       jra L601
+       .even
+L600:
+       mulsl a4@(16),d0
+L601:
+       movel d0,a5@(-128)
+       movel #-2147287024,a5@(-124)
+       movel d5,a0
+       clrl d0
+       movew a0@(38),d0
+       movel d0,a5@(-120)
+       clrl a5@(-116)
+       moveq #-112,d2
+       addl a5,d2
+       pea 68:w
+       movel d2,sp@-
+       pea a5@(-180)
+       jbsr _bcopy
+       lea sp@(12),sp
+       movel #263,a5@(-28)
+       movel d2,a5@(-24)
+       movel a5@(-188),a1
+       movel a1@(8),a5@(-20)
+       clrl d0
+       cmpl #264,a1@
+       jne L602
+       movel a1@(12),d0
+L602:
+       movel d0,a5@(-16)
+       movel a5@(-28),a5@(-44)
+       movel a5@(-24),a5@(-40)
+       movel a5@(-20),a5@(-36)
+       movel d0,a5@(-32)
+       movel d5,a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-44),a1
+       movel d5,a2
+       jbsr a3@
+       jra L604
+       .even
+L599:
+       btst #4,d4
+       jeq L604
+       clrl d1
+       btst #2,d4
+       jeq L606
+       movel #-2142480894,a5@(-180)
+       movel a4@(4),a5@(-176)
+       movel #-2142480864,a5@(-172)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl a4@(4),d0
+       movel d0,a5@(-168)
+       moveq #4,d1
+L606:
+       lea a5@(-180),a0
+       btst #3,d4
+       jeq L607
+       movel #-2142480895,a0@(d1:l:4)
+       addql #1,d1
+       movel a4@(24),a0@(d1:l:4)
+       addql #1,d1
+L607:
+       movel #-2147287024,a0@(d1:l:4)
+       addql #1,d1
+       movel d5,a1
+       clrl d0
+       movew a1@(38),d0
+       movel d0,a0@(d1:l:4)
+       clrl a0@(4,d1:l:4)
+       movel #263,a5@(-128)
+       movel a0,a5@(-124)
+       movel a5@(-188),a0
+       movel a0@(8),a5@(-120)
+       clrl d0
+       cmpl #264,a0@
+       jne L608
+       movel a0@(12),d0
+L608:
+       movel d0,a5@(-116)
+       movel a5@(-128),a5@(-144)
+       movel a5@(-124),a5@(-140)
+       movel a5@(-120),a5@(-136)
+       movel d0,a5@(-132)
+       movel d5,a1
+       movel a1@(-4),a0
+       movel a0@(8),a3
+       lea a5@(-144),a1
+       movel d5,a2
+       jbsr a3@
+L604:
+       movel d3,d0
+       moveml a5@(-228),#0x5cfc
+       unlk a5
+       rts
+.data
+       .even
+_boolMap.69:
+       .long -2147286999
+       .long 1
+       .long -2142480872
+       .long 2
+       .long -2142480873
+       .long 4
+       .long -2142480871
+       .long 8
+       .long 0
+.text
+       .even
+_LV_OMNew:
+       lea sp@(-28),sp
+       moveml #0x383e,sp@-
+       movel a0,a4
+       movel a1,d3
+       movel d0,a5
+       movel a4@(24),a0
+       movel a0@(8),a3
+       movel a5,a1
+       movel d3,a2
+       jbsr a3@
+       movel d0,d3
+       jeq L789
+       movel d3,a0
+       tstw a0@(12)
+       jge L791
+       moveq #4,d0
+       orl d0,a0@(44)
+L791:
+       clrl d0
+       movew a4@(32),d0
+       movel d3,a4
+       addl d0,a4
+       movel _UtilityBase,a6
+       moveq #4,d0
+       movel a5@(4),a0
+       lea _boolMap.69,a1
+#APP
+       jsr a6@(-0x2a:W)
+#NO_APP
+       movel d0,a4@(90)
+       movel _UtilityBase,a6
+       movel #-2147287007,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a2
+       tstl d0
+       jeq L792
+       movel a2@(8),a4@(134)
+       jra L793
+       .even
+L792:
+       movel d0,a4@(134)
+L793:
+       movel _UtilityBase,a6
+       movel #-2142480867,d0
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x1e:W)
+#NO_APP
+       movel d0,a0
+       tstl a0
+       jeq L794
+       movel a0@(4),d0
+       jeq L796
+       jra L902
+       .even
+L794:
+       movel _UtilityBase,a6
+       movel #-2147287000,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       tstl d0
+       jeq L796
+       movel _GfxBase,a6
+       movel d0,a0
+#APP
+       jsr a6@(-0x48:W)
+#NO_APP
+       tstl d0
+       jeq L796
+       bset #3,a4@(90)
+L902:
+       movel d0,a4@(134)
+L796:
+       movel a4@(134),a0
+       tstl a0
+       jeq L799
+       clrl d0
+       movew a0@(20),d0
+       movel d0,a4@(60)
+       jra L800
+       .even
+L799:
+       clrl a4@(60)
+L800:
+       movel _UtilityBase,a6
+       movel #-2142480869,d0
+       movel a4@(60),d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(60)
+       movel _UtilityBase,a6
+       movel #-2147254270,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(64)
+       movel _UtilityBase,a6
+       movel #-2142480868,d0
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x1e:W)
+#NO_APP
+       movel d0,a0
+       tstl d0
+       jeq L801
+       movel a0@(4),a4@(94)
+       jra L802
+       .even
+L801:
+       tstl a2
+       jeq L803
+       movel a2@(4),a0
+       movew a0@(14),a1
+       movew a0@(4),d2
+       cmpw a1,d2
+       jcc L806
+       movel d0,d1
+       movew a1,d1
+       jra L807
+       .even
+L806:
+       movel d0,d1
+       movew d2,d1
+L807:
+       movew a0@(10),d2
+       movew a0@(12),d0
+       cmpw d2,d0
+       jcc L808
+       clrl d0
+       movew d2,d0
+       cmpl d1,d0
+       jlt L809
+       jra L804
+       .even
+L808:
+       andl #0xFFFF,d0
+       cmpl d1,d0
+       jge L804
+L809:
+       movew a0@(14),d1
+       movew a0@(4),d0
+       cmpw d1,d0
+       jcs L903
+       jra L812
+       .even
+L804:
+       movew a0@(10),d1
+       movew a0@(12),d0
+       cmpw d1,d0
+       jcc L812
+L903:
+       clrl d0
+       movew d1,d0
+       jra L805
+       .even
+L812:
+       andl #0xFFFF,d0
+L805:
+       movel d0,a4@(94)
+       jra L802
+       .even
+L803:
+       moveq #-1,d1
+       movel d1,a4@(94)
+L802:
+       movel _UtilityBase,a6
+       movel #-2142480893,d0
+       moveq #-1,d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(12)
+       movel _UtilityBase,a6
+       movel #-2142480883,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a0
+       movel a0,a4@
+       jeq L815
+       movel #_ListGetItem,a4@(106)
+       movel #_ListGetNext,a4@(110)
+       movel #_ListGetPrev,a4@(114)
+       movel #_ListStringDrawItem,a4@(126)
+       bset #4,a4@(90)
+       moveq #-1,d4
+       cmpl a4@(12),d4
+       jne L824
+       clrl d0
+       movel a0@,a0
+       jra L904
+       .even
+L821:
+       addql #1,d0
+L904:
+       movel a0@,a0
+       tstl a0
+       jne L821
+       movel d0,a4@(12)
+       jra L824
+       .even
+L815:
+       movel _UtilityBase,a6
+       movel #-2142480882,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a0
+       movel d0,a4@
+       jeq L825
+       movel #_ArrayGetItem,a4@(106)
+       movel #_ArrayGetItem,a4@(110)
+       movel #_ArrayGetItem,a4@(114)
+       movel #_StringDrawItem,a4@(126)
+       moveq #-1,d1
+       cmpl a4@(12),d1
+       jne L824
+       clrl d1
+       tstl a0@
+       jeq L845
+       .even
+L829:
+       addql #1,d1
+       addql #4,a0
+       tstl a0@
+       jne L829
+       jra L845
+       .even
+L825:
+       movel _UtilityBase,a6
+       movel #-2142480881,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a0
+       movel a0,a4@
+       jeq L832
+       movel #_ListGetItem,a4@(106)
+       movel #_ListGetNext,a4@(110)
+       movel #_ListGetPrev,a4@(114)
+       movel #_ListImageDrawItem,a4@(126)
+       bset #4,a4@(90)
+       moveq #-1,d4
+       cmpl a4@(12),d4
+       jne L824
+       clrl d0
+       movel a0@,a0
+       jra L905
+       .even
+L838:
+       addql #1,d0
+L905:
+       movel a0@,a0
+       tstl a0
+       jne L838
+       movel d0,a4@(12)
+       jra L824
+       .even
+L832:
+       movel _UtilityBase,a6
+       movel #-2142480880,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a0
+       movel d0,a4@
+       jeq L824
+       movel #_ArrayGetItem,a4@(106)
+       movel #_ArrayGetItem,a4@(110)
+       movel #_ArrayGetItem,a4@(114)
+       movel #_ImageDrawItem,a4@(126)
+       moveq #-1,d1
+       cmpl a4@(12),d1
+       jne L824
+       clrl d1
+       tstl a0@
+       jeq L845
+       .even
+L846:
+       addql #1,d1
+       addql #4,a0
+       tstl a0@
+       jne L846
+L845:
+       movel d1,a4@(12)
+L824:
+       movel _UtilityBase,a6
+       movel #-2142480876,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(76)
+       movel _UtilityBase,a6
+       movel #-2142480865,d0
+       moveq #-1,d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(36)
+       clrl d0
+       movel a4@(90),d1
+       btst #3,d1
+       jeq L848
+       movel a4@(76),d2
+       jeq L849
+       movel a4@(12),d1
+       cmpl d0,d1
+       jle L848
+       movel d2,a2
+       movel d1,d2
+       negl d1
+       moveq #3,d4
+       andl d4,d1
+       jeq L852
+       cmpl d1,d4
+       jle L874
+       moveq #2,d4
+       cmpl d1,d4
+       jle L875
+       tstl a2@+
+       sne d0
+       moveq #1,d1
+       andl d1,d0
+       subql #1,d2
+L875:
+       tstl a2@+
+       jeq L881
+       addql #1,d0
+L881:
+       subql #1,d2
+L874:
+       tstl a2@+
+       jeq L884
+       addql #1,d0
+L884:
+       subql #1,d2
+       jeq L848
+       .even
+L852:
+       movel a2,a0
+       tstl a0@+
+       jeq L887
+       addql #1,d0
+L887:
+       lea a2@(8),a1
+       tstl a0@
+       jeq L890
+       addql #1,d0
+L890:
+       lea a2@(12),a0
+       tstl a1@
+       jeq L893
+       addql #1,d0
+L893:
+       lea a2@(16),a2
+       tstl a0@
+       jeq L896
+       addql #1,d0
+L896:
+       subql #4,d2
+       jne L852
+       jra L848
+       .even
+L849:
+       btst #28,d1
+       jeq L848
+       movel a4@,a0
+       tstl a0
+       jeq L848
+       movel a0@,a0
+       jra L906
+       .even
+L859:
+       addql #1,d0
+L906:
+       movel a0@,a0
+       tstl a0
+       jne L859
+L848:
+       movel d0,a4@(32)
+       movel _UtilityBase,a6
+       movel #-2142480878,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(16)
+       jeq L864
+       movel #-2147287033,sp@(32)
+       movel a4@(60),d0
+       addl a4@(64),d0
+       mulsl a4@(16),d0
+       movel d0,sp@(36)
+       clrl sp@(40)
+       movel sp@(32),sp@(44)
+       movel d0,sp@(48)
+       movel sp@(40),sp@(52)
+       movel _IntuitionBase,a6
+       movel d3,a0
+       lea sp@(44),a1
+#APP
+       jsr a6@(-0x288:W)
+#NO_APP
+L864:
+       movel #-2142480888,d2
+       movel _UtilityBase,a6
+       movel #-2142480894,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,d1
+       movel _UtilityBase,a6
+       movel d2,d0
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(4)
+       movel d0,a4@(40)
+       movel a4@(60),d1
+       addl a4@(64),d1
+       mulsl d0,d1
+       movel d1,a4@(20)
+       movel d1,a4@(44)
+       tstl a4@
+       jeq L865
+       movel #517,sp@(32)
+       movel d0,sp@(36)
+       movel a4@,sp@(40)
+       movel a4@(106),a3
+       lea sp@(32),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(8)
+L865:
+       movel _UtilityBase,a6
+       movel #-2142480850,d0
+       moveq #2,d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(72)
+       movel _UtilityBase,a6
+       movel #-2142480895,d0
+       moveq #-1,d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a4@(24)
+       movel d0,a4@(48)
+       moveq #-1,d4
+       cmpl d0,d4
+       jeq L867
+       movel #517,sp@(32)
+       movel d0,sp@(36)
+       movel a4@,sp@(40)
+       movel a4@(106),a3
+       lea sp@(32),a2
+       subl a1,a1
+       movel a4@(130),a0
+       jbsr a3@
+       movel d0,a4@(28)
+L867:
+       movel _UtilityBase,a6
+       movel #-2142480875,d0
+       clrl d1
+       movel a5@(4),a0
+#APP
+       jsr a6@(-0x24:W)
+#NO_APP
+       movel d0,a0
+       movel a0,a4@(130)
+       jeq L869
+       movel a0@(8),a4@(126)
+L869:
+       btst #1,a4@(93)
+       jeq L789
+       movel _GfxBase,a6
+#APP
+       jsr a6@(-0x204:W)
+#NO_APP
+       movel d0,a4@(138)
+L789:
+       movel d3,d0
+       moveml sp@+,#0x7c1c
+       lea sp@(28),sp
+       rts
+LC0:
+       .ascii "gadgetclass\0"
+       .even
+.globl _MakeListViewClass
+_MakeListViewClass:
+       movel a6,sp@-
+       movel a2,sp@-
+       movel _IntuitionBase,a6
+       subl a0,a0
+       lea LC0,a1
+       subl a2,a2
+       moveq #89,d0
+       notb d0
+       clrl d1
+#APP
+       jsr a6@(-0x2a6:W)
+#NO_APP
+       movel d0,a0
+       tstl a0
+       jeq L912
+       movel #_LVDispatcher,a0@(8)
+L912:
+       movel a0,d0
+       movel sp@+,a2
+       movel sp@+,a6
+       rts
+       .even
+.globl _FreeListViewClass
+_FreeListViewClass:
+       movel a6,sp@-
+       movel _IntuitionBase,a6
+#APP
+       jsr a6@(-0x2ca:W)
+#NO_APP
+       extl d0
+       movel sp@+,a6
+       rts
+       .even
+_LV_GMGoActive:
+       movel a2,sp@-
+       movel a0,a2
+       movel d0,a0
+       clrl d0
+       movew a2@(32),d0
+       tstl a1@(d0:l)
+       jeq L189
+       orw #128,a1@(12)
+       clrl d0
+       tstl a0@(8)
+       jeq L914
+       movel a0,d0
+       movel a2,a0
+       jbsr _LV_GMHandleInput
+       jra L914
+       .even
+L189:
+       moveq #2,d0
+L914:
+       movel sp@+,a2
+       rts
+       .even
+_LV_GMGoInactive:
+       clrl d0
+       movew a0@(32),d0
+       andl #1073741823,a1@(90,d0:l)
+       andw #65407,a1@(12)
+       rts
+       nop
+       .even
+_LV_OMGet:
+       moveml #0x2030,sp@-
+       movel a1,d1
+       movel d0,a1
+       clrl d0
+       movew a0@(32),d0
+       movel d1,a3
+       addl d0,a3
+       movel a1@(4),d0
+       addl #2142480895,d0
+       moveq #19,d2
+       cmpl d0,d2
+       jcs L785
+LI787:
+       movew pc@(L787-LI787-2:b,d0:l:2),d0
+       jmp pc@(2,d0:w)
+       .even
+L787:
+       .word L774-L787
+       .word L775-L787
+       .word L776-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L785-L787
+       .word L781-L787
+       .word L781-L787
+       .word L781-L787
+       .word L781-L787
+       .word L781-L787
+       .word L782-L787
+       .word L783-L787
+       .word L784-L787
+       .even
+L774:
+       movel a1@(8),a0
+       movel a3@(24),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L775:
+       movel a1@(8),a0
+       movel a3@(4),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L776:
+       movel a1@(8),a0
+       movel a3@(12),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L781:
+       movel a1@(8),a0
+       movel a3@,a0@
+       moveq #1,d0
+       jra L915
+       .even
+L782:
+       movel a1@(8),a0
+       movel a3@(16),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L783:
+       movel a1@(8),a0
+       movel a3@(28),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L784:
+       movel a1@(8),a0
+       movel a3@(76),a0@
+       moveq #1,d0
+       jra L915
+       .even
+L785:
+       movel a0@(24),a0
+       movel a0@(8),a3
+       movel d1,a2
+       jbsr a3@
+L915:
+       moveml sp@+,#0xc04
+       rts
+       .even
+_LV_OMDispose:
+       moveml #0x3032,sp@-
+       movel a0,a2
+       movel a1,d2
+       movel d0,d3
+       clrl d0
+       movew a2@(32),d0
+       movel d2,a3
+       addl d0,a3
+       movel a3@(138),d0
+       jeq L908
+       movel _GfxBase,a6
+       movel d0,a0
+#APP
+       jsr a6@(-0x216:W)
+#NO_APP
+L908:
+       btst #3,a3@(90)
+       jeq L909
+       movel _GfxBase,a6
+       movel a3@(134),a1
+#APP
+       jsr a6@(-0x4e:W)
+#NO_APP
+L909:
+       movel a2@(24),a0
+       movel a0@(8),a3
+       movel d3,a1
+       movel d2,a2
+       jbsr a3@
+       moveml sp@+,#0x4c0c
+       rts
diff --git a/gadgets/ListView/ListViewHooks.c b/gadgets/ListView/ListViewHooks.c
new file mode 100644 (file)
index 0000000..daa1aa0
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+**     $Id: ListViewHooks.c,v 1.3 2000/01/12 21:18:07 bernie Exp $
+**
+**     Copyright (C) 1996,97 Bernardo Innocenti
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     Internal drawing and browsing hooks the listview class
+*/
+
+#define USE_BUILTIN_MATH
+#define INTUI_V36_NAMES_ONLY
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H            /* Avoid dupe defs of boopsi funcs */
+
+#include <exec/types.h>
+#include <intuition/intuition.h>
+#include <intuition/intuitionbase.h>
+#include <graphics/gfxbase.h>
+#include <graphics/gfxmacros.h>
+
+#include <proto/intuition.h>
+#include <proto/graphics.h>
+
+#ifdef __STORM__
+       #pragma header
+#endif
+
+#define LV_GADTOOLS_STUFF
+#include <gadgets/ListViewClass.h>
+
+#include <CompilerSpecific.h>
+#include <DebugMacros.h>
+
+
+
+/* Definitions for builtin List hook */
+
+APTR HOOKCALL ListGetItem(
+       REG(a0, struct Hook                     *hook),
+       REG(a1, struct Node                     *node),
+       REG(a2, struct lvGetItem        *lvgi));
+APTR HOOKCALL ListGetNext(
+       REG(a0, struct Hook                     *hook),
+       REG(a1, struct Node                     *node),
+       REG(a2, struct lvGetNext        *lvgn));
+APTR HOOKCALL ListGetPrev(
+       REG(a0, struct Hook                     *hook),
+       REG(a1, struct Node                     *node),
+       REG(a2, struct lvGetPrev        *lvgp));
+ULONG HOOKCALL ListStringDrawItem(
+       REG(a0, struct Hook                     *hook),
+       REG(a1, struct Node                     *node),
+       REG(a2, struct lvDrawItem       *lvdi));
+ULONG HOOKCALL ListImageDrawItem(
+       REG(a0, struct Hook                     *hook),
+       REG(a1, struct Node                     *node),
+       REG(a2, struct lvDrawItem       *lvdi));
+
+
+/* Definitions for builtin Array hook */
+
+APTR HOOKCALL ArrayGetItem(
+       REG(a0, struct Hook                     *hook),
+       REG(a1, STRPTR                          *item),
+       REG(a2, struct lvGetItem        *lvgi));
+ULONG HOOKCALL StringDrawItem(
+       REG(a0, struct Hook                     *hook),
+       REG(a1, STRPTR                           str),
+       REG(a2, struct lvDrawItem       *lvdi));
+ULONG HOOKCALL ImageDrawItem(
+       REG(a0, struct Hook                     *hook),
+       REG(a1, struct Image            *img),
+       REG(a2, struct lvDrawItem       *lvdi));
+
+
+
+APTR HOOKCALL ListGetItem(
+       UNUSED(REG(a0, struct Hook *hook)),
+       REG(a1, struct Node *node),
+       REG(a2, struct lvGetItem *lvg))
+{
+       ULONG i;
+
+       ASSERT_VALID_PTR(lvg)
+
+       node = ((struct List *)(lvg->lvgi_Items))->lh_Head;
+
+       /* Warning: no sanity check is made against
+        * list being shorter than expected!
+        */
+       for (i = 0; i < lvg->lvgi_Number; i++)
+       {
+               ASSERT_VALID_PTR(node)
+               node = node->ln_Succ;
+       }
+
+       return (APTR)node;
+}
+
+
+
+APTR HOOKCALL ListGetNext(
+       UNUSED(REG(a0, struct Hook *hook)),
+       REG(a1, struct Node *node),
+       UNUSED(REG(a2, struct lvGetItem *lvg)))
+{
+       ASSERT_VALID_PTR(node)
+       ASSERT_VALID_PTR(lvg)
+
+       return (APTR)(node->ln_Succ->ln_Succ ? node->ln_Succ : NULL);
+}
+
+
+
+APTR HOOKCALL ListGetPrev(
+       UNUSED(REG(a0, struct Hook *hook)),
+       REG(a1, struct Node *node),
+       UNUSED(REG(a2, struct lvGetItem *lvg)))
+{
+       ASSERT_VALID_PTR(node)
+       ASSERT_VALID_PTR(lvg)
+
+       return (APTR)(node->ln_Pred->ln_Pred ? node->ln_Pred : NULL);
+}
+
+
+
+ULONG HOOKCALL ListStringDrawItem(
+       REG(a0, struct Hook *hook),
+       REG(a1, struct Node *node),
+       REG(a2, struct lvDrawItem *lvdi))
+{
+       ASSERT_VALID_PTR(node)
+       ASSERT_VALID_PTR(lvdi)
+
+       return StringDrawItem(hook, node->ln_Name, lvdi);
+}
+
+
+
+ULONG HOOKCALL ListImageDrawItem(
+       REG(a0, struct Hook *hook),
+       REG(a1, struct Node *node),
+       REG(a2, struct lvDrawItem *lvdi))
+{
+       ASSERT_VALID_PTR(node)
+       ASSERT_VALID_PTR(lvdi)
+
+       return ImageDrawItem(hook, (struct Image *)node->ln_Name, lvdi);
+}
+
+
+
+APTR HOOKCALL ArrayGetItem(
+       UNUSED(REG(a0, struct Hook *hook)),
+       UNUSED(REG(a1, STRPTR *item)),
+       REG(a2, struct lvGetItem *lvg))
+{
+       ASSERT_VALID_PTR(lvg)
+       ASSERT_VALID_PTR(lvg->lvgi_Items)
+
+       return (APTR)(((STRPTR *)lvg->lvgi_Items)[lvg->lvgi_Number]);
+}
+
+
+
+ULONG HOOKCALL StringDrawItem(
+       UNUSED(REG(a0, struct Hook *hook)),
+       REG(a1, STRPTR str),
+       REG(a2, struct lvDrawItem       *lvdi))
+{
+       struct RastPort *rp;
+       ULONG len;
+
+       ASSERT_VALID_PTR(lvdi)
+       rp = lvdi->lvdi_RastPort;
+       ASSERT_VALID_PTR(rp)
+       ASSERT_VALID_PTR_OR_NULL(str)
+
+       if (!str)
+               /* Move to the leftmost pixel of the rectangle
+                * to have the following RectFill() clear all the line
+                */
+               Move(rp, lvdi->lvdi_Bounds.MinX, 0);
+       else
+       {
+               struct TextExtent textent;
+
+               if (lvdi->lvdi_State == LVR_NORMAL)
+               {
+                       SetABPenDrMd(rp, lvdi->lvdi_DrawInfo->dri_Pens[TEXTPEN],
+                               lvdi->lvdi_DrawInfo->dri_Pens[BACKGROUNDPEN],
+                               JAM2);
+               }
+               else
+               {
+                       SetABPenDrMd(rp, lvdi->lvdi_DrawInfo->dri_Pens[FILLTEXTPEN],
+                               lvdi->lvdi_DrawInfo->dri_Pens[FILLPEN],
+                               JAM2);
+               }
+
+               Move(rp, lvdi->lvdi_Bounds.MinX, lvdi->lvdi_Bounds.MinY + rp->Font->tf_Baseline);
+
+               len = strlen(str);
+
+               if (!(lvdi->lvdi_Flags & LVF_CLIPPED))
+               {
+                       /* Calculate how much text will fit in the listview width */
+                       len = TextFit(rp, str, len, &textent, NULL, 1,
+                               lvdi->lvdi_Bounds.MaxX - lvdi->lvdi_Bounds.MinX + 1,
+                               lvdi->lvdi_Bounds.MaxY - lvdi->lvdi_Bounds.MinY + 1);
+               }
+
+               Text(rp, str, len);
+
+               /* Text() will move the pen X position to
+                * lvdi->lvdi_Bounds.MinX + textent.te_Width.
+                */
+       }
+
+       /* Now clear the rest of the row. rp->cp_x is updated by Text() to the
+        * next character to print.
+        */
+       SetAPen(rp, lvdi->lvdi_DrawInfo->dri_Pens[(lvdi->lvdi_State == LVR_NORMAL) ?
+               BACKGROUNDPEN : FILLPEN]);
+       RectFill(rp, rp->cp_x,
+               lvdi->lvdi_Bounds.MinY,
+               lvdi->lvdi_Bounds.MaxX,
+               lvdi->lvdi_Bounds.MaxY);
+
+
+       return LVCB_OK;
+}
+
+
+
+ULONG HOOKCALL ImageDrawItem(
+       UNUSED(REG(a0, struct Hook *hook)),
+       REG(a1, struct Image *img),
+       REG(a2, struct lvDrawItem *lvdi))
+{
+       struct RastPort *rp;
+       UWORD left;
+
+       ASSERT_VALID_PTR_OR_NULL(img)
+       ASSERT_VALID_PTR(lvdi)
+       rp = lvdi->lvdi_RastPort;
+       ASSERT_VALID_PTR(rp)
+
+       if (!img)
+               /* Move to the leftmost pixel of the item rectangle
+                * to have the following RectFill() clear all the line
+                */
+               left = lvdi->lvdi_Bounds.MinX;
+       else
+       {
+               DrawImageState(rp, img,
+                       lvdi->lvdi_Bounds.MinX, lvdi->lvdi_Bounds.MinY,
+                       lvdi->lvdi_State, lvdi->lvdi_DrawInfo);
+
+               left = lvdi->lvdi_Bounds.MinX + img->Width;
+       }
+
+       /* Now clear the rest of the row. rp->cp_x is updated by Text() to the
+        * next character to print.
+        */
+       SetAPen(rp, lvdi->lvdi_DrawInfo->dri_Pens[(lvdi->lvdi_State == LVR_NORMAL) ?
+               BACKGROUNDPEN : FILLPEN]);
+       RectFill(rp, left,
+               lvdi->lvdi_Bounds.MinY,
+               lvdi->lvdi_Bounds.MaxX,
+               lvdi->lvdi_Bounds.MaxY);
+
+       return LVCB_OK;
+}
diff --git a/gadgets/ListView/Makefile b/gadgets/ListView/Makefile
new file mode 100644 (file)
index 0000000..261ec59
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# $Id: Makefile,v 1.1 2000/01/12 21:16:52 bernie Exp $
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+TOP := ../..
+
+include $(TOP)/config.mk
+
+#
+# Class specific information
+#
+CLASSLIB       := listview.gadget
+CLASSSRC       := ListViewClass.c ListViewHooks.c
+CLASSOBJ       := $(TOP)/common/GetGadgetBox.o
+DEMOSRC                := LVDemo.c
+DEMOOBJ                := ../ScrollButton/ScrollButtonClass_static.o
+DEMOPROG       := ListViewDemo
+NOSTDLIB       := 1
+INSTALLDIR     := gadgets
+
+#
+# Class version information
+#
+CLASSVER       := 1
+CLASSREV       := 7
+CLASSDATE      := (22.8.99)
+
+include $(TOP)/common/general.mk
diff --git a/gadgets/Makefile b/gadgets/Makefile
new file mode 100644 (file)
index 0000000..28730bc
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# $Id: Makefile,v 1.1 2000/01/12 20:48:56 bernie Exp $
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+TOP := ..
+SUBDIRS := SmartGroup ScrollButton SliderBar ListView PIPWin
+# not yet: ResizeGClass
+
+include $(TOP)/common/general.mk
diff --git a/gadgets/MeterGClass/Makefile b/gadgets/MeterGClass/Makefile
new file mode 100644 (file)
index 0000000..eb79630
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(BOOPSITOP)/config.mk
+include config.mk
+
+ARG_COMMON :=
+ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o
+ARG_LIB := $(ARG_COMMON)
+ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV)
+ARG_PRIVATE := $(ARG_COMMON)
+ARG_OBJ := $(ARG_COMMON)
+
+DEP_COMMON :=
+DEP_ALL := $(DEP_COMMON) OpenClass.o
+DEP_LIB := $(DEP_COMMON)
+DEP_DEBUG := $(DEP_COMMON) OpenClass.o
+DEP_PRIVATE := $(DEP_COMMON)
+DEP_OBJ := $(DEP_COMMON)
+
+include $(BOOPSITOP)/common/general.mk
+
+OpenClass.o: OpenClass.c
+       $(MAKE) -C $(BOOPSITOP)/common/ $@
diff --git a/gadgets/PIPWin/GNUmakefile.nothanks b/gadgets/PIPWin/GNUmakefile.nothanks
new file mode 100644 (file)
index 0000000..4908f95
--- /dev/null
@@ -0,0 +1,58 @@
+##
+##     $VER: PIPWin_Makefile 2.6 (19.10.98)
+##
+##     Copyright (C) 1996,97 by Bernardo Innocenti
+##
+##     Makefile for gcc
+##
+
+# Name of the final executable
+#
+PROJ = PIPWin
+
+# Object files in this project
+#
+OBJS = startup_gcc.o PIPWin.o PIPClass.o
+
+# C compiler name
+#
+CC = gcc
+
+# Make the project
+#
+all: $(PROJ)
+
+# Remove all targets and intermediate files
+#
+clean:
+       -Delete $(PROJ) $(OBJS)
+
+
+###########################################################
+# gcc release version should be compiled with these flags
+#
+# NOTE: compiling with -fbaserel is currently not
+#       possible because of the well known gcc/egcs
+#              "register spilled" problem.
+#
+CFLAGS = -c -O3 -finline-functions -fno-implement-inlines \
+ -fomit-frame-pointer -fstrength-reduce \
+ -msmall-code -mregparm -I/gg/include -I/include \
+ -Wunused -Wreturn-type -D$(OSVER)
+LFLAGS = -s
+LIBS = -noixemul -nostdlib
+
+
+###########################################################
+# gcc - Make the executable
+###########################################################
+#
+startup_gcc.o: startup_gcc.s
+       $(AS) startup_gcc.s -o startup_gcc.o
+
+.c.o: VectorGlyphIClass.h
+       $(CC) $(*).c $(CFLAGS)
+
+$(PROJ): $(OBJS)
+       $(CC) $(OBJS) -o $(PROJ) $(LFLAGS) $(LIBS)
+       @Protect $(PROJ) +e
diff --git a/gadgets/PIPWin/Makefile b/gadgets/PIPWin/Makefile
new file mode 100644 (file)
index 0000000..1086b1d
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+TOP := ../..
+include $(TOP)/config.mk
+
+#
+# Class specific information
+#
+#CLASSLIB      := pip.gadget
+CLASSSRC       := PIPClass.c
+CLASSOBJ       := $(TOP)/common/GetGadgetBox.o
+DEMOSRC                := PIPWin.c
+NOSTDLIB       := 1
+INSTALLDIR     := gadgets
+
+#
+# Class version information
+#
+CLASSVER       := 1
+CLASSREV       := 7
+CLASSDATE      := (25.12.99)
+
+include $(TOP)/common/general.mk
diff --git a/gadgets/PIPWin/PIPClass.c b/gadgets/PIPWin/PIPClass.c
new file mode 100644 (file)
index 0000000..1f83803
--- /dev/null
@@ -0,0 +1,677 @@
+/*
+**     PIPClass.c
+**
+**     Copyright (C) 1996,97 Bernardo Innocenti
+**
+**     Picture In Picture gadget class
+*/
+
+#define INTUI_V36_NAMES_ONLY
+
+#include <exec/types.h>
+#include <exec/libraries.h>
+#include <intuition/intuition.h>
+#include <intuition/intuitionbase.h>
+#include <intuition/screens.h>
+#include <intuition/classes.h>
+#include <intuition/gadgetclass.h>
+
+#include <proto/intuition.h>
+#include <proto/graphics.h>
+#include <proto/utility.h>
+
+#include <CompilerSpecific.h>
+#include <DebugMacros.h>
+#include <BoopsiStubs.h>
+
+#include "PIPClass.h"
+
+
+
+/* PIP gadget private instance data */
+
+struct PIPData
+{
+       struct Screen   *Scr;                   /* Snoop this screen...                         */
+       struct BitMap   *BitMap;                /* ...or this BitMap                            */
+       WORD                    Width,  Height; /* Size of snooped object                       */
+       WORD                    OffX,   OffY;   /* Current XY offset of the view        */
+       WORD                    StartX, StartY; /* Start coords for mouse dragging      */
+       WORD                    Dragging;               /* TRUE if dragging with mouse          */
+       WORD                    Dummy;                  /* Keep data longword aligned           */
+       struct IBox             GBox;                   /* Real gadget size                                     */
+};
+
+
+
+/* Local function prototypes */
+
+static void            PIP_GMRender            (Class *cl, struct Gadget *g, struct gpRender *msg);
+static ULONG   PIP_GMHandleInput       (Class *cl, struct Gadget *g, struct gpInput *msg);
+static void            PIP_GMGoInactive        (Class *cl, struct Gadget *g, struct gpGoInactive *msg);
+static void            PIP_GMLayout            (Class *cl, struct Gadget *g, struct gpLayout *msg);
+static ULONG   PIP_OMNew                       (Class *cl, struct Gadget *g, struct opSet *msg);
+static ULONG   PIP_OMSet                       (Class *cl, struct Gadget *g, struct opUpdate *msg);
+static ULONG   PIP_OMGet                       (Class *cl, struct Gadget *g, struct opGet *msg);
+static ULONG   PIP_PIPMRefresh         (Class *cl, struct Gadget *g, struct pippRefresh *msg);
+static void            RestrictXY                      (struct PIPData *pip);
+static void            GetGadgetBox            (struct GadgetInfo *ginfo, struct Gadget *g, struct IBox *rect);
+
+
+
+static ULONG HOOKCALL PIPDispatcher(
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, Msg msg))
+{
+       switch (msg->MethodID)
+       {
+               case GM_RENDER:
+                       PIP_GMRender(cl, g, (struct gpRender *)msg);
+                       return TRUE;
+
+               case GM_GOACTIVE:
+               case GM_HANDLEINPUT:
+                       return PIP_GMHandleInput(cl, g, (struct gpInput *)msg);
+
+               case GM_GOINACTIVE:
+                       PIP_GMGoInactive(cl, g, (struct gpGoInactive *)msg);
+                       return TRUE;
+
+               case GM_LAYOUT:
+                       /* This method is only supported on V39 and above */
+                       PIP_GMLayout(cl, g, (struct gpLayout *)msg);
+                       return TRUE;
+
+               case OM_NEW:
+                       return PIP_OMNew(cl, g, (struct opSet *)msg);
+
+               /* We don't need to override OM_DISPOSE */
+
+               case OM_SET:
+               case OM_UPDATE:
+                       return PIP_OMSet(cl, g, (struct opUpdate *)msg);
+
+               case OM_GET:
+                       return PIP_OMGet(cl, g, (struct opGet *)msg);
+
+               case PIPM_REFRESH:
+                       return PIP_PIPMRefresh(cl, g, (struct pippRefresh *)msg);
+
+               default:
+                       /* Unsupported method: let our superclass's
+                        * dispatcher take a look at it.
+                        */
+                       return DoSuperMethodA(cl, (Object *)g, msg);
+       }
+}
+
+
+
+static void PIP_GMRender(Class *cl, struct Gadget *g, struct gpRender *msg)
+{
+       struct PIPData  *pip = INST_DATA(cl, g);
+       struct BitMap   *bitmap;
+
+
+       if (pip->Scr)
+               bitmap = pip->Scr->RastPort.BitMap;     /* Get screen bitmap */
+       else if (pip->BitMap)
+               bitmap = pip->BitMap;                           /* Use provided bitmap */
+       else
+               bitmap = NULL;                                          /* Do nothing otherwise */
+
+
+       switch (msg->gpr_Redraw)
+       {
+               case GREDRAW_REDRAW:
+
+                       if (!bitmap || (bitmap->Depth < msg->gpr_RPort->BitMap->Depth))
+                       {
+                               /* Clearing all our visible area is needed because
+                                * BltBitMapRastPort() will not clear the bitplanes beyond
+                                * the last bitplane in the source bitmap.
+                                *
+                                * NOTE: The pen number really needs to be 0, not BACKGROUNDPEN!
+                                */
+                               SetAPen(msg->gpr_RPort, 0);
+                               RectFill(msg->gpr_RPort,
+                                       pip->GBox.Left, pip->GBox.Top,
+                                       pip->GBox.Left + pip->GBox.Width, pip->GBox.Top + pip->GBox.Height);
+                       }
+
+                       /* NOTE: I'm falling through here! */
+
+               case GREDRAW_UPDATE:
+
+                       if (bitmap)
+                       {
+                               /* Scaling, remapping and other similar features could be added here */
+
+                               /* Update gadget display */
+                               BltBitMapRastPort(bitmap, pip->OffX, pip->OffY,
+                                       msg->gpr_RPort, pip->GBox.Left, pip->GBox.Top,
+                                       min (pip->GBox.Width, pip->Width), min (pip->GBox.Height, pip->Height),
+                                       0x0C0);
+                       }
+                       /* NOTE: I'm falling through here! */
+
+               default:
+                       break;
+       }
+}
+
+
+
+static ULONG PIP_GMHandleInput(Class *cl, struct Gadget *g, struct gpInput *msg)
+{
+       struct PIPData          *pip = INST_DATA (cl, g);
+       struct InputEvent       *ie = msg->gpi_IEvent;
+
+
+       /* Handle GM_GOACTIVE */
+       if (msg->MethodID == GM_GOACTIVE)
+       {
+               if (!pip->Scr && !pip->BitMap)
+                       return GMR_NOREUSE;
+
+               g->Flags |= GFLG_SELECTED;
+
+               /* Do not process InputEvent when the gadget has been
+                * activated by ActivateGadget().
+                */
+               if (!ie)
+                       return GMR_MEACTIVE;
+
+               /* Note: The input event that triggered the gadget
+                * activation (usually a mouse click) should be passed
+                * to the GM_HANDLEINPUT method, so we fall down to it.
+                */
+       }
+
+       /* Handle GM_HANDLEINPUT */
+       switch (ie->ie_Class)
+       {
+               case IECLASS_RAWMOUSE:
+               {
+                       switch (ie->ie_Code)
+                       {
+                               case MENUDOWN:
+                                       /* Deactivate gadget on menu button press */
+                                       return GMR_REUSE;
+
+                               case SELECTDOWN:
+
+                                       /* Check click outside gadget box */
+
+                                       if ((msg->gpi_Mouse.X < 0) ||
+                                               (msg->gpi_Mouse.X >= pip->GBox.Width) ||
+                                               (msg->gpi_Mouse.Y < 0) ||
+                                               (msg->gpi_Mouse.Y >= pip->GBox.Height))
+                                               return GMR_REUSE;
+
+                                       /* Store current mouse coordinates for mouse dragging */
+                                       pip->StartX = pip->OffX + msg->gpi_Mouse.X;
+                                       pip->StartY = pip->OffY + msg->gpi_Mouse.Y;
+                                       pip->Dragging = TRUE;
+
+                                       break;
+
+                               case SELECTUP:
+
+                                       /* Stop mouse dragging mode */
+                                       pip->Dragging = FALSE;
+
+                                       /* Send one final notification to our targets */
+                                       UpdateAttrs((Object *)g, msg->gpi_GInfo, 0,
+                                               PIPA_OffX,                      pip->StartX - msg->gpi_Mouse.X,
+                                               PIPA_OffY,                      pip->StartY - msg->gpi_Mouse.Y,
+                                               TAG_DONE);
+
+                                       break;
+
+
+                               default: /* Mouse just moved */
+
+                                       /* Call our OM_UPDATE method to change the object attributes.
+                                        * This will also send notification to targets and
+                                        * update the contents of the gadget.
+                                        */
+                                       if (pip->Dragging)
+                                               UpdateAttrs((Object *)g, msg->gpi_GInfo, OPUF_INTERIM,
+                                                       PIPA_OffX,                      pip->StartX - msg->gpi_Mouse.X,
+                                                       PIPA_OffY,                      pip->StartY - msg->gpi_Mouse.Y,
+                                                       GA_ID,                          g->GadgetID,
+                                                       TAG_DONE);
+                       }
+                       return GMR_MEACTIVE;
+               }
+
+               case IECLASS_RAWKEY:
+               {
+                       LONG tags[3];
+                       WORD pos;
+
+                       switch (ie->ie_Code)
+                       {
+                               case CURSORUP:
+                                       if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
+                                               pos = 0;
+                                       else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
+                                               pos = pip->OffY - pip->GBox.Height + 1;
+                                       else if (ie->ie_Qualifier & IEQUALIFIER_CONTROL)
+                                               pos = pip->OffY - 8;
+                                       else
+                                               pos = pip->OffY - 1;
+
+
+                                       tags[0] = PIPA_OffY;
+                                       tags[1] = pos;
+                                       tags[2] = TAG_DONE;
+                                       break;
+
+                               case CURSORDOWN:
+                                       if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
+                                               pos = pip->Height - pip->GBox.Height;
+                                       else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
+                                               pos = pip->OffY + pip->GBox.Height - 1;
+                                       else if (ie->ie_Qualifier & IEQUALIFIER_CONTROL)
+                                               pos = pip->OffY + 8;
+                                       else
+                                               pos = pip->OffY + 1;
+
+                                       tags[0] = PIPA_OffY;
+                                       tags[1] = pos;
+                                       tags[2] = TAG_DONE;
+                                       break;
+
+                               case CURSORLEFT:
+                                       if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
+                                               pos = 0;
+                                       else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
+                                               pos = pip->OffX - pip->GBox.Width + 1;
+                                       else if (ie->ie_Qualifier & IEQUALIFIER_CONTROL)
+                                               pos = pip->OffX - 8;
+                                       else
+                                               pos = pip->OffX - 1;
+
+                                       tags[0] = PIPA_OffX;
+                                       tags[1] = pos;
+                                       tags[2] = TAG_DONE;
+                                       break;
+
+                               case CURSORRIGHT:
+                                       if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
+                                               pos = pip->Width - pip->GBox.Width;
+                                       else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
+                                               pos = pip->OffX + pip->GBox.Height - 1;
+                                       else if (ie->ie_Qualifier & IEQUALIFIER_CONTROL)
+                                               pos = pip->OffX + 8;
+                                       else
+                                               pos = pip->OffX + 1;
+
+                                       tags[0] = PIPA_OffX;
+                                       tags[1] = pos;
+                                       tags[2] = TAG_DONE;
+                                       break;
+
+                               default:
+                                       tags[0] = TAG_DONE;
+                       }
+
+                       if (tags[0] != TAG_DONE)
+                               DoMethod((Object *)g, OM_UPDATE, tags, msg->gpi_GInfo, OPUF_INTERIM);
+
+                       return GMR_MEACTIVE;
+               }
+
+               default:
+                       return GMR_MEACTIVE;
+       }
+}
+
+
+
+static void PIP_GMGoInactive(Class *cl, struct Gadget *g, struct gpGoInactive *msg)
+{
+       struct PIPData *pip = INST_DATA (cl, g);
+
+       pip->Dragging = FALSE;
+       g->Flags &= ~GFLG_SELECTED;
+}
+
+
+
+static void PIP_GMLayout(Class *cl, struct Gadget *g, struct gpLayout *msg)
+{
+       struct PIPData *pip = INST_DATA(cl, g);
+
+       GetGadgetBox(msg->gpl_GInfo, g, &pip->GBox);
+       RestrictXY(pip);
+
+       /* Notify our targets about it */
+       NotifyAttrs((Object *)g, msg->gpl_GInfo, 0,
+               PIPA_OffX,                      pip->OffX,
+               PIPA_OffY,                      pip->OffY,
+               PIPA_Width,                     pip->Width,
+               PIPA_Height,            pip->Height,
+               PIPA_DisplayWidth,      pip->GBox.Width,
+               PIPA_DisplayHeight,     pip->GBox.Height,
+               GA_ID,                          g->GadgetID,
+               TAG_DONE);
+}
+
+
+
+static ULONG PIP_OMNew(Class *cl, struct Gadget *g, struct opSet *msg)
+{
+       ULONG result;
+
+       if (result = DoSuperMethodA(cl, (Object *)g, (Msg)msg))
+       {
+               struct PIPData *pip = (struct PIPData *) INST_DATA(cl, (Object *)result);
+
+               /* Read creation time attributes */
+               pip->Scr        = (struct Screen *) GetTagData(PIPA_Screen,     NULL,   msg->ops_AttrList);
+               pip->BitMap     = (struct BitMap *) GetTagData(PIPA_BitMap,     NULL,   msg->ops_AttrList);
+               pip->OffX       = (WORD)                        GetTagData(PIPA_OffX,   0,              msg->ops_AttrList);
+               pip->OffY       = (WORD)                        GetTagData(PIPA_OffY,   0,              msg->ops_AttrList);
+               pip->Dragging = FALSE;
+       }
+       return result;
+}
+
+
+
+static ULONG PIP_OMSet(Class *cl, struct Gadget *g, struct opUpdate *msg)
+{
+       struct PIPData  *pip = (struct PIPData *) INST_DATA(cl, g);
+       struct TagItem  *ti,
+                                       *tstate = msg->opu_AttrList;
+       ULONG   result = FALSE;
+       BOOL    do_super_method = FALSE,
+                       render                  = FALSE,
+                       notify                  = FALSE;
+
+       while (ti = NextTagItem(&tstate))
+               switch (ti->ti_Tag)
+               {
+                       case PIPA_Screen:
+                               pip->BitMap     = NULL;
+
+                               if (pip->Scr = (struct Screen *)ti->ti_Data)
+                               {
+                                       pip->Width      = pip->Scr->Width;
+                                       pip->Height     = pip->Scr->Height;
+                               }
+                               else
+                                       pip->Width = pip->Height = 0;
+
+                               RestrictXY(pip);
+
+                               break;
+
+                       case PIPA_BitMap:
+                               pip->Scr = NULL;
+                               if (pip->BitMap = (struct BitMap *)ti->ti_Data)
+                               {
+                                       pip->Width      = pip->BitMap->BytesPerRow << 3;
+                                       pip->Height     = pip->BitMap->Rows;
+                               }
+                               else
+                                       pip->Width = pip->Height = 0;
+
+                               RestrictXY(pip);
+
+                               render = TRUE;
+                               notify = TRUE;
+
+                               break;
+
+                       case PIPA_OffX:
+                               if (pip->OffX != ti->ti_Data)
+                               {
+                                       WORD newx = (WORD)ti->ti_Data;
+
+                                       /* Restrict offset to valid limits */
+                                       if (newx + pip->GBox.Width > pip->Width)
+                                               newx = pip->Width - pip->GBox.Width;
+                                       if (newx < 0)
+                                               newx = 0;
+
+                                       if (newx != pip->OffX)
+                                       {
+                                               pip->OffX = newx;
+                                               render = TRUE;
+                                               notify = TRUE;
+                                       }
+                               }
+                               break;
+
+                       case PIPA_OffY:
+                               if (pip->OffY != ti->ti_Data)
+                               {
+                                       WORD newy = (WORD)ti->ti_Data;
+
+                                       /* Restrict offset to valid limits */
+                                       if (newy + pip->GBox.Height > pip->Height)
+                                               newy = pip->Height - pip->GBox.Height;
+                                       if (newy < 0)
+                                               newy = 0;
+
+                                       if (newy != pip->OffY)
+                                       {
+                                               pip->OffY = newy;
+                                               render = TRUE;
+                                               notify = TRUE;
+                                       }
+                               }
+                               break;
+
+                       case PIPA_MoveUp:
+                               if (pip->OffY)
+                               {
+                                       if (pip->OffY > 8)
+                                               pip->OffY -= 8;
+                                       else
+                                               pip->OffY = 0;
+
+                                       render = TRUE;
+                                       notify = TRUE;
+                               }
+                               break;
+
+                       case PIPA_MoveDown:
+                               if (pip->OffY < pip->Height - pip->GBox.Height)
+                               {
+                                       if (pip->OffY + pip->GBox.Height < pip->Height - 8)
+                                               pip->OffY += 8;
+                                       else
+                                               pip->OffY = pip->Height - pip->GBox.Height;
+
+                                       render = TRUE;
+                                       notify = TRUE;
+                               }
+                               break;
+
+                       case PIPA_MoveLeft:
+                               if (pip->OffX)
+                               {
+                                       if (pip->OffX > 8)
+                                               pip->OffX -= 8;
+                                       else
+                                               pip->OffX = 0;
+
+                                       render = TRUE;
+                                       notify = TRUE;
+                               }
+                               break;
+
+                       case PIPA_MoveRight:
+                               if (pip->OffX < pip->Width - pip->GBox.Width)
+                               {
+                                       if (pip->OffX + pip->GBox.Width < pip->Width - 8)
+                                               pip->OffX += 8;
+                                       else
+                                               pip->OffX = pip->Width - pip->GBox.Width;
+
+                                       render = TRUE;
+                                       notify = TRUE;
+                               }
+                               break;
+
+                       default:
+                               /* This little optimization avoids forwarding the
+                                * OM_SET method to our superclass when there are
+                                * no unknown tags.
+                                */
+                               do_super_method = TRUE;
+                               break;
+               }
+
+
+       /* Forward method to our superclass dispatcher, only when needed */
+
+       if (do_super_method)
+               result = (DoSuperMethodA(cl, (Object *)g, (Msg) msg));
+
+
+       /* Update gadget imagery, only when needed */
+
+       if (render && msg->opu_GInfo)
+       {
+               struct RastPort *rp;
+
+               if (rp = ObtainGIRPort(msg->opu_GInfo))
+               {
+                       DoMethod((Object *)g,
+                               GM_RENDER, msg->opu_GInfo, rp, GREDRAW_UPDATE);
+                       ReleaseGIRPort(rp);
+                       result = TRUE;
+               }
+       }
+
+
+       /* Notify our targets about all changed attributes, only when needed */
+
+       if (notify)
+               NotifyAttrs((Object *)g, msg->opu_GInfo,
+                       (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0,
+                       PIPA_OffX,                      pip->OffX,
+                       PIPA_OffY,                      pip->OffY,
+                       GA_ID,                          g->GadgetID,
+                       TAG_DONE);
+
+       return result;
+}
+
+
+
+static ULONG PIP_OMGet(Class *cl, struct Gadget *g, struct opGet *msg)
+{
+       struct PIPData *pip = INST_DATA (cl, g);
+
+       switch (msg->opg_AttrID)
+       {
+               case PIPA_Screen:
+                       *(msg->opg_Storage) = (ULONG) pip->Scr;
+                       return TRUE;
+
+               case PIPA_BitMap:
+                       *(msg->opg_Storage) = (ULONG) pip->BitMap;
+                       return TRUE;
+
+               case PIPA_OffX:
+                       *(msg->opg_Storage) = (ULONG) pip->OffX;
+                       return TRUE;
+
+               case PIPA_OffY:
+                       *(msg->opg_Storage) = (ULONG) pip->OffY;
+                       return TRUE;
+
+               case PIPA_Width:
+                       *(msg->opg_Storage) = (ULONG) pip->Width;
+                       return TRUE;
+
+               case PIPA_Height:
+                       *(msg->opg_Storage) = (ULONG) pip->Height;
+                       return TRUE;
+
+               default:
+                       return DoSuperMethodA(cl, (Object *)g, (Msg) msg);
+       }
+}
+
+
+
+static ULONG PIP_PIPMRefresh(Class *cl, struct Gadget *g, struct pippRefresh *msg)
+{
+       struct RastPort *rp;
+
+       if (msg->pipp_GInfo && (rp = ObtainGIRPort(msg->pipp_GInfo)))
+       {
+               /* Call our GM_RENDER method */
+
+               DoMethod((Object *)g, GM_RENDER, msg->pipp_GInfo, rp, GREDRAW_UPDATE);
+               ReleaseGIRPort(rp);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+
+static void RestrictXY(struct PIPData *pip)
+
+/* Restrict XOff and YOff inside bitmap limits */
+{
+       if (pip->OffY + pip->GBox.Height > pip->Height)
+               pip->OffY = pip->Height - pip->GBox.Height;
+       if (pip->OffY < 0) pip->OffY = 0;
+
+       if (pip->OffX + pip->GBox.Width > pip->Width)
+               pip->OffX = pip->Width - pip->GBox.Width;
+       if (pip->OffX < 0) pip->OffX = 0;
+}
+
+
+
+static void GetGadgetBox(struct GadgetInfo *ginfo, struct Gadget *g, struct IBox *rect)
+
+/* This function gets the actual IBox where a gadget exists
+ * in a window.  The special cases it handles are all the REL#?
+ * (relative positioning flags).
+ */
+{
+       rect->Left = g->LeftEdge;
+       if (g->Flags & GFLG_RELRIGHT) rect->Left += ginfo->gi_Domain.Width - 1;
+
+       rect->Top = g->TopEdge;
+       if (g->Flags & GFLG_RELBOTTOM) rect->Top += ginfo->gi_Domain.Height - 1;
+
+       rect->Width = g->Width;
+       if (g->Flags & GFLG_RELWIDTH) rect->Width += ginfo->gi_Domain.Width;
+
+       rect->Height = g->Height;
+       if (g->Flags & GFLG_RELHEIGHT) rect->Height += ginfo->gi_Domain.Height;
+}
+
+
+
+Class *MakePIPClass(void)
+{
+       Class *PIPClass;
+
+       if (PIPClass = MakeClass(NULL, GADGETCLASS, NULL, sizeof (struct PIPData), 0))
+               PIPClass->cl_Dispatcher.h_Entry = (ULONG (*)()) PIPDispatcher;
+
+       return PIPClass;
+}
+
+
+
+void FreePIPClass(Class *PIPClass)
+{
+       FreeClass(PIPClass);
+}
diff --git a/gadgets/PIPWin/PIPClass.h b/gadgets/PIPWin/PIPClass.h
new file mode 100644 (file)
index 0000000..dea71c0
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef PIPCLASS_H
+#define PIPCLASS_H
+/*
+**     PIPClass.h
+**
+**     Copyright (C) 1996,97 by Bernardo Innocenti
+**
+**     'Picture In Picture' class built on top of the "gadgetclass".
+**
+*/
+
+#define PIPCLASS       "pipclass"
+#define PIPVERS                1
+
+
+Class  *MakePIPClass (void);
+void    FreePIPClass (Class *PIPClass);
+
+
+
+/********************/
+/* Class Attributes */
+/********************/
+
+#define PIP_Dummy                      (TAG_USER | ('P'<<16) | ('I'<< 8))
+
+#define PIPA_Screen                    (PIP_Dummy+1)
+       /* (IGS) Screen to capture data from
+        */
+
+#define PIPA_BitMap                    (PIP_Dummy+2)
+       /* (IGS) BitMap to capture data from
+        */
+
+#define PIPA_OffX                      (PIP_Dummy+3)
+#define PIPA_OffY                      (PIP_Dummy+4)
+       /* (IGSNU) Offsett of the PIP view
+        */
+
+#define PIPA_Width                     (PIP_Dummy+5)
+#define PIPA_Height                    (PIP_Dummy+6)
+       /* (GN) Dimensions of the bitmap being captured.
+        */
+
+#define PIPA_DisplayWidth              (PIP_Dummy+7)
+#define PIPA_DisplayHeight             (PIP_Dummy+8)
+       /* (GN) Dimensions of the PIP display.
+        */
+
+#define PIPA_MoveUp                    (PIP_Dummy+9)
+#define PIPA_MoveDown          (PIP_Dummy+10)
+#define PIPA_MoveLeft          (PIP_Dummy+11)
+#define PIPA_MoveRight         (PIP_Dummy+12)
+       /* (S) Scroll the display towads a direction
+        */
+
+
+/*****************/
+/* Class Methods */
+/*****************/
+
+#define PIPM_REFRESH           (PIP_Dummy+1)
+/*
+ * Tell the object to update its imagery to reflect any changes
+ * in the attached Screen or BitMap.
+ */
+
+struct pippRefresh
+{
+       ULONG   MethodID;
+       struct GadgetInfo       *pipp_GInfo;
+};
+
+#endif /* !PIPCLASS_H */
diff --git a/gadgets/PIPWin/PIPWin.c b/gadgets/PIPWin/PIPWin.c
new file mode 100644 (file)
index 0000000..59cc01a
--- /dev/null
@@ -0,0 +1,1015 @@
+/*
+**     $Id: PIPWin.c,v 1.2 2000/01/12 21:01:01 bernie Exp $
+**
+**     Use 4 chars wide TABs to read this file.
+**
+**
+**     Introduction
+**     ============
+**
+**     This program opens a window showing the contents of a user selected
+**     public screen. The PIP view can be scrolled around by dragging it
+**     with mouse or using the cursor keys.
+**
+**     The source code shows how to create a resizable window with sliders
+**     and how to write a custom `boopsi' class on top of the gadgetclass.
+**
+**
+**     Usage
+**     =====
+**
+**     PipWin SCREEN,PUB/K,DELAY/K,LEFT/K,TOP/K,WIDTH/K,HEIGHT/K
+**
+**     SCREEN
+**             the name of the public screen to monitorize
+**
+**     PUBSCREEN
+**             name of the public screen where the window should open
+**
+**     DELAY
+**             delay between window refreshes, in tenth of seconds (default: 20)
+**
+**     LEFT, TOP, WIDTH, HEIGHT
+**             window geometry (in pixels)
+**
+**
+**     Compiling
+**     =========
+**
+**     This project can be compiled with:
+**             - SAS/C (version 6.58 or newer)
+**             - gcc (version 2.7.2.1 or newer) and egcs (version 1.1b or newer)
+**             - StormC (version 2.00.14 or newer)
+**
+**     You get the smallest executable with SAS/C. gcc will give you
+**     quite a lot of warnings with the tag calls. Don't worry about them.
+**
+**
+**     History
+**     =======
+**
+**     1.0 (3.12.95) -- First version by Alfonso Caschili
+**
+**     1.1 (27.3.96) -- Major revamp by Bernardo Innocenti
+**
+**             - Source cleaned up, re-indented and commented the way I like it :)
+**
+**             - Fixed a bug with CTRL-C handling
+**
+**             - Does not keep a lock on the screen where the window opens for all the time
+**
+**             - Argument parsing improved a bit
+**
+**             - Does not need C startup code anymore (saves some KB)
+**
+**             - Window positioning and sizing is a bit smarter
+**
+**             - Does not refresh the window twice on startup
+**
+**
+**     2.0 (14.4.96) -- Rewritten using a `boopsi' class by Bernardo Innocenti
+**
+**             - Created the PIP 'boopsi' class
+**
+**             - Added sliders and buttons in window borders
+**
+**             - Added no-op backfilling hook (makes resizing and depth arragnging
+**               much faster and less flickering
+**
+**
+**     2.1 (8.5.96)
+**
+**             - Fixed window positioning bug.  Window was being positioned just below
+**               the screen title bar, but it was looking on the titlebar height of
+**               the screen being captured instead of the screen when the window was
+**               to be opened
+**
+**             - Changed PATTA_#? attributes to PIPA_#? attributes in the boopsi
+**               interconnection diagram.  PATTA_ is the attribute prefix for the
+**               pattedit.gadget, another boopsi class written by me
+**
+**             - Changed to always keep a lock on the screen where the window opens.
+**               This is needed because we are trying to free the associated DrawInfo
+**               strucure *after* closing the window.  Without a proper lock, our host
+**               screen could close just after we closed our window, which would make
+**               the parameter we pass to FreeScreenDrawInfo() an invalid pointer
+**
+**             - Fixed a bug that caused a call to still BltBitMapRastPort() with a
+**               NULL BitMap pointer when the PIPA_BitMap attribute was set to NULL
+**
+**             - Added error report for bad arguments
+**
+**
+**     2.2 (28.4.97)
+**
+**             - Added gcc compiler support (untested)
+**
+**             - Now uses a custom DoMethod() stub (faster than calling amiga.lib one)
+**
+**             - Fixed the arrow buttons positioning when their width/height is
+**               not the same of the size gadget
+**
+**     2.3 (10.5.97)
+**
+**             - Fixed LEFT, TOP, WIDTH & HEIGHT command line arguments. The
+**               OpenPIPWin() function was passing the *pointers* to the LONG
+**               values to OpenWindowTags(). (Riccardo Torrini)
+**
+**             - Dragging the view to the extreme left or top does no longer send
+**               negative numbers when notifying the sliders.
+**
+**             - Removed test to check if GetScreenDrawInfo() fails because this
+**               function is always successful
+**
+**
+**     2.4 (15.8.97)
+**
+**             - Added StormC compiler support
+**
+**             - gcc support tested: works fine with latest GeekGadgets snapshot
+**
+**
+**     2.5 (15.9.97)
+**
+**             - Compiled with SAS/C 6.58
+**
+**             - Improved SMakefile, now PIPWin is not need to be linked with
+**               any static libraries
+**
+**             - Size reduced even more!
+**
+**     2.6 (13.10.97)
+**
+**             - Fixed scroll bars positioning with non standard window
+**               border sizes
+**
+**             - gcc version can now be built without linking with libnix
+**
+**             - Replaced call to RefreshGList() with the new PIPM_Refresh
+**               class method, which in turn calls GM_RENDER with mode GREDRAW_UPDATE.
+**
+**
+**     To Do
+**     =====
+**
+**             - Add a requester to select a public screen to snoop
+**
+**             - Allow opening more than one window
+**
+**             - Workbench startup and ToolTypes parsing
+**
+**             - Allow zooming into the bitmap
+**
+**             - Make the pipclass update its imagery automatically at given
+**               time intervals.  This would require creating a Process for each
+**               istance the class, or perhaps one single Process for all objects.
+**               Unfortunately, most gadgetclass methods can not be called by
+**               soft interrupts, so it seems we really need a process :-(
+**
+**             - This one is very ambitious: it should be possible to forward mouse
+**               and keyboard input to the screen being displayed.  This would allow
+**               the user to actually USE programs without bringing their screens
+**               to front
+**
+**             - Optimize display scrolling in some special cases.  When the bitmap
+**               of the screen being displayed is not the same format of the bitmap
+**               where the PIP gadget renders (i.e.: they arn't `friend bitmaps'),
+**               some kind of conversion (e.g.: planar to chunky) will be done
+**               transparently by CopyBitMapRastPort().  This operation might be
+**               very slow, making more convenient to ScrollRaster() the existing
+**               image and copy just the part that gets revealed by the scrolling
+**
+**             - Change the mouse pointer to a grabbing hand while user is dragging
+**               the display
+**
+**
+**     Copyright Notice
+**     ================
+**
+**     Copyright © 1995 by Alfonso Caschili <valdus@mbox.vol.it>.
+**     Freely Distributable.
+**
+**     Copyright © 1996,97 by Bernardo Innocenti <bernie@cosmos.it>.
+**     Freely Distributable, as long as source code, documentation and
+**     executable are kept together.  Permission is granted to release
+**     modified versions of this program as long as all existing copyright
+**     notices are left intact.
+**
+*/
+
+#define _ANSI_SOURCE
+#define INTUI_V36_NAMES_ONLY
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H    /* Avoid including this header file because of
+                                                        * conflicting definitions in BoopsiStubs.h
+                                                        */
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <exec/execbase.h>
+#include <dos/rdargs.h>
+#include <intuition/intuition.h>
+#include <intuition/intuitionbase.h>
+#include <intuition/screens.h>
+#include <intuition/classes.h>
+#include <intuition/classusr.h>
+#include <intuition/gadgetclass.h>
+#include <intuition/imageclass.h>
+#include <intuition/icclass.h>
+#include <devices/timer.h>
+
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <proto/dos.h>
+#include <proto/utility.h>
+
+#include <CompilerSpecific.h>
+#include <DebugMacros.h>
+#include <BoopsiStubs.h>
+
+#include "PIPClass.h"
+
+
+
+/* Local function prototypes */
+LONG SAVEDS                             _main                  (void);
+static struct PIPHandle        *OpenPIPWin             (UBYTE *spyscreen, UBYTE *pubscreen,
+                                                                               ULONG *left, ULONG *top, ULONG *width, ULONG *height);
+static void                             ClosePIPWin    (struct PIPHandle *piphandle);
+static struct Gadget   *CreateGadgets  (struct PIPHandle *piphandle);
+static void                             DisposeGadgets (struct PIPHandle *piphandle);
+static void                             CreateImages   (struct DrawInfo *dri);
+static void                             FreeImages             (void);
+static Class *                  MakeScrollButtonClass  (void);
+static BOOL                             FreeScrollButtonClass  (Class *cl);
+static ULONG HOOKCALL   ScrollButtonDispatcher (
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, struct gpInput *gpi));
+
+
+
+/* Definitions for argument parsing */
+
+#define ARGS_TEMPLATE  "SCREEN,PUBSCREEN/K,DELAY/K/N,"                         \
+                                               "LEFT/K/N,TOP/K/N,WIDTH/K/N,HEIGHT/K/N"
+
+enum
+{
+       ARG_SCREEN, ARG_PUBSCREEN, ARG_DELAY,
+       ARG_LEFT, ARG_TOP, ARG_WIDTH, ARG_HEIGHT, ARG_COUNT
+};
+
+
+/* Gadgets IDs */
+
+enum
+{
+       GAD_PIP, GAD_VSLIDER, GAD_HSLIDER,
+       GAD_UPBUTTON, GAD_DOWNBUTTON, GAD_LEFTBUTTON, GAD_RIGHTBUTTON,
+       GAD_COUNT
+};
+
+
+/* Images IDs */
+
+enum
+{
+       IMG_UP, IMG_DOWN, IMG_LEFT, IMG_RIGHT, IMG_COUNT
+};
+
+
+
+/* This structure describes an open PIP window */
+
+struct PIPHandle
+{
+       struct Window   *Win;
+       struct Screen   *Scr;
+       struct DrawInfo *DrawInfo;
+       struct Screen   *SpyScr;
+       struct Gadget   *Gad[GAD_COUNT];
+       APTR                     Model;
+};
+
+
+
+/* Version tag */
+
+static const UBYTE versiontag[] = "$VER: PIPWin 2.6 (13.10.97) by Bernardo Innocenti & Alfonso Caschili";
+static const UBYTE PrgName[] = "PIPWin";
+
+
+
+/* Workaround a bug in StormC header file <proto/utility.h> */
+
+#ifdef __STORM__
+       #define UTILITYBASETYPE struct Library
+#else
+       #define UTILITYBASETYPE struct UtilityBase
+#endif
+
+
+/* Library bases */
+
+struct ExecBase                        *SysBase;
+struct DosLibrary              *DOSBase;
+struct IntuitionBase   *IntuitionBase;
+struct GfxBase                 *GfxBase;
+UTILITYBASETYPE                        *UtilityBase;
+
+
+
+/* Our private `boopsi' classes */
+
+static Class                   *PIPClass;
+static Class                   *ScrollButtonClass;
+
+
+
+/* 'boopsi' images for all our windows
+ *
+ * These variables must be NULL at startup time. We are not
+ * going to explicitly initialize them because otherwise
+ * Storm C 2.0 would generate a constructor to do it :-)
+ * LoasSeg() will clear the BSS data section for us, so
+ * these variables are guaranteed to be NULL anyway.
+ */
+static struct Image            *Img[IMG_COUNT];
+static ULONG                    ImgWidth[IMG_COUNT];
+static ULONG                    ImgHeight[IMG_COUNT];
+
+
+
+/* Attribute translations for object interconnections */
+
+static const ULONG MapPIPToHSlider[] =
+{
+       PIPA_OffX,                      PGA_Top,
+       PIPA_Width,                     PGA_Total,
+       PIPA_DisplayWidth,      PGA_Visible,
+       TAG_DONE
+};
+
+static const ULONG MapHSliderToPIP[] =
+{
+       PGA_Top,        PIPA_OffX,
+       TAG_DONE
+};
+
+static const ULONG MapPIPToVSlider[] =
+{
+       PIPA_OffY,                      PGA_Top,
+       PIPA_Height,            PGA_Total,
+       PIPA_DisplayHeight,     PGA_Visible,
+       TAG_DONE
+};
+
+
+static const ULONG MapVSliderToPIP[] =
+{
+       PGA_Top,        PIPA_OffY,
+       TAG_DONE
+};
+
+static const ULONG MapUpButtonToPIP[] =
+{
+       GA_ID,          PIPA_MoveUp,
+       TAG_DONE
+};
+
+static const ULONG MapDownButtonToPIP[] =
+{
+       GA_ID,          PIPA_MoveDown,
+       TAG_DONE
+};
+
+static const ULONG MapLeftButtonToPIP[] =
+{
+       GA_ID,          PIPA_MoveLeft,
+       TAG_DONE
+};
+
+static const ULONG MapRightButtonToPIP[] =
+{
+       GA_ID,          PIPA_MoveRight,
+       TAG_DONE
+};
+
+
+
+LONG SAVEDS _main(void)
+
+/* Main program entry point.  When linking without startup code, this
+ * must be the first function in the first object module listed on the
+ * linker command line.  We also need to initialize SysBase and open
+ * all needed libraries manually.
+ */
+{
+       struct PIPHandle        *piphandle;
+       struct RDArgs           *rdargs;
+       struct MsgPort          *TimerMsgPort;
+       struct timerequest      *TimerIO;
+       LONG                             args[ARG_COUNT] = { 0 };
+       LONG                             sigwait, sigrcvd;
+       LONG                             secs, micros;
+       LONG                             retval = RETURN_FAIL;
+       BOOL                             quit   = FALSE;
+
+
+       /* Initialize SysBase */
+       SysBase = *((struct ExecBase **)4UL);
+
+       if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37L))
+       {
+               if (UtilityBase = (UTILITYBASETYPE *) OpenLibrary("utility.library", 37L))
+               {
+                       /* Parse shell arguments */
+                       if (rdargs = ReadArgs(ARGS_TEMPLATE, args, NULL))
+                       {
+                               if (args[ARG_DELAY])
+                               {
+                                       /* We use utility.library math because it works for 68000 too */
+                                       secs    = UDivMod32(*((LONG *)args[ARG_DELAY]), 10);
+                                       micros  = UMult32((*((LONG *)args[ARG_DELAY]) - UMult32 (secs, 10)), 100000);
+                               }
+                               else
+                               {
+                                       secs    = 2;
+                                       micros  = 0;
+                               }
+
+                               if (IntuitionBase = (struct IntuitionBase *)
+                                       OpenLibrary("intuition.library", 39))
+                               {
+                                       if (GfxBase = (struct GfxBase *)
+                                               OpenLibrary("graphics.library", 39))
+                                       {
+                                               if (TimerMsgPort = CreateMsgPort())
+                                               {
+                                                       if (TimerIO = (struct timerequest *) CreateIORequest(TimerMsgPort, sizeof (struct timerequest)))
+                                                       {
+                                                               if (!OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)TimerIO, 0))
+                                                               {
+                                                                       if (PIPClass = MakePIPClass())
+                                                                       {
+                                                                               if (ScrollButtonClass = MakeScrollButtonClass())
+                                                                               {
+                                                                                       if (piphandle = OpenPIPWin((UBYTE *)args[ARG_SCREEN], (UBYTE *)args[ARG_PUBSCREEN],
+                                                                                               (ULONG *)args[ARG_LEFT], (ULONG *)args[ARG_TOP],
+                                                                                               (ULONG *)args[ARG_WIDTH], (ULONG *)args[ARG_HEIGHT]))
+                                                                                       {
+                                                                                               /* Pre-calculate the signal mask for Wait() */
+                                                                                               sigwait = (1 << TimerMsgPort->mp_SigBit) |
+                                                                                                       (1 << piphandle->Win->UserPort->mp_SigBit) |
+                                                                                                       SIGBREAKF_CTRL_C;
+
+                                                                                               /* Send our first IORequest to timer.device */
+                                                                                               TimerIO->tr_node.io_Command     = TR_ADDREQUEST;
+                                                                                               TimerIO->tr_time.tv_secs        = secs;
+                                                                                               TimerIO->tr_time.tv_micro       = micros;
+                                                                                               SendIO ((struct IORequest *)TimerIO);
+
+                                                                                               /* Now for the main loop.  As you can see, it is really
+                                                                                                * very compact.  That's the magic of boopsi! :-)
+                                                                                                */
+                                                                                               while (!quit)
+                                                                                               {
+                                                                                                       /* Sleep until something interesting occurs */
+                                                                                                       sigrcvd = Wait(sigwait);
+
+                                                                                                       /* Now handle received signals */
+
+                                                                                                       /* Break signal? */
+                                                                                                       if (sigrcvd & SIGBREAKF_CTRL_C)
+                                                                                                               quit = TRUE;
+
+                                                                                                       /* timer.device? */
+                                                                                                       if (sigrcvd & (1 << TimerMsgPort->mp_SigBit))
+                                                                                                       {
+                                                                                                               /* Update the PIP gadget and send another
+                                                                                                                * request to the timer.device
+                                                                                                                */
+                                                                                                               DoGadgetMethod(piphandle->Gad[GAD_PIP], piphandle->Win, NULL,
+                                                                                                                       PIPM_REFRESH, NULL);
+
+                                                                                                               TimerIO->tr_node.io_Command     = TR_ADDREQUEST;
+                                                                                                               TimerIO->tr_time.tv_secs        = secs;
+                                                                                                               TimerIO->tr_time.tv_micro       = micros;
+                                                                                                               SendIO((struct IORequest *)TimerIO);
+                                                                                                       }
+
+                                                                                                       /* IDCMP message? */
+                                                                                                       if (sigrcvd & (1 << piphandle->Win->UserPort->mp_SigBit))
+                                                                                                       {
+                                                                                                               struct IntuiMessage     *msg;
+
+                                                                                                               while (msg = (struct IntuiMessage *) GetMsg(piphandle->Win->UserPort))
+                                                                                                               {
+                                                                                                                       switch (msg->Class)
+                                                                                                                       {
+                                                                                                                               case IDCMP_CLOSEWINDOW:
+                                                                                                                                       quit = TRUE;
+                                                                                                                                       break;
+
+                                                                                                                               default:
+                                                                                                                                       break;
+                                                                                                                       }
+                                                                                                                       ReplyMsg ((struct Message *) msg);
+                                                                                                               }
+                                                                                                       }
+                                                                                               } /* End while (!quit) */
+
+                                                                                               retval = RETURN_OK;
+
+                                                                                               /* Abort the IORequest sent to the timer.device */
+                                                                                               AbortIO((struct IORequest *)TimerIO);
+                                                                                               WaitIO((struct IORequest *)TimerIO);
+
+                                                                                               ClosePIPWin(piphandle);
+                                                                                       }
+
+                                                                                       FreeImages();
+                                                                                       /* This one cannot fail */
+                                                                                       FreeScrollButtonClass(ScrollButtonClass);
+                                                                               }
+                                                                               /* This one cannot fail */
+                                                                               FreePIPClass(PIPClass);
+                                                                       }
+                                                                       CloseDevice((struct IORequest *)TimerIO);
+                                                               }
+                                                               DeleteIORequest((struct IORequest *)TimerIO);
+                                                       }
+                                                       DeleteMsgPort(TimerMsgPort);
+                                               }
+                                               CloseLibrary((struct Library *)GfxBase);
+                                       }
+                                       CloseLibrary((struct Library *)IntuitionBase);
+                               }
+                               FreeArgs(rdargs);
+                       }
+                       else PrintFault(IoErr(), (STRPTR)PrgName);
+
+                       CloseLibrary((struct Library *)UtilityBase);
+               }
+               CloseLibrary((struct Library *)DOSBase);
+       }
+
+       return retval;
+}
+
+
+
+static struct PIPHandle *OpenPIPWin(UBYTE *screen, UBYTE *pubscreen,
+       ULONG *left, ULONG *top, ULONG *width, ULONG *height)
+{
+       struct PIPHandle        *piphandle;
+       struct Gadget           *glist;
+
+
+       if (piphandle = AllocMem(sizeof (struct PIPHandle), MEMF_ANY | MEMF_CLEAR))
+       {
+               if (piphandle->SpyScr = LockPubScreen(screen))
+               {
+                       if (piphandle->Scr = LockPubScreen(pubscreen))
+                       {
+                               if (glist = CreateGadgets(piphandle))
+                               {
+                                       SetAttrs(glist,
+                                               PIPA_Screen,    piphandle->SpyScr,
+                                               TAG_DONE);
+
+                                       if (piphandle->Win = OpenWindowTags(NULL,
+                                               WA_Left,                        left ? *left : 0,
+                                               WA_Top,                         top ? *top : piphandle->Scr->BarHeight + 1,
+                                               WA_InnerWidth,          width ? *width : piphandle->SpyScr->Width,
+                                               WA_InnerHeight,         height ? *height : piphandle->SpyScr->Height,
+                                               WA_MinWidth,            64,
+                                               WA_MinHeight,           64,
+                                               WA_MaxWidth,            piphandle->SpyScr->Width,
+                                               WA_MaxHeight,           piphandle->SpyScr->Height,
+                                               WA_PubScreen,           piphandle->Scr,
+                                               WA_PubScreenFallBack, TRUE,
+                                               WA_AutoAdjust,          TRUE,
+                                               WA_IDCMP,                       IDCMP_CLOSEWINDOW,
+                                               WA_Flags,                       WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
+                                                                                       WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM |
+                                                                                       WFLG_SIMPLE_REFRESH | WFLG_NOCAREREFRESH,
+                                               WA_Gadgets,                     glist,
+                                               WA_BackFill,            LAYERS_NOBACKFILL,
+                                               WA_Title,                       piphandle->SpyScr->DefaultTitle,
+                                               WA_ScreenTitle,         versiontag + 6,
+                                               TAG_DONE))
+
+                                               /* We need to keep our screen locked all the time
+                                                * because we want to free the associated DrawInfo
+                                                * *after* the window has been closed and
+                                                * FreeScreenDrawInfo() wants a pointer to a *valid*
+                                                * Screen.
+                                                */
+                                               return piphandle;
+                                       DisposeGadgets(piphandle);
+                               }
+                               UnlockPubScreen(NULL, piphandle->Scr);
+                       }
+                       UnlockPubScreen(NULL, piphandle->SpyScr);
+               }
+               FreeMem(piphandle, sizeof (struct PIPHandle));
+       }
+       return NULL;
+}
+
+
+
+static void ClosePIPWin(struct PIPHandle *piphandle)
+{
+       /* Close our window. No need to reply queued messages,
+        * Intuition is clever enough to care about this for us.
+        */
+       CloseWindow(piphandle->Win);
+       DisposeGadgets(piphandle);
+       UnlockPubScreen(NULL, piphandle->Scr);
+       UnlockPubScreen(NULL, piphandle->SpyScr);
+       FreeMem(piphandle, sizeof (struct PIPHandle));
+}
+
+
+
+/*
+ *     Diagram of object interconnections
+ *     ==================================
+ *
+ *
+ *                    ScrollButtonClass objects
+ *     +----------+ +------------+ +------------+ +-------------+
+ *     | UpButton | | DownButton | | LeftButton | | RightButton |
+ *     +----------+ +------------+ +------------+ +-------------+
+ *      | GA_ID =     | GA_ID =       | GA_ID =       | GA_ID =
+ *      | PIPA_MoveUp | PIPA_MoveDown | PIPA_MoveLeft | PIPA_MoveRight
+ *      |             |               |               |
+ *      |  +----------+               |               |
+ *      |  |  +-----------------------+               |
+ *      |  |  |  +------------------------------------+
+ *      |  |  |  |        propgclass object     icclass object
+ *      |  |  |  |          +-----------+      +--------------+
+ *      |  |  |  |          |  HSlider  |<-----| PIPToHSlider |
+ *      |  |  |  |          +-----------+      +--------------+
+ *      |  |  |  |      PGA_Top = |                 ^ PIPA_OffX  = PGA_Top
+ *      |  |  |  |      PIPA_OffX |                 | PIPA_Width = PGA_Visible
+ *      |  |  |  |                |                 | PIPA_DisplayWidth =
+ *      V  V  V  V                V                 |              PGA_Total
+ *     +-----------+         ***********            |
+ *     |           |-------->*         *------------+
+ *     |    PIP    |         *  Model  *
+ *     |           |<--------*         *------------+
+ *     +-----------+         ***********            |
+ *                                ^                 |
+ *                      PGA_Top = |                 |
+ *                      PIPA_OffY |                 V  icclass object
+ *                          +-----------+      +--------------+
+ *                          |  VSlider  |<-----| PIPToVSlider |
+ *                          +-----------+      +--------------+
+ *                        propgclass object     PIPA_OffY   = PGA_Top
+ *                                              PIPA_Height = PGA_Visible
+ *                                              PIPA_DisplayHeight = PGA_Total
+ */
+
+static struct Gadget *CreateGadgets(struct PIPHandle *piphandle)
+{
+       struct DrawInfo *dri;
+       struct Screen   *scr = piphandle->Scr;
+       struct Image    *SizeImage;
+       ULONG SizeWidth = 18, SizeHeight = 11;  /* Default values */
+
+       /* GetScreenDrawInfo() never fails */
+       dri = piphandle->DrawInfo = GetScreenDrawInfo (scr);
+
+       /* Create a new size image to get its size */
+       if (SizeImage = NewObject(NULL, SYSICLASS,
+               SYSIA_Which,    SIZEIMAGE,
+               SYSIA_DrawInfo, dri,
+               TAG_DONE))
+       {
+               /* Get size gadget geometry */
+               GetAttr(IA_Width, SizeImage, &SizeWidth);
+               GetAttr(IA_Height, SizeImage, &SizeHeight);
+
+               /* And then get rid of it... */
+               DisposeObject(SizeImage);
+       }
+
+       /* No need to check this: in case of failure we would just
+        * get no images in the scroll buttons, but we can still try
+        * to open our window.
+        */
+       CreateImages(dri);
+
+       if (piphandle->Model = NewObjectA(NULL, MODELCLASS, NULL))
+               if (piphandle->Gad[GAD_PIP] = NewObject (PIPClass, NULL,
+                       GA_ID,                  GAD_PIP,
+                       GA_Left,                scr->WBorLeft,
+                       GA_Top,                 scr->WBorTop + scr->Font->ta_YSize + 1,
+                       GA_RelWidth,    - SizeWidth - scr->WBorLeft,
+                       GA_RelHeight,   - (scr->WBorTop + scr->Font->ta_YSize + SizeHeight + 1),
+                       GA_DrawInfo,    dri,
+                       ICA_TARGET,             piphandle->Model,
+                       TAG_DONE))
+                       if (piphandle->Gad[GAD_VSLIDER] = NewObject(NULL, PROPGCLASS,
+                               GA_ID,                  GAD_VSLIDER,
+                               GA_Previous,    piphandle->Gad[GAD_PIP],
+                               GA_RelRight,    - SizeWidth + 5,
+                               GA_Top,                 scr->WBorTop + scr->Font->ta_YSize + 2,
+                               GA_Width,               SizeWidth - 8,
+                               GA_RelHeight,   - (scr->WBorTop + scr->Font->ta_YSize +
+                                                               SizeHeight + ImgHeight[IMG_DOWN] + ImgHeight[IMG_UP] + 4),
+                               GA_RightBorder, TRUE,
+                               GA_DrawInfo,    dri,
+                               PGA_Freedom,    FREEVERT,
+                               PGA_Borderless, ((dri->dri_Flags & DRIF_NEWLOOK) && (dri->dri_Depth != 1)),
+                               PGA_NewLook,    TRUE,
+                               ICA_TARGET,             piphandle->Model,
+                               ICA_MAP,                MapVSliderToPIP,
+                               TAG_DONE))
+                               if (piphandle->Gad[GAD_HSLIDER] = NewObject(NULL, PROPGCLASS,
+                                       GA_ID,                  GAD_HSLIDER,
+                                       GA_Previous,    piphandle->Gad[GAD_VSLIDER],
+                                       GA_RelBottom,   - SizeHeight + ((SizeHeight > 15) ? 4 : 3),
+                                       GA_Left,                scr->WBorLeft,
+                                       GA_Height,              SizeHeight - ((SizeHeight > 15)  ? 6 : 4),
+                                       GA_RelWidth,    - (SizeWidth + ImgWidth[IMG_RIGHT] + ImgWidth[IMG_LEFT] + scr->WBorLeft + 2),
+                                       GA_BottomBorder,TRUE,
+                                       GA_DrawInfo,    dri,
+                                       PGA_Freedom,    FREEHORIZ,
+                                       PGA_Borderless, ((dri->dri_Flags & DRIF_NEWLOOK) && (dri->dri_Depth != 1)),
+                                       PGA_NewLook,    TRUE,
+                                       ICA_TARGET,             piphandle->Model,
+                                       ICA_MAP,                MapHSliderToPIP,
+                                       TAG_DONE))
+                                       if (piphandle->Gad[GAD_UPBUTTON] = NewObject(ScrollButtonClass, NULL,
+                                               GA_ID,                  GAD_UPBUTTON,
+                                               GA_Previous,    piphandle->Gad[GAD_HSLIDER],
+                                               GA_RelBottom,   - SizeHeight - ImgHeight[IMG_DOWN] - ImgHeight[IMG_UP] + 1,
+                                               GA_RelRight,    - ImgWidth[IMG_DOWN] + 1,
+                                               GA_RightBorder, TRUE,
+                                               GA_DrawInfo,    dri,
+                                               GA_Image,               Img[IMG_UP],
+                                               ICA_TARGET,             piphandle->Gad[GAD_PIP],
+                                               ICA_MAP,                MapUpButtonToPIP,
+                                               TAG_DONE))
+                                               if (piphandle->Gad[GAD_DOWNBUTTON] = NewObject(ScrollButtonClass, NULL,
+                                                       GA_ID,                  GAD_DOWNBUTTON,
+                                                       GA_Previous,    piphandle->Gad[GAD_UPBUTTON],
+                                                       GA_RelBottom,   - SizeHeight - ImgHeight[IMG_DOWN] + 1,
+                                                       GA_RelRight,    - ImgWidth[IMG_DOWN] + 1,
+                                                       GA_RightBorder, TRUE,
+                                                       GA_DrawInfo,    dri,
+                                                       GA_Image,               Img[IMG_DOWN],
+                                                       ICA_TARGET,             piphandle->Gad[GAD_PIP],
+                                                       ICA_MAP,                MapDownButtonToPIP,
+                                                       TAG_DONE))
+                                                       if (piphandle->Gad[GAD_LEFTBUTTON] = NewObject(ScrollButtonClass, NULL,
+                                                               GA_ID,                  GAD_LEFTBUTTON,
+                                                               GA_Previous,    piphandle->Gad[GAD_DOWNBUTTON],
+                                                               GA_RelBottom,   - ImgHeight[IMG_LEFT] + 1,
+                                                               GA_RelRight,    - SizeWidth - ImgWidth[IMG_RIGHT] - ImgWidth[IMG_LEFT] + 1,
+                                                               GA_BottomBorder,TRUE,
+                                                               GA_DrawInfo,    dri,
+                                                               GA_Image,               Img[IMG_LEFT],
+                                                               ICA_TARGET,             piphandle->Gad[GAD_PIP],
+                                                               ICA_MAP,                MapLeftButtonToPIP,
+                                                               TAG_DONE))
+                                                               if (piphandle->Gad[GAD_RIGHTBUTTON] = NewObject(ScrollButtonClass, NULL,
+                                                                       GA_ID,                  GAD_RIGHTBUTTON,
+                                                                       GA_Previous,    piphandle->Gad[GAD_LEFTBUTTON],
+                                                                       GA_RelBottom,   - ImgHeight[IMG_RIGHT] + 1,
+                                                                       GA_RelRight,    - SizeWidth - ImgWidth[IMG_RIGHT] + 1,
+                                                                       GA_BottomBorder,TRUE,
+                                                                       GA_DrawInfo,    dri,
+                                                                       GA_Image,               Img[IMG_RIGHT],
+                                                                       ICA_TARGET,             piphandle->Gad[GAD_PIP],
+                                                                       ICA_MAP,                MapRightButtonToPIP,
+                                                                       TAG_DONE))
+                                                                       {
+                                                                               APTR icobject;
+
+                                                                               /* Connect VSlider to Model */
+
+                                                                               if (icobject = NewObject(NULL, ICCLASS,
+                                                                                       ICA_TARGET,     piphandle->Gad[GAD_VSLIDER],
+                                                                                       ICA_MAP,        MapPIPToVSlider,
+                                                                                       TAG_DONE))
+                                                                                       if (!DoMethod (piphandle->Model, OM_ADDMEMBER, icobject))
+                                                                                               DisposeObject (icobject);
+
+                                                                               /* Connect HSlider to Model */
+
+                                                                               if (icobject = NewObject(NULL, ICCLASS,
+                                                                                       ICA_TARGET,     piphandle->Gad[GAD_HSLIDER],
+                                                                                       ICA_MAP,        MapPIPToHSlider,
+                                                                                       TAG_DONE))
+                                                                                       if (!DoMethod (piphandle->Model, OM_ADDMEMBER, icobject))
+                                                                                               DisposeObject (icobject);
+
+                                                                               /* Connect Model to PIP */
+
+                                                                               SetAttrs(piphandle->Model,
+                                                                                       ICA_TARGET, piphandle->Gad[GAD_PIP],
+                                                                                       TAG_DONE);
+
+                                                                               return piphandle->Gad[GAD_PIP];
+                                                                       }
+       DisposeGadgets(piphandle);
+
+       return NULL;
+}
+
+
+
+static void DisposeGadgets(struct PIPHandle *piphandle)
+{
+       ULONG i;
+
+       for (i = 0; i < GAD_COUNT; i++)
+       {
+               DisposeObject(piphandle->Gad[i]);
+               /* piphandle->Gad[i] = NULL; */
+       }
+
+       /* Freeing the Model will also free its two targets */
+       DisposeObject(piphandle->Model);
+       /* piphandle->Model = NULL */
+
+       FreeScreenDrawInfo(piphandle->Scr, piphandle->DrawInfo);
+       /* piphandle->DrawInfo = NULL */
+}
+
+
+
+static void CreateImages(struct DrawInfo *dri)
+
+/* Create 4 arrow images for the window scrolling buttons.
+ *
+ * Why bother checking for failure? The arrow images are not
+ * life critical in our program...
+ */
+{
+       static ULONG imagetypes[IMG_COUNT] = { UPIMAGE, DOWNIMAGE, LEFTIMAGE, RIGHTIMAGE };
+       ULONG i;
+
+       for (i = 0; i < IMG_COUNT; i++)
+               if (!Img[i])
+                       if (Img[i] = (struct Image *)NewObject(NULL, SYSICLASS,
+                               SYSIA_Which,    imagetypes[i],
+                               SYSIA_DrawInfo, dri,
+                               TAG_DONE))
+                       {
+                               /* Ask image width and height */
+                               GetAttr(IA_Width, Img[i], &ImgWidth[i]);
+                               GetAttr(IA_Height, Img[i], &ImgHeight[i]);
+                       }
+}
+
+
+
+static void FreeImages(void)
+{
+       ULONG i;
+
+       for (i = 0; i < IMG_COUNT; i++)
+               DisposeObject((APTR)Img[i]);    /* DisposeObject(NULL) is safe */
+}
+
+
+
+/*
+**     ScrollButtonClass
+**
+**     This code has been taken from ScrollerWindow 0.3
+**     Copyright © 1994 Christoph Feck, TowerSystems.
+**
+**     Subclass of buttongclass.  The ROM class has two problems, which make
+**     it not quite usable for scrollarrows.  The first problem is the missing
+**     delay.  Once the next INTUITICK gets send by input.device, the ROM
+**     class already sends a notification.  The other problem is that it also
+**     notifies us, when the button finally gets released (which is necessary
+**     for command buttons).
+**
+**     We define a new class with the GM_GOACTIVE and GM_HANDLEINPUT method
+**     overloaded to work around these problems.
+*/
+
+
+
+/* Function prototypes */
+
+static ULONG HOOKCALL ScrollButtonDispatcher(
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, struct gpInput *gpi));
+
+
+/* Per object instance data */
+struct ScrollButtonData
+{
+       /* The number of ticks we still have to wait
+        * before sending any notification.
+        */
+       ULONG TickCounter;
+};
+
+
+
+static ULONG HOOKCALL ScrollButtonDispatcher(
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, struct gpInput *gpi))
+
+/* ScrollButton Class Dispatcher entrypoint.
+ * Handle BOOPSI messages.
+ */
+{
+       struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g);
+
+       switch (gpi->MethodID)
+       {
+               case GM_GOACTIVE:
+                       /* May define an attribute to make delay configurable */
+                       bd->TickCounter = 3;
+
+                       /* Notify our target that we have initially hit. */
+                       NotifyAttrs((Object *)g, gpi->gpi_GInfo, 0,
+                               GA_ID,  g->GadgetID,
+                               TAG_DONE);
+
+                       /* Send more input */
+                       return GMR_MEACTIVE;
+
+               case GM_HANDLEINPUT:
+               {
+                       ULONG retval = GMR_MEACTIVE;
+                       UWORD selected = 0;
+
+                       /* This also works with classic (non-boopsi) images. */
+                       if (PointInImage((gpi->gpi_Mouse.X << 16) + (gpi->gpi_Mouse.Y), g->GadgetRender))
+                       {
+                               /* We are hit */
+                               selected = GFLG_SELECTED;
+                       }
+
+                       if (gpi->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE && gpi->gpi_IEvent->ie_Code == SELECTUP)
+                       {
+                               /* Gadgetup, time to go */
+                               retval = GMR_NOREUSE;
+                               /* Unselect the gadget on our way out... */
+                               selected = 0;
+                       }
+                       else if (gpi->gpi_IEvent->ie_Class == IECLASS_TIMER)
+                       {
+                               /* We got a tick: decrement counter, and if 0, send notify. */
+
+                               if (bd->TickCounter) bd->TickCounter--;
+                               else if (selected)
+                                       /* Notify our target that we are still being hit */
+                                       NotifyAttrs((Object *)g, gpi->gpi_GInfo, 0,
+                                               GA_ID,  g->GadgetID,
+                                               TAG_DONE);
+                       }
+
+                       if ((g->Flags & GFLG_SELECTED) != selected)
+                       {
+                               struct RastPort *rp;
+
+                               /* Update changes in gadget render */
+                               g->Flags ^= GFLG_SELECTED;
+                               if (rp = ObtainGIRPort(gpi->gpi_GInfo))
+                               {
+                                       DoMethod((Object *) g, GM_RENDER, gpi->gpi_GInfo, rp, GREDRAW_UPDATE);
+                                       ReleaseGIRPort (rp);
+                               }
+                       }
+                       return retval;
+               }
+
+               default:
+                       /* Super class handles everything else */
+                       return (DoSuperMethodA(cl, (Object *)g, (Msg) gpi));
+       }
+}
+
+
+
+static Class *MakeScrollButtonClass(void)
+{
+       Class *class;
+
+       if (class = MakeClass(NULL, BUTTONGCLASS, NULL, sizeof(struct ScrollButtonData), 0))
+               class->cl_Dispatcher.h_Entry = (ULONG (*)()) ScrollButtonDispatcher;
+
+       return class;
+}
+
+
+
+static BOOL FreeScrollButtonClass(Class *cl)
+{
+       return (FreeClass(cl));
+}
diff --git a/gadgets/PIPWin/PIPWin.mdbi b/gadgets/PIPWin/PIPWin.mdbi
new file mode 100755 (executable)
index 0000000..02ebb32
Binary files /dev/null and b/gadgets/PIPWin/PIPWin.mdbi differ
diff --git a/gadgets/PIPWin/PIPWin.project b/gadgets/PIPWin/PIPWin.project
new file mode 100755 (executable)
index 0000000..9d648d1
--- /dev/null
@@ -0,0 +1,39 @@
+;MaxonCPP-Project
+
+<Project-Options>
+-dir "Work:SC/src/PIPWin/" -args "" -stack 10 -pri 0
+<End>
+
+
+<Linker-Options>
+-gD -gs -gh50 -w100 
+-j "PROGDIR:amiga/mcpp-libs/" 
+<End>
+
+<C-Options>
+-waCEFNMOPRTV -pc -g00 -g80 -gO -gb0 -gM -bs0 -a0 -t -px -bf -mX 
+-i "PROGDIR:amiga/c-inc/" 
+-i "Include:" 
+<End>
+
+<ASM-Options>
+-c cWSElMo0F -0xff 
+-i "Include:" 
+<End>
+
+
+<CSources>
+"PIPWin.c" "PIPWin.o"
+       <Object>
+               -pri 5
+       <End>
+"PIPClass.c" "PIPClass.o"
+<End>
+
+<LinkLibs>
+"LIB:amiga.lib"
+       <Object>
+               -dontlink 
+       <End>
+<End>
+
diff --git a/gadgets/PIPWin/PIPWin.readme b/gadgets/PIPWin/PIPWin.readme
new file mode 100644 (file)
index 0000000..cab007a
--- /dev/null
@@ -0,0 +1,37 @@
+Short:    Picture In Picture window/boopsi class (binary + C source)
+Author:   bernie@shock.cosmos.it (Bernardo Innocenti)
+Uploader: bernie@shock.cosmos.it (Bernardo Innocenti)
+Type:     dev/src
+Version:  2.6
+Replaces: dev/src/PIPWin.lha
+
+ PIPWin opens a window on any public screen which shows the contents of
+a user selected public screen. You can resize and scroll by dragging
+inside the window or using the cursor keys.
+
+The source code demonstrates how to:
+
+       * Building a `boopsi' class on top of the gadgetclass
+
+       * Writing a `boopsi' dispatcher with complex input handling
+
+       * Using `boopsi' sysiclass images
+
+       * Connecting `boopsi' objects together using the icclass
+
+       * Overlaying the buttongclass to make a scrollbutton
+
+       * Creating a sizeable window with sliders
+
+       * Making a C program with no startup and no need to link
+         with static libraries such as amiga.lib
+
+       * Using the timer.device
+
+       * Making Amiga specific code which works with SAS/C,
+         GCC and StormC.
+
+       * Correctly opening/closing libraries, devices and other
+         system resources
+
+       * Parsing command line arguments with ReadArgs()
diff --git a/gadgets/PIPWin/PIPWin.sas b/gadgets/PIPWin/PIPWin.sas
new file mode 100755 (executable)
index 0000000..258aabd
Binary files /dev/null and b/gadgets/PIPWin/PIPWin.sas differ
diff --git a/gadgets/PIPWin/SMakefile b/gadgets/PIPWin/SMakefile
new file mode 100644 (file)
index 0000000..b687e2d
--- /dev/null
@@ -0,0 +1,95 @@
+##
+##     $Id:$
+##
+##     Copyright (C) 1996,97 by Bernardo Innocenti
+##
+##     Makefile for SAS/C
+##
+
+###########################################################
+# Name of the main executable
+###########################################################
+#
+PROJ = PIPWin
+
+
+###########################################################
+# Package configuration
+###########################################################
+#
+
+# Cpu to compile for (eg: "68020").
+#
+CPU = 68000
+
+
+###########################################################
+# Object files in this project
+###########################################################
+#
+OBJS = PIPWin.o PIPClass.o
+
+
+###########################################################
+# Make the project
+###########################################################
+#
+all: $(PROJ)
+
+
+###########################################################
+# Remove all targets and intermediate files
+###########################################################
+#
+clean:
+       -Delete $(PROJ) $(OBJS)
+
+
+###########################################################
+# Dependences
+###########################################################
+#
+PIPWin.c PIPClass.c: PIPClass.h
+
+
+###########################################################
+# Compiler, linker and assembler flags
+###########################################################
+#
+
+# C compiler flags for both release and debug versions
+#
+COMMON_CFLAGS = PARAMETERS=REGISTERS STRINGMERGE NOSTACKCHECK NOCHECKABORT \
+       NOICONS NOLINK DATA=NEAR CODE=NEAR STRSECT=CODE DEF=$(OSVER) CPU=$(CPU)
+
+# C compiler optimization flags
+#
+OPT_CFLAGS = OPTIMIZE OPTTIME OPTSCHEDULER OPTINLINELOCAL \
+       OPTRDEPTH=4 OPTDEPTH=4 OPTCOMP=8
+
+# Debug flags: don't optimize and include all symbols in debug hunks
+#
+DEBUG_CFLAGS = NOOPTIMIZE DEBUG=FULLFLUSH ONERROR=CONTINUE DEF=DEBUG
+
+
+# RELEASE version should be compiled with these flags
+#
+CFLAGS = $(COMMON_CFLAGS) $(OPT_CFLAGS)
+LFLAGS = NODEBUG SMALLCODE SMALLDATA NOALVS NOICONS
+
+
+# DEBUG version should be compiled with these flags
+#
+#CFLAGS = $(COMMON_CFLAGS) $(DEBUG_CFLAGS)
+#LFLAGS = ADDSYM SMALLCODE SMALLDATA BATCH NOALVS NOICONS
+#LIBS = LIB LIB:debug.lib
+
+
+###########################################################
+# Make the executable
+###########################################################
+#
+# NOTE: Using implicit rule to compile C files
+
+$(PROJ): $(OBJS)
+       $(LD) FROM $(OBJS) TO $(PROJ) $(LIBS) $(LFLAGS)
diff --git a/gadgets/ResizeGClass/Makefile b/gadgets/ResizeGClass/Makefile
new file mode 100644 (file)
index 0000000..eb79630
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(BOOPSITOP)/config.mk
+include config.mk
+
+ARG_COMMON :=
+ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o
+ARG_LIB := $(ARG_COMMON)
+ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV)
+ARG_PRIVATE := $(ARG_COMMON)
+ARG_OBJ := $(ARG_COMMON)
+
+DEP_COMMON :=
+DEP_ALL := $(DEP_COMMON) OpenClass.o
+DEP_LIB := $(DEP_COMMON)
+DEP_DEBUG := $(DEP_COMMON) OpenClass.o
+DEP_PRIVATE := $(DEP_COMMON)
+DEP_OBJ := $(DEP_COMMON)
+
+include $(BOOPSITOP)/common/general.mk
+
+OpenClass.o: OpenClass.c
+       $(MAKE) -C $(BOOPSITOP)/common/ $@
diff --git a/gadgets/ResizeGClass/config.mk b/gadgets/ResizeGClass/config.mk
new file mode 100644 (file)
index 0000000..2581884
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+###########################################################
+# your stuff
+#
+CLASSLIB := resize.gadget
+CLASSSRC := ResizeGClass.c
+DEMOSRC  := ResizeGDemo.c
+SUBDIR   := gadgets
+
+
+###########################################################
+# class version information
+#
+CLASSVER  := 0
+CLASSREV  := 1
+CLASSDATE := (6.4.99)
+
+
+###########################################################
+# variable to make the linked library version
+#
+PRV := PRIVATE_RESIZEGCLASS
+
diff --git a/gadgets/ScrollButton/Makefile b/gadgets/ScrollButton/Makefile
new file mode 100644 (file)
index 0000000..1f0f97d
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+TOP := ../..
+
+include $(TOP)/config.mk
+
+#
+# Class specific information
+#
+CLASSLIB       := scrollbutton.gadget
+CLASSSRC       := ScrollButtonClass.c
+CLASSOBJ       := $(TOP)/common/GetGadgetBox.o
+NOSTDLIB       := 1
+INSTALLDIR     := gadgets
+
+#
+# Class version information
+#
+CLASSVER       := 1
+CLASSREV       := 0
+CLASSDATE      := (21.3.2000)
+
+include $(TOP)/common/general.mk
+
diff --git a/gadgets/ScrollButton/ScrollButtonClass.c b/gadgets/ScrollButton/ScrollButtonClass.c
new file mode 100644 (file)
index 0000000..ceb99b7
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+**     $Id: ScrollButtonClass.c,v 1.1 1999/02/07 14:24:43 bernie Exp $
+**
+**     Copyright (C) 1998,99 Bernardo Innocenti
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     The ScrollButtonClass is a simple subclass of the buttongclass
+**     specialized for scroll buttons. See ScrollButtonClass.h for a detailed
+**     description.
+*/
+
+#define USE_BUILTIN_MATH
+#define INTUI_V36_NAMES_ONLY
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H            /* Avoid dupe defs of boopsi funcs */
+
+
+#include <intuition/gadgetclass.h>
+#include <intuition/imageclass.h>
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <proto/utility.h>
+
+#include <gadgets/ScrollButtonClass.h>
+
+#include <CompilerSpecific.h>
+#include <DebugMacros.h>
+#include <DiagnosticMacros.h>
+#include <BoopsiStubs.h>
+#include <BoopsiLib.h>
+
+#ifdef __STORM__
+       #pragma header
+#endif
+
+
+
+/* Per object instance data */
+struct ScrollButtonData
+{
+       /* The number of ticks we still have to wait
+        * before sending any notification.
+        */
+       ULONG TickCounter;
+
+       struct IBox GBox;               /* Our gadget bounds            */
+       struct IBox FrameBox;   /* Frame size and position      */
+
+       BOOL LayoutDone;                /* Need to recalculate above info? */
+};
+
+
+
+/* Local function prototypes */
+
+static ULONG   SB_GMGoActive   (Class *cl, struct Gadget *g, struct gpInput *gpi);
+static ULONG   SB_GMHandleInput(Class *cl, struct Gadget *g, struct gpInput *gpi);
+static void            SB_GMRender             (Class *cl, struct Gadget *g, struct gpRender *gpr);
+static void            SB_GMLayout             (Class *cl, struct Gadget *g, struct gpLayout *gpl);
+static ULONG   SB_OMSet                (Class *cl, struct Gadget *g, struct opUpdate *msg);
+
+static ULONG HOOKCALL ScrollButtonDispatcher(
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, Msg msg));
+
+
+
+#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB)
+
+       /* Class library support functions */
+       struct ClassLibrary     *       HOOKCALL _UserLibInit           (REG(a6, struct ClassLibrary *mybase));
+       struct ClassLibrary     *       HOOKCALL _UserLibCleanup        (REG(a6, struct ClassLibrary *mybase));
+       Class *                                 HOOKCALL _GetEngine                     (REG(a6, struct ClassLibrary *mybase));
+
+       /* Library data */
+       const UBYTE LibName[] = "scrollbutton.gadget";
+       const UBYTE LibVer[] = { '$', 'V', 'E', 'R', ':', ' ' };
+       const UBYTE LibId[] = "scrollbutton.gadget 1.0 (19.3.2000) © 1997-2000 Bernardo Innocenti\n";
+
+       /* Workaround a bug in StormC header file <proto/utility.h> */
+       #ifdef __STORM__
+               #define UTILITYBASETYPE struct Library
+       #else
+               #define UTILITYBASETYPE struct UtilityBase
+       #endif
+
+       /* Library bases */
+       struct ExecBase                 *SysBase                = NULL;
+       struct IntuitionBase    *IntuitionBase  = NULL;
+       UTILITYBASETYPE                 *UtilityBase    = NULL;
+#endif
+
+
+
+static ULONG SB_GMGoActive(Class *cl, struct Gadget *g, struct gpInput *gpi)
+{
+       struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g);
+
+       DB2(DBPRINTF("ScrollButton: GM_GOACTIVE\n");)
+       ASSERT_VALID_PTR(bd)
+
+       /* May define an attribute to make delay configurable */
+       bd->TickCounter = 3;
+
+       /* Notify our target that we have initially hit. */
+       NotifyAttrs((Object *)g, gpi->gpi_GInfo, 0,
+               GA_ID,  g->GadgetID,
+               TAG_DONE);
+
+       /* Send more input */
+       return GMR_MEACTIVE;
+}
+
+
+
+static ULONG SB_GMHandleInput(Class *cl, struct Gadget *g, struct gpInput *gpi)
+{
+       struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g);
+       struct RastPort *rp;
+       ULONG retval = GMR_MEACTIVE;
+       UWORD selected = 0;
+
+       DB2 (DBPRINTF ("ScrollButton: GM_HANDLEINPUT\n");)
+       ASSERT_VALID_PTR(bd)
+
+       /* This also works with classic (non-boopsi) images. */
+       if (PointInImage((gpi->gpi_Mouse.X << 16) + (gpi->gpi_Mouse.Y), g->GadgetRender))
+       {
+               /* We are hit */
+               selected = GFLG_SELECTED;
+       }
+
+       if (gpi->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE && gpi->gpi_IEvent->ie_Code == SELECTUP)
+       {
+               /* Gadgetup, time to go */
+               retval = GMR_NOREUSE;
+               /* Unselect the gadget on our way out... */
+               selected = 0;
+       }
+       else if (gpi->gpi_IEvent->ie_Class == IECLASS_TIMER)
+       {
+               /* We got a tick. Decrement counter, and if 0, send notify. */
+
+               if (bd->TickCounter)
+                       bd->TickCounter--;
+               else if (selected)
+                       /* Notify our target that we are still being hit */
+                       NotifyAttrs ((Object *)g, gpi->gpi_GInfo, 0,
+                               GA_ID,  g->GadgetID,
+                               TAG_DONE);
+       }
+
+       if ((g->Flags & GFLG_SELECTED) != selected)
+       {
+               /* Update changes in gadget render */
+               g->Flags ^= GFLG_SELECTED;
+               if (rp = ObtainGIRPort (gpi->gpi_GInfo))
+               {
+                       DoMethod((Object *) g, GM_RENDER, gpi->gpi_GInfo, rp, GREDRAW_UPDATE);
+                       ReleaseGIRPort(rp);
+               }
+       }
+       return retval;
+}
+
+
+
+static void SB_GMRender(Class *cl, struct Gadget *g, struct gpRender *gpr)
+{
+       struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g);
+       struct impDraw impdraw;
+
+       DB2(DBPRINTF("ScrollButton: GM_RENDER\n");)
+       ASSERT_VALID_PTR(bd)
+
+       if (!bd->LayoutDone)
+               SB_GMLayout(cl, g, (struct gpLayout *)gpr);
+
+       impdraw.MethodID        = IM_DRAWFRAME;
+       impdraw.imp_RPort       = gpr->gpr_RPort;
+       impdraw.imp_DrInfo      = gpr->gpr_GInfo->gi_DrInfo;
+
+       /* Check if we are living inside an inactive window border */
+       if ((g->Activation & (GACT_RIGHTBORDER | GACT_LEFTBORDER | GACT_TOPBORDER | GACT_BOTTOMBORDER)) &&
+               gpr->gpr_GInfo->gi_Window &&
+               (!(gpr->gpr_GInfo->gi_Window->Flags & WFLG_WINDOWACTIVE)))
+       {
+               impdraw.imp_State = (g->Flags & GFLG_SELECTED) ?
+                       IDS_INACTIVESELECTED :
+                       ((g->Flags & GFLG_DISABLED) ? IDS_INACTIVEDISABLED : IDS_INACTIVENORMAL );
+       }
+       else
+       {
+               impdraw.imp_State = (g->Flags & GFLG_SELECTED) ?
+                       ((g->Flags & GFLG_DISABLED) ? IDS_SELECTEDDISABLED : IDS_SELECTED ) :
+                       ((g->Flags & GFLG_DISABLED) ? IDS_DISABLED : IDS_NORMAL );
+       }
+
+       /* Check whether our label image is valid and can be sent a boopsi message */
+       if ((g->Flags & GFLG_LABELIMAGE) && g->GadgetText &&
+               (((struct Image *)g->GadgetText)->Depth == CUSTOMIMAGEDEPTH))
+       {
+               impdraw.imp_Offset.X    = bd->GBox.Left - bd->FrameBox.Left;
+               impdraw.imp_Offset.Y    = bd->GBox.Top - bd->FrameBox.Top;
+               impdraw.imp_Dimensions.Width    = bd->GBox.Width - bd->FrameBox.Width;
+               impdraw.imp_Dimensions.Height   = bd->GBox.Height - bd->FrameBox.Height;
+
+               DoMethodA((Object *)g->GadgetText, (Msg)&impdraw);
+       }
+
+       /* Check whether our framing image is valid and can be sent a boopsi message */
+       if ((g->Flags & GFLG_GADGIMAGE) && g->GadgetRender &&
+               (((struct Image *)g->GadgetRender)->Depth == CUSTOMIMAGEDEPTH))
+       {
+               impdraw.imp_Offset.X    = bd->GBox.Left;
+               impdraw.imp_Offset.Y    = bd->GBox.Top;
+               impdraw.imp_Dimensions.Width    = bd->GBox.Width;
+               impdraw.imp_Dimensions.Height   = bd->GBox.Height;
+
+               DoMethodA((Object *)g->GadgetRender, (Msg)&impdraw);
+       }
+}
+
+
+
+static void SB_GMLayout(Class *cl, struct Gadget *g, struct gpLayout *gpl)
+{
+       struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g);
+
+       DB2(DBPRINTF("ScrollButton: GM_LAYOUT\n");)
+       ASSERT_VALID_PTR(bd)
+
+       /* Compute new button size */
+       GetGadgetBox(gpl->gpl_GInfo, g, &bd->GBox);
+
+       /* Check if our framing image is valid and can be sent a boopsi message */
+       if ((g->Flags & GFLG_GADGIMAGE) && g->GadgetRender &&
+               (((struct Image *)g->GadgetRender)->Depth == CUSTOMIMAGEDEPTH))
+       {
+               struct IBox fakecontents = { 0, 0, 0, 0 };
+
+               /* Ask the frame what is its size */
+               DoMethod((Object *)g->GadgetRender, IM_FRAMEBOX,
+                       &fakecontents, &bd->FrameBox, gpl->gpl_GInfo->gi_DrInfo, 0);
+       }
+
+       bd->LayoutDone = TRUE;
+}
+
+
+
+static ULONG SB_OMSet (Class *cl, struct Gadget *g, struct opUpdate *msg)
+{
+       struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g);
+       struct TagItem  *ti, *tstate = msg->opu_AttrList;
+
+       DB1(DBPRINTF("ScrollButton: OM_SET\n");)
+       ASSERT_VALID_PTR(bd)
+       ASSERT_VALID_PTR(tstate)
+
+       while (ti = NextTagItem(&tstate))
+       {
+               /* Check for any of GA_Width, GA_RelWidth, GA_Height, GA_RelHeight.
+                * This test assumes that the values of these tags are consecutive
+                * and will break whenever their definitions are changed.
+                */
+               if ((ti->ti_Tag >= GA_Width) && (ti->ti_Tag <= GA_RelHeight))
+                       bd->LayoutDone = FALSE;
+       }
+
+       /* The superclass handles everything else */
+       return (DoSuperMethodA(cl, (Object *)g, (Msg) msg));
+}
+
+
+
+static ULONG HOOKCALL ScrollButtonDispatcher(
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, Msg msg))
+
+/* ScrollButton Class Dispatcher entrypoint.
+ * Handle boopsi messages.
+ */
+{
+       switch (msg->MethodID)
+       {
+               case GM_GOACTIVE:
+                       return SB_GMGoActive(cl, g, (struct gpInput *)msg);
+
+               case GM_HANDLEINPUT:
+                       return SB_GMHandleInput(cl, g, (struct gpInput *)msg);
+
+               case GM_RENDER:
+                       SB_GMRender(cl, g, (struct gpRender *)msg);
+                       return TRUE;
+
+               case GM_LAYOUT:
+                       SB_GMLayout(cl, g, (struct gpLayout *)msg);
+                       return TRUE;
+
+               case OM_SET:
+               case OM_UPDATE:
+                       return SB_OMSet(cl, g, (struct opUpdate *)msg);
+
+               default:
+                       /* Super class handles everything else */
+                       return (DoSuperMethodA(cl, (Object *)g, msg));
+       }
+}
+
+
+
+Class *MakeScrollButtonClass (void)
+{
+       Class *class;
+
+       if (class = MakeClass(NULL, BUTTONGCLASS, NULL, sizeof(struct ScrollButtonData), 0))
+               class->cl_Dispatcher.h_Entry = (ULONG (*)()) ScrollButtonDispatcher;
+
+       return class;
+}
+
+Class *MakeFrScrollButtonClass (void)
+{
+       Class *class;
+
+       if (class = MakeClass (NULL, FRBUTTONCLASS, NULL, sizeof(struct ScrollButtonData), 0))
+               class->cl_Dispatcher.h_Entry = (ULONG (*)()) ScrollButtonDispatcher;
+
+       return class;
+}
+
+BOOL FreeScrollButtonClass (Class *cl)
+{
+       return (FreeClass(cl));
+}
+
+
+
+#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB)
+/*
+ * Class library support functions
+ */
+
+struct ClassLibrary * HOOKCALL _UserLibInit(REG(a6, struct ClassLibrary *mybase))
+{
+       /* Initialize SysBase */
+       SysBase = *((struct ExecBase **)4UL);
+
+       if (!((UtilityBase = (UTILITYBASETYPE *) OpenLibrary("utility.library", 39)) &&
+               (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39))))
+       {
+               _UserLibCleanup(mybase);
+               return NULL;
+       }
+
+       if (!(mybase->cl_Class = MakeScrollButtonClass()))
+       {
+               _UserLibCleanup(mybase);
+               return NULL;
+       }
+
+       AddClass(mybase->cl_Class);
+       return mybase;
+}
+
+struct ClassLibrary * HOOKCALL _UserLibCleanup(REG(a6, struct ClassLibrary *mybase))
+{
+       if (mybase->cl_Class)
+               if (!FreeScrollButtonClass(mybase->cl_Class))
+                       return NULL;
+
+       CloseLibrary((struct Library *)IntuitionBase);
+       CloseLibrary((struct Library *)UtilityBase);
+
+       return mybase;
+}
+
+Class * HOOKCALL _GetEngine(REG(a6, struct ClassLibrary *mybase))
+{
+       return mybase->cl_Class;
+}
+
+#endif /* (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) */
diff --git a/gadgets/SliderBar/FrPropGClass.c b/gadgets/SliderBar/FrPropGClass.c
new file mode 100644 (file)
index 0000000..3640553
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+**     $Id: FrPropGClass.c,v 1.1 1999/02/07 14:24:42 bernie Exp $
+**
+**     Copyright (C) 1999,2000 Bernardo Innocenti
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     A simple subclass of the propgclass which can be surrounded
+**     by a boopsi frame image specified through the GA_LabelImage tag.
+*/
+
+#define USE_BUILTIN_MATH
+#define INTUI_V36_NAMES_ONLY
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H            /* Avoid dupe defs of boopsi funcs */
+
+
+#include <intuition/gadgetclass.h>
+#include <intuition/imageclass.h>
+#include <proto/intuition.h>
+
+#ifdef __STORM__
+       #pragma header
+#endif
+
+#include "CompilerSpecific.h"
+#include "DebugMacros.h"
+#include "BoopsiStubs.h"
+
+#include "FrPropGClass.h"
+
+
+
+
+/* Per object instance data */
+struct FrPropData
+{
+       Object *        Frame;
+       struct IBox FrameBox;
+};
+
+
+
+/* ScrollButton Class Dispatcher entrypoint.
+ * Handle boopsi messages.
+ */
+static ULONG HOOKCALL FrPropDispatcher (
+       REG(a0, Class * cl),
+       REG(a2, struct Gadget * g),
+       REG(a1, Msg msg))
+{
+       struct FrPropData *fpd;
+
+       switch (msg->MethodID)
+       {
+               case OM_NEW:
+                       DB2(DBPRINTF("FrPropGClass: OM_NEW\n");)
+
+                       if (g = (struct Gadget *)DoSuperMethodA (cl, (Object *)g, (Msg)msg))
+                       {
+                               fpd = (struct FrPropData *) INST_DATA(cl, g);
+
+                               /* HACK: the gadgetclass copies the contents
+                                * of the GA_LabelImage tag into the Gadget structure.
+                                * We steal the frame from there and then clear it,
+                                * otherwise the gadgetclass will try to draw the frame
+                                * itself.
+                                */
+                               fpd->Frame = (Object *) g->GadgetText;
+                               g->GadgetText = NULL;
+                               g->Flags &= ~GFLG_LABELIMAGE;
+
+                               /* Ask Intuition to send us GM_LAYOUT messages */
+                               g->Flags |= GFLG_RELSPECIAL;
+                       }
+                       return (ULONG)g;
+
+               case GM_LAYOUT:
+                       DB2(DBPRINTF("FrPropGClass: GM_LAYOUT\n");)
+
+                       fpd = (struct FrPropData *) INST_DATA(cl, g);
+
+                       if (fpd->Frame)
+                       {
+                               struct IBox gbox;
+
+                               /* Compute current gadget size */
+                               GetGadgetBox(((struct gpLayout *)msg)->gpl_GInfo, g, &gbox);
+
+                               DB2(DBPRINTF("FrPropGClass:   GBox :%ld t:%ld w:%ld h:%ld\n",
+                                               fpd->FrameBox.Left, fpd->FrameBox.Top,
+                                               fpd->FrameBox.Width, fpd->FrameBox.Height);)
+
+                               /* Calculate dimensions of our framing image */
+                               DoMethod(fpd->Frame, IM_FRAMEBOX, &gbox, &fpd->FrameBox,
+                                       ((struct gpLayout *)msg)->gpl_GInfo->gi_DrInfo, 0);
+                       }
+                       break; /* go to DoSuperMethod() below */
+
+               case GM_RENDER:
+                       if (((struct gpRender *)msg)->gpr_Redraw == GREDRAW_REDRAW)
+                       {
+                               fpd = (struct FrPropData *) INST_DATA(cl, g);
+                               DB2(DBPRINTF("FrPropGClass: GM_RENDER - GREDRAW_REDRAW\n");)
+                               ASSERT_VALID_PTR(fpd)
+
+                               if (fpd->Frame)
+                               {
+                                       ASSERT_VALID_PTR(fpd->Frame)
+                                       DB2(DBPRINTF("FrPropGClass:   Frame l:%ld t:%ld w:%ld h:%ld\n",
+                                               fpd->FrameBox.Left, fpd->FrameBox.Top,
+                                               fpd->FrameBox.Width, fpd->FrameBox.Height);)
+
+                                       DoMethod(fpd->Frame, IM_DRAWFRAME,
+                                               ((struct gpRender *)msg)->gpr_RPort,                                    /* imp_RPort            */
+                                               (fpd->FrameBox.Left << 16) | (fpd->FrameBox.Top),               /* imp_Offset           */
+                                               IDS_NORMAL,                                                                                             /* imp_State            */
+                                               ((struct gpRender *)msg)->gpr_GInfo->gi_DrInfo,                 /* imp_DrInfo           */
+                                               (fpd->FrameBox.Width << 16) | (fpd->FrameBox.Height));  /* imp_Dimensions       */
+                               }
+                       }
+                       break; /* go to DoSuperMethod() below */
+
+               case OM_UPDATE:
+               {
+                       ULONG result;
+                       Class *oldclass;
+
+                       /* This is a dirty workaround for a bug in the propgclass.
+                        *
+                        * It appears that the dispatcher of the propgclass detects
+                        * when an object is made from a subclass. In this case,
+                        * it stops sending itself the GM_REDRAW message when the
+                        * PGA_#? attributes are updated. The result is that the
+                        * prop does not update its visual when the attributes are
+                        * changed.
+                        *
+                        * The workaround we use here is to temporarly switch the
+                        * object true class to propgclass before passing the
+                        * OM_UPDATE method to our superclass.
+                        */
+                       oldclass = OCLASS(g);
+                       OCLASS(g) = cl->cl_Super;
+                       result = CoerceMethodA (cl->cl_Super, (Object *)g, msg);
+                       OCLASS(g) = oldclass;
+                       return result;
+               }
+
+               default:
+                       break; /* go to DoSuperMethod() below */
+       }
+
+       /* Super class handles everything */
+       return (DoSuperMethodA (cl, (Object *)g, msg));
+}
+
+
+
+Class * MakeFrPropGClass(void)
+{
+       Class * class;
+
+       if (class = MakeClass (NULL, PROPGCLASS, NULL, sizeof(struct FrPropData), 0))
+               class->cl_Dispatcher.h_Entry = (ULONG (*)()) FrPropDispatcher;
+
+       return class;
+}
+
+
+
+BOOL FreeFrPropGClass(Class *cl)
+{
+       return (FreeClass(cl));
+}
diff --git a/gadgets/SliderBar/Makefile b/gadgets/SliderBar/Makefile
new file mode 100644 (file)
index 0000000..3fb8976
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(BOOPSITOP)/config.mk
+include config.mk
+
+ARG_COMMON :=
+ARG_ALL := $(ARG_COMMON)
+ARG_LIB := $(ARG_COMMON)
+ARG_DEBUG := $(ARG_COMMON)
+ARG_PRIVATE := $(ARG_COMMON)
+ARG_OBJ := $(ARG_COMMON)
+ARG_INSTALL := $(ARG_COMMON)
+
+DEP_COMMON :=
+DEP_ALL := $(DEP_COMMON)
+DEP_LIB := $(DEP_COMMON)
+DEP_DEBUG := $(DEP_COMMON)
+DEP_PRIVATE := $(DEP_COMMON)
+DEP_OBJ := $(DEP_COMMON)
+
+include $(BOOPSITOP)/common/general.mk
+
diff --git a/gadgets/SliderBar/SliderBarDemo.c b/gadgets/SliderBar/SliderBarDemo.c
new file mode 100644 (file)
index 0000000..c6ac67b
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+**     $Id: SliderBarDemo.c,v 1.1 1999/02/07 14:24:43 bernie Exp $
+**
+**     Copyright (C) 1999 Bernardo Innocenti (<bernardo.innocenti@usa.net>)
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**
+**     Introduction
+**     ============
+**
+**     This program shows the usage of the `boopsi' "sliderbargclass" gadget.
+**     It can only be started from the shell (not from Workbench).
+**
+**
+**     Compiling
+**     =========
+**
+**     This project can be compiled with SAS/C 6.58 or better and
+**     StormC 2.00.23 or better. You get the smaller and faster
+**     executable with SAS/C. SAS/C will give you a couple of warnings
+**     on the library bases which are defined static. This warning can't be
+**     fixed without patching the system headers. Don't worry about it.
+**
+**
+**     History
+**     =======
+**
+**     1.0 (30.1.99)   First release
+**
+**
+**     Known Bugs
+**     ==========
+**
+**             - This code has never been tested on V37.
+**
+**
+**     License
+**     =======
+**
+**     This software is freely distributable as long as the source code,
+**     documentation and executables are kept together.  Permission is granted
+**     to release modified versions of this program as long as all existing
+**     copyright notices are left intact.
+*/
+
+#define INTUI_V36_NAMES_ONLY
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H    /* Avoid including this header file because of
+                                                        * conflicting definitions in BoopsiStubs.h
+                                                        */
+
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <exec/execbase.h>
+
+#include <dos/dos.h>
+
+#include <intuition/intuition.h>
+#include <intuition/intuitionbase.h>
+#include <intuition/screens.h>
+#include <intuition/classes.h>
+#include <intuition/gadgetclass.h>
+#include <intuition/icclass.h>
+
+#include <proto/exec.h>
+#include <proto/intuition.h>
+
+#include "CompilerSpecific.h"
+#include "DebugMacros.h"
+#include "BoopsiStubs.h"
+
+#include "SliderBarGClass.h"
+
+
+/* Local function prototypes */
+LONG SAVEDS                                     main                   (void);
+static struct SBDHandle                *OpenSBDWin             (UBYTE *pubscreen, ULONG left, ULONG top,
+                                                                                       ULONG width, ULONG height);
+static void                                     CloseSBDWin    (struct SBDHandle *sbdhandle);
+static struct Gadget           *CreateGadgets  (struct SBDHandle *sbdhandle);
+static void                                     DisposeGadgets (struct SBDHandle *sbdhandle);
+static struct ClassLibrary     *OpenClass              (STRPTR name, ULONG version);
+
+
+
+/* This structure describes an open SliderBarDemo window */
+
+struct SBDHandle
+{
+       struct Window   *Win;
+       struct Screen   *Scr;
+       struct Gadget   *Slider[4];
+};
+
+
+
+/* Version tag */
+
+static UBYTE versiontag[] = "$VER: SlideBarDemo 1.0 (30.1.99) by Bernardo Innocenti";
+
+
+/* Library bases */
+static struct ExecBase         *SysBase;
+static struct IntuitionBase    *IntuitionBase;
+
+/* `boopsi' class library base */
+static struct ClassLibrary     *SliderBarBase;
+
+
+
+LONG SAVEDS _main (void)
+
+/* Main program entry point.  When linking without startup code, this
+ * must be the first function in the first object module listed on the
+ * linker command line.  We also need to initialize SysBase and open
+ * all needed libraries manually.
+ */
+{
+       struct SBDHandle *sbdhandle;
+       LONG                     sigwait, sigrcvd;
+       LONG                     retval = RETURN_FAIL;
+       BOOL                     quit   = FALSE;
+
+
+       /* Initialize SysBase */
+       SysBase = *((struct ExecBase **)4UL);
+
+       if (IntuitionBase = (struct IntuitionBase *)OpenLibrary ("intuition.library", 39L))
+       {
+               if (SliderBarBase = OpenClass ("sliderbar.gadget", 0))
+               {
+                       if (sbdhandle = OpenSBDWin (NULL, 0, 20, 320, 200))
+                       {
+                               /* Pre-calculate the signal mask for Wait() */
+                               sigwait = (1 << sbdhandle->Win->UserPort->mp_SigBit) |
+                                       SIGBREAKF_CTRL_C;
+
+                               /* Now for the main loop.  As you can see, it is really
+                                * very compact. That's the magic of boopsi! :-)
+                                */
+                               while (!quit)
+                               {
+                                       /* Sleep until something interesting occurs */
+                                       sigrcvd = Wait (sigwait);
+
+                                       /* Now handle received signals */
+
+                                       /* Break signal? */
+                                       if (sigrcvd & SIGBREAKF_CTRL_C)
+                                               quit = TRUE;
+
+                                       /* IDCMP message? */
+                                       if (sigrcvd & (1 << sbdhandle->Win->UserPort->mp_SigBit))
+                                       {
+                                               struct IntuiMessage     *msg;
+
+                                               while (msg = (struct IntuiMessage *) GetMsg (sbdhandle->Win->UserPort))
+                                               {
+                                                       switch (msg->Class)
+                                                       {
+                                                               case IDCMP_CLOSEWINDOW:
+                                                                       quit = TRUE;
+                                                                       break;
+
+                                                               default:
+                                                                       break;
+                                                       }
+                                                       ReplyMsg ((struct Message *) msg);
+                                               }
+                                       }
+                               } /* End while (!quit) */
+
+                               retval = RETURN_OK;
+
+                               CloseSBDWin (sbdhandle);
+                       }
+
+                       /* This cannot fail. Passing NULL is ok. */
+                       CloseLibrary ((struct Library *)SliderBarBase);
+               }
+               CloseLibrary ((struct Library *)IntuitionBase);
+       }
+
+       return retval;
+}
+
+
+
+static struct SBDHandle *OpenSBDWin (UBYTE *pubscreen,
+       ULONG left, ULONG top, ULONG width, ULONG height)
+{
+       struct SBDHandle        *sbdhandle;
+       struct Gadget           *glist;
+
+       if (sbdhandle = AllocMem (sizeof (struct SBDHandle), MEMF_ANY | MEMF_CLEAR))
+       {
+               if (sbdhandle->Scr = LockPubScreen (pubscreen))
+               {
+                       if (glist = CreateGadgets (sbdhandle))
+                       {
+                               if (sbdhandle->Win = OpenWindowTags (NULL,
+                                       WA_Top,                         top,
+                                       WA_Left,                        left,
+                                       WA_InnerWidth,          width,
+                                       WA_InnerHeight,         height,
+                                       WA_PubScreen,           sbdhandle->Scr,
+                                       WA_PubScreenFallBack, TRUE,
+                                       WA_AutoAdjust,          TRUE,
+                                       WA_IDCMP,                       IDCMP_CLOSEWINDOW,
+                                       WA_Flags,                       WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
+                                                                               WFLG_SIZEGADGET | WFLG_SIMPLE_REFRESH | WFLG_NOCAREREFRESH,
+                                       WA_Gadgets,                     glist,
+                                       WA_Title,                       versiontag + 6,
+                                       WA_MinWidth,            64,
+                                       WA_MinHeight,           64,
+                                       WA_MaxWidth,            -1,
+                                       WA_MaxHeight,           -1,
+                                       TAG_DONE))
+                               {
+                                       UnlockPubScreen (NULL, sbdhandle->Scr);
+                                       return sbdhandle;
+                               }
+                               DisposeGadgets (sbdhandle);
+                       }
+                       UnlockPubScreen (NULL, sbdhandle->Scr);
+               }
+               FreeMem (sbdhandle, sizeof (struct SBDHandle));
+       }
+       return NULL;
+}
+
+
+
+static void CloseSBDWin (struct SBDHandle *sbdhandle)
+{
+       /* Close our window. No need to reply queued messages,
+        * Intuition is clever enough to care about this for us.
+        */
+       CloseWindow (sbdhandle->Win);
+       DisposeGadgets (sbdhandle);
+       FreeMem (sbdhandle, sizeof (struct SBDHandle));
+}
+
+#define SLIDER_THICKNESS 20
+
+static struct Gadget *CreateGadgets (struct SBDHandle *sbdhandle)
+{
+       struct Screen   *scr = sbdhandle->Scr;
+       LONG left,right, top, bottom, width, height;
+
+
+       left    = scr->WBorLeft + 10;
+       right   = - scr->WBorRight - 25 - SLIDER_THICKNESS;
+       top             = scr->WBorTop + scr->Font->ta_YSize + 10;
+       bottom  = - scr->WBorBottom - 10 - SLIDER_THICKNESS;
+       width   = right - left - 1;
+       height  = bottom - top - 1;
+
+       sbdhandle->Slider[0] = NewObject (NULL, SLIDERBARGCLASS,
+               GA_Left,                left,
+               GA_Top,                 top,
+               GA_Width,               SLIDER_THICKNESS,
+               GA_RelHeight,   height,
+               PGA_Total,              120,
+               PGA_Top,                50,
+               PGA_Visible,    20,
+               LAYOUTA_Orientation, LORIENT_VERT,
+               TAG_DONE);
+
+       sbdhandle->Slider[1] = NewObject (NULL, SLIDERBARGCLASS,
+               GA_Previous,    sbdhandle->Slider[0],
+               GA_Left,                left,
+               GA_RelBottom,   bottom,
+               GA_RelWidth,    width + SLIDER_THICKNESS,
+               GA_Height,              SLIDER_THICKNESS,
+               PGA_Total,              140,
+               PGA_Top,                50,
+               PGA_Visible,    40,
+               LAYOUTA_Orientation, LORIENT_HORIZ,
+               ICA_TARGET,             sbdhandle->Slider[0],
+               TAG_DONE);
+
+       sbdhandle->Slider[2] = NewObject (NULL, SLIDERBARGCLASS,
+               GA_Previous,    sbdhandle->Slider[1],
+               GA_RelRight,    right,
+               GA_Top,                 top,
+               GA_Width,               SLIDER_THICKNESS,
+               GA_RelHeight,   height,
+               PGA_Total,              140,
+               PGA_Top,                50,
+               PGA_Visible,    40,
+               LAYOUTA_Orientation, LORIENT_VERT,
+               ICA_TARGET,             sbdhandle->Slider[1],
+               TAG_DONE);
+
+       sbdhandle->Slider[3] = NewObject (NULL, SLIDERBARGCLASS,
+               GA_Previous,    sbdhandle->Slider[2],
+               GA_Top,                 top,
+               GA_Left,                left + SLIDER_THICKNESS,
+               GA_RelWidth,    width - SLIDER_THICKNESS,
+               GA_Height,              SLIDER_THICKNESS,
+               PGA_Total,              140,
+               PGA_Top,                50,
+               PGA_Visible,    40,
+               LAYOUTA_Orientation, LORIENT_HORIZ,
+               ICA_TARGET,             sbdhandle->Slider[2],
+               TAG_DONE);
+
+
+       if (sbdhandle->Slider[0] &&
+               sbdhandle->Slider[1] &&
+               sbdhandle->Slider[2] &&
+               sbdhandle->Slider[3])
+       {
+               return sbdhandle->Slider[0];
+       }
+       else
+       {
+               DisposeGadgets (sbdhandle);
+               return NULL;
+       }
+}
+
+
+
+static void DisposeGadgets (struct SBDHandle *sbdhandle)
+{
+       int i;
+
+       for (i = 0; i < 4; i++)
+               DisposeObject (sbdhandle->Slider[i]);
+}
+
+
+
+static struct ClassLibrary *OpenClass (STRPTR name, ULONG version)
+
+/* Open named class. Look both in current and gadgets/ directory
+ */
+{
+       static struct EasyStruct OpenClassES =
+       {
+               sizeof (struct EasyStruct),
+               0,
+               versiontag + 6,
+               "Couldn't open %s version %ld or greater",
+               "Ok"
+       };
+       static const char prefix[] = "gadgets/";
+
+       struct ClassLibrary *classbase;
+       char buf[256];
+       int i;
+
+
+       if (!(classbase = (struct ClassLibrary *)OpenLibrary (name, version)))
+       {
+               /* We can't use AddPart() here because we didn't open dos.library */
+
+               /* Copy the prefix in the buffer */
+               for (i = 0; buf[i] = prefix[i]; i++);
+
+               /* Append the name */
+               while (buf[i++] = *name++);
+
+               /* Try again */
+               classbase = (struct ClassLibrary *)OpenLibrary (buf, version);
+
+               if (!classbase)
+               {
+                       /* Report an error */
+                       EasyRequest (NULL, &OpenClassES, NULL, buf, version);
+               }
+       }
+       return classbase;
+}
diff --git a/gadgets/SliderBar/SliderBarGClass.c b/gadgets/SliderBar/SliderBarGClass.c
new file mode 100644 (file)
index 0000000..700b66d
--- /dev/null
@@ -0,0 +1,773 @@
+/*
+**     $Id: SliderBarGClass.c,v 1.1 1999/02/07 14:24:43 bernie Exp $
+**
+**     Copyright (C) 1999 Bernardo Innocenti
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     "sliderbargclass", a GadTools like slider with scroll buttons.
+**     See the header file "SliderBarGClass.h" for class documentation.
+*/
+
+/* Supported class flavours:
+ *
+ * FLAVOUR_CLASSLIB
+ *     Build a class library if this option is set or
+ *     a static linker object otherwise.
+ *
+ * FLAVOUR_PUBCLASS
+ *     Call AddClass() to show this class globally if set,
+ *     make a private class otherwise.
+ */
+#define FLAVOUR_CLASSLIB       (1<<0)
+#define FLAVOUR_PUBCLASS       (1<<1)
+
+#define CLASS_FLAVOUR (FLAVOUR_CLASSLIB | FLAVOUR_PUBCLASS)
+
+/* Definitions for system headers */
+#define USE_BUILTIN_MATH
+#define INTUI_V36_NAMES_ONLY
+#define INTUITION_IOBSOLETE_H
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H            /* Avoid dupe defines of boopsi funcs */
+
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <utility/tagitem.h>
+#include <intuition/intuition.h>
+#include <intuition/classes.h>
+#include <intuition/classusr.h>
+#include <intuition/gadgetclass.h>
+#include <intuition/imageclass.h>
+#include <intuition/icclass.h>
+
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <proto/utility.h>
+
+#include <CompilerSpecific.h>
+#include <DebugMacros.h>
+#include <DiagnosticMacros.h>
+#include <BoopsiStubs.h>
+
+#include <images/VectorGlyphIClass.h>
+#include <gadgets/SmartGroupGClass.h>
+#include <gadgets/ScrollButtonClass.h>
+#include "FrPropGClass.h"
+#include "SliderBarGClass.h"
+
+#ifdef __STORM__
+       #pragma header
+#endif
+
+
+#define        BUTTON_WIDTH    16
+#define        BUTTON_HEIGHT   16
+
+/* Local function prototypes */
+
+INLINE void GetGadgetBox (struct GadgetInfo *ginfo, struct Gadget *g, struct IBox *box);
+
+static ULONG HOOKCALL SliderBarDispatcher (
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, Msg msg));
+
+static void            SB_GMLayout     (Class *cl, struct Gadget *g, struct gpLayout *msg);
+static ULONG   SB_OMNew        (Class *cl, struct Gadget *g, struct opSet *msg);
+static void            SB_OMDispose(Class *cl, struct Gadget *g, Msg msg);
+static ULONG   SB_OMGet        (Class *cl, struct Gadget *g, struct opGet *msg);
+static ULONG   SB_OMSet        (Class *cl, struct Gadget *g, struct opUpdate *msg);
+
+
+
+/* Per-object instance data */
+struct SBData
+{
+       /* Children */
+       Object *Prop, *DecButton, *IncButton;
+
+       /* VectorGlyph images for the buttons */
+       Object *IncImage, *DecImage;
+
+       /* Copy of prop attributes */
+       LONG    Top, Total, Visible;
+
+       /* Slider orientation: can be LORIENT_VERT or LORIENT_HORIZ */
+       ULONG   Orientation;
+};
+
+
+
+/* Global class data */
+struct SBClassData
+{
+       /* Boopsi frame to put around our children */
+       Object                          *Frame;
+
+       /* Classes we are using */
+       Class                           *SmartGroupGClass;
+       Class                           *FrScrollButtonClass;
+       Class                           *FrPropGClass;
+       Class                           *VectorGlyphIClass;
+       struct ClassLibrary     *VectorGlyphBase;
+};
+
+
+#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB)
+
+       /* Class library support functions */
+       struct ClassLibrary     *       HOOKCALL _UserLibInit           (REG(a6, struct ClassLibrary *mybase));
+       struct ClassLibrary     *       HOOKCALL _UserLibCleanup        (REG(a6, struct ClassLibrary *mybase));
+       Class *                                 HOOKCALL _GetEngine                     (REG(a6, struct ClassLibrary *mybase));
+
+       /* Library data */
+       const UBYTE LibName[] = "sliderbar.gadget";
+       const UBYTE LibVer[] = { '$', 'V', 'E', 'R', ':', ' ' };
+       const UBYTE LibId[] = "sliderbar.gadget 1.0 (30.1.99) © 1999 Bernardo Innocenti\n";
+
+       /* Workaround a bug in StormC header file <proto/utility.h> */
+       #ifdef __STORM__
+               #define UTILITYBASETYPE struct Library
+       #else
+               #define UTILITYBASETYPE struct UtilityBase
+       #endif
+
+       /* Library bases - also used by the FrScrollButtonClass and the FrPropGClass */
+       struct ExecBase                 *SysBase                = NULL;
+       struct IntuitionBase    *IntuitionBase  = NULL;
+       UTILITYBASETYPE                 *UtilityBase    = NULL;
+#endif
+
+
+/* Static variables */
+
+static LONG MapPropToSB[] =
+{
+       PGA_Top,        SBA_InternalTop,
+       TAG_DONE
+};
+
+
+static LONG MapButtonToSB[] =
+{
+       GA_ID,          SBA_Adjust,
+       TAG_DONE
+};
+
+
+
+INLINE void GetGadgetBox (struct GadgetInfo *ginfo, struct Gadget *g, struct IBox *box)
+
+/* Gets the actual IBox where a gadget exists in a window.
+ * The special cases it handles are all the REL#? (relative positioning flags).
+ *
+ * This function returns the gadget size in the provided IBox structure,
+ * computing the values from the coordinates of the gadget and the window
+ * inside which it lives.
+ */
+{
+       ASSERT_VALID_PTR(g)
+       ASSERT_VALID_PTR(ginfo)
+       ASSERT_VALID_PTR(box)
+
+       box->Left = g->LeftEdge;
+       if (g->Flags & GFLG_RELRIGHT)
+               box->Left += ginfo->gi_Domain.Width - 1;
+
+       box->Top = g->TopEdge;
+       if (g->Flags & GFLG_RELBOTTOM)
+               box->Top += ginfo->gi_Domain.Height - 1;
+
+       box->Width = g->Width;
+       if (g->Flags & GFLG_RELWIDTH)
+               box->Width += ginfo->gi_Domain.Width;
+
+       box->Height = g->Height;
+       if (g->Flags & GFLG_RELHEIGHT)
+               box->Height += ginfo->gi_Domain.Height;
+}
+
+
+
+static void SB_GMLayout (Class *cl, struct Gadget *g, struct gpLayout *msg)
+{
+       struct SBData           *sb = (struct SBData *) INST_DATA (cl, (Object *)g);
+       struct SBClassData      *classdata = (struct SBClassData *)cl->cl_UserData;
+       struct IBox gbox, framebox, contentsbox = { 0, 0, 0, 0 };
+
+       DB2 (kprintf ("SliderBarClass: GM_LAYOUT\n");)
+       ASSERT_VALID_PTR(sb)
+       ASSERT_VALID_PTR(classdata)
+
+
+       /* Collect new group size */
+       GetGadgetBox (msg->gpl_GInfo, g, &gbox);
+
+       /* Query the frame on its nominal width and height */
+       DoMethod (classdata->Frame, IM_FRAMEBOX, &contentsbox, &framebox,
+               msg->gpl_GInfo->gi_DrInfo, 0);
+
+       /* Size our children accordingly */
+
+       if (sb->Orientation == LORIENT_VERT)
+       {
+               SetAttrs (sb->Prop,
+                       GA_Left,        gbox.Left + framebox.Width / 2,
+                       GA_Top,         gbox.Top + framebox.Height / 2,
+                       GA_Width,       gbox.Width - framebox.Width,
+                       GA_Height,      gbox.Height - framebox.Height - BUTTON_HEIGHT * 2,
+                       TAG_DONE);
+
+               if (sb->DecButton)
+                       SetAttrs (sb->DecButton,
+                               GA_Left,        gbox.Left,
+                               GA_Top,         gbox.Top + gbox.Height - BUTTON_HEIGHT * 2,
+                               GA_Width,       gbox.Width,
+                               GA_Height,      BUTTON_HEIGHT,
+                               TAG_DONE);
+
+               if (sb->IncButton)
+                       SetAttrs (sb->IncButton,
+                               GA_Left,        gbox.Left,
+                               GA_Top,         gbox.Top + gbox.Height - BUTTON_HEIGHT,
+                               GA_Width,       gbox.Width,
+                               GA_Height,      BUTTON_HEIGHT,
+                               TAG_DONE);
+       }
+       else /* LORIENT_HORIZ */
+       {
+               SetAttrs (sb->Prop,
+                       GA_Left,        gbox.Left + framebox.Width / 2,
+                       GA_Top,         gbox.Top + framebox.Height / 2,
+                       GA_Width,       gbox.Width - framebox.Width - BUTTON_WIDTH * 2,
+                       GA_Height,      gbox.Height - framebox.Height,
+                       TAG_DONE);
+
+               if (sb->DecButton)
+                       SetAttrs (sb->DecButton,
+                               GA_Left,        gbox.Left + gbox.Width - BUTTON_WIDTH * 2,
+                               GA_Top,         gbox.Top,
+                               GA_Width,       BUTTON_WIDTH,
+                               GA_Height,      gbox.Height,
+                               TAG_DONE);
+
+               if (sb->IncButton)
+                       SetAttrs (sb->IncButton,
+                               GA_Left,        gbox.Left + gbox.Width - BUTTON_WIDTH,
+                               GA_Top,         gbox.Top,
+                               GA_Width,       BUTTON_WIDTH,
+                               GA_Height,      gbox.Height,
+                               TAG_DONE);
+       }
+
+       DoSuperMethodA (cl, (Object *)g, (Msg)msg);
+}
+
+
+
+static ULONG SB_OMNew (Class *cl, struct Gadget *g, struct opSet *msg)
+{
+       struct SBData           *sb;
+       struct SBClassData      *classdata;
+
+       DB2 (DBPRINTF ("SliderBarGClass: OM_NEW\n");)
+
+       if (g = (struct Gadget *)DoSuperMethodA (cl, (Object *)g, (Msg)msg))
+       {
+               classdata = (struct SBClassData *)cl->cl_UserData;
+               sb = (struct SBData *) INST_DATA (cl, (Object *)g);
+               ASSERT_VALID_PTR(sb)
+               ASSERT_VALID_PTR(classdata)
+
+
+               /* Initialize the object instance */
+               sb->DecButton = NULL;
+               sb->IncButton = NULL;
+               sb->IncImage = NULL;
+               sb->DecImage = NULL;
+               sb->Orientation = GetTagData (LAYOUTA_Orientation, LORIENT_HORIZ, msg->ops_AttrList);
+               sb->Top         = GetTagData (PGA_Top, 0, msg->ops_AttrList);
+               sb->Total       = GetTagData (PGA_Total, 0, msg->ops_AttrList);
+               sb->Visible     = GetTagData (PGA_Visible, 0, msg->ops_AttrList);
+
+               if (sb->Prop = NewObject (classdata->FrPropGClass, NULL,
+                       GA_ID,                  g->GadgetID,    /* Same as our ID */
+                       GA_LabelImage,  classdata->Frame,
+                       PGA_Freedom,    (sb->Orientation == LORIENT_VERT) ? FREEVERT : FREEHORIZ,
+                       PGA_NewLook,    TRUE,
+                       PGA_Borderless, TRUE,
+                       PGA_Top,                sb->Top,
+                       PGA_Total,              sb->Total,
+                       PGA_Visible,    sb->Visible,
+                       ICA_TARGET,             g,      /* target on us */
+                       ICA_MAP,                MapPropToSB,
+                       TAG_DONE))
+               {
+                       /* From now on, the groupgclass will dispose this object for us */
+                       DoMethod ((Object *)g, OM_ADDMEMBER, sb->Prop);
+
+                       /* Don't bother checking for failure here:
+                        * the images are not mission-critical.
+                        */
+                       sb->DecImage = NewObject (classdata->VectorGlyphIClass, NULL,
+                               SYSIA_Which, (sb->Orientation == LORIENT_VERT) ? VG_UPARROW : VG_LEFTARROW,
+                               TAG_DONE);
+
+                       if (sb->DecButton = NewObject (classdata->FrScrollButtonClass, NULL,
+                               GA_ID,                  -1,
+                               GA_LabelImage,  sb->DecImage,
+                               GA_Image,               classdata->Frame,
+                               ICA_TARGET,             g, /* target on us */
+                               ICA_MAP,                MapButtonToSB,
+                               TAG_DONE))
+                       {
+                               /* From now on, the groupgclass will dispose this object for us */
+                               DoMethod ((Object *)g, OM_ADDMEMBER, sb->DecButton);
+                       }
+
+                       /* Don't bother checking for failure here:
+                        * the images are not mission-critical.
+                        */
+                       sb->IncImage = NewObject (classdata->VectorGlyphIClass, NULL,
+                               SYSIA_Which, (sb->Orientation == LORIENT_VERT) ? VG_DOWNARROW : VG_RIGHTARROW,
+                               TAG_DONE);
+
+                       if (sb->IncButton = NewObject (classdata->FrScrollButtonClass, NULL,
+                               GA_ID,                  +1,
+                               GA_LabelImage,  sb->IncImage,
+                               GA_Image,               classdata->Frame,
+                               ICA_TARGET,             g, /* target on us */
+                               ICA_MAP,                MapButtonToSB,
+                               TAG_DONE))
+                       {
+                               /* From now on, the groupgclass will dispose this object for us */
+                               DoMethod ((Object *)g, OM_ADDMEMBER, sb->IncButton);
+                       }
+
+                       return (ULONG)g;        /* Return newly created instance */
+               }
+
+               /* Commit suicide without disturbing the dispatchers of our subclasses */
+               CoerceMethod (cl, (Object *)g, OM_DISPOSE);
+       }
+
+       return 0;       /* Fail */
+}
+
+
+
+static void SB_OMDispose (Class *cl, struct Gadget *g, Msg msg)
+{
+       struct SBData *sb = (struct SBData *) INST_DATA (cl, (Object *)g);
+
+       /* The groupgclass will dispose all our children for us */
+
+       DisposeObject (sb->IncImage);
+       DisposeObject (sb->DecImage);
+
+       /* Our superclass will cleanup everything else now */
+       DoSuperMethodA (cl, (Object *)g, msg);
+
+       /* From now on, our instance data is no longer available */
+}
+
+
+static ULONG SB_OMSet (Class *cl, struct Gadget *g, struct opUpdate *msg)
+{
+       struct SBData   *sb = INST_DATA (cl, g);
+       struct TagItem  *ti, *tstate = msg->opu_AttrList;
+       ULONG action = 0;       /* see flag definitions below */
+       ULONG result;
+
+       ASSERT_VALID_PTR(sb)
+       ASSERT_VALID_PTR_OR_NULL(tstate)
+
+       DB2 (DBPRINTF ((msg->MethodID == OM_SET) ?
+               "SliderBarGClass: OM_SET\n" :
+               "SliderBarGClass: OM_UPDATE\n");)
+
+
+       /* Definitions for the ations to be taken right after
+        * scanning the attributes list in OM_SET/OM_UPDATE.
+        * For speed reasons we pack them together in a single variable,
+        * so we can set and test multiple flags in once.
+        */
+       #define ACTIONF_DO_SUPER_METHOD (1<<0)
+       #define ACTIONF_NOTIFY_TOP              (1<<1)
+       #define ACTIONF_NOTIFY_ALL              (1<<2)
+       #define ACTIONF_UPDATE_CHILD    (1<<3)
+
+
+       while (ti = NextTagItem (&tstate))
+               switch (ti->ti_Tag)
+               {
+                       case GA_ID:
+                               if (msg->MethodID == OM_SET)
+                               {
+                                       DB2 (DBPRINTF ("  GA_ID, %ld\n", ti->ti_Data);)
+
+                                       /* Avoid forwarding all taglists to superclass because of GA_ID */
+                                       g->GadgetID = ti->ti_Data;
+                               }
+                               break;
+
+                       case PGA_Top:
+                               if (sb->Top != ti->ti_Data)
+                               {
+                                       sb->Top = ti->ti_Data;
+                                       action |= ACTIONF_NOTIFY_TOP | ACTIONF_UPDATE_CHILD;
+                               }
+                               break;
+
+                       case PGA_Total:
+                               if (sb->Total != ti->ti_Data)
+                               {
+                                       sb->Total = ti->ti_Data;
+                                       action |= ACTIONF_NOTIFY_ALL | ACTIONF_UPDATE_CHILD;
+                               }
+                               break;
+
+                       case PGA_Visible:
+                               if (sb->Visible != ti->ti_Data)
+                               {
+                                       sb->Visible = ti->ti_Data;
+                                       action |= ACTIONF_NOTIFY_ALL | ACTIONF_UPDATE_CHILD;
+                               }
+                               break;
+
+                       case SBA_InternalTop:
+                               /* Prop gadget updating us */
+                               if (sb->Top != ti->ti_Data)
+                               {
+                                       sb->Top = ti->ti_Data;
+                                       action |= ACTIONF_NOTIFY_TOP;
+                               }
+                               break;
+
+                       case SBA_Adjust:
+                       {
+                               LONG newtop = sb->Top + (LONG)((WORD)ti->ti_Data);
+
+                               /* Clip result to allowable values */
+                               if (newtop < 0) newtop = 0;
+                               if (newtop > sb->Total - sb->Visible) newtop = sb->Total - sb->Visible;
+
+                               if (newtop != sb->Top)
+                               {
+                                       sb->Top = newtop;
+                                       action |= ACTIONF_NOTIFY_TOP | ACTIONF_UPDATE_CHILD;
+                               }
+
+                               break;
+                       }
+
+                       default:
+                               action |= ACTIONF_DO_SUPER_METHOD;
+                               break;
+               }
+
+       /* Forward method to our superclass dispatcher, only if needed */
+       if (action & ACTIONF_DO_SUPER_METHOD)
+       {
+               DB2 (DBPRINTF ("SliderBarGClass:   Forwarding OM_SET/OM_UPDATE to superclass\n"));
+               result = (DoSuperMethodA (cl, (Object *)g, (Msg) msg));
+       }
+       else
+               result = TRUE;
+
+       if (action & ACTIONF_UPDATE_CHILD)
+       {
+               if (action & ACTIONF_NOTIFY_ALL)
+               {
+                       DB2 (DBPRINTF ("SliderBarGClass:   Update child ALL\n"));
+
+                       UpdateAttrs (sb->Prop, msg->opu_GInfo,
+                               (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0,
+                               PGA_Top,                sb->Top,
+                               PGA_Total,              sb->Total,
+                               PGA_Visible,    sb->Visible,
+                               TAG_DONE);
+               }
+               else /* Top only */
+               {
+                       DB2 (DBPRINTF ("SliderBarGClass:   Update child PGA_Top (%ld)\n", sb->Top));
+
+                       UpdateAttrs (sb->Prop, msg->opu_GInfo,
+                               (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0,
+                               PGA_Top,                sb->Top,
+                               TAG_DONE);
+               }
+       }
+
+       if (action & ACTIONF_NOTIFY_ALL)
+       {
+               DB2 (DBPRINTF ("SliderBarGClass:   Notify target ALL\n"));
+
+               NotifyAttrs ((Object *)g, msg->opu_GInfo,
+                       (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0,
+                       PGA_Top,                sb->Top,
+                       PGA_Total,              sb->Total,
+                       PGA_Visible,    sb->Visible,
+                       GA_ID,                  g->GadgetID,
+                       TAG_DONE);
+       }
+       else if (action & ACTIONF_NOTIFY_TOP)
+       {
+               DB2 (DBPRINTF ("SliderBarGClass:   Notify target TOP\n"));
+
+               NotifyAttrs ((Object *)g, msg->opu_GInfo,
+                       (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0,
+                       PGA_Top,                sb->Top,
+                       GA_ID,                  g->GadgetID,
+                       TAG_DONE);
+       }
+
+       return result;
+}
+
+
+static ULONG SB_OMGet (Class *cl, struct Gadget *g, struct opGet *msg)
+{
+       struct SBData *sb = INST_DATA (cl, g);
+
+       ASSERT_VALID_PTR(sb)
+       ASSERT_VALID_PTR(msg->opg_Storage)
+
+       DB2 (DBPRINTF ("ScrollBarGClass: OM_GET\n");)
+
+
+       switch (msg->opg_AttrID)
+       {
+               case PGA_Top:
+                       *msg->opg_Storage = (ULONG) sb->Top;
+                       return TRUE;
+
+               case PGA_Total:
+                       *msg->opg_Storage = (ULONG) sb->Total;
+                       return TRUE;
+
+               case PGA_Visible:
+                       *msg->opg_Storage = (ULONG) sb->Visible;
+                       return TRUE;
+
+               default:
+                       return FALSE;
+       }
+}
+
+
+static ULONG HOOKCALL SliderBarDispatcher (
+       REG(a0, Class *cl),
+       REG(a2, struct Gadget *g),
+       REG(a1, Msg msg))
+
+/* SliderBar class dispatcher - Handles all boopsi messages. */
+{
+       ASSERT_VALID_PTR(cl)
+       ASSERT_VALID_PTR(g)
+       ASSERT_VALID_PTR(msg)
+
+
+       switch (msg->MethodID)
+       {
+               case GM_LAYOUT:
+                       /* This method is only supported on V39 and above */
+                       SB_GMLayout (cl, g, (struct gpLayout *)msg);
+                       return TRUE;
+
+               case OM_SET:
+               case OM_UPDATE:
+                       return SB_OMSet (cl, g, (struct opUpdate *)msg);
+
+               case OM_GET:
+                       return SB_OMGet (cl, g, (struct opGet *)msg);
+
+               case OM_NEW:
+                       return SB_OMNew (cl, g, (struct opSet *)msg);
+
+               case OM_DISPOSE:
+                       SB_OMDispose (cl, g, msg);
+                       return TRUE;
+
+               default:
+                       /* Unsupported method: let our superclass's dispatcher take
+                        * a look at it. This includes all gadget methods sent
+                        * by Intuition: GM_HITTEST, GM_RENDER, GM_HANDLEINPUT,
+                        * GM_GOACTIVE and GM_GOINACTIVE. All these methods are
+                        * automatically forwarded to our children by our superclass.
+                        */
+                       DB2 (DBPRINTF ("SliderBarGClass: passing unknown method 0x%lx to superclass\n",
+                               msg->MethodID);)
+                       return DoSuperMethodA (cl, (Object *)g, msg);
+       }
+}
+
+
+
+Class *MakeSliderBarGClass (void)
+{
+       Class *class;
+       struct SBClassData *classdata;
+       Class *smartgrp;
+
+       if (!(smartgrp = MakeSmartGroupGClass()))
+               return NULL;
+
+       if (class = MakeClass (
+#if (CLASS_FLAVOUR & FLAVOUR_PUBCLASS)
+               SLIDERBARGCLASS,
+#else
+               NULL,
+#endif
+               NULL, smartgrp, sizeof (struct SBData), 0))
+       {
+               class->cl_Dispatcher.h_Entry = (ULONG (*)()) SliderBarDispatcher;
+
+               /* Allocate storage for global class data */
+               if (classdata = AllocMem (sizeof (struct SBClassData), MEMF_PUBLIC | MEMF_CLEAR))
+               {
+                       class->cl_UserData = (ULONG) classdata;
+
+                       classdata->SmartGroupGClass = smartgrp;
+
+                       classdata->FrScrollButtonClass = MakeFrScrollButtonClass();
+                       ASSERT_VALID_PTR (classdata->FrScrollButtonClass);
+
+                       classdata->FrPropGClass = MakeFrPropGClass();
+                       ASSERT_VALID_PTR (classdata->FrPropGClass);
+
+                       if (classdata->VectorGlyphBase = (struct ClassLibrary *)
+                               OpenLibrary ("images/vectorglyph.image", 0))
+                       {
+                               classdata->VectorGlyphIClass = classdata->VectorGlyphBase->cl_Class;
+                               ASSERT_VALID_PTR (classdata->VectorGlyphIClass);
+
+                               if (classdata->Frame = NewObject (NULL, FRAMEICLASS,
+                                       IA_EdgesOnly,   TRUE,
+                                       IA_FrameType,   FRAME_BUTTON,
+                                       TAG_DONE))
+                               {
+#if (CLASS_FLAVOUR & FLAVOUR_PUBCLASS)
+                                       AddClass (class);
+#endif
+                                       return class;
+                               }
+                       }
+                       else
+                       {
+                               static struct EasyStruct OpenClassES =
+                               {
+                                       sizeof (struct EasyStruct),
+                                       0,
+#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB)
+                                       LibName,
+#else
+                                       "sliderbar.gadget",
+#endif
+                                       "Couldn't open images/vectorglyph.image",
+                                       "Ok"
+                               };
+
+                               /* Report an error */
+                               EasyRequestArgs (NULL, &OpenClassES, NULL, NULL);
+                       }
+               }
+
+               FreeSliderBarGClass (class);
+       }
+
+       return NULL;
+}
+
+
+BOOL FreeSliderBarGClass (Class *class)
+{
+       struct SBClassData *classdata;
+
+       if (class)
+       {
+               ASSERT_VALID_PTR(class)
+
+               classdata = (struct SBClassData *)class->cl_UserData;
+
+               /* Try to remove the class */
+               if (FreeClass (class))
+               {
+                       if (classdata)
+                       {
+                               ASSERT_VALID_PTR(classdata)
+                               ASSERT_VALID_PTR_OR_NULL(classdata->Frame);
+                               ASSERT_VALID_PTR_OR_NULL(classdata->VectorGlyphBase)
+                               ASSERT_VALID_PTR_OR_NULL(classdata->FrScrollButtonClass)
+                               ASSERT_VALID_PTR_OR_NULL(classdata->FrPropGClass)
+                               ASSERT_VALID_PTR_OR_NULL(classdata->SmartGroupGClass)
+
+                               /* Cleanup global class data.
+                                *
+                                * NOTE: NULL is safe in DisposeObject() and CloseLibrary() since V36
+                                */
+                               DisposeObject(classdata->Frame);
+                               CloseLibrary ((struct Library *)classdata->VectorGlyphBase);
+                               FreeFrScrollButtonClass (classdata->FrScrollButtonClass);
+                               FreeFrPropGClass (classdata->FrPropGClass);
+                               FreeSmartGroupGClass (classdata->SmartGroupGClass);
+                               FreeMem (classdata, sizeof (struct SBClassData));
+                       }
+                       return TRUE;
+               }
+               return FALSE;
+       }
+       return TRUE;
+}
+
+
+
+#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB)
+/*
+ * Class library support functions
+ */
+
+struct ClassLibrary * HOOKCALL _UserLibInit (REG(a6, struct ClassLibrary *mybase))
+{
+       SysBase = *((struct ExecBase **)4);     /* Initialize SysBase */
+
+       IntuitionBase   = (struct IntuitionBase *) OpenLibrary ("intuition.library", 39);
+       UtilityBase             = (UTILITYBASETYPE *) OpenLibrary ("utility.library", 39);
+
+       if (!(IntuitionBase && UtilityBase))
+       {
+               _UserLibCleanup (mybase);
+               return NULL;
+       }
+
+       if (mybase->cl_Class = MakeSliderBarGClass ())
+       {
+               return mybase;
+       }
+       else
+       {
+               _UserLibCleanup (mybase);
+               return NULL;
+       }
+}
+
+struct ClassLibrary * HOOKCALL _UserLibCleanup (REG(a6, struct ClassLibrary *mybase))
+{
+       if (mybase->cl_Class)
+               if (!FreeSliderBarGClass (mybase->cl_Class))
+                       return NULL;
+
+       CloseLibrary ((struct Library *)UtilityBase);
+       CloseLibrary ((struct Library *)IntuitionBase);
+
+       return mybase;
+}
+
+Class * HOOKCALL _GetEngine (REG(a6, struct ClassLibrary *mybase))
+{
+       return (mybase->cl_Class);
+}
+
+#endif /* (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) */
diff --git a/gadgets/SmartGroup/Makefile b/gadgets/SmartGroup/Makefile
new file mode 100644 (file)
index 0000000..3fb8976
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(BOOPSITOP)/config.mk
+include config.mk
+
+ARG_COMMON :=
+ARG_ALL := $(ARG_COMMON)
+ARG_LIB := $(ARG_COMMON)
+ARG_DEBUG := $(ARG_COMMON)
+ARG_PRIVATE := $(ARG_COMMON)
+ARG_OBJ := $(ARG_COMMON)
+ARG_INSTALL := $(ARG_COMMON)
+
+DEP_COMMON :=
+DEP_ALL := $(DEP_COMMON)
+DEP_LIB := $(DEP_COMMON)
+DEP_DEBUG := $(DEP_COMMON)
+DEP_PRIVATE := $(DEP_COMMON)
+DEP_OBJ := $(DEP_COMMON)
+
+include $(BOOPSITOP)/common/general.mk
+
diff --git a/gadgets/SmartGroup/SmartGroupGClass.c b/gadgets/SmartGroup/SmartGroupGClass.c
new file mode 100644 (file)
index 0000000..b18a28c
--- /dev/null
@@ -0,0 +1,694 @@
+/*
+**     $Id: SmartGroupGClass.c,v 1.1 1999/02/07 14:24:44 bernie Exp $
+**
+**     Copyright (C) 1999 Bernardo Innocenti
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     "smartgroupgclass", a subclass of the gadgetclass which replaces
+**     and enhances the builtin groupgclass.
+**     See the header file "SmartGroupGClass.h" for class documentation.
+*/
+
+/* Definitions for system headers */
+#define USE_BUILTIN_MATH
+#define INTUI_V36_NAMES_ONLY
+#define INTUITION_IOBSOLETE_H
+#define __USE_SYSBASE
+#define  CLIB_ALIB_PROTOS_H            /* Avoid dupe defines of boopsi funcs */
+
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <utility/tagitem.h>
+#include <intuition/intuition.h>
+#include <intuition/classes.h>
+#include <intuition/classusr.h>
+#include <intuition/gadgetclass.h>
+
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <proto/utility.h>
+
+#ifdef __STORM__
+       #pragma header
+#endif
+
+#include <gadgets/SmartGroupGClass.h>
+
+#include <CompilerSpecific.h>
+#include <DebugMacros.h>
+#include <ListMacros.h>
+#include <BoopsiStubs.h>
+#include <BoopsiLib.h>
+
+
+/* Local function prototypes */
+
+static ULONG HOOKCALL SmartGroupDispatcher (REG(a0, Class *cl), REG(a2, Object *o), REG(a1, Msg msg));
+
+static ULONG   ASMCALL SG_GMHitTest    (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpHitTest *msg));
+static void            ASMCALL SG_GMRender             (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpRender *msg));
+static ULONG   ASMCALL SG_GMGoActive   (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpInput *msg));
+static ULONG   ASMCALL SG_GMHandleInput(REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpInput *msg));
+static void            ASMCALL SG_GMGoInactive (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpGoInactive *msg));
+static ULONG   ASMCALL SG_GMHelpTest   (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpHitTest *msg));
+static void            ASMCALL SG_GMLayout             (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpLayout *msg));
+static ULONG   ASMCALL SG_GMDomain             (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpDomain *msg));
+static ULONG   ASMCALL SG_OMNew                (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opSet *msg));
+static void            ASMCALL SG_OMDispose    (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, Msg msg));
+//static ULONG ASMCALL SG_OMSet                (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opUpdate *msg));
+static void            ASMCALL SG_OMAddMember  (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opMember *msg));
+static void            ASMCALL SG_OMRemMember  (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opMember *msg));
+
+/* Per-object instance data */
+
+struct GroupData
+{
+       struct MinList          ChildList;
+
+       struct ExtGadget *      ActiveChild;
+       struct IBox                     GBox;
+
+       /* Group orientation: can be LORIENT_VERT or LORIENT_HORIZ */
+       ULONG                           Orientation;
+};
+
+
+
+#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB)
+
+       /* Class library support functions */
+       struct ClassLibrary     *       HOOKCALL _UserLibInit           (REG(a6, struct ClassLibrary *mybase));
+       struct ClassLibrary     *       HOOKCALL _UserLibCleanup        (REG(a6, struct ClassLibrary *mybase));
+       Class *                                 HOOKCALL _GetEngine                     (REG(a6, struct ClassLibrary *mybase));
+
+       /* Library data */
+       const UBYTE LibName[] = "sliderbar.gadget";
+       const UBYTE LibVer[] = { '$', 'V', 'E', 'R', ':', ' ' };
+       const UBYTE LibId[] = "smartgroup.gadget 1.0 (6.1.99) © 1999 Bernardo Innocenti\n";
+
+       /* Workaround a bug in StormC header file <proto/utility.h> */
+       #ifdef __STORM__
+               #define UTILITYBASETYPE struct Library
+       #else
+               #define UTILITYBASETYPE struct UtilityBase
+       #endif
+
+       /* Library bases */
+       static struct ExecBase          *SysBase                = NULL;
+       static struct IntuitionBase     *IntuitionBase  = NULL;
+       static UTILITYBASETYPE          *UtilityBase    = NULL;
+
+#endif
+
+
+
+static ULONG ASMCALL SG_GMHitTest (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpHitTest *msg))
+{
+       struct GroupData *gd = INST_DATA (cl, g);
+       struct ExtGadget *child;
+       APTR object_state;
+       WORD x, y;
+
+       DB2 (DBPRINTF ("SmartGroupGClass: GM_HITTEST\n");)
+       ASSERT_VALID_PTR(gd)
+
+       object_state = (APTR)gd->ChildList.mlh_Head;
+       ASSERT_VALID_PTR(object_state)
+
+       x = msg->gpht_Mouse.X + gd->GBox.Left;
+       y = msg->gpht_Mouse.Y + gd->GBox.Top;
+
+       /* Search over all our children */
+       while (child = (struct ExtGadget *)NextObject(&object_state))
+       {
+               ASSERT_VALID_PTR(child)
+
+               /* Check whether the mouse coordinates are inside
+                * the gadget rectangle of our child
+                */
+               if ((x >= child->LeftEdge) &&
+                       (x < child->LeftEdge + child->Width) &&
+                       (y >= child->TopEdge) &&
+                       (y < child->TopEdge + child->Height))
+               {
+                       struct gpHitTest childmsg;
+
+                       childmsg.MethodID               = GM_HITTEST;
+                       childmsg.gpht_GInfo             = msg->gpht_GInfo;
+                       childmsg.gpht_Mouse.X   = x - child->LeftEdge;
+                       childmsg.gpht_Mouse.Y   = y - child->TopEdge;
+
+                       if (DoMethodA ((Object *)child, (Msg)&childmsg) == GMR_GADGETHIT)
+                       {
+                               gd->ActiveChild = child;
+                               return GMR_GADGETHIT;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+
+
+static void ASMCALL SG_GMRender(REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpRender *msg))
+{
+       struct GroupData *gd = INST_DATA (cl, g);
+       Object *o;
+       APTR object_state;
+
+       DB2 (DBPRINTF ("SmartGroupGClass: GM_RENDER\n");)
+
+       ASSERT_VALID_PTR(gd)
+       object_state = (APTR)gd->ChildList.mlh_Head;
+       ASSERT_VALID_PTR(object_state)
+
+       /* The groupgclass disposes all its children automatically */
+       while (o = NextObject(&object_state))
+       {
+               ASSERT_VALID_PTR(o)
+               DoMethodA (o, (Msg)msg);
+       }
+}
+
+
+
+static ULONG ASMCALL SG_GMGoActive (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpInput *msg))
+{
+       struct GroupData *gd = INST_DATA (cl, g);
+
+       DB2 (DBPRINTF ("SmartGroupGClass: GM_GOACTIVE\n");)
+       ASSERT_VALID_PTR(gd)
+       ASSERT_VALID_PTR(gd->ActiveChild)
+
+       if (gd->ActiveChild)
+       {
+               struct gpInput childmsg;
+
+               childmsg.MethodID               = GM_GOACTIVE;
+               childmsg.gpi_GInfo              = msg->gpi_GInfo;
+               childmsg.gpi_IEvent             = msg->gpi_IEvent;
+               childmsg.gpi_Termination= msg->gpi_Termination;
+               childmsg.gpi_Mouse.X    = msg->gpi_Mouse.X + gd->GBox.Left
+                       - gd->ActiveChild->LeftEdge;
+               childmsg.gpi_Mouse.Y    = msg->gpi_Mouse.Y + gd->GBox.Top
+                       - gd->ActiveChild->TopEdge;
+               childmsg.gpi_TabletData = msg->gpi_TabletData;
+
+               return (DoMethodA ((Object *)gd->ActiveChild, (Msg)&childmsg));
+       }
+
+       gd->ActiveChild = NULL;
+       return GMR_NOREUSE;
+}
+
+
+
+static ULONG ASMCALL SG_GMHandleInput (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpInput *msg))
+{
+       struct GroupData *gd = INST_DATA (cl, g);
+
+       DB2 (DBPRINTF ("SmartGroupGClass: GM_HANDLEINPUT\n");)
+       ASSERT_VALID_PTR(gd)
+       ASSERT_VALID_PTR(gd->ActiveChild)
+
+       if (gd->ActiveChild)
+       {
+               struct gpInput childmsg;
+
+               childmsg.MethodID               = GM_HANDLEINPUT;
+               childmsg.gpi_GInfo              = msg->gpi_GInfo;
+               childmsg.gpi_IEvent             = msg->gpi_IEvent;
+               childmsg.gpi_Termination= msg->gpi_Termination;
+               childmsg.gpi_Mouse.X    = msg->gpi_Mouse.X + gd->GBox.Left
+                       - gd->ActiveChild->LeftEdge;
+               childmsg.gpi_Mouse.Y    = msg->gpi_Mouse.Y + gd->GBox.Top
+                       - gd->ActiveChild->TopEdge;
+               childmsg.gpi_TabletData = msg->gpi_TabletData;
+
+               DB2 (DBPRINTF ("SmartGroupGClass:   Translating coords: X=%ld, Y=%ld\n",
+                       childmsg.gpi_Mouse.X, childmsg.gpi_Mouse.Y);)
+
+               return DoMethodA ((Object *)gd->ActiveChild, (Msg)&childmsg);
+       }
+
+       return GMR_NOREUSE;
+}
+
+
+
+static void ASMCALL SG_GMGoInactive (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpGoInactive *msg))
+{
+       struct GroupData *gd = INST_DATA (cl, g);
+
+       DB2 (DBPRINTF ("SmartGroupGClass: GM_GOINACTIVE\n");)
+       ASSERT_VALID_PTR(gd)
+       ASSERT_VALID_PTR(gd->ActiveChild)
+
+       if (gd->ActiveChild)
+       {
+               DoMethodA ((Object *)gd->ActiveChild, (Msg)msg);
+               gd->ActiveChild = NULL;
+       }
+}
+
+
+
+static ULONG ASMCALL SG_GMHelpTest (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpHitTest *msg))
+{
+       struct GroupData *gd = INST_DATA (cl, g);
+       struct ExtGadget *child;
+       APTR object_state;
+       WORD x, y;
+
+       DB1 (DBPRINTF ("SmartGroupGClass: GM_HELPTEST\n");)
+
+       ASSERT_VALID_PTR(gd)
+       object_state = (APTR)gd->ChildList.mlh_Head;
+       ASSERT_VALID_PTR(object_state)
+
+
+       if ((g->Flags & GFLG_EXTENDED) && (g->MoreFlags & GMORE_GADGETHELP))
+       {
+               x = msg->gpht_Mouse.X + gd->GBox.Left;
+               y = msg->gpht_Mouse.Y + gd->GBox.Top;
+
+               /* Search over all our children */
+               while (child = (struct ExtGadget *)NextObject(&object_state))
+               {
+                       ASSERT_VALID_PTR(child)
+
+                       /* Limit to gadgets that understand GM_HELPTEST */
+                       if ((child->Flags & GFLG_EXTENDED) && (child->MoreFlags & GMORE_GADGETHELP))
+                       {
+                               if (child->MoreFlags & GMORE_BOUNDS)
+                               {
+                                       /* Check whether the mouse coordinates are inside
+                                        * the gadget rectangle of our child
+                                        */
+                                       if ((x >= child->BoundsLeftEdge) &&
+                                               (x < child->BoundsLeftEdge + child->BoundsWidth) &&
+                                               (y >= child->BoundsTopEdge) &&
+                                               (y < child->BoundsTopEdge + child->BoundsHeight))
+                                       {
+                                               struct gpHitTest childmsg;
+
+                                               childmsg.MethodID               = GM_HELPTEST;
+                                               childmsg.gpht_GInfo             = msg->gpht_GInfo;
+                                               childmsg.gpht_Mouse.X   = x - child->BoundsLeftEdge;
+                                               childmsg.gpht_Mouse.Y   = y - child->BoundsTopEdge;
+
+                                               if (DoMethodA ((Object *)child, (Msg)&childmsg) == GMR_HELPHIT)
+                                               {
+                                                       gd->ActiveChild = child;
+                                                       return GMR_HELPHIT;
+                                               }
+                                       }
+                               }
+                               else /* No valid bounds, use gadget select box */
+                               {
+                                       /* Check whether the mouse coordinates are inside
+                                        * the gadget rectangle of our child
+                                        */
+                                       if ((x >= child->LeftEdge) &&
+                                               (x < child->LeftEdge + child->Width) &&
+                                               (y >= child->TopEdge) &&
+                                               (y < child->TopEdge + child->Height))
+                                       {
+                                               struct gpHitTest childmsg;
+
+                                               childmsg.MethodID               = GM_HELPTEST;
+                                               childmsg.gpht_GInfo             = msg->gpht_GInfo;
+                                               childmsg.gpht_Mouse.X   = x - child->LeftEdge;
+                                               childmsg.gpht_Mouse.Y   = y - child->TopEdge;
+
+                                               if (DoMethodA ((Object *)child, (Msg)&childmsg) == GMR_HELPHIT)
+                                               {
+                                                       gd->ActiveChild = child;
+                                                       return GMR_HELPHIT;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return GMR_NOHELPHIT;
+}
+
+
+
+static void ASMCALL SG_GMLayout(REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpLayout *msg))
+{
+       struct GroupData *gd = (struct GroupData *) INST_DATA (cl, (Object *)g);
+       struct ExtGadget *child;
+       APTR object_state;
+
+       DB2 (DBPRINTF ("SmartGroupGClass: GM_LAYOUT\n");)
+       ASSERT_VALID_PTR(gd)
+
+       /* Collect new group size */
+       GetGadgetBounds(msg->gpl_GInfo, g, &gd->GBox);
+
+       /* Forward GM_LAYOUT to our children that need it */
+
+       object_state = (APTR)gd->ChildList.mlh_Head;
+       ASSERT_VALID_PTR(object_state)
+
+       while (child = (struct ExtGadget *)NextObject(&object_state))
+       {
+               ASSERT_VALID_PTR(child)
+
+               if (child->Flags & (
+                       GFLG_RELBOTTOM |
+                       GFLG_RELRIGHT |
+                       GFLG_RELWIDTH |
+                       GFLG_RELHEIGHT |
+                       GFLG_RELSPECIAL))
+               {
+                       DB2 (DBPRINTF ("SmartGroupGClass:   Forwarding GM_LAYOUT to child\n");)
+                       DoMethodA ((Object *)child, (Msg)msg);
+               }
+       }
+}
+
+
+
+static ULONG ASMCALL SG_GMDomain (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpDomain *msg))
+{
+       DB1 (DBPRINTF ("SmartGroupGClass: GM_DOMAIN\n");)
+
+       /* TODO */
+       return 0;
+}
+
+
+
+static ULONG ASMCALL SG_OMNew (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opSet *msg))
+{
+       struct GroupData *gd;
+       struct TagItem *ti, *tstate = msg->ops_AttrList;
+
+       DB1 (DBPRINTF ("SmartGroupGClass: OM_NEW\n");)
+
+       if (g = (struct ExtGadget *)DoSuperMethodA (cl, (Object *)g, (Msg)msg))
+       {
+               gd = (struct GroupData *) INST_DATA (cl, (Object *)g);
+               ASSERT_VALID_PTR(gd)
+
+               DB (if (g->Flags & GFLG_EXTENDED)
+                       DBPRINTF ("SmartGroupGClass:   Wow, we are an ExtGadget!\n");)
+
+               /* Initialize object instance data */
+               NEWLIST((struct List *)&gd->ChildList);
+               gd->ActiveChild = NULL;
+               gd->ActiveChild = NULL;
+
+               gd->Orientation = LORIENT_NONE;
+
+               while (ti = NextTagItem (&tstate))
+                       switch (ti->ti_Tag)
+                       {
+                               case SGA_Child:
+                               {
+                                       struct opMember opam;
+
+                                       if (!ti->ti_Data)
+                                       {
+                                               /* Commit suicide without disturbing the
+                                                * dispatchers of our subclasses
+                                                */
+                                               SG_OMDispose (cl, g, NULL);
+                                               return NULL;
+                                       }
+
+                                       ASSERT_VALID_PTR(ti->ti_Data)
+                                       opam.opam_Object = (Object *)ti->ti_Data;
+                                       SG_OMAddMember (cl, g, &opam);
+                                       break;
+                               }
+
+                               case LAYOUTA_Orientation:
+                                       gd->Orientation = ti->ti_Data;
+                                       break;
+
+                               default:
+                                       break;
+                       }
+
+               /* Intuition sends GM_LAYOUT messages only to gadgets with
+                * relative postion. Since we need to recalculate the
+                * positions of our children when the window resizes, we
+                * set the GFLG_RELSPECIAL property if to be notified in all cases.
+                */
+               g->Flags |= GFLG_RELSPECIAL;
+       }
+
+       return (ULONG)g;
+}
+
+
+
+static void ASMCALL SG_OMDispose (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, Msg msg))
+{
+       struct GroupData *gd = (struct GroupData *) INST_DATA (cl, (Object *)g);
+       Object *o;
+       APTR object_state;
+
+       DB1 (DBPRINTF ("SmartGroupGClass: OM_DISPOSE\n");)
+
+       ASSERT_VALID_PTR(gd)
+       object_state = (APTR)gd->ChildList.mlh_Head;
+       ASSERT_VALID_PTR(object_state)
+
+       /* The groupgclass disposes all its children automatically */
+       while (o = NextObject(&object_state))
+       {
+               ASSERT_VALID_PTR(o)
+               DoMethod (o, OM_REMOVE);
+               DisposeObject(o);
+       }
+
+       /* Our superclass will cleanup everything else now */
+       DoSuperMethodA (cl, (Object *)g, msg);
+
+       /* From now on, our instance data is no longer available */
+}
+
+
+#if 0
+static ULONG ASMCALL SG_OMSet (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opUpdate *msg))
+{
+       struct GroupData *gd = INST_DATA (cl, g);
+       struct TagItem *ti, *tstate = msg->opu_AttrList;
+
+       DB1 (DBPRINTF ("SmartGroupGClass: OM_SET\n");)
+
+       ASSERT_VALID_PTR(gd)
+       ASSERT_VALID_PTR_OR_NULL(tstate)
+
+       DB2 (DBPRINTF ((msg->MethodID == OM_SET) ?
+               "SliderBarGClass: OM_SET\n" :
+               "SliderBarGClass: OM_UPDATE\n");)
+
+
+       while (ti = NextTagItem (&tstate))
+               switch (ti->ti_Tag)
+               {
+                       default:
+                               break;
+               }
+
+               result = TRUE;
+
+
+       return result;
+}
+#endif
+
+
+
+static void ASMCALL SG_OMAddMember (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opMember *msg))
+{
+       struct GroupData *gd = INST_DATA (cl, g);
+       ASSERT_VALID_PTR(gd)
+       DB1 (DBPRINTF ("SmartGroupGClass: OM_ADDMEMBER\n");)
+
+       if(msg->opam_Object)
+       {
+               ASSERT_VALID_PTR(msg->opam_Object)
+
+               /* TODO: check for GMORE_SCROLLRASTER ? */
+
+               DoMethod (msg->opam_Object, OM_ADDTAIL, &gd->ChildList);
+       }
+}
+
+
+
+static void ASMCALL SG_OMRemMember (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opMember *msg))
+{
+       struct GroupData *gd = INST_DATA (cl, g);
+
+       DB1 (DBPRINTF ("SmartGroupGClass: OM_REMMEBRER\n");)
+       ASSERT_VALID_PTR(gd)
+
+       DoMethod (msg->opam_Object, OM_REMOVE);
+
+       if (msg->opam_Object == (Object *)gd->ActiveChild)
+               gd->ActiveChild = NULL;
+
+       /* TODO: resize & redraw group */
+}
+
+
+
+static ULONG HOOKCALL SmartGroupDispatcher (
+       REG(a0, Class *cl),
+       REG(a2, Object *o),
+       REG(a1, Msg msg))
+
+/* SmartGroup class dispatcher - Handles all boopsi messages. */
+{
+       static const HookPtr GMHooks[] =
+       {
+               /* GM_HITTEST           */ (HookPtr)SG_GMHitTest,
+               /* GM_RENDER            */ (HookPtr)SG_GMRender,
+               /* GM_GOACTIVE          */ (HookPtr)SG_GMGoActive,
+               /* GM_HANDLEINPUT       */ (HookPtr)SG_GMHandleInput,
+               /* GM_GOINACTIVE        */ (HookPtr)SG_GMGoInactive,
+               /* GM_HELPTEST          */ (HookPtr)SG_GMHelpTest,
+               /* GM_LAYOUT            */ (HookPtr)SG_GMLayout,
+               /* GM_DOMAIN            */ (HookPtr)SG_GMDomain
+       };
+
+       static const HookPtr OMHooks[] =
+       {
+               /* OM_NEW               */ (HookPtr)SG_OMNew,
+               /* OM_DISPOSE   */ (HookPtr)SG_OMDispose,
+               /* OM_SET               */ (HookPtr)NULL,
+               /* OM_GET               */ (HookPtr)NULL,
+               /* OM_ADDTAIL   */ (HookPtr)NULL,
+               /* OM_REMOVE    */ (HookPtr)NULL,
+               /* OM_NOTIFY    */ (HookPtr)NULL,
+               /* OM_UPDATE    */ (HookPtr)NULL,
+               /* OM_ADDMEMBER */ (HookPtr)SG_OMAddMember,
+               /* OM_REMMEMBER */ (HookPtr)SG_OMRemMember
+       };
+
+       ULONG id;
+
+       ASSERT_VALID_PTR(cl)
+       ASSERT_VALID_PTR(o)
+       ASSERT_VALID_PTR(msg)
+
+       /* Optimized boopsi class dispatcher.
+        *
+        * This class overrides almost all gadgetclass and rootclass messages.
+        * The usual switch() statement on msg->MessageID would be quite inefficient.
+        * Most compilers aren't smart enough to implement it with two jump tables
+        * as we did here. This code relies on the values assigned to the method IDs
+        * in the headers to remain constant. It will break otherwise.
+        */
+
+       id = msg->MethodID;
+
+       if (id <= GM_DOMAIN)
+               return GMHooks[id](cl, o, msg);
+
+       id -= OM_NEW;
+
+       if (id <= (OM_REMMEMBER - OM_NEW))
+               if (OMHooks[id])
+                       return OMHooks[id](cl, o, msg);
+
+       return DoSuperMethodA (cl, o, msg);
+}
+
+
+
+Class *MakeSmartGroupGClass (void)
+{
+       Class *class;
+
+       if (class = MakeClass (
+#if (CLASS_FLAVOUR & FLAVOUR_PUBCLASS)
+               SMARTGROUPGCLASS,
+#else
+               NULL,
+#endif
+               GADGETCLASS, NULL, sizeof (struct GroupData), 0))
+       {
+               class->cl_Dispatcher.h_Entry = (ULONG (*)()) SmartGroupDispatcher;
+       }
+
+       return class;
+}
+
+
+BOOL FreeSmartGroupGClass (Class *class)
+{
+       if (class)
+       {
+               ASSERT_VALID_PTR(class)
+
+               /* Try to remove the class */
+               if (FreeClass (class))
+                       return TRUE;
+
+               return FALSE;
+       }
+       return TRUE;
+}
+
+
+
+#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB)
+/*
+ * Class library support functions
+ */
+
+struct ClassLibrary * HOOKCALL _UserLibInit (REG(a6, struct ClassLibrary *mybase))
+{
+       SysBase = *((struct ExecBase **)4);     /* Initialize SysBase */
+
+       IntuitionBase   = (struct IntuitionBase *) OpenLibrary ("intuition.library", 39);
+       UtilityBase             = (UTILITYBASETYPE *) OpenLibrary ("utility.library", 39);
+
+       if (!(IntuitionBase && UtilityBase))
+       {
+               _UserLibCleanup (mybase);
+               return NULL;
+       }
+
+       if (mybase->cl_Class = MakeSmartGroupGClass ())
+       {
+               return mybase;
+       }
+       else
+       {
+               _UserLibCleanup (mybase);
+               return NULL;
+       }
+}
+
+struct ClassLibrary * HOOKCALL _UserLibCleanup (REG(a6, struct ClassLibrary *mybase))
+{
+       if (mybase->cl_Class)
+               if (!FreeSliderBarGClass (mybase->cl_Class))
+                       return NULL;
+
+       CloseLibrary ((struct Library *)UtilityBase);
+       CloseLibrary ((struct Library *)IntuitionBase);
+
+       return mybase;
+}
+
+Class * HOOKCALL _GetEngine (REG(a6, struct ClassLibrary *mybase))
+{
+       return (mybase->cl_Class);
+}
+
+#endif /* (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) */
diff --git a/gadgets/ToolManagerGClass/Makefile b/gadgets/ToolManagerGClass/Makefile
new file mode 100644 (file)
index 0000000..eb79630
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# $Id:$
+#
+# Copyright (C) 1999 by Matteo Cavalleri
+#
+
+include $(BOOPSITOP)/config.mk
+include config.mk
+
+ARG_COMMON :=
+ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o
+ARG_LIB := $(ARG_COMMON)
+ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV)
+ARG_PRIVATE := $(ARG_COMMON)
+ARG_OBJ := $(ARG_COMMON)
+
+DEP_COMMON :=
+DEP_ALL := $(DEP_COMMON) OpenClass.o
+DEP_LIB := $(DEP_COMMON)
+DEP_DEBUG := $(DEP_COMMON) OpenClass.o
+DEP_PRIVATE := $(DEP_COMMON)
+DEP_OBJ := $(DEP_COMMON)
+
+include $(BOOPSITOP)/common/general.mk
+
+OpenClass.o: OpenClass.c
+       $(MAKE) -C $(BOOPSITOP)/common/ $@
diff --git a/include/BoopsiLib.h b/include/BoopsiLib.h
new file mode 100644 (file)
index 0000000..af655c5
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+**     $Id: BoopsiLib.h,v 1.1 2000/01/12 20:30:05 bernie Exp $
+**
+**     Copyright (C) 1999 Bernardo Innocenti
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     Prototypes for the GetGadgetBox() and GetGadgetBounds() helpers
+*/
+
+#ifndef INTUITION_CGHOOKS_H
+#include <intuition/cghooks.h>
+#endif
+
+#ifndef INTUITION_IMAGECLASS_H
+#include <intuition/imageclass.h>
+#endif
+
+
+/* Supported class flavours:
+ *
+ * FLAVOUR_CLASSLIB
+ *     Build a class library if this option is set or
+ *     a static linker object otherwise.
+ *
+ * FLAVOUR_PUBCLASS
+ *     Call AddClass() to show this class globally if set,
+ *     make a private class otherwise.
+ */
+#define FLAVOUR_CLASSLIB       (1<<0)
+#define FLAVOUR_PUBCLASS       (1<<1)
+
+
+
+/* Useful functions to compute the actual size of a gadget, regardless
+ * of its relativity flags
+ */
+void GetGadgetBox(struct GadgetInfo *ginfo, struct ExtGadget *g, struct IBox *box);
+void GetGadgetBounds(struct GadgetInfo *ginfo, struct ExtGadget *g, struct IBox *bounds);
+
+
+/* Convert a struct IBox to a struct Rectangle
+ */
+INLINE void IBoxToRect(struct IBox *box, struct Rectangle *rect)
+{
+       ASSERT_VALID_PTR(box)
+       ASSERT_VALID_PTR(rect)
+
+       rect->MinX = box->Left;
+       rect->MinY = box->Top;
+       rect->MaxX = box->Left + box->Width - 1;
+       rect->MaxY = box->Top + box->Height - 1;
+}
+
+
+/* Tell if a gadget has a boopsi frame
+ */
+INLINE BOOL GadgetHasFrame(struct Gadget *g)
+{
+       return (BOOL)(
+               g->GadgetRender &&
+               (g->Flags & GFLG_GADGIMAGE) &&
+               (((struct Image *)g->GadgetRender)->Depth == CUSTOMIMAGEDEPTH));
+}
+
+
+/* Some layers magic adapded from "MUI.undoc",
+ * by Alessandro Zummo <azummo@ita.flashnet.it>
+ */
+
+/* This macro evalutates to true when the layer is
+ * covered by another layer
+ */
+#define LayerCovered(l)                                                                        \
+       ((!(l)->ClipRect) ||                                                            \
+       ((l)->bounds.MinX != (l)->ClipRect->bounds.MinX) ||     \
+       ((l)->bounds.MinY != (l)->ClipRect->bounds.MinY) ||     \
+       ((l)->bounds.MaxX != (l)->ClipRect->bounds.MaxX) ||     \
+       ((l)->bounds.MaxY != (l)->ClipRect->bounds.MaxY))
+
+/* memcmp(&(l)->ClipRect->bounds, &(l)->bounds, sizeof (struct Rectangle))) */
+
+/* This macro evalutates to true if the layer has damage regions */
+#define LayerDamaged(l) \
+       ((l)->DamageList && (l)->DamageList->RegionRectangle)
+
+/* This macro checks if ScrollRaster() needs to be called to
+ * scroll the layer damage after a scrolling operation.
+ */
+#define NeedZeroScrollRaster(l) \
+       (((l)->Flags & LAYERSIMPLE) && (LayerCovered(l) || LayerDamaged(l)))
diff --git a/include/BoopsiStubs.h b/include/BoopsiStubs.h
new file mode 100644 (file)
index 0000000..43f0cc0
--- /dev/null
@@ -0,0 +1,243 @@
+#ifndef BOOPSISTUBS_H
+#define BOOPSISTUBS_H
+/*
+**     $Id: boopsistubs.h,v 1.2 2000/07/15 20:45:32 stegerg Exp $
+**
+**     Copyright (C) 1997,1999,2000 Bernardo Innocenti <bernie@cosmos.it>
+**     All rights reserved.
+**
+**     Using these inline versions of the amiga.lib boopsi support functions
+**     results in faster and smaller code against their linked library
+**     counterparts. When debug is active, these functions will also
+**     validate the parameters you pass in.
+*/
+
+/* The USE_BOOPSI_STUBS symbol prevents redefinition of the following stubs with
+ * their amiga.lib equivalents. In AmigaOS, this trick works only if you are using
+ * a patched version of <clib/alib_protos.h>
+ */
+#ifndef USE_BOOPSI_STUBS
+#define USE_BOOPSI_STUBS
+#endif /* USE_BOOPSI_STUBS */
+
+
+#ifndef INTUITION_CLASSES_H
+#include <intuition/classes.h>
+#endif /* INTUITION_CLASSES_H */
+
+#if defined(_AROS)
+
+       #ifndef AROS_DEBUG_H
+       #include <aros/debug.h>
+       #endif /* AROS_DEBUG_H */
+
+       #ifndef AROS_ASMCALL_H
+       #include <aros/asmcall.h>
+       #endif /* AROS_ASMCALL_H */
+
+       #define _CALL_DISPATCHER(entry, cl, o, msg) \
+               AROS_UFC3(IPTR, entry, \
+                       AROS_UFCA(Class *, cl, A0), \
+                       AROS_UFCA(Object *, o, A2), \
+                       AROS_UFCA(APTR, msg, A1))
+
+       #ifndef INLINE
+       #define INLINE static inline
+       #endif
+
+#else /* !_AROS */
+
+       #ifndef COMPILERSPECIFIC_H
+       #include "CompilerSpecific.h"
+       #endif /* COMPILERSPECIFIC_H */
+
+       #ifndef DEBUGMACROS_H
+       #include "DebugMacros.h"
+       #endif /* DEBUGMACROS_H */
+
+       /* the _HookPtr type is a shortcut for a pointer to a hook function */
+       typedef ASMCALL IPTR (*HookPtr)
+               (REG(a0, Class *), REG(a2, Object *), REG(a1, APTR));
+
+       #define _CALL_DISPATCHER(entry, cl, o, msg) \
+               ((HookPtr)(entry))(cl, o, msg)
+
+#endif /* _AROS */
+
+
+
+/* SAS/C is clever enough to inline these even var-args functions, while gcc and egcs
+ * refuse to do it (yikes!).  The GCC versions of these functions are macro blocks
+ * similar to those  used in the inline/#?.h headers.
+ */
+#if defined(__SASC) || defined (__STORM__)
+
+       INLINE ULONG CoerceMethodA(Class *cl, Object *o, Msg msg)
+       {
+               ASSERT_VALID_PTR(cl);
+               ASSERT_VALID_PTR_OR_NULL(o);
+
+               return _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg);
+       }
+
+       INLINE ULONG DoSuperMethodA(Class *cl, Object *o, Msg msg)
+       {
+               ASSERT_VALID_PTR(cl);
+               ASSERT_VALID_PTR_OR_NULL(o);
+
+               cl = cl->cl_Super;
+               return _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg);
+       }
+
+       INLINE ULONG DoMethodA(Object *o, Msg msg)
+       {
+               Class *cl;
+               ASSERT_VALID_PTR(o);
+               cl = OCLASS (o);
+               ASSERT_VALID_PTR(cl);
+
+               return _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg);
+       }
+
+       INLINE ULONG CoerceMethod(Class *cl, Object *o, ULONG MethodID, ...)
+       {
+               ASSERT_VALID_PTR(cl);
+               ASSERT_VALID_PTR_OR_NULL(o);
+
+               return ((HookPtr)cl->cl_Dispatcher.h_Entry) ((APTR)cl, (APTR)o, (APTR)&MethodID);
+       }
+
+       INLINE ULONG DoSuperMethod(Class *cl, Object *o, ULONG MethodID, ...)
+       {
+               ASSERT_VALID_PTR(cl);
+               ASSERT_VALID_PTR_OR_NULL(o);
+
+               cl = cl->cl_Super;
+               return ((HookPtr)cl->cl_Dispatcher.h_Entry) ((APTR)cl, (APTR)o, (APTR)&MethodID);
+       }
+
+       INLINE ULONG DoMethod(Object *o, ULONG MethodID, ...)
+       {
+               Class *cl;
+
+               ASSERT_VALID_PTR(o);
+               cl = OCLASS (o);
+               ASSERT_VALID_PTR(cl);
+
+               return ((HookPtr)cl->cl_Dispatcher.h_Entry) ((APTR)cl, (APTR)o, (APTR)&MethodID);
+       }
+
+       /* varargs stub for the OM_NOTIFY method */
+       INLINE void NotifyAttrs(Object *o, struct GadgetInfo *gi, ULONG flags, Tag attr1, ...)
+       {
+               ASSERT_VALID_PTR(o);
+               ASSERT_VALID_PTR_OR_NULL(gi);
+
+               DoMethod(o, OM_NOTIFY, &attr1, gi, flags);
+       }
+
+       /* varargs stub for the OM_UPDATE method */
+       INLINE void UpdateAttrs(Object *o, struct GadgetInfo *gi, ULONG flags, Tag attr1, ...)
+       {
+               ASSERT_VALID_PTR(o);
+               ASSERT_VALID_PTR_OR_NULL(gi);
+
+               DoMethod(o, OM_UPDATE, &attr1, gi, flags);
+       }
+
+       /* varargs stub for the OM_SET method. Similar to SetAttrs(), but allows
+        * to pass the GadgetInfo structure
+        */
+       INLINE void SetAttrsGI(Object *o, struct GadgetInfo *gi, ULONG flags, Tag attr1, ...)
+       {
+               ASSERT_VALID_PTR(o);
+               ASSERT_VALID_PTR_OR_NULL(gi);
+
+               DoMethod(o, OM_SET, &attr1, gi, flags);
+       }
+
+#elif defined(__GNUC__)
+
+       #define CoerceMethodA(cl, o, msg) \
+       ({ \
+               ASSERT_VALID_PTR(cl); \
+               ASSERT_VALID_PTR_OR_NULL(o); \
+               _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg); \
+       })
+
+       #define DoSuperMethodA(cl, o, msg) \
+       ({ \
+               Class *_cl; \
+               ASSERT_VALID_PTR(cl); \
+               ASSERT_VALID_PTR_OR_NULL(o); \
+               _cl = cl->cl_Super; \
+               ASSERT_VALID_PTR(_cl); \
+               _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, msg); \
+       })
+
+       #define DoMethodA(o, msg) \
+       ({ \
+               Class *_cl; \
+               ASSERT_VALID_PTR(o); \
+               _cl = OCLASS(o); \
+               ASSERT_VALID_PTR(_cl); \
+               _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, msg); \
+       })
+
+       #define CoerceMethod(cl, o, msg...) \
+       ({ \
+               IPTR _msg[] = { msg }; \
+               ASSERT_VALID_PTR(cl); \
+               ASSERT_VALID_PTR_OR_NULL(o); \
+               _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, _msg); \
+       })
+
+       #define DoSuperMethod(cl, o, msg...) \
+       ({ \
+               Class *_cl; \
+               IPTR _msg[] = { msg }; \
+               ASSERT_VALID_PTR(cl); \
+               ASSERT_VALID_PTR_OR_NULL(o); \
+               _cl = cl->cl_Super; \
+               ASSERT_VALID_PTR(_cl); \
+               _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \
+       })
+
+       #define DoMethod(o, msg...) \
+       ({ \
+               Class *_cl; \
+               IPTR _msg[] = { msg }; \
+               ASSERT_VALID_PTR(o); \
+               _cl = OCLASS(o); \
+               ASSERT_VALID_PTR_OR_NULL(_cl); \
+               _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \
+       })
+
+       /* Var-args stub for the OM_NOTIFY method */
+       #define NotifyAttrs(o, gi, flags, attrs...) \
+       ({ \
+               Class *_cl; \
+               IPTR _attrs[] = { attrs }; \
+               IPTR _msg[] = { OM_NOTIFY, (IPTR)_attrs, (IPTR)gi, flags }; \
+               ASSERT_VALID_PTR(o); \
+               _cl = OCLASS(o); \
+               ASSERT_VALID_PTR(_cl); \
+               ASSERT_VALID_PTR_OR_NULL(gi); \
+               _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \
+       })
+
+       /* Var-args stub for the OM_UPDATE method */
+       #define UpdateAttrs(o, gi, flags, attrs...) \
+       ({ \
+               Class *_cl; \
+               IPTR _attrs[] = { attrs }; \
+               IPTR _msg[] = { OM_UPDATE, (IPTR)_attrs, (IPTR)gi, flags }; \
+               ASSERT_VALID_PTR(o); \
+               _cl = OCLASS(o); \
+               ASSERT_VALID_PTR(_cl); \
+               ASSERT_VALID_PTR_OR_NULL(gi); \
+               _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \
+       })
+#endif
+
+#endif /* !BOOPSISTUBS_H */
diff --git a/include/CompilerSpecific.h b/include/CompilerSpecific.h
new file mode 100644 (file)
index 0000000..4a59158
--- /dev/null
@@ -0,0 +1,315 @@
+#ifndef COMPILERSPECIFIC_H
+#define COMPILERSPECIFIC_H
+/*
+**     $Id: CompilerSpecific.h,v 1.3 2000/01/12 20:30:24 bernie Exp $
+**
+**     Copyright (C) 1997-2000 Bernardo Innocenti <bernie@cosmos.it>
+**     All rights reserved.
+**
+**     Defines wrappers for several compiler dependent constructs,
+**     including function attributes and register specification for
+**     function arguments. Supports AROS, gcc, SAS/C, egcs, Storm C, VBCC,
+**     Maxon C, DICE and Aztec C.
+**
+**     You can easily add support for other compilers as well. Please
+**     return any changes you make to me, so I can add them to my
+**     personal copy of this file.
+**
+**     Here is a short description of the macros defined below:
+**
+**     LIBCALL
+**             Shared library entry point, with register args
+**
+**     HOOKCALL
+**             Hook or boopsi dispatcher entry point with arguments
+**             passed in registers
+**
+**     GLOBALCALL
+**             Attribute for functions to be exported to other modules for
+**             global access within the same executable file.
+**             Usually defined to "extern", but can be overridden for special
+**             needs, such as compiling all modules together in a single
+**             object module to optimize code better.
+**
+**     INLINE
+**             Please put function body inline to the calling code
+**
+**     STDARGS
+**             Function uses standard C conventions for arguments
+**
+**     ASMCALL
+**             Function takes arguments in the specified 68K registers
+**
+**     REGCALL
+**             Function takes arguments in registers choosen by the compiler
+**
+**     CONSTCALL
+**             Function does not modify any global variable
+**
+**     FORMATCALL(archetype,string_index,first_to_check)
+**             Function uses printf or scanf-like formatting
+**
+**     SAVEDS
+**             Function needs to reload context for small data model
+**
+**     INTERRUPT
+**             Function will be called from within an interrupt
+**
+**     NORETURN
+**             Function does never return
+**
+**     ALIGNED
+**             Variable must be aligned to longword boundaries
+**
+**     SECTION_CHIP
+**             Variable must be stored in CHIP RAM
+**
+**     XDEF
+**             Attribute for symbols to be exported to other modules for
+**             global access within the same executable file.
+**             Usually defined to an empty value.
+**
+**     XREF
+**             Attribute for symbols to be imported from other modules
+**             within the same executable file.
+**             Usually defined to "extern".
+**
+**     UNUSED(var)
+**             Explicitly specify a function parameter as being
+**             unused to prevent a compiler warning.
+**
+**     REG(reg,arg)
+**             Put argument <arg> in 68K register <reg>
+**
+**     min(a,b)
+**             Return the minimum between <a> and <b>
+**
+**     max(a,b)
+**             Return the maximum between <a> and <b>
+**
+**     abs(a)
+**             Return the absolute value of <a>
+**
+**     _COMPILED_WITH
+**             A string containing the name of the compiler
+*/
+
+#if defined(_AROS)
+       /* AROS + GCC (not m68k native) */
+
+       #define INLINE          static inline
+       #define STDARGS         /* nothing */
+       #define ASMCALL         /* nothing */
+       #define REGCALL         /* nothing */
+       #define CONSTCALL       __attribute__((const))
+       #define FORMATCALL(a,s,f) __attribute__((format(a,s,f)))
+       #define SAVEDS          /* nothing */
+       #define INTERRUPT       /* nothing */
+       #define NORETURN        __attribute__((noreturn))
+       #define ALIGNED         __attribute__((aligned(4)))
+       #define UNUSED(var)     var __attribute__((unused))
+       #define SECTION_CHIP    /* nothing */
+       #define REG(reg,arg)    arg
+       #define _COMPILED_WITH  "GCC"
+
+#elif defined(__GNUC__)
+       /* GeekGadgets gcc 2.95.2 or better (works with 2.7.2.1 too) */
+
+       #define INLINE          static inline
+       #define STDARGS         __attribute__((stkparm))
+       #define ASMCALL         /* nothing */
+       #define REGCALL         /* nothing */
+       #define CONSTCALL       __attribute__((const))
+       #define FORMATCALL(a,s,f)       __attribute__((format(a,s,f)))
+       #define SAVEDS          __attribute__((saveds))
+       #define INTERRUPT       __attribute__((interrupt))
+       #define NORETURN        __attribute__((noreturn))
+       #define ALIGNED         __attribute__((aligned(4)))
+       #define UNUSED(var)     var __attribute__((unused))
+       #if defined(__mc68000__)
+       # define SECTION_CHIP   __attribute__((chip))
+       # define REG(reg,arg)   arg __asm(#reg)
+       #else
+       # define SECTION_CHIP   /* nothing */
+       # define REG(reg,arg)   arg
+       #endif
+       #define _COMPILED_WITH  "GCC"
+       #define min(a,b)        (((a)<(b))?(a):(b))
+       #define max(a,b)        (((a)>(b))?(a):(b))
+
+#elif defined(__SASC)
+       /* SAS/C 6.58 or better */
+
+       #define INLINE          static __inline
+       #define STDARGS         __stdargs
+       #define ASMCALL         __asm
+       #define REGCALL         __regcall
+       #define CONSTCALL       /* unsupported */
+       #define FORMATCALL      /* unsupported */
+       #define SAVEDS          __saveds
+       #define INTERRUPT       __interrupt
+       #define NORETURN        /* unsupported */
+       #define ALIGNED         __aligned
+       #define SECTION_CHIP    __chip
+       #define UNUSED(var)     var /* unsupported */
+       #define REG(reg,arg)    register __##reg arg
+       #define _COMPILED_WITH  "SAS/C"
+
+       /* For min(), max() and abs() */
+       #define USE_BUILTIN_MATH
+       #include <string.h>
+
+#elif defined(__STORM__)
+       /* StormC 2.00.23 or better */
+       #define INLINE          __inline
+       #define STDARGS         /* nothing */
+       #define ASMCALL         /* nothing */
+       #define REGCALL         register
+       #define CONSTCALL       /* unsupported */
+       #define FORMATCALL      /* unsupported */
+       #define SAVEDS          __saveds
+       #define INTERRUPT       __interrupt
+       #define NORETURN        /* unsupported */
+       #define ALIGNED         /* unsupported */
+       #define SECTION_CHIP    __chip
+       #define UNUSED(var)     var /* unsupported */
+       #define REG(reg,arg)    register __##reg arg
+       #define _COMPILED_WITH  "StormC"
+
+       #define min(a,b)        (((a)<(b))?(a):(b))
+       #define max(a,b)        (((a)>(b))?(a):(b))
+       #define abs(a)          (((a)>0)?(a):-(a))
+
+       #define _INLINE_INCLUDES
+       #include <string.h>
+
+#elif defined(__VBCC__)
+       /* VBCC 0.7 (m68k) or better */
+
+       #define INLINE          static __inline
+       #define STDARGS         /* unsupported */
+       #define ASMCALL         /* nothing */
+       #define REGCALL         /* nothing */
+       #define CONSTCALL       /* unsupported */
+       #define FORMATCALL      /* unsupported */
+       #define SAVEDS          __saveds
+       #define INTERRUPT       /* unsupported */
+       #define NORETURN        /* unsupported */
+       #define ALIGNED         /* unsupported */
+       #define SECTION_CHIP    __chip
+       #define UNUSED(var)     var /* unsupported */
+       #define REG(reg,arg)    __reg(##reg) arg
+       #define _COMPILED_WITH  "VBCC"
+
+       #error VBCC compiler support is untested. Please check all the above definitions
+
+#elif defined(__MAXON__)
+       /* Maxon C/C++ 3.0 */
+
+       #define INLINE          static inline
+       #define STDARGS         /* ? */
+       #define ASMCALL         /* ? */
+       #define REGCALL         /* ? */
+       #define CONSTCALL       /* unsupported */
+       #define FORMATCALL      /* unsupported */
+       #define SAVEDS          /* unsupported */
+       #define INTERRUPT       /* unsupported */
+       #define NORETURN        /* unsupported */
+       #define ALIGNED         /* unsupported */
+       #define UNUSED(var)     var /* unsupported */
+       #define REG(reg,arg)    register __##reg arg
+       #define _COMPILED_WITH  "Maxon C"
+
+       /* For min(), max() and abs() */
+       #define USE_BUILTIN_MATH
+       #include <string.h>
+
+       #error Maxon C compiler support is untested. Please check all the above definitions
+
+#elif defined(_DCC)
+       /* DICE C 3.15 */
+
+       #define INLINE          static __inline
+       #define STDARGS         __stdargs
+       #define ASMCALL         /* nothing */
+       #define REGCALL         /* ? */
+       #define CONSTCALL       /* unsupported */
+       #define FORMATCALL      /* unsupported */
+       #define SAVEDS          __geta4
+       #define INTERRUPT       /* unsupported */
+       #define NORETURN        /* unsupported */
+       #define ALIGNED         __aligned
+       #define UNUSED(var)     var /* unsupported */
+       #define REG(reg,arg)    __##reg arg
+       #define _COMPILED_WITH  "DICE"
+
+       #define min(a,b)        (((a)<(b))?(a):(b))
+       #define max(a,b)        (((a)>(b))?(a):(b))
+       #define abs(a)          (((a)>0)?(a):-(a))
+
+       #error DICE compiler support is untested. Please check all the above definitions
+
+#elif defined(AZTEC_C)
+       /* Aztec/Manx C */
+
+       #define INLINE          static
+       #define STDARGS         /* ? */
+       #define ASMCALL         /* ? */
+       #define REGCALL         /* ? */
+       #define CONSTCALL       /* unsupported */
+       #define FORMATCALL      /* unsupported */
+       #define SAVEDS          __geta4
+       #define INTERRUPT       /* unsupported */
+       #define NORETURN        /* unsupported */
+       #define ALIGNED         __aligned
+       #define UNUSED(var)     var /* unsupported */
+       #define REG(reg,arg)    __##reg arg
+       #define _COMPILED_WITH  "Manx C"
+
+       #define min(a,b)        (((a)<(b))?(a):(b))
+       #define max(a,b)        (((a)>(b))?(a):(b))
+       #define abs(a)          (((a)>0)?(a):-(a))
+
+       #error Aztec/Manx C compiler support is untested. Please check all the above definitions
+#else
+       #error Please add compiler specific definitions for your compiler
+#endif
+
+
+/* CONST_STRPTR is a new typedef provided since the V44 version of
+ * <exec/types.h>. Passing "const char *" parameters will only work
+ * if the OS protos are using CONST_STRPTR accordingly, otherwise you
+ * will get a lot of compiler warnings for const to volatile conversions.
+ *
+ * Using "const" where it is appropriate helps the compiler optimizing
+ * code better, so this mess is probably worth it.
+ */
+#if (!defined(_AROS)) && (INCLUDE_VERSION < 44)
+typedef char *CONST_STRPTR;
+#endif
+
+
+/* Special function attributes */
+
+#define LIBCALL                ASMCALL SAVEDS
+#define HOOKCALL       ASMCALL SAVEDS
+#ifdef __cplusplus
+       #define GLOBALCALL extern "C"
+#else
+       #define GLOBALCALL
+#endif
+
+/* special variable attributes */
+#define XDEF
+#define XREF extern
+
+
+/* AROS Compatibility: IPTR is a type which can store a pointer
+ * as well as a long integer.
+ */
+#if !defined(IPTR) && !defined(__typedef_IPTR)
+#define IPTR unsigned long
+#endif /* IPTR */
+
+
+#endif /* !COMPILERSPECIFIC_H */
diff --git a/include/DebugMacros.h b/include/DebugMacros.h
new file mode 100644 (file)
index 0000000..cca9f8f
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef DEBUGMACROS_H
+#define DEBUGMACROS_H
+/*
+**     $Id: DebugMacros.h,v 1.3 2000/01/12 20:30:24 bernie Exp $
+**
+**     Copyright (C) 1995,96,97,98,99 Bernardo Innocenti <bernardo.innocenti@usa.net>
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     Some handy debug macros which are automatically excluded when the
+**     _DEBUG preprocessor symbol isn't defined. To make debug executables,
+**     you must link with debug.lib or any module containing the kprintf()
+**     function.
+**
+**     Here is a short description of the macros defined below:
+**
+**     ILLEGAL
+**             Output an inline "ILLEGAL" 68K opcode, which will
+**             be interpreted as a breakpoint by most debuggers.
+**
+**     bug
+**     DBPRINTF
+**             Output a formatted string to the debug console. This
+**             macro uses the debug.lib/kprintf() function by default.
+**
+**     ASSERT(x)
+**             Do nothing if the expression <x> evalutates to a
+**             non-zero value, output a debug message otherwise.
+**
+**     ASSERT_VALID_PTR(x)
+**             Checks if the expression <x> points to a valid
+**             memory location, and outputs a debug message
+**             otherwise. A NULL pointer is considered VALID.
+**
+**     ASSERT_VALID_PTR_OR_NULL(x)
+**             Checks if the expression <x> points to a valid
+**             memory location, and outputs a debug message
+**             otherwise. A NULL pointer is considered INVALID.
+**
+**     D(x)
+**     DB(x)
+**             Compile the expression <x> when making a debug
+**             executable, otherwise omit it.
+**
+**     DB1(x)
+**             DB verbosity level 1. Compile the expression <x> when the
+**             preprocessor symbol DEBUG is defined to a number greater or
+**             equal to 1.
+**
+**     DB2(x)
+**             DB verbosity level 2. Compile the expression <x> when the
+**             preprocessor symbol _DEBUG is defined to a number greater or
+**             equal to 2.
+*/
+
+/* Accept DEBUG as well as _DEBUG */
+#ifndef _DEBUG
+#      ifdef DEBUG
+#              define _DEBUG DEBUG
+#      else
+#              define _DEBUG 0
+#      endif
+#endif
+
+#if _DEBUG
+
+       /* Needed for TypeOfMem() */
+       #ifndef  PROTO_EXEC_H
+       #include <proto/exec.h>
+       #endif /* PROTO_EXEC_H */
+
+       #if defined(__SASC)
+
+               extern void __builtin_emit (int);
+               // #define ILLEGAL __builtin_emit(0x4AFC)
+               #define ILLEGAL 0
+               STDARGS extern void kprintf (const char *, ...);
+
+       #elif defined(__GNUC__)
+
+               /* GCC doesn't accept asm statements in the middle of an
+                * expression such as `a ? b : asm("something")'.
+                */
+               #define ILLEGAL illegal()
+               static __inline__ int illegal(void) { asm("illegal"); return 0; }
+               extern void STDARGS FORMATCALL(printf,1,2) kprintf(const char *, ...);
+
+       #else
+               #error Please add compiler specific definitions for your compiler
+       #endif
+
+
+       /* common definitions for ASSERT and DB macros */
+
+       #define DBPRINTF kprintf
+       #define bug kprintf
+
+       /* The trick with THIS_FILE is meant to avoid multiple allocations of
+        * the filename string for each occurrence of these macros. To reduce
+        * debug executable size, each module should cooperate by undefinining
+        * the THIS_FILE macro and declaring a static global symbol with the
+        * same name.
+        */
+       #define THIS_FILE __FILE__
+
+       #define ASSERT(x) ( (x) ? 0 :                                                                   \
+               ( DBPRINTF("\x07%s:%ld: assertion failed: %s\n",                        \
+               THIS_FILE, __LINE__, #x) , ILLEGAL ) );
+
+       #define ASSERT_VALID_PTR_OR_NULL(x) ( ((((APTR)(x)) == NULL) || \
+               (((LONG)(x) > 1024) &&  TypeOfMem((APTR)(x)))) ? 0 :            \
+               ( DBPRINTF("\x07%s:%ld: bad pointer: %s = $%lx\n",      \
+               THIS_FILE, __LINE__, #x, (APTR)(x)) , ILLEGAL ) );
+
+       #define ASSERT_VALID_PTR(x) ( (((LONG)(x) > 1024) &&                    \
+               TypeOfMem((APTR)(x))) ? 0 :                                                                     \
+               ( DBPRINTF("\x07%s, %ld: bad pointer: %s = $%lx\n",                     \
+               THIS_FILE, __LINE__, #x, (APTR)(x)) , ILLEGAL ) );
+
+       #define D(x) x
+       #define DB(x) x
+       #define DB1(x) x
+
+       #if _DEBUG >= 2
+               #define DB2(x) x
+       #else
+               #define DB2(x)
+       #endif
+
+       #if _DEBUG >= 3
+               #define DB3(x) x
+       #else
+               #define DB3(x)
+       #endif
+#else
+       #define ASSERT_VALID_PTR(x)
+       #define ASSERT_VALID_PTR_OR_NULL(x)
+       #define ASSERT(x)
+       #define DB(x)
+       #define D(x)
+       #define DB1(x)
+       #define DB2(x)
+       #define DB3(x)
+#endif /* _DEBUG */
+
+#endif /* !DEBUGMACROS_H */
diff --git a/include/DiagnosticMacros.h b/include/DiagnosticMacros.h
new file mode 100644 (file)
index 0000000..4135a7c
--- /dev/null
@@ -0,0 +1,146 @@
+#ifndef DIAGNOSTICMACROS_H
+#define DIAGNOSTICMACROS_H
+/*
+**     $Id: DiagnosticMacros.h,v 1.3 2000/01/12 20:29:05 bernie Exp $
+**
+**     Copyright (C) 1999 Bernardo Innocenti <bernardo.innocenti@usa.net>
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     These are some handy macros to dump some common system
+**     structures to the debug console. Use DUMP_XXX(pointer)
+**     in your code to get a full dump of the structure contents.
+**
+**     These macros will automatically disable themselves when the
+**     preprocessor symbol DEBUG isn't defined.
+*/
+
+#ifdef DEBUG
+
+#define DUMP_BITMAP(p)         DumpBitMap(p, #p);
+#define DUMP_LAYER(p)          DumpLayer(p, #p);
+#define DUMP_GADGETINFO(p)     DumpGadgetInfo (p, #p);
+
+#ifdef INTUITION_CGHOOKS_H
+static void DumpGadgetInfo (struct GadgetInfo *p, const char *name)
+{
+       if (p)
+       {
+               DBPRINTF ("struct GadgetInfo * %s (at 0x%lx) = {\n", name, p);
+               DBPRINTF ("    struct Screen *    gi_Screen    = 0x%lx\n", p->gi_Screen);
+               DBPRINTF ("    struct Window *    gi_Window    = 0x%lx\n", p->gi_Window);
+               DBPRINTF ("    struct Requester * gi_Requester = 0x%lx\n", p->gi_Requester);
+
+               DBPRINTF ("    struct RastPort *  gi_RastPort  = 0x%lx\n", p->gi_RastPort);
+               DBPRINTF ("    struct Layer *     gi_Layer     = 0x%lx\n", p->gi_Layer);
+               DBPRINTF ("    struct IBox        gi_Domain    = { %ld, %ld, %ld, %ld }\n",
+                       p->gi_Domain.Left, p->gi_Domain.Top, p->gi_Domain.Width, p->gi_Domain.Height);
+               DBPRINTF ("    UBYTE              gi_Pens      = { %ld, %ld }\n",
+                       p->gi_Pens.DetailPen, p->gi_Pens.BlockPen);
+               DBPRINTF ("    struct DrawInfo *  gi_DrInfo    = 0x%lx\n", p->gi_DrInfo);
+       }
+       else
+               DBPRINTF ("    struct GadgetInfo * %s = NULL\n", name);
+}
+#endif /* !INTUITION_CGHOOKS_H */
+
+#ifdef GRAPHICS_GFX_H
+static void DumpBitMap (struct BitMap *p, const char *name)
+{
+       if (p)
+       {
+               DBPRINTF ("struct BitMap * %s (at 0x%lx) = {\n", name, p);
+               DBPRINTF ("    UWORD    BytesPerRow = %ld\n", p->BytesPerRow);
+               DBPRINTF ("    UWORD    Rows        = %ld\n", p->Rows);
+               DBPRINTF ("    UBYTE    Flags       = 0x%lx\n", p->Flags);
+               DBPRINTF ("    UBYTE    Depth       = %ld\n", p->Depth);
+               DBPRINTF ("    UWORD    pad         = %ld\n", p->pad);
+               DBPRINTF ("    PLANEPTR Planes[8]   = { 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx }\n",
+                       p->Planes[0], p->Planes[1], p->Planes[2], p->Planes[3],
+                       p->Planes[4], p->Planes[5], p->Planes[6], p->Planes[7]);
+               DBPRINTF ("};\n");
+       }
+       else
+               DBPRINTF ("    struct BitMap * %s = NULL\n", name);
+}
+#endif /* !GRAPHICS_GFX_H */
+
+
+#ifdef GRAPHICS_CLIP_H
+static void DumpLayer (struct Layer *p, const char *name)
+{
+       if (p)
+       {
+               char flags[128];
+
+               flags[0] = '\0';
+
+               if (p->Flags & LAYERSIMPLE)             strcat(flags, "LAYERSIMPLE");
+               if (p->Flags & LAYERSMART)              strcat(flags, " | LAYERSMART");
+               if (p->Flags & LAYERSUPER)              strcat(flags, " | LAYERSUPER");
+               if (p->Flags & 0x0008)                  strcat(flags, " | 0x0008");
+               if (p->Flags & LAYERUPDATING)   strcat(flags, " | LAYERUPDATING");
+               if (p->Flags & 0x0020)                  strcat(flags, " | 0x0020");
+               if (p->Flags & LAYERBACKDROP)   strcat(flags, " | LAYERBACKDROP");
+               if (p->Flags & LAYERREFRESH)    strcat(flags, " | LAYERREFRESH");
+               if (p->Flags & LAYER_CLIPRECTS_LOST) strcat(flags, " | LAYER_CLIPRECTS_LOST");
+               if (p->Flags & LAYERIREFRESH)   strcat (flags, " | LAYERIREFRESH");
+               if (p->Flags & LAYERIREFRESH2)  strcat (flags, " | LAYERIREFRESH2");
+               if (p->Flags & 0x0800)                  strcat(flags, " | 0x0800");
+               if (p->Flags & 0x1000)                  strcat(flags, " | 0x1000");
+               if (p->Flags & 0x2000)                  strcat(flags, " | 0x2000");
+               if (p->Flags & 0x4000)                  strcat(flags, " | 0x4000");
+               if (p->Flags & 0x8000)                  strcat(flags, " | 0x8000");
+
+
+               DBPRINTF ("struct Layer * %s (at 0x%lx) = {\n", name, p);
+               DBPRINTF ("    struct Layer *      front         = 0x%lx, back = 0x%lx\n", p->front, p->back);
+               DBPRINTF ("    struct ClipRect *   ClipRect      = 0x%lx\n", p->ClipRect);
+               DBPRINTF ("    struct RastPort *   rp            = 0x%lx\n", p->rp);
+        DBPRINTF ("    struct Rectangle    bounds        = { %ld, %ld, %ld, %ld }\n",
+               p->bounds.MinX, p->bounds.MinY, p->bounds.MaxX, p->bounds.MaxY);
+        DBPRINTF ("    UBYTE               reserved[4]   = { %ld, %ld, %ld, %ld }\n",
+               p->reserved[0], p->reserved[1], p->reserved[2], p->reserved[3]);
+               DBPRINTF ("    UWORD               priority      = %ld\n", p->priority);
+               DBPRINTF ("    UWORD               Flags         = 0x%lx (%s)\n", p->Flags, flags);
+               DBPRINTF ("    struct BitMap *     SuperBitMap   = 0x%lx\n", p->SuperBitMap);
+               DBPRINTF ("    struct ClipRect *   SuperClipRect = 0x%lx\n", p->SuperClipRect);
+               DBPRINTF ("    APTR                Window        = 0x%lx\n", p->Window);
+               DBPRINTF ("    UWORD               Scroll_X      = %ld, Scroll_Y = %ld\n", p->Scroll_X, p->Scroll_Y);
+               DBPRINTF ("    struct ClipRect *   cr            = 0x%lx, cr2 = 0x%lx, crnew = 0x%lx\n",
+                       p->cr, p->cr2, p->crnew);
+               DBPRINTF ("    struct ClipRect *   SuperSaveClipRects = 0x%lx\n", p->SuperSaveClipRects);
+               DBPRINTF ("    struct ClipRect *   _cliprects    = 0x%lx\n", p->_cliprects);
+               DBPRINTF ("    struct Layer_Info * LayerInfo     = 0x%lx\n", p->LayerInfo);
+               DBPRINTF ("    struct SignalSemaphore Lock = {\n");
+               DBPRINTF ("        WORD          ss_NestCount = %ld\n", p->Lock.ss_NestCount);
+               DBPRINTF ("        struct Task * ss_Owner     = 0x%lx\n", p->Lock.ss_Owner);
+        DBPRINTF ("        ...\n");
+               DBPRINTF ("    };\n");
+               DBPRINTF ("    struct Hook *       BackFill      = 0x%lx\n", p->BackFill);
+               DBPRINTF ("    ULONG               reserved1     = 0x%lx\n", p->reserved1);
+               DBPRINTF ("    struct Region *     ClipRegion    = 0x%lx\n", p->ClipRegion);
+               DBPRINTF ("    struct Region *     saveClipRects = 0x%lx\n", p->saveClipRects);
+               DBPRINTF ("    WORD                Width         = %ld, Height = %ld\n", p->Width, p->Height);
+               DBPRINTF ("    UBYTE               reserved2[18] = ...\n");
+               DBPRINTF ("    struct Region *     DamageList    = 0x%lx\n", p->DamageList);
+               DBPRINTF ("};\n");
+       }
+       else
+               DBPRINTF ("struct Layer * %s = NULL\n", name);
+}
+#endif /* !GRAPHICS_CLIP_H */
+
+
+
+
+#else /* DEBUG not defined */
+
+#define DUMP_BITMAP(x)
+#define DUMP_LAYER(x)
+#define DUMP_GADGETINFO(x)
+
+#endif /* !DEBUG */
+
+#endif /* !DIAGNOSTICMACROS_H */
diff --git a/include/ListMacros.h b/include/ListMacros.h
new file mode 100644 (file)
index 0000000..b19bc64
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef LISTMACROS_H
+#define LISTMACROS_H
+/*
+**     $Id: ListMacros.h,v 1.2 1999/02/07 14:41:02 bernie Exp $
+**
+**     Copyright (C) 1997 Bernardo Innocenti <bernardo.innocenti@usa.net>
+**     All rights reserved.
+**
+**     Use 4 chars wide TABs to read this source
+**
+**     Some handy macros for list operations.  Using these macros is faster
+**     than calling their exec.library equivalents, but they will eventually
+**     make your code a little bigger and are also subject to common macro
+**     side effects.
+*/
+
+
+#define NEWLIST(l)     ( (l)->lh_TailPred = (struct Node *)(l),                        \
+                                       (l)->lh_Tail = 0,                                                                       \
+                                       (l)->lh_Head = (struct Node *)(&((l)->lh_Tail)) )
+
+#define ADDHEAD(l,n) ( (n)->ln_Pred = (struct Node *)(l),                              \
+                                       (n)->ln_Succ = (l)->lh_Head,                                            \
+                                       (l)->lh_Head->ln_Pred = (n),                                            \
+                                       (l)->lh_Head = (n) )
+
+#define ADDTAIL(l,n) ( (n)->ln_Succ = (struct Node *)(&((l)->lh_Tail)),        \
+                                       (n)->ln_Pred = (l)->lh_TailPred,                                        \
+                                       (l)->lh_TailPred->ln_Succ = (n),                                        \
+                                       (l)->lh_TailPred = (n) )
+
+#define REMOVE(n)      ( (n)->ln_Succ->ln_Pred = (n)->ln_Pred,                         \
+                                       (n)->ln_Pred->ln_Succ = (n)->ln_Succ )
+
+#define GETHEAD(l)     ( (l)->lh_Head->ln_Succ ? (l)->lh_Head : (struct Node *)NULL )
+
+#define GETTAIL(l)  ( (l)->lh_TailPred->ln_Succ ? (l)->lh_TailPred : (struct Node *)NULL )
+
+#define GETSUCC(n)  ( (n)->ln_Succ->ln_Succ ? (n)->ln_Succ : (struct Node *)NULL )
+
+#define GETPRED(n)  ( (n)->ln_Pred->ln_Pred ? (n)->ln_Pred : (struct Node *)NULL )
+
+
+#ifdef __GNUC__
+
+#define REMHEAD(l)                                                                                                                     \
+({                                                                                                                                                     \
+       struct Node *n = (l)->lh_Head;                                                                                  \
+       n->ln_Succ ?                                                                                                                    \
+               (l)->lh_Head = n->ln_Succ,                                                                                      \
+                       (l)->lh_Head->ln_Pred = (struct Node *)(l),                                             \
+                       n :                                                                                                                             \
+               NULL;                                                                                                                           \
+})
+
+#define REMTAIL(l)                                                                                                                     \
+({                                                                                                                                                     \
+       struct Node *n = (l)->lh_TailPred;                                                                              \
+       n->ln_Pred ?                                                                                                                    \
+               (l)->lh_TailPred = n->ln_Pred,                                                                          \
+                       (l)->lh_TailPred->ln_Succ = (struct Node *)(&((l)->lh_Tail)),   \
+                       n :                                                                                                                             \
+               NULL;                                                                                                                           \
+})
+
+
+#else
+
+/* These two can't be implemented as macros without the GCC ({...}) language extension */
+
+INLINE struct Node *REMHEAD(struct List *l)
+{
+       struct Node *n = l->lh_Head;
+
+       if (n->ln_Succ)
+       {
+               l->lh_Head = n->ln_Succ;
+               l->lh_Head->ln_Pred = (struct Node *)l;
+               return n;
+       }
+       return NULL;
+}
+
+INLINE struct Node *REMTAIL(struct List *l)
+{
+       struct Node *n = l->lh_TailPred;
+
+       if (n->ln_Pred)
+       {
+               l->lh_TailPred = n->ln_Pred;
+               l->lh_TailPred->ln_Succ = (struct Node *)(&(l->lh_Tail));
+               return n;
+       }
+       return NULL;
+}
+
+#endif
+
+#endif /* !LISTMACROS_H */
diff --git a/include/README b/include/README
new file mode 100644 (file)
index 0000000..6e31866
--- /dev/null
@@ -0,0 +1,45 @@
+Short:    Boopsi, cross compiling and debug support macros
+Author:   bernie@cosmos.it (Bernardo Innocenti)
+Uploader: bernie@cosmos.it (Bernardo Innocenti)
+Type:     dev/src
+Version:  2.0
+
+ During the developement of my projects I've written some useful
+macros that simplify some common problems. The macros have eventually
+grown to full header files that I'm now using almost everywhere.
+
+ I've packaged all these headers in a distribution archive, in the hope
+that they will be useful to other programmers as well.
+
+
+ - CompilerSpecific.h
+       Defines wrappers for several compiler dependent constructs,
+       including function attributes and register specification for
+       function arguments. Supports SAS/C, gcc, EGCS, Storm C, Maxon C,
+       DICE and Aztec C.
+
+ - BoopsiStubs.h
+       Using these inline versions of the amiga.lib boopsi support functions
+       results in faster and smaller code against their linked library
+       counterparts. When debug is active, these functions will also
+       validate the parameters you pass in.
+
+ - BoopsiLib.h
+       Additional macros and inline functions for boopsi class developement.
+
+ - DebugMacros.h
+       Some handy debug macros which are automatically excluded when the
+       DEBUG preprocessor symbol isn't defined. To make debug executables,
+       you must link with debug.lib or any linker module containing a
+       kprintf()-like function.
+
+ - DiagnosticMacros.h
+       Some handy macros to dump some common system structs to the
+       debug console. Use DUMP_XXX(pointer) in your code to get a
+       detailed dump of the structure contents.
+
+ - ListMacros.h
+       Some handy macros for list operations. Using these macros is faster
+       than calling their exec.library equivalents, but they will eventually
+       make your code a little bigger and are also subject to common macro
+       side effects.
diff --git a/include/gadgets/FrPropGClass.h b/include/gadgets/FrPropGClass.h
new file mode 100644 (file)
index 0000000..cc0e495
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef FRPROPGCLASS_H
+#define FRPROPGCLASS_H
+/*
+**     $Id: FrPropGClass.h,v 1.1 1999/02/07 14:24:42 bernie Exp $
+**
+**     Copyright (C) 1999 Bernardo Innocenti
+**     All rights reserved.
+**
+**     A simple subclass of the propgclass which supports to be framed
+**     with any boopsi image. The frame must be specified specified
+**     through the GA_LabelImage tag because the GA_Image already has
+**     a special meaning for the propgclass.
+**
+**     Unfortunately The original ROM class is not smart enough to do
+**     this simple job by itself. This new class overloads the GM_RENDER
+**     method to work around these problems.
+*/
+
+
+#define FRPROPGCLASS           "frpropgclass"
+#define FRPROPGVERS    1
+
+
+/* Functions to initialize and destroy the class */
+Class  *MakeFrPropGClass       (void);
+BOOL    FreeFrPropGClass       (Class *cl);
+
+
+
+/*****************/
+/* Class Methods */
+/*****************/
+
+/* This class does not define any new methods */
+
+/********************/
+/* Class Attributes */
+/********************/
+
+/* #define FPGA_Dummy (TAG_USER | ('F'<<16) | ('P'<<8)) */
+
+/* This class does not define any new attributes */
+
+
+
+
+#endif /* !FRPROPGCLASS_H */
diff --git a/include/gadgets/ListBoxClass.h b/include/gadgets/ListBoxClass.h
new file mode 100644 (file)
index 0000000..7d08e37
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef LISTBOXCLASS_H
+#define LISTBOXCLASS_H
+/*
+**     ListBoxClass.h
+**
+**     Copyright (C) 1997 by Bernardo Innocenti
+**
+**     ListBox class built on top of the "groupgclass".
+**
+*/
+
+#include <gadgets/ListViewClass.h>
+
+
+#define LISTBOXCLASS   "listboxclass"
+#define LISTBOXVERS            1
+
+
+/* Class initializer and terminator. Only avalable for the
+ * static linker object flavour.
+ */
+Class  *MakeListBoxClass(void);
+BOOL    FreeListBoxClass(Class *ListViewClass);
+
+
+
+/*****************/
+/* Class Methods */
+/*****************/
+
+/* This class does not define any new methods */
+
+/********************/
+/* Class Attributes */
+/********************/
+
+/* #define LBA_Dummy (TAG_USER | ('L'<<16) | ('B'<<8)) */
+
+/* This class does not define any new attributes */
+
+
+#endif /* !LISTBOXCLASS_H */
diff --git a/include/gadgets/ListViewClass.h b/include/gadgets/ListViewClass.h
new file mode 100644 (file)
index 0000000..45a0dba
--- /dev/null
@@ -0,0 +1,445 @@
+#ifndef LISTVIEWCLASS_H
+#define LISTVIEWCLASS_H
+/*
+**     $Id: ListViewClass.h,v 1.4 2000/01/12 21:18:06 bernie Exp $
+**
+**     Copyright (C) 1996,97,99 by Bernardo Innocenti
+**
+**     ListView class built on top of the "gadgetclass".
+**
+*/
+
+#define LISTVIEWCLASS  "listviewclass"
+#define LISTVIEWVERS   1
+
+
+Class  *MakeListViewClass(void);
+BOOL    FreeListViewClass(Class *LVClass);
+
+
+
+/*
+ * New Methods
+ */
+
+/* This class does not define any new methods */
+
+
+/*
+ * New Attributes
+ */
+
+#define LVA_Dummy                      (TAG_USER | ('L'<<16) | ('V'<<8))
+
+#define LVA_Selected           (LVA_Dummy+1)
+       /* [IGSNU] (LONG) - Selected item number. ~0 (-1) indicates that no
+        * item is selected.
+        */
+
+#define LVA_Top                                (LVA_Dummy+2)
+       /* [IGSNU] (LONG) - Number of top displayed item. Default is 0.
+        */
+
+#define LVA_Total                      (LVA_Dummy+3)
+       /* [IGSN] (LONG) - Total number of items in list.
+        * This attribute can be set when LVA_StringArray, LVA_ImageArray
+        * or LVA_CustomList is used. If you pass -1 or omit this tag,
+        * the ListView class will count the items in the array until it
+        * finds a NULL entry. If you know the number of nodes in your list,
+        * you will save some internal overhead by telling it to the
+        * ListView with the LVA_Total tag, expecially when using the
+        * LVA_StringList and LVA_ImageList modes. You must set LVA_Total
+        * each time you provide a new list or array, and in the same
+        * OM_SET call.
+        * Be careful: no checks are made on the values you are passing!
+        */
+
+#define LVA_SelectItem         (LVA_Dummy+4)
+       /* [SN] (LONG) - Add item specified by ti_Data to the
+        * selection list.
+        */
+
+#define LVA_DeselectItem       (LVA_Dummy+5)
+       /* [SN] (LONG) - Remove item specified by ti_Data from the
+        * selection list.
+        */
+
+#define LVA_ToggleItem         (LVA_Dummy+6)
+       /* [SN] (LONG) - Toggle item selection.
+        */
+
+#define LVA_ClearSelected      (LVA_Dummy+7)
+       /* [SN] (LONG) - Remove the selected state to AALL items.
+        */
+
+
+#define LVA_MakeVisible                (LVA_Dummy+8)
+       /* [ISU] (BOOL) - Make this item visible by doing the minimum required
+        * scrolling.
+        */
+
+#define LVA_MoveUp                     (LVA_Dummy+9)
+#define LVA_MoveDown           (LVA_Dummy+10)
+#define LVA_MoveLeft           (LVA_Dummy+11)
+#define LVA_MoveRight          (LVA_Dummy+12)
+       /* [SU] - Scroll the display up/down. left/right movement is not
+        * yet supported.
+        */
+
+#define LVA_StringList         (LVA_Dummy+13)
+#define LVA_StringArray                (LVA_Dummy+14)
+#define LVA_ImageList          (LVA_Dummy+15)
+#define LVA_ImageArray         (LVA_Dummy+16)
+#define LVA_CustomList         (LVA_Dummy+17)
+#define LVA_Labels                     LVA_StringList
+       /* [ISG] - List of items to display. All structures and strings
+        * are referenced, not copied, so they must stay in memory
+        * while the ListView gadget displays them.
+        *
+        * LVA_StringList (AKA LVA_Labels) passes a pointer to a
+        * List (or MinList) of Node structures. The strings
+        * pointed by ln_Name will be displayed as item labels.
+        *
+        * LVA_StringArray specifies a pointer to an array of STRPTR which
+        * will be used as item labels.  The array must be NULL terminated
+        * unless the LVA_Count is set.
+        *
+        * LVA_ImageList passes a pointer to a List (or MinList)
+        * of Node structures. The ln_Name field of each Node structure
+        * must point to a normal Image structure or to an instance of
+        * the imageclass (or a subclass of it).
+        *
+        * LVA_ImageArray specifies a pointer to an array of pointers to
+        * Image structures or imageclass objects.  The array must be NULL
+        * terminated unless the LVA_Count attribute is used.
+        *
+        * LVA_CustomList can be used to provide a data structure which
+        * is neither a list nor an array.  Custom user functions will
+        * be called to retrieve the items. The data passed with this
+        * tag will be passed to the user functions.
+        *
+        * Setting one of these attributes to NULL causes the contents
+        * of the ListView gadget to be cleared.
+        *
+        * Setting one of these attributes to ~0 (-1) detaches the
+        * items from the ListView.  You must detach your list before
+        * adding or removing items.  This isn't required when using
+        * array oriented item lists.
+        */
+
+#define LVA_Visible                    (LVA_Dummy+18)
+       /* [IGN] (ULONG) - Number of visible items. When this attribute is
+        * passed on intialization, the ListView gadget will resize
+        * itself to make the desired number of lines visible. this
+        * feature is incompatible with GA_RelHeight. LVA_Visible at
+        * creation time requires a valid DrawInfo passed with the
+        * GA_DrawInfo tag.
+        */
+
+#define LVA_SelectedPtr                (LVA_Dummy+19)
+       /* [GN] (APTR) - Selected item pointer or NULL when no
+        * items are selected.
+        */
+
+#define LVA_SelectArray                (LVA_Dummy+20)
+       /* [ISGNU] (ULONG *) - This array of ULONGs is only used in
+        * LVA_#?Array modes, when multiple selection is active. It will
+        * hold the selection status of all items in the list. Each
+        * element will be 0 if the related item is unselected, and
+        * it will indicate the selection order when the item is
+        * selected.
+        */
+
+#define LVA_CallBack           (LVA_Dummy+21)
+       /* [I] (struct Hook *) - Callback hook for various listview operations.
+        * The call back hook is called with:
+        *              A0 - struct Hook *
+        *              A1 - struct LVDrawMsg *
+        *              A2 - struct Node *
+        * The callback hook *must* check the lvdm_MethodID field of the
+        * message and only do processing if it is known. If any other
+        * value is passed, the callback hook must return LVCB_UNKNOWN.
+        */
+
+#define LVA_ShowSelected       (LVA_Dummy+23)
+       /* [I] (BOOL) - Enable highlighting selected items (default is TRUE).
+        * Note that this is different from the GadTools ListView default,
+        * which is not displaying the selected item.
+        */
+
+#define LVA_Clipped                    (LVA_Dummy+24)
+       /* [I] (BOOL) - When this attribute is set, the ListView gadget
+        * installs a ClipRegion in its Layer whenever it redraws its items.
+        * (defaults is FALSE).
+        */
+
+#define LVA_DoMultiSelect      (LVA_Dummy+25)
+       /* [I] (BOOL) - Allows picking multiple items from the list
+        * (default is FALSE).
+        * When MultiSelect mode is active and a List structure is used,
+        * the ListView gadget keeps track of which items are selected
+        * by setting/clearing the ln_Type field of the Node structure.
+        * When items are passed with an array, you must also provide
+        * a second array for storing selection information (LVA_SelectArray).
+        * When item number n is selected, then the n-th BOOL of this array
+        * is set with its selection order.
+        */
+
+#define LVA_ItemHeight         (LVA_Dummy+27)
+       /* [I] (ULONG) - Exact height of an item. Defaults to be the Y size
+        * of the font used to draw the text labels. The listview will ask
+        * the height to its Image items if not explicitly given.
+        */
+
+#define LVA_MaxPen                     (LVA_Dummy+28)
+       /* [I] (LONG) - The maximum pen number used by rendering in a custom
+        * rendering callback hook. This is used to optimize the
+        * rendering and scrolling of the listview display (default is
+        * the maximum pen number used by all of TEXTPEN, BACKGROUNDPEN,
+        * FILLPEN, TEXTFILLPEN and BLOCKPEN).
+        */
+
+#define LVA_TextFont           (LVA_Dummy+29)
+       /* [I] (struct TextFont *) - Font to be used for rendering texts.
+        * Defaults to the default screen font.
+        */
+
+#define LVA_DoubleClick                (LVA_Dummy+30)
+       /* [N] (ULONG) - The item specified by ti_Data has been double clicked.
+        */
+
+#define LVA_MaxSelect          (LVA_Dummy+31)
+       /* [IS] (ULONG) - Maximum number of selected items to allow in multiselect
+        * mode. If you later set this tag with a more restrictive condition, the
+        * listview will NOT deselect any of the currently selected items to
+        * satisfy your request. Default is unlimited (~0).
+        */
+
+#define LVA_PixelTop           (LVA_Dummy+32)
+       /* [ISGNU] (ULONG) - Offset from top of list in pixel units. Useful for
+        * scrollers.
+        */
+
+#define LVA_PixelHeight                (LVA_Dummy+33)
+       /* [N] (LONG) - Total height of list in pixel units. Useful for scrollers.
+        */
+
+#define LVA_PixelVVisible      (LVA_Dummy+34)
+       /* [N] (LONG) - Number of vertical visible pixels. Useful for scrollers.
+        */
+
+#define LVA_PixelLeft          (LVA_Dummy+35)
+       /* [ISNU] (LONG) - Offset from left of list in pixel units. Useful for scrollers.
+        */
+
+#define LVA_PixelWidth         (LVA_Dummy+36)
+       /* [ISNG] (LONG) - Total width of list in pixel units. Useful for scrollers.
+        */
+
+#define LVA_PixelHVisible      (LVA_Dummy+37)
+       /* [N] (LONG) - Number of horizontal visible pixels. Useful for scrollers.
+        */
+
+#define LVA_Title                      (LVA_Dummy+38)
+       /* [IS] - Listview title item. This item will be drawn on the top line of
+        * the list and will not scroll. ti_Data points to an item in the same
+        * format of the items list (e.g.: If it is LVA_StringArray, then it will
+        * be a Node * with ln_Name pointing to a text string. The item will be
+        * passed to the custom item drawing hook. (TODO)
+        */
+
+#define LVA_Columns                    (LVA_Dummy+39)
+       /* [I] (LONG) - Number of columns to be displayed. Default is 1. If set
+        * to ~0, the listview will precheck all items to calculate this number
+        * automatically. (TODO)
+        */
+
+#define LVA_ColumnSpacing      (LVA_Dummy+40)
+       /* [I] (ULONG) - Spacing between columns in pixel units.
+        * Default is 4 pixels. (TODO)
+        */
+
+#define LVA_ColumnWidths       (LVA_Dummy+41)
+       /* [IGS] (ULONG *) - Points to an array of ULONGs containing the width of
+        * each column expressed in pixel units.  A value of -1 causes the
+        * ListView to automatically calculate the width of the column, by
+        * asking the width to all items. (TODO)
+        */
+
+#define LVA_ColumnSeparator    (LVA_Dummy+42)
+       /* [I] (UBYTE) - When the listview is in multicolumn mode, the
+        * internal text label routines will scan the string for this
+        * character, as a separator for the column labels. This defaults
+        * to '\t', so a label for a three column list view would look
+        * like this: "One\tTwo\tThree". (TODO)
+        */
+
+#define LVA_ResizeColumns      (LVA_Dummy+43)
+       /* [IS] (BOOL) - Allows the user to resize the columns by dragging
+        * on the listview title line. (TODO)
+        */
+
+#define LVA_SelectTick         (LVA_Dummy+44)
+       /* [I] When user selects an item, show a checkmark on the left
+        * instead of rendering the item in selected state. (TODO)
+        */
+
+#define LVA_ScrollInertia      (LVA_Dummy+45)
+       /* [IS] (ULONG) - Sets the scrolling inertia of the listview.
+        * Defaults to 4 for LVA_Clipped mode, 0 for a non-clipped listview.
+        * (TODO)
+        */
+
+#define LVA_ScrollRatio                (LVA_Dummy+46)
+       /* [IS] (ULONG) - If you ask the listview to scroll more than
+        * LVA_Visible / LVA_ScrollRatio lines, all the listview contents
+        * will be redrawn instead.  The minimum value of 1 will trigger a
+        * full redraw only when ALL the listview visible part is scrolled away.
+        * The default value is 2, which is a good compromise for items which
+        * can redraw themselves relatively quickly, such as simple text
+        * labels or bitmap images.
+        */
+
+/* Public flags */
+#define LVB_READONLY           0       /* Do not allow item selection                          */
+#define LVB_CLIPPED                    1       /* Clip item drawing inside their boxes         */
+#define LVB_SHOWSELECTED       2       /* Hilights the selected item                           */
+#define LVB_DOMULTISELECT      3       /* Allows user to pick more than one item       */
+#define LVB_SMOOTHSCROLLING    4       /* Scoll pixel by pixel                                         */
+#define LVB_RESIZECOLUMNS      5       /* Allow user to resize the columns                     */
+
+/* Internal flags - DO NOT USE */
+#define LVB_CLOSEFONT          27      /* Close the font when disposing the object     */
+#define LVB_LIST                       28      /* Using an exec List                                           */
+#define LVB_DONTDRAW           29      /* Do not perform any drawing operations        */
+#define LVB_SCROLLING          30      /* User scrolling with middle mouse button      */
+#define LVB_DRAGGING           31      /* User dragging selection with LMB                     */
+
+
+#define LVF_READONLY           (1<<LVB_READONLY)
+#define LVF_CLIPPED                    (1<<LVB_CLIPPED)
+#define LVF_SHOWSELECTED       (1<<LVB_SHOWSELECTED)
+#define LVF_DOMULTISELECT      (1<<LVB_DOMULTISELECT)
+#define LVF_SMOOTHSCROLLING    (1<<LVB_SMOOTHSCROLLING)
+#define LVF_RESIZECOLUMNS      (1<<LVB_RESIZECOLUMNS)
+
+#define LVF_CLOSEFONT          (1<<LVB_CLOSEFONT)
+#define LVF_LIST                       (1<<LVB_LIST)
+#define LVF_DONTDRAW           (1<<LVB_DONTDRAW)
+#define LVF_SCROLLING          (1<<LVB_SCROLLING)
+#define LVF_DRAGGING           (1<<LVB_DRAGGING)
+
+
+
+/*
+ * Changed attributes:
+ *
+ * GA_ToggleSelect
+ *     [I] (BOOL) - When TRUE, the listview gadget will allow deselecting items
+ *     by clicking on them.
+ *
+ * GA_Image
+ *     [IS] (struct Image *), (Object *) - Specifies a framing boopsi image
+ *     which will be rendered around the gadget. This attribute works much
+ *     like in the frbuttonclass. (the default is a frameless gadget).
+ *
+ * GA_SelectRender
+ *     [IS] (struct Image *) - Specifies an imageclass object to be used as
+ *     cursor/selection.  The image will be drawn in IDS_SELECTED state
+ *     for the selected item and IDS_NORMAL for all all other highlighted
+ *     items. (TODO)
+ *
+ * GA_Immediate
+ *     [I] (BOOL) - Sends interim notifications when the selected item changes.
+ *
+ * GA_TextAttr
+ *     [I] (struct TextAttr *) - Font to be used for rendering texts.
+ *     Defaults to the default screen font. See also LVA_TextFont.
+ *
+ * GA_ReadOnly
+ *     [I] (BOOL) - Prevent selection of items (default is FALSE).
+ *
+ * LAYOUTA_Spacing
+ *     [I] (UWORD) - Extra space to place between the items of the listview
+ *     (defaults to 0).
+ *
+ */
+
+/* FIX: Define here the attributes that not present
+ * before V42 of <intuition/gadgetclass.h>.
+ */
+#ifndef GA_ReadOnly
+       #define GA_ReadOnly (GA_Dummy+41)
+#endif
+#ifndef GA_TextAttr
+       #define GA_TextAttr (GA_Dummy+40)
+#endif
+
+
+/* Do not define these if <libraries/gadtools.h> will be included too */
+
+#ifdef LV_GADTOOLS_STUFF
+
+/* The different types of messages that a listview callback hook can see */
+#define LV_DRAW                0x202L          /* draw yourself, with state    */
+
+/* Possible return values from a callback hook */
+#define LVCB_OK                        0               /* callback understands this message type               */
+#define LVCB_UNKNOWN   1               /* callback does not understand this message    */
+
+/* states for LVDrawMsg.lvdm_State */
+#define LVR_NORMAL                             0       /* the usual                            */
+#define LVR_SELECTED                   1       /* for selected gadgets         */
+#define LVR_NORMALDISABLED             2       /* for disabled gadgets         */
+#define LVR_SELECTEDDISABLED   8       /* disabled and selected        */
+
+#endif /* LV_GADTOOLS_STUFF */
+
+#define LVR_TITLE                              16      /* ListView title item          */
+
+
+/* More callback hook methods */
+
+#define LV_GETNEXT             0x203L  /* gimme next item in list              */
+#define LV_GETPREV             0x204L  /* gimme previous item in list  */
+#define LV_GETITEM             0x205L  /* gimme item handle by number  */
+
+/* These two methods can be used to optimize listview rendering
+ * operations.  You can safely assume that the rastport attributes
+ * you set inside LV_DRAWBEGIN will remain unchanged for all
+ * subsequent calls to LV_DRAW, until an LV_DRAWEND is issued.
+ * They do also provide a way to lock/unlock the list of items
+ * if the access to its item needs to be arbitrated by a semaphore.
+ */
+#define LV_DRAWBEGIN   0x206L  /* prepare to draw items                */
+#define LV_DRAWEND             0x207L  /* items drawing completed              */
+
+
+
+/* More messages */
+
+struct lvDrawItem
+{
+       ULONG                           lvdi_MethodID;  /* LV_DRAW                                              */
+       LONG                            lvdi_Current;   /* Current item number                  */
+       APTR                            lvdi_Items;             /* Pointer to List, array, etc. */
+       struct RastPort         *lvdi_RastPort; /* where to render to                   */
+       struct DrawInfo         *lvdi_DrawInfo; /* useful to have around                */
+       struct Rectangle        lvdi_Bounds;    /* limits of where to render    */
+       ULONG                           lvdi_State;             /* how to render                                */
+       ULONG                           lvdi_Flags;             /* Current LVF_#? flags                 */
+};
+
+struct lvGetItem
+{
+       ULONG   lvgi_MethodID;  /* LV_GETITEM                                   */
+       ULONG   lvgi_Number;    /* Number of item to get                */
+       APTR    lvgi_Items;             /* Pointer to List, array, etc. */
+};
+
+#define lvGetNext      lvGetItem
+#define lvGetPrev      lvGetItem
+#define lvDrawBegin    lvGetItem       /* lvgi_Number has no useful meaning    */
+#define lvDrawEnd      lvGetItem       /* lvgi_Number has no useful meaning    */
+
+#endif /* !LISTVIEWCLASS_H */
diff --git a/include/gadgets/PIPClass.h b/include/gadgets/PIPClass.h
new file mode 100644 (file)
index 0000000..dea71c0
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef PIPCLASS_H
+#define PIPCLASS_H
+/*
+**     PIPClass.h
+**
+**     Copyright (C) 1996,97 by Bernardo Innocenti
+**
+**     'Picture In Picture' class built on top of the "gadgetclass".
+**
+*/
+
+#define PIPCLASS       "pipclass"
+#define PIPVERS                1
+
+
+Class  *MakePIPClass (void);
+void    FreePIPClass (Class *PIPClass);
+
+
+
+/********************/
+/* Class Attributes */
+/********************/
+
+#define PIP_Dummy                      (TAG_USER | ('P'<<16) | ('I'<< 8))
+
+#define PIPA_Screen                    (PIP_Dummy+1)
+       /* (IGS) Screen to capture data from
+        */
+
+#define PIPA_BitMap                    (PIP_Dummy+2)
+       /* (IGS) BitMap to capture data from
+        */
+
+#define PIPA_OffX                      (PIP_Dummy+3)
+#define PIPA_OffY                      (PIP_Dummy+4)
+       /* (IGSNU) Offsett of the PIP view
+        */
+
+#define PIPA_Width                     (PIP_Dummy+5)
+#define PIPA_Height                    (PIP_Dummy+6)
+       /* (GN) Dimensions of the bitmap being captured.
+        */
+
+#define PIPA_DisplayWidth              (PIP_Dummy+7)
+#define PIPA_DisplayHeight             (PIP_Dummy+8)
+       /* (GN) Dimensions of the PIP display.
+        */
+
+#define PIPA_MoveUp                    (PIP_Dummy+9)
+#define PIPA_MoveDown          (PIP_Dummy+10)
+#define PIPA_MoveLeft          (PIP_Dummy+11)
+#define PIPA_MoveRight         (PIP_Dummy+12)
+       /* (S) Scroll the display towads a direction
+        */
+
+
+/*****************/
+/* Class Methods */
+/*****************/
+
+#define PIPM_REFRESH           (PIP_Dummy+1)
+/*
+ * Tell the object to update its imagery to reflect any changes
+ * in the attached Screen or BitMap.
+ */
+
+struct pippRefresh
+{
+       ULONG   MethodID;
+       struct GadgetInfo       *pipp_GInfo;
+};
+
+#endif /* !PIPCLASS_H */
diff --git a/include/gadgets/ResizeGClass.h b/include/gadgets/ResizeGClass.h
new file mode 100644 (file)
index 0000000..ae2d687
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef RESIZEGCLASS_H
+#define RESIZEGCLASS_H
+/*
+**         $VER: ResizeGClass 0.1 (22.1.99)
+**
+**
+**  ResizeGClass - (c) 1999 Matteo Cavalleri
+**  
+**
+**  Please read the documentation for
+**  usage and license of this source.
+*/
+
+/* /// "Global" */
+
+/* to debug a boopsi class it's best to compile it as a */
+/* linked library, since this avoid a lot of troubles   */
+#ifdef  DEBUG
+    #define PRIVATE_RESIZEGCLASS
+#endif
+
+/* attributes for this class */
+#define RSA_Dummy               (TAG_USER  + 0x60100)
+#define RSA_LabelDisplay        (RSA_Dummy + 1)
+
+/* this should never be used by the application */
+#define RSA_EditMode            (RSA_Dummy + 99)
+
+#ifndef PRIVATE_RESIZEGCLASS
+    #define RESIZEGCLASS          "resizegclass"
+    #ifndef CLASSLIBRARY_H
+        #include "common/ClassLibrary.h"
+    #endif
+#else
+    Class *makeResizeGClass(void);
+
+    #define freeResizeGClass(cl) FreeClass(cl)
+#endif
+
+/* /// */
+
+#endif
+
diff --git a/include/gadgets/ScrollButtonClass.h b/include/gadgets/ScrollButtonClass.h
new file mode 100644 (file)
index 0000000..f5460cb
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef SCROLLBUTTONCLASS_H
+#define SCROLLBUTTONCLASS_H
+/*
+**     $Id: ScrollButtonClass.h,v 1.2 1999/01/30 13:23:12 bernie Exp $
+**
+**     Copyright (C) 1996,99 Bernardo Innocenti
+**
+**     This code is inspierd from ScrollerWindow 0.3
+**     Copyright © 1994 Christoph Feck, TowerSystems.
+**
+**     Use 4 chars wide TABs to read this file
+**
+**     The ROM buttongclass has two problems which make it not quite usable
+**     for scroll arrows. The first problem is the missing delay. Once the next
+**     INTUITICK gets sent by input.device, the ROM class already sends a
+**     notification. The other problem is that it also notifies us, when the
+**     button finally gets released (which is necessary for command buttons).
+**
+**     We define two new classes with the GM_GOACTIVE and GM_HANDLEINPUT methods
+**     overloaded to work around these problems. The ScrollButtonClass is a
+**     subclass of the buttongclass, suitable for use in the borders of a window.
+**     The FrScrollButtonClass is instead a subclass of the FrButtonGClass. Both
+**     classes share the same dispatcher: the only difference is the superclass
+**     passed at CreateClass() time.
+*/
+
+
+#define SCROLLBUTTONCLASS      "scrollbuttonclass"
+#define SCROLLBUTTONVERS       1
+
+
+/* Functions to initialize and destroy the classes */
+
+Class  *MakeScrollButtonClass (void);
+Class  *MakeFrScrollButtonClass (void);
+BOOL    FreeScrollButtonClass (Class *cl);
+
+#define FreeFrScrollButtonClass FreeScrollButtonClass
+
+
+
+/*****************/
+/* Class Methods */
+/*****************/
+
+/* This class does not define any new methods */
+
+/********************/
+/* Class Attributes */
+/********************/
+
+/* #define SBA_Dummy (TAG_USER | ('S'<<16) | ('B'<<8)) */
+
+/* This class does not define any new attributes */
+
+
+
+
+#endif /* !SCROLLBUTTONCLASS_H */
diff --git a/include/gadgets/SliderBarGClass.h b/include/gadgets/SliderBarGClass.h
new file mode 100644 (file)
index 0000000..3b616a4
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+**     $Id: SliderBarGClass.h,v 1.1 1999/02/07 14:24:43 bernie Exp $
+**
+**     Copyright (C) 1999 Bernardo Innocenti
+**     All rights reserved.
+**
+**     "sliderbargclass", a compound gadget which implements
+**     the GadTools SLIDER_KIND in a boopsi fashon. This class
+**     is derived from the groupgclass but from the outside it
+**     can be manipulated as it were a normal propgclass boopsi
+**     gadget. The slider bar gadget frames all its childs
+**     automatically so it doesn't need an additional frame.
+**
+**     The up/down and left/right buttons are built using the
+**     ScrollButton class using the glyphs provided by the
+**     vectorglyph class.
+*/
+
+#define SLIDERBARGCLASS "sliderbargclass"
+#define SLIDERBARVERS  1
+
+
+/* Class initializer and terminator. Only avalable when
+ * the class is compiled in the static linker object flavour.
+ */
+Class  *MakeSliderBarGClass (void);
+BOOL    FreeSliderBarGClass (Class *ListViewClass);
+
+
+/*
+ * New Methods:
+ *
+ *     This class does not define any new methods
+ */
+
+
+/*
+ * New Attributes:
+ *
+ */
+#define SBA_Dummy                      (TAG_USER | ('S'<<16) | ('B'<<8))
+
+#define SBA_Adjust                     (SBA_Dummy + 1)
+       /* [SU] (LONG) - Add the specified SIGNED quantity to the PGA_Top
+        * attribute. The result is clipped to valid values. This attribute
+        * is used internally by the class to handle the scroll buttons.
+        */
+
+#define SBA_InternalTop                (SBA_Dummy + 2)
+       /* [U] (ULONG) - PRIVATE: DO NOTO USE. Used by internal
+        * notification to synchronize the local copy of the Top
+        * attribute with the embedded Prop gadget.
+        */
+
+/*
+ * Changed attributes:
+ *
+ * LAYOUTA_Orientation
+ *     [I] (ULONG) - Pass one of the LORIENT_#? modes.
+ *     Defaults to LORIENT_HORIZ.
+ *
+ * PGA_Top
+ * PGA_Total
+ * PGA_Visible
+ *     [ISGNU] (LONG) - These attributes are supported exactly as if
+ *     they were inherited from the propgclass.
+ *
+ */
+
+/* FIX: Define the attributes that not present
+ * before V42 of <intuition/gadgetclass.h>.
+ */
+#ifndef LAYOUTA_Dummy
+       #define LAYOUTA_Dummy           (TAG_USER+0x38000)
+       #define LAYOUTA_Orientation     (LAYOUTA_Dummy+0x0003)
+       #define LORIENT_NONE    0
+       #define LORIENT_HORIZ   1
+       #define LORIENT_VERT    2
+#endif
+
+
+/*
+ * Changed methods:
+ *
+ * OM_SET
+ * OM_UPDATE
+ *     The class will intercept GA_Top, GA_Left, GA_Width and GA_Height
+ *     and adjust its childs accordingly. The PGA_#? attributes
+ *     are forwarded to the embedded prop gadget.
+ *
+ * GM_LAYOUT
+ *     The class will adjust the position and size of all its children
+ *     and forward the GM_LAYOUT method to them.
+ */
diff --git a/include/gadgets/SmartGroupGClass.h b/include/gadgets/SmartGroupGClass.h
new file mode 100644 (file)
index 0000000..fe952b5
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+**     $Id: SmartGroupGClass.h,v 1.1 1999/02/07 14:24:44 bernie Exp $
+**
+**     Copyright (C) 1999 Bernardo Innocenti
+**     All rights reserved.
+**
+**     "smartgroupgclass", a class similar to the groupgclass
+**     that allows attaching any number of child gadgets that
+**     will behave like a single gadget. Input processing and
+**     rendering are deferred to the children as appropriate.
+**
+**     The original ROM class is not very usable because it has
+**     a lot of bugs and limitations:
+**
+**     - Doesn't forward GM_LAYOUT to its children
+**     - Does not work when GA_RelRight or GA_RelBottom are set
+**     - Ignores GA_(Rel)Width and GA_(Rel)Height on creation
+**       and recalculates its size when new children are attached.
+**     - Can not layout its children automatically
+**
+**     The smartgroupgclass provides the custom creation-time
+**     attribute SGA_Child, which allows to attach child gadgets
+**     to it in a single call to NewObject() instead of calling
+**     OM_ADDMEMBER several times later. This enables the user
+**     to create a whole GUI with a single C statement like this:
+**
+**     if (glist = NewObject(NULL, SMARTGROUPGCLASS,
+**             LAYOUTA_Orientation, LORIENT_VERT,
+**             SGA_Child, NewObject(NULL SMARTGROUPGCLASS,
+**                     LAYOUTA_Orientation, LORIENT_HORIZ,
+**                     SGA_Child, NewObject(...),
+**                     SGA_Child, NewObject(...),
+**                     TAG_DONE),
+**             SGA_Child, NewObject(...),
+**             TAG_DONE))
+**             {
+**                     /* ... use your glist here... */
+**                     DeleteObject (glist);
+**             }
+**             else
+**                     printf ("Failed to create the application!\n");
+*/
+
+#define SMARTGROUPGCLASS "smartgroupgclass"
+#define SMARTGROUPVERS 1
+
+
+/* Class initializer and terminator. Only avalable when
+ * the class is compiled in the static linker object flavour.
+ */
+Class  *MakeSmartGroupGClass (void);
+BOOL    FreeSmartGroupGClass (Class *class);
+
+
+/*
+ * New Methods:
+ *
+ *     This class does not define any new methods
+ */
+
+
+/*
+ * New Attributes:
+ *
+ */
+#define SGA_Dummy                      (TAG_USER | ('S'<<16) | ('G'<<8))
+
+#define SGA_Child                      (SGA_Dummy + 1)
+       /* [I] (struct Gadget *) - Attach the specified child to
+        * the group at creation time. If the argument is NULL,
+        * the group will be disposed and OM_NEW will also
+        * return NULL. This makes it easy to create a whole user
+        * interface by nesting several calls to NewObject() and
+        * testing the result of the higher level group only.
+        */
+
+/*
+ * Changed attributes:
+ *
+ * LAYOUTA_Orientation
+ *     [I] (ULONG) - Pass one of the LORIENT_#? modes.
+ *     Defaults to LORIENT_HORIZ.
+ *
+ */
+
+/* FIX: Define the attributes that not present
+ * before V42 of <intuition/gadgetclass.h>.
+ */
+#ifndef LAYOUTA_Dummy
+       #define LAYOUTA_Dummy           (TAG_USER+0x38000)
+       #define LAYOUTA_Orientation     (LAYOUTA_Dummy+0x0003)
+       #define LORIENT_NONE    0
+       #define LORIENT_HORIZ   1
+       #define LORIENT_VERT    2
+#endif
+
+
+/*
+ * Changed methods:
+ *
+ *     The class redefines all the GM_#? methods and defers processing
+ *     to its children in a way that makes the group behave as it was
+ *     a single gadget. The children may still choose to send
+ *     notification directly to the application or to gadgets attached
+ *     to other groups.
+ */
diff --git a/include/images/CVS/Entries b/include/images/CVS/Entries
new file mode 100644 (file)
index 0000000..ba5058b
--- /dev/null
@@ -0,0 +1,4 @@
+/ExtFrameIClass.h/1.1/Sun Aug 22 20:31:25 1999//
+/LabelTextIClass.h/1.1/Tue Apr 13 18:48:07 1999//
+/VectorGlyphIClass.h/1.1/Sat Apr 10 19:17:41 1999//
+D
diff --git a/include/images/CVS/Repository b/include/images/CVS/Repository
new file mode 100644 (file)
index 0000000..7a99062
--- /dev/null
@@ -0,0 +1 @@
+OpenBoopsi/include/images
diff --git a/include/images/CVS/Root b/include/images/CVS/Root
new file mode 100644 (file)
index 0000000..62ab471
--- /dev/null
@@ -0,0 +1 @@
+:pserver:bernie@sunsite:/usr/local/cvsroot
diff --git a/include/images/ExtFrameIClass.h b/include/images/ExtFrameIClass.h
new file mode 100644 (file)
index 0000000..c16f0b1
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef EXTFRAMEICLASS_H
+#define EXTFRAMEICLASS_H
+/*
+**  ExtFrameIClass - (c) 1999 Matteo Cavalleri
+**
+**
+**  Please read the documentation for
+**  usage and license of this source.
+*/
+
+/* /// "Global" */
+
+/* supported frame types */
+
+/* these are the same as defined in imageclass.h
+**
+** #define FRAME_DEFAULT        0
+** #define FRAME_BUTTON         1
+** #define FRAME_RIDGE          2
+** #define FRAME_ICONDROPBOX    3
+**
+** these are new frame types
+*/
+#define FRAME_FLAT              4
+#define FRAME_XEN               5
+#define FRAME_BUTTON2           6
+#define FRAME_RIDGE2            7
+
+/* maximum number of frames defined, never to
+** be used outside the class (it must be equal
+** to the last defined frame, not bigger)
+*/
+#define EXTFRAME_MAXFRAME       7
+
+/* attributes for this class */
+#define IA_FrameDistance        (IA_Dummy + 0x53)
+#define IA_InnerDistance        (IA_Dummy + 0x54)
+#define IA_PenBackground        (IA_Dummy + 0x55)
+#define IA_PenSelBackground     (IA_Dummy + 0x56)
+#define IA_PenShine             (IA_Dummy + 0x57)
+#define IA_PenShadow            (IA_Dummy + 0x58)
+#define IA_PenHalfShine         (IA_Dummy + 0x59)
+#define IA_PenHalfShadow        (IA_Dummy + 0x5a)
+
+/* flags for IM_FRAMEBOX method
+**
+** #define FRAMEF_SPECIFY       (1 << 0)
+*/
+#define FRAMEF_QUERY            (1 << 1)
+
+#ifndef PRIVATE_EXTFRAMEICLASS
+    #define EXTFRAMEICLASS      "extframeiclass"
+#else
+    Class *makeExtFrameIClass(void);
+
+    #define freeExtFrameIClass(cl) FreeClass(cl)
+#endif
+
+/* /// */
+
+#endif
+
diff --git a/include/images/LabelTextIClass.h b/include/images/LabelTextIClass.h
new file mode 100644 (file)
index 0000000..93ee313
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef LABELTEXTICLASS_H
+#define LABELTEXTICLASS_H
+/*
+**  LabelTextIClass - (c) 1999 Matteo Cavalleri
+**  
+**
+**  Please read the documentation for
+**  usage and license of this source.
+*/
+
+/* /// "Global" */
+
+/* label types */
+#define LTA_TYPE_NORMAL         0   /* simple text with the shadow pen   */
+#define LTA_TYPE_HILIGHT        1   /* simple text with the shine pen    */
+#define LTA_TYPE_3D             2   /* 3d text with shadow and shine pen */
+
+/* maximum number of renderings defined, never to
+** be used outside the class (it must be equal
+** to the last defined value, not bigger)
+*/
+#define LABELTEXT_MAXTYPE        2
+
+/* label positions */
+#define LTA_POSITION_INSIDE     0
+#define LTA_POSITION_ABOVE      1
+#define LTA_POSITION_BELOW      2
+#define LTA_POSITION_LEFT       3
+#define LTA_POSITION_RIGHT      4
+
+/* maximum number of position defined, never to
+** be used outside the class (it must be equal
+** to the last defined value, not bigger)
+*/
+#define LABELTEXT_MAXPOS         4
+
+/* label alignment */
+#define LTA_ALIGN_CENTER        0
+#define LTA_ALIGN_TOP           1
+#define LTA_ALIGN_BOTTOM        2
+#define LTA_ALIGN_LEFT          3
+#define LTA_ALIGN_RIGHT         4
+
+/* maximum number of position defined, never to
+** be used outside the class (it must be equal
+** to the last defined value, not bigger)
+*/
+#define LABELTEXT_MAXALIGN       4
+
+/* attributes for this class */
+#define LTA_Label               (IA_Dummy + 0x71)
+#define LTA_LabelType           (IA_Dummy + 0x72)
+#define LTA_Distance            (IA_Dummy + 0x73)
+#define LTA_Position            (IA_Dummy + 0x74)
+#define LTA_Align               (IA_Dummy + 0x75)
+#define LTA_Font                (IA_Dummy + 0x76)
+#define LTA_PenBackground       (IA_Dummy + 0x77)
+#define LTA_PenShine            (IA_Dummy + 0x78)
+#define LTA_PenShadow           (IA_Dummy + 0x79)
+#define LTA_PenHalfShine        (IA_Dummy + 0x7a)
+#define LTA_PenHalfShadow       (IA_Dummy + 0x7b)
+
+#ifndef PRIVATE_LABELTEXTICLASS
+    #define LABELTEXTICLASS          "labeltexticlass"
+    #ifndef CLASSLIBRARY_H
+        #include "common/ClassLibrary.h"
+    #endif
+#else
+    Class *makeLabelTextIClass(void);
+
+    #define freeLabelTextIClass(cl) FreeClass(cl)
+#endif
+
+/* /// */
+
+#endif
+
diff --git a/include/images/VectorGlyphIClass.h b/include/images/VectorGlyphIClass.h
new file mode 100644 (file)
index 0000000..79544f7
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+**     VectorGlyphIClass.h
+**
+**     Copyright (C) 1995,96,97,98 by Bernardo Innocenti
+**
+**     "vectorglyphiclass" class, a vector image class built
+**     on top of the "imageclass", providing some useful
+**     glyphs for buttons.
+*/
+
+#define VECTORGLYPHCLASS "vectorglyphiclass"
+
+Class  *MakeVectorGlyphIClass(void);
+BOOL    FreeVectorGlyphIClass(Class *class);
+
+/* Values for the SYSIA_Which attribute */
+#define VG_PLAY                        0
+#define VG_STOP                        1
+#define VG_REW                 2
+#define VG_FWD                 3
+#define VG_PICK                        4
+#define VG_UPARROW             5
+#define VG_DOWNARROW   6
+#define VG_LEFTARROW   7
+#define VG_RIGHTARROW  8
+
+
+/* Number of glyphs offered by the vectorglyph.image class */
+#define VG_IMGCOUNT 9