From: Bernie Innocenti Date: Fri, 11 Mar 2011 06:13:43 +0000 (-0500) Subject: Initial commit X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=HEAD;p=amiga%2FOpenBoopsi.git Initial commit --- 1226995c5ff87cf6ce4b61c085fa7993f5db96ca diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c01d83f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +*.gadget diff --git a/BUGS b/BUGS new file mode 100755 index 0000000..897dad9 --- /dev/null +++ b/BUGS @@ -0,0 +1,38 @@ +Known bugs in the provided classes +================================== + + Common: + + - Some of the demo programs will exit silently when they fail + to open any of the required classes. In this case you must + copy them to your SYS:Classes/[images|gadgets]/ directory + in order to avoid the problem. You can also solve this + problem by adding The dist/classes directory to the LIBS: + multi-assign: + + > Assign LIBS: dist/classes/ ADD + + When you are done, you can cleanup by typing: + + > Assign LIBS: dist/classes/ REMOVE + + + + ListViewClass specific: + + - The clipping mode appears to work well with the original + layers routines and also with CyberGraphX's "SUPERLAYERS" + option. When using Picasso 96, the clipped window will + draw incorrectly and scrolling will sometimes hang the system. + + - In some cases the clipped listview with big font size calls + Text() with a slightly negative Y coordinate in the RastPort. + This shows a OS bug which corrupts the item displayed on the + top of the list. This problem would need further investigation. + It happens on AGA, CyberGraphX and Picasso96. + + +Known bugs in Intuition's builtin classes +========================================= + + TODO diff --git a/ChangeLog b/ChangeLog new file mode 100755 index 0000000..e69de29 diff --git a/GUIDELINES b/GUIDELINES new file mode 100644 index 0000000..71a9cbd --- /dev/null +++ b/GUIDELINES @@ -0,0 +1,129 @@ +$Id: GUIDELINES,v 1.1 2000/01/12 20:37:03 bernie Exp $ + + +OpenBoopsi Guidelines +===================== + + This is a brief guideline to explain you how the OpenBoopsi root is + organized, how the makefiles system work, etc. so that you can add + your own class without problems and even without writing your own + Makefile! (more or less ;-) + + The OpenBoopsi tree is structured in this way: + + OpenBoopsi root/ + Makefile + config.mk + + images/ + Makefile + class1/ + Makefile + config.mk + Class1.c + Class1Demo.c + class2/ + etc. + gadgets/ + Makefile + class1/ + Makefile + config.mk + etc. + include/ + common/ + general.mk + BoopsiStubs.h + etc. + images/ + Class1.h + etc. + etc. + + +These are things you should know: + +Makefiles +========= + +1) There is a global "config.mk" files where are defined all the compiler + specific variables, like command line options, tools, paths, etc. It is + divided in two sections and you usually should need to modify only the + first one. This file is placed in the OpenBoosi root. Run 'make help' for + a listing of the current configuration. + +2) There are different local "config.mk" files. They contain classes + specific informations, i.e. class name, class version, etc. They are + placed in every classes' directory and are required, so if you add a + new class to the OpenBoopsi project you must write one of this file. + An empty config.mk file is provided in the docs/ drawer with all the + explanations you will need. + +3) The top level Makefile will call all the makefiles in the other + subdirectories to build the complete distribution, as usual. However, + this Makefile also has a special target which sets up your build + environment. Without this preliminar step you won't be able to compile + anything. Read the INSTALL file or just run 'make help-setup' for a + more detailed explanation of this required step. + +4) The makefiles present in every classes' directory are simple dummy + makefiles. They just include the local "config.mk" file and the real + Makefile, so you just need to copy it in your class' directory without + any modifications. + +5) It is possibleto customize the local makefiles to pass custom "arguments" + to the true Makefile, so if e.g. your class need to link a specific object + you don't need to modify the general Makefile. Read the docs/empty_Makefile + file for a detailed explanation. + +6) You can obviously add to the local Makefile your own targets, e.g. for + creating a custom object that need to be linked to the demo program + (and that you will need to pass to the general Makefile via the argument + system described above). + +7) The "general.mk" file in the common/ directory is the Makefile used to + compile all the classes. It is included by the various local makefiles. + This method has three great advantages: 1) if the Makefile is changed or + improved it does not need to be copied in every subdirectories and 2) + you don't need to write your own custom Makefile, just the config.mk + 3) if you write a better/different Makefile other user can take + advantages of this just by including your Makefile instead of the + standard one. + +8) Remember that custom makefiles must support the defined targets or it + will be impossible to build all the distribution calling the top level + Makefile. You can find a list of the required targets and their purposes + in the general.mk file. + +9) If you want your own custom Makefile we suggest you to put it in the + common/ directory (so don't call it Makefile, give it a different name) + and then change your class' local Makefile to include your custom true + Makefile instead of the default one. In this way other people can use your + Makefile without the need to copy it to their subdirectories. + + +Includes +======== + +1) All the includes must be placed in the appropriate include/ subdirectories. + You must leave includes in the classes subdirectories only if they e.g. contain + private definitions needed by the class only, i.e. no other programs or classes + can include it. + +2) The makefiles already know where they should search for the needed + includes and how to tell the compiler to find them, so you should not + worry about this. + +3) To include the required headers in your programs or classes just follow + this example: + +#include "common/BoopsiStubs.h" +#include "images/VectorGlyph.h" +#include "gadgets/ListView.h" +#include "RequesterClass.h" +#include "MyPrivateInclude.h" + +4) IMPORTANT: in the example above the last two includes look identical, + however the first should be placed in the include/ dir (and not + in one of its subdirectories!) while the latter should go in the class + own directory. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..583664b --- /dev/null +++ b/INSTALL @@ -0,0 +1,15 @@ +$Id: INSTALL,v 1.1 2000/01/12 20:36:51 bernie Exp $ + +How to build the project +======================== + + Run "make setup". It will create an env variable with the name of the dir +where you have unpacked the OpenBoopsi distribution. This variable is +required, so don't remove it! It will also be copied in ENVARC:, so you +will need to do the setup only once. Running 'make help-setup' will +print a brief explanation and the value that will be assigned to the +environment variable when you do the setup. + + It is also advisable to read the GUIDELINES file for a detailed +description of the distribution structure and how the makefiles +are organized. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..161a3d1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,482 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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 + + 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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..222061b --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +## +## $Id: Makefile,v 1.1 2000/01/12 20:37:38 bernie Exp $ +## +## This Makefile must be processed with GNU make 3.76.1 +## which is available on Aminet: dev/c/make_bin.lha +## +## Copyright (C) 1999 by B. Innocenti & M. Cavalleri +## + +SUBDIRS := common classes images gadgets + +include config.mk + +ifeq ($(COMPILER),gcc) + TOP := $(shell pwd) +else + TOP := $(shell cd) +endif + +include common/general.mk diff --git a/README b/README new file mode 100644 index 0000000..b551e92 --- /dev/null +++ b/README @@ -0,0 +1,82 @@ +$Id: README,v 1.1 2000/01/12 20:32:09 bernie Exp $ + + +About `boopsi' +============== + + The achronim `boopsi' stands for Basic Object Oriented Programming System +for Intuition. This facility is available in AmigaOS since Kickstart V36. +boopsi is primary meant as an OOP framework for GUI components such as +gadgets, images, texts and so on. + + The system provides several boopsi classes which are the OOP counterparts +of the plain Intuition gadgets and other important structures such as Image +and IntuiText. There are also classes that allow building a network of +interconnected boopsi objects so that each object can notify the others +about its attributes. This boopsi communication system enables the gadgets +to talk each other so they can react to user input in complex ways, freeing +the application from most of the GUI administration duties. + + +Other GUI systems +================= + + Unfortunately, the built-in Intuition classes are not very powerful, +nor flexible enough for todays applications. That's why so many +alternative GUI systems have appeared during the past years. Some +of these systems are also based on boopsi, while others provide +their own API through a shared library. + + The main disadvantage with these GUI systems mentioned above is +none of them is free. In this case we are referring to the GNU meaning +of the word `free'. It means that the users and the developers are +not given enough freedom. Some GUI systems are shareware, some others +come with a license that forbids or limits their use for commercial +applications. Few of them come with their source code and in most +cases they don't give you the freedom to change it. On the technical +side, the major limit of the current GUI systems is that they are +usually mutually exclusive. You can't mix objects from two different +systems to take advantage of the features of both. + + +About the boopsi OSS project +============================ + + The goal of this project is providing a comprehensive set of +boopsi classes for general application developement. The main +developemnt guidelines are: + + - providing a pure boopsi API for GUI construction. There + are no additional libraries. + + - integration with the system built-in classes, whenever + possible. + + - support the current V39/V40 OS along with the current + RTG systems. + + - Sticking to clean AmigaOS programming, except when it is + absolutely impossible to do so to workaround known + OS bugs. + + - Adopting a distributed developement model. Source code + is freely available and anyone is allowed to improve or + add new functionality. + + - Leave the choice to the application developer. + The classes will be available in several flavours, + including shared class libraries, linker library and + a monolithic shared library. + + - Find the best trade-off beteen efficiency, portability + and configurability + + +DISCLAIMER +========== + + This software is provided AS-IS, without any explicit or implied warranty. + + This software is to be considered PRELIMINARY and SUBJECT TO CHANGE. +It has not been tested accurately and it may contain BUGS that could +easily CRASH YOUR SYSTEM. diff --git a/STYLE b/STYLE new file mode 100644 index 0000000..4f153d4 --- /dev/null +++ b/STYLE @@ -0,0 +1,185 @@ +$VER OpenBOOPSI Project Style Guide 1.1 (4.5.99) + + + OpenBOOPSI Project Style Guide + +---- + + +0. SUMMARY + + 1. Introduction + 2. Comments + 2.1 General Rules + 2.2 Language + 2.3 Single line comments + 2.4 Multi line comments + 3. Blank Spaces + 3.1 Tabs + 3.2 Spaces + 3.3 Empty lines + 4. Naming Conventions + 4.1 General Rules + 4.2 Functions + 4.3 Variables + + +1. INTRODUCTION + + This is a brief guide on recommended source code formatting style + for the OpenBOOPSI Project classes. Every source file added to this + project should conform as close as possible to the rules given in + this document to mantain consistency within the source tree. + + It might happen that you're already used to a different coding + style. Yes, we all understand well that changing your style can be + frustrating for any programmer. But the need to keep the source + code style consistent is more important than each one's habits. + No one will blame you if you don't strictly follow these + guidelines, but we will be glad if you do. + + +2. COMMENTS + + 2.1 GENERAL RULES + + Comment as much as you can. Other programmers will read your + sources and since most of them will have different knowledge of + Amiga programming and/or different ways to do a certain thing they + may not understand the purpose or the inner working of some of your + code, so try to explain what you are doing. Obviously avoid comments + such as "now open a window" right above a OpenWindow() function call. + + 2.2 LANGUAGE + + Comments must be written in english. + + 2.3 SINGLE LINE COMMENTS + + Single line comments should follow the ANSI C syntax, i.e. + using the "/* */" construct. C++ comments must not be used + because not all C compilers do support them. + + 2.4 MULTI LINE COMMENTS + + Comments spanning over multiple lines should be formatted this way: + + /* This is a very very very + * very very long comment! + */ + + +3. BLANK SPACES + + 3.1 TABS + + Tabs are four spaces wide. + + 3.2 SPACES + + There should be a space after commas. + + There should never be a space after a * when it's used with pointers, + e.g.: + + ULONG *pointer = NULL; + *pointer = 45 * y; + + There should be a blank space around operators, e.g.: + + var1 + var2; + var1 & var2; + etc. + + the only exceptions are prefix and postfix ++ and -- operators, + i.e.: + + var--; + ++var; + + Before a parenthesis there should never be blank spaces if + it follow a keyword or a function name. e.g. + + if() /* good */ + DoMethod(); /* also good */ + while () /* wrong! */ + yourfunction (); /* also wrong! */ + + 3.3 EMPTY LINES + + After the #include block and after the #define one there should be + two empty lines. + + Between the declaration of the global variables and the beginning of + the code there should be two empty lines. + + Between the end of a function and the next one there should be three + empty lines. + + Any code block enclosed in braces should be preceded by an empty line. + An open brace should be on a line by itself. After a closing brace there + should be one empty line, except when another closing brace follows. e.g. + + if(z == 1) + { + z++; + } + + y += z + 3; + + if(y > 8) + { + f = do_some_stuff(); + + if(f == TRUE) + { + printf("ok!\n"); + } + } + + /* the following is wrong! */ + + if(y==1) { + z++; + } + y+=z +3; + if (y >8) + { etc. } + + +4. NAMING CONVENTIONS + + 4.3 GENERAL RULES + + Everything related to the classes (methods, functions, etc.) should + have a prefix (two or three letter maximum) that recalls the name of + the class. i.e. if your class is called "BananaSplit" its methods + should be called something like BSM_SHAKE, its attributes should look + like BSA_SugarSpuns, etc. + + 4.2 FUNCTIONS + + Method functions should obviously follow the general rule and have + the above mentioned prefix, e.g.: + + BS_GoActive(); + + Function names should have the first letters of each word + forming their names capitalized, like system's one. e.g.: + + MyWonderfulFunction() + + 4.3 VARIABLES + + Variables name must be in english and must have a meaning! Please + avoid names such as "foobar" or "dummy"! We hate them! + Some examples: + + struct Window *win; /* these are good */ + ULONG result; + + struct BitMap *dummy1; /* these are wrong! */ + struct RastPort *dummy2; + + Names of local variables should be all in lowercase. Global + variables should have their initials uppercase. diff --git a/TODO b/TODO new file mode 100755 index 0000000..e69de29 diff --git a/classes/ExtRequesterClass/Makefile b/classes/ExtRequesterClass/Makefile new file mode 100644 index 0000000..92449a0 --- /dev/null +++ b/classes/ExtRequesterClass/Makefile @@ -0,0 +1,23 @@ +# +# $Id: Makefile,v 1.1 2000/01/12 20:40:56 bernie Exp $ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(TOP)/config.mk + +ARG_COMMON := +ARG_ALL := $(ARG_COMMON) +ARG_LIB := $(ARG_COMMON) +ARG_DEBUG := $(ARG_COMMON) +ARG_PRIVATE := $(ARG_COMMON) +ARG_OBJ := $(ARG_COMMON) + +DEP_COMMON := +DEP_ALL := $(DEP_COMMON) +DEP_LIB := $(DEP_COMMON) +DEP_DEBUG := $(DEP_COMMON) +DEP_PRIVATE := $(DEP_COMMON) +DEP_OBJ := $(DEP_COMMON) + +include $(TOP)/common/general.mk diff --git a/classes/Makefile b/classes/Makefile new file mode 100644 index 0000000..54b2e11 --- /dev/null +++ b/classes/Makefile @@ -0,0 +1,9 @@ +# +# $Id: Makefile,v 1.1 2000/01/12 20:40:06 bernie Exp $ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +SUBDIRS := ExtRequesterClass + +include $(TOP)/common/general.mk diff --git a/common/ClassLib.s b/common/ClassLib.s new file mode 100755 index 0000000..d9bc8c2 --- /dev/null +++ b/common/ClassLib.s @@ -0,0 +1,298 @@ +****************************************************************************** +* +* $VER: ClassLib.asm (5.9.97) +* +* Copyright (C) 1995,96,97 by Bernardo Innocenti +* +****************************************************************************** +* +* This source is based on the RomTag.asm source I've found somewhere :-) +* +* + INCLUDE "exec/types.i" + INCLUDE "exec/macros.i" + INCLUDE "exec/libraries.i" + INCLUDE "exec/lists.i" + INCLUDE "exec/alerts.i" + INCLUDE "exec/initializers.i" + INCLUDE "exec/resident.i" + INCLUDE "exec/execbase.i" + INCLUDE "libraries/dos.i" + + INCLUDE "exec/funcdef.i" + INCLUDE "exec/exec_lib.i" + + +; BOOPSI class libraries should use this structure as the base for their +; library data. This allows developers to obtain the class pointer for +; performing object-less inquiries. + + STRUCTURE ClassBase,0 + STRUCT cl_Lib,LIB_SIZE ; Embedded library + UWORD cl_Pad ; Align the structure + APTR cl_Class ; Class pointer + APTR cl_SegList ; SegList pointer + LABEL ClassLibrary_SIZEOF + +;--------------------------------------------------------------------------- + + XDEF _LibFuncTable + XDEF _LibDataTable + + XREF _LibName + XREF _LibId + XREF __UserLibInit + XREF __UserLibCleanup + + XREF __GetEngine + +;--------------------------------------------------------------------------- + + SECTION Code + +; First executable location, must return an error to the caller + + moveq #-1,d0 + rts + +;--------------------------------------------------------------------------- + +_ROMTAG: + DC.W RTC_MATCHWORD ; UWORD RT_MATCHWORD + DC.L _ROMTAG ; APTR RT_MATCHTAG + DC.L _ENDCODE ; APTR RT_ENDSKIP + DC.B RTF_AUTOINIT ; UBYTE RT_FLAGS + DC.B LIBVERSION ; UBYTE RT_VERSION + DC.B NT_LIBRARY ; UBYTE RT_TYPE + DC.B 0 ; BYTE RT_PRI <--- WARNING: Using negative values here will cause trouble! + DC.L _LibName ; APTR RT_NAME + DC.L _LibId ; APTR RT_IDSTRING + DC.L _LibInitTable ; APTR RT_INIT + + +* The RomTag specified that we were RTF_AUTOINIT. This means that rt_Init +* points to the table below. (Without RTF_AUTOINIT it would point to a +* routine to run.) +* +* Our library base is a standard struct Library, followed by a WORD +* pad, a pointer to the boopsi Class structure of the external +* boopsi class and a pointer to our SegList. The SegList pointer +* will be returned by LibExpunge() in order to have our code UnloadSeg()'ed +* The Class pointer will be initialized by UserLibInit(). + +_LibInitTable: + dc.l ClassLibrary_SIZEOF + dc.l _LibFuncTable + dc.l _LibDataTable + dc.l _LibInit + + + +* Table of functions included in this library; the first 4 are the same +* for any library and for internal Exec use only. + + +_LibFuncTable: + dc.l _LibOpen + dc.l _LibClose + dc.l _LibExpunge + dc.l _LibExtFunc + dc.l __GetEngine + dc.l -1 + +;V_DEF MACRO +; dc.w \1 + (* - _LibFuncTable) +; ENDM +; +;_LibFuncTable: +; dc.w -1 ; It's weird: the cool way didn't work for me :-( +; V_DEF _LibOpen +; V_DEF _LibClose +; V_DEF _LibExpunge +; V_DEF _LibExtFunc +; V_DEF __GetEngine +; dc.w -1 + + + +_LibDataTable + INITBYTE LN_TYPE,NT_LIBRARY + INITLONG LN_NAME,_LibName + INITBYTE LN_PRI,-5 + INITBYTE LIB_FLAGS,(LIBF_SUMUSED!LIBF_CHANGED) + INITWORD LIB_VERSION,LIBVERSION + INITWORD LIB_REVISION,LIBREVISION + INITLONG LIB_IDSTRING,_LibId + dc.w 0 + + + CNOP 0,4 + + +* The following function will be called at startup time. +* +* Inputs: +* LibPtr (d0) - Pointer to the library base, initialized due to the +* specifications in DataTable +* SegList (a0) - BPTR to the segment list +* _SysBase (a6) - The usual ExecBase pointer +* +* Result: +* LibPtr, if all was okay and the library may be linked into the +* system library list. NULL otherwise. +* +_LibInit: + move.l d0,a1 + move.l a0,cl_SegList(a1) ; Save SegList + +; Check CPU for 68020 or better + IFD _MC68020_ + move.w AttnFlags(a6),d1 + btst.w #AFB_68020,d1 + beq.s fail$ + ENDC + + move.l a6,-(sp) ; Save SysBase + move.l d0,a6 ; Put our base in a6 + jsr __UserLibInit ; Call user init + move.l a6,a1 ; save our base to a1 + move.l (sp)+,a6 ; Retrieve SysBase + tst.l d0 + beq.s fail$ + rts + +fail$ + bsr FreeBase ; Free library base + moveq #0,d0 + rts + + +* The following functions are called from exec.library/OpenLibrary(), +* exec.library/CloseLibrary() and exec.library/ExpungeLibrary(), +* respectively. Exec passes our library base pointer in A6. +* +* Task switching will be turned off while these functions are being +* executed, so they must be as short as possible. As the data inside +* the library base is protected with Forbid(), these functions must +* not make calls which would explicitly or implicitly turn on multitasking. +* This includes opening other disk based libraries. The problem may be +* overcame by protecting the library base with a SignalSemaphore. +* + + +* This function is called from exec.library/OpenLibrary(). +* +* Inputs: +* LibPtr (a6) - Pointer to the library base +* Version (d0) - The suggested version number +* +* Result: +* LibPtr, if successful, NULL otherwise +* + +_LibOpen: + addq.w #1,LIB_OPENCNT(a6) + bclr.b #LIBB_DELEXP,LIB_FLAGS(a6) ; Prevent delayed expunge + move.l a6,d0 + rts + + + +* This function is called from exec/CloseLibrary(). +* +* Inputs: +* LibPtr (A6) - pointer to the library base as returned from OpenLibrary(). +* +* Result: +* Segment list of the library (see arguments of _LibInit), if there +* was a delayed expunge and the library is no longer open, NULL +* otherwise. +* +_LibClose: + subq.w #1,LIB_OPENCNT(a6) + tst.w LIB_OPENCNT(a6) + bne.s .NoExpunge + btst.b #LIBB_DELEXP,LIB_FLAGS(a6) + beq.s .NoExpunge + + bra.s _LibExpunge + +.NoExpunge + moveq.l #0,d0 + rts + + + +* This function is called from exec.library/RemoveLibrary(). +* +* Inputs: +* LibPtr (A6) - pointer to the library base. +* +* Result: +* Segment list of the library (see arguments of _LibInit()), +* if the library isn't opened currently, NULL otherwise. +* + +_LibExpunge: + + ; Flag library base for delayed expunge + bset.b #LIBB_DELEXP,LIB_FLAGS(a6) + tst.w LIB_OPENCNT(a6) ; Only expunge if OpenCnt == 0 + bne.s .DoNotExpunge + +.NotOpen + + jsr __UserLibCleanup ; Call user cleanup code + tst.l d0 + beq.s .DoNotExpunge + + move.l cl_SegList(a6),-(sp) ; Save SegList pointer + + move.l a6,a1 + REMOVE ; Remove us from Exec library list. + + +; Free the library base + + move.l a6,a1 ; LibBase + move.l a6,-(sp) ; Save A6 + move.l 4.w,a6 ; Load SysBase + bsr FreeBase ; Free our library base + move.l (sp)+,a6 ; Restore A6 + + move.l (sp)+,d0 ; Return our SegList + rts + +.DoNotExpunge + +; NOTE: I'm falling in _LibExtFunc from here! + + + +* Dummy function to return 0 + +_LibExtFunc: + moveq #0,d0 + rts + + +* Frees our library base +* +* Inputs: +* LibBase (a1) - Pointer to Library structure. +* SysBase (a6) - Pointer to SysBase +* +FreeBase: + moveq.l #0,d0 + move.l a1,a0 + move.w LIB_NEGSIZE(a0),d0 + suba.l d0,a1 ; Get pointer to real start of library base + add.w LIB_POSSIZE(a0),d0 ; Total library size (LIB_POSSIZE + LIB_NEGSIZE) + jsr _LVOFreeMem(a6) + rts + +;----------------------------------------------------------------------- + +_ENDCODE + + END diff --git a/common/GetGadgetBox.c b/common/GetGadgetBox.c new file mode 100644 index 0000000..e9192f6 --- /dev/null +++ b/common/GetGadgetBox.c @@ -0,0 +1,88 @@ +/* +** $Id:$ +** +** Copyright (C) 1999 Bernardo Innocenti +** All rights reserved. +** +** Use 4 chars wide TABs to read this file +** +** GetGadgetBox() computes the actual IBox where a gadget exists in a window. +** The special cases it handles are all the REL#? (relative positioning flags). +** +** This function returns the gadget size in the provided +** IBox structure, computing the values from the coordinates +** in the gadget structure and the container (window or requester) +** where it lives. +*/ + +#include + +#include +#include +#include + + +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 */ +#define GADGET_BOUNDS(g) ((struct IBox *)&((struct ExtGadget *)(g))->BoundsLeftEdge) + + +void GetGadgetBounds(struct GadgetInfo *ginfo, struct ExtGadget *g, struct IBox *bounds) +{ + struct IBox *box; + + ASSERT_VALID_PTR(g) + ASSERT_VALID_PTR(ginfo) + ASSERT_VALID_PTR(bounds) + + + box = ((g->Flags & GFLG_EXTENDED) && (g->MoreFlags & GMORE_BOUNDS)) ? + GADGET_BOUNDS(g) : GADGET_BOX(g); + + memcpy(bounds, box, sizeof(struct IBox)); + + if (g->Flags & GFLG_RELRIGHT) + bounds->Left += ginfo->gi_Domain.Width - 1; + + if (g->Flags & GFLG_RELBOTTOM) + bounds->Top += ginfo->gi_Domain.Height - 1; + + if (g->Flags & GFLG_RELWIDTH) + bounds->Width += ginfo->gi_Domain.Width; + + if (g->Flags & GFLG_RELHEIGHT) + bounds->Height += ginfo->gi_Domain.Height; +} diff --git a/common/Makefile b/common/Makefile new file mode 100644 index 0000000..8e6fbd6 --- /dev/null +++ b/common/Makefile @@ -0,0 +1,90 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(TOP)/config.mk + +COMMON_OBJS = GetGadgetBox.o + +all: $(GST) $(APP_STARTUP) $(COMMON_OBJS) + +help-all: + @echo "This target compile the custom startup code and place it" + @echo "in the obj/ directory, create the GST (Global Symbol Table)" + @echo "for SAS/C users." + @echo + +lib: + $(NOP) + +help-lib: + @echo "This target does nothing."; echo + +debug: + $(NOP) + +help-debug: + @echo "This target does nothing."; echo + +private: + $(NOP) + +help-private: + @echo "This target does nothing."; echo + +obj: $(APP_STARTUP) + +help-obj: + @echo "This target compile the custom startup code and place it" + @echo "in the obj/ directory." + @echo + +clean: + $(RM) $(APP_STARTUP) $(GST) + +help-clean: + @echo "This target deletes the custom startup code object and the GST." + @echo + +install: + $(NOP) + +help-install: + @echo "This target does nothing."; echo + + +########################################################### +# Compile custom startup code for applications +########################################################### + +$(APP_STARTUP): $(APP_STARTUP_SRC) + $(AS) $< $(TO) $@ + +########################################################### +# Compile common objects +########################################################### + +$(COMMON_OBJS): %.o : %.c + $(CC) $< $(TO) $@ $(O_CFLAGS) + + +########################################################### +# Make Global Symbol Table to speed up compiling +########################################################### +# +# We must define some symbols here because defining them +# inside GST.c won't work as expected. (SAS/C bug?) +# +# NOTE: The GST file does not depend on any headers because +# otherwise all objects would be remade each time you edit +# one of the header files. +# + +$(GST): GST.c + ifeq ($(strip $(COMPILER)),sc) + $(CC) FROM gst.c MAKEGST $(GST) NOOBJNAME $(O_CFLAGS) \ + DEF=INTUI_V36_NAMES_ONLY DEF=__USE_SYSBASE \ + DEF=CLIB_ALIB_PROTOS_H + endif diff --git a/common/OpenClass.c b/common/OpenClass.c new file mode 100644 index 0000000..305f498 --- /dev/null +++ b/common/OpenClass.c @@ -0,0 +1,44 @@ +struct ClassLibrary *OpenClass(CONST_STRPTR name, CONST_STRPTR prefix, ULONG version) + +/* Open named class. Look both in current and images/ directory + */ +{ + static struct EasyStruct OpenClassES = + { + sizeof(struct EasyStruct), + 0, + versiontag + 6, + "Couldn't open %s version %ld or greater", + "Ok" + }; + + struct ClassLibrary *classbase; + char buf[256]; + int i; + + + if (!(classbase = (struct ClassLibrary *)OpenLibrary(name, version))) + { + /* We can't use AddPart() here because we didn't open dos.library */ + + /* Copy the prefix in the buffer */ + for (i = 0; buf[i] = prefix[i]; i++); + + /* Insert trailing character if missing */ + if(buf[i] != '/') + buf[++i] = '/'; + + /* Append the name */ + while (buf[i++] = *name++); + + /* Try again */ + classbase = (struct ClassLibrary *)OpenLibrary(buf, version); + + if (!classbase) + { + /* Report an error */ + EasyRequest(NULL, &OpenClassES, NULL, buf, version); + } + } + return classbase; +} diff --git a/common/general.mk b/common/general.mk new file mode 100644 index 0000000..edf4ea9 --- /dev/null +++ b/common/general.mk @@ -0,0 +1,277 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +# This makefile is flexible enough to be used for every +# class of the OpenBoopsi project. You should not need to +# modify anything +# +# all: create the demo program and the class library +# with no debugging information and code +# +# lib: create just the library of the public class +# with no debugging information and code +# +# private: create the demo program linked with optimized version of the class +# +# debug: create the demo program linked with debug version of the class +# +# obj: create just the class object ready to be linked +# to a program, with no debugging information and code +# +# install: copy the demos and classes to the appropriate +# directories +# + +########################################################### +# some variables... +# +BOOPSI_DEPS := $(INCDIR)/BoopsiStubs.h $(INCDIR)/CompilerSpecific.h $(INCDIR)/DebugMacros.h +CLASSOBJ_SHARED := $(subst .c,_shared.o,$(CLASSSRC)) +CLASSOBJ_STATIC := $(subst .c,_static.o,$(CLASSSRC)) +CLASSOBJ_DEBUG := $(subst .c,_dbg.o,$(CLASSSRC)) +CLASSINC := $(subst .c,.h,$(CLASSRC)) +DEMOOBJ_STATIC := $(subst .c,_static.o,$(DEMOSRC)) +DEMOOBJ_SHARED := $(subst .c,_shared.o,$(DEMOSRC)) +DEMOOBJ_DEBUG := $(subst .c,_dbg.o,$(DEMOSRC)) + +# Provide a default name for the demo program +ifeq ($(strip $(DEMOPROG)),) + ifneq ($(strip $(DEMOSRC)),) + DEMOPROG := $(subst .c,,$(DEMOSRC)) + endif +endif + +# Generate the name of the debug demo +ifneq ($(strip $(DEMOPROG)),) + DEMOPROG_DEBUG := $(DEMOPROG)_debug +endif + +########################################################### +# additional compiler flags +# +ifeq ($(strip $(COMPILER)),gcc) + LIB_CFLAGS := -DDATE="\"$(CLASSDATE)"\" -DNAME="\"$(CLASSLIB)"\" \ + -DVERSION="\"$(CLASSVER).$(CLASSREV)"\" +else + LIB_CFLAGS := $(DEF) DATE=$(CLASSDATE) $(DEF) NAME="$(CLASSLIB)" \ + $(DEF) VERSION="$(CLASSVER).$(CLASSREV)" +endif + +O_CFLAGS += $(LIB_CFLAGS) +D_CFLAGS += $(LIB_CFLAGS) + + +########################################################### +# additional assembler flags +# do not modify the spaces in the lines below! +# +O_SFLAGS += SET "LIBVERSION=$(CLASSVER),LIBREVISION=$(CLASSREV) " +D_SFLAGS += SET "LIBVERSION=$(CLASSVER),LIBREVISION=$(CLASSREV) " + + +########################################################### +# Main targets +########################################################### +# + +all: $(DEMOPROG) $(CLASSLIB) +ifneq ($(strip $(SUBDIRS)),) + for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) ; done +endif + +help-all: + @echo "This target will build all the classes and demo programs."; echo + + +lib: $(CLASSLIB) +ifneq ($(strip $(SUBDIRS)),) + for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) lib ; done +endif + +help-lib: + @echo "This target will build all the classes (but not the demo programs)."; echo + + +obj: $(CLASSOBJ_STATIC) +ifneq ($(strip $(SUBDIRS)),) + for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) obj ; done +endif + +help-obj: + @echo "This target create the classes object ready to be linked as a static" + @echo "library, with no debugging code."; echo + + +private: $(DEMOPROG) +ifneq ($(strip $(SUBDIRS)),) + for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) private ; done +endif + +help-private: + @echo "This target will build all the demo programs with the classes linked" + @echo "as static libraries. No debug code and symbols are added." + @echo + @echo "This may be useful to let other users test new versions of the classes" + @echo "without the need to install them or without overwriting old versions" + @echo "that may have been installed."; echo + + +debug: $(DEMOPROG_DEBUG) +ifneq ($(strip $(SUBDIRS)),) + for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) debug ; done +endif + +help-debug: + @echo "This target will build all the demo programs with the classes linked" + @echo "as static libraries. Debug code and symbols are added."; echo + + +install: +ifneq ($(strip $(SUBDIRS)),) + for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) install ; done +endif +ifneq ($(strip $(DEMOPROG)),) + $(CP) $(DEMOPROG) $(PREFIX)/demos/ +endif +ifneq ($(strip $(CLASSLIB)),) + $(CP) $(CLASSLIB) $(PREFIX)/classes/$(INSTALLDIR)/ +endif + +help-install: + @echo "This target copy all the classes and the demos in the dist/ directory," + @echo "placing the classes in the correct subdirectories."; echo + + +clean: +ifneq ($(strip $(SUBDIRS)),) + for i in $(SUBDIRS); do $(MAKE) -C $$i TOP=$(TOP) clean ; done +endif + $(RM) $(DEMOPROG) $(CLASSLIB) $(CLASSOBJ_STATIC) + +help-clean: + @echo "This target delete all the demoprograms, all the classes and all" + @echo "the objects in the sources subdirectories."; echo + + +help: + @echo "Type 'make help-(targetname) (e.g. 'make help-all') to get" + @echo "a detailed help for each target"; echo + @echo "Current package configuration:" + @echo "------------------------------" + @echo "Defined targets: all; lib; debug; private; obj; install; clean; setup;" + @echo "Defined subdirs: $(patsubst %,%;,$(SUBDIRS))"; echo + @echo "Your OpenBoopsi root directory: $(TOP)."; echo + @echo "Configured compiler: $(COMPILER)." + @echo "Configured cpu: $(CPU)." +ifeq ($(strip $(NOSTDLIB)),0) + @echo "Configured demo linking method: standard startup code." +else + @echo "Configured demo linking method: custom startup code." +endif + @echo; echo "Happy compiling!"; echo + + +########################################################### +# build the class library +########################################################### +# +$(CLASSLIB): ClassLib.o $(CLASSOBJ_SHARED) $(CLASSOBJ) + @$(ECHO) "Building class library..." + $(LDNOLIB) ClassLib.o $(CLASSOBJ_SHARED) $(CLASSOBJ) $(TO) $@ $(O_LFLAGS) $(ARG_LIB) + $(FLUSHLIBS) + + +########################################################### +# compile class source +########################################################### +# + +# All objects depend on their headers +$(CLASSOBJ_SHARED) $(CLASSOBJ_STATIC) $(CLASSOBJ_DEBUG): $(CLASSINC) $(BOOPSI_DEPS) + +$(CLASSOBJ_SHARED): %_shared.o : %.c + $(CC) $< $(TO) $@ $(O_CFLAGS) -DCLASS_FLAVOUR=3 + +$(CLASSOBJ_STATIC): %_static.o : %.c + $(CC) $< $(TO) $@ $(O_CFLAGS) -DCLASS_FLAVOUR=0 + +$(CLASSOBJ_DEBUG): %_dbg.o : %.c + $(CC) $< $(TO) $@ $(D_CFLAGS) -DCLASS_FLAVOUR=0 + +########################################################### +# assemble the class library init code +########################################################### +# +# All this mess is required since PhxAss can't handle +# UNIX paths. It would also be possible to link this +# object without converting it, but it seems that +# this leads to a bigger executable... +# +ClassLib.o: $(TOP)/common/ClassLib.s Makefile +ifeq ($(strip $(COMPILER)),gcc) + $(CP) $< /t + $(ASM) T:ClassLib.s TO T:temp.o $(O_SFLAGS) + $(HUNK2AOUT) /t/temp.o >NIL: + $(REN) obj.* $@ + $(RM) /t/ClassLib.s /t/temp.o +else + $(ASM) $< $(TO) $@ $(O_SFLAGS) +endif + + +########################################################### +# build the demo program +########################################################### +# +ifneq ($(strip $(DEMOPROG)),) + +$(DEMOPROG): $(DEMOOBJ_STATIC) $(DEMOOBJ) $(CLASSOBJ_STATIC) $(CLASSOBJ) + @$(ECHO) "Linking demo..." +ifeq ($(strip $(NOSTDLIB)),0) + $(LD) $(TO) $@ $(DEMOOBJ_STATIC) $(DEMOOBJ) $(CLASSOBJ_STATIC) $(CLASSOBJ) $(O_LIBS) $(O_LFLAGS) +else + $(LDNOLIB) $(TO) $@ $(APP_STARTUP) $(DEMOOBJ_STATIC) $(DEMOOBJ) $(CLASSOBJ_STATIC) $(CLASSOBJ) $(O_LIBS) $(O_LFLAGS) +endif + +$(DEMOPROG_DEBUG): $(DEMOOBJ_DEBUG) $(DEMOOBJ) $(CLASSOBJ_DEBUG) $(CLASSOBJ) +ifeq ($(strip $(NOSTDLIB)),0) + $(CC) $(TO) $@ $(DEMOOBJ_DEBUG) $(DEMOOBJ) $(CLASSOBJ_DEBUG) $(CLASSOBJ) $(D_LIBS) $(D_LFLAGS) +else + $(LDNOLIB) $(TO) $@ $(APP_STARTUP) $(DEMOOBJ_DEBUG) $(DEMOOBJ) $(CLASSOBJ_DEBUG) $(CLASSOBJ) $(D_LIBS) $(D_LFLAGS) +endif + +endif + + +########################################################### +# compile demo source +########################################################### +# + +# All objects depend on their headers +$(DEMOOBJ_SHARED) $(DEMOOBJ_DEBUG) $(DEMOOBJ_STATIC): $(CLASSINC) + +$(DEMOOBJ_SHARED): %_shared.o : %.c + $(CC) $< $(TO) $@ $(O_CFLAGS) -DCLASS_FLAVOUR=3 + +$(DEMOOBJ_STATIC): %_static.o : %.c + $(CC) $< $(TO) $@ $(O_CFLAGS) -DCLASS_FLAVOUR=0 + +$(DEMOOBJ_DEBUG): %_dbg.o : %.c + $(CC) $< $(TO) $@ $(D_CFLAGS) -DCLASS_FLAVOUR=0 + + +########################################################### +# GNU make quirks +########################################################### + +# disable all implicit rules for suffixes known to GNU make such as .c and .o +.SUFFIXES: + +# Explicitly declare standard targets as phony +.PHONY: all lib debug private obj install clean help \ + help-all help-lib help-debug help-private help-obj \ + help-install help-clean diff --git a/common/gst.c b/common/gst.c new file mode 100644 index 0000000..ba73e8f --- /dev/null +++ b/common/gst.c @@ -0,0 +1,52 @@ +/* +** $Id:$ +** +** Copyright (C) 1997,99 by Bernardo Innocenti +** +** This is a dummy source file used to make the Global Symbol Table +** for the boopsi classes. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "CompilerSpecific.h" +#include "DebugMacros.h" + +/* Can't include these in GST because they define some inline stuff + * + * #include "BoopsiStubs.h" + * #include "ListMacros.h" + */ + +/* Can't include these because otherwise the GST would need to be + * remade each time you edit one of the headers. + * + * #define LV_GADTOOLS_STUFF + * #include "ScrollButtonClass.h" + * #include "ListViewClass.h" + * #include "VectorGlyphIClass.h" + * #include "ListBoxClass.h" + */ diff --git a/common/startup_gcc.s b/common/startup_gcc.s new file mode 100644 index 0000000..ca4a05d --- /dev/null +++ b/common/startup_gcc.s @@ -0,0 +1,2 @@ +.text + jmp __main diff --git a/common/startup_sc.s b/common/startup_sc.s new file mode 100644 index 0000000..a37c6b0 --- /dev/null +++ b/common/startup_sc.s @@ -0,0 +1,9 @@ + + XREF @_main + + SECTION CODE,code + +_start: + jmp @_main + + END diff --git a/common/startup_storm.s b/common/startup_storm.s new file mode 100644 index 0000000..912a205 --- /dev/null +++ b/common/startup_storm.s @@ -0,0 +1,9 @@ + + XREF __main + + SECTION CODE,code + +_start: + bra __main + + END diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..6156aa7 --- /dev/null +++ b/config.mk @@ -0,0 +1,214 @@ +## +## $Id: config.mk,v 1.1 2000/01/12 20:34:26 bernie Exp $ +## +## Build environment configuration parameters +## Copyright (C) 1999 by B. Innocenti & M. Cavalleri + + +########################################################### +# Package configuration +########################################################### + +# CPU to compile for (eg: "68020"). +# +CPU := 68020 + +# Compiler to use. Possible options are: +# sc - SAS/C 6.58 or better +# gcc - gcc 2.7.2 or EGCS 1.1b +# vbcc - Not yet supported +# stormc - Not yet supported +# +COMPILER := gcc + +# Additional include directories (e.g.: system headers) +# +C_INCLUDE_PATH := -I/gg/include -I/include + +# compiling options: set this variable to +# 0 to link the demo programs with the standard +# startup libraries, se to other values to +# link to obj/app_startup.o +# +NOSTDLIB := 0 + + +########################################################### +# Tools used in the Makefiles +########################################################### + +NOP := echo +ECHO := echo +FLUSHLIBS := Avail FLUSH >NIL: +MAKEINFO := GG:bin/makeinfo +FD2PRAGMA := fd2pragma +HUNK2AOUT := hunk2aout +FLEXCAT := FlexCat +ARCHIVER := LZX -3 -e -r a + + +########################################################### +# Compiler, linker and assembler flags +########################################################### + +# Flags for SAS/C +# +ifeq ($(strip $(COMPILER)),sc) + + APP_STARTUP_SRC := $(TOP)/common/startup_sc.s + + CC := sc + AS := PhxAss + ASM := $(AS) + LD := PhxLnk + LDNOLIB := PhxLnk + CP := copy CLONE + REN := rename + RM := delete + + # GST usage must sometimes be disabled due to bugs in SAS/C 6.58 + GST := $(OBJDIR)/$(PROJNAME).gst + + # Note: Using the "STRCONST" compiler option requires + # patched versions of the OS headers to work correctly + + # compiler flags + # + OPT_CFLAGS := OPTIMIZE OPTTIME OPTSCHEDULER OPTINLINELOCAL \ + OPTRDEPTH=4 OPTDEPTH=4 OPTCOMP=8 DATA=NEAR CODE=NEAR + DBG_CFLAGS := NOOPTIMIZE DEBUG=FULLFLUSH ONERROR=CONTINUE CODE=FAR \ + DATA=FAR DEF DEBUG=1 + CMN_CFLAGS := PARAMS=REGISTERS STRMERGE AFP UTILLIB INCDIR=$(INCDIR) \ + NOSTKCHK NOCHKABORT NOICONS STRSECT=CODE GST $(GST) CPU=$(CPU) + + # assembler flags + # + OPT_SFLAGS := SMALLDATA SMALLCODE ALIGN MACHINE=$(CPU) OPT ! + DBG_SFLAGS := SYMDEBUG LINEDEBUG SET "_DEBUG=1" + CMN_SFLAGS := INCPATH=INCLUDE:,$(INCDIR) NOEXE QUIET + + # linker flags + # + # Use the utility.library for 32bit multiplication and division. + # + # The C runtime library is never used but it's still needed because + # SAS/C sometimes generates code that referencess symbols such as + # _CXAMEMSET or _CXAMEMCPY + # + OPT_LFLAGS := NODEBUG + DBG_LFLAGS := NOSHORTRELOCS ADDSYM + CMN_LFLAGS := SMALLCODE SMALLDATA NOALVS NOICONS BATCH DEFINE \ + "__CXM33=__UCXM33,__CXD33=__UCXD33,__CXM22=__UCXM22,__CXD22=__UCXD22" + + OPT_LIBS := + DBG_LIBS := LIB:debug.lib LIB:small.lib + CMN_LIBS := LIB:sc.lib + + # misc flags + # + TO := TO + OBJ := NOLINK + DEF := DEFINE + + # Additional flags for SAS/C GST support + # + ifneq ($(strip $(GST)),) + CMN_CFLAGS += GST=$(GST) + endif +endif + +# +# Flags for gcc or egcs +# +ifeq ($(strip $(COMPILER)),gcc) + + APP_STARTUP_SRC := $(TOP)/common/startup_gcc.s + + CC := gcc -c + AS := as + ASM := PhxAss + LD := gcc -noixemul + LDNOLIB := gcc -nostartfiles -noixemul + CP := cp + MV := mv + REN := $(MV) + RM := rm + + # compiler flags + # + # if you have some custom include directory we suggest you to + # use the variable C_INCLUDE_PATH instead of adding it to + # the directories list below via tha argument -I + # + OPT_CFLAGS := -O2 -msmall-code -fomit-frame-pointer -mregparm -funroll-loops \ + -finline-functions -fno-implement-inlines + DBG_CFLAGS := -D_DEBUG=1 -g + CMN_CFLAGS := -m$(CPU) -Wundef -Wimplicit -Winline -Wreturn-type \ + -I$(TOP)/include/ $(C_INCLUDE_PATH) + + # assembler flags (for PhxAss, not as. these are needed + # to compile the library startup code). + # + OPT_SFLAGS := SMALLDATA SMALLCODE ALIGN MACHINE=$(CPU) OPT ! + DBG_SFLAGS := SYMDEBUG LINEDEBUG SET "DEBUG" + CMN_SFLAGS := INCPATH=INCLUDE:,$(INCDIR) NOEXE QUIET + + # linker flags + # + OPT_LFLAGS := -s + DBG_LFLAGS := + CMN_LFLAGS := + + OPT_LIBS := + DBG_LIBS := -lamiga_debug + CMN_LIBS := + + # misc flags + # + TO := -o + OBJ := -c + DEF := -D +endif + + + +########################################################### +########################################################### +# You shouldn't need to modify anything below this line +########################################################### +########################################################### + + + +# distribution version is compiled with these flags +# +O_CFLAGS := $(CMN_CFLAGS) $(OPT_CFLAGS) +O_SFLAGS := $(CMN_SFLAGS) $(OPT_SFLAGS) +O_LFLAGS := $(CMN_LFLAGS) $(OPT_LFLAGS) +O_LIBS := $(CMN_LIBS) $(OPT_LIBS) + + +# debug version is compiled with these flags +# +D_CFLAGS := $(CMN_CFLAGS) $(DBG_CFLAGS) +D_SFLAGS := $(CMN_SFLAGS) $(DBG_SFLAGS) +D_LFLAGS := $(CMN_LFLAGS) $(DBG_LFLAGS) +D_LIBS := $(CMN_LIBS) $(DBG_LIBS) + + +########################################################### +# Paths +########################################################### + +OBJDIR := $(TOP)/obj +INCDIR := $(TOP)/include +PREFIX := $(TOP)/dist + +PROJNAME := OpenBoopsi +ARCNAME := $(PREFIX)/$(PROJNAME).lzx +SRCARCNAME := $(PREFIX)/$(PROJNAME)_src.lzx + +# APP_STARTUP_SRC is defined in the +# compiler specific sections +# +APP_STARTUP := $(OBJDIR)/app_startup.o diff --git a/docs/ExtFrameIClass.doc b/docs/ExtFrameIClass.doc new file mode 100644 index 0000000..76523fb --- /dev/null +++ b/docs/ExtFrameIClass.doc @@ -0,0 +1,96 @@ +TABLE OF CONTENTS + +extframe.image/extframe.image + extframe.image/extframe.image extframe.image/extframe.image + + NAME + extframe.image -- extended frame BBOPSI image (V1) + + FUNCTION + The extframe class is a complete replacement of the built in + frameiclass provided by Intuition. It can render itself using the + pens specified by the application, or can use the standard DrawInfo + pens (like the original frameiclass) when the needed pens have not + been supplied. It offers some new frame type, like the well known + XEN frame. It offers an improved configurability (quite every aspect + of the frame can be configured), an extended IM_FRAMEBOX method and + some OS3 specific optimizations. + It is made to be as fast as possible and offer the possibility to + programmers to add new frame types with little or no changes at all + at the GM_RENDER method. + This class is a subclass of the imageclass, and support all the + attributes of the frameiclass class (at least it should), so you + must read their doc to learn the supported tags and their meaning. + Here I will list only the class specific tags or methods. + + METHODS + IM_FRAMEBOX -- Ask the frame information on its size according to + its content. It is identical to the frameiclass method, but + offers a new flag beside the standard FRAMEF_SPECIFY. If you + specify the new FRAMEF_QUERY flag, you supply the FrameBox + (instead of the ContentsBox) and the frame will fill the + ContentsBox with the appropriate size/position value taking + into consideration the frame thickness, the space between the + frame and its contents, etc. + + TAGS + + IA_FrameDistance -- Space between the frame and the gadget in pixel. + Negative values are allowed. + + Applicability is (ISG) + + IA_InnerDistance -- Space between the two 'side' of a frame. For + example a inner distance of 0 pixel will make a FRAME_ICONDROPBOX + frame look like a FRAME_RIDGE frame. Currently this tag has + effect only on the FRAME_ICONDROPBOX frame. + + Applicability is (ISG) + + IA_PenBackground -- Specify the background pen. Used only if + you did not specify the IA_EdgesOnly attribute. If this + tag is not specified or is set to -1 the standard BACKGROUNDPEN + pen will be used. + + Applicability is (ISG) + + IA_PenSelBackground -- Specify the pen used to fill the frame + when it's in the selected state. Ignored if the frame is a + IA_EdgesOnly one. If it is not specified or is set to -1 + the FILLPEN pen will be used. + + Applicability is (ISG) + + IA_PenShine -- Specify the pen number used for the shine pen (i.e. + for raised borders). If it is not specified or set to -1 the + standard SHINEPEN will be used. + + Applicability is (ISG) + + IA_PenShadow -- Specify the pen number used for the shadow pen. + (i.e. for recessed borders). If it is not specified or set to -1 + the standard SHADOWPEN will be used. + + Applicability is (ISG) + + IA_PenHalfShine -- Specify the halfshine pen. If it is not specified + or set to -1 the standard SHINEPEN will be used. It's usually a + bit darker than the shine pen and is commonly used in the xen + frame. + + Applicability is (ISG) + + IA_PenHalfShadow -- Specify the halfshadow pen. If it is not + specified or set to -1 the standard SHADOWPEN will be used. It's + usually a bit brighter than the shadow pen and is commonly used + for the xen frame. + + Applicability is (ISG) + + BUGS + The tags supported by the frameiclass are not very well documented, + so this class may not support all the needed tags. + + SEE ALSO + The "Image Subclasses" chapter of the Intuition Reference Manual. + diff --git a/docs/Intuition b/docs/Intuition new file mode 100644 index 0000000..db7096a --- /dev/null +++ b/docs/Intuition @@ -0,0 +1,523 @@ + +INDICE + +Introduzione + Come si comporta Intuition + Come si comporta MUI + +Problemi + Problema n. 1 (input.device bloccato; Intuition) + Problema n. 2 (refresh della GUI bloccato; MUI) + +Ipotesi di soluzioni + Possibile soluzione per il problema n. 1 (sotto-task IDCMP in parallelo) + Possibile soluzione per il problema n. 2 (classe MUI con task asincrono) + +Considerazioni finali + Funzionamento seriale dell'input.device + Fattibilità di un patch per Intuition + + +INTRODUZIONE + +Come si comporta Intuition +-------------------------- + +L'input dell'utente viene letto, comunicando direttamente con l'hardware, +da keyboard.device e gameport.device, che lo trasmettono all'input.device. + +Quest'ultimo unisce le diverse informazioni sull'input in un unico stream +(flusso) di "eventi di input", omogeneo e sequenziale, rappresentato con +una lista di strutture InputEvent. + +L'input.device passa poi tale lista ad una serie di "input handler", secondo +un ordine basato sulla loro priorità. + +Ciascun handler può intraprendere delle azioni in base al contenuto della +lista ricevuta in ingresso; può inoltre apporre modifiche alla lista stessa +aggiungendo, rimuovendo o alterando eventi. In uscita l'handler restituisce +la lista modificata, la quale diventerà l'ingresso per l'handler successivo. + +Il codice di un handler viene eseguito come una normale chiamata a funzione: +di conseguenza esso gira sempre nel contesto del task dell'input.device. + +Normalmente l'handler con priorità massima è quello della commodities.library +(che quindi intercetta gli eventi prima di chiunque altro), tranne che nel +caso in cui essa non sia stata ancora aperta. + +L'handler immediatamente successivo è tipicamente quello di Intuition; la +sua funzione è "interpretare", ed eventualmente filtrare, tutti quegli eventi +che possono influire sullo stato della GUI o sulle attività dei programmi che +ne fanno uso. + +Questo handler fondamentalmente si limita a chiamare la funzione Intuition() +della intuition.library, passandole come unico argomento il puntatore alla +lista di eventi ricevuto in ingresso. + +Intuition() verifica la natura di ogni singolo evento e, se necessario, +reagisce ad esso eseguendo opportune azioni, come ad esempio attivare una +finestra, modificare l'aspetto e lo stato di un gadget o inviare un messaggio +ad un applicativo. + +La casistica più comune comprende: + +· Refresh automatico di una componente della GUI (bordo di una finestra, + gadget non BOOPSI, barra del titolo di uno schermo). + +· Visualizzazione di menu + +· Invocazione dell'opportuno metodo di un gadget BOOPSI + +· Nessuna azione visibile (es.: click all'interno di una finestra, ma non + su un gadget) + +A ciascuna di queste azioni può essere associato l'invio di un particolare +messaggio, rappresentato da una struttura IntuiMessage, all'applicativo +"proprietario" della finestra correntemente attiva (normalmente il task che +l'ha aperta). + +Gli IntuiMessage hanno spesso una corrispondenza stretta con gli InputEvent +da cui derivano. + +Al termine di queste azioni gli eventi che non possono essere utili agli +handler successivi vengono rimossi dalla lista, altri (generalmente utili +a console.device) vengono aggiunti, e la funzione Intuition() termina +restituendo all'handler il puntatore alla nuova lista. + +Infine l'handler di Intuition restituisce a sua volta il puntatore +all'input.device che può quindi passarlo all'handler successivo, solitamente +quello di console.device. + _ _ _ _ _ _ + | \ \ \ \ \ | + |Applicativo| + |_\_\_\_\_\_| + InputEvent stream /|\ + .····················. _ _ _|_ _ __ + : : | | + _ _ _ _ _ _ _ _ _ _ _: _ _ _ _ __ _ _ V _ _ __ _ |Messaggio ad| +| | | | | | |applicativo | +|keyboard.device|-. | |==>|Input handler (CX) | |__ _ _ _ _ _| +|_ _ _ _ _ _ _ _| \ | | |_ _ _ _ _ _ _ _ _ _| /\ + _ _ _ _ _ _ _ _ \ | | _ __ _ _ V _ _ __ _ _ ||_ _ _ _ +| | \ |input.device| | | | | +|gameport.device|----->| task |==>|Input handler (I) |==>|Intuition()| +|_ _ _ _ _ _ _ _| / | | |_ _ _ _ _ _ _ _ _ _| |_ _ _ _ _ _| + _ _ _ _ _ _ _ _ / | | _ __ _ _ V _ _ __ _ || +| | / | | | | _ _ \/_ _ +| timer.device |-' | |==>|Input handler (c.d)| | | +|_ _ _ _ _ _ _ _| |__ _ _ _ _ _| |_ _ _ _ _ _ _ _ _ _| |Refresh | + : |della GUI| + _: |_ _ _ _ _| + / \_/ || + : _ _ _ _ \/_ _ _ _ + : | | + V |Esecuzione metodo| + ///// |_ _ _ _ _ _ _ _ _| + +Questo meccanismo comporta che l'unico codice eseguito nel contesto di un +applicativo che faccia uso di Intuition è quello che si occupa di rispondere +agli IntuiMessage ed intraprendere eventuali azioni in base al loro contenuto +(generalmente finalizzate a svolgere il compito richiesto dall'utente più +che a gestire l'interfaccia; tuttavia nel caso di GadTools alcune operazioni +di gestione della GUI vengono affidate al task dell'applicativo mediante le +funzioni GT_GetIMsg() e GT_ReplyIMsg()). + +In particolare, nel caso dei gadget BOOPSI, la risposta della GUI risulta +sempre immediata e "in tempo reale", indipendentemente dalle operazioni che +l'applicativo sta svolgendo nello stesso momento, poiché di fatto se ne +occupa asincronamente un altro task (quello dell'input.device). + + +Come si comporta MUI +-------------------- + +La differenza fondamentale tra MUI ed Intuition è che i suoi gadget, pur +essendo oggetti BOOPSI, sono sottoclassi di "rootclass" piuttosto che di +"gadgetclass". Di conseguenza non sono riconosciuti da Intuition come dei +normali gadget e non vengono quindi gestiti automaticamente dalla funzione +Intuition(). Tutto ciò che quest'ultima rileva quando l'utente interagisce +con i gadget MUI è una serie di eventi IDCMP_MOUSEBUTTONS e IDCMP_MOUSEMOVE +che essa trasmette, invariati, al task proprietario della finestra. + +Quest'ultimo tipicamente si trova in uno stato di attesa degli eventi. +Per ogni evento ricevuto chiama una funzione MUI di gestione dell'input +(per l'esattezza invoca un metodo di una particolare classe) la quale +è poi in grado di determinare a quale gadget MUI va passato, mediante +l'invocazione di un suo opportuno metodo, l'evento appena letto. + _ _ _ _ _ _ _ _ _ __ + | \ \ \ \ \ \ \ \ \ \| + |Operazioni programma| + |_\_\_\_\_\_\_\_\_\_\| + _ _ _ _ _ _ _ _ __ /\ + _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _|| _ _ _ _ +| | |Semplice messaggio| | \ \ \ \ \ | | \ \ \ \ \ \ \ \ | +|Intuition()|==>| all'applicativo |---->|Applicativo| |Refresh della GUI| +|_ _ _ _ _ _| | (IDCMP_MOUSE#?) | |_\_\_\_\_\_| |_\_\_\_\_\_\_\_\_| + |__ _ _ _ _ _ _ _ _| || /\ + _ _ _ \/_ _ __ _ _ _ _|| _ _ _ _ + | \ \ \ \ \ \ \| | \ \ \ \ \ \ \ \ | + |Gestione input|==>|Esecuzione metodo| + |_\_\_\_\_\_\_\| |_\_\_\_\_\_\_\_\_| + +Con MUI, di conseguenza, la risposta della GUI (almeno con le classi di +gadget standard fornite con il pacchetto) risulta sincrona alle operazioni +del task dell'applicativo, in quanto avviene nel suo stesso contesto. + + +PROBLEMI + +Problema n. 1 (input.device bloccato; Intuition) +------------------------------------------------ + +La gestione dell'input secondo il modello di Intuition, cioè tramite un +handler, ha il vantaggio di garantire pressoché sempre una risposta immediata +da parte della GUI, anche nel caso in cui l'applicativo non fosse pronto a +reagire all'input ricevuto. + +Tuttavia, poiché l'handler di Intuition opera sempre, come già illustrato, +nel contesto dell'input.device, qualsiasi trasmissione di eventi di input +nel sistema risulta completamente bloccata fino alla conclusione delle sue +operazioni. + +Il problema si manifesta in modo evidente soprattutto con i gadget BOOPSI; +infatti l'handler invoca opportuni metodi di tali gadget quando l'input +dell'utente è diretto a loro o comporta una modifica del loro stato. Nel +caso di metodi particolarmente complessi, come quelli dei gadget associati +ai DataType, il tempo di esecuzione può essere elevato, e di conseguenza +la trasmissione dell'input nell'intero sistema può subire una sospensione di +durata non trascurabile. + +Il sintomo più tipico è il blocco del puntatore del mouse, ma anche altre +attività del sistema operativo che si basino su una regolare ricezione di +eventi di input (ad esempio quelli generati dal timer.device) rischiano di +venire ostacolate con conseguenze imprevedibili. + + +Problema n. 2 (refresh della GUI bloccato; MUI) +----------------------------------------------- + +Il sistema MUI presenta un problema per certi versi opposto, ma ugualmente +fastidioso per l'utente. Con i gadget di MUI le operazioni svolte nel +contesto del task dell'input.device sono sempre molto limitate e di breve +durata; si tratta per lo più di comunicare una serie di click dei pulsanti +del mouse (e spostamenti di quest'ultimo) all'applicativo associato al canale +IDCMP della finestra attiva. + +Ogni operazione relativa alla GUI viene poi effettuata nel contesto del task +che riceve i messaggi in questione. Nel caso esso sia occupato in qualche +elaborazione e quindi non si trovi in attesa di segnali dalla porta IDCMP, +come è facile immaginare, nessun tipo di aggiornamento della GUI verrà +attuato fino alla conclusione delle operazioni. + +L'utente, in questo caso, non osservando alcuna risposta dai gadget con cui +tenta di interagire, può avere l'impressione che l'intero programma sia +bloccato e non semplicemente impegnato in altre attività. + +Nel caso migliore l'utente si fa una cattiva opinione del programma; inoltre +l'incertezza sul da farsi può portare l'utente a danneggiare inavvertitamente +il lavoro che sta svolgendo mediante l'applicativo. Ad esempio, un tentativo +di selezione ripetuta dello stesso gadget (nella speranza di una ripresa del +funzionamento del programma) può provocare effetti collaterali indesiderati +nell'istante in cui l'applicativo ricomincia a gestire l'input e si occupa di +quello nel frattempo ricevuto. + + +IPOTESI DI SOLUZIONI + +Possibile soluzione per il problema n. 1 (sotto-task IDCMP in parallelo) +------------------------------------------------------------------------ + +Una possibile soluzione al primo problema, attuabile al livello di Intuition, +è la gestione multithreaded degli eventi di input trasmessi al suo handler +dall'input.device, che in tal modo si libererebbe molto rapidamente dopo +la chiamata alla funzione Intuition(). Come realizzare questo nella pratica? + +Un'idea potrebbe essere associare ad ogni schermo e finestra un task +dedicato, creato all'apertura ed eliminato alla chiusura. Ciascuno di questi +task riceverebbe solo gli eventi che lo riguardano e potrebbe gestirli del +tutto asincronamente al resto del sistema e in particolare all'input.device. + +Per rendere possibile ciò sarebbe necessario apportare alcune modifiche alla +funzione Intuition(): + +1. Essa dovrebbe, preliminarmente, esaminare la lista di InputEvent ricevuta + dall'input.device e in base ad essa costruire una seconda lista privata + copiando tutti gli eventi che riguardano la GUI. + +2. Fatto ciò, tutti gli eventi che non devono essere rilevati dagli altri + handler dovrebbero essere rimossi dalla lista principale. + +3. La lista privata di eventi dovrebbe poi essere separata in sottoliste, + ognuna indirizzata all'opportuna finestra (o all'opportuno schermo). + +4. Ogni sottolista dovrebbe essere spedita, tramite un opportuno messaggio, + al task associato alla finestra (o schermo) destinazione. + +5. A questo punto Intuition() potrebbe terminare subito la sua esecuzione, + senza aspettare alcuna risposta dai task a cui ha spedito i messaggi; + in questo modo l'input.device sarebbe subito libero di proseguire la + sua attività. + +Una possibile variante è il passaggio (subito dopo il punto 2) della lista +privata ad un task "intermedio" che si occupi di eseguire le operazioni +rimanenti; in questo caso Intuition() potrebbe terminare prima del punto 3. +Questo ipotetico task intermedio potrebbe ad esempio venire creato in modo +automatico all'apertura della intuition.library. + +Occorre prestare molta attenzione all'implementazione del punto 2, in quanto +è necessario stabilire delle regole precise in base alle quali si possa +determinare IN ANTICIPO e senza ambiguità se un evento riguarda o no la GUI e +se esso debba venire trasmesso o no ai successivi handler. Questo potrebbe, +oggettivamente, non essere un compito facile. + +In particolare, se un evento deve essere modificato da Intuition e poi +trasmesso al resto degli handler, bisogna che: + +- Si sappia già come modificarlo PRIMA di passarlo al task destinatario, + per non dover aspettare che questo termini fornendo informazioni sulla + modifica da effettuare (soluzione non sempre applicabile), oppure + +- Il task destinatario, dopo avere modificato personalmente l'evento, si + occupi di REINSERIRLO nella catena di InputEvent a monte dell'handler di + Intuition. Questo si può realizzare ad esempio aggiungendolo ad una coda + di eventi globale periodicamente letta dall'handler, oppure sfruttando + la commodities.library. Non basta chiamare direttamente Intuition() con + l'evento in questione poiché si rimarrebbe nel contesto del task. + Le regole per realizzare ciò potrebbero risultare abbastanza complicate. + +Ammettendo di risolvere questi problemi, restano da esaminare i compiti dei +singoli task destinatari. + +Quelli associati alle finestre svolgerebbero esattamente gli stessi compiti +che attualmente sono svolti dalla funzione Intuition(), cioè aggiornare lo +stato della GUI, invocare opportuni metodi di eventuali gadget BOOPSI +selezionati e spedire IntuiMessage all'applicativo che "possiede" la finestra +(con l'unica avvertenza, ovvia del resto, di assicurarsi che il task sia +completamente rientrante ed esegua una corretta arbitrazione sui dati globali +di IntuitionBase). + +I task associati agli schermi non dovrebbero fare altro che gestire la +selezione degli unici due possibili gadget, quello di trascinamento e quello +di profondità, nonché la disattivazione di tutte le finestre in caso di +click del mouse su una zona libera dello schermo, l'autoscrolling e lo screen +dragging tramite Amiga sinistro + mouse. + +Si potrebbe anche pensare ad un ulteriore task indipendente che gestisca +semplicemente il movimento del puntatore, ma questo è un compito talmente +banale che potrebbe essere svolto direttamente (e più rapidamente) dalla +funzione Intuition(). + _ _ _ _ _ _ + | \ \ \ \ \ | + |Applicativo| + |_\_\_\_\_\_| + InputEvent stream /|\ + .····················. | + : : :::::::::::::::: + _ _ _: _ _ _ _ __ _ _ V _ _ __ _ ::Messaggio ad:: +| | | | ::applicativo::: +| |==>|Input handler (CX) | :::::::::::::::: +| | |_ _ _ _ _ _ _ _ _ _| /\ +| | _ __ _ _ V _ _ __ _ _ _ _ _ _ _ || +|input.device| | | | | ::::::::::::::::: +| task |==>|Input handler (I) |==>|Intuition()|-->::Task finestra:: +| | |_ _ _ _ _ _ _ _ _ _| |_ _ _ _ _ _| ::::::::::::::::: +| | _ __ _ _ V _ _ __ _ || +| | | | \/ +| |==>|Input handler (c.d)| ::::::::::::: +|__ _ _ _ _ _| |_ _ _ _ _ _ _ _ _ _| ::Refresh:::: + : ::della GUI:: + _: ::::::::::::: + / \_/ || + : \/ + : ::::::::::::::::::::: + V ::Esecuzione metodo:: + ///// ::::::::::::::::::::: + + +Per concludere, si può osservare che in realtà sarebbe abbastanza raro che +la stessa lista contenga eventi indirizzati a finestre diverse; l'utente, +in circostanze normali, non dovrebbe essere più veloce dell'elaborazione +dell'input da parte del sistema. Un'eccezione sono gli eventi di timer (che +non sono generati dall'utente e sono sempre diretti a tutte le finestre). + +Alla luce di questa considerazione si potrebbe pensare di lasciare al +programmatore (o addirittura all'utente) la facoltà di decidere quali +finestre debbano essere dotate di un task IDCMP dedicato, e quali invece +possano semplicemente appoggiarsi ad un task IDCMP globale. + + +Possibile soluzione per il problema n. 2 (classe MUI con task asincrono) +------------------------------------------------------------------------ + +Il problema di MUI potrebbe risolversi molto facilmente con una riscrittura +delle classi di base del sistema. + +L'idea è che il dispatcher di un gadget MUI non dovrebbe eseguire in sequenza +(e nel contesto dell'applicativo) il refresh della GUI e poi la chiamata alla +funzione di callback associata al gadget. + +Ogni istanza di una classe di gadget MUI dovrebbe avere un proprio task +privato a cui affidare la chiamata alla funzione di callback, rendendola +così asincrona rispetto al refresh grafico. Tale task potrebbe essere creato +dal metodo OM_NEW della classe e distrutto in seguito da OM_DISPOSE. +Eventuali valori di ritorno diretti all'applicativo potrebbero essere +comunicati mediante messaggi (gestiti automaticamente dal task del gadget). + +Il refresh grafico dei gadget, invece, essendo generalmente un'operazione +abbastanza rapida, potrebbe essere affidato ad un unico task globale; una +possibilità sarebbe quella di creare questo task all'apertura della libreria +MUIMaster. + + :::::::::::::::::::::::: ::::::::::::::::::: + ::Operazioni programma::<==::Task del gadget:: + :::::::::::::::::::::::: ::::::::::::::::::: + _ _ _ _ _ _ _ _ __ /|\ + _ _ _ _ _ _ | | _ _ _ _ _ __ _ _ _ _ | _ _ _ _ +| | |Semplice messaggio| | \ \ \ \ \ \ \| | \ \ \ \ \ \ \ \ | +|Intuition()|==>| all'applicativo |-+ |Gestione input|==>|Esecuzione metodo| +|_ _ _ _ _ _| | (IDCMP_MOUSE#?) | | |_\_\_\_\_\_\_\| |_\_\_\_\_\_\_\_\_| + |__ _ _ _ _ _ _ _ _| | /\ | + | _ _ ||_ _ _ \|/ + | | \ \ \ \ \ | ;;;;;;;;;;;;;;;;;;;;; + +-->|Applicativo| ;;Refresh della GUI;; + |_\_\_\_\_\_| ;;;;;;;;;;;;;;;;;;;;; + +Se le operazioni di refresh non necessitano di restituire alcun valore al +dispatcher dell'oggetto (oppure alla funzione di MUI che gestisce l'input) +quest'ultimo verrebbe disimpegnato immediatamente; in caso contrario sarebbe +sufficiente che il task preposto al refresh svolgesse tutte le sue operazioni +prima di rispondere al dispatcher con ReplyMsg(), e copiasse il valore di +ritorno in un apposito campo del messaggio "restituito" al mittente. + +Questo ovviamente terrebbe impegnato il task dell'applicativo per un tempo +leggermente superiore, ma le operazioni di refresh grafico puro e semplice +non dovrebbero, nella maggior parte dei casi, richiedere più di qualche +millisecondo (come del resto accade per Intuition nel caso di gadget non +troppo complicati). Chiaramente se tale comportamento fosse richiesto per +TUTTI i gadget sarebbe più conveniente evitare del tutto l'uso di un task +separato per il refresh, mantenendo però quello dedicato al callback. + +Sarebbero possibili diverse variazioni sul tema: ad esempio, l'ordine in cui +vengono "richiamati" i due task potrebbe influenzare, sia pure di poco, la +prontezza del refresh e quindi della risposta all'utente da parte della GUI; +oppure in certi casi potrebbe essere conveniente creare "al volo" il task +preposto al callback in modo che l'applicativo possa eseguire più volte +contemporaneamente la stessa funzione (se la sua natura lo consente). + +In ogni caso questa soluzione eliminerebbe alla radice il problema del +"blocco" apparente della risposta della GUI durante un'intensa attività +dell'applicativo, senza per questo tornare al modello "mono-threaded" +adottato attualmente da Intuition. L'alternativa proposta per quest'ultimo +(vedi paragrafo precedente) risolverebbe in teoria anche il problema di MUI, +ma solo se i gadget MUI fossero istanze di "gadgetclass", cosa che al +momento, in pratica, non accade. + + +CONSIDERAZIONI FINALI + +Funzionamento seriale dell'input.device +--------------------------------------- + +Come già detto, l'input.device propaga lo stream di eventi di input +attraverso i vari handler in cascata. Gli handler non sono altro che +funzioni chiamate, una dopo l'altra, dal task dell'input.device; ogni +handler riceve in ingresso il valore di uscita del precedente (e cioè +il puntatore ad una particolare lista di InputEvent). + +Questo è un meccanismo intrinsecamente seriale; inoltre esso implica che gli +handler di priorità più alta (come quello di Intuition) debbano esaminare, +tra gli altri, molti eventi che non li riguardano direttamente e che vanno +semplicemente trasmessi agli handler successivi. + +Come aumentare il parallelismo nelle operazioni dell'input.device? + +Ingenuamente si potrebbe pensare di avere diverse code, ognuna gestita da +un task indipendente, tra cui suddividere gli eventi in base al tipo degli +handler che tali code alimentano; ovviamente occorrerebbe che gli handler +di una coda non abbiano mai la necessità di trasmettere eventi a quelli di +un'altra coda. + +Purtroppo in pratica questo non è una soluzione, dato che porterebbe a +ricreare la situazione corrente. Infatti normalmente gli handler esistenti +nel sistema sono pochi (per lo più Commodities, Intuition e console.device) +ed è difficile individuare tipi di eventi che non interessino, anche solo +potenzialmente, almeno due di essi. + +In particolare, la quasi totalità degli eventi di input generati dall'utente +interessa in qualche modo Intuition, che viene ad essere un vero e proprio +"collo di bottiglia". + +Più vantaggioso risulterebbe applicare questa soluzione al livello dei +singoli handler; ciascuno di essi, a meno che il suo funzionamento sia +molto semplice, potrebbe gestire l'input in arrivo ripartendolo in modo +opportuno tra diversi task paralleli (come illustrato riguardo al problema +di Intuition). + +In questo modo sorgerebbe però il problema della trasmissione del flusso +di input lungo la catena di handler. Ognuno di essi potrebbe trasmettere +al successivo solo gli eventi che può scartare immediatamente come "non +rilevanti" per le sue attività, ma gli sarebbe preclusa la possibilità di +modificare gli eventi utilizzati, o crearne di nuovi in base ai risultati +della loro elaborazione, e reinserirli nella posizione originale: questa +operazione generalmente richiederebbe la conoscenza di dati non disponibili +a priori e, d'altra parte, una sincronizzazione con i suoi task per ottenere +da essi tali dati annullerebbe ovviamente tutti i vantaggi del parallelismo. + +E` dunque necessario, volendo impiegare un simile modello: + +· Stabilire delle regole estremamente precise per decidere quando l'ordine + relativo di due eventi vada mantenuto oppure sia ininfluente; + +· Limitare al massimo la necessità di trasmettere informazioni tra un + handler e il successivo (nel caso di entità strettamente connesse, come + Intuition e console.device, questo potrebbe rivelarsi un problema serio); + +· Assicurarsi, ad esempio mediante semafori, che venga sempre mantenuta la + consistenza interna dei valori che definiscono lo stato di un handler (e + quindi dell'entità software che si appoggia ad esso) anche in presenza + di numerosi sotto-task che possono accedere a tali valori. + +Ad esempio, se l'utente attiva una finestra di Shell e poi preme un tasto +sulla tastiera, è necessario che il console.device riceva l'evento "finestra +attiva" PRIMA di quello "tasto premuto", nonostante il fatto che il secondo +potrebbe venire trasmesso immediatamente mentre il primo richiederebbe una +più lunga elaborazione da parte di Intuition. + +Ancora, quando l'utente trascina un gadget proporzionale sarebbe auspicabile +che la posizione relativa di knob e puntatore del mouse rimanesse costante, +anche se gli spostamenti dei due oggetti vengono gestiti da due diversi task. + +La trasmissione di eventi agli handler successivi potrebbe ad esempio essere +implementata mediante una coda ausiliaria globale svuotata periodicamente, +accessibile a tutti i sotto-task di un handler, purché si presti la massima +attenzione a mantenerla sempre perfettamente ordinata e ad inserire in essa +anche quegli eventi (e solo quelli) che, pur non dovendo essere elaborati +dall'handler corrente, possono risentire dell'ordine in cui vengono trasmessi +rispetto a certi altri eventi. + +Queste considerazioni non pretendono certamente di costituire una soluzione +completa, preferibile ad altre o facilmente realizzabile; si tratta solo di +riflessioni su alcuni aspetti del problema di cui probabilmente converrebbe +tenere conto. + + +Fattibilità di un patch per Intuition +------------------------------------- + +E` possibile, tramite un patch, applicare all'attuale versione di Intuition +i criteri appena esposti? + +Probabilmente no. + +L'idea sarebbe di applicare un patch alla funzione Intuition() per forzare +il passaggio dell'input ad un task separato che se ne occupi, permettendo +all'handler di Intuition di terminare subito la sua esecuzione. Ma anche +immaginando di risolvere quasi tutti i problemi prima descritti, resta sempre +l'impossibilità di garantire la consistenza dei dati PRIVATI contenuti nella +struttura IntuitionBase, a cui sarebbe facile, in questo modo, effettuare +un accesso asincrono. + +Non è escluso che si possa trovare una soluzione anche a questo problema, ma +con ogni probabilità a questo punto conviene aspettare che sia Amiga Inc. ad +implementare nel sistema operativo una gestione dell'input più efficiente. + diff --git a/docs/LabelTextIClass.doc b/docs/LabelTextIClass.doc new file mode 100755 index 0000000..669699c --- /dev/null +++ b/docs/LabelTextIClass.doc @@ -0,0 +1,181 @@ +TABLE OF CONTENTS + +labeltext.image/labeltext.image + labeltext.image/labeltext.image labeltext.image/labeltext.image + + NAME + labeltext.image -- label BBOPSI image (V1) + + FUNCTION + The labeltext class is a little BOOPSI class that provides a complete + label handling. A label can be placed inside or outside a gadget + (above, below, left, right or inside) with different alignments + (centered, left aligned, right aligned, etc.) with a couple of + different rendering methods (normal, hilighted, 3d). It is able to + use the standard DrawInfo pens when no custom pens are supplied and + the system default font when no custom font is supplied. + It supports various image states (i.e. normal, selected, disabled, + etc.) This class has also a nice API for easy layer clipping when it + is necessary. + + METHODS + IM_DRAW -- Tell the class to render itself. Before calling this + method for the first time you should first invoke the IM_FRAMEBOX + method and then the IM_DRAW one using the FrameBox Left and Top + field or the Image LeftEdge and TopEdge fields. Note that these + coordinates are NOT exactly the ones the label will use, i.e. + if you do a Text() call using that coordinates you'll get a text + slightly shifted. In other words if you calculate yourself the + coordinates of the label you won't be able to draw it in the right + place. This is required for an easy layer clipping support. + NB: You must alway supply the imp_Offset coordinates, even if the + Image->LeftEdge and Image->TopEdge field already contain the right + values. + + IM_FRAMEBOX -- This method tell the class to calculate its position + relative to the ContentsBox coordinates and according to its + alignment attributes. For this reason the ContenstBox is usually + filled with the gadgets coordinates. Moreover the FrameBox structure + is filled with the coordinates of the rectangle required by the + label to draw itself. In this way the gadget can easily perform + the correct layer clipping if necessary. Example: + + + struct IBox cbox, fbox; + struct Rectangle rect; + + DoMethod((Object *)gad->GadgetText, IM_FRAMEBOX, (ULONG)&(cbox), (ULONG)&fbox, NULL); + + rect.MinX = MAX(msg->gpr_GInfo->gi_Window->BorderLeft, fbox.Left); + rect.MinY = MAX(msg->gpr_GInfo->gi_Window->BorderTop, fbox.Top); + rect.MaxX = MIN(msg->gpr_GInfo->gi_Window->Width - msg->gpr_GInfo->gi_Window->BorderRight, + fbox.Left + fbox.Width - 1); + rect.MaxY = MIN(msg->gpr_GInfo->gi_Window->Height - msg->gpr_GInfo->gi_Window->BorderBottom, + fbox.Top + fbox.Height - 1); + + OrRectRegion(new_region, &rect); + old_region = InstallClipRegion(msg->gpr_GInfo->gi_Layer, new_region); + + + The same rectangle is then usually used to tell the label to draw + or erase itself (using the Left and Top field) but it is not + required, since the class modifies its coordinates with the values + it calculated the last time IM_FRAMEBOX was invoked (i.e. you may + alternatively supply the img->LeftEdge and img->TopEdge values). + + If you specify the FRAMEF_SPECIFY flag the label will check if it + fit in the ContentsBox rectangle. If not the FrameBox Left and + Top fields will be set to -1. You can blindly pass this values + to the IM_DRAW or IM_ERASE method, since the class knows that it + has not to render itself. The FrameBox Width and Height fields + are set to an arbitrary value to avoid problems if the gadget do + layer clipping without checking the result of the IM_FRAMEBOX + method. + + NOTE: If you change some attributes (e.g. the font) you should call + the IM_FRAMEBOX method again, so that the label can recalculate + its position and size. + + TAGS + + ELA_Label -- Pointer to the string the class will print. You MUST + supply this tag when you create an object. The label will not + deallocate the string when disposed. + + Applicability is (ISG) + + ELA_LabelType -- Specify the way the label should render itself. See + the include file for the currently supported values. + + Applicability is (ISG) + + ELA_Distance -- The distance from the gadget borders. Note that the + label does not know about frame thickness. e.g. if you draw a + label inside a gadget, left aligned with a distance of 0 pixel, + the label will likely draw itself over the left border of the + frame. If you want to avoid this you must set this attribute to + a value at least equal to the frame thickness. + + Applicability is (ISG) + + ELA_Position -- Tell the label where it should draw itself, i.e. + above the gadget, below, to the left, etc. Note that 'gadget' + is somewhat misleading, since the label calculates its position + relative to any rectangle. i.e. when you call the IM_FRAMEBOX + method, you usually pass as the ContentsBox the gadget + coordinates, but if you want you could, e.g. tell the label + to center itself in the window titlebar. + See the include file for the values of this tag. + + Applicability is (ISG) + + ELA_Align -- Set the alignment of the label. If the label is placed + above or below the gadget the label can be centered, left aligned + or right aligned. If placed to the side of the gadget it can be + vertically centered or aligned to the top or to the bottom of the + gadget. If it is placed inside it can be centered, aligned to the + top or bottom (always horizontally centered) or aligned to the + left or right (vertically centered). + + Applicability is (ISG) + + ELA_Font -- Specify the font the label will use to draw itself. + It must be a TextFont pointer, i.e. the one you'll get with + the OpenFont() function. The label will not close the font + when disposed. + + Applicability is (ISG) + + ELA_PenBackgound -- Specify the pen number used for the background + pen. If it is not specified or set to -1 the standard DrawInfo + BACKGROUNDPEN will be used. Currently it is used only to erase + the label. + + Applicability is (ISG) + + ELA_PenShine -- Specify the pen number used for the shine pen. + If it is not specified or set to -1 the standard SHINEPEN will + be used. Currently this is used for the 'hilight' and '3d' labels. + + Applicability is (ISG) + + ELA_PenShadow -- Specify the pen number used for the shadow pen. + If it is not specified or set to -1 the standard SHADOWPEN will + be used. This is the pen used for 'normal' and '3d' labels. + + Applicability is (ISG) + + ELA_PenHalfShine -- Specify the halfshine pen. If it is not specified + or set to -1 the standard SHINEPEN will be used. It's usually a + bit darker than the shine pen and is currently used for the + disabled state. + + Applicability is (ISG) + + ELA_PenHalfShadow -- Specify the halfshadow pen. If it is not + specified or set to -1 the standard SHADOWPEN will be used. + It'susually a bit brighter than the shadow pen and is currently + used for the disabled state. + + Applicability is (ISG) + + NOTE + Usually a single BOOPSI image (e.g. a frame) may be used by different + gadgets at the same time. This is true even for the textlabel class, + but there are a couple of little "problem" or side effects that may + be encountered. First every time the IM_FRAMEBOX method is called the + image LeftEdge and TopEdge fields are changed, so the gadgets should + take care of storing the result of this method by their own (i.e. they + should save the FrameBox Left and top fields somewhere), since if they + call the IM_DRAW method using the image coordinates they may use the + result of another gadget's IM_FRAMEBOX call. Second the text to be + printed (and maybe even the font) should be set every time before a + IM_DRAW method since it's very unlikely that different gadgets need to + display the same string. + Currently I don't know if there's some nice and elegant way to solve + this, so you should create a different instance of this class for every + gadget that will use a lebeltext object. + + SEE ALSO + The "Image Subclasses" chapter of the Intuition Reference Manual. + diff --git a/docs/NoteBOOPSI b/docs/NoteBOOPSI new file mode 100644 index 0000000..b227ff8 --- /dev/null +++ b/docs/NoteBOOPSI @@ -0,0 +1,149 @@ + +Alcune note sulla struttura GadgetInfo +-------------------------------------- + +Apparentemente l'input handler di Intuition riutilizza sempre, quando ciò è +possibile, la stessa struttura GadgetInfo quando invoca un metodo di un +gadget custom. Del resto il singolo task dell'input.device può solo invocare +un metodo dopo l'altro in sequenza e nella maggioranza dei casi non necessita +di avere contemporaneamente più di una struttura GadgetInfo. + +Nella struttura GadgetInfo un gadget custom riceve nel campo gi_Layer il +puntatore al layer associato al "contenitore logico" in cui si trova il +gadget stesso. + +· Un gadget custom situato in una finestra normale, oppure nella zona interna + di una finestra GIMMEZEROZERO riceve in gi_Layer il puntatore al layer di + Window.RPort. Il "contenitore logico" è l'area dell'intera finestra, oppure + l'area della sua zona interna. + +· Un gadget custom situato nella zona esterna di una finestra GIMMEZEROZERO + (GZZGADGET) riceve in gi_Layer il puntatore al layer di Window.BorderRPort. + Il "contenitore logico" è l'area dell'intera finestra. + +· Un gadget custom situato in un requester (REQGADGET) riceve in gi_Layer il + puntatore al layer del requester (Requester.ReqLayer). + Il "contenitore logico" è l'area del requester. + +· Un gadget custom situato nella titlebar di uno schermo (SCRGADGET) riceve + in gi_Layer il puntatore al layer della titlebar (Screen.BarLayer). + Il "contenitore logico" è l'area della titlebar. + +· Un gadget custom situato in un gruppo (cioè appartenente alla lista interna + di un gadget "groupgclass") riceve in gi_Layer un valore che dipende dal + "contenitore logico" del gruppo stesso, ricadendo così in uno dei quattro + casi precedenti. + +Il campo gi_RastPort è uguale a gi_Screen->BarLayer->rp quando il gadget +appartiene ad una finestra o ad un requester, e punta a gi_Screen.RastPort +quando invece il gadget appartiene alla titlebar dello schermo. +Ignoro le ragioni di questo fatto; in ogni caso questa RastPort per +qualche motivo non deve venire utilizzata per il rendering (nel caso di +un gadget SCRGADGET essa non ha nemmeno un layer). + +Chiamando ObtainGIRPort() si ottiene un clone della RastPort di gi_Layer, che +punta allo stesso layer, il quale punta alla RastPort originale (quella della +finestra interna, o quella del bordo per le finestre GIMMEZEROZERO, ecc.). + +Inoltre ObtainGIRPort() esegue un LockLayer() su gi_Layer. Apparentemente +gi_Layer ha già tre lock quando Intuition invoca il metodo GM_RENDER (solo due +nel caso di un gadget SCRGADGET) mentre non è bloccato nel caso di tutti gli +altri metodi. + +Per il metodo GM_RENDER il valore di gpr_RPort è esattamente lo stesso che +si otterrebbe chiamando ObtainGIRPort(), il che suggerisce che tale RastPort +clonata sia unica e conservata da qualche parte. In effetti a quanto ho visto +finora ObtainGIRPort() restituisce sempre lo stesso indirizzo, qualunque sia +il contesto. + +I valori di gi_Screen, gi_Window e gi_Requester sono inizializzati in modo +opportuno (oppure nulli se non applicabili, a parte gi_Screen). + +Tabella di esempio per un gadget in una finestra non GZZ: + + +-------------------------------------------------------------------------+ + | gi_Window: W | + | gi_Layer: RL, LWindow: W, LRastPort: R | + | gi_RastPort: S, BitMap: bm, Layer: SL, LWindow: 0, LRastPort: S | + | gi_Window->RPort: R, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R | + | gi_Window->BorderRP: 0, BitMap: --, Layer: --, LWindow: -, LRastPort: - | + | gpr_RPort: C, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R | + | ObtainGIRPort(): C, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R | + +-------------------------------------------------------------------------+ + +Tabella di esempio per un gadget non GZZ in una finestra GZZ: + + +-------------------------------------------------------------------------+ + | gi_Window: W | + | gi_Layer: RL, LWindow: W, LRastPort: R | + | gi_RastPort: S, BitMap: bm, Layer: SL, LWindow: 0, LRastPort: S | + | gi_Window->RPort: R, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R | + | gi_Window->BorderRP: B, BitMap: bm, Layer: BL, LWindow: W, LRastPort: B | + | gpr_RPort: C, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R | + | ObtainGIRPort(): C, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R | + +-------------------------------------------------------------------------+ + +Tabella di esempio per un gadget GZZ in una finestra GZZ: + + +-------------------------------------------------------------------------+ + | gi_Window: W | + | gi_Layer: BL, LWindow: W, LRastPort: B | + | gi_RastPort: S, BitMap: bm, Layer: SL, LWindow: 0, LRastPort: S | + | gi_Window->RPort: R, BitMap: bm, Layer: RL, LWindow: W, LRastPort: R | + | gi_Window->BorderRP: B, BitMap: bm, Layer: BL, LWindow: W, LRastPort: B | + | gpr_RPort: C, BitMap: bm, Layer: BL, LWindow: W, LRastPort: B | + | ObtainGIRPort(): C, BitMap: bm, Layer: BL, LWindow: W, LRastPort: B | + +-------------------------------------------------------------------------+ + +Il campo gi_Domain contiene larghezza e altezza del "contenitore logico" del +gadget. Nel caso di un gadget SCRGADGET, l'altezza è stranamente quella dello +schermo, mentre sarebbe più corretto se fosse quella della titlebar. Inoltre +un gadget che appartenga ad un gruppo ha come "contenitore logico" quello che +contiene il gruppo, e non il gruppo stesso (probabilmente in quanto il gruppo +non ha un layer proprio). +Gli offset contenuti in gi_Domain sono la distanza della posizione (espressa +in coordinate di schermo) del layer associato al "contenitore logico" del +gadget dalla posizione (sempre in coordinate di schermo) del suo "contenitore +fisico primario" (cioè lo schermo per i gadget SCRGADGET e la finestra per +tutti gli altri, anche se REQGADGET oppure appartenenti ad un gruppo). + +La funzione DoGadgetMethodA() crea una struttura GadgetInfo appropriata +in base al tipo di gadget di cui viene invocato il metodo. Se è di tipo +GZZGADGET, REQGADGET o SCRGADGET viene scelto il layer corretto, e anche +gi_Domain viene inizializzato adeguatamente. + +Un problema è che "gadgetclass" e "icclass" nell'implementare il metodo +OM_NOTIFY non chiamano DoGadgetMethodA() per invocare il metodo OM_UPDATE +dell'oggetto ICA_TARGET, bensì gli passano direttamente il puntatore a +GadgetInfo ricevuto, che fa riferimento al contesto dell'oggetto notificante +e non, come sarebbe corretto, a quello dell'oggetto notificato! + +Non si devono annidare chiamate a ObtainGIRPort(), altrimenti la RastPort +clonata (sempre la stessa) può venire modificata ad ogni chiamata. In +realtà probabilmente se si rimane nello stesso contesto la RastPort clonata +viene reinizializzata ogni volta con gli stessi valori, per cui non cambia +niente. Il vero pericolo sta nell'invocare un metodo di un altro gadget che +chiami ObtainGIRPort() mentre si è ancora all'interno del proprio blocco +ObtainGIRPort(). +In entrambi i casi comunque può verificarsi un errore 01000008 (Semaphore +in illegal state). +Del resto chiamare tanto ObtainGIRPort() quanto DoGadgetMethodA() all'interno +di un blocco ObtainGIRPort() dovrebbe essere scorretto comunque (sono due +funzioni di Intuition). + + +Note varie +---------- + +GACT_IMMEDIATE viene sempre rispettato anche per i gadget custom o BOOPSI. +Il valore di Code del messaggio IDCMP_GADGETDOWN è sempre zero e non può +essere impostato dal dispatcher in alcun metodo (GM_HITTEST/GM_GOACTIVE). + +GACT_RELVERIFY è necessario affinché l'uso di GMR_VERIFY + gpi_Termination +generi effettivamente un messaggio IDCMP_GADGETUP; in sua assenza esso non +viene generato. Viceversa la sua presenza non garantisce l'invio di tali +messaggi; ciò è deciso dal dispatcher nei metodi GM_GOACTIVE e GM_HANDLEINPUT. + +La documentazione del metodo IM_FRAMEBOX sul RKM è sbagliata! Viene invertito +il ruolo di imp_ContentsBox e imp_FrameBox. + diff --git a/docs/empty_Makefile b/docs/empty_Makefile new file mode 100644 index 0000000..c17c250 --- /dev/null +++ b/docs/empty_Makefile @@ -0,0 +1,96 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +## This is the 'local' makefile, i.e. the makefile +## that is placed in very classes' directory. +## You can simply copy it in your class' directory +## and rename it to 'Makefile', or, if you want, you +## can customize it. +## +## We also suggest you to delete the lines beginning +## with two '##' like the ones you are reading now. +## This will make the processing of this file faster +## since make won't have to strip tons of comments. +## +include $(BOOPSITOP)/config.mk +## +## This include the local configuration +## for your class, i.e. the file with +## the class name, version, etc. +## It must be present and properly +## customized. Read the Empty_config.mk +## file in the docs/ directory for a more +## detailed explanation. +## +include config.mk + +## +## These variables will be used by the general.mk +## files, so you may use them to pass "arguments" +## to it, e.g. if you need to link a specific object +## to your demo program or class. +## +## the ARG_COMMON is the arguments that will be used +## for all the targets, the other variables will be +## used only for the specific target +## +## example +## +## ARG_ALL := $(ARG_COMMON) MyObj.o +## +ARG_COMMON := +ARG_ALL := $(ARG_COMMON) +ARG_LIB := $(ARG_COMMON) +ARG_DEBUG := $(ARG_COMMON) +ARG_PRIVATE := $(ARG_COMMON) +ARG_OBJ := $(ARG_COMMON) +ARG_INSTALL := $(ARG_COMMON) + +## +## These variables will be used by the general.mk +## files, so you may use them to pass "arguments" +## to it, e.g. if you need to add new dependencies +## to the various targets +## +## the DEP_COMMON is the arguments that will be used +## for all the targets, the other variables will be +## used only for the specific target +## +## example +## +## DEP_ALL := $(DEP_COMMON) MyObj.o +## +DEP_COMMON := +DEP_ALL := $(DEP_COMMON) +DEP_LIB := $(DEP_COMMON) +DEP_DEBUG := $(DEP_COMMON) +DEP_PRIVATE := $(DEP_COMMON) +DEP_OBJ := $(DEP_COMMON) + +## +## This is the real makefile. If you +## don't like it you can include your +## own makefile. We suggest you to put it +## in the common/ directory (with a name +## different from 'general.mk') and to include +## it rather than writing it here, so that +## other user can use it for their classes. +## +## example +## +## include $(BOOPSITOP)/common/mycustommakefile.mk +## +include $(BOOPSITOP)/common/general.mk + +## +## Below you can add your own custom targets that are +## needed for your class. +## +## example +## +## MyObj.o: MyObj.c +## $(CC) $^ $(O) $@ +## diff --git a/docs/empty_config.mk b/docs/empty_config.mk new file mode 100644 index 0000000..6f9a513 --- /dev/null +++ b/docs/empty_config.mk @@ -0,0 +1,137 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +## This is an empty local config.mk file. You should fill +## the required fields, copy it to your class directory +## and rename it to "config.mk". +## Detailed explanations of the various variables are +## given below. Please be sure to give the right value +## to all the variables, or you may get unpredictable +## results!! +## +## We also suggest you to delete the lines beginning with +## two '##' like the ones you are reading now. This will +## make the processing of this file faster since make +## won't have to strip tons of comments. + +########################################################### +# your stuff +# + +## +## CLASSLIB is the name of the compiled class, like +## "label.image" or "listview.gadget", etc. +## This is required by the makefile. It will also +## define the symbol "NAME" with this variable's +## value so that it can be used in your source. +## +## example: +## +## CLASSLIB := button.gadget +## +CLASSLIB := +## +## CLASSSRC is the name of the source code of +## your class, extension included. +## This is required by the Makefile. +## +## example +## +## CLASSSRC := ButtonGClass.c +## +CLASSSRC := +## +## DEMOSRC is the name of the source code +## of your demo program, extension included. +## This is required by the Makefile. +## +## example +## +## DEMOSRC := ButtonGDemo.c +## +DEMOSRC := +## +## SUBDIR is the directory name where your class +## will be copied when you will execute the +## 'install' target. It must be "images" if your +## class is a BOOPSI image, "gadgets" if your class +## is a BOOPSI gadget or just an empty string if +## your class is a general BOOPSI object. +## +## example +## +## SUBDIR := gadgets +## +SUBDIR := + + +########################################################### +# class version information +# + +## +## CLASSVER is the version number of your class library +## e.g. if your library is version 1.2 CLASSVER is 1. +## It is required to compile the library startup code, +## and will also be used to define a symbol named VERSION, +## so that you can use it in your source code. +## +## example +## +## CLASSVER := 1 +## +CLASSVER := +## +## CLASSREV is the revision number of your class library +## e.g. if your library is version 1.2 CLASSREV is 2. +## It is required to compile the library startup code, +## and will also be used to define a symbol named VERSION, +## so that you can use it in your source code. +## +## example +## +## CLASSREV := 2 +## +CLASSREV := +## +## CLASSDATE is the date of your class library. It follow +## the standard AmigaOS rules, so it must be enclosed in +## parenthesis and have the following format: Day.Month.Year +## It is used to define a symbol named DATE so that you can +## use it in your source code. +## +## example +## +## CLASSDATE := (6.4.99) +## +CLASSDATE := + + +########################################################### +# variable to make the linked library version +# + +## +## PRV variables is used to compile the class as a linked +## library instead of the shared version. It is simply +## used to define a preprocessor simbol with the name +## you give here. +## It's up to you to create a class that can be compiled +## as a shared or static library depending on the +## definition of this symbol. The current makefile +## define it for a couple of targets, like 'debug', so +## we suggest you to implement this features. It's very +## easy and in most cases requires just some copy & paste +## from existing classes. Look at them or ask in the +## OpenBoopsi mailing list if you need a more detailed +## explanation. +## +## example +## +## PRV := PRIVATE_GADGETCLASS +## +PRV := + diff --git a/gadgets/ClockGClass/Makefile b/gadgets/ClockGClass/Makefile new file mode 100644 index 0000000..eb79630 --- /dev/null +++ b/gadgets/ClockGClass/Makefile @@ -0,0 +1,27 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(BOOPSITOP)/config.mk +include config.mk + +ARG_COMMON := +ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o +ARG_LIB := $(ARG_COMMON) +ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV) +ARG_PRIVATE := $(ARG_COMMON) +ARG_OBJ := $(ARG_COMMON) + +DEP_COMMON := +DEP_ALL := $(DEP_COMMON) OpenClass.o +DEP_LIB := $(DEP_COMMON) +DEP_DEBUG := $(DEP_COMMON) OpenClass.o +DEP_PRIVATE := $(DEP_COMMON) +DEP_OBJ := $(DEP_COMMON) + +include $(BOOPSITOP)/common/general.mk + +OpenClass.o: OpenClass.c + $(MAKE) -C $(BOOPSITOP)/common/ $@ diff --git a/gadgets/LauncherGClass/Makefile b/gadgets/LauncherGClass/Makefile new file mode 100644 index 0000000..95064ba --- /dev/null +++ b/gadgets/LauncherGClass/Makefile @@ -0,0 +1,28 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(BOOPSITOP)/config.mk +include config.mk + +ARG_COMMON := +ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o +ARG_LIB := $(ARG_COMMON) +ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV) +ARG_PRIVATE := $(ARG_COMMON) +ARG_OBJ := $(ARG_COMMON) + +DEP_COMMON := +DEP_ALL := $(DEP_COMMON) OpenClass.o +DEP_LIB := $(DEP_COMMON) +DEP_DEBUG := $(DEP_COMMON) OpenClass.o +DEP_PRIVATE := $(DEP_COMMON) +DEP_OBJ := $(DEP_COMMON) + +include config.mk +include $(BOOPSITOP)/common/general.mk + +OpenClass.o: OpenClass.c + $(MAKE) -C $(BOOPSITOP)/common/ $@ diff --git a/gadgets/ListBox/ListBoxClass.c b/gadgets/ListBox/ListBoxClass.c new file mode 100644 index 0000000..e0c2ddf --- /dev/null +++ b/gadgets/ListBox/ListBoxClass.c @@ -0,0 +1,547 @@ +/* +** $Id: ListBoxClass.c,v 1.3 1999/01/30 13:25:03 bernie Exp $ +** +** Copyright (C) 1997,98,99 Bernardo Innocenti () +** 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef __STORM__ + #pragma header +#endif + +#define LV_GADTOOLS_STUFF +#include + +#include +#include +#include +#include + + + +/* Sliders dimensions + */ +#define VSLIDER_WIDTH 18 +#define HSLIDER_HEIGHT 18 + + +/* Per-object instance data */ +struct LBData +{ + /* struct Gadget *ThisGadget; (not used) */ + + /* Group children */ + Object *ListView; + Object *HSlider; + Object *VSlider; + Object *LVToVSliderIC; + Object *LVToHSliderIC; + + Object *Model; /* The ic object that makes our children talk to each other */ + Object *Frame; /* The frame to put around the child objects */ + + /* Frame size */ + LONG FrameWidth, FrameHeight; + + /* These two have the same meaning, but we keep both updated + * because the Rectangle structure (MinX, MinY, MaxX, MaxY) + * is more handy in some cases, while the IBox structure + * (Left/Top/Width/Height) is best for other cases. + */ + struct IBox GBox; + struct Rectangle GRect; +}; + + +/* Global class data */ +struct LBClassData +{ + Class *SliderBarGClass; + struct ClassLibrary *SliderBarBase; +}; + + + +#define SLIDERBARGCLASS_PTR ( ((struct LBClassData *)(cl->cl_UserData))->SliderBarGClass ) + + + +extern Class *ListViewClass; + + +/* Local function prototypes */ +static void LB_GMLayout (Class *cl, struct Gadget *g, struct gpLayout *msg); +static ULONG LB_OMSet (Class *cl, struct Gadget *g, struct opUpdate *msg); +static ULONG LB_OMGet (Class *cl, struct Gadget *g, struct opGet *msg); +static ULONG LB_OMNew (Class *cl, struct Gadget *g, struct opSet *msg); +static void LB_OMDispose (Class *cl, struct Gadget *g, Msg msg); + +static void CreateVSlider (Class *cl, struct Gadget *g, struct LBData *lb, struct DrawInfo *dri); +static void CreateHSlider (Class *cl, struct Gadget *g, struct LBData *lb, struct DrawInfo *dri); +static void DeleteVSlider (struct Gadget *g, struct LBData *lb); +static void DeleteHSlider (struct Gadget *g, struct LBData *lb); + + + + +/* Attribute translations for object interconnections */ + +static LONG MapLVToHSlider[] = +{ + LVA_PixelLeft, PGA_Top, + LVA_PixelWidth, PGA_Total, + LVA_PixelHVisible, PGA_Visible, + TAG_DONE +}; + +static LONG MapHSliderToLV[] = +{ + PGA_Top, LVA_PixelLeft, + TAG_DONE +}; + +static LONG MapLVToVSlider[] = +{ + LVA_PixelTop, PGA_Top, + LVA_PixelHeight, PGA_Total, + LVA_PixelVVisible, PGA_Visible, + TAG_DONE +}; + +static LONG MapVSliderToLV[] = +{ + PGA_Top, LVA_PixelTop, + TAG_DONE +}; + + + +static ULONG HOOKCALL LBDispatcher( + REG(a0, Class *cl), + REG(a2, struct Gadget *g), + REG(a1, Msg msg)) +{ + ASSERT_VALID_PTR(cl) + ASSERT_VALID_PTR(g) + ASSERT_VALID_PTR(msg) + + switch (msg->MethodID) + { + case GM_LAYOUT: + /* This method is only supported on V39 and above */ + LB_GMLayout(cl, g, (struct gpLayout *)msg); + return TRUE; + + case OM_SET: + case OM_UPDATE: + return LB_OMSet(cl, g, (struct opUpdate *)msg); + + case OM_GET: + return LB_OMGet(cl, g, (struct opGet *)msg); + + case OM_NEW: + return LB_OMNew(cl, g, (struct opSet *)msg); + + case OM_DISPOSE: + LB_OMDispose(cl, g, msg); + return TRUE; + + default: + /* Unsupported method: let our superclass's dispatcher take + * a look at it. This includes all gadget methods sent + * by Intuition: GM_RENDER, GM_HANDLEINPUT, GM_GOACTIVE and + * GM_GOINACTIVE. These methods are automatically forwarded + * to our child gadgets by the groupgclass. + */ + DB2 (DBPRINTF("ListBoxClass: passing unknown method 0x%lx to superclass\n", msg->MethodID);) + return DoSuperMethodA (cl, (Object *)g, msg); + } +} + + + +static void LB_GMLayout(Class *cl, struct Gadget *g, struct gpLayout *msg) +{ + struct LBData *lb = (struct LBData *) INST_DATA(cl, (Object *)g); + + DB(DBPRINTF("ListBoxClass: GM_LAYOUT\n");) + ASSERT_VALID_PTR(lb) + + + /* Collect new gadget size */ + GetGadgetBox(msg->gpl_GInfo, (struct ExtGadget *)g, &lv->GBox); + IBoxToRect(&lv->GBox, &lv->GRect); + + + /* Size our children accordingly */ + SetAttrs(lb->ListView, + GA_Left, lb->GBox.Left + lb->FrameWidth / 2, + GA_Top, lb->GBox.Top + lb->FrameHeight / 2, + GA_Width, lb->GBox.Width - lb->FrameWidth - VSLIDER_WIDTH, + GA_Height, lb->GBox.Height - lb->FrameHeight - HSLIDER_HEIGHT, + TAG_DONE); + + if (lb->VSlider) + SetAttrs(lb->VSlider, + GA_Left, lb->GRect.MaxX - VSLIDER_WIDTH + 1, + GA_Top, lb->GBox.Top, + GA_Width, VSLIDER_WIDTH, + GA_Height, lb->GBox.Height, + TAG_DONE); + + + /* NOTE: it seems that the groupgclass does not forward GM_LAYOUT + * to its children, so we must handle this here. + */ + DoMethodA(lb->ListView, (Msg)msg); + if (lb->VSlider) DoMethodA(lb->VSlider, (Msg)msg); +} + + + +static ULONG LB_OMSet(Class *cl, struct Gadget *g, struct opUpdate *msg) +{ + struct LBData *lb = (struct LBData *) INST_DATA(cl, (Object *)g); + + DB2(DBPRINTF("ListBoxClass: OM_SET\n");) + ASSERT_VALID_PTR(lb) + + if (lb->ListView) + /* Forward attributes to our listview */ + DoMethodA (lb->ListView, (Msg)msg); + + /* Also forward to our superclass */ + return DoSuperMethodA (cl, (Object *)g, (Msg) msg); +} + + + +static ULONG LB_OMGet(Class *cl, struct Gadget *g, struct opGet *msg) +{ + struct LBData *lb = (struct LBData *) INST_DATA(cl, (Object *)g); + + DB2(DBPRINTF("ListBoxClass: OM_GET\n");) + ASSERT_VALID_PTR(lb) + + /* Forward this method to our listview */ + return DoMethodA(lb->ListView, (Msg)msg); +} + + + +static ULONG LB_OMNew(Class *cl, struct Gadget *g, struct opSet *msg) +{ + struct LBData *lb; + struct DrawInfo *dri; + + + DB2(DBPRINTF("ListBoxClass: OM_NEW\n");) + + if (g = (struct Gadget *)DoSuperMethodA(cl, (Object *)g, (Msg)msg)) + { + /* Set the GMORE_SCROLLRASTER flag */ + if (g->Flags & GFLG_EXTENDED) + { + DB(DBPRINTF("ListBoxClass: OM_NEW: Setting GMORE_SCROLLRASTER\n");) + ((struct ExtGadget *)g)->MoreFlags |= GMORE_SCROLLRASTER; + } + + lb = (struct LBData *) INST_DATA(cl, (Object *)g); + ASSERT_VALID_PTR(lb) + + + /* Clear the object instance */ + memset(lb, 0, sizeof (struct LBData)); + + + /* Store a pointer to this object (a Gadget) in the class private + * instance. This way we can avoid passing it along to all functions. + */ + /* lb->ThisGadget = g; (not used) */ + + + /* May be NULL */ + dri = (struct DrawInfo *) GetTagData(GA_DrawInfo, NULL, msg->ops_AttrList); + + + /* Create a frame to put around us */ + if (lb->Frame = NewObject(NULL, FRAMEICLASS, + IA_EdgesOnly, TRUE, + IA_FrameType, FRAME_BUTTON, + TAG_DONE)) + { + struct IBox FrameBox, ContentsBox = { 0, 0, 0, 0 }; + + /* Ask the frame about its nominal frame width and height */ + DoMethod((Object *)lb->Frame, IM_FRAMEBOX, &ContentsBox, &FrameBox, dri, 0); + + /* Remember it later */ + lb->FrameWidth = FrameBox.Width; + lb->FrameHeight = FrameBox.Height; + } + + /* Create a model object. This will be the core of the boopsi attributes + * network used by the sub-objects to talk each other. We pass our + * initalization tags to the model so it will pick up the correct + * ICA_TARGET and ICA_MAP, if specified with NewObject(). + */ + if (lb->Model = NewObjectA(NULL, MODELCLASS, NULL)) + { + /* Create the ListView and pass all creation time attributes to it. + * Note that any GA_#? attributes are also passed to the listview, + * so it will have the same size of its container. + */ + if (lb->ListView = NewObject(ListViewClass, NULL, + GA_Image, lb->Frame, + TAG_MORE, msg->ops_AttrList)) + { + /* From now on, the groupgclass will dispose this object for us */ + DoMethod((Object *)g, OM_ADDMEMBER, lb->ListView); + + /* Connect Model to ListView */ + { + APTR icobject; + + if (icobject = NewObject(NULL, ICCLASS, + ICA_TARGET, lb->ListView, + TAG_DONE)) + if (!DoMethod(lb->Model, OM_ADDMEMBER, icobject)) + DisposeObject(icobject); + } + + /* Connect ListView to Model */ + SetAttrs(lb->ListView, + ICA_TARGET, lb->Model, + TAG_DONE); + + /* Add sliders */ + CreateVSlider(cl, g, lb, dri); + CreateHSlider(cl, g, lb, dri); + + /* Set the gadget width and height because the groupgclass + * always forces them to 0 on creation. + */ + { + struct TagItem *tag; + + if (tag = FindTagItem(GA_RelWidth, msg->ops_AttrList)) + SetAttrs(g, + GA_RelWidth, tag->ti_Data, + TAG_DONE); + else + SetAttrs (g, + GA_Width, GetTagData(GA_Width, g->Width, msg->ops_AttrList), + TAG_DONE); + + if (tag = FindTagItem(GA_RelHeight, msg->ops_AttrList)) + SetAttrs(g, + GA_RelHeight, tag->ti_Data, + TAG_DONE); + else + SetAttrs(g, + GA_Height, GetTagData (GA_Height, g->Height, msg->ops_AttrList), + TAG_DONE); + + DB2(DBPRINTF("ListBoxClass: OM_NEW: size set to L=%ld T=%ld W=%ld H=%ld\n", + g->LeftEdge, g->TopEdge, g->Width, g->Height);) + } + + /* TODO: Handle creation-time attributes */ + + return (ULONG)g; /* Return newly created istance */ + } + } + + + /* Dispose object without disturbing the dispatchers of our sub-classes, if any */ + CoerceMethod(cl, (Object *)g, OM_DISPOSE); + } + + return 0; /* Fail */ +} + + + +static void LB_OMDispose(Class *cl, struct Gadget *g, Msg msg) +{ + struct LBData *lb = (struct LBData *) INST_DATA(cl, (Object *)g); + + DB(DBPRINTF("ListBoxClass: OM_DISPOSE\n");) + ASSERT_VALID_PTR(lb) + + + DeleteHSlider(g, lb); + DeleteVSlider(g, lb); + + /* Dispose the child objects that aren't freed automatically by the modelclass. + * Note that here we are disposing the Frame before we dispose the gadgets that + * may be still using it. Everything will go well unless those classes will + * access the frame within their OM_DISPOSE methods (very silly). + */ + DisposeObject(lb->Model); + DisposeObject(lb->Frame); + + /* Our superclass will cleanup everything else now */ + DoSuperMethodA(cl, (Object *)g, (Msg) msg); + + /* From now on, our instance data is no longer available */ +} + + + +static void CreateVSlider(Class *cl, struct Gadget *g, struct LBData *lb, struct DrawInfo *dri) +{ + if (lb->VSlider = NewObject(SLIDERBARGCLASS_PTR, NULL, + GA_ID, g->GadgetID, /* Same as our ID */ + GA_DrawInfo, dri, + GA_LabelImage, lb->Frame, + PGA_Freedom, FREEVERT, + PGA_NewLook, TRUE, + PGA_Borderless, TRUE, + LAYOUTA_Orientation, LORIENT_VERT, + ICA_TARGET, lb->Model, + ICA_MAP, MapVSliderToLV, + TAG_DONE)) + { + /* From now on, the groupgclass will dispose this object for us */ + DoMethod((Object *)g, OM_ADDMEMBER, lb->VSlider); + + /* Connect Model to ListView */ + SetAttrs(lb->Model, + ICA_TARGET, lb->ListView, + TAG_DONE); + + /* Connect VSlider to Model */ + if (lb->LVToVSliderIC = NewObject(NULL, ICCLASS, + ICA_TARGET, lb->VSlider, + ICA_MAP, MapLVToVSlider, + TAG_DONE)) + if (!DoMethod(lb->Model, OM_ADDMEMBER, lb->LVToVSliderIC)) + DisposeObject(lb->LVToVSliderIC); + } +} + + + +static void CreateHSlider(Class *cl, struct Gadget *g, struct LBData *lb, struct DrawInfo *dri) +{ + /* TODO */ +} + + +static void DeleteVSlider(struct Gadget *g, struct LBData *lb) +{ + if (lb->LVToVSliderIC) + { + ASSERT_VALID_PTR(lb->LVToVSliderIC) + ASSERT_VALID_PTR(lb->Model) + + DoMethod (lb->Model, OM_REMMEMBER, lb->LVToVSliderIC); + DisposeObject (lb->LVToVSliderIC); + lb->LVToVSliderIC = NULL; + } + + if (lb->VSlider) + { + ASSERT_VALID_PTR(lb->VSlider) + + DoMethod ((Object *)g, OM_REMMEMBER, lb->VSlider); + DisposeObject (lb->VSlider); + lb->VSlider = NULL; + } +} + + + +static void DeleteHSlider(struct Gadget *g, struct LBData *lb) +{ + /* TODO */ +} + + + +Class *MakeListBoxClass(void) +{ + Class *class; + struct LBClassData *classdata; + + if (class = MakeClass(NULL, GROUPGCLASS, NULL, sizeof (struct LBData), 0)) + { + class->cl_Dispatcher.h_Entry = (ULONG (*)()) LBDispatcher; + + /* Allocate storage for global class data */ + if (classdata = AllocMem(sizeof (struct LBClassData), MEMF_PUBLIC | MEMF_CLEAR)) + { + class->cl_UserData = (ULONG) classdata; + + if (classdata->SliderBarBase = (struct ClassLibrary *) + OpenLibrary("gadgets/sliderbar.gadget", 0)) + { + classdata->SliderBarGClass = classdata->SliderBarBase->cl_Class; + ASSERT_VALID_PTR(classdata->SliderBarGClass); + + return class; + } + } + + FreeListBoxClass(class); + } + + return NULL; +} + + + +BOOL FreeListBoxClass(Class *class) +{ + struct LBClassData *classdata; + + if (class) + { + ASSERT_VALID_PTR(class) + + classdata = (struct LBClassData *)class->cl_UserData; + + /* Try to remove the class */ + if (FreeClass(class)) + { + if (classdata) + { + ASSERT_VALID_PTR(classdata) + ASSERT_VALID_PTR_OR_NULL(classdata->SliderBarBase) + + /* Cleanup global class data */ + + /* NULL is safe in CloseLibrary() since V36 */ + CloseLibrary((struct Library *)classdata->SliderBarBase); + FreeMem(classdata, sizeof (struct LBClassData)); + } + return TRUE; + } + return FALSE; + } + return TRUE; +} diff --git a/gadgets/ListBox/Makefile b/gadgets/ListBox/Makefile new file mode 100644 index 0000000..4b80f8e --- /dev/null +++ b/gadgets/ListBox/Makefile @@ -0,0 +1,29 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(TOP)/config.mk + +# +# Class specific information +# +CLASSLIB := listbox.gadget +CLASSSRC := ListBoxClass.c +DEMOSRC := +INSTALLDIR := gadgets + +# +# Class version information +# +CLASSVER := 1 +CLASSREV := 7 +CLASSDATE := (22.8.99) + +# +# variable to make the linked library version +# +PRV := + +include $(TOP)/common/general.mk diff --git a/gadgets/ListView/BoopsiLV.readme b/gadgets/ListView/BoopsiLV.readme new file mode 100644 index 0000000..1b1ad8d --- /dev/null +++ b/gadgets/ListView/BoopsiLV.readme @@ -0,0 +1,81 @@ +Short: Fast boopsi ListView class with many features (w/ src) +Author: bernardo.innocenti@usa.net (Bernardo Innocenti) +Uploader: bernardo.innocenti@usa.net (Bernardo Innocenti) +Type: dev/src +Version: 2.0 + + The ListBoxClass is a flexible and efficient boopsi gadget class which +replaces the original GadTools LISTVIEW_KIND gadget and offers a lot +more functionality. It's a subclass of the groupgclass and incorporates +several other gadgets to build a full featured listview with vertical +and horizontal scroll bars, a surrounding border and, of course, a +ListView object. + + The ListViewClass is a subclass of Intuition's gadgetclass which +builds a plain listview gadget without any border or scroll bars. +It handles selection of multiple items and it can be resized on the fly. +The GFLG_REL#? attributes are fully supported and you can even display +a list of images and other boopsi objects. Lists with multiple columns +are possible but not yet implemented. Horizontal scrolling would also +be easy to add. Usually you don't need to create objects from this class +directly because the ListBoxClass will do it for you. + + The LVDemo program demonstrates the usage of both classes. The +ListViewClass is attached to scroll bars in the window borders. +The demo is also a useful source of information on several +Intuition and boopsi topics. + + Three different binary versions are provided: + + LVDemo_Generic + Works even on plain 68000 and includes OS 2.0 support + + LVDemo_020_OS30 + Optimized for 68020, no OS 2.0 support + + LVDemo_Trace + Outputs debug messages with kprintf(), view them with + serial terminal or sushi + + + Some features: + + + Easy to use (almost a drop-in replacement for LISTVIEW_KIND) + + Can be resized and supports GREL_#? flags + + Multiple selection of items + + Notifies your `boopsi' sliders + + Multiple columns (TODO) + + Redraws quickly without clearing + (which is good for solid window sizing) + + Horizontal scrolling (TODO) + + Items can be `boopsi' images as well as texts + + Using arrays instead of exec lists + + You can use `boopsi' label images instead of plain text + + You can use your own custom rendering hook + + You can use your own item-retriving callback hook + + List titles (TODO) + + Full Keyboard control (shift, alt and control key combos + are supported) + + Asynchronous scrolling with inertia (TODO) + + OS 3.0 optimized (V39-only version also available) + + RTG friendly and optimized (no planar stuff in chunky bitmaps) + + Small code size! (less then 10KB) + + Written in C to be highly portable across compilers and CPUs + + Comes with source code with detailed comments + + Source code compiles with SAS/C, StormC and GCC + + Subclasses can be easlily derived from the base listview class + + +The source code shows how to: + + * Build a `boopsi' class on top of the gadgetclass + * Build a `boopsi' class on top of the groupgclass + * Write a `boopsi' gadget dispatcher with complex GM_DRAW + and GM_HANDLEINPUT + * Use the `boopsi' sysiclass images + * Connect `boopsi' objects together using the icclass + * Overlay the buttongclass to make a scroll button + * Create a sizeable window with sliders + * Make a C program without startup + * Correctly opening/closing libraries, windows and other + system resources diff --git a/gadgets/ListView/LVDemo.c b/gadgets/ListView/LVDemo.c new file mode 100644 index 0000000..6b5c2e4 --- /dev/null +++ b/gadgets/ListView/LVDemo.c @@ -0,0 +1,1004 @@ +/* +** $Id: LVDemo.c,v 1.3 2000/01/12 21:17:25 bernie Exp $ +** +** Introduction +** ============ +** +** This program demonstrates how to use the `boopsi' ListView gadget. +** +** The source code shows how to create a resizable window with sliders +** and how to write a custom `boopsi' class on top of the gadgetclass. +** +** +** Compiling +** ========= +** +** This project can be compiled with SAS/C 6.58 or better and +** GeekGadget's GCC 2.95.2 or better. +** You get the smallest executable with SAS/C. GCC will give +** you quite a lot of warnings with the tag calls. Don't worry about them. +** +** +** History +** ======= +** +** 0.1 (23.6.96) First try +** 1.0 (21.1.97) First alpha release +** 1.1 (24.5.97) Lotsa bugs fixed, implemented LVA_DoubleClick +** 1.2 (31.8.97) Lotsa bugs fixed, implemented LVA_Clipped +** Fixed memory leak with the test list +** 1.3 (5.9.97) Improved initial sliders notification +** Added multiple selection (LVA_DoMultiselect) +** Fixed scrolling problems in some unusual conditions +** 1.4 (8.9.97) Sets GMORE_SCROLLRASTER in OM_NEW +** Multiple demo windows showing the features of the class +** 1.5 (14.9.97) Added LVA_ItemSpacing +** Finally fixed the LVA_Clipped mode! +** +** 1.6 (2.10.97) Added StormC support +** Implemented pixel-wise vertical scrolling for clipped mode +** Reworked the class istance data and some code +** +** 1.7 (15.12.98) Added ListBoxClass +** Moved ScrollButtonClass in its own file +** Removed function OpenClass() +** Updated to latest version of VectorGlyphIClass +** +** +** Known Bugs +** ========== +** +** - This code has never been tested on V37. +** +** - Middle mouse button scrolling does not work because +** of a bug in input.device V40. +** +** +** Copyright Notice +** ================ +** +** Copyright © 1996,97,98,00 by Bernardo Innocenti . +** 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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef __STORM__ + #pragma header +#endif + +#include +#include +//#include +#include + +#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 */ + +#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 ." +}; + +#define TESTSTRINGS_CNT (sizeof (TestStrings) / sizeof (CONST_STRPTR)) + + + +LONG SAVEDS _main(void) + +/* Main program entry point. When linking without startup code, this + * must be the first function in the first object module listed on the + * linker command line. We also need to initialize SysBase and open + * all needed libraries manually. + */ +{ + struct MinList winlist; + struct MsgPort *winport; + struct Library *VectorGlyphBase = NULL; + LONG sigwait, sigrcvd; + LONG retval = RETURN_FAIL; /* = RETURN_FAIL */ + BOOL quit = FALSE; + + + /* Initialize SysBase */ + SysBase = *((struct ExecBase **)4UL); + + /* Open system libraries */ + + if ((UtilityBase = (UTILITYBASETYPE *) OpenLibrary("utility.library", 37L)) && + (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39L)) && + (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39L)) && + (LayersBase = OpenLibrary("layers.library", 39L))) + { + if ((ListViewClass = MakeListViewClass()) && +// (ListBoxClass = MakeListBoxClass()) && + (ScrollButtonClass = MakeScrollButtonClass()) && + (VectorGlyphBase = OpenLibrary("images/vectorglyph.image", 0))) + { + NEWLIST((struct List *)&winlist); + + if (winport = OpenDemoWindows((struct List *)&winlist)) + { + /* Pre-calculate the signal mask for Wait() */ + sigwait = (1 << winport->mp_SigBit) | + SIGBREAKF_CTRL_C; + + /* Now for the main loop. As you can see, it is really + * very compact. That's the magic of boopsi! :-) + */ + while (!quit) + { + /* Sleep until something interesting occurs */ + sigrcvd = Wait(sigwait); + + /* Now handle received signals */ + + /* Break signal? */ + if (sigrcvd & SIGBREAKF_CTRL_C) + quit = TRUE; + + /* IDCMP message? */ + if (sigrcvd & (1 << winport->mp_SigBit)) + { + struct IntuiMessage *msg; + + while (msg = (struct IntuiMessage *) GetMsg(winport)) + { + switch (msg->Class) + { + case IDCMP_CLOSEWINDOW: + quit = TRUE; + break; + + default: + break; + } + ReplyMsg((struct Message *) msg); + } + } + } /* End while (!quit) */ + + retval = 0; /* RETURN_OK */ + + CloseDemoWindows((struct List *)&winlist); + } + + FreeImages (); + } + + /* These cannot fail. Passing NULL is ok. */ + CloseLibrary((struct Library *)VectorGlyphBase); + FreeScrollButtonClass(ScrollButtonClass); +// FreeListBoxClass(ListBoxClass); + FreeListViewClass(ListViewClass); + } + + /* Passing NULL to CloseLibrary() was illegal in pre-V37 Exec. + * To avoid crashing when someone attempts to run this program + * on an old OS, we need to test the first library base we tried + * to open. + */ + if (UtilityBase) + { + CloseLibrary((struct Library *)LayersBase); + CloseLibrary((struct Library *)GfxBase); + CloseLibrary((struct Library *)IntuitionBase); + CloseLibrary((struct Library *)UtilityBase); + } + + return retval; +} + + + +static struct MsgPort *OpenDemoWindows(struct List *winlist) +{ + struct LVHandle *lvhandle; + struct MsgPort *winport; + + if (DiskfontBase = OpenLibrary("diskfont.library", 0L)) + { + static struct TextAttr attr = + { + "times.font", + 24, + FSB_ITALIC, + 0 + }; + + CustomFont = OpenDiskFont(&attr); + CloseLibrary(DiskfontBase); + } + + /* Setup windows shared Message Port */ + if (winport = CreateMsgPort()) + { +/* if (lvhandle = OpenLVWin(NULL, winport, + "ListBox test", + LVA_StringList, TRUE, 600, 20, 320, 128, + TAG_DONE)) + ADDTAIL(winlist, (struct Node *)lvhandle); +*/ +/* if (lvhandle = OpenLVWin(NULL, winport, + "LVA_TextFont = times/24/italic, LVA_Clipped = TRUE", + LVA_StringList, FALSE, 320, 320, 320, 64, + LVA_TextFont, CustomFont, + LVA_Clipped, TRUE, + TAG_DONE)) + ADDTAIL(winlist, (struct Node *)lvhandle); +*/ +/* if (lvhandle = OpenLVWin(NULL, winport, + "LAYOUTA_Spacing = 4", + LVA_StringList, FALSE, 256, 256, 320, 64, + LAYOUTA_Spacing, 4, + TAG_DONE)) + ADDTAIL(winlist, (struct Node *)lvhandle); +*/ +/* if (lvhandle = OpenLVWin(NULL, winport, + "GA_ReadOnly = TRUE; LVA_Selected = 3", + LVA_StringList, FALSE, 192, 192, 320, 64, + GA_ReadOnly, TRUE, + LVA_Selected, 3, + TAG_DONE)) + ADDTAIL(winlist, (struct Node *)lvhandle); +*/ + if (lvhandle = OpenLVWin(NULL, winport, + "Single selection image list, LVA_Clipped = TRUE", + LVA_ImageList, FALSE, 128, 128, 320, 128, + LVA_ItemHeight, IMAGES_HEIGHT, + LVA_Clipped, TRUE, + TAG_DONE)) + ADDTAIL(winlist, (struct Node *)lvhandle); +/* + if (lvhandle = OpenLVWin(NULL, winport, + "LVA_DoMultiSelect = TRUE; LVA_StringArray", + LVA_StringArray, FALSE, 64, 64, 320, 128, + LVA_DoMultiSelect, TRUE, + TAG_DONE)) + ADDTAIL(winlist, (struct Node *)lvhandle); +*/ +/* if (lvhandle = OpenLVWin(NULL, winport, + "Plain, single selection string list", + LVA_StringList, FALSE, 0, 20, 320, 128, + TAG_DONE)) + ADDTAIL(winlist, (struct Node *)lvhandle); +*/ + /* Abort only if no windows could be opened */ + if (IsListEmpty(winlist)) + { + DeleteMsgPort(winport); + CloseFont (CustomFont); + return NULL; + } + } + + return winport; +} + + + +static void CloseDemoWindows(struct List *winlist) +{ + struct MsgPort *winport = NULL; + struct LVHandle *lvhandle; + + while (lvhandle = (struct LVHandle *) REMHEAD(winlist)) + { + /* Safe way to close a shared IDCMP port window */ + + Forbid(); + { + struct Node *succ; + struct Message *msg; + + winport = lvhandle->Win->UserPort; + msg = (struct Message *) winport->mp_MsgList.lh_Head; + + /* Now remove any pending message from the shared IDCMP port */ + while (succ = msg->mn_Node.ln_Succ) + { + /* Since we are closing all our windows at once, + * we don't need to check to which window this + * message was addressed. + */ + REMOVE((struct Node *)msg); + ReplyMsg (msg); + msg = (struct Message *) succ; + } + + /* Keep intuition from freeing our port... */ + lvhandle->Win->UserPort = NULL; + + /* ...and from sending us any more messages. */ + ModifyIDCMP(lvhandle->Win, 0L); + } + Permit(); + + CloseLVWin(lvhandle); + } + + DeleteMsgPort(winport); /* NULL is ok */ + + if (CustomFont) + CloseFont(CustomFont); +} + + + + +static struct LVHandle *OpenLVWin(CONST_STRPTR pubscreen, + struct MsgPort *winport, CONST_STRPTR title, ULONG mode, BOOL useListBox, + ULONG left, ULONG top, ULONG width, ULONG height, ULONG moreTags, ...) +{ + struct LVHandle *lvhandle; + struct Gadget *glist; + + if (lvhandle = AllocMem(sizeof (struct LVHandle), MEMF_ANY | MEMF_CLEAR)) + { + if (lvhandle->Scr = LockPubScreen(pubscreen)) + { + /* GetScreenDrawInfo() never fails */ + lvhandle->DrawInfo = GetScreenDrawInfo(lvhandle->Scr); + + /* Set listview operating mode and ListBox flag */ + lvhandle->Mode = mode; + lvhandle->UseListBox = useListBox; + + CreateItems (lvhandle); + + if (glist = CreateLVGadgets(lvhandle, (struct TagItem *)&moreTags)) + { + if (lvhandle->Win = OpenWindowTags(NULL, + WA_Top, top, + WA_Left, left, + WA_InnerWidth, width, + WA_InnerHeight, height, + WA_PubScreen, lvhandle->Scr, + WA_Gadgets, glist, + WA_Title, title, + /* Since we are going to redraw the whole window anyway, + * we can disable backfilling to avoid flashes while + * resizing or revealing the window. + */ + WA_BackFill, useListBox ? NULL : LAYERS_NOBACKFILL, + WA_ScreenTitle, versiontag + 6, + WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM | + WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH | WFLG_NOCAREREFRESH, + WA_PubScreenFallBack, TRUE, + WA_AutoAdjust, TRUE, + WA_MinWidth, 64, + WA_MinHeight, 64, + WA_MaxWidth, -1, + WA_MaxHeight, -1, + TAG_DONE)) + { + lvhandle->Win->UserPort = winport; + ModifyIDCMP(lvhandle->Win, IDCMP_CLOSEWINDOW); + + /* We need to keep our screen locked all the time + * because we want to free the associated DrawInfo + * *after* the window has been closed and + * FreeScreenDrawInfo() wants a pointer to a *valid* + * Screen. + */ + return lvhandle; + } + + DisposeGadgets(lvhandle); + } + + FreeScreenDrawInfo(lvhandle->Scr, lvhandle->DrawInfo); + /* lvhandle->DrawInfo = NULL */ + + UnlockPubScreen(NULL, lvhandle->Scr); + } + FreeMem(lvhandle, sizeof(struct LVHandle)); + } + return NULL; +} + + + +static void CloseLVWin(struct LVHandle *lvhandle) +{ + /* Close our window. No need to reply queued messages, + * Intuition is clever enough to care about this for us. + */ + CloseWindow(lvhandle->Win); + DisposeGadgets(lvhandle); + UnlockPubScreen(NULL, lvhandle->Scr); + + FreeVec(lvhandle->SelectArray); /* NULL is ok */ + + if ((lvhandle->Mode == LVA_StringList) || (lvhandle->Mode == LVA_ImageList)) + { + struct Node *node; + + /* Free the test list */ + while (node = REMHEAD (&lvhandle->TestList)) + { + if (lvhandle->Mode == LVA_ImageList) + DisposeObject ((Object *)node->ln_Name); + FreeMem (node, sizeof (struct Node)); + } + } + + FreeMem (lvhandle, sizeof (struct LVHandle)); +} + + + +/* Diagram of object interconnections for the ListView window + * ========================================================== + * + * ScrollButtonClass objects + * +----------+ +------------+ +------------+ +-------------+ + * | UpButton | | DownButton | | LeftButton | | RightButton | + * +----------+ +------------+ +------------+ +-------------+ + * | GA_ID = | GA_ID = | GA_ID = | GA_ID = + * | LVA_MoveUp | LVA_MoveDown | LVA_MoveLeft | LVA_MoveRight + * | | | | + * | +----------+ | | + * | | +-----------------------+ | + * | | | +------------------------------------+ + * | | | | propgclass object icclass object + * | | | | +-----------+ +--------------+ + * | | | | | HSlider |<-----| PIPToHSlider | + * | | | | +-----------+ +--------------+ + * | | | | PGA_Top = | ^ LVA_Top = PGA_Top + * | | | | LVA_Left | | LVA_Visible = PGA_Visible + * | | | | | | + * V V V V V | + * +-----------+ *********** | + * | |-------->* *------------+ + * | ListView | * Model * + * | |<--------* *------------+ + * +-----------+ *********** | + * ^ | + * PGA_Top = | | + * LVA_Top | V icclass object + * +-----------+ +--------------+ + * | VSlider |<-----| PIPToVSlider | + * +-----------+ +--------------+ + * propgclass object LVA_Top = PGA_Top + * LVA_Visible = PGA_Visible + */ + +static struct Gadget *CreateLVGadgets(struct LVHandle *lvhandle, + struct TagItem *moreTags) +{ + struct Screen *scr = lvhandle->Scr; + ULONG SizeWidth = 18, SizeHeight = 11; /* Default size */ + struct Image *SizeImage; + + /* Create a size image to get its... uhm... size */ + if (SizeImage = NewObject(NULL, SYSICLASS, + SYSIA_Which, SIZEIMAGE, + SYSIA_DrawInfo, lvhandle->DrawInfo, + TAG_DONE)) + { + /* Get size gadget geometry */ + GetAttr(IA_Width, SizeImage, &SizeWidth); + GetAttr(IA_Height, SizeImage, &SizeHeight); + + /* And then get rid of it... */ + DisposeObject(SizeImage); + } + + +/* if (lvhandle->UseListBox) + { + lvhandle->Gad[GAD_LV] = NewObject(ListBoxClass, NULL, + GA_ID, GAD_LV, + GA_Left, scr->WBorLeft, + GA_Top, scr->WBorTop + scr->Font->ta_YSize + 1, + GA_RelWidth, - SizeWidth - scr->WBorLeft, + GA_RelHeight, - (scr->WBorTop + scr->Font->ta_YSize + SizeHeight + 1), + GA_DrawInfo, lvhandle->DrawInfo, + lvhandle->Mode, lvhandle->Items, + LVA_Total, lvhandle->Total, + LVA_SelectArray, lvhandle->SelectArray, + TAG_MORE, moreTags); + + return lvhandle->Gad[GAD_LV]; + } +*/ + + /* Code to create normal ListView class and its gadgets */ + + + /* No need to check this: in case of failure we would just + * get no images in the scroll buttons, but we can still try + * to open our window anyway. + */ + CreateImages(lvhandle->DrawInfo); + + if (lvhandle->Model = NewObjectA(NULL, MODELCLASS, NULL)) + if (lvhandle->Gad[GAD_LV] = NewObject(ListViewClass, NULL, + GA_ID, GAD_LV, + GA_Left, scr->WBorLeft, + GA_Top, scr->WBorTop + scr->Font->ta_YSize + 1, + GA_RelWidth, - SizeWidth - scr->WBorLeft, + GA_RelHeight, - (scr->WBorTop + scr->Font->ta_YSize + SizeHeight + 1), + GA_DrawInfo, lvhandle->DrawInfo, + ICA_TARGET, lvhandle->Model, + lvhandle->Mode, lvhandle->Items, + LVA_Total, lvhandle->Total, + LVA_SelectArray, lvhandle->SelectArray, + TAG_MORE, moreTags)) + if (lvhandle->Gad[GAD_VSLIDER] = NewObject(NULL, PROPGCLASS, + GA_ID, GAD_VSLIDER, + GA_Previous, lvhandle->Gad[GAD_LV], + GA_RelRight, - SizeWidth + 5, + GA_Top, scr->WBorTop + scr->Font->ta_YSize + 2, + GA_Width, SizeWidth - 8, + GA_RelHeight, - (scr->WBorTop + scr->Font->ta_YSize + + SizeHeight + ImgHeight[IMG_DOWN] + ImgHeight[IMG_UP] + 4), + GA_RightBorder, TRUE, + GA_DrawInfo, lvhandle->DrawInfo, + PGA_Freedom, FREEVERT, + PGA_Borderless, ((lvhandle->DrawInfo->dri_Flags & DRIF_NEWLOOK) && + (lvhandle->DrawInfo->dri_Depth != 1)), + PGA_NewLook, TRUE, + ICA_TARGET, lvhandle->Model, + ICA_MAP, MapVSliderToLV, + TAG_DONE)) + if (lvhandle->Gad[GAD_HSLIDER] = NewObject(NULL, PROPGCLASS, + GA_ID, GAD_HSLIDER, + GA_Previous, lvhandle->Gad[GAD_VSLIDER], + GA_RelBottom, - SizeHeight + ((SizeHeight > 15) ? 4 : 3), + GA_Left, scr->WBorLeft, + GA_Height, SizeHeight - ((SizeHeight > 15) ? 6 : 4), + GA_RelWidth, - (SizeWidth + ImgWidth[IMG_RIGHT] + ImgWidth[IMG_LEFT] + scr->WBorLeft + 2), + GA_BottomBorder,TRUE, + GA_DrawInfo, lvhandle->DrawInfo, + PGA_Freedom, FREEHORIZ, + PGA_Borderless, ((lvhandle->DrawInfo->dri_Flags & DRIF_NEWLOOK) && + (lvhandle->DrawInfo->dri_Depth != 1)), + PGA_NewLook, TRUE, + ICA_TARGET, lvhandle->Model, + ICA_MAP, MapHSliderToLV, + TAG_DONE)) + if (lvhandle->Gad[GAD_UPBUTTON] = NewObject(ScrollButtonClass, NULL, + GA_ID, GAD_UPBUTTON, + GA_Previous, lvhandle->Gad[GAD_HSLIDER], + GA_RelBottom, - SizeHeight - ImgHeight[IMG_DOWN] - ImgHeight[IMG_UP] + 1, + GA_RelRight, - ImgWidth[IMG_DOWN] + 1, + GA_RightBorder, TRUE, + GA_DrawInfo, lvhandle->DrawInfo, + GA_Image, Img[IMG_UP], + ICA_TARGET, lvhandle->Gad[GAD_LV], + ICA_MAP, MapUpButtonToLV, + TAG_DONE)) + if (lvhandle->Gad[GAD_DOWNBUTTON] = NewObject(ScrollButtonClass, NULL, + GA_ID, GAD_DOWNBUTTON, + GA_Previous, lvhandle->Gad[GAD_UPBUTTON], + GA_RelBottom, - SizeHeight - ImgHeight[IMG_DOWN] + 1, + GA_RelRight, - ImgWidth[IMG_DOWN] + 1, + GA_RightBorder, TRUE, + GA_DrawInfo, lvhandle->DrawInfo, + GA_Image, Img[IMG_DOWN], + ICA_TARGET, lvhandle->Gad[GAD_LV], + ICA_MAP, MapDownButtonToLV, + TAG_DONE)) + if (lvhandle->Gad[GAD_LEFTBUTTON] = NewObject(ScrollButtonClass, NULL, + GA_ID, GAD_LEFTBUTTON, + GA_Previous, lvhandle->Gad[GAD_DOWNBUTTON], + GA_RelBottom, - ImgHeight[IMG_LEFT] + 1, + GA_RelRight, - SizeWidth - ImgWidth[IMG_RIGHT] - ImgWidth[IMG_LEFT] + 1, + GA_BottomBorder,TRUE, + GA_DrawInfo, lvhandle->DrawInfo, + GA_Image, Img[IMG_LEFT], + ICA_TARGET, lvhandle->Gad[GAD_LV], + ICA_MAP, MapLeftButtonToLV, + TAG_DONE)) + if (lvhandle->Gad[GAD_RIGHTBUTTON] = NewObject(ScrollButtonClass, NULL, + GA_ID, GAD_RIGHTBUTTON, + GA_Previous, lvhandle->Gad[GAD_LEFTBUTTON], + GA_RelBottom, - ImgHeight[IMG_RIGHT] + 1, + GA_RelRight, - SizeWidth - ImgWidth[IMG_RIGHT] + 1, + GA_BottomBorder,TRUE, + GA_DrawInfo, lvhandle->DrawInfo, + GA_Image, Img[IMG_RIGHT], + ICA_TARGET, lvhandle->Gad[GAD_LV], + ICA_MAP, MapRightButtonToLV, + TAG_DONE)) + { + APTR icobject; + + /* Connect VSlider to Model */ + + if (icobject = NewObject(NULL, ICCLASS, + ICA_TARGET, lvhandle->Gad[GAD_VSLIDER], + ICA_MAP, MapLVToVSlider, + TAG_DONE)) + if (!DoMethod(lvhandle->Model, OM_ADDMEMBER, icobject)) + DisposeObject (icobject); + + /* Connect HSlider to Model */ + + if (icobject = NewObject(NULL, ICCLASS, + ICA_TARGET, lvhandle->Gad[GAD_HSLIDER], + ICA_MAP, MapLVToHSlider, + TAG_DONE)) + if (!DoMethod(lvhandle->Model, OM_ADDMEMBER, icobject)) + DisposeObject (icobject); + + /* Connect Model to ListView */ + + SetAttrs(lvhandle->Model, + ICA_TARGET, lvhandle->Gad[GAD_LV], + TAG_DONE); + + return lvhandle->Gad[GAD_LV]; + } + DisposeGadgets(lvhandle); + + return NULL; +} + + + +static void DisposeGadgets(struct LVHandle *lvhandle) +{ + ULONG i; + + for (i = 0; i < GAD_COUNT; i++) + { + DisposeObject(lvhandle->Gad[i]); + /* lvhandle->Gad[i] = NULL; */ + } + + /* Freeing the Model will also free its two targets */ + DisposeObject(lvhandle->Model); + /* lvhandle->Model = NULL */ +} + + + +static void CreateItems(struct LVHandle *lvhandle) +{ + if ((lvhandle->Mode == LVA_StringList) || (lvhandle->Mode == LVA_ImageList)) + { + struct Node *node; + ULONG i, cnt; + + + if (lvhandle->Mode == LVA_StringList) + cnt = TESTSTRINGS_CNT; + else /* LVA_ImageList */ + cnt = VG_IMGCOUNT * 8; + + + /* Build a list of nodes to test the list */ + + NEWLIST(&lvhandle->TestList); + + for (i = 0; i < cnt; i++) + { + if (node = AllocMem(sizeof (struct Node), MEMF_PUBLIC)) + { + if (lvhandle->Mode == LVA_StringList) + node->ln_Name = TestStrings[i]; + else + node->ln_Name = (STRPTR) NewObject(NULL, VECTORGLYPHCLASS, + SYSIA_Which, i % VG_IMGCOUNT, + SYSIA_DrawInfo, lvhandle->DrawInfo, + IA_Width, IMAGES_WIDTH, + IA_Height, IMAGES_HEIGHT, + TAG_DONE); + + /* Unselect all items */ + node->ln_Type = 0; + + ADDTAIL (&lvhandle->TestList, node); + + lvhandle->Total++; + } + } + + lvhandle->Items = &lvhandle->TestList; + } + else if (lvhandle->Mode == LVA_StringArray) + { + lvhandle->Items = TestStrings; + lvhandle->Total = TESTSTRINGS_CNT; + lvhandle->SelectArray = AllocVec (TESTSTRINGS_CNT * sizeof (ULONG), + MEMF_CLEAR | MEMF_PUBLIC); + } + else /* (lvhandle->Mode == LVA_ImageArray) */ + { + lvhandle->Items = NULL; /* No items */ + lvhandle->Total = -1; /* Unknown */ + } +} + + + +static void CreateImages(struct DrawInfo *dri) + +/* Create 4 arrow images for the window scroll buttons. + * + * Why bother checking for failure? The arrow images are not + * life critical in our program... + */ +{ + static ULONG imagetypes[IMG_COUNT] = { UPIMAGE, DOWNIMAGE, LEFTIMAGE, RIGHTIMAGE }; + ULONG i; + + for (i = 0; i < IMG_COUNT; i++) + if (!Img[i]) + if (Img[i] = (struct Image *)NewObject (NULL, SYSICLASS, + SYSIA_Which, imagetypes[i], + SYSIA_DrawInfo, dri, + TAG_DONE)) + { + /* Ask image width and height */ + GetAttr(IA_Width, Img[i], &ImgWidth[i]); + GetAttr(IA_Height, Img[i], &ImgHeight[i]); + } +} + + + +static void FreeImages (void) +{ + ULONG i; + + for (i = 0; i < IMG_COUNT; i++) + DisposeObject((APTR)Img[i]); /* DisposeObject(NULL) is safe */ +} diff --git a/gadgets/ListView/ListViewClass.c b/gadgets/ListView/ListViewClass.c new file mode 100644 index 0000000..5a1b51f --- /dev/null +++ b/gadgets/ListView/ListViewClass.c @@ -0,0 +1,2238 @@ +/* +** $Id: ListViewClass.c,v 1.4 2000/01/12 21:18:06 bernie Exp $ +** +** Copyright (C) 1996,97,99 Bernardo Innocenti +** 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define LV_GADTOOLS_STUFF +#include + +#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 */ + 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 */ + #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 to . No sanity checks are performed + * to ensure that all items between and are really visible. + */ +{ + struct lvDrawItem lvdi; + LONG selected; + + + ASSERT_VALID_PTR(lv) + ASSERT_VALID_PTR(msg) + ASSERT(first <= last) + ASSERT(last < lv->Total) + + DB2( DBPRINTF (" RedrawItems (first = %ld, last = %ld)\n", first, last);) + + + lvdi.lvdi_Current = first; + lvdi.lvdi_Items = lv->Items; + lvdi.lvdi_RastPort = msg->gpr_RPort; + lvdi.lvdi_DrawInfo = msg->gpr_GInfo->gi_DrInfo; + lvdi.lvdi_Flags = lv->Flags; + + GetItemBounds (lv, &lvdi.lvdi_Bounds, first); + + if (!item) + { + lvdi.lvdi_MethodID = LV_GETITEM; + item = lv->GetItemFunc (lv->CallBack, NULL, (struct lvGetItem *)&lvdi); + } + + if (lv->DrawBeginFunc) + { + lvdi.lvdi_MethodID = LV_DRAWBEGIN; + lv->DrawBeginFunc (lv->CallBack, item, (struct lvDrawBegin *)&lvdi); + } + + for (;;) + { + if (lv->Flags & LVF_DOMULTISELECT) + { + if (lv->SelectArray) + /* Array selection */ + selected = lv->SelectArray[lvdi.lvdi_Current]; + else + if (lv->Flags & LVF_LIST) + /* Node selection */ + selected = (((struct Node *)item)->ln_Type); + else + selected = 0; + } + else + /* Single selection */ + selected = (lvdi.lvdi_Current == lv->Selected); + + lvdi.lvdi_State = selected ? LVR_SELECTED : LVR_NORMAL; + + lvdi.lvdi_MethodID = LV_DRAW; + lv->DrawItemFunc (lv->CallBack, item, &lvdi); + + if (++lvdi.lvdi_Current > last) + break; + + lvdi.lvdi_MethodID = LV_GETNEXT; + item = lv->GetNextFunc (lv->CallBack, item, (struct lvGetNext *)&lvdi); + + lvdi.lvdi_Bounds.MinY += lv->ItemHeight + lv->Spacing; + lvdi.lvdi_Bounds.MaxY += lv->ItemHeight + lv->Spacing; + } + + if (lv->DrawEndFunc) + { + lvdi.lvdi_MethodID = LV_DRAWEND; + lv->DrawEndFunc (lv->CallBack, item, (struct lvDrawEnd *)&lvdi); + } +} + + + +static void LV_GMRender(Class *cl, struct Gadget *g, struct gpRender *msg) +{ + struct LVData *lv = INST_DATA (cl, g); + struct RastPort *rp = msg->gpr_RPort; + + ASSERT_VALID_PTR(lv) + ASSERT_VALID_PTR(rp) + + DB2 (DBPRINTF ("GM_RENDER: msg->gpr_Redraw = %s\n", + (msg->gpr_Redraw == GREDRAW_TOGGLE) ? "GREDRAW_TOGGLE" : + ((msg->gpr_Redraw == GREDRAW_REDRAW) ? "GREDRAW_REDRAW" : + ((msg->gpr_Redraw == GREDRAW_UPDATE) ? "GREDRAW_UPDATE" : + "*** Unknown GREDRAW mode ***")) );) + + + if (lv->Flags & LVF_DONTDRAW) + return; + + if (lv->Items && lv->Visible) + { + struct TextFont *oldfont = NULL; + struct Region *oldregion; + BOOL layerupdating = FALSE; + + if (rp->Font != lv->Font) + { + oldfont = rp->Font; + SetFont (rp, lv->Font); + } + + if (lv->ClipRegion) + { + ASSERT_VALID_PTR(lv->ClipRegion) + ASSERT_VALID_PTR(msg->gpr_RPort->Layer) + DB2(DBPRINTF ("Calling InstallClipRegion()...\n");) + + /* Workaround for installing clip regions in + * updating layers within a boopsi gadget dispatcher, + * as suggested by Jochen Bechen. + */ +// if (msg->gpr_RPort->Layer->Flags & LAYERUPDATING) +// { +// layerupdating = TRUE; +// EndUpdate(msg->gpr_RPort->Layer, FALSE); +// } + oldregion = InstallClipRegion(rp->Layer, lv->ClipRegion); + } + + switch (msg->gpr_Redraw) + { + case GREDRAW_TOGGLE: /* Toggle selected item */ + { + BOOL drawnew = (lv->Selected >= lv->Top) && (lv->Selected < lv->Top + lv->Visible), + drawold = (lv->OldSelected >= lv->Top) && (lv->OldSelected < lv->Top + lv->Visible); + + if (drawold || drawnew) + { + struct lvDrawItem lvdi; + lvdi.lvdi_Items = lv->Items; + lvdi.lvdi_RastPort = rp; + lvdi.lvdi_DrawInfo = msg->gpr_GInfo->gi_DrInfo; + lvdi.lvdi_Flags = lv->Flags; + + + if (lv->DrawBeginFunc) + { + lvdi.lvdi_MethodID = LV_DRAWBEGIN; + lv->DrawBeginFunc(lv->CallBack, NULL, (struct lvDrawBegin *)&lvdi); + } + + lvdi.lvdi_MethodID = LV_DRAW; + + if (drawnew) + { + GetItemBounds (lv, &lvdi.lvdi_Bounds, lv->Selected); + lvdi.lvdi_State = IsItemSelected (lv, lv->SelectedPtr, lv->Selected) ? + LVR_SELECTED : LVR_NORMAL; + lvdi.lvdi_Current = lv->Selected; + + lv->DrawItemFunc (lv->CallBack, lv->SelectedPtr, &lvdi); + } + + if (drawold) + { + GetItemBounds (lv, &lvdi.lvdi_Bounds, lv->OldSelected); + lvdi.lvdi_State = IsItemSelected (lv, lv->OldSelectedPtr, lv->OldSelected) ? + LVR_SELECTED : LVR_NORMAL; + lvdi.lvdi_Current = lv->OldSelected; + + lv->DrawItemFunc (lv->CallBack, lv->OldSelectedPtr, &lvdi); + } + + if (lv->DrawEndFunc) + { + lvdi.lvdi_MethodID = LV_DRAWEND; + lv->DrawEndFunc (lv->CallBack, NULL, (struct lvDrawEnd *)&lvdi); + } + } + + lv->OldSelected = lv->Selected; + lv->OldSelectedPtr = lv->SelectedPtr; + + break; + } + + case GREDRAW_REDRAW: /* Redraw everything */ + { + LONG ycoord; + + /* Set the background pen */ + SetAPen (rp, msg->gpr_GInfo->gi_DrInfo->dri_Pens[BACKGROUNDPEN]); + /* SetAPen (rp, -1); Used to debug clearing code */ + + /* Now clear the spacing between the items */ + if (lv->Spacing && lv->Items && lv->Visible) + { + LONG i, lastitem; + + ycoord = lv->GRect.MinY + lv->ItemHeight; + lastitem = min (lv->Visible, lv->Total - lv->Top) - 1; + + for (i = 0 ; i < lastitem; i++) + { + RectFill (rp, lv->GRect.MinX, ycoord, + lv->GRect.MaxX, ycoord + lv->Spacing - 1); + + ycoord += lv->ItemHeight + lv->Spacing; + } + } + else + ycoord = lv->GRect.MinY + min (lv->Visible, lv->Total - lv->Top) + * lv->ItemHeight; + + /* Now let's clear bottom part of gadget */ + RectFill (rp, lv->GRect.MinX, ycoord, + lv->GRect.MaxX, lv->GRect.MaxY); + + /* Finally, draw the items */ + RedrawItems (lv, msg, lv->Top, + min (lv->Top + lv->Visible, lv->Total) - 1, lv->TopPtr); + + break; + } + + case GREDRAW_UPDATE: /* Scroll ListView */ + { + LONG scroll_dy, scroll_height; + + if (lv->ClipRegion) + { + /* Calculate scrolling amount in pixels */ + if (!(scroll_dy = lv->PixelTop - lv->OldPixelTop)) + /* Do nothing if called improperly */ + break; + + /* Scroll everything */ + scroll_height = lv->GBox.Height; + } + else + { + if (!(lv->Top - lv->OldTop)) + /* Do nothing if called improperly */ + break; + + /* Calculate scrolling amount in pixels */ + scroll_dy = (lv->Top - lv->OldTop) * (lv->ItemHeight + lv->Spacing); + + /* Only scroll upto last visible item */ + scroll_height = lv->Visible * (lv->ItemHeight + lv->Spacing) - lv->Spacing; + } + + if (abs(scroll_dy) > lv->MaxScroll) + { + /* Redraw everything when listview has been scrolled too much */ + RedrawItems (lv, msg, lv->Top, + min (lv->Top + lv->Visible, lv->Total) - 1, lv->TopPtr); + } + else + { + /* Optimize scrolling on planar displays if possible */ + SetMaxPen (rp, lv->MaxPen); + + /* We use ClipBlit() to scroll the listview because it doesn't clear + * the scrolled region like ScrollRaster() would do. Unfortunately, + * ClipBlit() does not scroll along the damage regions, so we also + * call ScrollRaster() with the mask set to 0, which will scroll the + * layer damage regions without actually modifying the display. + */ + + if (scroll_dy > 0) /* Scroll Down */ + { + ClipBlit (rp, lv->GBox.Left, lv->GBox.Top + scroll_dy, + rp, lv->GBox.Left, lv->GBox.Top, + lv->GBox.Width, scroll_height - scroll_dy, + 0x0C0); + + if (lv->ClipRegion) + { + /* NOTE: We subtract 1 pixel to avoid an exact division which would + * render one item beyond the end when the slider is dragged + * all the way down. + */ + RedrawItems(lv, msg, + (lv->OldPixelTop + lv->GBox.Height) / (lv->ItemHeight + lv->Spacing), + (lv->PixelTop + lv->GBox.Height - 1) / (lv->ItemHeight + lv->Spacing), + NULL); + } + else + RedrawItems(lv, msg, + lv->Visible + lv->OldTop, + lv->Visible + lv->Top - 1, + NULL); + } + else /* Scroll Up */ + { + ClipBlit(rp, lv->GBox.Left, lv->GBox.Top, + rp, lv->GBox.Left, lv->GBox.Top - scroll_dy, + lv->GBox.Width, scroll_height + scroll_dy, + 0x0C0); + + + if (lv->ClipRegion) + RedrawItems(lv, msg, + lv->PixelTop / (lv->ItemHeight + lv->Spacing), + lv->OldPixelTop / (lv->ItemHeight + lv->Spacing), + NULL); + else + RedrawItems(lv, msg, + lv->Top, + lv->OldTop - 1, + lv->TopPtr); + } + + /* This will scroll the layer damage regions without actually + * scrolling the display, but only if our layer really needs it. + */ + if (NeedZeroScrollRaster(rp->Layer)) + { + UBYTE oldmask = rp->Mask; /* Would GetRPAttr() be better? */ + + DB2 (DBPRINTF (" Calling ScrollRaster()\n");) + SetWriteMask(rp, 0); + ScrollRaster(rp, 0, scroll_dy, + lv->GRect.MinX, lv->GRect.MinY, + lv->GRect.MaxX, + lv->GRect.MaxY); + + SetWriteMask(rp, oldmask); + } + + /* Restore MaxPen in our RastPort */ + SetMaxPen(rp, -1); + } + + /* Update OldTop to the current Top item and + * OldPixelTop to the current PixelTop position. + */ + lv->OldTop = lv->Top; + lv->OldPixelTop = lv->PixelTop; + + break; + } + + default: + break; + } + + if (lv->ClipRegion) + { + /* Restore old clipping region in our layer */ + DB2 (DBPRINTF ("GM_RENDER: Resoring old ClipRegion\n");) + ASSERT_VALID_PTR_OR_NULL(oldregion) + InstallClipRegion (rp->Layer, oldregion); + if (layerupdating) + BeginUpdate(msg->gpr_RPort->Layer); + } + + if (oldfont) + SetFont (rp, oldfont); + } + else if (msg->gpr_Redraw == GREDRAW_REDRAW) + { + /* Clear all gadget contents */ + SetAPen (rp, msg->gpr_GInfo->gi_DrInfo->dri_Pens[BACKGROUNDPEN]); + RectFill (rp, lv->GRect.MinX, lv->GRect.MinY, lv->GRect.MaxX, lv->GRect.MaxY); + } + + + /* Last but not least, draw the frame if we have one associated */ + + if ((msg->gpr_Redraw == GREDRAW_REDRAW) && GadgetHasFrame(g)) + { + DB2 (DBPRINTF("ListViewClass: Rendering my own frame\n");) + + DoMethod((Object *)g->GadgetRender, IM_DRAWFRAME, + msg->gpr_RPort, /* imp_RPort */ + (lv->FrameBox.Left << 16) | (lv->FrameBox.Top), /* imp_Offset */ + IDS_NORMAL, /* imp_State */ + msg->gpr_GInfo->gi_DrInfo, /* imp_DrInfo */ + (lv->FrameBox.Width << 16) | (lv->FrameBox.Height));/* imp_Dimensions */ + } +} + + + +static ULONG LV_GMGoActive(Class *cl, struct Gadget *g, struct gpInput *msg) +{ + struct LVData *lv = INST_DATA (cl, g); + + ASSERT_VALID_PTR(lv) + DB2 (DBPRINTF ("GM_GOACTIVE: gpi_IEvent = $%lx\n", msg->gpi_IEvent);) + + + if (!lv->Items) + return GMR_NOREUSE; + + g->Flags |= GFLG_SELECTED; + + /* Do not process InputEvent when the gadget has been + * activated by ActivateGadget(). + */ + if (!msg->gpi_IEvent) + return GMR_MEACTIVE; + + /* Note: The input event that triggered the gadget + * activation (usually a mouse click) should be passed + * to the GM_HANDLEINPUT method, so we fall down to it. + */ + return LV_GMHandleInput (cl, g, msg); +} + + + +INLINE LONG ItemHit (struct LVData *lv, UNUSED(WORD x), WORD y) + +/* Determine which item has been hit with gadget relative + * coordinates x and y. + */ +{ + return ((y + lv->PixelTop) / (lv->ItemHeight + lv->Spacing)); +} + + + +static ULONG LV_GMHandleInput (Class *cl, struct Gadget *g, struct gpInput *msg) +{ + struct LVData *lv = INST_DATA (cl, g); + struct InputEvent *ie = msg->gpi_IEvent; + ULONG result = GMR_MEACTIVE; + + ASSERT_VALID_PTR(lv) +/* DB2 (DBPRINTF ("GM_HANDLEINPUT: ie_Class = $%lx, ie->ie_Code = $%lx, " + "gpi_Mouse.X = %ld, gpi_Mouse.Y = %ld\n", + ie->ie_Class, ie->ie_Code, msg->gpi_Mouse.X, msg->gpi_Mouse.Y);) +*/ + switch (ie->ie_Class) + { + case IECLASS_RAWKEY: + { + LONG tags[5]; + LONG pos; + + switch (ie->ie_Code) + { + case CURSORUP: + if ((lv->Flags & LVF_READONLY) || (ie->ie_Qualifier & IEQUALIFIER_CONTROL)) + { + if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) + pos = lv->Top - lv->Visible / 2; + else + pos = lv->Top - 1; + + if (pos < 0) pos = 0; + + tags[0] = LVA_Top; + tags[1] = pos; + tags[2] = TAG_DONE; + } + else + { + if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) + pos = 0; + else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) + pos = lv->Selected - lv->Visible + 1; + else + pos = lv->Selected - 1; + + if (pos < 0) pos = 0; + + tags[0] = LVA_Selected; + tags[1] = pos; + tags[2] = LVA_MakeVisible; + tags[3] = pos; + tags[4] = TAG_DONE; + } + break; + + case CURSORDOWN: + if ((lv->Flags & LVF_READONLY) || (ie->ie_Qualifier & IEQUALIFIER_CONTROL)) + { + if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) + pos = lv->Top + lv->Visible / 2; + else + pos = lv->Top + 1; + + tags[0] = LVA_Top; + tags[1] = pos; + tags[2] = TAG_DONE; + } + else + { + if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) + pos = lv->Total - 1; + else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) + pos = lv->Selected + lv->Visible - 1; + else + pos = lv->Selected + 1; + + tags[0] = LVA_Selected; + tags[1] = pos; + tags[2] = LVA_MakeVisible; + tags[3] = pos; + tags[4] = TAG_DONE; + } + break; + + default: + tags[0] = TAG_DONE; + + } /* End switch (ie->ie_Code) */ + + if (tags[0] != TAG_DONE) + DoMethod ((Object *)g, OM_UPDATE, tags, msg->gpi_GInfo, + (ie->ie_Qualifier & IEQUALIFIERB_REPEAT) ? OPUF_INTERIM : 0); + + break; + } + + case IECLASS_RAWMOUSE: + { + LONG selected; + + switch (ie->ie_Code) + { + case SELECTDOWN: + + /* Check for click outside gadget box */ + + if ((msg->gpi_Mouse.X < 0) || + (msg->gpi_Mouse.X >= lv->GBox.Width) || + (msg->gpi_Mouse.Y < 0) || + (msg->gpi_Mouse.Y >= lv->GBox.Height)) + { + result = GMR_REUSE; + break; + } + + /* Start dragging mode */ + lv->Flags |= LVF_DRAGGING; + + if (lv->Flags & LVF_READONLY) + break; + + /* Select an item */ + selected = ItemHit (lv, msg->gpi_Mouse.X, msg->gpi_Mouse.Y); + + /* No action when selecting over blank space in the bottom */ + if ((selected < 0) || (selected >= lv->Total)) + break; + + /* Backup current selection for RMB undo */ + lv->BackupSelected = lv->Selected; + lv->BackupPixelTop = lv->PixelTop; + + if (selected == lv->Selected) + { + /* Check for double click */ + if (DoubleClick (lv->DoubleClickSecs, lv->DoubleClickMicros, + ie->ie_TimeStamp.tv_secs, ie->ie_TimeStamp.tv_micro)) + UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0, + LVA_DoubleClick, selected, + TAG_DONE); + } + + if (lv->Flags & LVF_DOMULTISELECT) + /* Setup for multiple items drag selection */ + lv->DragSelect = IsItemSelected (lv, NULL, selected) ? + LVA_DeselectItem : LVA_SelectItem; + else if (g->Activation & GACT_TOGGLESELECT) + { + /* Setup for single item toggle */ + lv->DragSelect = LVA_Selected; + if (selected == lv->Selected) + selected = ~0; + } + else /* Single selection */ + /* Setup for single item drag selection */ + lv->DragSelect = LVA_Selected; + + UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0, + lv->DragSelect, selected, + TAG_DONE); + + /* Save double click info */ + lv->DoubleClickSecs = ie->ie_TimeStamp.tv_secs; + lv->DoubleClickMicros = ie->ie_TimeStamp.tv_micro; + break; + + case MENUDOWN: + /* Undo selection & position when RMB is pressed */ + if (lv->Flags & (LVF_DRAGGING | LVF_SCROLLING)) + { + /* Stop dragging and scrolling modes */ + lv->Flags &= ~(LVF_DRAGGING | LVF_SCROLLING); + + if ((lv->BackupSelected != lv->Selected) || + (lv->BackupPixelTop != lv->PixelTop)) + { + UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0, + (lv->Flags & LVF_READONLY) ? + TAG_IGNORE : LVA_Selected, lv->BackupSelected, + LVA_PixelTop, lv->BackupPixelTop, + TAG_DONE); + } + } + else + /* Deactivate gadget on menu button press */ + result = GMR_REUSE; + + break; + + case MIDDLEDOWN: + /* Argh, input.device never sends this event in V40! */ + DB1 (DBPRINTF ("MIDDLEDOWN received\n");) + + /* Start MMB scrolling */ + lv->BackupPixelTop = lv->PixelTop; + lv->BackupSelected = lv->Selected; + lv->MiddleMouseY = msg->gpi_Mouse.Y; + lv->Flags |= LVF_DRAGGING; + break; + + case SELECTUP: + + /* Stop dragging mode */ + lv->Flags &= ~LVF_DRAGGING; + + if (g->Activation & GACT_RELVERIFY) + { + /* Send IDCMP_GADGETUP message to our parent window */ + msg->gpi_Termination = &lv->Selected; + result = GMR_NOREUSE | GMR_VERIFY; + } + break; + + case MIDDLEUP: + /* Argh, input.device never sends this event in V40! */ + DB1 (DBPRINTF ("scrolling off\n");) + + /* Stop MMB scrolling */ + lv->Flags &= ~LVF_SCROLLING; + break; + + default: /* Mouse moved */ + + /* Holding LMB? */ + if (lv->Flags & LVF_DRAGGING) + { + /* Select an item */ + selected = ItemHit (lv, msg->gpi_Mouse.X, msg->gpi_Mouse.Y); + + /* Moved over another item inside the currently displayed list? */ + if ((selected != lv->Selected) && !(lv->Flags & LVF_READONLY) + && (selected >= lv->Top) && (selected < lv->Top + lv->Visible)) + { + /* Single selection */ + + /* Call our OM_UPDATE method to change the attributes. + * This will also send notification to targets and + * update the contents of the gadget. + */ + UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0, + lv->DragSelect, selected, + TAG_DONE); + } + } + + /* Holding MMB? */ + if (lv->Flags & LVF_SCROLLING) + { + DB1 (DBPRINTF (" scrolling\n");) + selected = (msg->gpi_Mouse.Y - lv->MiddleMouseY) + + lv->BackupPixelTop; + + UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0, + LVA_PixelTop, selected < 0 ? 0 : selected, + TAG_DONE); + } + + } /* End switch (ie->ie_Code) */ + + break; + } + + case IECLASS_TIMER: + + /* Holding LMB? */ + if (lv->Flags & LVF_DRAGGING) + { + /* Mouse above the upper item? */ + if ((msg->gpi_Mouse.Y < 0) && lv->Top) + { + /* Scroll up */ + UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0, + LVA_MoveUp, 1, + (lv->Flags & LVF_READONLY) ? TAG_IGNORE : LVA_Selected, lv->Top - 1, + TAG_DONE); + } + /* Mouse below the bottom item? */ + else if (msg->gpi_Mouse.Y / (lv->ItemHeight + lv->Spacing) >= lv->Visible) + { + /* Scroll down */ + UpdateAttrs ((Object *)g, msg->gpi_GInfo, 0, + LVA_MoveDown, 1, + (lv->Flags & LVF_READONLY) ? TAG_IGNORE : LVA_Selected, lv->Top + lv->Visible, + TAG_DONE); + } + } + break; + + default: + ; + + } /* End switch (ie->ie_Class) */ + + return result; +} + + + +static void LV_GMGoInactive (Class *cl, struct Gadget *g, UNUSED(struct gpGoInactive *msg)) +{ + struct LVData *lv = INST_DATA (cl, g); + ASSERT_VALID_PTR(lv) + + DB1 (DBPRINTF ("ListViewClass: GM_GOINACTIVE\n");) + + /* Stop dragging and scrolling modes */ + lv->Flags &= ~(LVF_DRAGGING | LVF_SCROLLING); + + /* Mark gadget inactive */ + g->Flags &= ~GFLG_SELECTED; +} + + + +static void LV_GMLayout(Class *cl, struct Gadget *g, struct gpLayout *msg) +{ + struct LVData *lv = INST_DATA (cl, g); + LONG visible; + + DB2 (DBPRINTF ("ListViewClass: GM_LAYOUT\n");) + ASSERT_VALID_PTR(lv) + ASSERT_VALID_PTR(msg->gpl_GInfo) + ASSERT_VALID_PTR(msg->gpl_GInfo->gi_DrInfo) + ASSERT_VALID_PTR(msg->gpl_GInfo->gi_DrInfo->dri_Font) + + + /* We shouldn't draw inside the GM_LAYOUT method: the + * GM_REDRAW method will be called by Intuition shortly after. + */ + lv->Flags |= LVF_DONTDRAW; + + /* Collect new gadget size */ + GetGadgetBox(msg->gpl_GInfo, (struct ExtGadget *)g, &lv->GBox); + IBoxToRect(&lv->GBox, &lv->GRect); + + if (GadgetHasFrame(g)) + /* Calculate dimensions of our framing image */ + DoMethod((Object *)g->GadgetRender, + IM_FRAMEBOX, &lv->GBox, &lv->FrameBox, msg->gpl_GInfo->gi_DrInfo, 0); + + /* Calculate clipping region for gadget LVA_Clipped mode */ + if (lv->ClipRegion) + { + /* Remove previous clipping rectangle, if any */ + ClearRegion (lv->ClipRegion); + + /* Install a clipping rectangle around the gadget box. + * We don't check for failure because we couldn't do + * anything otherwise. + */ + OrRectRegion (lv->ClipRegion, &lv->GRect); + } + + /* Setup Font if not yet done */ + if (!lv->Font) + { + lv->Font = msg->gpl_GInfo->gi_DrInfo->dri_Font; + if (!lv->ItemHeight) + lv->ItemHeight = lv->Font->tf_YSize; + } + + if (lv->ItemHeight) + { + if (lv->ClipRegion) + /* Allow displaying an incomplete item at the bottom of the listview, + * plus one incomplete item at the top. + */ + visible = (lv->GBox.Height + lv->ItemHeight + lv->Spacing - 1) / + (lv->ItemHeight + lv->Spacing); + else + /* get maximum number of items fitting in the listview height. + * Ignore spacing for the last visible item. + */ + visible = (lv->GBox.Height + lv->Spacing) / (lv->ItemHeight + lv->Spacing); + } + else + visible = 0; + + lv->MaxScroll = lv->GBox.Height / lv->ScrollRatio; + + + /* Send initial notification to our sliders, or update them to + * the new values. The slieders will get the correct size also + * in the special case where the list is attached at creation + * time and the sliders are attached later using a model object. + * + * The private class attribute LVA_Visible will handle everything for us. + */ + UpdateAttrs ((Object *)g, msg->gpl_GInfo, 0, + LVA_Visible, visible, + TAG_DONE); + + /* Re-enable drawing */ + lv->Flags &= ~LVF_DONTDRAW; +} + + + +static ULONG LV_OMSet(Class *cl, struct Gadget *g, struct opUpdate *msg) +{ + struct LVData *lv = INST_DATA (cl, g); + struct TagItem *ti, + *tstate = msg->opu_AttrList; + ULONG result; + UWORD action = 0; /* See flag definitions below */ + + ASSERT_VALID_PTR(lv) + ASSERT_VALID_PTR_OR_NULL(tstate) + + DB2 (DBPRINTF ((msg->MethodID == OM_SET) ? + "ListViewClass: OM_SET\n" : + "ListViewClass: OM_UPDATE:\n");) + + + /* Definitions for the ations to be taken right after + * scanning the attributes list in OM_SET/OM_UPDATE. + * For speed reasons we pack them together in a single variable, + * so we can set and test multiple flags in once. + */ + #define LVF_DO_SUPER_METHOD (1<<0) + #define LVF_REDRAW (1<<1) + #define LVF_SCROLL (1<<2) + #define LVF_TOGGLESELECT (1<<3) + #define LVF_NOTIFY (1<<4) + #define LVF_NOTIFYALL (1<<5) + + + while ((ti = NextTagItem (&tstate))) + switch (ti->ti_Tag) + { + case GA_ID: + if (msg->MethodID == OM_SET) + { + DB2 (DBPRINTF (" GA_ID, %ld\n", ti->ti_Data);) + + /* Avoid forwarding all taglists to superclass because of GA_ID */ + g->GadgetID = ti->ti_Data; + } + break; + + case LVA_Selected: + DB2 (DBPRINTF (" LVA_Selected, %ld\n", ti->ti_Data);) + + if (lv->Items) + { + LONG newselected = ti->ti_Data; + + if (newselected != ~0) + newselected = (newselected >= lv->Total) ? + (lv->Total - 1) : newselected; + + if (lv->Selected != newselected) + { + if (((lv->Selected >= lv->Top) && + (lv->Selected < lv->Top + lv->Visible)) || + ((newselected >= lv->Top) && + (newselected < lv->Top + lv->Visible))) + action |= LVF_TOGGLESELECT; + + lv->Selected = newselected; + + if (newselected == ~0) + lv->SelectedPtr = NULL; + else + lv->SelectedPtr = GetItem(lv, newselected); + + action |= LVF_NOTIFY; + } + } + break; + + case LVA_Top: + DB2 (DBPRINTF (" LVA_Top, %ld\n", ti->ti_Data);) + + if ((lv->Top != (LONG)ti->ti_Data) && lv->Items) + { + /* This will scroll the listview contents when needed */ + + lv->Top = (((LONG)ti->ti_Data + lv->Visible) >= lv->Total) ? + ((lv->Total <= lv->Visible) ? 0 : (lv->Total - lv->Visible)) + : (LONG)ti->ti_Data; + lv->PixelTop = lv->Top * (lv->ItemHeight + lv->Spacing); + + /* TODO: optimize for some special cases: + * Top == oldtop + 1 and Top == oldtop - 1 + */ + lv->TopPtr = GetItem(lv, lv->Top); + action |= LVF_SCROLL | LVF_NOTIFY; + } + break; + + case LVA_Total: + DB2 (DBPRINTF (" LVA_Total, %ld\n", ti->ti_Data);) + + /* We don't hhandle LVA_Total except when setting a new + * list or array of items. + */ + break; + + case LVA_SelectItem: + DB2 (DBPRINTF (" LVA_SelectItem, %ld\n", ti->ti_Data);) + + /* Check LVA_MaxSelect */ + if (lv->SelectCount >= lv->MaxSelect) + DisplayBeep (msg->opu_GInfo ? msg->opu_GInfo->gi_Screen : NULL); + else if (lv->Items) + { + LONG newselected = ((LONG)ti->ti_Data >= lv->Total) ? + (lv->Total - 1) : (LONG)ti->ti_Data; + + if (((lv->Selected >= lv->Top) && + (lv->Selected < lv->Top + lv->Visible)) || + ((newselected >= lv->Top) && + (newselected < lv->Top + lv->Visible))) + action |= LVF_TOGGLESELECT; + + lv->Selected = newselected; + lv->SelectedPtr = GetItem(lv, newselected); + + if (!IsItemSelected(lv, lv->SelectedPtr, newselected)) + { + lv->SelectCount++; + + if (lv->SelectArray) + lv->SelectArray[newselected] = lv->SelectCount; + else if (lv->Flags & LVF_LIST) + ((struct Node *)lv->SelectedPtr)->ln_Type = lv->SelectCount; + } + action |= LVF_NOTIFY; + } + break; + + case LVA_DeselectItem: + DB2 (DBPRINTF (" LVA_DeselectItem, %ld\n", ti->ti_Data);) + + if (lv->Items) + { + LONG newselected = ((LONG)ti->ti_Data >= lv->Total) ? + (lv->Total - 1) : (LONG)ti->ti_Data; + + if (((lv->Selected >= lv->Top) && + (lv->Selected < lv->Top + lv->Visible)) || + ((newselected >= lv->Top) && + (newselected < lv->Top + lv->Visible))) + action |= LVF_TOGGLESELECT; + + lv->Selected = newselected; + lv->SelectedPtr = GetItem(lv, newselected); + + if (IsItemSelected(lv, lv->SelectedPtr, newselected)) + { + lv->SelectCount--; + + if (lv->SelectArray) + lv->SelectArray[lv->Selected] = 0; + else if (lv->Flags & LVF_LIST) + ((struct Node *)lv->SelectedPtr)->ln_Type = 0; + + action |= LVF_NOTIFY; + } + } + break; + + case LVA_ToggleItem: + DB2 (DBPRINTF (" LVA_ToggleItem, %ld\n", ti->ti_Data);) + + if (lv->Items) + { + LONG newselected = ((LONG)ti->ti_Data >= lv->Total) ? + (lv->Total - 1) : (LONG)ti->ti_Data; + + if (((lv->Selected >= lv->Top) && + (lv->Selected < lv->Top + lv->Visible)) || + ((newselected >= lv->Top) && + (newselected < lv->Top + lv->Visible))) + action |= LVF_TOGGLESELECT; + + lv->Selected = newselected; + lv->SelectedPtr = GetItem(lv, newselected); + + if (IsItemSelected(lv, lv->SelectedPtr, lv->Selected)) + { + /* Deselect */ + lv->SelectCount--; + + if (lv->SelectArray) + lv->SelectArray[lv->Selected] = 0; + else if (lv->Flags & LVF_LIST) + ((struct Node *)lv->SelectedPtr)->ln_Type = 0; + } + else + { + /* Check LVA_MaxSelect */ + if (lv->SelectCount >= lv->MaxSelect) + DisplayBeep (msg->opu_GInfo ? msg->opu_GInfo->gi_Screen : NULL); + else + { + /* Select */ + lv->SelectCount++; + + if (lv->SelectArray) + lv->SelectArray[lv->Selected] = lv->SelectCount; + else if (lv->Flags & LVF_LIST) + ((struct Node *)lv->SelectedPtr)->ln_Type = lv->SelectCount; + } + } + + action |= LVF_NOTIFY; + } + break; + + case LVA_ClearSelected: + DB2 (DBPRINTF (" LVA_ClearSelected, %ld\n", ti->ti_Data);) + + if (lv->Items) + { + LONG newselected = (LONG)ti->ti_Data; + LONG i; + + if (((lv->Selected >= lv->Top) && + (lv->Selected < lv->Top + lv->Visible)) || + ((newselected >= lv->Top) && + (newselected < lv->Top + lv->Visible))) + action |= LVF_TOGGLESELECT; + + lv->Selected = ~0; + lv->SelectedPtr = NULL; + lv->SelectCount = 0; + + + /* Clear the selections */ + + if (lv->SelectArray) + for (i = 0; i < lv->Total; i++) + lv->SelectArray[i] = 0; + else if (lv->Flags & LVF_LIST) + { + struct Node *node; + + for (node = ((struct List *)lv->Items)->lh_Head; + node->ln_Succ; + node = node->ln_Succ) + { + node->ln_Type = 0; + ASSERT_VALID_PTR_OR_NULL(node); + } + } + + /* TODO: check if total redraw is really needed */ + action |= LVF_REDRAW | LVF_NOTIFY; + } + break; + + case LVA_MakeVisible: + { + LONG itemnum = (LONG)ti->ti_Data; + + DB2 (DBPRINTF (" LVA_MakeVisible, %ld\n", ti->ti_Data);) + + if (itemnum < 0) + itemnum = 0; + + if (itemnum >= lv->Total) + itemnum = lv->Total - 1; + + if (itemnum < lv->Top) + { + /* Scroll up */ + + lv->Top = itemnum; + lv->TopPtr = GetItem(lv, lv->Top); + action |= LVF_SCROLL | LVF_NOTIFY; + } + else if (itemnum >= lv->Top + lv->Visible) + { + /* Scroll down */ + + lv->Top = itemnum - lv->Visible + 1; + lv->TopPtr = GetItem(lv, lv->Top); + action |= LVF_SCROLL | LVF_NOTIFY; + } + break; + } + + case LVA_MoveUp: + DB2 (DBPRINTF (" LVA_MoveUp, %ld\n", ti->ti_Data);) + + if ((lv->Top > 0) && lv->Items) + { + lv->Top--; + lv->TopPtr = GetPrev (lv, lv->TopPtr, lv->Top); + action |= LVF_SCROLL | LVF_NOTIFY; + } + break; + + case LVA_MoveDown: + DB2 (DBPRINTF (" LVA_MoveDown, %ld\n", ti->ti_Data);) + + if ((lv->Top + lv->Visible < lv->Total) && lv->Items) + { + lv->Top++; + lv->TopPtr = GetNext (lv, lv->TopPtr, lv->Top); + action |= LVF_SCROLL | LVF_NOTIFY; + } + break; + + case LVA_MoveLeft: + DB2 (DBPRINTF (" Unimplemented attr: LVA_MoveLeft\n");) + break; + + case LVA_MoveRight: + DB2 (DBPRINTF (" Unimplemented attr: LVA_MoveRight\n");) + break; + + case LVA_StringList: + DB2 (DBPRINTF (" LVA_StringList, $%lx\n", ti->ti_Data);) + + if (ti->ti_Data == (ULONG)~0L) + lv->Items = NULL; + else + { + ASSERT_VALID_PTR_OR_NULL(ti->ti_Data) + + lv->Items = (void *)ti->ti_Data; + lv->GetItemFunc = ListGetItem; + lv->GetNextFunc = ListGetNext; + lv->GetPrevFunc = ListGetPrev; + lv->DrawItemFunc = ListStringDrawItem; + lv->Flags |= LVF_LIST; + + lv->Total = GetTagData (LVA_Total, ~0, msg->opu_AttrList); + if (lv->Total == ~0) + lv->Total = CountNodes(lv->Items); + + lv->SelectCount = CountSelections (lv); + + action |= LVF_REDRAW | LVF_NOTIFYALL; + } + break; + + case LVA_StringArray: + DB2 (DBPRINTF (" LVA_StringArray, $%lx\n", ti->ti_Data);) + + if (ti->ti_Data == (ULONG)~0L) + lv->Items = NULL; + else + { + ASSERT_VALID_PTR_OR_NULL(ti->ti_Data) + + lv->Items = (void *)ti->ti_Data; + lv->GetItemFunc = ArrayGetItem; + lv->GetNextFunc = ArrayGetItem; + lv->GetPrevFunc = ArrayGetItem; + lv->DrawItemFunc = StringDrawItem; + lv->Flags &= ~LVF_LIST; + + lv->Total = GetTagData (LVA_Total, ~0, msg->opu_AttrList); + if ((lv->Total == ~0) && lv->Items) + { + /* Count items */ + ULONG i = 0; + while (((APTR *)lv->Items)[i]) i++; + lv->Total = i; + } + + lv->SelectCount = CountSelections(lv); + + action |= LVF_REDRAW | LVF_NOTIFYALL; + } + break; + + case LVA_ImageList: + DB2 (DBPRINTF (" LVA_ImageList, $%lx\n", ti->ti_Data);) + + if (ti->ti_Data == (ULONG)~0L) + lv->Items = NULL; + else + { + ASSERT_VALID_PTR_OR_NULL(ti->ti_Data) + + lv->Items = (void *) ti->ti_Data; + lv->GetItemFunc = ListGetItem; + lv->GetNextFunc = ListGetNext; + lv->GetPrevFunc = ListGetPrev; + lv->DrawItemFunc = ListImageDrawItem; + lv->Flags |= LVF_LIST; + + lv->Total = GetTagData (LVA_Total, ~0, msg->opu_AttrList); + if (lv->Total == ~0) + lv->Total = CountNodes(lv->Items); + + lv->SelectCount = CountSelections(lv); + + action |= LVF_REDRAW | LVF_NOTIFYALL; + } + break; + + case LVA_ImageArray: + DB2 (DBPRINTF (" LVA_ImageArray, $%lx\n", ti->ti_Data);) + + if (ti->ti_Data == (ULONG)~0L) + lv->Items = NULL; + else + { + ASSERT_VALID_PTR_OR_NULL(ti->ti_Data) + + lv->Items = (void *) ti->ti_Data; + lv->GetItemFunc = ArrayGetItem; + lv->GetNextFunc = ArrayGetItem; + lv->GetPrevFunc = ArrayGetItem; + lv->DrawItemFunc = ImageDrawItem; + lv->Flags &= ~LVF_LIST; + + lv->Total = GetTagData (LVA_Total, ~0, msg->opu_AttrList); + if ((lv->Total == ~0) && lv->Items) + { + /* Count items */ + ULONG i = 0; + while (((APTR *)lv->Items)[i]) i++; + lv->Total = i; + } + + action |= LVF_REDRAW | LVF_NOTIFYALL; + } + break; + + case LVA_CustomList: + DB2 (DBPRINTF (" LVA_CustomList, $%lx\n", ti->ti_Data);) + + if (ti->ti_Data == (ULONG)~0L) + lv->Items = NULL; + else + { + ASSERT_VALID_PTR_OR_NULL(ti->ti_Data) + + lv->Items = (void *) ti->ti_Data; + lv->SelectCount = CountSelections (lv); + + action |= LVF_REDRAW | LVF_NOTIFYALL; + } + break; + + case LVA_Visible: + DB2 (DBPRINTF (" LVA_Visible, %ld\n", ti->ti_Data);) + + /* This attribute can only be set internally, and will + * trigger a full slider notification. + */ + lv->Visible = (LONG)ti->ti_Data; + action |= LVF_NOTIFYALL; + + + /* Also scroll the ListView if needed. */ + if (lv->ClipRegion) + { + LONG height = lv->Total * (lv->ItemHeight + lv->Spacing); + LONG newtop; + + if (lv->PixelTop + lv->GBox.Height >= height) + { + lv->PixelTop = height - lv->GBox.Height; + if (lv->PixelTop < 0) + lv->PixelTop = 0; + + newtop = lv->PixelTop / (lv->ItemHeight + lv->Spacing); + if (newtop != lv->Top) + { + lv->Top = newtop; + lv->TopPtr = GetItem(lv, newtop); + } + action |= LVF_SCROLL; + } + } + else if (lv->Top + lv->Visible >= lv->Total) + { + lv->Top = (lv->Total <= lv->Visible) ? 0 : (lv->Total - lv->Visible); + lv->TopPtr = GetItem(lv, lv->Top); + lv->PixelTop = lv->Top * (lv->ItemHeight + lv->Spacing); + action |= LVF_SCROLL; + } + break; + + case LVA_SelectArray: + DB2 (DBPRINTF (" LVA_SelectArray, $%lx\n", ti->ti_Data);) + ASSERT_VALID_PTR_OR_NULL(ti->ti_Data) + + lv->SelectArray = (ULONG *)ti->ti_Data; + lv->SelectCount = CountSelections (lv); + action |= LVF_REDRAW; + break; + + case LVA_MaxSelect: + DB2(DBPRINTF(" LVA_MaxSelect, %ld\n", ti->ti_Data);) + + lv->MaxSelect = ti->ti_Data; + /* NOTE: We are not checking lv->SelectCount */ + break; + + case LVA_PixelTop: /* Handle pixel-wise scrolling */ + DB2(DBPRINTF(" LVA_PixelTop, %ld\n", ti->ti_Data);) + + if (((LONG)ti->ti_Data != lv->PixelTop) && lv->Items && lv->ItemHeight) + { + LONG newtop; + + lv->PixelTop = (LONG)ti->ti_Data; + action |= LVF_SCROLL; + + newtop = lv->PixelTop / (lv->ItemHeight + lv->Spacing); + newtop = ((newtop + lv->Visible) >= lv->Total) ? + ((lv->Total <= lv->Visible) ? 0 : (lv->Total - lv->Visible)) + : newtop; + + if (newtop != lv->Top) + { + /* TODO: optimize GetItem() for some special cases: + * Top = oldtop + 1 and Top = oldtop - 1 + */ + lv->Top = newtop; + lv->TopPtr = GetItem(lv, newtop); + action |= LVF_NOTIFY | LVF_SCROLL; + } + } + break; + + case LVA_ScrollRatio: + DB2 (DBPRINTF (" LVA_ScrollRatio, %ld\n", ti->ti_Data);) + ASSERT(ti->ti_Data != 0) + + lv->ScrollRatio = (LONG)ti->ti_Data; + lv->MaxScroll = lv->GBox.Height / lv->ScrollRatio; + break; + + default: + DB2 (DBPRINTF (" Passing unknown tag to superclass: $%lx, %ld\n", + ti->ti_Tag, ti->ti_Data);) + + /* This little optimization avoids forwarding the + * OM_SET method to our superclass then there are + * no unknown tags. + */ + action |= LVF_DO_SUPER_METHOD; + break; + } + + DB2 (DBPRINTF (" TAG_DONE\n");) + + /* Forward method to our superclass dispatcher, only if needed */ + + if (action & LVF_DO_SUPER_METHOD) + result = (DoSuperMethodA (cl, (Object *)g, (Msg) msg)); + else + result = TRUE; + + + /* Update gadget imagery, only when needed */ + + if ((action & (LVF_REDRAW | LVF_SCROLL | LVF_TOGGLESELECT)) + && msg->opu_GInfo && !(lv->Flags & LVF_DONTDRAW)) + { + struct RastPort *rp; + + if ((rp = ObtainGIRPort (msg->opu_GInfo))) + { + /* Just redraw everything */ + if (action & LVF_REDRAW) + DoMethod ((Object *)g, GM_RENDER, msg->opu_GInfo, rp, GREDRAW_REDRAW); + else + { + /* Both these may happen at the same time */ + + if (action & LVF_SCROLL) + DoMethod ((Object *)g, GM_RENDER, msg->opu_GInfo, rp, + GREDRAW_UPDATE); + + if (action & LVF_TOGGLESELECT) + DoMethod ((Object *)g, GM_RENDER, msg->opu_GInfo, rp, + GREDRAW_TOGGLE); + } + + ReleaseGIRPort (rp); + } + DB1(else DBPRINTF ("*** ObtainGIRPort() failed!\n");) + } + + + /* Notify our targets about changed attributes */ + + if (action & LVF_NOTIFYALL) + { + DB2(DBPRINTF("ListViewClass: OM_NOTIFY ALL\n");) + DB2(DBPRINTF(" LVA_Top, %ld\n", lv->Top);) + DB2(DBPRINTF(" LVA_Total, %ld\n", lv->Total);) + DB2(DBPRINTF(" LVA_Visible, %ld\n", lv->Visible);) + DB2(DBPRINTF(" LVA_Selected, %ld\n", lv->Selected);) + DB2(DBPRINTF(" LVA_PixelTop, %ld\n", lv->PixelTop);) + DB2(DBPRINTF(" LVA_PixelHeight, %ld\n", lv->Total * (lv->ItemHeight + lv->Spacing));) + DB2(DBPRINTF(" LVA_PixelVVisible, %ld\n", lv->GBox.Height);) + DB2(DBPRINTF(" TAG_DONE\n");) + + NotifyAttrs((Object *)g, msg->opu_GInfo, + (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0, + LVA_Top, lv->Top, + LVA_Total, lv->Total, + LVA_Visible, lv->Visible, + LVA_Selected, lv->Selected, + LVA_PixelTop, lv->PixelTop, + LVA_PixelHeight, lv->Total * (lv->ItemHeight + lv->Spacing), + LVA_PixelVVisible, lv->ClipRegion ? + lv->GBox.Height : + lv->Visible * (lv->ItemHeight + lv->Spacing), + GA_ID, g->GadgetID, + TAG_DONE); + } + else if (action & LVF_NOTIFY) + { + IPTR tags[9]; + int cnt = 0; + + if (action & LVF_SCROLL) + { + tags[0] = LVA_Top; tags[1] = lv->Top; + tags[2] = LVA_PixelTop; tags[3] = lv->Top * (lv->ItemHeight + lv->Spacing); + cnt = 4; + } + + if (action & LVF_TOGGLESELECT) + { + tags[cnt++] = LVA_Selected; tags[cnt++] = lv->Selected; + } + + tags[cnt++] = GA_ID; tags[cnt++] = g->GadgetID; + tags[cnt] = TAG_DONE; + + DoMethod((Object *)g, OM_NOTIFY, tags, msg->opu_GInfo, + (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0); + } + + return result; +} + + + +static ULONG LV_OMGet(Class *cl, struct Gadget *g, struct opGet *msg) +{ + struct LVData *lv = INST_DATA (cl, g); + + ASSERT_VALID_PTR(lv) + ASSERT_VALID_PTR(msg->opg_Storage) + + DB2 (DBPRINTF("ListViewClass: OM_GET\n");) + + + switch (msg->opg_AttrID) + { + case LVA_Selected: + *msg->opg_Storage = (ULONG) lv->Selected; + return TRUE; + + case LVA_Top: + *msg->opg_Storage = (ULONG) lv->Top; + return TRUE; + + case LVA_Total: + *msg->opg_Storage = (ULONG) lv->Total; + return TRUE; + + case LVA_StringList: + case LVA_StringArray: + case LVA_ImageList: + case LVA_ImageArray: + case LVA_CustomList: + *msg->opg_Storage = (ULONG) lv->Items; + return TRUE; + + case LVA_Visible: + *msg->opg_Storage = (ULONG) lv->Visible; + return TRUE; + + case LVA_SelectedPtr: + *msg->opg_Storage = (ULONG) lv->SelectedPtr; + return TRUE; + + case LVA_SelectArray: + *msg->opg_Storage = (ULONG) lv->SelectArray; + return TRUE; + + default: + return DoSuperMethodA (cl, (Object *)g, (Msg) msg); + } +} + + + +static ULONG LV_OMNew(Class *cl, struct Gadget *g, struct opSet *msg) +{ + struct LVData *lv; + struct TagItem *tag; + struct DrawInfo *drawinfo; + + + DB2(DBPRINTF("ListViewClass: OM_NEW\n");) + + if ((g = (struct Gadget *)DoSuperMethodA(cl, (Object *)g, (Msg)msg))) + { + /* Set the GMORE_SCROLLRASTER flag */ + if (g->Flags & GFLG_EXTENDED) + { + DB(DBPRINTF(" Setting GMORE_SCROLLRASTER\n");) + ((struct ExtGadget *)g)->MoreFlags |= GMORE_SCROLLRASTER; + } + + lv = (struct LVData *) INST_DATA (cl, (Object *)g); + ASSERT_VALID_PTR(lv) + + /* Handle creation-time attributes */ + + /* Map boolean attributes */ + { + static IPTR boolMap[] = + { + GA_ReadOnly, LVF_READONLY, + LVA_Clipped, LVF_CLIPPED, + LVA_ShowSelected, LVF_SHOWSELECTED, + LVA_DoMultiSelect, LVF_DOMULTISELECT, + TAG_DONE + }; + + lv->Flags = PackBoolTags ( + LVF_SHOWSELECTED, + msg->ops_AttrList, + (struct TagItem *)boolMap); + } + + + /* Select font to use when drawing the Listview labels */ + + /* First, try to get the font from our DrawInfo... */ + + if ((drawinfo = (struct DrawInfo *) + GetTagData (GA_DrawInfo, NULL, msg->ops_AttrList))) + { + ASSERT_VALID_PTR(drawinfo) + lv->Font = drawinfo->dri_Font; + } + else + lv->Font = NULL; + + + /* ...then override it with LVA_TextFont */ + + if ((tag = FindTagItem (LVA_TextFont, msg->ops_AttrList))) + { + if (tag->ti_Data) + { + lv->Font = (struct TextFont *)tag->ti_Data; + ASSERT_VALID_PTR_OR_NULL(lv->Font) + } + } + else /* Otherwise, try GA_TextAttr */ + { + struct TextAttr *attr; + struct TextFont *font; + + if ((attr = (struct TextAttr *)GetTagData (GA_TextAttr, + NULL, msg->ops_AttrList))) + { + if ((font = OpenFont(attr))) + { + /* Must remember to close this font later */ + lv->Flags |= LVF_CLOSEFONT; + lv->Font = font; + } + } + } + + /* Calculate ItemHeight */ + + if (lv->Font) + /* Get height from font Y size */ + lv->ItemHeight = lv->Font->tf_YSize; + else + lv->ItemHeight = 0; + + lv->ItemHeight = GetTagData(LVA_ItemHeight, lv->ItemHeight, msg->ops_AttrList); + lv->Spacing = GetTagData(LAYOUTA_Spacing, 0, msg->ops_AttrList); + + if ((tag = FindTagItem(LVA_MaxPen, msg->ops_AttrList))) + lv->MaxPen = tag->ti_Data; + else + { + if (drawinfo) + lv->MaxPen = max ( + max (drawinfo->dri_Pens[BACKGROUNDPEN], + drawinfo->dri_Pens[TEXTPEN]), + max (drawinfo->dri_Pens[FILLPEN], + drawinfo->dri_Pens[FILLTEXTPEN])); + else + lv->MaxPen = (ULONG)-1; + } + + + lv->Total = GetTagData (LVA_Total, ~0, msg->ops_AttrList); + + if ((lv->Items = (APTR) GetTagData (LVA_StringList, NULL, msg->ops_AttrList))) + { + ASSERT_VALID_PTR_OR_NULL(lv->Items) + lv->GetItemFunc = ListGetItem; + lv->GetNextFunc = ListGetNext; + lv->GetPrevFunc = ListGetPrev; + lv->DrawItemFunc = ListStringDrawItem; + lv->Flags |= LVF_LIST; + + if (lv->Total == ~0) + lv->Total = CountNodes(lv->Items); + } + else if ((lv->Items = (APTR) GetTagData (LVA_StringArray, NULL, msg->ops_AttrList))) + { + ASSERT_VALID_PTR_OR_NULL(lv->Items) + lv->GetItemFunc = ArrayGetItem; + lv->GetNextFunc = ArrayGetItem; + lv->GetPrevFunc = ArrayGetItem; + lv->DrawItemFunc = StringDrawItem; + + if (lv->Total == ~0) + { + /* Count items */ + ULONG i = 0; + while (((APTR *)lv->Items)[i]) i++; + lv->Total = i; + } + } + else if ((lv->Items = (APTR)GetTagData(LVA_ImageList, NULL, msg->ops_AttrList))) + { + ASSERT_VALID_PTR_OR_NULL(lv->Items) + lv->GetItemFunc = ListGetItem; + lv->GetNextFunc = ListGetNext; + lv->GetPrevFunc = ListGetPrev; + lv->DrawItemFunc = ListImageDrawItem; + lv->Flags |= LVF_LIST; + + if (lv->Total == ~0) + lv->Total = CountNodes(lv->Items); + } + else if ((lv->Items = (APTR) GetTagData (LVA_ImageArray, NULL, msg->ops_AttrList))) + { + ASSERT_VALID_PTR_OR_NULL(lv->Items) + lv->GetItemFunc = ArrayGetItem; + lv->GetNextFunc = ArrayGetItem; + lv->GetPrevFunc = ArrayGetItem; + lv->DrawItemFunc = ImageDrawItem; + + if (lv->Total == ~0) + { + /* Count items */ + ULONG i = 0; + while (((APTR *)lv->Items)[i]) i++; + lv->Total = i; + } + } + + lv->SelectArray = (ULONG *)GetTagData (LVA_SelectArray, NULL, msg->ops_AttrList); + lv->MaxSelect = GetTagData (LVA_MaxSelect, -1, msg->ops_AttrList); + lv->SelectCount = CountSelections(lv); + + if ((lv->Visible = GetTagData(LVA_Visible, 0, msg->ops_AttrList))) + { + SetAttrs (g, + GA_Height, lv->Visible * (lv->ItemHeight + lv->Spacing), + TAG_DONE); + } + + /* Initialize Top and all related values */ + + lv->OldTop = lv->Top = GetTagData(LVA_MakeVisible, + GetTagData (LVA_Top, 0, msg->ops_AttrList), msg->ops_AttrList); + lv->OldPixelTop = lv->PixelTop = lv->Top * (lv->ItemHeight + lv->Spacing); + + if (lv->Items) + lv->TopPtr = GetItem(lv, lv->Top); + + lv->ScrollRatio = GetTagData(LVA_ScrollRatio, 2, msg->ops_AttrList); + ASSERT(lv->ScrollRatio != 0) + + if ((lv->OldSelected = + lv->Selected = GetTagData(LVA_Selected, ~0, msg->ops_AttrList)) != ~0) + lv->SelectedPtr = GetItem(lv, lv->Selected); + + if ((lv->CallBack = (struct Hook *)GetTagData (LVA_CallBack, NULL, + msg->ops_AttrList))) + { + ASSERT_VALID_PTR_OR_NULL(lv->CallBack->h_Entry) + lv->DrawItemFunc = (LVDrawHook *) lv->CallBack->h_Entry; + } + + if (lv->Flags & LVF_CLIPPED) + lv->ClipRegion = NewRegion (); + } + return (ULONG)g; +} + + + +static void LV_OMDispose(Class *cl, struct Gadget *g, Msg msg) +{ + struct LVData *lv; + + lv = (struct LVData *) INST_DATA (cl, (Object *)g); + + DB2 (DBPRINTF ("ListViewClass: OM_DISPOSE\n");) + ASSERT_VALID_PTR(lv) + + if (lv->ClipRegion) + DisposeRegion (lv->ClipRegion); + + if (lv->Flags & LVF_CLOSEFONT) + CloseFont(lv->Font); + + /* Our superclass will cleanup everything else now */ + DoSuperMethodA (cl, (Object *)g, (Msg) msg); + + /* From now on, our instance data is no longer available */ +} + + + +/* Class support functions */ + + +Class *MakeListViewClass(void) +{ + Class *LVClass; + + if ((LVClass = MakeClass(NULL, GADGETCLASS, NULL, sizeof (struct LVData), 0))) + LVClass->cl_Dispatcher.h_Entry = (ULONG (*)()) LVDispatcher; + + return LVClass; +} + + + +BOOL FreeListViewClass(Class *LVClass) +{ + ASSERT_VALID_PTR_OR_NULL(LVClass) + return FreeClass(LVClass); +} + + +#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) +/* + * Class library support functions + */ + +struct ClassLibrary * HOOKCALL _UserLibInit(REG(a6, struct ClassLibrary *mybase)) +{ + /* Initialize SysBase */ + SysBase = *((struct ExecBase **)4UL); + + if (!((UtilityBase = (UTILITYBASETYPE *) OpenLibrary("utility.library", 39)) && + (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39)) && + (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39)) && + (LayersBase = OpenLibrary("layers.library", 39)))) + { + _UserLibCleanup(mybase); + return NULL; + } + + if (!(mybase->cl_Class = MakeListViewClass())) + { + _UserLibCleanup(mybase); + return NULL; + } + + AddClass(mybase->cl_Class); + return mybase; +} + +struct ClassLibrary * HOOKCALL _UserLibCleanup(REG(a6, struct ClassLibrary *mybase)) +{ + if (mybase->cl_Class) + if (!FreeListViewClass(mybase->cl_Class)) + return NULL; + + CloseLibrary((struct Library *)LayersBase); + CloseLibrary((struct Library *)GfxBase); + CloseLibrary((struct Library *)IntuitionBase); + CloseLibrary((struct Library *)UtilityBase); + + return mybase; +} + +Class * HOOKCALL _GetEngine(REG(a6, struct ClassLibrary *mybase)) +{ + return mybase->cl_Class; +} + +#endif /* (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) */ diff --git a/gadgets/ListView/ListViewClass_static.newinline.s b/gadgets/ListView/ListViewClass_static.newinline.s new file mode 100644 index 0000000..aa2c682 --- /dev/null +++ b/gadgets/ListView/ListViewClass_static.newinline.s @@ -0,0 +1,4072 @@ +#NO_APP +gcc2_compiled.: +___gnu_compiled_c: +.text + .even +_LVDispatcher: + moveml #0x2030,sp@- + movel a2,d1 + movel a1@,d0 + moveq #6,d2 + cmpl d0,d2 + jeq L14 + jcs L23 + moveq #2,d2 + cmpl d0,d2 + jeq L11 + jcs L24 + moveq #1,d2 + cmpl d0,d2 + jeq L10 + jra L20 + .even +L24: + moveq #3,d2 + cmpl d0,d2 + jeq L12 + moveq #4,d2 + cmpl d0,d2 + jeq L13 + jra L20 + .even +L23: + cmpl #259,d0 + jeq L16 + jhi L25 + cmpl #257,d0 + jeq L18 + cmpl #258,d0 + jeq L19 + jra L20 + .even +L25: + cmpl #260,d0 + jeq L17 + cmpl #264,d0 + jeq L16 + jra L20 + .even +L10: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMRender + moveq #1,d0 + jra L26 + .even +L11: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMGoActive + jra L27 + .even +L12: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMHandleInput + jra L27 + .even +L13: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMGoInactive + moveq #1,d0 + jra L26 + .even +L14: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMLayout + moveq #1,d0 + jra L26 + .even +L16: + movel a1,d0 + movel d1,a1 + jbsr _LV_OMSet + jra L27 + .even +L17: + movel a1,d0 + movel d1,a1 + jbsr _LV_OMGet + jra L27 + .even +L18: + movel a1,d0 + movel d1,a1 + jbsr _LV_OMNew + jra L27 + .even +L19: + movel a1,d0 + movel d1,a1 + jbsr _LV_OMDispose + moveq #1,d0 + jra L26 + .even +L20: + movel a0@(24),a0 + movel a0@(8),a3 + movel d1,a2 + jbsr a3@ +L27: +L26: + moveml sp@+,#0xc04 + rts + .even +_RedrawItems: + lea sp@(-40),sp + moveml #0x303c,sp@- + movel a0,a4 + movel d0,d2 + movel d1,d3 + movel sp@(68),a5 + movel d2,sp@(28) + movel a4@,sp@(32) + movel a1@(8),sp@(36) + movel a1@(4),a0 + movel a0@(30),sp@(40) + movel a4@(90),sp@(56) + movew a4@(150),sp@(44) + movew a4@(154),sp@(48) + tstl a4@(138) + jeq L68 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d2,d0 + addw a4@(152),d0 + subw a4@(22),d0 + jra L69 + .even +L68: + subl a4@(4),d2 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d2,d0 + addw a4@(152),d0 +L69: + movew d0,sp@(46) + addw a4@(62),d0 + subqw #1,d0 + movew d0,sp@(50) + moveq #24,d2 + addl sp,d2 + tstl a5 + jne L71 + movel #517,sp@(24) + movel a4@(106),a3 + movel d2,a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a5 +L71: + movel a4@(118),a3 + tstl a3 + jeq L73 + movel #518,sp@(24) + movel d2,a2 + movel a5,a1 + movel a4@(130),a0 + jbsr a3@ + jra L73 + .even +L82: + movel #515,sp@(24) + movel a4@(110),a3 + movel d2,a2 + movel a5,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a5 + movew a4@(62),d0 + addw a4@(66),d0 + addw d0,sp@(46) + addw d0,sp@(50) +L73: + movel a4@(90),d0 + btst #3,d0 + jeq L76 + movel a4@(76),a0 + tstl a0 + jeq L77 + movel sp@(28),d0 + movel a0@(d0:l:4),d0 + jra L81 + .even +L77: + btst #28,d0 + jeq L79 + clrl d0 + moveb a5@(8),d0 + jra L81 + .even +L79: + clrl d0 + jra L81 + .even +L76: + movel sp@(28),d0 + cmpl a4@(24),d0 + seq d0 + extbl d0 + negl d0 +L81: + tstl d0 + sne d0 + extbl d0 + negl d0 + movel d0,sp@(52) + movel #514,sp@(24) + movel a4@(126),a3 + movel d2,a2 + movel a5,a1 + movel a4@(130),a0 + jbsr a3@ + movel sp@(28),d0 + movel d0,d1 + addql #1,d1 + movel d1,sp@(28) + addql #1,d0 + cmpl d0,d3 + jge L82 + movel a4@(122),a3 + tstl a3 + jeq L84 + movel #519,sp@(24) + movel a5,a1 + movel a4@(130),a0 + jbsr a3@ +L84: + moveml sp@+,#0x3c0c + lea sp@(40),sp + rts + .even +_LV_GMRender: + lea sp@(-72),sp + moveml #0x3f3e,sp@- + movel a1,sp@(60) + movel d0,sp@(56) + clrl d0 + movew a0@(32),d0 + movel a1,a4 + addl d0,a4 + movel sp@(56),a0 + movel a0@(8),a5 + btst #5,a4@(90) + jne L85 + tstl a4@ + jeq L87 + tstl a4@(16) + jeq L87 + clrl sp@(52) + clrw sp@(46) + movel a5@(52),d0 + movel a4@(134),d1 + cmpl d0,d1 + jeq L88 + movel d0,sp@(52) + movel _GfxBase,a2 + movel a2,a6 + movel d1,a0 + movel a5,a1 + jbsr a2@(-66) +L88: + tstl a4@(138) + jeq L89 + movel sp@(56),a1 + movel a1@(8),a0 + movel a0@,a0 + btst #4,a0@(31) + jeq L90 + movew #1,sp@(46) + movel _LayersBase,a1 + movel a1,a6 + clrl d0 + jbsr a1@(-84) +L90: + movel _LayersBase,a2 + movel a2,a6 + movel a4@(138),a1 + movel a5@,a0 + jbsr a2@(-174) + movel d0,sp@(48) +L89: + movel sp@(56),a2 + movel a2@(12),d0 + moveq #1,d1 + cmpl d0,d1 + jeq L127 + jlt L157 + tstl d0 + jeq L92 + jra L91 + .even +L157: + moveq #2,d3 + cmpl d0,d3 + jeq L138 + jra L91 + .even +L92: + clrw d3 + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L93 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + sgt d0 + moveb d0,d3 + extw d3 + negw d3 +L93: + clrw d4 + movel a4@(48),d2 + cmpl d2,d1 + jgt L94 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + sgt d0 + moveb d0,d4 + extw d4 + negw d4 +L94: + tstw d4 + jne L96 + tstw d3 + jeq L95 +L96: + movel a4@,sp@(84) + movel a5,sp@(88) + movel sp@(56),a1 + movel a1@(4),a0 + movel a0@(30),sp@(92) + movel a4@(90),sp@(108) + movel a4@(118),a3 + tstl a3 + jeq L97 + movel #518,sp@(76) + lea sp@(76),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ +L97: + movel #514,sp@(76) + tstw d3 + jeq L98 + movel a4@(24),d1 + movew a4@(150),sp@(96) + movew a4@(154),sp@(100) + tstl a4@(138) + jeq L99 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d0,d1 + movew d1,d0 + addw a4@(152),d0 + subw a4@(22),d0 + jra L100 + .even +L99: + subl a4@(4),d1 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d0,d1 + movew d1,d0 + addw a4@(152),d0 +L100: + movew d0,sp@(98) + addw a4@(62),d0 + subqw #1,d0 + movew d0,sp@(102) + movel a4@(28),a1 + movel a4@(24),d1 + movel a4@(90),d0 + btst #3,d0 + jeq L102 + movel a4@(76),a0 + tstl a0 + jeq L103 + movel a0@(d1:l:4),d0 + jra L104 + .even +L103: + btst #28,d0 + jeq L105 + tstl a1 + jne L166 + movel #517,sp@(64) + movel d1,sp@(68) + movel a4@,sp@(72) + movel a4@(106),a3 + lea sp@(64),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L108 +L166: + clrl d0 + moveb a1@(8),d0 + jra L104 + .even +L108: +L105: + clrl d0 + jra L104 + .even +L102: + moveq #1,d0 +L104: + tstl d0 + sne d0 + extbl d0 + negl d0 + movel d0,sp@(104) + movel a4@(24),sp@(80) + movel a4@(126),a3 + lea sp@(76),a2 + movel a4@(28),a1 + movel a4@(130),a0 + jbsr a3@ +L98: + tstw d4 + jeq L112 + movel a4@(48),d1 + movew a4@(150),sp@(96) + movew a4@(154),sp@(100) + tstl a4@(138) + jeq L113 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d0,d1 + movew d1,d0 + addw a4@(152),d0 + subw a4@(22),d0 + jra L114 + .even +L113: + subl a4@(4),d1 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d0,d1 + movew d1,d0 + addw a4@(152),d0 +L114: + movew d0,sp@(98) + addw a4@(62),d0 + subqw #1,d0 + movew d0,sp@(102) + movel a4@(52),a1 + movel a4@(48),d0 + movel a4@(90),d1 + btst #3,d1 + jeq L116 + movel a4@(76),a0 + tstl a0 + jeq L117 + movel a0@(d0:l:4),d0 + jra L118 + .even +L117: + btst #28,d1 + jeq L119 + tstl a1 + jne L167 + movel #517,sp@(64) + movel d0,sp@(68) + movel a4@,sp@(72) + movel a4@(106),a3 + lea sp@(64),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L122 +L167: + clrl d0 + moveb a1@(8),d0 + jra L118 + .even +L122: +L119: + clrl d0 + jra L118 + .even +L116: + cmpl a4@(24),d0 + seq d0 + extbl d0 + negl d0 +L118: + tstl d0 + sne d0 + extbl d0 + negl d0 + movel d0,sp@(104) + movel a4@(48),sp@(80) + movel a4@(126),a3 + lea sp@(76),a2 + movel a4@(52),a1 + movel a4@(130),a0 + jbsr a3@ +L112: + movel a4@(122),a3 + tstl a3 + jeq L95 + movel #519,sp@(76) + lea sp@(76),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ +L95: + movel a4@(24),a4@(48) + movel a4@(28),a4@(52) + jra L91 + .even +L127: + movel _GfxBase,a2 + movel sp@(56),a1 + movel a1@(4),a0 + movel a0@(30),a0 + movel a0@(4),a0 + movel a2,a6 + clrl d0 + movew a0@(14),d0 + movel a5,a1 + jbsr a2@(-342) + movel a4@(64),a1 + tstl a1 + jeq L128 + tstl a4@ + jeq L128 + movel a4@(16),d1 + jeq L128 + movew a4@(152),a0 + movel a0,a3 + addl a4@(60),a3 + movel a4@(12),d0 + subl a4@(4),d0 + cmpl d0,d1 + jge L129 + movel d1,d0 +L129: + subql #1,d0 + tstl d0 + jle L135 + movel d0,d4 + negl d0 + moveq #3,d1 + andl d1,d0 + jeq L133 + cmpl d0,d1 + jle L170 + moveq #2,d3 + cmpl d0,d3 + jle L171 + movel _GfxBase,a0 + movel a0,a6 + lea a1@(-1,a3:l),a1 + movel a1,d3 + movew a4@(154),d2 + extl d2 + movel a3,d1 + movew a4@(150),d0 + extl d0 + movel a5,a1 + jbsr a0@(-306) + movel a4@(60),d0 + addl a4@(64),d0 + addl d0,a3 + subql #1,d4 +L171: + movel _GfxBase,a0 + movel a3,d3 + addl a4@(64),d3 + movel a0,a6 + subql #1,d3 + movew a4@(154),d2 + extl d2 + movel a3,d1 + movew a4@(150),d0 + extl d0 + movel a5,a1 + jbsr a0@(-306) + movel a4@(60),d0 + addl a4@(64),d0 + addl d0,a3 + subql #1,d4 +L170: + movel _GfxBase,a0 + movel a3,d3 + addl a4@(64),d3 + movel a0,a6 + subql #1,d3 + movew a4@(154),d2 + extl d2 + movel a3,d1 + movew a4@(150),d0 + extl d0 + movel a5,a1 + jbsr a0@(-306) + movel a4@(60),d0 + addl a4@(64),d0 + addl d0,a3 + subql #1,d4 + jeq L135 + .even +L133: + movel _GfxBase,a0 + movel a3,d3 + addl a4@(64),d3 + movel a0,a6 + subql #1,d3 + movew a4@(154),d2 + extl d2 + movel a3,d1 + movew a4@(150),d0 + extl d0 + movel a5,a1 + jbsr a0@(-306) + movel a4@(64),a0 + movel a4@(60),d0 + addl a0,d0 + addl d0,a3 + movel _GfxBase,a2 + movel a2,a6 + lea a0@(-1,a3:l),a0 + movel a0,d3 + movew a4@(154),d2 + extl d2 + movel a3,d1 + movew a4@(150),d0 + extl d0 + movel a5,a1 + jbsr a2@(-306) + movel a4@(64),a0 + movel a4@(60),d0 + addl a0,d0 + addl d0,a3 + movel _GfxBase,a2 + movel a2,a6 + lea a0@(-1,a3:l),a0 + movel a0,d3 + movew a4@(154),d2 + extl d2 + movel a3,d1 + movew a4@(150),d0 + extl d0 + movel a5,a1 + jbsr a2@(-306) + movel a4@(64),a0 + movel a4@(60),d0 + addl a0,d0 + addl d0,a3 + movel _GfxBase,a2 + movel a2,a6 + lea a0@(-1,a3:l),a0 + movel a0,d3 + movew a4@(154),d2 + extl d2 + movel a3,d1 + movew a4@(150),d0 + extl d0 + movel a5,a1 + jbsr a2@(-306) + movel a4@(60),d0 + addl a4@(64),d0 + addl d0,a3 + subql #4,d4 + jne L133 + jra L135 + .even +L128: + movew a4@(152),a0 + movel a4@(12),d1 + subl a4@(4),d1 + movel a4@(16),d0 + cmpl d1,d0 + jge L136 + movel d0,d1 +L136: + mulsl a4@(60),d1 + lea a0@(0,d1:l),a3 +L135: + movel _GfxBase,a0 + movel a0,a6 + movew a4@(156),d3 + extl d3 + movew a4@(154),d2 + extl d2 + movel a3,d1 + movew a4@(150),d0 + extl d0 + movel a5,a1 + jbsr a0@(-306) + movel a4@(4),d0 + movel d0,d2 + addl a4@(16),d2 + movel a4@(12),d1 + cmpl d1,d2 + jge L137 + movel d2,d1 +L137: + movel a4@(8),sp@- + subql #1,d1 + movel sp@(60),a1 + movel a4,a0 + jbsr _RedrawItems + addql #4,sp + jra L91 + .even +L138: + tstl a4@(138) + jeq L139 + movel a4@(20),d7 + subl a4@(44),d7 + jeq L91 + movew a4@(148),d5 + extl d5 + jra L141 + .even +L139: + movel a4@(4),d0 + movel a4@(40),d1 + cmpl d0,d1 + jeq L91 + movel d0,d7 + subl d1,d7 + movel a4@(64),d1 + movel a4@(60),d0 + addl d1,d0 + mulsl d0,d7 + movel a4@(16),d5 + mulsl d0,d5 + subl d1,d5 +L141: + movel d7,d0 + jge L144 + negl d0 +L144: + cmpl a4@(68),d0 + jle L143 + movel a4@(4),d0 + movel d0,d2 + addl a4@(16),d2 + movel a4@(12),d1 + cmpl d1,d2 + jge L145 + movel d2,d1 +L145: + movel a4@(8),sp@- + subql #1,d1 + movel sp@(60),a1 + movel a4,a0 + jbsr _RedrawItems + addql #4,sp + jra L146 + .even +L143: + movel _GfxBase,a1 + movel a1,a6 + movel a4@(94),d0 + movel a5,a0 + jbsr a1@(-990) + tstl d7 + jle L147 + movel _GfxBase,a2 + movew a4@(144),a0 + movew a4@(142),a1 + movel a2,a6 + moveq #63,d6 + notb d6 + subl d7,d5 + movew a4@(146),d4 + extl d4 + movel a0,d3 + movel a1,d2 + movel a5,a1 + movel d3,d1 + addl d7,d1 + movel d2,d0 + movel a5,a0 + jbsr a2@(-552) + tstl a4@(138) + jeq L148 + movew a4@(148),a0 + movel a4@(20),d1 + addl a0,d1 + subql #1,d1 + movel a4@(60),d2 + addl a4@(64),d2 + divsl d2,d1 + movel a4@(44),d0 + addl a0,d0 + divsl d2,d0 + clrl sp@- + jra L187 + .even +L148: + movel a4@(16),d0 + movel d0,d1 + addl a4@(4),d1 + clrl sp@- + subql #1,d1 + addl a4@(40),d0 + jra L187 + .even +L147: + movel _GfxBase,a2 + movew a4@(144),a0 + movew a4@(142),a1 + movel a2,a6 + moveq #63,d6 + notb d6 + addl d7,d5 + movew a4@(146),d4 + extl d4 + movel a0,d3 + subl d7,d3 + movel a1,d2 + movel a5,a1 + movel a0,d1 + movel d2,d0 + movel a5,a0 + jbsr a2@(-552) + tstl a4@(138) + jeq L151 + movel a4@(60),d0 + addl a4@(64),d0 + movel a4@(44),d1 + divsl d0,d1 + movel a4@(20),d3 + divsl d0,d3 + movel d3,d0 + clrl sp@- + jra L187 + .even +L151: + movel a4@(8),sp@- + movel a4@(40),d1 + subql #1,d1 + movel a4@(4),d0 +L187: + movel sp@(60),a1 + movel a4,a0 + jbsr _RedrawItems + addql #4,sp + movel a5@,a1 + btst #0,a1@(31) + jeq L153 + movel a1@(8),a0 + tstl a0 + jeq L154 + movel a1@(16),d1 + movel a0@(16),d0 + cmpl d1,d0 + jne L154 + movel a1@(20),d1 + movel a0@(20),d0 + cmpl d1,d0 + jne L154 + movel a1@(156),a0 + tstl a0 + jeq L153 + tstl a0@(8) + jeq L153 +L154: + moveb a5@(24),d6 + movel _GfxBase,a1 + movel a1,a6 + clrl d0 + movel a5,a0 + jbsr a1@(-984) + movel _GfxBase,a0 + movel a0,a6 + movew a4@(156),d5 + extl d5 + movew a4@(154),d4 + extl d4 + movew a4@(152),d3 + extl d3 + movew a4@(150),d2 + extl d2 + movel d7,d1 + clrl d0 + movel a5,a1 + jbsr a0@(-396) + movel _GfxBase,a1 + movel a1,a6 + clrl d0 + moveb d6,d0 + movel a5,a0 + jbsr a1@(-984) +L153: + movel _GfxBase,a1 + movel a1,a6 + moveq #-1,d0 + movel a5,a0 + jbsr a1@(-990) +L146: + movel a4@(4),a4@(40) + movel a4@(20),a4@(44) +L91: + tstl a4@(138) + jeq L158 + movel _LayersBase,a2 + movel a2,a6 + movel sp@(48),a1 + movel a5@,a0 + jbsr a2@(-174) + tstw sp@(46) + jeq L158 + movel _LayersBase,a1 + movel sp@(56),a2 + movel a2@(8),a0 + movel a1,a6 + movel a0@,a0 + jbsr a1@(-78) +L158: + tstl sp@(52) + jeq L161 + movel _GfxBase,a2 + movel a2,a6 + movel sp@(52),a0 + movel a5,a1 + jbsr a2@(-66) + jra L161 + .even +L87: + moveq #1,d0 + movel sp@(56),a0 + cmpl a0@(12),d0 + jne L85 + movel _GfxBase,a2 + movel a0@(4),a0 + movel a0@(30),a0 + movel a0@(4),a0 + movel a2,a6 + clrl d0 + movew a0@(14),d0 + movel a5,a1 + jbsr a2@(-342) + movel _GfxBase,a0 + movel a0,a6 + movew a4@(156),d3 + extl d3 + movew a4@(154),d2 + extl d2 + movew a4@(152),d1 + extl d1 + movew a4@(150),d0 + extl d0 + movel a5,a1 + jbsr a0@(-306) +L161: + moveq #1,d0 + movel sp@(56),a0 + cmpl a0@(12),d0 + jne L85 + clrl d0 + movel sp@(60),a1 + movel a1@(18),a0 + tstl a0 + jeq L164 + btst #2,a1@(13) + jeq L164 + cmpw #-1,a0@(8) + seq d0 + extbl d0 + negl d0 +L164: + tstw d0 + jeq L85 + movel #518,sp@(88) + movel sp@(56),a2 + movel a2@(8),sp@(92) + movew a4@(158),d1 + swap d1 + clrw d1 + movew a4@(160),d0 + extl d0 + orl d0,d1 + movel d1,sp@(96) + clrl sp@(100) + movel a2@(4),a0 + movel a0@(30),sp@(104) + movew a4@(162),d1 + swap d1 + clrw d1 + movew a4@(164),d0 + extl d0 + orl d0,d1 + movel d1,sp@(108) + movel sp@(88),sp@(64) + movel sp@(92),sp@(68) + movel sp@(96),sp@(72) + movel sp@(100),sp@(76) + movel sp@(104),sp@(80) + movel d1,sp@(84) + movel sp@(60),a0 + movel a0@(18),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + lea sp@(64),a1 + jbsr a3@ +L85: + moveml sp@+,#0x7cfc + lea sp@(72),sp + rts + .even +_LV_GMHandleInput: + lea sp@(-140),sp + moveml #0x3f3e,sp@- + movel a1,sp@(76) + movel d0,d6 + clrl d0 + movew a0@(32),d0 + movel a1,a4 + addl d0,a4 + movel d6,a0 + movel a0@(8),sp@(72) + clrl sp@(68) + movel sp@(72),a1 + clrl d0 + moveb a1@(4),d0 + moveq #2,d1 + cmpl d0,d1 + jeq L221 + jlt L279 + moveq #1,d1 + cmpl d0,d1 + jeq L194 + jra L193 + .even +L279: + moveq #6,d1 + cmpl d0,d1 + jeq L268 + jra L193 + .even +L194: + movel sp@(72),a0 + clrl d0 + movew a0@(6),d0 + moveq #76,d1 + cmpl d0,d1 + jeq L196 + moveq #77,d1 + cmpl d0,d1 + jeq L208 + jra L218 + .even +L196: + movel sp@(72),a0 + movew a0@(8),d1 + btst #0,a4@(93) + jne L198 + btst #3,d1 + jeq L197 +L198: + bftst d1{#30:#2} + jeq L199 + movel a4@(16),d0 + jpl L283 + addql #1,d0 +L283: + asrl #1,d0 + movel a4@(4),a4 + subl d0,a4 + movel a4,d0 + jra L200 + .even +L199: + movel a4@(4),d0 + subql #1,d0 +L200: + tstl d0 + jge L212 + clrl d0 + jra L212 + .even +L197: + movew d1,d0 + andw #48,d0 + jne L281 + bftst d1{#30:#2} + jeq L205 + movel a4@(24),d0 + subl a4@(16),d0 + addql #1,d0 + jra L204 + .even +L205: + movel a4@(24),d0 + subql #1,d0 +L204: + tstl d0 + jge L215 +L281: + clrl d0 + jra L215 + .even +L208: + movel sp@(72),a1 + movew a1@(8),d1 + btst #0,a4@(93) + jne L210 + movew d1,d2 + btst #3,d2 + jeq L209 +L210: + bftst d1{#30:#2} + jeq L211 + movel a4@(16),d0 + jpl L284 + addql #1,d0 +L284: + asrl #1,d0 + addl a4@(4),d0 + jra L212 + .even +L211: + movel a4@(4),d0 + addql #1,d0 +L212: + movel #-2142480894,sp@(160) + movel d0,sp@(164) + clrl sp@(168) + jra L195 + .even +L209: + movew d2,d0 + andw #48,d0 + jeq L214 + movel a4@(12),d0 + subql #1,d0 + jra L215 + .even +L214: + bftst d2{#30:#2} + jeq L216 + movel a4@(24),d0 + addl a4@(16),d0 + subql #1,d0 + jra L215 + .even +L216: + movel a4@(24),d0 + addql #1,d0 +L215: + movel #-2142480895,sp@(160) + movel d0,sp@(164) + movel #-2142480888,sp@(168) + movel d0,sp@(172) + clrl sp@(176) + jra L195 + .even +L218: + clrl sp@(160) +L195: + tstl sp@(160) + jeq L193 + movel #264,sp@(128) + lea sp@(160),a2 + movel a2,sp@(132) + movel d6,a0 + movel a0@(4),sp@(136) + movel sp@(72),a1 + movew a1@(8),d0 + andw #9,d0 + sne d0 + extbl d0 + negl d0 + movel d0,sp@(140) + movel sp@(128),sp@(144) + movel a2,sp@(148) + movel sp@(136),sp@(152) + movel d0,sp@(156) + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + lea sp@(144),a1 + jbsr a3@ + jra L193 + .even +L221: + movel sp@(72),a0 + clrl d0 + movew a0@(6),d0 + moveq #106,d1 + cmpl d0,d1 + jeq L256 + jlt L267 + moveq #104,d1 + cmpl d0,d1 + jeq L223 + moveq #105,d1 + cmpl d0,d1 + jeq L249 + jra L260 + .even +L267: + cmpl #232,d0 + jeq L257 + cmpl #234,d0 + jeq L259 + jra L260 + .even +L223: + movel d6,a0 + movew a0@(16),d0 + jlt L225 + cmpw a4@(146),d0 + jge L225 + movew a0@(18),d1 + jlt L225 + cmpw a4@(148),d1 + jlt L224 +L225: + movew #4,a1 + movel a1,sp@(68) + jra L193 + .even +L224: + movel a4@(90),d0 + bset #31,d0 + movel d0,a4@(90) + btst #0,d0 + jne L193 + movel a4@(20),a0 + lea a0@(d1:w),a2 + movel a2,d5 + movel a4@(60),d0 + addl a4@(64),d0 + divsl d0,d5 + movel d5,d4 + jlt L193 + cmpl a4@(12),d4 + jge L193 + movel a4@(24),a4@(80) + movel a0,a4@(84) + lea sp@(128),a0 + movel a0,sp@(52) + lea sp@(144),a1 + movel a1,sp@(48) + lea sp@(148),a2 + movel a2,sp@(44) + lea sp@(152),a2 + lea sp@(140),a5 + lea sp@(112),a0 + movel a0,sp@(64) + lea sp@(116),a1 + movel a1,sp@(60) + lea sp@(120),a0 + movel a0,sp@(56) + moveq #124,d7 + addl sp,d7 + cmpl a4@(24),d4 + jne L230 + movel _IntuitionBase,a0 + movel a0,a6 + movel sp@(72),a1 + movel a1@(18),d3 + movel a1@(14),d2 + movel a4@(102),d1 + movel a4@(98),d0 + jbsr a0@(-102) + tstw d0 + jeq L230 + movel #-2142480866,sp@(128) + movel d4,sp@(132) + clrl sp@(136) + movel #264,sp@(112) + movel sp@(52),sp@(116) + movel d6,a0 + movel a0@(4),sp@(120) + clrl sp@(124) + movel sp@(64),a1 + movel a1@,a5@ + movel sp@(48),a0 + movel sp@(60),a1 + movel a1@,a0@ + movel sp@(44),a0 + movel sp@(56),a1 + movel a1@,a0@ + movel d7,a0 + movel a0@,a2@ + movel sp@(76),a1 + movel a1@(-4),a0 + movel a0@(8),a3 + movel a5,a1 + movel sp@(76),a2 + jbsr a3@ +L230: + movel a4@(90),d0 + btst #3,d0 + jeq L232 + movel a4@(76),a0 + tstl a0 + jeq L236 + movel a0@(d5:l:4),d0 + jra L237 + .even +L236: + btst #28,d0 + jeq L233 + movel #517,sp@(112) + movel d5,sp@(116) + movel a4@,sp@(120) + movel a4@(106),a3 + lea sp@(112),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a0 + clrl d0 + tstl a0 + jeq L241 + clrl d0 + moveb a0@(8),d0 +L241: +L237: + movel #-2142480891,d1 + tstl d0 + jne L234 +L233: + movel #-2142480892,d1 +L234: + movel d1,a4@(56) + jra L245 + .even +L232: + movel sp@(76),a2 + btst #0,a2@(14) + jeq L246 + movel #-2142480895,a4@(56) + cmpl a4@(24),d5 + jne L245 + moveq #-1,d4 + jra L245 + .even +L246: + movel #-2142480895,a4@(56) +L245: + movel a4@(56),sp@(124) + movel d4,sp@(128) + clrl sp@(132) + movel sp@(64),a0 + movel d7,a1 + movel a1@,a0@ + movel sp@(60),a2 + movel sp@(52),a0 + movel a0@,a2@ + movel sp@(56),a1 + movel sp@(132),a1@ + lea sp@(136),a1 + movel #264,sp@(96) + lea sp@(112),a2 + movel a2,sp@(100) + movel d6,a0 + movel a0@(4),sp@(104) + clrl sp@(108) + movel sp@(96),a1@ + movel sp@(100),a5@ + movel sp@(48),a2 + movel sp@(104),a2@ + movel sp@(44),a0 + movel sp@(108),a0@ + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + jbsr a3@ + movel sp@(72),a0 + movel a0@(14),a4@(98) + movel a0@(18),a4@(102) + jra L193 + .even +L249: + movel a4@(90),d1 + movel d1,d0 + andl #-1073741824,d0 + jeq L250 + movel d1,d0 + andl #1073741823,d0 + movel d0,a4@(90) + movel a4@(80),d2 + cmpl a4@(24),d2 + jne L252 + movel a4@(84),a0 + cmpl a4@(20),a0 + jeq L193 +L252: + movel #-2142480895,d0 + btst #0,d1 + jeq L253 + moveq #1,d0 +L253: + movel d0,sp@(116) + movel d2,sp@(120) + movel #-2142480864,sp@(124) + movel a4@(84),sp@(128) + clrl sp@(132) + movel d0,sp@(96) + movel d2,sp@(100) + movel sp@(124),sp@(104) + movel sp@(128),sp@(108) + movel sp@(132),sp@(112) + lea sp@(136),a1 + movel #264,sp@(80) + lea sp@(96),a2 + movel a2,sp@(84) + movel d6,a0 + movel a0@(4),sp@(88) + clrl sp@(92) + movel sp@(80),a1@ + movel sp@(84),sp@(140) + movel sp@(88),sp@(144) + movel sp@(92),sp@(148) + jra L282 + .even +L250: + moveq #4,d0 + movel d0,sp@(68) + jra L193 + .even +L256: + movel a4@(20),a4@(84) + movel a4@(24),a4@(80) + movel d6,a0 + movew a0@(18),a4@(88) + bset #7,a4@(90) + jra L193 + .even +L257: + bclr #7,a4@(90) + movel sp@(76),a1 + btst #0,a1@(15) + jeq L193 + lea a4@(24),a4 + movel d6,a2 + movel a4,a2@(12) + moveq #10,d0 + movel d0,sp@(68) + jra L193 + .even +L259: + bclr #6,a4@(90) + jra L193 + .even +L260: + movel a4@(90),d1 + jge L261 + movel d6,a1 + movew a1@(18),a0 + movel a0,d4 + addl a4@(20),d4 + movel a4@(60),d0 + addl a4@(64),d0 + divsl d0,d4 + cmpl a4@(24),d4 + jeq L261 + btst #0,d1 + jne L261 + movel a4@(4),d0 + cmpl d4,d0 + jgt L261 + addl a4@(16),d0 + cmpl d4,d0 + jle L261 + movel a4@(56),sp@(92) + movel d4,sp@(96) + clrl sp@(100) + movel sp@(92),sp@(80) + movel d4,sp@(84) + movel sp@(100),sp@(88) + lea sp@(104),a1 + movel #264,sp@(120) + lea sp@(80),a2 + movel a2,sp@(124) + movel d6,a0 + movel a0@(4),sp@(128) + clrl sp@(132) + movel sp@(120),a1@ + movel sp@(124),sp@(108) + movel sp@(128),sp@(112) + movel sp@(132),sp@(116) + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + jbsr a3@ +L261: + btst #6,a4@(90) + jeq L193 + movel d6,a1 + movew a1@(18),a0 + subw a4@(88),a0 + movel a0,d4 + addl a4@(84),d4 + movel #-2142480864,sp@(80) + movel d4,d0 + jge L265 + clrl d0 +L265: + movel d0,sp@(84) + clrl sp@(88) + movel #264,sp@(108) + lea sp@(80),a2 + movel a2,sp@(112) + movel d6,a0 + movel a0@(4),sp@(116) + clrl sp@(120) + movel sp@(108),sp@(92) + movel a2,sp@(96) + movel sp@(116),sp@(100) + movel sp@(120),sp@(104) + movel sp@(76),a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea sp@(92),a1 + movel sp@(76),a2 + jbsr a3@ + jra L193 + .even +L268: + movel a4@(90),d2 + jge L193 + movel d6,a2 + tstw a2@(18) + jge L270 + movel a4@(4),d1 + jeq L270 + movel #-2142480887,sp@(100) + moveq #1,d0 + movel d0,sp@(104) + movel #-2142480895,d0 + btst #0,d2 + jeq L271 + moveq #1,d0 +L271: + movel d0,sp@(108) + subql #1,d1 + movel d1,sp@(112) + clrl sp@(116) + movel sp@(100),sp@(80) + movel sp@(104),sp@(84) + movel d0,sp@(88) + movel d1,sp@(92) + movel sp@(116),sp@(96) + lea sp@(120),a1 + movel #264,sp@(136) + lea sp@(80),a0 + movel a0,sp@(140) + movel d6,a2 + movel a2@(4),sp@(144) + clrl sp@(148) + movel sp@(136),a1@ + movel sp@(140),sp@(124) + movel sp@(144),sp@(128) + movel sp@(148),sp@(132) +L282: + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + jbsr a3@ + jra L193 + .even +L270: + movel d6,a0 + movew a0@(18),d0 + extl d0 + movel a4@(60),d1 + addl a4@(64),d1 + divsl d1,d0 + movel a4@(16),d1 + cmpl d0,d1 + jgt L193 + movel #-2142480886,sp@(100) + moveq #1,d0 + movel d0,sp@(104) + movel #-2142480895,d0 + btst #0,a4@(93) + jeq L275 + moveq #1,d0 +L275: + movel d0,sp@(108) + addl a4@(4),d1 + movel d1,sp@(112) + clrl sp@(116) + movel sp@(100),sp@(80) + movel sp@(104),sp@(84) + movel d0,sp@(88) + movel d1,sp@(92) + movel sp@(116),sp@(96) + lea sp@(120),a1 + movel #264,sp@(136) + lea sp@(80),a0 + movel a0,sp@(140) + movel d6,a2 + movel a2@(4),sp@(144) + clrl sp@(148) + movel sp@(136),a1@ + movel sp@(140),sp@(124) + movel sp@(144),sp@(128) + movel sp@(148),sp@(132) + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + jbsr a3@ +L193: + movel sp@(68),d0 + moveml sp@+,#0x7cfc + lea sp@(140),sp + rts + .even +_LV_GMLayout: + lea sp@(-64),sp + moveml #0x3f3e,sp@- + movel a1,a5 + movel d0,sp@(44) + clrl d0 + movew a0@(32),d0 + lea a5@(0,d0:l),a4 + bset #5,a4@(90) + lea a4@(142),a2 + movel a2,d0 + movel sp@(44),a3 + movel a3@(4),a0 + jbsr _GetGadgetBox + lea a4@(150),a0 + movew a2@,a0@ + movew a2@(2),a0@(2) + movew a2@,d0 + addw a2@(4),d0 + subqw #1,d0 + movew d0,a0@(4) + movew a2@(2),d0 + addw a2@(6),d0 + subqw #1,d0 + movew d0,a0@(6) + clrl d0 + movel a5@(18),a0 + tstl a0 + jeq L289 + btst #2,a5@(13) + jeq L289 + cmpw #-1,a0@(8) + seq d0 + extbl d0 + negl d0 +L289: + moveq #64,d3 + addl sp,d3 + moveq #84,d2 + addl sp,d2 + moveq #88,d6 + addl sp,d6 + lea sp@(92),a1 + moveq #76,d4 + addl sp,d4 + moveq #80,d5 + addl sp,d5 + tstw d0 + jeq L288 + movel #519,sp@(64) + lea a4@(142),a0 + movel a0,sp@(68) + lea a4@(158),a2 + movel a2,sp@(72) + movel sp@(44),a3 + movel a3@(4),a0 + movel a0@(30),sp@(76) + clrl sp@(80) + movel d2,a0 + movel d3,a2 + movel a2@,a0@ + movel d6,a3 + movel sp@(68),a3@ + movel sp@(72),a1@ + movel d4,a0 + movel a0@,sp@(96) + movel d5,a1 + movel a1@,sp@(100) + movel a5@(18),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + movel d2,a1 + jbsr a3@ +L288: + movel a4@(138),d0 + jeq L291 + movel _GfxBase,a1 + movel a1,a6 + movel d0,a0 + jbsr a1@(-528) + movel _GfxBase,a2 + movel a2,a6 + lea a4@(150),a1 + movel a4@(138),a0 + jbsr a2@(-510) +L291: + tstl a4@(134) + jne L292 + movel sp@(44),a2 + movel a2@(4),a0 + movel a0@(30),a0 + movel a0@(8),a4@(134) + tstl a4@(60) + jne L298 + movel a4@(134),a0 + clrl d0 + movew a0@(20),d0 + movel d0,a4@(60) +L292: + tstl a4@(60) + jeq L294 +L298: + tstl a4@(138) + jeq L295 + movew a4@(148),a2 + movel a4@(60),d0 + lea a2@(0,d0:l),a1 + movel a4@(64),a0 + lea a0@(-1,a1:l),a1 + movel a1,d1 + addl a0,d0 + divsl d0,d1 + movel a2,d0 + jra L297 + .even +L295: + movew a4@(148),a0 + movel a4@(64),d0 + movel a0,d1 + addl d0,d1 + addl a4@(60),d0 + divsl d0,d1 + movel a0,d0 + jra L297 + .even +L294: + clrl d1 + movew a4@(148),d0 + extl d0 +L297: + movel d0,d7 + divsl a4@(72),d7 + movel d7,a4@(68) + movel #-2142480878,sp@(64) + movel d1,sp@(68) + clrl sp@(72) + movel #264,sp@(48) + movel d3,sp@(52) + movel sp@(44),a0 + movel a0@(4),sp@(56) + clrl sp@(60) + movel d4,a1 + movel sp@(48),a1@ + movel d5,a2 + movel sp@(52),a2@ + movel d2,a3 + movel sp@(56),a3@ + movel d6,a0 + movel sp@(60),a0@ + movel a5@(-4),a0 + movel a0@(8),a3 + lea sp@(76),a1 + movel a5,a2 + jbsr a3@ + bclr #5,a4@(90) + moveml sp@+,#0x7cfc + lea sp@(64),sp + rts + .even +_LV_OMSet: + link a5,#-188 + moveml #0x3f3a,sp@- + movel a0,d7 + movel a1,d5 + movel d0,a5@(-188) + clrl d0 + movew a0@(32),d0 + movel d5,a4 + addl d0,a4 + movel a5@(-188),a0 + movel a0@(4),a5@(-184) + clrw d4 + movel a5,d6 + addl #-184,d6 + jra L300 + .even +L302: + movel a0@,d0 + cmpl #-2142480884,d0 + jhi L583 + cmpl #-2142480885,d0 + jcc L300 + cmpl #-2142480891,d0 + jeq L352 + jhi L584 + cmpl #-2142480894,d0 + jeq L318 + jhi L585 + cmpl #-2147287024,d0 + jeq L304 + cmpl #-2142480895,d0 + jeq L306 + jra L581 + .even +L585: + cmpl #-2142480893,d0 + jeq L300 + cmpl #-2142480892,d0 + jeq L326 + jra L581 + .even +L584: + cmpl #-2142480888,d0 + jeq L422 + jhi L586 + cmpl #-2142480890,d0 + jeq L374 + cmpl #-2142480889,d0 + jeq L404 + jra L581 + .even +L586: + cmpl #-2142480887,d0 + jeq L430 + cmpl #-2142480886,d0 + jeq L433 + jra L581 + .even +L583: + cmpl #-2142480879,d0 + jeq L524 + jhi L587 + cmpl #-2142480882,d0 + jeq L465 + jcs L438 + cmpl #-2142480881,d0 + jeq L489 + cmpl #-2142480880,d0 + jeq L516 + jra L581 + .even +L587: + cmpl #-2142480865,d0 + jeq L571 + jhi L588 + cmpl #-2142480878,d0 + jeq L543 + cmpl #-2142480876,d0 + jeq L554 + jra L581 + .even +L588: + cmpl #-2142480864,d0 + jeq L572 + cmpl #-2142480850,d0 + jeq L580 + jra L581 + .even +L304: + movel a5@(-188),a1 + cmpl #259,a1@ + jne L300 + movel d5,a2 + movew a0@(6),a2@(38) + jra L300 + .even +L306: + tstl a4@ + jeq L300 + movel a0@(4),d1 + moveq #-1,d0 + cmpl d1,d0 + jeq L308 + movel a4@(12),d2 + movel d1,d0 + cmpl d0,d2 + jgt L309 + movel d2,d0 + subql #1,d0 +L309: + movel d0,d1 +L308: + movel a4@(24),a0 + cmpl a0,d1 + jeq L300 + movel a4@(4),d2 + cmpl a0,d2 + jgt L314 + movel d2,d0 + addl a4@(16),d0 + cmpl a0,d0 + jgt L313 +L314: + cmpl d1,d2 + jgt L312 + movel d2,d0 + addl a4@(16),d0 + cmpl d1,d0 + jle L312 +L313: + orw #8,d4 +L312: + movel d1,a4@(24) + moveq #-1,d0 + cmpl d1,d0 + jne L315 + clrl a4@(28) + jra L396 + .even +L315: + movel #517,a5@(-12) + movel d1,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) + jra L396 + .even +L318: + movel a0@(4),d2 + cmpl a4@(4),d2 + jeq L300 + tstl a4@ + jeq L300 + movel a4@(16),a0 + movel d2,d0 + addl a0,d0 + movel a4@(12),d1 + cmpl d0,d1 + jgt L321 + cmpl d1,a0 + slt d0 + moveb d0,d2 + extbl d2 + subl a0,d1 + andl d1,d2 +L321: + movel d2,a4@(4) + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d2,d0 + movel d0,a4@(20) + movel #517,a5@(-12) + movel d2,a5@(-8) + jra L755 + .even +L326: + movel a4@(32),d1 + cmpl a4@(36),d1 + jcs L327 + movel _IntuitionBase,d0 + movel d0,a0 + lea a0@(-96),a2 + movel a5@(-188),a0 + movel a0@(8),a1 + clrl d1 + tstl a1 + jeq L328 + movel a1@,d1 +L328: + movel d0,a6 + movel d1,a0 + jbsr a2@ + jra L300 + .even +L327: + tstl a4@ + jeq L300 + movel a0@(4),d1 + movel a4@(12),d0 + movel d0,d3 + subql #1,d3 + cmpl d1,d0 + jle L332 + movel d1,d3 +L332: + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L336 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + jgt L335 +L336: + cmpl d3,d1 + jgt L334 + movel d1,d0 + addl a4@(16),d0 + cmpl d3,d0 + jle L334 +L335: + orw #8,d4 +L334: + movel d3,a4@(24) + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) + movel d0,a1 + movel a4@(90),d0 + btst #3,d0 + jeq L339 + movel a4@(76),a0 + tstl a0 + jeq L340 + movel a0@(d3:l:4),d0 + jra L341 + .even +L340: + btst #28,d0 + jeq L610 + tstl a1 + jne L611 + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L345 +L611: + clrl d0 + moveb a1@(8),d0 + jra L341 + .even +L345: + clrl d0 + jra L341 + .even +L339: + cmpl a4@(24),d3 + seq d0 + extbl d0 + negl d0 +L341: + tstl d0 + jne L396 +L610: + movel a4@(32),d0 + movel d0,a1 + addql #1,a1 + movel a1,a4@(32) + movel a4@(76),a0 + tstl a0 + jeq L401 + addql #1,d0 + movel d0,a0@(d3:l:4) + jra L396 + .even +L352: + tstl a4@ + jeq L300 + movel a0@(4),d1 + movel a4@(12),d0 + movel d0,d3 + subql #1,d3 + cmpl d1,d0 + jle L354 + movel d1,d3 +L354: + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L358 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + jgt L357 +L358: + cmpl d3,d1 + jgt L356 + movel d1,d0 + addl a4@(16),d0 + cmpl d3,d0 + jle L356 +L357: + orw #8,d4 +L356: + movel d3,a4@(24) + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) + movel d0,a1 + movel a4@(90),d0 + btst #3,d0 + jeq L361 + movel a4@(76),a0 + tstl a0 + jeq L362 + movel a0@(d3:l:4),d0 + jra L363 + .even +L362: + btst #28,d0 + jeq L300 + tstl a1 + jne L612 + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L367 +L612: + clrl d0 + moveb a1@(8),d0 + jra L363 + .even +L367: + clrl d0 + jra L363 + .even +L361: + cmpl a4@(24),d3 + seq d0 + extbl d0 + negl d0 +L363: + tstl d0 + jeq L300 +L771: + subql #1,a4@(32) + movel a4@(76),a0 + tstl a0 + jne L770 + btst #4,a4@(90) + jeq L396 + movel a4@(28),a0 + clrb a0@(8) + jra L396 + .even +L374: + tstl a4@ + jeq L300 + movel a0@(4),d1 + movel a4@(12),d0 + movel d0,d3 + subql #1,d3 + cmpl d1,d0 + jle L376 + movel d1,d3 +L376: + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L380 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + jgt L379 +L380: + cmpl d3,d1 + jgt L378 + movel d1,d0 + addl a4@(16),d0 + cmpl d3,d0 + jle L378 +L379: + orw #8,d4 +L378: + movel d3,a4@(24) + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) + movel d0,a1 + movel a4@(24),d1 + movel a4@(90),d0 + btst #3,d0 + jeq L383 + movel a4@(76),a0 + tstl a0 + jeq L384 + movel a0@(d1:l:4),d0 + jra L385 + .even +L384: + btst #28,d0 + jeq L382 + tstl a1 + jne L613 + movel #517,a5@(-12) + movel d1,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L389 +L613: + clrl d0 + moveb a1@(8),d0 + jra L385 + .even +L389: + clrl d0 + jra L385 + .even +L383: + moveq #1,d0 +L385: + tstl d0 + jeq L382 + jra L771 + .even +L770: + movel a4@(24),d0 + clrl a0@(d0:l:4) + jra L396 + .even +L382: + movel a4@(32),d1 + cmpl a4@(36),d1 + jcs L397 + movel _IntuitionBase,d0 + movel d0,a0 + lea a0@(-96),a2 + movel a5@(-188),a0 + movel a0@(8),a1 + clrl d1 + tstl a1 + jeq L398 + movel a1@,d1 +L398: + movel d0,a6 + movel d1,a0 + jbsr a2@ + jra L396 + .even +L397: + movel d1,a1 + addql #1,a1 + movel a1,a4@(32) + movel a4@(76),a0 + tstl a0 + jeq L401 + movel a4@(24),d0 + addql #1,d1 + movel d1,a0@(d0:l:4) + jra L396 + .even +L401: + btst #4,a4@(90) + jeq L396 + movel a4@(28),a0 + moveb a4@(35),a0@(8) +L396: + orw #16,d4 + jra L300 + .even +L404: + tstl a4@ + jeq L300 + movel a0@(4),d3 + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L408 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + jgt L407 +L408: + cmpl d3,d1 + jgt L406 + movel d1,d0 + addl a4@(16),d0 + cmpl d3,d0 + jle L406 +L407: + orw #8,d4 +L406: + moveq #-1,d0 + movel d0,a4@(24) + clrl a4@(28) + clrl a4@(32) + tstl a4@(76) + jeq L409 + clrl d1 + movew d4,d0 + orw #18,d0 + cmpl a4@(12),d1 + jge L415 + .even +L413: + movel a4@(76),a0 + clrl a0@(d1:l:4) + addql #1,d1 + cmpl a4@(12),d1 + jlt L413 + jra L415 + .even +L409: + movew d4,d0 + orw #18,d0 + btst #4,a4@(90) + jeq L415 + movel a4@,a0 + jra L757 + .even +L420: + clrb a0@(8) +L757: + movel a0@,a0 + tstl a0@ + jne L420 +L415: + movew d0,d4 + jra L300 + .even +L422: + movel a0@(4),d1 + jge L423 + clrl d1 +L423: + movel a4@(12),d0 + cmpl d1,d0 + jgt L424 + movel d0,d1 + subql #1,d1 +L424: + movel a4@(4),d0 + cmpl d1,d0 + jle L425 + movel d1,a4@(4) + movel #517,a5@(-12) + movel d1,a5@(-8) + jra L755 + .even +L425: + movel a4@(16),d2 + addl d2,d0 + cmpl d1,d0 + jgt L300 + subl d2,d1 + movel d1,d0 + addql #1,d0 + jra L758 + .even +L430: + movel a4@(4),d0 + jle L300 + movel a4@,d1 + jeq L300 + movel d0,a0 + subql #1,a0 + movel a0,a4@(4) + movel a4@(8),a1 + movel #516,a5@(-12) + subql #1,d0 + movel d0,a5@(-8) + movel d1,a5@(-4) + movel a4@(114),a3 + lea a5@(-12),a2 + jra L759 + .even +L433: + movel a4@(4),d1 + movel d1,d0 + addl a4@(16),d0 + cmpl a4@(12),d0 + jge L300 + movel a4@,d0 + jeq L300 + movel d1,a1 + addql #1,a1 + movel a1,a4@(4) + movel a4@(8),a1 + movel #515,a5@(-12) + addql #1,d1 + movel d1,a5@(-8) + movel d0,a5@(-4) + movel a4@(110),a3 + lea a5@(-12),a2 + jra L759 + .even +L438: + movel a0@(4),d0 + moveq #-1,d1 + cmpl d0,d1 + jeq L760 + movel d0,a4@ + movel #_ListGetItem,a4@(106) + movel #_ListGetNext,a4@(110) + movel #_ListGetPrev,a4@(114) + movel #_ListStringDrawItem,a4@(126) + bset #4,a4@(90) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(-188),a2 + movel a2@(4),a0 + moveq #-1,d1 + movel #-2142480893,d0 + jbsr a1@(-36) + movel d0,a4@(12) + movew d4,d3 + orw #34,d3 + moveq #-1,d1 + cmpl d0,d1 + jne L441 + movel a4@,a0 + clrl d0 + tstl a0 + jeq L442 + movel a0@,a0 + jra L761 + .even +L446: + addql #1,d0 +L761: + movel a0@,a0 + tstl a0 + jne L446 +L442: + movel d0,a4@(12) +L441: + clrl d0 + movel a4@(90),d1 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L450 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L453 + cmpl d1,d4 + jle L728 + moveq #2,d4 + cmpl d1,d4 + jle L729 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L729: + tstl a3@+ + jeq L735 + addql #1,d0 +L735: + subql #1,a2 +L728: + tstl a3@+ + jeq L738 + addql #1,d0 +L738: + subql #1,a2 + tstl a2 + jeq L555 + .even +L453: + movel a3,a0 + tstl a0@+ + jeq L741 + addql #1,d0 +L741: + lea a3@(8),a1 + tstl a0@ + jeq L744 + addql #1,d0 +L744: + lea a3@(12),a0 + tstl a1@ + jeq L747 + addql #1,d0 +L747: + lea a3@(16),a3 + tstl a0@ + jeq L750 + addql #1,d0 +L750: + subql #4,a2 + tstl a2 + jne L453 + jra L555 + .even +L450: + btst #28,d1 + jeq L555 + movel a4@,a0 + tstl a0 + jeq L555 + movel a0@,a0 + jra L762 + .even +L460: + addql #1,d0 +L762: + movel a0@,a0 + tstl a0 + jne L460 + jra L555 + .even +L465: + movel a0@(4),d0 + moveq #-1,d1 + cmpl d0,d1 + jeq L760 + movel d0,a4@ + movel #_ArrayGetItem,a4@(106) + movel #_ArrayGetItem,a4@(110) + movel #_ArrayGetItem,a4@(114) + movel #_StringDrawItem,a4@(126) + bclr #4,a4@(90) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(-188),a2 + movel a2@(4),a0 + moveq #-1,d1 + movel #-2142480893,d0 + jbsr a1@(-36) + movel d0,a4@(12) + movew d4,d3 + orw #34,d3 + moveq #-1,d1 + cmpl d0,d1 + jne L468 + movel a4@,a0 + tstl a0 + jeq L468 + clrl d0 + tstl a0@ + jeq L470 + .even +L471: + addql #1,d0 + addql #4,a0 + tstl a0@ + jne L471 +L470: + movel d0,a4@(12) +L468: + clrl d0 + movel a4@(90),d1 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L474 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L477 + cmpl d1,d4 + jle L700 + moveq #2,d4 + cmpl d1,d4 + jle L701 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L701: + tstl a3@+ + jeq L707 + addql #1,d0 +L707: + subql #1,a2 +L700: + tstl a3@+ + jeq L710 + addql #1,d0 +L710: + subql #1,a2 + tstl a2 + jeq L555 + .even +L477: + movel a3,a0 + tstl a0@+ + jeq L713 + addql #1,d0 +L713: + lea a3@(8),a1 + tstl a0@ + jeq L716 + addql #1,d0 +L716: + lea a3@(12),a0 + tstl a1@ + jeq L719 + addql #1,d0 +L719: + lea a3@(16),a3 + tstl a0@ + jeq L722 + addql #1,d0 +L722: + subql #4,a2 + tstl a2 + jne L477 + jra L555 + .even +L474: + btst #28,d1 + jeq L555 + movel a4@,a0 + tstl a0 + jeq L555 + movel a0@,a0 + jra L763 + .even +L484: + addql #1,d0 +L763: + movel a0@,a0 + tstl a0 + jne L484 + jra L555 + .even +L489: + movel a0@(4),d0 + moveq #-1,d1 + cmpl d0,d1 + jeq L760 + movel d0,a4@ + movel #_ListGetItem,a4@(106) + movel #_ListGetNext,a4@(110) + movel #_ListGetPrev,a4@(114) + movel #_ListImageDrawItem,a4@(126) + bset #4,a4@(90) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(-188),a2 + movel a2@(4),a0 + moveq #-1,d1 + movel #-2142480893,d0 + jbsr a1@(-36) + movel d0,a4@(12) + movew d4,d3 + orw #34,d3 + moveq #-1,d1 + cmpl d0,d1 + jne L492 + movel a4@,a0 + clrl d0 + tstl a0 + jeq L493 + movel a0@,a0 + jra L764 + .even +L497: + addql #1,d0 +L764: + movel a0@,a0 + tstl a0 + jne L497 +L493: + movel d0,a4@(12) +L492: + clrl d0 + movel a4@(90),d1 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L501 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L504 + cmpl d1,d4 + jle L672 + moveq #2,d4 + cmpl d1,d4 + jle L673 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L673: + tstl a3@+ + jeq L679 + addql #1,d0 +L679: + subql #1,a2 +L672: + tstl a3@+ + jeq L682 + addql #1,d0 +L682: + subql #1,a2 + tstl a2 + jeq L555 + .even +L504: + movel a3,a0 + tstl a0@+ + jeq L685 + addql #1,d0 +L685: + lea a3@(8),a1 + tstl a0@ + jeq L688 + addql #1,d0 +L688: + lea a3@(12),a0 + tstl a1@ + jeq L691 + addql #1,d0 +L691: + lea a3@(16),a3 + tstl a0@ + jeq L694 + addql #1,d0 +L694: + subql #4,a2 + tstl a2 + jne L504 + jra L555 + .even +L501: + btst #28,d1 + jeq L555 + movel a4@,a0 + tstl a0 + jeq L555 + movel a0@,a0 + jra L765 + .even +L511: + addql #1,d0 +L765: + movel a0@,a0 + tstl a0 + jne L511 + jra L555 + .even +L516: + movel a0@(4),d0 + moveq #-1,d1 + cmpl d0,d1 + jeq L760 + movel d0,a4@ + movel #_ArrayGetItem,a4@(106) + movel #_ArrayGetItem,a4@(110) + movel #_ArrayGetItem,a4@(114) + movel #_ImageDrawItem,a4@(126) + bclr #4,a4@(90) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(-188),a2 + movel a2@(4),a0 + moveq #-1,d1 + movel #-2142480893,d0 + jbsr a1@(-36) + movel d0,a4@(12) + movew d4,d3 + orw #34,d3 + moveq #-1,d1 + cmpl d0,d1 + jne L766 + movel a4@,a0 + tstl a0 + jeq L766 + clrl d0 + tstl a0@ + jeq L521 + .even +L522: + addql #1,d0 + addql #4,a0 + tstl a0@ + jne L522 +L521: + movel d0,a4@(12) + jra L766 + .even +L524: + movel a0@(4),a1 + moveq #-1,d0 + cmpl a1,d0 + jne L525 +L760: + clrl a4@ + jra L300 + .even +L525: + movel a1,a4@ + clrl d0 + movel a4@(90),d1 + movew d4,d3 + orw #34,d3 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L528 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L531 + cmpl d1,d4 + jle L644 + moveq #2,d4 + cmpl d1,d4 + jle L645 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L645: + tstl a3@+ + jeq L651 + addql #1,d0 +L651: + subql #1,a2 +L644: + tstl a3@+ + jeq L654 + addql #1,d0 +L654: + subql #1,a2 + tstl a2 + jeq L555 + .even +L531: + movel a3,a0 + tstl a0@+ + jeq L657 + addql #1,d0 +L657: + lea a3@(8),a1 + tstl a0@ + jeq L660 + addql #1,d0 +L660: + lea a3@(12),a0 + tstl a1@ + jeq L663 + addql #1,d0 +L663: + lea a3@(16),a3 + tstl a0@ + jeq L666 + addql #1,d0 +L666: + subql #4,a2 + tstl a2 + jne L531 + jra L555 + .even +L528: + btst #28,d1 + jeq L555 + tstl a1 + jeq L555 + movel a1@,a0 + jra L767 + .even +L538: + addql #1,d0 +L767: + movel a0@,a0 + tstl a0 + jne L538 + jra L555 + .even +L543: + movel a0@(4),a4@(16) + orw #32,d4 + tstl a4@(138) + jeq L544 + movel a4@(60),d1 + addl a4@(64),d1 + mulsl a4@(12),d1 + movew a4@(148),a0 + movel a4@(20),d0 + addl a0,d0 + cmpl d0,d1 + jgt L300 + movel d1,d0 + subl a0,d0 + movel d0,a4@(20) + jge L546 + clrl a4@(20) +L546: + movel a4@(60),d0 + addl a4@(64),d0 + movel a4@(20),d1 + divsl d0,d1 + cmpl a4@(4),d1 + jeq L768 + movel d1,a4@(4) + movel #517,a5@(-12) + movel d1,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(8) + jra L768 + .even +L544: + movel a4@(16),d2 + movel a4@(4),d0 + addl d2,d0 + movel a4@(12),d1 + cmpl d0,d1 + jgt L300 + cmpl d1,d2 + slt d0 + extbl d0 + subl d2,d1 + andl d1,d0 + movel d0,a4@(4) + movel #517,a5@(-12) + movel d0,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(8) + movel a4@(60),d0 + addl a4@(64),d0 + mulsl a4@(4),d0 + movel d0,a4@(20) +L768: + orw #4,d4 + jra L300 + .even +L554: + movel a0@(4),a4@(76) + clrl d0 + movel a4@(90),d1 + movew d4,d3 + orw #2,d3 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L556 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L559 + cmpl d1,d4 + jle L617 + moveq #2,d4 + cmpl d1,d4 + jle L618 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L618: + tstl a3@+ + jeq L624 + addql #1,d0 +L624: + subql #1,a2 +L617: + tstl a3@+ + jeq L627 + addql #1,d0 +L627: + subql #1,a2 + tstl a2 + jeq L555 + .even +L559: + movel a3,a0 + tstl a0@+ + jeq L630 + addql #1,d0 +L630: + lea a3@(8),a1 + tstl a0@ + jeq L633 + addql #1,d0 +L633: + lea a3@(12),a0 + tstl a1@ + jeq L636 + addql #1,d0 +L636: + lea a3@(16),a3 + tstl a0@ + jeq L639 + addql #1,d0 +L639: + subql #4,a2 + tstl a2 + jne L559 + jra L555 + .even +L556: + btst #28,d1 + jeq L555 + movel a4@,a0 + tstl a0 + jeq L555 + movel a0@,a0 + jra L769 + .even +L566: + addql #1,d0 +L769: + movel a0@,a0 + tstl a0 + jne L566 +L555: + movel d0,a4@(32) +L766: + movew d3,d4 + jra L300 + .even +L571: + movel a0@(4),a4@(36) + jra L300 + .even +L572: + movel a0@(4),d1 + cmpl a4@(20),d1 + jeq L300 + tstl a4@ + jeq L300 + movel a4@(60),d0 + jeq L300 + movel d1,a4@(20) + orw #4,d4 + addl a4@(64),d0 + movel d1,d3 + divsl d0,d3 + movel a4@(16),d2 + movel d3,d0 + addl d2,d0 + movel a4@(12),d1 + cmpl d0,d1 + jgt L574 + cmpl d1,d2 + slt d0 + extbl d0 + subl d2,d1 + andl d1,d0 + jra L575 + .even +L574: + movel d3,d0 +L575: + cmpl a4@(4),d0 + jeq L300 +L758: + movel d0,a4@(4) + movel #517,a5@(-12) + movel d0,a5@(-8) +L755: + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 +L759: + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(8) + orw #20,d4 + jra L300 + .even +L580: + movel a0@(4),a4@(72) + movew a4@(148),d0 + extl d0 + movel d0,d1 + divsl a4@(72),d1 + movel d1,a4@(68) + jra L300 + .even +L581: + orw #1,d4 +L300: + movel _UtilityBase,a1 + movel a1,a6 + movel d6,a0 + jbsr a1@(-48) + movel d0,a0 + tstl a0 + jne L302 + btst #0,d4 + jeq L590 + movel d7,a1 + movel a1@(24),a0 + movel a0@(8),a3 + movel a5@(-188),a1 + movel d5,a2 + jbsr a3@ + movel d0,d3 + jra L592 + .even +L590: + moveq #1,d3 +L592: + movew d4,d0 + andw #14,d0 + jeq L593 + movel a5@(-188),a2 + movel a2@(8),d0 + jeq L593 + btst #5,a4@(90) + jne L593 + movel _IntuitionBase,a1 + movel a1,a6 + movel d0,a0 + jbsr a1@(-558) + movel d0,d2 + jeq L593 + btst #1,d4 + jeq L595 + moveq #1,d0 + movel d0,a5@(-44) + movel a2@(8),a5@(-40) + movel d2,a5@(-36) + movel d0,a5@(-32) + movel d0,a5@(-28) + movel a5@(-40),a5@(-24) + movel d2,a5@(-20) + movel d0,a5@(-16) + movel d5,a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea a5@(-28),a1 + movel d5,a2 + jbsr a3@ + jra L596 + .even +L595: + btst #2,d4 + jeq L597 + moveq #1,d0 + movel d0,a5@(-28) + movel a5@(-188),a0 + movel a0@(8),a5@(-24) + movel d2,a5@(-20) + moveq #2,d0 + movel d0,a5@(-16) + movel a5@(-28),a5@(-44) + movel a5@(-24),a5@(-40) + movel d2,a5@(-36) + movel d0,a5@(-32) + movel d5,a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea a5@(-44),a1 + movel d5,a2 + jbsr a3@ +L597: + btst #3,d4 + jeq L596 + moveq #1,d0 + movel d0,a5@(-28) + movel a5@(-188),a0 + movel a0@(8),a5@(-24) + movel d2,a5@(-20) + clrl a5@(-16) + movel d0,a5@(-44) + movel a5@(-24),a5@(-40) + movel d2,a5@(-36) + movel a5@(-16),a5@(-32) + movel d5,a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea a5@(-44),a1 + movel d5,a2 + jbsr a3@ +L596: + movel _IntuitionBase,a1 + movel a1,a6 + movel d2,a0 + jbsr a1@(-564) +L593: + btst #5,d4 + jeq L599 + movel #-2142480894,a5@(-180) + movel a4@(4),a5@(-176) + movel #-2142480893,a5@(-172) + movel a4@(12),a5@(-168) + movel #-2142480878,a5@(-164) + movel a4@(16),a5@(-160) + movel #-2142480895,a5@(-156) + movel a4@(24),a5@(-152) + movel #-2142480864,a5@(-148) + movel a4@(20),a5@(-144) + movel #-2142480863,a5@(-140) + movel a4@(60),d0 + addl a4@(64),d0 + movel a4@(12),d1 + mulsl d0,d1 + movel d1,a5@(-136) + movel #-2142480862,a5@(-132) + tstl a4@(138) + jeq L600 + movew a4@(148),d0 + extl d0 + jra L601 + .even +L600: + mulsl a4@(16),d0 +L601: + movel d0,a5@(-128) + movel #-2147287024,a5@(-124) + movel d5,a0 + clrl d0 + movew a0@(38),d0 + movel d0,a5@(-120) + clrl a5@(-116) + moveq #-112,d2 + addl a5,d2 + pea 68:w + movel d2,sp@- + pea a5@(-180) + jbsr _bcopy + lea sp@(12),sp + movel #263,a5@(-28) + movel d2,a5@(-24) + movel a5@(-188),a1 + movel a1@(8),a5@(-20) + clrl d0 + cmpl #264,a1@ + jne L602 + movel a1@(12),d0 +L602: + movel d0,a5@(-16) + movel a5@(-28),a5@(-44) + movel a5@(-24),a5@(-40) + movel a5@(-20),a5@(-36) + movel d0,a5@(-32) + movel d5,a2 + movel a2@(-4),a0 + movel a0@(8),a3 + lea a5@(-44),a1 + jbsr a3@ + jra L604 + .even +L599: + btst #4,d4 + jeq L604 + clrl d1 + btst #2,d4 + jeq L606 + movel #-2142480894,a5@(-180) + movel a4@(4),a5@(-176) + movel #-2142480864,a5@(-172) + movel a4@(60),d0 + addl a4@(64),d0 + mulsl a4@(4),d0 + movel d0,a5@(-168) + moveq #4,d1 +L606: + lea a5@(-180),a0 + btst #3,d4 + jeq L607 + movel #-2142480895,a0@(d1:l:4) + addql #1,d1 + movel a4@(24),a0@(d1:l:4) + addql #1,d1 +L607: + movel #-2147287024,a0@(d1:l:4) + addql #1,d1 + movel d5,a1 + clrl d0 + movew a1@(38),d0 + movel d0,a0@(d1:l:4) + clrl a0@(4,d1:l:4) + movel #263,a5@(-128) + movel a0,a5@(-124) + movel a5@(-188),a2 + movel a2@(8),a5@(-120) + clrl d0 + cmpl #264,a2@ + jne L608 + movel a2@(12),d0 +L608: + movel d0,a5@(-116) + movel a5@(-128),a5@(-144) + movel a5@(-124),a5@(-140) + movel a5@(-120),a5@(-136) + movel d0,a5@(-132) + movel d5,a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea a5@(-144),a1 + movel d5,a2 + jbsr a3@ +L604: + movel d3,d0 + moveml a5@(-228),#0x5cfc + unlk a5 + rts +.data + .even +_boolMap.69: + .long -2147286999 + .long 1 + .long -2142480872 + .long 2 + .long -2142480873 + .long 4 + .long -2142480871 + .long 8 + .long 0 +.text + .even +_LV_OMNew: + lea sp@(-28),sp + moveml #0x383e,sp@- + movel a0,a4 + movel a1,d4 + movel d0,a5 + movel a4@(24),a0 + movel a0@(8),a3 + movel a5,a1 + movel d4,a2 + jbsr a3@ + movel d0,d4 + jeq L789 + movel d4,a0 + tstw a0@(12) + jge L791 + moveq #4,d0 + orl d0,a0@(44) +L791: + clrl d0 + movew a4@(32),d0 + movel d4,a4 + addl d0,a4 + movel _UtilityBase,a2 + movel a2,a6 + lea _boolMap.69,a1 + movel a5@(4),a0 + moveq #4,d0 + jbsr a2@(-42) + movel d0,a4@(90) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2147287007,d0 + jbsr a1@(-36) + movel d0,a2 + tstl a2 + jeq L792 + movel a2@(8),a4@(134) + jra L793 + .even +L792: + clrl a4@(134) +L793: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + movel #-2142480867,d0 + jbsr a1@(-30) + movel d0,a0 + tstl a0 + jeq L794 + movel a0@(4),d0 + jeq L796 + jra L902 + .even +L794: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2147287000,d0 + jbsr a1@(-36) + tstl d0 + jeq L796 + movel _GfxBase,a1 + movel a1,a6 + movel d0,a0 + jbsr a1@(-72) + tstl d0 + jeq L796 + bset #3,a4@(90) +L902: + movel d0,a4@(134) +L796: + movel a4@(134),a0 + tstl a0 + jeq L799 + clrl d0 + movew a0@(20),d0 + movel d0,a4@(60) + jra L800 + .even +L799: + clrl a4@(60) +L800: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + movel a4@(60),d1 + movel #-2142480869,d0 + jbsr a1@(-36) + movel d0,a4@(60) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2147254270,d0 + jbsr a1@(-36) + movel d0,a4@(64) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + movel #-2142480868,d0 + jbsr a1@(-30) + movel d0,a0 + tstl a0 + jeq L801 + movel a0@(4),a4@(94) + jra L802 + .even +L801: + tstl a2 + jeq L803 + movel a2@(4),a0 + movew a0@(14),d1 + movew a0@(4),d0 + cmpw d1,d0 + jcc L806 + clrl d2 + movew d1,d2 + jra L807 + .even +L806: + clrl d2 + movew d0,d2 +L807: + movew a0@(10),d1 + movew a0@(12),d0 + cmpw d1,d0 + jcc L808 + clrl d0 + movew d1,d0 + cmpl d2,d0 + jlt L809 + jra L804 + .even +L808: + andl #0xFFFF,d0 + cmpl d2,d0 + jge L804 +L809: + movew a0@(14),d1 + movew a0@(4),d0 + cmpw d1,d0 + jcs L903 + jra L812 + .even +L804: + movew a0@(10),d1 + movew a0@(12),d0 + cmpw d1,d0 + jcc L812 +L903: + clrl d0 + movew d1,d0 + jra L805 + .even +L812: + andl #0xFFFF,d0 +L805: + movel d0,a4@(94) + jra L802 + .even +L803: + moveq #-1,d1 + movel d1,a4@(94) +L802: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + moveq #-1,d1 + movel #-2142480893,d0 + jbsr a1@(-36) + movel d0,a4@(12) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2142480883,d0 + jbsr a1@(-36) + movel d0,a0 + movel a0,a4@ + jeq L815 + movel #_ListGetItem,a4@(106) + movel #_ListGetNext,a4@(110) + movel #_ListGetPrev,a4@(114) + movel #_ListStringDrawItem,a4@(126) + bset #4,a4@(90) + moveq #-1,d3 + cmpl a4@(12),d3 + jne L824 + clrl d0 + movel a0@,a0 + jra L904 + .even +L821: + addql #1,d0 +L904: + movel a0@,a0 + tstl a0 + jne L821 + jra L845 + .even +L815: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2142480882,d0 + jbsr a1@(-36) + movel d0,a0 + movel a0,a4@ + jeq L825 + movel #_ArrayGetItem,a4@(106) + movel #_ArrayGetItem,a4@(110) + movel #_ArrayGetItem,a4@(114) + movel #_StringDrawItem,a4@(126) + moveq #-1,d0 + cmpl a4@(12),d0 + jne L824 + clrl d0 + tstl a0@ + jeq L845 + .even +L829: + addql #1,d0 + addql #4,a0 + tstl a0@ + jne L829 + jra L845 + .even +L825: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2142480881,d0 + jbsr a1@(-36) + movel d0,a0 + movel a0,a4@ + jeq L832 + movel #_ListGetItem,a4@(106) + movel #_ListGetNext,a4@(110) + movel #_ListGetPrev,a4@(114) + movel #_ListImageDrawItem,a4@(126) + bset #4,a4@(90) + moveq #-1,d1 + cmpl a4@(12),d1 + jne L824 + clrl d0 + movel a0@,a0 + jra L905 + .even +L838: + addql #1,d0 +L905: + movel a0@,a0 + tstl a0 + jne L838 + jra L845 + .even +L832: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2142480880,d0 + jbsr a1@(-36) + movel d0,a0 + movel a0,a4@ + jeq L824 + movel #_ArrayGetItem,a4@(106) + movel #_ArrayGetItem,a4@(110) + movel #_ArrayGetItem,a4@(114) + movel #_ImageDrawItem,a4@(126) + moveq #-1,d3 + cmpl a4@(12),d3 + jne L824 + clrl d0 + tstl a0@ + jeq L845 + .even +L846: + addql #1,d0 + addql #4,a0 + tstl a0@ + jne L846 +L845: + movel d0,a4@(12) +L824: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2142480876,d0 + jbsr a1@(-36) + movel d0,a4@(76) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + moveq #-1,d1 + movel #-2142480865,d0 + jbsr a1@(-36) + movel d0,a4@(36) + clrl d0 + movel a4@(90),d1 + btst #3,d1 + jeq L848 + movel a4@(76),d2 + jeq L849 + movel a4@(12),d1 + cmpl d0,d1 + jle L848 + movel d2,a2 + movel d1,d2 + negl d1 + moveq #3,d3 + andl d3,d1 + jeq L852 + cmpl d1,d3 + jle L874 + moveq #2,d3 + cmpl d1,d3 + jle L875 + tstl a2@+ + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,d2 +L875: + tstl a2@+ + jeq L881 + addql #1,d0 +L881: + subql #1,d2 +L874: + tstl a2@+ + jeq L884 + addql #1,d0 +L884: + subql #1,d2 + jeq L848 + .even +L852: + movel a2,a0 + tstl a0@+ + jeq L887 + addql #1,d0 +L887: + lea a2@(8),a1 + tstl a0@ + jeq L890 + addql #1,d0 +L890: + lea a2@(12),a0 + tstl a1@ + jeq L893 + addql #1,d0 +L893: + lea a2@(16),a2 + tstl a0@ + jeq L896 + addql #1,d0 +L896: + subql #4,d2 + jne L852 + jra L848 + .even +L849: + btst #28,d1 + jeq L848 + movel a4@,a0 + tstl a0 + jeq L848 + movel a0@,a0 + jra L906 + .even +L859: + addql #1,d0 +L906: + movel a0@,a0 + tstl a0 + jne L859 +L848: + movel d0,a4@(32) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2142480878,d0 + jbsr a1@(-36) + movel d0,a4@(16) + jeq L864 + movel #-2147287033,sp@(32) + movel a4@(60),d0 + addl a4@(64),d0 + mulsl a4@(16),d0 + movel d0,sp@(36) + clrl sp@(40) + movel sp@(32),sp@(44) + movel d0,sp@(48) + movel sp@(40),sp@(52) + movel _IntuitionBase,a2 + movel a2,a6 + lea sp@(44),a1 + movel d4,a0 + jbsr a2@(-648) +L864: + movel _UtilityBase,d2 + movel d2,a0 + lea a0@(-36),a2 + movel a5@(4),d3 + movel d2,a6 + movel d3,a0 + clrl d1 + movel #-2142480894,d0 + jbsr a2@ + movel d3,a0 + movel d0,d1 + movel #-2142480888,d0 + jbsr a2@ + movel d0,d1 + movel d1,a4@(4) + movel d1,a4@(40) + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d1,d0 + movel d0,a4@(20) + movel d0,a4@(44) + tstl a4@ + jeq L865 + movel #517,sp@(32) + movel d1,sp@(36) + movel a4@,sp@(40) + movel a4@(106),a3 + lea sp@(32),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(8) +L865: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + moveq #2,d1 + movel #-2142480850,d0 + jbsr a1@(-36) + movel d0,a4@(72) + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + moveq #-1,d1 + movel #-2142480895,d0 + jbsr a1@(-36) + movel d0,a4@(24) + movel d0,a4@(48) + moveq #-1,d1 + cmpl d0,d1 + jeq L867 + movel #517,sp@(32) + movel d0,sp@(36) + movel a4@,sp@(40) + movel a4@(106),a3 + lea sp@(32),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) +L867: + movel _UtilityBase,a1 + movel a1,a6 + movel a5@(4),a0 + clrl d1 + movel #-2142480875,d0 + jbsr a1@(-36) + movel d0,a0 + movel a0,a4@(130) + jeq L869 + movel a0@(8),a4@(126) +L869: + btst #1,a4@(93) + jeq L789 + movel _GfxBase,a0 + movel a0,a6 + jbsr a0@(-516) + movel d0,a4@(138) +L789: + movel d4,d0 + moveml sp@+,#0x7c1c + lea sp@(28),sp + rts +LC0: + .ascii "gadgetclass\0" + .even +.globl _MakeListViewClass +_MakeListViewClass: + moveml #0x32,sp@- + movel _IntuitionBase,a3 + movel a3,a6 + clrl d1 + moveq #89,d0 + notb d0 + subl a2,a2 + lea LC0,a1 + subl a0,a0 + jbsr a3@(-678) + movel d0,a0 + tstl a0 + jeq L912 + movel #_LVDispatcher,a0@(8) +L912: + movel a0,d0 + moveml sp@+,#0x4c00 + rts + .even +.globl _FreeListViewClass +_FreeListViewClass: + movel a6,sp@- + movel _IntuitionBase,a1 + movel a1,a6 + jbsr a1@(-714) + extl d0 + movel sp@+,a6 + rts + .even +_LV_GMGoActive: + movel a2,sp@- + movel a0,a2 + movel d0,a0 + clrl d0 + movew a2@(32),d0 + tstl a1@(d0:l) + jeq L189 + orw #128,a1@(12) + clrl d0 + tstl a0@(8) + jeq L914 + movel a0,d0 + movel a2,a0 + jbsr _LV_GMHandleInput + jra L914 + .even +L189: + moveq #2,d0 +L914: + movel sp@+,a2 + rts + .even +_LV_GMGoInactive: + clrl d0 + movew a0@(32),d0 + andl #1073741823,a1@(90,d0:l) + andw #65407,a1@(12) + rts + nop + .even +_LV_OMGet: + moveml #0x2030,sp@- + movel a1,d1 + movel d0,a1 + clrl d0 + movew a0@(32),d0 + movel d1,a3 + addl d0,a3 + movel a1@(4),d0 + addl #2142480895,d0 + moveq #19,d2 + cmpl d0,d2 + jcs L785 +LI787: + movew pc@(L787-LI787-2:b,d0:l:2),d0 + jmp pc@(2,d0:w) + .even +L787: + .word L774-L787 + .word L775-L787 + .word L776-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L781-L787 + .word L781-L787 + .word L781-L787 + .word L781-L787 + .word L781-L787 + .word L782-L787 + .word L783-L787 + .word L784-L787 + .even +L774: + movel a1@(8),a0 + movel a3@(24),a0@ + moveq #1,d0 + jra L915 + .even +L775: + movel a1@(8),a0 + movel a3@(4),a0@ + moveq #1,d0 + jra L915 + .even +L776: + movel a1@(8),a0 + movel a3@(12),a0@ + moveq #1,d0 + jra L915 + .even +L781: + movel a1@(8),a0 + movel a3@,a0@ + moveq #1,d0 + jra L915 + .even +L782: + movel a1@(8),a0 + movel a3@(16),a0@ + moveq #1,d0 + jra L915 + .even +L783: + movel a1@(8),a0 + movel a3@(28),a0@ + moveq #1,d0 + jra L915 + .even +L784: + movel a1@(8),a0 + movel a3@(76),a0@ + moveq #1,d0 + jra L915 + .even +L785: + movel a0@(24),a0 + movel a0@(8),a3 + movel d1,a2 + jbsr a3@ +L915: + moveml sp@+,#0xc04 + rts + .even +_LV_OMDispose: + moveml #0x3032,sp@- + movel a0,a2 + movel a1,d2 + movel d0,d3 + clrl d0 + movew a2@(32),d0 + movel d2,a3 + addl d0,a3 + movel a3@(138),d0 + jeq L908 + movel _GfxBase,a1 + movel a1,a6 + movel d0,a0 + jbsr a1@(-534) +L908: + btst #3,a3@(90) + jeq L909 + movel _GfxBase,a0 + movel a0,a6 + movel a3@(134),a1 + jbsr a0@(-78) +L909: + movel a2@(24),a0 + movel a0@(8),a3 + movel d3,a1 + movel d2,a2 + jbsr a3@ + moveml sp@+,#0x4c0c + rts diff --git a/gadgets/ListView/ListViewClass_static.oldinline.s b/gadgets/ListView/ListViewClass_static.oldinline.s new file mode 100644 index 0000000..92a4766 --- /dev/null +++ b/gadgets/ListView/ListViewClass_static.oldinline.s @@ -0,0 +1,4136 @@ +#NO_APP +gcc2_compiled.: +___gnu_compiled_c: +.text + .even +_LVDispatcher: + moveml #0x2030,sp@- + movel a2,d1 + movel a1@,d0 + moveq #6,d2 + cmpl d0,d2 + jeq L14 + jcs L23 + moveq #2,d2 + cmpl d0,d2 + jeq L11 + jcs L24 + moveq #1,d2 + cmpl d0,d2 + jeq L10 + jra L20 + .even +L24: + moveq #3,d2 + cmpl d0,d2 + jeq L12 + moveq #4,d2 + cmpl d0,d2 + jeq L13 + jra L20 + .even +L23: + cmpl #259,d0 + jeq L16 + jhi L25 + cmpl #257,d0 + jeq L18 + cmpl #258,d0 + jeq L19 + jra L20 + .even +L25: + cmpl #260,d0 + jeq L17 + cmpl #264,d0 + jeq L16 + jra L20 + .even +L10: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMRender + moveq #1,d0 + jra L26 + .even +L11: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMGoActive + jra L27 + .even +L12: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMHandleInput + jra L27 + .even +L13: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMGoInactive + moveq #1,d0 + jra L26 + .even +L14: + movel a1,d0 + movel d1,a1 + jbsr _LV_GMLayout + moveq #1,d0 + jra L26 + .even +L16: + movel a1,d0 + movel d1,a1 + jbsr _LV_OMSet + jra L27 + .even +L17: + movel a1,d0 + movel d1,a1 + jbsr _LV_OMGet + jra L27 + .even +L18: + movel a1,d0 + movel d1,a1 + jbsr _LV_OMNew + jra L27 + .even +L19: + movel a1,d0 + movel d1,a1 + jbsr _LV_OMDispose + moveq #1,d0 + jra L26 + .even +L20: + movel a0@(24),a0 + movel a0@(8),a3 + movel d1,a2 + jbsr a3@ +L27: +L26: + moveml sp@+,#0xc04 + rts + .even +_RedrawItems: + lea sp@(-40),sp + moveml #0x303c,sp@- + movel a0,a4 + movel d0,d2 + movel d1,d3 + movel sp@(68),a5 + movel d2,sp@(28) + movel a4@,sp@(32) + movel a1@(8),sp@(36) + movel a1@(4),a0 + movel a0@(30),sp@(40) + movel a4@(90),sp@(56) + movew a4@(150),sp@(44) + movew a4@(154),sp@(48) + tstl a4@(138) + jeq L68 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d2,d0 + addw a4@(152),d0 + subw a4@(22),d0 + jra L69 + .even +L68: + subl a4@(4),d2 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d2,d0 + addw a4@(152),d0 +L69: + movew d0,sp@(46) + addw a4@(62),d0 + subqw #1,d0 + movew d0,sp@(50) + moveq #24,d2 + addl sp,d2 + tstl a5 + jne L71 + movel #517,sp@(24) + movel a4@(106),a3 + movel d2,a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a5 +L71: + movel a4@(118),a3 + tstl a3 + jeq L73 + movel #518,sp@(24) + movel d2,a2 + movel a5,a1 + movel a4@(130),a0 + jbsr a3@ + jra L73 + .even +L82: + movel #515,sp@(24) + movel a4@(110),a3 + movel d2,a2 + movel a5,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a5 + movew a4@(62),d0 + addw a4@(66),d0 + addw d0,sp@(46) + addw d0,sp@(50) +L73: + movel a4@(90),d0 + btst #3,d0 + jeq L76 + movel a4@(76),a0 + tstl a0 + jeq L77 + movel sp@(28),d0 + movel a0@(d0:l:4),d0 + jra L81 + .even +L77: + btst #28,d0 + jeq L79 + clrl d0 + moveb a5@(8),d0 + jra L81 + .even +L79: + clrl d0 + jra L81 + .even +L76: + movel sp@(28),d0 + cmpl a4@(24),d0 + seq d0 + extbl d0 + negl d0 +L81: + tstl d0 + sne d0 + extbl d0 + negl d0 + movel d0,sp@(52) + movel #514,sp@(24) + movel a4@(126),a3 + movel d2,a2 + movel a5,a1 + movel a4@(130),a0 + jbsr a3@ + movel sp@(28),d0 + movel d0,d1 + addql #1,d1 + movel d1,sp@(28) + addql #1,d0 + cmpl d0,d3 + jge L82 + movel a4@(122),a3 + tstl a3 + jeq L84 + movel #519,sp@(24) + movel a5,a1 + movel a4@(130),a0 + jbsr a3@ +L84: + moveml sp@+,#0x3c0c + lea sp@(40),sp + rts + .even +_LV_GMRender: + lea sp@(-72),sp + moveml #0x3f3e,sp@- + movel a1,sp@(60) + movel d0,sp@(56) + clrl d0 + movew a0@(32),d0 + movel a1,a4 + addl d0,a4 + movel sp@(56),a0 + movel a0@(8),a5 + btst #5,a4@(90) + jne L85 + tstl a4@ + jeq L87 + tstl a4@(16) + jeq L87 + clrl sp@(52) + clrw sp@(46) + movel a5@(52),d0 + movel a4@(134),d1 + cmpl d0,d1 + jeq L88 + movel d0,sp@(52) + movel _GfxBase,a6 + movel a5,a1 + movel d1,a0 +#APP + jsr a6@(-0x42:W) +#NO_APP +L88: + tstl a4@(138) + jeq L89 + movel sp@(56),a1 + movel a1@(8),a0 + movel a0@,a0 + btst #4,a0@(31) + jeq L90 + movew #1,sp@(46) + movel _LayersBase,a6 + clrl d0 +#APP + jsr a6@(-0x54:W) +#NO_APP +L90: + movel _LayersBase,a6 + movel a5@,a0 + movel a4@(138),a1 +#APP + jsr a6@(-0xae:W) +#NO_APP + movel d0,sp@(48) +L89: + movel sp@(56),a0 + movel a0@(12),d0 + moveq #1,d1 + cmpl d0,d1 + jeq L127 + jlt L157 + tstl d0 + jeq L92 + jra L91 + .even +L157: + moveq #2,d3 + cmpl d0,d3 + jeq L138 + jra L91 + .even +L92: + clrw d3 + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L93 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + sgt d0 + moveb d0,d3 + extw d3 + negw d3 +L93: + clrw d4 + movel a4@(48),d2 + cmpl d2,d1 + jgt L94 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + sgt d0 + moveb d0,d4 + extw d4 + negw d4 +L94: + tstw d4 + jne L96 + tstw d3 + jeq L95 +L96: + movel a4@,sp@(84) + movel a5,sp@(88) + movel sp@(56),a1 + movel a1@(4),a0 + movel a0@(30),sp@(92) + movel a4@(90),sp@(108) + movel a4@(118),a3 + tstl a3 + jeq L97 + movel #518,sp@(76) + lea sp@(76),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ +L97: + movel #514,sp@(76) + tstw d3 + jeq L98 + movel a4@(24),d1 + movew a4@(150),sp@(96) + movew a4@(154),sp@(100) + tstl a4@(138) + jeq L99 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d0,d1 + movew d1,d0 + addw a4@(152),d0 + subw a4@(22),d0 + jra L100 + .even +L99: + subl a4@(4),d1 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d0,d1 + movew d1,d0 + addw a4@(152),d0 +L100: + movew d0,sp@(98) + addw a4@(62),d0 + subqw #1,d0 + movew d0,sp@(102) + movel a4@(28),a1 + movel a4@(24),d1 + movel a4@(90),d0 + btst #3,d0 + jeq L102 + movel a4@(76),a0 + tstl a0 + jeq L103 + movel a0@(d1:l:4),d0 + jra L104 + .even +L103: + btst #28,d0 + jeq L105 + tstl a1 + jne L166 + movel #517,sp@(64) + movel d1,sp@(68) + movel a4@,sp@(72) + movel a4@(106),a3 + lea sp@(64),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L108 +L166: + clrl d0 + moveb a1@(8),d0 + jra L104 + .even +L108: +L105: + clrl d0 + jra L104 + .even +L102: + moveq #1,d0 +L104: + tstl d0 + sne d0 + extbl d0 + negl d0 + movel d0,sp@(104) + movel a4@(24),sp@(80) + movel a4@(126),a3 + lea sp@(76),a2 + movel a4@(28),a1 + movel a4@(130),a0 + jbsr a3@ +L98: + tstw d4 + jeq L112 + movel a4@(48),d1 + movew a4@(150),sp@(96) + movew a4@(154),sp@(100) + tstl a4@(138) + jeq L113 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d0,d1 + movew d1,d0 + addw a4@(152),d0 + subw a4@(22),d0 + jra L114 + .even +L113: + subl a4@(4),d1 + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d0,d1 + movew d1,d0 + addw a4@(152),d0 +L114: + movew d0,sp@(98) + addw a4@(62),d0 + subqw #1,d0 + movew d0,sp@(102) + movel a4@(52),a1 + movel a4@(48),d0 + movel a4@(90),d1 + btst #3,d1 + jeq L116 + movel a4@(76),a0 + tstl a0 + jeq L117 + movel a0@(d0:l:4),d0 + jra L118 + .even +L117: + btst #28,d1 + jeq L119 + tstl a1 + jne L167 + movel #517,sp@(64) + movel d0,sp@(68) + movel a4@,sp@(72) + movel a4@(106),a3 + lea sp@(64),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L122 +L167: + clrl d0 + moveb a1@(8),d0 + jra L118 + .even +L122: +L119: + clrl d0 + jra L118 + .even +L116: + cmpl a4@(24),d0 + seq d0 + extbl d0 + negl d0 +L118: + tstl d0 + sne d0 + extbl d0 + negl d0 + movel d0,sp@(104) + movel a4@(48),sp@(80) + movel a4@(126),a3 + lea sp@(76),a2 + movel a4@(52),a1 + movel a4@(130),a0 + jbsr a3@ +L112: + movel a4@(122),a3 + tstl a3 + jeq L95 + movel #519,sp@(76) + lea sp@(76),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ +L95: + movel a4@(24),a4@(48) + movel a4@(28),a4@(52) + jra L91 + .even +L127: + movel sp@(56),a1 + movel a1@(4),a0 + movel a0@(30),a0 + movel a0@(4),a0 + movel _GfxBase,a6 + movel a5,a1 + clrl d0 + movew a0@(14),d0 +#APP + jsr a6@(-0x156:W) +#NO_APP + movel a4@(64),a3 + tstl a3 + jeq L128 + tstl a4@ + jeq L128 + movel a4@(16),d1 + jeq L128 + movew a4@(152),a0 + movel a0,a2 + addl a4@(60),a2 + movel a4@(12),d0 + subl a4@(4),d0 + cmpl d0,d1 + jge L129 + movel d1,d0 +L129: + subql #1,d0 + tstl d0 + jle L135 + movel d0,d4 + negl d0 + moveq #3,d1 + andl d1,d0 + jeq L133 + cmpl d0,d1 + jle L170 + moveq #2,d3 + cmpl d0,d3 + jle L171 + movel _GfxBase,a6 + movel a5,a1 + movew a4@(150),d0 + extl d0 + movel a2,d1 + movew a4@(154),d2 + extl d2 + lea a3@(-1,a2:l),a3 + movel a3,d3 +#APP + jsr a6@(-0x132:W) +#NO_APP + movel a4@(60),d0 + addl a4@(64),d0 + addl d0,a2 + subql #1,d4 +L171: + movel a2,d3 + addl a4@(64),d3 + movel _GfxBase,a6 + movel a5,a1 + movew a4@(150),d0 + extl d0 + movel a2,d1 + movew a4@(154),d2 + extl d2 + subql #1,d3 +#APP + jsr a6@(-0x132:W) +#NO_APP + movel a4@(60),d0 + addl a4@(64),d0 + addl d0,a2 + subql #1,d4 +L170: + movel a2,d3 + addl a4@(64),d3 + movel _GfxBase,a6 + movel a5,a1 + movew a4@(150),d0 + extl d0 + movel a2,d1 + movew a4@(154),d2 + extl d2 + subql #1,d3 +#APP + jsr a6@(-0x132:W) +#NO_APP + movel a4@(60),d0 + addl a4@(64),d0 + addl d0,a2 + subql #1,d4 + jeq L135 + .even +L133: + movel a2,d3 + addl a4@(64),d3 + movel _GfxBase,a6 + movel a5,a1 + movew a4@(150),d0 + extl d0 + movel a2,d1 + movew a4@(154),d2 + extl d2 + subql #1,d3 +#APP + jsr a6@(-0x132:W) +#NO_APP + movel a4@(64),a0 + movel a4@(60),d0 + addl a0,d0 + addl d0,a2 + movel _GfxBase,a6 + movel a5,a1 + movew a4@(150),d0 + extl d0 + movel a2,d1 + movew a4@(154),d2 + extl d2 + lea a0@(-1,a2:l),a0 + movel a0,d3 +#APP + jsr a6@(-0x132:W) +#NO_APP + movel a4@(64),a0 + movel a4@(60),d0 + addl a0,d0 + addl d0,a2 + movel _GfxBase,a6 + movel a5,a1 + movew a4@(150),d0 + extl d0 + movel a2,d1 + movew a4@(154),d2 + extl d2 + lea a0@(-1,a2:l),a0 + movel a0,d3 +#APP + jsr a6@(-0x132:W) +#NO_APP + movel a4@(64),a0 + movel a4@(60),d0 + addl a0,d0 + addl d0,a2 + movel _GfxBase,a6 + movel a5,a1 + movew a4@(150),d0 + extl d0 + movel a2,d1 + movew a4@(154),d2 + extl d2 + lea a0@(-1,a2:l),a0 + movel a0,d3 +#APP + jsr a6@(-0x132:W) +#NO_APP + movel a4@(60),d0 + addl a4@(64),d0 + addl d0,a2 + subql #4,d4 + jne L133 + jra L135 + .even +L128: + movew a4@(152),a0 + movel a4@(12),d1 + subl a4@(4),d1 + movel a4@(16),d0 + cmpl d1,d0 + jge L136 + movel d0,d1 +L136: + mulsl a4@(60),d1 + lea a0@(0,d1:l),a2 +L135: + movel _GfxBase,a6 + movel a5,a1 + movew a4@(150),d0 + extl d0 + movel a2,d1 + movew a4@(154),d2 + extl d2 + movew a4@(156),d3 + extl d3 +#APP + jsr a6@(-0x132:W) +#NO_APP + movel a4@(4),d0 + movel d0,d2 + addl a4@(16),d2 + movel a4@(12),d1 + cmpl d1,d2 + jge L137 + movel d2,d1 +L137: + movel a4@(8),sp@- + subql #1,d1 + movel sp@(60),a1 + movel a4,a0 + jbsr _RedrawItems + addql #4,sp + jra L91 + .even +L138: + tstl a4@(138) + jeq L139 + movel a4@(20),d7 + subl a4@(44),d7 + jeq L91 + movew a4@(148),d5 + extl d5 + jra L141 + .even +L139: + movel a4@(4),d0 + movel a4@(40),d1 + cmpl d0,d1 + jeq L91 + movel d0,d7 + subl d1,d7 + movel a4@(64),d1 + movel a4@(60),d0 + addl d1,d0 + mulsl d0,d7 + movel a4@(16),d5 + mulsl d0,d5 + subl d1,d5 +L141: + movel d7,d0 + jge L144 + negl d0 +L144: + cmpl a4@(68),d0 + jle L143 + movel a4@(4),d0 + movel d0,d2 + addl a4@(16),d2 + movel a4@(12),d1 + cmpl d1,d2 + jge L145 + movel d2,d1 +L145: + movel a4@(8),sp@- + subql #1,d1 + movel sp@(60),a1 + movel a4,a0 + jbsr _RedrawItems + addql #4,sp + jra L146 + .even +L143: + movel _GfxBase,a6 + movel a5,a0 + movel a4@(94),d0 +#APP + jsr a6@(-0x3de:W) +#NO_APP + tstl d7 + jle L147 + movew a4@(144),a2 + movel _GfxBase,a6 + movel a5,a0 + movew a4@(142),d0 + extl d0 + movel a2,d1 + addl d7,d1 + movel a0,a1 + movel d0,d2 + movel a2,d3 + movew a4@(146),d4 + extl d4 + subl d7,d5 + moveq #63,d6 + notb d6 +#APP + jsr a6@(-0x228:W) +#NO_APP + tstl a4@(138) + jeq L148 + movew a4@(148),a0 + movel a4@(20),d1 + addl a0,d1 + subql #1,d1 + movel a4@(60),d2 + addl a4@(64),d2 + divsl d2,d1 + movel a4@(44),d0 + addl a0,d0 + divsl d2,d0 + clrl sp@- + jra L187 + .even +L148: + movel a4@(16),d0 + movel d0,d1 + addl a4@(4),d1 + clrl sp@- + subql #1,d1 + addl a4@(40),d0 + jra L187 + .even +L147: + movew a4@(144),a1 + movel _GfxBase,a6 + movel a5,a0 + movew a4@(142),d0 + extl d0 + movel a1,d1 + movel a0,a1 + movel d0,d2 + movel d1,d3 + subl d7,d3 + movew a4@(146),d4 + extl d4 + addl d7,d5 + moveq #63,d6 + notb d6 +#APP + jsr a6@(-0x228:W) +#NO_APP + tstl a4@(138) + jeq L151 + movel a4@(60),d0 + addl a4@(64),d0 + movel a4@(44),d1 + divsl d0,d1 + movel a4@(20),d3 + divsl d0,d3 + movel d3,d0 + clrl sp@- + jra L187 + .even +L151: + movel a4@(8),sp@- + movel a4@(40),d1 + subql #1,d1 + movel a4@(4),d0 +L187: + movel sp@(60),a1 + movel a4,a0 + jbsr _RedrawItems + addql #4,sp + movel a5@,a1 + btst #0,a1@(31) + jeq L153 + movel a1@(8),a0 + tstl a0 + jeq L154 + movel a1@(16),d1 + movel a0@(16),d0 + cmpl d1,d0 + jne L154 + movel a1@(20),d1 + movel a0@(20),d0 + cmpl d1,d0 + jne L154 + movel a1@(156),a0 + tstl a0 + jeq L153 + tstl a0@(8) + jeq L153 +L154: + moveb a5@(24),d6 + movel _GfxBase,a6 + movel a5,a0 + clrl d0 +#APP + jsr a6@(-0x3d8:W) +#NO_APP + movel _GfxBase,a6 + movel a5,a1 + clrl d0 + movel d7,d1 + movew a4@(150),d2 + extl d2 + movew a4@(152),d3 + extl d3 + movew a4@(154),d4 + extl d4 + movew a4@(156),d5 + extl d5 +#APP + jsr a6@(-0x18c:W) +#NO_APP + movel _GfxBase,a6 + movel a5,a0 + clrl d0 + moveb d6,d0 +#APP + jsr a6@(-0x3d8:W) +#NO_APP +L153: + movel _GfxBase,a6 + movel a5,a0 + moveq #-1,d0 +#APP + jsr a6@(-0x3de:W) +#NO_APP +L146: + movel a4@(4),a4@(40) + movel a4@(20),a4@(44) +L91: + tstl a4@(138) + jeq L158 + movel _LayersBase,a6 + movel a5@,a0 + movel sp@(48),a1 +#APP + jsr a6@(-0xae:W) +#NO_APP + tstw sp@(46) + jeq L158 + movel sp@(56),a1 + movel a1@(8),a0 + movel _LayersBase,a6 + movel a0@,a0 +#APP + jsr a6@(-0x4e:W) +#NO_APP +L158: + tstl sp@(52) + jeq L161 + movel _GfxBase,a6 + movel a5,a1 + movel sp@(52),a0 +#APP + jsr a6@(-0x42:W) +#NO_APP + jra L161 + .even +L87: + moveq #1,d0 + movel sp@(56),a0 + cmpl a0@(12),d0 + jne L85 + movel a0@(4),a0 + movel a0@(30),a0 + movel a0@(4),a0 + movel _GfxBase,a6 + movel a5,a1 + clrl d0 + movew a0@(14),d0 +#APP + jsr a6@(-0x156:W) +#NO_APP + movel _GfxBase,a6 + movel a5,a1 + movew a4@(150),d0 + extl d0 + movew a4@(152),d1 + extl d1 + movew a4@(154),d2 + extl d2 + movew a4@(156),d3 + extl d3 +#APP + jsr a6@(-0x132:W) +#NO_APP +L161: + moveq #1,d0 + movel sp@(56),a0 + cmpl a0@(12),d0 + jne L85 + clrl d0 + movel sp@(60),a1 + movel a1@(18),a0 + tstl a0 + jeq L164 + btst #2,a1@(13) + jeq L164 + cmpw #-1,a0@(8) + seq d0 + extbl d0 + negl d0 +L164: + tstw d0 + jeq L85 + movel #518,sp@(88) + movel sp@(56),a0 + movel a0@(8),sp@(92) + movew a4@(158),d1 + swap d1 + clrw d1 + movew a4@(160),d0 + extl d0 + orl d0,d1 + movel d1,sp@(96) + clrl sp@(100) + movel a0@(4),a0 + movel a0@(30),sp@(104) + movew a4@(162),d1 + swap d1 + clrw d1 + movew a4@(164),d0 + extl d0 + orl d0,d1 + movel d1,sp@(108) + movel sp@(88),sp@(64) + movel sp@(92),sp@(68) + movel sp@(96),sp@(72) + movel sp@(100),sp@(76) + movel sp@(104),sp@(80) + movel d1,sp@(84) + movel sp@(60),a1 + movel a1@(18),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + lea sp@(64),a1 + jbsr a3@ +L85: + moveml sp@+,#0x7cfc + lea sp@(72),sp + rts + .even +_LV_GMHandleInput: + lea sp@(-140),sp + moveml #0x3f3e,sp@- + movel a1,sp@(76) + movel d0,d6 + clrl d0 + movew a0@(32),d0 + movel a1,a4 + addl d0,a4 + movel d6,a0 + movel a0@(8),sp@(72) + clrl sp@(68) + movel sp@(72),a1 + clrl d0 + moveb a1@(4),d0 + moveq #2,d1 + cmpl d0,d1 + jeq L221 + jlt L279 + moveq #1,d1 + cmpl d0,d1 + jeq L194 + jra L193 + .even +L279: + moveq #6,d1 + cmpl d0,d1 + jeq L268 + jra L193 + .even +L194: + movel sp@(72),a0 + clrl d0 + movew a0@(6),d0 + moveq #76,d1 + cmpl d0,d1 + jeq L196 + moveq #77,d1 + cmpl d0,d1 + jeq L208 + jra L218 + .even +L196: + movel sp@(72),a0 + movew a0@(8),d1 + btst #0,a4@(93) + jne L198 + btst #3,d1 + jeq L197 +L198: + bftst d1{#30:#2} + jeq L199 + movel a4@(16),d0 + jpl L283 + addql #1,d0 +L283: + asrl #1,d0 + movel a4@(4),a4 + subl d0,a4 + movel a4,d0 + jra L200 + .even +L199: + movel a4@(4),d0 + subql #1,d0 +L200: + tstl d0 + jge L212 + clrl d0 + jra L212 + .even +L197: + movew d1,d0 + andw #48,d0 + jne L281 + bftst d1{#30:#2} + jeq L205 + movel a4@(24),d0 + subl a4@(16),d0 + addql #1,d0 + jra L204 + .even +L205: + movel a4@(24),d0 + subql #1,d0 +L204: + tstl d0 + jge L215 +L281: + clrl d0 + jra L215 + .even +L208: + movel sp@(72),a1 + movew a1@(8),d1 + btst #0,a4@(93) + jne L210 + movew d1,d2 + btst #3,d2 + jeq L209 +L210: + bftst d1{#30:#2} + jeq L211 + movel a4@(16),d0 + jpl L284 + addql #1,d0 +L284: + asrl #1,d0 + addl a4@(4),d0 + jra L212 + .even +L211: + movel a4@(4),d0 + addql #1,d0 +L212: + movel #-2142480894,sp@(160) + movel d0,sp@(164) + clrl sp@(168) + jra L195 + .even +L209: + movew d2,d0 + andw #48,d0 + jeq L214 + movel a4@(12),d0 + subql #1,d0 + jra L215 + .even +L214: + bftst d2{#30:#2} + jeq L216 + movel a4@(24),d0 + addl a4@(16),d0 + subql #1,d0 + jra L215 + .even +L216: + movel a4@(24),d0 + addql #1,d0 +L215: + movel #-2142480895,sp@(160) + movel d0,sp@(164) + movel #-2142480888,sp@(168) + movel d0,sp@(172) + clrl sp@(176) + jra L195 + .even +L218: + clrl sp@(160) +L195: + tstl sp@(160) + jeq L193 + movel #264,sp@(128) + lea sp@(160),a2 + movel a2,sp@(132) + movel d6,a0 + movel a0@(4),sp@(136) + movel sp@(72),a1 + movew a1@(8),d0 + andw #9,d0 + sne d0 + extbl d0 + negl d0 + movel d0,sp@(140) + movel sp@(128),sp@(144) + movel a2,sp@(148) + movel sp@(136),sp@(152) + movel d0,sp@(156) + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + lea sp@(144),a1 + jbsr a3@ + jra L193 + .even +L221: + movel sp@(72),a0 + clrl d0 + movew a0@(6),d0 + moveq #106,d1 + cmpl d0,d1 + jeq L256 + jlt L267 + moveq #104,d1 + cmpl d0,d1 + jeq L223 + moveq #105,d1 + cmpl d0,d1 + jeq L249 + jra L260 + .even +L267: + cmpl #232,d0 + jeq L257 + cmpl #234,d0 + jeq L259 + jra L260 + .even +L223: + movel d6,a0 + movew a0@(16),d0 + jlt L225 + cmpw a4@(146),d0 + jge L225 + movew a0@(18),d1 + jlt L225 + cmpw a4@(148),d1 + jlt L224 +L225: + movew #4,a1 + movel a1,sp@(68) + jra L193 + .even +L224: + movel a4@(90),d0 + bset #31,d0 + movel d0,a4@(90) + btst #0,d0 + jne L193 + movel a4@(20),a0 + lea a0@(d1:w),a2 + movel a2,d5 + movel a4@(60),d0 + addl a4@(64),d0 + divsl d0,d5 + movel d5,d4 + jlt L193 + cmpl a4@(12),d4 + jge L193 + movel a4@(24),a4@(80) + movel a0,a4@(84) + lea sp@(128),a0 + movel a0,sp@(52) + lea sp@(144),a1 + movel a1,sp@(48) + lea sp@(148),a2 + movel a2,sp@(44) + lea sp@(152),a2 + lea sp@(140),a5 + lea sp@(112),a0 + movel a0,sp@(64) + lea sp@(116),a1 + movel a1,sp@(60) + lea sp@(120),a0 + movel a0,sp@(56) + moveq #124,d7 + addl sp,d7 + cmpl a4@(24),d4 + jne L230 + movel _IntuitionBase,a6 + movel a4@(98),d0 + movel a4@(102),d1 + movel sp@(72),a1 + movel a1@(14),d2 + movel a1@(18),d3 +#APP + jsr a6@(-0x66:W) +#NO_APP + tstw d0 + jeq L230 + movel #-2142480866,sp@(128) + movel d4,sp@(132) + clrl sp@(136) + movel #264,sp@(112) + movel sp@(52),sp@(116) + movel d6,a0 + movel a0@(4),sp@(120) + clrl sp@(124) + movel sp@(64),a1 + movel a1@,a5@ + movel sp@(48),a0 + movel sp@(60),a1 + movel a1@,a0@ + movel sp@(44),a0 + movel sp@(56),a1 + movel a1@,a0@ + movel d7,a0 + movel a0@,a2@ + movel sp@(76),a1 + movel a1@(-4),a0 + movel a0@(8),a3 + movel a5,a1 + movel sp@(76),a2 + jbsr a3@ +L230: + movel a4@(90),d0 + btst #3,d0 + jeq L232 + movel a4@(76),a0 + tstl a0 + jeq L236 + movel a0@(d5:l:4),d0 + jra L237 + .even +L236: + btst #28,d0 + jeq L233 + movel #517,sp@(112) + movel d5,sp@(116) + movel a4@,sp@(120) + movel a4@(106),a3 + lea sp@(112),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a0 + clrl d0 + tstl a0 + jeq L241 + clrl d0 + moveb a0@(8),d0 +L241: +L237: + movel #-2142480891,d1 + tstl d0 + jne L234 +L233: + movel #-2142480892,d1 +L234: + movel d1,a4@(56) + jra L245 + .even +L232: + movel sp@(76),a2 + btst #0,a2@(14) + jeq L246 + movel #-2142480895,a4@(56) + cmpl a4@(24),d5 + jne L245 + moveq #-1,d4 + jra L245 + .even +L246: + movel #-2142480895,a4@(56) +L245: + movel a4@(56),sp@(124) + movel d4,sp@(128) + clrl sp@(132) + movel sp@(64),a0 + movel d7,a1 + movel a1@,a0@ + movel sp@(60),a2 + movel sp@(52),a0 + movel a0@,a2@ + movel sp@(56),a1 + movel sp@(132),a1@ + lea sp@(136),a1 + movel #264,sp@(96) + lea sp@(112),a2 + movel a2,sp@(100) + movel d6,a0 + movel a0@(4),sp@(104) + clrl sp@(108) + movel sp@(96),a1@ + movel sp@(100),a5@ + movel sp@(48),a2 + movel sp@(104),a2@ + movel sp@(44),a0 + movel sp@(108),a0@ + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + jbsr a3@ + movel sp@(72),a0 + movel a0@(14),a4@(98) + movel a0@(18),a4@(102) + jra L193 + .even +L249: + movel a4@(90),d1 + movel d1,d0 + andl #-1073741824,d0 + jeq L250 + movel d1,d0 + andl #1073741823,d0 + movel d0,a4@(90) + movel a4@(80),d2 + cmpl a4@(24),d2 + jne L252 + movel a4@(84),a0 + cmpl a4@(20),a0 + jeq L193 +L252: + movel #-2142480895,d0 + btst #0,d1 + jeq L253 + moveq #1,d0 +L253: + movel d0,sp@(116) + movel d2,sp@(120) + movel #-2142480864,sp@(124) + movel a4@(84),sp@(128) + clrl sp@(132) + movel d0,sp@(96) + movel d2,sp@(100) + movel sp@(124),sp@(104) + movel sp@(128),sp@(108) + movel sp@(132),sp@(112) + lea sp@(136),a1 + movel #264,sp@(80) + lea sp@(96),a2 + movel a2,sp@(84) + movel d6,a0 + movel a0@(4),sp@(88) + clrl sp@(92) + movel sp@(80),a1@ + movel sp@(84),sp@(140) + movel sp@(88),sp@(144) + movel sp@(92),sp@(148) + jra L282 + .even +L250: + moveq #4,d0 + movel d0,sp@(68) + jra L193 + .even +L256: + movel a4@(20),a4@(84) + movel a4@(24),a4@(80) + movel d6,a0 + movew a0@(18),a4@(88) + bset #7,a4@(90) + jra L193 + .even +L257: + bclr #7,a4@(90) + movel sp@(76),a1 + btst #0,a1@(15) + jeq L193 + lea a4@(24),a4 + movel d6,a2 + movel a4,a2@(12) + moveq #10,d0 + movel d0,sp@(68) + jra L193 + .even +L259: + bclr #6,a4@(90) + jra L193 + .even +L260: + movel a4@(90),d1 + jge L261 + movel d6,a1 + movew a1@(18),a0 + movel a0,d4 + addl a4@(20),d4 + movel a4@(60),d0 + addl a4@(64),d0 + divsl d0,d4 + cmpl a4@(24),d4 + jeq L261 + btst #0,d1 + jne L261 + movel a4@(4),d0 + cmpl d4,d0 + jgt L261 + addl a4@(16),d0 + cmpl d4,d0 + jle L261 + movel a4@(56),sp@(92) + movel d4,sp@(96) + clrl sp@(100) + movel sp@(92),sp@(80) + movel d4,sp@(84) + movel sp@(100),sp@(88) + lea sp@(104),a1 + movel #264,sp@(120) + lea sp@(80),a2 + movel a2,sp@(124) + movel d6,a0 + movel a0@(4),sp@(128) + clrl sp@(132) + movel sp@(120),a1@ + movel sp@(124),sp@(108) + movel sp@(128),sp@(112) + movel sp@(132),sp@(116) + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + jbsr a3@ +L261: + btst #6,a4@(90) + jeq L193 + movel d6,a1 + movew a1@(18),a0 + subw a4@(88),a0 + movel a0,d4 + addl a4@(84),d4 + movel #-2142480864,sp@(80) + movel d4,d0 + jge L265 + clrl d0 +L265: + movel d0,sp@(84) + clrl sp@(88) + movel #264,sp@(108) + lea sp@(80),a2 + movel a2,sp@(112) + movel d6,a0 + movel a0@(4),sp@(116) + clrl sp@(120) + movel sp@(108),sp@(92) + movel a2,sp@(96) + movel sp@(116),sp@(100) + movel sp@(120),sp@(104) + movel sp@(76),a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea sp@(92),a1 + movel sp@(76),a2 + jbsr a3@ + jra L193 + .even +L268: + movel a4@(90),d2 + jge L193 + movel d6,a2 + tstw a2@(18) + jge L270 + movel a4@(4),d1 + jeq L270 + movel #-2142480887,sp@(100) + moveq #1,d0 + movel d0,sp@(104) + movel #-2142480895,d0 + btst #0,d2 + jeq L271 + moveq #1,d0 +L271: + movel d0,sp@(108) + subql #1,d1 + movel d1,sp@(112) + clrl sp@(116) + movel sp@(100),sp@(80) + movel sp@(104),sp@(84) + movel d0,sp@(88) + movel d1,sp@(92) + movel sp@(116),sp@(96) + lea sp@(120),a1 + movel #264,sp@(136) + lea sp@(80),a0 + movel a0,sp@(140) + movel d6,a2 + movel a2@(4),sp@(144) + clrl sp@(148) + movel sp@(136),a1@ + movel sp@(140),sp@(124) + movel sp@(144),sp@(128) + movel sp@(148),sp@(132) +L282: + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + jbsr a3@ + jra L193 + .even +L270: + movel d6,a0 + movew a0@(18),d0 + extl d0 + movel a4@(60),d1 + addl a4@(64),d1 + divsl d1,d0 + movel a4@(16),d1 + cmpl d0,d1 + jgt L193 + movel #-2142480886,sp@(100) + moveq #1,d0 + movel d0,sp@(104) + movel #-2142480895,d0 + btst #0,a4@(93) + jeq L275 + moveq #1,d0 +L275: + movel d0,sp@(108) + addl a4@(4),d1 + movel d1,sp@(112) + clrl sp@(116) + movel sp@(100),sp@(80) + movel sp@(104),sp@(84) + movel d0,sp@(88) + movel d1,sp@(92) + movel sp@(116),sp@(96) + lea sp@(120),a1 + movel #264,sp@(136) + lea sp@(80),a0 + movel a0,sp@(140) + movel d6,a2 + movel a2@(4),sp@(144) + clrl sp@(148) + movel sp@(136),a1@ + movel sp@(140),sp@(124) + movel sp@(144),sp@(128) + movel sp@(148),sp@(132) + movel sp@(76),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + jbsr a3@ +L193: + movel sp@(68),d0 + moveml sp@+,#0x7cfc + lea sp@(140),sp + rts + .even +_LV_GMLayout: + lea sp@(-64),sp + moveml #0x3f3e,sp@- + movel a1,a5 + movel d0,sp@(44) + clrl d0 + movew a0@(32),d0 + lea a5@(0,d0:l),a4 + bset #5,a4@(90) + lea a4@(142),a2 + movel a2,d0 + movel sp@(44),a3 + movel a3@(4),a0 + jbsr _GetGadgetBox + lea a4@(150),a0 + movew a2@,a0@ + movew a2@(2),a0@(2) + movew a2@,d0 + addw a2@(4),d0 + subqw #1,d0 + movew d0,a0@(4) + movew a2@(2),d0 + addw a2@(6),d0 + subqw #1,d0 + movew d0,a0@(6) + clrl d0 + movel a5@(18),a0 + tstl a0 + jeq L289 + btst #2,a5@(13) + jeq L289 + cmpw #-1,a0@(8) + seq d0 + extbl d0 + negl d0 +L289: + moveq #64,d3 + addl sp,d3 + moveq #84,d2 + addl sp,d2 + moveq #88,d6 + addl sp,d6 + lea sp@(92),a1 + moveq #76,d4 + addl sp,d4 + moveq #80,d5 + addl sp,d5 + tstw d0 + jeq L288 + movel #519,sp@(64) + lea a4@(142),a0 + movel a0,sp@(68) + lea a4@(158),a2 + movel a2,sp@(72) + movel sp@(44),a3 + movel a3@(4),a0 + movel a0@(30),sp@(76) + clrl sp@(80) + movel d2,a0 + movel d3,a2 + movel a2@,a0@ + movel d6,a3 + movel sp@(68),a3@ + movel sp@(72),a1@ + movel d4,a0 + movel a0@,sp@(96) + movel d5,a1 + movel a1@,sp@(100) + movel a5@(18),a2 + movel a2@(-4),a0 + movel a0@(8),a3 + movel d2,a1 + jbsr a3@ +L288: + movel a4@(138),d0 + jeq L291 + movel _GfxBase,a6 + movel d0,a0 +#APP + jsr a6@(-0x210:W) +#NO_APP + movel _GfxBase,a6 + movel a4@(138),a0 + lea a4@(150),a1 +#APP + jsr a6@(-0x1fe:W) +#NO_APP +L291: + tstl a4@(134) + jne L292 + movel sp@(44),a2 + movel a2@(4),a0 + movel a0@(30),a0 + movel a0@(8),a4@(134) + tstl a4@(60) + jne L298 + movel a4@(134),a0 + clrl d0 + movew a0@(20),d0 + movel d0,a4@(60) +L292: + tstl a4@(60) + jeq L294 +L298: + tstl a4@(138) + jeq L295 + movew a4@(148),a2 + movel a4@(60),d0 + lea a2@(0,d0:l),a1 + movel a4@(64),a0 + lea a0@(-1,a1:l),a1 + movel a1,d1 + addl a0,d0 + divsl d0,d1 + movel a2,d0 + jra L297 + .even +L295: + movew a4@(148),a0 + movel a4@(64),d0 + movel a0,d1 + addl d0,d1 + addl a4@(60),d0 + divsl d0,d1 + movel a0,d0 + jra L297 + .even +L294: + clrl d1 + movew a4@(148),d0 + extl d0 +L297: + movel d0,d7 + divsl a4@(72),d7 + movel d7,a4@(68) + movel #-2142480878,sp@(64) + movel d1,sp@(68) + clrl sp@(72) + movel #264,sp@(48) + movel d3,sp@(52) + movel sp@(44),a0 + movel a0@(4),sp@(56) + clrl sp@(60) + movel d4,a1 + movel sp@(48),a1@ + movel d5,a2 + movel sp@(52),a2@ + movel d2,a3 + movel sp@(56),a3@ + movel d6,a0 + movel sp@(60),a0@ + movel a5@(-4),a0 + movel a0@(8),a3 + lea sp@(76),a1 + movel a5,a2 + jbsr a3@ + bclr #5,a4@(90) + moveml sp@+,#0x7cfc + lea sp@(64),sp + rts + .even +_LV_OMSet: + link a5,#-188 + moveml #0x3f3a,sp@- + movel a0,d7 + movel a1,d5 + movel d0,a5@(-188) + clrl d0 + movew a0@(32),d0 + movel d5,a4 + addl d0,a4 + movel a5@(-188),a0 + movel a0@(4),a5@(-184) + clrw d4 + movel a5,d6 + addl #-184,d6 + jra L300 + .even +L302: + movel a0@,d0 + cmpl #-2142480884,d0 + jhi L583 + cmpl #-2142480885,d0 + jcc L300 + cmpl #-2142480891,d0 + jeq L352 + jhi L584 + cmpl #-2142480894,d0 + jeq L318 + jhi L585 + cmpl #-2147287024,d0 + jeq L304 + cmpl #-2142480895,d0 + jeq L306 + jra L581 + .even +L585: + cmpl #-2142480893,d0 + jeq L300 + cmpl #-2142480892,d0 + jeq L326 + jra L581 + .even +L584: + cmpl #-2142480888,d0 + jeq L422 + jhi L586 + cmpl #-2142480890,d0 + jeq L374 + cmpl #-2142480889,d0 + jeq L404 + jra L581 + .even +L586: + cmpl #-2142480887,d0 + jeq L430 + cmpl #-2142480886,d0 + jeq L433 + jra L581 + .even +L583: + cmpl #-2142480879,d0 + jeq L524 + jhi L587 + cmpl #-2142480882,d0 + jeq L465 + jcs L438 + cmpl #-2142480881,d0 + jeq L489 + cmpl #-2142480880,d0 + jeq L516 + jra L581 + .even +L587: + cmpl #-2142480865,d0 + jeq L571 + jhi L588 + cmpl #-2142480878,d0 + jeq L543 + cmpl #-2142480876,d0 + jeq L554 + jra L581 + .even +L588: + cmpl #-2142480864,d0 + jeq L572 + cmpl #-2142480850,d0 + jeq L580 + jra L581 + .even +L304: + movel a5@(-188),a1 + cmpl #259,a1@ + jne L300 + movel d5,a1 + movew a0@(6),a1@(38) + jra L300 + .even +L306: + tstl a4@ + jeq L300 + movel a0@(4),d1 + moveq #-1,d0 + cmpl d1,d0 + jeq L308 + movel a4@(12),d2 + movel d1,d0 + cmpl d0,d2 + jgt L309 + movel d2,d0 + subql #1,d0 +L309: + movel d0,d1 +L308: + movel a4@(24),a0 + cmpl a0,d1 + jeq L300 + movel a4@(4),d2 + cmpl a0,d2 + jgt L314 + movel d2,d0 + addl a4@(16),d0 + cmpl a0,d0 + jgt L313 +L314: + cmpl d1,d2 + jgt L312 + movel d2,d0 + addl a4@(16),d0 + cmpl d1,d0 + jle L312 +L313: + orw #8,d4 +L312: + movel d1,a4@(24) + moveq #-1,d0 + cmpl d1,d0 + jne L315 + clrl a4@(28) + jra L396 + .even +L315: + movel #517,a5@(-12) + movel d1,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) + jra L396 + .even +L318: + movel a0@(4),d2 + cmpl a4@(4),d2 + jeq L300 + tstl a4@ + jeq L300 + movel a4@(16),a0 + movel d2,d0 + addl a0,d0 + movel a4@(12),d1 + cmpl d0,d1 + jgt L321 + cmpl d1,a0 + slt d0 + moveb d0,d2 + extbl d2 + subl a0,d1 + andl d1,d2 +L321: + movel d2,a4@(4) + movel a4@(60),d0 + addl a4@(64),d0 + mulsl d2,d0 + movel d0,a4@(20) + movel #517,a5@(-12) + movel d2,a5@(-8) + jra L755 + .even +L326: + movel a4@(32),d1 + cmpl a4@(36),d1 + jcs L327 + movel a5@(-188),a0 + movel a0@(8),a1 + clrl d0 + tstl a1 + jeq L328 + movel a1@,d0 +L328: + movel _IntuitionBase,a6 + movel d0,a0 +#APP + jsr a6@(-0x60:W) +#NO_APP + jra L300 + .even +L327: + tstl a4@ + jeq L300 + movel a0@(4),d1 + movel a4@(12),d0 + movel d0,d3 + subql #1,d3 + cmpl d1,d0 + jle L332 + movel d1,d3 +L332: + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L336 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + jgt L335 +L336: + cmpl d3,d1 + jgt L334 + movel d1,d0 + addl a4@(16),d0 + cmpl d3,d0 + jle L334 +L335: + orw #8,d4 +L334: + movel d3,a4@(24) + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) + movel d0,a1 + movel a4@(90),d0 + btst #3,d0 + jeq L339 + movel a4@(76),a0 + tstl a0 + jeq L340 + movel a0@(d3:l:4),d0 + jra L341 + .even +L340: + btst #28,d0 + jeq L610 + tstl a1 + jne L611 + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L345 +L611: + clrl d0 + moveb a1@(8),d0 + jra L341 + .even +L345: + clrl d0 + jra L341 + .even +L339: + cmpl a4@(24),d3 + seq d0 + extbl d0 + negl d0 +L341: + tstl d0 + jne L396 +L610: + movel a4@(32),d0 + movel d0,a1 + addql #1,a1 + movel a1,a4@(32) + movel a4@(76),a0 + tstl a0 + jeq L401 + addql #1,d0 + movel d0,a0@(d3:l:4) + jra L396 + .even +L352: + tstl a4@ + jeq L300 + movel a0@(4),d1 + movel a4@(12),d0 + movel d0,d3 + subql #1,d3 + cmpl d1,d0 + jle L354 + movel d1,d3 +L354: + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L358 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + jgt L357 +L358: + cmpl d3,d1 + jgt L356 + movel d1,d0 + addl a4@(16),d0 + cmpl d3,d0 + jle L356 +L357: + orw #8,d4 +L356: + movel d3,a4@(24) + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) + movel d0,a1 + movel a4@(90),d0 + btst #3,d0 + jeq L361 + movel a4@(76),a0 + tstl a0 + jeq L362 + movel a0@(d3:l:4),d0 + jra L363 + .even +L362: + btst #28,d0 + jeq L300 + tstl a1 + jne L612 + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L367 +L612: + clrl d0 + moveb a1@(8),d0 + jra L363 + .even +L367: + clrl d0 + jra L363 + .even +L361: + cmpl a4@(24),d3 + seq d0 + extbl d0 + negl d0 +L363: + tstl d0 + jeq L300 +L771: + subql #1,a4@(32) + movel a4@(76),a0 + tstl a0 + jne L770 + btst #4,a4@(90) + jeq L396 + movel a4@(28),a0 + clrb a0@(8) + jra L396 + .even +L374: + tstl a4@ + jeq L300 + movel a0@(4),d1 + movel a4@(12),d0 + movel d0,d3 + subql #1,d3 + cmpl d1,d0 + jle L376 + movel d1,d3 +L376: + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L380 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + jgt L379 +L380: + cmpl d3,d1 + jgt L378 + movel d1,d0 + addl a4@(16),d0 + cmpl d3,d0 + jle L378 +L379: + orw #8,d4 +L378: + movel d3,a4@(24) + movel #517,a5@(-12) + movel d3,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) + movel d0,a1 + movel a4@(24),d1 + movel a4@(90),d0 + btst #3,d0 + jeq L383 + movel a4@(76),a0 + tstl a0 + jeq L384 + movel a0@(d1:l:4),d0 + jra L385 + .even +L384: + btst #28,d0 + jeq L382 + tstl a1 + jne L613 + movel #517,a5@(-12) + movel d1,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a1 + tstl a1 + jeq L389 +L613: + clrl d0 + moveb a1@(8),d0 + jra L385 + .even +L389: + clrl d0 + jra L385 + .even +L383: + moveq #1,d0 +L385: + tstl d0 + jeq L382 + jra L771 + .even +L770: + movel a4@(24),d0 + clrl a0@(d0:l:4) + jra L396 + .even +L382: + movel a4@(32),d1 + cmpl a4@(36),d1 + jcs L397 + movel a5@(-188),a0 + movel a0@(8),a1 + clrl d0 + tstl a1 + jeq L398 + movel a1@,d0 +L398: + movel _IntuitionBase,a6 + movel d0,a0 +#APP + jsr a6@(-0x60:W) +#NO_APP + jra L396 + .even +L397: + movel d1,a1 + addql #1,a1 + movel a1,a4@(32) + movel a4@(76),a0 + tstl a0 + jeq L401 + movel a4@(24),d0 + addql #1,d1 + movel d1,a0@(d0:l:4) + jra L396 + .even +L401: + btst #4,a4@(90) + jeq L396 + movel a4@(28),a0 + moveb a4@(35),a0@(8) +L396: + orw #16,d4 + jra L300 + .even +L404: + tstl a4@ + jeq L300 + movel a0@(4),d3 + movel a4@(24),d2 + movel a4@(4),d1 + cmpl d2,d1 + jgt L408 + movel d1,d0 + addl a4@(16),d0 + cmpl d2,d0 + jgt L407 +L408: + cmpl d3,d1 + jgt L406 + movel d1,d0 + addl a4@(16),d0 + cmpl d3,d0 + jle L406 +L407: + orw #8,d4 +L406: + moveq #-1,d0 + movel d0,a4@(24) + clrl a4@(28) + clrl a4@(32) + tstl a4@(76) + jeq L409 + clrl d1 + movew d4,d0 + orw #18,d0 + cmpl a4@(12),d1 + jge L415 + .even +L413: + movel a4@(76),a0 + clrl a0@(d1:l:4) + addql #1,d1 + cmpl a4@(12),d1 + jlt L413 + jra L415 + .even +L409: + movew d4,d0 + orw #18,d0 + btst #4,a4@(90) + jeq L415 + movel a4@,a0 + jra L757 + .even +L420: + clrb a0@(8) +L757: + movel a0@,a0 + tstl a0@ + jne L420 +L415: + movew d0,d4 + jra L300 + .even +L422: + movel a0@(4),d1 + jge L423 + clrl d1 +L423: + movel a4@(12),d0 + cmpl d1,d0 + jgt L424 + movel d0,d1 + subql #1,d1 +L424: + movel a4@(4),d0 + cmpl d1,d0 + jle L425 + movel d1,a4@(4) + movel #517,a5@(-12) + movel d1,a5@(-8) + jra L755 + .even +L425: + movel a4@(16),d2 + addl d2,d0 + cmpl d1,d0 + jgt L300 + subl d2,d1 + movel d1,d0 + addql #1,d0 + jra L758 + .even +L430: + movel a4@(4),d0 + jle L300 + movel a4@,d1 + jeq L300 + movel d0,a0 + subql #1,a0 + movel a0,a4@(4) + movel a4@(8),a1 + movel #516,a5@(-12) + subql #1,d0 + movel d0,a5@(-8) + movel d1,a5@(-4) + movel a4@(114),a3 + lea a5@(-12),a2 + jra L759 + .even +L433: + movel a4@(4),d1 + movel d1,d0 + addl a4@(16),d0 + cmpl a4@(12),d0 + jge L300 + movel a4@,d0 + jeq L300 + movel d1,a1 + addql #1,a1 + movel a1,a4@(4) + movel a4@(8),a1 + movel #515,a5@(-12) + addql #1,d1 + movel d1,a5@(-8) + movel d0,a5@(-4) + movel a4@(110),a3 + lea a5@(-12),a2 + jra L759 + .even +L438: + movel a0@(4),d0 + moveq #-1,d1 + cmpl d0,d1 + jeq L760 + movel d0,a4@ + movel #_ListGetItem,a4@(106) + movel #_ListGetNext,a4@(110) + movel #_ListGetPrev,a4@(114) + movel #_ListStringDrawItem,a4@(126) + bset #4,a4@(90) + movel _UtilityBase,a6 + movel #-2142480893,d0 + moveq #-1,d1 + movel a5@(-188),a1 + movel a1@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(12) + movew d4,d3 + orw #34,d3 + moveq #-1,d1 + cmpl d0,d1 + jne L441 + movel a4@,a0 + clrl d0 + tstl a0 + jeq L442 + movel a0@,a0 + jra L761 + .even +L446: + addql #1,d0 +L761: + movel a0@,a0 + tstl a0 + jne L446 +L442: + movel d0,a4@(12) +L441: + clrl d0 + movel a4@(90),d1 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L450 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L453 + cmpl d1,d4 + jle L728 + moveq #2,d4 + cmpl d1,d4 + jle L729 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L729: + tstl a3@+ + jeq L735 + addql #1,d0 +L735: + subql #1,a2 +L728: + tstl a3@+ + jeq L738 + addql #1,d0 +L738: + subql #1,a2 + tstl a2 + jeq L555 + .even +L453: + movel a3,a0 + tstl a0@+ + jeq L741 + addql #1,d0 +L741: + lea a3@(8),a1 + tstl a0@ + jeq L744 + addql #1,d0 +L744: + lea a3@(12),a0 + tstl a1@ + jeq L747 + addql #1,d0 +L747: + lea a3@(16),a3 + tstl a0@ + jeq L750 + addql #1,d0 +L750: + subql #4,a2 + tstl a2 + jne L453 + jra L555 + .even +L450: + btst #28,d1 + jeq L555 + movel a4@,a0 + tstl a0 + jeq L555 + movel a0@,a0 + jra L762 + .even +L460: + addql #1,d0 +L762: + movel a0@,a0 + tstl a0 + jne L460 + jra L555 + .even +L465: + movel a0@(4),d0 + moveq #-1,d1 + cmpl d0,d1 + jeq L760 + movel d0,a4@ + movel #_ArrayGetItem,a4@(106) + movel #_ArrayGetItem,a4@(110) + movel #_ArrayGetItem,a4@(114) + movel #_StringDrawItem,a4@(126) + bclr #4,a4@(90) + movel _UtilityBase,a6 + movel #-2142480893,d0 + moveq #-1,d1 + movel a5@(-188),a1 + movel a1@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(12) + movew d4,d3 + orw #34,d3 + moveq #-1,d1 + cmpl d0,d1 + jne L468 + movel a4@,a0 + tstl a0 + jeq L468 + clrl d0 + tstl a0@ + jeq L470 + .even +L471: + addql #1,d0 + addql #4,a0 + tstl a0@ + jne L471 +L470: + movel d0,a4@(12) +L468: + clrl d0 + movel a4@(90),d1 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L474 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L477 + cmpl d1,d4 + jle L700 + moveq #2,d4 + cmpl d1,d4 + jle L701 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L701: + tstl a3@+ + jeq L707 + addql #1,d0 +L707: + subql #1,a2 +L700: + tstl a3@+ + jeq L710 + addql #1,d0 +L710: + subql #1,a2 + tstl a2 + jeq L555 + .even +L477: + movel a3,a0 + tstl a0@+ + jeq L713 + addql #1,d0 +L713: + lea a3@(8),a1 + tstl a0@ + jeq L716 + addql #1,d0 +L716: + lea a3@(12),a0 + tstl a1@ + jeq L719 + addql #1,d0 +L719: + lea a3@(16),a3 + tstl a0@ + jeq L722 + addql #1,d0 +L722: + subql #4,a2 + tstl a2 + jne L477 + jra L555 + .even +L474: + btst #28,d1 + jeq L555 + movel a4@,a0 + tstl a0 + jeq L555 + movel a0@,a0 + jra L763 + .even +L484: + addql #1,d0 +L763: + movel a0@,a0 + tstl a0 + jne L484 + jra L555 + .even +L489: + movel a0@(4),d0 + moveq #-1,d1 + cmpl d0,d1 + jeq L760 + movel d0,a4@ + movel #_ListGetItem,a4@(106) + movel #_ListGetNext,a4@(110) + movel #_ListGetPrev,a4@(114) + movel #_ListImageDrawItem,a4@(126) + bset #4,a4@(90) + movel _UtilityBase,a6 + movel #-2142480893,d0 + moveq #-1,d1 + movel a5@(-188),a1 + movel a1@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(12) + movew d4,d3 + orw #34,d3 + moveq #-1,d1 + cmpl d0,d1 + jne L492 + movel a4@,a0 + clrl d0 + tstl a0 + jeq L493 + movel a0@,a0 + jra L764 + .even +L497: + addql #1,d0 +L764: + movel a0@,a0 + tstl a0 + jne L497 +L493: + movel d0,a4@(12) +L492: + clrl d0 + movel a4@(90),d1 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L501 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L504 + cmpl d1,d4 + jle L672 + moveq #2,d4 + cmpl d1,d4 + jle L673 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L673: + tstl a3@+ + jeq L679 + addql #1,d0 +L679: + subql #1,a2 +L672: + tstl a3@+ + jeq L682 + addql #1,d0 +L682: + subql #1,a2 + tstl a2 + jeq L555 + .even +L504: + movel a3,a0 + tstl a0@+ + jeq L685 + addql #1,d0 +L685: + lea a3@(8),a1 + tstl a0@ + jeq L688 + addql #1,d0 +L688: + lea a3@(12),a0 + tstl a1@ + jeq L691 + addql #1,d0 +L691: + lea a3@(16),a3 + tstl a0@ + jeq L694 + addql #1,d0 +L694: + subql #4,a2 + tstl a2 + jne L504 + jra L555 + .even +L501: + btst #28,d1 + jeq L555 + movel a4@,a0 + tstl a0 + jeq L555 + movel a0@,a0 + jra L765 + .even +L511: + addql #1,d0 +L765: + movel a0@,a0 + tstl a0 + jne L511 + jra L555 + .even +L516: + movel a0@(4),d0 + moveq #-1,d1 + cmpl d0,d1 + jeq L760 + movel d0,a4@ + movel #_ArrayGetItem,a4@(106) + movel #_ArrayGetItem,a4@(110) + movel #_ArrayGetItem,a4@(114) + movel #_ImageDrawItem,a4@(126) + bclr #4,a4@(90) + movel _UtilityBase,a6 + movel #-2142480893,d0 + moveq #-1,d1 + movel a5@(-188),a1 + movel a1@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(12) + movew d4,d3 + orw #34,d3 + moveq #-1,d1 + cmpl d0,d1 + jne L766 + movel a4@,a0 + tstl a0 + jeq L766 + clrl d0 + tstl a0@ + jeq L521 + .even +L522: + addql #1,d0 + addql #4,a0 + tstl a0@ + jne L522 +L521: + movel d0,a4@(12) + jra L766 + .even +L524: + movel a0@(4),a1 + moveq #-1,d0 + cmpl a1,d0 + jne L525 +L760: + clrl a4@ + jra L300 + .even +L525: + movel a1,a4@ + clrl d0 + movel a4@(90),d1 + movew d4,d3 + orw #34,d3 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L528 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L531 + cmpl d1,d4 + jle L644 + moveq #2,d4 + cmpl d1,d4 + jle L645 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L645: + tstl a3@+ + jeq L651 + addql #1,d0 +L651: + subql #1,a2 +L644: + tstl a3@+ + jeq L654 + addql #1,d0 +L654: + subql #1,a2 + tstl a2 + jeq L555 + .even +L531: + movel a3,a0 + tstl a0@+ + jeq L657 + addql #1,d0 +L657: + lea a3@(8),a1 + tstl a0@ + jeq L660 + addql #1,d0 +L660: + lea a3@(12),a0 + tstl a1@ + jeq L663 + addql #1,d0 +L663: + lea a3@(16),a3 + tstl a0@ + jeq L666 + addql #1,d0 +L666: + subql #4,a2 + tstl a2 + jne L531 + jra L555 + .even +L528: + btst #28,d1 + jeq L555 + tstl a1 + jeq L555 + movel a1@,a0 + jra L767 + .even +L538: + addql #1,d0 +L767: + movel a0@,a0 + tstl a0 + jne L538 + jra L555 + .even +L543: + movel a0@(4),a4@(16) + orw #32,d4 + tstl a4@(138) + jeq L544 + movel a4@(60),d1 + addl a4@(64),d1 + mulsl a4@(12),d1 + movew a4@(148),a0 + movel a4@(20),d0 + addl a0,d0 + cmpl d0,d1 + jgt L300 + movel d1,d0 + subl a0,d0 + movel d0,a4@(20) + jge L546 + clrl a4@(20) +L546: + movel a4@(60),d0 + addl a4@(64),d0 + movel a4@(20),d1 + divsl d0,d1 + cmpl a4@(4),d1 + jeq L768 + movel d1,a4@(4) + movel #517,a5@(-12) + movel d1,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(8) + jra L768 + .even +L544: + movel a4@(16),d2 + movel a4@(4),d0 + addl d2,d0 + movel a4@(12),d1 + cmpl d0,d1 + jgt L300 + cmpl d1,d2 + slt d0 + extbl d0 + subl d2,d1 + andl d1,d0 + movel d0,a4@(4) + movel #517,a5@(-12) + movel d0,a5@(-8) + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(8) + movel a4@(60),d0 + addl a4@(64),d0 + mulsl a4@(4),d0 + movel d0,a4@(20) +L768: + orw #4,d4 + jra L300 + .even +L554: + movel a0@(4),a4@(76) + clrl d0 + movel a4@(90),d1 + movew d4,d3 + orw #2,d3 + btst #3,d1 + jeq L555 + movel a4@(76),a0 + tstl a0 + jeq L556 + movel a4@(12),d2 + cmpl d0,d2 + jle L555 + movel a0,a3 + movel d2,a2 + movel d2,d1 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L559 + cmpl d1,d4 + jle L617 + moveq #2,d4 + cmpl d1,d4 + jle L618 + movel a0@+,d0 + movel a0,a3 + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,a2 +L618: + tstl a3@+ + jeq L624 + addql #1,d0 +L624: + subql #1,a2 +L617: + tstl a3@+ + jeq L627 + addql #1,d0 +L627: + subql #1,a2 + tstl a2 + jeq L555 + .even +L559: + movel a3,a0 + tstl a0@+ + jeq L630 + addql #1,d0 +L630: + lea a3@(8),a1 + tstl a0@ + jeq L633 + addql #1,d0 +L633: + lea a3@(12),a0 + tstl a1@ + jeq L636 + addql #1,d0 +L636: + lea a3@(16),a3 + tstl a0@ + jeq L639 + addql #1,d0 +L639: + subql #4,a2 + tstl a2 + jne L559 + jra L555 + .even +L556: + btst #28,d1 + jeq L555 + movel a4@,a0 + tstl a0 + jeq L555 + movel a0@,a0 + jra L769 + .even +L566: + addql #1,d0 +L769: + movel a0@,a0 + tstl a0 + jne L566 +L555: + movel d0,a4@(32) +L766: + movew d3,d4 + jra L300 + .even +L571: + movel a0@(4),a4@(36) + jra L300 + .even +L572: + movel a0@(4),d1 + cmpl a4@(20),d1 + jeq L300 + tstl a4@ + jeq L300 + movel a4@(60),d0 + jeq L300 + movel d1,a4@(20) + orw #4,d4 + addl a4@(64),d0 + movel d1,d3 + divsl d0,d3 + movel a4@(16),d2 + movel d3,d0 + addl d2,d0 + movel a4@(12),d1 + cmpl d0,d1 + jgt L574 + cmpl d1,d2 + slt d0 + extbl d0 + subl d2,d1 + andl d1,d0 + jra L575 + .even +L574: + movel d3,d0 +L575: + cmpl a4@(4),d0 + jeq L300 +L758: + movel d0,a4@(4) + movel #517,a5@(-12) + movel d0,a5@(-8) +L755: + movel a4@,a5@(-4) + movel a4@(106),a3 + lea a5@(-12),a2 + subl a1,a1 +L759: + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(8) + orw #20,d4 + jra L300 + .even +L580: + movel a0@(4),a4@(72) + movew a4@(148),d0 + extl d0 + movel d0,d1 + divsl a4@(72),d1 + movel d1,a4@(68) + jra L300 + .even +L581: + orw #1,d4 +L300: + movel _UtilityBase,a6 + movel d6,a0 +#APP + jsr a6@(-0x30:W) +#NO_APP + movel d0,a0 + tstl a0 + jne L302 + btst #0,d4 + jeq L590 + movel d7,a1 + movel a1@(24),a0 + movel a0@(8),a3 + movel a5@(-188),a1 + movel d5,a2 + jbsr a3@ + movel d0,d3 + jra L592 + .even +L590: + moveq #1,d3 +L592: + movew d4,d0 + andw #14,d0 + jeq L593 + movel a5@(-188),a0 + movel a0@(8),d0 + jeq L593 + btst #5,a4@(90) + jne L593 + movel _IntuitionBase,a6 + movel d0,a0 +#APP + jsr a6@(-0x22e:W) +#NO_APP + movel d0,d2 + jeq L593 + btst #1,d4 + jeq L595 + moveq #1,d1 + movel d1,a5@(-44) + movel a5@(-188),a0 + movel a0@(8),a5@(-40) + movel d0,a5@(-36) + movel d1,a5@(-32) + movel d1,a5@(-28) + movel a5@(-40),a5@(-24) + movel d0,a5@(-20) + movel d1,a5@(-16) + movel d5,a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea a5@(-28),a1 + movel d5,a2 + jbsr a3@ + jra L596 + .even +L595: + btst #2,d4 + jeq L597 + moveq #1,d1 + movel d1,a5@(-28) + movel a5@(-188),a0 + movel a0@(8),a5@(-24) + movel d0,a5@(-20) + moveq #2,d0 + movel d0,a5@(-16) + movel d1,a5@(-44) + movel a5@(-24),a5@(-40) + movel a5@(-20),a5@(-36) + movel d0,a5@(-32) + movel d5,a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea a5@(-44),a1 + movel d5,a2 + jbsr a3@ +L597: + btst #3,d4 + jeq L596 + moveq #1,d0 + movel d0,a5@(-28) + movel a5@(-188),a0 + movel a0@(8),a5@(-24) + movel d2,a5@(-20) + clrl a5@(-16) + movel d0,a5@(-44) + movel a5@(-24),a5@(-40) + movel d2,a5@(-36) + movel a5@(-16),a5@(-32) + movel d5,a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea a5@(-44),a1 + movel d5,a2 + jbsr a3@ +L596: + movel _IntuitionBase,a6 + movel d2,a0 +#APP + jsr a6@(-0x234:W) +#NO_APP +L593: + btst #5,d4 + jeq L599 + movel #-2142480894,a5@(-180) + movel a4@(4),a5@(-176) + movel #-2142480893,a5@(-172) + movel a4@(12),a5@(-168) + movel #-2142480878,a5@(-164) + movel a4@(16),a5@(-160) + movel #-2142480895,a5@(-156) + movel a4@(24),a5@(-152) + movel #-2142480864,a5@(-148) + movel a4@(20),a5@(-144) + movel #-2142480863,a5@(-140) + movel a4@(60),d0 + addl a4@(64),d0 + movel a4@(12),d1 + mulsl d0,d1 + movel d1,a5@(-136) + movel #-2142480862,a5@(-132) + tstl a4@(138) + jeq L600 + movew a4@(148),d0 + extl d0 + jra L601 + .even +L600: + mulsl a4@(16),d0 +L601: + movel d0,a5@(-128) + movel #-2147287024,a5@(-124) + movel d5,a0 + clrl d0 + movew a0@(38),d0 + movel d0,a5@(-120) + clrl a5@(-116) + moveq #-112,d2 + addl a5,d2 + pea 68:w + movel d2,sp@- + pea a5@(-180) + jbsr _bcopy + lea sp@(12),sp + movel #263,a5@(-28) + movel d2,a5@(-24) + movel a5@(-188),a1 + movel a1@(8),a5@(-20) + clrl d0 + cmpl #264,a1@ + jne L602 + movel a1@(12),d0 +L602: + movel d0,a5@(-16) + movel a5@(-28),a5@(-44) + movel a5@(-24),a5@(-40) + movel a5@(-20),a5@(-36) + movel d0,a5@(-32) + movel d5,a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea a5@(-44),a1 + movel d5,a2 + jbsr a3@ + jra L604 + .even +L599: + btst #4,d4 + jeq L604 + clrl d1 + btst #2,d4 + jeq L606 + movel #-2142480894,a5@(-180) + movel a4@(4),a5@(-176) + movel #-2142480864,a5@(-172) + movel a4@(60),d0 + addl a4@(64),d0 + mulsl a4@(4),d0 + movel d0,a5@(-168) + moveq #4,d1 +L606: + lea a5@(-180),a0 + btst #3,d4 + jeq L607 + movel #-2142480895,a0@(d1:l:4) + addql #1,d1 + movel a4@(24),a0@(d1:l:4) + addql #1,d1 +L607: + movel #-2147287024,a0@(d1:l:4) + addql #1,d1 + movel d5,a1 + clrl d0 + movew a1@(38),d0 + movel d0,a0@(d1:l:4) + clrl a0@(4,d1:l:4) + movel #263,a5@(-128) + movel a0,a5@(-124) + movel a5@(-188),a0 + movel a0@(8),a5@(-120) + clrl d0 + cmpl #264,a0@ + jne L608 + movel a0@(12),d0 +L608: + movel d0,a5@(-116) + movel a5@(-128),a5@(-144) + movel a5@(-124),a5@(-140) + movel a5@(-120),a5@(-136) + movel d0,a5@(-132) + movel d5,a1 + movel a1@(-4),a0 + movel a0@(8),a3 + lea a5@(-144),a1 + movel d5,a2 + jbsr a3@ +L604: + movel d3,d0 + moveml a5@(-228),#0x5cfc + unlk a5 + rts +.data + .even +_boolMap.69: + .long -2147286999 + .long 1 + .long -2142480872 + .long 2 + .long -2142480873 + .long 4 + .long -2142480871 + .long 8 + .long 0 +.text + .even +_LV_OMNew: + lea sp@(-28),sp + moveml #0x383e,sp@- + movel a0,a4 + movel a1,d3 + movel d0,a5 + movel a4@(24),a0 + movel a0@(8),a3 + movel a5,a1 + movel d3,a2 + jbsr a3@ + movel d0,d3 + jeq L789 + movel d3,a0 + tstw a0@(12) + jge L791 + moveq #4,d0 + orl d0,a0@(44) +L791: + clrl d0 + movew a4@(32),d0 + movel d3,a4 + addl d0,a4 + movel _UtilityBase,a6 + moveq #4,d0 + movel a5@(4),a0 + lea _boolMap.69,a1 +#APP + jsr a6@(-0x2a:W) +#NO_APP + movel d0,a4@(90) + movel _UtilityBase,a6 + movel #-2147287007,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a2 + tstl d0 + jeq L792 + movel a2@(8),a4@(134) + jra L793 + .even +L792: + movel d0,a4@(134) +L793: + movel _UtilityBase,a6 + movel #-2142480867,d0 + movel a5@(4),a0 +#APP + jsr a6@(-0x1e:W) +#NO_APP + movel d0,a0 + tstl a0 + jeq L794 + movel a0@(4),d0 + jeq L796 + jra L902 + .even +L794: + movel _UtilityBase,a6 + movel #-2147287000,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + tstl d0 + jeq L796 + movel _GfxBase,a6 + movel d0,a0 +#APP + jsr a6@(-0x48:W) +#NO_APP + tstl d0 + jeq L796 + bset #3,a4@(90) +L902: + movel d0,a4@(134) +L796: + movel a4@(134),a0 + tstl a0 + jeq L799 + clrl d0 + movew a0@(20),d0 + movel d0,a4@(60) + jra L800 + .even +L799: + clrl a4@(60) +L800: + movel _UtilityBase,a6 + movel #-2142480869,d0 + movel a4@(60),d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(60) + movel _UtilityBase,a6 + movel #-2147254270,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(64) + movel _UtilityBase,a6 + movel #-2142480868,d0 + movel a5@(4),a0 +#APP + jsr a6@(-0x1e:W) +#NO_APP + movel d0,a0 + tstl d0 + jeq L801 + movel a0@(4),a4@(94) + jra L802 + .even +L801: + tstl a2 + jeq L803 + movel a2@(4),a0 + movew a0@(14),a1 + movew a0@(4),d2 + cmpw a1,d2 + jcc L806 + movel d0,d1 + movew a1,d1 + jra L807 + .even +L806: + movel d0,d1 + movew d2,d1 +L807: + movew a0@(10),d2 + movew a0@(12),d0 + cmpw d2,d0 + jcc L808 + clrl d0 + movew d2,d0 + cmpl d1,d0 + jlt L809 + jra L804 + .even +L808: + andl #0xFFFF,d0 + cmpl d1,d0 + jge L804 +L809: + movew a0@(14),d1 + movew a0@(4),d0 + cmpw d1,d0 + jcs L903 + jra L812 + .even +L804: + movew a0@(10),d1 + movew a0@(12),d0 + cmpw d1,d0 + jcc L812 +L903: + clrl d0 + movew d1,d0 + jra L805 + .even +L812: + andl #0xFFFF,d0 +L805: + movel d0,a4@(94) + jra L802 + .even +L803: + moveq #-1,d1 + movel d1,a4@(94) +L802: + movel _UtilityBase,a6 + movel #-2142480893,d0 + moveq #-1,d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(12) + movel _UtilityBase,a6 + movel #-2142480883,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a0 + movel a0,a4@ + jeq L815 + movel #_ListGetItem,a4@(106) + movel #_ListGetNext,a4@(110) + movel #_ListGetPrev,a4@(114) + movel #_ListStringDrawItem,a4@(126) + bset #4,a4@(90) + moveq #-1,d4 + cmpl a4@(12),d4 + jne L824 + clrl d0 + movel a0@,a0 + jra L904 + .even +L821: + addql #1,d0 +L904: + movel a0@,a0 + tstl a0 + jne L821 + movel d0,a4@(12) + jra L824 + .even +L815: + movel _UtilityBase,a6 + movel #-2142480882,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a0 + movel d0,a4@ + jeq L825 + movel #_ArrayGetItem,a4@(106) + movel #_ArrayGetItem,a4@(110) + movel #_ArrayGetItem,a4@(114) + movel #_StringDrawItem,a4@(126) + moveq #-1,d1 + cmpl a4@(12),d1 + jne L824 + clrl d1 + tstl a0@ + jeq L845 + .even +L829: + addql #1,d1 + addql #4,a0 + tstl a0@ + jne L829 + jra L845 + .even +L825: + movel _UtilityBase,a6 + movel #-2142480881,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a0 + movel a0,a4@ + jeq L832 + movel #_ListGetItem,a4@(106) + movel #_ListGetNext,a4@(110) + movel #_ListGetPrev,a4@(114) + movel #_ListImageDrawItem,a4@(126) + bset #4,a4@(90) + moveq #-1,d4 + cmpl a4@(12),d4 + jne L824 + clrl d0 + movel a0@,a0 + jra L905 + .even +L838: + addql #1,d0 +L905: + movel a0@,a0 + tstl a0 + jne L838 + movel d0,a4@(12) + jra L824 + .even +L832: + movel _UtilityBase,a6 + movel #-2142480880,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a0 + movel d0,a4@ + jeq L824 + movel #_ArrayGetItem,a4@(106) + movel #_ArrayGetItem,a4@(110) + movel #_ArrayGetItem,a4@(114) + movel #_ImageDrawItem,a4@(126) + moveq #-1,d1 + cmpl a4@(12),d1 + jne L824 + clrl d1 + tstl a0@ + jeq L845 + .even +L846: + addql #1,d1 + addql #4,a0 + tstl a0@ + jne L846 +L845: + movel d1,a4@(12) +L824: + movel _UtilityBase,a6 + movel #-2142480876,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(76) + movel _UtilityBase,a6 + movel #-2142480865,d0 + moveq #-1,d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(36) + clrl d0 + movel a4@(90),d1 + btst #3,d1 + jeq L848 + movel a4@(76),d2 + jeq L849 + movel a4@(12),d1 + cmpl d0,d1 + jle L848 + movel d2,a2 + movel d1,d2 + negl d1 + moveq #3,d4 + andl d4,d1 + jeq L852 + cmpl d1,d4 + jle L874 + moveq #2,d4 + cmpl d1,d4 + jle L875 + tstl a2@+ + sne d0 + moveq #1,d1 + andl d1,d0 + subql #1,d2 +L875: + tstl a2@+ + jeq L881 + addql #1,d0 +L881: + subql #1,d2 +L874: + tstl a2@+ + jeq L884 + addql #1,d0 +L884: + subql #1,d2 + jeq L848 + .even +L852: + movel a2,a0 + tstl a0@+ + jeq L887 + addql #1,d0 +L887: + lea a2@(8),a1 + tstl a0@ + jeq L890 + addql #1,d0 +L890: + lea a2@(12),a0 + tstl a1@ + jeq L893 + addql #1,d0 +L893: + lea a2@(16),a2 + tstl a0@ + jeq L896 + addql #1,d0 +L896: + subql #4,d2 + jne L852 + jra L848 + .even +L849: + btst #28,d1 + jeq L848 + movel a4@,a0 + tstl a0 + jeq L848 + movel a0@,a0 + jra L906 + .even +L859: + addql #1,d0 +L906: + movel a0@,a0 + tstl a0 + jne L859 +L848: + movel d0,a4@(32) + movel _UtilityBase,a6 + movel #-2142480878,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(16) + jeq L864 + movel #-2147287033,sp@(32) + movel a4@(60),d0 + addl a4@(64),d0 + mulsl a4@(16),d0 + movel d0,sp@(36) + clrl sp@(40) + movel sp@(32),sp@(44) + movel d0,sp@(48) + movel sp@(40),sp@(52) + movel _IntuitionBase,a6 + movel d3,a0 + lea sp@(44),a1 +#APP + jsr a6@(-0x288:W) +#NO_APP +L864: + movel #-2142480888,d2 + movel _UtilityBase,a6 + movel #-2142480894,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,d1 + movel _UtilityBase,a6 + movel d2,d0 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(4) + movel d0,a4@(40) + movel a4@(60),d1 + addl a4@(64),d1 + mulsl d0,d1 + movel d1,a4@(20) + movel d1,a4@(44) + tstl a4@ + jeq L865 + movel #517,sp@(32) + movel d0,sp@(36) + movel a4@,sp@(40) + movel a4@(106),a3 + lea sp@(32),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(8) +L865: + movel _UtilityBase,a6 + movel #-2142480850,d0 + moveq #2,d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(72) + movel _UtilityBase,a6 + movel #-2142480895,d0 + moveq #-1,d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a4@(24) + movel d0,a4@(48) + moveq #-1,d4 + cmpl d0,d4 + jeq L867 + movel #517,sp@(32) + movel d0,sp@(36) + movel a4@,sp@(40) + movel a4@(106),a3 + lea sp@(32),a2 + subl a1,a1 + movel a4@(130),a0 + jbsr a3@ + movel d0,a4@(28) +L867: + movel _UtilityBase,a6 + movel #-2142480875,d0 + clrl d1 + movel a5@(4),a0 +#APP + jsr a6@(-0x24:W) +#NO_APP + movel d0,a0 + movel a0,a4@(130) + jeq L869 + movel a0@(8),a4@(126) +L869: + btst #1,a4@(93) + jeq L789 + movel _GfxBase,a6 +#APP + jsr a6@(-0x204:W) +#NO_APP + movel d0,a4@(138) +L789: + movel d3,d0 + moveml sp@+,#0x7c1c + lea sp@(28),sp + rts +LC0: + .ascii "gadgetclass\0" + .even +.globl _MakeListViewClass +_MakeListViewClass: + movel a6,sp@- + movel a2,sp@- + movel _IntuitionBase,a6 + subl a0,a0 + lea LC0,a1 + subl a2,a2 + moveq #89,d0 + notb d0 + clrl d1 +#APP + jsr a6@(-0x2a6:W) +#NO_APP + movel d0,a0 + tstl a0 + jeq L912 + movel #_LVDispatcher,a0@(8) +L912: + movel a0,d0 + movel sp@+,a2 + movel sp@+,a6 + rts + .even +.globl _FreeListViewClass +_FreeListViewClass: + movel a6,sp@- + movel _IntuitionBase,a6 +#APP + jsr a6@(-0x2ca:W) +#NO_APP + extl d0 + movel sp@+,a6 + rts + .even +_LV_GMGoActive: + movel a2,sp@- + movel a0,a2 + movel d0,a0 + clrl d0 + movew a2@(32),d0 + tstl a1@(d0:l) + jeq L189 + orw #128,a1@(12) + clrl d0 + tstl a0@(8) + jeq L914 + movel a0,d0 + movel a2,a0 + jbsr _LV_GMHandleInput + jra L914 + .even +L189: + moveq #2,d0 +L914: + movel sp@+,a2 + rts + .even +_LV_GMGoInactive: + clrl d0 + movew a0@(32),d0 + andl #1073741823,a1@(90,d0:l) + andw #65407,a1@(12) + rts + nop + .even +_LV_OMGet: + moveml #0x2030,sp@- + movel a1,d1 + movel d0,a1 + clrl d0 + movew a0@(32),d0 + movel d1,a3 + addl d0,a3 + movel a1@(4),d0 + addl #2142480895,d0 + moveq #19,d2 + cmpl d0,d2 + jcs L785 +LI787: + movew pc@(L787-LI787-2:b,d0:l:2),d0 + jmp pc@(2,d0:w) + .even +L787: + .word L774-L787 + .word L775-L787 + .word L776-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L785-L787 + .word L781-L787 + .word L781-L787 + .word L781-L787 + .word L781-L787 + .word L781-L787 + .word L782-L787 + .word L783-L787 + .word L784-L787 + .even +L774: + movel a1@(8),a0 + movel a3@(24),a0@ + moveq #1,d0 + jra L915 + .even +L775: + movel a1@(8),a0 + movel a3@(4),a0@ + moveq #1,d0 + jra L915 + .even +L776: + movel a1@(8),a0 + movel a3@(12),a0@ + moveq #1,d0 + jra L915 + .even +L781: + movel a1@(8),a0 + movel a3@,a0@ + moveq #1,d0 + jra L915 + .even +L782: + movel a1@(8),a0 + movel a3@(16),a0@ + moveq #1,d0 + jra L915 + .even +L783: + movel a1@(8),a0 + movel a3@(28),a0@ + moveq #1,d0 + jra L915 + .even +L784: + movel a1@(8),a0 + movel a3@(76),a0@ + moveq #1,d0 + jra L915 + .even +L785: + movel a0@(24),a0 + movel a0@(8),a3 + movel d1,a2 + jbsr a3@ +L915: + moveml sp@+,#0xc04 + rts + .even +_LV_OMDispose: + moveml #0x3032,sp@- + movel a0,a2 + movel a1,d2 + movel d0,d3 + clrl d0 + movew a2@(32),d0 + movel d2,a3 + addl d0,a3 + movel a3@(138),d0 + jeq L908 + movel _GfxBase,a6 + movel d0,a0 +#APP + jsr a6@(-0x216:W) +#NO_APP +L908: + btst #3,a3@(90) + jeq L909 + movel _GfxBase,a6 + movel a3@(134),a1 +#APP + jsr a6@(-0x4e:W) +#NO_APP +L909: + movel a2@(24),a0 + movel a0@(8),a3 + movel d3,a1 + movel d2,a2 + jbsr a3@ + moveml sp@+,#0x4c0c + rts diff --git a/gadgets/ListView/ListViewHooks.c b/gadgets/ListView/ListViewHooks.c new file mode 100644 index 0000000..daa1aa0 --- /dev/null +++ b/gadgets/ListView/ListViewHooks.c @@ -0,0 +1,276 @@ +/* +** $Id: ListViewHooks.c,v 1.3 2000/01/12 21:18:07 bernie Exp $ +** +** Copyright (C) 1996,97 Bernardo Innocenti +** +** Use 4 chars wide TABs to read this file +** +** Internal drawing and browsing hooks the listview class +*/ + +#define USE_BUILTIN_MATH +#define INTUI_V36_NAMES_ONLY +#define __USE_SYSBASE +#define CLIB_ALIB_PROTOS_H /* Avoid dupe defs of boopsi funcs */ + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef __STORM__ + #pragma header +#endif + +#define LV_GADTOOLS_STUFF +#include + +#include +#include + + + +/* Definitions for builtin List hook */ + +APTR HOOKCALL ListGetItem( + REG(a0, struct Hook *hook), + REG(a1, struct Node *node), + REG(a2, struct lvGetItem *lvgi)); +APTR HOOKCALL ListGetNext( + REG(a0, struct Hook *hook), + REG(a1, struct Node *node), + REG(a2, struct lvGetNext *lvgn)); +APTR HOOKCALL ListGetPrev( + REG(a0, struct Hook *hook), + REG(a1, struct Node *node), + REG(a2, struct lvGetPrev *lvgp)); +ULONG HOOKCALL ListStringDrawItem( + REG(a0, struct Hook *hook), + REG(a1, struct Node *node), + REG(a2, struct lvDrawItem *lvdi)); +ULONG HOOKCALL ListImageDrawItem( + REG(a0, struct Hook *hook), + REG(a1, struct Node *node), + REG(a2, struct lvDrawItem *lvdi)); + + +/* Definitions for builtin Array hook */ + +APTR HOOKCALL ArrayGetItem( + REG(a0, struct Hook *hook), + REG(a1, STRPTR *item), + REG(a2, struct lvGetItem *lvgi)); +ULONG HOOKCALL StringDrawItem( + REG(a0, struct Hook *hook), + REG(a1, STRPTR str), + REG(a2, struct lvDrawItem *lvdi)); +ULONG HOOKCALL ImageDrawItem( + REG(a0, struct Hook *hook), + REG(a1, struct Image *img), + REG(a2, struct lvDrawItem *lvdi)); + + + +APTR HOOKCALL ListGetItem( + UNUSED(REG(a0, struct Hook *hook)), + REG(a1, struct Node *node), + REG(a2, struct lvGetItem *lvg)) +{ + ULONG i; + + ASSERT_VALID_PTR(lvg) + + node = ((struct List *)(lvg->lvgi_Items))->lh_Head; + + /* Warning: no sanity check is made against + * list being shorter than expected! + */ + for (i = 0; i < lvg->lvgi_Number; i++) + { + ASSERT_VALID_PTR(node) + node = node->ln_Succ; + } + + return (APTR)node; +} + + + +APTR HOOKCALL ListGetNext( + UNUSED(REG(a0, struct Hook *hook)), + REG(a1, struct Node *node), + UNUSED(REG(a2, struct lvGetItem *lvg))) +{ + ASSERT_VALID_PTR(node) + ASSERT_VALID_PTR(lvg) + + return (APTR)(node->ln_Succ->ln_Succ ? node->ln_Succ : NULL); +} + + + +APTR HOOKCALL ListGetPrev( + UNUSED(REG(a0, struct Hook *hook)), + REG(a1, struct Node *node), + UNUSED(REG(a2, struct lvGetItem *lvg))) +{ + ASSERT_VALID_PTR(node) + ASSERT_VALID_PTR(lvg) + + return (APTR)(node->ln_Pred->ln_Pred ? node->ln_Pred : NULL); +} + + + +ULONG HOOKCALL ListStringDrawItem( + REG(a0, struct Hook *hook), + REG(a1, struct Node *node), + REG(a2, struct lvDrawItem *lvdi)) +{ + ASSERT_VALID_PTR(node) + ASSERT_VALID_PTR(lvdi) + + return StringDrawItem(hook, node->ln_Name, lvdi); +} + + + +ULONG HOOKCALL ListImageDrawItem( + REG(a0, struct Hook *hook), + REG(a1, struct Node *node), + REG(a2, struct lvDrawItem *lvdi)) +{ + ASSERT_VALID_PTR(node) + ASSERT_VALID_PTR(lvdi) + + return ImageDrawItem(hook, (struct Image *)node->ln_Name, lvdi); +} + + + +APTR HOOKCALL ArrayGetItem( + UNUSED(REG(a0, struct Hook *hook)), + UNUSED(REG(a1, STRPTR *item)), + REG(a2, struct lvGetItem *lvg)) +{ + ASSERT_VALID_PTR(lvg) + ASSERT_VALID_PTR(lvg->lvgi_Items) + + return (APTR)(((STRPTR *)lvg->lvgi_Items)[lvg->lvgi_Number]); +} + + + +ULONG HOOKCALL StringDrawItem( + UNUSED(REG(a0, struct Hook *hook)), + REG(a1, STRPTR str), + REG(a2, struct lvDrawItem *lvdi)) +{ + struct RastPort *rp; + ULONG len; + + ASSERT_VALID_PTR(lvdi) + rp = lvdi->lvdi_RastPort; + ASSERT_VALID_PTR(rp) + ASSERT_VALID_PTR_OR_NULL(str) + + if (!str) + /* Move to the leftmost pixel of the rectangle + * to have the following RectFill() clear all the line + */ + Move(rp, lvdi->lvdi_Bounds.MinX, 0); + else + { + struct TextExtent textent; + + if (lvdi->lvdi_State == LVR_NORMAL) + { + SetABPenDrMd(rp, lvdi->lvdi_DrawInfo->dri_Pens[TEXTPEN], + lvdi->lvdi_DrawInfo->dri_Pens[BACKGROUNDPEN], + JAM2); + } + else + { + SetABPenDrMd(rp, lvdi->lvdi_DrawInfo->dri_Pens[FILLTEXTPEN], + lvdi->lvdi_DrawInfo->dri_Pens[FILLPEN], + JAM2); + } + + Move(rp, lvdi->lvdi_Bounds.MinX, lvdi->lvdi_Bounds.MinY + rp->Font->tf_Baseline); + + len = strlen(str); + + if (!(lvdi->lvdi_Flags & LVF_CLIPPED)) + { + /* Calculate how much text will fit in the listview width */ + len = TextFit(rp, str, len, &textent, NULL, 1, + lvdi->lvdi_Bounds.MaxX - lvdi->lvdi_Bounds.MinX + 1, + lvdi->lvdi_Bounds.MaxY - lvdi->lvdi_Bounds.MinY + 1); + } + + Text(rp, str, len); + + /* Text() will move the pen X position to + * lvdi->lvdi_Bounds.MinX + textent.te_Width. + */ + } + + /* Now clear the rest of the row. rp->cp_x is updated by Text() to the + * next character to print. + */ + SetAPen(rp, lvdi->lvdi_DrawInfo->dri_Pens[(lvdi->lvdi_State == LVR_NORMAL) ? + BACKGROUNDPEN : FILLPEN]); + RectFill(rp, rp->cp_x, + lvdi->lvdi_Bounds.MinY, + lvdi->lvdi_Bounds.MaxX, + lvdi->lvdi_Bounds.MaxY); + + + return LVCB_OK; +} + + + +ULONG HOOKCALL ImageDrawItem( + UNUSED(REG(a0, struct Hook *hook)), + REG(a1, struct Image *img), + REG(a2, struct lvDrawItem *lvdi)) +{ + struct RastPort *rp; + UWORD left; + + ASSERT_VALID_PTR_OR_NULL(img) + ASSERT_VALID_PTR(lvdi) + rp = lvdi->lvdi_RastPort; + ASSERT_VALID_PTR(rp) + + if (!img) + /* Move to the leftmost pixel of the item rectangle + * to have the following RectFill() clear all the line + */ + left = lvdi->lvdi_Bounds.MinX; + else + { + DrawImageState(rp, img, + lvdi->lvdi_Bounds.MinX, lvdi->lvdi_Bounds.MinY, + lvdi->lvdi_State, lvdi->lvdi_DrawInfo); + + left = lvdi->lvdi_Bounds.MinX + img->Width; + } + + /* Now clear the rest of the row. rp->cp_x is updated by Text() to the + * next character to print. + */ + SetAPen(rp, lvdi->lvdi_DrawInfo->dri_Pens[(lvdi->lvdi_State == LVR_NORMAL) ? + BACKGROUNDPEN : FILLPEN]); + RectFill(rp, left, + lvdi->lvdi_Bounds.MinY, + lvdi->lvdi_Bounds.MaxX, + lvdi->lvdi_Bounds.MaxY); + + return LVCB_OK; +} diff --git a/gadgets/ListView/Makefile b/gadgets/ListView/Makefile new file mode 100644 index 0000000..261ec59 --- /dev/null +++ b/gadgets/ListView/Makefile @@ -0,0 +1,30 @@ +# +# $Id: Makefile,v 1.1 2000/01/12 21:16:52 bernie Exp $ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +TOP := ../.. + +include $(TOP)/config.mk + +# +# Class specific information +# +CLASSLIB := listview.gadget +CLASSSRC := ListViewClass.c ListViewHooks.c +CLASSOBJ := $(TOP)/common/GetGadgetBox.o +DEMOSRC := LVDemo.c +DEMOOBJ := ../ScrollButton/ScrollButtonClass_static.o +DEMOPROG := ListViewDemo +NOSTDLIB := 1 +INSTALLDIR := gadgets + +# +# Class version information +# +CLASSVER := 1 +CLASSREV := 7 +CLASSDATE := (22.8.99) + +include $(TOP)/common/general.mk diff --git a/gadgets/Makefile b/gadgets/Makefile new file mode 100644 index 0000000..28730bc --- /dev/null +++ b/gadgets/Makefile @@ -0,0 +1,11 @@ +# +# $Id: Makefile,v 1.1 2000/01/12 20:48:56 bernie Exp $ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +TOP := .. +SUBDIRS := SmartGroup ScrollButton SliderBar ListView PIPWin +# not yet: ResizeGClass + +include $(TOP)/common/general.mk diff --git a/gadgets/MeterGClass/Makefile b/gadgets/MeterGClass/Makefile new file mode 100644 index 0000000..eb79630 --- /dev/null +++ b/gadgets/MeterGClass/Makefile @@ -0,0 +1,27 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(BOOPSITOP)/config.mk +include config.mk + +ARG_COMMON := +ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o +ARG_LIB := $(ARG_COMMON) +ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV) +ARG_PRIVATE := $(ARG_COMMON) +ARG_OBJ := $(ARG_COMMON) + +DEP_COMMON := +DEP_ALL := $(DEP_COMMON) OpenClass.o +DEP_LIB := $(DEP_COMMON) +DEP_DEBUG := $(DEP_COMMON) OpenClass.o +DEP_PRIVATE := $(DEP_COMMON) +DEP_OBJ := $(DEP_COMMON) + +include $(BOOPSITOP)/common/general.mk + +OpenClass.o: OpenClass.c + $(MAKE) -C $(BOOPSITOP)/common/ $@ diff --git a/gadgets/PIPWin/GNUmakefile.nothanks b/gadgets/PIPWin/GNUmakefile.nothanks new file mode 100644 index 0000000..4908f95 --- /dev/null +++ b/gadgets/PIPWin/GNUmakefile.nothanks @@ -0,0 +1,58 @@ +## +## $VER: PIPWin_Makefile 2.6 (19.10.98) +## +## Copyright (C) 1996,97 by Bernardo Innocenti +## +## Makefile for gcc +## + +# Name of the final executable +# +PROJ = PIPWin + +# Object files in this project +# +OBJS = startup_gcc.o PIPWin.o PIPClass.o + +# C compiler name +# +CC = gcc + +# Make the project +# +all: $(PROJ) + +# Remove all targets and intermediate files +# +clean: + -Delete $(PROJ) $(OBJS) + + +########################################################### +# gcc release version should be compiled with these flags +# +# NOTE: compiling with -fbaserel is currently not +# possible because of the well known gcc/egcs +# "register spilled" problem. +# +CFLAGS = -c -O3 -finline-functions -fno-implement-inlines \ + -fomit-frame-pointer -fstrength-reduce \ + -msmall-code -mregparm -I/gg/include -I/include \ + -Wunused -Wreturn-type -D$(OSVER) +LFLAGS = -s +LIBS = -noixemul -nostdlib + + +########################################################### +# gcc - Make the executable +########################################################### +# +startup_gcc.o: startup_gcc.s + $(AS) startup_gcc.s -o startup_gcc.o + +.c.o: VectorGlyphIClass.h + $(CC) $(*).c $(CFLAGS) + +$(PROJ): $(OBJS) + $(CC) $(OBJS) -o $(PROJ) $(LFLAGS) $(LIBS) + @Protect $(PROJ) +e diff --git a/gadgets/PIPWin/Makefile b/gadgets/PIPWin/Makefile new file mode 100644 index 0000000..1086b1d --- /dev/null +++ b/gadgets/PIPWin/Makefile @@ -0,0 +1,27 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +TOP := ../.. +include $(TOP)/config.mk + +# +# Class specific information +# +#CLASSLIB := pip.gadget +CLASSSRC := PIPClass.c +CLASSOBJ := $(TOP)/common/GetGadgetBox.o +DEMOSRC := PIPWin.c +NOSTDLIB := 1 +INSTALLDIR := gadgets + +# +# Class version information +# +CLASSVER := 1 +CLASSREV := 7 +CLASSDATE := (25.12.99) + +include $(TOP)/common/general.mk diff --git a/gadgets/PIPWin/PIPClass.c b/gadgets/PIPWin/PIPClass.c new file mode 100644 index 0000000..1f83803 --- /dev/null +++ b/gadgets/PIPWin/PIPClass.c @@ -0,0 +1,677 @@ +/* +** PIPClass.c +** +** Copyright (C) 1996,97 Bernardo Innocenti +** +** Picture In Picture gadget class +*/ + +#define INTUI_V36_NAMES_ONLY + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "PIPClass.h" + + + +/* PIP gadget private instance data */ + +struct PIPData +{ + struct Screen *Scr; /* Snoop this screen... */ + struct BitMap *BitMap; /* ...or this BitMap */ + WORD Width, Height; /* Size of snooped object */ + WORD OffX, OffY; /* Current XY offset of the view */ + WORD StartX, StartY; /* Start coords for mouse dragging */ + WORD Dragging; /* TRUE if dragging with mouse */ + WORD Dummy; /* Keep data longword aligned */ + struct IBox GBox; /* Real gadget size */ +}; + + + +/* Local function prototypes */ + +static void PIP_GMRender (Class *cl, struct Gadget *g, struct gpRender *msg); +static ULONG PIP_GMHandleInput (Class *cl, struct Gadget *g, struct gpInput *msg); +static void PIP_GMGoInactive (Class *cl, struct Gadget *g, struct gpGoInactive *msg); +static void PIP_GMLayout (Class *cl, struct Gadget *g, struct gpLayout *msg); +static ULONG PIP_OMNew (Class *cl, struct Gadget *g, struct opSet *msg); +static ULONG PIP_OMSet (Class *cl, struct Gadget *g, struct opUpdate *msg); +static ULONG PIP_OMGet (Class *cl, struct Gadget *g, struct opGet *msg); +static ULONG PIP_PIPMRefresh (Class *cl, struct Gadget *g, struct pippRefresh *msg); +static void RestrictXY (struct PIPData *pip); +static void GetGadgetBox (struct GadgetInfo *ginfo, struct Gadget *g, struct IBox *rect); + + + +static ULONG HOOKCALL PIPDispatcher( + REG(a0, Class *cl), + REG(a2, struct Gadget *g), + REG(a1, Msg msg)) +{ + switch (msg->MethodID) + { + case GM_RENDER: + PIP_GMRender(cl, g, (struct gpRender *)msg); + return TRUE; + + case GM_GOACTIVE: + case GM_HANDLEINPUT: + return PIP_GMHandleInput(cl, g, (struct gpInput *)msg); + + case GM_GOINACTIVE: + PIP_GMGoInactive(cl, g, (struct gpGoInactive *)msg); + return TRUE; + + case GM_LAYOUT: + /* This method is only supported on V39 and above */ + PIP_GMLayout(cl, g, (struct gpLayout *)msg); + return TRUE; + + case OM_NEW: + return PIP_OMNew(cl, g, (struct opSet *)msg); + + /* We don't need to override OM_DISPOSE */ + + case OM_SET: + case OM_UPDATE: + return PIP_OMSet(cl, g, (struct opUpdate *)msg); + + case OM_GET: + return PIP_OMGet(cl, g, (struct opGet *)msg); + + case PIPM_REFRESH: + return PIP_PIPMRefresh(cl, g, (struct pippRefresh *)msg); + + default: + /* Unsupported method: let our superclass's + * dispatcher take a look at it. + */ + return DoSuperMethodA(cl, (Object *)g, msg); + } +} + + + +static void PIP_GMRender(Class *cl, struct Gadget *g, struct gpRender *msg) +{ + struct PIPData *pip = INST_DATA(cl, g); + struct BitMap *bitmap; + + + if (pip->Scr) + bitmap = pip->Scr->RastPort.BitMap; /* Get screen bitmap */ + else if (pip->BitMap) + bitmap = pip->BitMap; /* Use provided bitmap */ + else + bitmap = NULL; /* Do nothing otherwise */ + + + switch (msg->gpr_Redraw) + { + case GREDRAW_REDRAW: + + if (!bitmap || (bitmap->Depth < msg->gpr_RPort->BitMap->Depth)) + { + /* Clearing all our visible area is needed because + * BltBitMapRastPort() will not clear the bitplanes beyond + * the last bitplane in the source bitmap. + * + * NOTE: The pen number really needs to be 0, not BACKGROUNDPEN! + */ + SetAPen(msg->gpr_RPort, 0); + RectFill(msg->gpr_RPort, + pip->GBox.Left, pip->GBox.Top, + pip->GBox.Left + pip->GBox.Width, pip->GBox.Top + pip->GBox.Height); + } + + /* NOTE: I'm falling through here! */ + + case GREDRAW_UPDATE: + + if (bitmap) + { + /* Scaling, remapping and other similar features could be added here */ + + /* Update gadget display */ + BltBitMapRastPort(bitmap, pip->OffX, pip->OffY, + msg->gpr_RPort, pip->GBox.Left, pip->GBox.Top, + min (pip->GBox.Width, pip->Width), min (pip->GBox.Height, pip->Height), + 0x0C0); + } + /* NOTE: I'm falling through here! */ + + default: + break; + } +} + + + +static ULONG PIP_GMHandleInput(Class *cl, struct Gadget *g, struct gpInput *msg) +{ + struct PIPData *pip = INST_DATA (cl, g); + struct InputEvent *ie = msg->gpi_IEvent; + + + /* Handle GM_GOACTIVE */ + if (msg->MethodID == GM_GOACTIVE) + { + if (!pip->Scr && !pip->BitMap) + return GMR_NOREUSE; + + g->Flags |= GFLG_SELECTED; + + /* Do not process InputEvent when the gadget has been + * activated by ActivateGadget(). + */ + if (!ie) + return GMR_MEACTIVE; + + /* Note: The input event that triggered the gadget + * activation (usually a mouse click) should be passed + * to the GM_HANDLEINPUT method, so we fall down to it. + */ + } + + /* Handle GM_HANDLEINPUT */ + switch (ie->ie_Class) + { + case IECLASS_RAWMOUSE: + { + switch (ie->ie_Code) + { + case MENUDOWN: + /* Deactivate gadget on menu button press */ + return GMR_REUSE; + + case SELECTDOWN: + + /* Check click outside gadget box */ + + if ((msg->gpi_Mouse.X < 0) || + (msg->gpi_Mouse.X >= pip->GBox.Width) || + (msg->gpi_Mouse.Y < 0) || + (msg->gpi_Mouse.Y >= pip->GBox.Height)) + return GMR_REUSE; + + /* Store current mouse coordinates for mouse dragging */ + pip->StartX = pip->OffX + msg->gpi_Mouse.X; + pip->StartY = pip->OffY + msg->gpi_Mouse.Y; + pip->Dragging = TRUE; + + break; + + case SELECTUP: + + /* Stop mouse dragging mode */ + pip->Dragging = FALSE; + + /* Send one final notification to our targets */ + UpdateAttrs((Object *)g, msg->gpi_GInfo, 0, + PIPA_OffX, pip->StartX - msg->gpi_Mouse.X, + PIPA_OffY, pip->StartY - msg->gpi_Mouse.Y, + TAG_DONE); + + break; + + + default: /* Mouse just moved */ + + /* Call our OM_UPDATE method to change the object attributes. + * This will also send notification to targets and + * update the contents of the gadget. + */ + if (pip->Dragging) + UpdateAttrs((Object *)g, msg->gpi_GInfo, OPUF_INTERIM, + PIPA_OffX, pip->StartX - msg->gpi_Mouse.X, + PIPA_OffY, pip->StartY - msg->gpi_Mouse.Y, + GA_ID, g->GadgetID, + TAG_DONE); + } + return GMR_MEACTIVE; + } + + case IECLASS_RAWKEY: + { + LONG tags[3]; + WORD pos; + + switch (ie->ie_Code) + { + case CURSORUP: + if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) + pos = 0; + else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) + pos = pip->OffY - pip->GBox.Height + 1; + else if (ie->ie_Qualifier & IEQUALIFIER_CONTROL) + pos = pip->OffY - 8; + else + pos = pip->OffY - 1; + + + tags[0] = PIPA_OffY; + tags[1] = pos; + tags[2] = TAG_DONE; + break; + + case CURSORDOWN: + if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) + pos = pip->Height - pip->GBox.Height; + else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) + pos = pip->OffY + pip->GBox.Height - 1; + else if (ie->ie_Qualifier & IEQUALIFIER_CONTROL) + pos = pip->OffY + 8; + else + pos = pip->OffY + 1; + + tags[0] = PIPA_OffY; + tags[1] = pos; + tags[2] = TAG_DONE; + break; + + case CURSORLEFT: + if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) + pos = 0; + else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) + pos = pip->OffX - pip->GBox.Width + 1; + else if (ie->ie_Qualifier & IEQUALIFIER_CONTROL) + pos = pip->OffX - 8; + else + pos = pip->OffX - 1; + + tags[0] = PIPA_OffX; + tags[1] = pos; + tags[2] = TAG_DONE; + break; + + case CURSORRIGHT: + if (ie->ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) + pos = pip->Width - pip->GBox.Width; + else if (ie->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) + pos = pip->OffX + pip->GBox.Height - 1; + else if (ie->ie_Qualifier & IEQUALIFIER_CONTROL) + pos = pip->OffX + 8; + else + pos = pip->OffX + 1; + + tags[0] = PIPA_OffX; + tags[1] = pos; + tags[2] = TAG_DONE; + break; + + default: + tags[0] = TAG_DONE; + } + + if (tags[0] != TAG_DONE) + DoMethod((Object *)g, OM_UPDATE, tags, msg->gpi_GInfo, OPUF_INTERIM); + + return GMR_MEACTIVE; + } + + default: + return GMR_MEACTIVE; + } +} + + + +static void PIP_GMGoInactive(Class *cl, struct Gadget *g, struct gpGoInactive *msg) +{ + struct PIPData *pip = INST_DATA (cl, g); + + pip->Dragging = FALSE; + g->Flags &= ~GFLG_SELECTED; +} + + + +static void PIP_GMLayout(Class *cl, struct Gadget *g, struct gpLayout *msg) +{ + struct PIPData *pip = INST_DATA(cl, g); + + GetGadgetBox(msg->gpl_GInfo, g, &pip->GBox); + RestrictXY(pip); + + /* Notify our targets about it */ + NotifyAttrs((Object *)g, msg->gpl_GInfo, 0, + PIPA_OffX, pip->OffX, + PIPA_OffY, pip->OffY, + PIPA_Width, pip->Width, + PIPA_Height, pip->Height, + PIPA_DisplayWidth, pip->GBox.Width, + PIPA_DisplayHeight, pip->GBox.Height, + GA_ID, g->GadgetID, + TAG_DONE); +} + + + +static ULONG PIP_OMNew(Class *cl, struct Gadget *g, struct opSet *msg) +{ + ULONG result; + + if (result = DoSuperMethodA(cl, (Object *)g, (Msg)msg)) + { + struct PIPData *pip = (struct PIPData *) INST_DATA(cl, (Object *)result); + + /* Read creation time attributes */ + pip->Scr = (struct Screen *) GetTagData(PIPA_Screen, NULL, msg->ops_AttrList); + pip->BitMap = (struct BitMap *) GetTagData(PIPA_BitMap, NULL, msg->ops_AttrList); + pip->OffX = (WORD) GetTagData(PIPA_OffX, 0, msg->ops_AttrList); + pip->OffY = (WORD) GetTagData(PIPA_OffY, 0, msg->ops_AttrList); + pip->Dragging = FALSE; + } + return result; +} + + + +static ULONG PIP_OMSet(Class *cl, struct Gadget *g, struct opUpdate *msg) +{ + struct PIPData *pip = (struct PIPData *) INST_DATA(cl, g); + struct TagItem *ti, + *tstate = msg->opu_AttrList; + ULONG result = FALSE; + BOOL do_super_method = FALSE, + render = FALSE, + notify = FALSE; + + while (ti = NextTagItem(&tstate)) + switch (ti->ti_Tag) + { + case PIPA_Screen: + pip->BitMap = NULL; + + if (pip->Scr = (struct Screen *)ti->ti_Data) + { + pip->Width = pip->Scr->Width; + pip->Height = pip->Scr->Height; + } + else + pip->Width = pip->Height = 0; + + RestrictXY(pip); + + break; + + case PIPA_BitMap: + pip->Scr = NULL; + if (pip->BitMap = (struct BitMap *)ti->ti_Data) + { + pip->Width = pip->BitMap->BytesPerRow << 3; + pip->Height = pip->BitMap->Rows; + } + else + pip->Width = pip->Height = 0; + + RestrictXY(pip); + + render = TRUE; + notify = TRUE; + + break; + + case PIPA_OffX: + if (pip->OffX != ti->ti_Data) + { + WORD newx = (WORD)ti->ti_Data; + + /* Restrict offset to valid limits */ + if (newx + pip->GBox.Width > pip->Width) + newx = pip->Width - pip->GBox.Width; + if (newx < 0) + newx = 0; + + if (newx != pip->OffX) + { + pip->OffX = newx; + render = TRUE; + notify = TRUE; + } + } + break; + + case PIPA_OffY: + if (pip->OffY != ti->ti_Data) + { + WORD newy = (WORD)ti->ti_Data; + + /* Restrict offset to valid limits */ + if (newy + pip->GBox.Height > pip->Height) + newy = pip->Height - pip->GBox.Height; + if (newy < 0) + newy = 0; + + if (newy != pip->OffY) + { + pip->OffY = newy; + render = TRUE; + notify = TRUE; + } + } + break; + + case PIPA_MoveUp: + if (pip->OffY) + { + if (pip->OffY > 8) + pip->OffY -= 8; + else + pip->OffY = 0; + + render = TRUE; + notify = TRUE; + } + break; + + case PIPA_MoveDown: + if (pip->OffY < pip->Height - pip->GBox.Height) + { + if (pip->OffY + pip->GBox.Height < pip->Height - 8) + pip->OffY += 8; + else + pip->OffY = pip->Height - pip->GBox.Height; + + render = TRUE; + notify = TRUE; + } + break; + + case PIPA_MoveLeft: + if (pip->OffX) + { + if (pip->OffX > 8) + pip->OffX -= 8; + else + pip->OffX = 0; + + render = TRUE; + notify = TRUE; + } + break; + + case PIPA_MoveRight: + if (pip->OffX < pip->Width - pip->GBox.Width) + { + if (pip->OffX + pip->GBox.Width < pip->Width - 8) + pip->OffX += 8; + else + pip->OffX = pip->Width - pip->GBox.Width; + + render = TRUE; + notify = TRUE; + } + break; + + default: + /* This little optimization avoids forwarding the + * OM_SET method to our superclass when there are + * no unknown tags. + */ + do_super_method = TRUE; + break; + } + + + /* Forward method to our superclass dispatcher, only when needed */ + + if (do_super_method) + result = (DoSuperMethodA(cl, (Object *)g, (Msg) msg)); + + + /* Update gadget imagery, only when needed */ + + if (render && msg->opu_GInfo) + { + struct RastPort *rp; + + if (rp = ObtainGIRPort(msg->opu_GInfo)) + { + DoMethod((Object *)g, + GM_RENDER, msg->opu_GInfo, rp, GREDRAW_UPDATE); + ReleaseGIRPort(rp); + result = TRUE; + } + } + + + /* Notify our targets about all changed attributes, only when needed */ + + if (notify) + NotifyAttrs((Object *)g, msg->opu_GInfo, + (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0, + PIPA_OffX, pip->OffX, + PIPA_OffY, pip->OffY, + GA_ID, g->GadgetID, + TAG_DONE); + + return result; +} + + + +static ULONG PIP_OMGet(Class *cl, struct Gadget *g, struct opGet *msg) +{ + struct PIPData *pip = INST_DATA (cl, g); + + switch (msg->opg_AttrID) + { + case PIPA_Screen: + *(msg->opg_Storage) = (ULONG) pip->Scr; + return TRUE; + + case PIPA_BitMap: + *(msg->opg_Storage) = (ULONG) pip->BitMap; + return TRUE; + + case PIPA_OffX: + *(msg->opg_Storage) = (ULONG) pip->OffX; + return TRUE; + + case PIPA_OffY: + *(msg->opg_Storage) = (ULONG) pip->OffY; + return TRUE; + + case PIPA_Width: + *(msg->opg_Storage) = (ULONG) pip->Width; + return TRUE; + + case PIPA_Height: + *(msg->opg_Storage) = (ULONG) pip->Height; + return TRUE; + + default: + return DoSuperMethodA(cl, (Object *)g, (Msg) msg); + } +} + + + +static ULONG PIP_PIPMRefresh(Class *cl, struct Gadget *g, struct pippRefresh *msg) +{ + struct RastPort *rp; + + if (msg->pipp_GInfo && (rp = ObtainGIRPort(msg->pipp_GInfo))) + { + /* Call our GM_RENDER method */ + + DoMethod((Object *)g, GM_RENDER, msg->pipp_GInfo, rp, GREDRAW_UPDATE); + ReleaseGIRPort(rp); + return TRUE; + } + + return FALSE; +} + + + +static void RestrictXY(struct PIPData *pip) + +/* Restrict XOff and YOff inside bitmap limits */ +{ + if (pip->OffY + pip->GBox.Height > pip->Height) + pip->OffY = pip->Height - pip->GBox.Height; + if (pip->OffY < 0) pip->OffY = 0; + + if (pip->OffX + pip->GBox.Width > pip->Width) + pip->OffX = pip->Width - pip->GBox.Width; + if (pip->OffX < 0) pip->OffX = 0; +} + + + +static void GetGadgetBox(struct GadgetInfo *ginfo, struct Gadget *g, struct IBox *rect) + +/* This function gets the actual IBox where a gadget exists + * in a window. The special cases it handles are all the REL#? + * (relative positioning flags). + */ +{ + rect->Left = g->LeftEdge; + if (g->Flags & GFLG_RELRIGHT) rect->Left += ginfo->gi_Domain.Width - 1; + + rect->Top = g->TopEdge; + if (g->Flags & GFLG_RELBOTTOM) rect->Top += ginfo->gi_Domain.Height - 1; + + rect->Width = g->Width; + if (g->Flags & GFLG_RELWIDTH) rect->Width += ginfo->gi_Domain.Width; + + rect->Height = g->Height; + if (g->Flags & GFLG_RELHEIGHT) rect->Height += ginfo->gi_Domain.Height; +} + + + +Class *MakePIPClass(void) +{ + Class *PIPClass; + + if (PIPClass = MakeClass(NULL, GADGETCLASS, NULL, sizeof (struct PIPData), 0)) + PIPClass->cl_Dispatcher.h_Entry = (ULONG (*)()) PIPDispatcher; + + return PIPClass; +} + + + +void FreePIPClass(Class *PIPClass) +{ + FreeClass(PIPClass); +} diff --git a/gadgets/PIPWin/PIPClass.h b/gadgets/PIPWin/PIPClass.h new file mode 100644 index 0000000..dea71c0 --- /dev/null +++ b/gadgets/PIPWin/PIPClass.h @@ -0,0 +1,74 @@ +#ifndef PIPCLASS_H +#define PIPCLASS_H +/* +** PIPClass.h +** +** Copyright (C) 1996,97 by Bernardo Innocenti +** +** 'Picture In Picture' class built on top of the "gadgetclass". +** +*/ + +#define PIPCLASS "pipclass" +#define PIPVERS 1 + + +Class *MakePIPClass (void); +void FreePIPClass (Class *PIPClass); + + + +/********************/ +/* Class Attributes */ +/********************/ + +#define PIP_Dummy (TAG_USER | ('P'<<16) | ('I'<< 8)) + +#define PIPA_Screen (PIP_Dummy+1) + /* (IGS) Screen to capture data from + */ + +#define PIPA_BitMap (PIP_Dummy+2) + /* (IGS) BitMap to capture data from + */ + +#define PIPA_OffX (PIP_Dummy+3) +#define PIPA_OffY (PIP_Dummy+4) + /* (IGSNU) Offsett of the PIP view + */ + +#define PIPA_Width (PIP_Dummy+5) +#define PIPA_Height (PIP_Dummy+6) + /* (GN) Dimensions of the bitmap being captured. + */ + +#define PIPA_DisplayWidth (PIP_Dummy+7) +#define PIPA_DisplayHeight (PIP_Dummy+8) + /* (GN) Dimensions of the PIP display. + */ + +#define PIPA_MoveUp (PIP_Dummy+9) +#define PIPA_MoveDown (PIP_Dummy+10) +#define PIPA_MoveLeft (PIP_Dummy+11) +#define PIPA_MoveRight (PIP_Dummy+12) + /* (S) Scroll the display towads a direction + */ + + +/*****************/ +/* Class Methods */ +/*****************/ + +#define PIPM_REFRESH (PIP_Dummy+1) +/* + * Tell the object to update its imagery to reflect any changes + * in the attached Screen or BitMap. + */ + +struct pippRefresh +{ + ULONG MethodID; + struct GadgetInfo *pipp_GInfo; +}; + +#endif /* !PIPCLASS_H */ diff --git a/gadgets/PIPWin/PIPWin.c b/gadgets/PIPWin/PIPWin.c new file mode 100644 index 0000000..59cc01a --- /dev/null +++ b/gadgets/PIPWin/PIPWin.c @@ -0,0 +1,1015 @@ +/* +** $Id: PIPWin.c,v 1.2 2000/01/12 21:01:01 bernie Exp $ +** +** Use 4 chars wide TABs to read this file. +** +** +** Introduction +** ============ +** +** This program opens a window showing the contents of a user selected +** public screen. The PIP view can be scrolled around by dragging it +** with mouse or using the cursor keys. +** +** The source code shows how to create a resizable window with sliders +** and how to write a custom `boopsi' class on top of the gadgetclass. +** +** +** Usage +** ===== +** +** PipWin SCREEN,PUB/K,DELAY/K,LEFT/K,TOP/K,WIDTH/K,HEIGHT/K +** +** SCREEN +** the name of the public screen to monitorize +** +** PUBSCREEN +** name of the public screen where the window should open +** +** DELAY +** delay between window refreshes, in tenth of seconds (default: 20) +** +** LEFT, TOP, WIDTH, HEIGHT +** window geometry (in pixels) +** +** +** Compiling +** ========= +** +** This project can be compiled with: +** - SAS/C (version 6.58 or newer) +** - gcc (version 2.7.2.1 or newer) and egcs (version 1.1b or newer) +** - StormC (version 2.00.14 or newer) +** +** You get the smallest executable with SAS/C. gcc will give you +** quite a lot of warnings with the tag calls. Don't worry about them. +** +** +** History +** ======= +** +** 1.0 (3.12.95) -- First version by Alfonso Caschili +** +** 1.1 (27.3.96) -- Major revamp by Bernardo Innocenti +** +** - Source cleaned up, re-indented and commented the way I like it :) +** +** - Fixed a bug with CTRL-C handling +** +** - Does not keep a lock on the screen where the window opens for all the time +** +** - Argument parsing improved a bit +** +** - Does not need C startup code anymore (saves some KB) +** +** - Window positioning and sizing is a bit smarter +** +** - Does not refresh the window twice on startup +** +** +** 2.0 (14.4.96) -- Rewritten using a `boopsi' class by Bernardo Innocenti +** +** - Created the PIP 'boopsi' class +** +** - Added sliders and buttons in window borders +** +** - Added no-op backfilling hook (makes resizing and depth arragnging +** much faster and less flickering +** +** +** 2.1 (8.5.96) +** +** - Fixed window positioning bug. Window was being positioned just below +** the screen title bar, but it was looking on the titlebar height of +** the screen being captured instead of the screen when the window was +** to be opened +** +** - Changed PATTA_#? attributes to PIPA_#? attributes in the boopsi +** interconnection diagram. PATTA_ is the attribute prefix for the +** pattedit.gadget, another boopsi class written by me +** +** - Changed to always keep a lock on the screen where the window opens. +** This is needed because we are trying to free the associated DrawInfo +** strucure *after* closing the window. Without a proper lock, our host +** screen could close just after we closed our window, which would make +** the parameter we pass to FreeScreenDrawInfo() an invalid pointer +** +** - Fixed a bug that caused a call to still BltBitMapRastPort() with a +** NULL BitMap pointer when the PIPA_BitMap attribute was set to NULL +** +** - Added error report for bad arguments +** +** +** 2.2 (28.4.97) +** +** - Added gcc compiler support (untested) +** +** - Now uses a custom DoMethod() stub (faster than calling amiga.lib one) +** +** - Fixed the arrow buttons positioning when their width/height is +** not the same of the size gadget +** +** 2.3 (10.5.97) +** +** - Fixed LEFT, TOP, WIDTH & HEIGHT command line arguments. The +** OpenPIPWin() function was passing the *pointers* to the LONG +** values to OpenWindowTags(). (Riccardo Torrini) +** +** - Dragging the view to the extreme left or top does no longer send +** negative numbers when notifying the sliders. +** +** - Removed test to check if GetScreenDrawInfo() fails because this +** function is always successful +** +** +** 2.4 (15.8.97) +** +** - Added StormC compiler support +** +** - gcc support tested: works fine with latest GeekGadgets snapshot +** +** +** 2.5 (15.9.97) +** +** - Compiled with SAS/C 6.58 +** +** - Improved SMakefile, now PIPWin is not need to be linked with +** any static libraries +** +** - Size reduced even more! +** +** 2.6 (13.10.97) +** +** - Fixed scroll bars positioning with non standard window +** border sizes +** +** - gcc version can now be built without linking with libnix +** +** - Replaced call to RefreshGList() with the new PIPM_Refresh +** class method, which in turn calls GM_RENDER with mode GREDRAW_UPDATE. +** +** +** To Do +** ===== +** +** - Add a requester to select a public screen to snoop +** +** - Allow opening more than one window +** +** - Workbench startup and ToolTypes parsing +** +** - Allow zooming into the bitmap +** +** - Make the pipclass update its imagery automatically at given +** time intervals. This would require creating a Process for each +** istance the class, or perhaps one single Process for all objects. +** Unfortunately, most gadgetclass methods can not be called by +** soft interrupts, so it seems we really need a process :-( +** +** - This one is very ambitious: it should be possible to forward mouse +** and keyboard input to the screen being displayed. This would allow +** the user to actually USE programs without bringing their screens +** to front +** +** - Optimize display scrolling in some special cases. When the bitmap +** of the screen being displayed is not the same format of the bitmap +** where the PIP gadget renders (i.e.: they arn't `friend bitmaps'), +** some kind of conversion (e.g.: planar to chunky) will be done +** transparently by CopyBitMapRastPort(). This operation might be +** very slow, making more convenient to ScrollRaster() the existing +** image and copy just the part that gets revealed by the scrolling +** +** - Change the mouse pointer to a grabbing hand while user is dragging +** the display +** +** +** Copyright Notice +** ================ +** +** Copyright © 1995 by Alfonso Caschili . +** Freely Distributable. +** +** Copyright © 1996,97 by Bernardo Innocenti . +** 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#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 */ + +#ifdef __STORM__ + #define UTILITYBASETYPE struct Library +#else + #define UTILITYBASETYPE struct UtilityBase +#endif + + +/* Library bases */ + +struct ExecBase *SysBase; +struct DosLibrary *DOSBase; +struct IntuitionBase *IntuitionBase; +struct GfxBase *GfxBase; +UTILITYBASETYPE *UtilityBase; + + + +/* Our private `boopsi' classes */ + +static Class *PIPClass; +static Class *ScrollButtonClass; + + + +/* 'boopsi' images for all our windows + * + * These variables must be NULL at startup time. We are not + * going to explicitly initialize them because otherwise + * Storm C 2.0 would generate a constructor to do it :-) + * LoasSeg() will clear the BSS data section for us, so + * these variables are guaranteed to be NULL anyway. + */ +static struct Image *Img[IMG_COUNT]; +static ULONG ImgWidth[IMG_COUNT]; +static ULONG ImgHeight[IMG_COUNT]; + + + +/* Attribute translations for object interconnections */ + +static const ULONG MapPIPToHSlider[] = +{ + PIPA_OffX, PGA_Top, + PIPA_Width, PGA_Total, + PIPA_DisplayWidth, PGA_Visible, + TAG_DONE +}; + +static const ULONG MapHSliderToPIP[] = +{ + PGA_Top, PIPA_OffX, + TAG_DONE +}; + +static const ULONG MapPIPToVSlider[] = +{ + PIPA_OffY, PGA_Top, + PIPA_Height, PGA_Total, + PIPA_DisplayHeight, PGA_Visible, + TAG_DONE +}; + + +static const ULONG MapVSliderToPIP[] = +{ + PGA_Top, PIPA_OffY, + TAG_DONE +}; + +static const ULONG MapUpButtonToPIP[] = +{ + GA_ID, PIPA_MoveUp, + TAG_DONE +}; + +static const ULONG MapDownButtonToPIP[] = +{ + GA_ID, PIPA_MoveDown, + TAG_DONE +}; + +static const ULONG MapLeftButtonToPIP[] = +{ + GA_ID, PIPA_MoveLeft, + TAG_DONE +}; + +static const ULONG MapRightButtonToPIP[] = +{ + GA_ID, PIPA_MoveRight, + TAG_DONE +}; + + + +LONG SAVEDS _main(void) + +/* Main program entry point. When linking without startup code, this + * must be the first function in the first object module listed on the + * linker command line. We also need to initialize SysBase and open + * all needed libraries manually. + */ +{ + struct PIPHandle *piphandle; + struct RDArgs *rdargs; + struct MsgPort *TimerMsgPort; + struct timerequest *TimerIO; + LONG args[ARG_COUNT] = { 0 }; + LONG sigwait, sigrcvd; + LONG secs, micros; + LONG retval = RETURN_FAIL; + BOOL quit = FALSE; + + + /* Initialize SysBase */ + SysBase = *((struct ExecBase **)4UL); + + if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37L)) + { + if (UtilityBase = (UTILITYBASETYPE *) OpenLibrary("utility.library", 37L)) + { + /* Parse shell arguments */ + if (rdargs = ReadArgs(ARGS_TEMPLATE, args, NULL)) + { + if (args[ARG_DELAY]) + { + /* We use utility.library math because it works for 68000 too */ + secs = UDivMod32(*((LONG *)args[ARG_DELAY]), 10); + micros = UMult32((*((LONG *)args[ARG_DELAY]) - UMult32 (secs, 10)), 100000); + } + else + { + secs = 2; + micros = 0; + } + + if (IntuitionBase = (struct IntuitionBase *) + OpenLibrary("intuition.library", 39)) + { + if (GfxBase = (struct GfxBase *) + OpenLibrary("graphics.library", 39)) + { + if (TimerMsgPort = CreateMsgPort()) + { + if (TimerIO = (struct timerequest *) CreateIORequest(TimerMsgPort, sizeof (struct timerequest))) + { + if (!OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)TimerIO, 0)) + { + if (PIPClass = MakePIPClass()) + { + if (ScrollButtonClass = MakeScrollButtonClass()) + { + if (piphandle = OpenPIPWin((UBYTE *)args[ARG_SCREEN], (UBYTE *)args[ARG_PUBSCREEN], + (ULONG *)args[ARG_LEFT], (ULONG *)args[ARG_TOP], + (ULONG *)args[ARG_WIDTH], (ULONG *)args[ARG_HEIGHT])) + { + /* Pre-calculate the signal mask for Wait() */ + sigwait = (1 << TimerMsgPort->mp_SigBit) | + (1 << piphandle->Win->UserPort->mp_SigBit) | + SIGBREAKF_CTRL_C; + + /* Send our first IORequest to timer.device */ + TimerIO->tr_node.io_Command = TR_ADDREQUEST; + TimerIO->tr_time.tv_secs = secs; + TimerIO->tr_time.tv_micro = micros; + SendIO ((struct IORequest *)TimerIO); + + /* Now for the main loop. As you can see, it is really + * very compact. That's the magic of boopsi! :-) + */ + while (!quit) + { + /* Sleep until something interesting occurs */ + sigrcvd = Wait(sigwait); + + /* Now handle received signals */ + + /* Break signal? */ + if (sigrcvd & SIGBREAKF_CTRL_C) + quit = TRUE; + + /* timer.device? */ + if (sigrcvd & (1 << TimerMsgPort->mp_SigBit)) + { + /* Update the PIP gadget and send another + * request to the timer.device + */ + DoGadgetMethod(piphandle->Gad[GAD_PIP], piphandle->Win, NULL, + PIPM_REFRESH, NULL); + + TimerIO->tr_node.io_Command = TR_ADDREQUEST; + TimerIO->tr_time.tv_secs = secs; + TimerIO->tr_time.tv_micro = micros; + SendIO((struct IORequest *)TimerIO); + } + + /* IDCMP message? */ + if (sigrcvd & (1 << piphandle->Win->UserPort->mp_SigBit)) + { + struct IntuiMessage *msg; + + while (msg = (struct IntuiMessage *) GetMsg(piphandle->Win->UserPort)) + { + switch (msg->Class) + { + case IDCMP_CLOSEWINDOW: + quit = TRUE; + break; + + default: + break; + } + ReplyMsg ((struct Message *) msg); + } + } + } /* End while (!quit) */ + + retval = RETURN_OK; + + /* Abort the IORequest sent to the timer.device */ + AbortIO((struct IORequest *)TimerIO); + WaitIO((struct IORequest *)TimerIO); + + ClosePIPWin(piphandle); + } + + FreeImages(); + /* This one cannot fail */ + FreeScrollButtonClass(ScrollButtonClass); + } + /* This one cannot fail */ + FreePIPClass(PIPClass); + } + CloseDevice((struct IORequest *)TimerIO); + } + DeleteIORequest((struct IORequest *)TimerIO); + } + DeleteMsgPort(TimerMsgPort); + } + CloseLibrary((struct Library *)GfxBase); + } + CloseLibrary((struct Library *)IntuitionBase); + } + FreeArgs(rdargs); + } + else PrintFault(IoErr(), (STRPTR)PrgName); + + CloseLibrary((struct Library *)UtilityBase); + } + CloseLibrary((struct Library *)DOSBase); + } + + return retval; +} + + + +static struct PIPHandle *OpenPIPWin(UBYTE *screen, UBYTE *pubscreen, + ULONG *left, ULONG *top, ULONG *width, ULONG *height) +{ + struct PIPHandle *piphandle; + struct Gadget *glist; + + + if (piphandle = AllocMem(sizeof (struct PIPHandle), MEMF_ANY | MEMF_CLEAR)) + { + if (piphandle->SpyScr = LockPubScreen(screen)) + { + if (piphandle->Scr = LockPubScreen(pubscreen)) + { + if (glist = CreateGadgets(piphandle)) + { + SetAttrs(glist, + PIPA_Screen, piphandle->SpyScr, + TAG_DONE); + + if (piphandle->Win = OpenWindowTags(NULL, + WA_Left, left ? *left : 0, + WA_Top, top ? *top : piphandle->Scr->BarHeight + 1, + WA_InnerWidth, width ? *width : piphandle->SpyScr->Width, + WA_InnerHeight, height ? *height : piphandle->SpyScr->Height, + WA_MinWidth, 64, + WA_MinHeight, 64, + WA_MaxWidth, piphandle->SpyScr->Width, + WA_MaxHeight, piphandle->SpyScr->Height, + WA_PubScreen, piphandle->Scr, + WA_PubScreenFallBack, TRUE, + WA_AutoAdjust, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | + WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM | + WFLG_SIMPLE_REFRESH | WFLG_NOCAREREFRESH, + WA_Gadgets, glist, + WA_BackFill, LAYERS_NOBACKFILL, + WA_Title, piphandle->SpyScr->DefaultTitle, + WA_ScreenTitle, versiontag + 6, + TAG_DONE)) + + /* We need to keep our screen locked all the time + * because we want to free the associated DrawInfo + * *after* the window has been closed and + * FreeScreenDrawInfo() wants a pointer to a *valid* + * Screen. + */ + return piphandle; + DisposeGadgets(piphandle); + } + UnlockPubScreen(NULL, piphandle->Scr); + } + UnlockPubScreen(NULL, piphandle->SpyScr); + } + FreeMem(piphandle, sizeof (struct PIPHandle)); + } + return NULL; +} + + + +static void ClosePIPWin(struct PIPHandle *piphandle) +{ + /* Close our window. No need to reply queued messages, + * Intuition is clever enough to care about this for us. + */ + CloseWindow(piphandle->Win); + DisposeGadgets(piphandle); + UnlockPubScreen(NULL, piphandle->Scr); + UnlockPubScreen(NULL, piphandle->SpyScr); + FreeMem(piphandle, sizeof (struct PIPHandle)); +} + + + +/* + * Diagram of object interconnections + * ================================== + * + * + * ScrollButtonClass objects + * +----------+ +------------+ +------------+ +-------------+ + * | UpButton | | DownButton | | LeftButton | | RightButton | + * +----------+ +------------+ +------------+ +-------------+ + * | GA_ID = | GA_ID = | GA_ID = | GA_ID = + * | PIPA_MoveUp | PIPA_MoveDown | PIPA_MoveLeft | PIPA_MoveRight + * | | | | + * | +----------+ | | + * | | +-----------------------+ | + * | | | +------------------------------------+ + * | | | | propgclass object icclass object + * | | | | +-----------+ +--------------+ + * | | | | | HSlider |<-----| PIPToHSlider | + * | | | | +-----------+ +--------------+ + * | | | | PGA_Top = | ^ PIPA_OffX = PGA_Top + * | | | | PIPA_OffX | | PIPA_Width = PGA_Visible + * | | | | | | PIPA_DisplayWidth = + * V V V V V | PGA_Total + * +-----------+ *********** | + * | |-------->* *------------+ + * | PIP | * Model * + * | |<--------* *------------+ + * +-----------+ *********** | + * ^ | + * PGA_Top = | | + * PIPA_OffY | V icclass object + * +-----------+ +--------------+ + * | VSlider |<-----| PIPToVSlider | + * +-----------+ +--------------+ + * propgclass object PIPA_OffY = PGA_Top + * PIPA_Height = PGA_Visible + * PIPA_DisplayHeight = PGA_Total + */ + +static struct Gadget *CreateGadgets(struct PIPHandle *piphandle) +{ + struct DrawInfo *dri; + struct Screen *scr = piphandle->Scr; + struct Image *SizeImage; + ULONG SizeWidth = 18, SizeHeight = 11; /* Default values */ + + /* GetScreenDrawInfo() never fails */ + dri = piphandle->DrawInfo = GetScreenDrawInfo (scr); + + /* Create a new size image to get its size */ + if (SizeImage = NewObject(NULL, SYSICLASS, + SYSIA_Which, SIZEIMAGE, + SYSIA_DrawInfo, dri, + TAG_DONE)) + { + /* Get size gadget geometry */ + GetAttr(IA_Width, SizeImage, &SizeWidth); + GetAttr(IA_Height, SizeImage, &SizeHeight); + + /* And then get rid of it... */ + DisposeObject(SizeImage); + } + + /* No need to check this: in case of failure we would just + * get no images in the scroll buttons, but we can still try + * to open our window. + */ + CreateImages(dri); + + if (piphandle->Model = NewObjectA(NULL, MODELCLASS, NULL)) + if (piphandle->Gad[GAD_PIP] = NewObject (PIPClass, NULL, + GA_ID, GAD_PIP, + GA_Left, scr->WBorLeft, + GA_Top, scr->WBorTop + scr->Font->ta_YSize + 1, + GA_RelWidth, - SizeWidth - scr->WBorLeft, + GA_RelHeight, - (scr->WBorTop + scr->Font->ta_YSize + SizeHeight + 1), + GA_DrawInfo, dri, + ICA_TARGET, piphandle->Model, + TAG_DONE)) + if (piphandle->Gad[GAD_VSLIDER] = NewObject(NULL, PROPGCLASS, + GA_ID, GAD_VSLIDER, + GA_Previous, piphandle->Gad[GAD_PIP], + GA_RelRight, - SizeWidth + 5, + GA_Top, scr->WBorTop + scr->Font->ta_YSize + 2, + GA_Width, SizeWidth - 8, + GA_RelHeight, - (scr->WBorTop + scr->Font->ta_YSize + + SizeHeight + ImgHeight[IMG_DOWN] + ImgHeight[IMG_UP] + 4), + GA_RightBorder, TRUE, + GA_DrawInfo, dri, + PGA_Freedom, FREEVERT, + PGA_Borderless, ((dri->dri_Flags & DRIF_NEWLOOK) && (dri->dri_Depth != 1)), + PGA_NewLook, TRUE, + ICA_TARGET, piphandle->Model, + ICA_MAP, MapVSliderToPIP, + TAG_DONE)) + if (piphandle->Gad[GAD_HSLIDER] = NewObject(NULL, PROPGCLASS, + GA_ID, GAD_HSLIDER, + GA_Previous, piphandle->Gad[GAD_VSLIDER], + GA_RelBottom, - SizeHeight + ((SizeHeight > 15) ? 4 : 3), + GA_Left, scr->WBorLeft, + GA_Height, SizeHeight - ((SizeHeight > 15) ? 6 : 4), + GA_RelWidth, - (SizeWidth + ImgWidth[IMG_RIGHT] + ImgWidth[IMG_LEFT] + scr->WBorLeft + 2), + GA_BottomBorder,TRUE, + GA_DrawInfo, dri, + PGA_Freedom, FREEHORIZ, + PGA_Borderless, ((dri->dri_Flags & DRIF_NEWLOOK) && (dri->dri_Depth != 1)), + PGA_NewLook, TRUE, + ICA_TARGET, piphandle->Model, + ICA_MAP, MapHSliderToPIP, + TAG_DONE)) + if (piphandle->Gad[GAD_UPBUTTON] = NewObject(ScrollButtonClass, NULL, + GA_ID, GAD_UPBUTTON, + GA_Previous, piphandle->Gad[GAD_HSLIDER], + GA_RelBottom, - SizeHeight - ImgHeight[IMG_DOWN] - ImgHeight[IMG_UP] + 1, + GA_RelRight, - ImgWidth[IMG_DOWN] + 1, + GA_RightBorder, TRUE, + GA_DrawInfo, dri, + GA_Image, Img[IMG_UP], + ICA_TARGET, piphandle->Gad[GAD_PIP], + ICA_MAP, MapUpButtonToPIP, + TAG_DONE)) + if (piphandle->Gad[GAD_DOWNBUTTON] = NewObject(ScrollButtonClass, NULL, + GA_ID, GAD_DOWNBUTTON, + GA_Previous, piphandle->Gad[GAD_UPBUTTON], + GA_RelBottom, - SizeHeight - ImgHeight[IMG_DOWN] + 1, + GA_RelRight, - ImgWidth[IMG_DOWN] + 1, + GA_RightBorder, TRUE, + GA_DrawInfo, dri, + GA_Image, Img[IMG_DOWN], + ICA_TARGET, piphandle->Gad[GAD_PIP], + ICA_MAP, MapDownButtonToPIP, + TAG_DONE)) + if (piphandle->Gad[GAD_LEFTBUTTON] = NewObject(ScrollButtonClass, NULL, + GA_ID, GAD_LEFTBUTTON, + GA_Previous, piphandle->Gad[GAD_DOWNBUTTON], + GA_RelBottom, - ImgHeight[IMG_LEFT] + 1, + GA_RelRight, - SizeWidth - ImgWidth[IMG_RIGHT] - ImgWidth[IMG_LEFT] + 1, + GA_BottomBorder,TRUE, + GA_DrawInfo, dri, + GA_Image, Img[IMG_LEFT], + ICA_TARGET, piphandle->Gad[GAD_PIP], + ICA_MAP, MapLeftButtonToPIP, + TAG_DONE)) + if (piphandle->Gad[GAD_RIGHTBUTTON] = NewObject(ScrollButtonClass, NULL, + GA_ID, GAD_RIGHTBUTTON, + GA_Previous, piphandle->Gad[GAD_LEFTBUTTON], + GA_RelBottom, - ImgHeight[IMG_RIGHT] + 1, + GA_RelRight, - SizeWidth - ImgWidth[IMG_RIGHT] + 1, + GA_BottomBorder,TRUE, + GA_DrawInfo, dri, + GA_Image, Img[IMG_RIGHT], + ICA_TARGET, piphandle->Gad[GAD_PIP], + ICA_MAP, MapRightButtonToPIP, + TAG_DONE)) + { + APTR icobject; + + /* Connect VSlider to Model */ + + if (icobject = NewObject(NULL, ICCLASS, + ICA_TARGET, piphandle->Gad[GAD_VSLIDER], + ICA_MAP, MapPIPToVSlider, + TAG_DONE)) + if (!DoMethod (piphandle->Model, OM_ADDMEMBER, icobject)) + DisposeObject (icobject); + + /* Connect HSlider to Model */ + + if (icobject = NewObject(NULL, ICCLASS, + ICA_TARGET, piphandle->Gad[GAD_HSLIDER], + ICA_MAP, MapPIPToHSlider, + TAG_DONE)) + if (!DoMethod (piphandle->Model, OM_ADDMEMBER, icobject)) + DisposeObject (icobject); + + /* Connect Model to PIP */ + + SetAttrs(piphandle->Model, + ICA_TARGET, piphandle->Gad[GAD_PIP], + TAG_DONE); + + return piphandle->Gad[GAD_PIP]; + } + DisposeGadgets(piphandle); + + return NULL; +} + + + +static void DisposeGadgets(struct PIPHandle *piphandle) +{ + ULONG i; + + for (i = 0; i < GAD_COUNT; i++) + { + DisposeObject(piphandle->Gad[i]); + /* piphandle->Gad[i] = NULL; */ + } + + /* Freeing the Model will also free its two targets */ + DisposeObject(piphandle->Model); + /* piphandle->Model = NULL */ + + FreeScreenDrawInfo(piphandle->Scr, piphandle->DrawInfo); + /* piphandle->DrawInfo = NULL */ +} + + + +static void CreateImages(struct DrawInfo *dri) + +/* Create 4 arrow images for the window scrolling buttons. + * + * Why bother checking for failure? The arrow images are not + * life critical in our program... + */ +{ + static ULONG imagetypes[IMG_COUNT] = { UPIMAGE, DOWNIMAGE, LEFTIMAGE, RIGHTIMAGE }; + ULONG i; + + for (i = 0; i < IMG_COUNT; i++) + if (!Img[i]) + if (Img[i] = (struct Image *)NewObject(NULL, SYSICLASS, + SYSIA_Which, imagetypes[i], + SYSIA_DrawInfo, dri, + TAG_DONE)) + { + /* Ask image width and height */ + GetAttr(IA_Width, Img[i], &ImgWidth[i]); + GetAttr(IA_Height, Img[i], &ImgHeight[i]); + } +} + + + +static void FreeImages(void) +{ + ULONG i; + + for (i = 0; i < IMG_COUNT; i++) + DisposeObject((APTR)Img[i]); /* DisposeObject(NULL) is safe */ +} + + + +/* +** ScrollButtonClass +** +** This code has been taken from ScrollerWindow 0.3 +** Copyright © 1994 Christoph Feck, TowerSystems. +** +** Subclass of buttongclass. The ROM class has two problems, which make +** it not quite usable for scrollarrows. The first problem is the missing +** delay. Once the next INTUITICK gets send by input.device, the ROM +** class already sends a notification. The other problem is that it also +** notifies us, when the button finally gets released (which is necessary +** for command buttons). +** +** We define a new class with the GM_GOACTIVE and GM_HANDLEINPUT method +** overloaded to work around these problems. +*/ + + + +/* Function prototypes */ + +static ULONG HOOKCALL ScrollButtonDispatcher( + REG(a0, Class *cl), + REG(a2, struct Gadget *g), + REG(a1, struct gpInput *gpi)); + + +/* Per object instance data */ +struct ScrollButtonData +{ + /* The number of ticks we still have to wait + * before sending any notification. + */ + ULONG TickCounter; +}; + + + +static ULONG HOOKCALL ScrollButtonDispatcher( + REG(a0, Class *cl), + REG(a2, struct Gadget *g), + REG(a1, struct gpInput *gpi)) + +/* ScrollButton Class Dispatcher entrypoint. + * Handle BOOPSI messages. + */ +{ + struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g); + + switch (gpi->MethodID) + { + case GM_GOACTIVE: + /* May define an attribute to make delay configurable */ + bd->TickCounter = 3; + + /* Notify our target that we have initially hit. */ + NotifyAttrs((Object *)g, gpi->gpi_GInfo, 0, + GA_ID, g->GadgetID, + TAG_DONE); + + /* Send more input */ + return GMR_MEACTIVE; + + case GM_HANDLEINPUT: + { + ULONG retval = GMR_MEACTIVE; + UWORD selected = 0; + + /* This also works with classic (non-boopsi) images. */ + if (PointInImage((gpi->gpi_Mouse.X << 16) + (gpi->gpi_Mouse.Y), g->GadgetRender)) + { + /* We are hit */ + selected = GFLG_SELECTED; + } + + if (gpi->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE && gpi->gpi_IEvent->ie_Code == SELECTUP) + { + /* Gadgetup, time to go */ + retval = GMR_NOREUSE; + /* Unselect the gadget on our way out... */ + selected = 0; + } + else if (gpi->gpi_IEvent->ie_Class == IECLASS_TIMER) + { + /* We got a tick: decrement counter, and if 0, send notify. */ + + if (bd->TickCounter) bd->TickCounter--; + else if (selected) + /* Notify our target that we are still being hit */ + NotifyAttrs((Object *)g, gpi->gpi_GInfo, 0, + GA_ID, g->GadgetID, + TAG_DONE); + } + + if ((g->Flags & GFLG_SELECTED) != selected) + { + struct RastPort *rp; + + /* Update changes in gadget render */ + g->Flags ^= GFLG_SELECTED; + if (rp = ObtainGIRPort(gpi->gpi_GInfo)) + { + DoMethod((Object *) g, GM_RENDER, gpi->gpi_GInfo, rp, GREDRAW_UPDATE); + ReleaseGIRPort (rp); + } + } + return retval; + } + + default: + /* Super class handles everything else */ + return (DoSuperMethodA(cl, (Object *)g, (Msg) gpi)); + } +} + + + +static Class *MakeScrollButtonClass(void) +{ + Class *class; + + if (class = MakeClass(NULL, BUTTONGCLASS, NULL, sizeof(struct ScrollButtonData), 0)) + class->cl_Dispatcher.h_Entry = (ULONG (*)()) ScrollButtonDispatcher; + + return class; +} + + + +static BOOL FreeScrollButtonClass(Class *cl) +{ + return (FreeClass(cl)); +} diff --git a/gadgets/PIPWin/PIPWin.mdbi b/gadgets/PIPWin/PIPWin.mdbi new file mode 100755 index 0000000..02ebb32 Binary files /dev/null and b/gadgets/PIPWin/PIPWin.mdbi differ diff --git a/gadgets/PIPWin/PIPWin.project b/gadgets/PIPWin/PIPWin.project new file mode 100755 index 0000000..9d648d1 --- /dev/null +++ b/gadgets/PIPWin/PIPWin.project @@ -0,0 +1,39 @@ +;MaxonCPP-Project + + +-dir "Work:SC/src/PIPWin/" -args "" -stack 10 -pri 0 + + + + +-gD -gs -gh50 -w100 +-j "PROGDIR:amiga/mcpp-libs/" + + + +-waCEFNMOPRTV -pc -g00 -g80 -gO -gb0 -gM -bs0 -a0 -t -px -bf -mX +-i "PROGDIR:amiga/c-inc/" +-i "Include:" + + + +-c cWSElMo0F -0xff +-i "Include:" + + + + +"PIPWin.c" "PIPWin.o" + + -pri 5 + +"PIPClass.c" "PIPClass.o" + + + +"LIB:amiga.lib" + + -dontlink + + + diff --git a/gadgets/PIPWin/PIPWin.readme b/gadgets/PIPWin/PIPWin.readme new file mode 100644 index 0000000..cab007a --- /dev/null +++ b/gadgets/PIPWin/PIPWin.readme @@ -0,0 +1,37 @@ +Short: Picture In Picture window/boopsi class (binary + C source) +Author: bernie@shock.cosmos.it (Bernardo Innocenti) +Uploader: bernie@shock.cosmos.it (Bernardo Innocenti) +Type: dev/src +Version: 2.6 +Replaces: dev/src/PIPWin.lha + + PIPWin opens a window on any public screen which shows the contents of +a user selected public screen. You can resize and scroll by dragging +inside the window or using the cursor keys. + +The source code demonstrates how to: + + * Building a `boopsi' class on top of the gadgetclass + + * Writing a `boopsi' dispatcher with complex input handling + + * Using `boopsi' sysiclass images + + * Connecting `boopsi' objects together using the icclass + + * Overlaying the buttongclass to make a scrollbutton + + * Creating a sizeable window with sliders + + * Making a C program with no startup and no need to link + with static libraries such as amiga.lib + + * Using the timer.device + + * Making Amiga specific code which works with SAS/C, + GCC and StormC. + + * Correctly opening/closing libraries, devices and other + system resources + + * Parsing command line arguments with ReadArgs() diff --git a/gadgets/PIPWin/PIPWin.sas b/gadgets/PIPWin/PIPWin.sas new file mode 100755 index 0000000..258aabd Binary files /dev/null and b/gadgets/PIPWin/PIPWin.sas differ diff --git a/gadgets/PIPWin/SMakefile b/gadgets/PIPWin/SMakefile new file mode 100644 index 0000000..b687e2d --- /dev/null +++ b/gadgets/PIPWin/SMakefile @@ -0,0 +1,95 @@ +## +## $Id:$ +## +## Copyright (C) 1996,97 by Bernardo Innocenti +## +## Makefile for SAS/C +## + +########################################################### +# Name of the main executable +########################################################### +# +PROJ = PIPWin + + +########################################################### +# Package configuration +########################################################### +# + +# Cpu to compile for (eg: "68020"). +# +CPU = 68000 + + +########################################################### +# Object files in this project +########################################################### +# +OBJS = PIPWin.o PIPClass.o + + +########################################################### +# Make the project +########################################################### +# +all: $(PROJ) + + +########################################################### +# Remove all targets and intermediate files +########################################################### +# +clean: + -Delete $(PROJ) $(OBJS) + + +########################################################### +# Dependences +########################################################### +# +PIPWin.c PIPClass.c: PIPClass.h + + +########################################################### +# Compiler, linker and assembler flags +########################################################### +# + +# C compiler flags for both release and debug versions +# +COMMON_CFLAGS = PARAMETERS=REGISTERS STRINGMERGE NOSTACKCHECK NOCHECKABORT \ + NOICONS NOLINK DATA=NEAR CODE=NEAR STRSECT=CODE DEF=$(OSVER) CPU=$(CPU) + +# C compiler optimization flags +# +OPT_CFLAGS = OPTIMIZE OPTTIME OPTSCHEDULER OPTINLINELOCAL \ + OPTRDEPTH=4 OPTDEPTH=4 OPTCOMP=8 + +# Debug flags: don't optimize and include all symbols in debug hunks +# +DEBUG_CFLAGS = NOOPTIMIZE DEBUG=FULLFLUSH ONERROR=CONTINUE DEF=DEBUG + + +# RELEASE version should be compiled with these flags +# +CFLAGS = $(COMMON_CFLAGS) $(OPT_CFLAGS) +LFLAGS = NODEBUG SMALLCODE SMALLDATA NOALVS NOICONS + + +# DEBUG version should be compiled with these flags +# +#CFLAGS = $(COMMON_CFLAGS) $(DEBUG_CFLAGS) +#LFLAGS = ADDSYM SMALLCODE SMALLDATA BATCH NOALVS NOICONS +#LIBS = LIB LIB:debug.lib + + +########################################################### +# Make the executable +########################################################### +# +# NOTE: Using implicit rule to compile C files + +$(PROJ): $(OBJS) + $(LD) FROM $(OBJS) TO $(PROJ) $(LIBS) $(LFLAGS) diff --git a/gadgets/ResizeGClass/Makefile b/gadgets/ResizeGClass/Makefile new file mode 100644 index 0000000..eb79630 --- /dev/null +++ b/gadgets/ResizeGClass/Makefile @@ -0,0 +1,27 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(BOOPSITOP)/config.mk +include config.mk + +ARG_COMMON := +ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o +ARG_LIB := $(ARG_COMMON) +ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV) +ARG_PRIVATE := $(ARG_COMMON) +ARG_OBJ := $(ARG_COMMON) + +DEP_COMMON := +DEP_ALL := $(DEP_COMMON) OpenClass.o +DEP_LIB := $(DEP_COMMON) +DEP_DEBUG := $(DEP_COMMON) OpenClass.o +DEP_PRIVATE := $(DEP_COMMON) +DEP_OBJ := $(DEP_COMMON) + +include $(BOOPSITOP)/common/general.mk + +OpenClass.o: OpenClass.c + $(MAKE) -C $(BOOPSITOP)/common/ $@ diff --git a/gadgets/ResizeGClass/config.mk b/gadgets/ResizeGClass/config.mk new file mode 100644 index 0000000..2581884 --- /dev/null +++ b/gadgets/ResizeGClass/config.mk @@ -0,0 +1,28 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +########################################################### +# your stuff +# +CLASSLIB := resize.gadget +CLASSSRC := ResizeGClass.c +DEMOSRC := ResizeGDemo.c +SUBDIR := gadgets + + +########################################################### +# class version information +# +CLASSVER := 0 +CLASSREV := 1 +CLASSDATE := (6.4.99) + + +########################################################### +# variable to make the linked library version +# +PRV := PRIVATE_RESIZEGCLASS + diff --git a/gadgets/ScrollButton/Makefile b/gadgets/ScrollButton/Makefile new file mode 100644 index 0000000..1f0f97d --- /dev/null +++ b/gadgets/ScrollButton/Makefile @@ -0,0 +1,28 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +TOP := ../.. + +include $(TOP)/config.mk + +# +# Class specific information +# +CLASSLIB := scrollbutton.gadget +CLASSSRC := ScrollButtonClass.c +CLASSOBJ := $(TOP)/common/GetGadgetBox.o +NOSTDLIB := 1 +INSTALLDIR := gadgets + +# +# Class version information +# +CLASSVER := 1 +CLASSREV := 0 +CLASSDATE := (21.3.2000) + +include $(TOP)/common/general.mk + diff --git a/gadgets/ScrollButton/ScrollButtonClass.c b/gadgets/ScrollButton/ScrollButtonClass.c new file mode 100644 index 0000000..ceb99b7 --- /dev/null +++ b/gadgets/ScrollButton/ScrollButtonClass.c @@ -0,0 +1,387 @@ +/* +** $Id: ScrollButtonClass.c,v 1.1 1999/02/07 14:24:43 bernie Exp $ +** +** Copyright (C) 1998,99 Bernardo Innocenti +** +** Use 4 chars wide TABs to read this file +** +** The ScrollButtonClass is a simple subclass of the buttongclass +** specialized for scroll buttons. See ScrollButtonClass.h for a detailed +** description. +*/ + +#define USE_BUILTIN_MATH +#define INTUI_V36_NAMES_ONLY +#define __USE_SYSBASE +#define CLIB_ALIB_PROTOS_H /* Avoid dupe defs of boopsi funcs */ + + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#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 */ + #ifdef __STORM__ + #define UTILITYBASETYPE struct Library + #else + #define UTILITYBASETYPE struct UtilityBase + #endif + + /* Library bases */ + struct ExecBase *SysBase = NULL; + struct IntuitionBase *IntuitionBase = NULL; + UTILITYBASETYPE *UtilityBase = NULL; +#endif + + + +static ULONG SB_GMGoActive(Class *cl, struct Gadget *g, struct gpInput *gpi) +{ + struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g); + + DB2(DBPRINTF("ScrollButton: GM_GOACTIVE\n");) + ASSERT_VALID_PTR(bd) + + /* May define an attribute to make delay configurable */ + bd->TickCounter = 3; + + /* Notify our target that we have initially hit. */ + NotifyAttrs((Object *)g, gpi->gpi_GInfo, 0, + GA_ID, g->GadgetID, + TAG_DONE); + + /* Send more input */ + return GMR_MEACTIVE; +} + + + +static ULONG SB_GMHandleInput(Class *cl, struct Gadget *g, struct gpInput *gpi) +{ + struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g); + struct RastPort *rp; + ULONG retval = GMR_MEACTIVE; + UWORD selected = 0; + + DB2 (DBPRINTF ("ScrollButton: GM_HANDLEINPUT\n");) + ASSERT_VALID_PTR(bd) + + /* This also works with classic (non-boopsi) images. */ + if (PointInImage((gpi->gpi_Mouse.X << 16) + (gpi->gpi_Mouse.Y), g->GadgetRender)) + { + /* We are hit */ + selected = GFLG_SELECTED; + } + + if (gpi->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE && gpi->gpi_IEvent->ie_Code == SELECTUP) + { + /* Gadgetup, time to go */ + retval = GMR_NOREUSE; + /* Unselect the gadget on our way out... */ + selected = 0; + } + else if (gpi->gpi_IEvent->ie_Class == IECLASS_TIMER) + { + /* We got a tick. Decrement counter, and if 0, send notify. */ + + if (bd->TickCounter) + bd->TickCounter--; + else if (selected) + /* Notify our target that we are still being hit */ + NotifyAttrs ((Object *)g, gpi->gpi_GInfo, 0, + GA_ID, g->GadgetID, + TAG_DONE); + } + + if ((g->Flags & GFLG_SELECTED) != selected) + { + /* Update changes in gadget render */ + g->Flags ^= GFLG_SELECTED; + if (rp = ObtainGIRPort (gpi->gpi_GInfo)) + { + DoMethod((Object *) g, GM_RENDER, gpi->gpi_GInfo, rp, GREDRAW_UPDATE); + ReleaseGIRPort(rp); + } + } + return retval; +} + + + +static void SB_GMRender(Class *cl, struct Gadget *g, struct gpRender *gpr) +{ + struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g); + struct impDraw impdraw; + + DB2(DBPRINTF("ScrollButton: GM_RENDER\n");) + ASSERT_VALID_PTR(bd) + + if (!bd->LayoutDone) + SB_GMLayout(cl, g, (struct gpLayout *)gpr); + + impdraw.MethodID = IM_DRAWFRAME; + impdraw.imp_RPort = gpr->gpr_RPort; + impdraw.imp_DrInfo = gpr->gpr_GInfo->gi_DrInfo; + + /* Check if we are living inside an inactive window border */ + if ((g->Activation & (GACT_RIGHTBORDER | GACT_LEFTBORDER | GACT_TOPBORDER | GACT_BOTTOMBORDER)) && + gpr->gpr_GInfo->gi_Window && + (!(gpr->gpr_GInfo->gi_Window->Flags & WFLG_WINDOWACTIVE))) + { + impdraw.imp_State = (g->Flags & GFLG_SELECTED) ? + IDS_INACTIVESELECTED : + ((g->Flags & GFLG_DISABLED) ? IDS_INACTIVEDISABLED : IDS_INACTIVENORMAL ); + } + else + { + impdraw.imp_State = (g->Flags & GFLG_SELECTED) ? + ((g->Flags & GFLG_DISABLED) ? IDS_SELECTEDDISABLED : IDS_SELECTED ) : + ((g->Flags & GFLG_DISABLED) ? IDS_DISABLED : IDS_NORMAL ); + } + + /* Check whether our label image is valid and can be sent a boopsi message */ + if ((g->Flags & GFLG_LABELIMAGE) && g->GadgetText && + (((struct Image *)g->GadgetText)->Depth == CUSTOMIMAGEDEPTH)) + { + impdraw.imp_Offset.X = bd->GBox.Left - bd->FrameBox.Left; + impdraw.imp_Offset.Y = bd->GBox.Top - bd->FrameBox.Top; + impdraw.imp_Dimensions.Width = bd->GBox.Width - bd->FrameBox.Width; + impdraw.imp_Dimensions.Height = bd->GBox.Height - bd->FrameBox.Height; + + DoMethodA((Object *)g->GadgetText, (Msg)&impdraw); + } + + /* Check whether our framing image is valid and can be sent a boopsi message */ + if ((g->Flags & GFLG_GADGIMAGE) && g->GadgetRender && + (((struct Image *)g->GadgetRender)->Depth == CUSTOMIMAGEDEPTH)) + { + impdraw.imp_Offset.X = bd->GBox.Left; + impdraw.imp_Offset.Y = bd->GBox.Top; + impdraw.imp_Dimensions.Width = bd->GBox.Width; + impdraw.imp_Dimensions.Height = bd->GBox.Height; + + DoMethodA((Object *)g->GadgetRender, (Msg)&impdraw); + } +} + + + +static void SB_GMLayout(Class *cl, struct Gadget *g, struct gpLayout *gpl) +{ + struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g); + + DB2(DBPRINTF("ScrollButton: GM_LAYOUT\n");) + ASSERT_VALID_PTR(bd) + + /* Compute new button size */ + GetGadgetBox(gpl->gpl_GInfo, g, &bd->GBox); + + /* Check if our framing image is valid and can be sent a boopsi message */ + if ((g->Flags & GFLG_GADGIMAGE) && g->GadgetRender && + (((struct Image *)g->GadgetRender)->Depth == CUSTOMIMAGEDEPTH)) + { + struct IBox fakecontents = { 0, 0, 0, 0 }; + + /* Ask the frame what is its size */ + DoMethod((Object *)g->GadgetRender, IM_FRAMEBOX, + &fakecontents, &bd->FrameBox, gpl->gpl_GInfo->gi_DrInfo, 0); + } + + bd->LayoutDone = TRUE; +} + + + +static ULONG SB_OMSet (Class *cl, struct Gadget *g, struct opUpdate *msg) +{ + struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g); + struct TagItem *ti, *tstate = msg->opu_AttrList; + + DB1(DBPRINTF("ScrollButton: OM_SET\n");) + ASSERT_VALID_PTR(bd) + ASSERT_VALID_PTR(tstate) + + while (ti = NextTagItem(&tstate)) + { + /* Check for any of GA_Width, GA_RelWidth, GA_Height, GA_RelHeight. + * This test assumes that the values of these tags are consecutive + * and will break whenever their definitions are changed. + */ + if ((ti->ti_Tag >= GA_Width) && (ti->ti_Tag <= GA_RelHeight)) + bd->LayoutDone = FALSE; + } + + /* The superclass handles everything else */ + return (DoSuperMethodA(cl, (Object *)g, (Msg) msg)); +} + + + +static ULONG HOOKCALL ScrollButtonDispatcher( + REG(a0, Class *cl), + REG(a2, struct Gadget *g), + REG(a1, Msg msg)) + +/* ScrollButton Class Dispatcher entrypoint. + * Handle boopsi messages. + */ +{ + switch (msg->MethodID) + { + case GM_GOACTIVE: + return SB_GMGoActive(cl, g, (struct gpInput *)msg); + + case GM_HANDLEINPUT: + return SB_GMHandleInput(cl, g, (struct gpInput *)msg); + + case GM_RENDER: + SB_GMRender(cl, g, (struct gpRender *)msg); + return TRUE; + + case GM_LAYOUT: + SB_GMLayout(cl, g, (struct gpLayout *)msg); + return TRUE; + + case OM_SET: + case OM_UPDATE: + return SB_OMSet(cl, g, (struct opUpdate *)msg); + + default: + /* Super class handles everything else */ + return (DoSuperMethodA(cl, (Object *)g, msg)); + } +} + + + +Class *MakeScrollButtonClass (void) +{ + Class *class; + + if (class = MakeClass(NULL, BUTTONGCLASS, NULL, sizeof(struct ScrollButtonData), 0)) + class->cl_Dispatcher.h_Entry = (ULONG (*)()) ScrollButtonDispatcher; + + return class; +} + +Class *MakeFrScrollButtonClass (void) +{ + Class *class; + + if (class = MakeClass (NULL, FRBUTTONCLASS, NULL, sizeof(struct ScrollButtonData), 0)) + class->cl_Dispatcher.h_Entry = (ULONG (*)()) ScrollButtonDispatcher; + + return class; +} + +BOOL FreeScrollButtonClass (Class *cl) +{ + return (FreeClass(cl)); +} + + + +#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) +/* + * Class library support functions + */ + +struct ClassLibrary * HOOKCALL _UserLibInit(REG(a6, struct ClassLibrary *mybase)) +{ + /* Initialize SysBase */ + SysBase = *((struct ExecBase **)4UL); + + if (!((UtilityBase = (UTILITYBASETYPE *) OpenLibrary("utility.library", 39)) && + (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39)))) + { + _UserLibCleanup(mybase); + return NULL; + } + + if (!(mybase->cl_Class = MakeScrollButtonClass())) + { + _UserLibCleanup(mybase); + return NULL; + } + + AddClass(mybase->cl_Class); + return mybase; +} + +struct ClassLibrary * HOOKCALL _UserLibCleanup(REG(a6, struct ClassLibrary *mybase)) +{ + if (mybase->cl_Class) + if (!FreeScrollButtonClass(mybase->cl_Class)) + return NULL; + + CloseLibrary((struct Library *)IntuitionBase); + CloseLibrary((struct Library *)UtilityBase); + + return mybase; +} + +Class * HOOKCALL _GetEngine(REG(a6, struct ClassLibrary *mybase)) +{ + return mybase->cl_Class; +} + +#endif /* (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) */ diff --git a/gadgets/SliderBar/FrPropGClass.c b/gadgets/SliderBar/FrPropGClass.c new file mode 100644 index 0000000..3640553 --- /dev/null +++ b/gadgets/SliderBar/FrPropGClass.c @@ -0,0 +1,175 @@ +/* +** $Id: FrPropGClass.c,v 1.1 1999/02/07 14:24:42 bernie Exp $ +** +** Copyright (C) 1999,2000 Bernardo Innocenti +** All rights reserved. +** +** Use 4 chars wide TABs to read this file +** +** A simple subclass of the propgclass which can be surrounded +** by a boopsi frame image specified through the GA_LabelImage tag. +*/ + +#define USE_BUILTIN_MATH +#define INTUI_V36_NAMES_ONLY +#define __USE_SYSBASE +#define CLIB_ALIB_PROTOS_H /* Avoid dupe defs of boopsi funcs */ + + +#include +#include +#include + +#ifdef __STORM__ + #pragma header +#endif + +#include "CompilerSpecific.h" +#include "DebugMacros.h" +#include "BoopsiStubs.h" + +#include "FrPropGClass.h" + + + + +/* Per object instance data */ +struct FrPropData +{ + Object * Frame; + struct IBox FrameBox; +}; + + + +/* ScrollButton Class Dispatcher entrypoint. + * Handle boopsi messages. + */ +static ULONG HOOKCALL FrPropDispatcher ( + REG(a0, Class * cl), + REG(a2, struct Gadget * g), + REG(a1, Msg msg)) +{ + struct FrPropData *fpd; + + switch (msg->MethodID) + { + case OM_NEW: + DB2(DBPRINTF("FrPropGClass: OM_NEW\n");) + + if (g = (struct Gadget *)DoSuperMethodA (cl, (Object *)g, (Msg)msg)) + { + fpd = (struct FrPropData *) INST_DATA(cl, g); + + /* HACK: the gadgetclass copies the contents + * of the GA_LabelImage tag into the Gadget structure. + * We steal the frame from there and then clear it, + * otherwise the gadgetclass will try to draw the frame + * itself. + */ + fpd->Frame = (Object *) g->GadgetText; + g->GadgetText = NULL; + g->Flags &= ~GFLG_LABELIMAGE; + + /* Ask Intuition to send us GM_LAYOUT messages */ + g->Flags |= GFLG_RELSPECIAL; + } + return (ULONG)g; + + case GM_LAYOUT: + DB2(DBPRINTF("FrPropGClass: GM_LAYOUT\n");) + + fpd = (struct FrPropData *) INST_DATA(cl, g); + + if (fpd->Frame) + { + struct IBox gbox; + + /* Compute current gadget size */ + GetGadgetBox(((struct gpLayout *)msg)->gpl_GInfo, g, &gbox); + + DB2(DBPRINTF("FrPropGClass: GBox :%ld t:%ld w:%ld h:%ld\n", + fpd->FrameBox.Left, fpd->FrameBox.Top, + fpd->FrameBox.Width, fpd->FrameBox.Height);) + + /* Calculate dimensions of our framing image */ + DoMethod(fpd->Frame, IM_FRAMEBOX, &gbox, &fpd->FrameBox, + ((struct gpLayout *)msg)->gpl_GInfo->gi_DrInfo, 0); + } + break; /* go to DoSuperMethod() below */ + + case GM_RENDER: + if (((struct gpRender *)msg)->gpr_Redraw == GREDRAW_REDRAW) + { + fpd = (struct FrPropData *) INST_DATA(cl, g); + DB2(DBPRINTF("FrPropGClass: GM_RENDER - GREDRAW_REDRAW\n");) + ASSERT_VALID_PTR(fpd) + + if (fpd->Frame) + { + ASSERT_VALID_PTR(fpd->Frame) + DB2(DBPRINTF("FrPropGClass: Frame l:%ld t:%ld w:%ld h:%ld\n", + fpd->FrameBox.Left, fpd->FrameBox.Top, + fpd->FrameBox.Width, fpd->FrameBox.Height);) + + DoMethod(fpd->Frame, IM_DRAWFRAME, + ((struct gpRender *)msg)->gpr_RPort, /* imp_RPort */ + (fpd->FrameBox.Left << 16) | (fpd->FrameBox.Top), /* imp_Offset */ + IDS_NORMAL, /* imp_State */ + ((struct gpRender *)msg)->gpr_GInfo->gi_DrInfo, /* imp_DrInfo */ + (fpd->FrameBox.Width << 16) | (fpd->FrameBox.Height)); /* imp_Dimensions */ + } + } + break; /* go to DoSuperMethod() below */ + + case OM_UPDATE: + { + ULONG result; + Class *oldclass; + + /* This is a dirty workaround for a bug in the propgclass. + * + * It appears that the dispatcher of the propgclass detects + * when an object is made from a subclass. In this case, + * it stops sending itself the GM_REDRAW message when the + * PGA_#? attributes are updated. The result is that the + * prop does not update its visual when the attributes are + * changed. + * + * The workaround we use here is to temporarly switch the + * object true class to propgclass before passing the + * OM_UPDATE method to our superclass. + */ + oldclass = OCLASS(g); + OCLASS(g) = cl->cl_Super; + result = CoerceMethodA (cl->cl_Super, (Object *)g, msg); + OCLASS(g) = oldclass; + return result; + } + + default: + break; /* go to DoSuperMethod() below */ + } + + /* Super class handles everything */ + return (DoSuperMethodA (cl, (Object *)g, msg)); +} + + + +Class * MakeFrPropGClass(void) +{ + Class * class; + + if (class = MakeClass (NULL, PROPGCLASS, NULL, sizeof(struct FrPropData), 0)) + class->cl_Dispatcher.h_Entry = (ULONG (*)()) FrPropDispatcher; + + return class; +} + + + +BOOL FreeFrPropGClass(Class *cl) +{ + return (FreeClass(cl)); +} diff --git a/gadgets/SliderBar/Makefile b/gadgets/SliderBar/Makefile new file mode 100644 index 0000000..3fb8976 --- /dev/null +++ b/gadgets/SliderBar/Makefile @@ -0,0 +1,26 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(BOOPSITOP)/config.mk +include config.mk + +ARG_COMMON := +ARG_ALL := $(ARG_COMMON) +ARG_LIB := $(ARG_COMMON) +ARG_DEBUG := $(ARG_COMMON) +ARG_PRIVATE := $(ARG_COMMON) +ARG_OBJ := $(ARG_COMMON) +ARG_INSTALL := $(ARG_COMMON) + +DEP_COMMON := +DEP_ALL := $(DEP_COMMON) +DEP_LIB := $(DEP_COMMON) +DEP_DEBUG := $(DEP_COMMON) +DEP_PRIVATE := $(DEP_COMMON) +DEP_OBJ := $(DEP_COMMON) + +include $(BOOPSITOP)/common/general.mk + diff --git a/gadgets/SliderBar/SliderBarDemo.c b/gadgets/SliderBar/SliderBarDemo.c new file mode 100644 index 0000000..c6ac67b --- /dev/null +++ b/gadgets/SliderBar/SliderBarDemo.c @@ -0,0 +1,378 @@ +/* +** $Id: SliderBarDemo.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 +** +** +** 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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "CompilerSpecific.h" +#include "DebugMacros.h" +#include "BoopsiStubs.h" + +#include "SliderBarGClass.h" + + +/* Local function prototypes */ +LONG SAVEDS main (void); +static struct SBDHandle *OpenSBDWin (UBYTE *pubscreen, ULONG left, ULONG top, + ULONG width, ULONG height); +static void CloseSBDWin (struct SBDHandle *sbdhandle); +static struct Gadget *CreateGadgets (struct SBDHandle *sbdhandle); +static void DisposeGadgets (struct SBDHandle *sbdhandle); +static struct ClassLibrary *OpenClass (STRPTR name, ULONG version); + + + +/* This structure describes an open SliderBarDemo window */ + +struct SBDHandle +{ + struct Window *Win; + struct Screen *Scr; + struct Gadget *Slider[4]; +}; + + + +/* Version tag */ + +static UBYTE versiontag[] = "$VER: SlideBarDemo 1.0 (30.1.99) by Bernardo Innocenti"; + + +/* Library bases */ +static struct ExecBase *SysBase; +static struct IntuitionBase *IntuitionBase; + +/* `boopsi' class library base */ +static struct ClassLibrary *SliderBarBase; + + + +LONG SAVEDS _main (void) + +/* Main program entry point. When linking without startup code, this + * must be the first function in the first object module listed on the + * linker command line. We also need to initialize SysBase and open + * all needed libraries manually. + */ +{ + struct SBDHandle *sbdhandle; + LONG sigwait, sigrcvd; + LONG retval = RETURN_FAIL; + BOOL quit = FALSE; + + + /* Initialize SysBase */ + SysBase = *((struct ExecBase **)4UL); + + if (IntuitionBase = (struct IntuitionBase *)OpenLibrary ("intuition.library", 39L)) + { + if (SliderBarBase = OpenClass ("sliderbar.gadget", 0)) + { + if (sbdhandle = OpenSBDWin (NULL, 0, 20, 320, 200)) + { + /* Pre-calculate the signal mask for Wait() */ + sigwait = (1 << sbdhandle->Win->UserPort->mp_SigBit) | + SIGBREAKF_CTRL_C; + + /* Now for the main loop. As you can see, it is really + * very compact. That's the magic of boopsi! :-) + */ + while (!quit) + { + /* Sleep until something interesting occurs */ + sigrcvd = Wait (sigwait); + + /* Now handle received signals */ + + /* Break signal? */ + if (sigrcvd & SIGBREAKF_CTRL_C) + quit = TRUE; + + /* IDCMP message? */ + if (sigrcvd & (1 << sbdhandle->Win->UserPort->mp_SigBit)) + { + struct IntuiMessage *msg; + + while (msg = (struct IntuiMessage *) GetMsg (sbdhandle->Win->UserPort)) + { + switch (msg->Class) + { + case IDCMP_CLOSEWINDOW: + quit = TRUE; + break; + + default: + break; + } + ReplyMsg ((struct Message *) msg); + } + } + } /* End while (!quit) */ + + retval = RETURN_OK; + + CloseSBDWin (sbdhandle); + } + + /* This cannot fail. Passing NULL is ok. */ + CloseLibrary ((struct Library *)SliderBarBase); + } + CloseLibrary ((struct Library *)IntuitionBase); + } + + return retval; +} + + + +static struct SBDHandle *OpenSBDWin (UBYTE *pubscreen, + ULONG left, ULONG top, ULONG width, ULONG height) +{ + struct SBDHandle *sbdhandle; + struct Gadget *glist; + + if (sbdhandle = AllocMem (sizeof (struct SBDHandle), MEMF_ANY | MEMF_CLEAR)) + { + if (sbdhandle->Scr = LockPubScreen (pubscreen)) + { + if (glist = CreateGadgets (sbdhandle)) + { + if (sbdhandle->Win = OpenWindowTags (NULL, + WA_Top, top, + WA_Left, left, + WA_InnerWidth, width, + WA_InnerHeight, height, + WA_PubScreen, sbdhandle->Scr, + WA_PubScreenFallBack, TRUE, + WA_AutoAdjust, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | + WFLG_SIZEGADGET | WFLG_SIMPLE_REFRESH | WFLG_NOCAREREFRESH, + WA_Gadgets, glist, + WA_Title, versiontag + 6, + WA_MinWidth, 64, + WA_MinHeight, 64, + WA_MaxWidth, -1, + WA_MaxHeight, -1, + TAG_DONE)) + { + UnlockPubScreen (NULL, sbdhandle->Scr); + return sbdhandle; + } + DisposeGadgets (sbdhandle); + } + UnlockPubScreen (NULL, sbdhandle->Scr); + } + FreeMem (sbdhandle, sizeof (struct SBDHandle)); + } + return NULL; +} + + + +static void CloseSBDWin (struct SBDHandle *sbdhandle) +{ + /* Close our window. No need to reply queued messages, + * Intuition is clever enough to care about this for us. + */ + CloseWindow (sbdhandle->Win); + DisposeGadgets (sbdhandle); + FreeMem (sbdhandle, sizeof (struct SBDHandle)); +} + +#define SLIDER_THICKNESS 20 + +static struct Gadget *CreateGadgets (struct SBDHandle *sbdhandle) +{ + struct Screen *scr = sbdhandle->Scr; + LONG left,right, top, bottom, width, height; + + + left = scr->WBorLeft + 10; + right = - scr->WBorRight - 25 - SLIDER_THICKNESS; + top = scr->WBorTop + scr->Font->ta_YSize + 10; + bottom = - scr->WBorBottom - 10 - SLIDER_THICKNESS; + width = right - left - 1; + height = bottom - top - 1; + + sbdhandle->Slider[0] = NewObject (NULL, SLIDERBARGCLASS, + GA_Left, left, + GA_Top, top, + GA_Width, SLIDER_THICKNESS, + GA_RelHeight, height, + PGA_Total, 120, + PGA_Top, 50, + PGA_Visible, 20, + LAYOUTA_Orientation, LORIENT_VERT, + TAG_DONE); + + sbdhandle->Slider[1] = NewObject (NULL, SLIDERBARGCLASS, + GA_Previous, sbdhandle->Slider[0], + GA_Left, left, + GA_RelBottom, bottom, + GA_RelWidth, width + SLIDER_THICKNESS, + GA_Height, SLIDER_THICKNESS, + PGA_Total, 140, + PGA_Top, 50, + PGA_Visible, 40, + LAYOUTA_Orientation, LORIENT_HORIZ, + ICA_TARGET, sbdhandle->Slider[0], + TAG_DONE); + + sbdhandle->Slider[2] = NewObject (NULL, SLIDERBARGCLASS, + GA_Previous, sbdhandle->Slider[1], + GA_RelRight, right, + GA_Top, top, + GA_Width, SLIDER_THICKNESS, + GA_RelHeight, height, + PGA_Total, 140, + PGA_Top, 50, + PGA_Visible, 40, + LAYOUTA_Orientation, LORIENT_VERT, + ICA_TARGET, sbdhandle->Slider[1], + TAG_DONE); + + sbdhandle->Slider[3] = NewObject (NULL, SLIDERBARGCLASS, + GA_Previous, sbdhandle->Slider[2], + GA_Top, top, + GA_Left, left + SLIDER_THICKNESS, + GA_RelWidth, width - SLIDER_THICKNESS, + GA_Height, SLIDER_THICKNESS, + PGA_Total, 140, + PGA_Top, 50, + PGA_Visible, 40, + LAYOUTA_Orientation, LORIENT_HORIZ, + ICA_TARGET, sbdhandle->Slider[2], + TAG_DONE); + + + if (sbdhandle->Slider[0] && + sbdhandle->Slider[1] && + sbdhandle->Slider[2] && + sbdhandle->Slider[3]) + { + return sbdhandle->Slider[0]; + } + else + { + DisposeGadgets (sbdhandle); + return NULL; + } +} + + + +static void DisposeGadgets (struct SBDHandle *sbdhandle) +{ + int i; + + for (i = 0; i < 4; i++) + DisposeObject (sbdhandle->Slider[i]); +} + + + +static struct ClassLibrary *OpenClass (STRPTR name, ULONG version) + +/* Open named class. Look both in current and gadgets/ directory + */ +{ + static struct EasyStruct OpenClassES = + { + sizeof (struct EasyStruct), + 0, + versiontag + 6, + "Couldn't open %s version %ld or greater", + "Ok" + }; + static const char prefix[] = "gadgets/"; + + struct ClassLibrary *classbase; + char buf[256]; + int i; + + + if (!(classbase = (struct ClassLibrary *)OpenLibrary (name, version))) + { + /* We can't use AddPart() here because we didn't open dos.library */ + + /* Copy the prefix in the buffer */ + for (i = 0; buf[i] = prefix[i]; i++); + + /* Append the name */ + while (buf[i++] = *name++); + + /* Try again */ + classbase = (struct ClassLibrary *)OpenLibrary (buf, version); + + if (!classbase) + { + /* Report an error */ + EasyRequest (NULL, &OpenClassES, NULL, buf, version); + } + } + return classbase; +} diff --git a/gadgets/SliderBar/SliderBarGClass.c b/gadgets/SliderBar/SliderBarGClass.c new file mode 100644 index 0000000..700b66d --- /dev/null +++ b/gadgets/SliderBar/SliderBarGClass.c @@ -0,0 +1,773 @@ +/* +** $Id: SliderBarGClass.c,v 1.1 1999/02/07 14:24:43 bernie Exp $ +** +** Copyright (C) 1999 Bernardo Innocenti +** All rights reserved. +** +** Use 4 chars wide TABs to read this file +** +** "sliderbargclass", a GadTools like slider with scroll buttons. +** See the header file "SliderBarGClass.h" for class documentation. +*/ + +/* Supported class flavours: + * + * FLAVOUR_CLASSLIB + * Build a class library if this option is set or + * a static linker object otherwise. + * + * FLAVOUR_PUBCLASS + * Call AddClass() to show this class globally if set, + * make a private class otherwise. + */ +#define FLAVOUR_CLASSLIB (1<<0) +#define FLAVOUR_PUBCLASS (1<<1) + +#define CLASS_FLAVOUR (FLAVOUR_CLASSLIB | FLAVOUR_PUBCLASS) + +/* Definitions for system headers */ +#define USE_BUILTIN_MATH +#define INTUI_V36_NAMES_ONLY +#define INTUITION_IOBSOLETE_H +#define __USE_SYSBASE +#define CLIB_ALIB_PROTOS_H /* Avoid dupe defines of boopsi funcs */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#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 */ + #ifdef __STORM__ + #define UTILITYBASETYPE struct Library + #else + #define UTILITYBASETYPE struct UtilityBase + #endif + + /* Library bases - also used by the FrScrollButtonClass and the FrPropGClass */ + struct ExecBase *SysBase = NULL; + struct IntuitionBase *IntuitionBase = NULL; + UTILITYBASETYPE *UtilityBase = NULL; +#endif + + +/* Static variables */ + +static LONG MapPropToSB[] = +{ + PGA_Top, SBA_InternalTop, + TAG_DONE +}; + + +static LONG MapButtonToSB[] = +{ + GA_ID, SBA_Adjust, + TAG_DONE +}; + + + +INLINE void GetGadgetBox (struct GadgetInfo *ginfo, struct Gadget *g, struct IBox *box) + +/* Gets the actual IBox where a gadget exists in a window. + * The special cases it handles are all the REL#? (relative positioning flags). + * + * This function returns the gadget size in the provided IBox structure, + * computing the values from the coordinates of the gadget and the window + * inside which it lives. + */ +{ + ASSERT_VALID_PTR(g) + ASSERT_VALID_PTR(ginfo) + ASSERT_VALID_PTR(box) + + box->Left = g->LeftEdge; + if (g->Flags & GFLG_RELRIGHT) + box->Left += ginfo->gi_Domain.Width - 1; + + box->Top = g->TopEdge; + if (g->Flags & GFLG_RELBOTTOM) + box->Top += ginfo->gi_Domain.Height - 1; + + box->Width = g->Width; + if (g->Flags & GFLG_RELWIDTH) + box->Width += ginfo->gi_Domain.Width; + + box->Height = g->Height; + if (g->Flags & GFLG_RELHEIGHT) + box->Height += ginfo->gi_Domain.Height; +} + + + +static void SB_GMLayout (Class *cl, struct Gadget *g, struct gpLayout *msg) +{ + struct SBData *sb = (struct SBData *) INST_DATA (cl, (Object *)g); + struct SBClassData *classdata = (struct SBClassData *)cl->cl_UserData; + struct IBox gbox, framebox, contentsbox = { 0, 0, 0, 0 }; + + DB2 (kprintf ("SliderBarClass: GM_LAYOUT\n");) + ASSERT_VALID_PTR(sb) + ASSERT_VALID_PTR(classdata) + + + /* Collect new group size */ + GetGadgetBox (msg->gpl_GInfo, g, &gbox); + + /* Query the frame on its nominal width and height */ + DoMethod (classdata->Frame, IM_FRAMEBOX, &contentsbox, &framebox, + msg->gpl_GInfo->gi_DrInfo, 0); + + /* Size our children accordingly */ + + if (sb->Orientation == LORIENT_VERT) + { + SetAttrs (sb->Prop, + GA_Left, gbox.Left + framebox.Width / 2, + GA_Top, gbox.Top + framebox.Height / 2, + GA_Width, gbox.Width - framebox.Width, + GA_Height, gbox.Height - framebox.Height - BUTTON_HEIGHT * 2, + TAG_DONE); + + if (sb->DecButton) + SetAttrs (sb->DecButton, + GA_Left, gbox.Left, + GA_Top, gbox.Top + gbox.Height - BUTTON_HEIGHT * 2, + GA_Width, gbox.Width, + GA_Height, BUTTON_HEIGHT, + TAG_DONE); + + if (sb->IncButton) + SetAttrs (sb->IncButton, + GA_Left, gbox.Left, + GA_Top, gbox.Top + gbox.Height - BUTTON_HEIGHT, + GA_Width, gbox.Width, + GA_Height, BUTTON_HEIGHT, + TAG_DONE); + } + else /* LORIENT_HORIZ */ + { + SetAttrs (sb->Prop, + GA_Left, gbox.Left + framebox.Width / 2, + GA_Top, gbox.Top + framebox.Height / 2, + GA_Width, gbox.Width - framebox.Width - BUTTON_WIDTH * 2, + GA_Height, gbox.Height - framebox.Height, + TAG_DONE); + + if (sb->DecButton) + SetAttrs (sb->DecButton, + GA_Left, gbox.Left + gbox.Width - BUTTON_WIDTH * 2, + GA_Top, gbox.Top, + GA_Width, BUTTON_WIDTH, + GA_Height, gbox.Height, + TAG_DONE); + + if (sb->IncButton) + SetAttrs (sb->IncButton, + GA_Left, gbox.Left + gbox.Width - BUTTON_WIDTH, + GA_Top, gbox.Top, + GA_Width, BUTTON_WIDTH, + GA_Height, gbox.Height, + TAG_DONE); + } + + DoSuperMethodA (cl, (Object *)g, (Msg)msg); +} + + + +static ULONG SB_OMNew (Class *cl, struct Gadget *g, struct opSet *msg) +{ + struct SBData *sb; + struct SBClassData *classdata; + + DB2 (DBPRINTF ("SliderBarGClass: OM_NEW\n");) + + if (g = (struct Gadget *)DoSuperMethodA (cl, (Object *)g, (Msg)msg)) + { + classdata = (struct SBClassData *)cl->cl_UserData; + sb = (struct SBData *) INST_DATA (cl, (Object *)g); + ASSERT_VALID_PTR(sb) + ASSERT_VALID_PTR(classdata) + + + /* Initialize the object instance */ + sb->DecButton = NULL; + sb->IncButton = NULL; + sb->IncImage = NULL; + sb->DecImage = NULL; + sb->Orientation = GetTagData (LAYOUTA_Orientation, LORIENT_HORIZ, msg->ops_AttrList); + sb->Top = GetTagData (PGA_Top, 0, msg->ops_AttrList); + sb->Total = GetTagData (PGA_Total, 0, msg->ops_AttrList); + sb->Visible = GetTagData (PGA_Visible, 0, msg->ops_AttrList); + + if (sb->Prop = NewObject (classdata->FrPropGClass, NULL, + GA_ID, g->GadgetID, /* Same as our ID */ + GA_LabelImage, classdata->Frame, + PGA_Freedom, (sb->Orientation == LORIENT_VERT) ? FREEVERT : FREEHORIZ, + PGA_NewLook, TRUE, + PGA_Borderless, TRUE, + PGA_Top, sb->Top, + PGA_Total, sb->Total, + PGA_Visible, sb->Visible, + ICA_TARGET, g, /* target on us */ + ICA_MAP, MapPropToSB, + TAG_DONE)) + { + /* From now on, the groupgclass will dispose this object for us */ + DoMethod ((Object *)g, OM_ADDMEMBER, sb->Prop); + + /* Don't bother checking for failure here: + * the images are not mission-critical. + */ + sb->DecImage = NewObject (classdata->VectorGlyphIClass, NULL, + SYSIA_Which, (sb->Orientation == LORIENT_VERT) ? VG_UPARROW : VG_LEFTARROW, + TAG_DONE); + + if (sb->DecButton = NewObject (classdata->FrScrollButtonClass, NULL, + GA_ID, -1, + GA_LabelImage, sb->DecImage, + GA_Image, classdata->Frame, + ICA_TARGET, g, /* target on us */ + ICA_MAP, MapButtonToSB, + TAG_DONE)) + { + /* From now on, the groupgclass will dispose this object for us */ + DoMethod ((Object *)g, OM_ADDMEMBER, sb->DecButton); + } + + /* Don't bother checking for failure here: + * the images are not mission-critical. + */ + sb->IncImage = NewObject (classdata->VectorGlyphIClass, NULL, + SYSIA_Which, (sb->Orientation == LORIENT_VERT) ? VG_DOWNARROW : VG_RIGHTARROW, + TAG_DONE); + + if (sb->IncButton = NewObject (classdata->FrScrollButtonClass, NULL, + GA_ID, +1, + GA_LabelImage, sb->IncImage, + GA_Image, classdata->Frame, + ICA_TARGET, g, /* target on us */ + ICA_MAP, MapButtonToSB, + TAG_DONE)) + { + /* From now on, the groupgclass will dispose this object for us */ + DoMethod ((Object *)g, OM_ADDMEMBER, sb->IncButton); + } + + return (ULONG)g; /* Return newly created instance */ + } + + /* Commit suicide without disturbing the dispatchers of our subclasses */ + CoerceMethod (cl, (Object *)g, OM_DISPOSE); + } + + return 0; /* Fail */ +} + + + +static void SB_OMDispose (Class *cl, struct Gadget *g, Msg msg) +{ + struct SBData *sb = (struct SBData *) INST_DATA (cl, (Object *)g); + + /* The groupgclass will dispose all our children for us */ + + DisposeObject (sb->IncImage); + DisposeObject (sb->DecImage); + + /* Our superclass will cleanup everything else now */ + DoSuperMethodA (cl, (Object *)g, msg); + + /* From now on, our instance data is no longer available */ +} + + +static ULONG SB_OMSet (Class *cl, struct Gadget *g, struct opUpdate *msg) +{ + struct SBData *sb = INST_DATA (cl, g); + struct TagItem *ti, *tstate = msg->opu_AttrList; + ULONG action = 0; /* see flag definitions below */ + ULONG result; + + ASSERT_VALID_PTR(sb) + ASSERT_VALID_PTR_OR_NULL(tstate) + + DB2 (DBPRINTF ((msg->MethodID == OM_SET) ? + "SliderBarGClass: OM_SET\n" : + "SliderBarGClass: OM_UPDATE\n");) + + + /* Definitions for the ations to be taken right after + * scanning the attributes list in OM_SET/OM_UPDATE. + * For speed reasons we pack them together in a single variable, + * so we can set and test multiple flags in once. + */ + #define ACTIONF_DO_SUPER_METHOD (1<<0) + #define ACTIONF_NOTIFY_TOP (1<<1) + #define ACTIONF_NOTIFY_ALL (1<<2) + #define ACTIONF_UPDATE_CHILD (1<<3) + + + while (ti = NextTagItem (&tstate)) + switch (ti->ti_Tag) + { + case GA_ID: + if (msg->MethodID == OM_SET) + { + DB2 (DBPRINTF (" GA_ID, %ld\n", ti->ti_Data);) + + /* Avoid forwarding all taglists to superclass because of GA_ID */ + g->GadgetID = ti->ti_Data; + } + break; + + case PGA_Top: + if (sb->Top != ti->ti_Data) + { + sb->Top = ti->ti_Data; + action |= ACTIONF_NOTIFY_TOP | ACTIONF_UPDATE_CHILD; + } + break; + + case PGA_Total: + if (sb->Total != ti->ti_Data) + { + sb->Total = ti->ti_Data; + action |= ACTIONF_NOTIFY_ALL | ACTIONF_UPDATE_CHILD; + } + break; + + case PGA_Visible: + if (sb->Visible != ti->ti_Data) + { + sb->Visible = ti->ti_Data; + action |= ACTIONF_NOTIFY_ALL | ACTIONF_UPDATE_CHILD; + } + break; + + case SBA_InternalTop: + /* Prop gadget updating us */ + if (sb->Top != ti->ti_Data) + { + sb->Top = ti->ti_Data; + action |= ACTIONF_NOTIFY_TOP; + } + break; + + case SBA_Adjust: + { + LONG newtop = sb->Top + (LONG)((WORD)ti->ti_Data); + + /* Clip result to allowable values */ + if (newtop < 0) newtop = 0; + if (newtop > sb->Total - sb->Visible) newtop = sb->Total - sb->Visible; + + if (newtop != sb->Top) + { + sb->Top = newtop; + action |= ACTIONF_NOTIFY_TOP | ACTIONF_UPDATE_CHILD; + } + + break; + } + + default: + action |= ACTIONF_DO_SUPER_METHOD; + break; + } + + /* Forward method to our superclass dispatcher, only if needed */ + if (action & ACTIONF_DO_SUPER_METHOD) + { + DB2 (DBPRINTF ("SliderBarGClass: Forwarding OM_SET/OM_UPDATE to superclass\n")); + result = (DoSuperMethodA (cl, (Object *)g, (Msg) msg)); + } + else + result = TRUE; + + if (action & ACTIONF_UPDATE_CHILD) + { + if (action & ACTIONF_NOTIFY_ALL) + { + DB2 (DBPRINTF ("SliderBarGClass: Update child ALL\n")); + + UpdateAttrs (sb->Prop, msg->opu_GInfo, + (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0, + PGA_Top, sb->Top, + PGA_Total, sb->Total, + PGA_Visible, sb->Visible, + TAG_DONE); + } + else /* Top only */ + { + DB2 (DBPRINTF ("SliderBarGClass: Update child PGA_Top (%ld)\n", sb->Top)); + + UpdateAttrs (sb->Prop, msg->opu_GInfo, + (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0, + PGA_Top, sb->Top, + TAG_DONE); + } + } + + if (action & ACTIONF_NOTIFY_ALL) + { + DB2 (DBPRINTF ("SliderBarGClass: Notify target ALL\n")); + + NotifyAttrs ((Object *)g, msg->opu_GInfo, + (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0, + PGA_Top, sb->Top, + PGA_Total, sb->Total, + PGA_Visible, sb->Visible, + GA_ID, g->GadgetID, + TAG_DONE); + } + else if (action & ACTIONF_NOTIFY_TOP) + { + DB2 (DBPRINTF ("SliderBarGClass: Notify target TOP\n")); + + NotifyAttrs ((Object *)g, msg->opu_GInfo, + (msg->MethodID == OM_UPDATE) ? msg->opu_Flags : 0, + PGA_Top, sb->Top, + GA_ID, g->GadgetID, + TAG_DONE); + } + + return result; +} + + +static ULONG SB_OMGet (Class *cl, struct Gadget *g, struct opGet *msg) +{ + struct SBData *sb = INST_DATA (cl, g); + + ASSERT_VALID_PTR(sb) + ASSERT_VALID_PTR(msg->opg_Storage) + + DB2 (DBPRINTF ("ScrollBarGClass: OM_GET\n");) + + + switch (msg->opg_AttrID) + { + case PGA_Top: + *msg->opg_Storage = (ULONG) sb->Top; + return TRUE; + + case PGA_Total: + *msg->opg_Storage = (ULONG) sb->Total; + return TRUE; + + case PGA_Visible: + *msg->opg_Storage = (ULONG) sb->Visible; + return TRUE; + + default: + return FALSE; + } +} + + +static ULONG HOOKCALL SliderBarDispatcher ( + REG(a0, Class *cl), + REG(a2, struct Gadget *g), + REG(a1, Msg msg)) + +/* SliderBar class dispatcher - Handles all boopsi messages. */ +{ + ASSERT_VALID_PTR(cl) + ASSERT_VALID_PTR(g) + ASSERT_VALID_PTR(msg) + + + switch (msg->MethodID) + { + case GM_LAYOUT: + /* This method is only supported on V39 and above */ + SB_GMLayout (cl, g, (struct gpLayout *)msg); + return TRUE; + + case OM_SET: + case OM_UPDATE: + return SB_OMSet (cl, g, (struct opUpdate *)msg); + + case OM_GET: + return SB_OMGet (cl, g, (struct opGet *)msg); + + case OM_NEW: + return SB_OMNew (cl, g, (struct opSet *)msg); + + case OM_DISPOSE: + SB_OMDispose (cl, g, msg); + return TRUE; + + default: + /* Unsupported method: let our superclass's dispatcher take + * a look at it. This includes all gadget methods sent + * by Intuition: GM_HITTEST, GM_RENDER, GM_HANDLEINPUT, + * GM_GOACTIVE and GM_GOINACTIVE. All these methods are + * automatically forwarded to our children by our superclass. + */ + DB2 (DBPRINTF ("SliderBarGClass: passing unknown method 0x%lx to superclass\n", + msg->MethodID);) + return DoSuperMethodA (cl, (Object *)g, msg); + } +} + + + +Class *MakeSliderBarGClass (void) +{ + Class *class; + struct SBClassData *classdata; + Class *smartgrp; + + if (!(smartgrp = MakeSmartGroupGClass())) + return NULL; + + if (class = MakeClass ( +#if (CLASS_FLAVOUR & FLAVOUR_PUBCLASS) + SLIDERBARGCLASS, +#else + NULL, +#endif + NULL, smartgrp, sizeof (struct SBData), 0)) + { + class->cl_Dispatcher.h_Entry = (ULONG (*)()) SliderBarDispatcher; + + /* Allocate storage for global class data */ + if (classdata = AllocMem (sizeof (struct SBClassData), MEMF_PUBLIC | MEMF_CLEAR)) + { + class->cl_UserData = (ULONG) classdata; + + classdata->SmartGroupGClass = smartgrp; + + classdata->FrScrollButtonClass = MakeFrScrollButtonClass(); + ASSERT_VALID_PTR (classdata->FrScrollButtonClass); + + classdata->FrPropGClass = MakeFrPropGClass(); + ASSERT_VALID_PTR (classdata->FrPropGClass); + + if (classdata->VectorGlyphBase = (struct ClassLibrary *) + OpenLibrary ("images/vectorglyph.image", 0)) + { + classdata->VectorGlyphIClass = classdata->VectorGlyphBase->cl_Class; + ASSERT_VALID_PTR (classdata->VectorGlyphIClass); + + if (classdata->Frame = NewObject (NULL, FRAMEICLASS, + IA_EdgesOnly, TRUE, + IA_FrameType, FRAME_BUTTON, + TAG_DONE)) + { +#if (CLASS_FLAVOUR & FLAVOUR_PUBCLASS) + AddClass (class); +#endif + return class; + } + } + else + { + static struct EasyStruct OpenClassES = + { + sizeof (struct EasyStruct), + 0, +#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) + LibName, +#else + "sliderbar.gadget", +#endif + "Couldn't open images/vectorglyph.image", + "Ok" + }; + + /* Report an error */ + EasyRequestArgs (NULL, &OpenClassES, NULL, NULL); + } + } + + FreeSliderBarGClass (class); + } + + return NULL; +} + + +BOOL FreeSliderBarGClass (Class *class) +{ + struct SBClassData *classdata; + + if (class) + { + ASSERT_VALID_PTR(class) + + classdata = (struct SBClassData *)class->cl_UserData; + + /* Try to remove the class */ + if (FreeClass (class)) + { + if (classdata) + { + ASSERT_VALID_PTR(classdata) + ASSERT_VALID_PTR_OR_NULL(classdata->Frame); + ASSERT_VALID_PTR_OR_NULL(classdata->VectorGlyphBase) + ASSERT_VALID_PTR_OR_NULL(classdata->FrScrollButtonClass) + ASSERT_VALID_PTR_OR_NULL(classdata->FrPropGClass) + ASSERT_VALID_PTR_OR_NULL(classdata->SmartGroupGClass) + + /* Cleanup global class data. + * + * NOTE: NULL is safe in DisposeObject() and CloseLibrary() since V36 + */ + DisposeObject(classdata->Frame); + CloseLibrary ((struct Library *)classdata->VectorGlyphBase); + FreeFrScrollButtonClass (classdata->FrScrollButtonClass); + FreeFrPropGClass (classdata->FrPropGClass); + FreeSmartGroupGClass (classdata->SmartGroupGClass); + FreeMem (classdata, sizeof (struct SBClassData)); + } + return TRUE; + } + return FALSE; + } + return TRUE; +} + + + +#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) +/* + * Class library support functions + */ + +struct ClassLibrary * HOOKCALL _UserLibInit (REG(a6, struct ClassLibrary *mybase)) +{ + SysBase = *((struct ExecBase **)4); /* Initialize SysBase */ + + IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 39); + UtilityBase = (UTILITYBASETYPE *) OpenLibrary ("utility.library", 39); + + if (!(IntuitionBase && UtilityBase)) + { + _UserLibCleanup (mybase); + return NULL; + } + + if (mybase->cl_Class = MakeSliderBarGClass ()) + { + return mybase; + } + else + { + _UserLibCleanup (mybase); + return NULL; + } +} + +struct ClassLibrary * HOOKCALL _UserLibCleanup (REG(a6, struct ClassLibrary *mybase)) +{ + if (mybase->cl_Class) + if (!FreeSliderBarGClass (mybase->cl_Class)) + return NULL; + + CloseLibrary ((struct Library *)UtilityBase); + CloseLibrary ((struct Library *)IntuitionBase); + + return mybase; +} + +Class * HOOKCALL _GetEngine (REG(a6, struct ClassLibrary *mybase)) +{ + return (mybase->cl_Class); +} + +#endif /* (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) */ diff --git a/gadgets/SmartGroup/Makefile b/gadgets/SmartGroup/Makefile new file mode 100644 index 0000000..3fb8976 --- /dev/null +++ b/gadgets/SmartGroup/Makefile @@ -0,0 +1,26 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(BOOPSITOP)/config.mk +include config.mk + +ARG_COMMON := +ARG_ALL := $(ARG_COMMON) +ARG_LIB := $(ARG_COMMON) +ARG_DEBUG := $(ARG_COMMON) +ARG_PRIVATE := $(ARG_COMMON) +ARG_OBJ := $(ARG_COMMON) +ARG_INSTALL := $(ARG_COMMON) + +DEP_COMMON := +DEP_ALL := $(DEP_COMMON) +DEP_LIB := $(DEP_COMMON) +DEP_DEBUG := $(DEP_COMMON) +DEP_PRIVATE := $(DEP_COMMON) +DEP_OBJ := $(DEP_COMMON) + +include $(BOOPSITOP)/common/general.mk + diff --git a/gadgets/SmartGroup/SmartGroupGClass.c b/gadgets/SmartGroup/SmartGroupGClass.c new file mode 100644 index 0000000..b18a28c --- /dev/null +++ b/gadgets/SmartGroup/SmartGroupGClass.c @@ -0,0 +1,694 @@ +/* +** $Id: SmartGroupGClass.c,v 1.1 1999/02/07 14:24:44 bernie Exp $ +** +** Copyright (C) 1999 Bernardo Innocenti +** All rights reserved. +** +** Use 4 chars wide TABs to read this file +** +** "smartgroupgclass", a subclass of the gadgetclass which replaces +** and enhances the builtin groupgclass. +** See the header file "SmartGroupGClass.h" for class documentation. +*/ + +/* Definitions for system headers */ +#define USE_BUILTIN_MATH +#define INTUI_V36_NAMES_ONLY +#define INTUITION_IOBSOLETE_H +#define __USE_SYSBASE +#define CLIB_ALIB_PROTOS_H /* Avoid dupe defines of boopsi funcs */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef __STORM__ + #pragma header +#endif + +#include + +#include +#include +#include +#include +#include + + +/* 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 */ + #ifdef __STORM__ + #define UTILITYBASETYPE struct Library + #else + #define UTILITYBASETYPE struct UtilityBase + #endif + + /* Library bases */ + static struct ExecBase *SysBase = NULL; + static struct IntuitionBase *IntuitionBase = NULL; + static UTILITYBASETYPE *UtilityBase = NULL; + +#endif + + + +static ULONG ASMCALL SG_GMHitTest (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpHitTest *msg)) +{ + struct GroupData *gd = INST_DATA (cl, g); + struct ExtGadget *child; + APTR object_state; + WORD x, y; + + DB2 (DBPRINTF ("SmartGroupGClass: GM_HITTEST\n");) + ASSERT_VALID_PTR(gd) + + object_state = (APTR)gd->ChildList.mlh_Head; + ASSERT_VALID_PTR(object_state) + + x = msg->gpht_Mouse.X + gd->GBox.Left; + y = msg->gpht_Mouse.Y + gd->GBox.Top; + + /* Search over all our children */ + while (child = (struct ExtGadget *)NextObject(&object_state)) + { + ASSERT_VALID_PTR(child) + + /* Check whether the mouse coordinates are inside + * the gadget rectangle of our child + */ + if ((x >= child->LeftEdge) && + (x < child->LeftEdge + child->Width) && + (y >= child->TopEdge) && + (y < child->TopEdge + child->Height)) + { + struct gpHitTest childmsg; + + childmsg.MethodID = GM_HITTEST; + childmsg.gpht_GInfo = msg->gpht_GInfo; + childmsg.gpht_Mouse.X = x - child->LeftEdge; + childmsg.gpht_Mouse.Y = y - child->TopEdge; + + if (DoMethodA ((Object *)child, (Msg)&childmsg) == GMR_GADGETHIT) + { + gd->ActiveChild = child; + return GMR_GADGETHIT; + } + } + } + + return 0; +} + + + +static void ASMCALL SG_GMRender(REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpRender *msg)) +{ + struct GroupData *gd = INST_DATA (cl, g); + Object *o; + APTR object_state; + + DB2 (DBPRINTF ("SmartGroupGClass: GM_RENDER\n");) + + ASSERT_VALID_PTR(gd) + object_state = (APTR)gd->ChildList.mlh_Head; + ASSERT_VALID_PTR(object_state) + + /* The groupgclass disposes all its children automatically */ + while (o = NextObject(&object_state)) + { + ASSERT_VALID_PTR(o) + DoMethodA (o, (Msg)msg); + } +} + + + +static ULONG ASMCALL SG_GMGoActive (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpInput *msg)) +{ + struct GroupData *gd = INST_DATA (cl, g); + + DB2 (DBPRINTF ("SmartGroupGClass: GM_GOACTIVE\n");) + ASSERT_VALID_PTR(gd) + ASSERT_VALID_PTR(gd->ActiveChild) + + if (gd->ActiveChild) + { + struct gpInput childmsg; + + childmsg.MethodID = GM_GOACTIVE; + childmsg.gpi_GInfo = msg->gpi_GInfo; + childmsg.gpi_IEvent = msg->gpi_IEvent; + childmsg.gpi_Termination= msg->gpi_Termination; + childmsg.gpi_Mouse.X = msg->gpi_Mouse.X + gd->GBox.Left + - gd->ActiveChild->LeftEdge; + childmsg.gpi_Mouse.Y = msg->gpi_Mouse.Y + gd->GBox.Top + - gd->ActiveChild->TopEdge; + childmsg.gpi_TabletData = msg->gpi_TabletData; + + return (DoMethodA ((Object *)gd->ActiveChild, (Msg)&childmsg)); + } + + gd->ActiveChild = NULL; + return GMR_NOREUSE; +} + + + +static ULONG ASMCALL SG_GMHandleInput (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpInput *msg)) +{ + struct GroupData *gd = INST_DATA (cl, g); + + DB2 (DBPRINTF ("SmartGroupGClass: GM_HANDLEINPUT\n");) + ASSERT_VALID_PTR(gd) + ASSERT_VALID_PTR(gd->ActiveChild) + + if (gd->ActiveChild) + { + struct gpInput childmsg; + + childmsg.MethodID = GM_HANDLEINPUT; + childmsg.gpi_GInfo = msg->gpi_GInfo; + childmsg.gpi_IEvent = msg->gpi_IEvent; + childmsg.gpi_Termination= msg->gpi_Termination; + childmsg.gpi_Mouse.X = msg->gpi_Mouse.X + gd->GBox.Left + - gd->ActiveChild->LeftEdge; + childmsg.gpi_Mouse.Y = msg->gpi_Mouse.Y + gd->GBox.Top + - gd->ActiveChild->TopEdge; + childmsg.gpi_TabletData = msg->gpi_TabletData; + + DB2 (DBPRINTF ("SmartGroupGClass: Translating coords: X=%ld, Y=%ld\n", + childmsg.gpi_Mouse.X, childmsg.gpi_Mouse.Y);) + + return DoMethodA ((Object *)gd->ActiveChild, (Msg)&childmsg); + } + + return GMR_NOREUSE; +} + + + +static void ASMCALL SG_GMGoInactive (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpGoInactive *msg)) +{ + struct GroupData *gd = INST_DATA (cl, g); + + DB2 (DBPRINTF ("SmartGroupGClass: GM_GOINACTIVE\n");) + ASSERT_VALID_PTR(gd) + ASSERT_VALID_PTR(gd->ActiveChild) + + if (gd->ActiveChild) + { + DoMethodA ((Object *)gd->ActiveChild, (Msg)msg); + gd->ActiveChild = NULL; + } +} + + + +static ULONG ASMCALL SG_GMHelpTest (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpHitTest *msg)) +{ + struct GroupData *gd = INST_DATA (cl, g); + struct ExtGadget *child; + APTR object_state; + WORD x, y; + + DB1 (DBPRINTF ("SmartGroupGClass: GM_HELPTEST\n");) + + ASSERT_VALID_PTR(gd) + object_state = (APTR)gd->ChildList.mlh_Head; + ASSERT_VALID_PTR(object_state) + + + if ((g->Flags & GFLG_EXTENDED) && (g->MoreFlags & GMORE_GADGETHELP)) + { + x = msg->gpht_Mouse.X + gd->GBox.Left; + y = msg->gpht_Mouse.Y + gd->GBox.Top; + + /* Search over all our children */ + while (child = (struct ExtGadget *)NextObject(&object_state)) + { + ASSERT_VALID_PTR(child) + + /* Limit to gadgets that understand GM_HELPTEST */ + if ((child->Flags & GFLG_EXTENDED) && (child->MoreFlags & GMORE_GADGETHELP)) + { + if (child->MoreFlags & GMORE_BOUNDS) + { + /* Check whether the mouse coordinates are inside + * the gadget rectangle of our child + */ + if ((x >= child->BoundsLeftEdge) && + (x < child->BoundsLeftEdge + child->BoundsWidth) && + (y >= child->BoundsTopEdge) && + (y < child->BoundsTopEdge + child->BoundsHeight)) + { + struct gpHitTest childmsg; + + childmsg.MethodID = GM_HELPTEST; + childmsg.gpht_GInfo = msg->gpht_GInfo; + childmsg.gpht_Mouse.X = x - child->BoundsLeftEdge; + childmsg.gpht_Mouse.Y = y - child->BoundsTopEdge; + + if (DoMethodA ((Object *)child, (Msg)&childmsg) == GMR_HELPHIT) + { + gd->ActiveChild = child; + return GMR_HELPHIT; + } + } + } + else /* No valid bounds, use gadget select box */ + { + /* Check whether the mouse coordinates are inside + * the gadget rectangle of our child + */ + if ((x >= child->LeftEdge) && + (x < child->LeftEdge + child->Width) && + (y >= child->TopEdge) && + (y < child->TopEdge + child->Height)) + { + struct gpHitTest childmsg; + + childmsg.MethodID = GM_HELPTEST; + childmsg.gpht_GInfo = msg->gpht_GInfo; + childmsg.gpht_Mouse.X = x - child->LeftEdge; + childmsg.gpht_Mouse.Y = y - child->TopEdge; + + if (DoMethodA ((Object *)child, (Msg)&childmsg) == GMR_HELPHIT) + { + gd->ActiveChild = child; + return GMR_HELPHIT; + } + } + } + } + } + } + + return GMR_NOHELPHIT; +} + + + +static void ASMCALL SG_GMLayout(REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpLayout *msg)) +{ + struct GroupData *gd = (struct GroupData *) INST_DATA (cl, (Object *)g); + struct ExtGadget *child; + APTR object_state; + + DB2 (DBPRINTF ("SmartGroupGClass: GM_LAYOUT\n");) + ASSERT_VALID_PTR(gd) + + /* Collect new group size */ + GetGadgetBounds(msg->gpl_GInfo, g, &gd->GBox); + + /* Forward GM_LAYOUT to our children that need it */ + + object_state = (APTR)gd->ChildList.mlh_Head; + ASSERT_VALID_PTR(object_state) + + while (child = (struct ExtGadget *)NextObject(&object_state)) + { + ASSERT_VALID_PTR(child) + + if (child->Flags & ( + GFLG_RELBOTTOM | + GFLG_RELRIGHT | + GFLG_RELWIDTH | + GFLG_RELHEIGHT | + GFLG_RELSPECIAL)) + { + DB2 (DBPRINTF ("SmartGroupGClass: Forwarding GM_LAYOUT to child\n");) + DoMethodA ((Object *)child, (Msg)msg); + } + } +} + + + +static ULONG ASMCALL SG_GMDomain (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct gpDomain *msg)) +{ + DB1 (DBPRINTF ("SmartGroupGClass: GM_DOMAIN\n");) + + /* TODO */ + return 0; +} + + + +static ULONG ASMCALL SG_OMNew (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opSet *msg)) +{ + struct GroupData *gd; + struct TagItem *ti, *tstate = msg->ops_AttrList; + + DB1 (DBPRINTF ("SmartGroupGClass: OM_NEW\n");) + + if (g = (struct ExtGadget *)DoSuperMethodA (cl, (Object *)g, (Msg)msg)) + { + gd = (struct GroupData *) INST_DATA (cl, (Object *)g); + ASSERT_VALID_PTR(gd) + + DB (if (g->Flags & GFLG_EXTENDED) + DBPRINTF ("SmartGroupGClass: Wow, we are an ExtGadget!\n");) + + /* Initialize object instance data */ + NEWLIST((struct List *)&gd->ChildList); + gd->ActiveChild = NULL; + gd->ActiveChild = NULL; + + gd->Orientation = LORIENT_NONE; + + while (ti = NextTagItem (&tstate)) + switch (ti->ti_Tag) + { + case SGA_Child: + { + struct opMember opam; + + if (!ti->ti_Data) + { + /* Commit suicide without disturbing the + * dispatchers of our subclasses + */ + SG_OMDispose (cl, g, NULL); + return NULL; + } + + ASSERT_VALID_PTR(ti->ti_Data) + opam.opam_Object = (Object *)ti->ti_Data; + SG_OMAddMember (cl, g, &opam); + break; + } + + case LAYOUTA_Orientation: + gd->Orientation = ti->ti_Data; + break; + + default: + break; + } + + /* Intuition sends GM_LAYOUT messages only to gadgets with + * relative postion. Since we need to recalculate the + * positions of our children when the window resizes, we + * set the GFLG_RELSPECIAL property if to be notified in all cases. + */ + g->Flags |= GFLG_RELSPECIAL; + } + + return (ULONG)g; +} + + + +static void ASMCALL SG_OMDispose (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, Msg msg)) +{ + struct GroupData *gd = (struct GroupData *) INST_DATA (cl, (Object *)g); + Object *o; + APTR object_state; + + DB1 (DBPRINTF ("SmartGroupGClass: OM_DISPOSE\n");) + + ASSERT_VALID_PTR(gd) + object_state = (APTR)gd->ChildList.mlh_Head; + ASSERT_VALID_PTR(object_state) + + /* The groupgclass disposes all its children automatically */ + while (o = NextObject(&object_state)) + { + ASSERT_VALID_PTR(o) + DoMethod (o, OM_REMOVE); + DisposeObject(o); + } + + /* Our superclass will cleanup everything else now */ + DoSuperMethodA (cl, (Object *)g, msg); + + /* From now on, our instance data is no longer available */ +} + + +#if 0 +static ULONG ASMCALL SG_OMSet (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opUpdate *msg)) +{ + struct GroupData *gd = INST_DATA (cl, g); + struct TagItem *ti, *tstate = msg->opu_AttrList; + + DB1 (DBPRINTF ("SmartGroupGClass: OM_SET\n");) + + ASSERT_VALID_PTR(gd) + ASSERT_VALID_PTR_OR_NULL(tstate) + + DB2 (DBPRINTF ((msg->MethodID == OM_SET) ? + "SliderBarGClass: OM_SET\n" : + "SliderBarGClass: OM_UPDATE\n");) + + + while (ti = NextTagItem (&tstate)) + switch (ti->ti_Tag) + { + default: + break; + } + + result = TRUE; + + + return result; +} +#endif + + + +static void ASMCALL SG_OMAddMember (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opMember *msg)) +{ + struct GroupData *gd = INST_DATA (cl, g); + ASSERT_VALID_PTR(gd) + DB1 (DBPRINTF ("SmartGroupGClass: OM_ADDMEMBER\n");) + + if(msg->opam_Object) + { + ASSERT_VALID_PTR(msg->opam_Object) + + /* TODO: check for GMORE_SCROLLRASTER ? */ + + DoMethod (msg->opam_Object, OM_ADDTAIL, &gd->ChildList); + } +} + + + +static void ASMCALL SG_OMRemMember (REG(a0, Class *cl), REG(a2, struct ExtGadget *g), REG(a1, struct opMember *msg)) +{ + struct GroupData *gd = INST_DATA (cl, g); + + DB1 (DBPRINTF ("SmartGroupGClass: OM_REMMEBRER\n");) + ASSERT_VALID_PTR(gd) + + DoMethod (msg->opam_Object, OM_REMOVE); + + if (msg->opam_Object == (Object *)gd->ActiveChild) + gd->ActiveChild = NULL; + + /* TODO: resize & redraw group */ +} + + + +static ULONG HOOKCALL SmartGroupDispatcher ( + REG(a0, Class *cl), + REG(a2, Object *o), + REG(a1, Msg msg)) + +/* SmartGroup class dispatcher - Handles all boopsi messages. */ +{ + static const HookPtr GMHooks[] = + { + /* GM_HITTEST */ (HookPtr)SG_GMHitTest, + /* GM_RENDER */ (HookPtr)SG_GMRender, + /* GM_GOACTIVE */ (HookPtr)SG_GMGoActive, + /* GM_HANDLEINPUT */ (HookPtr)SG_GMHandleInput, + /* GM_GOINACTIVE */ (HookPtr)SG_GMGoInactive, + /* GM_HELPTEST */ (HookPtr)SG_GMHelpTest, + /* GM_LAYOUT */ (HookPtr)SG_GMLayout, + /* GM_DOMAIN */ (HookPtr)SG_GMDomain + }; + + static const HookPtr OMHooks[] = + { + /* OM_NEW */ (HookPtr)SG_OMNew, + /* OM_DISPOSE */ (HookPtr)SG_OMDispose, + /* OM_SET */ (HookPtr)NULL, + /* OM_GET */ (HookPtr)NULL, + /* OM_ADDTAIL */ (HookPtr)NULL, + /* OM_REMOVE */ (HookPtr)NULL, + /* OM_NOTIFY */ (HookPtr)NULL, + /* OM_UPDATE */ (HookPtr)NULL, + /* OM_ADDMEMBER */ (HookPtr)SG_OMAddMember, + /* OM_REMMEMBER */ (HookPtr)SG_OMRemMember + }; + + ULONG id; + + ASSERT_VALID_PTR(cl) + ASSERT_VALID_PTR(o) + ASSERT_VALID_PTR(msg) + + /* Optimized boopsi class dispatcher. + * + * This class overrides almost all gadgetclass and rootclass messages. + * The usual switch() statement on msg->MessageID would be quite inefficient. + * Most compilers aren't smart enough to implement it with two jump tables + * as we did here. This code relies on the values assigned to the method IDs + * in the headers to remain constant. It will break otherwise. + */ + + id = msg->MethodID; + + if (id <= GM_DOMAIN) + return GMHooks[id](cl, o, msg); + + id -= OM_NEW; + + if (id <= (OM_REMMEMBER - OM_NEW)) + if (OMHooks[id]) + return OMHooks[id](cl, o, msg); + + return DoSuperMethodA (cl, o, msg); +} + + + +Class *MakeSmartGroupGClass (void) +{ + Class *class; + + if (class = MakeClass ( +#if (CLASS_FLAVOUR & FLAVOUR_PUBCLASS) + SMARTGROUPGCLASS, +#else + NULL, +#endif + GADGETCLASS, NULL, sizeof (struct GroupData), 0)) + { + class->cl_Dispatcher.h_Entry = (ULONG (*)()) SmartGroupDispatcher; + } + + return class; +} + + +BOOL FreeSmartGroupGClass (Class *class) +{ + if (class) + { + ASSERT_VALID_PTR(class) + + /* Try to remove the class */ + if (FreeClass (class)) + return TRUE; + + return FALSE; + } + return TRUE; +} + + + +#if (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) +/* + * Class library support functions + */ + +struct ClassLibrary * HOOKCALL _UserLibInit (REG(a6, struct ClassLibrary *mybase)) +{ + SysBase = *((struct ExecBase **)4); /* Initialize SysBase */ + + IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 39); + UtilityBase = (UTILITYBASETYPE *) OpenLibrary ("utility.library", 39); + + if (!(IntuitionBase && UtilityBase)) + { + _UserLibCleanup (mybase); + return NULL; + } + + if (mybase->cl_Class = MakeSmartGroupGClass ()) + { + return mybase; + } + else + { + _UserLibCleanup (mybase); + return NULL; + } +} + +struct ClassLibrary * HOOKCALL _UserLibCleanup (REG(a6, struct ClassLibrary *mybase)) +{ + if (mybase->cl_Class) + if (!FreeSliderBarGClass (mybase->cl_Class)) + return NULL; + + CloseLibrary ((struct Library *)UtilityBase); + CloseLibrary ((struct Library *)IntuitionBase); + + return mybase; +} + +Class * HOOKCALL _GetEngine (REG(a6, struct ClassLibrary *mybase)) +{ + return (mybase->cl_Class); +} + +#endif /* (CLASS_FLAVOUR & FLAVOUR_CLASSLIB) */ diff --git a/gadgets/ToolManagerGClass/Makefile b/gadgets/ToolManagerGClass/Makefile new file mode 100644 index 0000000..eb79630 --- /dev/null +++ b/gadgets/ToolManagerGClass/Makefile @@ -0,0 +1,27 @@ +# +# $Id:$ +# +# Copyright (C) 1999 by Matteo Cavalleri +# + +include $(BOOPSITOP)/config.mk +include config.mk + +ARG_COMMON := +ARG_ALL := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o +ARG_LIB := $(ARG_COMMON) +ARG_DEBUG := $(ARG_COMMON) $(BOOPSITOP)/common/OpenClass.o $(DEF) $(PRV) +ARG_PRIVATE := $(ARG_COMMON) +ARG_OBJ := $(ARG_COMMON) + +DEP_COMMON := +DEP_ALL := $(DEP_COMMON) OpenClass.o +DEP_LIB := $(DEP_COMMON) +DEP_DEBUG := $(DEP_COMMON) OpenClass.o +DEP_PRIVATE := $(DEP_COMMON) +DEP_OBJ := $(DEP_COMMON) + +include $(BOOPSITOP)/common/general.mk + +OpenClass.o: OpenClass.c + $(MAKE) -C $(BOOPSITOP)/common/ $@ diff --git a/include/BoopsiLib.h b/include/BoopsiLib.h new file mode 100644 index 0000000..af655c5 --- /dev/null +++ b/include/BoopsiLib.h @@ -0,0 +1,92 @@ +/* +** $Id: BoopsiLib.h,v 1.1 2000/01/12 20:30:05 bernie Exp $ +** +** Copyright (C) 1999 Bernardo Innocenti +** All rights reserved. +** +** Use 4 chars wide TABs to read this file +** +** Prototypes for the GetGadgetBox() and GetGadgetBounds() helpers +*/ + +#ifndef INTUITION_CGHOOKS_H +#include +#endif + +#ifndef INTUITION_IMAGECLASS_H +#include +#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 + */ + +/* This macro evalutates to true when the layer is + * covered by another layer + */ +#define LayerCovered(l) \ + ((!(l)->ClipRect) || \ + ((l)->bounds.MinX != (l)->ClipRect->bounds.MinX) || \ + ((l)->bounds.MinY != (l)->ClipRect->bounds.MinY) || \ + ((l)->bounds.MaxX != (l)->ClipRect->bounds.MaxX) || \ + ((l)->bounds.MaxY != (l)->ClipRect->bounds.MaxY)) + +/* memcmp(&(l)->ClipRect->bounds, &(l)->bounds, sizeof (struct Rectangle))) */ + +/* This macro evalutates to true if the layer has damage regions */ +#define LayerDamaged(l) \ + ((l)->DamageList && (l)->DamageList->RegionRectangle) + +/* This macro checks if ScrollRaster() needs to be called to + * scroll the layer damage after a scrolling operation. + */ +#define NeedZeroScrollRaster(l) \ + (((l)->Flags & LAYERSIMPLE) && (LayerCovered(l) || LayerDamaged(l))) diff --git a/include/BoopsiStubs.h b/include/BoopsiStubs.h new file mode 100644 index 0000000..43f0cc0 --- /dev/null +++ b/include/BoopsiStubs.h @@ -0,0 +1,243 @@ +#ifndef BOOPSISTUBS_H +#define BOOPSISTUBS_H +/* +** $Id: boopsistubs.h,v 1.2 2000/07/15 20:45:32 stegerg Exp $ +** +** Copyright (C) 1997,1999,2000 Bernardo Innocenti +** 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 + */ +#ifndef USE_BOOPSI_STUBS +#define USE_BOOPSI_STUBS +#endif /* USE_BOOPSI_STUBS */ + + +#ifndef INTUITION_CLASSES_H +#include +#endif /* INTUITION_CLASSES_H */ + +#if defined(_AROS) + + #ifndef AROS_DEBUG_H + #include + #endif /* AROS_DEBUG_H */ + + #ifndef AROS_ASMCALL_H + #include + #endif /* AROS_ASMCALL_H */ + + #define _CALL_DISPATCHER(entry, cl, o, msg) \ + AROS_UFC3(IPTR, entry, \ + AROS_UFCA(Class *, cl, A0), \ + AROS_UFCA(Object *, o, A2), \ + AROS_UFCA(APTR, msg, A1)) + + #ifndef INLINE + #define INLINE static inline + #endif + +#else /* !_AROS */ + + #ifndef COMPILERSPECIFIC_H + #include "CompilerSpecific.h" + #endif /* COMPILERSPECIFIC_H */ + + #ifndef DEBUGMACROS_H + #include "DebugMacros.h" + #endif /* DEBUGMACROS_H */ + + /* the _HookPtr type is a shortcut for a pointer to a hook function */ + typedef ASMCALL IPTR (*HookPtr) + (REG(a0, Class *), REG(a2, Object *), REG(a1, APTR)); + + #define _CALL_DISPATCHER(entry, cl, o, msg) \ + ((HookPtr)(entry))(cl, o, msg) + +#endif /* _AROS */ + + + +/* SAS/C is clever enough to inline these even var-args functions, while gcc and egcs + * refuse to do it (yikes!). The GCC versions of these functions are macro blocks + * similar to those used in the inline/#?.h headers. + */ +#if defined(__SASC) || defined (__STORM__) + + INLINE ULONG CoerceMethodA(Class *cl, Object *o, Msg msg) + { + ASSERT_VALID_PTR(cl); + ASSERT_VALID_PTR_OR_NULL(o); + + return _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg); + } + + INLINE ULONG DoSuperMethodA(Class *cl, Object *o, Msg msg) + { + ASSERT_VALID_PTR(cl); + ASSERT_VALID_PTR_OR_NULL(o); + + cl = cl->cl_Super; + return _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg); + } + + INLINE ULONG DoMethodA(Object *o, Msg msg) + { + Class *cl; + ASSERT_VALID_PTR(o); + cl = OCLASS (o); + ASSERT_VALID_PTR(cl); + + return _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg); + } + + INLINE ULONG CoerceMethod(Class *cl, Object *o, ULONG MethodID, ...) + { + ASSERT_VALID_PTR(cl); + ASSERT_VALID_PTR_OR_NULL(o); + + return ((HookPtr)cl->cl_Dispatcher.h_Entry) ((APTR)cl, (APTR)o, (APTR)&MethodID); + } + + INLINE ULONG DoSuperMethod(Class *cl, Object *o, ULONG MethodID, ...) + { + ASSERT_VALID_PTR(cl); + ASSERT_VALID_PTR_OR_NULL(o); + + cl = cl->cl_Super; + return ((HookPtr)cl->cl_Dispatcher.h_Entry) ((APTR)cl, (APTR)o, (APTR)&MethodID); + } + + INLINE ULONG DoMethod(Object *o, ULONG MethodID, ...) + { + Class *cl; + + ASSERT_VALID_PTR(o); + cl = OCLASS (o); + ASSERT_VALID_PTR(cl); + + return ((HookPtr)cl->cl_Dispatcher.h_Entry) ((APTR)cl, (APTR)o, (APTR)&MethodID); + } + + /* varargs stub for the OM_NOTIFY method */ + INLINE void NotifyAttrs(Object *o, struct GadgetInfo *gi, ULONG flags, Tag attr1, ...) + { + ASSERT_VALID_PTR(o); + ASSERT_VALID_PTR_OR_NULL(gi); + + DoMethod(o, OM_NOTIFY, &attr1, gi, flags); + } + + /* varargs stub for the OM_UPDATE method */ + INLINE void UpdateAttrs(Object *o, struct GadgetInfo *gi, ULONG flags, Tag attr1, ...) + { + ASSERT_VALID_PTR(o); + ASSERT_VALID_PTR_OR_NULL(gi); + + DoMethod(o, OM_UPDATE, &attr1, gi, flags); + } + + /* varargs stub for the OM_SET method. Similar to SetAttrs(), but allows + * to pass the GadgetInfo structure + */ + INLINE void SetAttrsGI(Object *o, struct GadgetInfo *gi, ULONG flags, Tag attr1, ...) + { + ASSERT_VALID_PTR(o); + ASSERT_VALID_PTR_OR_NULL(gi); + + DoMethod(o, OM_SET, &attr1, gi, flags); + } + +#elif defined(__GNUC__) + + #define CoerceMethodA(cl, o, msg) \ + ({ \ + ASSERT_VALID_PTR(cl); \ + ASSERT_VALID_PTR_OR_NULL(o); \ + _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg); \ + }) + + #define DoSuperMethodA(cl, o, msg) \ + ({ \ + Class *_cl; \ + ASSERT_VALID_PTR(cl); \ + ASSERT_VALID_PTR_OR_NULL(o); \ + _cl = cl->cl_Super; \ + ASSERT_VALID_PTR(_cl); \ + _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, msg); \ + }) + + #define DoMethodA(o, msg) \ + ({ \ + Class *_cl; \ + ASSERT_VALID_PTR(o); \ + _cl = OCLASS(o); \ + ASSERT_VALID_PTR(_cl); \ + _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, msg); \ + }) + + #define CoerceMethod(cl, o, msg...) \ + ({ \ + IPTR _msg[] = { msg }; \ + ASSERT_VALID_PTR(cl); \ + ASSERT_VALID_PTR_OR_NULL(o); \ + _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, _msg); \ + }) + + #define DoSuperMethod(cl, o, msg...) \ + ({ \ + Class *_cl; \ + IPTR _msg[] = { msg }; \ + ASSERT_VALID_PTR(cl); \ + ASSERT_VALID_PTR_OR_NULL(o); \ + _cl = cl->cl_Super; \ + ASSERT_VALID_PTR(_cl); \ + _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \ + }) + + #define DoMethod(o, msg...) \ + ({ \ + Class *_cl; \ + IPTR _msg[] = { msg }; \ + ASSERT_VALID_PTR(o); \ + _cl = OCLASS(o); \ + ASSERT_VALID_PTR_OR_NULL(_cl); \ + _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \ + }) + + /* Var-args stub for the OM_NOTIFY method */ + #define NotifyAttrs(o, gi, flags, attrs...) \ + ({ \ + Class *_cl; \ + IPTR _attrs[] = { attrs }; \ + IPTR _msg[] = { OM_NOTIFY, (IPTR)_attrs, (IPTR)gi, flags }; \ + ASSERT_VALID_PTR(o); \ + _cl = OCLASS(o); \ + ASSERT_VALID_PTR(_cl); \ + ASSERT_VALID_PTR_OR_NULL(gi); \ + _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \ + }) + + /* Var-args stub for the OM_UPDATE method */ + #define UpdateAttrs(o, gi, flags, attrs...) \ + ({ \ + Class *_cl; \ + IPTR _attrs[] = { attrs }; \ + IPTR _msg[] = { OM_UPDATE, (IPTR)_attrs, (IPTR)gi, flags }; \ + ASSERT_VALID_PTR(o); \ + _cl = OCLASS(o); \ + ASSERT_VALID_PTR(_cl); \ + ASSERT_VALID_PTR_OR_NULL(gi); \ + _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \ + }) +#endif + +#endif /* !BOOPSISTUBS_H */ diff --git a/include/CompilerSpecific.h b/include/CompilerSpecific.h new file mode 100644 index 0000000..4a59158 --- /dev/null +++ b/include/CompilerSpecific.h @@ -0,0 +1,315 @@ +#ifndef COMPILERSPECIFIC_H +#define COMPILERSPECIFIC_H +/* +** $Id: CompilerSpecific.h,v 1.3 2000/01/12 20:30:24 bernie Exp $ +** +** Copyright (C) 1997-2000 Bernardo Innocenti +** 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 in 68K register +** +** min(a,b) +** Return the minimum between and +** +** max(a,b) +** Return the maximum between and +** +** abs(a) +** Return the absolute value of +** +** _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 + +#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 + +#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 + + #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 + * . Passing "const char *" parameters will only work + * if the OS protos are using CONST_STRPTR accordingly, otherwise you + * will get a lot of compiler warnings for const to volatile conversions. + * + * Using "const" where it is appropriate helps the compiler optimizing + * code better, so this mess is probably worth it. + */ +#if (!defined(_AROS)) && (INCLUDE_VERSION < 44) +typedef char *CONST_STRPTR; +#endif + + +/* Special function attributes */ + +#define LIBCALL ASMCALL SAVEDS +#define HOOKCALL ASMCALL SAVEDS +#ifdef __cplusplus + #define GLOBALCALL extern "C" +#else + #define GLOBALCALL +#endif + +/* special variable attributes */ +#define XDEF +#define XREF extern + + +/* AROS Compatibility: IPTR is a type which can store a pointer + * as well as a long integer. + */ +#if !defined(IPTR) && !defined(__typedef_IPTR) +#define IPTR unsigned long +#endif /* IPTR */ + + +#endif /* !COMPILERSPECIFIC_H */ diff --git a/include/DebugMacros.h b/include/DebugMacros.h new file mode 100644 index 0000000..cca9f8f --- /dev/null +++ b/include/DebugMacros.h @@ -0,0 +1,147 @@ +#ifndef DEBUGMACROS_H +#define DEBUGMACROS_H +/* +** $Id: DebugMacros.h,v 1.3 2000/01/12 20:30:24 bernie Exp $ +** +** Copyright (C) 1995,96,97,98,99 Bernardo Innocenti +** 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 evalutates to a +** non-zero value, output a debug message otherwise. +** +** ASSERT_VALID_PTR(x) +** Checks if the expression 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 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 when making a debug +** executable, otherwise omit it. +** +** DB1(x) +** DB verbosity level 1. Compile the expression when the +** preprocessor symbol DEBUG is defined to a number greater or +** equal to 1. +** +** DB2(x) +** DB verbosity level 2. Compile the expression 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 + #endif /* PROTO_EXEC_H */ + + #if defined(__SASC) + + extern void __builtin_emit (int); + // #define ILLEGAL __builtin_emit(0x4AFC) + #define ILLEGAL 0 + STDARGS extern void kprintf (const char *, ...); + + #elif defined(__GNUC__) + + /* GCC doesn't accept asm statements in the middle of an + * expression such as `a ? b : asm("something")'. + */ + #define ILLEGAL illegal() + static __inline__ int illegal(void) { asm("illegal"); return 0; } + extern void STDARGS FORMATCALL(printf,1,2) kprintf(const char *, ...); + + #else + #error Please add compiler specific definitions for your compiler + #endif + + + /* common definitions for ASSERT and DB macros */ + + #define DBPRINTF kprintf + #define bug kprintf + + /* The trick with THIS_FILE is meant to avoid multiple allocations of + * the filename string for each occurrence of these macros. To reduce + * debug executable size, each module should cooperate by undefinining + * the THIS_FILE macro and declaring a static global symbol with the + * same name. + */ + #define THIS_FILE __FILE__ + + #define ASSERT(x) ( (x) ? 0 : \ + ( DBPRINTF("\x07%s:%ld: assertion failed: %s\n", \ + THIS_FILE, __LINE__, #x) , ILLEGAL ) ); + + #define ASSERT_VALID_PTR_OR_NULL(x) ( ((((APTR)(x)) == NULL) || \ + (((LONG)(x) > 1024) && TypeOfMem((APTR)(x)))) ? 0 : \ + ( DBPRINTF("\x07%s:%ld: bad pointer: %s = $%lx\n", \ + THIS_FILE, __LINE__, #x, (APTR)(x)) , ILLEGAL ) ); + + #define ASSERT_VALID_PTR(x) ( (((LONG)(x) > 1024) && \ + TypeOfMem((APTR)(x))) ? 0 : \ + ( DBPRINTF("\x07%s, %ld: bad pointer: %s = $%lx\n", \ + THIS_FILE, __LINE__, #x, (APTR)(x)) , ILLEGAL ) ); + + #define D(x) x + #define DB(x) x + #define DB1(x) x + + #if _DEBUG >= 2 + #define DB2(x) x + #else + #define DB2(x) + #endif + + #if _DEBUG >= 3 + #define DB3(x) x + #else + #define DB3(x) + #endif +#else + #define ASSERT_VALID_PTR(x) + #define ASSERT_VALID_PTR_OR_NULL(x) + #define ASSERT(x) + #define DB(x) + #define D(x) + #define DB1(x) + #define DB2(x) + #define DB3(x) +#endif /* _DEBUG */ + +#endif /* !DEBUGMACROS_H */ diff --git a/include/DiagnosticMacros.h b/include/DiagnosticMacros.h new file mode 100644 index 0000000..4135a7c --- /dev/null +++ b/include/DiagnosticMacros.h @@ -0,0 +1,146 @@ +#ifndef DIAGNOSTICMACROS_H +#define DIAGNOSTICMACROS_H +/* +** $Id: DiagnosticMacros.h,v 1.3 2000/01/12 20:29:05 bernie Exp $ +** +** Copyright (C) 1999 Bernardo Innocenti +** All rights reserved. +** +** Use 4 chars wide TABs to read this file +** +** These are some handy macros to dump some common system +** structures to the debug console. Use DUMP_XXX(pointer) +** in your code to get a full dump of the structure contents. +** +** These macros will automatically disable themselves when the +** preprocessor symbol DEBUG isn't defined. +*/ + +#ifdef DEBUG + +#define DUMP_BITMAP(p) DumpBitMap(p, #p); +#define DUMP_LAYER(p) DumpLayer(p, #p); +#define DUMP_GADGETINFO(p) DumpGadgetInfo (p, #p); + +#ifdef INTUITION_CGHOOKS_H +static void DumpGadgetInfo (struct GadgetInfo *p, const char *name) +{ + if (p) + { + DBPRINTF ("struct GadgetInfo * %s (at 0x%lx) = {\n", name, p); + DBPRINTF (" struct Screen * gi_Screen = 0x%lx\n", p->gi_Screen); + DBPRINTF (" struct Window * gi_Window = 0x%lx\n", p->gi_Window); + DBPRINTF (" struct Requester * gi_Requester = 0x%lx\n", p->gi_Requester); + + DBPRINTF (" struct RastPort * gi_RastPort = 0x%lx\n", p->gi_RastPort); + DBPRINTF (" struct Layer * gi_Layer = 0x%lx\n", p->gi_Layer); + DBPRINTF (" struct IBox gi_Domain = { %ld, %ld, %ld, %ld }\n", + p->gi_Domain.Left, p->gi_Domain.Top, p->gi_Domain.Width, p->gi_Domain.Height); + DBPRINTF (" UBYTE gi_Pens = { %ld, %ld }\n", + p->gi_Pens.DetailPen, p->gi_Pens.BlockPen); + DBPRINTF (" struct DrawInfo * gi_DrInfo = 0x%lx\n", p->gi_DrInfo); + } + else + DBPRINTF (" struct GadgetInfo * %s = NULL\n", name); +} +#endif /* !INTUITION_CGHOOKS_H */ + +#ifdef GRAPHICS_GFX_H +static void DumpBitMap (struct BitMap *p, const char *name) +{ + if (p) + { + DBPRINTF ("struct BitMap * %s (at 0x%lx) = {\n", name, p); + DBPRINTF (" UWORD BytesPerRow = %ld\n", p->BytesPerRow); + DBPRINTF (" UWORD Rows = %ld\n", p->Rows); + DBPRINTF (" UBYTE Flags = 0x%lx\n", p->Flags); + DBPRINTF (" UBYTE Depth = %ld\n", p->Depth); + DBPRINTF (" UWORD pad = %ld\n", p->pad); + DBPRINTF (" PLANEPTR Planes[8] = { 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx }\n", + p->Planes[0], p->Planes[1], p->Planes[2], p->Planes[3], + p->Planes[4], p->Planes[5], p->Planes[6], p->Planes[7]); + DBPRINTF ("};\n"); + } + else + DBPRINTF (" struct BitMap * %s = NULL\n", name); +} +#endif /* !GRAPHICS_GFX_H */ + + +#ifdef GRAPHICS_CLIP_H +static void DumpLayer (struct Layer *p, const char *name) +{ + if (p) + { + char flags[128]; + + flags[0] = '\0'; + + if (p->Flags & LAYERSIMPLE) strcat(flags, "LAYERSIMPLE"); + if (p->Flags & LAYERSMART) strcat(flags, " | LAYERSMART"); + if (p->Flags & LAYERSUPER) strcat(flags, " | LAYERSUPER"); + if (p->Flags & 0x0008) strcat(flags, " | 0x0008"); + if (p->Flags & LAYERUPDATING) strcat(flags, " | LAYERUPDATING"); + if (p->Flags & 0x0020) strcat(flags, " | 0x0020"); + if (p->Flags & LAYERBACKDROP) strcat(flags, " | LAYERBACKDROP"); + if (p->Flags & LAYERREFRESH) strcat(flags, " | LAYERREFRESH"); + if (p->Flags & LAYER_CLIPRECTS_LOST) strcat(flags, " | LAYER_CLIPRECTS_LOST"); + if (p->Flags & LAYERIREFRESH) strcat (flags, " | LAYERIREFRESH"); + if (p->Flags & LAYERIREFRESH2) strcat (flags, " | LAYERIREFRESH2"); + if (p->Flags & 0x0800) strcat(flags, " | 0x0800"); + if (p->Flags & 0x1000) strcat(flags, " | 0x1000"); + if (p->Flags & 0x2000) strcat(flags, " | 0x2000"); + if (p->Flags & 0x4000) strcat(flags, " | 0x4000"); + if (p->Flags & 0x8000) strcat(flags, " | 0x8000"); + + + DBPRINTF ("struct Layer * %s (at 0x%lx) = {\n", name, p); + DBPRINTF (" struct Layer * front = 0x%lx, back = 0x%lx\n", p->front, p->back); + DBPRINTF (" struct ClipRect * ClipRect = 0x%lx\n", p->ClipRect); + DBPRINTF (" struct RastPort * rp = 0x%lx\n", p->rp); + DBPRINTF (" struct Rectangle bounds = { %ld, %ld, %ld, %ld }\n", + p->bounds.MinX, p->bounds.MinY, p->bounds.MaxX, p->bounds.MaxY); + DBPRINTF (" UBYTE reserved[4] = { %ld, %ld, %ld, %ld }\n", + p->reserved[0], p->reserved[1], p->reserved[2], p->reserved[3]); + DBPRINTF (" UWORD priority = %ld\n", p->priority); + DBPRINTF (" UWORD Flags = 0x%lx (%s)\n", p->Flags, flags); + DBPRINTF (" struct BitMap * SuperBitMap = 0x%lx\n", p->SuperBitMap); + DBPRINTF (" struct ClipRect * SuperClipRect = 0x%lx\n", p->SuperClipRect); + DBPRINTF (" APTR Window = 0x%lx\n", p->Window); + DBPRINTF (" UWORD Scroll_X = %ld, Scroll_Y = %ld\n", p->Scroll_X, p->Scroll_Y); + DBPRINTF (" struct ClipRect * cr = 0x%lx, cr2 = 0x%lx, crnew = 0x%lx\n", + p->cr, p->cr2, p->crnew); + DBPRINTF (" struct ClipRect * SuperSaveClipRects = 0x%lx\n", p->SuperSaveClipRects); + DBPRINTF (" struct ClipRect * _cliprects = 0x%lx\n", p->_cliprects); + DBPRINTF (" struct Layer_Info * LayerInfo = 0x%lx\n", p->LayerInfo); + DBPRINTF (" struct SignalSemaphore Lock = {\n"); + DBPRINTF (" WORD ss_NestCount = %ld\n", p->Lock.ss_NestCount); + DBPRINTF (" struct Task * ss_Owner = 0x%lx\n", p->Lock.ss_Owner); + DBPRINTF (" ...\n"); + DBPRINTF (" };\n"); + DBPRINTF (" struct Hook * BackFill = 0x%lx\n", p->BackFill); + DBPRINTF (" ULONG reserved1 = 0x%lx\n", p->reserved1); + DBPRINTF (" struct Region * ClipRegion = 0x%lx\n", p->ClipRegion); + DBPRINTF (" struct Region * saveClipRects = 0x%lx\n", p->saveClipRects); + DBPRINTF (" WORD Width = %ld, Height = %ld\n", p->Width, p->Height); + DBPRINTF (" UBYTE reserved2[18] = ...\n"); + DBPRINTF (" struct Region * DamageList = 0x%lx\n", p->DamageList); + DBPRINTF ("};\n"); + } + else + DBPRINTF ("struct Layer * %s = NULL\n", name); +} +#endif /* !GRAPHICS_CLIP_H */ + + + + +#else /* DEBUG not defined */ + +#define DUMP_BITMAP(x) +#define DUMP_LAYER(x) +#define DUMP_GADGETINFO(x) + +#endif /* !DEBUG */ + +#endif /* !DIAGNOSTICMACROS_H */ diff --git a/include/ListMacros.h b/include/ListMacros.h new file mode 100644 index 0000000..b19bc64 --- /dev/null +++ b/include/ListMacros.h @@ -0,0 +1,99 @@ +#ifndef LISTMACROS_H +#define LISTMACROS_H +/* +** $Id: ListMacros.h,v 1.2 1999/02/07 14:41:02 bernie Exp $ +** +** Copyright (C) 1997 Bernardo Innocenti +** All rights reserved. +** +** Use 4 chars wide TABs to read this source +** +** Some handy macros for list operations. Using these macros is faster +** than calling their exec.library equivalents, but they will eventually +** make your code a little bigger and are also subject to common macro +** side effects. +*/ + + +#define NEWLIST(l) ( (l)->lh_TailPred = (struct Node *)(l), \ + (l)->lh_Tail = 0, \ + (l)->lh_Head = (struct Node *)(&((l)->lh_Tail)) ) + +#define ADDHEAD(l,n) ( (n)->ln_Pred = (struct Node *)(l), \ + (n)->ln_Succ = (l)->lh_Head, \ + (l)->lh_Head->ln_Pred = (n), \ + (l)->lh_Head = (n) ) + +#define ADDTAIL(l,n) ( (n)->ln_Succ = (struct Node *)(&((l)->lh_Tail)), \ + (n)->ln_Pred = (l)->lh_TailPred, \ + (l)->lh_TailPred->ln_Succ = (n), \ + (l)->lh_TailPred = (n) ) + +#define REMOVE(n) ( (n)->ln_Succ->ln_Pred = (n)->ln_Pred, \ + (n)->ln_Pred->ln_Succ = (n)->ln_Succ ) + +#define GETHEAD(l) ( (l)->lh_Head->ln_Succ ? (l)->lh_Head : (struct Node *)NULL ) + +#define GETTAIL(l) ( (l)->lh_TailPred->ln_Succ ? (l)->lh_TailPred : (struct Node *)NULL ) + +#define GETSUCC(n) ( (n)->ln_Succ->ln_Succ ? (n)->ln_Succ : (struct Node *)NULL ) + +#define GETPRED(n) ( (n)->ln_Pred->ln_Pred ? (n)->ln_Pred : (struct Node *)NULL ) + + +#ifdef __GNUC__ + +#define REMHEAD(l) \ +({ \ + struct Node *n = (l)->lh_Head; \ + n->ln_Succ ? \ + (l)->lh_Head = n->ln_Succ, \ + (l)->lh_Head->ln_Pred = (struct Node *)(l), \ + n : \ + NULL; \ +}) + +#define REMTAIL(l) \ +({ \ + struct Node *n = (l)->lh_TailPred; \ + n->ln_Pred ? \ + (l)->lh_TailPred = n->ln_Pred, \ + (l)->lh_TailPred->ln_Succ = (struct Node *)(&((l)->lh_Tail)), \ + n : \ + NULL; \ +}) + + +#else + +/* These two can't be implemented as macros without the GCC ({...}) language extension */ + +INLINE struct Node *REMHEAD(struct List *l) +{ + struct Node *n = l->lh_Head; + + if (n->ln_Succ) + { + l->lh_Head = n->ln_Succ; + l->lh_Head->ln_Pred = (struct Node *)l; + return n; + } + return NULL; +} + +INLINE struct Node *REMTAIL(struct List *l) +{ + struct Node *n = l->lh_TailPred; + + if (n->ln_Pred) + { + l->lh_TailPred = n->ln_Pred; + l->lh_TailPred->ln_Succ = (struct Node *)(&(l->lh_Tail)); + return n; + } + return NULL; +} + +#endif + +#endif /* !LISTMACROS_H */ diff --git a/include/README b/include/README new file mode 100644 index 0000000..6e31866 --- /dev/null +++ b/include/README @@ -0,0 +1,45 @@ +Short: Boopsi, cross compiling and debug support macros +Author: bernie@cosmos.it (Bernardo Innocenti) +Uploader: bernie@cosmos.it (Bernardo Innocenti) +Type: dev/src +Version: 2.0 + + During the developement of my projects I've written some useful +macros that simplify some common problems. The macros have eventually +grown to full header files that I'm now using almost everywhere. + + I've packaged all these headers in a distribution archive, in the hope +that they will be useful to other programmers as well. + + + - CompilerSpecific.h + Defines wrappers for several compiler dependent constructs, + including function attributes and register specification for + function arguments. Supports SAS/C, gcc, EGCS, Storm C, Maxon C, + DICE and Aztec C. + + - BoopsiStubs.h + Using these inline versions of the amiga.lib boopsi support functions + results in faster and smaller code against their linked library + counterparts. When debug is active, these functions will also + validate the parameters you pass in. + + - BoopsiLib.h + Additional macros and inline functions for boopsi class developement. + + - DebugMacros.h + Some handy debug macros which are automatically excluded when the + DEBUG preprocessor symbol isn't defined. To make debug executables, + you must link with debug.lib or any linker module containing a + kprintf()-like function. + + - DiagnosticMacros.h + Some handy macros to dump some common system structs to the + debug console. Use DUMP_XXX(pointer) in your code to get a + detailed dump of the structure contents. + + - ListMacros.h + Some handy macros for list operations. Using these macros is faster + than calling their exec.library equivalents, but they will eventually + make your code a little bigger and are also subject to common macro + side effects. diff --git a/include/gadgets/FrPropGClass.h b/include/gadgets/FrPropGClass.h new file mode 100644 index 0000000..cc0e495 --- /dev/null +++ b/include/gadgets/FrPropGClass.h @@ -0,0 +1,47 @@ +#ifndef FRPROPGCLASS_H +#define FRPROPGCLASS_H +/* +** $Id: FrPropGClass.h,v 1.1 1999/02/07 14:24:42 bernie Exp $ +** +** Copyright (C) 1999 Bernardo Innocenti +** All rights reserved. +** +** A simple subclass of the propgclass which supports to be framed +** with any boopsi image. The frame must be specified specified +** through the GA_LabelImage tag because the GA_Image already has +** a special meaning for the propgclass. +** +** Unfortunately The original ROM class is not smart enough to do +** this simple job by itself. This new class overloads the GM_RENDER +** method to work around these problems. +*/ + + +#define FRPROPGCLASS "frpropgclass" +#define FRPROPGVERS 1 + + +/* Functions to initialize and destroy the class */ +Class *MakeFrPropGClass (void); +BOOL FreeFrPropGClass (Class *cl); + + + +/*****************/ +/* Class Methods */ +/*****************/ + +/* This class does not define any new methods */ + +/********************/ +/* Class Attributes */ +/********************/ + +/* #define FPGA_Dummy (TAG_USER | ('F'<<16) | ('P'<<8)) */ + +/* This class does not define any new attributes */ + + + + +#endif /* !FRPROPGCLASS_H */ diff --git a/include/gadgets/ListBoxClass.h b/include/gadgets/ListBoxClass.h new file mode 100644 index 0000000..7d08e37 --- /dev/null +++ b/include/gadgets/ListBoxClass.h @@ -0,0 +1,42 @@ +#ifndef LISTBOXCLASS_H +#define LISTBOXCLASS_H +/* +** ListBoxClass.h +** +** Copyright (C) 1997 by Bernardo Innocenti +** +** ListBox class built on top of the "groupgclass". +** +*/ + +#include + + +#define LISTBOXCLASS "listboxclass" +#define LISTBOXVERS 1 + + +/* Class initializer and terminator. Only avalable for the + * static linker object flavour. + */ +Class *MakeListBoxClass(void); +BOOL FreeListBoxClass(Class *ListViewClass); + + + +/*****************/ +/* Class Methods */ +/*****************/ + +/* This class does not define any new methods */ + +/********************/ +/* Class Attributes */ +/********************/ + +/* #define LBA_Dummy (TAG_USER | ('L'<<16) | ('B'<<8)) */ + +/* This class does not define any new attributes */ + + +#endif /* !LISTBOXCLASS_H */ diff --git a/include/gadgets/ListViewClass.h b/include/gadgets/ListViewClass.h new file mode 100644 index 0000000..45a0dba --- /dev/null +++ b/include/gadgets/ListViewClass.h @@ -0,0 +1,445 @@ +#ifndef LISTVIEWCLASS_H +#define LISTVIEWCLASS_H +/* +** $Id: ListViewClass.h,v 1.4 2000/01/12 21:18:06 bernie Exp $ +** +** Copyright (C) 1996,97,99 by Bernardo Innocenti +** +** ListView class built on top of the "gadgetclass". +** +*/ + +#define LISTVIEWCLASS "listviewclass" +#define LISTVIEWVERS 1 + + +Class *MakeListViewClass(void); +BOOL FreeListViewClass(Class *LVClass); + + + +/* + * New Methods + */ + +/* This class does not define any new methods */ + + +/* + * New Attributes + */ + +#define LVA_Dummy (TAG_USER | ('L'<<16) | ('V'<<8)) + +#define LVA_Selected (LVA_Dummy+1) + /* [IGSNU] (LONG) - Selected item number. ~0 (-1) indicates that no + * item is selected. + */ + +#define LVA_Top (LVA_Dummy+2) + /* [IGSNU] (LONG) - Number of top displayed item. Default is 0. + */ + +#define LVA_Total (LVA_Dummy+3) + /* [IGSN] (LONG) - Total number of items in list. + * This attribute can be set when LVA_StringArray, LVA_ImageArray + * or LVA_CustomList is used. If you pass -1 or omit this tag, + * the ListView class will count the items in the array until it + * finds a NULL entry. If you know the number of nodes in your list, + * you will save some internal overhead by telling it to the + * ListView with the LVA_Total tag, expecially when using the + * LVA_StringList and LVA_ImageList modes. You must set LVA_Total + * each time you provide a new list or array, and in the same + * OM_SET call. + * Be careful: no checks are made on the values you are passing! + */ + +#define LVA_SelectItem (LVA_Dummy+4) + /* [SN] (LONG) - Add item specified by ti_Data to the + * selection list. + */ + +#define LVA_DeselectItem (LVA_Dummy+5) + /* [SN] (LONG) - Remove item specified by ti_Data from the + * selection list. + */ + +#define LVA_ToggleItem (LVA_Dummy+6) + /* [SN] (LONG) - Toggle item selection. + */ + +#define LVA_ClearSelected (LVA_Dummy+7) + /* [SN] (LONG) - Remove the selected state to AALL items. + */ + + +#define LVA_MakeVisible (LVA_Dummy+8) + /* [ISU] (BOOL) - Make this item visible by doing the minimum required + * scrolling. + */ + +#define LVA_MoveUp (LVA_Dummy+9) +#define LVA_MoveDown (LVA_Dummy+10) +#define LVA_MoveLeft (LVA_Dummy+11) +#define LVA_MoveRight (LVA_Dummy+12) + /* [SU] - Scroll the display up/down. left/right movement is not + * yet supported. + */ + +#define LVA_StringList (LVA_Dummy+13) +#define LVA_StringArray (LVA_Dummy+14) +#define LVA_ImageList (LVA_Dummy+15) +#define LVA_ImageArray (LVA_Dummy+16) +#define LVA_CustomList (LVA_Dummy+17) +#define LVA_Labels LVA_StringList + /* [ISG] - List of items to display. All structures and strings + * are referenced, not copied, so they must stay in memory + * while the ListView gadget displays them. + * + * LVA_StringList (AKA LVA_Labels) passes a pointer to a + * List (or MinList) of Node structures. The strings + * pointed by ln_Name will be displayed as item labels. + * + * LVA_StringArray specifies a pointer to an array of STRPTR which + * will be used as item labels. The array must be NULL terminated + * unless the LVA_Count is set. + * + * LVA_ImageList passes a pointer to a List (or MinList) + * of Node structures. The ln_Name field of each Node structure + * must point to a normal Image structure or to an instance of + * the imageclass (or a subclass of it). + * + * LVA_ImageArray specifies a pointer to an array of pointers to + * Image structures or imageclass objects. The array must be NULL + * terminated unless the LVA_Count attribute is used. + * + * LVA_CustomList can be used to provide a data structure which + * is neither a list nor an array. Custom user functions will + * be called to retrieve the items. The data passed with this + * tag will be passed to the user functions. + * + * Setting one of these attributes to NULL causes the contents + * of the ListView gadget to be cleared. + * + * Setting one of these attributes to ~0 (-1) detaches the + * items from the ListView. You must detach your list before + * adding or removing items. This isn't required when using + * array oriented item lists. + */ + +#define LVA_Visible (LVA_Dummy+18) + /* [IGN] (ULONG) - Number of visible items. When this attribute is + * passed on intialization, the ListView gadget will resize + * itself to make the desired number of lines visible. this + * feature is incompatible with GA_RelHeight. LVA_Visible at + * creation time requires a valid DrawInfo passed with the + * GA_DrawInfo tag. + */ + +#define LVA_SelectedPtr (LVA_Dummy+19) + /* [GN] (APTR) - Selected item pointer or NULL when no + * items are selected. + */ + +#define LVA_SelectArray (LVA_Dummy+20) + /* [ISGNU] (ULONG *) - This array of ULONGs is only used in + * LVA_#?Array modes, when multiple selection is active. It will + * hold the selection status of all items in the list. Each + * element will be 0 if the related item is unselected, and + * it will indicate the selection order when the item is + * selected. + */ + +#define LVA_CallBack (LVA_Dummy+21) + /* [I] (struct Hook *) - Callback hook for various listview operations. + * The call back hook is called with: + * A0 - struct Hook * + * A1 - struct LVDrawMsg * + * A2 - struct Node * + * The callback hook *must* check the lvdm_MethodID field of the + * message and only do processing if it is known. If any other + * value is passed, the callback hook must return LVCB_UNKNOWN. + */ + +#define LVA_ShowSelected (LVA_Dummy+23) + /* [I] (BOOL) - Enable highlighting selected items (default is TRUE). + * Note that this is different from the GadTools ListView default, + * which is not displaying the selected item. + */ + +#define LVA_Clipped (LVA_Dummy+24) + /* [I] (BOOL) - When this attribute is set, the ListView gadget + * installs a ClipRegion in its Layer whenever it redraws its items. + * (defaults is FALSE). + */ + +#define LVA_DoMultiSelect (LVA_Dummy+25) + /* [I] (BOOL) - Allows picking multiple items from the list + * (default is FALSE). + * When MultiSelect mode is active and a List structure is used, + * the ListView gadget keeps track of which items are selected + * by setting/clearing the ln_Type field of the Node structure. + * When items are passed with an array, you must also provide + * a second array for storing selection information (LVA_SelectArray). + * When item number n is selected, then the n-th BOOL of this array + * is set with its selection order. + */ + +#define LVA_ItemHeight (LVA_Dummy+27) + /* [I] (ULONG) - Exact height of an item. Defaults to be the Y size + * of the font used to draw the text labels. The listview will ask + * the height to its Image items if not explicitly given. + */ + +#define LVA_MaxPen (LVA_Dummy+28) + /* [I] (LONG) - The maximum pen number used by rendering in a custom + * rendering callback hook. This is used to optimize the + * rendering and scrolling of the listview display (default is + * the maximum pen number used by all of TEXTPEN, BACKGROUNDPEN, + * FILLPEN, TEXTFILLPEN and BLOCKPEN). + */ + +#define LVA_TextFont (LVA_Dummy+29) + /* [I] (struct TextFont *) - Font to be used for rendering texts. + * Defaults to the default screen font. + */ + +#define LVA_DoubleClick (LVA_Dummy+30) + /* [N] (ULONG) - The item specified by ti_Data has been double clicked. + */ + +#define LVA_MaxSelect (LVA_Dummy+31) + /* [IS] (ULONG) - Maximum number of selected items to allow in multiselect + * mode. If you later set this tag with a more restrictive condition, the + * listview will NOT deselect any of the currently selected items to + * satisfy your request. Default is unlimited (~0). + */ + +#define LVA_PixelTop (LVA_Dummy+32) + /* [ISGNU] (ULONG) - Offset from top of list in pixel units. Useful for + * scrollers. + */ + +#define LVA_PixelHeight (LVA_Dummy+33) + /* [N] (LONG) - Total height of list in pixel units. Useful for scrollers. + */ + +#define LVA_PixelVVisible (LVA_Dummy+34) + /* [N] (LONG) - Number of vertical visible pixels. Useful for scrollers. + */ + +#define LVA_PixelLeft (LVA_Dummy+35) + /* [ISNU] (LONG) - Offset from left of list in pixel units. Useful for scrollers. + */ + +#define LVA_PixelWidth (LVA_Dummy+36) + /* [ISNG] (LONG) - Total width of list in pixel units. Useful for scrollers. + */ + +#define LVA_PixelHVisible (LVA_Dummy+37) + /* [N] (LONG) - Number of horizontal visible pixels. Useful for scrollers. + */ + +#define LVA_Title (LVA_Dummy+38) + /* [IS] - Listview title item. This item will be drawn on the top line of + * the list and will not scroll. ti_Data points to an item in the same + * format of the items list (e.g.: If it is LVA_StringArray, then it will + * be a Node * with ln_Name pointing to a text string. The item will be + * passed to the custom item drawing hook. (TODO) + */ + +#define LVA_Columns (LVA_Dummy+39) + /* [I] (LONG) - Number of columns to be displayed. Default is 1. If set + * to ~0, the listview will precheck all items to calculate this number + * automatically. (TODO) + */ + +#define LVA_ColumnSpacing (LVA_Dummy+40) + /* [I] (ULONG) - Spacing between columns in pixel units. + * Default is 4 pixels. (TODO) + */ + +#define LVA_ColumnWidths (LVA_Dummy+41) + /* [IGS] (ULONG *) - Points to an array of ULONGs containing the width of + * each column expressed in pixel units. A value of -1 causes the + * ListView to automatically calculate the width of the column, by + * asking the width to all items. (TODO) + */ + +#define LVA_ColumnSeparator (LVA_Dummy+42) + /* [I] (UBYTE) - When the listview is in multicolumn mode, the + * internal text label routines will scan the string for this + * character, as a separator for the column labels. This defaults + * to '\t', so a label for a three column list view would look + * like this: "One\tTwo\tThree". (TODO) + */ + +#define LVA_ResizeColumns (LVA_Dummy+43) + /* [IS] (BOOL) - Allows the user to resize the columns by dragging + * on the listview title line. (TODO) + */ + +#define LVA_SelectTick (LVA_Dummy+44) + /* [I] When user selects an item, show a checkmark on the left + * instead of rendering the item in selected state. (TODO) + */ + +#define LVA_ScrollInertia (LVA_Dummy+45) + /* [IS] (ULONG) - Sets the scrolling inertia of the listview. + * Defaults to 4 for LVA_Clipped mode, 0 for a non-clipped listview. + * (TODO) + */ + +#define LVA_ScrollRatio (LVA_Dummy+46) + /* [IS] (ULONG) - If you ask the listview to scroll more than + * LVA_Visible / LVA_ScrollRatio lines, all the listview contents + * will be redrawn instead. The minimum value of 1 will trigger a + * full redraw only when ALL the listview visible part is scrolled away. + * The default value is 2, which is a good compromise for items which + * can redraw themselves relatively quickly, such as simple text + * labels or bitmap images. + */ + +/* Public flags */ +#define LVB_READONLY 0 /* Do not allow item selection */ +#define LVB_CLIPPED 1 /* Clip item drawing inside their boxes */ +#define LVB_SHOWSELECTED 2 /* Hilights the selected item */ +#define LVB_DOMULTISELECT 3 /* Allows user to pick more than one item */ +#define LVB_SMOOTHSCROLLING 4 /* Scoll pixel by pixel */ +#define LVB_RESIZECOLUMNS 5 /* Allow user to resize the columns */ + +/* Internal flags - DO NOT USE */ +#define LVB_CLOSEFONT 27 /* Close the font when disposing the object */ +#define LVB_LIST 28 /* Using an exec List */ +#define LVB_DONTDRAW 29 /* Do not perform any drawing operations */ +#define LVB_SCROLLING 30 /* User scrolling with middle mouse button */ +#define LVB_DRAGGING 31 /* User dragging selection with LMB */ + + +#define LVF_READONLY (1<. + */ +#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 will be included too */ + +#ifdef LV_GADTOOLS_STUFF + +/* The different types of messages that a listview callback hook can see */ +#define LV_DRAW 0x202L /* draw yourself, with state */ + +/* Possible return values from a callback hook */ +#define LVCB_OK 0 /* callback understands this message type */ +#define LVCB_UNKNOWN 1 /* callback does not understand this message */ + +/* states for LVDrawMsg.lvdm_State */ +#define LVR_NORMAL 0 /* the usual */ +#define LVR_SELECTED 1 /* for selected gadgets */ +#define LVR_NORMALDISABLED 2 /* for disabled gadgets */ +#define LVR_SELECTEDDISABLED 8 /* disabled and selected */ + +#endif /* LV_GADTOOLS_STUFF */ + +#define LVR_TITLE 16 /* ListView title item */ + + +/* More callback hook methods */ + +#define LV_GETNEXT 0x203L /* gimme next item in list */ +#define LV_GETPREV 0x204L /* gimme previous item in list */ +#define LV_GETITEM 0x205L /* gimme item handle by number */ + +/* These two methods can be used to optimize listview rendering + * operations. You can safely assume that the rastport attributes + * you set inside LV_DRAWBEGIN will remain unchanged for all + * subsequent calls to LV_DRAW, until an LV_DRAWEND is issued. + * They do also provide a way to lock/unlock the list of items + * if the access to its item needs to be arbitrated by a semaphore. + */ +#define LV_DRAWBEGIN 0x206L /* prepare to draw items */ +#define LV_DRAWEND 0x207L /* items drawing completed */ + + + +/* More messages */ + +struct lvDrawItem +{ + ULONG lvdi_MethodID; /* LV_DRAW */ + LONG lvdi_Current; /* Current item number */ + APTR lvdi_Items; /* Pointer to List, array, etc. */ + struct RastPort *lvdi_RastPort; /* where to render to */ + struct DrawInfo *lvdi_DrawInfo; /* useful to have around */ + struct Rectangle lvdi_Bounds; /* limits of where to render */ + ULONG lvdi_State; /* how to render */ + ULONG lvdi_Flags; /* Current LVF_#? flags */ +}; + +struct lvGetItem +{ + ULONG lvgi_MethodID; /* LV_GETITEM */ + ULONG lvgi_Number; /* Number of item to get */ + APTR lvgi_Items; /* Pointer to List, array, etc. */ +}; + +#define lvGetNext lvGetItem +#define lvGetPrev lvGetItem +#define lvDrawBegin lvGetItem /* lvgi_Number has no useful meaning */ +#define lvDrawEnd lvGetItem /* lvgi_Number has no useful meaning */ + +#endif /* !LISTVIEWCLASS_H */ diff --git a/include/gadgets/PIPClass.h b/include/gadgets/PIPClass.h new file mode 100644 index 0000000..dea71c0 --- /dev/null +++ b/include/gadgets/PIPClass.h @@ -0,0 +1,74 @@ +#ifndef PIPCLASS_H +#define PIPCLASS_H +/* +** PIPClass.h +** +** Copyright (C) 1996,97 by Bernardo Innocenti +** +** 'Picture In Picture' class built on top of the "gadgetclass". +** +*/ + +#define PIPCLASS "pipclass" +#define PIPVERS 1 + + +Class *MakePIPClass (void); +void FreePIPClass (Class *PIPClass); + + + +/********************/ +/* Class Attributes */ +/********************/ + +#define PIP_Dummy (TAG_USER | ('P'<<16) | ('I'<< 8)) + +#define PIPA_Screen (PIP_Dummy+1) + /* (IGS) Screen to capture data from + */ + +#define PIPA_BitMap (PIP_Dummy+2) + /* (IGS) BitMap to capture data from + */ + +#define PIPA_OffX (PIP_Dummy+3) +#define PIPA_OffY (PIP_Dummy+4) + /* (IGSNU) Offsett of the PIP view + */ + +#define PIPA_Width (PIP_Dummy+5) +#define PIPA_Height (PIP_Dummy+6) + /* (GN) Dimensions of the bitmap being captured. + */ + +#define PIPA_DisplayWidth (PIP_Dummy+7) +#define PIPA_DisplayHeight (PIP_Dummy+8) + /* (GN) Dimensions of the PIP display. + */ + +#define PIPA_MoveUp (PIP_Dummy+9) +#define PIPA_MoveDown (PIP_Dummy+10) +#define PIPA_MoveLeft (PIP_Dummy+11) +#define PIPA_MoveRight (PIP_Dummy+12) + /* (S) Scroll the display towads a direction + */ + + +/*****************/ +/* Class Methods */ +/*****************/ + +#define PIPM_REFRESH (PIP_Dummy+1) +/* + * Tell the object to update its imagery to reflect any changes + * in the attached Screen or BitMap. + */ + +struct pippRefresh +{ + ULONG MethodID; + struct GadgetInfo *pipp_GInfo; +}; + +#endif /* !PIPCLASS_H */ diff --git a/include/gadgets/ResizeGClass.h b/include/gadgets/ResizeGClass.h new file mode 100644 index 0000000..ae2d687 --- /dev/null +++ b/include/gadgets/ResizeGClass.h @@ -0,0 +1,43 @@ +#ifndef RESIZEGCLASS_H +#define RESIZEGCLASS_H +/* +** $VER: ResizeGClass 0.1 (22.1.99) +** +** +** ResizeGClass - (c) 1999 Matteo Cavalleri +** +** +** Please read the documentation for +** usage and license of this source. +*/ + +/* /// "Global" */ + +/* to debug a boopsi class it's best to compile it as a */ +/* linked library, since this avoid a lot of troubles */ +#ifdef DEBUG + #define PRIVATE_RESIZEGCLASS +#endif + +/* attributes for this class */ +#define RSA_Dummy (TAG_USER + 0x60100) +#define RSA_LabelDisplay (RSA_Dummy + 1) + +/* this should never be used by the application */ +#define RSA_EditMode (RSA_Dummy + 99) + +#ifndef PRIVATE_RESIZEGCLASS + #define RESIZEGCLASS "resizegclass" + #ifndef CLASSLIBRARY_H + #include "common/ClassLibrary.h" + #endif +#else + Class *makeResizeGClass(void); + + #define freeResizeGClass(cl) FreeClass(cl) +#endif + +/* /// */ + +#endif + diff --git a/include/gadgets/ScrollButtonClass.h b/include/gadgets/ScrollButtonClass.h new file mode 100644 index 0000000..f5460cb --- /dev/null +++ b/include/gadgets/ScrollButtonClass.h @@ -0,0 +1,59 @@ +#ifndef SCROLLBUTTONCLASS_H +#define SCROLLBUTTONCLASS_H +/* +** $Id: ScrollButtonClass.h,v 1.2 1999/01/30 13:23:12 bernie Exp $ +** +** Copyright (C) 1996,99 Bernardo Innocenti +** +** This code is inspierd from ScrollerWindow 0.3 +** Copyright © 1994 Christoph Feck, TowerSystems. +** +** Use 4 chars wide TABs to read this file +** +** The ROM buttongclass has two problems which make it not quite usable +** for scroll arrows. The first problem is the missing delay. Once the next +** INTUITICK gets sent by input.device, the ROM class already sends a +** notification. The other problem is that it also notifies us, when the +** button finally gets released (which is necessary for command buttons). +** +** We define two new classes with the GM_GOACTIVE and GM_HANDLEINPUT methods +** overloaded to work around these problems. The ScrollButtonClass is a +** subclass of the buttongclass, suitable for use in the borders of a window. +** The FrScrollButtonClass is instead a subclass of the FrButtonGClass. Both +** classes share the same dispatcher: the only difference is the superclass +** passed at CreateClass() time. +*/ + + +#define SCROLLBUTTONCLASS "scrollbuttonclass" +#define SCROLLBUTTONVERS 1 + + +/* Functions to initialize and destroy the classes */ + +Class *MakeScrollButtonClass (void); +Class *MakeFrScrollButtonClass (void); +BOOL FreeScrollButtonClass (Class *cl); + +#define FreeFrScrollButtonClass FreeScrollButtonClass + + + +/*****************/ +/* Class Methods */ +/*****************/ + +/* This class does not define any new methods */ + +/********************/ +/* Class Attributes */ +/********************/ + +/* #define SBA_Dummy (TAG_USER | ('S'<<16) | ('B'<<8)) */ + +/* This class does not define any new attributes */ + + + + +#endif /* !SCROLLBUTTONCLASS_H */ diff --git a/include/gadgets/SliderBarGClass.h b/include/gadgets/SliderBarGClass.h new file mode 100644 index 0000000..3b616a4 --- /dev/null +++ b/include/gadgets/SliderBarGClass.h @@ -0,0 +1,94 @@ +/* +** $Id: SliderBarGClass.h,v 1.1 1999/02/07 14:24:43 bernie Exp $ +** +** Copyright (C) 1999 Bernardo Innocenti +** All rights reserved. +** +** "sliderbargclass", a compound gadget which implements +** the GadTools SLIDER_KIND in a boopsi fashon. This class +** is derived from the groupgclass but from the outside it +** can be manipulated as it were a normal propgclass boopsi +** gadget. The slider bar gadget frames all its childs +** automatically so it doesn't need an additional frame. +** +** The up/down and left/right buttons are built using the +** ScrollButton class using the glyphs provided by the +** vectorglyph class. +*/ + +#define SLIDERBARGCLASS "sliderbargclass" +#define SLIDERBARVERS 1 + + +/* Class initializer and terminator. Only avalable when + * the class is compiled in the static linker object flavour. + */ +Class *MakeSliderBarGClass (void); +BOOL FreeSliderBarGClass (Class *ListViewClass); + + +/* + * New Methods: + * + * This class does not define any new methods + */ + + +/* + * New Attributes: + * + */ +#define SBA_Dummy (TAG_USER | ('S'<<16) | ('B'<<8)) + +#define SBA_Adjust (SBA_Dummy + 1) + /* [SU] (LONG) - Add the specified SIGNED quantity to the PGA_Top + * attribute. The result is clipped to valid values. This attribute + * is used internally by the class to handle the scroll buttons. + */ + +#define SBA_InternalTop (SBA_Dummy + 2) + /* [U] (ULONG) - PRIVATE: DO NOTO USE. Used by internal + * notification to synchronize the local copy of the Top + * attribute with the embedded Prop gadget. + */ + +/* + * Changed attributes: + * + * LAYOUTA_Orientation + * [I] (ULONG) - Pass one of the LORIENT_#? modes. + * Defaults to LORIENT_HORIZ. + * + * PGA_Top + * PGA_Total + * PGA_Visible + * [ISGNU] (LONG) - These attributes are supported exactly as if + * they were inherited from the propgclass. + * + */ + +/* FIX: Define the attributes that not present + * before V42 of . + */ +#ifndef LAYOUTA_Dummy + #define LAYOUTA_Dummy (TAG_USER+0x38000) + #define LAYOUTA_Orientation (LAYOUTA_Dummy+0x0003) + #define LORIENT_NONE 0 + #define LORIENT_HORIZ 1 + #define LORIENT_VERT 2 +#endif + + +/* + * Changed methods: + * + * OM_SET + * OM_UPDATE + * The class will intercept GA_Top, GA_Left, GA_Width and GA_Height + * and adjust its childs accordingly. The PGA_#? attributes + * are forwarded to the embedded prop gadget. + * + * GM_LAYOUT + * The class will adjust the position and size of all its children + * and forward the GM_LAYOUT method to them. + */ diff --git a/include/gadgets/SmartGroupGClass.h b/include/gadgets/SmartGroupGClass.h new file mode 100644 index 0000000..fe952b5 --- /dev/null +++ b/include/gadgets/SmartGroupGClass.h @@ -0,0 +1,106 @@ +/* +** $Id: SmartGroupGClass.h,v 1.1 1999/02/07 14:24:44 bernie Exp $ +** +** Copyright (C) 1999 Bernardo Innocenti +** All rights reserved. +** +** "smartgroupgclass", a class similar to the groupgclass +** that allows attaching any number of child gadgets that +** will behave like a single gadget. Input processing and +** rendering are deferred to the children as appropriate. +** +** The original ROM class is not very usable because it has +** a lot of bugs and limitations: +** +** - Doesn't forward GM_LAYOUT to its children +** - Does not work when GA_RelRight or GA_RelBottom are set +** - Ignores GA_(Rel)Width and GA_(Rel)Height on creation +** and recalculates its size when new children are attached. +** - Can not layout its children automatically +** +** The smartgroupgclass provides the custom creation-time +** attribute SGA_Child, which allows to attach child gadgets +** to it in a single call to NewObject() instead of calling +** OM_ADDMEMBER several times later. This enables the user +** to create a whole GUI with a single C statement like this: +** +** if (glist = NewObject(NULL, SMARTGROUPGCLASS, +** LAYOUTA_Orientation, LORIENT_VERT, +** SGA_Child, NewObject(NULL SMARTGROUPGCLASS, +** LAYOUTA_Orientation, LORIENT_HORIZ, +** SGA_Child, NewObject(...), +** SGA_Child, NewObject(...), +** TAG_DONE), +** SGA_Child, NewObject(...), +** TAG_DONE)) +** { +** /* ... use your glist here... */ +** DeleteObject (glist); +** } +** else +** printf ("Failed to create the application!\n"); +*/ + +#define SMARTGROUPGCLASS "smartgroupgclass" +#define SMARTGROUPVERS 1 + + +/* Class initializer and terminator. Only avalable when + * the class is compiled in the static linker object flavour. + */ +Class *MakeSmartGroupGClass (void); +BOOL FreeSmartGroupGClass (Class *class); + + +/* + * New Methods: + * + * This class does not define any new methods + */ + + +/* + * New Attributes: + * + */ +#define SGA_Dummy (TAG_USER | ('S'<<16) | ('G'<<8)) + +#define SGA_Child (SGA_Dummy + 1) + /* [I] (struct Gadget *) - Attach the specified child to + * the group at creation time. If the argument is NULL, + * the group will be disposed and OM_NEW will also + * return NULL. This makes it easy to create a whole user + * interface by nesting several calls to NewObject() and + * testing the result of the higher level group only. + */ + +/* + * Changed attributes: + * + * LAYOUTA_Orientation + * [I] (ULONG) - Pass one of the LORIENT_#? modes. + * Defaults to LORIENT_HORIZ. + * + */ + +/* FIX: Define the attributes that not present + * before V42 of . + */ +#ifndef LAYOUTA_Dummy + #define LAYOUTA_Dummy (TAG_USER+0x38000) + #define LAYOUTA_Orientation (LAYOUTA_Dummy+0x0003) + #define LORIENT_NONE 0 + #define LORIENT_HORIZ 1 + #define LORIENT_VERT 2 +#endif + + +/* + * Changed methods: + * + * The class redefines all the GM_#? methods and defers processing + * to its children in a way that makes the group behave as it was + * a single gadget. The children may still choose to send + * notification directly to the application or to gadgets attached + * to other groups. + */ diff --git a/include/images/CVS/Entries b/include/images/CVS/Entries new file mode 100644 index 0000000..ba5058b --- /dev/null +++ b/include/images/CVS/Entries @@ -0,0 +1,4 @@ +/ExtFrameIClass.h/1.1/Sun Aug 22 20:31:25 1999// +/LabelTextIClass.h/1.1/Tue Apr 13 18:48:07 1999// +/VectorGlyphIClass.h/1.1/Sat Apr 10 19:17:41 1999// +D diff --git a/include/images/CVS/Repository b/include/images/CVS/Repository new file mode 100644 index 0000000..7a99062 --- /dev/null +++ b/include/images/CVS/Repository @@ -0,0 +1 @@ +OpenBoopsi/include/images diff --git a/include/images/CVS/Root b/include/images/CVS/Root new file mode 100644 index 0000000..62ab471 --- /dev/null +++ b/include/images/CVS/Root @@ -0,0 +1 @@ +:pserver:bernie@sunsite:/usr/local/cvsroot diff --git a/include/images/ExtFrameIClass.h b/include/images/ExtFrameIClass.h new file mode 100644 index 0000000..c16f0b1 --- /dev/null +++ b/include/images/ExtFrameIClass.h @@ -0,0 +1,62 @@ +#ifndef EXTFRAMEICLASS_H +#define EXTFRAMEICLASS_H +/* +** ExtFrameIClass - (c) 1999 Matteo Cavalleri +** +** +** Please read the documentation for +** usage and license of this source. +*/ + +/* /// "Global" */ + +/* supported frame types */ + +/* these are the same as defined in imageclass.h +** +** #define FRAME_DEFAULT 0 +** #define FRAME_BUTTON 1 +** #define FRAME_RIDGE 2 +** #define FRAME_ICONDROPBOX 3 +** +** these are new frame types +*/ +#define FRAME_FLAT 4 +#define FRAME_XEN 5 +#define FRAME_BUTTON2 6 +#define FRAME_RIDGE2 7 + +/* maximum number of frames defined, never to +** be used outside the class (it must be equal +** to the last defined frame, not bigger) +*/ +#define EXTFRAME_MAXFRAME 7 + +/* attributes for this class */ +#define IA_FrameDistance (IA_Dummy + 0x53) +#define IA_InnerDistance (IA_Dummy + 0x54) +#define IA_PenBackground (IA_Dummy + 0x55) +#define IA_PenSelBackground (IA_Dummy + 0x56) +#define IA_PenShine (IA_Dummy + 0x57) +#define IA_PenShadow (IA_Dummy + 0x58) +#define IA_PenHalfShine (IA_Dummy + 0x59) +#define IA_PenHalfShadow (IA_Dummy + 0x5a) + +/* flags for IM_FRAMEBOX method +** +** #define FRAMEF_SPECIFY (1 << 0) +*/ +#define FRAMEF_QUERY (1 << 1) + +#ifndef PRIVATE_EXTFRAMEICLASS + #define EXTFRAMEICLASS "extframeiclass" +#else + Class *makeExtFrameIClass(void); + + #define freeExtFrameIClass(cl) FreeClass(cl) +#endif + +/* /// */ + +#endif + diff --git a/include/images/LabelTextIClass.h b/include/images/LabelTextIClass.h new file mode 100644 index 0000000..93ee313 --- /dev/null +++ b/include/images/LabelTextIClass.h @@ -0,0 +1,77 @@ +#ifndef LABELTEXTICLASS_H +#define LABELTEXTICLASS_H +/* +** LabelTextIClass - (c) 1999 Matteo Cavalleri +** +** +** Please read the documentation for +** usage and license of this source. +*/ + +/* /// "Global" */ + +/* label types */ +#define LTA_TYPE_NORMAL 0 /* simple text with the shadow pen */ +#define LTA_TYPE_HILIGHT 1 /* simple text with the shine pen */ +#define LTA_TYPE_3D 2 /* 3d text with shadow and shine pen */ + +/* maximum number of renderings defined, never to +** be used outside the class (it must be equal +** to the last defined value, not bigger) +*/ +#define LABELTEXT_MAXTYPE 2 + +/* label positions */ +#define LTA_POSITION_INSIDE 0 +#define LTA_POSITION_ABOVE 1 +#define LTA_POSITION_BELOW 2 +#define LTA_POSITION_LEFT 3 +#define LTA_POSITION_RIGHT 4 + +/* maximum number of position defined, never to +** be used outside the class (it must be equal +** to the last defined value, not bigger) +*/ +#define LABELTEXT_MAXPOS 4 + +/* label alignment */ +#define LTA_ALIGN_CENTER 0 +#define LTA_ALIGN_TOP 1 +#define LTA_ALIGN_BOTTOM 2 +#define LTA_ALIGN_LEFT 3 +#define LTA_ALIGN_RIGHT 4 + +/* maximum number of position defined, never to +** be used outside the class (it must be equal +** to the last defined value, not bigger) +*/ +#define LABELTEXT_MAXALIGN 4 + +/* attributes for this class */ +#define LTA_Label (IA_Dummy + 0x71) +#define LTA_LabelType (IA_Dummy + 0x72) +#define LTA_Distance (IA_Dummy + 0x73) +#define LTA_Position (IA_Dummy + 0x74) +#define LTA_Align (IA_Dummy + 0x75) +#define LTA_Font (IA_Dummy + 0x76) +#define LTA_PenBackground (IA_Dummy + 0x77) +#define LTA_PenShine (IA_Dummy + 0x78) +#define LTA_PenShadow (IA_Dummy + 0x79) +#define LTA_PenHalfShine (IA_Dummy + 0x7a) +#define LTA_PenHalfShadow (IA_Dummy + 0x7b) + +#ifndef PRIVATE_LABELTEXTICLASS + #define LABELTEXTICLASS "labeltexticlass" + #ifndef CLASSLIBRARY_H + #include "common/ClassLibrary.h" + #endif +#else + Class *makeLabelTextIClass(void); + + #define freeLabelTextIClass(cl) FreeClass(cl) +#endif + +/* /// */ + +#endif + diff --git a/include/images/VectorGlyphIClass.h b/include/images/VectorGlyphIClass.h new file mode 100644 index 0000000..79544f7 --- /dev/null +++ b/include/images/VectorGlyphIClass.h @@ -0,0 +1,29 @@ +/* +** VectorGlyphIClass.h +** +** Copyright (C) 1995,96,97,98 by Bernardo Innocenti +** +** "vectorglyphiclass" class, a vector image class built +** on top of the "imageclass", providing some useful +** glyphs for buttons. +*/ + +#define VECTORGLYPHCLASS "vectorglyphiclass" + +Class *MakeVectorGlyphIClass(void); +BOOL FreeVectorGlyphIClass(Class *class); + +/* Values for the SYSIA_Which attribute */ +#define VG_PLAY 0 +#define VG_STOP 1 +#define VG_REW 2 +#define VG_FWD 3 +#define VG_PICK 4 +#define VG_UPARROW 5 +#define VG_DOWNARROW 6 +#define VG_LEFTARROW 7 +#define VG_RIGHTARROW 8 + + +/* Number of glyphs offered by the vectorglyph.image class */ +#define VG_IMGCOUNT 9