chimera-2.0a19/ 40700 11610 11610 0 6724372006 11424 5ustar johnjohnchimera-2.0a19/doc/ 40700 11610 11610 0 6677561460 12204 5ustar johnjohnchimera-2.0a19/doc/INFO100600 11610 11610 3337 6677561434 12770 0ustar johnjohn Chimera 2.0 X11/Athena World-Wide Web Client written by John Kilburg and others Chimera is an X/Athena Web client for UNIX-based workstations. Chimera does not require Motif. Chimera can be found at or . There is a mailing list called bug-chimera@cs.unlv.edu that is used for bug reports, feature requests, and general chimera discussion. If you want to join the list (receive the emails that go to bug-chimera) send email to bug-chimera-request@cs.unlv.edu There is also a mailing list that receives announcements of new chimera releases. If you want to join the list, send email to chimera-announce-request@cs.unlv.edu Read INSTALL for installation instructions. Read README.hints for hints. Directories: chimera Chimera Core doc License information and other stuff. mxw Miscellaneous Xt widgets. image Library for GIFs, JPEGs, ... Nearly all of this was written by Erik Corry . html An attempt at an HTML renderer proto Library for HTTP, FTP, and local file access. common Generally useful functions port Contains functions and header files used for portability purposes See the file COPYRIGHT for license information. Jay Nietling (jay@egr.unlv.edu) and Greg Wohletz (greg@egr.unlv.edu) are the system guys for the engineering college at UNLV. They have done a really nice job of setting up and maintaining the computing environment here (Athena stuff and a ton of other goodies on a wad of architectures). John Kilburg john@cs.unlv.edu chimera-2.0a19/doc/COPYING100600 11610 11610 43076 6677561442 13370 0ustar johnjohn GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, 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 software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, 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 redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 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 Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. 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) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. chimera-2.0a19/doc/LCOPYING100600 11610 11610 61263 6677561453 13504 0ustar johnjohn GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, 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., 675 Mass Ave, Cambridge, MA 02139, 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! chimera-2.0a19/doc/LICENSE100600 11610 11610 1363 6677561453 13315 0ustar johnjohn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Please see the file COPYING for more information. chimera-2.0a19/doc/INSTALL100600 11610 11610 650 6677561454 13320 0ustar johnjohn------------------------- INSTALLATION INSTRUCTIONS ------------------------- To compile chimera, type: cp Common.tmpl.dist Common.tmpl # modify Common.tmpl if necessary xmkmf -a make Some releases of xmkmf are broken so you might have to type: xmkmf make Makefiles depend clean make You'll end up with a binary that should run OK without any other files. chimera-2.0a19/doc/COPYRIGHT100600 11610 11610 20364 6677561460 13623 0ustar johnjohnMost of the code was written by John and Erik and is GPL'd. See COPYING for details. If I've left anything out below please let me know. Also, if you see GPL'd replacements for anything not GPL'd please send it (or a pointer to it) to john@cs.unlv.edu. Other GPL'd code used: www/url_translate.c by Theodore Ts'o common/snprintf.c by Patrick Powell mxw/TextField* was written by Rob McMullen and is LGPL'd. ==== www/ ==== WWW.c has some code from the Xaw Viewport widget and is Copyright (c) 1989, 1994 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. ==== mxw/ ==== Also, the AuthDialog and MyDialog widgets are based on code from the Athena Dialog widget are Copyright (c) 1987, 1988, 1994 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ======= common/ ======= Some string functions were grabbed from the BSD libraries and are Copyright (c) 1988-1993 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the University of California, Berkeley and its contributors. 4. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. memmove.c from the X folks: Copyright (c) 1987 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. ====== image/ ====== gif.c, new.c, imagep.h were derived from code from xloadimage and are Copyright 1989, 1991 Jim Frost Copyright 1989 Kirk L. Johnson Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The author makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. chimera-2.0a19/doc/HINTS100600 11610 11610 5672 6677561461 13126 0ustar johnjohnThis is really kind of sparse. --------- Compiling --------- If you're unsure if chimera will compile then try the simplest thing: cp Common.tmpl.dist Common.tmpl xmkmf make Makefiles depend clean all I use HAVE_xxx_H defines to allow users with systems that don't have all of the standard header files to easily weed them out of the compilation. I also use HAVE_xxx where xxx is a function that doesn't appear in every system (e.g. the POSIX function mktime()) but the source can make allowances for this. Some functions are included in common that are required but that don't appear everywhere. You can have them linked in by specifying the proper NEED_xxx thing in Common.tmpl. Check common/Imakefile for a current list. If you have trouble doing the simplest thing, please let me know so that I can try to fix the problem. You should only have to change Common.tmpl. If you figure out what needs to be done to get it to compile (like adding a #if defined() thing in Common.tmpl with the proper defines set for a particular machine), please send it to me so that I can include it. Of course, I can't guarantee that I will include all contributions. If you need to specify site-dependent defines or libraries then search for SITE_* in Common.tmpl and add them there. Also, if you need to force the compiler to something special (say, gcc) then remove 'XCOMM' from the line (in Common.tmpl): XCOMM CC = gcc and change the compiler to whatever you need. --------- Resources --------- There are two types of resources used by chimera. X/GUI resources and, for lack of a better term, chimera resources. Chimera resources are formatted exactly like the X resources but are loaded separately. I strongly recommend that you do not use an app-defaults file unless you really want to change the appearance. I'm not even going to try to produce an example...you're on your own here or you can ask the bug-chimera list for examples (there are clever folks that will probably get around to this one of these days). If you install an older version of chimera that installed an app-defaults file then you should remove it or if you need it because 1.65 or some other version needs it then you can run 2.0 with the command: XFILESEARCHPATH="" chimera-2.0 By default, chimera looks for its own resources in ~/.chimera/resources. I recommend you create the directory ~/.chimera since most of the defaults for chimera will point to this directory for files. One possible resources file: bookmark.filename: ~/.chimera/bookmarks.html cache.directory: ~/.chimera/cache cache.persist: true chimera.homeURL: http://www/ html.propFontPattern: -adobe-helvetica-*-*-*-*-*-*-*-*-*-*-iso8859-1 view.capFiles: ~/.chimera/mailcap:~/.mailcap ------------ app-defaults ------------ Don't use them with Chimera v2. If you have an app-defaults file that you need for Chimera v1 then you should create a script that changes XUSERFILESEARCHPATH so that it doesn't look at the default app-defaults directory. chimera-2.0a19/ext/ 40700 11610 11610 0 6677561462 12241 5ustar johnjohnchimera-2.0a19/ext/ext.c100600 11610 11610 13422 6677561464 13330 0ustar johnjohn/* * ext.c * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_STRING_H #include #endif #include #include #include "port_after.h" #include "Chimera.h" typedef struct { char *use; char *incontent; char *outcontent; char *command; } ConvertEntry; typedef struct { MemPool mp; ChimeraSink wp; ChimeraRender wn; ChimeraGUI wd; ChimeraRender own; ChimeraRenderHooks *orh; ConvertEntry *c; int fd[2]; size_t i; } ExtInfo; typedef struct { MemPool mp; GList list; } ExtModuleInfo; static void ExtDestroy _ArgProto((void *)); static void *ExtInit _ArgProto((ChimeraRender, void *)); static void ExtAdd _ArgProto((void *)); static void ExtEnd _ArgProto((void *)); static void ExtCancel _ArgProto((void *)); static GList ReadConvertFiles _ArgProto((MemPool, char *)); /* * ExtDestroy */ static void ExtDestroy(closure) void *closure; { ExtInfo *ei = (ExtInfo *)closure; MPDestroy(ei->mp); return; } /* * ExtAdd */ static void ExtAdd(closure) void *closure; { ExtInfo *ei = (ExtInfo *)closure; byte *data; size_t len; GList mimelist; ssize_t rval; SinkGetData(ei->wp, &data, &len, &mimelist); if (len <= ei->i) return; if ((rval = write(ei->fd[0], data + ei->i, len - ei->i)) <= 0) { perror("ext write add"); return; } ei->i += rval; return; } /* * ExtEnd */ static void ExtEnd(closure) void *closure; { ExtInfo *ei = (ExtInfo *)closure; byte *data; size_t len; GList mimelist; ssize_t rval; char buffer[BUFSIZ]; SinkGetData(ei->wp, &data, &len, &mimelist); while (len > ei->i) { if ((rval = write(ei->fd[0], data + ei->i, len - ei->i)) <= 0) { perror("ext write end"); return; } ei->i += rval; } close(ei->fd[0]); /* while (read(ei->fd[1], buffer, sizeof(buffer)) > 0) ; */ close(ei->fd[1]); return; } /* * ExtCancel */ static void ExtCancel(closure) void *closure; { return; } /* * ExtInit */ static void * ExtInit(wn, closure) ChimeraRender wn; void *closure; { SinkData wp; char *content; ConvertEntry *c; ExtModuleInfo *emi = (ExtModuleInfo *)closure; ExtInfo *ei; MemPool mp; ChimeraRenderHooks *orh; wp = RenderToSink(wn); content = SinkGetInfo(wp, "content-type"); for (c = (ConvertEntry *)GListGetHead(emi->list); c != NULL; c = (ConvertEntry *)GListGetNext(emi->list)) { if (strcasecmp(content, c->incontent) == 0) break; } if (c == NULL) return(NULL); /* orh = WWWGetRenderHooks(WWWGetRenderContext(wn), c->outcontent); if (orh == NULL) return(NULL); */ mp = MPCreate(); ei = (ExtInfo *)MPCGet(mp, sizeof(ExtInfo)); ei->mp = mp; ei->c = c; ei->wd = RenderToGUI(wn); ei->wp = wp; ei->wn = wn; ei->orh = orh; if (PipeCommand(c->command, ei->fd) == -1) { MPDestroy(mp); return(NULL); } return(ei); } /* * ReadConvertFiles * * Reads in the convert entries in a list of files separated by colons. * For example, * * ~/.chimera_convert:~john/lib/convert:/local/infosys/lib/convert */ GList ReadConvertFiles(mp, filelist) MemPool mp; char *filelist; { ConvertEntry *c; char *f; char *filename; char buffer[BUFSIZ]; char use[BUFSIZ]; char incontent[BUFSIZ]; char outcontent[BUFSIZ]; char command[BUFSIZ]; FILE *fp; GList list; list = GListCreateX(mp); f = filelist; while ((filename = mystrtok(f, ':', &f)) != NULL) { filename = FixPath(mp, filename); if (filename == NULL) continue; fp = fopen(filename, "r"); if (fp == NULL) continue; while (fgets(buffer, sizeof(buffer), fp) != NULL) { if (buffer[0] == '#' || buffer[0] == '\n') continue; if (sscanf(buffer, "%s %s %s %[^\n]", use, incontent, outcontent, command) == 4) { c = (ConvertEntry *)MPCGet(mp, sizeof(ConvertEntry)); c->use = MPStrDup(mp, use); c->incontent = MPStrDup(mp, incontent); c->outcontent = MPStrDup(mp, outcontent); c->command = strcasecmp(command, "none") == 0 ? NULL:MPStrDup(mp, command); GListAddTail(list, c); } } fclose(fp); } return(list); } void InitModule_Ext(cres) ChimeraResources cres; { ChimeraRenderHooks rh; char *clist; ExtModuleInfo *emi; GList list; MemPool mp; ConvertEntry *c; if ((clist = ResourceGetString(cres, "convert.convertFiles")) == NULL) { clist = "~/.chimera/convert"; } mp = MPCreate(); list = ReadConvertFiles(mp, clist); if (GListEmpty(list)) { MPDestroy(mp); return; } emi = (ExtModuleInfo *)MPCGet(mp, sizeof(ExtModuleInfo)); emi->mp = mp; emi->list = list; for (c = (ConvertEntry *)GListGetHead(list); c != NULL; c = (ConvertEntry *)GListGetNext(list)) { memset(&rh, 0, sizeof(ChimeraRenderHooks)); rh.content = c->incontent; rh.class_context = emi; rh.class_destroy = ExtDestroy; rh.init = ExtInit; rh.add = ExtAdd; rh.end = ExtEnd; rh.destroy = ExtDestroy; rh.cancel = ExtCancel; RenderAddHooks(cres, &rh); } return; } chimera-2.0a19/mxw/ 40700 11610 11610 0 6724372007 12240 5ustar johnjohnchimera-2.0a19/mxw/Imakefile100600 11610 11610 543 6677561465 14151 0ustar johnjohn#include <../Common.tmpl> HEADERS = MyDialog.h MyDialogP.h TextField.h TextFieldP.h AuthDialogP.h \ AuthDialog.h SRCS = MyDialog.c TextField.c AuthDialog.c OBJS = MyDialog.o TextField.o AuthDialog.o EXTRA_INCLUDES = -I./ -I../port EXTRA_DEFINES = $(CHIMERA_DEFINES) NormalLibraryTarget(mxw, $(OBJS)) DependTarget() install.man:: chimera-2.0a19/mxw/MyDialog.h100600 11610 11610 7725 6677561467 14251 0ustar johnjohn/* Modified by John */ /*********************************************************** Copyright (c) 1987, 1988, 1994 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ #ifndef _MyDialog_h #define _MyDialog_h #include /*********************************************************************** * * MyDialog Widget * ***********************************************************************/ /* Parameters: Name Class RepType Default Value ---- ----- ------- ------------- background Background Pixel XtDefaultBackground border BorderColor Pixel XtDefaultForeground borderWidth BorderWidth Dimension 1 destroyCallback Callback Pointer NULL height Height Dimension computed at create icon Icon Pixmap 0 label Label String NULL mappedWhenManaged MappedWhenManaged Boolean True sensitive Sensitive Boolean True value Value String NULL width Width Dimension computed at create x Position Position 0 y Position Position 0 */ #define XtCIcon "Icon" #define XtNicon "icon" typedef struct _MyDialogClassRec *MyDialogWidgetClass; typedef struct _MyDialogRec *MyDialogWidget; extern WidgetClass mydialogWidgetClass; extern Widget MyDialogAddButton( #if NeedFunctionPrototypes Widget /* mydialog */, _Xconst char* /* name */, XtCallbackProc /* function */, XtPointer /* client_data */ #endif ); extern char *MyDialogGetValue( #if NeedFunctionPrototypes Widget /* w */ #endif ); extern void MyDialogSetValue( #if NeedFunctionPrototypes Widget /* w */, char * #endif ); extern void MyDialogSetMessage( #if NeedFunctionPrototypes Widget /* w */, char * #endif ); #endif /* _MyDialog_h */ chimera-2.0a19/mxw/MyDialog.c100600 11610 11610 24164 6677561473 14255 0ustar johnjohn/* Modified by John */ /*********************************************************** Copyright (c) 1987, 1988, 1994 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* NOTE: THIS IS NOT A WIDGET! Rather, this is an interface to a widget. It implements policy, and gives a (hopefully) easier-to-use interface than just directly making your own form. */ #include #include #include #include #include #include #include #include "TextField.h" #include "MyDialogP.h" static char defaultTranslations[] = "Return: MyPressReturn() \n\ Ctrlm: MyPressReturn() \n"; static XtResource resources[] = { { XtNlabel, XtCLabel, XtRString, sizeof(String), XtOffsetOf(MyDialogRec, mydialog.label), XtRString, NULL }, {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), XtOffsetOf(MyDialogRec, mydialog.callbacks),XtRCallback,(XtPointer)NULL}, }; static void Initialize(), ConstraintInitialize(), MyPressReturn(); static Boolean SetValues(); static XtActionsRec actionsList[] = { { "MyPressReturn", MyPressReturn } }; MyDialogClassRec mydialogClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) &formClassRec, /* class_name */ "MyDialog", /* widget_size */ sizeof(MyDialogRec), /* class_initialize */ XawInitializeWidgetSet, /* class_part init */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actionsList, /* num_actions */ XtNumber(actionsList), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave*/ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator*/ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* composite_class fields */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL }, { /* constraint_class fields */ /* subresourses */ NULL, /* subresource_count */ 0, /* constraint_size */ sizeof(MyDialogConstraintsRec), /* initialize */ ConstraintInitialize, /* destroy */ NULL, /* set_values */ NULL, /* extension */ NULL }, { /* form_class fields */ /* layout */ XtInheritLayout }, { /* mydialog_class fields */ /* empty */ 0 } }; WidgetClass mydialogWidgetClass = (WidgetClass)&mydialogClassRec; /* ARGSUSED */ static void Initialize(request, new, args, num_args) Widget request, new; ArgList args; Cardinal *num_args; { MyDialogWidget dw = (MyDialogWidget)new; dw->mydialog.messageW = XtVaCreateManagedWidget("mydialog_message", textfieldWidgetClass, new, XtNstring, dw->mydialog.label, XtNdisplayCaret, False, XtNeditable, False, XtNborderWidth, 0, XtNleft, XtChainLeft, XtNright, XtChainRight, NULL); dw->mydialog.valueW = XtVaCreateWidget("mydialog_value", textfieldWidgetClass, new, XtNfromVert, dw->mydialog.messageW, XtNleft, XtChainLeft, XtNright, XtChainRight, NULL); /* * if the value widget is being added after buttons, * then the buttons need new layout constraints. */ if (dw->composite.num_children > 1) { WidgetList children = dw->composite.children; Widget *childP; for (childP = children + dw->composite.num_children - 1; childP >= children; childP-- ) { if (*childP == dw->mydialog.messageW || *childP == dw->mydialog.messageW) continue; if (XtIsManaged(*childP) && XtIsSubclass(*childP, commandWidgetClass)) { ((MyDialogConstraints)(*childP)->core.constraints)-> form.vert_base = dw->mydialog.messageW; } } } XtOverrideTranslations(dw->mydialog.valueW, XtParseTranslationTable(defaultTranslations)); XtManageChild(dw->mydialog.valueW); XtSetKeyboardFocus(new, dw->mydialog.valueW); } /* ARGSUSED */ static void ConstraintInitialize(request, new, args, num_args) Widget request, new; ArgList args; Cardinal *num_args; { MyDialogWidget dw = (MyDialogWidget)new->core.parent; MyDialogConstraints constraint = (MyDialogConstraints)new->core.constraints; if (!XtIsSubclass(new, commandWidgetClass)) /* if not a button */ return; /* then just use defaults */ constraint->form.left = constraint->form.right = XtChainLeft; constraint->form.vert_base = dw->mydialog.valueW; if (dw->composite.num_children > 1) { WidgetList children = dw->composite.children; Widget *childP; for (childP = children + dw->composite.num_children - 1; childP >= children; childP-- ) { if (*childP == dw->mydialog.messageW || *childP == dw->mydialog.valueW) break; if (XtIsManaged(*childP) && XtIsSubclass(*childP, commandWidgetClass)) { constraint->form.horiz_base = *childP; break; } } } } /* ARGSUSED */ static Boolean SetValues(current, request, new, in_args, in_num_args) Widget current, request, new; ArgList in_args; Cardinal *in_num_args; { MyDialogWidget w = (MyDialogWidget)new; Boolean label_change = False; int i; for (i = 0; i < *in_num_args; i++) { if (strcmp(XtNlabel, in_args[i].name) == 0) label_change = True; } if (label_change) { TextFieldSetString(w->mydialog.messageW, w->mydialog.label); } return False; } Widget #if NeedFunctionPrototypes MyDialogAddButton(Widget mydialog, _Xconst char* name, XtCallbackProc function, XtPointer param) #else MyDialogAddButton(mydialog, name, function, param) Widget mydialog; String name; XtCallbackProc function; XtPointer param; #endif { /* * Correct Constraints are all set in ConstraintInitialize(). */ Widget button; button = XtVaCreateManagedWidget(name, commandWidgetClass, mydialog, NULL); if (function != NULL) /* don't add NULL callback func. */ XtAddCallback(button, XtNcallback, function, param); return(button); } void #if NeedFunctionPrototypes MyDialogSetMessage(Widget w, char *message) #else MyDialogSetMessage(w, message) Widget w; char *message; #endif { TextFieldSetString(((MyDialogWidget)w)->mydialog.messageW, message); return; } void #if NeedFunctionPrototypes MyDialogSetValue(Widget w, char *value) #else MyDialogSetValue(w, value) Widget w; char *value; #endif { TextFieldSetString(((MyDialogWidget)w)->mydialog.valueW, value); return; } char * #if NeedFunctionPrototypes MyDialogGetValue(Widget w) #else MyDialogGetValue(w) Widget w; #endif { return(TextFieldGetString(((MyDialogWidget)w)->mydialog.valueW)); } /* * MyPressReturn */ static void MyPressReturn(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { MyDialogWidget dw; dw = (MyDialogWidget)XtParent(w); XtCallCallbackList(XtParent(w), dw->mydialog.callbacks, (XtPointer) NULL); return; } chimera-2.0a19/mxw/MyDialogP.h100600 11610 11610 7047 6677561475 14365 0ustar johnjohn/* Modified by john */ /*********************************************************** Copyright (c) 1987, 1988 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* Private definitions for MyDialog widget */ #ifndef _MyDialogP_h #define _MyDialogP_h #include "MyDialog.h" #include typedef struct {int empty;} MyDialogClassPart; typedef struct _MyDialogClassRec { CoreClassPart core_class; CompositeClassPart composite_class; ConstraintClassPart constraint_class; FormClassPart form_class; MyDialogClassPart mydialog_class; } MyDialogClassRec; extern MyDialogClassRec mydialogClassRec; typedef struct _MyDialogPart { String label; /* initial message string */ XtCallbackList callbacks; /* callbacks */ /* private data */ Widget valueW; /* user response text field */ Widget messageW; /* message text field */ } MyDialogPart; typedef struct _MyDialogRec { CorePart core; CompositePart composite; ConstraintPart constraint; FormPart form; MyDialogPart mydialog; } MyDialogRec; typedef struct {int empty;} MyDialogConstraintsPart; typedef struct _MyDialogConstraintsRec { FormConstraintsPart form; MyDialogConstraintsPart mydialog; } MyDialogConstraintsRec, *MyDialogConstraints; #endif /* _MyDialogP_h */ chimera-2.0a19/mxw/TextField.h100600 11610 11610 6310 6677561477 14422 0ustar johnjohn/*----------------------------------------------------------------------------- * TextField A single line text entry widget * * Copyright (c) 1995 Robert W. McMullen * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Author: Rob McMullen * http://www.ae.utexas.edu/~rwmcm */ #ifndef _TextField_H #define _TextField_H #include #define _TextField_WIDGET_VERSION 1.0 #ifndef XtIsTextField #define XtIsTextField(w) XtIsSubclass((Widget)w, textfieldWidgetClass) #endif /* Athena style resource names */ #ifndef XtNecho #define XtNecho "echo" #endif #ifndef XtNpendingDelete #define XtNpendingDelete "pendingDelete" #endif #ifndef XtNlength #define XtNlength "length" #endif #ifndef XtNstring #define XtNstring "string" #endif #ifndef XtNinsertPosition #define XtNinsertPosition "insertPosition" #endif #ifndef XtNdisplayCaret #define XtNdisplayCaret "displayCaret" #endif #ifndef XtNeditable #define XtNeditable "editable" #endif #define XtNmargin "margin" #define XtNcursorWidth "cursorWidth" #define XtNallowSelection "allowSelection" #define XtNactivateCallback "activateCallback" /* Motif style resource names */ #ifndef XmNmaxLength #define XmNmaxLength XtNlength #endif #ifndef XmNvalue #define XmNvalue XtNvalue #endif #ifndef XmNcursorPosition #define XmNcursorPosition XtNinsertPosition #endif #ifndef XmNcursorPositionVisible #define XmNcursorPositionVisible XtNdisplayCaret #endif #ifndef XmNeditable #define XmNeditable XtNeditable #endif #ifndef XmNactivateCallback #define XmNactivateCallback XtNactivateCallback #endif extern WidgetClass textfieldWidgetClass; typedef struct _TextFieldClassRec *TextFieldWidgetClass; typedef struct _TextFieldRec *TextFieldWidget; typedef struct _TextFieldReturnStruct { int reason; /* Motif compatibility */ XEvent *event; char *string; } TextFieldReturnStruct; /* ** Public function declarations */ #if __STDC__ || defined(__cplusplus) #define P_(s) s #else #define P_(s) () #endif /* TextField.c */ Boolean TextFieldGetEditable P_((Widget aw)); int TextFieldGetInsertionPosition P_((Widget aw)); char *TextFieldGetString P_((Widget aw)); void TextFieldInsert P_((Widget aw, int pos, char *str)); void TextFieldReplace P_((Widget aw, int first, int last, char *str)); void TextFieldSetEditable P_((Widget aw, Boolean editable)); void TextFieldSetInsertionPosition P_((Widget aw, int pos)); void TextFieldSetSelection P_((Widget aw, int start, int end, Time time)); void TextFieldSetString P_((Widget aw, char *str)); #undef P_ #endif /* _TextField_H */ chimera-2.0a19/mxw/TextField.c100600 11610 11610 120317 6677561514 14451 0ustar johnjohn/*----------------------------------------------------------------------------- * TextField A single line text entry widget * * Copyright (c) 1995 Robert W. McMullen * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Author: Rob McMullen * http://www.ae.utexas.edu/~rwmcm */ #define _TextField_ #include #include #include #include #include #ifdef HAVE_STDLIB_H #include #endif #include "TextFieldP.h" #define offset(field) XtOffsetOf(TextFieldRec, text.field) static XtResource resources[] = { {XtNallowSelection, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(AllowSelection), XtRString, "True"}, {XtNdisplayCaret, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(DisplayCursor), XtRString, "True"}, {XtNecho, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(Echo), XtRString, "True"}, {XtNeditable, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(Editable), XtRString, "True"}, {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), offset(font), XtRString, XtDefaultFont}, {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(foreground_pixel), XtRString, XtDefaultForeground}, {XtNinsertPosition, XtCInsertPosition, XtRInt, sizeof(int), offset(CursorPos), XtRString, "0"}, {XtNlength, XtCLength, XtRInt, sizeof(int), offset(TextMaxLen), XtRString, "0"}, {XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension), offset(Margin), XtRString, "3"}, {XtNpendingDelete, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(PendingDelete), XtRString, "True"}, {XtNstring, XtCString, XtRString, sizeof(char *), offset(DefaultString), XtRString, NULL}, {XtNactivateCallback, XtCCallback, XtRCallback, sizeof(XtPointer), offset(ActivateCallback), XtRCallback, NULL}, }; #undef offset static void Initialize(); static void Destroy(); static void Redisplay(); static void Resize(); static Boolean SetValues(); static void Draw(), DrawInsert(), MassiveChangeDraw(), DrawTextReposition(), ClearHighlight(), DrawHighlight(), DrawCursor(), EraseCursor(); static Boolean PositionCursor(), MassiveCursorAdjust(); static void Nothing(), Activate(), InsertChar(), ForwardChar(), ForwardToEnd(), BackwardChar(), BackwardToStart(), DeleteNext(), DeleteToEnd(), DeletePrev(), DeleteToStart(), DeleteHighlighted(), TransposeChars(), SelectStart(), ExtendStart(), ExtendAdjust(), ExtendEnd(), InsertSelection(); static char defaultTranslations[] = "Right: forward-char()\n\ KP_Right: forward-char()\n\ Ctrlf: forward-char()\n\ Ctrle: forward-to-end()\n\ Left: backward-char()\n\ KP_Left: backward-char()\n\ Ctrlb: backward-char()\n\ Ctrla: backward-to-start()\n\ Ctrld: delete-next-char()\n\ Ctrlk: delete-to-end()\n\ Delete: delete-previous-char()\n\ BackSpace: delete-previous-char()\n\ Ctrlh: delete-previous-char()\n\ Ctrlu: delete-to-start()\n\ Ctrlw: delete-highlighted()\n\ Ctrlt: transpose-chars()\n\ Return: activate()\n\ : insert-char()\n\ Shift: extend-start()\n\ : select-start()\n\ : extend-adjust()\n\ : extend-end()\n\ : insert-selection()\n\ : extend-start()\n\ : extend-adjust()\n\ : extend-end()\n\ : enter-window()\n\ : leave-window()\n\ : focus-in()\n\ : focus-out()"; static XtActionsRec actions[] = { {"insert-char", InsertChar}, {"forward-char", ForwardChar}, {"forward-to-end", ForwardToEnd}, {"backward-char", BackwardChar}, {"backward-to-start", BackwardToStart}, {"delete-next-char", DeleteNext}, {"delete-to-end", DeleteToEnd}, {"delete-previous-char", DeletePrev}, {"delete-to-start", DeleteToStart}, {"delete-highlighted", DeleteHighlighted}, {"transpose-chars", TransposeChars}, {"activate", Activate}, {"select-start", SelectStart}, {"extend-start", ExtendStart}, {"extend-adjust", ExtendAdjust}, {"extend-end", ExtendEnd}, {"insert-selection", InsertSelection}, {"enter-window", Nothing}, {"leave-window", Nothing}, {"focus-in", Nothing}, {"focus-out", Nothing}, }; TextFieldClassRec textfieldClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) & widgetClassRec, /* class_name */ "TextField", /* widget_size */ sizeof(TextFieldRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ False, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ True, /* compress_exposure */ XtExposeCompressMultiple, /* compress_enterleave */ True, /* visible_interest */ True, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ defaultTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, { 0 /* some stupid compilers barf on empty structures */ } }; WidgetClass textfieldWidgetClass = (WidgetClass) & textfieldClassRec; /* Convenience macros */ #define TopMargin(w) (int)(w->text.Margin - 1) #define BottomMargin(w) (int)(w->text.Margin) /* Font functions */ #define FontHeight(f) (int)(f->max_bounds.ascent + f->max_bounds.descent) #define FontDescent(f) (int)(f->max_bounds.descent) #define FontAscent(f) (int)(f->max_bounds.ascent) #define FontTextWidth(f,c,l) (int)XTextWidth(f, c, l) static void InitializeGC(TextFieldWidget w) { static char dots[] = {2, 1, 1}; XGCValues values; XtGCMask mask; values.line_style = LineSolid; values.line_width = 0; values.fill_style = FillSolid; values.font = w->text.font->fid; values.background = w->core.background_pixel; values.foreground = w->text.foreground_pixel; mask = GCLineStyle | GCLineWidth | GCFillStyle | GCForeground | GCBackground | GCFont; w->text.drawGC = XtGetGC((Widget) w, mask, &values); values.foreground = w->core.background_pixel; values.background = w->text.foreground_pixel; w->text.highlightGC = XtGetGC((Widget) w, mask, &values); values.line_style = LineSolid; values.line_width = 0; values.background = w->core.background_pixel; values.foreground = w->text.foreground_pixel; mask = GCLineStyle | GCLineWidth | GCForeground | GCBackground; w->text.cursorGC = XtGetGC((Widget) w, mask, &values); values.foreground = w->core.background_pixel; values.background = w->text.foreground_pixel; w->text.eraseGC = XtGetGC((Widget) w, mask, &values); values.line_style = LineOnOffDash; values.background = w->core.background_pixel; values.foreground = w->text.foreground_pixel; w->text.dashGC = XtGetGC((Widget) w, mask, &values); XSetDashes(XtDisplay(w), w->text.dashGC, 0, &dots[1], (int) dots[0]); w->text.YOffset = TopMargin(w) + FontAscent(w->text.font); } static void ClipGC(TextFieldWidget w) { XRectangle clip; clip.x = 0; clip.y = w->text.YOffset - FontAscent(w->text.font) + 1; clip.width = w->text.ViewWidth + 1; clip.height = FontHeight(w->text.font); XSetClipRectangles(XtDisplay((Widget) w), w->text.drawGC, w->text.Margin, 0, &clip, 1, Unsorted); XSetClipRectangles(XtDisplay((Widget) w), w->text.highlightGC, w->text.Margin, 0, &clip, 1, Unsorted); } static void SetString(TextFieldWidget w, char *s) { int len; if (s) { len = strlen(s); if (len > w->text.TextAlloc) { w->text.TextAlloc += len; w->text.Text = XtRealloc(w->text.Text, w->text.TextAlloc); } strcpy(w->text.Text, s); w->text.TextLen = len; w->text.TextWidth = w->text.OldTextWidth = FontTextWidth(w->text.font, w->text.Text, w->text.TextLen); if ((w->text.TextMaxLen > 0) && (w->text.TextLen > w->text.TextMaxLen)) w->text.TextMaxLen = w->text.TextLen; } w->text.DefaultString = w->text.Text; } static void Initialize(Widget treq, Widget tnew, ArgList args, Cardinal * num) { TextFieldWidget new; int height; new = (TextFieldWidget) tnew; new->text.timer_id = (XtIntervalId) 0; new->text.multi_click_time = XtGetMultiClickTime(XtDisplay((Widget) new)); new->text.highlight_time = new->text.multi_click_time / 2; if (new->text.TextMaxLen > 0) { new->text.TextAlloc = new->text.TextMaxLen + 1; } else { new->text.TextAlloc = TEXTFIELD_ALLOC_SIZE; } new->text.Text = (char *) XtMalloc(new->text.TextAlloc); new->text.TextLen = 0; new->text.SelectionText = NULL; new->text.TextWidth = new->text.OldTextWidth = 0; if (new->text.DefaultString) SetString(new, new->text.DefaultString); if (new->text.CursorPos > 0) { if (new->text.CursorPos > new->text.TextLen) { new->text.CursorPos = new->text.TextLen; } } else { new->text.CursorPos = 0; } new->text.OldCursorX = -1; new->text.HighlightStart = new->text.HighlightEnd = -1; new->text.OldHighlightStart = new->text.OldHighlightEnd = -1; height = FontHeight(new->text.font); if (new->core.height == 0) new->core.height = (Dimension) height + TopMargin(new) + BottomMargin(new); if (new->core.width == 0) { new->text.ViewWidth = 200; new->core.width = new->text.ViewWidth + 2 * new->text.Margin; } else { int width; width = (int) new->core.width - 2 * new->text.Margin; if (width < 0) new->text.ViewWidth = new->core.width; else new->text.ViewWidth = width; } new->text.XOffset = new->text.OldXOffset = 0; InitializeGC(new); ClipGC(new); } static void Destroy(TextFieldWidget w) { XtReleaseGC((Widget) w, w->text.drawGC); XtReleaseGC((Widget) w, w->text.highlightGC); if (w->text.SelectionText) XtFree(w->text.SelectionText); XtFree(w->text.Text); } static void Redisplay(Widget aw, XExposeEvent * event, Region region) { TextFieldWidget w = (TextFieldWidget) aw; if (!XtIsRealized(aw)) return; Draw(w); } static Boolean SetValues(Widget current, Widget request, Widget reply, ArgList args, Cardinal * nargs) { TextFieldWidget w = (TextFieldWidget) current; TextFieldWidget new = (TextFieldWidget) reply; Boolean redraw = False; if ((w->text.foreground_pixel != new->text.foreground_pixel) || (w->core.background_pixel != new->core.background_pixel) || (w->text.font != new->text.font)) { XtReleaseGC((Widget) w, w->text.drawGC); XtReleaseGC((Widget) w, w->text.highlightGC); XtReleaseGC((Widget) w, w->text.cursorGC); XtReleaseGC((Widget) w, w->text.eraseGC); XtReleaseGC((Widget) w, w->text.dashGC); InitializeGC(new); redraw = True; } if ((w->text.CursorPos != new->text.CursorPos) || (w->text.DisplayCursor != new->text.DisplayCursor)) { redraw = True; } if (w->text.DefaultString != new->text.DefaultString) { redraw = True; SetString(new, new->text.DefaultString); new->text.HighlightStart = new->text.HighlightEnd = -1; new->text.CursorPos = new->text.TextLen; #ifdef DEBUG_TF printf("SetValues: %s\n", new->text.DefaultString); #endif } return redraw; } static void Resize(Widget aw) { TextFieldWidget w = (TextFieldWidget) aw; int width, height; if (!XtIsRealized(aw)) return; width = w->core.width - 2 * w->text.Margin; if (width < 0) w->text.ViewWidth = w->core.width; else w->text.ViewWidth = width; height = (((int) w->core.height - FontHeight(w->text.font)) / 2) + FontAscent(w->text.font); w->text.YOffset = height; ClipGC(w); MassiveChangeDraw(w); } static void TextDelete(TextFieldWidget w, int start, int len) { int i; if (len > 0) { for (i = start + len; i < w->text.TextLen; i++) w->text.Text[i - len] = w->text.Text[i]; w->text.TextLen -= len; w->text.TextWidth = FontTextWidth(w->text.font, w->text.Text, w->text.TextLen); w->text.Text[w->text.TextLen] = 0; } } static void TextDeleteHighlighted(TextFieldWidget w) { if (w->text.HighlightStart >= 0) { TextDelete(w, w->text.HighlightStart, w->text.HighlightEnd - w->text.HighlightStart); w->text.CursorPos = w->text.HighlightStart; w->text.HighlightStart = w->text.HighlightEnd = -1; } } /* returns value indicating if the text can be redrawn using the fast * method */ static Boolean TextInsert(TextFieldWidget w, char *buf, int len) { int i; Boolean regular_copy, fast_insert; fast_insert = True; if (len > 0) { if (w->text.HighlightStart >= 0) { fast_insert = False; if (w->text.PendingDelete) TextDeleteHighlighted(w); else ClearHighlight(w); } regular_copy = True; if (w->text.TextMaxLen > 0) { if (w->text.TextLen + len > w->text.TextMaxLen) regular_copy = False; } else if (w->text.TextLen + len > w->text.TextAlloc) { i = TEXTFIELD_ALLOC_SIZE; if (i < len) i = len; w->text.TextAlloc += i + 1; w->text.Text = XtRealloc(w->text.Text, w->text.TextAlloc); #ifdef DEBUG_TF printf("TextInsert: Alloced new space: %d bytes\n", w->text.TextAlloc); #endif } if (regular_copy) { for (i = w->text.TextLen - 1; i >= w->text.CursorPos; i--) w->text.Text[i + len] = w->text.Text[i]; strncpy(&w->text.Text[w->text.CursorPos], buf, len); w->text.FastInsertCursorStart = w->text.CursorPos; w->text.FastInsertTextLen = len; w->text.TextLen += len; w->text.CursorPos += len; } else { int i1; for (i = w->text.TextLen - 1; i >= w->text.CursorPos; i--) if (i + len < w->text.TextMaxLen) w->text.Text[i + len] = w->text.Text[i]; w->text.TextLen += len; if (w->text.TextLen > w->text.TextMaxLen) w->text.TextLen = w->text.TextMaxLen; i1 = w->text.CursorPos; for (i = 0; i < len; i++) { if (i1 < w->text.TextMaxLen) w->text.Text[i1] = *buf++; else break; i1++; } w->text.FastInsertCursorStart = w->text.CursorPos; w->text.FastInsertTextLen = i1 - w->text.CursorPos; w->text.CursorPos = i1; } w->text.TextWidth = FontTextWidth(w->text.font, w->text.Text, w->text.TextLen); w->text.Text[w->text.TextLen] = 0; } return fast_insert; } static int TextPixelToPos(TextFieldWidget w, int x) { int i, tot, cur, pos; pos = 0; x -= (int) w->text.Margin + w->text.XOffset; /* check if the cursor is before the 1st character */ if (x <= 0) { pos = 0; } /* OK, how 'bout after the last character */ else if (x > FontTextWidth(w->text.font, w->text.Text, w->text.TextLen)) { pos = w->text.TextLen; } /* must be in between somewhere... */ else { tot = 0; pos = -1; for (i = 0; i < w->text.TextLen; i++) { cur = FontTextWidth(w->text.font, &w->text.Text[i], 1); if (x < tot + (cur / 2)) { pos = i; break; } tot += cur; } if (pos < 0) pos = w->text.TextLen; } return pos; } /* * TextField Widget Action procedures */ /* ARGSUSED */ static void Nothing(Widget aw, XEvent * event, String * params, Cardinal * num_params) { } /* ARGSUSED */ static void Activate(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; TextFieldReturnStruct ret; ret.reason = 0; ret.event = event; ret.string = w->text.Text; if (XtNactivateCallback) XtCallCallbacks(aw, XtNactivateCallback, &ret); } /* ARGSUSED */ static void ForwardChar(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.Editable) return; ClearHighlight(w); if (w->text.CursorPos < w->text.TextLen) { w->text.CursorPos++; EraseCursor(w); if (PositionCursor(w)) DrawTextReposition(w); DrawCursor(w); } } /* ARGSUSED */ static void ForwardToEnd(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.Editable) return; ClearHighlight(w); if (w->text.CursorPos < w->text.TextLen) { w->text.CursorPos = w->text.TextLen; EraseCursor(w); if (PositionCursor(w)) DrawTextReposition(w); DrawCursor(w); } } /* ARGSUSED */ static void BackwardChar(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.Editable) return; ClearHighlight(w); if (w->text.CursorPos > 0) { w->text.CursorPos--; EraseCursor(w); if (PositionCursor(w)) DrawTextReposition(w); DrawCursor(w); } } /* ARGSUSED */ static void BackwardToStart(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.Editable) return; ClearHighlight(w); if (w->text.CursorPos > 0) { w->text.CursorPos=0; EraseCursor(w); if (PositionCursor(w)) DrawTextReposition(w); DrawCursor(w); } } /* ARGSUSED */ static void InsertChar(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; int len, i, j; #define INSERTCHARBUFSIZ 32 char buf[INSERTCHARBUFSIZ]; if (!w->text.Editable) return; len = XLookupString((XKeyEvent *) event, buf, BUFSIZ, NULL, NULL); /* Throw away characters with values < Space (32) */ for (i = 0; i < len; i++) { if (buf[i] < 32) { for (j = 0; j < len && j < (BUFSIZ - 1); j++) { buf[j] = buf[j+1]; } buf[j] = '\0'; len-=1; } } if (len > 0) { EraseCursor(w); if (TextInsert(w, buf, len)) DrawInsert(w); else Draw(w); } } /* ARGSUSED */ static void DeleteNext(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.Editable) return; if (w->text.CursorPos < w->text.TextLen) { ClearHighlight(w); TextDelete(w, w->text.CursorPos, 1); Draw(w); } } /* ARGSUSED */ static void DeleteToEnd(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.Editable) return; if (w->text.CursorPos < w->text.TextLen) { ClearHighlight(w); TextDelete(w, w->text.CursorPos, w->text.TextLen-w->text.CursorPos); Draw(w); } } /* ARGSUSED */ static void DeletePrev(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.Editable) return; if (w->text.CursorPos > 0) { ClearHighlight(w); TextDelete(w, w->text.CursorPos - 1, 1); w->text.CursorPos--; Draw(w); } } /* ARGSUSED */ static void DeleteToStart(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.Editable) return; if (w->text.CursorPos > 0) { ClearHighlight(w); TextDelete(w, 0, w->text.CursorPos); w->text.CursorPos=0; Draw(w); } } /* ARGSUSED */ static void DeleteHighlighted(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.Editable) return; if (w->text.HighlightStart >= 0 && w->text.PendingDelete) { TextDeleteHighlighted(w); MassiveChangeDraw(w); } } /* ARGSUSED */ static void TransposeChars(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; char c; if (!w->text.Editable) return; ClearHighlight(w); if (w->text.CursorPos > 0 && w->text.CursorPos < w->text.TextLen) { c = w->text.Text[w->text.CursorPos -1]; TextDelete(w, w->text.CursorPos - 1, 1); TextInsert(w, &c, 1); Draw(w); } } /* ARGSUSED */ static void SelectStart(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.AllowSelection) return; w->text.CursorPos = TextPixelToPos(w, event->xbutton.x); w->text.HighlightPivotStart = w->text.HighlightPivotEnd = w->text.CursorPos; if (w->text.HighlightStart >= 0) { ClearHighlight(w); } else { EraseCursor(w); DrawCursor(w); } } /* ARGSUSED */ static void ExtendStart(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; int pos; if (!w->text.AllowSelection) return; pos = TextPixelToPos(w, event->xbutton.x); EraseCursor(w); if (w->text.HighlightStart < 0) { w->text.HighlightStart = w->text.HighlightEnd = w->text.HighlightPivotStart = w->text.HighlightPivotEnd = w->text.CursorPos; } else { w->text.HighlightPivotStart = w->text.HighlightStart; w->text.HighlightPivotEnd = w->text.HighlightEnd; } if (pos < w->text.HighlightStart) { w->text.HighlightStart = pos; } else { w->text.HighlightEnd = pos; } w->text.CursorPos = pos; #ifdef DEBUG_TF printf("ExtendStart: %d - %d\n", w->text.HighlightStart, w->text.HighlightEnd); #endif DrawHighlight(w); DrawCursor(w); } static void ExtendHighlight(TextFieldWidget w) { int x, pos; if (!w->text.AllowSelection) return; x = w->text.timer_x; pos = TextPixelToPos(w, x); if (x < (int) w->text.Margin) { pos = TextPixelToPos(w, (int) 0); if (pos > 0) pos--; else if (pos == w->text.CursorPos) return; } else if (x > (int) (w->text.Margin + w->text.ViewWidth)) { pos = TextPixelToPos(w, (int) (w->text.Margin + w->text.ViewWidth)); if (pos < w->text.TextLen) pos++; else if (pos == w->text.CursorPos) return; } if (pos == w->text.CursorPos) return; EraseCursor(w); if (pos <= w->text.HighlightPivotStart) { w->text.HighlightStart = pos; w->text.HighlightEnd = w->text.HighlightPivotEnd; } else { w->text.HighlightStart = w->text.HighlightPivotStart; w->text.HighlightEnd = pos; } w->text.CursorPos = pos; #ifdef DEBUG_TF printf("Highlighting: x=%d pos=%d %d - %d\n", x, pos, w->text.HighlightStart, w->text.HighlightEnd); #endif if (PositionCursor(w)) DrawTextReposition(w); DrawHighlight(w); DrawCursor(w); } static void ExtendTimer(XtPointer client_data, XtIntervalId * idp) { TextFieldWidget w = (TextFieldWidget) client_data; ExtendHighlight(w); w->text.timer_id = XtAppAddTimeOut( XtWidgetToApplicationContext((Widget) w), (unsigned long) w->text.highlight_time, ExtendTimer, (XtPointer) w); } /* ARGSUSED */ static void ExtendAdjust(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; if (!w->text.AllowSelection) return; w->text.timer_x = event->xbutton.x; if (event->xbutton.x < w->text.Margin || event->xbutton.x > w->text.Margin + w->text.ViewWidth) { if (w->text.timer_id) ExtendHighlight(w); else ExtendTimer((XtPointer) w, (XtIntervalId) 0); } else { if (w->text.timer_id) { XtRemoveTimeOut(w->text.timer_id); w->text.timer_id = (XtIntervalId) 0; } ExtendHighlight(w); } } /* ARGSUSED */ static Boolean ConvertSelection(Widget aw, Atom * selection, Atom * target, Atom * type, XtPointer * value, unsigned long *length, int *format) { TextFieldWidget w = (TextFieldWidget) aw; XSelectionRequestEvent *req = XtGetSelectionRequest(aw, *selection, NULL); if (*target == XA_TARGETS(XtDisplay(aw))) { Atom *targetP, *std_targets; unsigned long std_length; XmuConvertStandardSelection(aw, req->time, selection, target, type, &std_targets, &std_length, format); *value = XtMalloc((unsigned) sizeof(Atom) * (std_length + 1)); targetP = *(Atom **) value; *length = std_length + 1; *targetP++ = XA_STRING; memmove((char *) targetP, (char *) std_targets, sizeof(Atom) * std_length); XtFree((char *) std_targets); *type = XA_ATOM; *format = sizeof(Atom) * 8; return True; } else if (*target == XA_STRING) { *length = (long) w->text.SelectionLen; *value = w->text.SelectionText; *type = XA_STRING; *format = 8; return True; } return False; } /* ARGSUSED */ static void LoseSelection(Widget aw, Atom * selection) { TextFieldWidget w = (TextFieldWidget) aw; ClearHighlight(w); } /* ARGSUSED */ static void ExtendEnd(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; int len; if (!w->text.AllowSelection) return; if (w->text.timer_id) { XtRemoveTimeOut(w->text.timer_id); w->text.timer_id = (XtIntervalId) 0; } len = w->text.HighlightEnd - w->text.HighlightStart; if (len > 0) { w->text.SelectionLen = len; if (w->text.SelectionText) XtFree(w->text.SelectionText); w->text.SelectionText = XtMalloc(len); strncpy(w->text.SelectionText, &w->text.Text[w->text.HighlightStart], len); XtOwnSelection(aw, XA_PRIMARY, event->xbutton.time, ConvertSelection, LoseSelection, NULL); XChangeProperty(XtDisplay(aw), DefaultRootWindow(XtDisplay(aw)), XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace, (unsigned char *) w->text.SelectionText, len); } } /* ARGSUSED */ static void RequestSelection(Widget aw, XtPointer client, Atom * selection, Atom * type, XtPointer value, unsigned long *length, int *format) { TextFieldWidget w = (TextFieldWidget) aw; if ((value == NULL) || (*length == 0)) { #ifdef DEBUG_TF printf("RequestSelection: no selection\n"); #endif } else { int savex; ClearHighlight(w); savex = w->text.OldCursorX; w->text.CursorPos = (int) client; #ifdef DEBUG_TF printf("RequestSelection: inserting %s length=%d at pos: %d\n", (char *) value, (int) (*length), w->text.CursorPos); #endif TextInsert(w, (char *) value, (int) (*length)); w->text.OldCursorX = savex; Draw(w); } } /* ARGSUSED */ static void InsertSelection(Widget aw, XEvent * event, String * params, Cardinal * num_params) { TextFieldWidget w = (TextFieldWidget) aw; int pos; if (!w->text.AllowSelection) return; pos = TextPixelToPos(w, event->xbutton.x); #ifdef DEBUG_TF printf("InsertSelection: event at pos: %d\n", pos); #endif XtGetSelectionValue(aw, XA_PRIMARY, XA_STRING, RequestSelection, (XtPointer) pos, event->xbutton.time); } /* * TextField private drawing functions */ static Boolean PositionCursor(TextFieldWidget w) { int x, start, end; Boolean moved; moved = False; if (w->text.CursorPos < 0) w->text.CursorPos = 0; else if (w->text.CursorPos > w->text.TextLen) w->text.CursorPos = w->text.TextLen; x = FontTextWidth(w->text.font, w->text.Text, w->text.CursorPos); start = -w->text.XOffset; end = start + w->text.ViewWidth; if (x < start) { w->text.XOffset = -x; moved = True; } else if (x > end) { w->text.XOffset = w->text.ViewWidth - x; moved = True; } return moved; } static Boolean MassiveCursorAdjust(TextFieldWidget w) { int start, end, last; Boolean moved; moved = False; end = FontTextWidth(w->text.font, w->text.Text, w->text.CursorPos); if (w->text.HighlightStart >= 0) start = FontTextWidth(w->text.font, w->text.Text, w->text.HighlightStart); else start = end; if (end < w->text.ViewWidth) { if (w->text.XOffset < 0) { w->text.XOffset = 0; moved = True; } } else if (start >= w->text.XOffset && end < w->text.XOffset + w->text.ViewWidth) return moved; else { last = FontTextWidth(w->text.font, w->text.Text, w->text.TextLen); if (start - end > w->text.ViewWidth) { if (last - end > w->text.ViewWidth) w->text.XOffset = w->text.ViewWidth - last; else w->text.XOffset = w->text.ViewWidth - end; } else if (end > w->text.ViewWidth) w->text.XOffset = w->text.ViewWidth - end; else w->text.XOffset = 0; moved = True; } return moved; } /* * Actually draw a range of text onto the widget */ static void DrawText(TextFieldWidget w, int start, int end, Boolean highlight) { int x; GC gc; if (!w->text.Echo) return; if (w->text.TextLen > 0) { if (start < 0) return; else if (end < start) { int temp; temp = start; start = end; end = temp; } if (end <= w->text.TextLen) { x = w->text.Margin + w->text.XOffset + FontTextWidth(w->text.font, w->text.Text, start); if (highlight) gc = w->text.highlightGC; else gc = w->text.drawGC; XDrawImageString(XtDisplay(w), XtWindow(w), gc, x, w->text.YOffset, &w->text.Text[start], end - start); } } } static void DrawTextRange(TextFieldWidget w, int start, int end) { if (!w->text.Echo) return; if (w->text.TextLen > 0) { if (start < 0) return; else if (end < start) { int temp; temp = start; start = end; end = temp; } /* If there is no highlighting, or the refresh area doesn't cross the */ /* the highlight borders, just redraw it. */ if (w->text.HighlightStart < 0 || start >= w->text.HighlightEnd || end <= w->text.HighlightStart) { DrawText(w, start, end, False); } /* OK, the refresh area crosses one or both highlight borders. */ else { int clip; while (start < end) { if (start < w->text.HighlightStart) { if (end <= w->text.HighlightStart) clip = end; else clip = w->text.HighlightStart; DrawText(w, start, clip, False); start = clip; } else if (start < w->text.HighlightEnd) { if (end <= w->text.HighlightEnd) clip = end; else clip = w->text.HighlightEnd; DrawText(w, start, clip, True); start = clip; } else { DrawText(w, start, end, False); start = end; } } } } } static void DrawTextReposition(TextFieldWidget w) { int xsrc, xdest, width, start, end; if (!w->text.Echo) return; if (w->text.XOffset < w->text.OldXOffset) { xsrc = w->text.OldXOffset - w->text.XOffset; xdest = 0; width = w->text.ViewWidth - xsrc + 1; /* Need to redraw some characters at the end. */ end = TextPixelToPos(w, w->text.Margin + w->text.ViewWidth); start = TextPixelToPos(w, w->text.Margin + w->text.ViewWidth - xsrc); } else if (w->text.XOffset > w->text.OldXOffset) { xsrc = 0; xdest = w->text.XOffset - w->text.OldXOffset; width = w->text.ViewWidth - xdest + 1; /* Need to redraw some characters at the beginning. */ start = TextPixelToPos(w, w->text.Margin); end = TextPixelToPos(w, w->text.Margin + xdest); } else return; if (width > 0) { #ifdef DEBUG_TF printf("Reposition: xoff=%d old=%d src=%d dest=%d width=%d refresh %d-%d\n", w->text.XOffset, w->text.OldXOffset, xsrc, xdest, width, start, end); #endif XCopyArea(XtDisplay(w), XtWindow(w), XtWindow(w), w->text.drawGC, w->text.Margin + xsrc, 0, (unsigned int) width, (unsigned int) w->core.height, w->text.Margin + xdest, 0); DrawTextRange(w, start, end); } w->text.OldXOffset = w->text.XOffset; } static void DrawTextWithCopyArea(TextFieldWidget w) { int x, insert_width; int xsrc, xdest, width; if (!w->text.Echo) return; x = w->text.XOffset; insert_width = FontTextWidth(w->text.font, &w->text.Text[w->text.FastInsertCursorStart], w->text.FastInsertTextLen); if (PositionCursor(w)) { /* * if the text is scrolled, then: * 1. the cursor is at the end * 2. the copy will move to the left. */ xsrc = 0; width = w->text.OldCursorX + x; xdest = w->text.ViewWidth - (x + w->text.OldCursorX) - insert_width; XCopyArea(XtDisplay(w), XtWindow(w), XtWindow(w), w->text.drawGC, w->text.Margin + xsrc, 0, (unsigned int) width, (unsigned int) w->core.height, w->text.Margin + xdest, 0); #ifdef DEBUG_TF printf("DrawInsert: x=%d xsrc=%d xdest=%d width=%d\n", x, xsrc, xdest, width); #endif } else { /* * the text hasn't been scrolled, so: * 1. the text left of the cursor won't change * 2. the stuff after the cursor will be moved right. */ xsrc = FontTextWidth(w->text.font, w->text.Text, w->text.FastInsertCursorStart) + x; width = w->text.ViewWidth - xsrc; xdest = xsrc + insert_width; XCopyArea(XtDisplay(w), XtWindow(w), XtWindow(w), w->text.drawGC, w->text.Margin + xsrc, 0, (unsigned int) width, (unsigned int) w->core.height, w->text.Margin + xdest, 0); #ifdef DEBUG_TF printf("DrawInsert: x=%d xsrc=%d xdest=%d width=%d\n", x, xsrc, xdest, width); #endif } DrawTextRange(w, w->text.FastInsertCursorStart, w->text.FastInsertCursorStart + w->text.FastInsertTextLen); if (w->text.TextMaxLen > 0) { /* * This is pretty much a hack: * clear everything to end of window if this is a * fixed length TextField */ xsrc = w->text.XOffset + w->text.TextWidth; width = w->text.ViewWidth - xsrc; /* printf("DrawInsert: TextWidth=%d Old=%d\n", w->text.TextWidth, w->text.OldTextWidth); */ XClearArea(XtDisplay(w), XtWindow(w), w->text.Margin + xsrc, 0, (unsigned int) width, w->core.height, False); } else if (w->text.TextWidth < w->text.OldTextWidth) { XClearArea(XtDisplay(w), XtWindow(w), w->text.Margin + w->text.XOffset + w->text.TextWidth, 0, w->text.OldTextWidth - w->text.TextWidth + 1, w->core.height, False); } w->text.OldTextWidth = w->text.TextWidth; w->text.OldXOffset = w->text.XOffset; } static void DrawAllText(TextFieldWidget w) { if (!w->text.Echo) return; DrawTextRange(w, 0, w->text.TextLen); if (w->text.TextWidth < w->text.OldTextWidth) { XClearArea(XtDisplay(w), XtWindow(w), w->text.Margin + w->text.XOffset + w->text.TextWidth, 0, w->text.OldTextWidth - w->text.TextWidth + 1, w->core.height, False); } w->text.OldTextWidth = w->text.TextWidth; w->text.OldXOffset = w->text.XOffset; w->text.OldHighlightStart = w->text.HighlightStart; w->text.OldHighlightEnd = w->text.HighlightEnd; } /* Draw an I-beam cursor */ static void DrawIBeamCursor(TextFieldWidget w, int x, GC gc) { XDrawLine(XtDisplay(w), XtWindow(w), gc, x, w->text.YOffset - FontAscent(w->text.font) - 1, x, w->text.YOffset + FontDescent(w->text.font) + 1); XDrawLine(XtDisplay(w), XtWindow(w), gc, x - 2, w->text.YOffset - FontAscent(w->text.font) - 1, x + 2, w->text.YOffset - FontAscent(w->text.font) - 1); XDrawLine(XtDisplay(w), XtWindow(w), gc, x - 2, w->text.YOffset + FontDescent(w->text.font) + 1, x + 2, w->text.YOffset + FontDescent(w->text.font) + 1); } static void DrawCursor(TextFieldWidget w) { int x; GC gc; if (w->text.DisplayCursor) { x = FontTextWidth(w->text.font, w->text.Text, w->text.CursorPos); w->text.OldCursorPos = w->text.CursorPos; w->text.OldCursorX = x; x += w->text.Margin + w->text.XOffset; gc = w->text.cursorGC; DrawIBeamCursor(w, x, gc); } } static void EraseCursor(TextFieldWidget w) { int x; if (w->text.DisplayCursor && w->text.OldCursorX >= 0) { x = w->text.OldCursorX + w->text.Margin + w->text.XOffset; DrawIBeamCursor(w, x, w->text.eraseGC); /* Little hack to fix up the character that might have been affected by * erasing the old cursor. */ if (w->text.OldCursorPos < w->text.TextLen) DrawTextRange(w, w->text.OldCursorPos, w->text.OldCursorPos + 1); } } static void ClearHighlight(TextFieldWidget w) { if (!w->text.Echo) return; if (w->text.HighlightStart >= 0) { EraseCursor(w); DrawText(w, w->text.HighlightStart, w->text.HighlightEnd, False); DrawCursor(w); w->text.HighlightStart = w->text.HighlightEnd = -1; } w->text.OldHighlightStart = w->text.OldHighlightEnd = -1; } static void DrawHighlight(TextFieldWidget w) { if (!w->text.Echo) return; if (w->text.OldHighlightStart < 0) { DrawText(w, w->text.HighlightStart, w->text.HighlightEnd, True); } else { DrawText(w, w->text.HighlightStart, w->text.OldHighlightStart, (w->text.HighlightStart < w->text.OldHighlightStart)); DrawText(w, w->text.HighlightEnd, w->text.OldHighlightEnd, (w->text.HighlightEnd > w->text.OldHighlightEnd)); } w->text.OldHighlightStart = w->text.HighlightStart; w->text.OldHighlightEnd = w->text.HighlightEnd; } /* * Special redraw function after a text insertion */ static void DrawInsert(TextFieldWidget w) { /* EraseCursor must be called before this */ DrawTextWithCopyArea(w); DrawCursor(w); } /* * Redraw the entire widget, but don't scroll the window much */ static void Draw(TextFieldWidget w) { EraseCursor(w); PositionCursor(w); DrawAllText(w); DrawCursor(w); } /* * Like Draw(), but has different rules about scrolling the window to * place the cursor in a good place */ static void MassiveChangeDraw(TextFieldWidget w) { EraseCursor(w); MassiveCursorAdjust(w); DrawAllText(w); DrawCursor(w); } /* * Motif-like TextField public functions * * Note that this set of functions is only a subset of the functions available * in the real Motif XmTextField. */ Boolean TextFieldGetEditable(Widget aw) { TextFieldWidget w = (TextFieldWidget) aw; if (!XtIsTextField(aw)) return 0; return w->text.Editable; } int TextFieldGetInsertionPosition(Widget aw) { TextFieldWidget w = (TextFieldWidget) aw; if (!XtIsTextField(aw)) return 0; return w->text.CursorPos; } char * TextFieldGetString(Widget aw) { TextFieldWidget w = (TextFieldWidget) aw; char *ret; if (!XtIsTextField(aw)) { ret = XtMalloc(1); *ret = '\0'; return ret; } ret = XtMalloc(w->text.TextLen + 1); strncpy(ret, w->text.Text, w->text.TextLen); ret[w->text.TextLen] = '\0'; return ret; } void TextFieldInsert(Widget aw, int pos, char *str) { TextFieldWidget w = (TextFieldWidget) aw; int len; if (!XtIsTextField(aw)) return; if (str && ((len = strlen(str)) > 0) && pos >= 0 && pos <= w->text.TextLen) { w->text.HighlightStart = w->text.HighlightEnd = pos; TextInsert(w, str, len); MassiveChangeDraw(w); } } void TextFieldReplace(Widget aw, int first, int last, char *str) { TextFieldWidget w = (TextFieldWidget) aw; int len; if (!XtIsTextField(aw)) return; if (str) { len = strlen(str); if (last > w->text.TextLen) last = w->text.TextLen; if (first <= last) { w->text.HighlightStart = first; w->text.HighlightEnd = last; TextDeleteHighlighted(w); TextInsert(w, str, len); MassiveChangeDraw(w); } } } void TextFieldSetEditable(Widget aw, Boolean editable) { TextFieldWidget w = (TextFieldWidget) aw; if (!XtIsTextField(aw)) return; w->text.Editable = editable; } void TextFieldSetInsertionPosition(Widget aw, int pos) { TextFieldWidget w = (TextFieldWidget) aw; if (!XtIsTextField(aw)) return; if (pos >= 0 && pos <= w->text.TextLen) { w->text.CursorPos = pos; MassiveChangeDraw(w); } } /* ARGSUSED */ void TextFieldSetSelection(Widget aw, int start, int end, Time time) { TextFieldWidget w = (TextFieldWidget) aw; if (!XtIsTextField(aw)) return; if (end < start) { int temp; temp = start; start = end; end = temp; } if (start < 0) start = 0; if (end > w->text.TextLen) end = w->text.TextLen; w->text.HighlightStart = start; w->text.HighlightEnd = w->text.CursorPos = end; MassiveChangeDraw(w); } void TextFieldSetString(Widget aw, char *str) { TextFieldWidget w = (TextFieldWidget) aw; int len; if (!XtIsTextField(aw)) return; if (str) { len = strlen(str); w->text.HighlightStart = 0; w->text.HighlightEnd = w->text.TextLen; TextDeleteHighlighted(w); TextInsert(w, str, len); MassiveChangeDraw(w); } } chimera-2.0a19/mxw/AuthDialog.c100600 11610 11610 33617 6677561522 14567 0ustar johnjohn/* Modified by John */ /*********************************************************** Copyright (c) 1987, 1988, 1994 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* NOTE: THIS IS NOT A WIDGET! Rather, this is an interface to a widget. It implements policy, and gives a (hopefully) easier-to-use interface than just directly making your own form. */ #include #include #include #include #include #include #include #include #include "TextField.h" #include "AuthDialogP.h" /* * After we have set the string in the value widget we set the * string to a magic value. So that when a SetValues request is made * on the mydialog value we will notice it, and reset the string. */ #define MAGIC_VALUE ((char *) 3) #define streq(a,b) (strcmp( (a), (b) ) == 0) static XtResource resources[] = { { XtNlabel, XtCLabel, XtRString, sizeof(String), XtOffsetOf(AuthDialogRec, authdialog.label), XtRString, NULL }, { "username", XtCValue, XtRString, sizeof(String), XtOffsetOf(AuthDialogRec, authdialog.username), XtRString, NULL }, { XtNicon, XtCIcon, XtRBitmap, sizeof(Pixmap), XtOffsetOf(AuthDialogRec, authdialog.icon), XtRImmediate, 0 }, { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), XtOffsetOf(AuthDialogRec, authdialog.callbacks),XtRCallback, NULL }, }; static void AuthInitialize(), AuthConstraintInitialize(); static void CreateAuthDialogFields(); static void UsernameActivate(); static void PasswordActivate(); static Boolean SetValues(); AuthDialogClassRec authdialogClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) &formClassRec, /* class_name */ "AuthDialog", /* widget_size */ sizeof(AuthDialogRec), /* class_initialize */ XawInitializeWidgetSet, /* class_part init */ NULL, /* class_inited */ FALSE, /* initialize */ AuthInitialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave*/ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator*/ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* composite_class fields */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL }, { /* constraint_class fields */ /* subresourses */ NULL, /* subresource_count */ 0, /* constraint_size */ sizeof(AuthDialogConstraintsRec), /* initialize */ AuthConstraintInitialize, /* destroy */ NULL, /* set_values */ NULL, /* extension */ NULL }, { /* form_class fields */ /* layout */ XtInheritLayout }, { /* authdialog_class fields */ /* empty */ 0 } }; WidgetClass authdialogWidgetClass = (WidgetClass)&authdialogClassRec; /* ARGSUSED */ static void AuthInitialize(request, new, args, num_args) Widget request, new; ArgList args; Cardinal *num_args; { AuthDialogWidget dw = (AuthDialogWidget)new; Arg arglist[9]; Cardinal arg_cnt = 0; XtSetArg(arglist[arg_cnt], XtNborderWidth, 0); arg_cnt++; XtSetArg(arglist[arg_cnt], XtNleft, XtChainLeft); arg_cnt++; if (dw->authdialog.icon != (Pixmap)0) { XtSetArg(arglist[arg_cnt], XtNbitmap, dw->authdialog.icon); arg_cnt++; XtSetArg(arglist[arg_cnt], XtNright, XtChainLeft); arg_cnt++; dw->authdialog.iconW = XtCreateManagedWidget( "icon", labelWidgetClass, new, arglist, arg_cnt ); arg_cnt = 2; XtSetArg(arglist[arg_cnt], XtNfromHoriz, dw->authdialog.iconW); arg_cnt++; } else dw->authdialog.iconW = (Widget)NULL; XtSetArg(arglist[arg_cnt], XtNlabel, dw->authdialog.label); arg_cnt++; XtSetArg(arglist[arg_cnt], XtNright, XtChainRight); arg_cnt++; dw->authdialog.labelW = XtCreateManagedWidget( "label", labelWidgetClass, new, arglist, arg_cnt); if (dw->authdialog.iconW != (Widget)NULL && (dw->authdialog.labelW->core.height < dw->authdialog.iconW->core.height)) { XtSetArg( arglist[0], XtNheight, dw->authdialog.iconW->core.height ); XtSetValues( dw->authdialog.labelW, arglist, ONE ); } CreateAuthDialogFields( (Widget) dw); } /* ARGSUSED */ static void AuthConstraintInitialize(request, new, args, num_args) Widget request, new; ArgList args; Cardinal *num_args; { AuthDialogWidget dw = (AuthDialogWidget)new->core.parent; AuthDialogConstraints constraint = (AuthDialogConstraints)new->core.constraints; if (!XtIsSubclass(new, commandWidgetClass)) /* if not a button */ return; /* then just use defaults */ constraint->form.left = constraint->form.right = XtChainLeft; constraint->form.vert_base = dw->authdialog.passwordW; if (dw->composite.num_children > 1) { WidgetList children = dw->composite.children; Widget *childP; for (childP = children + dw->composite.num_children - 1; childP >= children; childP-- ) { if (*childP == dw->authdialog.labelW || *childP == dw->authdialog.passwordW) break; if (XtIsManaged(*childP) && XtIsSubclass(*childP, commandWidgetClass)) { constraint->form.horiz_base = *childP; break; } } } } #define ICON 0 #define LABEL 1 #define NUM_CHECKS 2 /* ARGSUSED */ static Boolean SetValues(current, request, new, in_args, in_num_args) Widget current, request, new; ArgList in_args; Cardinal *in_num_args; { AuthDialogWidget w = (AuthDialogWidget)new; AuthDialogWidget old = (AuthDialogWidget)current; Arg args[5]; Cardinal num_args; int i; Boolean checks[NUM_CHECKS]; for (i = 0; i < NUM_CHECKS; i++) checks[i] = FALSE; for (i = 0; i < *in_num_args; i++) { if (streq(XtNicon, in_args[i].name)) checks[ICON] = TRUE; if (streq(XtNlabel, in_args[i].name)) checks[LABEL] = TRUE; } if (checks[ICON]) { if (w->authdialog.icon != (Pixmap)0) { XtSetArg( args[0], XtNbitmap, w->authdialog.icon ); if (old->authdialog.iconW != (Widget)NULL) { XtSetValues( old->authdialog.iconW, args, ONE ); } else { XtSetArg( args[1], XtNborderWidth, 0); XtSetArg( args[2], XtNleft, XtChainLeft); XtSetArg( args[3], XtNright, XtChainLeft); w->authdialog.iconW = XtCreateWidget( "icon", labelWidgetClass, new, args, FOUR ); ((AuthDialogConstraints) w->authdialog.labelW->core.constraints)-> form.horiz_base = w->authdialog.iconW; XtManageChild(w->authdialog.iconW); } } else if (old->authdialog.icon != (Pixmap)0) { ((AuthDialogConstraints) w->authdialog.labelW->core.constraints)-> form.horiz_base = (Widget)NULL; XtDestroyWidget(old->authdialog.iconW); w->authdialog.iconW = (Widget)NULL; } } if ( checks[LABEL] ) { num_args = 0; XtSetArg( args[num_args], XtNlabel, w->authdialog.label ); num_args++; if (w->authdialog.iconW != (Widget)NULL && (w->authdialog.labelW->core.height <= w->authdialog.iconW->core.height)) { XtSetArg(args[num_args], XtNheight, w->authdialog.iconW->core.height); num_args++; } XtSetValues( w->authdialog.labelW, args, num_args ); } if ( w->authdialog.username != old->authdialog.username ) { TextFieldSetString(w->authdialog.usernameW, w->authdialog.username); w->authdialog.username = MAGIC_VALUE; } return False; } /* Function Name: CreateAuthDialogFields * Description: Creates the authdialog widgets username and password * widgets. * Arguments: w - the authdialog widget. * Returns: none. * * must be called only when w->authdialog.value is non-nil. */ static void CreateAuthDialogFields(w) Widget w; { AuthDialogWidget dw = (AuthDialogWidget) w; dw->authdialog.usernameW = XtVaCreateWidget("username", textfieldWidgetClass, w, XtNstring, dw->authdialog.username, XtNfromVert, dw->authdialog.labelW, XtNleft, XtChainLeft, XtNright, XtChainRight, NULL); XtAddCallback(dw->authdialog.usernameW, XtNactivateCallback, UsernameActivate, dw); dw->authdialog.passwordW = XtVaCreateWidget("password", textfieldWidgetClass, w, XtNecho, False, XtNfromVert, dw->authdialog.usernameW, XtNleft, XtChainLeft, XtNright, XtChainRight, NULL); XtAddCallback(dw->authdialog.passwordW, XtNactivateCallback, PasswordActivate, dw); /* if the value widget is being added after buttons, * then the buttons need new layout constraints. */ if (dw->composite.num_children > 1) { WidgetList children = dw->composite.children; Widget *childP; for (childP = children + dw->composite.num_children - 1; childP >= children; childP-- ) { if (*childP == dw->authdialog.labelW || *childP == dw->authdialog.usernameW || *childP == dw->authdialog.passwordW) continue; if (XtIsManaged(*childP) && XtIsSubclass(*childP, commandWidgetClass)) { ((AuthDialogConstraints)(*childP)->core.constraints)-> form.vert_base = dw->authdialog.passwordW; } } } XtManageChild(dw->authdialog.usernameW); XtManageChild(dw->authdialog.passwordW); /* * Value widget gets the keyboard focus. */ XtSetKeyboardFocus(w, dw->authdialog.usernameW); dw->authdialog.username = MAGIC_VALUE; } void #if NeedFunctionPrototypes AuthDialogAddButton(Widget authdialog, _Xconst char* name, XtCallbackProc function, XtPointer param) #else AuthDialogAddButton(authdialog, name, function, param) Widget authdialog; String name; XtCallbackProc function; XtPointer param; #endif { /* * Correct Constraints are all set in AuthConstraintInitialize(). */ Widget button; button = XtCreateManagedWidget( name, commandWidgetClass, authdialog, (ArgList)NULL, (Cardinal)0 ); if (function != NULL) /* don't add NULL callback func. */ XtAddCallback(button, XtNcallback, function, param); } char * #if NeedFunctionPrototypes AuthDialogGetUsername(Widget w) #else AuthDialogGetUsername(w) Widget w; #endif { return(TextFieldGetString(((AuthDialogWidget)w)->authdialog.usernameW)); } char * #if NeedFunctionPrototypes AuthDialogGetPassword(Widget w) #else AuthDialogGetPassword(w) Widget w; #endif { return(TextFieldGetString(((AuthDialogWidget)w)->authdialog.passwordW)); } /* * UsernameActivate */ static void UsernameActivate(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { AuthDialogWidget dw; dw = (AuthDialogWidget)XtParent(w); XtSetKeyboardFocus((Widget)dw, dw->authdialog.passwordW); return; } /* * PasswordActivate */ static void PasswordActivate(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { AuthDialogWidget dw; dw = (AuthDialogWidget)XtParent(w); XtCallCallbackList(XtParent(w), dw->authdialog.callbacks, (XtPointer) NULL); return; } chimera-2.0a19/mxw/AuthDialog.h100600 11610 11610 7602 6677561523 14550 0ustar johnjohn/* Modified by John */ /*********************************************************** Copyright (c) 1987, 1988, 1994 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ #ifndef _AuthDialog_h #define _AuthDialog_h #include /*********************************************************************** * * AuthDialog Widget * ***********************************************************************/ /* Parameters: Name Class RepType Default Value ---- ----- ------- ------------- background Background Pixel XtDefaultBackground border BorderColor Pixel XtDefaultForeground borderWidth BorderWidth Dimension 1 destroyCallback Callback Pointer NULL height Height Dimension computed at create icon Icon Pixmap 0 label Label String NULL mappedWhenManaged MappedWhenManaged Boolean True sensitive Sensitive Boolean True value Value String NULL width Width Dimension computed at create x Position Position 0 y Position Position 0 */ #define XtCIcon "Icon" #define XtNicon "icon" typedef struct _AuthDialogClassRec *AuthDialogWidgetClass; typedef struct _AuthDialogRec *AuthDialogWidget; extern WidgetClass authdialogWidgetClass; extern void AuthDialogAddButton( #if NeedFunctionPrototypes Widget /* authdialog */, _Xconst char* /* name */, XtCallbackProc /* function */, XtPointer /* client_data */ #endif ); extern char *AuthDialogGetUsername( #if NeedFunctionPrototypes Widget /* w */ #endif ); extern char *AuthDialogGetPassword( #if NeedFunctionPrototypes Widget /* w */ #endif ); #endif /* _AuthDialog_h */ chimera-2.0a19/mxw/TextFieldP.h100600 11610 11610 6607 6677561525 14545 0ustar johnjohn/*----------------------------------------------------------------------------- * TextField A single line text entry widget * * Copyright (c) 1995 Robert W. McMullen * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Author: Rob McMullen * http://www.ae.utexas.edu/~rwmcm */ #ifndef _TextFieldP_H #define _TextFieldP_H #include #include "TextField.h" #define TEXTFIELD_ALLOC_SIZE 256 typedef struct { int dummy; /* keep compiler happy with dummy field */ } TextFieldClassPart; typedef struct _TextFieldClassRec { CoreClassPart core_class; TextFieldClassPart TextField_class; } TextFieldClassRec; extern TextFieldClassRec textfieldClassRec; typedef struct { /* Public stuff ... */ long foreground_pixel; /* data storage for resources ... */ long cursor_pixel; XFontStruct *font; Dimension Margin; int TextMaxLen; Boolean Echo; Boolean Editable; Boolean DisplayCursor; Boolean AllowSelection; Boolean PendingDelete; char *DefaultString; XtCallbackList ActivateCallback; /* Private stuff ... */ GC drawGC; /* GC for drawing and copying */ GC highlightGC; /* GC for highlighting text */ GC cursorGC; /* GC for cursor (not clipped like drawGC) */ GC dashGC; /* GC for cursor when we don't have focus */ GC eraseGC; /* GC for erasing (not clipped) */ int CursorPos; /* text position of cursor */ int OldCursorPos; /* previous position */ int OldCursorX; /* previous pixel pos of cursor */ int HighlightStart; /* text pos of leftmost highlight pos */ int HighlightEnd; /* text pos of rightmost highlight pos */ int HighlightPivotStart; /* left pivot pos for ExtendHighlight */ int HighlightPivotEnd; /* right ... */ int OldHighlightStart; /* save data */ int OldHighlightEnd; char *Text; /* pointer to the text */ int TextAlloc; /* number of bytes allocated for the text */ int TextLen; /* current length of text */ char *SelectionText; /* pointer to text selection, when needed */ int SelectionLen; /* length */ int FastInsertCursorStart; /* data storage for some text optimization */ int FastInsertTextLen; Dimension ViewWidth; /* visible width of widget */ int XOffset; /* offset from x=0 to start of text string */ int OldXOffset; int YOffset; /* y pixel offset to baseline of font */ int TextWidth; /* char width of text */ int OldTextWidth; XtIntervalId timer_id; /* timer for double click test */ int timer_x; /* save event x pos */ int highlight_time; /* time delay for scrolling */ int multi_click_time; /* local storage for XtGetMultiClickTime */ } TextFieldPart; typedef struct _TextFieldRec { CorePart core; TextFieldPart text; } TextFieldRec; #endif /* _TextFieldP_H */ chimera-2.0a19/mxw/AuthDialogP.h100600 11610 11610 7423 6677561527 14675 0ustar johnjohn/* Modified by john */ /*********************************************************** Copyright (c) 1987, 1988 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* Private definitions for AuthDialog widget */ #ifndef _AuthDialogP_h #define _AuthDialogP_h #include "AuthDialog.h" #include typedef struct {int empty;} AuthDialogClassPart; typedef struct _AuthDialogClassRec { CoreClassPart core_class; CompositeClassPart composite_class; ConstraintClassPart constraint_class; FormClassPart form_class; AuthDialogClassPart authdialog_class; } AuthDialogClassRec; extern AuthDialogClassRec authdialogClassRec; typedef struct _AuthDialogPart { /* resources */ String label; /* description of the authdialog */ String username; /* username string */ Pixmap icon; /* icon bitmap */ XtCallbackList callbacks; /* callbacks */ /* private data */ Widget iconW; /* widget to display the icon */ Widget labelW; /* widget to display description*/ Widget usernameW; /* username textfield */ Widget passwordW; /* password textfield */ } AuthDialogPart; typedef struct _AuthDialogRec { CorePart core; CompositePart composite; ConstraintPart constraint; FormPart form; AuthDialogPart authdialog; } AuthDialogRec; typedef struct {int empty;} AuthDialogConstraintsPart; typedef struct _AuthDialogConstraintsRec { FormConstraintsPart form; AuthDialogConstraintsPart authdialog; } AuthDialogConstraintsRec, *AuthDialogConstraints; #endif /* _AuthDialogP_h */ chimera-2.0a19/html/ 40700 11610 11610 0 6724372006 12370 5ustar johnjohnchimera-2.0a19/html/hr.c100600 11610 11610 3374 6677561542 13267 0ustar johnjohn/* * hr.c * * libhtml - HTML->X renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" #define HR_HEIGHT 20 #define HR_HALF_HEIGHT 10 /* * * Private functions * */ static void RenderHR _ArgProto((HTMLInfo, HTMLBox, Region)); /* * RenderHR */ static void RenderHR(li, box, r) HTMLInfo li; HTMLBox box; Region r; { XSetLineAttributes(li->dpy, li->gc, 1, LineSolid, CapNotLast, JoinRound); XDrawLine(li->dpy, li->win, li->gc, box->x, box->y + HR_HALF_HEIGHT, box->x + box->width, box->y + HR_HALF_HEIGHT); return; } /* * * Public Functions * */ /* * HandleHR */ void HTMLHorizontalRule(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLBox box; HTMLAddLineBreak(li, env); box = HTMLCreateBox(li, env); box->render = RenderHR; box->width = HTMLGetMaxWidth(li, env); box->height = HR_HEIGHT; HTMLEnvAddBox(li, env, box); HTMLAddLineBreak(li, env); return; } chimera-2.0a19/html/Imakefile100600 11610 11610 1265 6677561543 14321 0ustar johnjohn#include <../Common.tmpl> HEADERS = html.h htmltags.h SRCS = module.c html.c layout.c text.c misc.c font.c load.c flow.c \ head.c inline.c list.c form.c hr.c table.c map.c frame.c \ css.c OBJS = module.o html.o layout.o text.o misc.o font.o load.o flow.o \ head.o inline.o list.o form.o hr.o table.o map.o frame.o \ css.o EXTRA_DEFINES = $(CHIMERA_DEFINES) EXTRA_INCLUDES = -I../port -I../mxw -I../common -I../chimera NormalLibraryTarget(xhtml, $(OBJS)) cssxxx.o: css.c css.h $(CC) -c $(CDEBUGFLAGS) -DCSSDEBUG $(EXTRA_DEFINES) $(EXTRA_INCLUDES) css.c -o $@ csstest: cssxxx.o $(CC) cssxxx.o $(CHIMERA_LIBS) -o $@ DependTarget() install.man:: chimera-2.0a19/html/frame.c100600 11610 11610 25276 6724333527 13766 0ustar johnjohn/* * frame.c * * libhtml - HTML->X renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" #include "ChimeraStack.h" #define LASTRESORTSIZE 100 typedef struct HTMLFrameInfoP *HTMLFrameInfo; typedef struct HTMLFrameSetInfoP *HTMLFrameSetInfo; typedef struct HTMLFrameSizeP *HTMLFrameSize; struct HTMLFrameSizeP { unsigned int size; }; struct HTMLFrameInfoP { HTMLInfo li; HTMLBox box; ChimeraStack cs; ChimeraRequest *wr; int x, y; unsigned int width, height; char *name; HTMLFrameSetInfo fset; }; struct HTMLFrameSetInfoP { HTMLInfo li; bool horiz; GList sizes; GList frames; unsigned int other_size; HTMLFrameSize current_size; int x, y; }; static void SetupIFrame _ArgProto((HTMLInfo, HTMLBox)); static void DestroyIFrame _ArgProto((HTMLInfo, HTMLBox)); static GList GetSizes _ArgProto((HTMLInfo, char *, unsigned int)); /* not used static void FrameRenderAction _ArgProto((void *, ChimeraRender, ChimeraRequest *, char *)); static HTMLFrameInfo FindNamedFrame _ArgProto((HTMLInfo, char *)); */ /* * * ignores all the usual layout methods and * blasts the frames right onto the window. No point in messing * around with that stuff. The old-style frames are evil. * */ /* * SetupIFrame */ static void SetupIFrame(li, box) HTMLInfo li; HTMLBox box; { HTMLFrameInfo fi = (HTMLFrameInfo)box->closure; fi->cs = StackCreate(StackFromGUI(li->wc, li->wd), box->x, box->y, box->width, box->height, NULL, NULL); StackOpen(fi->cs, fi->wr); return; } /* * DestroyIFrame */ static void DestroyIFrame(li, box) HTMLInfo li; HTMLBox box; { HTMLFrameInfo fi = (HTMLFrameInfo)box->closure; if (fi->cs != NULL) StackDestroy(fi->cs); return; } /* * HTMLIFrame */ void HTMLIFrame(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLBox box; HTMLAttribID aid; HTMLFrameInfo fi; int width, height; char *url; ChimeraRequest *wr; if ((url = MLFindAttribute(p, "src")) == NULL) return; if ((wr = RequestCreate(li->cres, url, NULL)) == NULL) return; fi = (HTMLFrameInfo)MPCGet(li->mp, sizeof(struct HTMLFrameInfoP)); if ((width = MLAttributeToInt(p, "width")) < 0) width = 500; if ((height = MLAttributeToInt(p, "height")) < 0) height = 500; box = HTMLCreateBox(li, env); aid = HTMLAttributeToID(p, "align"); if (aid == ATTRIB_MIDDLE) box->baseline = height / 2; else if (aid == ATTRIB_TOP) box->baseline = 0; else if (aid == ATTRIB_LEFT) HTMLSetB(box, BOX_FLOAT_LEFT); else if (aid == ATTRIB_RIGHT) HTMLSetB(box, BOX_FLOAT_RIGHT); else box->baseline = height; box->setup = SetupIFrame; box->destroy = DestroyIFrame; box->width = width; box->height = height; box->closure = fi; fi->box = box; fi->li = li; fi->wr = wr; HTMLEnvAddBox(li, env, box); return; } /* * HTMLFrameInsert */ HTMLInsertStatus HTMLFrameInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { if (HTMLTagToID(env->tag) != TAG_FRAMESET) return(HTMLInsertReject); return(HTMLInsertOK); } /* * HTMLFrame */ void HTMLFrame(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLFrameInfo fi; char *url; ChimeraRequest *wr; HTMLFrameSetInfo fset; unsigned int size; fset = (HTMLFrameSetInfo)env->closure; if ((url = MLFindAttribute(p, "src")) == NULL) return; if ((wr = RequestCreate(li->cres, url, li->burl)) == NULL) return; fi = (HTMLFrameInfo)MPCGet(li->mp, sizeof(struct HTMLFrameInfoP)); fi->li = li; fi->wr = wr; fi->box = HTMLCreateBox(li, env); fi->box->destroy = DestroyIFrame; fi->box->closure = fi; fi->x = fset->x; fi->y = fset->y; fi->name = MLFindAttribute(p, "name"); fi->fset = fset; if (fset->current_size == NULL) size = LASTRESORTSIZE; else size = fset->current_size->size; if (fset->horiz) { fi->width = size; fi->height = fset->other_size; fset->x += size; } else { fi->width = fset->other_size; fi->height = size; fset->y += size; } GListAddHead(fset->frames, fi); fset->current_size = (HTMLFrameSize)GListGetNext(fset->sizes); return; } /* * HTMLFrameSetAccept */ bool HTMLFrameSetAccept(li, obj) HTMLInfo li; HTMLObject obj; { HTMLTag tag; if (obj->type == HTML_ENV && HTMLTagToID(obj->o.env->tag) != TAG_FRAMESET) { return(true); } if (obj->type == HTML_TAG) { if ((tag = HTMLGetTag(obj->o.p)) != NULL && HTMLTagToID(tag) == TAG_FRAME) { return(true); } } return(true); } /* * HTMLFrameSetInsert */ HTMLInsertStatus HTMLFrameSetInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv c; HTMLTagID tid; /* * Quick and dirty way to kill off frames from another location. */ if (li->noframeset) return(HTMLInsertReject); li->framesonly = true; for (c = (HTMLEnv)GListGetHead(li->envstack); c != NULL; c = (HTMLEnv)GListGetNext(li->envstack)) { tid = HTMLTagToID(c->tag); if (tid != TAG_FRAMESET && tid != TAG_HTML && tid != TAG_DOCUMENT) { return(HTMLInsertReject); } } return(HTMLInsertOK); } /* * GetSizes */ static GList GetSizes(li, s, len) HTMLInfo li; char *s; unsigned int len; { char *cp; GList list; HTMLFrameSize size; int x; int totalpc; list = GListCreateX(li->mp); size = MPGet(li->mp, sizeof(struct HTMLFrameSizeP)); totalpc = x = atoi(s); if (x <= 0) size->size = LASTRESORTSIZE; else size->size = len * x / 100; GListAddHead(list, size); for (cp = s; *cp != '\0'; cp++) { if (*cp == ',') { size = MPGet(li->mp, sizeof(struct HTMLFrameSizeP)); if (*(cp+1) == '*') x = 100 - totalpc; else x = atoi(cp + 1); x = atoi(cp + 1); if (x <= 0) x = 10; size->size = len * x / 100; GListAddTail(list, size); } } return(list); } /* * HTMLFrameSetBegin */ void HTMLFrameSetBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLFrameSetInfo pfset, fset; char *sizestr; unsigned int width, height; GUISetScrollBar(li->wd, false); GUIGetDimensions(li->wd, &width, &height); fset = (HTMLFrameSetInfo)MPCGet(li->mp, sizeof(struct HTMLFrameSetInfoP)); env->closure = fset; fset->frames = GListCreateX(li->mp); if ((sizestr = MLFindAttribute(p, "rows")) != NULL) { fset->horiz = false; fset->sizes = GetSizes(li, sizestr, height); } else if ((sizestr = MLFindAttribute(p, "cols")) != NULL) { fset->horiz = true; fset->sizes = GetSizes(li, sizestr, width); } else { fset->horiz = false; fset->sizes = GListCreateX(li->mp); } if (HTMLTagToID(env->penv->tag) == TAG_FRAMESET) { /* * Frameset inside a frameset so look at the parent to see if there * is a size given. */ pfset = (HTMLFrameSetInfo)env->penv->closure; if (pfset->current_size == NULL) fset->other_size = LASTRESORTSIZE; else { fset->other_size = pfset->current_size->size; pfset->current_size = (HTMLFrameSize)GListGetNext(pfset->sizes); fset->x = pfset->x; fset->y = pfset->y; if (pfset->horiz) pfset->x += fset->other_size; else pfset->y += fset->other_size; } } else { /* * Must be first frameset */ if (fset->horiz) fset->other_size = width; else fset->other_size = height; } fset->current_size = (HTMLFrameSize)GListGetHead(fset->sizes); GListAddHead(li->framesets, fset); return; } /* * HTMLFrameSetEnd */ void HTMLFrameSetEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLFrameInfo fi; HTMLFrameSetInfo fset = (HTMLFrameSetInfo)env->closure; for (fi = (HTMLFrameInfo)GListGetHead(fset->frames); fi != NULL; fi = (HTMLFrameInfo)GListGetNext(fset->frames)) { fi->cs = StackCreate(StackFromGUI(li->wc, li->wd), fi->x, fi->y, fi->width, fi->height, NULL, NULL); StackOpen(fi->cs, fi->wr); } return; } /* * HTMLNoFramesBegin */ void HTMLNoFramesBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { return; } /* * HTMLNoFramesEnd */ void HTMLNoFramesEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { return; } /* * HTMLDestroyFrameSets */ void HTMLDestroyFrameSets(li) HTMLInfo li; { HTMLFrameInfo fi; HTMLFrameSetInfo fset; for (fset = (HTMLFrameSetInfo)GListGetHead(li->framesets); fset != NULL; fset = (HTMLFrameSetInfo)GListGetNext(li->framesets)) { for (fi = (HTMLFrameInfo)GListGetHead(fset->frames); fi != NULL; fi = (HTMLFrameInfo)GListGetNext(fset->frames)) { StackDestroy(fi->cs); } } return; } /* * FindNamedFrame */ /* not used static HTMLFrameInfo FindNamedFrame(li, name) HTMLInfo li; char *name; { HTMLFrameSetInfo fset; HTMLFrameInfo fi; for (fset = (HTMLFrameSetInfo)GListGetHead(li->framesets); fset != NULL; fset = (HTMLFrameSetInfo)GListGetNext(li->framesets)) { for (fi = (HTMLFrameInfo)GListGetHead(fset->frames); fi != NULL; fi = (HTMLFrameInfo)GListGetNext(fset->frames)) { if (fi->name != NULL && strlen(fi->name) == strlen(name) && strcasecmp(fi->name, name) == 0) { return(fi); } } } return(NULL); } */ /* * HTMLFrameLoad * * This could fail in silly ways if there are multiple frames with the * same name. Worry about this later. */ void HTMLFrameLoad(li, wr, target) HTMLInfo li; ChimeraRequest *wr; char *target; { HTMLInfo hi; HTMLFrameSetInfo fset; HTMLFrameInfo fi; for (hi = (HTMLInfo)GListGetHead(li->lc->contexts); hi != NULL; hi = (HTMLInfo)GListGetNext(li->lc->contexts)) { for (fset = (HTMLFrameSetInfo)GListGetHead(hi->framesets); fset != NULL; fset = (HTMLFrameSetInfo)GListGetNext(hi->framesets)) { for (fi = (HTMLFrameInfo)GListGetHead(fset->frames); fi != NULL; fi = (HTMLFrameInfo)GListGetNext(fset->frames)) { if (fi->name != NULL && strlen(fi->name) == strlen(target) && strcasecmp(fi->name, target) == 0) { StackOpen(fi->cs, wr); } } } } return; } chimera-2.0a19/html/table.c100600 11610 11610 43117 6677561555 13770 0ustar johnjohn/* * table.c * * libhtml - HTML->X renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" typedef struct { HTMLBox box; unsigned int width; int rowspan, colspan; } HData; typedef struct { bool original; int rowspan, colspan; HData *ds; int rowspan2, colspan2; HData *ds2; } HCell; typedef struct { GList datas; int colcount; HCell *ca; } HRow; typedef struct { MemPool mp; unsigned int border; /* table border width */ HTMLBox box; /* table box */ HTMLBox dbox; /* current data box */ MLElement p; /* table tag element */ GList grid; /* grid of rows and data */ GList klist; /* list of kids */ int rowcount, colcount; /* nearly always greater than real */ int pass; unsigned int *cwidth, *rheight; /* column widths, row heights */ unsigned int *swidth; /* scaled columns widths */ unsigned int max_width; /* width available for table */ unsigned int inf_width; /* width with unbounded table size */ } HTable; /* * Private functions */ static void DestroyTable _ArgProto((HTMLInfo, HTMLBox)); static void SetupTable _ArgProto((HTMLInfo, HTMLBox)); static void RenderTable _ArgProto((HTMLInfo, HTMLBox, Region)); static void TablePosition1 _ArgProto((HTable *)); static void TablePosition2 _ArgProto((HTable *)); static void FillSpans _ArgProto((HTable *)); /* * SetupTable * * Called when the position of the table is known. Now set the location * of the child boxes and arrange to have their setup function called. */ static void SetupTable(li, box) HTMLInfo li; HTMLBox box; { int i, j; HRow *rs; HData *ds; int bx, by; HTable *ts = (HTable *)box->closure; bx = 0; by = 0; for (j = 0, rs = (HRow *)GListGetHead(ts->grid); rs != NULL; rs = (HRow *)GListGetNext(ts->grid), j++) { if (rs->ca == NULL) continue; for (i = 0; i < ts->colcount; i++) { if (rs->ca[i].ds != NULL && rs->ca[i].original) { ds = rs->ca[i].ds; ds->box->x = bx + box->x; ds->box->y = by + box->y; HTMLSetupBox(li, ds->box); bx += ts->cwidth[i]; } else { bx += ts->cwidth[i]; } } bx = 0; by += ts->rheight[j]; } return; } /* * RenderTable * * Called when the table has been exposed. Since the child boxes * will handle their own refresh only need to refresh the border if * there is one. */ static void RenderTable(li, box, r) HTMLInfo li; HTMLBox box; Region r; { HTable *ts = (HTable *)box->closure; HTMLBox c; for (c = (HTMLBox)GListGetHead(ts->klist); c != NULL; c = (HTMLBox)GListGetNext(ts->klist)) { HTMLRenderBox(li, r, c); } return; } /* * DestroyTable */ static void DestroyTable(li, box) HTMLInfo li; HTMLBox box; { HTable *ts = (HTable *)box->closure; HTMLBox c; while ((c = (HTMLBox)GListPop(ts->klist)) != NULL) { HTMLDestroyBox(li, c); } return; } /* * HTMLTableAddBox */ void HTMLTableAddBox(li, env, box) HTMLInfo li; HTMLEnv env; HTMLBox box; { return; } /* * HTMLTDAddBox */ void HTMLTDAddBox(li, env, box) HTMLInfo li; HTMLEnv env; HTMLBox box; { HTable *ts = (HTable *)env->closure; HTMLLayoutBox(li, ts->dbox, box); return; } /* * HTMLTDBegin * * Called when a tag is encountered */ void HTMLTDBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTable *ts; HRow *rs; HData *ds; ts = (HTable *)env->penv->closure; env->closure = ts; if (ts->pass == 0) { rs = (HRow *)GListGetTail(ts->grid); myassert(rs != NULL, "Could not find row data (1)."); ds = (HData *)MPCGet(ts->mp, sizeof(HData)); if (p == NULL) { ds->colspan = 1; ds->rowspan = 1; } else { if ((ds->colspan = MLAttributeToInt(p, "colspan")) < 1) ds->colspan = 1; if ((ds->rowspan = MLAttributeToInt(p, "rowspan")) < 1) ds->rowspan = 1; } GListAddTail(rs->datas, ds); rs->colcount += ds->colspan; if (rs->colcount > ts->colcount) ts->colcount = rs->colcount; /* this is more than the real count but that's ok. */ ts->rowcount += ds->rowspan; ts->dbox = ds->box = HTMLCreateFlowBox(li, env, li->tableCellInfinity); } else { rs = (HRow *)GListGetCurrent(ts->grid); myassert(rs != NULL, "Could not find row data (2)."); ds = (HData *)GListGetCurrent(rs->datas); myassert(ds != NULL, "Could not find cell data (2)."); ts->dbox = ds->box = HTMLCreateFlowBox(li, env, ds->width); } GListAddHead(ts->klist, ds->box); return; } /* * HTMLTDEnd * * Called when a tag is encountered */ void HTMLTDEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTable *ts = (HTable *)env->closure; HRow *rs; HTMLFinishFlowBox(li, ts->dbox); if (ts->pass > 0) { rs = (HRow *)GListGetCurrent(ts->grid); GListGetNext(rs->datas); } return; } /* * HTMLTRBegin */ void HTMLTRBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTable *ts; HRow *rs; ts = (HTable *)env->penv->closure; env->closure = ts; if (ts->pass == 0) { rs = (HRow *)MPCGet(ts->mp, sizeof(HRow)); GListAddTail(ts->grid, rs); rs->datas = GListCreateX(ts->mp); } else { rs = (HRow *)GListGetCurrent(ts->grid); GListGetHead(rs->datas); } return; } /* * HTMLTREnd */ void HTMLTREnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTable *ts; ts = (HTable *)env->penv->closure; env->closure = ts; if (ts->pass > 0) GListGetNext(ts->grid); return; } /* * HTMLTableBegin * * Called when is encountered. Has to deal with two passes. */ void HTMLTableBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLBox box; HTable *ts; char *value, *cp; int x; int border; unsigned int width, maxwidth; maxwidth = width = HTMLGetMaxWidth(li, env->penv); env->ff = FLOW_LEFT_JUSTIFY; env->anchor = NULL; if (env->closure == NULL) { ts = (HTable *)MPCGet(li->mp, sizeof(HTable)); ts->mp = li->mp; ts->p = p; env->closure = ts; if ((border = MLAttributeToInt(p, "border")) < 0) border = 0; ts->border = border; ts->grid = GListCreateX(ts->mp); ts->klist = GListCreateX(li->mp); if ((value = MLFindAttribute(p, "width")) != NULL) { if (isdigit(value[0])) { x = atoi(value); for (cp = value; ; cp++) { if (!isdigit(*cp)) break; } if (*cp != '\0') { if (*cp == '%') { if (x >= 10) width = width * x / 100; } else if (x >= 100) width = x; } else if (x >= 100) width = x; } } if (width > 0) ts->max_width = width; else ts->max_width = 0; } else { ts = (HTable *)env->closure; GListGetHead(ts->grid); GListClear(ts->klist); } ts->pass = env->pass; /* * Create the table box */ ts->box = box = HTMLCreateBox(li, env); box->setup = SetupTable; box->render = RenderTable; box->destroy = DestroyTable; box->closure = ts; return; } /* * HTMLTableEnd * * Called when
is encountered. Has to deal with two passes. */ void HTMLTableEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTable *ts = (HTable *)env->closure; if (ts->colcount == 0) return; if (ts->pass == 0) { /* * Do first pass size calculations. */ FillSpans(ts); TablePosition1(ts); /* * Now destroy the table box and its children since we need to rebuild * from scratch. */ HTMLDestroyBox(li, ts->box); ts->box = NULL; } else { TablePosition2(ts); HTMLEnvAddBox(li, env->penv, ts->box); } return; } /* * FillSpans */ static void FillSpans(ts) HTable *ts; { HRow *rs; HData *ds; int i, j, k; HCell *pca; ts->colcount *= 2; /* * Allocate an array for each row to keep track of the data grid. */ for (k = 0, rs = (HRow *)GListGetHead(ts->grid); rs != NULL; rs = (HRow *)GListGetNext(ts->grid), k++) { rs->ca = (HCell *)MPCGet(ts->mp, sizeof(HCell) * ts->colcount); } /* * Its possible rowspan has pushed things down a bit so add rows as * necessary. Overkill is OK. */ for (; k < ts->rowcount; k++) { rs = (HRow *)MPCGet(ts->mp, sizeof(HRow)); GListAddTail(ts->grid, rs); rs->datas = GListCreateX(ts->mp); rs->ca = (HCell *)MPCGet(ts->mp, sizeof(HCell) * ts->colcount); } /* * Put the data into the grids according to rowspan and colspan. */ pca = NULL; for (rs = (HRow *)GListGetHead(ts->grid); rs != NULL; rs = (HRow *)GListGetNext(ts->grid)) { /* * If there is a previous row then look at the HCell's above and * see if they need to be extended. We know the HCell above needs to * be extended down if rowspan > 1. Move rowspan - 1 down to the * current row. Also, move the colspan * value down (its not used, though) and the HData pointer. */ if (pca != NULL) { for (i = 0; i < ts->colcount; i++) { if (pca[i].ds != NULL && pca[i].rowspan > 1) { myassert(rs->ca[i].ds == NULL, "Cell visitation unexpected!"); rs->ca[i].rowspan = pca[i].rowspan - 1; rs->ca[i].colspan = pca[i].colspan; rs->ca[i].ds = pca[i].ds; } if (pca[i].ds2 != NULL && pca[i].rowspan2 > 1) { myassert(rs->ca[i].ds == NULL, "Cell visitation unexpected! (2)"); rs->ca[i].rowspan = pca[i].rowspan2 - 1; rs->ca[i].colspan = pca[i].colspan2; rs->ca[i].ds = pca[i].ds2; } } } /* * Now extend HData to the right depending on the colspan. */ for (ds = (HData *)GListGetHead(rs->datas); ds != NULL; ds = (HData *)GListGetNext(rs->datas)) { /* * Scan to the right and look for the first empty HCell. This needs * to be done because an HData above could have spanned down to fill * in the beginning of the row. * * This has to be done for each data section because a row that * was extended down may have used up space in the middle of the * row. */ for (i = 0; i < ts->colcount; i++) { if (rs->ca[i].ds == NULL) break; } myassert(ts->colcount != i, "Table column count confused."); rs->ca[i].original = true; for (j = 0; j < ds->colspan; j++, i++) { if (rs->ca[i].ds == NULL) { rs->ca[i].ds = ds; rs->ca[i].colspan = ds->colspan - j; rs->ca[i].rowspan = ds->rowspan; } else { rs->ca[i].ds2 = ds; rs->ca[i].colspan2 = ds->colspan - j; rs->ca[i].rowspan2 = ds->rowspan; } } } pca = rs->ca; } /* * Test code. Print out patterns to see if the internal representation * looks reasonable. */ /* for (rs = (HRow *)GListGetHead(ts->grid); rs != NULL; rs = (HRow *)GListGetNext(ts->grid)) { for (i = 0; i < ts->colcount; i++) { if (rs->ca[i].ds2 != NULL) printf ("o"); else if (rs->ca[i].ds != NULL && rs->ca[i].original) { printf ("%c", (char )((int)('A') + i)); } else if (rs->ca[i].ds != NULL) printf ("%c", (char )((int)('a') + i)); else printf ("x"); } printf("\n"); } */ return; } /* * TablePosition1 */ static void TablePosition1(ts) HTable *ts; { int i, j; HRow *rs; HData *ds; unsigned int twidth, width; /* * Allocate arrays to hold the column widths and row heights. * * cwidth = column width * swidth = scaled column width * rheight = row height */ ts->cwidth = (unsigned int *)MPCGet(ts->mp, sizeof(unsigned int) * ts->colcount); ts->swidth = (unsigned int *)MPCGet(ts->mp, sizeof(unsigned int) * ts->colcount); ts->rheight = (unsigned int *)MPCGet(ts->mp, sizeof(unsigned int) * ts->rowcount); /* * Figure out the unrestrained widths of the columns. Needed a little * later to determine the width of the table. */ twidth = 0; for (rs = (HRow *)GListGetHead(ts->grid); rs != NULL; rs = (HRow *)GListGetNext(ts->grid)) { for (i = 0; i < ts->colcount; i++) { if (rs->ca[i].ds != NULL) { ds = rs->ca[i].ds; width = ds->box->width / ds->colspan; if (width > ts->cwidth[i]) ts->cwidth[i] = width; } if (rs->ca[i].ds2 != NULL) { ds = rs->ca[i].ds2; width = ds->box->width / ds->colspan; if (width > ts->cwidth[i]) ts->cwidth[i] = width; } } } /* * Determine the width of the unrestrained table. */ twidth = 0; for (i = 0; i < ts->colcount; i++) { twidth += ts->cwidth[i]; } if (twidth > 0 && twidth > ts->max_width) { /* * Now scale the columns to fit in the space available attempting to keep * things in proportion. */ for (i = 0; i < ts->colcount; i++) { ts->swidth[i] = ts->max_width * ts->cwidth[i] / twidth; } } else { /* * No size problems so just copy the widths as-is. */ for (i = 0; i < ts->colcount; i++) { ts->swidth[i] = ts->cwidth[i]; } } /* * Finally, figure out the widths of individual cells. */ for (rs = (HRow *)GListGetHead(ts->grid); rs != NULL; rs = (HRow *)GListGetNext(ts->grid)) { for (i = 0; i < ts->colcount; i++) { if (rs->ca[i].ds != NULL && rs->ca[i].original) { /* * Add in the widths of all the columns for a column spanning * cell. */ ds = rs->ca[i].ds; for (j = 0; j + i < ts->colcount && j < ds->colspan; j++) { ds->width += ts->swidth[i + j]; } } } } return; } /* * TablePosition2 */ static void TablePosition2(ts) HTable *ts; { int i, j; unsigned int width, height; HRow *rs; HData *ds; memset(ts->cwidth, 0, ts->colcount * sizeof(unsigned int)); memset(ts->rheight, 0, ts->rowcount * sizeof(unsigned int)); /* * Get the columns widths and row heights for the restrained table * (second pass). */ for (j = 0, rs = (HRow *)GListGetHead(ts->grid); rs != NULL; rs = (HRow *)GListGetNext(ts->grid), j++) { for (i = 0; i < ts->colcount; i++) { if (rs->ca[i].ds != NULL) { ds = rs->ca[i].ds; width = ds->box->width / ds->colspan; if (width > ts->cwidth[i]) ts->cwidth[i] = width; height = ds->box->height / ds->rowspan; if (height > ts->rheight[j]) ts->rheight[j] = height; } if (rs->ca[i].ds2 != NULL) { ds = rs->ca[i].ds2; width = ds->box->width / ds->colspan; if (width > ts->cwidth[i]) ts->cwidth[i] = width; height = ds->box->height / ds->rowspan; if (height > ts->rheight[j]) ts->rheight[j] = height; } } } /* * Find the final width and height of the table. */ width = 0; height = 0; for (i = 0; i < ts->colcount; i++) { width += ts->cwidth[i]; } for (i = 0; i < ts->rowcount; i++) { height += ts->rheight[i]; } ts->box->width = width; ts->box->height = height; return; } /* * HTMLTableAccept */ bool HTMLTableAccept(li, obj) HTMLInfo li; HTMLObject obj; { if (obj->type != HTML_ENV) return(false); if (HTMLTagToID(obj->o.env->tag) != TAG_TR) return(false); return(true); } /* * HTMLTRAccept */ bool HTMLTRAccept(li, obj) HTMLInfo li; HTMLObject obj; { HTMLTagID tagid; if (obj->type != HTML_ENV) return(false); tagid = HTMLTagToID(obj->o.env->tag); if (tagid != TAG_TD && tagid != TAG_TH) return(false); return(true); } /* * HTMLTDInsert */ HTMLInsertStatus HTMLTDInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv c; HTMLTagID tid; for (c = (HTMLEnv)GListGetHead(li->envstack); c != NULL; c = (HTMLEnv)GListGetNext(li->envstack)) { tid = HTMLTagToID(c->tag); if (tid == TAG_TABLE || tid == TAG_TR) break; } if (c == NULL) return(HTMLInsertReject); else if (tid == TAG_TABLE) HTMLStartEnv(li, TAG_TR, NULL); else HTMLPopEnv(li, TAG_TR); return(HTMLInsertOK); } /* * HTMLTDClamp */ bool HTMLTDClamp(li, env) HTMLInfo li; HTMLEnv env; { HTMLEnv c; HTMLTagID tid; for (c = (HTMLEnv)GListGetHead(li->envstack); c != NULL; c = (HTMLEnv)GListGetNext(li->envstack)) { tid = HTMLTagToID(c->tag); if (tid == TAG_TABLE || tid == TAG_TD) break; } if (c == NULL) return(false); else if (tid == TAG_TABLE) return(false); return(true); } /* * HTMLTRInsert */ HTMLInsertStatus HTMLTRInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv tenv; if ((tenv = HTMLFindEnv(li, TAG_TABLE)) == NULL) return(HTMLInsertReject); HTMLPopEnv(li, TAG_TABLE); return(HTMLInsertOK); } /* * HTMLTRClamp */ bool HTMLTRClamp(li, env) HTMLInfo li; HTMLEnv env; { HTMLEnv c; HTMLTagID tid; for (c = (HTMLEnv)GListGetHead(li->envstack); c != NULL; c = (HTMLEnv)GListGetNext(li->envstack)) { tid = HTMLTagToID(c->tag); if (tid == TAG_TABLE || tid == TAG_TR) break; } if (c == NULL) return(false); else if (tid == TAG_TABLE) return(false); return(true); } /* * HTMLTDWidth */ unsigned int HTMLTDWidth(li, env) HTMLInfo li; HTMLEnv env; { HTable *ts = (HTable *)env->closure; return(HTMLGetBoxWidth(li, ts->dbox)); } chimera-2.0a19/html/css.c100600 11610 11610 35636 6724334152 13460 0ustar johnjohn/* * css.c * * Copyright (c) 1998, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "common.h" #include "Chimera.h" #include "css.h" struct CSSPropertyP { CSSRule cr; char *name; char *value; }; struct CSSSelectorP { char *tag; char *id; char *class; char *pclass; }; struct CSSRuleP { GList selectors; /* list of lists of CSSSelector's */ GList properties; /* list of CSSProperty's */ }; /* * Used to keep track of which buffer to take input from. Since new * text can be inserted at any time have to be able to store and restore * buffer context. */ struct CSSInputP { char *b; size_t blen; char *cp; char *ep; }; struct CSSContextP { MemPool mp; ChimeraContext cs; /* parser bookkeeping */ GList inputs; /* The Result: a list of rules and properties */ GList rules; GList props; /* callback information */ CSSProc proc; void *closure; ChimeraTask task; }; typedef struct CSSInputP *CSSInput; static char *ParseSpace _ArgProto((char *, char *)); static CSSSelector ParseSelector2 _ArgProto((MemPool, char *, size_t)); static GList ParseSelector1 _ArgProto((MemPool, char *, size_t)); static GList ParseSelector _ArgProto((MemPool, char *, size_t)); static CSSProperty ParseProperty _ArgProto((MemPool, char *, size_t)); static GList ParseProperties _ArgProto((MemPool, char *, size_t)); static bool ParseRule _ArgProto((CSSContext, CSSInput)); static bool ParseAt _ArgProto((CSSContext, CSSInput)); static void ParseCSS _ArgProto((CSSContext)); static int scompare _ArgProto((char *, char *)); static bool SelectorListMatch _ArgProto((GList, GList)); static char *ParseToChar _ArgProto((char *, char *, int, bool)); /* * ParseToChar * * Search for an expected character. Deals with escaped characters, * quoted strings, and pairs of braces/parens/brackets. */ static char * ParseToChar(cp, ep, c, chkws) char *cp, *ep; int c; bool chkws; { bool sq, dq, esc; sq = false; /* in single quote? */ dq = false; /* in double quote? */ esc = false; /* escape mode? */ while (cp < ep) { if (esc) esc = false; else if (*cp == '\\') esc = true; else if (dq && *cp != '"') dq = false; else if (sq && *cp != '\'') sq = false; else if (*cp == '"') dq = true; else if (*cp == '\'') sq = true; else if (*cp == c) return(cp); else if (chkws && isspace8(*cp)) return(cp); else if (*cp == '{') { if ((cp = ParseToChar(cp + 1, ep, '}', false)) == NULL) return(NULL); } else if (*cp == '(') { if ((cp = ParseToChar(cp + 1, ep, ')', false)) == NULL) return(NULL); } else if (*cp == '[') { if ((cp = ParseToChar(cp + 1, ep, ']', false)) == NULL) return(NULL); } cp++; } return(NULL); } /* * ParseAt * * This is lame. Handle @ statements later. * * Return false if @import occured. Return true if not. */ static bool ParseAt(css, ci) CSSContext css; CSSInput ci; { while (ci->cp < ci->ep) { if (*ci->cp == '{') { if ((ci->cp = ParseToChar(ci->cp + 1, ci->ep, '}', false)) == NULL) { ci->cp = ci->ep; } return(true); } else if (*ci->cp == ';') { ci->cp++; return(false); } ci->cp++; } return(true); } /* * ParseSpace * * Look for non-space and deal with comments. */ static char * ParseSpace(s, e) char *s, *e; { bool sc, ec, ic; sc = false; /* possible start comment? */ ec = false; /* possible end comment? */ ic = false; /* in comment? */ while (s < e) { if (ic) { if (ec && *s == '/') ic = false; else if (*s == '*') ec = true; else ec = false; } else if (sc && *s == '*') ic = true; else if (*s == '/') sc = true; else if (!isspace8(*s)) return(s); else sc = false; s++; } return(NULL); } static CSSProperty ParseProperty(mp, s, slen) MemPool mp; char *s; size_t slen; { char *ep, *colon, *x; CSSProperty prop; ep = s + slen; /* get rid of space in front of the declaration */ if ((s = ParseSpace(s, ep)) == NULL) return(NULL); /* search for the required colon or white space */ if ((colon = ParseToChar(s, ep, ':', true)) == NULL) return(NULL); prop = (CSSProperty)MPCGet(mp, sizeof(struct CSSPropertyP)); prop->name = (char *)MPGet(mp, colon - s + 1); strncpy(prop->name, s, colon - s); prop->name[colon - s] = '\0'; /* May have only reached white space before */ if (*colon != ':') { /* search for the required colon */ if ((colon = ParseToChar(colon, ep, ':', false)) == NULL) return(NULL); } /* remove space in front of the value */ if ((s = ParseSpace(colon + 1, ep)) == NULL) return(NULL); prop->value = (char *)MPGet(mp, ep - s + 1); /* Copy the value until end of input or whitespace is seen */ x = prop->value; while (s < ep) { if (isspace8(*s)) break; *x++ = *s++; } *x = '\0'; if (strlen(prop->name) == 0 || strlen(prop->value) == 0) return(NULL); return(prop); } static GList ParseProperties(mp, s, slen) MemPool mp; char *s; size_t slen; { char *last; char *ep; GList properties; CSSProperty prop; properties = GListCreateX(mp); ep = s + slen; while (s < ep) { last = s; s = ParseToChar(s, ep, ';', false); if (s == NULL) s = ep; if (last < s && (prop = ParseProperty(mp, last, s - last)) != NULL) { GListAddTail(properties, prop); } s++; } if (GListGetHead(properties) == NULL) return(NULL); return(properties); } static CSSSelector ParseSelector2(mp, s, slen) MemPool mp; char *s; size_t slen; { CSSSelector cs; char *tag = NULL; char *id = NULL; char *class = NULL; char *pclass = NULL; char *ep; char *t; cs = (CSSSelector)MPCGet(mp, sizeof(struct CSSSelectorP)); t = MPGet(mp, slen + 1); strncpy(t, s, slen); t[slen] = '\0'; s = t; if (*s == '#') id = s + 1; else if (*s == '.') class = s + 1; else if (*s == ':') pclass = s + 1; else { tag = s; ep = s + slen; while (s < ep) { if (*s == '#') { id = s + 1; *s = '\0'; break; } else if (*s == '.') { class = s + 1; *s = '\0'; break; } else if (*s == ':') { pclass = s + 1; *s = '\0'; break; } else s++; } } cs->tag = tag; cs->id = id; cs->class = class; cs->pclass = pclass; return(cs); } static GList ParseSelector1(mp, s, slen) MemPool mp; char *s; size_t slen; { char *ep = s + slen; char *cp; char *last; CSSSelector cs; GList selectors; if ((s = ParseSpace(s, ep)) == NULL) return(NULL); selectors = GListCreateX(mp); last = s; cp = s; while (cp < ep) { if (isspace8(*cp)) { if ((cs = ParseSelector2(mp, last, cp - last)) != NULL) { GListAddTail(selectors, cs); } if ((cp = ParseSpace(cp, ep)) == NULL) break; last = cp; } else cp++; } if (last < cp) { if ((cs = ParseSelector2(mp, last, cp - last)) != NULL) { GListAddTail(selectors, cs); } } if (GListGetHead(selectors) == NULL) return(NULL); return(selectors); } /* * ParseSelector */ static GList ParseSelector(mp, s, slen) MemPool mp; char *s; size_t slen; { GList slist, xlist; char *ep; char *last; slist = GListCreateX(mp); ep = s + slen; while (s < ep) { last = s; s = ParseToChar(s, ep, ',', false); if (s == NULL) s = ep; if (last < s && (xlist = ParseSelector1(mp, last, s - last)) != NULL) { GListAddTail(slist, xlist); } s++; } if (GListGetHead(slist) == NULL) return(NULL); return(slist); } /* * scompare * * do the sort of string comparison that we need here */ static int scompare(s1, s2) char *s1, *s2; { if (s1 == s2) return(0); if (s1 == NULL || s2 == NULL) return(-1); if (strlen(s1) != strlen(s2)) return(-1); return(strcasecmp(s1, s2)); } /* * ParseRule * * Parse a single rule. Return false if parsing error that leads to EOF. */ static bool ParseRule(css, ci) CSSContext css; CSSInput ci; { char *last; GList slist; GList plist; CSSRule cr; slist = GListCreateX(css->mp); last = ci->cp; if ((ci->cp = ParseToChar(ci->cp, ci->ep, '{', false)) == NULL) { ci->cp = ci->ep; return(false); } slist = ParseSelector(css->mp, last, ci->cp - last); ci->cp++; /* need to get past the '{' from above */ last = ci->cp; if ((ci->cp = ParseToChar(ci->cp, ci->ep, '}', false)) == NULL) { ci->cp = ci->ep; return(false); } plist = ParseProperties(css->mp, last, ci->cp - last); ci->cp++; /* * Return true because parse was successful. */ if (plist == NULL || GListGetHead(plist) == NULL || slist == NULL || GListGetHead(slist) == NULL) return(true); cr = (CSSRule)MPCGet(css->mp, sizeof(struct CSSRuleP)); cr->selectors = slist; cr->properties = plist; GListAddTail(css->rules, cr); return(true); } /* * ParseCSS * * Toplevel parser loop. */ static void ParseCSS(css) CSSContext css; { CSSInput ci = (CSSInput)GListGetHead(css->inputs); if (ci == NULL) { if (css->proc == NULL) return; /* * Should call callback here because this means all CSS text including * remote text has been parsed. Callback must be made from a toplevel * task so create a task first. */ return; } ci->cp = ParseSpace(ci->cp, ci->ep); while (ci->cp != NULL && ci->cp < ci->ep) { if (*ci->cp == '@') { if (!ParseAt(css, ci)) return; } else if (!ParseRule(css, ci)) return; ci->cp = ParseSpace(ci->cp, ci->ep); } GListPop(css->inputs); ParseCSS(css); return; } CSSContext CSSParseBuffer(cs, b, blen, proc, closure) ChimeraContext cs; char *b; size_t blen; CSSProc proc; void *closure; { CSSContext css; MemPool mp; CSSInput ci; mp = MPCreate(); css = (CSSContext)MPCGet(mp, sizeof(struct CSSContextP)); css->mp = mp; css->cs = cs; css->rules = GListCreateX(mp); css->props = GListCreateX(mp); css->inputs = GListCreateX(mp); css->proc = proc; css->closure = closure; ci = (CSSInput)MPCGet(mp, sizeof(struct CSSInputP)); ci->b = b; ci->blen = blen; ci->cp = b; ci->ep = b + blen; GListAddHead(css->inputs, ci); ParseCSS(css); return(css); } /* * CSSDestroyContext */ void CSSDestroyContext(css) CSSContext css; { MPDestroy(css->mp); return; } static bool SelectorListMatch(slist1, slist2) GList slist1, slist2; { CSSSelector cs, ncs; /* * This code needs attention. It compares two selector lists. */ for (cs = (CSSSelector)GListGetHead(slist1), ncs = (CSSSelector)GListGetHead(slist2); cs != NULL && ncs != NULL; cs = (CSSSelector)GListGetNext(slist1), ncs = (CSSSelector)GListGetNext(slist2)) { if (scompare(ncs->tag, cs->tag) != 0 || scompare(ncs->id, cs->id) != 0 || scompare(ncs->class, cs->class) != 0 || scompare(ncs->pclass, cs->pclass) != 0) { return(false); } } if (ncs != NULL || cs != NULL) return(false); return(true); } /* * CSSCreateSelector */ CSSSelector CSSCreateSelector(mp) MemPool mp; { return((CSSSelector)MPCGet(mp, sizeof(struct CSSSelectorP))); } /* * CSSSetSelector */ void CSSSetSelector(cs, tag, id, class, pclass) CSSSelector cs; char *tag, *id, *class, *pclass; { cs->tag = tag; cs->id = id; cs->class = class; cs->pclass = pclass; return; } /* * CSSFindProperty */ char * CSSFindProperty(css, selectors, name) CSSContext css; GList selectors; char *name; { CSSProperty p; GList slist, xlist; CSSSelector h; if ((h = GListGetHead(selectors)) != GListGetTail(selectors)) { slist = GListCreate(); GListAddHead(slist, h); } else slist = NULL; for (p = (CSSProperty)GListGetHead(css->props); p != NULL; p = (CSSProperty)GListGetNext(css->props)) { if (scompare(p->name, name) == 0) { for (xlist = (GList)GListGetHead(p->cr->selectors); xlist != NULL; xlist = (GList)GListGetNext(p->cr->selectors)) { if ((slist != NULL && SelectorListMatch(xlist, slist)) || SelectorListMatch(xlist, selectors)) { if (slist != NULL) GListDestroy(slist); return(p->value); } } } } if (slist != NULL) GListDestroy(slist); return(NULL); } /* * CSSPrintSelectorList */ void CSSPrintSelectorList(slist) GList slist; { CSSSelector s; for (s = (CSSSelector)GListGetHead(slist); s != NULL; s = (CSSSelector)GListGetNext(slist)) { if (s->tag != NULL) fprintf (stderr, "%s ", s->tag); if (s->id != NULL) fprintf (stderr, "%s ", s->id); if (s->class != NULL) fprintf (stderr, "%s ", s->class); if (s->pclass != NULL) fprintf (stderr, "%s ", s->pclass); fprintf (stderr, "\n"); } return; } /* * CSSPrint */ void CSSPrint(css) CSSContext css; { CSSRule cr; CSSSelector cs; GList slist; CSSProperty prop; for (cr = (CSSRule)GListGetHead(css->rules); cr != NULL; cr = (CSSRule)GListGetNext(css->rules)) { for (slist = (GList)GListGetHead(cr->selectors); slist != NULL; slist = (GList)GListGetNext(cr->selectors)) { for (cs = (CSSSelector)GListGetHead(slist); cs != NULL; cs = (CSSSelector)GListGetNext(slist)) { printf ("%s ", cs->tag); } printf (", "); } printf ("{\n"); for (prop = (CSSProperty)GListGetHead(cr->properties); prop != NULL; prop = (CSSProperty)GListGetNext(cr->properties)) { printf ("\t%s : %s;\n", prop->name, prop->value); } printf ("}\n"); } } #ifdef CSSDEBUG #include #include main(argc, argv) int argc; char *argv[]; { CSSContext css; FILE *fp; char *b; char *name; struct stat st; GList slist; CSSSelector cs; MemPool mp; if (argc < 2) exit(1); if (stat(argv[1], &st) != 0) exit(1); if ((b = (char *)alloc_mem(st.st_size)) == NULL) exit(1); if ((fp = fopen(argv[1], "r")) == NULL) exit(1); fread(b, 1, st.st_size, fp); fclose(fp); css = CSSParseBuffer(NULL, b, st.st_size, NULL, NULL); mp = MPCreate(); slist = GListCreate(); cs = CSSCreateSelector(mp); CSSSetSelector(cs, "H5", NULL, NULL, NULL); GListAddHead(slist, cs); name = "white-space"; if ((b = CSSFindProperty(css, slist, name)) != NULL) { printf ("%s == %s\n", name, b); } else printf ("%s not found\n", name); CSSPrint(css); CSSDestroyContext(css); exit(0); } #endif chimera-2.0a19/html/css.h100600 11610 11610 2612 6677561563 13450 0ustar johnjohn/* * css.h * * Copyright (c) 1998, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ typedef struct CSSPropertyP *CSSProperty; typedef struct CSSSelectorP *CSSSelector; typedef struct CSSRuleP *CSSRule; typedef struct CSSContextP *CSSContext; typedef void (*CSSProc) _ArgProto((void *)); void CSSDestroyContext _ArgProto((CSSContext)); CSSContext CSSParseBuffer _ArgProto((ChimeraContext, char *, size_t, CSSProc, void *)); CSSSelector CSSCreateSelector _ArgProto((MemPool)); void CSSSetSelector _ArgProto((CSSSelector, char *, char *, char *, char *)); char *CSSFindProperty _ArgProto((CSSContext, GList, char *)); void CSSPrintSelectorList _ArgProto((GList)); void CSSPrint _ArgProto((CSSContext)); chimera-2.0a19/html/csstest100711 11610 11610 243754 6677561616 14202 0ustar johnjohnELF@À4D¤4 (4@4@44@4@4pH@H@H€€pÈ@È@Èà@à@àDDp@@`` ``` /usr/lib/libc.so.1 óÿÿþÿÿÿÿâð0óÿÿþÿÿÿÿâð@@œ@ c  ppdp@p p(p'p ppbpp+p&p%p%cp-¶ÃÀp)@Hp @ 3DTfyˆp$@°p@p@$ptp/ð 3JÖ>$’9,33ïÀ[§ÆË=D4L·#8üMT4L¹ò,§_f4L4—¾Wry3ïÀ[ºÚ4\ˆ3¦ÛÀùg’.text.init__Argv__rld_obj_headexit__start_environ__istart__readenv_sigfpemain_mcount_gp_disp__Argc__iobMPCGetMPGetstrncpystrlenGListCreateXGListAddTailGListGetHeadstrcasecmpGListPopCSSParseBufferMPCreateTrackGListAddHeadCSSDestroyContextMPDestroyGListGetNextCSSCreateSelectorCSSSetSelectorCSSFindPropertyGListGetTailGListCreateTrackGListDestroyCSSPrintSelectorListfprintfCSSPrintprintfstatalloc_memfopenfreadfclose.rodatamemsetGListGetPrevGListGetCurrentGListRemoveItemGListEmptyGListMPGListPrintStatusGListClearmallocxmyassertMPStrDupstrcpyfreeMPPrintStatusfree_memcalloc_memcallocrealloc_memreallocalloc_stringFixPathgetenvgetpwnamstrcatmystrtokGetBaseFilenamefflushabortmytmpnamsnprintfgetpidtime.bssvsnprintfsprintflibXaw.so.2sgi2.0libXmu.sosgi1.0libXt.sosgi1.0libXext.sosgi1.0libX11.so.1sgi1.0libm.sosgi1.0libc.so.1sgi1.0libw.sosgi1.0libgen.sosgi1.0_endend_edataedata_etextetext__elf_header_ftextftext_fdatafdata_fbssfbss__program_header_table__dso_displacementvendorShellWidgetClassvendorShellClassRec€b ]/+B7ANO!.3MZ 01(V,9>`R*I:QL -# K2JY[;? '"$%&=6)8F45@CW<DaEGPH\STUX_^@ÀD€ÿ@[@ ÿË`ÿ cðÿ8%ÿO’Ü@ÿ@4ÿð@,ÿé@,ÿ(@ÀÿX@Ü ÿ|@10tÿÚ@<´\ÿç@=<ÿ÷@=LTÿ@> <ÿ@>Ü$ÿ@?$ÿ+@?$Œÿ\@DT$ÿj@D€Pÿs@DÐTÿ…@EpTÿ™@EÄŒÿ¦@FPLÿÅ@Hœ4ÿÎ@IÐÔÿë@K`¼ÿÖ@[`ÿÏ@[`ÿö`ÿý`ÿpÿÉpÿ pÿÂpÿtÿ¹t ÿ¾t ÿ`âðÿñ0p#@0B@@ƒ@P”‹@`°¹@p‘@€@¢@4©@ ¸@°¾@ÀPÄ@Ð|Ó@àÈ6@ðP@¨W@~@ ‘@0®@@”µ@P¾@`¼Þ@på@€ ý@@ @°tÍ@+4ˆÿ÷@,¼Pÿ @.˜Pÿ2@.è8ÿA@/ ÿ™@2¤ÌÿS@4p˜ÿ’@7Ðlÿ^@8<ÿÄ@8ÌÔÿê@9 èÿŸ@:ˆèÿo@;p`ÿ¬@;ÐDÿQ@<Dÿ@™€àx% ø 4?™€àx% ø 4@™€àx% ø 4A™€àx% ø 4B™€àx% ø 4C™€àx% ø 4D™€àx% ø 4Eà@%<Á'œÌ$Ÿà!ø%<ü8!Œç€$¤'¥Œç$ÿð¡è$$¦€'½ÿààÂ0!<<!Œ!€$¬&<<!Œ!€ü<<È!¬$<9€ô<!Œ!€ø¯¼¯ ð% ø ¬%¼<<È!9€0 ø ¼<<<<<È!9€¨œ !¼(!Ü0!Œ„€üŒ¥€øŒÆ€$Œ„Œ¥ ø ŒÆ¼<@ %<È!9€, ø ¼ '½à ø%<Á'œÊð™à!'½ÿЯ¿¯¼¯¤0¯¥4¯¦8¯§<¯ (¯ $¯  ®0¯4Ï+ ‘¸ „¯  ¹0$\“($ |¯© ª$@«0$"‘lr¯ $­( ®0$'‘Ïáh¯ (¸0$"“!$`¯¨$©0$'‘*A$ X¯«(¬0®8‘®]¢0O¯<à ¸0“+!!  O¢0A¨0${‘ !™€¤0¥4'9$}8% ø $„¯¢0ª0¼@9%+«0$(‘l™€¤0¥4'9$)8% ø $„¯¢0­0¼ #%®0$[‘Ïᙀ¤0¥4'9$]8% ø $„¯¢0¸0¼ %¹0'(¯¨0©0ª4*+ ÿq%¿'½0à<Á'œÈH™à!'½ÿد¿¯¼¯¤(¯¥,¯°®,ÏØ ø+ 2¹,${(‘ !ª,™€$}D'98%E  ø $„«,¼@€%­p¬, ­$ ®,$;Ï‘ø¹,(% ¯)%ª,K%m­M¬,Ž Ï+ ÿÐ$¿°'½(à<Á'œÇ$™à!'½ÿ刻¯ ¯ …+ 8®À¯à˜$/ ¯ ™$*!$¯¨¯ ©  Š$*A$ ¯«Œ$/$  ¯­ Ž)Á! á €%¯  $„…+ ÿÊ%à'½<Á'œÆ™à!'½ÿЯ¿¯¼¯¤0¯¥4¯¦8®4¯8ÏÀ!¯¸,™€¤4¥,'9Ì ø ¯¢4¹4¼ Ž%™€¤4¥,'9$: ø $¯¢(¨(¼€%™€Ø¤0$  ø ¼¯¢ ©(ª4™€Ô¤0*(# ø $¥« ¼­b­4™€4¬ ®( (%„ ø Í0#¼¨ ¯(¸4 øÈ#9P!¡@«($:‘l™€¤(¥,'9$: ø 8%¯¢(®(¼ÀL%™€¤(¥,'9Ì ø $„¯¢4­4¼ ?%¯,¸4™€Ô¤0ø(# ø $¥¨ ¼­© 9¯¹$ª4«,K+ ¬4‘Ž)Á! À­4¸$‘¯£¹4¨$'*% ¯©$¯ª4«4¬,l+ ÿé®$¡À™€8­  ø ¤@¼™€8¯  ø ä@¼%¢ ¿'½0à<Á'œÃ\™à!'½ÿЯ¿¯¼¯¤0¯¥4¯¦8™€¬¤0 ø ¼¯¢$®4¯8ÏÀ!¯¸(¹4¨((+ /©4¯©,™€¤4¥('9$; ø 8%¼¯¢4ª4@«(¯«4¬,­4+ ™€¤0€(%'9è ø ¬0#¯¢ ® ¼À™€¼¤$¥  ø ¼¯4%ø¯¸4¹4¨((+ ÿÓ™€Ä¤$ ø @¼%¢$¿'½0à<Á'œÂ™à!'½ÿÀ¯¿¯¼¯¤@¯¥D¯¦H¯ 8¯ 4¯ 0¯ ,™€Ø¤@$ ø ¼¯¢<™€Ô¥H¤@ ø $¥¼¯¢$™€4¤$¥D ø ¦H¼®$¯HÏÀ!£¹$¯¹D¨D$#‘ !ªD%KP¯«4¬D$.‘¡®D%ÏG¯¯0¸D$:“!¨D% >¯©,ªD¯ª8«D¬Hlh!¯­(®D¯(Ï+ 3¸D$#“! ¨D% ¯©4ªD¡@' «D$.‘l ­D%®¯®0¯D¡à¸D$:“! ¨D% ¯©,ªD¡@ «D%l¯¬D­D®(®+ ÿϯ8¸<¯¹4¨<­©0ª<­I«,¬<­‹ ¢<¿'½@à<Á'œ¿¸™à!'½ÿȯ¿¯¼¯¤8¯¥<¯¦@®<¯@ÏÀ!¯¸4™€¤<¥4'9Ì ø ¯¢<¹<¼ f%™€¬¤8 ø ¼¯¢$¨<¯¨,©<¯©0ª0«4K+ 3¬0‘)¡! & $™€®,¯0'9 ì¤8À(% ø î0#¯¢(¸(¼™€¼¤$¥( ø ¼™€¤0¥4'9Ì ø ¯¢0¹0¼  ¨0¯¨,©0%*¯ª0«0¬4l+ ÿÏ­,¯0¯+ ™€®,¸0'9 ì¤8À(% ø 0#¯¢(¹(¼ ™€¼¤$¥( ø ¼™€Ä¤$ ø @¼%¢$¿'½8à<Á'œ½¬™à!'½ÿЯ¿¯¼¯¤0¯¥4¯¦8™€¬¤0 ø ¼¯¢,®4¯8ÏÀ!¯¸$¹4¨$(+ /©4¯© ™€¤4¥$'9$, ø 8%¼¯¢4ª4@«$¯«4¬ ­4+ ™€¤0€(%'9#8 ø ¬0#¯¢(®(¼À™€¼¤,¥( ø ¼¯4%ø¯¸4¹4¨$(+ ÿÓ™€Ä¤, ø @¼%¢,¿'½0à<Á'œ¼T™à!'½ÿد¿¯¼¯¤(¯¥,¯°®(¯,Ï %¸(¹, $ÿÿ™€8¤( ø ¼@€%¤,™€8 ø P¼ $ÿÿ™€<¤(¥, ø ¼¿°'½(à<Á'œ»ˆ™à!'½ÿÀ¯¿¯¼¯¤@¯¥D¯°™€¬®@ ø 8¯Dø¯¸<¹D${8%$% ™€'9 ø ¨D¼@€%­©D* ­*a%­D™€¬<«@®'9%D€(%d ø Ì0#¼¯¢8¯Dø'­ù¨D ¯ª<™€©D$}'98%$ ø % «D¼@€%­p­D® ­®<%¹D¸<¬@/™€(%„'9” ø ø0#¼¯¢4¨D %I­ «4`™€Ä` % ø @ ¼®8À™€ÄÀ % ø @¼$™€Ø­@$ ø ¤¼¯¢,¬8¹,¯,¯4¸,¯™€¼ª@¥, ø D ¼$¿°'½@à<Á'œ¹`™à!'½ÿد¿¯¼¯¤(™€Ä®( ø $¯$à ¸( PN™€¨$'9Ì ø  ©$¼­"ª$K`2L l+ .­$$@®‘Ïá ™€¤(¥$'9¨ ø @¼- ™€¤(¥$'9'h ø @¼!™€¸$'9Ì ø  ¹$¼¯"¨$   *+ ÿÔ™€´«( ø d¼™€¤('9) ø ¼¿'½(à<Á'œ·¼™à!'½ÿЯ¿¯¼¯¤0¯¥4¯¦8¯§<™€Ð…€$( ø $¥`¼¯¢(™€Ø¤($  ø ¼¯¢,®(¯,­î¸0¹,¯8™€¬¤( ø ¨,¼­ ™€¬¤( ø ©,¼­"™€¬¤( ø ª,¼­B«<¬,­‹­@®,­Í™€Ø¤($ ø ¼¯¢$¯4¸$¯¹8¨$­©4ª$­I«4¬8®$lh!­Í ™€¸¯,¥$ ø ä¼™€¤,'9) ø ¼¢,¿'½0à<Á'œ¶4™à!'½ÿ௿¯¼¯¤ ™€à®  ø ļ¿'½ à<Á'œµä™à!'½ÿد¿¯¼¯¤(¯¥,™€Ä¤( ø ¼¯¢$¤,™€Ä ø ®$¼¯¢ À=¯ à:¹$¸ %™€'9&œ ø @¼™€¨ ©$'9&œ ø %@¼™€ª «$'9&œD ø e@ ¼™€¬ ­$'9&œ„  ø ¥ @¼%™€Ì¤( ø ¼¯¢$¤,™€Ì ø ®$¼¯¢ À¯ àÿȸ ¹$ %$¿'½(à<Á'œ´X™à!'½ÿ௿¯¼¯¤ ™€Ø¤ $ ø ¼¿'½ à<Á'œ´™à!¬…¬†¬‡®¬Ž ààà<Á'œ³Ð™à!'½ÿȯ¿¯¼¯¤8¯¥<¯¦@¯°™€Ä¤< ø ¼@€%¯°(™€È¤< ø P¼™€°…€$Ž ø $¥`¼¯¢0™€¸¤0¥( ø ¼¯ 0™€Ä®8 ø į¢4¯4¼àE™€¸4¥@'9&œ ø @4¼¹4(™€Ä ø ¯¢,©,¼ )ª0@ ™€¤,@(%'9-  ø @ ¼™€¤,¥<'9-  ø @ ¼«0`™€À¤0 ø ¼¬4 ‚­4™€Ì® ø į¢,¯,¼àÿÙ™€Ì¸8 ø ¯¢4¹4¼ ÿ½¨0™€À¤0 ø ¼%¿°'½8à<Á'œ±À™à!'½ÿد¿¯¼¯¤(™€Ä¤( ø ¯¢$®$¼ÀF¯$ø ¹$„€(…€&™€@$„ $¥` ø ¼¨$  ™€@„€(…€ª$$„ $¥` ø F¼«$l€ ™€@„€(…€­$$„ $¥` ø ¦¼®$Ï à ™€@„€(…€¸$$„ $¥` ø  ¼™€@„€(…€$„  ø $¥` ¼™€Ì¤( ø ¯¢$¹$¼ ÿ¼¿'½(à<Á'œ°L™à!'½ÿЯ¿¯¼¯¤0™€Ä®0 ø Ä ¯¢,¯,¼à^™€Ä¸, ø ¯¢$¹$¼ (™€Ä¤$ ø ¯¢(¨(¼™€D„€©($„`$ ø %¼™€Ì¤$ ø ¯¢(ª(¼@ÿñ™€D„€ ø $„`(¼™€Ì«, ø d¯¢$¬$¼€ÿÚ™€D„€ ø $„`,¼™€Ä­, ø ¤¯¢ ® ¼À¯ ™€D„€åæ ø $„`0¼™€Ì¸, ø ¯¢ ¹ ¼ ÿð™€D„€ ø $„`<¼™€Ì¨0 ø  ¯¢,©,¼ ÿ¤¿'½0à<Á'œ®€™à!'½ÿ0¯¿$¯¼ ¯¤Ð¯¥Ô®Ð)Á ™€,$ ø ¼ ™€H¯Ô'¥8 ø ä@¼ ™€,$ ø ¼ ™€ä¤h ø ¯¢Ä¸Ä¼ ™€,$ ø ¼ ¹Ô…€$™€L$¥`@ ø ¯¢È¨È¼ ™€,$ ø ¼ ™€P¤Ä$¦h ø §È¼ ™€T¤È ø ¼ ™€ %¥Ä¦h8% ø ¯ ¼ ¯¢Ì™€Ð…€$ ø $¥`D¼ ¯¢,™€°…€$ ø $¥`L¼ ¯¢4™€˜¤, ø ¼ ¯¢0™€œ…€¤00%8%¯  ø $¥`T¼ ™€¸¤4¥0 ø ¼ ‰€%)`X¯©À™€ ¤Ì¥4 ø ¦À¯¢ÄªÄ¼ @ ™€D„€¥À¦Ä ø $„`d¼ ™€D„€¥À ø $„`p¼ ™€¤¤Ì ø ¼ ™€”¤Ì ø ¼ ™€, % ø ¼ %¿$'½Ðà<Á'œ«à™à!ŒŽ¬®¬…ààà<Á'œ«°™à!'½ÿد¿¯¼¯¤(%®(Ïà%¸(¯¹$¨$ª( ­I™€X¤$(% ø $ ¼¢$¿'½(à<Á'œ« ™à!'½ÿد¿¯¼¯¤(™€Ø¤($ ø ¼¯¢$®(¯$­î¸$¯¢$¿'½(à<Á'œª´™à!'½ÿد¿¯¼¯¤(¯¥,™€Ð…€${ ø $¥`€¼¯¢$™€Ø¤$$ ø ¼¯¢ ®$¯ ­î¹ $¯8¢ ¿'½(à<Á'œª$™à!'½ÿد¿¯¼¯¤(®(Ï à#¸( (¯¨$©(* ¯ª «(l €­(® Ï­¯ ¸(  ¨( ­ ª(K ­K™€¤(¥ '97 ø ¼¢$%¿'½(à<Á'œ©P™à!'½ÿد¿¯¼¯¤(¯¥,™€¤('97@ ø ¯¢$®$¼À™€Ø¯($  ø 伯¢$¸(¨$ ­©(* @¬(«$ ­«®$¯(­î ¸( ¨$©(­(ª,¬$­Š¿'½(à<Á'œ¨h™à!'½ÿد¿¯¼¯¤(¯¥,™€¤('97@ ø ¯¢$®$¼À™€Ø¯($  ø 伯¢$¸(¨$­©(*@¬(«$­«®$¯(­î¸(  ¨$©(­( ª,¬$­Š¿'½(à<Á'œ§€™à!'½ÿ௿¯¼¯¤ ® Ïà™€à¸  ø ¼¿'½ à<Á'œ§ ™à!ŒŽ Àà%Œ ¬Œ˜ ààà<Á'œ¦Ü™à!ŒŽÀà%Œ¬Œ˜ààà<Á'œ¦˜™à!ŒŽÀà%Œø¬˜Œ™ à%Œˆààà<Á'œ¦<™à!ŒŽÀà%Œø¬˜Œ™ à%Œˆààà<Á'œ¥à™à!ŒŽÀà%Œàâàà<Á'œ¥¤™à!'½ÿد¿¯¼¯¤(¯¥,®(Ï àB¯¯$¸$¨,(7©(«$*K¬(­€­$®¯® ¯(¹$ø ¨$ª( ­I «(­$l®$¸(ϯ¹$(©$*+­j¬$ ®$ÏØ¯™€¤(¥$'97 ø ¼¹ ¯¹$¨$ ¯©$ª$@ÿÀ¿'½(à<Á'œ¤P™à!'½ÿø,… Œ… ,¥ %à'½<Á'œ¤™à!àŒ‚àà<Á'œ£ð™à!ààà<Á'œ£Ì™à!'½ÿø¬€ŒŽ ¯®¯ ¯à ¸¯¸¹(¯¨© ÿùª@Œ‹¬­‹Œ ¬¬€ ¬€à'½<Á'œ£@™à!'½ÿЯ¿¯¼¯¤0$¯®$¯0¨$À‚È€(H!%*¯ª(«( c k%®¯®,™€\¤, ø ¼¯¢ ¯,¸ ¯¹$¨ ­© ­ ¢ ¿'½0à<Á'œ¢”™à!'½ÿø(‚(€$¥ŒŽŒ˜Åx!+  %Œ™™@!¯¨Œ‰%P!¬Š¢à'½<Á'œ¢(™à!'½ÿد¿¯¼¯¤(¯¥,™€$'9?° ø ¼¯¢ ™€¤ $'9@\ ø ¼¯¢$™€è¤$…€†€$Ÿ +$¥` ø $Æ`¬¼® ¯$­î¸ ¨$­¢$¿'½(à<Á'œ¡h™à!'½ÿد¿¯¼¯¤(¯¥,™€è¤,…€†€$¾ +$¥`¸ ø $Æ`è¼®(ϯ¯$™€¤$¥,'9@\ ø ¯¢ ¸ ¼'™€¤,'9?° ø ¼¯¢$¹(©$(­(ª(¬$Kmp!­N¯$¸(¯™€¤$¥,'9@\ ø ¼¯¢ ™€è¤ …€†€$É +$¥`ô ø $Æa ¼¢ ¿'½(à<Á'œ 0™à!'½ÿد¿¯¼¯¤(¯¥,™€Ô¤(¥, ø ¼¯¢$™€X¤$(% ø ¦,¼¢$¿'½(à<Á'œŸ¼™à!'½ÿد¿¯¼¯¤(¯¥,®,À%™€8¤, ø ¼¯¢$™€Ô¥$¤( ø $¥¼¯¢ ™€`¤ ¥, ø ¼¢ ¿'½(à<Á'œŸ™à!'½ÿد¿¯¼¯¤(®(Ï௯$¸$¯¸ ¹$(¯¨$™€d¤  ø ¼©$ ÿô¿'½(à<Á'œžœ™à!ààà<Á'œžp™à!'½ÿ௿¯¼¯¤ ™€d¤  ø ¼¿'½ à<Á'œž ™à!'½ÿ௿¯¼¯¤ ¯¥$™€h¤ ¥$ ø ¼¿'½ à<Á'œÌ™à!'½ÿ௿¯¼¯¤ ™€\¤  ø ¼¿'½ à<Á'œ€™à!'½ÿ௿¯¼¯¤ ¯¥$™€l¤ ¥$ ø ¼¿'½ à<Á'œ,™à!'½ÿد¿¯¼¯¤(¯°™€8¤( ø ¼@€%&™€\ ø ¼¯¢$™€`¤$¥( ø ¼¢$¿°'½(à<Á'œœ ™à!'½ï¸¯¿$¯¼ ¯¤H¯¥L¯±¯°®L$~‘Ïá¸L¯¸8¹L$/“( “)$~!ªL%K¯«8¯ 8¬8€a­8$/‘®Á™€p„€ ø $„a ¯¢4¯4¼ à\%¸8',¯¨@¹8'ª<¯ª<')¯©@“+`$/a¬@®<‘¡Í¯@¨<%ø% ¯©<¯¸@“ @$/Aÿñ¹<£ ™€t'¤< ø ¼ ¯¢D«D`0%¬D¯­4™€8¤4 ø ¼ @ˆ%¤@™€8 ø ¼ @€%(!™€Ô$¥¤H ø ¼ ¯¢0™€`¤0¥4 ø ¼ ™€x¤0¥@ ø ¼ ™€Ü¤H¥L ø ¼ ¯¢0¢0¿$°±à'½H<Á'œšT™à!'½ÿø€D%Ž€¯¤%Îc𯮯‘ø+¹“(©%*¯ª‘Ke¬%¯­®‘Ïåÿú¸¨“¡©%*¯ª‹€­%kcð%lÿ®%Ïÿѯ¯¸£¹“(¬À©¬É‚€$Bcðà'½<Á'œ™ ™à!'½ÿد¿¯¼¯¤(®(À&%™€8¤( ø ¯(¼OÀ!'ÿÿ/+ ¯¹$¨$$/‘ !ª$¬(%Kÿÿl+ ÿô¯«$­$%®¯®$¸$“ %¢$¿'½(à<Á'œ˜L™à!'½ÿ௿¯¼¯¤ ¯¥$¯¦(¯§,® À™€@„€(…€¦(§,$„  ø $¥a(¼™€@„€(…€¦$$„  ø $¥a0¼™€|„€( ø $„ ¼™€€ ø ¼¿'½ à<Á'œ—™à!'½ÿÀ¯¿,¯¼(¯¤@¯±$¯° ™€Ô¤@$ ø ¼(¯¢<™€„ ø ¼(@ˆ% %™€ˆ ø ¼(@€%¯°™€ð†€‡€¤<$¯±$Æa4 ø $ça@¼(¢<¿,° ±$à'½@<Á'œ–Йà!'½ÿ௿¯¼¯¤ ¯¥$¯¦(¯§,® ¡À¯ ¸$€øÈ!'(ÿÿ¬(sô™€¤ ¥('9ML ø ¦,¼©$ Š€Jsô¡@™€8¤  ø ¼¿'½ à<Á'œ–$™à!'½ÿد¿¯¼¯¤(¯¥,¯¦0¯§4'®0%ϯ¯$™€ì¤(¥,¦0 ø §$¼™€8¤( ø ¼¿'½(à<Á'œ•¤™à!'½ÿˆ¯¿4¯¼0¯¤x¯¥|¯¦€¯±,¯°(¯ l®x€¬.sð¯|‘ø%ù¯¹|€%¯¸t¨t$%|¯ \¯ `¯ d$ ÿÿ¯©X¯ Tª|‘K%L¯¬|¯«t°t & ÿÛ-¡T _€ h€-!Œ-a¬¼h! T™€„€'9Zd ø $„aP¼0i$¯®dÿÞ$¯¸T¯ XÿÙ¯€$ÿü%ù!@$% ¯©€ ¯«`ÿϪ`@¬T€$ 0¯­\®TÀ ¸X¹tx€øx!x@ùH!%(ÿÐ ¯¨X«`¬t P€KP! P@Lh!%®ÿЯ®`ÿ±$¯¸lÿ­¯là ¹€$ÿü')!@$% ¯«€  ¯ªp¬€$ÿü%¡p$%د¸€Ï¯¯p¹`©\«X¯¹™€¤p$ '9U¤0%§d¯© ø ¯«¼0ù¨l ª€$ÿü%Lh$%¸¯¸€® ¯®p¯€$ÿü%ù!H$%+¯«€(¯¨p™€ª`¬\¸X'9U¤¤p$0%§d¯ª¯¬ ø ¯¸¼0Õ­l  ®€$ÿü%ÏáÈ$'+¯«€) ¯©p¨€$ÿü% A`$%˜¯¸€¯­p™€®`¯\«X'9U¤¤p$ $§d¯®¯¯ ø ¯«¼0±¹l ©€$ÿü%(P$%X¯¸€L ¯¬p­€$ÿü%®Áx$%믫€ù¯¹p™€©`¨\¸X'9U¤¤p$0%§d¯©¯¨ ø ¯¸¼0ªl@ ¬€$ÿü%¡p$%˯«€Ï ¯¯p¹€$ÿü')!@$%¯¸€ ¯ªp™€¬`­\«X'9U¤¤p$ÿð0%§d¯¬¯­ ø ¯«¼0i®€$ÿü%ÏáÈ$')¯©€8¯¸h™€¨X¤h'9T¥d¦`§\ ø ¯¨¼0Uª€$ÿü%Lh$%«¯«€®¯®t¯t'©D¡/'¹D£ ™€¸X'¤D'9T¥d¦`§\ ø ¯¸¼0<:¨€1 @% ¯¬€%ÿê«€1m %n ¯®€%Ñÿد€$ÿø%é!È$'8¯¸€ˆ% €%Öÿø÷¤H™€ªd¨`¬\­X'9Xˆ¤t¦H§L¯ª¯¨¯¬ ø ¯­¼0™€¤t'9ZÜ ø ¼0™€„€'9Zd ø $„ad¼0¯ l ™€¤t'9ZÜ ø ¼0«|‘n%o¯¯|À€%þs¯®t‰€)sð¡ ¿4°(±,à'½x<Á'œŽì™à!'½ÿЯ¿¯¼¯¤0¯¥4¯¦8¯§<®0À€%ïal¯¯0¸@¹@¯¹(¨0¯ (‘  ª(¬0%K¯«(‹h!‘®Àÿù¯8¸(øÈ#¯¹,¨,¯ ,©4 ª, `#¯¬,«,` ™€$ '9ZÜ ø ¼­,%®ÿÿ¯®,¯,àÿõ¸(¯ $¹0¨$(H!™€‘$'9ZÜ ø ¼ª$«(%L‹* ÿò¯¬$­,¡ ™€$ '9ZÜ ø ¼®,%ϯ¯,¸,ÿõ¿'½0à<Á'œL™à!'½ÿ°¯¿¯¼¯¤P¯¥T¯¦X¯§\¯°¯ L¯ 0¯ ,¯ (®P¯®H¯Xà ¸P$-¯¹L¨PH#¯©HªTA$ ¯«(¬T h#¯­T®(À€&at€&aˆ¯H¸Tª0'«4øÈ@!‘ K`! ¡‰­0%®¯®0¯H¸TøÈ¯¹H ¨HÿÞª0'«4KH!¡ ¬`­0p#¯®,¯,ᯠ,¸\¹,@#¯¨,ªd@ «,`©L ™€¤L'9ZÜ ø ¼¬,%ÿÿ¯­,¯ L®,À ™€¤d'9ZÜ ø ¼¯,%øÿÿ¯¸,¹, ÿõ¨, ™€$ '9ZÜ ø ¼ª,%Kÿÿ¯«,©, ÿõ¬L€™€¤L'9ZÜ ø ¼­0 °0™€'®4&ÿÿ¯°0x!'9ZÜ ø ‘伸0ÿô¹,! ™€$ '9ZÜ ø ¼¨,% ¯ª,«,`ÿõ¿°'½Pà<Á'œŠh™à!'½þد¿¯¼¯¤(¯¦0¯§4¯°®<À$ ¯¯<¸0123456789ABCDEF0123456789abcdef%-%d.%dð?plð?pŒð?pŒð?pŒð?pŒð?k„ð?pŒð?pŒð?k`ð?kpð?pŒð?k¬ð?kÌð?kÌð?kÌð?kÌð?kÌð?kÌð?kÌð?kÌð?kÌð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?mTð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?lÄð?pŒð?pŒð?pŒð?pŒð?pŒð?l4ð?pŒð?pŒð?ntð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?pŒð?oTð?mTð?pŒð?oÀð?oÀð?pŒð?pŒð?pŒð?pŒð?l$ð?pŒð?pŒð?lÄð?pŒð?pŒð?pŒð?oð?pŒð?l4ð?pŒð?pŒð?mä¶ÃÀ@A´î ´ðD±M<©(¦Å¦k¦Å¸§c®s§˜§È(¯ML§œ¦ål¦ \¦¡„¦¤p§ô§š¼¦ ð¨#ð¦áˆ¦ø|©„8§Ÿè§n,§˜@+@@,È@.¤@.ô@/,@2°@4|@7Ü@8H@8Ø@9¬@:”@;|@;Ü@< @ð<ÿÿÿüÿÿÿÿ GI DQÿÿÿôÿÿÿÿ(QW ÿÿïÜÿÿÿÿH6`L“ÿÿÿÿk†€àÿÿÿôÿÿÿÿ(Ž™3Tÿÿÿüÿÿÿÿ ¤­=&Dÿÿÿìÿÿÿÿ@½ÄFÿÿÿüÿÿÿÿ MU¬ +ÿÿÿôÿÿÿÿ(]l ,Kÿÿÿ¼ÿÿÿÿxoÕä)ùÿÿÿìÿÿÿÿ0ß÷^ „5aÿÿÿÌÿÿÿÿPü2u hFÿÿþôÿÿÿÿ(6P¡DS‘ÿÿÿüÿÿÿÿ SU·¼X¯ÿÿÿÿX\», ¯ÿÿ¯ÿÿ¯ÿÿ"¯ÿÿ(@À 0@Ì/ÿÿ>@ /ÿÿ( K@Ü K  ,  ,  ,  ,  ,  @Ì    , Ưi`¹%`» %`À@%`Ã`%`!`Æ)`Ï@8 Û  Þ  á  ã  ( éÿÿÿÿ ëÿÿÿø îÿÿÿô "ñÿÿÿð % Ϩ õ@¨8 .ý  (  +$  õ$ @Ì8 4 €2 €3 "ÿÿÿü 6ÿÿÿø 9ÿÿÿô <  @è8 F*  ?-  B/  C$ -4ÿÿÿü J7ÿÿÿø K=ÿÿÿô L?ÿÿÿð M” '¬ #D@”8 WT  PW  SY  T$ 8^ÿÿÿü [cÿÿÿø \fÿÿÿô ]qÿÿÿð `@ 2DX .v@ ì8 j…  cˆ  fŠ  g$ Fÿÿÿü n’ÿÿÿø q–ÿÿÿô r™ÿÿÿð sŸÿÿÿì t¦ÿÿÿè u©ÿÿÿä v4 =vL 9«@#88 ~º  w½  z¿  {$ RÄÿÿÿü ‚Çÿÿÿø ƒÊÿÿÿô „Ïÿÿÿð …Òÿÿÿì ˆô K« GÜ@%D8 ’ê  ‹í  Žï  $ ]ôÿÿÿü –úÿÿÿø ™ÿÿÿô œÿÿÿð @ WÜX S@&œ8    ž  Ÿ$ c° aÌ ^@'h8 ¨!  ¢%  ¥$ o(ÿÿÿü ¬-ÿÿÿø ­3ÿÿÿô °9ÿÿÿð ³;ÿÿÿì ¶>ÿÿÿè ¹ g( d@@)8 ¿I  ¼ uMÿÿÿü ÁŒ r@¤ pP@+4 Ï_  Äb  Çd  Èi  Ën  Î( vÿÿÿü Ózÿÿÿø Ö}ÿÿÿô Ùp |Pˆ v€@,¼ ß’  Ü †8 „€P ‚–@- 8 ç¨  á¯  ä  ޶ÿÿÿü ë¹ÿÿÿø ît Š–Œ ‡½@.˜ ôÏ  ñ “8 ‘½P Ò@.è ÿá €øä €ûè €üë €ýñ  þ  œ( šÒ8 ”ø@/         ( §ÿÿÿü  ÿÿÿø  #ÿÿÿô )ÿÿÿð ô ¡ø +@10 @   ­Fÿÿÿü \ ª+t ¨H@2¤ !Q   ¶Uÿÿÿü #Xÿÿÿø &[ÿÿÿô )aÿÿÿð ,´ °HÌ ®f@4p 0k  p  /  Äuÿÿÿü 2yÿÿÿø 5|ÿÿÿô 8~ÿÿÿð 9ƒÿÿÿh :†ÿÿÿd =Œÿÿÿ` @ÿÿÿ\ C€ ºf˜ · , P)`Z)`e)`o)` z)`„)`“)`)` , M)`T)`[)`d)`li` u%`z %`@%`…`%`‹h%`!`‘)` ,  ,  ,  , i`N%`S %`!`W)`i` ]%`b %`!`f)`i`m%`r@%`!` v)`~)`†)` , XU)`])`f)`m)`u)`|)`„)`Œ)`“)`™)`Ÿ)`q`§%`¯%`!` ¶)`À)`Å)`Í)`Õ)` Þ)`æ)`#î)`&ö)`)`)`))`)`)`#)`))`1)`7)`=)`,E)`K)`/S)`2])`5e)`n)`8y)`;„)`Œ)`”)`š)` )`¨)`°)`·)`¿)`Å)`>Í)`AÔ)`DÚ)`á)`é)`ó)`û)`)`G)`J)`&)`-)`M5)`N<)`F)`QN)`U)`])`e)`n)`v)`)`T‡)`W)`Z™)`]£)`¬)`¶)`¿)`É)``Ó)`i`VÜ%`c!`Sä)`k , i`\%`!`^)`f)`m)`t)`{)`ƒ)`ˆ)`Ž)`”)`›i`¡%`!` ¥)` , V)``)`k€i`r%`!`{)`‚)` , N)` , q`%`“%`!`˜)`)`¢)` , ‰‰`’)`š‰`¡)` , $i` ƒ%`Š %`“@%`œ`%`¥€%`ª %`³À%`ºà%`À%`!`É)` , ‰`Ÿ)`°‰`À)`ω`Ü)`è)`!ø‰`")`%)`( , $s‰`€)`Œ‰`™)`¥‰`®)`¶‰`!Â)`$Í)`'Õ i`â%`(å %`+ê@%`,!` ði`ý%`- %`.@%`/ `%`0!`i`%`1$ %`4!`/ i`#;%`7> %`:A@%`=H`%`@N€%`CT %`FYÀ%`Iaà%`J!` , R)`Zi`e%`i@%`!`m)`xi` €%`‡ %`!`i`Ÿ%`¦ %`!` ®i`¸%`!Ä@%`$!`Íi`Ö%`å %`!`ði`ú%`' %`!` )`* , iW)`^m`e%`o%`!`y)`‚m` %`•%`!`œ)`©Xi`²%`¿ %`Ð@%`Ü`%`ë%`$!` õ)`*€i`8%` %`@%`tm`6"%`-i`*)%`3 m`(i` /%`6!`5%`9 i`&<%`<D %`M@%`?!`!U%`B!`[ %`E!`c%`Hi`.j%`K!`+q%`Li`3y%`~ %`!`/…%`OŒ%`R!`”`%`U!`›)`Xi`<¥%`[!`9¯)`c¸m`AÅ%`fÒ%`g!`=á)`hð i`Hú%` %`k@%`nÀ%`q!`B!)`w-i`M6%`z< %`!`IG i`RS%`{Y %`a@%`!`Mj)`|rXi`g}%`ˆ %`‚’@%`…˜€%`ˆ €%`ª€%`˜µ %`›ÀÀ%`žËà%`¡Ö%`¤Þ@%`§æ€%`ªïÀ%`­û%`° @%`³À%`¶)%`¹4@%`Á!`S;)`É , Z)`a)`kˆi` €m` t%`}%`†%`#!`Ž%`)“%`š %`!`¡)`,i`¬%`/²€%`2!`¹)`5Äi`Í%`Ö %`8Þ@%`;éÀ%`>ò@%`Aþ %`D @%`Là%`!`")`R , Xi`a%`h %`!`p)`{i` †%`’@%`!`›)`¨(i`´%`Á@%`!Ï€%`Õ %`$ÛÀ%`æà%`'ð%`!` ü)`* , J$i` M%`T %`[@%`c`%`k€%`r %`zÀ%`‚à%`Š%`!` , *Rˆi`W%`^ %`f€%`m %`uÀ%`~à%`!…%`$Œ %`'”@%`*œ€%`0¤ %`¬À%`3´%`6¼@%`9Ä€%`Ï %`<ÙÀ%`?ã@%`E!`ë˜i`)ò%`Kù %`N€%`TÀ%`Wà%`Z%`]  %``'@%`c/`%`f7À%`l?%`G %`oO`%`rW %`u_à%`j%`xt@%`{~À%`!` , qã i`ê%`ð %`õ@%`!`ú@78  €  €  ú0  @7@8 !   ÿÿÿü %x  @7Ð ++  ( .ÿÿÿü /T l 1@8< 3B  G  2  Lÿÿÿü 7Oÿÿÿø :x 1 R@8Ì @[  = &^ÿÿÿü Bdÿÿÿø C¼ "RÔ f@9  Js  Fv  I  -|ÿÿÿü LÐ *fè '@:ˆ SŒ  O  R  4•ÿÿÿü UÐ 1è .˜@;p [¥  X 9H 7˜` 5¨@;Ð `µ €]  >4 <¨D :¸@< eÅ €b  C4 A¸D ?È@  …# €‚ _, ]< [&@>Ü Œ. €‰  d b&$ `1@?  h f1$ eB@?$ •M €’ oPÿÿÿü —Rÿÿÿø š| kBŒ i , i`N%`S %`!`W)`i` ]%`b %`!`f)`i`m%`r@%`!` v)`~)`†)` , q`%`•%`!`š)`Ÿ)`¤)` , {‰`„)`Œ‰`“)`™i`  %`¨ %`«@%`!­`%`$²€%`'· %`*!` , Lìi` m` ö%`ø%`ú%`ü%`þ%`!`%`!`)` i`%` %`@%`"!` #@?°8 (/  % 4ÿÿÿü ,9ÿÿÿø /=ÿÿÿô 2Bÿÿÿð 5” #¬ G@@\8 >P €8U €; Yÿÿÿü @\ Gl ]@@È Dk  p  C  (uÿÿÿü Hxÿÿÿø K¨ $]À !}@Aˆ Tƒ  N†  Q  0Šÿÿÿü Vÿÿÿø Y ,}8 )“@BÀ `š  Z  ]  7¡ÿÿÿü b\ 4“t 1£@C4 g¬  c¯  f  ?±ÿÿÿü iµÿÿÿø lˆ ;£  8¸@CÔ p  m FÅÿÿÿü rÇÿÿÿø uh B¸€ @É@DT x  J HÉ$ G , {‰`„)`Œ‰`“)`™i` ¢%`¨ %`!` , ã@D€ ì   8 ãP î@DÐ ù  ý    < îT @E$    4 L @Ep #      < T "@EÄ &/  %  3ÿÿÿü (p "Œ  , {‰`„)`Œ‰`“)` , -ã@FP ë  î  ( ÷ÿÿÿü ùÿÿÿø üÿÿÿô ÿÿïô  ÿÿïð  ÿÿïì !ÿÿïè "0 ãL  @Hœ () €#+ €$- €' 1ÿÿÿü *4ÿÿÿø +8cð`,$  4 <@IÐ 3L  2 Qÿÿÿü 5¼ <Ô T@J¤ ;^  6c  9g  :l  ( %¤ #T¼ q@K` @z  =$ +}ÿÿÿü B  (q¼ & , ZU)`])`f)`m)`u)`|)`„)`Œ)`“)`™)`Ÿ)`q`§%`¯%`!` ¶)`À)`Å)`Í)`Õ)` Þ)`æ)`#î)`&ö)`)`)`))`)`)`#)`))`1)`7)`=)`,E)`K)`/S)`2])`5e)`n)`8y)`;„)`Œ)`”)`š)` )`¨)`°)`·)`¿)`Å)`>Í)`AÔ)`DÚ)`â)`é)`ñ)`ù)`)` )`)`G)`J()`6)`=)`ME)`NL)`V)`Q^)`e)`m)`u)`~)`†)`)`T—)`W )`Z©)`]³)`¼)`Æ)`Ï)`Ù)``ã)`i`Xì%`c!`Uô)`k , $H$i` O%`W %`a@%`h`%`o€%`v %`À%`Šà%`‘%`!`š ÿð  ! ÿð ÿð6ÿð6 ! ÿð0ÿð ÿð!ÿðÿðÿðÿðÿð0ÿð ÿð# ÿð ÿð ÿðÿð'0ÿð0ÿð ÿð0ÿð ÿð"ÿðÿðÿðÿðÿð0ÿð ÿð$ ÿð ÿð ÿðÿð0ÿð0ÿð  !  ÿð ÿðÿð ÿð ÿð  ÿð ÿðÿð ÿð ÿð  ÿð ÿð ÿð ÿð ' ÿðÿð . ÿðÿð 5 ÿðÿð :ÿð ?ÿð Dÿð Iÿð Nÿð Sÿð [ ÿð ÿðÿð `ÿð ÿð eÿð iÿð p ÿð ÿð !  ÿð ÿð ÿð 0ÿðÿÿÿÿ ! ÿð  ! ÿð ÿð ÿð ÿð ÿð ÿð ÿð ÿð ÿð ÿð ! ÿðÿð# ÿð ÿðÿðÿð ÿð ÿð ÿð ÿðÿðÿð ÿð ÿð ÿð!ÿð )ÿð ÿð ÿð ÿð ÿð1 ÿð ÿð ÿð8ÿð a@ÿðÿð G ÿð ÿð K !  ÿð ÿð ÿð ÿð ÿð ÿð ! ÿðÿð ÿðÿð ! ÿð ÿð ÿð ÿð  ! ÿð ÿð0ÿðÿÿð0ÿðÿÿð&ÿð, ! ÿðÿðÿð ÿðÿðÿðÿðÿðÿðÿðÿðÿðÿð%ÿðÿðÿðÿðÿðÿðÿðÿðÿðÿðÿðÿðÿðÿð0ÿðÿð ÿðU ! ÿðÿðÿðÿð ! ÿð ÿÿÿÿ  !  ÿð ÿð ÿð 0ÿð ÿÿÿÿ ! ÿð ÿð  ! ÿð ÿð  ! ÿð7ÿð7 !  !  ! ÿðaÿð ÿðaÿðaÿð)0ÿð5F0ÿðS0ÿð0ÿðX] ! ÿð crt1text.sLOCALSZFRAMESZRAOFFGPOFF__start10$00000000001$0000000000_mcount/xlv3/bonsai-oct28/root/usr/include/regdef.h/xlv3/bonsai-oct28/root/usr/include/sgidefs.h/xlv3/bonsai-oct28/root/usr/include/sys/fpregdef.h/xlv3/bonsai-oct28/root/usr/include/asm.hcrt1tinit.s__istartcss.cfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/html/css.c88512654915300/usr/bin/cc -o cssxxx.o -c -g -fullwarn -DCSSDEBUG -DHAVE_STDLIB_H -DHAVE_STRING_H -DHAVE_UNISTD_H -DHAVE_STDDEF_H -DHAVE_UNAME -DHAVE_MKTIME -DHAVE_SIZE_T -DHAVE_SSIZE_T -DHAVE_STDARG_H -I../port -I../mxw -I../common -I../chimera css.c/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/htmlCSSInputPbblencpepCSSInputParseToCharcpepcchkwsxsqdqescParseAtcssciParseSpacesescecicParsePropertympsslenepcolonxpropParsePropertiesmpsslenlasteppropertiespropParseSelector2mpsslencstagidclasspclasseptParseSelector1mpsslenepcplastcsselectorsParseSelectormpsslenslistxlisteplastscompares1s2ParseRulecsscilastslistplisttcrpParseCSScssciCSSParseBuffercsbblenprocclosurecssmpciCSSDestroyContextcssSelectorListMatchslist1slist2csncsCSSCreateSelectormpCSSSetSelectorcstagidclasspclassCSSFindPropertycssselectorsnamepslistxlisthCSSPrintSelectorListslistsCSSPrintcsscrcsslistpropmainargcargvcssfpbnamestslistcsmp/usr/include/sgidefs.hfilthy:/usr/include/sgidefs.h8851265497123__int32_t__uint32_t__int64_t__uint64_t__psint_t__psunsigned_t__scint_t__scunsigned_t/usr/include/stdio.hfilthy:/usr/include/stdio.h88512654912558size_tfpos_tfpos64_tva_list__file_s_cnt_ptr_base_flag_fileFILE/usr/include/getopt.hfilthy:/usr/include/getopt.h8851265491362/usr/include/ctype.hfilthy:/usr/include/ctype.h8851265492954/usr/include/string.hfilthy:/usr/include/string.h8851265493820/usr/include/stdlib.hfilthy:/usr/include/stdlib.h8851265497379quotremdiv_tquotremldiv_tquotremlldiv_tssize_twchar_t/usr/include/sys/types.hfilthy:/usr/include/sys/types.h88512654913084uchar_tushort_tuint_tulong_taddr_tcaddr_tdaddr_tpgno_tpfn_tcnt_tpgcnt_tB_FALSEB_TRUEboolean_tid_tmajor_tminor_to_mode_to_dev_to_uid_to_gid_to_nlink_to_pid_to_ino_tmode_tdev_tuid_tgid_tnlink_tpid_tino_tino64_toff_toff64_t__scoff_tscoff_tblkcnt_tfsblkcnt_tfsfilcnt_tswblk_tpaddr_tkey_tuse_tsysid_tindex_tlock_tcpuid_tpri_taccum_tprid_tash_ttime_tclock_tclockid_ttimer_tuseconds_tbitnum_tbitlen_tprocessorid_ttoid_tqaddr_tinst_tmachreg_tfpreg_tint8_tuint8_tint16_tuint16_tint32_tuint32_tint64_tuint64_tintmax_tuintmax_tintptr_tuintptr_tu_int8_tu_int16_tu_int32_thostid_tsigbitsk_sigset_t/usr/include/sys/bsd_types.hfilthy:/usr/include/sys/bsd_types.h8851265491432rphysadruncharu_charushortu_shortuintu_intulongu_long_quadvalquad/usr/include/sys/select.hfilthy:/usr/include/sys/select.h8851265492842fd_mask_tufd_mask_tfd_setfds_bitsfd_setfd_mask/usr/include/stddef.hfilthy:/usr/include/stddef.h8851265491975ptrdiff_t../port/port_after.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/html/../port/port_after.h8851265493058falsetrueboolbyteword../common/common.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/html/../common/common.h8851265492810MemPoolPMemPoolGListPGList../common/url.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/html/../common/url.h8851265491800schemeusernamepasswordhostnameportfilenameparamsqueryfragmentURLParts../chimera/Chimera.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/html/../chimera/Chimera.h8851265492075ChimeraResourcesPChimeraResourcesChimeraContextPChimeraContextChimeraTaskPChimeraTaskChimeraTaskProcChimeraTimeOutPChimeraTimeOutChimeraTimeOutProc./css.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/html/./css.h8851265491418CSSPropertyPCSSPropertyCSSSelectorPCSSSelectorCSSRulePCSSRuleCSSContextPCSSContextCSSProcCSSPropertyPcrnamevalueCSSSelectorPtagidclasspclassCSSRulePselectorspropertiesCSSContextPmpcsinputsrulespropsprocclosuretask/usr/include/sys/time.hfilthy:/usr/include/sys/time.h8851265496598stamp_tUSTMSCpairustmscUSTMSCpairtimevaltv_sectv_usec__irix5_timevaltv_sectv_usecitimervalit_intervalit_valuetimezonetz_minuteswesttz_dsttimetimestructv_sectv_nsectimestruc_t/usr/include/sys/signal.hfilthy:/usr/include/sys/signal.h88512654915759SIG_PFsigvalsival_intsival_ptrsigval_tnotifyinfonisignonifuncnotifyinfo_tsigeventsigev_notifysigev_notifyinfosigev_valuesigev_reservedsigev_padsigevent_tsiginfosi_signosi_codesi_errnosi_pad__pid__uid__kill__utime__status__stime__cld__pdata__proc__addr__fault__fd__band__file__value__datasiginfo_t__sigbitssigset_t__sighandler__sa_handler__sa_sigaction__sighandler_tsigactionsa_flagssa_sighandlersa_masksa_resvsigaction_tsigstackss_spss_onstacksigaltstackss_spss_sizess_flagsstack_tsigcontextsc_regmasksc_statussc_pcsc_regssc_fpregssc_ownedfpsc_fpc_csrsc_fpc_eirsc_ssflagssc_mdhisc_mdlosc_causesc_badvaddrsc_triggersavesc_sigsetsc_fp_rounded_resultsc_pancakesc_padsigcontext_t/usr/include/sys/ucontext.hfilthy:/usr/include/sys/ucontext.h8851265495548greg_tgregset_tfpregsetfp_dregsfp_fregsfp_regsfp_rfp_csrfp_padfpregset_tgregsfpregsmcontext_tucontextuc_flagsuc_linkuc_sigmaskuc_stackuc_mcontextuc_pancakeuc_filleruc_triggersaveucontext_t/usr/include/sys/ptimers.hfilthy:/usr/include/sys/ptimers.h8851265491476timespectv_sectv_nsectimespec_titimerspecit_intervalit_valueitimerspec_tptimer_infonext_timeoutinterval_ticksignovalueclock_typenext_toidoverrun_cntptimer_info_t/usr/include/time.hfilthy:/usr/include/time.h8851265494826tmtm_sectm_mintm_hourtm_mdaytm_montm_yeartm_wdaytm_ydaytm_isdst/usr/include/sys/stat.hfilthy:/usr/include/sys/stat.h8851265496678statst_devst_pad1st_inost_modest_nlinkst_uidst_gidst_rdevst_pad2st_sizest_pad3st_atimst_mtimst_ctimst_blksizest_blocksst_fstypest_pad4stat64st_devst_pad1st_inost_modest_nlinkst_uidst_gidst_rdevst_pad2st_sizest_pad3st_atimst_mtimst_ctimst_blksizest_blocksst_fstypest_pad4list.cfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/common/list.c8838956265501/usr/bin/cc -g -fullwarn -xansi -32 -mips2 -Wf,-XNh2000 -I./ -I../port -nostdinc -I/usr/include -DSYSV -DSVR4 -DHAVE_STDLIB_H -DHAVE_STRING_H -DHAVE_UNISTD_H -DHAVE_STDDEF_H -DHAVE_UNAME -DHAVE_MKTIME -DHAVE_SIZE_T -DHAVE_SSIZE_T -DHAVE_STDARG_H -DFUNCPROTO=7 -DNARROWPROTO -c list.c/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/commonGNodePthingprevnextFreeListNodeglfGetFreedNodeglfGListCreateXmpglGListCreateTracklinefilempglGListPopglthingfGListAddHeadglthinggnGListAddTailglthinggnGListDestroyglGListGetHeadglGListGetTailglGListGetNextglGListGetPrevglGListGetCurrentglGListRemoveItemglthingcnGListEmptyglGListMPglGListPrintStatusGListClearglct/usr/include/stdlib.hfilthy:/usr/include/stdlib.h8838956267379quotremdiv_tquotremldiv_tquotremlldiv_tssize_twchar_t../port/port_after.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/common/../port/port_after.h8838956263058falsetrueboolbyteword./common.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/common/./common.h8838956262810MemPoolPMemPoolGListPGListGListPlocalmpmpfheadtailcmempool.cfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/common/mempool.c8838956275492/usr/bin/cc -g -fullwarn -xansi -32 -mips2 -Wf,-XNh2000 -I./ -I../port -nostdinc -I/usr/include -DSYSV -DSVR4 -DHAVE_STDLIB_H -DHAVE_STRING_H -DHAVE_UNISTD_H -DHAVE_STDDEF_H -DHAVE_UNAME -DHAVE_MKTIME -DHAVE_SIZE_T -DHAVE_SSIZE_T -DHAVE_STDARG_H -DFUNCPROTO=7 -DNARROWPROTO -c mempool.c/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/commonAlignmentabcdealignAlignmentpoolusedlennextcreate_poolalenblenlenplenpooluse_poolpoollenmemMPCreateTracklinefilemppoolMPGetmplenpoolmemMPCGetmplenmMPStrDupmpslennsMPDestroympmtMPPrintStatus./common.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/common/./common.h8838956272810MemPoolPMemPoolGListPGListMemPoolPplistlendmem.cfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/common/dmem.c8838956281428/usr/bin/cc -g -fullwarn -xansi -32 -mips2 -Wf,-XNh2000 -I./ -I../port -nostdinc -I/usr/include -DSYSV -DSVR4 -DHAVE_STDLIB_H -DHAVE_STRING_H -DHAVE_UNISTD_H -DHAVE_STDDEF_H -DHAVE_UNAME -DHAVE_MKTIME -DHAVE_SIZE_T -DHAVE_SSIZE_T -DHAVE_STDARG_H -DFUNCPROTO=7 -DNARROWPROTO -c dmem.c/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/commonfree_memmcalloc_memlenelenalloc_memlenrealloc_memslenalloc_stringstrns./common.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/common/./common.h8838956282810MemPoolPMemPoolGListPGListutil.cfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/common/util.c8838956293358/usr/bin/cc -g -fullwarn -xansi -32 -mips2 -Wf,-XNh2000 -I./ -I../port -nostdinc -I/usr/include -DSYSV -DSVR4 -DHAVE_STDLIB_H -DHAVE_STRING_H -DHAVE_UNISTD_H -DHAVE_STDDEF_H -DHAVE_UNAME -DHAVE_MKTIME -DHAVE_SIZE_T -DHAVE_SSIZE_T -DHAVE_STDARG_H -DFUNCPROTO=7 -DNARROWPROTO -c util.c/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/commonFixPathmpfilenamepcpcp2usernamefnamehomenewfilenamemystrtoksccdrcpcp2strGetBaseFilenamepathcpxmyassertisokmsgfilelinemytmpnammpn/usr/include/sys/types.hfilthy:/usr/include/sys/types.h88389562913084uchar_tushort_tuint_tulong_taddr_tcaddr_tdaddr_tpgno_tpfn_tcnt_tpgcnt_tB_FALSEB_TRUEboolean_tid_tmajor_tminor_to_mode_to_dev_to_uid_to_gid_to_nlink_to_pid_to_ino_tmode_tdev_tuid_tgid_tnlink_tpid_tino_tino64_toff_toff64_t__scoff_tscoff_tblkcnt_tfsblkcnt_tfsfilcnt_tswblk_tpaddr_tkey_tuse_tsysid_tindex_tlock_tcpuid_tpri_taccum_tprid_tash_tssize_ttime_tclock_twchar_tclockid_ttimer_tuseconds_tbitnum_tbitlen_tprocessorid_ttoid_tqaddr_tinst_tmachreg_tfpreg_tint8_tuint8_tint16_tuint16_tint32_tuint32_tint64_tuint64_tintmax_tuintmax_tintptr_tuintptr_tu_int8_tu_int16_tu_int32_thostid_tsigbitsk_sigset_t/usr/include/pwd.hfilthy:/usr/include/pwd.h8838956292775passwdpw_namepw_passwdpw_uidpw_gidpw_agepw_commentpw_gecospw_dirpw_shellxpasswdpw_namepw_passwdpw_uidpw_gidpw_agepw_commentpw_gecospw_dirpw_shellpw_originpw_yp_passwdpw_yp_gecospw_yp_dirpw_yp_shellpw_yp_netgroupcommentc_deptc_namec_acctc_bin/usr/include/errno.hfilthy:/usr/include/errno.h8838956291843/usr/include/stdlib.hfilthy:/usr/include/stdlib.h8838956297379quotremdiv_tquotremldiv_tquotremlldiv_t/usr/include/unistd.hfilthy:/usr/include/unistd.h88389562912941timevalacct_spi/usr/include/sys/uio.hfilthy:/usr/include/sys/uio.h8838956292290ioveciov_baseiov_leniovec_t/usr/include/sys/utime.hfilthy:/usr/include/sys/utime.h883895629613utimbufactimemodtime/usr/include/utime.hfilthy:/usr/include/utime.h8838956291328/usr/include/re_comp.hfilthy:/usr/include/re_comp.h883895629968snprintf.cfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/port/snprintf.c8838956248379/usr/bin/cc -g -fullwarn -xansi -32 -mips2 -Wf,-XNh2000 -I./ -nostdinc -I/usr/include -DSYSV -DSVR4 -DHAVE_STDLIB_H -DHAVE_STRING_H -DHAVE_UNISTD_H -DHAVE_STDDEF_H -DHAVE_UNAME -DHAVE_MKTIME -DHAVE_SIZE_T -DHAVE_SSIZE_T -DHAVE_STDARG_H -DFUNCPROTO=7 -DNARROWPROTO -c snprintf.c/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/portoutputendvsnprintfstrcountfmtargssnprintfstrcountfmt...apdoprbufferformatargschvaluelongflagstrvalueljustlenzpadprecisionset_precisiondvalnextchbfmtstrvalueljustlenzpadprecisionpadlenstrlenifmtnumvaluebasedosignljustlenzpadprecisionsignvalueuvalueconvertplacepadlencapsfmtdoublefmtvalueljustlenzpadprecisionconvertfmtstrldostrstrdopr_outchc./port_after.hfilthy:/a/truth.physics.unlv.edu/other/john/chimera/chimera-2.0a15/port/./port_after.h8838956243058falsetrueboolbytewordcrtninit.s.text.init__Argv__rld_obj_headexit__start_environ__istart__readenv_sigfpemain_mcount_gp_disp__Argc__iobMPCGetMPGetstrncpystrlenGListCreateXGListAddTailGListGetHeadstrcasecmpGListPopCSSParseBufferMPCreateTrackGListAddHeadCSSDestroyContextMPDestroyGListGetNextCSSCreateSelectorCSSSetSelectorCSSFindPropertyGListGetTailGListCreateTrackGListDestroyCSSPrintSelectorListfprintfCSSPrintprintfstatalloc_memfopenfreadfclose.rodatamemsetGListGetPrevGListGetCurrentGListRemoveItemGListEmptyGListMPGListPrintStatusGListClearmallocxmyassertMPStrDupstrcpyfreeMPPrintStatusfree_memcalloc_memcallocrealloc_memreallocalloc_stringFixPathgetenvgetpwnamstrcatmystrtokGetBaseFilenamefflushabortmytmpnamsnprintfgetpidtime.bssvsnprintfsprintflibXaw.so.2sgi2.0libXmu.sosgi1.0libXt.sosgi1.0libXext.sosgi1.0libX11.so.1sgi1.0libm.sosgi1.0libc.so.1sgi1.0libw.sosgi1.0libgen.sosgi1.0_endend_edataedata_etextetext__elf_header_ftextftext_fdatafdata_fbssfbss__program_header_table__dso_displacementvendorShellWidgetClassvendorShellClassRec@ÀS J €@@ÀS.  €@@À/ €@@À°4 €@@Àä+$ €@@ÀJ- €@@%’ÆK F6A’@·¬Þ RLÓ@c–èm5bÓ@ùNö¢xÓ@GLø²ŽÓ@“NúǤÓ@áŽüÖºÓ@oïXînÐÓ@ ^ªg\!æÓ@ Šy }üÓ@ ’X‚—Ó@ ê§… ¦(Ó@ ‘§Ž¸>Ó@8Ò”ÓTÓ@ *¢ í)jÓ@4f®$M€Ó@šÒc-–Ó@¯Hïi̬Ó@÷-X\UÂÓ@$ w±-ØÓ@.“ ÞîÓ@Á†š*ù‡Ó@7GTÄq (€ ÓŠ@7›Ž5)& ]@7)©H );2 ]@7Ò¹Q)M-> ]@?°‹×_L 52)zzJ ]J@?°"b¬« 1ô!V §@D€#6µ gt1)b §@D€%D™Ó6>n º@FP%ÝÙ- Ûs6YCzºM@FP(\ÿZ;œn‘@FP+[X`$; 2¨@FP,³L„;<¿@FP,ÿ~†;QÖ@FP-}`—;oí@FP-Ýo›;„@FP.Lj¢;š@FP.¶L¨;¯2@FP/Oª;¾I@L /Qw¬^ NÇ;ÍR` ¿@L 2È› C j Æ@[P3c C 1t€Æ                                 !   !"   #"   #$ % &'()*+,-#$ % &'()*+,-#$ % &'()*+,-#$ % &'()*+,-#$ % &'()*+,-#$ % &'()*+,-#$ % &'()*+,-#$ % &'()*+,-#$ % &'()*+,-#$ % &'()*+,-#. % /. % /0ÿÿ@À/ÿÿÿÿ@[@ÏÿÿÿÿË`Oÿÿÿÿ cðoÿÿÿÿ8ÿÿÿÿ%/ÿÿÿÿOÿÿÿÿÜ@/ÿÿÿÿ@4/ÿÿÿÿð@,/ÿÿÿÿé@,/ÿÿ(@À X@Ü |@10 ¨Ú@<´ Iç@= N÷@=L S@>  [@>Ü `@? e+@?$ i \@DT G"j@D€ "s@DÐ "…@Ep "™@EÄ $¦@FP $Å@Hœ $Î@IÐ $ë@K` &ÿÿÖ@[`/ÿÿÿÿÏ@[`/ÿÿÿÿö`Oÿÿÿÿý`OÿÿÿÿpOÿÿÿÿÉpOÿÿÿÿ pOÿÿÿÿÂpOÿÿtoÿÿÿÿ¹t Oÿÿÿÿ¾t Oÿÿ`âð¯ÿÿ0ÏÿÿpÀ#@0ÏÿÿB@@Ïÿÿ ƒ@PÏÿÿ ‹@`Ïÿÿ ¹@pÏÿÿ‘@€Ïÿÿ¢@Ïÿÿ©@ Ïÿÿ¸@°Ïÿÿ¾@ÀÏÿÿÄ@ÐÏÿÿ Ó@àÏÿÿ6@ðÏÿÿ P@ÏÿÿW@Ïÿÿ~@ Ïÿÿ‘@0Ïÿÿ(®@@Ïÿÿ&µ@PÏÿÿ ¾@`ÏÿÿÞ@pÏÿÿ(å@€Ïÿÿ)ý@Ïÿÿ@ Ïÿÿ@°ÏÿÿÍ@+4 v÷@,¼ ‚ @.˜ 2@.è ”A@/  ™@2¤ ®S@4p ·’@7Ð ^@8< Ä@8Ì ê@9  'Ÿ@:ˆ .o@;p 5¬@;Ð :Q@< ?@X renderer * * Copyright (c) 1994-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" static void EndTag _ArgProto((HTMLInfo, HTMLTag, MLElement)); static void StartTag _ArgProto((HTMLInfo, HTMLTag, MLElement)); static void AddObject _ArgProto((HTMLInfo, HTMLObjectType, void *)); static void DoEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); static bool BoxifyObject _ArgProto((HTMLInfo, HTMLEnv, HTMLObject)); static bool Boxify _ArgProto((HTMLInfo, HTMLEnv)); static void HTMLDocumentBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); static void HTMLDocumentEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); static void HTMLDocumentAddBox _ArgProto((HTMLInfo, HTMLEnv, HTMLBox)); static unsigned int HTMLDocumentWidth _ArgProto((HTMLInfo, HTMLEnv)); static void Unboxify _ArgProto((HTMLInfo, HTMLEnv)); static void PrintObject _ArgProto((HTMLObject)); #include "htmltags.h" typedef struct { HTMLTag tag; MLElement p; } PendingEnd; struct av { char *name; HTMLAttribID align; }; struct av alist[] = { { "left", ATTRIB_LEFT }, { "right", ATTRIB_RIGHT }, { "center", ATTRIB_CENTER }, { "top", ATTRIB_TOP }, { "bottom", ATTRIB_BOTTOM }, { "middle", ATTRIB_MIDDLE }, { "all", ATTRIB_ALL }, { NULL, ATTRIB_UNKNOWN } }; static int alist_len = sizeof(alist) / sizeof(alist[0]); /* * HTMLAttributeToID */ HTMLAttribID HTMLAttributeToID(p, name) MLElement p; char *name; { char *value; int i; if ((value = MLFindAttribute(p, name)) == NULL) return(ATTRIB_UNKNOWN); for (i = 0; i < alist_len; i++) { if (alist[i].name != NULL && strcasecmp(value, alist[i].name) == 0) { return(alist[i].align); } } return(ATTRIB_UNKNOWN); } /* * HTMLGetTag */ HTMLTag HTMLGetTag(p) MLElement p; { int i; char *name; if ((name = MLTagName(p)) == NULL) return(NULL); for (i = 0; i < tlist_len; i++) { if (tlist[i].name != NULL && strlen(name) == strlen(tlist[i].name) && strcasecmp(name, tlist[i].name) == 0 && !HTMLTestM(&tlist[i], MARKUP_FAKE)) { return(&tlist[i]); } } return(NULL); } /* * HTMLTagIDToTag */ HTMLTag HTMLTagIDToTag(tagid) HTMLTagID tagid; { int i; for (i = 0; i < tlist_len; i++) { if (tlist[i].id == tagid) return(&tlist[i]); } return(NULL); } /* * HTMLFindEnv */ HTMLEnv HTMLFindEnv(li, tagid) HTMLInfo li; HTMLTagID tagid; { HTMLEnv env; GList list; list = li->envstack; for (env = (HTMLEnv)GListGetHead(list); env != NULL; env = (HTMLEnv)GListGetNext(list)) { if (env->tag->id == tagid) return(env); } return(NULL); } /* * HTMLDelayLayout */ void HTMLDelayLayout(li) HTMLInfo li; { li->delayed++; return; } /* * HTMLContinueLayout */ void HTMLContinueLayout(li) HTMLInfo li; { myassert(li->delayed > 0, "Layout was not delayed."); li->delayed--; if (li->delayed == 0) Boxify(li, li->topenv); return; } /* * HTMLTagToID */ HTMLTagID HTMLTagToID(tag) HTMLTag tag; { return(tag->id); } /* * HTMLPopEnv */ HTMLEnv HTMLPopEnv(li, tagid) HTMLInfo li; HTMLTagID tagid; { HTMLEnv c; /* if (tagid == TAG_DOCUMENT) abort(); */ for (c = (HTMLEnv)GListGetHead(li->envstack); c != NULL; c = (HTMLEnv)GListGetNext(li->envstack)) { if (c->tag->id == tagid) break; } if (c == NULL) return(NULL); while ((c = (HTMLEnv)GListGetHead(li->envstack)) != NULL) { if (c->tag->id == tagid) break; DoEnd(li, c, NULL); } return(c); } /* * HTMLStartEnv */ void HTMLStartEnv(li, tagid, p) HTMLInfo li; HTMLTagID tagid; MLElement p; { char *str; HTMLTag tag; tag = HTMLTagIDToTag(tagid); if (p == NULL) { str = MPGet(li->mp, strlen(tag->name) + 3); strcpy(str, "<"); strcat(str, tag->name); strcat(str, ">"); p = MLCreateTag(li->hs, str, strlen(str)); } StartTag(li, tag, p); return; } /* * HTMLEndEnv */ void HTMLEndEnv(li, tagid) HTMLInfo li; HTMLTagID tagid; { EndTag(li, HTMLTagIDToTag(tagid), NULL); return; } /* * HTMLGetMaxWidth */ unsigned int HTMLGetMaxWidth(li, env) HTMLInfo li; HTMLEnv env; { HTMLEnv c; for (c = env; c != NULL; c = c->penv) { if (c->tag->w != NULL) return((c->tag->w)(li, c)); } return(0); } /* * PrintObject */ static void PrintObject(ho) HTMLObject ho; { char *text; size_t len; MLElementType mt; if (ho->type == HTML_ELEMENT) { MLGetText(ho->o.p, &text, &len); fwrite (text, 1, len, stdout); printf ("\n"); } else if (ho->type == HTML_TAG || ho->type == HTML_BEGINTAG || ho->type == HTML_ENDTAG) { mt = MLGetType(ho->o.p); if (mt == ML_ENDTAG) printf ("End tag: %s\n", MLTagName(ho->o.p)); else printf ("Begin tag: %s\n", MLTagName(ho->o.p)); } return; } /* * AddObject */ static void AddObject(li, hot, obj) HTMLInfo li; HTMLObjectType hot; void *obj; { HTMLEnv env; HTMLObject ho; ho = (HTMLObject)MPGet(li->mp, sizeof(struct HTMLObjectP)); ho->type = hot; if (hot == HTML_ENV) ho->o.env = (HTMLEnv)obj; else if (hot == HTML_ELEMENT) ho->o.p = (MLElement)obj; else if (hot == HTML_TAG) ho->o.p = (MLElement)obj; else if (hot == HTML_BEGINTAG) ho->o.p = (MLElement)obj; else if (hot == HTML_ENDTAG) ho->o.p = (MLElement)obj; else abort(); if (li->printTags) PrintObject(ho); if (hot != HTML_BEGINTAG && hot != HTML_ENDTAG) { for (env = (HTMLEnv)GListGetHead(li->envstack); env != NULL; env = (HTMLEnv)GListGetNext(li->envstack)) { if (env->tag->m == NULL || (env->tag->m)(li, ho)) break; } if (env == NULL) return; } else env = (HTMLEnv)GListGetHead(li->envstack); if (hot == HTML_ENV) ho->o.env->penv = env; /* * Add object to the object list for the environment. The first list * will be modified later. The second list will always stay the * same so there is always a place to find all the objects in an * environment. */ GListAddTail(env->olist, ho); GListAddTail(env->slist, ho); return; } /* * DoEnd */ static void DoEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { char *name; char *str; if (p == NULL) { if (env->tag->name == NULL) name = "internal"; else name = env->tag->name; str = (char *)MPGet(li->mp, strlen(name) + 4); strcpy(str, ""); p = MLCreateTag(li->hs, str, strlen(str)); } AddObject(li, HTML_ENDTAG, p); env = (HTMLEnv)GListPop(li->envstack); AddObject(li, HTML_ENV, env); return; } /* * EndTag */ static void EndTag(li, tag, p) HTMLInfo li; HTMLTag tag; MLElement p; { HTMLEnv etop; PendingEnd *pe; HTMLEnv env; /* * If there was no start tag then ignore. */ if (HTMLFindEnv(li, tag->id) == NULL) return; /* * Check to see if the end tag is supposed to clamp down on all * unterminated environments. */ if (HTMLTestM(tag, MARKUP_CLAMP)) { if (tag->c != NULL) { if ((tag->c)(li, (HTMLEnv)GListGetHead(li->envstack))) { while ((env = (HTMLEnv)GListGetHead(li->envstack)) != NULL) { DoEnd(li, env, NULL); if (env->tag->id == tag->id) break; } } } else { while ((env = (HTMLEnv)GListGetHead(li->envstack)) != NULL) { DoEnd(li, env, NULL); if (env->tag->id == tag->id) break; } } if ((pe = (PendingEnd *)GListPop(li->endstack)) != NULL) { EndTag(li, pe->tag, pe->p); return; } } else { /* * Make sure the end tag matches the current environment before * terminating the environment. If it doesn't match then stick it * in a list for possible use later. */ etop = (HTMLEnv)GListGetHead(li->envstack); if (tag->id == etop->tag->id) { DoEnd(li, etop, p); if ((pe = (PendingEnd *)GListPop(li->endstack)) != NULL) { EndTag(li, pe->tag, pe->p); return; } } else { pe = MPGet(li->mp, sizeof(PendingEnd)); pe->tag = tag; pe->p = p; GListAddTail(li->endstack, pe); } } return; } /* * StartTag */ static void StartTag(li, tag, p) HTMLInfo li; HTMLTag tag; MLElement p; { HTMLEnv env; HTMLEnv etop; HTMLInsertStatus status; if ((etop = (HTMLEnv)GListGetHead(li->envstack)) != NULL) { if (tag->p != NULL) { if ((status = (tag->p)(li, etop, p)) == HTMLInsertReject) return; } else status = HTMLInsertOK; } else status = HTMLInsertOK; if (!HTMLTestM(tag, MARKUP_EMPTY) || status == HTMLInsertEmpty) { env = MPCGet(li->mp, sizeof(struct HTMLEnvP)); env->tag = tag; env->olist = GListCreateX(li->mp); env->blist = GListCreateX(li->mp); env->slist = GListCreateX(li->mp); if (etop == NULL) li->topenv = env; GListAddHead(li->envstack, env); AddObject(li, HTML_BEGINTAG, p); } else AddObject(li, HTML_TAG, p); return; } /* * HTMLHandler * * This is where elements from the ML scanner come into the HTML parser. */ void HTMLHandler(closure, p) void *closure; MLElement p; { HTMLInfo li = (HTMLInfo)closure; HTMLTag tag; MLElementType mt; if ((mt = MLGetType(p)) == ML_EOF) { /* * fake a tag. */ HTMLFinish(li); /* * Render the parsed HTML */ Boxify(li, li->topenv); return; } else if (mt == ML_DATA) AddObject(li, HTML_ELEMENT, p); else if ((tag = HTMLGetTag(p)) != NULL) { if (mt == ML_ENDTAG) EndTag(li, tag, p); else StartTag(li, tag, p); } else if (li->printTags) { printf ("Unknown tag: %s\n", MLTagName(p)); } return; } /* * BoxifyObject */ static bool BoxifyObject(li, env, obj) HTMLInfo li; HTMLEnv env; HTMLObject obj; { HTMLTag tag; HTMLEnv cenv; CSSSelector cs; if (obj->type == HTML_ELEMENT) { if (env->tag->d != NULL) (env->tag->d)(li, env, obj->o.p); } else if (obj->type == HTML_TAG) { if ((tag = HTMLGetTag(obj->o.p)) != NULL) { myassert(tag->b != NULL, "No tag handler for lone tag!"); (tag->b)(li, env, obj->o.p); } } else if (obj->type == HTML_ENV) { cenv = obj->o.env; if (!cenv->visited) { cenv->ff = env->ff; cenv->anchor = env->anchor; cenv->fi = HTMLDupFont(li, env->fi); if (HTMLTestM(cenv->tag, MARKUP_SPACER)) { HTMLAddBlankLine(li, env); } cenv->visited = true; } if ((cs = (CSSSelector)GListPop(li->oldselectors)) == NULL) { cs = CSSCreateSelector(li->mp); } CSSSetSelector(cs, cenv->tag->name, NULL, NULL, NULL); GListAddHead(li->selectors, cs); if (Boxify(li, cenv)) return(true); GListAddHead(li->oldselectors, GListPop(li->selectors)); if (HTMLTestM(cenv->tag, MARKUP_SPACER)) { HTMLAddBlankLine(li, env); } } else if (obj->type == HTML_BEGINTAG) { if (env->tag->b != NULL) (env->tag->b)(li, env, obj->o.p); } else if (obj->type == HTML_ENDTAG) { if (env->tag->e != NULL) (env->tag->e)(li, env, obj->o.p); } else abort(); if (li->delayed > 0) { return(true); } return(false); } /* * Unboxify */ static void Unboxify(li, env) HTMLInfo li; HTMLEnv env; { HTMLObject c; GList t; env->visited = false; while ((c = (HTMLObject)GListPop(env->olist)) != NULL) { GListAddTail(env->blist, c); } t = env->olist; env->olist = env->blist; env->blist = t; for (c = (HTMLObject)GListGetHead(env->olist); c != NULL; c = (HTMLObject)GListGetNext(env->olist)) { if (c->type == HTML_ENV) Unboxify(li, c->o.env); } return; } /* * Boxify */ bool Boxify(li, env) HTMLInfo li; HTMLEnv env; { HTMLObject c; myassert(li->delayed == 0, "yikes"); while ((c = (HTMLObject)GListPop(env->olist)) != NULL) { if (BoxifyObject(li, env, c)) { if (c->type == HTML_ENV) GListAddHead(env->olist, c); else GListAddTail(env->blist, c); return(true); } else GListAddTail(env->blist, c); } if (HTMLTestM(env->tag, MARKUP_TWOPASS) && env->pass == 0) { env->pass++; Unboxify(li, env); Boxify(li, env); } return(false); } /* * HTMLEnvAddBox */ void HTMLEnvAddBox(li, env, box) HTMLInfo li; HTMLEnv env; HTMLBox box; { HTMLEnv c; for (c = env; c != NULL; c = c->penv) { if (c->tag->a != NULL) { (c->tag->a)(li, c, box); break; } } return; } /* * HTMLDocumentEnd */ static void HTMLDocumentEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLFinishFlowBox(li, li->firstbox); return; } /* * HTMLDocumentBegin */ static void HTMLDocumentBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { return; } /* * HTMLDocumentWidth */ static unsigned int HTMLDocumentWidth(li, env) HTMLInfo li; HTMLEnv env; { return(HTMLGetBoxWidth(li, li->firstbox)); } /* * HTMLDocumentAddBox */ static void HTMLDocumentAddBox(li, env, box) HTMLInfo li; HTMLEnv env; HTMLBox box; { HTMLLayoutBox(li, li->firstbox, box); return; } /* * HTMLFinish */ void HTMLFinish(li) HTMLInfo li; { HTMLPopEnv(li, TAG_DOCUMENT); HTMLEndEnv(li, TAG_DOCUMENT); return; } /* * HTMLStart */ void HTMLStart(li) HTMLInfo li; { HTMLStartEnv(li, TAG_DOCUMENT, MLCreateTag(li->hs, "", strlen(""))); li->topenv->ff = FLOW_LEFT_JUSTIFY; li->topenv->anchor = NULL; li->topenv->fi = HTMLDupFont(li, li->cfi); li->firstbox = HTMLCreateFlowBox(li, li->topenv, li->maxwidth - (li->lmargin + li->rmargin)); li->firstbox->x = li->lmargin; li->firstbox->y = li->rmargin; HTMLSetB(li->firstbox, BOX_TOPLEVEL); return; } /* * HTMLGetIDEnv */ HTMLEnv HTMLGetIDEnv(env, tid) HTMLEnv env; HTMLTagID tid; { HTMLEnv penv; HTMLTagID ptid; penv = env; while ((ptid = HTMLTagToID(penv->tag)) != TAG_DOCUMENT) { if (ptid == tid) return(penv); penv = penv->penv; } return(NULL); } chimera-2.0a19/html/html.h100600 11610 11610 42477 6677561631 13655 0ustar johnjohn/* * html.h * * libhtml - HTML->X renderer * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __HTML_H__ #define __HTML_H__ 1 #include #include #include "common.h" #include "Chimera.h" #include "ChimeraRender.h" #include "ChimeraGUI.h" #include "ml.h" #include "css.h" /* proposed HTML3.2 tags and some internal tags */ typedef enum { /* internal tags */ TAG_DOCUMENT, /* implemented? */ TAG_BR, TAG_ADDRESS, TAG_DIV, TAG_CENTER, TAG_A, TAG_MAP, TAG_AREA, TAG_IMG, TAG_HR, TAG_P, TAG_PRE, TAG_XMP, TAG_LISTING, TAG_PLAINTEXT, TAG_BLOCKQUOTE, TAG_DL, TAG_DD, TAG_DT, TAG_OL, TAG_UL, TAG_DIR, TAG_MENU, TAG_LI, TAG_FORM, TAG_INPUT, TAG_SELECT, TAG_OPTION, TAG_TEXTAREA, TAG_TABLE, TAG_TR, TAG_TH, TAG_TD, TAG_TITLE, TAG_BASE, TAG_SCRIPT, TAG_H1, TAG_H2, TAG_H3, TAG_H4, TAG_H5, TAG_H6, TAG_TT, TAG_I, TAG_B, TAG_STRIKE, TAG_BIG, TAG_SMALL, TAG_SUB, TAG_SUP, TAG_EM, TAG_STRING, TAG_DFN, TAG_CODE, TAG_SAMP, TAG_KBD, TAG_VAR, TAG_CITE, TAG_STRONG, /* do not implement */ TAG_HTML, TAG_BODY, TAG_HEAD, /* weird stuff? */ TAG_IFRAME, TAG_FRAME, TAG_FRAMESET, TAG_NOFRAMES, /* unimplemented */ TAG_LINK, TAG_APPLET, TAG_META, TAG_STYLE, TAG_CAPTION, TAG_FONT, TAG_PARAM, TAG_ISINDEX } HTMLTagID; typedef struct HTMLBoxP *HTMLBox; typedef struct HTMLInfoP *HTMLInfo; typedef struct HTMLClassP *HTMLClass; typedef struct HTMLObjectP *HTMLObject; typedef struct HTMLEnvP *HTMLEnv; typedef struct HTMLFontP *HTMLFont; typedef struct HTMLFontListP *HTMLFontList; typedef struct HTMLAnchorP *HTMLAnchor; typedef struct HTMLTagP *HTMLTag; typedef struct HTMLMapP *HTMLMap; typedef struct HTMLAreaP *HTMLArea; typedef struct HTMLStateP *HTMLState; /* * Box callbacks */ typedef void (*HTMLSetupProc) _ArgProto((HTMLInfo, HTMLBox)); typedef void (*HTMLDestroyProc) _ArgProto((HTMLInfo, HTMLBox)); typedef void (*HTMLRenderProc) _ArgProto((HTMLInfo, HTMLBox, Region)); typedef void (*HTMLLayoutProc) _ArgProto((HTMLInfo, HTMLBox, HTMLBox)); typedef unsigned int (*HTMLWidthProc) _ArgProto((HTMLInfo, HTMLBox)); /* * Tag callbacks */ typedef bool (*HTMLTagClampProc) _ArgProto((HTMLInfo, HTMLEnv)); typedef void (*HTMLTagRenderProc) _ArgProto((HTMLInfo, HTMLEnv, MLElement)); typedef bool (*HTMLTagAcceptProc) _ArgProto((HTMLInfo, HTMLObject)); typedef enum { HTMLInsertEmpty, HTMLInsertReject, HTMLInsertOK } HTMLInsertStatus; typedef HTMLInsertStatus (*HTMLTagInsertProc) _ArgProto((HTMLInfo, HTMLEnv, MLElement)); typedef void (*HTMLTagDataProc) _ArgProto((HTMLInfo, HTMLEnv, MLElement)); typedef void (*HTMLTagAddBoxProc) _ArgProto((HTMLInfo, HTMLEnv, HTMLBox)); typedef unsigned int (*HTMLTagWidthProc) _ArgProto((HTMLInfo, HTMLEnv)); typedef enum { FLOW_LEFT_JUSTIFY, FLOW_CENTER_JUSTIFY, FLOW_RIGHT_JUSTIFY } HTMLFlowAlign; /* * Environment */ typedef enum { HTML_ENV, HTML_ELEMENT, HTML_TAG, HTML_BEGINTAG, HTML_ENDTAG } HTMLObjectType; struct HTMLObjectP { HTMLObjectType type; union { MLElement p; HTMLEnv env; } o; }; struct HTMLEnvP { /* Keep track of html structure */ HTMLEnv penv; /* parent environment */ HTMLTag tag; /* tag that defines environment */ GList olist; /* object list */ GList blist; /* boxed object list */ GList slist; /* static object list */ int pass; /* Keep track of HTML rendering */ bool visited; /* used by boxify functions */ MLElement anchor; /* anchor to use in environment */ HTMLFont fi; /* font to use in environment */ HTMLFlowAlign ff; /* alignment in flow box */ void *closure; /* environment specific data */ }; typedef enum { BOX_NONE = 0x00000000, /* no flags set */ BOX_SPACE = 0x00000001, /* horizontal space */ BOX_LINEBREAK = 0x00000002, /* line break, duh. */ BOX_FLOAT_LEFT = 0x00000008, /* float to the left edge */ BOX_FLOAT_RIGHT = 0x00000010, /* float to the right edge */ BOX_VCENTER = 0x00000020, /* vertically center in parent */ BOX_PUSHED_LEFT = 0x00000040, /* box pushed left by floater */ BOX_PUSHED_RIGHT = 0x00000080, /* box pushed right by floater */ BOX_SELECT = 0x00000100, /* anchor box selected */ BOX_TOPLEVEL = 0x00000200, /* toplevel box ? */ BOX_CLEAR_LEFT = 0x00000400, /* clear past left aligned */ BOX_CLEAR_RIGHT = 0x00000800 /* clear past right aligned */ } HTMLBoxFlags; #define HTMLTestB(a, b) (((a)->bflags & (b)) != 0) #define HTMLClearB(a, b) ((a)->bflags &= ~(b)) #define HTMLSetB(a, b) ((a)->bflags |= (b)) /* This is still too big */ struct HTMLBoxP { HTMLEnv env; /* */ int baseline; /* level of alignment */ int x, y; /* upper-left coordinates */ unsigned int width, height; /* external dimensions */ HTMLBoxFlags bflags; /* misc. worthless flags */ /* rendering functions */ HTMLRenderProc render; /* called when output needed */ HTMLDestroyProc destroy; /* called when destroyed */ HTMLSetupProc setup; /* called by parent box */ HTMLLayoutProc layout; /* child box layout */ HTMLWidthProc maxwidth; /* called to return maximum width */ void *closure; /* state for functions */ }; struct HTMLAnchorP { HTMLBox box; char *name; MLElement p; }; struct HTMLStateP { int x, y; }; struct HTMLClassP { MemPool mp; bool font_setup_done; Display *dpy; XFontStruct *defaultFont; HTMLFontList prop; HTMLFontList fixed; GList oldstates; GList fonts; GList contexts; CSSContext css; }; struct HTMLInfoP { /* X */ Widget widget; Display *dpy; Window win; GC gc; Pixel anchor_color; Pixel anchor_select_color; Pixel fg, bg; /* www lib */ ChimeraContext wc; ChimeraResources cres; ChimeraGUI wd; ChimeraSink wp; ChimeraTask wt; ChimeraRender wn; GList sinks; GList loads; /* HTML */ CSSContext css; bool reload; unsigned int maxwidth, maxheight; MemPool mp; MLState hs; HTMLClass lc; HTMLFont cfi; HTMLBox firstbox; HTMLState ps; HTMLEnv searchenv; HTMLObject searchobj; HTMLEnv topenv; /* document environment */ GList envstack; /* tag hierarchy */ GList selectors; /* CSS selector list */ GList oldselectors; /* old CSS selector list */ GList endstack; /* pending end tags */ GList alist; /* anchor box list */ ChimeraTimeOut sto; /* select timeout */ HTMLAnchor sa; /* selected anchor */ int delayed; char *url; /* original URL */ char *burl; /* base URL */ char *title; /* title text */ HTMLAnchor over; GList maps; bool cancel; bool formatted; /* inside PRE tags - djhjr */ bool noframeset; bool framesonly; GList framesets; /* list of frames */ /* configurable goodies */ int textLineSpace; bool printHTMLErrors; int tmargin, bmargin; /* top, bottom margins */ int rmargin, lmargin; /* right, left margins */ unsigned int inlineTimeOut; unsigned int selectTimeOut; /* select timeout time */ unsigned int tableCellInfinity; /* infinite width for table cell */ bool flowDebug; bool constraintDebug; bool printTags; /* print tag and data hierarchy */ }; typedef enum { ATTRIB_UNKNOWN, ATTRIB_LEFT, ATTRIB_RIGHT, ATTRIB_TOP, ATTRIB_BOTTOM, ATTRIB_CENTER, ATTRIB_MIDDLE, ATTRIB_ALL } HTMLAttribID; /* * inline.c */ typedef struct { MLElement p; void *closure; } HTMLInlineInfo; typedef struct HTMLInlineP *HTMLInline; HTMLInline HTMLCreateInline _ArgProto((HTMLInfo, HTMLEnv, char *, HTMLInlineInfo *, ChimeraRenderHooks *, void *)); HTMLBox HTMLInlineToBox _ArgProto((HTMLInline)); void HTMLInlineDestroy _ArgProto((HTMLInline)); /* * text.c */ HTMLBox HTMLCreateTextBox _ArgProto((HTMLInfo, HTMLEnv, char *, size_t)); char *HTMLGetEnvText _ArgProto((MemPool, HTMLEnv)); void HTMLStringSpacify _ArgProto((char *, size_t)); void HTMLAddLineBreak _ArgProto((HTMLInfo, HTMLEnv)); void HTMLAddBlankLine _ArgProto((HTMLInfo, HTMLEnv)); /* * layout.c */ HTMLBox HTMLCreateBox _ArgProto((HTMLInfo, HTMLEnv)); void HTMLLayoutBox _ArgProto((HTMLInfo, HTMLBox, HTMLBox)); void HTMLSetupBox _ArgProto((HTMLInfo, HTMLBox)); void HTMLRenderBox _ArgProto((HTMLInfo, Region, HTMLBox)); void HTMLDestroyBox _ArgProto((HTMLInfo, HTMLBox)); unsigned HTMLGetBoxWidth _ArgProto((HTMLInfo, HTMLBox)); /* * html.c */ HTMLAttribID HTMLAttributeToID _ArgProto((MLElement, char *)); HTMLTag HTMLGetTag _ArgProto((MLElement)); HTMLTag HTMLTagIDToTag _ArgProto((HTMLTagID)); bool HTMLHandleTag _ArgProto((HTMLInfo, HTMLTag, MLElement)); HTMLEnv HTMLFindEnv _ArgProto((HTMLInfo, HTMLTagID)); void HTMLDelayLayout _ArgProto((HTMLInfo)); void HTMLContinueLayout _ArgProto((HTMLInfo)); HTMLTagID HTMLTagToID _ArgProto((HTMLTag)); void HTMLHandler _ArgProto((void *, MLElement)); HTMLEnv HTMLPopEnv _ArgProto((HTMLInfo, HTMLTagID)); void HTMLStartEnv _ArgProto((HTMLInfo, HTMLTagID, MLElement)); void HTMLEndEnv _ArgProto((HTMLInfo, HTMLTagID)); unsigned int HTMLGetMaxWidth _ArgProto((HTMLInfo, HTMLEnv)); void HTMLEnvAddBox _ArgProto((HTMLInfo, HTMLEnv, HTMLBox)); void HTMLStart _ArgProto((HTMLInfo)); void HTMLFinish _ArgProto((HTMLInfo)); HTMLEnv HTMLGetIDEnv _ArgProto((HTMLEnv, HTMLTagID)); /* * font.c */ XFontStruct *HTMLGetFont _ArgProto((HTMLInfo, HTMLEnv)); void HTMLSetupFonts _ArgProto((HTMLInfo)); void HTMLFreeFonts _ArgProto((HTMLClass)); void HTMLAddFontSlant _ArgProto((HTMLFont)); void HTMLAddFontWeight _ArgProto((HTMLFont)); void HTMLAddFontScale _ArgProto((HTMLFont)); void HTMLSetFontScale _ArgProto((HTMLFont, int)); HTMLFont HTMLDupFont _ArgProto((HTMLInfo, HTMLFont)); void HTMLSetFontFixed _ArgProto((HTMLFont)); void HTMLSetFontProp _ArgProto((HTMLFont)); /* * load.c */ int HTMLLoadAnchor _ArgProto((HTMLInfo, HTMLAnchor, int, int, char *, bool)); void HTMLPrintAnchor _ArgProto((HTMLInfo, HTMLAnchor, int, int, bool)); char *HTMLMakeURL _ArgProto((HTMLInfo, MemPool, char *)); int HTMLLoadURL _ArgProto((HTMLInfo, char *, char *, char *)); void HTMLPrintURL _ArgProto((HTMLInfo, char *)); void HTMLFindName _ArgProto((HTMLInfo, char *)); void HTMLAddAnchor _ArgProto((HTMLInfo, HTMLBox, char *, MLElement)); /* * module.c */ void HTMLSetFinalPosition _ArgProto((HTMLInfo)); /* * flow.c */ HTMLBox HTMLCreateFlowBox _ArgProto((HTMLInfo, HTMLEnv, unsigned int)); void HTMLFinishFlowBox _ArgProto((HTMLInfo, HTMLBox)); /* * map.c */ char *HTMLFindMapURL _ArgProto((HTMLInfo, char *, int, int)); /* * * Tag/Env handlers * */ /* * form.c */ void HTMLFormBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLFormEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLInput _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLOptionEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLSelectBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLSelectEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLTextareaEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); /* * inline.c */ void HTMLImg _ArgProto((HTMLInfo, HTMLEnv, MLElement)); HTMLInsertStatus HTMLImgInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); /* * hr.c */ void HTMLHorizontalRule _ArgProto((HTMLInfo, HTMLEnv, MLElement)); /* * list.c */ HTMLInsertStatus HTMLLIInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLLIBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); HTMLInsertStatus HTMLDTInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLDTBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); HTMLInsertStatus HTMLDDInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLDDBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); bool HTMLListAccept _ArgProto((HTMLInfo, HTMLObject)); bool HTMLDLAccept _ArgProto((HTMLInfo, HTMLObject)); void HTMLULBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLListEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLOLBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLDLBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLListAddBox _ArgProto((HTMLInfo, HTMLEnv, HTMLBox)); void HTMLItemAddBox _ArgProto((HTMLInfo, HTMLEnv, HTMLBox)); unsigned int HTMLItemWidth _ArgProto((HTMLInfo, HTMLEnv)); void HTMLItemEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); /* * text.c */ void HTMLPreBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLPreEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLPlainBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLPlainEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLFillData _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLPreData _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLPlainData _ArgProto((HTMLInfo, HTMLEnv, MLElement)); /* * misc.c */ void HTMLHxBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLHxEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLParaBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLParaEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); HTMLInsertStatus HTMLParaInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLBreak _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLAddressBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLAddressEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLAnchorBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); HTMLInsertStatus HTMLAnchorInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLBQBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLBQEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLFontBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLDivBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLDivEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLCenterBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLCenterEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); /* * table.c */ bool HTMLTableAccept _ArgProto((HTMLInfo, HTMLObject)); void HTMLTableBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLTableEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); bool HTMLTRAccept _ArgProto((HTMLInfo, HTMLObject)); HTMLInsertStatus HTMLTRInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); bool HTMLTRClamp _ArgProto((HTMLInfo, HTMLEnv)); void HTMLTRBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLTREnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); HTMLInsertStatus HTMLTDInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); bool HTMLTDClamp _ArgProto((HTMLInfo, HTMLEnv)); void HTMLTDBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLTDEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); unsigned int HTMLTDWidth _ArgProto((HTMLInfo, HTMLEnv)); void HTMLTableAddBox _ArgProto((HTMLInfo, HTMLEnv, HTMLBox)); void HTMLTDAddBox _ArgProto((HTMLInfo, HTMLEnv, HTMLBox)); /* * head.c */ void HTMLBase _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLTitleEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLMeta _ArgProto((HTMLInfo, HTMLEnv, MLElement)); /* * map.c */ bool HTMLMapAccept _ArgProto((HTMLInfo, HTMLObject)); HTMLInsertStatus HTMLAreaInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLAreaBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLMapBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLMapEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); /* * frame.c */ void HTMLIFrame _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLFrame _ArgProto((HTMLInfo, HTMLEnv, MLElement)); HTMLInsertStatus HTMLFrameInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLFrameSetBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLFrameSetEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); bool HTMLFrameSetAccept _ArgProto((HTMLInfo, HTMLObject)); HTMLInsertStatus HTMLFrameSetInsert _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLNoFramesBegin _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLNoFramesEnd _ArgProto((HTMLInfo, HTMLEnv, MLElement)); void HTMLDestroyFrameSets _ArgProto((HTMLInfo)); void HTMLFrameLoad _ArgProto((HTMLInfo, ChimeraRequest *, char*)); #endif chimera-2.0a19/html/head.c100600 11610 11610 2473 6677561632 13556 0ustar johnjohn/* * head.c * * libhtml - HTML->X renderer * * Copyright (c) 1996-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" void HTMLTitleEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { li->title = HTMLGetEnvText(li->mp, env); return; } void HTMLBase(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { char *url; if ((url = MLFindAttribute(p, "href")) != NULL) li->burl = url; return; } void HTMLMeta(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { return; } chimera-2.0a19/html/module.c100600 11610 11610 26304 6724333661 14151 0ustar johnjohn/* * module.c * * libhtml - HTML->X renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_STDLIB_H #include #endif #include #include #include "port_after.h" #include "html.h" static bool InAnchor _ArgProto((int, int, HTMLBox)); static void HTMLAdd _ArgProto((void *)); static void HTMLEnd _ArgProto((void *)); static bool HTMLExpose _ArgProto((void *, int, int, unsigned int, unsigned int)); static bool HTMLMotion _ArgProto((void *, int, int)); static bool HTMLMouse _ArgProto((void *, int, int, char *)); static byte *HTMLQuery _ArgProto((void *, char *)); static int HTMLSearch _ArgProto((void *, char *, int)); static void HTMLDestroy _ArgProto((void *)); static void HTMLCancel _ArgProto((void *)); static void *HTMLInit _ArgProto((ChimeraRender, void *, void *)); static void *HTMLGetState _ArgProto((void *)); static void HTMLClassDestroy _ArgProto((void *)); int InitModule_HTML _ArgProto((ChimeraResources)); static void DeselectTimeOut _ArgProto((ChimeraTimeOut, void *)); static void DeselectTimeOut(wt, closure) ChimeraTimeOut wt; void *closure; { HTMLAnchor a; HTMLInfo li = (HTMLInfo)closure; for (a = (HTMLAnchor)GListGetHead(li->alist); a != NULL; a = (HTMLAnchor)GListGetNext(li->alist)) { if (a->p == li->sa->p) { HTMLClearB(a->box, BOX_SELECT); HTMLRenderBox(li, NULL, a->box); } } return; } static void HTMLAdd(closure) void *closure; { HTMLInfo li = (HTMLInfo)closure; byte *data; size_t len; MIMEHeader mh; if (li->cancel) return; SinkGetData(li->wp, &data, &len, &mh); MLAddData(li->hs, (char *)data, len); return; } static void HTMLEnd(closure) void *closure; { HTMLInfo li = (HTMLInfo)closure; byte *data; size_t len; MIMEHeader mh; if (li->cancel) return; SinkGetData(li->wp, &data, &len, &mh); MLEndData(li->hs, (char *)data, len); return; } static bool HTMLExpose(closure, x, y, width, height) void *closure; int x, y; unsigned int width, height; { HTMLInfo li = (HTMLInfo)closure; Region r; XRectangle rec; r = XCreateRegion(); rec.x = (short)x; rec.y = (short)y; rec.width = (unsigned short)width; rec.height = (unsigned short)height; XUnionRectWithRegion(&rec, r, r); HTMLRenderBox(li, r, li->firstbox); XDestroyRegion(r); return(true); } /* * InAnchor */ static bool InAnchor(x, y, box) int x, y; HTMLBox box; { if (x > box->x && x < box->x + box->width && y > box->y && y < box->y + box->height) { return(true); } return(false); } static bool HTMLMouse(closure, x, y, action) void *closure; int x, y; char *action; { HTMLInfo li = (HTMLInfo)closure; HTMLAnchor a; GList list; list = li->alist; for (a = (HTMLAnchor)GListGetHead(list); a != NULL; a = (HTMLAnchor)GListGetNext(list)) { if (InAnchor(x, y, a->box)) { if (a->p != NULL) { li->sa = a; for (a = (HTMLAnchor)GListGetHead(list); a != NULL; a = (HTMLAnchor)GListGetNext(list)) { if (a->p == li->sa->p) { HTMLSetB(a->box, BOX_SELECT); HTMLRenderBox(li, NULL, a->box); } } XFlush(li->dpy); HTMLLoadAnchor(li, li->sa, x, y, action, false); if (li->sto != NULL) TimeOutDestroy(li->sto); li->sto = TimeOutCreate(li->cres, li->selectTimeOut, DeselectTimeOut, li); } break; } } return(true); } static bool HTMLMotion(closure, x, y) void *closure; int x, y; { HTMLInfo li = (HTMLInfo)closure; HTMLAnchor a; GList list; list = li->alist; for (a = (HTMLAnchor)GListGetHead(list); a != NULL; a = (HTMLAnchor)GListGetNext(list)) { if (InAnchor(x, y, a->box)) break; } if (a == NULL || a->p == NULL) RenderSendMessage(li->wn, NULL); else HTMLPrintAnchor(li, a, x, y, false); li->over = a; return(true); } /* * HTMLQuery */ static byte * HTMLQuery(closure, key) void *closure; char *key; { HTMLInfo li = (HTMLInfo)closure; if (strcmp(key, "title") == 0) { if (li->title != NULL) return(li->title); } return(NULL); } /* * HTMLSearch * * And here's an interesting development...there is no way to do a * search for text unless another field is added to HTMLBox. That * is unsavory. Work on this later. */ static int HTMLSearch(closure, key, mode) void *closure; char *key; int mode; { return(-1); } /* * HTMLCancel */ static void HTMLCancel(closure) void *closure; { HTMLInfo li = (HTMLInfo)closure; ChimeraSink wp; myassert(li != NULL, "HTMLInfo is NULL!"); for (wp = (ChimeraSink)GListGetHead(li->sinks); wp != NULL; wp = (ChimeraSink)GListGetNext(li->sinks)) { SinkCancel(wp); } li->cancel = true; if (li->wt != NULL) { TaskRemove(li->cres, li->wt); li->wt = NULL; } return; } /* * HTMLDestroy */ static void HTMLDestroy(closure) void *closure; { HTMLInfo li = (HTMLInfo)closure; ChimeraSink wp; GListRemoveItem(li->lc->contexts, li); HTMLDestroyBox(li, li->firstbox); while ((wp = (ChimeraSink)GListPop(li->sinks)) != NULL) { SinkDestroy(wp); } HTMLDestroyFrameSets(li); if (li->wt != NULL) TaskRemove(li->cres, li->wt); if (li->sto != NULL) TimeOutDestroy(li->sto); if (li->hs != NULL) MLDestroy(li->hs); MPDestroy(li->mp); return; } /* * HTMLInit */ static void * HTMLInit(wn, closure, state) ChimeraRender wn; void *closure; void *state; { HTMLInfo li; HTMLClass lc = (HTMLClass)closure; MemPool mp; char *url; ChimeraSink wp; ChimeraGUI wd; wp = RenderToSink(wn); wd = RenderToGUI(wn); url = SinkGetInfo(wp, "x-url"); mp = MPCreate(); li = (HTMLInfo)MPCGet(mp, sizeof(struct HTMLInfoP)); li->mp = mp; li->wc = RenderToContext(wn); li->cres = RenderToResources(wn); li->ps = (HTMLState)state; li->url = url; li->burl = url; li->wd = wd; li->wp = wp; li->wn = wn; li->widget = GUIToWidget(li->wd); li->hs = MLInit(HTMLHandler, li); li->lc = lc; li->css = lc->css; li->envstack = GListCreateX(mp); li->selectors = GListCreateX(mp); li->oldselectors = GListCreateX(mp); li->endstack = GListCreateX(mp); li->alist = GListCreateX(mp); li->maps = GListCreateX(mp); li->sinks = GListCreateX(mp); li->loads = GListCreateX(mp); li->framesets = GListCreateX(mp); if (SinkWasReloaded(wp)) li->reload = true; else li->reload = false; ResourceGetInt(li->cres, "html.leftMargin", &(li->lmargin)); if (li->lmargin <= 0) li->lmargin = 20; ResourceGetInt(li->cres, "html.rightMargin", &(li->rmargin)); if (li->rmargin <= 0) li->rmargin = 20; ResourceGetInt(li->cres, "html.bottomMargin", &(li->bmargin)); if (li->bmargin <= 0) li->bmargin = 20; ResourceGetInt(li->cres, "html.topMargin", &(li->tmargin)); if (li->tmargin <= 0) li->tmargin = 20; ResourceGetBool(li->cres, "html.printHTMLErrors", &(li->printHTMLErrors)); li->textLineSpace = -1; ResourceGetInt(li->cres, "html.textLineSpace", &(li->textLineSpace)); if (li->textLineSpace < 0) li->textLineSpace = 3; li->tableCellInfinity = 0; ResourceGetUInt(li->cres, "html.tableCellInfinity", &(li->tableCellInfinity)); ResourceGetUInt(li->cres, "html.inlineTimeOut", &(li->inlineTimeOut)); if (li->inlineTimeOut < 5) li->inlineTimeOut = 5000; ResourceGetUInt(li->cres, "html.selectTimeOut", &(li->selectTimeOut)); if (li->selectTimeOut < 1000) li->selectTimeOut = 1000; ResourceGetBool(li->cres, "html.flowDebug", &(li->flowDebug)); ResourceGetBool(li->cres, "html.constraintDebug", &(li->constraintDebug)); ResourceGetBool(li->cres, "html.printTags", &(li->printTags)); /* * Graphics setup */ li->dpy = GUIToDisplay(li->wd); li->win = GUIToWindow(li->wd); li->gc = DefaultGC(li->dpy, DefaultScreen(li->dpy)); GUIGetNamedColor(wd, "blue", &(li->anchor_color)); GUIGetNamedColor(wd, "red", &(li->anchor_select_color)); GUIGetNamedColor(wd, "black", &(li->fg)); XSetForeground(li->dpy, li->gc, li->fg); HTMLSetupFonts(li); GUISetScrollBar(wd, true); if (GUIGetDimensions(wd, &(li->maxwidth), &(li->maxheight)) == -1) { /* Dimensions of display not set so we'll set them. */ li->maxwidth = 200; li->maxheight = 200; GUISetDimensions(wd, li->maxwidth, li->maxheight); /* Now grab the internal dimensions again */ if (GUIGetDimensions(wd, &(li->maxwidth), &(li->maxheight)) == -1) { return(NULL); } } GListAddHead(lc->contexts, li); HTMLStart(li); return(li); } /* * HTMLClassDestroy */ static void HTMLClassDestroy(closure) void *closure; { HTMLClass lc = (HTMLClass)closure; HTMLFreeFonts(lc); MPDestroy(lc->mp); return; } /* * HTMLGetState */ void * HTMLGetState(closure) void *closure; { HTMLInfo li = (HTMLInfo)closure; HTMLState ps; if ((ps = (HTMLState)GListPop(li->lc->oldstates)) == NULL) { ps = (HTMLState)MPCGet(li->lc->mp, sizeof(struct HTMLStateP)); } GUIGetScrollPosition(li->wd, &(ps->x), &(ps->y)); return(ps); } /* * InitModule_HTML */ int InitModule_HTML(cres) ChimeraResources cres; { ChimeraRenderHooks rh; HTMLClass lc; MemPool mp; FILE *fp; char *cssfile; char *b; struct stat st; size_t rval, blen; mp = MPCreate(); lc = (HTMLClass)MPCGet(mp, sizeof(struct HTMLClassP)); lc->mp = mp; lc->oldstates = GListCreateX(mp); lc->contexts = GListCreateX(mp); /* * Snarf up the default style sheet. */ if ((cssfile = ResourceGetFilename(cres, mp, "html.cssFile")) != NULL) { if (stat(cssfile, &st) == 0 && (fp = fopen(cssfile, "r")) != NULL) { if ((b = (char *)alloc_mem(st.st_size)) == NULL) { while ((rval = fread(b + blen, 1, st.st_size - blen, fp)) > 0 && !feof(fp)) { blen += rval; } fclose(fp); if (blen == st.st_size) { lc->css = CSSParseBuffer(NULL, b, blen, NULL, NULL); } free_mem(b); } } } memset(&rh, 0, sizeof(rh)); rh.class_context = lc; rh.class_destroy = HTMLClassDestroy; rh.content = "text/html"; rh.init = HTMLInit; rh.add = HTMLAdd; rh.end = HTMLEnd; rh.search = HTMLSearch; rh.destroy = HTMLDestroy; rh.getstate = HTMLGetState; rh.query = HTMLQuery; rh.cancel = HTMLCancel; rh.expose = HTMLExpose; rh.select = HTMLMouse; rh.motion = HTMLMotion; RenderAddHooks(cres, &rh); return(0); } /* * HTMLSetFinalPosition */ void HTMLSetFinalPosition(li) HTMLInfo li; { char *cp; if (li->ps != NULL) { GUISetScrollPosition(li->wd, li->ps->x, li->ps->y); GListAddHead(li->lc->oldstates, li->ps); li->ps = NULL; } else { for (cp = li->url; *cp != '\0'; cp++) { if (*cp == '#') { HTMLFindName(li, cp + 1); return; } } } return; } chimera-2.0a19/html/text.c100600 11610 11610 17730 6677561642 13664 0ustar johnjohn/* * text.c * * libhtml - HTML->X renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" #define TAB_EXPANSION 4 typedef struct TextStateP { char *s; size_t len; } TextState; /* * * Private functions * */ static void RenderText _ArgProto((HTMLInfo, HTMLBox, Region)); static char *ExpandTabs _ArgProto((HTMLInfo, char *, size_t, size_t)); static void LineMode _ArgProto((HTMLInfo, HTMLEnv, MLElement)); static void HTMLPreformatted _ArgProto((HTMLInfo, HTMLEnv, char *, size_t)); /* * RenderText */ static void RenderText(li, box, r) HTMLInfo li; HTMLBox box; Region r; { TextState *ts = (TextState *)box->closure; int x, y; XFontStruct *font = HTMLGetFont(li, box->env); XSetFont(li->dpy, li->gc, font->fid); /* y position + ascent to line up correctly + descent for line spacing */ y = box->y + font->ascent; x = box->x; if (box->env->anchor != NULL) { if (HTMLTestB(box, BOX_SELECT)) { XSetForeground(li->dpy, li->gc, li->anchor_select_color); } else XSetForeground(li->dpy, li->gc, li->anchor_color); XDrawString(li->dpy, li->win, li->gc, x, y, ts->s, (int)ts->len); XDrawLine(li->dpy, li->win, li->gc, x, y + font->descent - 1, x + box->width, y + font->descent - 1); XSetForeground(li->dpy, li->gc, li->fg); } else { XDrawString(li->dpy, li->win, li->gc, x, y, ts->s, (int)ts->len); } return; } /* * HTMLCreateTextBox */ HTMLBox HTMLCreateTextBox(li, env, s, slen) HTMLInfo li; HTMLEnv env; char *s; size_t slen; { HTMLBox box; TextState *ts; HTMLBoxFlags bflags; XFontStruct *font = HTMLGetFont(li, env); if (s == NULL) { s = " "; slen = 1; bflags = BOX_SPACE; } else { bflags = BOX_NONE; } ts = (TextState *)MPCGet(li->mp, sizeof(TextState)); ts->s = s; ts->len = slen; box = HTMLCreateBox(li, env); HTMLSetB(box, bflags); box->closure = ts; box->render = RenderText; box->width = XTextWidth(font, s, slen); box->height = font->ascent + font->descent + li->textLineSpace; box->baseline = font->ascent + li->textLineSpace; return(box); } /* * HTMLPreformatted - basically, the guts of LineMode() */ static void HTMLPreformatted(li, env, text, len) HTMLInfo li; HTMLEnv env; char *text; size_t len; { char *cp, *lastcp, *start; size_t ptlen; char *s; bool tabbed; lastcp = text + len; tabbed = false; for (ptlen = 0, start = cp = text; cp < lastcp; cp++) { if (*cp == '\r') continue; else if (*cp == '\n') { if (tabbed) { s = ExpandTabs(li, start, cp - start, ptlen); HTMLEnvAddBox(li, env, HTMLCreateTextBox(li, env, s, ptlen)); } else { HTMLEnvAddBox(li, env, HTMLCreateTextBox(li, env, start, ptlen)); } HTMLAddLineBreak(li, env); ptlen = 0; start = cp + 1; tabbed = false; } else if (*cp == '\t') { ptlen += TAB_EXPANSION; tabbed = true; } else ptlen++; } if (tabbed) { s = ExpandTabs(li, start, cp - start, ptlen); HTMLEnvAddBox(li, env, HTMLCreateTextBox(li, env, s, ptlen)); } else { HTMLEnvAddBox(li, env, HTMLCreateTextBox(li, env, start, ptlen)); } return; } /* * * Public functions * */ /* * ExpandTabs */ static char * ExpandTabs(li, t, len, tlen) HTMLInfo li; char *t; size_t len; size_t tlen; { char *s, *cp, *lastcp, *xs; lastcp = t + len; s = (char *)MPGet(li->mp, tlen); for (cp = t, xs = s; cp < lastcp; cp++) { if (*cp == '\t') { memset(xs, ' ', TAB_EXPANSION); xs += TAB_EXPANSION; } else if (*cp != '\r') { *xs = *cp; xs++; } } return(s); } /* * LineMode */ static void LineMode(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { char *text; size_t len; MLGetText(p, &text, &len); if (text == NULL) return; HTMLPreformatted(li, env, text, len); return; } /* * HTMLPlainData */ void HTMLPlainData(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { LineMode(li, env, p); return; } /* * HTMLPreData */ void HTMLPreData(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { LineMode(li, env, p); return; } /* * HTMLFillData */ void HTMLFillData(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { char *s, *cp, *lastcp; bool found_space; char *text; size_t len; MLGetText(p, &text, &len); if (text == NULL) return; if (li->formatted) HTMLPreformatted(li, env, text, len); else { for (lastcp = text + len, cp = text; cp < lastcp; ) { for (found_space = false; cp < lastcp && isspace8(*cp); cp++) { found_space = true; } if (found_space) { HTMLEnvAddBox(li, env, HTMLCreateTextBox(li, env, NULL, 0)); } if (cp == lastcp) break; for (s = cp; cp < lastcp && !isspace8(*cp); cp++) ; HTMLEnvAddBox(li, env, HTMLCreateTextBox(li, env, s, cp - s)); } } return; } void HTMLPreBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLSetFontFixed(env->fi); li->formatted = true; /* would anyone actually nest PREs? - djhjr */ return; } void HTMLPreEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { li->formatted = false; /* nah... - djhjr */ return; } void HTMLPlainEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { return; } void HTMLPlainBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLSetFontFixed(env->fi); return; } void HTMLNoFrameBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { return; } /* * HTMLNoFrameEnd */ void HTMLNoFrameEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { return; } /* * HTMLGetText */ char * HTMLGetEnvText(mp, env) MemPool mp; HTMLEnv env; { HTMLObject c, b, e; char *text, *str; size_t tlen = 0; size_t len; GList list = env->slist; if (GListEmpty(list)) return(NULL); e = (HTMLObject)GListGetTail(list); for (b = c = (HTMLObject)GListGetHead(list); c != NULL; c = (HTMLObject)GListGetNext(list)) { if (c != b && c != e) { if (c->type != HTML_ENV) { MLGetText(c->o.p, &str, &len); tlen += len; } } } text = MPGet(mp, tlen + 1); tlen = 0; for (c = (HTMLObject)GListGetHead(list); c != NULL; c = (HTMLObject)GListGetNext(list)) { if (c != b && c != e) { if (c->type != HTML_ENV) { MLGetText(c->o.p, &str, &len); strncpy(text + tlen, str, len); tlen += len; } } } text[tlen] = '\0'; return(text); } /* * HTMLAddLineBreak */ void HTMLAddLineBreak(li, env) HTMLInfo li; HTMLEnv env; { HTMLBox box; box = HTMLCreateBox(li, env); HTMLSetB(box, BOX_LINEBREAK); HTMLEnvAddBox(li, env, box); return; } /* * HTMLAddBlankLine */ void HTMLAddBlankLine(li, env) HTMLInfo li; HTMLEnv env; { HTMLBox box; HTMLAddLineBreak(li, env); box = HTMLCreateBox(li, env); box->height = 6; box->width = 0; /* really really want this to be zero */ HTMLEnvAddBox(li, env, box); HTMLAddLineBreak(li, env); return; } /* * HTMLStringSpacify * * Turns all whitespace to spaces */ void HTMLStringSpacify(s, len) char *s; size_t len; { char *cp, *lastcp = s + len; for (cp = s; cp < lastcp; cp++) { if (isspace8(*cp)) *cp = ' '; } return; } chimera-2.0a19/html/htmltags.h100600 11610 11610 20067 6677561645 14530 0ustar johnjohn/* * htmltags.h * * libhtml - HTML->X renderer * Copyright (c) 1994-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ typedef enum { MARKUP_NONE = 0x00000000, MARKUP_EMPTY = 0x00000001, MARKUP_CLAMP = 0x00000002, MARKUP_FAKE = 0x00000004, MARKUP_SPACER = 0x00000008, MARKUP_TWOPASS = 0x00000010 } HTMLMarkupFlags; struct HTMLTagP { char *name; HTMLTagID id; /* rendering functions */ HTMLTagRenderProc b, e; HTMLTagDataProc d; HTMLTagAddBoxProc a; HTMLTagWidthProc w; /* flags for whatever seems convienent to make a flag */ HTMLMarkupFlags mflags; /* markup handling functions */ HTMLTagAcceptProc m; HTMLTagInsertProc p; HTMLTagClampProc c; }; #define HTMLTestM(a, b) (((a)->mflags & (b)) != 0) #define HTMLClearM(a, b) ((a)->mflags &= ~(b)) #define HTMLSetM(a, b) ((a)->mflags |= (b)) static struct HTMLTagP tlist[] = { /* misc.c */ { "h1", TAG_H1, HTMLHxBegin, HTMLHxEnd, HTMLFillData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "h2", TAG_H2, HTMLHxBegin, HTMLHxEnd, HTMLFillData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "h3", TAG_H3, HTMLHxBegin, HTMLHxEnd, HTMLFillData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "h4", TAG_H4, HTMLHxBegin, HTMLHxEnd, HTMLFillData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "h5", TAG_H5, HTMLHxBegin, HTMLHxEnd, HTMLFillData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "h6", TAG_H6, HTMLHxBegin, HTMLHxEnd, HTMLFillData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "plaintext", TAG_PLAINTEXT, HTMLPlainBegin, HTMLPlainEnd, HTMLPlainData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "listing", TAG_LISTING, HTMLPlainBegin, HTMLPlainEnd, HTMLPlainData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "pre", TAG_PRE, HTMLPreBegin, HTMLPreEnd, HTMLPreData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "xmp", TAG_XMP, HTMLPlainBegin, HTMLPlainEnd, HTMLPlainData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, NULL, NULL }, { "center", TAG_CENTER, HTMLCenterBegin, HTMLCenterEnd, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "div", TAG_DIV, HTMLDivBegin, HTMLDivEnd, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "blockquote", TAG_BLOCKQUOTE, HTMLBQBegin, HTMLBQEnd, HTMLFillData, NULL, NULL, MARKUP_CLAMP, NULL, NULL, NULL }, { "p", TAG_P, HTMLParaBegin, HTMLParaEnd, HTMLFillData, NULL, NULL, MARKUP_CLAMP | MARKUP_SPACER, NULL, HTMLParaInsert, NULL }, { "address", TAG_ADDRESS, HTMLAddressBegin, HTMLAddressEnd, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "hr", TAG_HR, HTMLHorizontalRule, NULL, NULL, NULL, NULL, MARKUP_EMPTY, NULL, NULL, NULL }, { "b", TAG_B, HTMLFontBegin, NULL, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "em", TAG_EM, HTMLFontBegin, NULL, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "strong", TAG_STRONG, HTMLFontBegin, NULL, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "tt", TAG_TT, HTMLFontBegin, NULL, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "cite", TAG_CITE, HTMLFontBegin, NULL, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "i", TAG_I, HTMLFontBegin, NULL, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "kbd", TAG_KBD, HTMLFontBegin, NULL, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "a", TAG_A, HTMLAnchorBegin, NULL, HTMLFillData, NULL, NULL, MARKUP_NONE, NULL, HTMLAnchorInsert, NULL }, { "br", TAG_BR, HTMLBreak, NULL, NULL, NULL, NULL, MARKUP_EMPTY, NULL, NULL, NULL }, /* inline.c */ { "img", TAG_IMG, HTMLImg, NULL, NULL, NULL, NULL, MARKUP_EMPTY, NULL, HTMLImgInsert, NULL }, /* list.c */ { "ul", TAG_UL, HTMLULBegin, HTMLListEnd, NULL, HTMLListAddBox, NULL, MARKUP_CLAMP | MARKUP_SPACER, HTMLListAccept, NULL, NULL }, { "dir", TAG_UL, HTMLULBegin, HTMLListEnd, NULL, HTMLListAddBox, NULL, MARKUP_CLAMP | MARKUP_SPACER, HTMLListAccept, NULL, NULL }, { "menu", TAG_UL, HTMLULBegin, HTMLListEnd, NULL, HTMLListAddBox, NULL, MARKUP_CLAMP | MARKUP_SPACER, HTMLListAccept, NULL, NULL }, { "ol", TAG_OL, HTMLOLBegin, HTMLListEnd, NULL, HTMLListAddBox, NULL, MARKUP_CLAMP | MARKUP_SPACER, HTMLListAccept, NULL, NULL }, { "dl", TAG_DL, HTMLDLBegin, HTMLListEnd, NULL, HTMLListAddBox, NULL, MARKUP_CLAMP | MARKUP_SPACER, HTMLDLAccept, NULL, NULL }, { "li", TAG_LI, HTMLLIBegin, HTMLItemEnd, HTMLFillData, HTMLItemAddBox, HTMLItemWidth, MARKUP_CLAMP, NULL, HTMLLIInsert, NULL }, { "dt", TAG_DT, HTMLDTBegin, HTMLItemEnd, HTMLFillData, HTMLItemAddBox, HTMLItemWidth, MARKUP_CLAMP, NULL, HTMLDTInsert, NULL }, { "dd", TAG_DD, HTMLDDBegin, HTMLItemEnd, HTMLFillData, HTMLItemAddBox, HTMLItemWidth, MARKUP_CLAMP, NULL, HTMLDDInsert, NULL }, /* head.c */ { "title", TAG_TITLE, NULL, HTMLTitleEnd, NULL, NULL, NULL, MARKUP_CLAMP, NULL, NULL, NULL }, { "style", TAG_STYLE, NULL, NULL, NULL, NULL, NULL, MARKUP_CLAMP, NULL, NULL, NULL }, { "script", TAG_SCRIPT, NULL, NULL, NULL, NULL, NULL, MARKUP_CLAMP, NULL, NULL, NULL }, { "base", TAG_BASE, HTMLBase, NULL, NULL, NULL, NULL, MARKUP_EMPTY, NULL, NULL, NULL }, { "meta", TAG_META, HTMLMeta, NULL, NULL, NULL, NULL, MARKUP_EMPTY, NULL, NULL, NULL }, /* form.c */ { "input", TAG_INPUT, HTMLInput, NULL, NULL, NULL, NULL, MARKUP_EMPTY, NULL, NULL, NULL }, { "select", TAG_SELECT, HTMLSelectBegin, HTMLSelectEnd, NULL, NULL, NULL, MARKUP_CLAMP, NULL, NULL, NULL }, { "option", TAG_OPTION, NULL, HTMLOptionEnd, NULL, NULL, NULL, MARKUP_NONE, NULL, NULL, NULL }, { "textarea", TAG_TEXTAREA, NULL, HTMLTextareaEnd, NULL, NULL, NULL, MARKUP_CLAMP, NULL, NULL, NULL }, { "form", TAG_FORM, HTMLFormBegin, HTMLFormEnd, HTMLFillData, NULL, NULL, MARKUP_CLAMP, NULL, NULL, NULL }, /* table.c */ { "table", TAG_TABLE, HTMLTableBegin, HTMLTableEnd, NULL, HTMLTableAddBox, NULL, MARKUP_CLAMP | MARKUP_SPACER | MARKUP_TWOPASS, HTMLTableAccept, NULL, NULL }, { "tr", TAG_TR, HTMLTRBegin, HTMLTREnd, NULL, NULL, NULL, MARKUP_CLAMP, HTMLTRAccept, HTMLTRInsert, HTMLTRClamp }, { "th", TAG_TH, HTMLTDBegin, HTMLTDEnd, HTMLFillData, HTMLTDAddBox, HTMLTDWidth, MARKUP_CLAMP, NULL, HTMLTDInsert, HTMLTDClamp }, { "td", TAG_TD, HTMLTDBegin, HTMLTDEnd, HTMLFillData, HTMLTDAddBox, HTMLTDWidth, MARKUP_CLAMP, NULL, HTMLTDInsert, HTMLTDClamp }, /* map.c */ { "map", TAG_MAP, HTMLMapBegin, HTMLMapEnd, NULL, NULL, NULL, MARKUP_CLAMP, HTMLMapAccept, NULL, NULL }, { "area", TAG_AREA, HTMLAreaBegin, NULL, NULL, NULL, NULL, MARKUP_EMPTY, NULL, HTMLAreaInsert, NULL }, /* frame.c */ { "iframe", TAG_IFRAME, HTMLIFrame, NULL, NULL, NULL, NULL, MARKUP_CLAMP, NULL, NULL, NULL }, { "frame", TAG_FRAME, HTMLFrame, NULL, NULL, NULL, NULL, MARKUP_EMPTY, NULL, HTMLFrameInsert, NULL }, { "frameset", TAG_FRAMESET, HTMLFrameSetBegin, HTMLFrameSetEnd, NULL, NULL, NULL, MARKUP_CLAMP, HTMLFrameSetAccept, HTMLFrameSetInsert, NULL }, { "noframes", TAG_NOFRAMES, HTMLNoFramesBegin, HTMLNoFramesEnd, NULL, NULL, NULL, MARKUP_CLAMP, NULL, NULL, NULL }, /* Internal tags */ { "xxx-document", TAG_DOCUMENT, HTMLDocumentBegin, HTMLDocumentEnd, HTMLFillData, HTMLDocumentAddBox, HTMLDocumentWidth, MARKUP_FAKE, NULL, NULL, NULL } }; static int tlist_len = sizeof(tlist) / sizeof(tlist[0]); chimera-2.0a19/html/inline.c100600 11610 11610 24622 6724366204 14142 0ustar johnjohn/* * inline.c * * libhtml - HTML->X renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" struct HTMLInlineP { HTMLInfo li; ChimeraGUI wd; ChimeraSink wp; ChimeraRender wn; HTMLInlineInfo ii; bool setupcalled; HTMLBox box; unsigned int width, height, border; unsigned int vspace, hspace; char *mapurl; bool ismap; HTMLEnv env; bool delayed; ChimeraRenderHooks orh; void *rc; }; static int ImgInit _ArgProto((ChimeraSink, void *)); static void ImgAdd _ArgProto((void *)); static void ImgEnd _ArgProto((void *)); static void ImgMessage _ArgProto((void *, char *)); static void DestroyInline _ArgProto((HTMLInfo, HTMLBox)); static bool InlineSelectCallback _ArgProto((void *, int, int, char *)); static bool InlineMotionCallback _ArgProto((void *, int, int)); void InlineResizeCallback _ArgProto((ChimeraGUI, void *, unsigned int, unsigned int)); static void InlineContinue _ArgProto((HTMLInline)); static void SetupInline _ArgProto((HTMLInfo, HTMLBox)); static void AddInline _ArgProto((HTMLInline)); static void HandleInlineReload _ArgProto((HTMLInfo, ChimeraRequest *)); /* * InlineContinue */ static void InlineContinue(isp) HTMLInline isp; { if (isp->delayed) { isp->delayed = false; HTMLContinueLayout(isp->li); } return; } /* * SetupInline */ static void SetupInline(li, box) HTMLInfo li; HTMLBox box; { HTMLInline isp = (HTMLInline)box->closure; isp->setupcalled = true; if (isp->wd != NULL) { GUIMap(isp->wd, box->x + isp->hspace, box->y + isp->vspace); } return; } /* * DestroyInline */ static void DestroyInline(li, box) HTMLInfo li; HTMLBox box; { HTMLInline isp = (HTMLInline)box->closure; if (isp->wn != NULL) { RenderDestroy(isp->wn); isp->wn = NULL; } if (isp->wp != NULL) { SinkSetHooks(isp->wp, NULL, NULL); isp->wp = NULL; } if (isp->wd != NULL) { GUIDestroy(isp->wd); isp->wd = NULL; } return; } /* * AddInline */ static void AddInline(isp) HTMLInline isp; { HTMLBox box; HTMLAttribID aid; int border; isp->box = box = HTMLCreateBox(isp->li, isp->env); if ((border = MLAttributeToInt(isp->ii.p, "border")) < 0) isp->border = 0; else isp->border = border; aid = HTMLAttributeToID(isp->ii.p, "align"); if (aid == ATTRIB_MIDDLE) box->baseline = isp->height / 2; else if (aid == ATTRIB_TOP) box->baseline = 0; else if (aid == ATTRIB_LEFT) HTMLSetB(box, BOX_FLOAT_LEFT); else if (aid == ATTRIB_RIGHT) HTMLSetB(box, BOX_FLOAT_RIGHT); else box->baseline = isp->height; box->setup = SetupInline; box->destroy = DestroyInline; box->width = isp->width + isp->hspace * 2; box->height = isp->height + isp->vspace * 2; box->closure = isp; HTMLEnvAddBox(isp->li, isp->env, box); return; } /* * InlineResizeCallback */ void InlineResizeCallback(wd, closure, width, height) ChimeraGUI wd; void *closure; unsigned int width, height; { HTMLInline isp = (HTMLInline)closure; if (isp->box == NULL) { isp->width = width; isp->height = height; AddInline(isp); InlineContinue(isp); } return; } /* * InlineSelectCallback */ static bool InlineSelectCallback(closure, x, y, action) void *closure; int x, y; char *action; { HTMLInline isp = (HTMLInline)closure; HTMLAnchor a; GList list; char *url; myassert(isp->box != NULL, "MouseCallback: box == NULL"); if (isp->mapurl != NULL) { if ((url = HTMLFindMapURL(isp->li, isp->mapurl, x, y)) != NULL) { HTMLLoadURL(isp->li, NULL, url, action); return(true); } } list = isp->li->alist; for (a = (HTMLAnchor)GListGetHead(list); a != NULL; a = (HTMLAnchor)GListGetNext(list)) { if (a->box == isp->box) { HTMLLoadAnchor(isp->li, a, x, y, action, isp->ismap); return(true); } } return(true); } static bool InlineMotionCallback(closure, x, y) void *closure; int x, y; { HTMLInline isp = (HTMLInline)closure; HTMLAnchor a; GList list; char *url; myassert(isp->box != NULL, "MotionCallback: box == NULL"); if (isp->mapurl != NULL) { if ((url = HTMLFindMapURL(isp->li, isp->mapurl, x, y)) != NULL) { HTMLPrintURL(isp->li, url); return(true); } } isp->li->over = NULL; list = isp->li->alist; for (a = (HTMLAnchor)GListGetHead(list); a != NULL; a = (HTMLAnchor)GListGetNext(list)) { if (a->box == isp->box) { HTMLPrintAnchor(isp->li, a, x, y, isp->ismap); isp->li->over = a; return(true); } } return(true); } /* * ImgMessage */ static void ImgMessage(closure, message) void *closure; char *message; { HTMLInline isp = (HTMLInline)closure; if (isp->li->wn != NULL) RenderSendMessage(isp->li->wn, message); return; } /* * ImgEnd */ static void ImgEnd(closure) void *closure; { HTMLInline isp = (HTMLInline)closure; RenderEnd(isp->wn); return; } /* * ImgAdd */ static void ImgAdd(closure) void *closure; { HTMLInline isp = (HTMLInline)closure; RenderAdd(isp->wn); return; } /* * ImgInit */ static int ImgInit(wp, closure) ChimeraSink wp; void *closure; { HTMLInline isp = (HTMLInline)closure; ChimeraRenderHooks *rh; char *ctype; ctype = SinkGetInfo(wp, "content-type"); if ((rh = RenderGetHooks(SinkToResources(wp), ctype)) == NULL) { SinkCancel(wp); InlineContinue(isp); return(-1); } isp->wd = GUICreate(isp->li->wc, isp->li->wd, InlineResizeCallback, isp); if (isp->width > 0 && isp->height > 0) { GUISetInitialDimensions(isp->wd, isp->width, isp->height); } if (isp->setupcalled) { GUIMap(isp->wd, isp->box->x + isp->hspace, isp->box->y + isp->vspace); } isp->wn = RenderCreate(isp->li->wc, isp->wd, isp->wp, rh, &(isp->orh), isp->rc, NULL, NULL, NULL); if (isp->wn == NULL) { SinkCancel(wp); return(-1); } return(0); } /* * * Public functions * */ HTMLInline HTMLCreateInline(li, env, url, ii, orh, rc) HTMLInfo li; HTMLEnv env; char *url; HTMLInlineInfo *ii; ChimeraRenderHooks *orh; void *rc; { ChimeraSinkHooks hooks; HTMLInline isp; ChimeraRequest *wr; int width, height, vspace, hspace; if ((wr = RequestCreate(li->cres, url, li->burl)) == NULL) { return(NULL); } if (li->reload) HandleInlineReload(li, wr); /* Select only image content that we can deal with directly */ if (RequestAddRegexContent(li->cres, wr, "image/*") <= 0) { RequestDestroy(wr); return(NULL); } isp = (HTMLInline)MPCGet(li->mp, sizeof(struct HTMLInlineP)); memcpy(&(isp->ii), ii, sizeof(HTMLInlineInfo)); isp->li = li; isp->env = env; if (orh == NULL) { memset(&(isp->orh), 0, sizeof(isp->orh)); isp->orh.select = InlineSelectCallback; isp->orh.motion = InlineMotionCallback; isp->rc = isp; } else { memcpy(&(isp->orh), orh, sizeof(ChimeraRenderHooks)); isp->rc = rc; } if ((width = MLAttributeToInt(ii->p, "width")) < 0) isp->width = 0; else isp->width = width; if ((height = MLAttributeToInt(ii->p, "height")) < 0) isp->height = 0; else isp->height = height; if ((vspace = MLAttributeToInt(ii->p, "vspace")) < 0) isp->vspace = 0; else isp->vspace = vspace; if ((hspace = MLAttributeToInt(ii->p, "hspace")) < 0) isp->hspace = 0; else isp->hspace = hspace; isp->ismap = MLFindAttribute(ii->p, "ismap") != NULL ? true:false; isp->mapurl = MLFindAttribute(ii->p, "usemap"); if (isp->width == 0 || isp->height == 0) { isp->delayed = true; HTMLDelayLayout(li); } else AddInline(isp); memset(&hooks, 0, sizeof(hooks)); hooks.init = ImgInit; hooks.add = ImgAdd; hooks.end = ImgEnd; hooks.message = ImgMessage; if ((isp->wp = SinkCreate(li->cres, wr)) == NULL) { InlineContinue(isp); } else { SinkSetHooks(isp->wp, &hooks, isp); GListAddHead(li->sinks, isp->wp); } return(isp); } /* * HTMLInlineToBox */ HTMLBox HTMLInlineToBox(is) HTMLInline is; { return(is->box); } /* * HTMLInlineToInfo */ HTMLInfo HTMLInlineToInfo(is) HTMLInline is; { return(is->li); } /* * HTMLInlineDestroy */ void HTMLInlineDestroy(is) HTMLInline is; { return; } /* * HTMLImg */ void HTMLImg(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { char *url; HTMLInlineInfo ii; if ((url = MLFindAttribute(p, "src")) == NULL) return; memset(&ii, 0, sizeof(HTMLInlineInfo)); ii.p = p; HTMLCreateInline(li, env, url, &ii, NULL, NULL); return; } /* * HTMLImgInsert * * Always OK image insertion for now. I suppose this is where one * could check for conditional image loading. The idea here is to * start the download as soon as possible. */ HTMLInsertStatus HTMLImgInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { char *url; ChimeraRequest *wr; ChimeraSink wp; if ((url = MLFindAttribute(p, "src")) == NULL) return(HTMLInsertOK); if ((wr = RequestCreate(li->cres, url, li->burl)) == NULL) { return(HTMLInsertOK); } if (li->reload) HandleInlineReload(li, wr); /* Select only image content that we can deal with directly */ if (RequestAddRegexContent(li->cres, wr, "image/*") <= 0) { RequestDestroy(wr); return(HTMLInsertOK); } if ((wp = SinkCreate(li->cres, wr)) != NULL) { SinkSetHooks(wp, NULL, NULL); GListAddHead(li->sinks, wp); } return(HTMLInsertOK); } /* * HandleInlineReload */ static void HandleInlineReload(li, wr) HTMLInfo li; ChimeraRequest *wr; { char *xurl; for (xurl = (char *)GListGetHead(li->loads); xurl != NULL; xurl = (char *)GListGetNext(li->loads)) { if (strlen(wr->url) == strlen(xurl) && strcmp(wr->url, xurl) == 0) { break; } } if (xurl == NULL) { RequestReload(wr, true); GListAddHead(li->loads, MPStrDup(li->mp, wr->url)); } return; } chimera-2.0a19/html/misc.c100600 11610 11610 12441 6677561653 13627 0ustar johnjohn/* * misc.c * * libhtml - HTML->X renderer * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" static void RenderAnchor _ArgProto((HTMLInfo, HTMLBox, Region)); /* * RenderAnchor */ static void RenderAnchor(li, box, r) HTMLInfo li; HTMLBox box; Region r; { return; } void HTMLAnchorBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { char *value; HTMLBox box; if ((value = MLFindAttribute(p, "name")) != NULL) { box = HTMLCreateBox(li, env); box->width = 2; box->height = 2; box->render = RenderAnchor; HTMLEnvAddBox(li, env, box); HTMLAddAnchor(li, box, value, NULL); } if (MLFindAttribute(p, "href") != NULL) env->anchor = p; return; } HTMLInsertStatus HTMLAnchorInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { if (MLFindAttribute(p, "href") == NULL) { if (MLFindAttribute(p, "name") != NULL) return(HTMLInsertEmpty); else return(HTMLInsertReject); } return(HTMLInsertOK); } void HTMLHxBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAttribID aid; HTMLTagID tagid; tagid = HTMLTagToID(env->tag); if (tagid == TAG_H1) HTMLSetFontScale(env->fi, 5); else if (tagid == TAG_H2) HTMLSetFontScale(env->fi, 4); else if (tagid == TAG_H3) HTMLSetFontScale(env->fi, 3); else if (tagid == TAG_H4) HTMLSetFontScale(env->fi, 2); else if (tagid == TAG_H5) HTMLSetFontScale(env->fi, 1); else if (tagid == TAG_H6) HTMLSetFontScale(env->fi, 0); aid = HTMLAttributeToID(p, "align"); if (aid == ATTRIB_CENTER || aid == ATTRIB_RIGHT) { if (aid == ATTRIB_CENTER) env->ff = FLOW_CENTER_JUSTIFY; else if (aid == ATTRIB_RIGHT) env->ff = FLOW_RIGHT_JUSTIFY; } return; } void HTMLHxEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { return; } void HTMLFontBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLTagID tagid = HTMLTagToID(env->tag); if (tagid == TAG_EM || tagid == TAG_CITE || tagid == TAG_I) { HTMLAddFontSlant(env->fi); } else if (tagid == TAG_B || tagid == TAG_STRONG) { HTMLAddFontWeight(env->fi); } else if (tagid == TAG_TT) HTMLSetFontFixed(env->fi); return; } void HTMLParaBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAttribID aid; aid = HTMLAttributeToID(p, "align"); if (aid == ATTRIB_CENTER || aid == ATTRIB_RIGHT) { if (aid == ATTRIB_CENTER) env->ff = FLOW_CENTER_JUSTIFY; else if (aid == ATTRIB_RIGHT) env->ff = FLOW_RIGHT_JUSTIFY; } return; } void HTMLParaEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { return; } HTMLInsertStatus HTMLParaInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { /* * If the current environment is

then terminate the environment * before starting the new one. */ if (HTMLTagToID(env->tag) == TAG_P) HTMLEndEnv(li, TAG_P); return(HTMLInsertOK); } /* * HTMLBreak */ void HTMLBreak(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAttribID aid; HTMLBox box; box = HTMLCreateBox(li, env); aid = HTMLAttributeToID(p, "clear"); if (aid == ATTRIB_LEFT) HTMLSetB(box, BOX_CLEAR_LEFT); else if (aid == ATTRIB_RIGHT) HTMLSetB(box, BOX_CLEAR_RIGHT); else if (aid == ATTRIB_ALL) HTMLSetB(box, BOX_CLEAR_RIGHT | BOX_CLEAR_LEFT); else HTMLSetB(box, BOX_LINEBREAK); HTMLEnvAddBox(li, env, box); return; } void HTMLAddressBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAddFontSlant(env->fi); HTMLAddBlankLine(li, env); return; } void HTMLAddressEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAddBlankLine(li, env); return; } void HTMLBQBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAddLineBreak(li, env); return; } void HTMLBQEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAddLineBreak(li, env); return; } void HTMLCenterBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { env->ff = FLOW_CENTER_JUSTIFY; HTMLAddLineBreak(li, env); return; } void HTMLCenterEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAddLineBreak(li, env); return; } void HTMLDivBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAttribID aid; aid = HTMLAttributeToID(p, "align"); if (aid == ATTRIB_CENTER) env->ff = FLOW_CENTER_JUSTIFY; else if (aid == ATTRIB_LEFT) env->ff = FLOW_LEFT_JUSTIFY; else if (aid == ATTRIB_RIGHT) env->ff = FLOW_RIGHT_JUSTIFY; HTMLAddLineBreak(li, env); return; } void HTMLDivEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAddLineBreak(li, env); return; } chimera-2.0a19/html/list.c100600 11610 11610 26371 6677561657 13662 0ustar johnjohn/* * list.c * * libhtml - HTML->X renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" /* * Numeric label stuff for

    supplied by * Jake Kesinger */ typedef enum { OL_NUMERIC, OL_ALPHA_CAP, OL_ALPHA_MINISCULE, OL_ROMAN_CAP, OL_ROMAN_MINISCULE } OListType; typedef struct { OListType type; /* type for ol list */ int count; /* count for ol list */ int bullet_diam; /* cached bullet size */ GList klist; /* list of item boxes */ HTMLBox lbox; /* list box */ HTMLBox ibox; /* item box */ HTMLBox tbox; /* text box inside item (dd, li) */ } HList; /* * * Private functions * */ static void RenderLI _ArgProto((HTMLInfo, HTMLBox, Region)); static void SetupList _ArgProto((HTMLInfo, HTMLBox)); static void RenderList _ArgProto((HTMLInfo, HTMLBox, Region)); static void DestroyList _ArgProto((HTMLInfo, HTMLBox)); static HList *CreateList _ArgProto((HTMLInfo, HTMLEnv)); static void OLNext _ArgProto((char *, size_t, int, OListType)); /* * SetupList */ static void SetupList(li, box) HTMLInfo li; HTMLBox box; { HList *hl = (HList *)box->closure; HTMLBox c; int ty = box->y; for (c = (HTMLBox)GListGetHead(hl->klist); c != NULL; c = (HTMLBox)GListGetNext(hl->klist)) { c->x = box->x; c->y = ty; HTMLSetupBox(li, c); ty += c->height; } return; } /* * RenderList */ static void RenderList(li, box, r) HTMLInfo li; HTMLBox box; Region r; { HList *hl = (HList *)box->closure; HTMLBox c; for (c = (HTMLBox)GListGetHead(hl->klist); c != NULL; c = (HTMLBox)GListGetNext(hl->klist)) { HTMLRenderBox(li, r, c); } return; } static void DestroyList(li, box) HTMLInfo li; HTMLBox box; { HList *ls = (HList *)box->closure; HTMLBox c; for (c = (HTMLBox)GListGetHead(ls->klist); c != NULL; c = (HTMLBox)GListGetNext(ls->klist)) { HTMLDestroyBox(li, c); } return; } /* * RenderLI */ static void RenderLI(li, box, r) HTMLInfo li; HTMLBox box; Region r; { unsigned int half = box->width / 2; XFillArc(li->dpy, li->win, li->gc, box->x + half, box->y + half, half, half, 0, 360 * 64); return; } /* * CreateList */ static HList * CreateList(li, env) HTMLInfo li; HTMLEnv env; { HList *ls; ls = (HList *)MPCGet(li->mp, sizeof(HList)); ls->lbox = HTMLCreateBox(li, env); ls->lbox->setup = SetupList; ls->lbox->render = RenderList; ls->lbox->destroy = DestroyList; ls->lbox->closure = ls; ls->klist = GListCreateX(li->mp); return(ls); } /* * * Public functions * */ void HTMLULBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HList *ls; XFontStruct *font; font = HTMLGetFont(li, env); ls = CreateList(li, env); ls->bullet_diam = font->ascent; env->closure = ls; env->ff = FLOW_LEFT_JUSTIFY; return; } void HTMLListEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HList *ls = (HList *)env->closure; HTMLEnvAddBox(li, env->penv, ls->lbox); return; } void HTMLOLBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HList *ls; char *startstr; char *variantstr; ls = CreateList(li, env); env->closure = ls; env->ff = FLOW_LEFT_JUSTIFY; /* * If the
      specifies a START or SEQNUM attribute, handle that, * otherwise the default is 1 */ if((startstr = MLFindAttribute(p, "start"))!= NULL) { ls->count = atoi(startstr); } else if((startstr = MLFindAttribute(p, "seqnum"))!= NULL) { ls->count = atoi(startstr); } else { ls->count = 1; } /* * Now see if said
        has a TYPE attribute. * Types are: * 1 ==> std numbering * aA ==>[aA]lphabetic * iI ==> [rR]oman */ if ((variantstr = MLFindAttribute(p, "type")) != NULL) { if (variantstr[0] == 'a') ls->type = OL_ALPHA_MINISCULE; else if (variantstr[0] == 'A') ls->type = OL_ALPHA_CAP; else if (variantstr[0] == 'i') ls->type = OL_ROMAN_MINISCULE; else if (variantstr[0] == 'I') ls->type = OL_ROMAN_CAP; else ls->type = OL_NUMERIC; } else { ls->type = OL_NUMERIC; } return; } void HTMLLIBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLBox box; HList *ls; char buffer[BUFSIZ]; ls = (HList *)env->penv->closure; ls->ibox = HTMLCreateFlowBox(li, env, HTMLGetMaxWidth(li, env->penv)); GListAddTail(ls->klist, ls->ibox); env->closure = ls; if (HTMLTagToID(env->penv->tag) == TAG_OL) { OLNext(buffer, sizeof(buffer), ls->count++, ls->type); box = HTMLCreateTextBox(li, env, MPStrDup(li->mp, buffer), strlen(buffer)); } else { box = HTMLCreateBox(li, env); box->width = ls->bullet_diam; box->height = ls->bullet_diam; box->render = RenderLI; } HTMLSetB(box, BOX_FLOAT_LEFT); HTMLLayoutBox(li, ls->ibox, box); ls->tbox = HTMLCreateFlowBox(li, env, HTMLGetMaxWidth(li, env->penv) - box->width); return; } void HTMLItemEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HList *ls = (HList *)env->closure; if (ls->tbox != NULL) { HTMLFinishFlowBox(li, ls->tbox); HTMLLayoutBox(li, ls->ibox, ls->tbox); } HTMLFinishFlowBox(li, ls->ibox); HTMLEnvAddBox(li, env->penv, ls->ibox); return; } void HTMLDDBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HList *ls; HTMLBox indent; ls = (HList *)env->penv->closure; ls->ibox = HTMLCreateFlowBox(li, env, HTMLGetMaxWidth(li, env->penv)); GListAddTail(ls->klist, ls->ibox); env->closure = ls; indent = HTMLCreateBox(li, env); if (ResourceGetUInt(li->cres, "html.dlIndent", &(indent->width)) == NULL) { indent->width = 20; } indent->height = 1; HTMLSetB(indent, BOX_FLOAT_LEFT); HTMLLayoutBox(li, ls->ibox, indent); ls->tbox = HTMLCreateFlowBox(li, env, HTMLGetMaxWidth(li, env->penv) - indent->width); return; } void HTMLDTBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HList *ls; ls = (HList *)env->penv->closure; ls->ibox = HTMLCreateFlowBox(li, env, HTMLGetMaxWidth(li, env->penv)); GListAddTail(ls->klist, ls->ibox); env->closure = ls; ls->tbox = NULL; /* this is important */ return; } void HTMLDLBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HList *ls; ls = CreateList(li, env); env->closure = ls; env->ff = FLOW_LEFT_JUSTIFY; return; } /* * OLNext */ static void OLNext(buffer, bsize, number, oltype) char *buffer; size_t bsize; int number; OListType oltype; { int i; char *cp; if (oltype == OL_ALPHA_CAP) { number = (number-1) % 26; number += 65; snprintf(buffer, bsize, "%c.", (char)number); } else if (oltype == OL_ALPHA_MINISCULE) { number = (number-1) % 26; number += 97; snprintf(buffer, bsize, "%c.", (char)number); } else if ((oltype==OL_ROMAN_CAP)||(oltype==OL_ROMAN_MINISCULE)) { /*Convert an integer to roman*/ i=0; if (number <0) { buffer[i++]='-'; number *= -1; } if (number==0) { buffer[i++]='0'; } while ((number > 0) && (i < BUFSIZ - 2)) { if (number >=1000) { number -=1000; buffer[i++]='M'; } else if (number >=900) { number -=100; buffer[i++]='C'; buffer[i++]='M'; } else if (number >= 500) { number -= 500; buffer[i++] ='D'; } else if (number >= 100) { number -= 100; buffer[i++] ='C'; } else if (number >= 90) { number-= 10; buffer[i++]='X'; buffer[i++]='C'; } else if (number >= 50) { number -= 50; buffer[i++] = 'L'; } else if (number >= 40) { number -= 10; buffer[i++]='X'; buffer[i++]='L'; } else if (number >= 10) { number -= 10; buffer[i++]='X'; } else if (number == 9) { number = 0; buffer[i++]='I'; buffer[i++]='X'; } else if (number >= 5) { number -= 5; buffer[i++]='V'; } else if (number == 4) { number = 0; buffer[i++]='I'; buffer[i++]='V'; } else if (number >=1) { number--; buffer[i++]='I'; } } buffer[i++] = '.'; buffer[i] = '\0'; /*We've done everything in caps, now convert to lowercase if necessary*/ if (oltype == OL_ROMAN_MINISCULE) { for (cp = buffer; *cp != '\0'; cp++) { *cp = tolower(*cp); } } } else { snprintf(buffer, sizeof(buffer), "%d.", number); } return; } bool HTMLListAccept(li, obj) HTMLInfo li; HTMLObject obj; { if (obj->type != HTML_ENV) return(false); if (HTMLTagToID(obj->o.env->tag) != TAG_LI) return(false); return(true); } bool HTMLDLAccept(li, obj) HTMLInfo li; HTMLObject obj; { if (obj->type != HTML_ENV) return(false); if (HTMLTagToID(obj->o.env->tag) != TAG_DD && HTMLTagToID(obj->o.env->tag) != TAG_DT) { return(false); } return(true); } HTMLInsertStatus HTMLLIInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv tenv; if ((tenv = HTMLFindEnv(li, TAG_UL)) == NULL && (tenv = HTMLFindEnv(li, TAG_OL)) == NULL) { return(HTMLInsertReject); } if (HTMLTagToID(tenv->tag) == TAG_UL) HTMLPopEnv(li, TAG_UL); else HTMLPopEnv(li, TAG_OL); return(HTMLInsertOK); } HTMLInsertStatus HTMLDDInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv tenv; if ((tenv = HTMLFindEnv(li, TAG_DL)) == NULL) { return(HTMLInsertReject); } HTMLPopEnv(li, TAG_DL); return(HTMLInsertOK); } HTMLInsertStatus HTMLDTInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv tenv; if ((tenv = HTMLFindEnv(li, TAG_DL)) == NULL) { return(HTMLInsertReject); } HTMLPopEnv(li, TAG_DL); return(HTMLInsertOK); } /* * HTMLItemAddBox */ void HTMLItemAddBox(li, env, box) HTMLInfo li; HTMLEnv env; HTMLBox box; { HList *ls = (HList *)env->closure; if (ls->tbox != NULL) HTMLLayoutBox(li, ls->tbox, box); else HTMLLayoutBox(li, ls->ibox, box); return; } /* * HTMLListAddBox */ void HTMLListAddBox(li, env, box) HTMLInfo li; HTMLEnv env; HTMLBox box; { HList *ls = (HList *)env->closure; HTMLBox parent = ls->lbox; if (box->width > parent->width) parent->width = box->width; parent->height += box->height; return; } /* * HTMLItemWidth */ unsigned int HTMLItemWidth(li, env) HTMLInfo li; HTMLEnv env; { HList *ls = (HList *)env->closure; if (ls->tbox != NULL) return(HTMLGetBoxWidth(li, ls->tbox)); else return(HTMLGetBoxWidth(li, ls->ibox)); } chimera-2.0a19/html/flow.c100600 11610 11610 27732 6724333412 13633 0ustar johnjohn/* * flow.c * * libhtml - HTML->X renderer * * Copyright (c) 1996-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" typedef struct { int x, y; int bloff; int bottom; unsigned int width, height; unsigned int maxwidth; GList boxes; /* list of boxes in line */ bool ended; HTMLFlowAlign ff; } HLine; typedef struct { GList lines; GList floaters; GList pending_floaters; GList constraints; unsigned int maxwidth; int nexty; int lfloaty; int rfloaty; int linecount; bool linebreak; } HFlow; typedef struct { int x, y; unsigned int width, height; } HCons; /* * * Private functions * */ static void LayoutFlow _ArgProto((HTMLInfo, HTMLBox, HTMLBox)); static unsigned int WidthFlow _ArgProto((HTMLInfo, HTMLBox)); static void SetupFlow _ArgProto((HTMLInfo, HTMLBox)); static void DestroyFlow _ArgProto((HTMLInfo, HTMLBox)); static void RenderFlow _ArgProto((HTMLInfo, HTMLBox, Region)); static void SetupHLine _ArgProto((HTMLInfo, HFlow *, HLine *)); static HLine *StartLine _ArgProto((HTMLInfo, HTMLEnv, HFlow *, HTMLBox)); static void EndLine _ArgProto((HTMLInfo, HFlow *, HLine *, HTMLBox)); static void AddFloater _ArgProto((HTMLInfo, HFlow *, HTMLBox, HTMLBox)); /* * DestroyFlow */ static void DestroyFlow(li, box) HTMLInfo li; HTMLBox box; { HFlow *hf = (HFlow *)box->closure; HLine *hl; HTMLBox c; for (hl = (HLine *)GListGetHead(hf->lines); hl != NULL; hl = (HLine *)GListGetNext(hf->lines)) { for (c = (HTMLBox)GListGetHead(hl->boxes); c != NULL; c = (HTMLBox)GListGetNext(hl->boxes)) { HTMLDestroyBox(li, c); } } for (c = (HTMLBox)GListGetHead(hf->floaters); c != NULL; c = (HTMLBox)GListGetNext(hf->floaters)) { HTMLDestroyBox(li, c); } return; } /* * RenderFlow */ static void RenderFlow(li, box, r) HTMLInfo li; HTMLBox box; Region r; { HFlow *hf = (HFlow *)box->closure; HLine *hl; HTMLBox c; HCons *hc; for (hl = (HLine *)GListGetHead(hf->lines); hl != NULL; hl = (HLine *)GListGetNext(hf->lines)) { if (XRectInRegion(r, hl->x, hl->y, hl->width, hl->height) != RectangleOut) { if (li->flowDebug) { XDrawRectangle(li->dpy, li->win, li->gc, hl->x, hl->y, hl->width, hl->height); } for (c = (HTMLBox)GListGetHead(hl->boxes); c != NULL; c = (HTMLBox)GListGetNext(hl->boxes)) { HTMLRenderBox(li, r, c); } } } for (c = (HTMLBox)GListGetHead(hf->floaters); c != NULL; c = (HTMLBox)GListGetNext(hf->floaters)) { if (XRectInRegion(r, c->x, c->y, c->width, c->height) != RectangleOut) { HTMLRenderBox(li, r, c); } } if (li->constraintDebug) { for (hc = (HCons *)GListGetHead(hf->constraints); hc != NULL; hc = (HCons *)GListGetNext(hf->constraints)) { XDrawRectangle(li->dpy, li->win, li->gc, hc->x + box->x, hc->y + box->y, hc->width, hc->height); } } return; } /* * AddFloater */ static void AddFloater(li, hf, parent, box) HTMLInfo li; HFlow *hf; HTMLBox parent; HTMLBox box; { HCons *hc; /* * Determine the location of the floating box. * The idea here is to push the floater below any other floaters on the * same side of the flow box and also make sure it clears any existing * lines. This is probably a bit paranoid but hopefully will prevent * any chance of overlap. */ if (HTMLTestB(box, BOX_FLOAT_LEFT)) { box->x = 0; box->y = hf->lfloaty; if (box->y < hf->nexty) box->y = hf->nexty; hf->lfloaty = box->y + box->height; } else { box->x = hf->maxwidth - box->width; if (box->x < 0) box->x = 0; box->y = hf->rfloaty; if (box->y < hf->nexty) box->y = hf->nexty; hf->rfloaty = box->y + box->height; } /* * Determine the new dimensions of the parent */ if (parent->width < box->x + box->width) { parent->width = box->x + box->width; } if (parent->height < box->y + box->height) { parent->height = box->y + box->height; } /* * Add a new constraints box */ hc = (HCons *)MPGet(li->mp, sizeof(HCons)); if (HTMLTestB(box, BOX_FLOAT_LEFT)) hc->x = box->width; else hc->x = 0; hc->y = box->y; hc->width = hf->maxwidth - box->width; hc->height = box->height; GListAddHead(hf->constraints, hc); GListAddTail(hf->floaters, box); if (HTMLTestB(parent, BOX_TOPLEVEL)) { box->x += parent->x; box->y += parent->y; HTMLSetupBox(li, box); } return; } /* * StartLine */ static HLine * StartLine(li, env, hf, parent) HTMLInfo li; HTMLEnv env; HFlow *hf; HTMLBox parent; { HLine *hl; HTMLBox floater; HCons *hc; while ((floater = GListPop(hf->pending_floaters)) != NULL) { AddFloater(li, hf, parent, floater); } /* * Add a new line to the end. */ hl = (HLine *)MPCGet(li->mp, sizeof(HLine)); hl->boxes = GListCreateX(li->mp); hl->ff = env->ff; GListAddTail(hf->lines, hl); hl->y = hf->nexty; hl->x = 0; hl->maxwidth = hf->maxwidth; /* * Determine if a constraint box has to be taken into account. */ for (hc = (HCons *)GListGetHead(hf->constraints); hc != NULL; hc = (HCons *)GListGetNext(hf->constraints)) { if (hl->y >= hc->y && hc->y + hc->height >= hl->y) { if (hc->x > hl->x) hl->x = hc->x; if (hc->x + hc->width < hl->x + hl->maxwidth) { /* * Check for extreme trouble. It might be possible for the * left edge of the line to go beyond the right side of the * constraint box. If so, try to push the line down past * everything else to avoid Trouble. */ if (hl->x > hc->x + hc->width) { hl->x = 0; hl->y = parent->height; hl->maxwidth = hf->maxwidth; break; } else hl->maxwidth = hc->x + hc->width; } } } hl->maxwidth -= hl->x; return(hl); } /* * EndLine */ static void EndLine(li, hf, hl, parent) HTMLInfo li; HFlow *hf; HLine *hl; HTMLBox parent; { myassert(!hl->ended, "Line already ended"); hf->linecount++; if (hl->width + hl->x > parent->width) parent->width = hl->width + hl->x; hf->nexty += hl->height; if (hf->nexty > parent->height) parent->height = hf->nexty; if (HTMLTestB(parent, BOX_TOPLEVEL)) { if (hf->linecount % 50 == 0) { GUISetDimensions(li->wd, parent->width + li->lmargin + li->rmargin, parent->height + li->tmargin + li->bmargin); } hl->x += parent->x; hl->y += parent->y; SetupHLine(li, hf, hl); } hl->ended = true; return; } /* * LayoutFlow */ static void LayoutFlow(li, child, parent) HTMLInfo li; HTMLBox child; HTMLBox parent; { HFlow *hf = (HFlow *)parent->closure; HLine *hl; unsigned int temp; if (li->framesonly) return; if (HTMLTestB(parent, BOX_TOPLEVEL)) li->noframeset = true; /* * Shove the floating box in a list and deal with it just before a new * line is started. */ if (HTMLTestB(child, BOX_FLOAT_LEFT | BOX_FLOAT_RIGHT)) { GListAddTail(hf->pending_floaters, child); return; } /* * Check for clear */ if (HTMLTestB(child, BOX_CLEAR_LEFT | BOX_CLEAR_RIGHT)) { if (HTMLTestB(child, BOX_CLEAR_LEFT) && hf->nexty < hf->lfloaty) { hf->nexty = hf->lfloaty; } if (HTMLTestB(child, BOX_CLEAR_RIGHT) && hf->nexty < hf->rfloaty) { hf->nexty = hf->rfloaty; } hf->linebreak = true; return; } /* * Check for new line. */ if ((hl = (HLine *)GListGetTail(hf->lines)) == NULL) { if (HTMLTestB(child, BOX_LINEBREAK | BOX_SPACE)) return; hl = StartLine(li, child->env, hf, parent); } else { if (HTMLTestB(child, BOX_LINEBREAK)) { hf->linebreak = true; return; } if (hf->linebreak || (child->width + hl->width > hl->maxwidth && !GListEmpty(hl->boxes))) { hf->linebreak = false; if (!hl->ended) EndLine(li, hf, hl, parent); hl = StartLine(li, child->env, hf, parent); if (HTMLTestB(child, BOX_SPACE)) return; } else hf->linebreak = false; } /* * Figure out how the new box changes the baseline offset (from * the top) and the bottom; */ if (HTMLTestB(child, BOX_VCENTER)) { temp = child->height / 2; if (temp > hl->bloff) hl->bloff = temp; if (temp > hl->bottom) hl->bottom = temp; } else { if (child->baseline > hl->bloff) hl->bloff = child->baseline; temp = child->height - child->baseline; if (temp > hl->bottom) hl->bottom = temp; } hl->width += child->width; hl->height = hl->bloff + hl->bottom; GListAddTail(hl->boxes, child); return; } /* * SetupHLine */ static void SetupHLine(li, hf, hl) HTMLInfo li; HFlow *hf; HLine *hl; { HTMLBox c; int x = hl->x; if (hl->ff & FLOW_CENTER_JUSTIFY) { if (hl->width < hl->maxwidth) x += hl->maxwidth / 2 - hl->width / 2; } else if (hl->ff & FLOW_RIGHT_JUSTIFY) { if (hl->width < hl->maxwidth) x += hl->maxwidth - hl->width; } for (c = (HTMLBox)GListGetHead(hl->boxes); c != NULL; c = (HTMLBox)GListGetNext(hl->boxes)) { c->x = x; c->y = hl->y; HTMLSetupBox(li, c); x += c->width; HTMLRenderBox(li, NULL, c); } return; } /* * SetupFlow */ static void SetupFlow(li, box) HTMLInfo li; HTMLBox box; { HFlow *hf = (HFlow *)box->closure; HLine *hl; HTMLBox c; if (HTMLTestB(box, BOX_TOPLEVEL)) return; for (c = (HTMLBox)GListGetHead(hf->floaters); c != NULL; c = (HTMLBox)GListGetNext(hf->floaters)) { c->x += box->x; c->y += box->y; HTMLSetupBox(li, c); } for (hl = (HLine *)GListGetHead(hf->lines); hl != NULL; hl = (HLine *)GListGetNext(hf->lines)) { hl->x += box->x; hl->y += box->y; SetupHLine(li, hf, hl); } return; } /* * WidthFlow */ static unsigned int WidthFlow(li, box) HTMLInfo li; HTMLBox box; { HFlow *hf = (HFlow *)box->closure; HLine *hl; if ((hl = (HLine *)GListGetTail(hf->lines)) == NULL || hf->linebreak) { return(hf->maxwidth); } return(hl->maxwidth - hl->width); } /* * * Public functions * */ /* * HTMLCreateFlowBox */ HTMLBox HTMLCreateFlowBox(li, env, maxwidth) HTMLInfo li; HTMLEnv env; unsigned int maxwidth; { HTMLBox box; HFlow *hf; hf = (HFlow *)MPCGet(li->mp, sizeof(HFlow)); hf->lines = GListCreateX(li->mp); hf->floaters = GListCreateX(li->mp); hf->pending_floaters = GListCreateX(li->mp); hf->constraints = GListCreateX(li->mp); /* woo hoo! */ if (maxwidth == 0) hf->maxwidth = 64000; else hf->maxwidth = maxwidth; box = HTMLCreateBox(li, env); box->setup = SetupFlow; box->render = RenderFlow; box->destroy = DestroyFlow; box->maxwidth = WidthFlow; box->layout = LayoutFlow; box->closure = hf; return(box); } /* * HTMLFinishFlowBox */ void HTMLFinishFlowBox(li, box) HTMLInfo li; HTMLBox box; { HFlow *hf = (HFlow *)box->closure; HLine *hl; HTMLBox child; if (HTMLTestB(box, BOX_TOPLEVEL) && !li->noframeset) return; if ((hl = (HLine *)GListGetTail(hf->lines)) != NULL) { if (!hl->ended) EndLine(li, hf, hl, box); } while ((child = (HTMLBox)GListPop(hf->pending_floaters)) != NULL) { AddFloater(li, hf, box, child); } if (HTMLTestB(box, BOX_TOPLEVEL)) { GUISetDimensions(li->wd, box->width + li->lmargin + li->rmargin, box->height + li->tmargin + li->bmargin); HTMLSetFinalPosition(li); } return; } chimera-2.0a19/html/map.c100600 11610 11610 12420 6677561666 13452 0ustar johnjohn/* * map.c * * libhtml - HTML->X renderer * * Copyright (c) 1996-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" typedef enum { HTMLMapShapeRect, HTMLMapShapeCircle, HTMLMapShapePoly, HTMLMapShapeDefault } HTMLMapShape; struct HTMLAreaP { HTMLMapShape shape; int *coords; int count; char *url; Region r; }; struct HTMLMapP { char *name; GList areas; HTMLArea defarea; }; static void MakeArea _ArgProto((HTMLInfo, HTMLMap, MLElement)); static void MakeArea(li, map, p) HTMLInfo li; HTMLMap map; MLElement p; { HTMLArea area; char *shape; char *href; char *coords; int i, j; char *cp; XPoint *xp; area = (HTMLArea)MPCGet(li->mp, sizeof(struct HTMLAreaP)); if ((coords = MLFindAttribute(p, "coords")) != NULL) { for (cp = coords, i = 0; *cp != '\0'; cp++) { if (*cp == ',') i++; } i++; area->coords = (int *)MPCGet(li->mp, sizeof(int) * i); area->coords[0] = atoi(coords); for (cp = coords, i = 1; *cp != '\0'; cp++) { if (*cp == ',') area->coords[i++] = atoi(cp + 1); } area->count = i; } if ((shape = MLFindAttribute(p, "shape")) == NULL) shape = "rect"; if (strcasecmp(shape, "circle") == 0) { area->shape = HTMLMapShapeCircle; GListAddTail(map->areas, area); } else if (strcasecmp(shape, "poly") == 0) { area->shape = HTMLMapShapePoly; if (area->count / 2 >= 3) { GListAddTail(map->areas, area); xp = (XPoint *)MPCGet(li->mp, sizeof(XPoint) * area->count / 2); for (j = 0, i = 0; j < area->count / 2; i += 2, j++) { xp[j].x = area->coords[i]; xp[j].y = area->coords[i + 1]; } area->r = XPolygonRegion(xp, area->count / 2, WindingRule); } } else if (strcasecmp(shape, "default") == 0) { area->shape = HTMLMapShapeDefault; if (map->defarea == NULL) map->defarea = area; } else { area->shape = HTMLMapShapeRect; GListAddTail(map->areas, area); } if ((href = MLFindAttribute(p, "href")) != NULL) area->url = href; return; } void HTMLMapBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLMap map; char *name; if ((name = MLFindAttribute(p, "name")) == NULL) return; map = (HTMLMap)MPCGet(li->mp, sizeof(struct HTMLMapP)); map->name = name; map->areas = GListCreateX(li->mp); env->closure = map; return; } void HTMLAreaBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLMap map; /* * Area doesn't create an environment so the current environment * must be the map environment. */ map = (HTMLMap)env->closure; MakeArea(li, map, p); return; } void HTMLMapEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLMap map; map = (HTMLMap)env->closure; GListAddTail(li->maps, map); return; } char * HTMLFindMapURL(li, url, x, y) HTMLInfo li; char *url; int x, y; { HTMLArea area; HTMLMap map; GList list; int dx, dy; double rd; URLParts *up; MemPool mp; mp = MPCreate(); if ((up = URLParse(mp, url)) == NULL || up->hostname != NULL || up->filename != NULL || up->fragment == NULL) { MPDestroy(mp); fprintf (stderr, "Local maps supported only.\n"); return(NULL); } list = li->maps; for (map = (HTMLMap)GListGetHead(list); map != NULL; map = (HTMLMap)GListGetNext(list)) { if (strcasecmp(map->name, up->fragment) == 0) break; } MPDestroy(mp); if (map == NULL) return(NULL); list = map->areas; for (area = (HTMLArea)GListGetHead(list); area != NULL; area = (HTMLArea)GListGetNext(list)) { if (area->shape == HTMLMapShapeRect) { if (area->count == 4 && area->coords[0] < x && x < area->coords[2] && area->coords[1] < y && y < area->coords[3]) { return(area->url); } } else if (area->shape == HTMLMapShapeCircle) { dx = x - area->coords[0]; dy = y - area->coords[1]; rd = sqrt((double)(dx * dx + dy * dy)); if ((int)rd < area->coords[2]) return(area->url); } else if (area->shape == HTMLMapShapePoly) { if (area->r != NULL && XPointInRegion(area->r, x, y)) return(area->url); } } if (map->defarea != NULL) return(map->defarea->url); return(NULL); } /* * HTMLMapAccept */ bool HTMLMapAccept(li, obj) HTMLInfo li; HTMLObject obj; { return(true); } /* * HTMLAreaInsert */ HTMLInsertStatus HTMLAreaInsert(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { if (HTMLTagToID(env->tag) != TAG_MAP) return(HTMLInsertReject); return(HTMLInsertOK); } chimera-2.0a19/html/load.c100600 11610 11610 10155 6677561670 13612 0ustar johnjohn/* * load.c * * libhtml - HTML->X renderer * * Copyright (c) 1996-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include "port_after.h" #include "html.h" #include "ChimeraStack.h" int HTMLLoadURL(li, frame, url, action) HTMLInfo li; char *frame; char *url; char *action; { ChimeraRequest *wr; if (url == NULL) return(-1); if (url[0] == '#') { HTMLFindName(li, url + 1); return(0); } wr = RequestCreate(li->cres, url, li->burl); RenderAction(li->wn, wr, action); return(0); } int HTMLLoadAnchor(li, anchor, x, y, action, ismap) HTMLInfo li; HTMLAnchor anchor; int x, y; char *action; bool ismap; { char *aurl, *url; char *target; MemPool mp; ChimeraRequest *wr; ChimeraStack cs; if ((url = MLFindAttribute(anchor->p, "href")) == NULL) return(-1); /* * This could be trouble. What if there is a 'target' attribute? * I think the solutuion is to prepend the base URL to the fragment * and submit it so that fragment stuff will end up on the document * stack. */ if (url[0] == '#') { HTMLFindName(li, url + 1); return(0); } if (ismap) { mp = MPCreate(); aurl = (char *)MPGet(mp, strlen(url) + 200); snprintf (aurl, strlen(url) + 200, "%s?%d,%d", url, x, y); url = aurl; } else mp = NULL; wr = RequestCreate(li->cres, url, li->burl); if (mp != NULL) MPDestroy(mp); if (wr == NULL) return(-1); if ((target = MLFindAttribute(anchor->p, "target")) != NULL) { HTMLFrameLoad(li, wr, target); } else { if ((cs = StackGetParent(StackFromGUI(li->wc, li->wd))) == NULL) { RenderAction(li->wn, wr, action); } else { StackAction(cs, wr, action); } } return(0); } void HTMLPrintURL(li, url) HTMLInfo li; char *url; { ChimeraRequest *wr; size_t len; char buffer[BUFSIZ + 100]; const char *msg = "Cannot handle "; /* this is the wrong thing to do! */ if (url == NULL) return; if ((wr = RequestCreate(li->cres, url, li->burl)) != NULL) { url = wr->url; } else { strcpy(buffer, msg); len = sizeof(buffer) - strlen(msg) - 1; strncat(buffer, url, len); buffer[sizeof(buffer) - 1] = '\0'; url = buffer; } RenderSendMessage(li->wn, url); if (wr != NULL) RequestDestroy(wr); return; } void HTMLPrintAnchor(li, anchor, x, y, ismap) HTMLInfo li; HTMLAnchor anchor; int x, y; bool ismap; { char *url, *aurl; MemPool mp; if ((url = MLFindAttribute(anchor->p, "href")) == NULL) return; if (ismap) { mp = MPCreate(); aurl = (char *)MPGet(mp, strlen(url) + 200); snprintf (aurl, strlen(url) + 200, "%s?%d,%d", url, x, y); url = aurl; HTMLPrintURL(li, url); MPDestroy(mp); } else HTMLPrintURL(li, url); return; } /* * HTMLAddAnchor */ void HTMLAddAnchor(li, box, name, p) HTMLInfo li; HTMLBox box; char *name; MLElement p; { HTMLAnchor a; a = (HTMLAnchor)MPCGet(li->mp, sizeof(struct HTMLAnchorP)); a->name = name; a->p = p; a->box = box; GListAddHead(li->alist, a); return; } /* * HTMLFindName */ void HTMLFindName(li, name) HTMLInfo li; char *name; { HTMLAnchor a; GList list; list = li->alist; for (a = (HTMLAnchor)GListGetHead(list); a != NULL; a = (HTMLAnchor)GListGetNext(list)) { if (a->name != NULL && strlen(name) == strlen(a->name) && strcasecmp(name, a->name) == 0) { GUISetScrollPosition(li->wd, 0, -(a->box->y)); return; } } return; } chimera-2.0a19/html/font.c100600 11610 11610 21440 6677561674 13644 0ustar johnjohn/* * font.c * * libhtml - HTML->X renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" /* * * You really don't want to look in here. * */ #define FONT_SCALE_COUNT 6 #define XLFD_FOUNDRY 0 #define XLFD_FAMILY 1 #define XLFD_WEIGHT_NAME 2 #define XLFD_SLANT 3 #define XLFD_SETWIDTH_NAME 4 #define XLFD_STYLE_NAME 5 #define XLFD_PIXEL_SIZE 6 #define XLFD_POINT_SIZE 7 #define XLFD_RES_X 8 #define XLFD_RES_Y 9 #define XLFD_SPACING 9 #define XLFD_AVERAGE_WIDTH 10 #define XLFD_REGISTRY 11 #define XLFD_ENCODING 12 #define XLFD_COUNT 13 /* Silly font information */ struct HTMLFontP { bool fixed; /* fixed width? */ int weight; /* bold, medium, ... */ int slant; /* italic, regular, ... */ int scale; /* scale of font */ int size; /* size of font */ XFontStruct *xfi; /* real font info */ }; struct HTMLFontListP { HTMLFont fontInfo; int count; int scale[FONT_SCALE_COUNT]; char **names; }; static void ParseXLFD _ArgProto((MemPool, char *, HTMLFont)); static HTMLFontList GetFontList _ArgProto((HTMLClass, char *)); static void FreeFontList _ArgProto((HTMLClass, HTMLFontList)); static XFontStruct *GetFont _ArgProto((HTMLClass, HTMLFontList, int)); /* * ParseXLFD * * Yipe! */ static void ParseXLFD(mp, xlfd, lfi) MemPool mp; char *xlfd; HTMLFont lfi; { char *fields[XLFD_COUNT]; int i; char *t; t = MPStrDup(mp, xlfd); t++; fields[0] = t; for (i = 1; i < XLFD_COUNT; t++) { if (*t == '-') { *t = '\0'; fields[i++] = t + 1; } } if (strcmp(fields[XLFD_WEIGHT_NAME], "bold") == 0 || strcmp(fields[XLFD_WEIGHT_NAME], "demi") == 0 || strcmp(fields[XLFD_WEIGHT_NAME], "demibold") == 0) { lfi->weight = 1; } else lfi->weight = 0; lfi->size = atoi(fields[XLFD_PIXEL_SIZE]); if (strcmp(fields[XLFD_SLANT], "i") == 0 || strcmp(fields[XLFD_SLANT], "o") == 0) { lfi->slant = 1; } else lfi->slant = 0; return; } /* * GetFont */ static XFontStruct * GetFont(lc, fl, i) HTMLClass lc; HTMLFontList fl; int i; { if (fl->fontInfo[i].xfi == NULL) { fl->fontInfo[i].xfi = XLoadQueryFont(lc->dpy, fl->names[i]); if (fl->fontInfo[i].xfi == NULL) return(lc->defaultFont); } return(fl->fontInfo[i].xfi); } /* * HTMLGetFont */ XFontStruct * HTMLGetFont(li, env) HTMLInfo li; HTMLEnv env; { int i; HTMLClass lc = li->lc; HTMLFont lfi; HTMLFontList fl; lfi = env->fi; if (lfi == NULL) { lfi = HTMLDupFont(li,li->cfi); env->fi = lfi; } /* * Check spacing */ if (lfi->fixed) fl = lc->fixed; else fl = lc->prop; /* * Check slant, size, and weight */ for (i = 0; i < fl->count; i++) { if (((lfi->weight > 0) == (fl->fontInfo[i].weight > 0)) && ((lfi->slant > 0) == (fl->fontInfo[i].slant > 0)) && fl->scale[lfi->scale] == fl->fontInfo[i].size) { return(GetFont(lc, fl, i)); } } /* * Check slant and size */ for (i = 0; i < fl->count; i++) { if (((lfi->slant > 0) == (fl->fontInfo[i].slant > 0)) && fl->scale[lfi->scale] == fl->fontInfo[i].size) { return(GetFont(lc, fl, i)); } } /* * Check weight and size */ for (i = 0; i < fl->count; i++) { if (((lfi->weight > 0) == (fl->fontInfo[i].weight > 0)) && fl->scale[lfi->scale] == fl->fontInfo[i].size) { return(GetFont(lc, fl, i)); } } /* * Check size */ for (i = 0; i < fl->count; i++) { if (fl->scale[lfi->scale] == fl->fontInfo[i].size) { return(GetFont(lc, fl, i)); } } return(lc->defaultFont); } /* * GetFontList */ static HTMLFontList GetFontList(lc, pattern) HTMLClass lc; char *pattern; { int count; int scale_count; int i, j, k; MemPool mp; HTMLFontList fl; fl = (HTMLFontList)MPCGet(lc->mp, sizeof(struct HTMLFontListP)); fl->names = XListFonts(lc->dpy, pattern, 999, &count); if (fl->names == NULL || count == 0) { fprintf (stderr, "Could not get font list\n"); fflush(stderr); exit(1); } fl->fontInfo = (HTMLFont)MPCGet(lc->mp, sizeof(struct HTMLFontP) * count); /* * Extract simple information from the XLFD strings. */ mp = MPCreate(); for (i = 0; i < count; i++) { ParseXLFD(mp, fl->names[i], &(fl->fontInfo[i])); } MPDestroy(mp); /* * Find sizes for each of the font scales. There must be a better way. * This should probably not take */ scale_count = 0; for (i = 0; i < count && scale_count < FONT_SCALE_COUNT; i++) { if (fl->fontInfo[i].size > 0) { for (j = 0; j < scale_count; j++) { if (fl->fontInfo[i].size == fl->scale[j]) break; if (fl->fontInfo[i].size < fl->scale[j]) { for (k = scale_count - 1; k >= j; k--) { fl->scale[k + 1] = fl->scale[k]; } fl->scale[j] = fl->fontInfo[i].size; scale_count++; break; } } if (j == scale_count) { fl->scale[j] = fl->fontInfo[i].size; scale_count++; } } } /* * This will probably never happen. */ if (scale_count == 0) { fl->scale[0] = fl->fontInfo[0].size; scale_count++; } /* * Fill out the rest if there aren't FONT_SCALE_COUNT */ if (scale_count < FONT_SCALE_COUNT) { for (i = scale_count; i < FONT_SCALE_COUNT; i++) { fl->scale[i] = fl->scale[i - 1]; } scale_count = FONT_SCALE_COUNT; } /* * Set miscellaneous information. */ fl->count = count; return(fl); } /* * HTMLSetupFonts */ void HTMLSetupFonts(li) HTMLInfo li; { char *name; HTMLClass lc = li->lc; /* * Default HTML font. */ li->cfi = (HTMLFont)MPCGet(li->mp, sizeof(struct HTMLFontP)); HTMLSetFontProp(li->cfi); HTMLSetFontScale(li->cfi, 2); /* * Only need to do HTML font information setup once. */ if (lc->font_setup_done) return; lc->dpy = li->dpy; /* * Font to use if all else fails */ name = ResourceGetString(li->cres, "html.defaultFont"); if (name == NULL) name = "variable"; if ((lc->defaultFont = XLoadQueryFont(li->dpy, name)) == NULL) { fprintf (stderr, "Could not get default font.\n"); fflush(stderr); exit(1); } /* * Get the font list pattern for the proportional fonts. Hopefully * a reasonable pattern was selected. */ name = ResourceGetString(li->cres, "html.propFontPattern"); if (name == NULL) name = "-adobe-times-*-*-*-*-*-*-*-*-*-*-iso8859-1"; lc->prop = GetFontList(lc, name); /* * Get the font list pattern for the fixed fonts. Hopefully * a reasonable pattern was selected. */ name = ResourceGetString(li->cres, "html.fixedFontPattern"); if (name == NULL) name = "-misc-fixed-*-*-*-*-*-*-*-*-*-*-iso8859-1"; lc->fixed = GetFontList(lc, name); lc->font_setup_done = true; return; } /* * FreeFontList */ static void FreeFontList(lc, fl) HTMLClass lc; HTMLFontList fl; { int i; if (fl->fontInfo != NULL) { for (i = 0; i < XLFD_COUNT; i++) { if (fl->fontInfo[i].xfi != NULL && fl->fontInfo[i].xfi != lc->defaultFont) { XFreeFont(lc->dpy, fl->fontInfo[i].xfi); } } } if (fl->names != NULL) XFreeFontNames(fl->names); return; } /* * HTMLFreeFonts */ void HTMLFreeFonts(lc) HTMLClass lc; { if (lc->prop != NULL) FreeFontList(lc, lc->prop); if (lc->fixed != NULL) FreeFontList(lc, lc->fixed); if (lc->defaultFont != NULL) XFreeFont(lc->dpy, lc->defaultFont); return; } HTMLFont HTMLDupFont(li, f) HTMLInfo li; HTMLFont f; { HTMLFont n; n = (HTMLFont)MPCGet(li->mp, sizeof(struct HTMLFontP)); memcpy(n, f, sizeof(struct HTMLFontP)); return(n); } void HTMLAddFontWeight(f) HTMLFont f; { f->weight++; return; } void HTMLAddFontSlant(f) HTMLFont f; { f->slant++; return; } void HTMLAddFontScale(f) HTMLFont f; { f->scale++; return; } void HTMLSetFontScale(f, scale) HTMLFont f; int scale; { f->scale = scale; return; } void HTMLSetFontProp(f) HTMLFont f; { f->fixed = false; return; } void HTMLSetFontFixed(f) HTMLFont f; { f->fixed = true; return; } chimera-2.0a19/html/form.c100600 11610 11610 53273 6677561703 13643 0ustar johnjohn/* * form.c * * libhtml - HTML->X renderer * * Copyright (c) 1996-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #ifndef HAVE_STRING_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "port_after.h" #include "TextField.h" #include "html.h" typedef struct InputStateP InputState; typedef struct FormStateP FormState; typedef struct RadioStateP RadioState; typedef struct OptionStateP OptionState; struct OptionStateP { char *value; bool selected; char *text; Widget sme; }; typedef enum { INPUT_TEXT, INPUT_PASSWORD, INPUT_CHECKBOX, INPUT_RADIO, INPUT_SUBMIT, INPUT_RESET, INPUT_RANGE, INPUT_AUDIO, INPUT_FILE, INPUT_SCRIBBLE, INPUT_HIDDEN, INPUT_IMAGE, INPUT_TEXTAREA, INPUT_SELECT } InputType; struct InputStateP { /* generic stuff */ InputType id; Widget w; /* the widget */ MLElement p; /* input tag */ FormState *fs; HTMLBox box; char *name; /* for image input */ HTMLInline img; /* select stuff */ bool multi; /* multi-select? */ GList oplist; ChimeraTimeOut iot; int x, y, button; /* coordinates if image clicked */ }; struct FormStateP { MLElement p; /* form tag info */ GList rslist; /* radio list */ GList islist; GList oplist; /* building option list */ HTMLInfo li; char *action; }; /* * * Private function prototypes * */ static InputState *CreateInputState _ArgProto((FormState *, MLElement, InputType)); static HTMLBox CreateInputBox _ArgProto((HTMLInfo, HTMLEnv, InputState *, unsigned int, unsigned int)); static void DestroyInput _ArgProto((HTMLInfo, HTMLBox)); static void CreateHidden _ArgProto((FormState *, HTMLEnv, MLElement)); static void CreateText _ArgProto((FormState *, HTMLEnv, MLElement, InputType)); static void CreateCheckbox _ArgProto((FormState *, HTMLEnv, MLElement)); static void CreateRadio _ArgProto((FormState *, HTMLEnv, MLElement)); static void CreateImage _ArgProto((FormState *, HTMLEnv, MLElement)); static void CreateCommand _ArgProto((FormState *, HTMLEnv, MLElement, InputType)); static char *NameValueToURLEncoded _ArgProto((MemPool, char **, char **, int)); static void MakeSelectWidget _ArgProto((HTMLInfo, FormState *, HTMLEnv)); static char *GetAsciiText _ArgProto((Widget)); static XFontStruct *GetFont _ArgProto((Widget)); static void SetupInput _ArgProto((HTMLInfo, HTMLBox)); static bool FormImageSelectCallback _ArgProto((void *, int, int, char *)); bool FormImageMotionCallback _ArgProto((void *, int, int)); static void SubmitCallback _ArgProto((Widget, XtPointer, XtPointer)); static void HandleSubmit _ArgProto((HTMLInfo, FormState *, InputState *, char *)); /* * Functions */ static XFontStruct * GetFont(w) Widget w; { XFontStruct *font; XtVaGetValues(w, XtNfont, &font, NULL); return(font); } static char * GetAsciiText(w) Widget w; { char *s; XtVaGetValues(w, XtNstring, &s, NULL); return(s); } /* * NameValueToURLEncoded */ static char * NameValueToURLEncoded(mp, names, values, count) MemPool mp; char **names; char **values; int count; { int i; char *finfo; char *sep; char *n, *v; size_t flen, alen; char *format = "%s%s=%s"; char *nf; sep = ""; finfo = ""; flen = 0; for (i = 0; i < count; i++) { if (names[i] == NULL) continue; n = URLEscape(mp, names[i], 0); if (values[i] != NULL) v = URLEscape(mp, values[i], 1); else v = ""; alen = flen + strlen(n) + strlen(v) + strlen(sep) + strlen(format) + 1; nf = (char *)MPGet(mp, alen); snprintf (nf, alen, "%s%s%s=%s", finfo, sep, n, v); finfo = nf; sep = "&"; flen = strlen(finfo); } return(finfo); } /* * HandleSubmit */ static void HandleSubmit(li, fs, ci, action) HTMLInfo li; FormState *fs; InputState *ci; char *action; { InputState *xi; int i; char **names; char **values; char *n; Boolean checked; int count; OptionState *co; ChimeraRequest *wr; if (fs->action == NULL) return; wr = RequestCreate(li->cres, fs->action, li->burl); if ((wr->input_method = MLFindAttribute(fs->p, "method")) != NULL) { wr->input_method = MPStrDup(wr->mp, wr->input_method); } wr->input_type = MPStrDup(wr->mp, "application/x-www-form-urlencoded"); count = 0; for (xi = (InputState *)GListGetHead(fs->islist); xi != NULL; xi = (InputState *)GListGetNext(fs->islist)) { count += 2; if (xi->id == TAG_SELECT) { for (co = (OptionState *)GListGetHead(xi->oplist); co != NULL; co = (OptionState *)GListGetNext(xi->oplist)) { if (co->selected) count++; } } } if (count == 0) { fprintf (stderr, "SubmitCallback error.\n"); return; } names = (char **)MPGet(wr->mp, sizeof(char **) * count); values = (char **)MPGet(wr->mp, sizeof(char **) * count); i = 0; for (xi = (InputState *)GListGetHead(fs->islist); xi != NULL; xi = (InputState *)GListGetNext(fs->islist)) { names[i] = NULL; values[i] = NULL; if ((n = MLFindAttribute(xi->p, "name")) == NULL) continue; if (xi->id == INPUT_TEXT || xi->id == INPUT_PASSWORD) { names[i] = n; values[i] = TextFieldGetString(xi->w); if (values[i] != NULL) values[i] = MPStrDup(wr->mp, values[i]); i++; } else if (xi->id == INPUT_TEXTAREA) { names[i] = n; values[i] = GetAsciiText(xi->w); if (values[i] != NULL) values[i] = MPStrDup(wr->mp, values[i]); i++; } else if (xi->id == INPUT_CHECKBOX || xi->id == INPUT_RADIO) { XtVaGetValues(xi->w, XtNstate, &checked, NULL); if (checked) { names[i] = n; values[i] = MLFindAttribute(xi->p, "value"); i++; } } else if (xi->id == INPUT_HIDDEN) { names[i] = n; values[i] = MLFindAttribute(xi->p, "value"); i++; } else if (xi->id == INPUT_SELECT) { for (co = (OptionState *)GListGetHead(xi->oplist); co != NULL; co = (OptionState *)GListGetNext(xi->oplist)) { if (co->selected) { names[i] = n; if (co->value != NULL) values[i] = co->value; else values[i] = co->text; i++; } } } } /* * Add data from the submit button/image */ if (ci->id == INPUT_IMAGE) { if ((n = MLFindAttribute(ci->p, "name")) != NULL) { names[i] = (char *)MPGet(wr->mp, strlen(n) + strlen(".x") + 1); strcpy(names[i], n); strcat(names[i], ".x"); values[i] = (char *)MPGet(wr->mp, 25); snprintf (values[i], 25, "%d", ci->x); i++; names[i] = (char *)MPGet(wr->mp, strlen(n) + strlen(".y") + 1); strcpy(names[i], n); strcat(names[i], ".y"); values[i] = (char *)MPGet(wr->mp, 25); snprintf (values[i], 25, "%d", ci->y); i++; } } else if (ci->id == INPUT_SUBMIT) { if ((n = MLFindAttribute(ci->p, "name")) != NULL) { names[i] = n; values[i] = MLFindAttribute(ci->p, "value"); i++; } } else { fprintf (stderr, "UNKNOWN SUBMIT INPUT\n"); MPDestroy(wr->mp); return; } if (i > 0) { wr->input_data = NameValueToURLEncoded(wr->mp, names, values, i); wr->input_len = strlen((char *)wr->input_data); } else { wr->input_data = NULL; wr->input_len = 0; } RenderAction(li->wn, wr, action); return; } /* * SubmitCallback */ static void SubmitCallback(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { InputState *ci = (InputState *)cldata; FormState *fs = ci->fs; HTMLInfo li = fs->li; HandleSubmit(li, fs, ci, "open"); return; } /* * ResetCallback * * Do something about this later. */ static void ResetCallback(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { return; } /* * SmeCallback */ static void SmeCallback(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { InputState *ci = (InputState *)cldata; String str; OptionState *co; for (co = (OptionState *)GListGetHead(ci->oplist); co != NULL; co = (OptionState *)GListGetNext(ci->oplist)) { if (co->sme == w) { if (co->selected) { if (ci->multi) co->selected = false; } else { co->selected = true; XtVaGetValues(w, XtNlabel, &str, NULL); XtVaSetValues(ci->w, XtNlabel, str, NULL); } } else if (!ci->multi) co->selected = false; } return; } /* * SetupInput */ static void SetupInput(li, box) HTMLInfo li; HTMLBox box; { InputState *ci = (InputState *)box->closure; /* if (ci->img != NULL) HTMLSetInlinePosition(ci->img, box->x, box->y); */ if (ci->w != NULL) { XtConfigureWidget(ci->w, (Position)box->x, (Position)box->y, (Dimension)(box->width - 10), (Dimension)(box->height - 5), (Dimension)1); XtManageChild(ci->w); } return; } /* * CreateInputBox */ static HTMLBox CreateInputBox(li, env, ci, width, height) HTMLInfo li; HTMLEnv env; InputState *ci; unsigned int width, height; { HTMLBox box; box = HTMLCreateBox(li, env); box->setup = SetupInput; box->destroy = DestroyInput; box->width = width + 10; box->height = height + 5; box->baseline = height; box->closure = ci; HTMLEnvAddBox(li, env, box); return(box); } /* * CreateInputState */ static InputState * CreateInputState(fs, p, type) FormState *fs; MLElement p; InputType type; { InputState *ci; ci = (InputState *)MPCGet(fs->li->mp, sizeof(InputState)); ci->p = p; ci->id = type; ci->fs = fs; GListAddTail(fs->islist, ci); return(ci); } /* * DestroyInput */ static void DestroyInput(li, box) HTMLInfo li; HTMLBox box; { InputState *ci = (InputState *)box->closure; if (ci->id == INPUT_RADIO) GListRemoveItem(ci->fs->rslist, ci); GListRemoveItem(ci->fs->islist, ci); if (ci->w != NULL) XtDestroyWidget(ci->w); if (ci->img != NULL) HTMLInlineDestroy(ci->img); if (ci->iot != NULL) TimeOutDestroy(ci->iot); return; } /* * CreateHidden */ static void CreateHidden(fs, env, p) FormState *fs; HTMLEnv env; MLElement p; { CreateInputState(fs, p, INPUT_HIDDEN); return; } /* * CreateText */ static void CreateText(fs, env, p, type) FormState *fs; HTMLEnv env; MLElement p; InputType type; { Widget w; int width, height; XFontStruct *font; char *value; HTMLBox box; InputState *ci; Boolean echo; char *name; if (type == INPUT_PASSWORD) { name = "password"; echo = False; } else { name = "text"; echo = True; } w = XtVaCreateManagedWidget(name, textfieldWidgetClass, fs->li->widget, XtNecho, echo, XtNlength, 500, NULL); if ((value = MLFindAttribute(p, "value")) != NULL) { value = MPStrDup(fs->li->mp, value); HTMLStringSpacify(value, strlen(value)); TextFieldSetString(w, value); } else { TextFieldSetString(w, ""); } if ((font = GetFont(w)) == NULL) height = 20; else height = font->ascent + font->descent + 5; /* Addition by LRD. tweaked to john's weird style */ if ((width = MLAttributeToInt(p, "size")) > 0) { if (width > 200) width = 200; } else width = 25; if (font == NULL) width = width * 8; else width = width * XTextWidth(font, "0", 1); /* End: replaces "width = 100;" */ ci = CreateInputState(fs, p, type); box = CreateInputBox(fs->li, env, ci, width, height); ci->w = w; return; } /* * CreateCheckbox */ static void CreateCheckbox(fs, env, p) FormState *fs; HTMLEnv env; MLElement p; { Widget w; Boolean state; HTMLBox box; InputState *ci; if (MLFindAttribute(p, "checked") != NULL) state = True; else state = False; w = XtVaCreateWidget("checkbox", toggleWidgetClass, fs->li->widget, XtNstate, state, XtNlabel, " ", NULL); ci = CreateInputState(fs, p, INPUT_CHECKBOX); box = CreateInputBox(fs->li, env, ci, 15, 15); ci->w = w; return; } /* * CreateRadio */ static void CreateRadio(fs, env, p) FormState *fs; HTMLEnv env; MLElement p; { Widget w; Boolean state; char *name; InputState *ci, *peer; HTMLBox box; if (MLFindAttribute(p, "checked") != NULL) state = True; else state = False; if ((name = MLFindAttribute(p, "name")) == NULL) name = "bozo"; for (peer = (InputState *)GListGetHead(fs->rslist); peer != NULL; peer = (InputState *)GListGetNext(fs->rslist)) { if (strlen(name) == strlen(peer->name) && strcasecmp(name, peer->name) == 0) break; } w = XtVaCreateWidget("radio", toggleWidgetClass, fs->li->widget, XtNstate, state, XtNlabel, " ", NULL); ci = CreateInputState(fs, p, INPUT_RADIO); box = CreateInputBox(fs->li, env, ci, 15, 15); ci->w = w; ci->name = (char *)MPStrDup(fs->li->mp, name); if (peer == NULL) { GListAddHead(fs->rslist, ci); XtVaSetValues(w, XtNstate, True, NULL); } else XtVaSetValues(w, XtNradioGroup, peer->w, NULL); return; } /* * CreateCommand */ static void CreateCommand(fs, env, p, type) FormState *fs; HTMLEnv env; MLElement p; InputType type; { Arg args[10]; int argcnt; int width, height; char *value; XFontStruct *font; Widget w; InputState *ci; char *name; HTMLBox box; argcnt = 0; name = type == INPUT_SUBMIT ? "submit":"reset"; if ((value = MLFindAttribute(p, "value")) != NULL) { value = MPStrDup(fs->li->mp, value); HTMLStringSpacify(value, strlen(value)); XtSetArg(args[argcnt], XtNlabel, value); argcnt++; } w = XtCreateWidget(name, commandWidgetClass, fs->li->widget, args, argcnt); XtVaGetValues(w, XtNlabel, &value, NULL); XtVaGetValues(w, XtNfont, &font, NULL); if (font == NULL) { width = 50; height = 20; } else { width = XTextWidth(font, value, strlen(value)) + 10; height = font->ascent + font->descent + 3; } ci = CreateInputState(fs, p, type); box = CreateInputBox(fs->li, env, ci, width, height); ci->w = w; if (type == INPUT_SUBMIT) { XtAddCallback(w, XtNcallback, SubmitCallback, (XtPointer)ci); } else if (type == INPUT_RESET) { XtAddCallback(w, XtNcallback, ResetCallback, (XtPointer)ci); } return; } /* * * Public functions * */ /* * HandleFormEnd */ void HTMLFormEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLAddLineBreak(li, env); return; } /* * HandleFormBegin */ void HTMLFormBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { FormState *fs; HTMLAddLineBreak(li, env); fs = (FormState *)MPCGet(li->mp, sizeof(FormState)); fs->p = p; fs->li = li; fs->islist = GListCreateX(li->mp); fs->rslist = GListCreateX(li->mp); fs->action = MLFindAttribute(p, "action"); env->closure = fs; return; } /* * HTMLInput */ void HTMLInput(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { char *type; HTMLEnv fenv; FormState *fs; if ((fenv = HTMLGetIDEnv(env, TAG_FORM)) == NULL) return; fs = (FormState *)fenv->closure; type = MLFindAttribute(p, "type"); if (type == NULL || strcasecmp(type, "text") == 0) { CreateText(fs, env, p, INPUT_TEXT); } else if (strcasecmp(type, "checkbox") == 0) CreateCheckbox(fs, env, p); else if (strcasecmp(type, "hidden") == 0) CreateHidden(fs, env, p); else if (strcasecmp(type, "image") == 0) CreateImage(fs, env, p); else if (strcasecmp(type, "password") == 0) { CreateText(fs, env, p, INPUT_PASSWORD); } else if (strcasecmp(type, "radio") == 0) CreateRadio(fs, env, p); else if (strcasecmp(type, "reset") == 0) { CreateCommand(fs, env, p, INPUT_RESET); } else if (strcasecmp(type, "submit") == 0) { CreateCommand(fs, env, p, INPUT_SUBMIT); } return; } /* * HTMLTextareaEnd */ void HTMLTextareaEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv fenv; FormState *fs; char *tatext; InputState *ci; int width, height; XFontStruct *font; int rows, cols; Widget w; HTMLBox box; HTMLObject obj; if ((fenv = HTMLGetIDEnv(env, TAG_FORM)) == NULL) return; fs = (FormState *)fenv->closure; if ((tatext = HTMLGetEnvText(li->mp, env)) == NULL) tatext = NULL; obj = (HTMLObject)GListGetHead(env->slist); w = XtVaCreateWidget("textarea", asciiTextWidgetClass, li->widget, XtNeditType, XtEtextEdit, XtNecho, True, XtNdisplayCaret, True, XtNstring, tatext, NULL); font = GetFont(w); if (font == NULL) height = 20; else height = font->ascent + font->descent + 2; width = XTextWidth(font, "X", 1); if ((rows = MLAttributeToInt(obj->o.p, "rows")) <= 0) rows = 5; height *= rows; if ((cols = MLAttributeToInt(obj->o.p, "cols")) <= 0) cols = 20; width *= cols; ci = CreateInputState(fs, obj->o.p, INPUT_TEXTAREA); box = CreateInputBox(fs->li, env, ci, width, height); ci->w = w; return; } /* * * SELECT input * */ /* * MakeSelectWidget */ static void MakeSelectWidget(li, fs, env) HTMLInfo li; FormState *fs; HTMLEnv env; { InputState *ci; int width, twidth; XFontStruct *font; Widget w, smw; HTMLBox box; OptionState *c; GList oplist = fs->oplist; HTMLObject obj; fs->oplist = NULL; if (GListEmpty(oplist)) return; for (c = (OptionState *)GListGetHead(oplist); c != NULL; c = (OptionState *)GListGetNext(oplist)) { if (c->selected) break; } if (c == NULL) { c = (OptionState *)GListGetHead(oplist); c->selected = true; } w = XtVaCreateWidget("menubutton", menuButtonWidgetClass, li->widget, XtNmenuName, "simplemenu", XtNlabel, c->text, NULL); smw = XtVaCreatePopupShell("simplemenu", simpleMenuWidgetClass, w, XtNwidth, 0, XtNheight, 0, NULL); XtVaGetValues(w, XtNfont, &font, NULL); width = 0; for (c = (OptionState *)GListGetHead(oplist); c != NULL; c = (OptionState *)GListGetNext(oplist)) { c->sme = XtVaCreateManagedWidget(c->text, smeBSBObjectClass, smw, NULL); twidth = XTextWidth(font, c->text, strlen(c->text)); if (width < twidth) width = twidth; } obj = (HTMLObject)GListGetHead(env->slist); ci = CreateInputState(fs, obj->o.p, INPUT_SELECT); box = CreateInputBox(fs->li, env, ci, width + 10, font->ascent + font->descent + 4); ci->w = w; ci->oplist = oplist; if (MLFindAttribute(obj->o.p, "multiple") != NULL) ci->multi = true; for (c = (OptionState *)GListGetHead(oplist); c != NULL; c = (OptionState *)GListGetNext(oplist)) { XtAddCallback(c->sme, XtNcallback, SmeCallback, (XtPointer)ci); } return; } /* * HTMLOptionEnd */ void HTMLOptionEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv fenv; FormState *formstate; OptionState *n; HTMLObject obj; if ((fenv = HTMLGetIDEnv(env, TAG_FORM)) == NULL) return; formstate = (FormState *)fenv->closure; obj = (HTMLObject)GListGetHead(env->slist); n = (OptionState *)MPCGet(li->mp, sizeof(OptionState)); if ((n->text = HTMLGetEnvText(li->mp, env)) == NULL) n->text = ""; n->value = MLFindAttribute(obj->o.p, "value"); if (MLFindAttribute(obj->o.p, "selected") != NULL) n->selected = true; GListAddTail(formstate->oplist, n); return; } /* * HTMLSelectBegin */ void HTMLSelectBegin(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv fenv; FormState *fs; if ((fenv = HTMLGetIDEnv(env, TAG_FORM)) == NULL) return; fs = (FormState *)fenv->closure; if (fs->oplist == NULL) fs->oplist = GListCreateX(li->mp); return; } /* * HTMLSelectEnd */ void HTMLSelectEnd(li, env, p) HTMLInfo li; HTMLEnv env; MLElement p; { HTMLEnv fenv; FormState *fs; if ((fenv = HTMLGetIDEnv(env, TAG_FORM)) == NULL) return; fs = (FormState *)fenv->closure; MakeSelectWidget(li, fs, env); return; } /* * * Image Input stuff * */ /* * FormImageSelectCallback */ static bool FormImageSelectCallback(closure, x, y, action) void *closure; int x, y; char *action; { InputState *ci = (InputState *)closure; ci->x = x; ci->y = y; HandleSubmit(ci->fs->li, ci->fs, ci, action); return(true); } bool FormImageMotionCallback(closure, x, y) void *closure; int x, y; { InputState *ci = (InputState *)closure; HTMLInfo li = ci->fs->li; if (ci->fs->action != NULL) HTMLPrintURL(li, ci->fs->action); return(true); } /* * CreateImage */ void CreateImage(fs, env, p) FormState *fs; HTMLEnv env; MLElement p; { char *url; HTMLInlineInfo ii; InputState *ci; ChimeraRenderHooks orh; if ((url = MLFindAttribute(p, "src")) == NULL) return; memset(&ii, 0, sizeof(ii)); ii.p = p; ii.closure = ci; memset(&orh, 0, sizeof(orh)); orh.select = FormImageSelectCallback; orh.motion = FormImageMotionCallback; ci = CreateInputState(fs, p, INPUT_IMAGE); ci->img = HTMLCreateInline(fs->li, env, url, &ii, &orh, ci); return; } chimera-2.0a19/html/layout.c100600 11610 11610 5125 6677561705 14170 0ustar johnjohn/* * layout.c * * libhtml - HTML->X renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "html.h" /* * HTMLDestroyBox */ void HTMLDestroyBox(li, box) HTMLInfo li; HTMLBox box; { if (box->destroy != NULL) (box->destroy)(li, box); return; } /* * HTMLCreateBox */ HTMLBox HTMLCreateBox(li, env) HTMLInfo li; HTMLEnv env; { HTMLBox box; box = (HTMLBox)MPCGet(li->mp, sizeof(struct HTMLBoxP)); box->env = env; return(box); } /* * HTMLRenderBox */ void HTMLRenderBox(li, r, box) HTMLInfo li; Region r; HTMLBox box; { Region xr; int x, y; unsigned int width, height; XRectangle rec; if (box->render == NULL) return; if (r == NULL) { GUIGetOnScreenDimensions(li->wd, &x, &y, &width, &height); r = XCreateRegion(); rec.x = (short)x; rec.y = (short)y; rec.width = (unsigned short)width; rec.height = (unsigned short)height; XUnionRectWithRegion(&rec, r, r); xr = r; } else xr = NULL; if (XRectInRegion(r, box->x, box->y, box->width, box->height)) { (box->render)(li, box, r); } if (xr != NULL) XDestroyRegion(xr); return; } /* * HTMLLayoutBox */ void HTMLLayoutBox(li, parent, box) HTMLInfo li; HTMLBox parent; HTMLBox box; { myassert(parent->layout != NULL, "Box cannot contain other boxes"); (parent->layout)(li, box, parent); return; } /* * HTMLSetupBox */ void HTMLSetupBox(li, box) HTMLInfo li; HTMLBox box; { HTMLEnv env = box->env; if (env->anchor != NULL) HTMLAddAnchor(li, box, NULL, env->anchor); if (box->setup != NULL) (box->setup)(li, box); return; } /* * HTMLGetBoxWidth */ unsigned int HTMLGetBoxWidth(li, box) HTMLInfo li; HTMLBox box; { myassert(box->maxwidth != NULL, "Box cannot contain other boxes"); return((box->maxwidth)(li, box)); } chimera-2.0a19/plain/ 40700 11610 11610 0 6724372007 12530 5ustar johnjohnchimera-2.0a19/plain/Imakefile100600 11610 11610 347 6677561723 14440 0ustar johnjohn#include <../Common.tmpl> SRCS = plain.c OBJS = plain.o EXTRA_DEFINES = $(CHIMERA_DEFINES) EXTRA_INCLUDES = -I../port -I../mxw -I../common -I../chimera NormalLibraryTarget(xplain, $(OBJS)) DependTarget() install.man:: chimera-2.0a19/plain/plain.c100600 11610 11610 20046 6724333557 14127 0ustar johnjohn/* * plain.c * * libplain - a bad plain text renderer * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * This sucks. */ #include "port_before.h" #include #ifdef HAVE_STDLIB_H #include #endif #include #include "port_after.h" #include "Chimera.h" #include "ChimeraRender.h" #define PLAIN_MARGIN 20 typedef struct { char *s; size_t len; int y; unsigned int width; } LineInfoP, *LineInfo; typedef struct { MemPool mp; GList lines; size_t off; size_t len; byte *data; XFontStruct *font; Window win; Widget w; Display *dpy; GC gc; Pixel fg, bg; ChimeraSink wp; ChimeraResources cres; ChimeraGUI wd; /* Dimensions stuff */ unsigned int lineSpace; unsigned int baseline; unsigned int lineheight; unsigned int width, height; LineInfo searchline; char *searchchar; LineInfo searchcur; char *searchstr; size_t searchlen; } PlainInfoP, *PlainInfo; static LineInfo MakeLine _ArgProto((PlainInfo, char *, size_t)); static void ParsePlainData _ArgProto((PlainInfo)); static int PlainSearch _ArgProto((void *, char *, int)); static LineInfo MakeLine(pi, s, len) PlainInfo pi; char *s; size_t len; { LineInfo li; li = (LineInfo)MPCGet(pi->mp, sizeof(LineInfoP)); li->s = s; li->len = len; li->y = pi->height; pi->height += pi->lineheight; li->width = XTextWidth(pi->font, s, len); if (li->width > pi->width) pi->width = li->width + PLAIN_MARGIN * 2; GUISetDimensions(pi->wd, pi->width, pi->height); XSetFont(pi->dpy, pi->gc, pi->font->fid); XSetForeground(pi->dpy, pi->gc, pi->fg); XDrawString(pi->dpy, pi->win, pi->gc, PLAIN_MARGIN, li->y + pi->baseline, li->s, (int)li->len); /* what to do about this ? */ GListAddTail(pi->lines, li); return(li); } static void ParsePlainData(pi) PlainInfo pi; { char *fcp, *cp, *lcp; MIMEHeader mh; SinkGetData(pi->wp, &(pi->data), &(pi->len), &mh); fcp = (char *)(pi->data + pi->off); lcp = (char *)(pi->data + pi->len); for (cp = fcp; cp < lcp; cp++) { if (*cp == '\r') { MakeLine(pi, fcp, cp - fcp); pi->off = (byte *)cp - pi->data + 1; fcp = cp + 1; if (fcp < lcp && *fcp == '\n') { fcp++; pi->off++; } } else if (*cp == '\n') { MakeLine(pi, fcp, cp - fcp); pi->off = (byte *)cp - pi->data + 1; fcp = cp + 1; } } return; } static void PlainAdd(closure) void *closure; { ParsePlainData((PlainInfo)closure); return; } static void PlainEnd(closure) void *closure; { PlainInfo pi = (PlainInfo)closure; ParsePlainData(pi); if (pi->off < pi->len) { MakeLine(pi, (char *)(pi->data + pi->off), pi->len - pi->off); } pi->height += pi->lineheight; GUISetDimensions(pi->wd, pi->width, pi->height); return; } static bool PlainExpose(closure, x, y, width, height) void *closure; int x, y; unsigned int width, height; { LineInfo li; PlainInfo pi = (PlainInfo)closure; Dimension swidth; XSetFont(pi->dpy, pi->gc, pi->font->fid); XSetForeground(pi->dpy, pi->gc, pi->fg); for (li = (LineInfo)GListGetHead(pi->lines); li != NULL; li = (LineInfo)GListGetNext(pi->lines)) { if (li == pi->searchcur) { XDrawString(pi->dpy, pi->win, pi->gc, PLAIN_MARGIN, li->y + pi->baseline, li->s, pi->searchstr - li->s); swidth = XTextWidth(pi->font, li->s, pi->searchstr - li->s); XSetForeground(pi->dpy, pi->gc, pi->bg); XSetBackground(pi->dpy, pi->gc, pi->fg); XDrawString(pi->dpy, pi->win, pi->gc, PLAIN_MARGIN + swidth, li->y + pi->baseline, pi->searchstr, pi->searchlen); XSetForeground(pi->dpy, pi->gc, pi->fg); XSetBackground(pi->dpy, pi->gc, pi->bg); swidth = XTextWidth(pi->font, pi->searchstr, pi->searchlen); XDrawString(pi->dpy, pi->win, pi->gc, PLAIN_MARGIN + swidth, li->y + pi->baseline, pi->searchstr + pi->searchlen, li->len - (pi->searchstr - li->s) - pi->searchlen); } else { XDrawString(pi->dpy, pi->win, pi->gc, PLAIN_MARGIN, li->y + pi->baseline, li->s, (int)li->len ); /* what to do about this ? */ } } return(true); } static bool PlainMouse(closure, x, y, action) void *closure; int x, y; char *action; { return(true); } static bool PlainMotion(closure, x, y) void *closure; int x, y; { return(true); } /* * PlainQuery */ static byte * PlainQuery(closure, key) void *closure; char *key; { return(NULL); } /* * PlainSearch */ static int PlainSearch(closure, data, mode) void *closure; char *data; int mode; { LineInfo li; PlainInfo pi = (PlainInfo)closure; char *cp, *lcp, *xcp, *dcp, *ldcp; size_t dlen; bool found; dlen = strlen(data); for (li = (LineInfo)GListGetHead(pi->lines); li != NULL; li = (LineInfo)GListGetNext(pi->lines)) { lcp = li->s + li->len; for (cp = li->s; cp < lcp; cp++) { if (*cp == data[0]) { dcp = data; ldcp = data + dlen; found = true; for (xcp = cp; dcp < ldcp && xcp < lcp; dcp++, xcp++) { if (*xcp != *dcp) { found = false; break; } } if (found && dcp == ldcp) { GUISetScrollPosition(pi->wd, 0, -(li->y)); pi->searchcur = li; pi->searchstr = cp; pi->searchlen = dlen; pi->searchline = li; pi->searchchar = xcp; return(0); } } } } return(-1); } /* * PlainDestroy */ static void PlainDestroy(closure) void *closure; { PlainInfo pi = (PlainInfo)closure; MPDestroy(pi->mp); return; } /* * PlainCancel */ static void PlainCancel(closure) void *closure; { return; } /* * PlainInit */ static void * PlainInit(wn, closure, state) ChimeraRender wn; void *closure; void *state; { PlainInfo pi; MemPool mp; char *name; unsigned int width, height; ChimeraSink wp; ChimeraGUI wd; wd = RenderToGUI(wn); wp = RenderToSink(wn); mp = MPCreate(); pi = (PlainInfo)MPCGet(mp, sizeof(PlainInfoP)); pi->mp = mp; pi->wp = wp; pi->lineheight = 40; pi->lines = GListCreateX(mp); pi->wd = wd; pi->cres = RenderToResources(wn); pi->dpy = GUIToDisplay(wd); pi->win = GUIToWindow(wd); pi->gc = DefaultGC(pi->dpy, DefaultScreen(pi->dpy)); pi->lineSpace = 2; name = ResourceGetString(pi->cres, "plain.font"); if (name == NULL) name = "fixed"; if ((pi->font = XLoadQueryFont(pi->dpy, name)) == NULL) { fprintf (stderr, "Could not get default font.\n"); fflush(stderr); return(NULL); } pi->baseline = pi->font->ascent + pi->lineSpace; pi->lineheight = pi->font->ascent + pi->font->descent + pi->lineSpace; pi->height = PLAIN_MARGIN; GUIGetNamedColor(wd, "black", &(pi->fg)); pi->bg = GUIBackgroundPixel(wd); XSetForeground(pi->dpy, pi->gc, pi->fg); GUISetScrollBar(wd, true); if (GUIGetDimensions(wd, &width, &height) == -1) { GUISetDimensions(wd, width, height); /* Now grab the internal dimensions again */ if (GUIGetDimensions(wd, &width, &height) == -1) { return(NULL); } } return(pi); } /* * InitModule_Plain */ int InitModule_Plain(cres) ChimeraResources cres; { ChimeraRenderHooks rh; memset(&rh, 0, sizeof(rh)); rh.class_destroy = NULL; rh.content = "text/plain"; rh.init = PlainInit; rh.add = PlainAdd; rh.end = PlainEnd; rh.destroy = PlainDestroy; rh.search = PlainSearch; rh.query = PlainQuery; rh.cancel = PlainCancel; rh.expose = PlainExpose; rh.select = PlainMouse; rh.motion = PlainMotion; RenderAddHooks(cres, &rh); return(0); } chimera-2.0a19/port/ 40700 11610 11610 0 6724372006 12410 5ustar johnjohnchimera-2.0a19/port/snprintf.c100600 11610 11610 20354 6724332632 14543 0ustar johnjohn/*************************************************************************** * LPRng - An Extended Print Spooler System * * Copyright 1988-1995 Patrick Powell, San Diego State University * papowell@sdsu.edu * See LICENSE for conditions of use. * *************************************************************************** * MODULE: snprintf.c * PURPOSE: LPRng version of printf - absolutely bombproof (hopefully!) **************************************************************************/ /* * * * Removed the 'plp' from function names and may have made other * modifications so if it looks mangled its my fault. * * -john * * */ #include #ifdef HAVE_STDARG_H #include #define HAVE_STDARGS /* let's hope that works everywhere (mj) */ #define VA_LOCAL_DECL va_list ap; #define VA_START(f) va_start(ap, f) #define VA_SHIFT(v,t) ; /* no-op for ANSI */ #define VA_END va_end(ap) #else #ifdef HAVE_VARARGS_H #include #undef HAVE_STDARGS #define VA_LOCAL_DECL va_list ap; #define VA_START(f) va_start(ap) /* f is ignored! */ #define VA_SHIFT(v,t) v = va_arg(ap,t) #define VA_END va_end(ap) #else XX ** NO VARARGS ** XX #endif #endif #ifdef HAVE_STRING_H #include #endif #include "port_after.h" /* * dopr(): poor man's version of doprintf */ static void dopr( char *buffer, const char *format, va_list args ); static void fmtstr( char *value, int ljust, int len, int zpad, int precision ); static void fmtnum( long value, int base, int dosign, int ljust, int len, int zpad, int precision ); static void fmtdouble( int fmt, double value, int ljust, int len, int zpad, int precision ); static void dostr( char * ); static char *output; static void dopr_outch( int c ); static char *end; /************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh. This sort of thing is always nasty do deal with. Note that * the version here does not include floating point... * * plp_snprintf() is used instead of sprintf() as it does limit checks * for string length. This covers a nasty loophole. * * The other functions are there to prevent NULL pointers from * causing nast effects. **************************************************************/ int vsnprintf(char *str, size_t count, const char *fmt, va_list args) { str[0] = 0; end = str+count-1; dopr( str, fmt, args ); if( count>0 ){ end[0] = 0; } return(strlen(str)); } /* VARARGS3 */ #ifdef HAVE_STDARGS int snprintf (char *str,size_t count,const char *fmt,...) #else int snprintf (va_alist) va_dcl #endif { #ifndef HAVE_STDARGS char *str; size_t count; char *fmt; #endif VA_LOCAL_DECL VA_START (fmt); VA_SHIFT (str, char *); VA_SHIFT (count, size_t ); VA_SHIFT (fmt, char *); (void) vsnprintf ( str, count, fmt, ap); VA_END; return( strlen( str ) ); } static void dopr( char *buffer, const char *format, va_list args ) { int ch; long value; int longflag = 0; char *strvalue; int ljust; int len; int zpad; int precision; int set_precision; double dval; output = buffer; while( (ch = *format++) ){ switch( ch ){ case '%': ljust = len = zpad = 0; precision = -1; set_precision = 0; nextch: ch = *format++; switch( ch ){ case 0: dostr( "**end of format**" ); return; case '-': ljust = 1; goto nextch; case '.': set_precision = 1; precision = 0; goto nextch; case '*': len = va_arg( args, int ); goto nextch; case '0': /* set zero padding if len not set */ if(len==0 && set_precision == 0 ) zpad = '0'; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if( set_precision ){ precision = precision*10 + ch - '0'; } else { len = len*10 + ch - '0'; } goto nextch; case 'l': longflag = 1; goto nextch; case 'u': case 'U': /*fmtnum(value,base,dosign,ljust,len, zpad, precision) */ if( longflag ){ value = va_arg( args, long ); } else { value = va_arg( args, int ); } fmtnum( value, 10,0, ljust, len, zpad, precision ); break; case 'o': case 'O': /*fmtnum(value,base,dosign,ljust,len, zpad, precision) */ if( longflag ){ value = va_arg( args, long ); } else { value = va_arg( args, int ); } fmtnum( value, 8,0, ljust, len, zpad, precision ); break; case 'd': case 'D': if( longflag ){ value = va_arg( args, long ); } else { value = va_arg( args, int ); } fmtnum( value, 10,1, ljust, len, zpad, precision ); break; case 'x': if( longflag ){ value = va_arg( args, long ); } else { value = va_arg( args, int ); } fmtnum( value, 16,0, ljust, len, zpad, precision ); break; case 'X': if( longflag ){ value = va_arg( args, long ); } else { value = va_arg( args, int ); } fmtnum( value,-16,0, ljust, len, zpad, precision ); break; case 's': strvalue = va_arg( args, char *); fmtstr( strvalue,ljust,len, zpad, precision ); break; case 'c': ch = va_arg( args, int ); { char b[2]; b[0] = ch; b[1] = 0; fmtstr( b,ljust,len, zpad, precision ); break; } break; case 'f': case 'g': dval = va_arg( args, double ); fmtdouble( ch, dval,ljust,len, zpad, precision ); break; case '%': dopr_outch( ch ); continue; default: dostr( "???????" ); } longflag = 0; break; default: dopr_outch( ch ); break; } } *output = 0; } /* * Format '%[-]len[.precision]s' * - = left justify (ljust) * len = minimum length * precision = numbers of chars in string to use */ static void fmtstr( char *value, int ljust, int len, int zpad, int precision ) { int padlen, strlen, i; /* amount to pad */ if( value == 0 ){ value = ""; } if( precision > 0 ){ strlen = precision; } else { for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */ } padlen = len - strlen; if( padlen < 0 ) padlen = 0; if( ljust ) padlen = -padlen; while( padlen > 0 ) { dopr_outch( ' ' ); --padlen; } /* output characters */ for( i = 0; i < strlen; ++i ) dopr_outch(value[i]); while( padlen < 0 ) { dopr_outch( ' ' ); ++padlen; } } static void fmtnum( long value, int base, int dosign, int ljust, int len, int zpad, int precision ) { int signvalue = 0; unsigned long uvalue; char convert[20]; int place = 0; int padlen = 0; /* amount to pad */ int caps = 0; /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", value, base, dosign, ljust, len, zpad )); */ uvalue = value; if( dosign ){ if( value < 0 ) { signvalue = '-'; uvalue = -value; } } if( base < 0 ){ caps = 1; base = -base; } do{ convert[place++] = (caps? "0123456789ABCDEF":"0123456789abcdef") [uvalue % (unsigned)base ]; uvalue = (uvalue / (unsigned)base ); }while(uvalue); convert[place] = 0; padlen = len - place; if( padlen < 0 ) padlen = 0; if( ljust ) padlen = -padlen; /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n", convert,place,signvalue,padlen)); */ if( zpad && padlen > 0 ){ if( signvalue ){ dopr_outch( signvalue ); --padlen; signvalue = 0; } while( padlen > 0 ){ dopr_outch( zpad ); --padlen; } } while( padlen > 0 ) { dopr_outch( ' ' ); --padlen; } if( signvalue ) dopr_outch( signvalue ); while( place > 0 ) dopr_outch( convert[--place] ); while( padlen < 0 ){ dopr_outch( ' ' ); ++padlen; } } static void fmtdouble( int fmt, double value, int ljust, int len, int zpad, int precision ) { char convert[128]; char fmtstr[128]; int l; if( len == 0 ) len = 10; if( len > sizeof(convert) - 10 ){ len = sizeof(convert) - 10; } if( precision > sizeof(convert) - 10 ){ precision = sizeof(convert) - 10; } if( precision > len ) precision = len; strcpy( fmtstr, "%" ); if( ljust ) strcat(fmtstr, "-" ); if( len ){ sprintf( fmtstr+strlen(fmtstr), "%d", len ); } if( precision > 0 ){ sprintf( fmtstr+strlen(fmtstr), ".%d", precision ); } l = strlen( fmtstr ); fmtstr[l] = fmt; fmtstr[l+1] = 0; sprintf( convert, fmtstr, value ); dostr( convert ); } static void dostr( char *str ) { while(*str) dopr_outch(*str++); } static void dopr_outch( int c ) { if( end == 0 || output < end ){ *output++ = c; } } chimera-2.0a19/port/Imakefile100600 11610 11610 1037 6677561743 14340 0ustar johnjohn#include <../Common.tmpl> #ifdef NEED_MEMMOVE SRC1 = memmove.c OBJ1 = memmove.o #endif #ifdef NEED_GETCWD SRC2 = getcwd.c OBJ2 = getcwd.o #endif #ifdef NEED_STRSTUFF SRC3 = strcasecmp.c strtol.c strstr.c strtoul.c OBJ3 = strcasecmp.o strtol.o strstr.o strtoul.o #endif #ifndef HAVE_SNPRINTF SRC5 = snprintf.c OBJ5 = snprintf.o #endif SRCS = junk.c $(SRC1) $(SRC2) $(SRC3) $(SRC5) OBJS = junk.o $(OBJ1) $(OBJ2) $(OBJ3) $(OBJ5) EXTRA_DEFINES = $(CHIMERA_DEFINES) EXTRA_INCLUDES = -I./ NormalLibraryTarget(xport, $(OBJS)) DependTarget() chimera-2.0a19/port/port_after.h100600 11610 11610 5736 6724332600 15034 0ustar johnjohn/* * port_after.h * * Copyright (c) 1996-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Should be included after all of the "system" header files. */ #ifndef __PORT_AFTER_H__ #define __PORT_AFTER_H__ 1 #include #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_LIMITS_H #include #endif #ifdef __QNX__ #include #include /* for snprintf(), vsnprintf() */ #define strcasecmp(s1, s2) stricmp(s1, s2) #define strncasecmp(s1, s2, n) strnicmp(s1, s2, n) #endif #ifdef __EMX__ #define strcasecmp(s1, s2) stricmp(s1, s2) #define strncasecmp(s1, s2, n) strnicmp(s1, s2, n) #endif #ifndef HAVE_SIZE_T typedef unsigned long size_t; #endif #ifndef HAVE_SSIZE_T typedef long ssize_t; #endif /* * ANSI-C stuff. Snarfed from xloadimage. */ #ifdef __STDC__ #if !defined(_ArgProto) #define _ArgProto(ARGS) ARGS #endif #else /* !__STDC__ */ /* "const" is an ANSI thing */ #if !defined(const) #define const #endif #if !defined(_ArgProto) #define _ArgProto(ARGS) () #endif #endif /* __STDC__ */ /* * If you have an old version of C++ without bool, you'll have to add * the ifdef here */ #ifndef __cplusplus #if !defined(bool_DEFINED) && !defined(true_DEFINED) && !defined(false_DEFINED) #define bool_DEFINED 1 #define true_DEFINED 1 #define false_DEFINED 1 typedef enum { false = 0, true = 1 } bool; #endif #ifndef bool_DEFINED #define bool_DEFINED 1 typedef int bool; #endif #ifndef true_DEFINED #define true_DEFINED 1 #define true 1 #endif #ifndef false_DEFINED #define false_DEFINED 1 #define false 0 #endif #endif /* __cplusplus */ #ifndef MAX #define MAX(a,b) ((a) < (b) ? (b) : (a)) #endif #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif /* * should be in limits.h */ #ifndef CHAR_BITS #define CHAR_BITS 8 #endif #ifndef byte_DEFINED #define byte_DEFINED 1 typedef unsigned char byte; #endif #ifndef word_DEFINED #define word_DEFINED 1 typedef unsigned long word; #endif /* * FILENAME_MAX apparently doesn't cut it. I don't see a decent * alternative. Invent one. If it clashes or isn't long enough then * try again. Repeat as necessary. */ #define MAXFILENAMELEN 1024 #define isspace8(a) ((a) < 33 && (a) >= 0) #ifndef HAVE_SNPRINTF #ifdef HAVE_STDARG_H int snprintf _ArgProto((char *, size_t, const char *, ...)); #endif #endif #endif chimera-2.0a19/port/getcwd.c100600 11610 11610 4043 6677561746 14153 0ustar johnjohn/* * getcwd.c -- * * This file provides an implementation of the getcwd procedure * that uses getwd, for systems with getwd but without getcwd. * * Copyright (c) 1993 The Regents of the University of California. * All rights reserved. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the * above copyright notice and the following two paragraphs appear in * all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ #ifndef lint static char rcsid[] = "$Header: /user6/ouster/tcl/compat/RCS/getcwd.c,v 1.2 93/07/12 14:00:59 ouster Exp $ SPRITE (Berkeley)"; #endif /* not lint */ #include #include #include extern char *getwd(); extern int errno; char * getcwd(buf, size) char *buf; /* Where to put path for current directory. */ int size; /* Number of bytes at buf. */ { char realBuffer[MAXFILENAMELEN+1]; int length; if (getwd(realBuffer) == NULL) { /* * There's not much we can do besides guess at an errno to * use for the result (the error message in realBuffer isn't * much use...). */ errno = EACCES; return NULL; } length = strlen(realBuffer); if (length >= size) { errno = ERANGE; return NULL; } strcpy(buf, realBuffer); return buf; } chimera-2.0a19/port/strstr.c100600 11610 11610 5000 6677561750 14224 0ustar johnjohn/* * strstr.c -- * * Source code for the "strstr" library routine. * * Copyright (c) 1988-1993 The Regents of the University of California. * All rights reserved. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the * above copyright notice and the following two paragraphs appear in * all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ #ifndef lint static char rcsid[] = "$Header: /user6/ouster/tcl/compat/RCS/strstr.c,v 1.2 93/03/19 15:25:40 ouster Exp $ SPRITE (Berkeley)"; #endif /* not lint */ /* *---------------------------------------------------------------------- * * strstr -- * * Locate the first instance of a substring in a string. * * Results: * If string contains substring, the return value is the * location of the first matching instance of substring * in string. If string doesn't contain substring, the * return value is 0. Matching is done on an exact * character-for-character basis with no wildcards or special * characters. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * strstr(string, substring) register char *string; /* String to search. */ char *substring; /* Substring to try to find in string. */ { register char *a, *b; /* First scan quickly through the two strings looking for a * single-character match. When it's found, then compare the * rest of the substring. */ b = substring; if (*b == 0) { return string; } for ( ; *string != 0; string += 1) { if (*string != *b) { continue; } a = string; while (1) { if (*b == 0) { return string; } if (*a++ != *b++) { break; } } b = substring; } return (char *) 0; } chimera-2.0a19/port/strtol.c100600 11610 11610 5533 6677561751 14226 0ustar johnjohn/* * strtol.c -- * * Source code for the "strtol" library procedure. * * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the * above copyright notice and the following two paragraphs appear in * all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ #ifndef lint static char rcsid[] = "$Header: /user6/ouster/tcl/compat/RCS/strtol.c,v 1.2 93/03/19 15:25:43 ouster Exp $ SPRITE (Berkeley)"; #endif /* not lint */ #include /* *---------------------------------------------------------------------- * * strtol -- * * Convert an ASCII string into an integer. * * Results: * The return value is the integer equivalent of string. If endPtr * is non-NULL, then *endPtr is filled in with the character * after the last one that was part of the integer. If string * doesn't contain a valid integer value, then zero is returned * and *endPtr is set to string. * * Side effects: * None. * *---------------------------------------------------------------------- */ long int strtol(string, endPtr, base) char *string; /* String of ASCII digits, possibly * preceded by white space. For bases * greater than 10, either lower- or * upper-case digits may be used. */ char **endPtr; /* Where to store address of terminating * character, or NULL. */ int base; /* Base for conversion. Must be less * than 37. If 0, then the base is chosen * from the leading characters of string: * "0x" means hex, "0" means octal, anything * else means decimal. */ { register char *p; int result; /* * Skip any leading blanks. */ p = string; while (isspace8(*p)) { p += 1; } /* * Check for a sign. */ if (*p == '-') { p += 1; result = -(strtoul(p, endPtr, base)); } else { if (*p == '+') { p += 1; } result = strtoul(p, endPtr, base); } if ((result == 0) && (endPtr != 0) && (*endPtr == p)) { *endPtr = string; } return result; } chimera-2.0a19/port/junk.c100600 11610 11610 102 6677561752 13612 0ustar johnjohn/* * junk.c * * placeholder */ void chimera_placeholder() { } chimera-2.0a19/port/strcasecmp.c100600 11610 11610 11503 6677561754 15060 0ustar johnjohn/* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)strcasecmp.c 5.10 (Berkeley) 1/26/91"; #endif /* LIBC_SCCS and not lint */ typedef unsigned char u_char; /* * This array is designed for mapping upper and lower case letter * together for a case independent comparison. The mappings are * based upon ascii character sequences. */ static const u_char charmap[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; int strcasecmp(s1, s2) const char *s1, *s2; { register const u_char *cm = charmap, *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; while (cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return (0); return (cm[*us1] - cm[*--us2]); } int strncasecmp(s1, s2, n) const char *s1, *s2; register size_t n; { if (n != 0) { register const u_char *cm = charmap, *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; do { if (cm[*us1] != cm[*us2++]) return (cm[*us1] - cm[*--us2]); if (*us1++ == '\0') break; } while (--n != 0); } return (0); } chimera-2.0a19/port/strtoul.c100600 11610 11610 11536 6677561756 14440 0ustar johnjohn/* * strtoul.c -- * * Source code for the "strtoul" library procedure. * * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the * above copyright notice and the following two paragraphs appear in * all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ #ifndef lint static char rcsid[] = "$Header: /user6/ouster/tcl/compat/RCS/strtoul.c,v 1.3 93/03/19 15:25:41 ouster Exp $ SPRITE (Berkeley)"; #endif /* not lint */ #include /* * The table below is used to convert from ASCII digits to a * numerical equivalent. It maps from '0' through 'z' to integers * (100 for non-digit characters). */ static char cvtIn[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */ 100, 100, 100, 100, 100, 100, 100, /* punctuation */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'Z' */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 100, 100, 100, 100, 100, 100, /* punctuation */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'z' */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}; /* *---------------------------------------------------------------------- * * strtoul -- * * Convert an ASCII string into an integer. * * Results: * The return value is the integer equivalent of string. If endPtr * is non-NULL, then *endPtr is filled in with the character * after the last one that was part of the integer. If string * doesn't contain a valid integer value, then zero is returned * and *endPtr is set to string. * * Side effects: * None. * *---------------------------------------------------------------------- */ unsigned long int strtoul(string, endPtr, base) char *string; /* String of ASCII digits, possibly * preceded by white space. For bases * greater than 10, either lower- or * upper-case digits may be used. */ char **endPtr; /* Where to store address of terminating * character, or NULL. */ int base; /* Base for conversion. Must be less * than 37. If 0, then the base is chosen * from the leading characters of string: * "0x" means hex, "0" means octal, anything * else means decimal. */ { register char *p; register unsigned long int result = 0; register unsigned digit; int anyDigits = 0; /* * Skip any leading blanks. */ p = string; while (isspace8(*p)) { p += 1; } /* * If no base was provided, pick one from the leading characters * of the string. */ if (base == 0) { if (*p == '0') { p += 1; if (*p == 'x') { p += 1; base = 16; } else { /* * Must set anyDigits here, otherwise "0" produces a * "no digits" error. */ anyDigits = 1; base = 8; } } else base = 10; } else if (base == 16) { /* * Skip a leading "0x" from hex numbers. */ if ((p[0] == '0') && (p[1] == 'x')) { p += 2; } } /* * Sorry this code is so messy, but speed seems important. Do * different things for base 8, 10, 16, and other. */ if (base == 8) { for ( ; ; p += 1) { digit = *p - '0'; if (digit > 7) { break; } result = (result << 3) + digit; anyDigits = 1; } } else if (base == 10) { for ( ; ; p += 1) { digit = *p - '0'; if (digit > 9) { break; } result = (10*result) + digit; anyDigits = 1; } } else if (base == 16) { for ( ; ; p += 1) { digit = *p - '0'; if (digit > ('z' - '0')) { break; } digit = cvtIn[digit]; if (digit > 15) { break; } result = (result << 4) + digit; anyDigits = 1; } } else { for ( ; ; p += 1) { digit = *p - '0'; if (digit > ('z' - '0')) { break; } digit = cvtIn[digit]; if (digit >= base) { break; } result = result*base + digit; anyDigits = 1; } } /* * See if there were any digits at all. */ if (!anyDigits) { p = string; } if (endPtr != 0) { *endPtr = p; } return result; } chimera-2.0a19/port/memmove.c100600 11610 11610 3164 6677561757 14350 0ustar johnjohn/* * memmove.c * * grabbed from X11R6 Xbsd/Berklib.c */ /* Copyright (c) 1987 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. */ char *memmove (b1, b2, length) register char *b1, *b2; register int length; { char *sb1 = b1; if (b2 < b1) { b1 += length; b2 += length; while (length--) *--b1 = *--b2; } else { while (length--) *b1++ = *b2++; } return sb1; } chimera-2.0a19/port/port_before.h100600 11610 11610 550 6677561760 15164 0ustar johnjohn/* * port_before.h * * Should be the first header file included. Could eventually contain * the HAVE_* defines to clean up the command line if necessary (maybe * useful to clean up the Common.tmpl.dist file). Maybe useful for * other weird situations. Inspired by the bind distribution. */ #ifdef __PORT_BEFORE_H__ #define __PORT_BEFORE_H__ #endif chimera-2.0a19/proto/ 40700 11610 11610 0 6724372007 12570 5ustar johnjohnchimera-2.0a19/proto/Imakefile100600 11610 11610 377 6677561771 14506 0ustar johnjohn#include <../Common.tmpl> SRCS = file.c http.c ftp.c mailto.c OBJS = file.o http.o ftp.o mailto.o INCLUDES = -I. -I../port -I../common -I../chimera EXTRA_DEFINES = $(CHIMERA_DEFINES) NormalLibraryTarget(xproto, $(OBJS)) DependTarget() install.man:: chimera-2.0a19/proto/http.c100600 11610 11610 67613 6724334205 14045 0ustar johnjohn/* * http.c * * Copyright (C) 1993-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "Chimera.h" #include "ChimeraStream.h" #include "ChimeraAuth.h" #include "ChimeraSource.h" #include "mime.h" /* * OK, this is a little bit weird. The context that is passed is * actually the address of the address of the context. This is * because once a context is returned by HTTPInit it can't be * changed (at least the way this circus works). Its convienent * to be able to destroy the context when a new connection is made * because of authorization stuff or a redirect occurs. */ /* * Size of chunks to allocate while reading. */ #define CHUNKSIZE 16384 #define PRINT_RATE 10 #define MSGLEN 1024 #define HM_OPEN 0 #define HM_RU 1 #define HM_RK 2 #define HM_DONE 3 #define HM_SEND 4 #define HM_WAITING 5 static struct http_message { char *name; char *def; } http_messages[] = { { "http.open", "Connecting to " }, { "http.read_unknown", " bytes read so far." }, { "http.read_known", " bytes remaining." }, { "http.done", "HTTP read finished." }, { "http.send", "Sending request..." }, { "http.waiting", "Waiting for a response from " }, { NULL, NULL }, }; typedef struct { char *username; char *password; char *hostname; char *realm; char *type; int port; } HTTPPassword; typedef struct { MemPool mp; char *msg[sizeof(http_messages) / sizeof(http_messages[0])]; size_t mlen; GList passwords; /* username/password/realm cache */ } HTTPClass; typedef struct { MemPool mp, rmp; ChimeraSource ws; ChimeraResources cres; /* addressing stuff */ ChimeraRequest *wr; /* request addresses */ char *url; /* URL to use for request */ URLParts *up; /* URLParts to use for request */ URLParts *pup; /* proxy server */ /* other stuff */ HTTPClass *hc; char msgbuf[MSGLEN]; int nline; int rcount; /* Information from HTTP status line */ int status; int major; int minor; /* authorization stuff */ ChimeraAuth wa; HTTPPassword *hp; char *auth_type; /* used for the Auth callback */ char *realm; /* used for the Auth callback */ ChimeraStream ios; /* Information about the data received. */ byte *b; size_t blen; size_t bsize; size_t bmax; size_t doff; /* offset to data beyond header */ MIMEHeader mh; } HTTPInfo; static int uuencode _ArgProto((unsigned char *, unsigned int, char *)); static byte *HTTPBuildRequest _ArgProto((HTTPInfo *, ssize_t *)); static int HTTPCreateInfo _ArgProto((HTTPInfo **, ChimeraSource, ChimeraRequest *, HTTPClass *, URLParts *, URLParts *, HTTPPassword *)); static void HTTPCancel _ArgProto((void *)); static void *HTTPInit _ArgProto((ChimeraSource, ChimeraRequest *, void *)); static void HTTPDestroy _ArgProto((void *)); static void HTTPDestroyInfo _ArgProto((HTTPInfo *)); static void HTTPGetData _ArgProto((void *, byte **, size_t *, MIMEHeader *)); static byte *HTTPRequest_Auth _ArgProto((HTTPInfo *, ssize_t *)); static byte *HTTPRequest_UserAgent _ArgProto((HTTPInfo *, ssize_t *)); static byte *HTTPRequest_AcceptLang _ArgProto((HTTPInfo *, ssize_t *)); static byte *HTTPRequest_Accept _ArgProto((HTTPInfo *, ssize_t *)); static byte *HTTPRequest_Pragma _ArgProto((HTTPInfo *, ssize_t *)); static byte *HTTPRequest_Method _ArgProto((HTTPInfo *, ssize_t *)); static byte *HTTPRequest_Host _ArgProto((HTTPInfo *, ssize_t *)); static byte *HTTPRequest_Data1 _ArgProto((HTTPInfo *, ssize_t *)); static byte *HTTPRequest_Data2 _ArgProto((HTTPInfo *, ssize_t *)); static void HTTPFailure _ArgProto((HTTPInfo *)); static void HTTPRead _ArgProto((HTTPInfo **, ChimeraStreamCallback)); void HTTPReadHeader _ArgProto((ChimeraStream, ssize_t, void *)); static void HTTPReadData _ArgProto((ChimeraStream, ssize_t, void *)); static void HTTPReadUnknown _ArgProto((ChimeraStream, ssize_t, void *)); static void HTTPRequestDone _ArgProto((ChimeraStream, ssize_t, void *)); static void HTTPClassDestroy _ArgProto((void *)); void InitModule_HTTP _ArgProto((ChimeraResources)); static char *HTTPGetFilename _ArgProto((HTTPInfo *)); static int HTTPCheckHeader _ArgProto((HTTPInfo **)); HTTPPassword *HTTPFindPassword _ArgProto((HTTPInfo *, char *, char *, int)); HTTPPassword *HTTPAddPassword _ArgProto((HTTPInfo *, char *, char *, char *, char *, char *, int)); static void HTTPAuthCallback _ArgProto((void *, char *, char *)); /* * crap for uuencode */ static char six2pr[64] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 'a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z', '0','1','2','3','4','5','6','7','8','9','+','/' }; /* * uuencode * * I snarfed this code from some version of libwww. * * ACKNOWLEDGEMENT: * This code is taken from rpem distribution, and was originally * written by Mark Riordan. * * AUTHORS: * MR Mark Riordan riordanmr@clvax1.cl.msu.edu * AL Ari Luotonen luotonen@dxcern.cern.ch * */ static int uuencode(bufin, nbytes, bufcoded) unsigned char *bufin; unsigned int nbytes; char *bufcoded; { /* ENC is the basic 1 character encoding function to make a char printing */ #define ENC(c) six2pr[c] register char *outptr = bufcoded; unsigned int i; for (i=0; i> 2); /* c1 */ *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /*c2*/ *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03));/*c3*/ *(outptr++) = ENC(bufin[2] & 077); /* c4 */ bufin += 3; } /* If nbytes was not a multiple of 3, then we have encoded too * many characters. Adjust appropriately. */ if (i == nbytes + 1) { /* There were only 2 bytes in that last group */ outptr[-1] = '='; } else if (i == nbytes + 2) { /* There was only 1 byte in that last group */ outptr[-1] = '='; outptr[-2] = '='; } *outptr = '\0'; return(outptr - bufcoded); } /* * HTTPAuthCallback */ static void HTTPAuthCallback(closure, username, password) void *closure; char *username; char *password; { HTTPInfo **hip = (HTTPInfo **)closure; HTTPInfo *hi = *hip; HTTPPassword *hp; if (username == NULL || password == NULL) { HTTPCancel(hip); return; } hp = HTTPAddPassword(hi, username, password, hi->realm, hi->auth_type, hi->up->hostname, hi->up->port); if (HTTPCreateInfo(hip, hi->ws, hi->wr, hi->hc, hi->up, hi->pup, hp) == -1) { HTTPFailure(hi); } HTTPDestroyInfo(hi); return; } /* * HTTPFindPassword */ HTTPPassword * HTTPFindPassword(hi, realm, hostname, port) HTTPInfo *hi; char *realm; char *hostname; int port; { HTTPPassword *hp; port = port == 0 ? 80:port; for (hp = (HTTPPassword *)GListGetHead(hi->hc->passwords); hp != NULL; hp = (HTTPPassword *)GListGetNext(hi->hc->passwords)) { if (strlen(realm) == strlen(hp->realm) && strcmp(realm, hp->realm) == 0 && strlen(hostname) == strlen(hp->hostname) && strcasecmp(hostname, hp->hostname) == 0 && port == hp->port) { return(hp); } } return(NULL); } /* * HTTPAddPassword */ HTTPPassword * HTTPAddPassword(hi, username, password, realm, type, hostname, port) HTTPInfo *hi; char *username; char *password; char *realm; char *type; char *hostname; int port; { HTTPPassword *hp; MemPool mp; if (username == NULL) return(NULL); if (hostname == NULL) return(NULL); mp = hi->hc->mp; hp = (HTTPPassword *)MPCGet(mp, sizeof(HTTPPassword)); hp->username = MPStrDup(mp, username); if (password != NULL) hp->password = MPStrDup(mp, password); else hp->password = MPStrDup(mp, ""); /* * Probably shouldn't have defaults here. Should just error out. */ if (realm != NULL) hp->realm = MPStrDup(mp, realm); else hp->realm = MPStrDup(mp, ""); if (type != NULL) hp->type = MPStrDup(mp, type); else hp->type = MPStrDup(mp, "basic"); hp->hostname = MPStrDup(mp, hostname); hp->port = port == 0 ? 80:port; GListAddHead(hi->hc->passwords, hp); return(hp); } /* * HTTPRequest_Auth */ static byte * HTTPRequest_Auth(hi, len) HTTPInfo *hi; ssize_t *len; { char *t, *line = NULL; const char *authfield = "Authorization: "; char *username; char *password; URLParts *up; if (hi->hp == NULL) return(NULL); if (hi->hp->type == NULL || strcasecmp(hi->hp->type, "basic") != 0) { return(NULL); } username = hi->hp->username; password = hi->hp->password; up = hi->up; line = (char *)MPGet(hi->rmp, strlen(authfield) + 2 * strlen(username) + 2 * strlen(":") + 2 * strlen(password != NULL ? password:"") + 2 * strlen(hi->hp->type) + strlen("\r\n") + 1); strcpy(line, username); if (password != NULL) { strcat(line, ":"); strcat(line, password); } t = (char *)MPGet(hi->rmp, strlen(line) * 2); uuencode(line, strlen(line), t); strcpy(line, authfield); strcat(line, hi->hp->type); strcat(line, " "); strcat(line, t); strcat(line, "\r\n"); if (line != NULL) *len = strlen(line); return((byte *)line); } /* * HTTPRequest_UserAgent */ static byte * HTTPRequest_UserAgent(hi, len) HTTPInfo *hi; ssize_t *len; { char *ua; char *line = NULL; const char *uaformat = "User-agent: %s\r\n"; size_t linelen; ua = ResourceGetString(hi->cres, "http.userAgent"); if (ua == NULL) return(NULL); linelen = strlen(uaformat) + strlen(ua) + 1; line = (char *)MPGet(hi->rmp, linelen); snprintf (line, linelen, uaformat, ua); if (line != NULL) *len = strlen(line); return((byte *)line); } /* * HTTPRequest_AcceptLang */ static byte * HTTPRequest_AcceptLang(hi, len) HTTPInfo *hi; ssize_t *len; { char *line; char *acc; const char *accformat = "Accept-Language: %s\r\n"; size_t linelen; if ((acc = ResourceGetString(hi->cres, "http.acceptLanguage")) != NULL) { linelen = strlen(accformat) + strlen(acc) + 1; line = (char *)MPGet(hi->rmp, linelen); snprintf (line, linelen, accformat, acc); *len = strlen(line); return((byte *)line); } return(NULL); } /* * HTTPRequest_Accept */ static byte * HTTPRequest_Accept(hi, len) HTTPInfo *hi; ssize_t *len; { GList list; char *nr; size_t rlen; size_t delimlen; char *line = NULL; const char *accfield = "Accept: "; const char *delim = ","; if (hi->wr->contents == NULL) line = "Accept: */*\r\n"; else { list = hi->wr->contents; delimlen = strlen(delim); rlen = 0; for (nr = (char *)GListGetHead(list); nr != NULL; nr = (char *)GListGetNext(list)) { rlen += strlen(nr) + delimlen; } line = (char *)MPGet(hi->rmp, strlen(accfield) + rlen + strlen("\r\n") + 1); strcpy(line, accfield); for (nr = (char *)GListGetHead(list); nr != NULL; ) { strcat(line, nr); if ((nr = GListGetNext(list)) != NULL) strcat(line, delim); } strcat(line, "\r\n"); } if (line != NULL) *len = strlen(line); return((byte *)line); } /* * HTTPRequest_Pragma */ static byte * HTTPRequest_Pragma(hi, len) HTTPInfo *hi; ssize_t *len; { const char *pragma = "Pragma: no-cache\r\n"; if (hi->wr->reload) { *len = strlen(pragma); return((byte *)MPStrDup(hi->rmp, pragma)); } return(NULL); } /* * HTTPRequest_Method */ static byte * HTTPRequest_Method(hi, len) HTTPInfo *hi; ssize_t *len; { char *filename; char *line = NULL; ChimeraRequest *wr; const char *getformat1 = "GET %s HTTP/1.0\r\n"; const char *getformat2 = "GET %s%s%s HTTP/1.0\r\n"; const char *postformat = "POST %s HTTP/1.0\r\n"; size_t linelen; filename = HTTPGetFilename(hi); wr = hi->wr; if (wr->input_method == NULL || strcasecmp(wr->input_method, "GET") == 0) { if (wr->input_data != NULL && wr->input_len > 0) { linelen = strlen(getformat2) + wr->input_len + strlen(filename) + strlen("?") + 1; line = (char *)MPGet(hi->rmp, linelen); snprintf (line, linelen, getformat2, filename, "?", wr->input_data); } else { linelen = strlen(getformat1) + strlen(filename) + 1; line = (char *)MPGet(hi->rmp, linelen); snprintf (line, linelen, getformat1, filename); } } else if (strcasecmp(wr->input_method, "POST") == 0) { linelen = strlen(postformat) + strlen(filename) + 1; line = (char *)MPGet(hi->rmp, linelen); snprintf (line, linelen, postformat, filename); } else { *len = -1; return(NULL); } if (line != NULL) *len = strlen(line); return((byte *)line); } /* * HTTPRequest_Host */ static byte * HTTPRequest_Host(hi, len) HTTPInfo *hi; ssize_t *len; { char *host; int port; char *line; size_t linelen; host = hi->up->hostname; port = hi->up->port; linelen = strlen(host) + strlen("Host:") + 50; line = (char *)MPCGet(hi->rmp, linelen); if (port == 0) snprintf (line, linelen, "Host: %s\r\n", host); else snprintf (line, linelen, "Host: %s:%d\r\n", host, port); if (line != NULL) *len = strlen(line); return((byte *)line); } /* * HTTPRequest_Data1 */ static byte * HTTPRequest_Data1(hi, len) HTTPInfo *hi; ssize_t *len; { char *line = NULL; const char *format = "Content-type: %s\r\nContent-length: %d\r\n"; ChimeraRequest *wr = hi->wr; size_t linelen; if (wr->input_method == NULL || strcasecmp(wr->input_method, "POST") != 0) { return(NULL); } if (wr->input_data != NULL && wr->input_len > 0 && wr->input_type != NULL) { linelen = strlen(format) + strlen(wr->input_type) + 101; line = (char *)MPGet(hi->rmp, linelen); snprintf (line, linelen, format, wr->input_type, wr->input_len); } if (line != NULL) *len = strlen(line); return((byte *)line); } /* * HTTPRequest_Data2 */ static byte * HTTPRequest_Data2(hi, len) HTTPInfo *hi; ssize_t *len; { ChimeraRequest *wr = hi->wr; if (wr->input_method == NULL || strcasecmp(wr->input_method, "POST") != 0) { return(NULL); } if (wr->input_data != NULL && wr->input_len > 0 && wr->input_type != NULL) { *len = wr->input_len; return(wr->input_data); } return(NULL); } /* * HTTPBuildRequest * * This became less efficient but easier to hack, I think. */ static byte * HTTPBuildRequest(hi, len) HTTPInfo *hi; ssize_t *len; { byte *line = NULL; do { *len = 0; if (hi->nline == 0) line = HTTPRequest_Method(hi, len); else if (hi->nline == 1) line = HTTPRequest_Host(hi, len); else if (hi->nline == 2) line = HTTPRequest_UserAgent(hi, len); else if (hi->nline == 3) line = HTTPRequest_Accept(hi, len); else if (hi->nline == 4) line = HTTPRequest_AcceptLang(hi, len); else if (hi->nline == 5) line = HTTPRequest_Pragma(hi, len); else if (hi->nline == 6) line = HTTPRequest_Auth(hi, len); /* this must be last */ else if (hi->nline == 7) line = HTTPRequest_Data1(hi, len); else if (hi->nline == 8) { *len = strlen("\r\n"); line = (byte *)MPStrDup(hi->rmp, "\r\n"); } else if (hi->nline == 9) line = HTTPRequest_Data2(hi, len); else break; hi->nline++; } while (line == NULL && *len != -1); return(line); } /* * HTTPFailure */ static void HTTPFailure(hi) HTTPInfo *hi; { HTTPCancel(&hi); SourceStop(hi->ws, "Read error during HTTP transfer"); return; } /* * HTTPGetFilename */ static char * HTTPGetFilename(hi) HTTPInfo *hi; { char *filename; /* * If there is a proxy URL supplied then get the entire URL and not just * just the filename part. If there is no proxy then just use the * filename part. */ if (hi->pup != NULL) filename = URLMakeString(hi->mp, hi->up, false); else filename = hi->up->filename; if (filename == NULL) filename = "/"; return(filename); } /* * HTTPRead */ static void HTTPRead(hip, func) HTTPInfo **hip; ChimeraStreamCallback func; { size_t rsize; HTTPInfo *hi = *hip; if (hi->bmax > 0) { rsize = hi->bmax - hi->blen; if (rsize > CHUNKSIZE) rsize = CHUNKSIZE; } else rsize = CHUNKSIZE; if (hi->bmax == 0 || ((hi->bsize - hi->blen) < rsize)) { if (hi->b == NULL) hi->b = (byte *)alloc_mem(rsize); else hi->b = (byte *)realloc_mem(hi->b, hi->bsize + rsize); hi->bsize += rsize; } StreamRead(hi->ios, hi->b + hi->blen, rsize, func, hip); return; } /* * HTTPReadData */ static void HTTPReadData(ios, len, closure) ChimeraStream ios; ssize_t len; void *closure; { HTTPInfo **hip = (HTTPInfo **)closure; HTTPInfo *hi = *hip; long rnum; char *rmsg; if (len < 0) { HTTPFailure(hi); return; } if (len > 0) hi->blen += len; if (len == 0 || ((hi->blen - hi->doff) == hi->bmax && hi->bmax > 0)) { SourceSendMessage(hi->ws, hi->hc->msg[HM_DONE]); SourceEnd(hi->ws); } else { /* * Don't want to return data until we know the final size...realloc() * causes trouble. */ if (hi->bmax > 0) { if (hi->blen - hi->doff > 0) SourceAdd(hi->ws); rmsg = hi->hc->msg[HM_RK]; rnum = (long)(hi->bmax - hi->blen - hi->doff); } else { rmsg = hi->hc->msg[HM_RU]; rnum = (long)(hi->blen - hi->doff); } if (hi->rcount++ % PRINT_RATE == 0) { snprintf (hi->msgbuf, sizeof(hi->msgbuf), "%ld %s", rnum, rmsg); SourceSendMessage(hi->ws, hi->msgbuf); } HTTPRead(hip, HTTPReadData); } return; } /* * HTTPCheckHeader * * Scrounges around in the header fields to see if there is any * interesting information. */ static int HTTPCheckHeader(hip) HTTPInfo **hip; { char *value; size_t clen; char *option; char *list; URLParts *up, *pup; char *url; char *username; char *cp; bool cache; HTTPInfo *hi = *hip; if (hi->status >= 300) cache = false; else cache = true; /* * Take action on MIME fields. */ if ((MIMEGetField(hi->mh, "location", &value) == 0 && value != NULL) && hi->status >= 300 && hi->status < 400) { up = URLParse(hi->mp, value); pup = NULL; /* Just blindly follow the URL unless it should be used as a proxy */ if (hi->status != 305) up = URLResolve(hi->mp, up, hi->up); else { pup = up; up = hi->up; } if (HTTPCreateInfo(hip, hi->ws, hi->wr, hi->hc, up, pup, hi->hp) == -1) { HTTPFailure(hi); } HTTPDestroyInfo(hi); return(-1); } if (MIMEGetField(hi->mh, "content-length", &value) == 0 && value != NULL) { clen = (size_t)atoi(value) + hi->doff; if (clen > 0 && clen > hi->blen && clen > hi->bsize) { hi->b = (byte *)realloc_mem(hi->b, clen); hi->bsize = clen; hi->bmax = clen; } else hi->bmax = 0; } if (MIMEGetField(hi->mh, "pragma", &value) == 0 && value != NULL) { list = value; while ((option = mystrtok(list, ' ', &list)) != NULL) { if (strcasecmp(option, "no-cache") == 0) cache = false; } } if (MIMEGetField(hi->mh, "www-authenticate", &value) == 0 && value != NULL && hi->hp == NULL) { cache = false; /* * Look for the authorization type and realm */ list = value; while ((option = mystrtok(list, ' ', &list)) != NULL) { if (strcasecmp(option, "basic") == 0) { hi->auth_type = MPStrDup(hi->mp, option); } else if (strncasecmp(option, "realm=", 6) == 0) { for (cp = option; *cp != '\0'; cp++) { if (*cp == '=') { hi->realm = MPStrDup(hi->mp, cp + 1); break; } } } } /* * If there is an authorization type and realm then try to * see if the password is already known. If not then ask the user * for a username and password. */ if (hi->auth_type != NULL && hi->realm != NULL) { if ((hi->hp = HTTPFindPassword(hi, hi->realm, hi->up->hostname, hi->up->port)) != NULL) { if (HTTPCreateInfo(hip, hi->ws, hi->wr, hi->hc, hi->up, hi->pup, hi->hp) == -1) { HTTPFailure(hi); } HTTPDestroyInfo(hi); return(-1); } else { if (hi->up->username != NULL) { if (hi->up->password != NULL) { HTTPAuthCallback(hip, hi->up->username, hi->up->password); } else username = hi->up->username; } else username = ""; hi->wa = AuthCreate(hi->cres, "Enter password", username, HTTPAuthCallback, hip); /* * If the authorization context is created then return -1 to * indicate that is the end of the transaction. If the context * is not created then pass through so the auth message will * appear. */ if (hi->wa != NULL) return(-1); } } } if (MIMEGetField(hi->mh, "content-type", &value) != 0 || value == NULL) { if ((value = ChimeraExt2Content(hi->cres, HTTPGetFilename(hi))) == NULL) { value = "text/html"; } MIMEAddField(hi->mh, "content-type", value); } if (hi->url != NULL) url = hi->url; else url = "unknown:/"; MIMEAddField(hi->mh, "x-url", url); /* Do not call this before dealing with "Location:" */ SourceInit(hi->ws, cache && hi->hp == NULL); return(0); } /* * HTTPReadHeader */ void HTTPReadHeader(ios, len, closure) ChimeraStream ios; ssize_t len; void *closure; { HTTPInfo **hip = (HTTPInfo **)closure; HTTPInfo *hi = *hip; char *cp; ssize_t i; size_t moff = 0; if (len <= 0) { HTTPFailure(hi); return; } if (MIMEFindData(hi->mh, hi->b, hi->blen + len, &(hi->doff)) == 0) { /* * Look for the end of the first line. */ for (i = 0, cp = (char *)hi->b; i < hi->doff; i++, cp++) { if (*cp == '\n') { moff = i + 1; break; } } myassert(i < hi->doff, "MIMEFindData must be broken"); if (sscanf((char *)hi->b, "HTTP/%d.%d %d", &hi->major, &hi->minor, &hi->status) != 3) { HTTPFailure(hi); return; } MIMEParseBuffer(hi->mh, hi->b + moff, hi->doff - moff); if (HTTPCheckHeader(hip) == -1) return; HTTPReadData(ios, len, closure); } else { snprintf (hi->msgbuf, sizeof(hi->msgbuf), "%ld %s", (long)hi->blen, hi->hc->msg[HM_RU]); SourceSendMessage(hi->ws, hi->msgbuf); hi->blen += len; HTTPRead(hip, HTTPReadHeader); } return; } /* * HTTPReadUnknown */ static void HTTPReadUnknown(ios, len, closure) ChimeraStream ios; ssize_t len; void *closure; { HTTPInfo **hip = (HTTPInfo **)closure; HTTPInfo *hi = *hip; char *content; size_t nblen; if (len < 0 || (len == 0 && hi->blen == 0)) { HTTPFailure(hi); return; } nblen = hi->blen + len; if (nblen < 5 && len > 0) { hi->blen = nblen; /* Not enough information to know the HTTP version */ HTTPRead(hip, HTTPReadUnknown); } else if (nblen >= 5 && strncmp("HTTP/", (char *)hi->b, 5) == 0) { HTTPReadHeader(ios, len, hip); } else { /* Must be HTTP/0.9 */ if ((content = ChimeraExt2Content(hi->cres, HTTPGetFilename(hi))) == NULL) { content = "text/html"; } MIMEAddField(hi->mh, "content-type", content); MIMEAddField(hi->mh, "x-url", hi->url); SourceInit(hi->ws, true); HTTPReadData(ios, len, hip); } snprintf (hi->msgbuf, sizeof(hi->msgbuf), "%ld %s", (long)hi->blen, hi->hc->msg[HM_RU]); SourceSendMessage(hi->ws, hi->msgbuf); return; } /* * HTTPRequestDone */ static void HTTPRequestDone(ios, rval, closure) ChimeraStream ios; ssize_t rval; void *closure; { byte *rdata; ssize_t rlen; HTTPInfo **hip = (HTTPInfo **)closure; HTTPInfo *hi = *hip; if (rval == -1) { HTTPFailure(hi); return; } if ((rdata = HTTPBuildRequest(hi, &rlen)) == NULL) { if (rlen == -1) HTTPFailure(hi); else HTTPRead(hip, HTTPReadUnknown); } else { StreamWrite(hi->ios, rdata, rlen, HTTPRequestDone, hip); } return; } /* * HTTPDestroy */ static void HTTPDestroy(closure) void *closure; { HTTPInfo **hip = (HTTPInfo **)closure; HTTPDestroyInfo(*hip); free_mem(hip); return; } /* * HTTPDestroyInfo */ static void HTTPDestroyInfo(hi) HTTPInfo *hi; { HTTPCancel(&hi); if (hi->rmp != NULL) MPDestroy(hi->rmp); if (hi->b != NULL) free_mem(hi->b); if (hi->mh != NULL) MIMEDestroyHeader(hi->mh); MPDestroy(hi->mp); return; } /* * HTTPCreateInfo */ static int HTTPCreateInfo(hip, ws, wr, hc, up, pup, hp) HTTPInfo **hip; ChimeraSource ws; ChimeraRequest *wr; HTTPClass *hc; URLParts *up, *pup; HTTPPassword *hp; { char *hostname; int port; HTTPInfo *hi; MemPool mp; mp = MPCreate(); *hip = hi = (HTTPInfo *)MPCGet(mp, sizeof(HTTPInfo)); hi->mp = mp; hi->hp = hp; hi->rmp = MPCreate(); hi->ws = ws; hi->wr = wr; hi->cres = SourceToResources(ws); hi->hc = hc; hi->mh = MIMECreateHeader(); hi->up = URLDup(mp, up); hi->url = URLMakeString(hi->mp, hi->up, true); if (pup != NULL) hi->pup = URLDup(mp, pup); else hi->pup = NULL; if (hi->pup != NULL) { hostname = pup->hostname; port = pup->port; } else { hostname = up->hostname; port = up->port; } snprintf (hi->msgbuf, sizeof(hi->msgbuf), "%s %s", hc->msg[HM_OPEN], hostname); SourceSendMessage(hi->ws, hi->msgbuf); hi->ios = StreamCreateINet(hi->cres, hostname, port == 0 ? 80:port); if (hi->ios == NULL) { HTTPDestroyInfo(hi); return(-1); } HTTPRequestDone(hi->ios, 0, (void *)hip); return(0); } /* * HTTPInit */ static void * HTTPInit(ws, wr, class_closure) ChimeraSource ws; ChimeraRequest *wr; void *class_closure; { HTTPClass *hc = (HTTPClass *)class_closure; HTTPInfo **hip; hip = (HTTPInfo **)alloc_mem(sizeof(HTTPInfo **)); if (HTTPCreateInfo(hip, ws, wr, hc, wr->up, wr->pup, NULL) == -1) { free_mem(hip); return(NULL); } return(hip); } /* * HTTPCancel * * Used to obliterate a connection. Use this when an error occurs which * could cause a connection to get messed up or at least a pain to * figure out. */ void HTTPCancel(closure) void *closure; { HTTPInfo *hi = *((HTTPInfo **)closure); if (hi->wa != NULL) { AuthDestroy(hi->wa); hi->wa = NULL; } if (hi->ios != NULL) { StreamDestroy(hi->ios); hi->ios = NULL; } return; } /* * HTTPClassDestroy */ static void HTTPClassDestroy(closure) void *closure; { HTTPClass *hc = (HTTPClass *)closure; MPDestroy(hc->mp); return; } /* * HTTPGetData */ static void HTTPGetData(closure, data, len, mh) void *closure; byte **data; size_t *len; MIMEHeader *mh; { HTTPInfo *hi = *((HTTPInfo **)closure); *data = hi->b + hi->doff; *len = hi->blen - hi->doff; *mh = hi->mh; return; } /* * InitModule_HTTP */ void InitModule_HTTP(cres) ChimeraResources cres; { ChimeraSourceHooks ph; HTTPClass *hc; MemPool mp; size_t tlen; int i; mp = MPCreate(); hc = (HTTPClass *)MPCGet(mp, sizeof(HTTPClass)); hc->mp = mp; hc->passwords = GListCreateX(mp); /* get the status messages and allocate a message work buffer */ for (i = 0; http_messages[i].name != NULL; i++) { if ((hc->msg[i] = ResourceGetString(cres, http_messages[0].name)) == NULL) { hc->msg[i] = http_messages[i].def; } if ((tlen = strlen(hc->msg[i])) > hc->mlen) hc->mlen = tlen; } memset(&ph, 0, sizeof(ph)); ph.class_closure = hc; ph.name = "http"; ph.init = HTTPInit; ph.destroy = HTTPDestroy; ph.stop = HTTPCancel; ph.getdata = HTTPGetData; ph.class_destroy = HTTPClassDestroy; SourceAddHooks(cres, &ph); return; } chimera-2.0a19/proto/ftp.c100600 11610 11610 44512 6677562011 13655 0ustar johnjohn/* * ftp.c * * Copyright 1993-1997, John Kilburg (john@cs.unlv.edu) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #include "port_after.h" #include "Chimera.h" #include "ChimeraStream.h" #include "ChimeraSource.h" #include "ChimeraAuth.h" #include "mime.h" #define PRINT_RATE 10 #define FM_OPEN 0 #define FM_RU 1 #define FM_RK 2 #define FM_DONE 3 #define FM_SEND 4 #define FM_WAITING 5 #define MSGLEN 1024 #define REQLEN 1024 static struct ftp_message { char *name; char *def; } ftp_messages[] = { { "ftp.open", "Connecting to " }, { "ftp.read_unknown", " bytes read so far." }, { "ftp.read_known", " bytes remaining." }, { "ftp.done", "FTP read finished." }, { "ftp.send", "Sending request..." }, { "ftp.waiting", "Waiting for a response from " }, { NULL, NULL }, }; typedef struct { char *username; char *password; char *hostname; int port; bool good; } FTPPassword; typedef struct { MemPool mp; char *header; char *trailer; GList passwords; } FTPClass; typedef struct FTPInfoP FTPInfo; typedef void (*FTPProc) _ArgProto((FTPInfo *)); static void FTPDestroy _ArgProto((void *)); static void FTPData _ArgProto((ChimeraStream, ssize_t, void *)); static void FTPDirData _ArgProto((ChimeraStream, ssize_t, void *)); static void FTPSimpleRead _ArgProto((ChimeraStream, ssize_t, void *)); static void FTPDummy _ArgProto((ChimeraStream, ssize_t, void *)); static void FTPDirRead _ArgProto((FTPInfo *)); static void FTPNlst _ArgProto((FTPInfo *)); static void FTPCwd _ArgProto((FTPInfo *)); static void FTPRetrieve _ArgProto((FTPInfo *)); static void FTPPassive _ArgProto((FTPInfo *)); static void FTPSize _ArgProto((FTPInfo *)); static void FTPType _ArgProto((FTPInfo *)); static void FTPUser _ArgProto((FTPInfo *)); static void FTPPass _ArgProto((FTPInfo *)); static void *FTPInit _ArgProto((ChimeraSource, ChimeraRequest *, void *)); static void FTPClassDestroy _ArgProto((void *)); static void FTPCancel _ArgProto((void *)); static void FTPGetData _ArgProto((void *, byte **, size_t *, MIMEHeader *)); static int ftp_strcmp _ArgProto((const void *, const void *)); static void FTPAuthCallback _ArgProto((void *, char *, char *)); void InitModule_FTP _ArgProto((ChimeraResources)); struct FTPInfoP { MemPool mp; ChimeraSource ws; ChimeraResources cres; ChimeraRequest *wr; FTPClass *fc; FTPProc rfunc; char msgbuf[MSGLEN]; char request[REQLEN]; char *msg[sizeof(ftp_messages) / sizeof(ftp_messages[0])]; int rcount; FTPPassword *fp; ChimeraAuth wa; /* control stream */ ChimeraStream cs; byte *cb; /* control buffer */ size_t cblen; /* control buffer content length */ size_t cbsize; /* control buffer size */ bool ignore_err; /* recognition of control errors */ /* data stream */ ChimeraStream ds; byte *db; /* data buffer */ size_t dblen; /* data buffer content length */ size_t dbsize; /* data buffer size */ size_t dbmax; /* data buffer maximum */ MIMEHeader mh; }; static char *FTPDirToHTML _ArgProto((FTPInfo *)); static void FTPWrite _ArgProto((ChimeraStream, ssize_t, void *)); static void FTPDestroyStream _ArgProto((FTPInfo *)); static void FTPReadData _ArgProto((FTPInfo *, ChimeraStreamCallback)); static void FTPReadControl _ArgProto((FTPInfo *, ChimeraStreamCallback)); static int FTPParseResponse _ArgProto((FTPInfo *)); static void FTPDummy _ArgProto((ChimeraStream, ssize_t, void *)); static void FTPFailure _ArgProto((FTPInfo *)); static void FTPSimple _ArgProto((FTPInfo *, FTPProc, bool)); static void FTPAddPassword _ArgProto((FTPInfo *, char *, char *)); static FTPPassword *FTPFindPassword _ArgProto((FTPInfo *, char *)); /* * FTPFindPassword */ static FTPPassword * FTPFindPassword(fi, username) FTPInfo *fi; char *username; { FTPPassword *fp; char *hostname; int port; hostname = fi->wr->up->hostname; port = fi->wr->up->port == 0 ? 21:fi->wr->up->port; for (fp = (FTPPassword *)GListGetHead(fi->fc->passwords); fp != NULL; fp = (FTPPassword *)GListGetNext(fi->fc->passwords)) { if (strcmp(username, fp->username) == 0 && strcasecmp(hostname, fp->hostname) == 0 && port == fp->port && fp->good) { return(fp); } } return(NULL); } /* * FTPAddPassword */ static void FTPAddPassword(fi, username, password) FTPInfo *fi; char *username; char *password; { FTPPassword *fp; MemPool mp; if (username == NULL) return; if (fi->wr->up->hostname == NULL) return; mp = fi->fc->mp; fp = (FTPPassword *)MPCGet(mp, sizeof(FTPPassword)); fp->username = MPStrDup(mp, username); if (password != NULL) fp->password = MPStrDup(mp, password); else fp->password = MPStrDup(mp, ""); fp->hostname = MPStrDup(mp, fi->wr->up->hostname); fp->port = fi->wr->up->port == 0 ? 21:fi->wr->up->port; GListAddHead(fi->fc->passwords, fp); fi->fp = fp; return; } /* * FTPFailure */ static void FTPFailure(fi) FTPInfo *fi; { SourceStop(fi->ws, "ftp failure"); FTPDestroyStream(fi); return; } /* * FTPDestroyStream */ static void FTPDestroyStream(fi) FTPInfo *fi; { if (fi->ds != NULL) { StreamDestroy(fi->ds); fi->ds = NULL; } if (fi->cs != NULL) { StreamDestroy(fi->cs); fi->cs = NULL; } return; } /* * FTPDestroy */ static void FTPDestroy(closure) void *closure; { FTPInfo *fi = (FTPInfo *)closure; FTPDestroyStream(fi); if (fi->db != NULL) free_mem(fi->db); if (fi->cb != NULL) free_mem(fi->cb); if (fi->mh != NULL) MIMEDestroyHeader(fi->mh); MPDestroy(fi->mp); return; } /* * FTPReadData */ static void FTPReadData(fi, func) FTPInfo *fi; ChimeraStreamCallback func; { size_t len; if (fi->dbmax > 0) { len = fi->dbmax - fi->dblen; if (len > BUFSIZ) len = BUFSIZ; } else len = BUFSIZ; if (len > 0) { if (fi->db == NULL) fi->db = (byte *)alloc_mem(len); else fi->db = (byte *)realloc_mem(fi->db, fi->dbsize + len); fi->dbsize += len; } StreamRead(fi->ds, fi->db + fi->dblen, len, func, fi); return; } /* * FTPReadControl */ static void FTPReadControl(fi, func) FTPInfo *fi; ChimeraStreamCallback func; { if (fi->cblen + BUFSIZ > fi->cbsize) { if (fi->cb == NULL) fi->cb = (byte *)alloc_mem(BUFSIZ); else fi->cb = (byte *)realloc_mem(fi->cb, fi->cbsize + BUFSIZ); fi->cbsize += BUFSIZ; } StreamRead(fi->cs, fi->cb + fi->cblen, BUFSIZ, func, fi); return; } /* * FTPData */ static void FTPData(ios, len, closure) ChimeraStream ios; ssize_t len; void *closure; { FTPInfo *fi = (FTPInfo *)closure; if (len < 0) { FTPFailure(fi); return; } if (len == 0) { SourceSendMessage(fi->ws, fi->msg[FM_DONE]); FTPCancel(fi); SourceEnd(fi->ws); } else { fi->dblen += len; if (fi->dbmax > 0) { if (fi->rcount++ % PRINT_RATE == 0) { snprintf (fi->msgbuf, sizeof(fi->msgbuf), "%ld %s", (long)(fi->dbmax - fi->dblen), fi->msg[FM_RK]); SourceSendMessage(fi->ws, fi->msgbuf); } SourceAdd(fi->ws); } else { if (fi->rcount++ % PRINT_RATE == 0) { snprintf (fi->msgbuf, sizeof(fi->msgbuf), "%ld %s", (long)fi->dblen, fi->msg[FM_RU]); SourceSendMessage(fi->ws, fi->msgbuf); } } FTPReadData(fi, FTPData); } return; } /* * ftp_dirdata */ static void FTPDirData(ios, len, closure) ChimeraStream ios; ssize_t len; void *closure; { FTPInfo *fi = (FTPInfo *)closure; if (len > 0) { fi->dblen += len; FTPReadData(fi, FTPDirData); return; } else if (len < 0) { FTPFailure(fi); return; } MIMEAddField(fi->mh, "content-type", "text/html"); MIMEAddField(fi->mh, "x-url", fi->wr->url); fi->db = FTPDirToHTML(fi); fi->dblen = strlen(fi->db); FTPDestroyStream(fi); SourceInit(fi->ws, fi->fp == NULL); SourceEnd(fi->ws); return; } /* * FTPParseResponse */ static int FTPParseResponse(fi) FTPInfo *fi; { char *cp; char *b = (char *)fi->cb; size_t len = fi->cblen; if (b[len - 1] == '\n') { if (*(b + 3) == ' ') return(atoi(b)); for (cp = b + len - 2; cp >= b; cp--) { if (*cp == '\n' && *(cp + 4) == ' ') return(atoi(cp + 1)); } } return(-1); } /* * FTPSimpleRead */ static void FTPSimpleRead(ios, len, closure) ChimeraStream ios; ssize_t len; void *closure; { int ecode; FTPInfo *fi = (FTPInfo *)closure; if (len < 0) { FTPFailure(fi); return; } fi->cblen += len; if ((ecode = FTPParseResponse(fi)) == -1) { FTPReadControl(fi, FTPSimpleRead); return; } if (ecode < 400 || fi->ignore_err) { (fi->rfunc)(fi); fi->cblen = 0; } else FTPFailure(fi); return; } /* * FTPWrite */ static void FTPWrite(ios, len, closure) ChimeraStream ios; ssize_t len; void *closure; { FTPReadControl((FTPInfo *)closure, FTPSimpleRead); return; } /* * FTPSimple */ static void FTPSimple(fi, rfunc, ignore_err) FTPInfo *fi; FTPProc rfunc; bool ignore_err; { fi->rfunc = rfunc; fi->ignore_err = ignore_err; SourceSendMessage(fi->ws, fi->msg[FM_SEND]); StreamWrite(fi->cs, (byte *)fi->request, strlen(fi->request), FTPWrite, fi); return; } /* * FTPDirRead */ static void FTPDirRead(fi) FTPInfo *fi; { FTPReadData(fi, FTPDirData); return; } /* * FTPNlst */ static void FTPNlst(fi) FTPInfo *fi; { snprintf (fi->request, sizeof(fi->request), "NLST\r\n"); FTPSimple(fi, FTPDirRead, false); return; } /* * FTPDummy */ static void FTPDummy(ios, len, closure) ChimeraStream ios; ssize_t len; void *closure; { return; } /* * FTPCwd */ static void FTPCwd(fi) FTPInfo *fi; { int ecode; char *filename; filename = fi->wr->up->filename; sscanf((char*)fi->cb, "%d", &ecode); if (ecode < 400) { char *content; if ((content = ChimeraExt2Content(fi->cres, filename)) == NULL) { content = "text/plain"; } MIMEAddField(fi->mh, "content-type", content); MIMEAddField(fi->mh, "x-url", fi->wr->url); SourceInit(fi->ws, fi->fp == NULL); FTPReadData(fi, FTPData); FTPReadControl(fi, FTPDummy); } else { snprintf (fi->request, sizeof(fi->request), "CWD %s\r\n", filename); FTPSimple(fi, FTPNlst, false); } return; } /* * FTPRetrieve */ static void FTPRetrieve(fi) FTPInfo *fi; { int h0, h1, h2, h3, p0, p1, reply, n; const char *format = "RETR %s\r\n"; char dhost[BUFSIZ]; int dport; n = sscanf((char *)fi->cb, "%d %*[^(] (%d,%d,%d,%d,%d,%d)", &reply, &h0, &h1, &h2, &h3, &p0, &p1); if (n != 7 || reply != 227) { /* error */ return; } snprintf (dhost, sizeof(dhost), "%d.%d.%d.%d", h0, h1, h2, h3); dport = (p0 << 8) + p1; /* * Check for error here. */ if ((fi->ds = StreamCreateINet(fi->cres, dhost, dport)) == NULL) { return; } snprintf (fi->request, sizeof(fi->request), format, fi->wr->up->filename); FTPSimple(fi, FTPCwd, true); return; } /* * FTPPassive */ static void FTPPassive(fi) FTPInfo *fi; { int ecode; long size; sscanf((char *)fi->cb, "%d %ld", &ecode, &size); fi->dbmax = (size_t)size; if (ecode >= 400) fi->dbmax = 0; else { fi->db = (byte *)realloc_mem(fi->db, fi->dbmax); fi->dbsize = fi->dbmax; } snprintf (fi->request, sizeof(fi->request), "PASV\r\n"); FTPSimple(fi, FTPRetrieve, true); return; } /* * FTPSize */ static void FTPSize(fi) FTPInfo *fi; { snprintf (fi->request, sizeof(fi->request), "SIZE %s\r\n", fi->wr->up->filename); FTPSimple(fi, FTPPassive, true); return; } /* * FTPType */ static void FTPType(fi) FTPInfo *fi; { /* Now we know the password succeeded so check it as OK */ if (fi->fp != NULL) fi->fp->good = true; snprintf (fi->request, sizeof(fi->request), "TYPE I\r\n"); FTPSimple(fi, FTPSize, false); return; } /* * FTPPass */ static void FTPPass(fi) FTPInfo *fi; { char *uname; const char *pformat = "PASS %s\r\n"; if (fi->fp != NULL) { snprintf (fi->request, sizeof(fi->request), pformat, fi->fp->password); } else if (fi->wr->up->password != NULL) { snprintf (fi->request, sizeof(fi->request), pformat, fi->wr->up->password); } else if ((uname = getenv("EMAIL")) != NULL) { snprintf (fi->request, sizeof(fi->request), pformat, uname); } else { snprintf (fi->request, sizeof(fi->request), "PASS -nobody@nowhere.org\r\n"); } FTPSimple(fi, FTPType, false); return; } /* * FTPAuthCallback */ static void FTPAuthCallback(closure, username, password) void *closure; char *username; char *password; { FTPInfo *fi = (FTPInfo *)closure; if (username == NULL || password == NULL) { FTPCancel(fi); return; } FTPAddPassword(fi, username, password); AuthDestroy(fi->wa); fi->wa = NULL; FTPUser(fi); return; } /* * FTPUser */ static void FTPUser(fi) FTPInfo *fi; { const char *uformat = "USER %s\r\n"; if (fi->fp != NULL) { snprintf (fi->request, sizeof(fi->request), uformat, fi->fp->username); } else if (fi->wr->up->username != NULL) { if (fi->wr->up->password == NULL) { if ((fi->fp = FTPFindPassword(fi, fi->wr->up->username)) == NULL) { fi->wa = AuthCreate(fi->cres, "Enter password", fi->wr->up->username, FTPAuthCallback, fi); if (fi->wa != NULL) return; } } snprintf (fi->request, sizeof(fi->request), uformat, fi->wr->up->username); } else { snprintf (fi->request, sizeof(fi->request), "USER anonymous\r\n"); } FTPSimple(fi, FTPPass, false); return; } /* * FTPInit */ static void * FTPInit(ws, wr, class_closure) ChimeraSource ws; ChimeraRequest *wr; void *class_closure; { FTPInfo *fi; MemPool mp; size_t mlen, tlen; int i; mp = MPCreate(); fi = (FTPInfo *)MPCGet(mp, sizeof(FTPInfo)); fi->mp = mp; fi->ws = ws; fi->wr = wr; fi->cres = SourceToResources(ws); fi->fc = (FTPClass *)class_closure; fi->mh = MIMECreateHeader(); /* get the status messages and allocate a message work buffer */ mlen = 0; for (i = 0; ftp_messages[i].name != NULL; i++) { if ((fi->msg[i] = ResourceGetString(fi->cres, ftp_messages[0].name)) == NULL) { fi->msg[i] = ftp_messages[i].def; } if ((tlen = strlen(fi->msg[i])) > mlen) mlen = tlen; } snprintf (fi->msgbuf, sizeof(fi->msgbuf), "%s %s", fi->msg[FM_OPEN], wr->up->hostname); SourceSendMessage(fi->ws, fi->msgbuf); fi->cs = StreamCreateINet(fi->cres, wr->up->hostname, wr->up->port == 0 ? 21:wr->up->port); if (fi->cs == NULL) { FTPDestroy(fi); return(NULL); } fi->rfunc = FTPUser; FTPReadControl(fi, FTPSimpleRead); return(fi); } /* * FTPClassDestroy */ static void FTPClassDestroy(closure) void *closure; { FTPClass *fc = (FTPClass *)closure; MPDestroy(fc->mp); return; } /* * FTPCancel */ static void FTPCancel(closure) void *closure; { FTPInfo *fi = (FTPInfo *)closure; if (fi->wa != NULL) { AuthDestroy(fi->wa); fi->wa = NULL; } FTPDestroyStream(fi); return; } static void FTPGetData(closure, data, len, mh) void *closure; byte **data; size_t *len; MIMEHeader *mh; { FTPInfo *fi = (FTPInfo *)closure; *data = fi->db; *len = fi->dblen; *mh = fi->mh; return; } /* * InitModule_FTP */ void InitModule_FTP(cres) ChimeraResources cres; { ChimeraSourceHooks ph; FTPClass *fc; MemPool mp; mp = MPCreate(); fc = (FTPClass *)MPCGet(mp, sizeof(FTPClass)); fc->mp = mp; fc->passwords = GListCreateX(mp); fc->header = ResourceGetString(cres, "ftp.dirheader"); if (fc->header == NULL) { fc->header = "

        FTP Directory

          "; } fc->trailer = ResourceGetString(cres, "ftp.dirtrailer"); if (fc->trailer == NULL) fc->trailer = "
        "; memset(&ph, 0, sizeof(ph)); ph.class_closure = fc; ph.class_destroy = FTPClassDestroy; ph.name = "ftp"; ph.init = FTPInit; ph.destroy = FTPDestroy; ph.stop = FTPCancel; ph.getdata = FTPGetData; SourceAddHooks(cres, &ph); return; } static int ftp_strcmp(a, b) const void *a, *b; { return(strcmp(*((char **)a), *((char **)b))); } /* * FTPDirToHTML * * Convert directory list to HTML */ static char * FTPDirToHTML(fi) FTPInfo *fi; { char *f; int i; char *hostname; char *filename; const char *entry = "
      1. %s\n"; byte *cp, *lastcp, *dname; int sacount; char **sa; int olen, hlen, flen, elen; FTPClass *fc = fi->fc; if (fi->wr->up->username != NULL) { size_t t; t = strlen(fi->wr->up->username); t += strlen("@"); t += strlen(fi->wr->up->hostname); hostname = MPGet(fi->mp, t + 1); strcpy(hostname, fi->wr->up->username); strcat(hostname, "@"); strcat(hostname, fi->wr->up->hostname); } else { hostname = fi->wr->up->hostname; } filename = fi->wr->up->filename; hlen = strlen(hostname); flen = strlen(filename); elen = strlen(entry); sacount = 0; for (cp = fi->db, lastcp = cp + fi->dblen; cp < lastcp; cp++) { if (*cp == '\n') sacount++; } sa = (char **)MPGet(fi->mp, sizeof(char *) * sacount); dname = fi->db; olen = 0; for (i = 0, cp = fi->db, lastcp = cp + fi->dblen; cp < lastcp; cp++) { if (*cp == '\n') { sa[i] = (char *)dname; *cp = '\0'; dname = (byte *)cp + 1; olen += hlen + 20 + flen + elen + strlen(sa[i]) * 2; i++; } } qsort(sa, sacount, sizeof(char *), ftp_strcmp); olen += strlen(fc->header) + 2 * flen + hlen + strlen(fc->trailer) + 1; f = (char *)alloc_mem(olen); snprintf (f, olen, fc->header, filename, hostname, filename); if (filename[0] != '\0' && filename[1] == '\0') filename = ""; for (i = 0; i < sacount; i++) { snprintf(f + strlen(f), olen - strlen(f), entry, hostname, fi->wr->up->port == 0 ? 21:fi->wr->up->port, filename, sa[i], sa[i]); } strcat(f, fc->trailer); return(f); } chimera-2.0a19/proto/file.c100600 11610 11610 24036 6723345545 14005 0ustar johnjohn/* * file.c * * Copyright (c) 1995-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #if defined(SYSV) || defined(SVR4) || defined(__arm) || defined(__QNX__) #include #define DIRSTUFF struct dirent #else #include #define DIRSTUFF struct direct #endif #include "port_after.h" #include "Chimera.h" #include "ChimeraSource.h" #include "ChimeraAuth.h" #include "mime.h" #define PRINT_RATE 10 #define MSGLEN 4096 /* this needs to be big */ /* Jim Rees fix */ #ifndef S_ISDIR #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif #ifndef S_ISBLK #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) #endif #ifndef S_ISREG #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif #ifndef S_ISFIFO #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) #endif #ifndef S_ISCHR #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) #endif /* not POSIX but what the heck */ #ifndef S_ISLNK #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) #endif typedef struct { FILE *fp; off_t size; } RegInfo; typedef struct { DIR *dp; int size; int used; char *dirname; char **sa; char *direntry; } DirInfo; typedef struct { MemPool mp; bool directory; bool stopped; ChimeraSource ws; ChimeraResources cres; ChimeraTask wt; ChimeraRequest *wr; char *filename; DirInfo di; RegInfo ri; bool init_done; char mbuf[MSGLEN]; char *rstr; int pcount; byte *data; size_t len; MIMEHeader mh; } FileInfo; static void DirRead _ArgProto((void *)); static void FileRead _ArgProto((void *)); static void FileGetData _ArgProto((void *, byte **, size_t *, MIMEHeader *)); static int local_strcmp _ArgProto((const void *, const void *)); static void DirEOF _ArgProto((FileInfo *)); static void FileCancel _ArgProto((void *)); static void FileDestroy _ArgProto((void *)); static void *FileInit _ArgProto((ChimeraSource, ChimeraRequest *, void *)); void InitModule_File _ArgProto((ChimeraResources)); static int local_strcmp(a, b) const void *a, *b; { return(strcmp(*((char **)a), *((char **)b))); } /* * DirEOF */ static void DirEOF(fi) FileInfo *fi; { int i; char *f; char **sa = fi->di.sa; char *cp; int flen; static char *header1 = ""; static char *header2 = "
          \n"; static char *trailer1 = "\n
        "; static char *format = "
      2. %s%s\n"; if (fi->di.used > 0) qsort(sa, fi->di.used, sizeof(char *), local_strcmp); for (i = 0, flen = 0; i < fi->di.used; i++) { flen += 2 * strlen(sa[i]) + strlen(format) + strlen(fi->di.dirname); } flen += strlen(header1) + strlen(header2) + strlen(trailer1) + sizeof(char); f = (char *)alloc_mem(flen); strcpy(f, header1); strcat(f, header2); for (i = 0; i < fi->di.used; i++) { for (cp = sa[i]; *cp != '\0'; cp++) { if (isspace8(*cp)) break; } *cp++ = '\0'; snprintf(f + strlen(f), flen - strlen(f), format, fi->di.dirname, sa[i], sa[i], cp); } strcat(f, trailer1); fi->data = (byte *)f; fi->len = strlen(f); fi->init_done = true; SourceInit(fi->ws, false); if (!fi->stopped) SourceEnd(fi->ws); return; } /* * DirRead */ static void DirRead(closure) void *closure; { FileInfo *fi = (FileInfo *)closure; DIRSTUFF *de; int salen; struct stat fs; if ((de = readdir(fi->di.dp)) == NULL) { closedir(fi->di.dp); fi->di.dp = NULL; DirEOF(fi); fi->wt = NULL; return; } strcpy(fi->mbuf, fi->di.dirname); strcat(fi->mbuf, de->d_name); if (stat(fi->mbuf, &fs) != -1) { if (S_ISREG(fs.st_mode)) { snprintf(fi->mbuf, sizeof(fi->mbuf), " (%ld bytes)", (long)fs.st_size); } else if (S_ISDIR(fs.st_mode)) strcpy(fi->mbuf, "/"); #ifndef __EMX__ else if (S_ISLNK(fs.st_mode)) strcpy(fi->mbuf, " <link>"); else if (S_ISFIFO(fs.st_mode)) strcpy(fi->mbuf, " <pipe>"); else if (S_ISBLK(fs.st_mode)) strcpy(fi->mbuf, " <block device>"); #endif else if (S_ISCHR(fs.st_mode)) strcpy(fi->mbuf, " <char device>"); else strcpy(fi->mbuf, " <unknown>"); } else strcpy(fi->mbuf, " "); /* * Resize the file entry table if needed. */ if (fi->di.used >= fi->di.size) { char **nsa; nsa = (char **)MPGet(fi->mp, fi->di.size * 2 * sizeof(char *)); memcpy(nsa, fi->di.sa, fi->di.size * sizeof(char *)); fi->di.size *= 2; fi->di.sa = nsa; } salen = strlen(de->d_name) + strlen(fi->mbuf) + 2 * sizeof(char); fi->di.sa[fi->di.used] = (char *)MPGet(fi->mp, salen); strcpy(fi->di.sa[fi->di.used], de->d_name); strcat(fi->di.sa[fi->di.used], " "); strcat(fi->di.sa[fi->di.used], fi->mbuf); fi->di.used++; if (fi->pcount++ % PRINT_RATE == 0) { snprintf (fi->mbuf, sizeof(fi->mbuf), fi->rstr, fi->di.used, fi->filename); SourceSendMessage(fi->ws, fi->mbuf); } fi->wt = TaskSchedule(fi->cres, DirRead, fi); return; } /* * FileRead */ static void FileRead(closure) void *closure; { int readlen; FileInfo *fi = (FileInfo *)closure; readlen = fi->ri.size - fi->len; if (readlen > BUFSIZ) readlen = BUFSIZ; if ((readlen = fread(fi->data + fi->len, 1, readlen, fi->ri.fp)) == 0) { fclose(fi->ri.fp); fi->ri.fp = NULL; if (fi->init_done) SourceEnd(fi->ws); fi->wt = NULL; } else { if (fi->len == 0) { fi->init_done = true; SourceInit(fi->ws, false); if (fi->stopped) return; } fi->len += readlen; SourceAdd(fi->ws); if (fi->pcount++ % PRINT_RATE == 0) { snprintf (fi->mbuf, sizeof(fi->mbuf), fi->rstr, fi->len, fi->filename); SourceSendMessage(fi->ws, fi->mbuf); } fi->wt = TaskSchedule(fi->cres, FileRead, fi); } return; } /* * FileCancel */ static void FileCancel(closure) void *closure; { FileInfo *fi = (FileInfo *)closure; fi->stopped = true; if (fi->wt != NULL) { TaskRemove(fi->cres, fi->wt); fi->wt = NULL; } if (fi->di.dp != NULL) { closedir(fi->di.dp); fi->di.dp = NULL; } if (fi->ri.fp != NULL) { fclose(fi->ri.fp); fi->ri.fp = NULL; } return; } /* * FileDestroy */ static void FileDestroy(closure) void *closure; { FileInfo *fi = (FileInfo *)closure; FileCancel(fi); if (fi->data != NULL) free_mem(fi->data); if (fi->mh != NULL) MIMEDestroyHeader(fi->mh); MPDestroy(fi->mp); return; } /* * FileInit */ static void * FileInit(ws, wr, class_closure) ChimeraSource ws; ChimeraRequest *wr; void *class_closure; { FileInfo *fi; struct stat s, as, *rs; ChimeraTaskProc func; char *rname, *drname; char *content; MemPool mp; char *autofile, *autopath, *tpath; size_t len; char *filename; if (wr->up->filename == NULL) filename = "/"; else filename = wr->up->filename; if (stat(filename, &s) == -1) return(NULL); rs = &s; tpath = filename; mp = MPCreate(); fi = (FileInfo *)MPCGet(mp, sizeof(FileInfo)); fi->mp = mp; fi->ws = ws; fi->cres = SourceToResources(ws); fi->wr = wr; fi->mh = MIMECreateHeader(); fi->filename = MPStrDup(mp, filename); if (S_ISDIR(s.st_mode) && (autofile = ResourceGetString(fi->cres, "file.autoLoad")) != NULL) { len = strlen(filename); autopath = (char *)MPGet(mp, len + strlen(autofile) + strlen("/") + 1); strcpy(autopath, fi->filename); if (fi->filename[len - 1] != '/') strcat(autopath, "/"); strcat(autopath, autofile); if (stat(autopath, &as) == 0) { tpath = autopath; rs = &as; } } if (S_ISDIR(rs->st_mode)) { fi->directory = true; if ((fi->di.dp = opendir(fi->filename)) == NULL) { FileCancel(fi); return(NULL); } fi->di.dirname = (char *)MPGet(fi->mp, strlen(fi->filename) + strlen("/") + sizeof(char)); strcpy(fi->di.dirname, fi->filename); if (fi->filename[strlen(fi->filename) - 1] != '/') { strcat(fi->di.dirname, "/"); } fi->di.size = 512; fi->di.sa = (char **)MPGet(fi->mp, sizeof(char **) * fi->di.size); rname = "file.readdir"; drname = "Read %d entries from %s"; func = DirRead; content = "text/html"; } else { fi->directory = false; if ((fi->ri.fp = fopen(tpath, "r")) == NULL) { FileCancel(fi); return(NULL); } fi->data = (byte *)alloc_mem((size_t)rs->st_size); fi->ri.size = rs->st_size; rname = "file.readfile"; drname = "Read %d bytes from %s"; func = FileRead; if ((content = ChimeraExt2Content(fi->cres, tpath)) == NULL) { content = "text/plain"; } } MIMEAddField(fi->mh, "content-type", content); MIMEAddField(fi->mh, "x-url", fi->wr->url); if ((fi->rstr = ResourceGetString(fi->cres, rname)) == NULL) { fi->rstr = drname; } fi->wt = TaskSchedule(fi->cres, func, fi); return(fi); } static void FileGetData(closure, data, len, mh) void *closure; byte **data; size_t *len; MIMEHeader *mh; { FileInfo *fi = (FileInfo *)closure; *data = fi->data; *len = fi->len; *mh = fi->mh; return; } /* * InitModule_File */ void InitModule_File(cres) ChimeraResources cres; { ChimeraSourceHooks ph; memset(&ph, 0, sizeof(ph)); ph.name = "file"; ph.init = FileInit; ph.destroy = FileDestroy; ph.stop = FileCancel; ph.getdata = FileGetData; SourceAddHooks(cres, &ph); return; } chimera-2.0a19/proto/mailto.c100600 11610 11610 24211 6677562020 14343 0ustar johnjohn/* * mailto.c * * Copyright 1997, Dave Davey * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_STDLIB_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_UNAME #include #endif #include "port_after.h" #include "../mxw/TextField.h" #include "common.h" #include "../mxw/MyDialog.h" #include "Chimera.h" #include "ChimeraSource.h" #include "mime.h" /* * hacked by john a little bit so you know where the blames goes. * status messages are ugly. */ typedef struct MailtoInfoP MailtoInfo; typedef struct MailtoActionInfoP MailtoActionInfo; char *URLUnescape(MemPool mp, char *url); static char *sendmail _ArgProto((ChimeraResources, char *)); void InitModule_Mailto _ArgProto((ChimeraResources)); static void MailtoClassDestroy _ArgProto((void *)); static void *MailtoInit _ArgProto((ChimeraSource, ChimeraRequest *, void *)); static void MailtoCancel _ArgProto((void *)); static void MailtoDestroy _ArgProto((void *)); static void MailtoGetData _ArgProto((void *, byte **, size_t *, MIMEHeader *)); static void MakeMailtoForm _ArgProto((void *)); static void *MailtoActionInit _ArgProto((ChimeraSource, ChimeraRequest *, void *)); static void MailtoActionCancel _ArgProto((void *)); static void MailtoActionDestroy _ArgProto((void *)); static void MailtoActionGetData _ArgProto((void *, byte **, size_t *, MIMEHeader *)); typedef struct { MemPool mp; char *header; char *trailer; } MailtoClass; struct MailtoInfoP { MemPool mp; ChimeraSource ws; ChimeraResources cres; ChimeraRequest *wr; MailtoClass *mc; ChimeraTask wt; byte *data; size_t len; byte *address; MIMEHeader mh; }; struct MailtoActionInfoP { MemPool mp; ChimeraSource ws; ChimeraResources cres; ChimeraRequest *wr; ChimeraTask wt; byte *data; size_t len; MIMEHeader mh; }; /* * InitModule_Mailto */ void InitModule_Mailto(cres) ChimeraResources cres; { ChimeraSourceHooks ph; MailtoClass *mc; MemPool mp; mp = MPCreate(); mc = (MailtoClass *)MPCGet(mp, sizeof(MailtoClass)); mc->mp = mp; mc->header = ResourceGetString(cres, "mailto.dirheader"); if (mc->header == NULL) { mc->header = "

        Mailto

          "; } mc->trailer = ResourceGetString(cres, "mailto.dirtrailer"); if (mc->trailer == NULL) mc->trailer = ""; memset(&ph, 0, sizeof(ph)); ph.class_closure = mc; ph.class_destroy = MailtoClassDestroy; ph.name = "mailto"; ph.init = MailtoInit; ph.destroy = MailtoDestroy; ph.stop = MailtoCancel; ph.getdata = MailtoGetData; SourceAddHooks(cres, &ph); memset(&ph, 0, sizeof(ph)); ph.name = "x-mailtoaction"; ph.init = MailtoActionInit; ph.destroy = MailtoActionDestroy; ph.stop = MailtoActionCancel; ph.getdata = MailtoActionGetData; SourceAddHooks(cres, &ph); return; } /* * MailtoClassDestroy */ static void MailtoClassDestroy(closure) void *closure; { MailtoClass *mc = (MailtoClass *)closure; MPDestroy(mc->mp); return; } /* * MailtoInit */ static void * MailtoInit(ws, wr, class_closure) ChimeraSource ws; ChimeraRequest *wr; void *class_closure; { /* ** get here when click on mailto link ** wr->url points to url including "mailto" */ MailtoInfo *mi; MemPool mp; ChimeraTaskProc func; char *p; if((p = strchr(wr->url, ':')) == NULL) return(NULL); mp = MPCreate(); mi = (MailtoInfo *)MPCGet(mp, sizeof(MailtoInfo)); mi->address = p+1; mi->mp = mp; mi->ws = ws; mi->wr = wr; mi->cres = SourceToResources(ws); mi->mc = (MailtoClass *)class_closure; func = MakeMailtoForm; mi->wt = TaskSchedule(mi->cres, func, mi); mi->mh = MIMECreateHeader(); MIMEAddField(mi->mh, "content-type", "text/html"); MIMEAddField(mi->mh, "x-url", mi->wr->url); return(mi); } /* * MailtoCancel */ static void MailtoCancel(closure) void *closure; { /* nothing to do here ? */ /* what if sendmail "hangs" ? */ return; } /* * MailtoDestroy */ static void MailtoDestroy(closure) void *closure; { MailtoInfo *mi = (MailtoInfo *)closure; if (mi->wt != NULL) TaskRemove(mi->cres, mi->wt); MPDestroy(mi->mp); return; } static void MailtoGetData(closure, data, len, mh) void *closure; byte **data; size_t *len; MIMEHeader *mh; { MailtoInfo *mi = (MailtoInfo *)closure; *data = mi->data; *len = mi->len; *mh = mi->mh; return; } enum { FROM, TO, CC, SUBJECT, MESSAGE }; struct MailHeader { char *name; char *contents; char *input_type; } MailHeaders[] = { { "From", "", "INPUT size=64" }, { "To", "", "INPUT size=64" }, { "Cc", "", "INPUT size=64" }, { "Subject", "", "INPUT size=64" }, { "Message", "", "TEXTAREA rows=20 cols=64" }, { NULL, NULL } }; /* * MakeMailForm */ static void MakeMailtoForm(closure) void *closure; { char *f; MailtoInfo *mi = (MailtoInfo *)closure; struct passwd *p; #ifdef HAVE_UNAME struct utsname uts; #endif char *sender; char *username; struct MailHeader *mh; if ((sender = ResourceGetString(mi->cres, "user.email")) == NULL) { #ifdef HAVE_UNAME if((p = getpwuid(getuid())) == NULL) username = "nobody"; else username = p->pw_name; uname(&uts); sender = (char *)MPCGet(mi->mp, strlen(username) + strlen(uts.nodename) + 2); strcpy(sender, username); strcat(sender, "@"); strcat(sender, uts.nodename); #else sender = ""; #endif } MailHeaders[FROM].contents = sender; MailHeaders[TO].contents = mi->address; MailHeaders[CC].contents = ""; MailHeaders[SUBJECT].contents = mi->wr->parent_url; MailHeaders[MESSAGE].contents = ""; f = (char *)MPCGet(mi->mp, BUFSIZ); strcpy(f, "\n\nChimera Mail\n\n"); strcat(f, "\n

          Chimera Mail

          \n
          \n"); strcat(f, "
          \n\n"); for(mh = MailHeaders; mh->name != NULL; mh++) { strcat(f, "\n"); } strcat(f, "
          \n

          "); strcat(f, mh->name); strcat(f, ":

          \n<"); strcat(f, mh->input_type); strcat(f, " name=\""); strcat(f, mh->name); strcat(f, "\" type=\"text\" value=\""); if(mh->contents) strcat(f, mh->contents); strcat(f, "\">\n"); strcat(f, "
          \n"); strcat(f, "\n"); strcat(f, "\n"); strcat(f, "
          \n\n\n"); mi->data = (byte *)f; mi->len = strlen(f); SourceInit(mi->ws, false); SourceEnd(mi->ws); mi->wt = NULL; return; } static void MailtoAction(closure) void *closure; { MailtoActionInfo *mi = (MailtoActionInfo *)closure; char *f; if (strstr(mi->wr->input_data, "Cancel") != NULL) { f = "mail cancelled by the user"; } else if (strstr(mi->wr->input_data, "SendMail") != NULL) { f = sendmail(mi->cres, mi->wr->input_data); } else f = "unexpected input_data"; mi->data = (byte *)f; mi->len = strlen(f); SourceInit(mi->ws, false); SourceEnd(mi->ws); mi->wt = NULL; return; } static char * sendmail(cres, data) ChimeraResources cres; char *data; { MemPool mp; FILE *fp; char *p; struct MailHeader *mh; char *mailer; char *f; if ((mailer = ResourceGetString(cres, "mailto.mailer")) == NULL) { #ifdef __EMX__ mailer = "sendmail -t"; #else mailer = "/usr/lib/sendmail -t"; #endif } if ((fp = popen(mailer, "w")) != NULL) { mp = MPCreate(); mh = MailHeaders; for(mh = MailHeaders; mh->name != NULL; mh++) { p = strstr(data, mh->name) + strlen(mh->name) + 1; data = strchr(data, '&'); *data++ = '\0'; mh->contents = URLUnescape(mp, p); if(strcmp(mh->name, "Message") == 0) fprintf(fp, "X-Mailer: Chimera\n\n"); else { if(mh->contents == NULL || strlen(mh->contents) == 0) continue; fprintf(fp,"%s: ", mh->name); } fprintf(fp, "%s\n", mh->contents); } /* signature ?? */ pclose(fp); MPDestroy(mp); f = "mail sent"; } else f = "popen() failed"; return(f); } /* * MailtoActionInit */ static void * MailtoActionInit(ws, wr, class_closure) ChimeraSource ws; ChimeraRequest *wr; void *class_closure; { /* ** get here when click on mailto link ** wr->url points to url including "x-mailtoaction" */ MailtoActionInfo *mi; MemPool mp; ChimeraTaskProc func; mp = MPCreate(); mi = (MailtoActionInfo *)MPCGet(mp, sizeof(MailtoActionInfo)); mi->mp = mp; mi->ws = ws; mi->wr = wr; mi->cres = SourceToResources(ws); func = MailtoAction; mi->wt = TaskSchedule(mi->cres, func, mi); mi->mh = MIMECreateHeader(); MIMEAddField(mi->mh, "content-type", "text/plain"); MIMEAddField(mi->mh, "x-url", mi->wr->url); return(mi); } /* * MailtoActionCancel */ static void MailtoActionCancel(closure) void *closure; { /* nothing to do here ? */ /* what if sendmail "hangs" ? */ return; } /* * MailtoActionDestroy */ static void MailtoActionDestroy(closure) void *closure; { MailtoActionInfo *mi = (MailtoActionInfo *)closure; if (mi->wt != NULL) TaskRemove(mi->cres, mi->wt); MPDestroy(mi->mp); return; } static void MailtoActionGetData(closure, data, len, mh) void *closure; byte **data; size_t *len; MIMEHeader *mh; { MailtoActionInfo *mi = (MailtoActionInfo *)closure; *data = mi->data; *len = mi->len; *mh = mi->mh; return; } chimera-2.0a19/Imakefile100600 11610 11610 1336 6677562032 13346 0ustar johnjohn#include <./Common.tmpl> #define IHaveSubDirs #if HasGcc #ifdef CDebugging #define PassCDebugFlags "CDEBUGFLAGS=-g -Wall" #else #define PassCDebugFlags "CDEBUGFLAGS=-O -Wall" #endif #else #ifdef CDebugging #define PassCDebugFlags "CDEBUGFLAGS=-g $(OS_DEBUG_FLAGS)" #else #define PassCDebugFlags "CDEBUGFLAGS=-O $(OS_DEBUG_FLAGS)" #endif #endif SUBDIRS = port common image html plain proto mxw chimera MakeSubdirs($(SUBDIRS)) InstallSubdirs($(SUBDIRS)) DependSubdirs($(SUBDIRS)) CleanSubdirs($(SUBDIRS)) MakefileSubdirs($(SUBDIRS)) InstallManSubdirs($(SUBDIRS)) myclean: clean $(RM) Common.tmpl Makefile Makefile.bak make.err make.out .depend for i in $(SUBDIRS); do \ $(RM) $$i/Makefile $$i/Makefile.bak $$i/.depend; \ done chimera-2.0a19/CHANGES100600 11610 11610 121014 6724372031 12553 0ustar johnjohn2.0 --- alpha 19 - 19990530 -------- Cancelling a blocked source caused a NULL function to get called...should be fixed. Changed chimera/source.c. Portability changes for the NEC EWS4800/360PX. Yozo Toda Portability changes to make gcc quieter when compiling. Fixed function type errors. Alexander Mai NULL return from malloc() in common/mempool.c at least triggers an error message now but doesn't handle it. Fixed a problem which caused a cached entry to get bypassed. Changes made to TryMemoryCache() in chimera/source.c. alpha 18 - 19990527 ------------------- Fixed bug in proto/file.c that caused chimera to crash when large directory listings were being processed. Hostnames entered in the URL field or with the Open dialog are transformed into http://hostname/. Change made to chimera/request.c. alpha 16/17 - 19990408 ---------------------- Added to the beginning of the key bindings so that they didn't conflict with regular keystrokes. alpha 15 - 19980517 ------------------- Reload flag was ignored in SinkCreate() in chimera/source.c which caused reloads to fail if the document was in core. Started hacking on CSS parser thing. Created html/css.c and html/css.h with some integration with existing html/ code. Image load concurrance increased in html/inline.c. Added patch to chimera/resource.c. Content could be accessed uninitialized in TryMemoryCache(). smarry@pantransit.smar.reptiles.org Problem with uninitialized variable in AddObject() in htm/html.c. smarry@pantransit.smar.reptiles.org Localhost and hostname weren't allowed as proxy hosts. This caused trouble with local proxies like wwwoffle. wr->pup wasn't being passed to HTTPCreateInfo() from HTTPInit(). The request sent to HTTP proxies was not complete. Fixed HTTPGetFilename(). Keyboard accelerators added. Changes in chimera/WWW.c and chimera/head.c Andrew M. Bishop alpha 14 - 19980103 ------------------- Fixed the authorization handling code in proto/http.c that was broken in the previous release. Included string.h in common/mime.c Alexander Mai Modified chimera/Imakefile to work better with OS/2. Alexander Mai Worked on chimera/source.c to make handling of downloads less buggy. Worked on chimera/view.c and chimera/stack.c to make handling of external viewers less buggy. alpha 13 - 19971217 ------------------- Changed common/mime.c to do a better job of parsing the headers that appear in MIMEish streams. Required modifications to other bits of code that called the functions in common/mime.c. Added patch to fix portability problems in image/jpegp.h and image/jpeg.c. Tom Lane Removed buggy error checking abort() thing in html/html.c. Tom Lane Code in proto/http.c reworked a bit to account for changes in common/mime.c and to simplify it a bit. alpha 12 - 19971211 ------------------- Added mention that app-defaults files should be avoided for v2 and that a wrapper should be created if v1 and v2 are being used on the same system to point v2 away from the v1 app-defaults file. Added patch to html/misc.c to fix problems with bold and strong text. Russell King Chimera now looks at the last argument on the command line as the URL. Regis Rampnoux Added patches for missing common.h in files in image/ Alexander Mai Fixed prototype in chimera/ChimeraSource.h "Nelson H. F. Beebe" Patch to frame code in html/frame.c. Dave Davey alpha 11 -------- Fixed memory leak at chimera/stack.c:280. Frame-related memory leak still exists. Fixed access of NULL ptr caused by lack of rows/cols attribute in frameset in html/frame.c. alpha 10 -------- Added patch for EMX/OS2. Alexander Mai Added patch to allow filenames as the initial URL. Added patch to fix relative URLs for redirects in proto/http.c. Julian Coleman alpha 9 ------- Fixed HTMLTitleEnd in html/head.c. Patch for QNX in common/uproc.c and bug in proto/http.c. "D. J. Hawkey Jr." Fixed initialization of parent_url in chimera/request.c. Dave Davey Resource user.email added to use as value for the From: field in proto/mailto.c. alpha 8 ------- prototype for snprintf() added to port_after.h. trouble expected. more prototypes added. ChimeraRequest destroyed twice in chimera/source.c. "Bradley G. Kaiser" Added font fixup code to html/font.c "Bradley G. Kaiser" Tag IDs are now compared instead of tag structure addresses in html/html.c which fixes environment disaster bug spotted by john kraft NULL filename part in URL caused URLs to be resolved incorrectly. common/url.c:resolve_filename() changed. Added mailto code from. Big win. Dave Davey Resource added to allow new head to get triggered on a type of URL. Example: mailto.newhead: true Resource added to allow the user to specify something besides sendmail in proto/mailto.c. alpha 7 ------- Added "find" button. Added string find capability to plain text renderer. Bg/fg color broken. Changed search and query callbacks so they aren't such a pain to deal with. Cleaned up some compiler complaints about functions without prototypes. alpha 6 ------- RequestCreate in chimera/request.c now properly calls the custom URL parser callbacks and allows a URL to be handled completely by a proxy. Moved architecture specific debugging flag selections from the toplevel Imakefile to Common.tmpl.dist. Added patch to html/form.c to fix problem with call to RenderAction. Erik Johannessen Patch provided so that if the path is not defined by the resource view.path then the PATH environment variable is used when the path for external programs is specified. Also, added '/' in mytmpnam in common/util.c. Sander van Malssen Added '()' to the command passed to system() in chimera/view.c. Added popup to display the progress of downloads that will be viewed with external viewers and to allow them to be cancelled. Frame 'src' had to be an absolute URL. Now it can be a relative URL. Made other random hacks in chimera/ and html/ to make the target attribute work. Whoops, it doesn't work yet. Form image submit works better. alpha 5 ------- More work on HTML frames. Added various patches by J.D.Coleman@newcastle.ac.uk Fixed problems with using FILENAME_MAX. Reported by roessner@rbg.informatik.th-darmstadt.de External viewers now work. Bug reported by Yozo Toda Moving to name anchors should work now. The previous position of a document should be remembered correctly now. HTTP basic authentication should work. alpha 4 ------- Moved files from www/ and main/ into chimera/. Reworked stuff and gratituously changed names to satisfy my inner child. Added HTML frames. alpha 3 ------- Added '#include ' to common/mime.c. Removed (XPointer *) from mxw/TextField.c. Older versions of X don't define XPointer. alpha 2 ------- Added patch to www/io.c for HPUX. Tom Lane Added new jpeg.c and jpegp.h. Tom Lane Added linebreak after
          Fixed problem in html/flow.c:WidthFlow(). Width was not calculated correctly after linebreak. Added code in html/flow.c:LayoutFlow() to make
          work. Fixed a few type mismatches lurking in html/*.c. Added modifier for library names in Common.tmpl.dist in case system library names clash. Stuck 'x' on the front of chimera library names to prevent clashes. alpha 1 ------- Added patch to html/font.c to make font weight selection better. Jean-Marc Lasgouttes Added patch to HTMLTDInsert() to deal with missing correctly. Added another tag handling kludge function to HTMLTag. This one is used to figure out how to clamp down end tags for things like
            and . cfh-2.0 ------- alpha 171-190 ------------- Entities are case sensitive. Changed strncasecmp to strncmp. Erik Fixed code in common/mime.c to find the HTTP status. Fixed code for setting path in main/view.c. Various fixes from "D. J. Hawkey Jr." for PRE tags, URL handling, and QNX. Created a bunch of resource access functions to make it easier to access resource values. Made cache resource dealings more reasonable as suggested by Yozo Toda Added chimera.urlLogFile resource. If set to a valid writable file will append a log of URLs that were loaded at the toplevel. Discovered reentrancy problem in main/download.c. Same problem in main/view.c. (should be fixed now) Smarasderagd Removed JCONFIG_INCLUDED from image/jpeg.c because it caused definitions to get messed up in jpeg.h. Tom Lane Resources should now be correctly free'd when a head is destroyed in main/widget.c. Added support for 'Host' field in proto/http.c. Fixed a bunch of memory leaks (but not even close to all of them). Added tracking code to common/list.c and common/mempool.c. Added a 'reusable' flag to the Scheme structure in www/data.c to indicate cached documents can be reused without setting the cache flag which would cause them to be recached. Added argument to WWWCancelData() to allow a distinction between cancelling callbacks and actually cancelling the data. Also hacked around to make sure the code kept track of downloads more correctly. Added code to html/inline.c to make sure that when the reload flag is set that an inline is only reloaded once. Added code to www/context.c to look for the www.maxDownloads resource to set the maximum number of concurrent downloads. Added/fixed the code that actually limits the number of concurrent downloads. Whoops. FTP code communicates failures back up the handler chain. Probably needs more work but should work better. Code in common/ml.c took a dump when untagged text showed up. Should be fixed now. The accept list is now taken in account when searching to see if a current download can be used instead of starting a new download. See TryMemoryCache in data.c for details. Added code to look at www.printLoadMessages resource. Markup language parser code in common/ml.c revised to work a bit better. Mostly changed to make comment handling work better. Patch to add keyboard editting commands to the text widget. Joy! "J.D.Coleman" Added code to highlight tags when selected. If the first document is not HTML then no HTML fonts are created but the HTML class code still tried to free them. Should be fixed now. Added config for AIX 3.2.5. mark olesen Lots of reworked code in html/. alpha 169-170 ------------- -lsocket -lnsl added to OS_LIBS in Common.tmpl.dist for Solaris. Yozo Toda Modified Common.tmpl.dist install directories as suggested by Jean-Marc.Lasgouttes@inria.fr Made config changes for QNX. "D. J. Hawkey Jr." Switched URLParse back to putting NULL in filename if it is zero-length. Doesn't change it if it is NULL. Changed the file: code to change a NULL filename to "/". Added endianism for 68xxx. David Wolfskill Changed column scaling in html/table.c:TablePosition1. Scaled box width didn't include the width of all of the columns when colspan > 1. Changed html/table.c:TablePosition1. Fixed another problem in common/mempool.c and rearranged things a bit. Worked on main/download.c to make downloads behave a little better. Added patch for 1x1 interlaced GIF problem. Smarasderagd Changed the MIME code to try to make it a bit faster. Changes had to be made all over the place. alpha 166-168 ------------- Added file.autoLoad resource. If defined then the file protocol checks to see if the URL specifies a directory and, if it does, checks to see if the file specified in file.autoLoad exists in that directory and loads it instead of a directory listing. Added patch to fix alignment problem in mempool.c. "J.D.Coleman" Code in proto/http.c no longer cares about the useRedirect resource. Let HTTP error messages display instead of trying to trap the messages in proto/http.c. Fixed cache flag bug in proto/http.c. Removed -Wmissing-* because it caused old versions of gcc to become upset. Made sure inputs for forms are removed from any lists they might be in when they're destroyed because the two-pass thing that happens for tables causes a whole heap of trouble. If a cache directory can't be found then a message is printed on stderr. The environment variable WWW_HOME can be used to specify the first document. URLParse always returns "/" instead of a NULL or zero-length filename. Listened to Jonny Quest theme by Reverend Horton Heat. Liked it. alpha 165 --------- Added __convex__ to image/image_endian.h. Added ConvexArchitecture to Common.tmpl.dist. David DeSimone Hopefully Common.tmpl.dist will deal with Solaris more reasonably. Help from lots of people from bug-chimera. Added HPArchitecture based on tip from Otmar Stahl Cut buffer cleared if there is a valid URL inside that is used to start a new shell. Fixed problem with horizontal scrollbar introduced when the trouble-causing arguments were removed from www/WWW.c Replaced 'clock' with 'time' in common/util.c Added DIV tag to html/misc.c. Finally found a really annoying bug in the table code. Rowspan > 1 in the middle of a row caused trouble. Dialogs now have one label area instead of two. alpha 164 --------- Switched over to Alignment struct/union thing in common/mempool.c. Markku Savela . Got rid of trouble-causing arguments in www/WWW.c. alpha 163 --------- Commented out table debugging code. Re-enabled comment parsing in common/ml.c. common/mempool.c uses MEMPOOL_ALIGNSIZE to determine the alignment size. The default is sizeof(size_t). Boxes accessing related data after the data was destroyed causing seg violation in html/module.c:HTMLDestroy. Do box destruction first. Messages for downloading and other activities should appear in the shell(s) that apply. Added extra field to the file dialog so that file operation messages will appear in the right spot. Patch for URL escaping in common/url.c and html/form.c Jake Kesinger Patch for broken font handling in plain/plain.c "T. Alexander Popiel" Fakes before looks bad but shouldn't cause a core file to appear. Missing 'l' in 'lenv' in HTMLOListEnd in html/list.c. Added NetBSDArchitecture to Common.tmpl.dist Added missing definitions to common/common.h for functions in common/list.c "J.D.Coleman" Fixed other random table weirdness (my powers of description are stretched to the max with some of this sludge I'm writing). alpha 112-161 ------------- Lots of code reworked, moved around, and other fun stuff. Added GPL. Added Rob McMullen's TextField widget. Incorporated patch for numbering ordered lists. Jake Kesinger ? Added patch for dealing with malloc failures to the image/ code. Smarasderagd Frames disappeared alpha 111 --------- Made changes with the way frame position is set. The position of a document is passed to the renderer for it to deal with. Fixed anchor handling in the HTML code. Added for check "id" attribute. Erik Corry The HTML code now has a timeout that will destroy an inline if it takes too long to find its size. Moved the cache code into www/. alpha 110 --------- Frames are refreshed when they are resized. Made changes to html/* to improve HTML handling. Comments are handled slightly differently in common/ml.c. FreeBSD added to Common.tmpl.dist. Added support for the dreaded
            tag. alpha 109 --------- Fixed MEMPOOL_DEBUG usage in the defintion of pool. common/mempool.c. NULL pointer accessed in www/frame.c:FrameQuery() sometimes when source requested. Ben Taylor Added http.useRedirect resource which makes HTTP 302s act like 301s. Fixed SELECT form problems and cleaned up the code. Did the same for the textarea code. Fixed MxwGetFont()...was always returning NULL. Reworked CallTagHandler() a bit. XMP added...acts like PRE. Clone will really do a clone now...the URL is taken from the cloned window. The resource chimera.cloneHome can be set to force the clone to use the home page. Listing and XMP should work correctly now. HTML code reworked a bit. Line 235 in www/frame.c used frame->fcontext instead of value like it was supposed to. Fixed a problem with bookmarks...the element handler wasn't handling elements correctly. alpha 108 --------- Fixed problems in html/form.c. Reworked things a bit. Still in bad shape. alpha 107 --------- Changed proportional font default pattern in html/font.c. Big win. Rob McMullen Added patch to fix 'ENDIAN' preprocessor goodies in image/ and fix homeless startup crash. Erik Corry Cleaned up frame and proto handling code in www/proto.c and www/frame.c Made the connection count code in www/proto.c work. Pressing "source" won't cause a reload. Created FrameRedisplay(). Doing a reload caused all subsequent loads to inherit the reload flag. Put a line in Common.tmpl to show where you can force a special compiler. Added margins to the HTML renderer. Defaults to 20. Tags are handled the old way...if tags are overlapped then end tags are simulated to eliminate overlap. Changed font code so that the fixed fonts work the same way as the proportional fonts. Fixed bookmark create problems. Strings were not being allocated correctly...they were auto vars that got wiped out. Worked on the markup parsing. Seems to handle comments and stuff in general more correctly. Simplified Element handling and made all of the 'common/ml' types opaque. More function calls! Less mucking with internals! Worked on HTML list handling...didn't handle bad HTML as well as it could. Added better isspace() called isspace8(). Erik Corry alpha 106 --------- Parentless frames needed a fake parent ID to prevent collions with real parent IDs. Solves all sorts of terrible problems. Added external viewer code. Had to rearrange www/proto.c, www/frame.c, and create src/view.c. Should be faster. Made a whole bunch of changes to the HTML renderer to better deal with errors and to a problem that caused paragraphs (and other tags) to wipe out previous tag environments. Redirect URLs are correctly passed back from protocol handlers to the URL stack. HTTP passes it back for status "Moved permanently" only. Forms fixed. Multi-selects work internally (how useful!). Form image works. Won't crash if no bookmarks are available. Cache now uses an integer ID for the filename that is kept in the cache index. Unfortunately, you can only have 2^31 cache entries on most machines. HTTP code was looking for the location: field and ignoring the status. Nexus server returns location field even when status was not 300-399. This caused a nifty loop. GET /something?mumble queries failed because it was assumed to be NULL terminated but wasn't necessarily NULL terminated. FrameDestroy() was not free'ing everything. Bookmark now works when there is no bookmark file. alpha 104-105 ------------- InitModule_Message() was not initializing ProtoHooks correctly. Smarasderagd Source button works now. Simplified the code in www/io.c...it was getting too hairy without providing any benefits. Renamed functions in www/ and other places to something more reasonable. Changed the behavior of MLMultiGetText() so that it is more reasonable to use. Reworked the forms code a bit: textarea and option text collection is simpler. I note the following typo: cfh102-2.0/www/mime.c: { image/x-xpimap, xpm }, Michael Kellen Moved the stuff in misc/ to proto/. Updated README.hints. Changed the download code so that a save file requester appears at the end of the transfer instead of an entire screen in the main display.
            causes a line break. HTMLQuery() in module/html.c could not deal with a NULL title. Rearranged and messed around with code to try to get the memory usage down a bit. Bookmark code now works pretty much the way it did in 1.65. Bookmark file is an HTML-like file. changes in src/ Added resource to set the maximum length of a cache filename length. See lib/resources for details. I can't remember who asked me for this. Messed around with Common.tmpl and the Imakefiles to make it easier for me. Fixed line layout code to take baselines into account to make the "align" attribute work. Changed a bunch of stuff in html/ */* is added to the end of the accept string. Changed proto/http.c. URL resolution fixed and simplified slightly. '..' caused problems and things like '//' were not removed which messed up the cache. Added common/dir.c and modified www/url.c. Made lots of worthless cosmetic changes to the functions in html/. Added check for _SSIZE_T and _SIZE_T to common/common.h Added image input field to forms support. Fixed FTP. Broke in 103. InitModule_File wasn't initializing structure properly. proto/file.c changed. Forms code memory overrun. html/form.c changed. alpha 103 --------- Readded code to use the base filename of a URL as the default name for saving stuff. aXe scrolling text widget removed. The title was not being terminated at the right time in AddBookmark() in src/bookmark.c. Support for tag added. Jake Kesinger alpha 102 --------- A colon delimited list of filenames can be specified for the dbFiles resource. URL failure was not being reported back to the parent frame. This caused HTML rendering to stop forever waiting for the image. Partially fixed. Reported by Karl Eichwalder . Added support for the size attribute for form text input. Larry Doolittle Paragraph align attribute was being carried over into the following paragraphs if the aligned paragraph didn't have an end tag. Fixed. Reported by Karl Eichwalder Feeling silly...added some support for frames. html/frame.c. Cleaned up the URL load code in HTML and shoved it in html/load.c. HandleSelect() was causing trouble if called for but there was never a
            or more reasonably. Fixed bad declaration for HTMLAttributeToID in html/html.h. Steven E Lumos Made Common.tmpl.dist style a bit more consistent. Added patch submitted in 1994(!) to map URLs to other URLs using regular expressions. Theodore Ts'o This has been disabled for now for performance reasons. When a new head/shell is started the cut buffer is examined for a URL. If there is a valid URL at the beginning then it will be loaded. Changed main/main.c. In url.c:URLParse look for other separators not just '/' before ':'. Revampled www/request.c:WWWBuildRequest to make it more efficient hopefully. Baseline should be fixed for forms widgets. Switched over to using snprintf and fixed size buffers in a few places. Mostly in message handling. Included code for snprintf from LPRng-2.4.2. www/mime.c:MIMEFindData searched one byte too far which caused really all sorts of irritating trouble. alpha 162 --------- Added LinuxArchitecture to Common.tmpl.dist Proportional scaling of table columns added to html/table.c. Added BSD386Architecture to Common.tmpl.dist Baseline code for inline images fixed. Referenced NULL pointer in SubmitCallback fixed in html/form.c. Table width was ending up as 0 (probably a bug) which was later used in a division. Fixed to not cause SIGFPE. All traces of the app-defaults file removed (hopefully). Right floating objects should now float to the right hand side even if there aren't enough objects to push it to the edge. or before a