Branch: refs/heads/master Author: Frank Lanitz frank@frank.uvena.de Committer: Frank Lanitz frank@frank.uvena.de Date: Sun, 26 Aug 2012 09:16:12 Commit: ca0c77f32eaa317784e1624900fd3128a72d2ffe https://github.com/geany/geany-plugins/commit/ca0c77f32eaa317784e1624900fd31...
Log Message: ----------- Merge pull request #61 from codebrainz/markdown
New Plugin: Markdown
Modified Paths: -------------- Makefile.am build/markdown.m4 configure.ac markdown/AUTHORS markdown/COPYING markdown/ChangeLog markdown/Makefile.am markdown/NEWS markdown/README markdown/discount/COPYRIGHT markdown/discount/CREDITS markdown/discount/Csio.c markdown/discount/Makefile.am markdown/discount/amalloc.c markdown/discount/amalloc.h markdown/discount/basename.c markdown/discount/blocktags markdown/discount/config.h markdown/discount/css.c markdown/discount/cstring.h markdown/discount/discount-changes.patch markdown/discount/docheader.c markdown/discount/dumptree.c markdown/discount/emmatch.c markdown/discount/flags.c markdown/discount/generate.c markdown/discount/html5.c markdown/discount/markdown.c markdown/discount/markdown.h markdown/discount/mkdio.c markdown/discount/mkdio.h markdown/discount/resource.c markdown/discount/setup.c markdown/discount/tags.c markdown/discount/tags.h markdown/discount/toc.c markdown/discount/version.c markdown/discount/xml.c markdown/discount/xmlpage.c markdown/docs/Makefile.am markdown/docs/help.html markdown/docs/plugin.png markdown/docs/plugin_mgr.png markdown/docs/plugin_prefs.png markdown/docs/plugin_small.png markdown/docs/set_filetype.png markdown/docs/settings.png markdown/src/Makefile.am markdown/src/conf.c markdown/src/conf.h markdown/src/plugin.c markdown/src/viewer.c markdown/src/viewer.h
Modified: Makefile.am 4 files changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -90,6 +90,10 @@ if ENABLE_GPROJECT SUBDIRS += gproject endif
+if ENABLE_MARKDOWN +SUBDIRS += markdown +endif + if ENABLE_MULTITERM SUBDIRS += multiterm endif
Modified: build/markdown.m4 21 files changed, 21 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,21 @@ +AC_DEFUN([GP_CHECK_MARKDOWN], +[ + GP_ARG_DISABLE([markdown], [auto]) + + GTK_VERSION=2.16 + WEBKIT_VERSION=1.1.13 + + GP_CHECK_PLUGIN_DEPS([markdown], [MARKDOWN], + [gtk+-2.0 >= ${GTK_VERSION} + webkit-1.0 >= ${WEBKIT_VERSION} + gthread-2.0]) + + GP_STATUS_PLUGIN_ADD([Markdown], [$enable_markdown]) + + AC_CONFIG_FILES([ + markdown/Makefile + markdown/discount/Makefile + markdown/src/Makefile + markdown/docs/Makefile + ]) +])
Modified: configure.ac 1 files changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -46,6 +46,7 @@ GP_CHECK_GEANYVC GP_CHECK_GEANYPG GP_CHECK_GENIUSPASTE GP_CHECK_GPROJECT +GP_CHECK_MARKDOWN GP_CHECK_MULTITERM GP_CHECK_PRETTYPRINTER GP_CHECK_SHIFTCOLUMN
Modified: markdown/AUTHORS 1 files changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1 @@ +Matthew Brush mbrush@codebrainz.ca
Modified: markdown/COPYING 339 files changed, 339 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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 + + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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. + + <signature of Ty Coon>, 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 Lesser General +Public License instead of this License.
Modified: markdown/ChangeLog 0 files changed, 0 insertions(+), 0 deletions(-) =================================================================== No diff available, check online
Modified: markdown/Makefile.am 4 files changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,4 @@ +include $(top_srcdir)/build/vars.auxfiles.mk + +SUBDIRS = discount src docs +plugin = markdown
Modified: markdown/NEWS 0 files changed, 0 insertions(+), 0 deletions(-) =================================================================== No diff available, check online
Modified: markdown/README 182 files changed, 182 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,182 @@ +Markdown +======== + +.. image:: plugin_small.png + :align: center + :alt: The Markdown plugin in action + :target: plugin.png + +.. contents:: + +About +----- + +This plugin provides a real-time preview of rendered Markdown, that is, +`Markdown http://daringfireball.net/projects/markdown`_ converted to HTML +and inserted into an HTML template and loaded into a +`WebKit http://www.webkit.org`_ view. + +Features +-------- + + * Allows placing the preview in the sidebar or message window areas + * Updates the preview on-the-fly as you type, automatically. + * Allows simple customization of fonts and colours and complete control + with custom template files. + +Usage +----- + +The preview is active by default for all documents with a Markdown filetype +set. To set a document's filetype, choose from the menus: + +.. image:: set_filetype.png + :align: center + :alt: Choosing Document->Set Filetype->Markup Languages->Markdown source file + :target: set_filetype.png + +Other than that the operation should be fully automatic. Use the Plugin +Preferences mechanism to customize some settings as described below. + +For more information on Markdown syntax, read the +`Markdown Syntax Documentation +http://daringfireball.net/projects/markdown/syntax`_. + +*Preferences* +^^^^^^^^^^^^^ + +.. image:: settings.png + :align: center + :alt: The Markdown plugin's preferences GUI + :target: settings.png + +Using Geany's normal Plugin Preferences mechanism, you can customize some +important settings related to the Markdown preview. The preferences dialog +allows changing the following settings: + +========= =================================================================== +Name Description +========= =================================================================== +Position The area of Geany's UI to put the preview view, currently either + in the sidebar or message window (bottom) areas. +Font The regular body font of the preview. +Code Font The font to use for the code tags (monospaced) font of the preview. +BG Color The preview's background color. +FG Color The preview's foreground (text) color. +Template The file containing the HTML template for the preview. +========= =================================================================== + +There's two ways to access the Plugin settings, one is through the +Plugin Manager using the buttons highlighted below: + +.. image:: plugin_mgr.png + :align: center + :alt: The Plugin Manager dialog showing the Help and Preferences buttons. + :target: plugin_mgr.png + +Clicking the ``Help`` button opens this document in HTML format in your web +browser. The other way to access the plugin's preferences is through the +``Edit`` menu as pictured below: + +.. image:: plugin_prefs.png + :align: center + :alt: Accessing plugin preferences from the Edit menu. + :target: plugin_prefs.png + +*Custom Templates* +^^^^^^^^^^^^^^^^^^ + +You can provide a custom HTML template file which contains the substitution +strings that get replaced at run-time. The following substitution strings +are available: + +============================ ================================================ +Substitution String Description +============================ ================================================ +``@@markdown@@`` The most important substitution string and + gets replaced with the HTML generated from the + editor's Markdown buffer. Not having this one + in the template makes the plugin completely + useless. +``@@font_name@@`` The normal font family. +``@@code_font_name@@`` The code/monospace font family. +``@@font_point_size@@`` The size in points of the normal font. +``@@code_font_point_size@@`` The size in points of the code/monospace font. +``@@bg_color@@`` The background color in hex/HTML color notation. +``@@fg_color@@`` The foreground (text) color in hex/HTML color + notation. +============================ ================================================ + +The default template file (at the time of writing) contains the following +HTML code:: + + <html> + <head> + <style type="text/css"> + body { + font-family: @@font_name@@; + font-size: @@font_point_size@@pt; + background-color: @@bg_color@@; + color: @@fg_color@@; + } + code { + font-family: @@code_font_name@@; + font-size: @@code_font_point_size@@pt; + } + </style> + </head> + <body> + @@markdown@@ + </body> + </html> + +As you can see it's just normal HTML/CSS and you can tweak it to make the +preview contents look exactly how you want. The preview view is a WebKit +browser, the same one used by `Google's Chrome Browser +http://google.com/chrome`_ and `Apple's Safari Browser +http://apple.com/safari`_ as well as numerous others, and it supports many +modern features such as HTML5 and CSS3 support (at least partially). + +If you mess up the default ``template.html`` file, just delete it and the +default one will be recreated the next time the Markdown plugin is reloaded +(for example when Geany restarts). + +Requirements +------------ + +The plugin depends on the following libraries: + + * `GTK+ http://www.gtk.org`_ 2.16 or greater + * `WebKitGTK+ http://webkitgtk.org`_ 1.1.18 or greater + +License +------- + +The Markdown plugin is licensed under the GNU General Public License, +version 2. For the full text of the license, please visit +http://www.gnu.org/licenses/gpl-2.0.html. The GPL license covers all code +and files *not* in the ``discount`` directory. + +All code inside the ``discount`` directory is under a BSD-style license +(see the ``discount/COPYRIGHT`` file) and all contributions to this code +*will* remain under this license. This will make it easier to integrate +improvements to Discount back upstream if it ever makes sense. So far the +only changes are superficial to allow it to build with the Geany-Plugins +build system and to prevent some compiler warnings. + +Authors +------- + +The Geany Markdown plugin is written and maintained by:: + + Matthew Brush <matt(at)geany(dot)org> + +The plugin includes the Discount Markdown library, developed by:: + + David Loren Parsons http://www.pell.portland.or.us/~orc + +Contact +------- + +You can email me at ``matt(at)geany(dot)org``, or find me on the +``#geany`` IRC channel on FreeNode, with the nickname ``codebrainz``.
Modified: markdown/discount/COPYRIGHT 47 files changed, 47 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,47 @@ +->Copyright (C) 2007 David Loren Parsons. +All rights reserved.<- + +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, sublicence, 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: + + 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, and in the same place and form as other + copyright, license and disclaimer information. + + 3. The end-user documentation included with the redistribution, if + any, must include the following acknowledgment: + + This product includes software developed by + David Loren Parsons http://www.pell.portland.or.us/~orc + + in the same place and form as other third-party acknowledgments. + Alternately, this acknowledgment may appear in the software + itself, in the same form and location as other such third-party + acknowledgments. + + 4. Except as contained in this notice, the name of David Loren + Parsons shall not be used in advertising or otherwise to promote + the sale, use or other dealings in this Software without prior + written authorization from David Loren Parsons. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 DAVID LOREN PARSONS 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.
Modified: markdown/discount/CREDITS 35 files changed, 35 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,35 @@ +Discount is primarily my work, but it has only reached the point +where it is via contributions, critiques, and bug reports from a +host of other people, some of which are listed before. If your +name isn't on this list, please remind me + -david parsons (orc@pell.chi.il.us) + + +Josh Wood -- Plan9 support. +Mike Schiraldi -- Reddit style automatic links, MANY MANY MANY + bug reports about boundary conditions and + places where I didn't get it right. +Jjgod Jiang -- Table of contents support. +Petite Abeille -- Many bug reports about places where I didn't + get it right. +Tim Channon -- inspiration for the `mkd_xhtmlpage()` function +Christian Herenz-- Many bug reports regarding my implementation of + `[]()` and `![]()` +A.S.Bradbury -- Portability bug reports for 64 bit systems. +Joyent -- Loan of a solaris box so I could get discount + working under solaris. +Ryan Tomayko -- Portability requests (and the rdiscount ruby + binding.) +yidabu -- feedback on the documentation, bug reports + against utf-8 support. +Pierre Joye -- bug reports, php discount binding. +Masayoshi Sekimura- perl discount binding. +Jeremy Hinegardner- bug reports about list handling. +Andrew White -- bug reports about the format of generated urls. +Steve Huff -- bug reports about Makefile portability (for Fink) +Ignacio Burgue?o-- bug reports about `>%class%` +Henrik Nyh -- bug reports about embedded html handling. +John J. Foerch -- bug reports about incorrect `–` and `—` + translations. + +
Modified: markdown/discount/Csio.c 61 files changed, 61 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,61 @@ +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include "cstring.h" +#include "markdown.h" +#include "amalloc.h" + + +/* putc() into a cstring + */ +void +Csputc(int c, Cstring *iot) +{ + EXPAND(*iot) = c; +} + + +/* printf() into a cstring + */ +int +Csprintf(Cstring *iot, char *fmt, ...) +{ + va_list ptr; + int siz=100; + + do { + RESERVE(*iot, siz); + va_start(ptr, fmt); + siz = vsnprintf(T(*iot)+S(*iot), ALLOCATED(*iot)-S(*iot), fmt, ptr); + va_end(ptr); + } while ( siz > (ALLOCATED(*iot)-S(*iot)) ); + + S(*iot) += siz; + return siz; +} + + +/* write() into a cstring + */ +int +Cswrite(Cstring *iot, char *bfr, int size) +{ + RESERVE(*iot, size); + memcpy(T(*iot)+S(*iot), bfr, size); + S(*iot) += size; + return size; +} + + +/* reparse() into a cstring + */ +void +Csreparse(Cstring *iot, char *buf, int size, int flags) +{ + MMIOT f; + ___mkd_initmmiot(&f, 0); + ___mkd_reparse(buf, size, 0, &f); + ___mkd_emblock(&f); + SUFFIX(*iot, T(f.out), S(f.out)); + ___mkd_freemmiot(&f, 0); +}
Modified: markdown/discount/Makefile.am 31 files changed, 31 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,31 @@ +noinst_LTLIBRARIES = libdiscount.la + +libdiscount_la_SOURCES = \ + amalloc.c \ + amalloc.h \ + basename.c \ + config.h \ + Csio.c \ + css.c \ + cstring.h \ + docheader.c \ + dumptree.c \ + emmatch.c \ + flags.c \ + generate.c \ + html5.c \ + markdown.c \ + markdown.h \ + mkdio.c \ + mkdio.h \ + resource.c \ + setup.c \ + tags.c \ + tags.h \ + toc.c \ + version.c \ + xml.c \ + xmlpage.c + +libdiscount_la_CPPFLAGS = @MARKDOWN_CFLAGS@ +libdiscount_la_LIBADD = @MARKDOWN_LIBS@
Modified: markdown/discount/amalloc.c 111 files changed, 111 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,111 @@ +/* + * debugging malloc()/realloc()/calloc()/free() that attempts + * to keep track of just what's been allocated today. + */ + +#include <stdio.h> +#include <stdlib.h> + +#define MAGIC 0x1f2e3d4c + +struct alist { int magic, size; struct alist *next, *last; }; + +static struct alist list = { 0, 0, 0, 0 }; + +static int mallocs=0; +static int reallocs=0; +static int frees=0; + +void * +acalloc(int size, int count) +{ + struct alist *ret = calloc(size + sizeof(struct alist), count); + + if ( ret ) { + ret->magic = MAGIC; + ret->size = size * count; + if ( list.next ) { + ret->next = list.next; + ret->last = &list; + ret->next->last = ret; + list.next = ret; + } + else { + ret->last = ret->next = &list; + list.next = list.last = ret; + } + ++mallocs; + return ret+1; + } + return 0; +} + + +void* +amalloc(int size) +{ + return acalloc(size,1); +} + + +void +afree(void *ptr) +{ + struct alist *p2 = ((struct alist*)ptr)-1; + + if ( p2->magic == MAGIC ) { + p2->last->next = p2->next; + p2->next->last = p2->last; + ++frees; + free(p2); + } + else + free(ptr); +} + + +void * +arealloc(void *ptr, int size) +{ + struct alist *p2 = ((struct alist*)ptr)-1; + struct alist save; + + if ( p2->magic == MAGIC ) { + save.next = p2->next; + save.last = p2->last; + p2 = realloc(p2, sizeof(*p2) + size); + + if ( p2 ) { + p2->size = size; + p2->next->last = p2; + p2->last->next = p2; + ++reallocs; + return p2+1; + } + else { + save.next->last = save.last; + save.last->next = save.next; + return 0; + } + } + return realloc(ptr, size); +} + + +void +adump() +{ + struct alist *p; + + + for ( p = list.next; p && (p != &list); p = p->next ) { + fprintf(stderr, "allocated: %d byte%s\n", p->size, (p->size==1) ? "" : "s"); + fprintf(stderr, " [%.*s]\n", p->size, (char*)(p+1)); + } + + if ( getenv("AMALLOC_STATISTICS") ) { + fprintf(stderr, "%d malloc%s\n", mallocs, (mallocs==1)?"":"s"); + fprintf(stderr, "%d realloc%s\n", reallocs, (reallocs==1)?"":"s"); + fprintf(stderr, "%d free%s\n", frees, (frees==1)?"":"s"); + } +}
Modified: markdown/discount/amalloc.h 29 files changed, 29 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,29 @@ +/* + * debugging malloc()/realloc()/calloc()/free() that attempts + * to keep track of just what's been allocated today. + */ +#ifndef AMALLOC_D +#define AMALLOC_D + +#include "config.h" + +#ifdef USE_AMALLOC + +extern void *amalloc(int); +extern void *acalloc(int,int); +extern void *arealloc(void*,int); +extern void afree(void*); +extern void adump(); + +#define malloc amalloc +#define calloc acalloc +#define realloc arealloc +#define free afree + +#else + +#define adump() (void)1 + +#endif + +#endif/*AMALLOC_D*/
Modified: markdown/discount/basename.c 43 files changed, 43 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,43 @@ +/* + * mkdio -- markdown front end input functions + * + * Copyright (C) 2007 David L Parsons. + * The redistribution terms are provided in the COPYRIGHT file that must + * be distributed with this source code. + */ +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#include "mkdio.h" +#include "cstring.h" +#include "amalloc.h" + +static char * +e_basename(const char *string, const int size, void *context) +{ + char *ret; + char *base = (char*)context; + + if ( base && string && (*string == '/') && (ret=malloc(strlen(base)+size+2)) ) { + strcpy(ret, base); + strncat(ret, string, size); + return ret; + } + return 0; +} + +static void +e_free(char *string, void *context) +{ + if ( string ) free(string); +} + +void +mkd_basename(MMIOT *document, char *base) +{ + mkd_e_url(document, e_basename); + mkd_e_data(document, base); + mkd_e_free(document, e_free); +}
Modified: markdown/discount/blocktags 33 files changed, 33 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,33 @@ +static struct kw blocktags[] = { + { "P", 1, 0 }, + { "DL", 2, 0 }, + { "H1", 2, 0 }, + { "H2", 2, 0 }, + { "H3", 2, 0 }, + { "H4", 2, 0 }, + { "H5", 2, 0 }, + { "H6", 2, 0 }, + { "HR", 2, 1 }, + { "OL", 2, 0 }, + { "UL", 2, 0 }, + { "BDO", 3, 0 }, + { "DFN", 3, 0 }, + { "DIV", 3, 0 }, + { "MAP", 3, 0 }, + { "PRE", 3, 0 }, + { "WBR", 3, 0 }, + { "XMP", 3, 0 }, + { "NOBR", 4, 0 }, + { "STYLE", 5, 0 }, + { "TABLE", 5, 0 }, + { "CENTER", 6, 0 }, + { "IFRAME", 6, 0 }, + { "OBJECT", 6, 0 }, + { "SCRIPT", 6, 0 }, + { "ADDRESS", 7, 0 }, + { "LISTING", 7, 0 }, + { "PLAINTEXT", 9, 0 }, + { "BLOCKQUOTE", 10, 0 }, +}; + +#define NR_blocktags 29
Modified: markdown/discount/config.h 35 files changed, 35 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,35 @@ +/* + * In the upstream Discount tree, this file is auto-generated, for the + * Geany plugin it's not. + */ +#ifndef DISCOUNT_CONFIG_H +#define DISCOUNT_CONFIG_H 1 + +#include <glib.h> + +G_BEGIN_DECLS + +#define OS_LINUX G_OS_UNIX +#define USE_DISCOUNT_DL 0 +#define DWORD guint32 +#define WORD guint16 +#define BYTE guint8 +#define HAVE_BASENAME 0 +#define HAVE_LIBGEN_H 0 +#define HAVE_PWD_H 0 +#define HAVE_GETPWUID 0 +#define HAVE_SRANDOM 0 +#define INITRNG(x) srandom((unsigned int)x) +#define HAVE_BZERO 0 +#define HAVE_RANDOM 0 +#define COINTOSS() (random()&1) +#define HAVE_STRCASECMP 0 +#define HAVE_STRNCASECMP 0 +#define HAVE_FCHDIR 0 +#define TABSTOP 4 +#define HAVE_MALLOC_H 0 +#define VERSION "2.1.3" + +G_END_DECLS + +#endif /* DISCOUNT_CONFIG_H */
Modified: markdown/discount/css.c 85 files changed, 85 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,85 @@ +/* markdown: a C implementation of John Gruber's Markdown markup language. + * + * Copyright (C) 2009 David L Parsons. + * The redistribution terms are provided in the COPYRIGHT file that must + * be distributed with this source code. + */ +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> + +#include "config.h" + +#include "cstring.h" +#include "markdown.h" +#include "amalloc.h" + + +/* + * dump out stylesheet sections. + */ +static void +stylesheets(Paragraph *p, Cstring *f) +{ + Line* q; + + for ( ; p ; p = p->next ) { + if ( p->typ == STYLE ) { + for ( q = p->text; q ; q = q->next ) { + Cswrite(f, T(q->text), S(q->text)); + Csputc('\n', f); + } + } + if ( p->down ) + stylesheets(p->down, f); + } +} + + +/* dump any embedded styles to a string + */ +int +mkd_css(Document *d, char **res) +{ + Cstring f; + int size; + + if ( res && d && d->compiled ) { + *res = 0; + CREATE(f); + RESERVE(f, 100); + stylesheets(d->code, &f); + + if ( (size = S(f)) > 0 ) { + EXPAND(f) = 0; + /* HACK ALERT! HACK ALERT! HACK ALERT! */ + *res = T(f);/* we know that a T(Cstring) is a character pointer */ + /* so we can simply pick it up and carry it away, */ + /* leaving the husk of the Ctring on the stack */ + /* END HACK ALERT */ + } + else + DELETE(f); + return size; + } + return EOF; +} + + +/* dump any embedded styles to a file + */ +int +mkd_generatecss(Document *d, FILE *f) +{ + char *res; + int written = EOF, size = mkd_css(d, &res); + + if ( size > 0 ) + written = fwrite(res, 1, size, f); + if ( res ) + free(res); + return (written == size) ? size : EOF; +}
Modified: markdown/discount/cstring.h 77 files changed, 77 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,77 @@ +/* two template types: STRING(t) which defines a pascal-style string + * of element (t) [STRING(char) is the closest to the pascal string], + * and ANCHOR(t) which defines a baseplate that a linked list can be + * built up from. [The linked list /must/ contain a ->next pointer + * for linking the list together with.] + */ +#ifndef _CSTRING_D +#define _CSTRING_D + +#include <string.h> +#include <stdlib.h> + +#ifndef __WITHOUT_AMALLOC +# include "amalloc.h" +#endif + +/* expandable Pascal-style string. + */ +#define STRING(type) struct { type *text; int size, alloc; } + +#define CREATE(x) ( (T(x) = (void*)0), (S(x) = (x).alloc = 0) ) +#define EXPAND(x) (S(x)++)[(S(x) < (x).alloc) \ + ? (T(x)) \ + : (T(x) = T(x) ? realloc(T(x), sizeof T(x)[0] * ((x).alloc += 100)) \ + : malloc(sizeof T(x)[0] * ((x).alloc += 100)) )] + +#define DELETE(x) ALLOCATED(x) ? (free(T(x)), S(x) = (x).alloc = 0) \ + : ( S(x) = 0 ) +#define CLIP(t,i,sz) \ + ( ((i) >= 0) && ((sz) > 0) && (((i)+(sz)) <= S(t)) ) ? \ + (memmove(&T(t)[i], &T(t)[i+sz], (S(t)-(i+sz)+1)*sizeof(T(t)[0])), \ + S(t) -= (sz)) : -1 + +#define RESERVE(x, sz) T(x) = ((x).alloc > S(x) + (sz) \ + ? T(x) \ + : T(x) \ + ? realloc(T(x), sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x))) \ + : malloc(sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x)))) +#define SUFFIX(t,p,sz) \ + memcpy(((S(t) += (sz)) - (sz)) + \ + (T(t) = T(t) ? realloc(T(t), sizeof T(t)[0] * ((t).alloc += sz)) \ + : malloc(sizeof T(t)[0] * ((t).alloc += sz))), \ + (p), sizeof(T(t)[0])*(sz)) + +#define MDPREFIX(t,p,sz) \ + RESERVE( (t), (sz) ); \ + if ( S(t) ) { memmove(T(t)+(sz), T(t), S(t)); } \ + memcpy( T(t), (p), (sz) ); \ + S(t) += (sz) + +/* reference-style links (and images) are stored in an array + */ +#define T(x) (x).text +#define S(x) (x).size +#define ALLOCATED(x) (x).alloc + +/* abstract anchor type that defines a list base + * with a function that attaches an element to + * the end of the list. + * + * the list base field is named .text so that the T() + * macro will work with it. + */ +#define ANCHOR(t) struct { t *text, *end; } +#define E(t) ((t).end) + +#define ATTACH(t, p) ( T(t) ? ( (E(t)->next = (p)), (E(t) = (p)) ) \ + : ( (T(t) = E(t) = (p)) ) ) + +typedef STRING(char) Cstring; + +extern void Csputc(int, Cstring *); +extern int Csprintf(Cstring *, char *, ...); +extern int Cswrite(Cstring *, char *, int); +extern void Csreparse(Cstring *, char *, int, int); + +#endif/*_CSTRING_D*/
Modified: markdown/discount/discount-changes.patch 1006 files changed, 1006 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,1006 @@ +Only in discount/: blocktags +Only in discount/: config.h +Only in discount-2.1.3/: configure.inc +Only in discount-2.1.3/: configure.sh +diff -ru discount-2.1.3/cstring.h discount/cstring.h +--- discount-2.1.3/cstring.h 2012-01-16 13:08:52.000000000 -0800 ++++ discount/cstring.h 2012-07-16 02:46:53.027807216 -0700 +@@ -42,7 +42,7 @@ + : malloc(sizeof T(t)[0] * ((t).alloc += sz))), \ + (p), sizeof(T(t)[0])*(sz)) + +-#define PREFIX(t,p,sz) \ ++#define MDPREFIX(t,p,sz) \ + RESERVE( (t), (sz) ); \ + if ( S(t) ) { memmove(T(t)+(sz), T(t), S(t)); } \ + memcpy( T(t), (p), (sz) ); \ +Only in discount/: .deps +Only in discount/: discount-changes.patch +diff -ru discount-2.1.3/emmatch.c discount/emmatch.c +--- discount-2.1.3/emmatch.c 2012-01-16 13:08:52.000000000 -0800 ++++ discount/emmatch.c 2012-07-16 02:46:53.031807216 -0700 +@@ -141,7 +141,7 @@ + + emblock(f, first, e); + +- PREFIX(start->b_text, emtags[match-1].open, emtags[match-1].size-1); ++ MDPREFIX(start->b_text, emtags[match-1].open, emtags[match-1].size-1); + SUFFIX(end->b_post, emtags[match-1].close, emtags[match-1].size); + + emmatch(f, first, last); +diff -ru discount-2.1.3/generate.c discount/generate.c +--- discount-2.1.3/generate.c 2012-01-16 13:08:52.000000000 -0800 ++++ discount/generate.c 2012-07-16 17:56:36.659229192 -0700 +@@ -115,7 +115,7 @@ + Qchar(int c, MMIOT *f) + { + block *cur; +- ++ + if ( S(f->Q) == 0 ) { + cur = &EXPAND(f->Q); + memset(cur, 0, sizeof *cur); +@@ -125,7 +125,7 @@ + cur = &T(f->Q)[S(f->Q)-1]; + + EXPAND(cur->b_text) = c; +- ++ + } + + +@@ -188,7 +188,7 @@ + MMIOT sub; + + ___mkd_initmmiot(&sub, f->footnotes); +- ++ + sub.flags = f->flags | flags; + sub.cb = f->cb; + sub.ref_prefix = f->ref_prefix; +@@ -196,10 +196,10 @@ + push(bfr, size, &sub); + EXPAND(sub.in) = 0; + S(sub.in)--; +- ++ + text(&sub); + ___mkd_emblock(&sub); +- ++ + Qwrite(T(sub.out), S(sub.out), f); + + ___mkd_freemmiot(&sub, f->footnotes); +@@ -223,7 +223,7 @@ + if ( !( ispunct(c) || isspace(c) ) ) + Qchar('\', f); + } +- ++ + if ( c == '&' ) + Qstring("&", f); + else if ( c == '<' ) +@@ -355,7 +355,7 @@ + /* extract a <...>-encased url from the input stream. + * (markdown 1.0.2b8 compatibility; older versions + * of markdown treated the < and > as syntactic +- * sugar that didn't have to be there. 1.0.2b8 ++ * sugar that didn't have to be there. 1.0.2b8 + * requires a closing >, and then falls into the + * title or closing ) + */ +@@ -385,13 +385,13 @@ + good=1; + else if ( image && (c == '=') && linkysize(f,p) ) + good=1; +- else ++ else + good=( c == ')' ); + + if ( good ) { + if ( peek(f, 1) == ')' ) + pull(f); +- ++ + ___mkd_tidy(&p->link); + } + +@@ -437,12 +437,12 @@ + } + if ( peek(f, 1) == ')' ) + pull(f); +- ++ + ___mkd_tidy(&p->link); +- ++ + if ( mayneedtotrim && (T(p->link)[S(p->link)-1] == '>') ) + --S(p->link); +- ++ + return 1; + } + +@@ -453,12 +453,12 @@ + static struct _protocol { + char *name; + int nlen; +-} protocol[] = { ++} protocol[] = { + #define _aprotocol(x) { x, (sizeof x)-1 } +- _aprotocol( "https:" ), +- _aprotocol( "http:" ), ++ _aprotocol( "https:" ), ++ _aprotocol( "http:" ), + _aprotocol( "news:" ), +- _aprotocol( "ftp:" ), ++ _aprotocol( "ftp:" ), + #undef _aprotocol + }; + #define NRPROTOCOLS (sizeof protocol / sizeof protocol[0]) +@@ -479,7 +479,7 @@ + + /* + * all the tag types that linkylinky can produce are +- * defined by this structure. ++ * defined by this structure. + */ + typedef struct linkytype { + char *pat; +@@ -538,12 +538,12 @@ + printlinkyref(MMIOT *f, linkytype *tag, char *link, int size) + { + char *edit; +- ++ + if ( f->flags & IS_LABEL ) + return; +- ++ + Qstring(tag->link_pfx, f); +- ++ + if ( tag->kind & IS_URL ) { + if ( f->cb && f->cb->e_url && (edit = (*f->cb->e_url)(link, size, f->cb->e_data)) ) { + puturl(edit, strlen(edit), f, 0); +@@ -583,7 +583,7 @@ + { + if ( ref->flags & REFERENCED ) + return 0; +- ++ + if ( f->flags & IS_LABEL ) + ___mkd_reparse(T(text), S(text), linkt.flags, f); + else { +@@ -659,7 +659,7 @@ + int start = mmiottell(f); + Cstring name; + Footnote key, *ref; +- ++ + int status = 0; + int extra_footnote = 0; + +@@ -677,7 +677,7 @@ + + if ( isspace(peek(f,1)) ) + pull(f); +- ++ + if ( peek(f,1) == '[' ) { + pull(f); /* consume leading '[' */ + goodlink = linkylabel(f, &key.tag); +@@ -692,7 +692,7 @@ + if ( (f->flags & MKD_EXTRA_FOOTNOTE) && (!image) && S(name) && T(name)[0] == '^' ) + extra_footnote = 1; + } +- ++ + if ( goodlink ) { + if ( !S(key.tag) ) { + DELETE(key.tag); +@@ -737,7 +737,7 @@ + } + } + +- ++ + /* + * convert an email address to a string of nonsense + */ +@@ -775,7 +775,7 @@ + { + int size, count, c; + int subsize=0, subtick=0; +- ++ + *endticks = ticks; + for (size = 0; (c=peek(f,size+ticks)) != EOF; size ++) { + if ( (c == tickchar) && ( count = nrticks(size+ticks,tickchar,f)) ) { +@@ -836,7 +836,7 @@ + + if ( size > 1 && peek(f, size-1) == ' ' ) --size; + if ( peek(f,i) == ' ' ) ++i, --size; +- ++ + Qstring("<code>", f); + code(f, cursor(f)+(i-1), size); + Qstring("</code>", f); +@@ -873,17 +873,17 @@ + maybe_address(char *p, int size) + { + int ok = 0; +- ++ + for ( ;size && (isalnum(*p) || strchr("._-+*", *p)); ++p, --size) + ; + + if ( ! (size && *p == '@') ) + return 0; +- ++ + --size, ++p; + + if ( size && *p == '.' ) return 0; +- ++ + for ( ;size && (isalnum(*p) || strchr("._-+", *p)); ++p, --size ) + if ( *p == '.' && size > 1 ) ok = 1; + +@@ -902,7 +902,7 @@ + int address= 0; + int mailto = 0; + char *text = cursor(f); +- ++ + if ( f->flags & MKD_NOLINKS ) return 0; + + if ( (size > 7) && strncasecmp(text, "mailto:", 7) == 0 ) { +@@ -912,10 +912,10 @@ + address = 1; + mailto = 7; /* 7 is the length of "mailto:"; we need this */ + } +- else ++ else + address = maybe_address(text, size); + +- if ( address ) { ++ if ( address ) { + Qstring("<a href="", f); + if ( !mailto ) { + /* supply a mailto: protocol if one wasn't attached */ +@@ -982,7 +982,7 @@ + return 0; + else + size++; +- ++ + if ( forbidden_tag(f) ) + return 0; + +@@ -996,7 +996,7 @@ + return 1; + } + } +- ++ + return 0; + } + +@@ -1226,7 +1226,7 @@ + else + Qchar(c, f); + break; +- ++ + case '!': if ( peek(f,1) == '[' ) { + pull(f); + if ( tag_text(f) || !linkylinky(1, f) ) +@@ -1296,7 +1296,7 @@ + Qem(f,c,rep); + } + break; +- ++ + case '~': if ( (f->flags & (MKD_NOSTRIKETHROUGH|MKD_TAGTEXT|MKD_STRICT)) || ! tickhandler(f,c,2,0, delspan) ) + Qchar(c, f); + break; +@@ -1317,7 +1317,7 @@ + } + Qchar(c, f); + break; +- ++ + case ':': case '|': + if ( f->flags & MKD_NOTABLES ) { + Qchar('\', f); +@@ -1326,7 +1326,7 @@ + } + Qchar(c, f); + break; +- ++ + case '>': case '#': case '.': case '-': + case '+': case '{': case '}': case ']': + case '!': case '[': case '*': case '_': +@@ -1413,7 +1413,7 @@ + ___mkd_tidy(&p->text); + if ( T(p->text)[S(p->text)-1] == '|' ) + --S(p->text); +- ++ + Qstring("<tr>\n", f); + while ( idx < S(p->text) ) { + first = idx; +@@ -1474,7 +1474,7 @@ + for (p=T(dash->text), start=dash->dle; start < S(dash->text); ) { + char first, last; + int end; +- ++ + last=first=0; + for (end=start ; (end < S(dash->text)) && p[end] != '|'; ++ end ) { + if ( p[end] == '\' ) +@@ -1569,10 +1569,10 @@ + printhtml(Line *t, MMIOT *f) + { + int blanks; +- ++ + for ( blanks=0; t ; t = t->next ) + if ( S(t->text) ) { +- for ( ; blanks; --blanks ) ++ for ( ; blanks; --blanks ) + Qchar('\n', f); + + Qwrite(T(t->text), S(t->text), f); +@@ -1651,7 +1651,7 @@ + display(Paragraph *p, MMIOT *f) + { + if ( !p ) return 0; +- ++ + switch ( p->typ ) { + case STYLE: + case WHITESPACE: +@@ -1660,15 +1660,15 @@ + case HTML: + printhtml(p->text, f); + break; +- ++ + case CODE: + printcode(p->text, f); + break; +- ++ + case QUOTE: + htmlify(p->down, p->ident ? "div" : "blockquote", p->ident, f); + break; +- ++ + case UL: + case OL: + case AL: +@@ -1694,7 +1694,7 @@ + case SOURCE: + htmlify(p->down, 0, 0, f); + break; +- ++ + default: + printblock(p, f); + break; +@@ -1715,7 +1715,7 @@ + return; + + Csprintf(&m->out, "\n<div class="footnotes">\n<hr/>\n<ol>\n"); +- ++ + for ( i=1; i <= m->reference; i++ ) { + for ( j=0; j < S(*m->footnotes); j++ ) { + t = &T(*m->footnotes)[j]; +@@ -1740,22 +1740,23 @@ + mkd_document(Document *p, char **res) + { + int size; +- ++ + if ( p && p->compiled ) { +- if ( ! p->html ) { +- htmlify(p->code, 0, 0, p->ctx); +- if ( p->ctx->flags & MKD_EXTRA_FOOTNOTE ) +- mkd_extra_footnotes(p->ctx); +- p->html = 1; +- } + +- size = S(p->ctx->out); +- +- if ( (size == 0) || T(p->ctx->out)[size-1] ) +- EXPAND(p->ctx->out) = 0; +- +- *res = T(p->ctx->out); +- return size; ++ if ( ! p->html ) { ++ htmlify(p->code, 0, 0, p->ctx); ++ if ( p->ctx->flags & MKD_EXTRA_FOOTNOTE ) ++ mkd_extra_footnotes(p->ctx); ++ p->html = 1; ++ } ++ ++ size = S(p->ctx->out); ++ ++ if ( (size == 0) || T(p->ctx->out)[size-1] ) ++ EXPAND(p->ctx->out) = 0; ++ ++ *res = T(p->ctx->out); ++ return size; + } + return EOF; + } +Only in discount-2.1.3/: INSTALL +Only in discount-2.1.3/: main.c +Only in discount-2.1.3/: Makefile.in +Only in discount-2.1.3/: makepage.1 +Only in discount-2.1.3/: makepage.c +Only in discount-2.1.3/: markdown.1 +Only in discount-2.1.3/: markdown.3 +Only in discount-2.1.3/: markdown.7 +diff -ru discount-2.1.3/markdown.c discount/markdown.c +--- discount-2.1.3/markdown.c 2012-01-16 13:08:52.000000000 -0800 ++++ discount/markdown.c 2012-07-16 19:52:23.619155626 -0700 +@@ -125,11 +125,11 @@ + * the !-- doesn't need to end in a whitespace + */ + return &comment; +- ++ + /* find how long the tag is so we can check to see if + * it's a block-level tag + */ +- for ( i=1; i < len && T(p->text)[i] != '>' ++ for ( i=1; i < len && T(p->text)[i] != '>' + && T(p->text)[i] != '/' + && !isspace(T(p->text)[i]); ++i ) + ; +@@ -193,7 +193,7 @@ + l->flags |= CHECKED; + l->kind = chk_text; + l->count = 0; +- ++ + if (l->dle >= 4) { l->kind=chk_code; return; } + + for ( eol = S(l->text); eol > l->dle && isspace(T(l->text)[eol-1]); --eol ) +@@ -261,10 +261,10 @@ + int i, closing, depth=0; + + *unclosed = 0; +- ++ + if ( tag == &comment ) + return commentblock(p, unclosed); +- ++ + if ( tag->selfclose ) { + ret = f.t->next; + f.t->next = 0; +@@ -286,7 +286,7 @@ + } + } + } +- else { ++ else { + if ( closing = (c == '/') ) c = flogetc(&f); + + for ( i=0; i < tag->size; c=flogetc(&f) ) { +@@ -369,7 +369,7 @@ + issetext(Line *t, int *htyp) + { + Line *n; +- ++ + /* check for setext-style HEADER + * ====== + */ +@@ -407,10 +407,10 @@ + end_of_block(Line *t) + { + int dummy; +- ++ + if ( !t ) + return 0; +- ++ + return ( (S(t->text) <= t->dle) || ishr(t) || ishdr(t, &dummy) ); + } + +@@ -448,11 +448,11 @@ + is_extra_dt(Line *t, int *clip) + { + #if USE_EXTRA_DL +- ++ + if ( t && t->next && T(t->text)[0] != '=' + && T(t->text)[S(t->text)-1] != '=') { + Line *x; +- ++ + if ( iscode(t) || end_of_block(t) ) + return 0; + +@@ -460,7 +460,7 @@ + *clip = x->dle+2; + return t; + } +- ++ + if ( x=is_extra_dt(t->next, clip) ) + return x; + } +@@ -488,7 +488,7 @@ + { + int i, j; + char *q; +- ++ + if ( end_of_block(t) ) + return 0; + +@@ -514,7 +514,7 @@ + return AL; + } + +- strtoul(T(t->text)+t->dle, &q, 10); ++ unsigned long res = strtoul(T(t->text)+t->dle, &q, 10); + if ( (q > T(t->text)+t->dle) && (q == T(t->text) + (j-1)) ) { + j = nextnonblank(t,j); + *clip = (j > 4) ? 4 : j; +@@ -539,7 +539,7 @@ + /* p->text is header, p->next->text is -'s or ='s + */ + pp->hnumber = (T(p->next->text)[0] == '=') ? 1 : 2; +- ++ + ret = p->next->next; + ___mkd_freeLine(p->next); + p->next = 0; +@@ -614,7 +614,7 @@ + Paragraph *ret; + + first = (*ptr); +- ++ + /* don't allow zero-length code fences + */ + if ( (first->next == 0) || iscodefence(first->next, first->count) ) +@@ -744,7 +744,7 @@ + * it just takes ^> to start a quote, following lines, if quoted, + * assume that the prefix is ``> ''. This means that code needs + * to be indented *5* spaces from the leading '>', but *4* spaces +- * from the start of the line. This does not appear to be ++ * from the start of the line. This does not appear to be + * documented in the reference implementation, but it's the + * way the markdown sample web form at Daring Fireball works. + */ +@@ -782,14 +782,14 @@ + if ( isdivmarker(p->text,0,flags) ) { + char *prefix = "class"; + int i; +- ++ + q = p->text; + p->text = p->text->next; + + if ( (i = szmarkerclass(1+T(q->text))) == 3 ) + /* and this would be an "%id:" prefix */ + prefix="id"; +- ++ + if ( p->ident = malloc(4+strlen(prefix)+S(q->text)) ) + sprintf(p->ident, "%s="%.*s"", prefix, S(q->text)-(i+2), + T(q->text)+(i+1) ); +@@ -861,7 +861,7 @@ + { + ParagraphRoot d = { 0, 0 }; + Paragraph *p; +- Line *q = top->text, *text = 0, *labels; ++ Line *q = top->text, *text = 0, *labels; + int z, para; + + while (( labels = q )) { +@@ -874,8 +874,8 @@ + + if (( para = (text != q->next) )) + ___mkd_freeLineRange(q, text); +- +- q->next = 0; ++ ++ q->next = 0; + if ( kind == 1 /* discount dl */ ) + for ( q = labels; q; q = q->next ) { + CLIP(q->text, 0, 1); +@@ -901,7 +901,7 @@ + anchor.next = text; + ___mkd_freeLineRange(&anchor,q); + text = q; +- ++ + } + + if ( kind == 2 && is_extra_dd(q) ) +@@ -922,7 +922,7 @@ + int para = 0, z; + + while (( text = q )) { +- ++ + p = Pp(&d, text, LISTITEM); + text = listitem(p, clip, f->flags, 0); + +@@ -973,7 +973,7 @@ + Line *np = p->next; + + Footnote *foot = &EXPAND(*f->footnotes); +- ++ + CREATE(foot->tag); + CREATE(foot->link); + CREATE(foot->title); +@@ -1201,14 +1201,14 @@ + while ( ptr ) { + if ( iscode(ptr) ) { + p = Pp(&d, ptr, CODE); +- ++ + if ( f->flags & MKD_1_COMPAT) { + /* HORRIBLE STANDARDS KLUDGE: the first line of every block + * has trailing whitespace trimmed off. + */ + ___mkd_tidy(&p->text->text); + } +- ++ + ptr = codeblock(p); + } + #if WITH_FENCED_CODE +@@ -1276,10 +1276,10 @@ + mkd_compile(Document *doc, DWORD flags) + { + if ( !doc ) +- return 0; ++ return 0; + + if ( doc->compiled ) +- return 1; ++ return 1; + + doc->compiled = 1; + memset(doc->ctx, 0, sizeof(MMIOT) ); +@@ -1300,3 +1300,15 @@ + return 1; + } + ++char *mkd_compile_document(const char *s, DWORD flags) ++{ ++ char *ptr = NULL; ++ Document *doc; ++ ++ doc = mkd_string(s, strlen(s), flags); ++ mkd_compile(doc, 0); ++ mkd_document(doc, &ptr); ++ ptr = mkd_cleanup_return_buffer(doc, NULL); ++ ++ return ptr; ++} +diff -ru discount-2.1.3/markdown.h discount/markdown.h +--- discount-2.1.3/markdown.h 2012-01-16 13:08:52.000000000 -0800 ++++ discount/markdown.h 2012-07-16 19:52:01.611155862 -0700 +@@ -19,7 +19,7 @@ + } Footnote; + + /* each input line is read into a Line, which contains the line, +- * the offset of the first non-space character [this assumes ++ * the offset of the first non-space character [this assumes + * that all tabs will be expanded to spaces!], and a pointer to + * the next line. + */ +@@ -144,6 +144,7 @@ + Callback_data cb; /* callback functions & private data */ + } Document; + ++extern char *mkd_compile_document(const char *, DWORD); + + extern int mkd_firstnonblank(Line *); + extern int mkd_compile(Document *, DWORD); +@@ -155,6 +156,7 @@ + extern int mkd_xml(char *, int , char **); + extern int mkd_generatexml(char *, int, FILE *); + extern void mkd_cleanup(Document *); ++extern char *mkd_cleanup_return_buffer(Document *, long*); + extern int mkd_line(char *, int, char **, DWORD); + extern int mkd_generateline(char *, int, FILE*, DWORD); + #define mkd_text mkd_generateline +@@ -180,6 +182,7 @@ + extern void ___mkd_freefootnotes(MMIOT *); + extern void ___mkd_initmmiot(MMIOT *, void *); + extern void ___mkd_freemmiot(MMIOT *, void *); ++extern char* ___mkd_freemmiot_return_buffer(MMIOT *, void *, long*); + extern void ___mkd_freeLineRange(Line *, Line *); + extern void ___mkd_xml(char *, int, FILE *); + extern void ___mkd_reparse(char *, int, int, MMIOT*); +Only in discount-2.1.3/: mkd2html.1 +Only in discount-2.1.3/: mkd2html.c +Only in discount-2.1.3/: mkd-callbacks.3 +Only in discount-2.1.3/: mkd-extensions.7 +Only in discount-2.1.3/: mkd-functions.3 +diff -ru discount-2.1.3/mkdio.c discount/mkdio.c +--- discount-2.1.3/mkdio.c 2012-01-16 13:08:52.000000000 -0800 ++++ discount/mkdio.c 2012-07-16 18:03:40.619224702 -0700 +@@ -24,11 +24,11 @@ + Document *ret = calloc(sizeof(Document), 1); + + if ( ret ) { +- if (( ret->ctx = calloc(sizeof(MMIOT), 1) )) { +- ret->magic = VALID_DOCUMENT; +- return ret; +- } +- free(ret); ++ if (( ret->ctx = calloc(sizeof(MMIOT), 1) )) { ++ ret->magic = VALID_DOCUMENT; ++ return ret; ++ } ++ free(ret); + } + return 0; + } +@@ -50,22 +50,22 @@ + ATTACH(a->content, p); + + while ( size-- ) { +- if ( (c = *str++) == '\t' ) { +- /* expand tabs into ->tabstop spaces. We use ->tabstop +- * because the ENTIRE FREAKING COMPUTER WORLD uses editors +- * that don't do ^T/^D, but instead use tabs for indentation, +- * and, of course, set their tabs down to 4 spaces +- */ +- do { +- EXPAND(p->text) = ' '; +- } while ( ++xp % a->tabstop ); +- } +- else if ( c >= ' ' ) { +- if ( c == '|' ) +- p->flags |= PIPECHAR; +- EXPAND(p->text) = c; +- ++xp; +- } ++ if ( (c = *str++) == '\t' ) { ++ /* expand tabs into ->tabstop spaces. We use ->tabstop ++ * because the ENTIRE FREAKING COMPUTER WORLD uses editors ++ * that don't do ^T/^D, but instead use tabs for indentation, ++ * and, of course, set their tabs down to 4 spaces ++ */ ++ do { ++ EXPAND(p->text) = ' '; ++ } while ( ++xp % a->tabstop ); ++ } ++ else if ( c >= ' ' ) { ++ if ( c == '|' ) ++ p->flags |= PIPECHAR; ++ EXPAND(p->text) = c; ++ ++xp; ++ } + } + EXPAND(p->text) = 0; + S(p->text)--; +@@ -102,37 +102,37 @@ + CREATE(line); + + while ( (c = (*getc)(ctx)) != EOF ) { +- if ( c == '\n' ) { +- if ( pandoc != EOF && pandoc < 3 ) { +- if ( S(line) && (T(line)[0] == '%') ) +- pandoc++; +- else +- pandoc = EOF; +- } +- queue(a, &line); +- S(line) = 0; +- } +- else if ( isprint(c) || isspace(c) || (c & 0x80) ) +- EXPAND(line) = c; ++ if ( c == '\n' ) { ++ if ( pandoc != EOF && pandoc < 3 ) { ++ if ( S(line) && (T(line)[0] == '%') ) ++ pandoc++; ++ else ++ pandoc = EOF; ++ } ++ queue(a, &line); ++ S(line) = 0; ++ } ++ else if ( isprint(c) || isspace(c) || (c & 0x80) ) ++ EXPAND(line) = c; + } + + if ( S(line) ) +- queue(a, &line); ++ queue(a, &line); + + DELETE(line); + + if ( (pandoc == 3) && !(flags & (MKD_NOHEADER|MKD_STRICT)) ) { +- /* the first three lines started with %, so we have a header. +- * clip the first three lines out of content and hang them +- * off header. +- */ +- Line *headers = T(a->content); ++ /* the first three lines started with %, so we have a header. ++ * clip the first three lines out of content and hang them ++ * off header. ++ */ ++ Line *headers = T(a->content); ++ ++ a->title = headers; header_dle(a->title); ++ a->author= headers->next; header_dle(a->author); ++ a->date = headers->next->next; header_dle(a->date); + +- a->title = headers; header_dle(a->title); +- a->author= headers->next; header_dle(a->author); +- a->date = headers->next->next; header_dle(a->date); +- +- T(a->content) = headers->next->next->next; ++ T(a->content) = headers->next->next->next; + } + + return a; +@@ -227,7 +227,7 @@ + char *line; + + size = mkd_line(s, len, &line, IS_LABEL); +- ++ + if ( labelformat && (size>0) && !isalpha(line[0]) ) + (*outchar)('L',out); + for ( i=0; i < size ; i++ ) { +@@ -241,7 +241,7 @@ + else + (*outchar)(c,out); + } +- ++ + if (line) + free(line); + } +@@ -266,13 +266,13 @@ + { + MMIOT f; + int len; +- ++ + mkd_parse_line(bfr, size, &f, flags); + + if ( len = S(f.out) ) { + /* kludge alert; we know that T(f.out) is malloced memory, + * so we can just steal it away. This is awful -- there +- * should be an opaque method that transparently moves ++ * should be an opaque method that transparently moves + * the pointer out of the embedded Cstring. + */ + EXPAND(f.out) = 0; +Only in discount/: mkdio.h +Only in discount-2.1.3/: mkdio.h.in +Only in discount-2.1.3/: mkd-line.3 +Only in discount-2.1.3/: mktags.c +Only in discount-2.1.3/: pgm_options.c +Only in discount-2.1.3/: pgm_options.h +Only in discount-2.1.3/: Plan9 +Only in discount-2.1.3/: README +diff -ru discount-2.1.3/resource.c discount/resource.c +--- discount-2.1.3/resource.c 2012-01-16 13:08:52.000000000 -0800 ++++ discount/resource.c 2012-07-16 18:40:37.947201222 -0700 +@@ -107,14 +107,33 @@ + void + ___mkd_freemmiot(MMIOT *f, void *footnotes) + { +- if ( f ) { +- DELETE(f->in); +- DELETE(f->out); +- DELETE(f->Q); +- if ( f->footnotes != footnotes ) +- ___mkd_freefootnotes(f); +- memset(f, 0, sizeof *f); +- } ++ if ( f ) { ++ DELETE(f->in); ++ DELETE(f->out); ++ DELETE(f->Q); ++ if ( f->footnotes != footnotes ) ++ ___mkd_freefootnotes(f); ++ memset(f, 0, sizeof *f); ++ } ++} ++ ++/* free the contents of a MMIOT except the output buffer, but leave the ++ * object alone. return the output buffer to the caller. */ ++char * ++___mkd_freemmiot_return_buffer(MMIOT *f, void *footnotes, long *out_len) ++{ ++ char *ptr = NULL; ++ if ( f ) { ++ DELETE(f->in); ++ ptr = T(f->out); /* save pointer */ ++ if (out_len) ++ *out_len = S(f->out); /* save length */ ++ DELETE(f->Q); ++ if ( f->footnotes != footnotes ) ++ ___mkd_freefootnotes(f); ++ memset(f, 0, sizeof *f); ++ } ++ return ptr; + } + + +@@ -140,18 +159,41 @@ + void + mkd_cleanup(Document *doc) + { +- if ( doc && (doc->magic == VALID_DOCUMENT) ) { +- if ( doc->ctx ) { +- ___mkd_freemmiot(doc->ctx, 0); +- free(doc->ctx); +- } +- +- if ( doc->code) ___mkd_freeParagraph(doc->code); +- if ( doc->title) ___mkd_freeLine(doc->title); +- if ( doc->author) ___mkd_freeLine(doc->author); +- if ( doc->date) ___mkd_freeLine(doc->date); +- if ( T(doc->content) ) ___mkd_freeLines(T(doc->content)); +- memset(doc, 0, sizeof doc[0]); +- free(doc); ++ if ( doc && (doc->magic == VALID_DOCUMENT) ) { ++ if ( doc->ctx ) { ++ ___mkd_freemmiot(doc->ctx, 0); ++ free(doc->ctx); ++ } ++ ++ if ( doc->code) ___mkd_freeParagraph(doc->code); ++ if ( doc->title) ___mkd_freeLine(doc->title); ++ if ( doc->author) ___mkd_freeLine(doc->author); ++ if ( doc->date) ___mkd_freeLine(doc->date); ++ if ( T(doc->content) ) ___mkd_freeLines(T(doc->content)); ++ memset(doc, 0, sizeof doc[0]); ++ free(doc); ++ } ++} ++ ++char * ++mkd_cleanup_return_buffer(Document *doc, long *out_len) ++{ ++ char *ptr = NULL; ++ ++ if ( doc && (doc->magic == VALID_DOCUMENT) ) { ++ if ( doc->ctx ) { ++ ptr = ___mkd_freemmiot_return_buffer(doc->ctx, 0, out_len); ++ free(doc->ctx); + } ++ ++ if ( doc->code) ___mkd_freeParagraph(doc->code); ++ if ( doc->title) ___mkd_freeLine(doc->title); ++ if ( doc->author) ___mkd_freeLine(doc->author); ++ if ( doc->date) ___mkd_freeLine(doc->date); ++ if ( T(doc->content) ) ___mkd_freeLines(T(doc->content)); ++ memset(doc, 0, sizeof doc[0]); ++ free(doc); ++ } ++ ++ return ptr; + } +Only in discount-2.1.3/: tests +Only in discount-2.1.3/: theme.1 +Only in discount-2.1.3/: theme.c +Only in discount-2.1.3/: tools +Only in discount-2.1.3/: VERSION +Only in discount/: version.c +Only in discount-2.1.3/: version.c.in
Modified: markdown/discount/docheader.c 49 files changed, 49 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,49 @@ +/* + * docheader -- get values from the document header + * + * Copyright (C) 2007 David L Parsons. + * The redistribution terms are provided in the COPYRIGHT file that must + * be distributed with this source code. + */ +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#include "cstring.h" +#include "markdown.h" +#include "amalloc.h" + +static char * +onlyifset(Line *l) +{ + char *ret = T(l->text) + l->dle; + + return ret[0] ? ret : 0; +} + +char * +mkd_doc_title(Document *doc) +{ + if ( doc && doc->title ) + return onlyifset(doc->title); + return 0; +} + + +char * +mkd_doc_author(Document *doc) +{ + if ( doc && doc->author ) + return onlyifset(doc->author); + return 0; +} + + +char * +mkd_doc_date(Document *doc) +{ + if ( doc && doc->date ) + return onlyifset(doc->date); + return 0; +}
Modified: markdown/discount/dumptree.c 152 files changed, 152 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,152 @@ +/* markdown: a C implementation of John Gruber's Markdown markup language. + * + * Copyright (C) 2007 David L Parsons. + * The redistribution terms are provided in the COPYRIGHT file that must + * be distributed with this source code. + */ +#include <stdio.h> +#include "markdown.h" +#include "cstring.h" +#include "amalloc.h" + +struct frame { + int indent; + char c; +}; + +typedef STRING(struct frame) Stack; + +static char * +Pptype(int typ) +{ + switch (typ) { + case WHITESPACE: return "whitespace"; + case CODE : return "code"; + case QUOTE : return "quote"; + case MARKUP : return "markup"; + case HTML : return "html"; + case DL : return "dl"; + case UL : return "ul"; + case OL : return "ol"; + case LISTITEM : return "item"; + case HDR : return "header"; + case HR : return "hr"; + case TABLE : return "table"; + case SOURCE : return "source"; + case STYLE : return "style"; + default : return "mystery node!"; + } +} + +static void +pushpfx(int indent, char c, Stack *sp) +{ + struct frame *q = &EXPAND(*sp); + + q->indent = indent; + q->c = c; +} + + +static void +poppfx(Stack *sp) +{ + S(*sp)--; +} + + +static void +changepfx(Stack *sp, char c) +{ + char ch; + + if ( !S(*sp) ) return; + + ch = T(*sp)[S(*sp)-1].c; + + if ( ch == '+' || ch == '|' ) + T(*sp)[S(*sp)-1].c = c; +} + + +static void +printpfx(Stack *sp, FILE *f) +{ + int i; + char c; + + if ( !S(*sp) ) return; + + c = T(*sp)[S(*sp)-1].c; + + if ( c == '+' || c == '-' ) { + fprintf(f, "--%c", c); + T(*sp)[S(*sp)-1].c = (c == '-') ? ' ' : '|'; + } + else + for ( i=0; i < S(*sp); i++ ) { + if ( i ) + fprintf(f, " "); + fprintf(f, "%*s%c", T(*sp)[i].indent + 2, " ", T(*sp)[i].c); + if ( T(*sp)[i].c == '`' ) + T(*sp)[i].c = ' '; + } + fprintf(f, "--"); +} + + +static void +dumptree(Paragraph *pp, Stack *sp, FILE *f) +{ + int count; + Line *p; + int d; + static char *Begin[] = { 0, "P", "center" }; + + while ( pp ) { + if ( !pp->next ) + changepfx(sp, '`'); + printpfx(sp, f); + + d = fprintf(f, "[%s", Pptype(pp->typ)); + if ( pp->ident ) + d += fprintf(f, " %s", pp->ident); + if ( pp->align > 1 ) + d += fprintf(f, ", <%s>", Begin[pp->align]); + + for (count=0, p=pp->text; p; ++count, (p = p->next) ) + ; + + if ( count ) + d += fprintf(f, ", %d line%s", count, (count==1)?"":"s"); + + d += fprintf(f, "]"); + + if ( pp->down ) { + pushpfx(d, pp->down->next ? '+' : '-', sp); + dumptree(pp->down, sp, f); + poppfx(sp); + } + else fputc('\n', f); + pp = pp->next; + } +} + + +int +mkd_dump(Document *doc, FILE *out, int flags, char *title) +{ + Stack stack; + + if (mkd_compile(doc, flags) ) { + + CREATE(stack); + pushpfx(fprintf(out, "%s", title), doc->code->next ? '+' : '-', &stack); + dumptree(doc->code, &stack, out); + DELETE(stack); + + mkd_cleanup(doc); + return 0; + } + return -1; +}
Modified: markdown/discount/emmatch.c 188 files changed, 188 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,188 @@ +/* markdown: a C implementation of John Gruber's Markdown markup language. + * + * Copyright (C) 2010 David L Parsons. + * The redistribution terms are provided in the COPYRIGHT file that must + * be distributed with this source code. + */ +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> + +#include "config.h" + +#include "cstring.h" +#include "markdown.h" +#include "amalloc.h" + + +/* emmatch: the emphasis mangler that's run after a block + * of html has been generated. + * + * It should create MarkdownTest_1.0 (and _1.0.3) + * compatable emphasis for non-pathological cases + * and it should fail in a standards-compliant way + * when someone attempts to feed it junk. + * + * Emmatching is done after the input has been + * processed into a STRING (f->Q) of text and + * emphasis blocks. After ___mkd_emblock() finishes, + * it truncates f->Q and leaves the rendered paragraph + * if f->out. + */ + + +/* empair() -- find the NEAREST matching emphasis token (or + * subtoken of a 3+ long emphasis token. + */ +static int +empair(MMIOT *f, int first, int last, int match) +{ + + int i; + block *begin, *p; + + begin = &T(f->Q)[first]; + + for (i=first+1; i <= last; i++) { + p = &T(f->Q)[i]; + + if ( (p->b_type != bTEXT) && (p->b_count <= 0) ) + continue; /* break? */ + + if ( p->b_type == begin->b_type ) { + if ( p->b_count == match ) /* exact match */ + return i; + + if ( p->b_count > 2 ) /* fuzzy match */ + return i; + } + } + return 0; +} /* empair */ + + +/* emfill() -- if an emphasis token has leftover stars or underscores, + * convert them back into character and append them to b_text. + */ +static void +emfill(block *p) +{ + int j; + + if ( p->b_type == bTEXT ) + return; + + for (j=0; j < p->b_count; j++) + EXPAND(p->b_text) = p->b_char; + p->b_count = 0; +} /* emfill */ + + +static void +emclose(MMIOT *f, int first, int last) +{ + int j; + + for (j=first+1; j<last-1; j++) + emfill(&T(f->Q)[j]); +} + + +static struct emtags { + char open[10]; + char close[10]; + int size; +} emtags[] = { { "<em>" , "</em>", 5 }, { "<strong>", "</strong>", 9 } }; + + +static void emblock(MMIOT*,int,int); + + +/* emmatch() -- match emphasis for a single emphasis token. + */ +static void +emmatch(MMIOT *f, int first, int last) +{ + block *start = &T(f->Q)[first]; + int e, e2, match; + + switch (start->b_count) { + case 2: if ( e = empair(f,first,last,match=2) ) + break; + case 1: e = empair(f,first,last,match=1); + break; + case 0: return; + default: + e = empair(f,first,last,1); + e2= empair(f,first,last,2); + + if ( e2 >= e ) { + e = e2; + match = 2; + } + else + match = 1; + break; + } + + if ( e ) { + /* if we found emphasis to match, match it, recursively call + * emblock to match emphasis inside the new html block, add + * the emphasis markers for the block, then (tail) recursively + * call ourself to match any remaining emphasis on this token. + */ + block *end = &T(f->Q)[e]; + + end->b_count -= match; + start->b_count -= match; + + emblock(f, first, e); + + MDPREFIX(start->b_text, emtags[match-1].open, emtags[match-1].size-1); + SUFFIX(end->b_post, emtags[match-1].close, emtags[match-1].size); + + emmatch(f, first, last); + } +} /* emmatch */ + + +/* emblock() -- walk a blocklist, attempting to match emphasis + */ +static void +emblock(MMIOT *f, int first, int last) +{ + int i; + + for ( i = first; i <= last; i++ ) + if ( T(f->Q)[i].b_type != bTEXT ) + emmatch(f, i, last); + emclose(f, first, last); +} /* emblock */ + + +/* ___mkd_emblock() -- emblock a string of blocks, then concatenate the + * resulting text onto f->out. + */ +void +___mkd_emblock(MMIOT *f) +{ + int i; + block *p; + + emblock(f, 0, S(f->Q)-1); + + for (i=0; i < S(f->Q); i++) { + p = &T(f->Q)[i]; + emfill(p); + + if ( S(p->b_post) ) { SUFFIX(f->out, T(p->b_post), S(p->b_post)); + DELETE(p->b_post); } + if ( S(p->b_text) ) { SUFFIX(f->out, T(p->b_text), S(p->b_text)); + DELETE(p->b_text); } + } + + S(f->Q) = 0; +} /* ___mkd_emblock */
Modified: markdown/discount/flags.c 84 files changed, 84 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,84 @@ +#include <stdio.h> +#include "markdown.h" + +struct flagnames { + DWORD flag; + char *name; +}; + +static struct flagnames flagnames[] = { + { MKD_NOLINKS, "!LINKS" }, + { MKD_NOIMAGE, "!IMAGE" }, + { MKD_NOPANTS, "!PANTS" }, + { MKD_NOHTML, "!HTML" }, + { MKD_STRICT, "STRICT" }, + { MKD_TAGTEXT, "TAGTEXT" }, + { MKD_NO_EXT, "!EXT" }, + { MKD_CDATA, "CDATA" }, + { MKD_NOSUPERSCRIPT, "!SUPERSCRIPT" }, + { MKD_NORELAXED, "!RELAXED" }, + { MKD_NOTABLES, "!TABLES" }, + { MKD_NOSTRIKETHROUGH,"!STRIKETHROUGH" }, + { MKD_TOC, "TOC" }, + { MKD_1_COMPAT, "MKD_1_COMPAT" }, + { MKD_AUTOLINK, "AUTOLINK" }, + { MKD_SAFELINK, "SAFELINK" }, + { MKD_NOHEADER, "!HEADER" }, + { MKD_TABSTOP, "TABSTOP" }, + { MKD_NODIVQUOTE, "!DIVQUOTE" }, + { MKD_NOALPHALIST, "!ALPHALIST" }, + { MKD_NODLIST, "!DLIST" }, + { MKD_EXTRA_FOOTNOTE, "FOOTNOTE" }, +}; +#define NR(x) (sizeof x/sizeof x[0]) + + +void +mkd_flags_are(FILE *f, DWORD flags, int htmlplease) +{ + int i; + int not, set, even=1; + char *name; + + if ( htmlplease ) + fprintf(f, "<table class="mkd_flags_are">\n"); + for (i=0; i < NR(flagnames); i++) { + set = flags & flagnames[i].flag; + name = flagnames[i].name; + if ( not = (*name == '!') ) { + ++name; + set = !set; + } + + if ( htmlplease ) { + if ( even ) fprintf(f, " <tr>"); + fprintf(f, "<td>"); + } + else + fputc(' ', f); + + if ( !set ) + fprintf(f, htmlplease ? "<s>" : "!"); + + fprintf(f, "%s", name); + + if ( htmlplease ) { + if ( !set ) + fprintf(f, "</s>"); + fprintf(f, "</td>"); + if ( !even ) fprintf(f, "</tr>\n"); + } + even = !even; + } + if ( htmlplease ) { + if ( even ) fprintf(f, "</tr>\n"); + fprintf(f, "</table>\n"); + } +} + +void +mkd_mmiot_flags(FILE *f, MMIOT *m, int htmlplease) +{ + if ( m ) + mkd_flags_are(f, m->flags, htmlplease); +}
Modified: markdown/discount/generate.c 1763 files changed, 1763 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,1763 @@ +/* markdown: a C implementation of John Gruber's Markdown markup language. + * + * Copyright (C) 2007 David L Parsons. + * The redistribution terms are provided in the COPYRIGHT file that must + * be distributed with this source code. + */ +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> + +#include "config.h" + +#include "cstring.h" +#include "markdown.h" +#include "amalloc.h" + +typedef int (*stfu)(const void*,const void*); +typedef void (*spanhandler)(MMIOT*,int); + +/* forward declarations */ +static void text(MMIOT *f); +static Paragraph *display(Paragraph*, MMIOT*); + +/* externals from markdown.c */ +int __mkd_footsort(Footnote *, Footnote *); + +/* + * push text into the generator input buffer + */ +static void +push(char *bfr, int size, MMIOT *f) +{ + while ( size-- > 0 ) + EXPAND(f->in) = *bfr++; +} + + +/* look <i> characters ahead of the cursor. + */ +static inline int +peek(MMIOT *f, int i) +{ + + i += (f->isp-1); + + return (i >= 0) && (i < S(f->in)) ? T(f->in)[i] : EOF; +} + + +/* pull a byte from the input buffer + */ +static inline int +pull(MMIOT *f) +{ + return ( f->isp < S(f->in) ) ? T(f->in)[f->isp++] : EOF; +} + + +/* return a pointer to the current position in the input buffer. + */ +static inline char* +cursor(MMIOT *f) +{ + return T(f->in) + f->isp; +} + + +static inline int +isthisspace(MMIOT *f, int i) +{ + int c = peek(f, i); + + return isspace(c) || (c == EOF); +} + + +static inline int +isthisalnum(MMIOT *f, int i) +{ + int c = peek(f, i); + + return (c != EOF) && isalnum(c); +} + + +static inline int +isthisnonword(MMIOT *f, int i) +{ + return isthisspace(f, i) || ispunct(peek(f,i)); +} + + +/* return/set the current cursor position + */ +#define mmiotseek(f,x) (f->isp = x) +#define mmiottell(f) (f->isp) + + +/* move n characters forward ( or -n characters backward) in the input buffer. + */ +static void +shift(MMIOT *f, int i) +{ + if (f->isp + i >= 0 ) + f->isp += i; +} + + +/* Qchar() + */ +static void +Qchar(int c, MMIOT *f) +{ + block *cur; + + if ( S(f->Q) == 0 ) { + cur = &EXPAND(f->Q); + memset(cur, 0, sizeof *cur); + cur->b_type = bTEXT; + } + else + cur = &T(f->Q)[S(f->Q)-1]; + + EXPAND(cur->b_text) = c; + +} + + +/* Qstring() + */ +static void +Qstring(char *s, MMIOT *f) +{ + while (*s) + Qchar(*s++, f); +} + + +/* Qwrite() + */ +static void +Qwrite(char *s, int size, MMIOT *f) +{ + while (size-- > 0) + Qchar(*s++, f); +} + + +/* Qprintf() + */ +static void +Qprintf(MMIOT *f, char *fmt, ...) +{ + char bfr[80]; + va_list ptr; + + va_start(ptr,fmt); + vsnprintf(bfr, sizeof bfr, fmt, ptr); + va_end(ptr); + Qstring(bfr, f); +} + + +/* Qem() + */ +static void +Qem(MMIOT *f, char c, int count) +{ + block *p = &EXPAND(f->Q); + + memset(p, 0, sizeof *p); + p->b_type = (c == '*') ? bSTAR : bUNDER; + p->b_char = c; + p->b_count = count; + + memset(&EXPAND(f->Q), 0, sizeof(block)); +} + + +/* generate html from a markup fragment + */ +void +___mkd_reparse(char *bfr, int size, int flags, MMIOT *f) +{ + MMIOT sub; + + ___mkd_initmmiot(&sub, f->footnotes); + + sub.flags = f->flags | flags; + sub.cb = f->cb; + sub.ref_prefix = f->ref_prefix; + + push(bfr, size, &sub); + EXPAND(sub.in) = 0; + S(sub.in)--; + + text(&sub); + ___mkd_emblock(&sub); + + Qwrite(T(sub.out), S(sub.out), f); + + ___mkd_freemmiot(&sub, f->footnotes); +} + + +/* + * write out a url, escaping problematic characters + */ +static void +puturl(char *s, int size, MMIOT *f, int display) +{ + unsigned char c; + + while ( size-- > 0 ) { + c = *s++; + + if ( c == '\' && size-- > 0 ) { + c = *s++; + + if ( !( ispunct(c) || isspace(c) ) ) + Qchar('\', f); + } + + if ( c == '&' ) + Qstring("&", f); + else if ( c == '<' ) + Qstring("<", f); + else if ( c == '"' ) + Qstring("%22", f); + else if ( isalnum(c) || ispunct(c) || (display && isspace(c)) ) + Qchar(c, f); + else if ( c == 003 ) /* untokenize ^C */ + Qstring(" ", f); + else + Qprintf(f, "%%%02X", c); + } +} + + +/* advance forward until the next character is not whitespace + */ +static int +eatspace(MMIOT *f) +{ + int c; + + for ( ; ((c=peek(f, 1)) != EOF) && isspace(c); pull(f) ) + ; + return c; +} + + +/* (match (a (nested (parenthetical (string.))))) + */ +static int +parenthetical(int in, int out, MMIOT *f) +{ + int size, indent, c; + + for ( indent=1,size=0; indent; size++ ) { + if ( (c = pull(f)) == EOF ) + return EOF; + else if ( (c == '\') && (peek(f,1) == out || peek(f,1) == in) ) { + ++size; + pull(f); + } + else if ( c == in ) + ++indent; + else if ( c == out ) + --indent; + } + return size ? (size-1) : 0; +} + + +/* extract a []-delimited label from the input stream. + */ +static int +linkylabel(MMIOT *f, Cstring *res) +{ + char *ptr = cursor(f); + int size; + + if ( (size = parenthetical('[',']',f)) != EOF ) { + T(*res) = ptr; + S(*res) = size; + return 1; + } + return 0; +} + + +/* see if the quote-prefixed linky segment is actually a title. + */ +static int +linkytitle(MMIOT *f, char quote, Footnote *ref) +{ + int whence = mmiottell(f); + char *title = cursor(f); + char *e; + register int c; + + while ( (c = pull(f)) != EOF ) { + e = cursor(f); + if ( c == quote ) { + if ( (c = eatspace(f)) == ')' ) { + T(ref->title) = 1+title; + S(ref->title) = (e-title)-2; + return 1; + } + } + } + mmiotseek(f, whence); + return 0; +} + + +/* extract a =HHHxWWW size from the input stream + */ +static int +linkysize(MMIOT *f, Footnote *ref) +{ + int height=0, width=0; + int whence = mmiottell(f); + int c; + + if ( isspace(peek(f,0)) ) { + pull(f); /* eat '=' */ + + for ( c = pull(f); isdigit(c); c = pull(f)) + width = (width * 10) + (c - '0'); + + if ( c == 'x' ) { + for ( c = pull(f); isdigit(c); c = pull(f)) + height = (height*10) + (c - '0'); + + if ( isspace(c) ) + c = eatspace(f); + + if ( (c == ')') || ((c == ''' || c == '"') && linkytitle(f, c, ref)) ) { + ref->height = height; + ref->width = width; + return 1; + } + } + } + mmiotseek(f, whence); + return 0; +} + + +/* extract a <...>-encased url from the input stream. + * (markdown 1.0.2b8 compatibility; older versions + * of markdown treated the < and > as syntactic + * sugar that didn't have to be there. 1.0.2b8 + * requires a closing >, and then falls into the + * title or closing ) + */ +static int +linkybroket(MMIOT *f, int image, Footnote *p) +{ + int c; + int good = 0; + + T(p->link) = cursor(f); + for ( S(p->link)=0; (c = pull(f)) != '>'; ++S(p->link) ) { + /* pull in all input until a '>' is found, or die trying. + */ + if ( c == EOF ) + return 0; + else if ( (c == '\') && ispunct(peek(f,2)) ) { + ++S(p->link); + pull(f); + } + } + + c = eatspace(f); + + /* next nonspace needs to be a title, a size, or ) + */ + if ( ( c == ''' || c == '"' ) && linkytitle(f,c,p) ) + good=1; + else if ( image && (c == '=') && linkysize(f,p) ) + good=1; + else + good=( c == ')' ); + + if ( good ) { + if ( peek(f, 1) == ')' ) + pull(f); + + ___mkd_tidy(&p->link); + } + + return good; +} /* linkybroket */ + + +/* extract a (-prefixed url from the input stream. + * the label is either of the format `<link>`, where I + * extract until I find a >, or it is of the format + * `text`, where I extract until I reach a ')', a quote, + * or (if image) a '=' + */ +static int +linkyurl(MMIOT *f, int image, Footnote *p) +{ + int c; + int mayneedtotrim=0; + + if ( (c = eatspace(f)) == EOF ) + return 0; + + if ( c == '<' ) { + pull(f); + if ( !(f->flags & MKD_1_COMPAT) ) + return linkybroket(f,image,p); + mayneedtotrim=1; + } + + T(p->link) = cursor(f); + for ( S(p->link)=0; (c = peek(f,1)) != ')'; ++S(p->link) ) { + if ( c == EOF ) + return 0; + else if ( (c == '"' || c == ''') && linkytitle(f, c, p) ) + break; + else if ( image && (c == '=') && linkysize(f, p) ) + break; + else if ( (c == '\') && ispunct(peek(f,2)) ) { + ++S(p->link); + pull(f); + } + pull(f); + } + if ( peek(f, 1) == ')' ) + pull(f); + + ___mkd_tidy(&p->link); + + if ( mayneedtotrim && (T(p->link)[S(p->link)-1] == '>') ) + --S(p->link); + + return 1; +} + + + +/* prefixes for <automatic links> + */ +static struct _protocol { + char *name; + int nlen; +} protocol[] = { +#define _aprotocol(x) { x, (sizeof x)-1 } + _aprotocol( "https:" ), + _aprotocol( "http:" ), + _aprotocol( "news:" ), + _aprotocol( "ftp:" ), +#undef _aprotocol +}; +#define NRPROTOCOLS (sizeof protocol / sizeof protocol[0]) + + +static int +isautoprefix(char *text, int size) +{ + int i; + struct _protocol *p; + + for (i=0, p=protocol; i < NRPROTOCOLS; i++, p++) + if ( (size >= p->nlen) && strncasecmp(text, p->name, p->nlen) == 0 ) + return 1; + return 0; +} + + +/* + * all the tag types that linkylinky can produce are + * defined by this structure. + */ +typedef struct linkytype { + char *pat; + int szpat; + char *link_pfx; /* tag prefix and link pointer (eg: "<a href=""" */ + char *link_sfx; /* link suffix (eg: """ */ + int WxH; /* this tag allows width x height arguments */ + char *text_pfx; /* text prefix (eg: ">" */ + char *text_sfx; /* text suffix (eg: "</a>" */ + int flags; /* reparse flags */ + int kind; /* tag is url or something else? */ +#define IS_URL 0x01 +} linkytype; + +static linkytype imaget = { 0, 0, "<img src="", """, + 1, " alt="", "" />", MKD_NOIMAGE|MKD_TAGTEXT, IS_URL }; +static linkytype linkt = { 0, 0, "<a href="", """, + 0, ">", "</a>", MKD_NOLINKS, IS_URL }; + +/* + * pseudo-protocols for [][]; + * + * id: generates <a id="link">tag</a> + * class: generates <span class="link">tag</span> + * raw: just dump the link without any processing + */ +static linkytype specials[] = { + { "id:", 3, "<span id="", """, 0, ">", "</span>", 0, 0 }, + { "raw:", 4, 0, 0, 0, 0, 0, MKD_NOHTML, 0 }, + { "lang:", 5, "<span lang="", """, 0, ">", "</span>", 0, 0 }, + { "abbr:", 5, "<abbr title="", """, 0, ">", "</abbr>", 0, 0 }, + { "class:", 6, "<span class="", """, 0, ">", "</span>", 0, 0 }, +} ; + +#define NR(x) (sizeof x / sizeof x[0]) + +/* see if t contains one of our pseudo-protocols. + */ +static linkytype * +pseudo(Cstring t) +{ + int i; + linkytype *r; + + for ( i=0, r=specials; i < NR(specials); i++,r++ ) { + if ( (S(t) > r->szpat) && (strncasecmp(T(t), r->pat, r->szpat) == 0) ) + return r; + } + return 0; +} + + +/* print out the start of an `img' or `a' tag, applying callbacks as needed. + */ +static void +printlinkyref(MMIOT *f, linkytype *tag, char *link, int size) +{ + char *edit; + + if ( f->flags & IS_LABEL ) + return; + + Qstring(tag->link_pfx, f); + + if ( tag->kind & IS_URL ) { + if ( f->cb && f->cb->e_url && (edit = (*f->cb->e_url)(link, size, f->cb->e_data)) ) { + puturl(edit, strlen(edit), f, 0); + if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data); + } + else + puturl(link + tag->szpat, size - tag->szpat, f, 0); + } + else + ___mkd_reparse(link + tag->szpat, size - tag->szpat, MKD_TAGTEXT, f); + + Qstring(tag->link_sfx, f); + + if ( f->cb && f->cb->e_flags && (edit = (*f->cb->e_flags)(link, size, f->cb->e_data)) ) { + Qchar(' ', f); + Qstring(edit, f); + if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data); + } +} /* printlinkyref */ + + +/* helper function for php markdown extra footnotes; allow the user to + * define a prefix tag instead of just `fn` + */ +static char * +p_or_nothing(p) +MMIOT *p; +{ + return p->ref_prefix ? p->ref_prefix : "fn"; +} + + +/* php markdown extra/daring fireball style print footnotes + */ +static int +extra_linky(MMIOT *f, Cstring text, Footnote *ref) +{ + if ( ref->flags & REFERENCED ) + return 0; + + if ( f->flags & IS_LABEL ) + ___mkd_reparse(T(text), S(text), linkt.flags, f); + else { + ref->flags |= REFERENCED; + ref->refnumber = ++ f->reference; + Qprintf(f, "<sup id="%sref:%d"><a href="#%s:%d" rel="footnote">%d</a></sup>", + p_or_nothing(f), ref->refnumber, + p_or_nothing(f), ref->refnumber, ref->refnumber); + } + return 1; +} /* extra_linky */ + + +/* print out a linky (or fail if it's Not Allowed) + */ +static int +linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref) +{ + linkytype *tag; + + if ( image || (ref == 0) ) + tag = &imaget; + else if ( tag = pseudo(ref->link) ) { + if ( f->flags & (MKD_NO_EXT|MKD_SAFELINK) ) + return 0; + } + else if ( (f->flags & MKD_SAFELINK) && T(ref->link) + && (T(ref->link)[0] != '/') + && !isautoprefix(T(ref->link), S(ref->link)) ) + /* if MKD_SAFELINK, only accept links that are local or + * a well-known protocol + */ + return 0; + else + tag = &linkt; + + if ( f->flags & tag->flags ) + return 0; + + if ( f->flags & IS_LABEL ) + ___mkd_reparse(T(text), S(text), tag->flags, f); + else if ( tag->link_pfx ) { + printlinkyref(f, tag, T(ref->link), S(ref->link)); + + if ( tag->WxH ) { + if ( ref->height ) Qprintf(f," height="%d"", ref->height); + if ( ref->width ) Qprintf(f, " width="%d"", ref->width); + } + + if ( S(ref->title) ) { + Qstring(" title="", f); + ___mkd_reparse(T(ref->title), S(ref->title), MKD_TAGTEXT, f); + Qchar('"', f); + } + + Qstring(tag->text_pfx, f); + ___mkd_reparse(T(text), S(text), tag->flags, f); + Qstring(tag->text_sfx, f); + } + else + Qwrite(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f); + + return 1; +} /* linkyformat */ + + +/* + * process embedded links and images + */ +static int +linkylinky(int image, MMIOT *f) +{ + int start = mmiottell(f); + Cstring name; + Footnote key, *ref; + + int status = 0; + int extra_footnote = 0; + + CREATE(name); + memset(&key, 0, sizeof key); + + if ( linkylabel(f, &name) ) { + if ( peek(f,1) == '(' ) { + pull(f); + if ( linkyurl(f, image, &key) ) + status = linkyformat(f, name, image, &key); + } + else { + int goodlink, implicit_mark = mmiottell(f); + + if ( isspace(peek(f,1)) ) + pull(f); + + if ( peek(f,1) == '[' ) { + pull(f); /* consume leading '[' */ + goodlink = linkylabel(f, &key.tag); + } + else { + /* new markdown implicit name syntax doesn't + * require a second [] + */ + mmiotseek(f, implicit_mark); + goodlink = !(f->flags & MKD_1_COMPAT); + + if ( (f->flags & MKD_EXTRA_FOOTNOTE) && (!image) && S(name) && T(name)[0] == '^' ) + extra_footnote = 1; + } + + if ( goodlink ) { + if ( !S(key.tag) ) { + DELETE(key.tag); + T(key.tag) = T(name); + S(key.tag) = S(name); + } + + if ( ref = bsearch(&key, T(*f->footnotes), S(*f->footnotes), + sizeof key, (stfu)__mkd_footsort) ) { + if ( extra_footnote ) + status = extra_linky(f,name,ref); + else + status = linkyformat(f, name, image, ref); + } + else if ( f->flags & IS_LABEL ) + status = linkyformat(f, name, image, 0); + } + } + } + + DELETE(name); + ___mkd_freefootnote(&key); + + if ( status == 0 ) + mmiotseek(f, start); + + return status; +} + + +/* write a character to output, doing text escapes ( & -> &, + * > -> > < -> < ) + */ +static void +cputc(int c, MMIOT *f) +{ + switch (c) { + case '&': Qstring("&", f); break; + case '>': Qstring(">", f); break; + case '<': Qstring("<", f); break; + default : Qchar(c, f); break; + } +} + + +/* + * convert an email address to a string of nonsense + */ +static void +mangle(char *s, int len, MMIOT *f) +{ + while ( len-- > 0 ) { + Qstring("&#", f); + Qprintf(f, COINTOSS() ? "x%02x;" : "%02d;", *((unsigned char*)(s++)) ); + } +} + + +/* nrticks() -- count up a row of tick marks + */ +static int +nrticks(int offset, int tickchar, MMIOT *f) +{ + int tick = 0; + + while ( peek(f, offset+tick) == tickchar ) tick++; + + return tick; +} /* nrticks */ + + +/* matchticks() -- match a certain # of ticks, and if that fails + * match the largest subset of those ticks. + * + * if a subset was matched, return the # of ticks + * that were matched. + */ +static int +matchticks(MMIOT *f, int tickchar, int ticks, int *endticks) +{ + int size, count, c; + int subsize=0, subtick=0; + + *endticks = ticks; + for (size = 0; (c=peek(f,size+ticks)) != EOF; size ++) { + if ( (c == tickchar) && ( count = nrticks(size+ticks,tickchar,f)) ) { + if ( count == ticks ) + return size; + else if ( count ) { + if ( (count > subtick) && (count < ticks) ) { + subsize = size; + subtick = count; + } + size += count; + } + } + } + if ( subsize ) { + *endticks = subtick; + return subsize; + } + return 0; +} /* matchticks */ + + +/* code() -- write a string out as code. The only characters that have + * special meaning in a code block are * `<' and `&' , which + * are /always/ expanded to < and & + */ +static void +code(MMIOT *f, char *s, int length) +{ + int i,c; + + for ( i=0; i < length; i++ ) + if ( (c = s[i]) == 003) /* ^C: expand back to 2 spaces */ + Qstring(" ", f); + else + cputc(c, f); +} /* code */ + + +/* delspan() -- write out a chunk of text, blocking with <del>...</del> + */ +static void +delspan(MMIOT *f, int size) +{ + Qstring("<del>", f); + ___mkd_reparse(cursor(f)-1, size, 0, f); + Qstring("</del>", f); +} + + +/* codespan() -- write out a chunk of text as code, trimming one + * space off the front and/or back as appropriate. + */ +static void +codespan(MMIOT *f, int size) +{ + int i=0; + + if ( size > 1 && peek(f, size-1) == ' ' ) --size; + if ( peek(f,i) == ' ' ) ++i, --size; + + Qstring("<code>", f); + code(f, cursor(f)+(i-1), size); + Qstring("</code>", f); +} /* codespan */ + + +/* before letting a tag through, validate against + * MKD_NOLINKS and MKD_NOIMAGE + */ +static int +forbidden_tag(MMIOT *f) +{ + int c = toupper(peek(f, 1)); + + if ( f->flags & MKD_NOHTML ) + return 1; + + if ( c == 'A' && (f->flags & MKD_NOLINKS) && !isthisalnum(f,2) ) + return 1; + if ( c == 'I' && (f->flags & MKD_NOIMAGE) + && strncasecmp(cursor(f)+1, "MG", 2) == 0 + && !isthisalnum(f,4) ) + return 1; + return 0; +} + + +/* Check a string to see if it looks like a mail address + * "looks like a mail address" means alphanumeric + some + * s@@ Diff output truncated at 100000 characters. @@
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: TBD).