From 1226995c5ff87cf6ce4b61c085fa7993f5db96ca Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Fri, 11 Mar 2011 01:13:43 -0500 Subject: [PATCH 1/1] Initial commit --- .gitignore | 2 + BUGS | 38 + ChangeLog | 0 GUIDELINES | 129 + INSTALL | 15 + LICENSE | 482 ++ Makefile | 20 + README | 82 + STYLE | 185 + TODO | 0 classes/ExtRequesterClass/Makefile | 23 + classes/Makefile | 9 + common/ClassLib.s | 298 ++ common/GetGadgetBox.c | 88 + common/Makefile | 90 + common/OpenClass.c | 44 + common/general.mk | 277 ++ common/gst.c | 52 + common/startup_gcc.s | 2 + common/startup_sc.s | 9 + common/startup_storm.s | 9 + config.mk | 214 + docs/ExtFrameIClass.doc | 96 + docs/Intuition | 523 +++ docs/LabelTextIClass.doc | 181 + docs/NoteBOOPSI | 149 + docs/empty_Makefile | 96 + docs/empty_config.mk | 137 + gadgets/ClockGClass/Makefile | 27 + gadgets/LauncherGClass/Makefile | 28 + gadgets/ListBox/ListBoxClass.c | 547 +++ gadgets/ListBox/Makefile | 29 + gadgets/ListView/BoopsiLV.readme | 81 + gadgets/ListView/LVDemo.c | 1004 ++++ gadgets/ListView/ListViewClass.c | 2238 +++++++++ .../ListView/ListViewClass_static.newinline.s | 4072 ++++++++++++++++ .../ListView/ListViewClass_static.oldinline.s | 4136 +++++++++++++++++ gadgets/ListView/ListViewHooks.c | 276 ++ gadgets/ListView/Makefile | 30 + gadgets/Makefile | 11 + gadgets/MeterGClass/Makefile | 27 + gadgets/PIPWin/GNUmakefile.nothanks | 58 + gadgets/PIPWin/Makefile | 27 + gadgets/PIPWin/PIPClass.c | 677 +++ gadgets/PIPWin/PIPClass.h | 74 + gadgets/PIPWin/PIPWin.c | 1015 ++++ gadgets/PIPWin/PIPWin.mdbi | Bin 0 -> 152 bytes gadgets/PIPWin/PIPWin.project | 39 + gadgets/PIPWin/PIPWin.readme | 37 + gadgets/PIPWin/PIPWin.sas | Bin 0 -> 7216 bytes gadgets/PIPWin/SMakefile | 95 + gadgets/ResizeGClass/Makefile | 27 + gadgets/ResizeGClass/config.mk | 28 + gadgets/ScrollButton/Makefile | 28 + gadgets/ScrollButton/ScrollButtonClass.c | 387 ++ gadgets/SliderBar/FrPropGClass.c | 175 + gadgets/SliderBar/Makefile | 26 + gadgets/SliderBar/SliderBarDemo.c | 378 ++ gadgets/SliderBar/SliderBarGClass.c | 773 +++ gadgets/SmartGroup/Makefile | 26 + gadgets/SmartGroup/SmartGroupGClass.c | 694 +++ gadgets/ToolManagerGClass/Makefile | 27 + include/BoopsiLib.h | 92 + include/BoopsiStubs.h | 243 + include/CompilerSpecific.h | 315 ++ include/DebugMacros.h | 147 + include/DiagnosticMacros.h | 146 + include/ListMacros.h | 99 + include/README | 45 + include/gadgets/FrPropGClass.h | 47 + include/gadgets/ListBoxClass.h | 42 + include/gadgets/ListViewClass.h | 445 ++ include/gadgets/PIPClass.h | 74 + include/gadgets/ResizeGClass.h | 43 + include/gadgets/ScrollButtonClass.h | 59 + include/gadgets/SliderBarGClass.h | 94 + include/gadgets/SmartGroupGClass.h | 106 + include/images/CVS/Entries | 4 + include/images/CVS/Repository | 1 + include/images/CVS/Root | 1 + include/images/ExtFrameIClass.h | 62 + include/images/LabelTextIClass.h | 77 + include/images/VectorGlyphIClass.h | 29 + 83 files changed, 22518 insertions(+) create mode 100644 .gitignore create mode 100755 BUGS create mode 100755 ChangeLog create mode 100644 GUIDELINES create mode 100644 INSTALL create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README create mode 100644 STYLE create mode 100755 TODO create mode 100644 classes/ExtRequesterClass/Makefile create mode 100644 classes/Makefile create mode 100755 common/ClassLib.s create mode 100644 common/GetGadgetBox.c create mode 100644 common/Makefile create mode 100644 common/OpenClass.c create mode 100644 common/general.mk create mode 100644 common/gst.c create mode 100644 common/startup_gcc.s create mode 100644 common/startup_sc.s create mode 100644 common/startup_storm.s create mode 100644 config.mk create mode 100644 docs/ExtFrameIClass.doc create mode 100644 docs/Intuition create mode 100755 docs/LabelTextIClass.doc create mode 100644 docs/NoteBOOPSI create mode 100644 docs/empty_Makefile create mode 100644 docs/empty_config.mk create mode 100644 gadgets/ClockGClass/Makefile create mode 100644 gadgets/LauncherGClass/Makefile create mode 100644 gadgets/ListBox/ListBoxClass.c create mode 100644 gadgets/ListBox/Makefile create mode 100644 gadgets/ListView/BoopsiLV.readme create mode 100644 gadgets/ListView/LVDemo.c create mode 100644 gadgets/ListView/ListViewClass.c create mode 100644 gadgets/ListView/ListViewClass_static.newinline.s create mode 100644 gadgets/ListView/ListViewClass_static.oldinline.s create mode 100644 gadgets/ListView/ListViewHooks.c create mode 100644 gadgets/ListView/Makefile create mode 100644 gadgets/Makefile create mode 100644 gadgets/MeterGClass/Makefile create mode 100644 gadgets/PIPWin/GNUmakefile.nothanks create mode 100644 gadgets/PIPWin/Makefile create mode 100644 gadgets/PIPWin/PIPClass.c create mode 100644 gadgets/PIPWin/PIPClass.h create mode 100644 gadgets/PIPWin/PIPWin.c create mode 100755 gadgets/PIPWin/PIPWin.mdbi create mode 100755 gadgets/PIPWin/PIPWin.project create mode 100644 gadgets/PIPWin/PIPWin.readme create mode 100755 gadgets/PIPWin/PIPWin.sas create mode 100644 gadgets/PIPWin/SMakefile create mode 100644 gadgets/ResizeGClass/Makefile create mode 100644 gadgets/ResizeGClass/config.mk create mode 100644 gadgets/ScrollButton/Makefile create mode 100644 gadgets/ScrollButton/ScrollButtonClass.c create mode 100644 gadgets/SliderBar/FrPropGClass.c create mode 100644 gadgets/SliderBar/Makefile create mode 100644 gadgets/SliderBar/SliderBarDemo.c create mode 100644 gadgets/SliderBar/SliderBarGClass.c create mode 100644 gadgets/SmartGroup/Makefile create mode 100644 gadgets/SmartGroup/SmartGroupGClass.c create mode 100644 gadgets/ToolManagerGClass/Makefile create mode 100644 include/BoopsiLib.h create mode 100644 include/BoopsiStubs.h create mode 100644 include/CompilerSpecific.h create mode 100644 include/DebugMacros.h create mode 100644 include/DiagnosticMacros.h create mode 100644 include/ListMacros.h create mode 100644 include/README create mode 100644 include/gadgets/FrPropGClass.h create mode 100644 include/gadgets/ListBoxClass.h create mode 100644 include/gadgets/ListViewClass.h create mode 100644 include/gadgets/PIPClass.h create mode 100644 include/gadgets/ResizeGClass.h create mode 100644 include/gadgets/ScrollButtonClass.h create mode 100644 include/gadgets/SliderBarGClass.h create mode 100644 include/gadgets/SmartGroupGClass.h create mode 100644 include/images/CVS/Entries create mode 100644 include/images/CVS/Repository create mode 100644 include/images/CVS/Root create mode 100644 include/images/ExtFrameIClass.h create mode 100644 include/images/LabelTextIClass.h create mode 100644 include/images/VectorGlyphIClass.h 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 0000000000000000000000000000000000000000..02ebb320a197704ecbc849400b32947d18c89a07 GIT binary patch literal 152 zcmZ?s5AtPTV3^?R;^Y||666kK`!WbHu=plclYU#>j!uSglFdIGeBs)WCn)dAm?D9seBBK p3|tIC48jZyvgQl|0sg^$Kv9NZXa4{oB>1_m?T8vq5RAS(a> literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..258aabde89c11a6607d104d3a36a188efd132a42 GIT binary patch literal 7216 zcmbtZeQaCTbw7`MqMqm{nbQw&`BWgx#ymH?m6e4bMCp9MDG72`_JvPF0}Y~ZlY}>a{q?=$^Yij zJ?^>rgJl{u?mWM>`<{Ag+g%#%1O00c{5QJq(s-TtHq=>hk<)J|Ez=Q1ZD_a_xcs^8a+$_ z1@tY+^UJ>mw?T}q_v@53+qCY2SMy=4GkN~uXu;b?Ejh{p&ikJ^ZE2D}O49Ma{cB*OWlTFTe*uZcux1RfrN#0g^b5flFa|Iqkg?g{ zpO*@hJpZ64L1X0Y8Kyt*L#r-~x9Q$t`V%&mY13C{@%d8mRQ0v)$XsPJdrxy zYLK#Vr?pk9HL2!{9d{|Oz2tu>{1S8-4diINAmt;vK^@vlMz@}%Er5IUK8mvZ(5)-T z+(?OOJ9!mI;@S`+6&SyksKCg;xC-@pH=QV~!S_jMA>`6xkSZC7VV0tM<3G|#k6JEj zH0H=9pjy^pO`LfJc7gWwU3aO$(ITkr#NMCKc!ry;Bl;&rU$*=BK6Z?bQvYXG{9i98 z&W#=I{>)k@R`S{_>5*}JO|g>q#{XK$GL3DR{maXknf~Z9v>);tT8@Ua6w^Lhy-YRo z(PdkPN?MjD{l?Joy!=z^06ol?_Q#vI?R5Y3z&=tsNC|`Am|RlokZxGvEJ(sTQP*lh|juAgQqe z`5~`1AtVh!(v7yHEYtOOtucH?h9Dcu`ocnj7^Na{9cGe1IkOxqy=eRMxUYMU9W?Tjgl!7T)C+oP9#yub1ce;5+w}&sXez zR%qT}lKTc?{^ZQsy!+xp`u#TPl)LARTNdErjC_{kKGL{}0%xi3gVPIP$+nWI=A{e5 zMtRsMPvCH3>0RrU22i5iYwKD)-M9Ei+c&QWSYoM`*a~iF%-(71>l&OF@CuE41dhJu z=;+ZsOheVWunz22E&4L7*&ra++4ck9wtLkNo}h7~Nv@As_A?Ut^iy%jK-}L|&d>t>lHQ)=C`dkVc!L zu%AzmIi_iuB40+)`iH5?|NUR^=_d^eYE|0_`c$99lH2s>uJVjLCElYB)1z&chN%N^ z)KvToM>A^uH>DAhsk!e`dLAQNOeMf0TQc4b9#Kg(7F%2x>2XGS$|H5gA|z9{hDhBK zqB`U6jStjm+CUAX9-JqxjNE>dke!WJUB8B0L^(Y~>jgBeCG;8ry{6ZSHmgTbC%q=% zDPzvXnS*GOBT+!7%FwH@3;R3K5s@c|W<{PLngLBrj2tRM1>vbg-__YKi4Kb>COROZ zm}pek>4&h=$)IJ*f&NT{E$hDW<`w@G$!tm3eOdI>QqSKHD436+ifB7`HJBqq^I{j` zS{i5G9@KE;+emArOL_8bh7Du1cJooHp{5xeZj{>4OIi!gf(_d#z#o0!f!Nxj1ibHSSPEoPOAIZIXQc^tr1nV-UWwd>uL| z1GiPO*XC6pt;nlAF71_hvpv(KZK4JlhH}xEv$CJ-BbMm6me!!3(>ux4*x0oMYE+XR zCgSgr#UuWHP-@~ksHIsNSm|%I#4x#LV8uz|>W1x!^MxTl*IJG(wX7woCE$+%?seLP z(>;&1<39;+Od0B(D z3T-voYP4_zA_p&S9>B{^-{a6JkI~8Y9P)v-rULd>z-uaCm0|uH%^hmXPK*?W3rA>n z2Exr8Dff48OK;zv45z*ww;{bh+_Qb4`$fH9PlgA!_YMkRa92vS-|6caGz4U9@7rOB zL86K2nc0b%iQIIVt63P%k5BA>v@Fd`96V5H8$ED%V*df6Lq`rx?9UD#Iz$I^qX)7! zNclo8Z#wYAej6B>oteo^m#}#$IcwaJ*0mVHoyQ27%7-1~Xg-#HBVRrAXQ*XA)ecg) zgas`74-)qNzAkrsgy5xSQ=8S}-B%KMnT?4b^erpNrb>ecLjX-Im#rAzIG6 z3ly|K(?UUH8BzNngG)N+fDYs=?=VU05S5L20{zFRy#no<$QRi}^~NQm+bG7nugxQl z>m7+sarK{wnQ}Br7Nk=OE>zF*1!=5K9j8yoGv?vDS*G((XsliPeN*0jCexDWHG>6u zx)gMZrHFuQ5m9)d*X&XzshVn8BDR9F{*t&MH6xe0^fme>l0^=N7Sw_H4H_c-{)bw1 zW<9b(BQl=?t2F6eRMeqxja#ZGK#>C>K(EqJ*U#ND!{PPSfq z?{CQ5f?YvI7T;0+mWQxcB#+A$5q$+HFZ#dbF(v#WkA0S*8l07pR?_~d7))rpHO2G< z#%U;{YB+OnI>gl2xvR*KDrWJ%&tV^LAQQD=Klt49>9x=!3O!=Or2PBPE}RSX{#oq5 zLb9)gsxEA#s?j)m8Eo91=lkzF-T#KYXl!rnY^BDIM&o^B@%lnXqrQzgj78wq!#9cs z-=1{pu>JGFKY;HmJ29`TInvzGN=meq>bAC$+TLs|8b32G<18*3mo6?GbopH&slAn$ z$_q}5HV$`~h~ING6Q~N3R*lmra`SjeDvk5)5A#xnlyxO*E?2BH)4%J;dNcGWTbeSNh zYbHKL4Ll!IKGq!C)}OXSWGx!SvxrLg71!~|oT36irUeE*%~7d*0x#3RC!7Eu=n!~1 zFOG1WyQK(!jIW5266Ze$=THXqw}?njVE{U__IY8S4*sTV7(bbhAQs_o@f^i7U3s_Y z)w8C4It@FdyPxmIh=v=Qn`+EDd*lTh>*e0=*z+-p@4QP!c$xK#=oB}K;bQy;;2&}L z`#{+YD|t`H1iuw40pGk7+x^6qQWYzupRy8NUR4uSXwviqO)yfSiTao(?g~xD9PX^K zatgkZ>8!Aox~c|Pp+W=oF%2qLkWtAPsCNysskD>GM=9hZg>Ue~Ci5YB>6*}KcyTQ(Y?rz9sZrkw*vb@WM%_Br8p}P zUSGJHv$HV2&)qCgfU`em@bgj4lrKmI_ zotLh~kr!}+$-xt5-R5!J9u$1nkvF3tLcREidy9M>9{H>I8K&G|AhXs-e0O4-@s5TZ z;X?a3{o8p7zMaA+jhSy_?^Qo?j8VKWk1X>RqP>azfjydYoKaj_xM=0nl8mTQTVr4xk z!EN)772FD-SIumBJyon%sdWkzP2i}MS5uwUIx(VPqzP*Q_t;wCgtaO;*|&yd_g(5? zkA+WO3-C>W?w`k9A!+)x@8Ue%@_01hT!@t-0(5D!i%%PzDD9=!*!xS&$MhpAU3jV4 z1X=lZC}Pr`;FuIA*N1Zw=BLb*dX7j^a5u+!&97K|PC*ZqZFZPCLn4Q}jYXUacs(>O zJ@I@{bOpCTg|j$EjwF{N6YKnmufwY+q5z#Wu{x-A=!aP zaDu>=h*OMcRwj);_OaZLqmP{^_uJ9;R`mZ5HiWc$SVq{7??PPn+Vz}mzZLbIOBL1= z_1qj@{6ubRTrFcccb`yl)*K!+56sxL_lvtwpP`~b1Z#o5Ulw=#22~AW6qzopO_SVd z;pCF3)>N*cTHGD$v@q&HY`DaUR%?2JU%#8PfQz+9D`TXJXMktpN4Sl%6@d2u?{V{nk%5h{xP&a{^M-@A3m8lg_H-VbRR6(r@A4jGA|Ets0d7KoD z2iI%GNB^?G*(2GHm%7`(<--}`!vg~iQG&W?l=cuRc^aWX>ZMK;m1*k1jp-Fi;go5o zmnn%ziag>NDf)`gro2XEMQ`O;a#s8fhnMr(pHThUIOHSufAAMWyHbO@;gzvRxV0S> mIR4G-pG}9B+j@zyH<{NY^K76aj4chs=PvJ557ykq0T2>tZ literal 0 HcmV?d00001 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 -- 2.25.1