--- /dev/null
+*.o
+*.gadget
--- /dev/null
+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
--- /dev/null
+$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.
--- /dev/null
+$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.
--- /dev/null
+ 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!
--- /dev/null
+##
+## $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
--- /dev/null
+$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.
--- /dev/null
+$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.
--- /dev/null
+#
+# $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
--- /dev/null
+#
+# $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
--- /dev/null
+******************************************************************************
+*
+* $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
--- /dev/null
+/*
+** $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;
+}
--- /dev/null
+#
+# $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
--- /dev/null
+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;
+}
--- /dev/null
+#
+# $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
--- /dev/null
+/*
+** $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"
+ */
--- /dev/null
+.text
+ jmp __main
--- /dev/null
+
+ XREF @_main
+
+ SECTION CODE,code
+
+_start:
+ jmp @_main
+
+ END
--- /dev/null
+
+ XREF __main
+
+ SECTION CODE,code
+
+_start:
+ bra __main
+
+ END
--- /dev/null
+##
+## $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
--- /dev/null
+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.
+
--- /dev/null
+
+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.
+
--- /dev/null
+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.
+
--- /dev/null
+
+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.
+
--- /dev/null
+#
+# $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) $@
+##
--- /dev/null
+#
+# $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 :=
+
--- /dev/null
+#
+# $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/ $@
--- /dev/null
+#
+# $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/ $@
--- /dev/null
+/*
+** $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;
+}
--- /dev/null
+#
+# $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
--- /dev/null
+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
--- /dev/null
+/*
+** $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 */
+}
--- /dev/null
+/*
+** $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) */
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+/*
+** $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;
+}
--- /dev/null
+#
+# $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
--- /dev/null
+#
+# $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
--- /dev/null
+#
+# $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/ $@
--- /dev/null
+##
+## $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
--- /dev/null
+#
+# $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
--- /dev/null
+/*
+** 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);
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+** $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));
+}
--- /dev/null
+;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>
+
--- /dev/null
+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()
--- /dev/null
+##
+## $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)
--- /dev/null
+#
+# $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/ $@
--- /dev/null
+#
+# $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
+
--- /dev/null
+#
+# $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
+
--- /dev/null
+/*
+** $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) */
--- /dev/null
+/*
+** $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));
+}
--- /dev/null
+#
+# $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
+
--- /dev/null
+/*
+** $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;
+}
--- /dev/null
+/*
+** $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) */
--- /dev/null
+#
+# $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
+
--- /dev/null
+/*
+** $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) */
--- /dev/null
+#
+# $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/ $@
--- /dev/null
+/*
+** $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)))
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+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.
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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
+
--- /dev/null
+#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 */
--- /dev/null
+/*
+** $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.
+ */
--- /dev/null
+/*
+** $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.
+ */
--- /dev/null
+/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
--- /dev/null
+OpenBoopsi/include/images
--- /dev/null
+:pserver:bernie@sunsite:/usr/local/cvsroot
--- /dev/null
+#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
+
--- /dev/null
+#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
+
--- /dev/null
+/*
+** 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