summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDon Scorgie <dscorgie@src.gnome.org>2007-07-30 21:46:35 +0000
committerDon Scorgie <dscorgie@src.gnome.org>2007-07-30 21:46:35 +0000
commitd9eb206fa6e6e42fad9cf1a07947e5ec502e4b69 (patch)
tree37f37194801a20aad7cd6ae7468cae128884ad55
parent89a4f049d8729dc6cac08ad14e5e4b1ba9c6d9d2 (diff)
downloadyelp-d9eb206fa6e6e42fad9cf1a07947e5ec502e4b69.tar.gz
Merge of yelp rework branch:
- Depreciate yelp-*-pager in favour of yelp-document and such. Gives us on-demand loading of pages - Switch to using rarian instead of scrollkeeper - Update to using shiny newness of gnome-doc-utils - Make printing docbook pretty - Clean up lots of errors and general cleanup of other source files - Make our resolver much, much better - and remove reliance on libgnome there svn path=/trunk/; revision=2848
-rw-r--r--ChangeLog901
-rw-r--r--configure.in54
-rw-r--r--po/ChangeLog37
-rw-r--r--po/oc.po174
-rw-r--r--po/te.po2
-rw-r--r--src/Makefile.am146
-rw-r--r--src/test-document.c149
-rw-r--r--src/test-man-parser.c49
-rw-r--r--src/test-page.c83
-rw-r--r--src/test-resolver.c271
-rw-r--r--src/test-transform.c163
-rw-r--r--src/yelp-base.c26
-rw-r--r--src/yelp-db-pager.c10
-rw-r--r--src/yelp-db-print-pager.c4
-rw-r--r--src/yelp-db-print.c767
-rw-r--r--src/yelp-db-print.h54
-rw-r--r--src/yelp-debug.c2
-rw-r--r--src/yelp-debug.h3
-rw-r--r--src/yelp-docbook.c785
-rw-r--r--src/yelp-docbook.h53
-rw-r--r--src/yelp-document.c807
-rw-r--r--src/yelp-document.h132
-rw-r--r--src/yelp-error.c120
-rw-r--r--src/yelp-error.h38
-rw-r--r--src/yelp-info-pager.c2
-rw-r--r--src/yelp-info-parser.c23
-rw-r--r--src/yelp-info.c433
-rw-r--r--src/yelp-info.h53
-rw-r--r--src/yelp-io-channel.c2
-rw-r--r--src/yelp-main.c6
-rw-r--r--src/yelp-man-pager.c2
-rw-r--r--src/yelp-man-parser.c45
-rw-r--r--src/yelp-man-parser.h4
-rw-r--r--src/yelp-man.c490
-rw-r--r--src/yelp-man.h53
-rw-r--r--src/yelp-page.c164
-rw-r--r--src/yelp-page.h88
-rw-r--r--src/yelp-print.c8
-rw-r--r--src/yelp-search-pager.c26
-rw-r--r--src/yelp-search-parser.c1459
-rw-r--r--src/yelp-search-parser.h36
-rw-r--r--src/yelp-search.c391
-rw-r--r--src/yelp-search.h53
-rw-r--r--src/yelp-settings.c225
-rw-r--r--src/yelp-settings.h34
-rw-r--r--src/yelp-toc-pager.c278
-rw-r--r--src/yelp-toc.c833
-rw-r--r--src/yelp-toc.h54
-rw-r--r--src/yelp-transform.c416
-rw-r--r--src/yelp-transform.h81
-rw-r--r--src/yelp-utils.c1287
-rw-r--r--src/yelp-utils.h126
-rw-r--r--src/yelp-window.c1654
-rw-r--r--src/yelp-window.h3
-rw-r--r--src/yelp-xslt-pager.c4
-rw-r--r--stylesheets/toc2html.xsl8
-rw-r--r--stylesheets/yelp-common.xsl4
-rw-r--r--yelp.desktop.in.in2
58 files changed, 10431 insertions, 2746 deletions
diff --git a/ChangeLog b/ChangeLog
index 04aa7147..52e26530 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,904 @@
+
+== REWORK CHANGES ==
+
+2007-07-30 Don Scorgie <dscorgie@svn.gnome.org>
+
+ Merge of yelp rework branch:
+ - Depreciate yelp-*-pager in favour of
+ yelp-document and such.
+ Gives us on-demand loading of pages
+ - Switch to using rarian instead of scrollkeeper
+ - Update to using shiny newness of gnome-doc-utils
+ - Make printing docbook pretty
+ - Clean up lots of errors and general cleanup
+ of other source files
+ - Make our resolver much, much better
+ - and remove reliance on libgnome there
+
+
+2007-07-30 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-settings.c:
+ * configure.in:
+ * src/yelp-settings.h:
+ * src/Makefile.am:
+ * stylesheets/yelp-common.xsl:
+ Make themes sort-of work. Good enough for
+ a release, anyway.
+
+2007-07-29 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-window.c:
+ Make loading of files directly work again
+
+2007-07-24 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-info.c:
+ * src/yelp-man.c:
+ * src/yelp-docbook.c:
+ Add in some pretty parameters
+
+ * src/yelp-db-print.c:
+ Fix parameters to make printed docs *slightly*
+ prettier
+
+ * src/yelp-search-parser.c:
+ Convert search across to use Rarian
+ and clean up lots of crud from the file
+
+2007-07-23 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * configure.ac:
+ * src/yelp-base.c:
+ * src/yelp-search-parser.c:
+ * src/yelp-search.c:
+ * src/yelp-window.c:
+ * src/yelp-window.h:
+ * src/yelp-utils.c:
+ * src/yelp-utils.h:
+ * src/Makefile.am:
+ * src/yelp-main.c:
+ Massive cleanup
+ Remove old code from yelp-utils
+ Fix shutdown requests from sessions (hopefully)
+ Remove as many warnings as possible (the rest are
+ mostly mozilla errors)
+ Make sure we get and set GLIB_GENMARSHAL as, apparently,
+ we have never done this which seems to result in badness
+ making the marshal.list
+
+ * src/Makefile.am:
+ * configure.ac:
+ * src/yelp-toc.c:
+ * src/yelp-search-parser.c:
+ * src/yelp-window.c:
+ * src/yelp-info-parser.c:
+ Lots of fun updates...
+ Clean up yelp-window.c a LOT
+ Remove old, obsolete code
+ Make search, man and info mandatory
+ Bump g-d-u min version to include new db2xhtml
+ code
+ Remove extra printf I'd forgotten
+
+2007-07-10 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-window.c:
+ Handle external URI's
+ Beginnings of error support (not complete)
+
+2007-07-08 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-window.c:
+ * src/yelp-search.c:
+ * src/yelp-search.h:
+ * src/yelp-search-parser.c:
+ * src/yelp-search-parser.h:
+ * src/yelp-utils.c:
+ * src/Makefile.am:
+ First pass at searching.
+ Search still relies on scrollkeeper. Other
+ than that, it seems to all work (with basic search at least)
+
+ * src/yelp-db-print.c:
+ * src/yelp-db-print.h:
+ * src/Makefile.am:
+ Make printing (pages and documents) work again.
+ Although, the calling xslt needs somewhat cleaned
+ up, it doesn't look particularly appealing atm.
+
+ * configure.in:
+ Temporarily work around breakage in gnome-doc-utils
+
+ * src/yelp-window.c:
+ Add back (empty) print menu items to stop errors
+ Add the "Loading..." and watch cursor when we are loading
+ Correctly set the sensitivity of relevant menu items for DocBooks
+ Make "About this document" work again
+
+ * src/yelp-docbook.c:
+ Since the new g-d-u currently has a list of topics on the
+ right, don't display the sections pane
+
+ * src/yelp-window.c:
+ Make history work again
+ Make loading HTML docs work
+
+ * src/yelp-utils.h:
+ * src/yelp-utils.c:
+ Make a distinction between html and xhtml
+ to keep gecko happy
+
+2007-07-07 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-utils.c:
+ * src/yelp-toc.c:
+ Fix info page titles in TOC
+ Fix file:// uri's when with too many /'s
+
+ * src/Makefile.am:
+ * src/yelp-info-parser.c:
+ * src/yelp-info.c:
+ * src/yelp-info.h:
+ * src/yelp-window.c:
+ Convert info pages across to new pager system
+ Hook up info pages into yelp, new style
+ Fix various things in the parser to cope with
+ having less available info for resolving frags
+
+ * src/yelp-toc.c:
+ Fix the most annoying error message in the world EVER
+ Unexpected async xlib errors generally mean threading issues
+ except, apparently, when you're trying to parse using libxml
+ in which case, they could mean anything. In this case, it
+ meant the params passed in was not NULL terminating.
+ Why this resulted in an unexpected xlib async reply is
+ left as an exercise to the reader. I spent 7 days trying to
+ figure it out.
+
+2007-07-01 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-toc.c:
+ Now Rarian is fast, don't split out man and info pages.
+ Add in params so the TOC looks nice and shiny
+ Fix a couple of silly warnings
+
+ * src/yelp-base.c:
+ Move initialisation of bookmarks and settings to before TOC
+
+2007-06-20 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * configure.in:
+ * src/test-resolver.c:
+ * src/yelp-toc.c:
+ * src/yelp-window.c:
+ * src/yelp-utils.c:
+ * src/yelp-utils.h:
+ Spoon is now Rarian. Bump min version to 0.5.0
+
+2007-06-14 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-utils.c:
+ Minor fix to recognise man:<filepath>
+
+ * src/Makefile.am:
+ * src/yelp-window.c:
+ Add support for docbook (yay!) and
+ man pages
+ Rename silly function names to something slightly
+ more sensible
+ Update my email address in help dialog (minor)
+
+ * src/test-document.c:
+ * src/yelp-document.c:
+ * src/yelp-document.h:
+ * src/yelp-docbook.c:
+ Add support for getting the sections GtkTreeModel
+ out
+
+ * src/yelp-page.c:
+ * src/yelp-page.h:
+ Add functions to get the length (remaining)
+ of page
+
+
+2007-06-13 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-window.c:
+ Make bookmarks work in the New World Order
+
+ * src/yelp-base.c:
+ start loading yelp-toc at start of
+ base to take advantage of threading
+ and make the toc load even quicker
+ (except man pages of course)
+
+ * src/yelp-toc.c:
+ Make icon work (when the rest of the
+ customisations are plumbed in)
+
+ * src/yelp-utils.c:
+ Fix result for TOC pages
+
+ * src/yelp-document.c:
+ Fix crash when canceling page request
+
+ * src/yelp-window.c:
+ Implement canceling of requests
+ Implement location dialog
+
+2007-06-12 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-window.c:
+ * src/yelp-base.c:
+ * src/yelp-window.h:
+ * src/yelp-utils.c:
+ * src/yelp-utils.h:
+ * src/Makefile.am:
+ * stylesheets/toc2html.xsl:
+ First pass at making yelp work again
+ Very, very broken, but TOC shows up (and is navigatable)
+ Thought, nothing else works and is
+ liable to crash if used
+ rename YELP_TYPE_* to YELP_SPOON_TYPE_*
+ to stop conflict when compiling
+ Oh, and introduce hundreds of compiler warnings
+
+ * src/yelp-toc.c:
+ * src/yelp-toc.h:
+ Make TOC doc singleton
+
+2007-06-12 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-utils.c:
+ Add ghelp resolve support
+ Many minor fixes to pass default test suite
+
+ * src/test-resolver.c:
+ Add default tests
+
+
+2007-06-11 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-utils.c:
+ Add man page resolver support. Make info fall back
+ to man pages when not found
+
+2007-06-11 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/test-resolver.c:
+ Add gnome-vfs-init() and section (for results section)
+
+ * src/yelp-utils.c:
+ Add support for resolving info and full path uri's.
+
+ * src/yelp-utils.h:
+ Add long description of resolver function
+
+2007-06-02 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/test-resolver.c:
+ Bit more framework
+
+ * src/yelp-utils.c:
+ * src/yelp-utils.h:
+ Beginnings of testing (sort-of recognises different types)
+ Add enum for different types
+ Add lots of printfs that should be removed at some point
+
+2007-05-31 Don Scorgie <dscorgie@svn.gnome.org>
+
+ * src/yelp-utils.h:
+ * src/yelp-utils.c:
+ Beginning (empty) of new utils resolver (masked by DON_UTILS define)
+
+ * src/test-resolver.c:
+ * src/Makefile.am:
+ Beginnings of resolver test
+
+
+2007-04-30 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-toc.c:
+ Add in man pages
+ Do an interesting use of the new stuff to
+ run 3 transforms - main, info and man so
+ we quickly get the main page, then get man and info when ready
+
+ * src/yelp-document.h:
+ * src/yelp-document.c:
+ Add yelp_document_has_page that's used
+ in yelp-toc
+
+2007-04-26 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-toc.c:
+ Add info page support
+
+ * stylesheets/toc2html.xsl:
+ * src/test-document.c:
+ * src/yelp-toc.c:
+ Make TOC work properly with new document structure
+
+ * src/yelp-page.c:
+ * src/yelp-docbook.c:
+ Various misc. changes to make docbook work properly
+ Add TODO's
+
+2007-04-24 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-toc.c:
+ * src/yelp-toc.h:
+ * src/yelp-db-pager.c:
+ * src/test-document.c:
+ * src/Makefile.am:
+ Initial commit of new yelp-toc (broken)
+ Add toc option to test-document (broken)
+
+
+2007-04-22 Shaun McCance <shaunm@gnome.org>
+
+ * ChangeLog
+ * src/Makefile.am:
+ * src/test-man-parser.c:
+ * src/yelp-debug.h:
+ * src/yelp-error.c:
+ * src/yelp-error.h:
+ * src/yelp-io-channel.c:
+ * src/yelp-man-parser.c:
+ * src/yelp-man-parser.h:
+ * src/yelp-utils.c:
+ * src/yelp-utils.h:
+ - Merging yelp-document into yelp-spoon
+
+2007-04-14 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-toc-pager.c:
+ Convert info TOC to use new spoon work
+ (slightly later) Convert man TOC to use new spoon work as well
+
+2007-03-25 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * stylesheets/toc2html.xsl:
+ * src/yelp-toc-pager.c:
+ First pass at spoon integration
+ TOC correctly displayed, replacing all sk code
+ with spoon_for_each_in_category()
+
+ * src/yelp-toc-pager.c:
+ * configure.in:
+ First work on Spoon integration
+ Search for pkg-config Spoon file
+ Run a spoon-for-each, printing doc names
+
+2007-03-12 Shaun McCance <shaunm@gnome.org>
+
+ * configure.in:
+ * NEWS:
+ - Version 2.18.0
+
+2007-02-23 Christian Persch <chpe@svn.gnome.org>
+
+ * src/Yelper.cpp:
+ * src/Yelper.h:
+ Fix for mozilla API change on trunk.
+
+2006-12-01 Christian Persch <chpe@cvs.gnome.org>
+
+ * configure.in:
+ * m4/gecko.m4:
+ * src/Makefile.am:
+ * src/Yelper.cpp:
+ Fix for mozilla API change on trunk.
+
+2006-11-20 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * NEWS:
+ * configure.in:
+ - Version 2.16.2
+
+2006-11-20 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-utils.c:
+ When info:dir contains a link to a subdir,
+ but not an info name, work as expected
+ (Really fixes bug #371680)
+
+ * src/yelp-io-channel.c:
+ Check the file exists and is valid before trying
+ to read it (fixes bug #371680)
+
+ * src/yelp-gecko-services.cpp:
+ Fix printing ranges (bug #370618, Christian Persch)
+
+ * src/yelp-info-parser.c:
+ When whitespace on new line of a note is < 2,
+ don't crash (bug #376861)
+ Fix crash on libc info page (bug #367410, Matthias Clasen)
+
+2006-11-05 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-main.c:
+ Don't crash when saving session (bug #364790)
+
+ * src/yelp-search-pager.c:
+ Replace ':' chars in search strings with ' '
+ Stops from crashing (bug #364768)
+ Don't chew memory when search string contains
+ 2 consecutive spaces
+
+2006-10-25 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-info-parser.c:
+ Fix double free in stupid link types only used by gdb
+ info page (apparently). Bug #364850
+
+ * src/yelp-search-pager.c:
+ Don't crash when searching for empty term. Bug #363949
+
+2006-10-07 Elijah Newren <newren gmail com>
+
+ * src/yelp-print.c (yelp_print_present_status_dialog): Remove
+ markup from translatable messages. #360450
+
+2006-10-05 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-utils.c:
+ Don't crash when manpath (prog) || MANPATH (env.)
+ is available
+
+==================== 2.16.1 ====================
+2006-10-02 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * NEWS:
+ * configure.in:
+ - Version 2.16.1
+
+2006-09-29 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-settings.c:
+ * src/yelp-settings.h:
+ * src/yelp-window.c:
+ Make F7 toggle caret properly
+ Set initial state of caret in prefs window
+
+2006-09-17 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/Yelper.cpp:
+ * src/Yelper.h:
+
+ Fix the build with gecko trunk.
+
+2006-09-12 Christian Persch <chpe@cvs.gnome.org>
+
+ * m4/gecko.m4:
+
+ Prefer xulrunner over mozilla.
+
+==================== 2.16.0 ====================
+2006-09-04 Brent Smith <gnome@nextreality.net>
+
+ * NEWS:
+ * configure.in:
+ - Version 2.16.0
+
+2006-09-03 Brent Smith <gnome@nextreality.net>
+
+ * src/yelp-toc-pager.c: (toc_add_doc_info): check if the document
+ category exists, and return if it does not should fix 353554
+
+2006-08-30 Don Scorgie <don@Madaline>
+
+ * src/yelp-io-channel.c:
+ Don't double free bzip streams
+
+2006-08-30 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-search-pager.c:
+ Move online url to perminant address at gnome.org
+
+2006-08-28 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-io-channel.c:
+ Supress critical warning when it isn't actually
+ critical
+
+ * src/yelp-info-parser.c:
+ * src/yelp-io-channel.c:
+ Don't fall over when part of the info file
+ goes missing (bug #353209)
+
+2006-08-16 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-search-pager.c:
+ Fix crash when apropos goes nuts (bug #347467)
+ Patch from Priit Laes
+
+2006-08-10 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-info-parser.c:
+ Fix stupid crash on CVS info file caused by
+ fake *Notes, trying to trick yelp into making
+ them hyperlinks when they shouldn't be
+
+==================== 2.15.91 ====================
+2006-08-07 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * NEWS:
+ * configure.in:
+ - Version 2.15.91
+
+ * src/yelp-search-pager.c:
+ Remove translation of online URL in anticipation of a
+ new script to do the redirection
+
+2006-08-05 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-pager.c:
+ * src/yelp-toc-pager.c:
+ * src/yelp-window.c:
+ * src/yelp-search-pager.c:
+ Various misc. cleanups.
+ - Keep track of idle functions and callbacks
+ - don't use depreciated gtk_idle_add function
+ Based on patch from Christian Persch
+
+ * src/yelp-main.c:
+ Initialise dbus threading before gnome-vfs. Bug #350079
+
+2006-07-25 Shaun McCance <shaunm@gnome.org>
+
+ * data/toc.xml.in:
+ - Changed "Sound & Vision" to "Sound & Video"
+
+2006-07-25 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * stylesheets/search2html.xsl:
+ Remove fixed font sizes from search results
+ Remove fixed colours from search results
+ Fixes bug #348563 and makes page respect
+ theme setting
+
+
+==================== 2.15.5 ====================
+
+2006-07-24 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * NEWS:
+ * configure.in:
+ - Version 2.15.5
+
+2006-07-24 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-search-pager.c:
+ * stylesheets/search2html.xsl:
+ Add a new link to the search results to allow
+ repeating the search online at the GNOME support forums
+ Additionally: Allow better translation of the message
+ Allow translation of the site name
+ Additionally (2): Allow online search locations to be
+ translated to point to support sites
+ in a native language
+
+
+2006-07-23 Brent Smith <gnome@nextreality.net>
+
+ * configure.in: Depend on beagle 0.2.4 since that is the first version
+ with the beagle_util_daemon_is_running() function.
+ * src/yelp-search-pager.c: (search_pager_class_init):
+ Use beagle_util_daemon_is_running() to make sure that the daemon is
+ actually running, and the socket at ~/.beagle/socket is not stale.
+ Fixes #348362
+
+2006-07-23 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-search-pager.c:
+ Large basic search update:
+ - Common words are ignored (how, do etc.)
+ - Common suffixes and prefixes are checked
+ - Fix problems with searching in some docbook docs
+ - Better scoring mechanism
+ - Slightly improved matching algorithm
+ - Fix searching HTML docs
+ - Better snippet highlighting
+ - Clean sections of code slightly
+ Bugs fixed: #341797, #341800, #347819 (work around)
+ Partially fixed: #335962
+
+
+ * src/yelp-settings.c:
+ Use a gtk_link_button instead of gnome_href
+
+ * src/yelp-print.c:
+ * src/yelp-print.h:
+ * src/yelp-gecko-services.cpp:
+ * src/yelp-gecko-services.h:
+ * src/Yelper.cpp:
+ * configure.in:
+ Move to GtkPrinting.
+ Bump min gtk version to 2.10
+ Remove libgnomeprint dependency
+
+2006-07-22 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * configure.in:
+ Remove additional but not run pkg-config check
+
+ * src/yelp-window.c:
+ Remove a couple of headers that shouldn't be here
+ Remove call to gnome_help_display_desktop and
+ replace with a much simpler call to create a new window
+ and show the relevant section of the user guide, making it
+ much quicker to display help->Contents
+
+ * src/yelp-html.cpp:
+ * src/yelp-window.c:
+ Remove libgnomeui dependancy from both.
+ Switch to GTK_STOCK_ABOUT instead of libgnome equivalent
+
+2006-07-21 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-window.c:
+ * src/yelp-search-pager.c:
+ Clean up some compiler warnings
+ (Casts and unused variables)
+
+2006-07-19 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-toc-pager.c:
+ Select the correct translation of the description of sections
+ Fixes bug #347816
+ Clean up a couple of compiler warnings
+
+==================== 2.15.4 ====================
+
+2006-07-10 Brent Smith <gnome@nextreality.net>
+
+ * NEWS:
+ * configure.in:
+ - Version 2.15.4
+
+2006-07-10 Brent Smith <gnome@nextreality.net>
+
+ * data/info.xml.in:
+ * data/man.xml.in:
+ * data/scrollkeeper.xml:
+ * data/toc.xml.in:
+ - Restructure the table of contents to make most documentation
+ accessible via a single click (except for man pages and info pages)
+ - Put descriptions for each section at the top in the right side
+ above the document listing
+ - Rename the top level category to 'Desktop' and include the
+ User guide, System Administration Guide, and Accessibility Guide
+ in this section
+ * src/yelp-pager.c: (yelp_pager_get_page_from_id):
+ * src/yelp-pager.h:
+ * src/yelp-toc-pager.c: (toc_pager_resolve_frag),
+ (toc_process_pending), (process_mandir_pending),
+ (process_info_pending), (process_read_menu), (process_cleanup):
+ * src/yelp-window.c: (window_do_load_pager), (pager_finish_cb):
+ Load each table of contents page on demand instead of
+ creating all pages at once.
+ * stylesheets/toc2html.xsl:
+ Maintain a list of categories on the left hand side in the
+ table of contents, that expands subcategories for the currently
+ selected category
+
+2006-07-07 Wouter Bolsterlee <uws+gnome@xs4all.nl>
+
+ * src/yelp-window.c: (tree_row_expand_cb):
+ Expand/collapse on double-click. Really fixes bug
+ #346871.
+
+2006-07-07 Don Scorgie <dscorgie@cvs.gnome.org>
+
+ * src/yelp-window.c:
+ Expand sections on double-click (bug #346871)
+
+=======
+2007-04-12 Shaun McCance <shaunm@gnome.org>
+
+ * src/Makefile.am:
+ * src/yelp-man.c:
+ * src/yelp-man.h:
+ * src/test-document.c:
+ - Made man pages work with YelpDocument
+
+ * src/yelp-docbook.c:
+ * src/yelp-document.c:
+ - General clean up
+
+2007-04-12 Shaun McCance <shaunm@gnome.org>
+
+ * src/yelp-document.c:
+ * src/yelp-page.c:
+ * src/yelp-page.h:
+ - Added preliminary support for mime types in yelp-page
+
+2007-04-12 Shaun McCance <shaunm@gnome.org>
+
+ * src/yelp-man-parser.c:
+ * src/Makefile.am:
+ - Made yelp-man-parser use yelp-debug
+
+2007-04-11 Shaun McCance <shaunm@gnome.org>
+
+ * src/yelp-error.c:
+ * src/yelp-error.h:
+ * src/yelp-io-channel.c:
+ - Added back the GError convenience functions
+
+ * src/Makefile.am:
+ * src/test-man-parser.c:
+ * src/yelp-man-parser.c:
+ * src/yelp-man-parser.h:
+ - Getting the man stuff to work in the new world order
+
+ * src/yelp-transform.c:
+ - Added a cast to shut gcc up
+
+ * src/test-document.c:
+ * src/yelp-document.h:
+ * src/yelp-docbook.c:
+ * src/yelp-docbook.h:
+ * src/yelp-page.c:
+ * src/yelp-page.h:
+ - Moving much of the request-handling to YelpDocument
+
+2007-04-04 Shaun McCance <shaunm@gnome.org>
+
+ * src/yelp-error.c:
+ * src/yelp-error.h:
+ - Added yelp_error_copy
+
+ * src/yelp-transform.c:
+ - Added a few debug statements
+
+ * src/test-transform.c:
+ - Added the --random-timeout option
+
+ * src/yelp-page.c:
+ - Don't use g_free with memory slicese.
+
+ * src/yelp-docbook.c:
+ * src/yelp-docbook.h:
+ * src/yelp-document.c:
+ * src/yelp-document.h:
+ - Added a more-or-less complete YelpDocument implementation for DocBook
+
+ * src/test-document.c:
+ * src/Makefile.am:
+ - Added a test program for YelpDocument, currently only using DocBook
+
+2007-03-22 Shaun McCance <shaunm@gnome.org>
+
+ * src/test-transform.c:
+ * src/yelp-transform.c:
+ * src/yelp-transform.h:
+ - Do not do callbacks if released
+
+ * src/yelp-page.h:
+ - Added a comment
+
+ * src/yelp-document.c:
+ * src/yelp-document.h:
+ - Filled out the abstract functions
+
+ * src/Makefile.am:
+ - Some changes to the test programs we build
+
+2007-03-20 Shaun McCance <shaunm@gnome.org>
+
+ * src/yelp-transform.c:
+ - Added some locks
+
+ * src/Makefile.am:
+ * src/test-page.c:
+ - Adding a test application for YelpPage
+
+ * src/yelp-page.c:
+ * src/yelp-page.h:
+ - Fairly complete YelpPage for strings
+
+ * src/yelp-document.c:
+ * src/yelp-document.h:
+ - Big not-yet-done changes, but needed for test-page
+
+2007-03-20 Shaun McCance <shaunm@gnome.org>
+
+ * src/yelp-transform.c:
+ - Fixed concurrency issues when freeing
+
+ * src/test-transform.c:
+ - Using GOption to get a --timeout option
+ - Don't release a transform twice
+
+2007-03-20 Shaun McCance <shaunm@gnome.org>
+
+ * src/test-transform.c:
+ * src/yelp-error.c:
+ * src/yelp-error.h:
+ - Making YelpError cleaner and more usable for our purposes
+
+ * src/yelp-transform.c:
+ * src/yelp-transform.h:
+ - Copyright in 2007 too
+
+ * src/yelp-page.c:
+ * src/yelp-page.h:
+ - The beginnings of the new read()-able YelpPage
+
+ * src/Makefile.am:
+ - yelp-error.h != yelp-transform.h
+
+2007-03-17 Shaun McCance <shaunm@gnome.org>
+
+ * src/test-transform.c:
+ * src/yelp-transform.c:
+ * src/yelp-transform.h:
+ - Changed the callback API a bit, basically ready
+
+2006-07-03 Brent Smith <gnome@nextreality.net>
+
+ * src/yelp-document.c: (yelp_document_dispose),
+ (yelp_document_finalize), (yelp_document_class_init),
+ (yelp_document_init), (document_set_property),
+ (document_get_property), (yelp_document_get_page),
+ (yelp_document_cancel_get), (yelp_document_get_sections),
+ (yelp_document_add_page):
+ * src/yelp-document.h:
+ * src/yelp-page.c: (yelp_page_new), (yelp_page_set_id),
+ (yelp_page_get_id), (yelp_page_set_title), (yelp_page_get_title),
+ (yelp_page_set_contents), (yelp_page_get_contents),
+ (yelp_page_set_prev_id), (yelp_page_get_prev_id),
+ (yelp_page_set_next_id), (yelp_page_get_next_id),
+ (yelp_page_set_toc_id), (yelp_page_get_toc_id), (yelp_page_free):
+ * src/yelp-page.h:
+ - Add these to the correct directory
+ * yelp-document.c:
+ * yelp-document.h:
+ * yelp-page.c:
+ * yelp-page.h:
+ - Remove these (I put them in the wrong directory in the last commit)
+
+2006-07-03 Brent Smith <gnome@nextreality.net>
+
+ * src/yelp-debug.h: Put an #ifdef around HAVE_CONFIG_H
+ * src/yelp-utils.c:
+ * src/yelp-utils.h:
+ - Get rid of the unused YelpDocPage type and related function(s)
+ - created branch "yelp-document", branchpoint
+ YELP_DOCUMENT_BRANCHPOINT for working on the new YelpDocument API; see
+ http://live.gnome.org/Yelp
+ * yelp-document.c: (yelp_document_dispose),
+ (yelp_document_finalize), (yelp_document_class_init),
+ (yelp_document_init), (document_set_property),
+ (document_get_property), (yelp_document_get_page),
+ (yelp_document_cancel_get), (yelp_document_get_sections),
+ (yelp_document_add_page):
+ * yelp-document.h:
+ * yelp-page.c: (yelp_page_new), (yelp_page_set_id),
+ (yelp_page_get_id), (yelp_page_set_title), (yelp_page_get_title),
+ (yelp_page_set_contents), (yelp_page_get_contents),
+ (yelp_page_set_prev_id), (yelp_page_get_prev_id),
+ (yelp_page_set_next_id), (yelp_page_get_next_id),
+ (yelp_page_set_toc_id), (yelp_page_get_toc_id), (yelp_page_free):
+ * yelp-page.h:
+ New files yelp-document.[ch] and yelp-page.[ch] for the new API
+
+2006-07-03 Shaun McCance <shaunm@gnome.org>
+
+ * src/Makefile.am:
+ * src/test-transform.c:
+ * src/yelp-transform.c:
+ * src/yelp-transform.h:
+ * src/yelp-error.c:
+ * src/yelp-error.h:
+ - Glorious threaded XSLT transformation
+
+== END OF REWORK CHANGES ==
+
+
2007-04-20 Christian Kirbach <Christian.Kirbach@googlemail.com>
* yelp.desktop.in.in:
diff --git a/configure.in b/configure.in
index afca729e..d7a1d338 100644
--- a/configure.in
+++ b/configure.in
@@ -1,4 +1,4 @@
-AC_INIT([Yelp],[2.18.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=yelp],[yelp])
+AC_INIT([Yelp],[2.18.0],[http://bugzilla.gnome.org/enter_bug.cgi?product=yelp],[yelp])
GNOME_COMMON_INIT
@@ -66,7 +66,7 @@ AM_GLIB_DEFINE_LOCALEDIR([GNOMELOCALEDIR])
PKG_CHECK_MODULES(YELP,
[
gconf-2.0
- gnome-doc-utils >= 0.3.1
+ gnome-doc-utils >= 0.11.1
gtk+-unix-print-2.0
gnome-vfs-2.0 >= 1.1
gtk+-2.0 >= 2.10.0
@@ -78,6 +78,7 @@ PKG_CHECK_MODULES(YELP,
libexslt >= 0.8.1
libstartup-notification-1.0 >= 0.8
dbus-glib-1
+ rarian >= 0.5.0
])
AC_SUBST([YELP_CFLAGS])
AC_SUBST([YELP_LIBS])
@@ -88,9 +89,15 @@ XSLT_PATH="`$PKG_CONFIG --variable=xsltdir gnome-doc-utils`"
DB_TITLE="$XSLT_PATH""/docbook/common/db-title.xsl"
AC_SUBST(DB_TITLE)
-DB2HTML="`$PKG_CONFIG --variable=db2html gnome-doc-utils`"
+DB2HTML="`$PKG_CONFIG --variable=db2xhtml gnome-doc-utils`"
AC_SUBST(DB2HTML)
+GDU_ICON_PATH="`$PKG_CONFIG --variable=icondir gnome-doc-utils`/hicolor/48x48/"
+AC_SUBST(GDU_ICON_PATH)
+
+GLIB_GENMARSHAL="`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`"
+AC_SUBST(GLIB_GENMARSHAL)
+
#
# If Pango included the shared library dependencies from X11 in
# the pkg-config output, then we use that (to avoid duplicates).
@@ -121,34 +128,6 @@ fi
AC_SUBST(X_LIBS)
-AC_ARG_ENABLE([man],
- [AC_HELP_STRING([--enable-man],
- [turn on man page support [default=yes]])],,
- enable_man=yes)
-AC_ARG_ENABLE([info],
- [AC_HELP_STRING([--enable-info],
- [turn on GNU info support [default=yes]])],,
- enable_info=yes)
-if test "x$enable_man" = "xyes"; then
- AC_DEFINE(ENABLE_MAN, 1, [turn on man page support])
- AM_CONDITIONAL(ENABLE_MAN, true)
-else
- AM_CONDITIONAL(ENABLE_MAN, false)
-fi
-if test "x$enable_info" = "xyes"; then
- AC_DEFINE(ENABLE_INFO, 1, [turn on GNU info support])
- AM_CONDITIONAL(ENABLE_INFO, true)
-else
- AM_CONDITIONAL(ENABLE_INFO, false)
-fi
-
-if test "x$enable_man" = "xyes" -o "x$enable_info" = "xyes"; then
- AC_DEFINE(ENABLE_MAN_OR_INFO, 1, [turn of man page or GNU info support])
- AM_CONDITIONAL(ENABLE_MAN_OR_INFO, true)
-else
- AM_CONDITIONAL(ENABLE_MAN_OR_INFO, false)
-fi
-
dnl ******
dnl beagle
@@ -157,7 +136,7 @@ dnl ******
BEAGLE_MODULES="libbeagle-0.0 >= 0.2.4"
AC_ARG_WITH([search],
- [AC_HELP_STRING([--with-search=basic|beagle|auto|no],
+ [AC_HELP_STRING([--with-search=basic|beagle|auto],
[turn on search support [default=auto]])], ,
with_search=auto)
@@ -165,7 +144,6 @@ if test "x$with_search" = "xauto"; then
PKG_CHECK_MODULES(YELP_SEARCH, $BEAGLE_MODULES, have_beagle=yes, have_beagle=no)
fi
-AM_CONDITIONAL(ENABLE_SEARCH, test x"$with_search" != xno)
AM_CONDITIONAL(ENABLE_BEAGLE, test x"$with_search" = xbeagle)
if test "x$with_search" = "xbeagle"; then
@@ -176,18 +154,12 @@ fi
case "x$with_search" in
"xbasic")
search_backend="basic"
- AC_DEFINE(ENABLE_SEARCH, 1, [Define if you want any search])
;;
"xbeagle")
search_backend="beagle"
- AC_DEFINE(ENABLE_SEARCH, 1, [Define if you want any search])
AC_DEFINE(ENABLE_BEAGLE, 1, [Define if you want the power of Beagle])
;;
- "xno")
- search_backend="none"
- ;;
"xauto")
- AC_DEFINE(ENABLE_SEARCH, 1)
search_backend="auto - basic"
if test x$have_beagle = xyes; then
AC_DEFINE(ENABLE_BEAGLE, 1)
@@ -195,7 +167,7 @@ case "x$with_search" in
fi
;;
*)
- AC_MSG_ERROR([Unknown search type selected - Please use --with-search=auto|basic|beagle|no])
+ AC_MSG_ERROR([Unknown search type selected - Please use --with-search=auto|basic|beagle])
;;
esac
@@ -289,8 +261,6 @@ yelp-$VERSION:
compiler: ${CC}
Debug enabled: ${enable_debug}
- Man Pages enabled: ${enable_man}
- Info Pages enabled: ${enable_info}
Search backend: ${search_backend}
Mozilla version: ${MOZILLA}
"
diff --git a/po/ChangeLog b/po/ChangeLog
index 8e7532c4..f9c50687 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,40 +1,3 @@
-2007-07-16 Ilkka Tuohela <hile@iki.fi>
-
- * fi.po: Updated Finnish translation.
-
-2007-07-16 Sunil Mohan Adapa <sunil@atc.tcs.com>
-
- * te.po: Added Telugu translation done by
- Bharat Kumar <jonnalagaddabharat@gmail.com>.
-
-2007-06-28 Priit Laes <plaes@svn.gnome.org>
-
- * et.po: Estonian translation update by Ivar Smolin.
-
-2007-06-13 Yair Hershkovitz <yairhr@gmail.com>
-
- * he.po: Updated Hebrew translation.
-
-2007-05-23 Rhys Jones <rhys@sucs.org>
-
- * cy.po: Updated Welsh translation.
-
-2007-04-17 Guntupalli Karunakar <karunakar@indlinux.org>
-
- * hi.po: Updated Hindi translation.
-
-2007-04-10 Peter Bach <bach.peter@gmail.com>
-
- * da.po: Updated Danish translation.
-
-2007-04-03 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
-
- * eu.po: Updated Basque translation.
-
-2007-03-25 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
-
- * gl.po: Updated Galician Translation.
-
2007-03-23 Luca Ferretti <elle.uca@libero.it>
* it.po: Updated Italian translation.
diff --git a/po/oc.po b/po/oc.po
index b7d33e80..aa688288 100644
--- a/po/oc.po
+++ b/po/oc.po
@@ -8,16 +8,16 @@ msgid ""
msgstr ""
"Project-Id-Version: or\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-08-10 00:46+0200\n"
+"POT-Creation-Date: 2007-07-29 15:14+0100\n"
"PO-Revision-Date: 2007-05-13 13:26+0200\n"
"Last-Translator: Yannig MARCHEGAY <yannig@marchegay.org>\n"
"Language-Team: Occitan (post 1500) <ubuntu-l10n-oci@lists.ubuntu.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-#: ../data/info.xml.in.h:1 ../src/yelp-toc-pager.c:1849
+#: ../data/info.xml.in.h:1 ../src/yelp-toc-pager.c:1847
msgid "GNU Info Pages"
msgstr "Paginas d'informacions GNU"
@@ -61,7 +61,7 @@ msgstr "Periferics materials"
msgid "Kernel Routines"
msgstr ""
-#: ../data/man.xml.in.h:10 ../src/yelp-toc-pager.c:1843
+#: ../data/man.xml.in.h:10 ../src/yelp-toc-pager.c:1841
msgid "Manual Pages"
msgstr "Paginas del manual"
@@ -605,7 +605,7 @@ msgstr ""
"Impossible d'analizar '%s'. Ja lo fichièr existís pas, ja es pas una pagina "
"XML corrècta."
-#: ../src/yelp-io-channel.c:101
+#: ../src/yelp-io-channel.c:107
#, c-format
msgid ""
"The file ‘%s’ could not be read and decoded. The file may be compressed in "
@@ -614,20 +614,20 @@ msgstr ""
"Impossible de legir e descodar lo fichièr \"%s\". Es possible que lo fichièr "
"siá compressat dins un format pas gerit."
-#: ../src/yelp-main.c:91
+#: ../src/yelp-main.c:92
msgid "Use a private session"
msgstr "Utilisar una session privada"
-#: ../src/yelp-main.c:100
+#: ../src/yelp-main.c:101
msgid "Define which cache directory to use"
msgstr "Definís lo repertòri d'escondedor d'utilizar"
#. Commandline parsing is done here
-#: ../src/yelp-main.c:354
+#: ../src/yelp-main.c:358
msgid " GNOME Help Browser"
msgstr " Navegador d'ajuda GNOME"
-#: ../src/yelp-main.c:372 ../yelp.desktop.in.in.h:2
+#: ../src/yelp-main.c:376 ../yelp.desktop.in.in.h:2
msgid "Help"
msgstr "Ajuda"
@@ -661,23 +661,19 @@ msgstr "Aquesta estampadoira gerís pas l'estampatge"
msgid "Printer %s does not support postscript printing."
msgstr "L'estampadoira %s gerís pas l'estampatge PostScript."
-#: ../src/yelp-print.c:337
+#: ../src/yelp-print.c:337 ../src/yelp-print.c:365
msgid "Printing"
msgstr "Estampatge"
-#: ../src/yelp-print.c:364
-msgid "<b>Printing</b>"
-msgstr ""
-
-#: ../src/yelp-print.c:366
+#: ../src/yelp-print.c:367
msgid "Waiting to print"
msgstr ""
-#: ../src/yelp-print.c:578
+#: ../src/yelp-print.c:579
msgid "An error occurred while printing"
msgstr "I a agut una error al moment d'estampar"
-#: ../src/yelp-print.c:582
+#: ../src/yelp-print.c:583
#, c-format
msgid "It was not possible to print your document: %s"
msgstr "Impossible d'estampar vòstre document : %s"
@@ -719,17 +715,17 @@ msgstr "Resultas de la recèrca per \"%s\""
msgid "Repeat the search online at %s"
msgstr ""
-#: ../src/yelp-search-pager.c:905 ../src/yelp-toc-pager.c:2144
+#: ../src/yelp-search-pager.c:905 ../src/yelp-toc-pager.c:2068
#: ../src/yelp-xslt-pager.c:364
msgid "No href attribute found on yelp:document"
msgstr ""
-#: ../src/yelp-search-pager.c:919 ../src/yelp-toc-pager.c:2157
+#: ../src/yelp-search-pager.c:919 ../src/yelp-toc-pager.c:2081
#: ../src/yelp-xslt-pager.c:380 ../src/yelp-xslt-pager.c:531
msgid "Out of memory"
msgstr "Pas pro de memòria"
-#: ../src/yelp-search-pager.c:960 ../src/yelp-toc-pager.c:2206
+#: ../src/yelp-search-pager.c:960 ../src/yelp-toc-pager.c:2130
msgid "Help Contents"
msgstr "Somari de l'ajuda"
@@ -741,7 +737,7 @@ msgstr "Somari de l'ajuda"
#. * "how do I", and words for functional states like "not",
#. * "work", and "broken".
#.
-#: ../src/yelp-search-pager.c:1286
+#: ../src/yelp-search-pager.c:1288
msgid ""
"a:about:an:are:as:at:be:broke:broken:by:can:can't:dialog:dialogue:do:doesn't:"
"doesnt:don't:dont:explain:for:from:get:gets:got:make:makes:not:when:has:have:"
@@ -757,7 +753,7 @@ msgstr ""
#. * E.g. if the common prefix is re then the string would be
#. * "re:"
#.
-#: ../src/yelp-search-pager.c:1302
+#: ../src/yelp-search-pager.c:1304
msgid "re"
msgstr ""
@@ -768,11 +764,11 @@ msgstr ""
#. * please use the strig NULL. If there is only 1, please
#. * add a colon at the end of the list
#.
-#: ../src/yelp-search-pager.c:1311
+#: ../src/yelp-search-pager.c:1313
msgid "ers:er:ing:es:s:'s"
msgstr ""
-#: ../src/yelp-search-pager.c:1506 ../src/yelp-toc-pager.c:631
+#: ../src/yelp-search-pager.c:1518 ../src/yelp-toc-pager.c:629
#, c-format
msgid "Could not load the OMF file '%s'."
msgstr "Impossible de cargar lo fichièr OMF '%s'."
@@ -802,248 +798,248 @@ msgstr "Impossible de cargar lo fichièr OMF '%s'."
msgid "yelp-watermark-blockquote-201C"
msgstr "yelp-watermark-blockquote-00AB"
-#: ../src/yelp-toc-pager.c:268
+#: ../src/yelp-toc-pager.c:267
msgid "YelpTocPager: Pause count is negative."
msgstr ""
-#: ../src/yelp-toc-pager.c:379 ../src/yelp-toc-pager.c:1957
+#: ../src/yelp-toc-pager.c:378
#, c-format
msgid ""
"The table of contents could not be processed. The file ‘%s’ is either "
"missing or is not a valid XSLT stylesheet."
msgstr ""
-#: ../src/yelp-toc-pager.c:1110
+#: ../src/yelp-toc-pager.c:1109
#, c-format
msgid "Read man page for %s"
msgstr "Legir la pagina man per %s"
-#: ../src/yelp-toc-pager.c:1703
+#: ../src/yelp-toc-pager.c:1701
#, c-format
msgid "Read info page for %s"
msgstr "Legir la pagina info per %s"
-#: ../src/yelp-toc-pager.c:1816
+#: ../src/yelp-toc-pager.c:1814
#, c-format
msgid ""
"The table of contents could not be loaded. The file ‘%s’ is either missing "
"or is not well-formed XML."
msgstr ""
-#: ../src/yelp-toc-pager.c:1838
+#: ../src/yelp-toc-pager.c:1836
msgid "Command Line Help"
msgstr "Ajuda per la linha de comanda"
-#: ../src/yelp-window.c:318
+#: ../src/yelp-window.c:317
msgid "_File"
msgstr "_Fichièr"
-#: ../src/yelp-window.c:319
+#: ../src/yelp-window.c:318
msgid "_Edit"
msgstr "_Edicion"
-#: ../src/yelp-window.c:320
+#: ../src/yelp-window.c:319
msgid "_Go"
msgstr "_Anar"
-#: ../src/yelp-window.c:321
+#: ../src/yelp-window.c:320
msgid "_Bookmarks"
msgstr "_Favorits"
-#: ../src/yelp-window.c:322
+#: ../src/yelp-window.c:321
msgid "_Help"
msgstr "_Ajuda"
-#: ../src/yelp-window.c:325
+#: ../src/yelp-window.c:324
msgid "_New Window"
msgstr "Fenèstra _nòva"
-#: ../src/yelp-window.c:330
+#: ../src/yelp-window.c:329
msgid "Print This Document"
msgstr "Estampar aqueste document"
-#: ../src/yelp-window.c:335
+#: ../src/yelp-window.c:334
msgid "Print This Page"
msgstr "Estampar aquesta pagina"
-#: ../src/yelp-window.c:340
+#: ../src/yelp-window.c:339
msgid "About This Document"
msgstr "A prepaus del document"
-#: ../src/yelp-window.c:345
+#: ../src/yelp-window.c:344
msgid "Open _Location"
msgstr "Dobrir un _emplaçament"
-#: ../src/yelp-window.c:350
+#: ../src/yelp-window.c:349
msgid "_Close Window"
msgstr "_Tampar la fenèstra"
-#: ../src/yelp-window.c:356
+#: ../src/yelp-window.c:355
msgid "_Copy"
msgstr "_Copiar"
-#: ../src/yelp-window.c:362
+#: ../src/yelp-window.c:361
msgid "_Select All"
msgstr "Tot _seleccionar"
-#: ../src/yelp-window.c:367
+#: ../src/yelp-window.c:366
msgid "_Find..."
msgstr "_Recèrcar"
-#: ../src/yelp-window.c:372
+#: ../src/yelp-window.c:371
msgid "Find Pre_vious"
msgstr "Recèrcar lo _precedent"
-#: ../src/yelp-window.c:374
+#: ../src/yelp-window.c:373
msgid "Find previous occurrence of the word or phrase"
msgstr ""
-#: ../src/yelp-window.c:377
+#: ../src/yelp-window.c:376
msgid "Find Ne_xt"
msgstr "Recèrcar lo seguent"
-#: ../src/yelp-window.c:379
+#: ../src/yelp-window.c:378
msgid "Find next occurrence of the word or phrase"
msgstr ""
-#: ../src/yelp-window.c:382
+#: ../src/yelp-window.c:381
msgid "_Preferences"
msgstr "_Preferéncias"
-#: ../src/yelp-window.c:387
+#: ../src/yelp-window.c:386
msgid "_Reload"
msgstr "_Tornar cargar"
-#: ../src/yelp-window.c:399
+#: ../src/yelp-window.c:398
msgid "_Back"
msgstr "_Tornar"
-#: ../src/yelp-window.c:401
+#: ../src/yelp-window.c:400
msgid "Show previous page in history"
msgstr "Visualizar la pagina precedenta de l'istoric"
-#: ../src/yelp-window.c:404
+#: ../src/yelp-window.c:403
msgid "_Forward"
msgstr "_Seguent"
-#: ../src/yelp-window.c:406
+#: ../src/yelp-window.c:405
msgid "Show next page in history"
msgstr "Visualizar la pagina seguenta de l'istoric"
-#: ../src/yelp-window.c:409
+#: ../src/yelp-window.c:408
msgid "_Help Topics"
msgstr "Somari de l'_ajuda"
-#: ../src/yelp-window.c:411
+#: ../src/yelp-window.c:410
msgid "Go to the listing of help topics"
msgstr ""
-#: ../src/yelp-window.c:414
+#: ../src/yelp-window.c:413
msgid "_Previous Section"
msgstr "Seccion _precedenta"
-#: ../src/yelp-window.c:419
+#: ../src/yelp-window.c:418
msgid "_Next Section"
msgstr "Seccion _seguenta"
-#: ../src/yelp-window.c:424 ../src/yelp-window.c:456
+#: ../src/yelp-window.c:423 ../src/yelp-window.c:455
msgid "_Contents"
msgstr "_Somari"
-#: ../src/yelp-window.c:430
+#: ../src/yelp-window.c:429
msgid "_Add Bookmark"
msgstr "_Apondre un favorit"
-#: ../src/yelp-window.c:435
+#: ../src/yelp-window.c:434
msgid "_Edit Bookmarks..."
msgstr "_Editar los favorits..."
-#: ../src/yelp-window.c:441
+#: ../src/yelp-window.c:440
msgid "_Open Link"
msgstr "_Dubrir lo ligam"
-#: ../src/yelp-window.c:446
+#: ../src/yelp-window.c:445
msgid "Open Link in _New Window"
msgstr "Dobrir lo ligam dins una fenèstra _nòva"
-#: ../src/yelp-window.c:451
+#: ../src/yelp-window.c:450
msgid "_Copy Link Address"
msgstr "_Copiar l'adreça del ligam"
-#: ../src/yelp-window.c:458
+#: ../src/yelp-window.c:457
msgid "Help On this application"
msgstr "Ajuda sus l'aplicacion"
-#: ../src/yelp-window.c:461
+#: ../src/yelp-window.c:460
msgid "_About"
msgstr "_A prepaus"
-#: ../src/yelp-window.c:466
+#: ../src/yelp-window.c:465
msgid "Copy _Email Address"
msgstr "Copiar l'adreça _electronica"
-#: ../src/yelp-window.c:515
+#: ../src/yelp-window.c:514
msgid "Help Browser"
msgstr "Navegador d'ajuda"
-#: ../src/yelp-window.c:926 ../src/yelp-window.c:1082
+#: ../src/yelp-window.c:925 ../src/yelp-window.c:1081
msgid "The Uniform Resource Identifier for the file is invalid."
msgstr "L'URI del fichièr es pas valid."
-#: ../src/yelp-window.c:938 ../src/yelp-window.c:1077
+#: ../src/yelp-window.c:937 ../src/yelp-window.c:1076
#, c-format
msgid ""
"The Uniform Resource Identifier ‘%s’ is invalid or does not point to an "
"actual file."
msgstr ""
-#: ../src/yelp-window.c:1026 ../src/yelp-window.c:1506
+#: ../src/yelp-window.c:1025 ../src/yelp-window.c:1505
msgid "Man pages are not supported in this version."
msgstr "Las paginas de manual son pas geridas dins aquesta version."
-#: ../src/yelp-window.c:1036 ../src/yelp-window.c:1497
+#: ../src/yelp-window.c:1035 ../src/yelp-window.c:1496
msgid "GNU info pages are not supported in this version"
msgstr "Las paginas GNU info son pas geridas dins aquesta version"
-#: ../src/yelp-window.c:1052 ../src/yelp-window.c:1519
+#: ../src/yelp-window.c:1051 ../src/yelp-window.c:1518
msgid "Search is not supported in this version."
msgstr "La foncion de recèrca es pas gerida dins aquesta version."
-#: ../src/yelp-window.c:1057
+#: ../src/yelp-window.c:1056
msgid ""
"SGML documents are no longer supported. Please ask the author of the "
"document to convert to XML."
msgstr ""
-#: ../src/yelp-window.c:1223
+#: ../src/yelp-window.c:1222
msgid "_Search:"
msgstr "_Recèrcar :"
-#: ../src/yelp-window.c:1224
+#: ../src/yelp-window.c:1223
msgid "Search for other documentation"
msgstr "Recercar d'autras documentacions"
-#: ../src/yelp-window.c:1386
+#: ../src/yelp-window.c:1385
msgid "Fin_d:"
msgstr "_Recèrcar :"
-#: ../src/yelp-window.c:1406
+#: ../src/yelp-window.c:1405
msgid "Find _Next"
msgstr "Recèrcar lo seguent"
-#: ../src/yelp-window.c:1418
+#: ../src/yelp-window.c:1417
msgid "Find _Previous"
msgstr "Recèrcar lo _precedent"
-#: ../src/yelp-window.c:1532
+#: ../src/yelp-window.c:1531
#, c-format
msgid ""
"A transformation context could not be created for the file ‘%s’. The format "
"may not be supported."
msgstr ""
-#: ../src/yelp-window.c:1562 ../src/yelp-window.c:1981
-#: ../src/yelp-window.c:2064
+#: ../src/yelp-window.c:1561 ../src/yelp-window.c:1980
+#: ../src/yelp-window.c:2063
#, c-format
msgid ""
"The section ‘%s’ does not exist in this document. If you were directed to "
@@ -1051,29 +1047,30 @@ msgid ""
"maintainers of that application."
msgstr ""
-#: ../src/yelp-window.c:1677 ../src/yelp-window.c:2468
+#: ../src/yelp-window.c:1676 ../src/yelp-window.c:2467
#, c-format
msgid ""
"The file ‘%s’ could not be read. This file might be missing, or you might "
"not have permissions to read it."
msgstr ""
-#: ../src/yelp-window.c:1728
+#: ../src/yelp-window.c:1727
msgid "Loading..."
msgstr "Cargament..."
#. Note to translators: put here your name (and address) so it
#. * will show up in the "about" box
-#: ../src/yelp-window.c:2911
+#: ../src/yelp-window.c:2901
msgid "translator-credits"
msgstr ""
-"La còla occitana de revirada d'Ubuntu, 2007 - ubuntu-l10n-oci@lists.ubuntu.com"
+"La còla occitana de revirada d'Ubuntu, 2007 - ubuntu-l10n-oci@lists.ubuntu."
+"com"
-#: ../src/yelp-window.c:2914
+#: ../src/yelp-window.c:2904
msgid "Yelp"
msgstr "Yelp"
-#: ../src/yelp-window.c:2916
+#: ../src/yelp-window.c:2906
msgid "A documentation browser and viewer for the Gnome Desktop."
msgstr "Un navegador e legidor de documentacion pel burèu GNOME."
@@ -1096,4 +1093,3 @@ msgstr ""
#: ../yelp.desktop.in.in.h:1
msgid "Get help with GNOME"
msgstr ""
-
diff --git a/po/te.po b/po/te.po
index d176165e..16285153 100644
--- a/po/te.po
+++ b/po/te.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: yelp\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-07-16 16:26+0530\n"
+"POT-Creation-Date: 2007-07-16 12:14+0100\n"
"PO-Revision-Date: 2007-07-16 16:28+0530\n"
"Last-Translator: Bharat Kumar <jonnalagaddabharat@gmail.com>\n"
"Language-Team: Swecha Telugu Localisation Team <localisation@swecha.org>\n"
diff --git a/src/Makefile.am b/src/Makefile.am
index f8c48782..741ce799 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,41 +4,31 @@ yelp_SOURCES = \
Yelper.cpp Yelper.h \
yelp-base.c yelp-base.h \
yelp-bookmarks.c yelp-bookmarks.h \
- yelp-db-pager.c yelp-db-pager.h \
- yelp-db-print-pager.c yelp-db-print-pager.h \
yelp-debug.c yelp-debug.h \
yelp-error.c yelp-error.h \
yelp-gecko-utils.cpp yelp-gecko-utils.h \
yelp-html.cpp yelp-html.h \
yelp-io-channel.c yelp-io-channel.h \
- yelp-pager.c yelp-pager.h \
yelp-settings.c yelp-settings.h \
- yelp-toc-pager.c yelp-toc-pager.h \
yelp-utils.c yelp-utils.h \
yelp-window.c yelp-window.h \
- yelp-xslt-pager.c yelp-xslt-pager.h \
yelp-marshal.c yelp-marshal.h \
yelp-main.c \
yelp-print.c yelp-print.h \
- yelp-gecko-services.h yelp-gecko-services.cpp
-
-if ENABLE_MAN
-yelp_SOURCES += \
- yelp-man-parser.c yelp-man-parser.h \
- yelp-man-pager.c yelp-man-pager.h
-endif
-
-if ENABLE_INFO
-yelp_SOURCES += \
- yelp-info-pager.c yelp-info-pager.h \
- yelp-info-parser.c yelp-info-parser.h
-endif
-
-if ENABLE_SEARCH
-yelp_SOURCES += \
- gtkentryaction.c gtkentryaction.h \
- yelp-search-pager.c yelp-search-pager.h
-endif
+ yelp-page.c yelp-page.h \
+ yelp-transform.c yelp-transform.h \
+ yelp-gecko-services.h yelp-gecko-services.cpp \
+ yelp-document.h yelp-document.c \
+ yelp-toc.h yelp-toc.c \
+ yelp-docbook.h yelp-docbook.c \
+ yelp-db-print.c yelp-db-print.h \
+ yelp-man-parser.c yelp-man-parser.h \
+ yelp-man.c yelp-man.h \
+ yelp-info.c yelp-info.h \
+ yelp-info-parser.c yelp-info-parser.h \
+ gtkentryaction.c gtkentryaction.h \
+ yelp-search.c yelp-search.h \
+ yelp-search-parser.c yelp-search-parser.h
YELP_DEFINES = \
-DG_LOG_DOMAIN=\"Yelp\" \
@@ -50,7 +40,8 @@ YELP_DEFINES = \
-DSERVERDIR=\"$(libexecdir)\" \
-DBINDIR=\""$(bindir)"\" \
-DSHAREDIR=\""$(pkgdatadir)"\" \
- -DMOZILLA_HOME=\""$(MOZILLA_HOME)\""
+ -DMOZILLA_HOME=\""$(MOZILLA_HOME)\"" \
+ -DGDU_ICON_PATH=\"$(GDU_ICON_PATH)\"
mozilla_include_subdirs = \
. \
@@ -102,68 +93,67 @@ yelp_LDADD = \
yelp_LDFLAGS = -R$(MOZILLA_HOME) $(AM_LDFLAGS)
-check_PROGRAMS = test-man-parser test-pager test-uri
+check_PROGRAMS = \
+ test-document \
+ test-man-parser \
+ test-page \
+ test-transform \
+ test-resolver
+
+test_document_SOURCES = \
+ yelp-debug.c yelp-debug.h \
+ yelp-docbook.c yelp-docbook.h \
+ yelp-document.c yelp-document.h \
+ yelp-error.c yelp-error.h \
+ yelp-io-channel.c yelp-io-channel.h \
+ yelp-man.c yelp-man.h \
+ yelp-man-parser.c yelp-man-parser.h \
+ yelp-page.c yelp-page.h \
+ yelp-toc.c yelp-toc.h \
+ yelp-transform.c yelp-transform.h \
+ test-document.c
+test_document_CFLAGS = $(YELP_CFLAGS) $(AM_CFLAGS) $(YELP_DEFINES)
+test_document_LDADD = $(YELP_LIBS) $(Z_LIBS) $(BZ_LIBS)
+test_document_LDFLAGS = $(AM_LDFLAGS)
test_man_parser_SOURCES = \
+ yelp-debug.c yelp-debug.h \
yelp-error.c yelp-error.h \
yelp-io-channel.c yelp-io-channel.h \
yelp-man-parser.c yelp-man-parser.h \
- yelp-utils.c yelp-utils.h \
test-man-parser.c
-
-test_man_parser_CPPFLAGS = \
- $(YELP_DEFINES) \
- $(AM_CPPFLAGS)
-
-test_man_parser_CFLAGS = \
- $(YELP_CFLAGS) \
- $(AM_CFLAGS)
-
+test_man_parser_CPPFLAGS = $(YELP_DEFINES) $(AM_CPPFLAGS)
+test_man_parser_CFLAGS = $(YELP_CFLAGS) $(AM_CFLAGS)
test_man_parser_LDADD = $(YELP_LIBS) $(Z_LIBS) $(BZ_LIBS)
-
test_man_parser_LDFLAGS = $(AM_LDFLAGS)
-test_pager_SOURCES = \
- yelp-db-pager.c yelp-db-pager.h \
- yelp-db-print-pager.c yelp-db-print-pager.h \
- yelp-error.c yelp-error.h \
- yelp-io-channel.c yelp-io-channel.h \
- yelp-man-pager.c yelp-man-pager.h \
- yelp-man-parser.c yelp-man-parser.h \
- yelp-pager.c yelp-pager.h \
- yelp-toc-pager.c yelp-toc-pager.h \
- yelp-utils.c yelp-utils.h \
- yelp-xslt-pager.c yelp-xslt-pager.h \
- yelp-marshal.c yelp-marshal.h \
- test-pager.c
-
-test_pager_CPPFLAGS = \
- $(YELP_DEFINES) \
- $(AM_CPPFLAGS)
-
-test_pager_CFLAGS = \
- $(YELP_CFLAGS) \
- $(AM_CFLAGS)
-
-test_pager_LDADD = $(YELP_LIBS) $(POPT_LIBS) $(Z_LIBS) $(BZ_LIBS)
-
-test_pager_LDFLAGS = $(AM_LDFLAGS)
-
-test_uri_SOURCES = \
- yelp-utils.c yelp-utils.h \
- test-uri.c
-
-test_uri_CPPFLAGS = \
- $(YELP_DEFINES) \
- $(AM_CPPFLAGS)
-
-test_uri_CFLAGS = \
- $(YELP_CFLAGS) \
- $(AM_CFLAGS)
-
-test_uri_LDADD = $(YELP_LIBS)
-
-test_uri_LDFLAGS = $(AM_LDFLAGS)
+test_page_SOURCES = \
+ yelp-debug.c yelp-debug.h \
+ yelp-document.c yelp-document.h \
+ yelp-error.c yelp-error.h \
+ yelp-page.c yelp-page.h \
+ test-page.c
+test_page_CFLAGS = $(YELP_CFLAGS) $(AM_CFLAGS) $(YELP_DEFINES)
+test_page_LDADD = $(YELP_LIBS)
+test_page_LDFLAGS = $(AM_LDFLAGS)
+
+test_transform_SOURCES = \
+ yelp-debug.c yelp-debug.h \
+ yelp-error.c yelp-error.h \
+ yelp-transform.c yelp-transform.h \
+ test-transform.c
+test_transform_CFLAGS = $(YELP_CFLAGS) $(AM_CFLAGS) $(YELP_DEFINES)
+test_transform_LDADD = $(YELP_LIBS)
+test_transform_LDFLAGS = $(AM_LDFLAGS)
+
+test_resolver_SOURCES = \
+ yelp-debug.c yelp-debug.h \
+ yelp-error.c yelp-error.h \
+ yelp-utils.c yelp-utils.h \
+ test-resolver.c
+test_resolver_CFLAGS = $(YELP_CFLAGS) $(AM_CFLAGS) $(YELP_DEFINES)
+test_resolver_LDADD = $(YELP_LIBS)
+test_resolver_LDFLAGS = $(AM_LDFLAGS)
@INTLTOOL_SERVER_RULE@
diff --git a/src/test-document.c b/src/test-document.c
new file mode 100644
index 00000000..a7adb427
--- /dev/null
+++ b/src/test-document.c
@@ -0,0 +1,149 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2006 Shaun McCance
+ *
+ * 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., 59 Temple Place - Suite 330, Cambridge, MA 02139, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+
+#include "yelp-error.h"
+#include "yelp-docbook.h"
+#include "yelp-man.h"
+#include "yelp-toc.h"
+
+static gchar *mode = NULL;
+static gchar **files = NULL;
+static const GOptionEntry options[] = {
+ { "mode", 'm',
+ 0, G_OPTION_ARG_STRING,
+ &mode,
+ "One of man, docbook or toc", "MODE" },
+ { G_OPTION_REMAINING,
+ 0, 0, G_OPTION_ARG_FILENAME_ARRAY,
+ &files, NULL, NULL },
+ { NULL }
+};
+
+static void document_func (YelpDocument *document,
+ YelpDocumentSignal signal,
+ gint req_id,
+ gpointer *func_data,
+ gpointer user_data);
+
+GMainLoop *loop;
+
+static void
+document_func (YelpDocument *document,
+ YelpDocumentSignal signal,
+ gint req_id,
+ gpointer *func_data,
+ gpointer user_data)
+{
+ gchar contents[60];
+ gchar *contents_;
+ gsize read;
+ YelpPage *page;
+ YelpError *error;
+ switch (signal) {
+ case YELP_DOCUMENT_SIGNAL_PAGE:
+ page = (YelpPage *) func_data;
+ printf ("PAGE: %s (%i)\n", page->id, req_id);
+ printf (" PREV: %s\n", page->prev_id);
+ printf (" NEXT: %s\n", page->next_id);
+ printf (" UP: %s\n", page->up_id);
+ printf (" ROOT: %s\n", page->root_id);
+ printf (" SECTIONS: %s\n", yelp_document_get_sections (document) ? "yep": "nah");
+ yelp_page_read (page, contents, 60, &read, NULL);
+ /* contents isn't \0-terminated */
+ contents_ = g_strndup (contents, read);
+ printf (" DATA: %s\n", contents_);
+ g_free (contents_);
+ yelp_page_free (page);
+ break;
+ case YELP_DOCUMENT_SIGNAL_TITLE:
+ printf ("TITLE: %s (%i)\n", (gchar *) func_data, req_id);
+ g_free (func_data);
+ break;
+ case YELP_DOCUMENT_SIGNAL_ERROR:
+ error = (YelpError *) func_data;
+ printf ("ERROR: %s\n", yelp_error_get_title (error));
+ printf (" %s\n", yelp_error_get_message (error));
+ yelp_error_free (error);
+ break;
+ }
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ GOptionContext *context;
+ YelpDocument *document;
+ gint i;
+
+ g_thread_init (NULL);
+ gdk_threads_init ();
+ gdk_threads_leave ();
+
+ gtk_init (&argc, &argv);
+
+ context = g_option_context_new ("FILE PAGE_IDS...");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+
+ if (!mode)
+ mode = g_strdup ("docbook");
+
+ if ((files == NULL || files[0] == NULL) && !g_str_equal (mode, "toc")) {
+ g_printerr ("Usage: test-docbook FILE PAGE_IDS...\n");
+ return 1;
+ }
+
+ if (g_str_equal (mode, "man"))
+ document = yelp_man_new (files[0]);
+ else if (g_str_equal (mode, "toc"))
+ document = yelp_toc_new ();
+ else if (g_str_equal (mode, "docbook"))
+ document = yelp_docbook_new (files[0]);
+ else {
+ g_error ("Unknown test. Please try again later\n");
+ return 3;
+ }
+
+ if ((files == NULL || files[1] == NULL) && (!g_str_equal (mode, "toc")))
+ yelp_document_get_page (document, "x-yelp-index", (YelpDocumentFunc) document_func, NULL);
+ else if (!g_str_equal (mode, "toc")) {
+ for (i = 1; files[i]; i++)
+ yelp_document_get_page (document, files[i], (YelpDocumentFunc) document_func, NULL);
+ } else {
+ if (files) {
+ for (i = 0; files[i]; i++)
+ yelp_document_get_page (document, files[i], (YelpDocumentFunc) document_func, NULL);
+ } else {
+ yelp_document_get_page (document, "index", (YelpDocumentFunc) document_func, NULL);
+ }
+ }
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+
+ gdk_threads_leave ();
+
+ return 0;
+}
diff --git a/src/test-man-parser.c b/src/test-man-parser.c
index 3b115430..38b38497 100644
--- a/src/test-man-parser.c
+++ b/src/test-man-parser.c
@@ -19,39 +19,50 @@
* Author: Shaun McCance <shaunm@gnome.org>
*/
-#include <libgnomevfs/gnome-vfs.h>
+#include <glib.h>
+#include <libxml/tree.h>
+
#include "yelp-man-parser.h"
-#include "yelp-utils.h"
+
+static gchar **files = NULL;
+static const GOptionEntry options[] = {
+ { G_OPTION_REMAINING,
+ 0, 0, G_OPTION_ARG_FILENAME_ARRAY,
+ &files, NULL, NULL },
+ { NULL }
+};
gint
main (gint argc, gchar **argv)
{
+ GOptionContext *context;
YelpManParser *parser;
- YelpDocInfo *doc_info;
- xmlDocPtr doc;
+ xmlDocPtr doc;
+ gchar *encoding;
+ gint i;
+
+ context = g_option_context_new ("FILES...");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
- if (argc < 2) {
- g_error ("Usage: test-man-parser file\n");
+ if (files == NULL || files[0] == NULL) {
+ g_printerr ("Usage: test-man-parser [OPTION...] FILES...\n");
return 1;
}
- gnome_vfs_init ();
-
parser = yelp_man_parser_new ();
- doc_info = yelp_doc_info_get (argv[1], FALSE);
- if (!doc_info) {
- printf ("Failed to load URI: %s\n", argv[1]);
- return -1;
- }
- doc = yelp_man_parser_parse_doc (parser, doc_info);
- yelp_man_parser_free (parser);
+ encoding = (gchar *) g_getenv("MAN_ENCODING");
+ if (encoding == NULL)
+ encoding = "ISO-8859-1";
- xmlDocDump (stdout, doc);
- xmlFreeDoc (doc);
+ for (i = 0; files[i]; i++) {
+ doc = yelp_man_parser_parse_file (parser, files[i], encoding);
+ xmlDocDump (stdout, doc);
+ xmlFreeDoc (doc);
+ }
- gnome_vfs_shutdown ();
+ yelp_man_parser_free (parser);
return 0;
}
-
diff --git a/src/test-page.c b/src/test-page.c
new file mode 100644
index 00000000..c7d2c701
--- /dev/null
+++ b/src/test-page.c
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330, Cambridge, MA 02139, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#include <glib.h>
+
+#include "yelp-page.h"
+#include "yelp-error.h"
+
+#define READ_SIZE 1024
+
+static gchar *file = NULL;
+static const GOptionEntry options[] = {
+ { G_OPTION_REMAINING,
+ 0, 0, G_OPTION_ARG_FILENAME,
+ &file, NULL, NULL },
+ { NULL }
+};
+
+gint
+main (gint argc, gchar **argv)
+{
+ GOptionContext *context;
+ YelpPage *page;
+ YelpError *error;
+ gchar buffer[READ_SIZE];
+ gsize read;
+ gint num_reads;
+
+ context = g_option_context_new ("[FILE]");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+
+ if (file == NULL) {
+ gint i;
+ gchar *str, *new;
+ str = g_strdup ("Fe fi fo fum. I smell the blood of an Englishman.\n");
+ for (i = 0; i < 5; i++) {
+ new = g_strconcat (str, str, str, str, str, str, str, NULL);
+ g_free (str);
+ str = new;
+ }
+ page = yelp_page_new_string (NULL, NULL, str);
+ } else {
+ g_error ("File pages not yet supported.\n");
+ return 1;
+ }
+
+ num_reads = 0;
+ while (yelp_page_read (page, buffer, READ_SIZE, &read, &error)
+ == G_IO_STATUS_NORMAL) {
+ gchar *str;
+ num_reads++;
+ /* buffer isn't NULL-terminated */
+ str = g_strndup (buffer, READ_SIZE);
+ printf ("%s", str);
+ g_free (str);
+ }
+
+ printf ("\n%i total reads\n", num_reads);
+ printf ("%i bytes in last read\n", read);
+
+ yelp_page_free (page);
+
+ return 0;
+}
diff --git a/src/test-resolver.c b/src/test-resolver.c
new file mode 100644
index 00000000..b39d11a5
--- /dev/null
+++ b/src/test-resolver.c
@@ -0,0 +1,271 @@
+/* A test util to try out the new
+ * yelp-utils resolver for URIs
+ * Basically, tries to resolve each
+ * given URI and compares to the expected results
+ * (only checks the files exist and the type is correct)
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include "yelp-utils.h"
+
+
+int DefaultTests (void);
+int TestFile (char *uri);
+
+
+int
+TestFile (char *uri)
+{
+ return (g_file_test (uri, G_FILE_TEST_EXISTS));
+}
+
+int
+DefaultTests (void)
+{
+ gchar *result = NULL;
+ gchar *section = NULL;
+ YelpRrnType restype = YELP_TYPE_ERROR;
+
+ /* First, normal docs - these will only work with rrn XDG_DATA_DIRS set correctly */
+ /* Normal doc, no section */
+ restype = yelp_uri_resolve ("ghelp:user-guide", &result, &section);
+ if (restype != YELP_TYPE_DOC || !TestFile (result) ||
+ section != NULL) {
+ return 101;
+ }
+ g_free (result); result=NULL;
+
+ /* Section type 1*/
+ restype = yelp_uri_resolve ("ghelp:user-guide#madeupsection", &result, &section);
+ if (restype != YELP_TYPE_DOC || !TestFile (result) ||
+ !g_str_equal (section, "madeupsection")) {
+ return 102;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* Section type 2 */
+ restype = yelp_uri_resolve ("ghelp:user-guide?madeupsection", &result, &section);
+ if (restype != YELP_TYPE_DOC || !TestFile (result) ||
+ !g_str_equal (section, "madeupsection")) {
+ return 103;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* man pages - only work with correct man pages installed */
+ /* Simple man page */
+ restype = yelp_uri_resolve ("man:yelp", &result, &section);
+ if (restype != YELP_TYPE_MAN || !TestFile (result) ||
+ !g_str_equal (section, "1")) {
+ return 104;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* man page from specific section 1*/
+ restype = yelp_uri_resolve ("man:yelp(1)", &result, &section);
+ if (restype != YELP_TYPE_MAN || !TestFile (result) ||
+ !g_str_equal (section, "1")) {
+ return 105;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* man page from specific section 2*/
+ restype = yelp_uri_resolve ("man:yelp.1", &result, &section);
+ if (restype != YELP_TYPE_MAN || !TestFile (result) ||
+ !g_str_equal (section, "1")) {
+ return 106;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* man page from specific section 3*/
+ restype = yelp_uri_resolve ("man:yelp#1", &result, &section);
+ if (restype != YELP_TYPE_MAN || !TestFile (result) ||
+ !g_str_equal (section, "1")) {
+ return 107;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* Info pages */
+ /* Simple info page */
+ restype = yelp_uri_resolve ("info:cvs", &result, &section);
+ if (restype != YELP_TYPE_INFO || !TestFile (result) ||
+ section != NULL) {
+ return 108;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* info page with section */
+ restype = yelp_uri_resolve ("info:cvs#toolbar", &result, &section);
+ if (restype != YELP_TYPE_INFO || !TestFile (result) ||
+ !g_str_equal (section, "toolbar")) {
+ return 109;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* info page with section 2*/
+ restype = yelp_uri_resolve ("info:cvs?toolbar", &result, &section);
+ if (restype != YELP_TYPE_INFO || !TestFile (result) ||
+ !g_str_equal (section, "toolbar")) {
+ return 110;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+
+ /* info page with section included */
+ restype = yelp_uri_resolve ("info:autopoint", &result, &section);
+ if (restype != YELP_TYPE_INFO || !TestFile (result) ||
+ !g_str_equal (section, "autopoint Invocation")) {
+ return 111;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* Other types: html - no html installed by default. Should be the same
+ * as ghelp
+ */
+ /* External */
+ restype = yelp_uri_resolve ("http://www.gnome.org", &result, &section);
+ if (restype != YELP_TYPE_EXTERNAL) {
+ return 112;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* External, but local */
+ restype = yelp_uri_resolve ("/usr/bin/yelp", &result, &section);
+ if (restype != YELP_TYPE_EXTERNAL) {
+ return 113;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* External, local using file: uri */
+ restype = yelp_uri_resolve ("file:///usr/bin/yelp", &result, &section);
+ if (restype != YELP_TYPE_EXTERNAL) {
+ return 114;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* Local, file, readable */
+ restype = yelp_uri_resolve ("file:///usr/share/gnome/help/user-guide/C/user-guide.xml", &result, &section);
+ if (restype != YELP_TYPE_DOC || !TestFile (result) ||
+ section != NULL) {
+ return 115;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* Local, readable, html */
+ restype = yelp_uri_resolve ("/usr/share/doc/shared-mime-info/shared-mime-info-spec.html/index.html", &result, &section);
+ if (restype != YELP_TYPE_HTML || !TestFile (result) ||
+ section != NULL) {
+ return 116;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* Local, readable, html, with section */
+ restype = yelp_uri_resolve ("/usr/share/doc/shared-mime-info/shared-mime-info-spec.html/index.html#foobar", &result, &section);
+ if (restype != YELP_TYPE_HTML || !TestFile (result) ||
+ !g_str_equal (section, "foobar")) {
+ return 117;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+ /* error */
+ restype = yelp_uri_resolve ("file:///usr/fake_file1", &result, &section);
+ if (restype != YELP_TYPE_ERROR || result != NULL || section != NULL) {
+ return 118;
+ }
+ g_free (result); result=NULL;
+ g_free (section); section = NULL;
+
+
+
+
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i=1;
+
+ /* Used within yelp-utils */
+ gnome_vfs_init ();
+
+ if (argc % 2 != 1) {
+ printf ("Usage: %s [<test-uri> <type> <test-uri> <type> ... ]\n", argv[0]);
+ printf ("type can be one of:\n");
+ printf ("man, info, doc, html, external, fail\n");
+ return 1;
+ }
+
+ if (argc == 1) {
+ int ret;
+ ret = DefaultTests ();
+ return ret;
+ }
+ while (i < argc) {
+ char *uri = argv[i];
+ char *type = argv[i+1];
+ char *result = NULL;
+ char *section = NULL;
+ YelpRrnType restype = YELP_TYPE_ERROR;
+
+
+ printf ("uri: %s type: %s\n", argv[i], argv[i+1]);
+
+ if (g_str_equal (type, "doc")) {
+ restype = yelp_uri_resolve (argv[i], &result, &section);
+ if (restype != YELP_TYPE_DOC || !TestFile (result)) {
+ printf ("Failed doc test %s. Aborting.\n", uri);
+ return 2;
+ }
+ } else if (g_str_equal (type, "info")) {
+ restype = yelp_uri_resolve (argv[i], &result, &section);
+ if (restype != YELP_TYPE_INFO || !TestFile (result)) {
+ printf ("Failed doc test %s. Aborting.\n", uri);
+ return 3;
+ }
+ } else if (g_str_equal (type, "man")) {
+ restype = yelp_uri_resolve (argv[i], &result, &section);
+ if (restype != YELP_TYPE_MAN || !TestFile (result)) {
+ printf ("Failed doc test %s. Aborting.\n", uri);
+ return 4;
+ }
+ } else if (g_str_equal (type, "external")) {
+ restype = yelp_uri_resolve (argv[i], &result, &section);
+ if (restype != YELP_TYPE_EXTERNAL) {
+ printf ("Failed doc test %s. Aborting.\n", uri, restype, YELP_TYPE_EXTERNAL);
+ return 5;
+ }
+ } else if (g_str_equal (type, "error")) {
+ restype = yelp_uri_resolve (argv[i], &result, &section);
+ if (restype != YELP_TYPE_ERROR || result != NULL) {
+ printf ("Failed doc test %s. Aborting.\n", uri);
+ return 6;
+ }
+ } else {
+ printf ("Unknown test: %s. Ignoring.\n", type);
+ }
+ i+=2;
+ g_free (result);
+ result = NULL;
+ }
+ return 0;
+}
+
+
diff --git a/src/test-transform.c b/src/test-transform.c
new file mode 100644
index 00000000..ae659be0
--- /dev/null
+++ b/src/test-transform.c
@@ -0,0 +1,163 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2006 Shaun McCance
+ *
+ * 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., 59 Temple Place - Suite 330, Cambridge, MA 02139, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#include <glib.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+
+#include "yelp-error.h"
+#include "yelp-transform.h"
+
+static gint timeout = -1;
+static gboolean random_timeout = FALSE;
+static gchar **files = NULL;
+static const GOptionEntry options[] = {
+ { "random-timeout", 'r',
+ 0, G_OPTION_ARG_NONE,
+ &random_timeout,
+ "Time out after a random amount of time", NULL },
+ { "timeout", 't',
+ 0, G_OPTION_ARG_INT,
+ &timeout,
+ "Time out after N milliseconds", "N" },
+ { G_OPTION_REMAINING,
+ 0, 0, G_OPTION_ARG_FILENAME_ARRAY,
+ &files, NULL, NULL },
+ { NULL }
+};
+
+GMainLoop *loop;
+
+static void
+transform_release (YelpTransform *transform)
+{
+ printf ("\nRELEASE\n");
+ yelp_transform_release (transform);
+ /* Quit after pending things are done. This helps test
+ * whether YelpTransform takes its release seriously.
+ */
+ g_idle_add ((GSourceFunc) g_main_loop_quit, loop);
+}
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer *func_data,
+ gpointer user_data)
+{
+ gchar *chunk_id;
+ gchar *chunk_data;
+ gchar *chunk_short;
+ YelpError *error;
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ chunk_id = (gchar *) func_data;
+ printf ("\nCHUNK: %s\n", chunk_id);
+
+ chunk_data = yelp_transform_eat_chunk (transform, chunk_id);
+ chunk_short = g_strndup (chunk_data, 300);
+ printf ("%s\n", chunk_short);
+
+ g_free (chunk_short);
+ g_free (chunk_data);
+ g_free (chunk_id);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ error = (YelpError *) func_data;
+ printf ("\nERROR: %s\n", yelp_error_get_title (error));
+ yelp_error_free (error);
+ break;
+ case YELP_TRANSFORM_FINAL:
+ printf ("\nFINAL\n");
+ transform_release (transform);
+ break;
+ }
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ GOptionContext *context;
+ xmlParserCtxtPtr parser;
+ xmlDocPtr doc;
+ YelpTransform *transform;
+ gchar **params;
+ gchar *stylesheet;
+ gchar *file;
+
+ g_thread_init (NULL);
+
+ context = g_option_context_new ("[STYLESHEET] FILE");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+
+ if (files == NULL || files[0] == NULL) {
+ g_printerr ("Usage: test-transform [OPTION...] [STYLESHEET] FILE\n");
+ return 1;
+ }
+
+ if (files[1] == NULL) {
+ stylesheet = DATADIR"/yelp/xslt/db2html.xsl";
+ file = files[0];
+ } else {
+ stylesheet = files[0];
+ file = files[1];
+ }
+
+ params = g_new0 (gchar *, 7);
+ params[0] = "db.chunk.extension";
+ params[1] = "\"\"";
+ params[2] = "db.chunk.info_basename";
+ params[3] = "\"x-yelp-titlepage\"";
+ params[4] = "db.chunk.max_depth";
+ params[5] = "2";
+ params[6] = NULL;
+
+ transform = yelp_transform_new (stylesheet,
+ (YelpTransformFunc) transform_func,
+ NULL);
+ parser = xmlNewParserCtxt ();
+ doc = xmlCtxtReadFile (parser,
+ file,
+ NULL,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+ xmlFreeParserCtxt (parser);
+ xmlXIncludeProcessFlags (doc,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+ yelp_transform_start (transform, doc, params);
+
+ if (random_timeout) {
+ GRand *rand = g_rand_new ();
+ timeout = g_rand_int_range (rand, 80, 280);
+ g_rand_free (rand);
+ }
+
+ if (timeout >= 0)
+ g_timeout_add (timeout, (GSourceFunc) transform_release, transform);
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+
+ return 0;
+}
diff --git a/src/yelp-base.c b/src/yelp-base.c
index 6761e969..98c23e6d 100644
--- a/src/yelp-base.c
+++ b/src/yelp-base.c
@@ -32,8 +32,7 @@
#include "yelp-window.h"
#include "yelp-settings.h"
-#include "yelp-pager.h"
-#include "yelp-toc-pager.h"
+#include "yelp-toc.h"
#include "yelp-base.h"
#include "yelp-bookmarks.h"
#include "server-bindings.h"
@@ -98,9 +97,12 @@ yelp_base_init (YelpBase *base)
priv->toc_tree = g_node_new (NULL);
priv->index = NULL;
priv->windows = NULL;
-
yelp_bookmarks_init ();
yelp_settings_init ();
+ /* Init here to start processing before
+ * we even start the window */
+ yelp_toc_new();
+
}
static void
@@ -129,8 +131,7 @@ server_get_url_list (YelpBase *server, gchar **urls, GError **error)
{
gint len, i;
GSList *node;
- YelpDocInfo *doc_info;
- gchar *uri;
+ const gchar *uri;
YelpBasePriv *priv;
priv = server->priv;
@@ -139,23 +140,18 @@ server_get_url_list (YelpBase *server, gchar **urls, GError **error)
node = priv->windows;
- doc_info = yelp_window_get_doc_info (YELP_WINDOW (node->data));
- uri = yelp_doc_info_get_uri (doc_info, NULL,
- YELP_URI_TYPE_ANY);
+ uri = yelp_window_get_uri ((YelpWindow *) node->data);
*urls = g_strdup (uri);
- g_free (uri);
node = node->next;
for (i = 0; node; node = node->next, i++) {
gchar *list;
- doc_info = yelp_window_get_doc_info (YELP_WINDOW (node->data));
- uri = yelp_doc_info_get_uri (doc_info, NULL,
- YELP_URI_TYPE_ANY);
- list = g_strconcat (*urls, ";", uri, NULL);
+ uri = yelp_window_get_uri ((YelpWindow *) node->data);
+
+ list = g_strconcat (uri, ";", *urls, NULL);
g_free (*urls);
*urls = g_strdup (list);
g_free (list);
- g_free (uri);
}
return TRUE;
}
@@ -200,7 +196,7 @@ yelp_base_new (gboolean priv)
if (!priv)
yelp_base_register_dbus (base);
base->priv->private_session = priv;
- yelp_toc_pager_init ();
+ //yelp_toc_pager_init ();
return base;
}
diff --git a/src/yelp-db-pager.c b/src/yelp-db-pager.c
index 928c8d20..800ff5f0 100644
--- a/src/yelp-db-pager.c
+++ b/src/yelp-db-pager.c
@@ -235,7 +235,7 @@ db_pager_parse (YelpPager *pager)
XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
XML_PARSE_NOENT | XML_PARSE_NONET );
if (doc == NULL) {
- g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_DOC,
+ g_set_error (&error, YELP_GERROR, YELP_ERROR_NO_DOC,
_("The file ‘%s’ could not be parsed. Either the file "
"does not exist, or it is not well-formed XML."),
filename);
@@ -295,8 +295,8 @@ db_pager_params (YelpPager *pager)
debug_print (DB_FUNCTION, "entering\n");
- g_return_val_if_fail (pager != NULL, NULL);
- g_return_val_if_fail (YELP_IS_DB_PAGER (pager), NULL);
+ g_return_val_if_fail (pager != NULL, FALSE);
+ g_return_val_if_fail (YELP_IS_DB_PAGER (pager), FALSE);
priv = YELP_DB_PAGER (pager)->priv;
if (yelp_pager_get_state (pager) >= YELP_PAGER_STATE_ERROR)
@@ -496,12 +496,10 @@ node_get_title (DBWalker *walker, gchar *type)
{
gchar *title = NULL;
xmlChar *node_name = (xmlChar *) walker->cur->name;
+ xmlNodePtr child = NULL;
xmlNodePtr title_node = NULL;
if (xmlStrcmp (node_name, BAD_CAST "refentry")) {
-
- xmlNodePtr child = NULL;
-
/*refentry is special cased below */
title_node = node_find_child (walker->cur, type);
if (!title_node) {
diff --git a/src/yelp-db-print-pager.c b/src/yelp-db-print-pager.c
index 734d7deb..8e184004 100644
--- a/src/yelp-db-print-pager.c
+++ b/src/yelp-db-print-pager.c
@@ -228,8 +228,8 @@ db_print_pager_params (YelpPager *pager)
doc_info = yelp_pager_get_doc_info (pager);
- g_return_val_if_fail (pager != NULL, NULL);
- g_return_val_if_fail (YELP_IS_DB_PRINT_PAGER (pager), NULL);
+ g_return_val_if_fail (pager != NULL, FALSE);
+ g_return_val_if_fail (YELP_IS_DB_PRINT_PAGER (pager), FALSE);
priv = YELP_DB_PRINT_PAGER (pager)->priv;
if (yelp_pager_get_state (pager) >= YELP_PAGER_STATE_ERROR)
diff --git a/src/yelp-db-print.c b/src/yelp-db-print.c
new file mode 100644
index 00000000..61d7d1c6
--- /dev/null
+++ b/src/yelp-db-print.c
@@ -0,0 +1,767 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ * Author: Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xinclude.h>
+
+#include "yelp-error.h"
+#include "yelp-db-print.h"
+#include "yelp-settings.h"
+#include "yelp-transform.h"
+#include "yelp-debug.h"
+
+#define STYLESHEET DATADIR"/yelp/xslt/db2html.xsl"
+
+#define YELP_DBPRINT_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_DBPRINT, YelpDbprintPriv))
+
+typedef enum {
+ DBPRINT_STATE_BLANK, /* Brand new, run transform as needed */
+ DBPRINT_STATE_PARSING, /* Parsing/transforming document, please wait */
+ DBPRINT_STATE_PARSED, /* All done, if we ain't got it, it ain't here */
+ DBPRINT_STATE_STOP /* Stop everything now, object to be disposed */
+} DbprintState;
+
+struct _YelpDbprintPriv {
+ gchar *filename;
+ DbprintState state;
+
+ GMutex *mutex;
+ GThread *thread;
+
+ gboolean process_running;
+ gboolean transform_running;
+
+ YelpTransform *transform;
+
+ xmlDocPtr xmldoc;
+ xmlNodePtr xmlcur;
+ gint max_depth;
+ gint cur_depth;
+ gchar *cur_page_id;
+ gchar *cur_prev_id;
+};
+
+
+static void dbprint_class_init (YelpDbprintClass *klass);
+static void dbprint_init (YelpDbprint *dbprint);
+static void dbprint_try_dispose (GObject *object);
+static void dbprint_dispose (GObject *object);
+
+/* YelpDocument */
+static void dbprint_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+
+/* YelpTransform */
+static void transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpDbprint *dbprint);
+static void transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpDbprint *dbprint);
+static void transform_final_func (YelpTransform *transform,
+ YelpDbprint *dbprint);
+
+/* Threaded */
+static void dbprint_process (YelpDbprint *dbprint);
+
+#if 0
+/* Walker */
+static void dbprint_walk (YelpDbprint *dbprint);
+static gboolean dbprint_walk_chunkQ (YelpDbprint *dbprint);
+static gboolean dbprint_walk_divisionQ (YelpDbprint *dbprint);
+static gchar * dbprint_walk_get_title (YelpDbprint *dbprint);
+#endif
+
+static YelpDocumentClass *parent_class;
+
+GType
+yelp_dbprint_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpDbprintClass),
+ NULL, NULL,
+ (GClassInitFunc) dbprint_class_init,
+ NULL, NULL,
+ sizeof (YelpDbprint),
+ 0,
+ (GInstanceInitFunc) dbprint_init,
+ };
+ type = g_type_register_static (YELP_TYPE_DOCUMENT,
+ "YelpDbprint",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+dbprint_class_init (YelpDbprintClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = dbprint_try_dispose;
+
+ document_class->request = dbprint_request;
+ document_class->cancel = NULL;
+
+ g_type_class_add_private (klass, sizeof (YelpDbprintPriv));
+}
+
+static void
+dbprint_init (YelpDbprint *dbprint)
+{
+ YelpDbprintPriv *priv;
+ priv = dbprint->priv = YELP_DBPRINT_GET_PRIVATE (dbprint);
+
+
+ priv->state = DBPRINT_STATE_BLANK;
+
+ priv->mutex = g_mutex_new ();
+}
+
+static void
+dbprint_try_dispose (GObject *object)
+{
+ YelpDbprintPriv *priv;
+
+ g_assert (object != NULL && YELP_IS_DBPRINT (object));
+
+ priv = YELP_DBPRINT (object)->priv;
+
+ g_mutex_lock (priv->mutex);
+ if (priv->process_running || priv->transform_running) {
+ priv->state = DBPRINT_STATE_STOP;
+ g_idle_add ((GSourceFunc) dbprint_try_dispose, object);
+ g_mutex_unlock (priv->mutex);
+ } else {
+ g_mutex_unlock (priv->mutex);
+ dbprint_dispose (object);
+ }
+}
+
+static void
+dbprint_dispose (GObject *object)
+{
+ YelpDbprint *dbprint = YELP_DBPRINT (object);
+
+ g_free (dbprint->priv->filename);
+
+ if (dbprint->priv->xmldoc)
+ xmlFreeDoc (dbprint->priv->xmldoc);
+
+ g_free (dbprint->priv->cur_page_id);
+ g_free (dbprint->priv->cur_prev_id);
+
+ g_mutex_free (dbprint->priv->mutex);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_dbprint_new (gchar *filename)
+{
+ YelpDbprint *dbprint;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " filename = \"%s\"\n", filename);
+
+ dbprint = (YelpDbprint *) g_object_new (YELP_TYPE_DBPRINT, NULL);
+ dbprint->priv->filename = g_strdup (filename);
+
+ yelp_document_add_page_id (YELP_DOCUMENT (dbprint), "x-yelp-titlepage", "x-yelp-titlepage");
+
+ return (YelpDocument *) dbprint;
+}
+
+
+/******************************************************************************/
+/** YelpDocument **************************************************************/
+
+static void
+dbprint_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpDbprint *dbprint;
+ YelpDbprintPriv *priv;
+ YelpError *error;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " req_id = %i\n", req_id);
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+ g_assert (document != NULL && YELP_IS_DBPRINT (document));
+
+ if (handled) {
+ return;
+ }
+
+ dbprint = YELP_DBPRINT (document);
+ priv = dbprint->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ switch (priv->state) {
+ case DBPRINT_STATE_BLANK:
+ priv->state = DBPRINT_STATE_PARSING;
+ priv->process_running = TRUE;
+ priv->thread = g_thread_create ((GThreadFunc) dbprint_process,
+ dbprint, FALSE, NULL);
+ break;
+ case DBPRINT_STATE_PARSING:
+ break;
+ case DBPRINT_STATE_PARSED:
+ case DBPRINT_STATE_STOP:
+ error = yelp_error_new (_("Page not found"),
+ _("The page %s was not found in the document %s."),
+ page_id, priv->filename);
+ yelp_document_error_request (document, req_id, error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpDbprint *dbprint)
+{
+ YelpDbprintPriv *priv;
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (dbprint != NULL && YELP_IS_DBPRINT (dbprint));
+
+ priv = dbprint->priv;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == DBPRINT_STATE_STOP) {
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ g_free (func_data);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_error_free ((YelpError *) func_data);
+ break;
+ case YELP_TRANSFORM_FINAL:
+ break;
+ }
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ return;
+ }
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ transform_page_func (transform, (gchar *) func_data, dbprint);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_document_error_pending (YELP_DOCUMENT (dbprint), (YelpError *) func_data);
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ break;
+ case YELP_TRANSFORM_FINAL:
+ transform_final_func (transform, dbprint);
+ break;
+ }
+}
+
+static void
+transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpDbprint *dbprint)
+{
+ YelpDbprintPriv *priv;
+ gchar *content;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = dbprint->priv;
+ g_mutex_lock (priv->mutex);
+
+ content = yelp_transform_eat_chunk (transform, page_id);
+ yelp_document_add_page (YELP_DOCUMENT (dbprint), page_id, content);
+
+ g_free (page_id);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+static void
+transform_final_func (YelpTransform *transform, YelpDbprint *dbprint)
+{
+ YelpError *error;
+ YelpDbprintPriv *priv = dbprint->priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_mutex_lock (priv->mutex);
+
+ error = yelp_error_new (_("Page not found"),
+ _("The requested page was not found in the document %s."),
+ priv->filename);
+ yelp_document_error_pending (YELP_DOCUMENT (dbprint), error);
+
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+
+ if (priv->xmldoc)
+ xmlFreeDoc (priv->xmldoc);
+ priv->xmldoc = NULL;
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** Threaded ******************************************************************/
+
+static void
+dbprint_process (YelpDbprint *dbprint)
+{
+ YelpDbprintPriv *priv;
+ xmlDocPtr xmldoc = NULL;
+ xmlChar *id = NULL;
+ YelpError *error = NULL;
+ xmlParserCtxtPtr parserCtxt = NULL;
+ YelpDocument *document;
+ gchar **params;
+ gint params_i = 0;
+ gint params_max = 20;
+
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (dbprint != NULL && YELP_IS_DBPRINT (dbprint));
+ g_object_ref (dbprint);
+ priv = dbprint->priv;
+ document = YELP_DOCUMENT (dbprint);
+
+ if (!g_file_test (priv->filename, G_FILE_TEST_IS_REGULAR)) {
+ error = yelp_error_new (_("File not found"),
+ _("The file ‘%s’ does not exist."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ parserCtxt = xmlNewParserCtxt ();
+ xmldoc = xmlCtxtReadFile (parserCtxt,
+ (const char *) priv->filename, NULL,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+
+ if (xmldoc == NULL) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because it is"
+ " not a well-formed XML document."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ if (xmlXIncludeProcessFlags (xmldoc,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET )
+ < 0) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because"
+ " one or more of its included files is not"
+ " a well-formed XML document."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ g_mutex_lock (priv->mutex);
+ if (!xmlStrcmp (xmlDocGetRootElement (xmldoc)->name, BAD_CAST "book"))
+ priv->max_depth = 2;
+ else
+ priv->max_depth = 1;
+
+ priv->xmldoc = xmldoc;
+ priv->xmlcur = xmlDocGetRootElement (xmldoc);
+
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+ if (id) {
+ yelp_document_set_root_id (document, (gchar *) id);
+ yelp_document_add_page_id (document, "x-yelp-index", (gchar *) id);
+ yelp_document_add_prev_id (document, (gchar *) id, "x-yelp-titlepage");
+ yelp_document_add_next_id (document, "x-yelp-titlepage", (gchar *) id);
+ }
+ else {
+ yelp_document_set_root_id (document, "x-yelp-index");
+ yelp_document_add_page_id (document, "x-yelp-index", "x-yelp-index");
+ yelp_document_add_prev_id (document, "x-yelp-index", "x-yelp-titlepage");
+ yelp_document_add_next_id (document, "x-yelp-titlepage", "x-yelp-index");
+ /* add the id attribute to the root element with value "index"
+ * so when we try to load the document later, it doesn't fail */
+ xmlNewProp (priv->xmlcur, BAD_CAST "id", BAD_CAST "x-yelp-index");
+ }
+ g_mutex_unlock (priv->mutex);
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == DBPRINT_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+ g_mutex_unlock (priv->mutex);
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == DBPRINT_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+ priv->transform = yelp_transform_new (STYLESHEET,
+ (YelpTransformFunc) transform_func,
+ dbprint);
+ priv->transform_running = TRUE;
+ /* FIXME: we probably need to set our own params */
+
+ params = g_new0 (gchar *, params_max);
+
+ yelp_settings_params (&params, &params_i, &params_max);
+
+ if ((params_i + 10) >= params_max - 1) {
+ params_max += 20;
+ params = g_renew (gchar *, params, params_max);
+ }
+ params[params_i++] = "db.chunk.extension";
+ params[params_i++] = g_strdup ("\"\"");
+ params[params_i++] = "db.chunk.info_basename";
+ params[params_i++] = g_strdup ("\"index\"");
+ params[params_i++] = "db.chunk.max_depth";
+ params[params_i++] = g_strdup ("0");
+ params[params_i++] = "db2html.navbar.top";
+ params[params_i++] = g_strdup ("0");
+ params[params_i++] = "db2html.navbar.bottom";
+ params[params_i++] = g_strdup ("0");
+ params[params_i++] = "db2html.sidenav";
+ params[params_i++] = g_strdup ("0");
+
+ params[params_i] = NULL;
+
+ yelp_transform_start (priv->transform,
+ priv->xmldoc,
+ params);
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ if (id)
+ xmlFree (id);
+ if (parserCtxt)
+ xmlFreeParserCtxt (parserCtxt);
+
+ priv->process_running = FALSE;
+ g_object_unref (dbprint);
+}
+
+#if 0
+/******************************************************************************/
+/** Walker ********************************************************************/
+
+static void
+dbprint_walk (YelpDbprint *dbprint)
+{
+ static gint autoid = 0;
+ gchar autoidstr[20];
+ xmlChar *id = NULL;
+ xmlChar *title = NULL;
+ gchar *old_page_id = NULL;
+ xmlNodePtr cur, old_cur;
+ GtkTreeIter iter;
+ GtkTreeIter *old_iter = NULL;
+ YelpDbprintPriv *priv = dbprint->priv;
+ YelpDocument *document = YELP_DOCUMENT (dbprint);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_DEBUG, " priv->xmlcur->name: %s\n", priv->xmlcur->name);
+
+ /* check for the yelp:chunk-depth or db.chunk.max_depth processing
+ * instruction and set the max chunk depth accordingly.
+ */
+ if (priv->cur_depth == 0)
+ for (cur = priv->xmlcur; cur; cur = cur->prev)
+ if (cur->type == XML_PI_NODE)
+ if (!xmlStrcmp (cur->name, (const xmlChar *) "yelp:chunk-depth") ||
+ !xmlStrcmp (cur->name, (const xmlChar *) "db.chunk.max_depth")) {
+ gint max = atoi ((gchar *) cur->content);
+ if (max)
+ priv->max_depth = max;
+ break;
+ }
+
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+
+ if (dbprint_walk_chunkQ (dbprint)) {
+ title = BAD_CAST dbprint_walk_get_title (dbprint);
+
+ /* if id attribute is not present, autogenerate a
+ * unique value, and insert it into the in-memory tree */
+ if (!id) {
+ g_snprintf (autoidstr, 20, "_auto-gen-id-%d", ++autoid);
+ xmlNewProp (priv->xmlcur, BAD_CAST "id", BAD_CAST autoidstr);
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+ }
+
+ debug_print (DB_DEBUG, " id: \"%s\"\n", id);
+ debug_print (DB_DEBUG, " title: \"%s\"\n", title);
+
+ yelp_document_add_title (document, (gchar *) id, (gchar *) title);
+
+
+ if (priv->cur_prev_id) {
+ yelp_document_add_prev_id (document, (gchar *) id, priv->cur_prev_id);
+ yelp_document_add_next_id (document, priv->cur_prev_id, (gchar *) id);
+ g_free (priv->cur_prev_id);
+ }
+ priv->cur_prev_id = g_strdup ((gchar *) id);
+
+ if (priv->cur_page_id)
+ yelp_document_add_up_id (document, (gchar *) id, priv->cur_page_id);
+ old_page_id = priv->cur_page_id;
+ priv->cur_page_id = g_strdup ((gchar *) id);
+
+ }
+
+ old_cur = priv->xmlcur;
+ priv->cur_depth++;
+
+ if (id)
+ yelp_document_add_page_id (document, (gchar *) id, priv->cur_page_id);
+
+ for (cur = priv->xmlcur->children; cur; cur = cur->next) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ priv->xmlcur = cur;
+ dbprint_walk (dbprint);
+ }
+ }
+ priv->cur_depth--;
+ priv->xmlcur = old_cur;
+
+ if (dbprint_walk_chunkQ (dbprint)) {
+ priv->sections_iter = old_iter;
+ g_free (priv->cur_page_id);
+ priv->cur_page_id = old_page_id;
+ }
+
+ if (priv->cur_depth == 0) {
+ g_free (priv->cur_prev_id);
+ priv->cur_prev_id = NULL;
+
+ g_free (priv->cur_page_id);
+ priv->cur_page_id = NULL;
+ }
+
+ if (id != NULL)
+ xmlFree (id);
+ if (title != NULL)
+ xmlFree (title);
+}
+
+static gboolean
+dbprint_walk_chunkQ (YelpDbprint *dbprint)
+{
+ if (dbprint->priv->cur_depth <= dbprint->priv->max_depth
+ && dbprint_walk_divisionQ (dbprint))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static gboolean
+dbprint_walk_divisionQ (YelpDbprint *dbprint)
+{
+ xmlNodePtr node = dbprint->priv->xmlcur;
+ return (!xmlStrcmp (node->name, (const xmlChar *) "appendix") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "article") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "book") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "bibliography") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "chapter") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "colophon") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "glossary") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "index") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "part") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "preface") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "reference") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refentry") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect1") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect2") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect3") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsection") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect1") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect2") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect3") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect4") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect5") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "section") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "set") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "setindex") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "simplesect") );
+}
+
+static gchar *
+dbprint_walk_get_title (YelpDbprint *dbprint)
+{
+ gchar *infoname = NULL;
+ xmlNodePtr child = NULL;
+ xmlNodePtr title = NULL;
+ xmlNodePtr title_tmp = NULL;
+ YelpDbprintPriv *priv = dbprint->priv;
+
+ if (!xmlStrcmp (priv->xmlcur->name, BAD_CAST "refentry")) {
+ /* The title for a refentry element can come from the following:
+ * refmeta/refentrytitle
+ * refentryinfo/title[abbrev]
+ * refnamediv/refname
+ * We take the first one we find.
+ */
+ for (child = priv->xmlcur->children; child; child = child->next) {
+ if (!xmlStrcmp (child->name, BAD_CAST "refmeta")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "refentrytitle"))
+ break;
+ }
+ if (title)
+ goto done;
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "refentryinfo")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "titleabbrev"))
+ break;
+ else if (!xmlStrcmp (title->name, BAD_CAST "title"))
+ title_tmp = title;
+ }
+ if (title)
+ goto done;
+ else if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "refnamediv")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "refname"))
+ break;
+ else if (!xmlStrcmp (title->name, BAD_CAST "refpurpose")) {
+ title = NULL;
+ break;
+ }
+ }
+ if (title)
+ goto done;
+ }
+ else if (!xmlStrncmp (child->name, BAD_CAST "refsect", 7))
+ break;
+ }
+ }
+ else {
+ /* The title for other elements appears in the following:
+ * title[abbrev]
+ * *info/title[abbrev]
+ * blockinfo/title[abbrev]
+ * objectinfo/title[abbrev]
+ * We take them in that order.
+ */
+ xmlNodePtr infos[3] = {NULL, NULL, NULL};
+ int i;
+
+ infoname = g_strdup_printf ("%sinfo", priv->xmlcur->name);
+
+ for (child = priv->xmlcur->children; child; child = child->next) {
+ if (!xmlStrcmp (child->name, BAD_CAST "titleabbrev")) {
+ title = child;
+ goto done;
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "title"))
+ title_tmp = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST infoname))
+ infos[0] = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST "blockinfo"))
+ infos[1] = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST "objectinfo"))
+ infos[2] = child;
+ }
+
+ if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+
+ for (i = 0; i < 3; i++) {
+ child = infos[i];
+ if (child) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "titleabbrev"))
+ goto done;
+ else if (!xmlStrcmp (title->name, BAD_CAST "title"))
+ title_tmp = title;
+ }
+ if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+ }
+ }
+ }
+
+ done:
+ g_free (infoname);
+
+ if (title)
+ return (gchar *) xmlNodeGetContent (title);
+ else
+ return g_strdup (_("Unknown"));
+}
+#endif
diff --git a/src/yelp-db-print.h b/src/yelp-db-print.h
new file mode 100644
index 00000000..c0ded190
--- /dev/null
+++ b/src/yelp-db-print.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ * Author: Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifndef __YELP_DB_PRINT_H__
+#define __YELP_DB_PRINT_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_DBPRINT (yelp_dbprint_get_type ())
+#define YELP_DBPRINT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_DBPRINT, YelpDbprint))
+#define YELP_DBPRINT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_DBPRINT, YelpDbprintClass))
+#define YELP_IS_DBPRINT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_DBPRINT))
+#define YELP_IS_DBPRINT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_DBPRINT))
+#define YELP_DBPRINT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_DBPRINT, YelpDbprintClass))
+
+typedef struct _YelpDbprint YelpDbprint;
+typedef struct _YelpDbprintClass YelpDbprintClass;
+typedef struct _YelpDbprintPriv YelpDbprintPriv;
+
+struct _YelpDbprint {
+ YelpDocument parent;
+ YelpDbprintPriv *priv;
+};
+
+struct _YelpDbprintClass {
+ YelpDocumentClass parent_class;
+};
+
+GType yelp_dbprint_get_type (void);
+YelpDocument * yelp_dbprint_new (gchar *uri);
+
+#endif /* __YELP_DB_PRINT_H__ */
diff --git a/src/yelp-debug.c b/src/yelp-debug.c
index ae47c52b..34aa56df 100644
--- a/src/yelp-debug.c
+++ b/src/yelp-debug.c
@@ -27,7 +27,7 @@
#include "yelp-debug.h"
-static const GDebugKey debug_keys[] = {
+GDebugKey debug_keys[] = {
{ "function-calls", DB_FUNCTION },
{ "function-args", DB_ARG },
{ "enable-profiling", DB_PROFILE },
diff --git a/src/yelp-debug.h b/src/yelp-debug.h
index 657859f9..846ad750 100644
--- a/src/yelp-debug.h
+++ b/src/yelp-debug.h
@@ -23,7 +23,10 @@
G_BEGIN_DECLS
+#ifdef HAVE_CONFIG_H
#include <config.h>
+#endif
+
#include <glib.h>
typedef enum {
diff --git a/src/yelp-docbook.c b/src/yelp-docbook.c
new file mode 100644
index 00000000..1f34b174
--- /dev/null
+++ b/src/yelp-docbook.c
@@ -0,0 +1,785 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xinclude.h>
+
+#include "yelp-error.h"
+#include "yelp-docbook.h"
+#include "yelp-settings.h"
+#include "yelp-transform.h"
+#include "yelp-debug.h"
+
+#define STYLESHEET DATADIR"/yelp/xslt/db2html.xsl"
+
+#define YELP_DOCBOOK_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_DOCBOOK, YelpDocbookPriv))
+
+typedef enum {
+ DOCBOOK_STATE_BLANK, /* Brand new, run transform as needed */
+ DOCBOOK_STATE_PARSING, /* Parsing/transforming document, please wait */
+ DOCBOOK_STATE_PARSED, /* All done, if we ain't got it, it ain't here */
+ DOCBOOK_STATE_STOP /* Stop everything now, object to be disposed */
+} DocbookState;
+
+struct _YelpDocbookPriv {
+ gchar *filename;
+ DocbookState state;
+
+ GMutex *mutex;
+ GThread *thread;
+
+ gboolean process_running;
+ gboolean transform_running;
+
+ YelpTransform *transform;
+
+ GtkTreeModel *sections;
+ GtkTreeIter *sections_iter; /* On the stack, do not free */
+
+ xmlDocPtr xmldoc;
+ xmlNodePtr xmlcur;
+ gint max_depth;
+ gint cur_depth;
+ gchar *cur_page_id;
+ gchar *cur_prev_id;
+};
+
+
+static void docbook_class_init (YelpDocbookClass *klass);
+static void docbook_init (YelpDocbook *docbook);
+static void docbook_try_dispose (GObject *object);
+static void docbook_dispose (GObject *object);
+
+/* YelpDocument */
+static void docbook_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+static gpointer docbook_get_sections (YelpDocument *document);
+
+/* YelpTransform */
+static void transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpDocbook *docbook);
+static void transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpDocbook *docbook);
+static void transform_final_func (YelpTransform *transform,
+ YelpDocbook *docbook);
+
+/* Threaded */
+static void docbook_process (YelpDocbook *docbook);
+
+/* Walker */
+static void docbook_walk (YelpDocbook *docbook);
+static gboolean docbook_walk_chunkQ (YelpDocbook *docbook);
+static gboolean docbook_walk_divisionQ (YelpDocbook *docbook);
+static gchar * docbook_walk_get_title (YelpDocbook *docbook);
+
+
+static YelpDocumentClass *parent_class;
+
+GType
+yelp_docbook_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpDocbookClass),
+ NULL, NULL,
+ (GClassInitFunc) docbook_class_init,
+ NULL, NULL,
+ sizeof (YelpDocbook),
+ 0,
+ (GInstanceInitFunc) docbook_init,
+ };
+ type = g_type_register_static (YELP_TYPE_DOCUMENT,
+ "YelpDocbook",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+docbook_class_init (YelpDocbookClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = docbook_try_dispose;
+
+ document_class->request = docbook_request;
+ document_class->cancel = NULL;
+ /*document_class->get_sections = docbook_get_sections;*/
+
+ g_type_class_add_private (klass, sizeof (YelpDocbookPriv));
+}
+
+static void
+docbook_init (YelpDocbook *docbook)
+{
+ YelpDocbookPriv *priv;
+ priv = docbook->priv = YELP_DOCBOOK_GET_PRIVATE (docbook);
+
+ priv->sections = NULL;
+
+ priv->state = DOCBOOK_STATE_BLANK;
+
+ priv->mutex = g_mutex_new ();
+}
+
+static void
+docbook_try_dispose (GObject *object)
+{
+ YelpDocbookPriv *priv;
+
+ g_assert (object != NULL && YELP_IS_DOCBOOK (object));
+
+ priv = YELP_DOCBOOK (object)->priv;
+
+ g_mutex_lock (priv->mutex);
+ if (priv->process_running || priv->transform_running) {
+ priv->state = DOCBOOK_STATE_STOP;
+ g_idle_add ((GSourceFunc) docbook_try_dispose, object);
+ g_mutex_unlock (priv->mutex);
+ } else {
+ g_mutex_unlock (priv->mutex);
+ docbook_dispose (object);
+ }
+}
+
+static void
+docbook_dispose (GObject *object)
+{
+ YelpDocbook *docbook = YELP_DOCBOOK (object);
+
+ g_free (docbook->priv->filename);
+
+ g_object_unref (docbook->priv->sections);
+
+ if (docbook->priv->xmldoc)
+ xmlFreeDoc (docbook->priv->xmldoc);
+
+ g_free (docbook->priv->cur_page_id);
+ g_free (docbook->priv->cur_prev_id);
+
+ g_mutex_free (docbook->priv->mutex);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_docbook_new (gchar *filename)
+{
+ YelpDocbook *docbook;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " filename = \"%s\"\n", filename);
+
+ docbook = (YelpDocbook *) g_object_new (YELP_TYPE_DOCBOOK, NULL);
+ docbook->priv->filename = g_strdup (filename);
+
+ yelp_document_add_page_id (YELP_DOCUMENT (docbook), "x-yelp-titlepage", "x-yelp-titlepage");
+
+ docbook->priv->sections =
+ GTK_TREE_MODEL (gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING));
+
+ return (YelpDocument *) docbook;
+}
+
+
+/******************************************************************************/
+/** YelpDocument **************************************************************/
+
+static gpointer
+docbook_get_sections (YelpDocument *document)
+{
+ YelpDocbook *db = (YelpDocbook *) document;
+
+ return (gpointer) (db->priv->sections);
+}
+
+static void
+docbook_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpDocbook *docbook;
+ YelpDocbookPriv *priv;
+ YelpError *error;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " req_id = %i\n", req_id);
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+ g_assert (document != NULL && YELP_IS_DOCBOOK (document));
+
+ if (handled) {
+ return;
+ }
+
+ docbook = YELP_DOCBOOK (document);
+ priv = docbook->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ switch (priv->state) {
+ case DOCBOOK_STATE_BLANK:
+ priv->state = DOCBOOK_STATE_PARSING;
+ priv->process_running = TRUE;
+ priv->thread = g_thread_create ((GThreadFunc) docbook_process,
+ docbook, FALSE, NULL);
+ break;
+ case DOCBOOK_STATE_PARSING:
+ break;
+ case DOCBOOK_STATE_PARSED:
+ case DOCBOOK_STATE_STOP:
+ error = yelp_error_new (_("Page not found"),
+ _("The page %s was not found in the document %s."),
+ page_id, priv->filename);
+ yelp_document_error_request (document, req_id, error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpDocbook *docbook)
+{
+ YelpDocbookPriv *priv;
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (docbook != NULL && YELP_IS_DOCBOOK (docbook));
+
+ priv = docbook->priv;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == DOCBOOK_STATE_STOP) {
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ g_free (func_data);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_error_free ((YelpError *) func_data);
+ break;
+ case YELP_TRANSFORM_FINAL:
+ break;
+ }
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ return;
+ }
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ transform_page_func (transform, (gchar *) func_data, docbook);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_document_error_pending (YELP_DOCUMENT (docbook), (YelpError *) func_data);
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ break;
+ case YELP_TRANSFORM_FINAL:
+ transform_final_func (transform, docbook);
+ break;
+ }
+}
+
+static void
+transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpDocbook *docbook)
+{
+ YelpDocbookPriv *priv;
+ gchar *content;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = docbook->priv;
+ g_mutex_lock (priv->mutex);
+
+ content = yelp_transform_eat_chunk (transform, page_id);
+ yelp_document_add_page (YELP_DOCUMENT (docbook), page_id, content);
+
+ g_free (page_id);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+static void
+transform_final_func (YelpTransform *transform, YelpDocbook *docbook)
+{
+ YelpError *error;
+ YelpDocbookPriv *priv = docbook->priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_mutex_lock (priv->mutex);
+
+ error = yelp_error_new (_("Page not found"),
+ _("The requested page was not found in the document %s."),
+ priv->filename);
+ yelp_document_error_pending (YELP_DOCUMENT (docbook), error);
+
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+
+ if (priv->xmldoc)
+ xmlFreeDoc (priv->xmldoc);
+ priv->xmldoc = NULL;
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** Threaded ******************************************************************/
+
+static void
+docbook_process (YelpDocbook *docbook)
+{
+ YelpDocbookPriv *priv;
+ xmlDocPtr xmldoc = NULL;
+ xmlChar *id = NULL;
+ YelpError *error = NULL;
+ xmlParserCtxtPtr parserCtxt = NULL;
+ YelpDocument *document;
+
+ gint params_i = 0;
+ gint params_max = 10;
+ gchar **params = NULL;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (docbook != NULL && YELP_IS_DOCBOOK (docbook));
+ g_object_ref (docbook);
+ priv = docbook->priv;
+ document = YELP_DOCUMENT (docbook);
+
+ if (!g_file_test (priv->filename, G_FILE_TEST_IS_REGULAR)) {
+ error = yelp_error_new (_("File not found"),
+ _("The file ‘%s’ does not exist."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ parserCtxt = xmlNewParserCtxt ();
+ xmldoc = xmlCtxtReadFile (parserCtxt,
+ (const char *) priv->filename, NULL,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+
+ if (xmldoc == NULL) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because it is"
+ " not a well-formed XML document."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ if (xmlXIncludeProcessFlags (xmldoc,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET )
+ < 0) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because"
+ " one or more of its included files is not"
+ " a well-formed XML document."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ g_mutex_lock (priv->mutex);
+ if (!xmlStrcmp (xmlDocGetRootElement (xmldoc)->name, BAD_CAST "book"))
+ priv->max_depth = 2;
+ else
+ priv->max_depth = 1;
+
+ priv->xmldoc = xmldoc;
+ priv->xmlcur = xmlDocGetRootElement (xmldoc);
+
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+ if (id) {
+ yelp_document_set_root_id (document, (gchar *) id);
+ yelp_document_add_page_id (document, "x-yelp-index", (gchar *) id);
+ yelp_document_add_prev_id (document, (gchar *) id, "x-yelp-titlepage");
+ yelp_document_add_next_id (document, "x-yelp-titlepage", (gchar *) id);
+ }
+ else {
+ yelp_document_set_root_id (document, "x-yelp-index");
+ yelp_document_add_page_id (document, "x-yelp-index", "x-yelp-index");
+ yelp_document_add_prev_id (document, "x-yelp-index", "x-yelp-titlepage");
+ yelp_document_add_next_id (document, "x-yelp-titlepage", "x-yelp-index");
+ /* add the id attribute to the root element with value "index"
+ * so when we try to load the document later, it doesn't fail */
+ xmlNewProp (priv->xmlcur, BAD_CAST "id", BAD_CAST "x-yelp-index");
+ }
+ g_mutex_unlock (priv->mutex);
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == DOCBOOK_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+ g_mutex_unlock (priv->mutex);
+
+ docbook_walk (docbook);
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == DOCBOOK_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+ priv->transform = yelp_transform_new (STYLESHEET,
+ (YelpTransformFunc) transform_func,
+ docbook);
+ priv->transform_running = TRUE;
+
+ params = g_new0 (gchar *, params_max);
+ yelp_settings_params (&params, &params_i, &params_max);
+
+
+ if ((params_i + 10) >= params_max - 1) {
+ params_max += 20;
+ params = g_renew (gchar *, params, params_max);
+ }
+
+ params[params_i] = NULL;
+
+ yelp_transform_start (priv->transform,
+ priv->xmldoc,
+ params);
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ if (id)
+ xmlFree (id);
+ if (parserCtxt)
+ xmlFreeParserCtxt (parserCtxt);
+
+ priv->process_running = FALSE;
+ g_object_unref (docbook);
+}
+
+
+/******************************************************************************/
+/** Walker ********************************************************************/
+
+static void
+docbook_walk (YelpDocbook *docbook)
+{
+ static gint autoid = 0;
+ gchar autoidstr[20];
+ xmlChar *id = NULL;
+ xmlChar *title = NULL;
+ gchar *old_page_id = NULL;
+ xmlNodePtr cur, old_cur;
+ GtkTreeIter iter;
+ GtkTreeIter *old_iter = NULL;
+ YelpDocbookPriv *priv = docbook->priv;
+ YelpDocument *document = YELP_DOCUMENT (docbook);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_DEBUG, " priv->xmlcur->name: %s\n", priv->xmlcur->name);
+
+ /* check for the yelp:chunk-depth or db.chunk.max_depth processing
+ * instruction and set the max chunk depth accordingly.
+ */
+ if (priv->cur_depth == 0)
+ for (cur = priv->xmlcur; cur; cur = cur->prev)
+ if (cur->type == XML_PI_NODE)
+ if (!xmlStrcmp (cur->name, (const xmlChar *) "yelp:chunk-depth") ||
+ !xmlStrcmp (cur->name, (const xmlChar *) "db.chunk.max_depth")) {
+ gint max = atoi ((gchar *) cur->content);
+ if (max)
+ priv->max_depth = max;
+ break;
+ }
+
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+
+ if (docbook_walk_chunkQ (docbook)) {
+ title = BAD_CAST docbook_walk_get_title (docbook);
+
+ /* if id attribute is not present, autogenerate a
+ * unique value, and insert it into the in-memory tree */
+ if (!id) {
+ g_snprintf (autoidstr, 20, "_auto-gen-id-%d", ++autoid);
+ xmlNewProp (priv->xmlcur, BAD_CAST "id", BAD_CAST autoidstr);
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+ }
+
+ debug_print (DB_DEBUG, " id: \"%s\"\n", id);
+ debug_print (DB_DEBUG, " title: \"%s\"\n", title);
+
+ yelp_document_add_title (document, (gchar *) id, (gchar *) title);
+
+ gdk_threads_enter ();
+ gtk_tree_store_append (GTK_TREE_STORE (priv->sections),
+ &iter,
+ priv->sections_iter);
+ gtk_tree_store_set (GTK_TREE_STORE (priv->sections),
+ &iter,
+ YELP_DOCUMENT_COLUMN_ID, id,
+ YELP_DOCUMENT_COLUMN_TITLE, title,
+ -1);
+ gdk_threads_leave ();
+
+ if (priv->cur_prev_id) {
+ yelp_document_add_prev_id (document, (gchar *) id, priv->cur_prev_id);
+ yelp_document_add_next_id (document, priv->cur_prev_id, (gchar *) id);
+ g_free (priv->cur_prev_id);
+ }
+ priv->cur_prev_id = g_strdup ((gchar *) id);
+
+ if (priv->cur_page_id)
+ yelp_document_add_up_id (document, (gchar *) id, priv->cur_page_id);
+ old_page_id = priv->cur_page_id;
+ priv->cur_page_id = g_strdup ((gchar *) id);
+
+ old_iter = priv->sections_iter;
+ if (priv->xmlcur->parent->type != XML_DOCUMENT_NODE)
+ priv->sections_iter = &iter;
+ }
+
+ old_cur = priv->xmlcur;
+ priv->cur_depth++;
+
+ if (id)
+ yelp_document_add_page_id (document, (gchar *) id, priv->cur_page_id);
+
+ for (cur = priv->xmlcur->children; cur; cur = cur->next) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ priv->xmlcur = cur;
+ docbook_walk (docbook);
+ }
+ }
+ priv->cur_depth--;
+ priv->xmlcur = old_cur;
+
+ if (docbook_walk_chunkQ (docbook)) {
+ priv->sections_iter = old_iter;
+ g_free (priv->cur_page_id);
+ priv->cur_page_id = old_page_id;
+ }
+
+ if (priv->cur_depth == 0) {
+ g_free (priv->cur_prev_id);
+ priv->cur_prev_id = NULL;
+
+ g_free (priv->cur_page_id);
+ priv->cur_page_id = NULL;
+ }
+
+ if (id != NULL)
+ xmlFree (id);
+ if (title != NULL)
+ xmlFree (title);
+}
+
+static gboolean
+docbook_walk_chunkQ (YelpDocbook *docbook)
+{
+ if (docbook->priv->cur_depth <= docbook->priv->max_depth
+ && docbook_walk_divisionQ (docbook))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static gboolean
+docbook_walk_divisionQ (YelpDocbook *docbook)
+{
+ xmlNodePtr node = docbook->priv->xmlcur;
+ return (!xmlStrcmp (node->name, (const xmlChar *) "appendix") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "article") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "book") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "bibliography") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "chapter") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "colophon") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "glossary") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "index") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "part") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "preface") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "reference") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refentry") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect1") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect2") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect3") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsection") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect1") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect2") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect3") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect4") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect5") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "section") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "set") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "setindex") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "simplesect") );
+}
+
+static gchar *
+docbook_walk_get_title (YelpDocbook *docbook)
+{
+ gchar *infoname = NULL;
+ xmlNodePtr child = NULL;
+ xmlNodePtr title = NULL;
+ xmlNodePtr title_tmp = NULL;
+ YelpDocbookPriv *priv = docbook->priv;
+
+ if (!xmlStrcmp (priv->xmlcur->name, BAD_CAST "refentry")) {
+ /* The title for a refentry element can come from the following:
+ * refmeta/refentrytitle
+ * refentryinfo/title[abbrev]
+ * refnamediv/refname
+ * We take the first one we find.
+ */
+ for (child = priv->xmlcur->children; child; child = child->next) {
+ if (!xmlStrcmp (child->name, BAD_CAST "refmeta")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "refentrytitle"))
+ break;
+ }
+ if (title)
+ goto done;
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "refentryinfo")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "titleabbrev"))
+ break;
+ else if (!xmlStrcmp (title->name, BAD_CAST "title"))
+ title_tmp = title;
+ }
+ if (title)
+ goto done;
+ else if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "refnamediv")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "refname"))
+ break;
+ else if (!xmlStrcmp (title->name, BAD_CAST "refpurpose")) {
+ title = NULL;
+ break;
+ }
+ }
+ if (title)
+ goto done;
+ }
+ else if (!xmlStrncmp (child->name, BAD_CAST "refsect", 7))
+ break;
+ }
+ }
+ else {
+ /* The title for other elements appears in the following:
+ * title[abbrev]
+ * *info/title[abbrev]
+ * blockinfo/title[abbrev]
+ * objectinfo/title[abbrev]
+ * We take them in that order.
+ */
+ xmlNodePtr infos[3] = {NULL, NULL, NULL};
+ int i;
+
+ infoname = g_strdup_printf ("%sinfo", priv->xmlcur->name);
+
+ for (child = priv->xmlcur->children; child; child = child->next) {
+ if (!xmlStrcmp (child->name, BAD_CAST "titleabbrev")) {
+ title = child;
+ goto done;
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "title"))
+ title_tmp = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST infoname))
+ infos[0] = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST "blockinfo"))
+ infos[1] = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST "objectinfo"))
+ infos[2] = child;
+ }
+
+ if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+
+ for (i = 0; i < 3; i++) {
+ child = infos[i];
+ if (child) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "titleabbrev"))
+ goto done;
+ else if (!xmlStrcmp (title->name, BAD_CAST "title"))
+ title_tmp = title;
+ }
+ if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+ }
+ }
+ }
+
+ done:
+ g_free (infoname);
+
+ if (title)
+ return (gchar *) xmlNodeGetContent (title);
+ else
+ return g_strdup (_("Unknown"));
+}
diff --git a/src/yelp-docbook.h b/src/yelp-docbook.h
new file mode 100644
index 00000000..9690a718
--- /dev/null
+++ b/src/yelp-docbook.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_DOCBOOK_H__
+#define __YELP_DOCBOOK_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_DOCBOOK (yelp_docbook_get_type ())
+#define YELP_DOCBOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_DOCBOOK, YelpDocbook))
+#define YELP_DOCBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_DOCBOOK, YelpDocbookClass))
+#define YELP_IS_DOCBOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_DOCBOOK))
+#define YELP_IS_DOCBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_DOCBOOK))
+#define YELP_DOCBOOK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_DOCBOOK, YelpDocbookClass))
+
+typedef struct _YelpDocbook YelpDocbook;
+typedef struct _YelpDocbookClass YelpDocbookClass;
+typedef struct _YelpDocbookPriv YelpDocbookPriv;
+
+struct _YelpDocbook {
+ YelpDocument parent;
+ YelpDocbookPriv *priv;
+};
+
+struct _YelpDocbookClass {
+ YelpDocumentClass parent_class;
+};
+
+GType yelp_docbook_get_type (void);
+YelpDocument * yelp_docbook_new (gchar *uri);
+
+#endif /* __YELP_DOCBOOK_H__ */
diff --git a/src/yelp-document.c b/src/yelp-document.c
new file mode 100644
index 00000000..0679d568
--- /dev/null
+++ b/src/yelp-document.c
@@ -0,0 +1,807 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "yelp-document.h"
+#include "yelp-debug.h"
+
+#define YELP_DOCUMENT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_DOCUMENT, YelpDocumentPriv))
+
+typedef struct _Request Request;
+struct _Request {
+ YelpDocument *document;
+ YelpDocumentFunc func;
+ gpointer user_data;
+
+ YelpError *error;
+
+ gint req_id;
+ gchar *page_id;
+
+ gint idle_funcs;
+ gboolean cancel;
+};
+
+struct _YelpDocumentPriv {
+ GMutex *mutex;
+
+ gchar *root_id;
+
+ GHashTable *reqs_by_req_id; /* Indexed by the request ID */
+ GHashTable *reqs_by_page_id; /* Indexed by page ID, contains GSList */
+ GSList *reqs_pending; /* List of requests that need a page */
+
+ GtkTreeModel *sections; /* Sections of the document, for display */
+ /* Real page IDs map to themselves, so this list doubles
+ * as a list of all valid page IDs.
+ */
+ GHashTable *page_ids; /* Mapping of fragment IDs to real page IDs */
+ GHashTable *titles; /* Mapping of page IDs to titles */
+ GHashTable *contents; /* Mapping of page IDs to string content */
+ GHashTable *pages; /* Mapping of page IDs to open YelpPages */
+
+ GHashTable *prev_ids; /* Mapping of page IDs to "previous page" IDs */
+ GHashTable *next_ids; /* Mapping of page IDs to "next page" IDs */
+ GHashTable *up_ids; /* Mapping of page IDs to "up page" IDs */
+};
+
+static void document_class_init (YelpDocumentClass *klass);
+static void document_init (YelpDocument *document);
+static void document_dispose (GObject *object);
+static gpointer document_get_sections (YelpDocument *document);
+
+static gboolean request_idle_title (Request *request);
+static gboolean request_idle_page (Request *request);
+static gboolean request_idle_error (Request *request);
+static void request_try_free (Request *request);
+static void request_free (Request *request);
+
+static void hash_slist_insert (GHashTable *hash,
+ const gchar *key,
+ gpointer value);
+static void hash_slist_remove (GHashTable *hash,
+ const gchar *key,
+ gpointer value);
+
+GStaticMutex str_mutex = G_STATIC_MUTEX_INIT;
+GHashTable *str_refs = NULL;
+static gchar * str_ref (gchar *str);
+static void str_unref (gchar *str);
+
+static GObjectClass *parent_class;
+
+GType
+yelp_document_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpDocumentClass),
+ NULL, NULL,
+ (GClassInitFunc) document_class_init,
+ NULL, NULL,
+ sizeof (YelpDocument),
+ 0,
+ (GInstanceInitFunc) document_init,
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "YelpDocument",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+document_class_init (YelpDocumentClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = document_dispose;
+
+ klass->get_sections = document_get_sections;
+
+ g_type_class_add_private (klass, sizeof (YelpDocumentPriv));
+}
+
+static void
+document_init (YelpDocument *document)
+{
+ YelpDocumentPriv *priv;
+
+ document->priv = priv = YELP_DOCUMENT_GET_PRIVATE (document);
+
+ priv->mutex = g_mutex_new ();
+
+ priv->reqs_by_req_id =
+ g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL,
+ (GDestroyNotify) request_try_free);
+ priv->reqs_by_page_id =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free,
+ (GDestroyNotify) g_slist_free);
+ priv->reqs_pending = NULL;
+
+ priv->sections = NULL;
+ priv->page_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ priv->titles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ priv->contents = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free,
+ (GDestroyNotify) str_unref);
+ priv->pages = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free,
+ (GDestroyNotify) g_slist_free);
+ priv->prev_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ priv->next_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ priv->up_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+}
+
+static gpointer
+document_get_sections (YelpDocument *document)
+{
+ return NULL;
+}
+
+
+static void
+document_dispose (GObject *object)
+{
+ YelpDocument *document = YELP_DOCUMENT (object);
+
+ g_free (document->priv->root_id);
+
+ g_slist_free (document->priv->reqs_pending);
+ g_hash_table_destroy (document->priv->reqs_by_page_id);
+ g_hash_table_destroy (document->priv->reqs_by_req_id);
+
+ g_hash_table_destroy (document->priv->page_ids);
+ g_hash_table_destroy (document->priv->titles);
+
+ g_hash_table_destroy (document->priv->contents);
+ g_hash_table_destroy (document->priv->pages);
+
+ g_hash_table_destroy (document->priv->prev_ids);
+ g_hash_table_destroy (document->priv->next_ids);
+ g_hash_table_destroy (document->priv->up_ids);
+
+ g_mutex_free (document->priv->mutex);
+
+ parent_class->dispose (object);
+}
+
+/******************************************************************************/
+
+gint
+yelp_document_get_page (YelpDocument *document,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpDocumentPriv *priv;
+ gchar *real_id;
+ gboolean handled = FALSE;
+ Request *request;
+ gint req_id;
+ static gint request_id = 0;
+
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+
+ priv = document->priv;
+
+ request = g_slice_new0 (Request);
+ request->document = document;
+ request->func = func;
+ request->user_data = user_data;
+ request->req_id = req_id = ++request_id;
+
+ real_id = g_hash_table_lookup (priv->page_ids, page_id);
+ if (real_id)
+ request->page_id = g_strdup (real_id);
+ else
+ request->page_id = g_strdup (page_id);
+
+ g_mutex_lock (priv->mutex);
+
+ g_hash_table_insert (priv->reqs_by_req_id,
+ GINT_TO_POINTER (req_id),
+ request);
+ hash_slist_insert (priv->reqs_by_page_id,
+ request->page_id,
+ request);
+ priv->reqs_pending = g_slist_prepend (priv->reqs_pending, request);
+
+ if (g_hash_table_lookup (priv->titles, request->page_id)) {
+ request->idle_funcs++;
+ g_idle_add ((GSourceFunc) request_idle_title, request);
+ }
+
+ if (g_hash_table_lookup (priv->contents, request->page_id)) {
+ request->idle_funcs++;
+ g_idle_add ((GSourceFunc) request_idle_page, request);
+ handled = TRUE;
+ }
+
+ g_mutex_unlock (priv->mutex);
+
+ YELP_DOCUMENT_GET_CLASS (document)->request (document,
+ req_id,
+ handled,
+ request->page_id,
+ func,
+ user_data);
+
+ return req_id;
+}
+
+void
+yelp_document_cancel_page (YelpDocument *document, gint req_id)
+{
+ YelpDocumentPriv *priv;
+ Request *request;
+
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " req_id = %i\n", req_id);
+
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+ request = g_hash_table_lookup (priv->reqs_by_req_id,
+ GINT_TO_POINTER (req_id));
+ if (request) {
+ priv->reqs_pending = g_slist_remove (priv->reqs_pending,
+ (gconstpointer) request);
+ hash_slist_remove (priv->reqs_by_page_id,
+ request->page_id,
+ request);
+ } else {
+ g_warning ("YelpDocument: Attempted to remove request %i,"
+ " but no such request exists.",
+ req_id);
+ }
+ g_mutex_unlock (priv->mutex);
+
+ if (YELP_DOCUMENT_GET_CLASS (document)->cancel)
+ YELP_DOCUMENT_GET_CLASS (document)->cancel (document, req_id);
+}
+
+/******************************************************************************/
+
+void
+yelp_document_release_page (YelpDocument *document, YelpPage *page)
+{
+ YelpDocumentPriv *priv;
+
+ g_return_if_fail (YELP_IS_DOCUMENT (document));
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ hash_slist_remove (priv->pages, page->id, page);
+ if (page->content)
+ str_unref (page->content);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+/******************************************************************************/
+
+void
+yelp_document_set_root_id (YelpDocument *document, gchar *root_id)
+{
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ if (document->priv->root_id)
+ g_free (document->priv->root_id);
+
+ document->priv->root_id = g_strdup (root_id);
+}
+
+void
+yelp_document_add_page_id (YelpDocument *document, gchar *id, gchar *page_id)
+{
+ GSList *reqs, *cur;
+ Request *request;
+ gchar *title, *contents;
+ YelpDocumentPriv *priv;
+
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+ if (g_hash_table_lookup (priv->page_ids, id)) {
+ g_warning ("YelpDocument: Attempted to add an ID mapping from"
+ " %s to %s, but %s is already mapped.",
+ id, page_id, id);
+ g_mutex_unlock (priv->mutex);
+ return;
+ }
+
+ g_hash_table_insert (priv->page_ids, g_strdup (id), g_strdup (page_id));
+
+ if (!g_str_equal (id, page_id)) {
+ title = g_hash_table_lookup (priv->titles, page_id);
+ contents = g_hash_table_lookup (priv->contents, page_id);
+ reqs = g_hash_table_lookup (priv->reqs_by_page_id, id);
+ for (cur = reqs; cur != NULL; cur = cur->next) {
+ if (cur->data) {
+ request = (Request *) cur->data;
+ g_free (request->page_id);
+ request->page_id = g_strdup (page_id);
+ hash_slist_insert (priv->reqs_by_page_id, page_id, request);
+ if (title) {
+ request->idle_funcs++;
+ g_idle_add ((GSourceFunc) request_idle_title, request);
+ }
+ if (contents) {
+ request->idle_funcs++;
+ g_idle_add ((GSourceFunc) request_idle_page, request);
+ }
+ }
+ }
+ if (reqs)
+ g_hash_table_remove (priv->reqs_by_page_id, id);
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+void
+yelp_document_add_prev_id (YelpDocument *document, gchar *page_id, gchar *prev_id)
+{
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ g_mutex_lock (document->priv->mutex);
+ g_hash_table_replace (document->priv->prev_ids, g_strdup (page_id), g_strdup (prev_id));
+ g_mutex_unlock (document->priv->mutex);
+}
+
+void
+yelp_document_add_next_id (YelpDocument *document, gchar *page_id, gchar *next_id)
+{
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ g_mutex_lock (document->priv->mutex);
+ g_hash_table_replace (document->priv->next_ids, g_strdup (page_id), g_strdup (next_id));
+ g_mutex_unlock (document->priv->mutex);
+}
+
+void
+yelp_document_add_up_id (YelpDocument *document, gchar *page_id, gchar *up_id)
+{
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ g_mutex_lock (document->priv->mutex);
+ g_hash_table_replace (document->priv->up_ids, g_strdup (page_id), g_strdup (up_id));
+ g_mutex_unlock (document->priv->mutex);
+}
+
+void
+yelp_document_add_title (YelpDocument *document, gchar *page_id, gchar *title)
+{
+ GSList *reqs, *cur;
+ Request *request;
+ YelpDocumentPriv *priv;
+
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ debug_print (DB_FUNCTION, "entering\n");
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ g_hash_table_replace (priv->titles, g_strdup (page_id), g_strdup (title));
+
+ reqs = g_hash_table_lookup (priv->reqs_by_page_id, page_id);
+ for (cur = reqs; cur != NULL; cur = cur->next) {
+ if (cur->data) {
+ request = (Request *) cur->data;
+ request->idle_funcs++;
+ g_idle_add ((GSourceFunc) request_idle_title, request);
+ }
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+void
+yelp_document_add_page (YelpDocument *document, gchar *page_id, const gchar *contents)
+{
+ GSList *reqs, *cur;
+ Request *request;
+ YelpDocumentPriv *priv;
+
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ g_hash_table_replace (priv->contents,
+ g_strdup (page_id),
+ str_ref ((gchar *) contents));
+
+ reqs = g_hash_table_lookup (priv->reqs_by_page_id, page_id);
+ for (cur = reqs; cur != NULL; cur = cur->next) {
+ if (cur->data) {
+ request = (Request *) cur->data;
+ request->idle_funcs++;
+ g_idle_add ((GSourceFunc) request_idle_page, request);
+ }
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+gboolean
+yelp_document_has_page (YelpDocument *document, gchar *page_id)
+{
+ gchar *content;
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+ content = g_hash_table_lookup (document->priv->contents, page_id);
+ return !(content == NULL);
+}
+
+GtkTreeModel *
+yelp_document_get_sections (YelpDocument *document)
+{
+ return (YELP_DOCUMENT_GET_CLASS (document)->get_sections(document));
+}
+
+void
+yelp_document_error_request (YelpDocument *document, gint req_id, YelpError *error)
+{
+ Request *request;
+ YelpDocumentPriv *priv;
+
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ debug_print (DB_FUNCTION, "entering\n");
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ request = g_hash_table_lookup (priv->reqs_by_req_id,
+ GINT_TO_POINTER (req_id));
+ if (request) {
+ request->error = error;
+ request->idle_funcs++;
+ g_idle_add ((GSourceFunc) request_idle_error, request);
+ } else {
+ yelp_error_free (error);
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+void
+yelp_document_error_pending (YelpDocument *document, YelpError *error)
+{
+ GSList *cur;
+ Request *request;
+ YelpDocumentPriv *priv;
+
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ debug_print (DB_FUNCTION, "entering\n");
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ if (priv->reqs_pending) {
+ for (cur = priv->reqs_pending; cur; cur = cur->next) {
+ request = cur->data;
+ if (cur->next)
+ request->error = yelp_error_copy (error);
+ else
+ request->error = error;
+ request->idle_funcs++;
+ g_idle_add ((GSourceFunc) request_idle_error, request);
+ }
+
+ g_slist_free (priv->reqs_pending);
+ priv->reqs_pending = NULL;
+ } else {
+ yelp_error_free (error);
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+/******************************************************************************/
+
+static gboolean
+request_idle_title (Request *request)
+{
+ YelpDocument *document;
+ YelpDocumentPriv *priv;
+ YelpDocumentFunc func = NULL;
+ gchar *title;
+ gint req_id = 0;
+ gpointer user_data = user_data;
+
+ g_assert (request != NULL && YELP_IS_DOCUMENT (request->document));
+
+ if (request->cancel) {
+ request->idle_funcs--;
+ return FALSE;
+ }
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ document = g_object_ref (request->document);
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ title = g_hash_table_lookup (priv->titles, request->page_id);
+ if (title) {
+ func = request->func;
+ req_id = request->req_id;
+ title = g_strdup (title);
+ user_data = request->user_data;
+ }
+
+ request->idle_funcs--;
+ g_mutex_unlock (priv->mutex);
+
+ if (func)
+ func (document,
+ YELP_DOCUMENT_SIGNAL_TITLE,
+ req_id,
+ title,
+ user_data);
+
+ g_object_unref (document);
+ return FALSE;
+}
+
+static gboolean
+request_idle_page (Request *request)
+{
+ YelpDocument *document;
+ YelpDocumentPriv *priv;
+ YelpDocumentFunc func = NULL;
+ YelpPage *page = NULL;
+ gchar *contents, *tmp;
+ gint req_id = 0;
+ gpointer user_data = user_data;
+
+ g_assert (request != NULL && YELP_IS_DOCUMENT (request->document));
+
+ if (request->cancel) {
+ request->idle_funcs--;
+ return FALSE;
+ }
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ document = g_object_ref (request->document);
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ contents = g_hash_table_lookup (priv->contents, request->page_id);
+ if (contents) {
+ func = request->func;
+ req_id = request->req_id;
+ user_data = request->user_data;
+
+ /* FIXME: there will come a day when we can't just assume XHTML */
+ page = yelp_page_new_string (YELP_DOCUMENT (request->document),
+ request->page_id,
+ str_ref (contents),
+ YELP_PAGE_MIME_XHTML);
+ tmp = g_hash_table_lookup (priv->prev_ids, request->page_id);
+ if (tmp)
+ page->prev_id = g_strdup (tmp);
+ tmp = g_hash_table_lookup (priv->next_ids, request->page_id);
+ if (tmp)
+ page->next_id = g_strdup (tmp);
+ tmp = g_hash_table_lookup (priv->up_ids, request->page_id);
+ if (tmp)
+ page->up_id = g_strdup (tmp);
+ if (priv->root_id)
+ page->root_id = g_strdup (priv->root_id);
+ priv->reqs_pending = g_slist_remove (priv->reqs_pending, request);
+ }
+
+ request->idle_funcs--;
+ g_mutex_unlock (priv->mutex);
+
+ if (func) {
+ func (document,
+ YELP_DOCUMENT_SIGNAL_PAGE,
+ req_id,
+ page,
+ user_data);
+ }
+
+ g_object_unref (document);
+
+ return FALSE;
+}
+
+static gboolean
+request_idle_error (Request *request)
+{
+ YelpDocument *document;
+ YelpDocumentPriv *priv;
+ YelpDocumentFunc func = NULL;
+ YelpError *error = NULL;
+ gint req_id = 0;
+ gpointer user_data = user_data;
+
+ g_assert (request != NULL && YELP_IS_DOCUMENT (request->document));
+
+ if (request->cancel) {
+ request->idle_funcs--;
+ return FALSE;
+ }
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ document = g_object_ref (request->document);
+ priv = document->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ if (request->error) {
+ func = request->func;
+ req_id = request->req_id;
+ user_data = request->user_data;
+ error = request->error;
+ request->error = NULL;
+
+ priv->reqs_pending = g_slist_remove (priv->reqs_pending, request);
+ }
+
+ request->idle_funcs--;
+ g_mutex_unlock (priv->mutex);
+
+ if (func)
+ func (document,
+ YELP_DOCUMENT_SIGNAL_ERROR,
+ req_id,
+ error,
+ user_data);
+
+ g_object_unref (document);
+ return FALSE;
+}
+
+static void
+request_try_free (Request *request) {
+ debug_print (DB_FUNCTION, "entering\n");
+ request->cancel = TRUE;
+
+ if (request->idle_funcs == 0)
+ request_free (request);
+ else
+ g_idle_add ((GSourceFunc) request_try_free, request);
+}
+
+static void
+request_free (Request *request)
+{
+ debug_print (DB_FUNCTION, "entering\n");
+ g_free (request->page_id);
+ g_free (request);
+}
+
+/******************************************************************************/
+
+static void
+hash_slist_insert (GHashTable *hash,
+ const gchar *key,
+ gpointer value)
+{
+ GSList *list;
+ list = g_hash_table_lookup (hash, key);
+ if (list) {
+ list->next = g_slist_prepend (list->next, value);
+ } else {
+ list = g_slist_prepend (NULL, value);
+ list = g_slist_prepend (list, NULL);
+ g_hash_table_insert (hash, g_strdup (key), list);
+ }
+}
+
+static void
+hash_slist_remove (GHashTable *hash,
+ const gchar *key,
+ gpointer value)
+{
+ GSList *list;
+ list = g_hash_table_lookup (hash, key);
+ if (list) {
+ list = g_slist_remove (list, value);
+ if (list->next == NULL)
+ g_hash_table_remove (hash, key);
+ }
+}
+
+static gchar *
+str_ref (gchar *str)
+{
+ gpointer p;
+ guint i;
+
+ g_static_mutex_lock (&str_mutex);
+
+ if (str_refs == NULL)
+ str_refs = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ p = g_hash_table_lookup (str_refs, str);
+
+ i = GPOINTER_TO_UINT (p);
+ i++;
+ p = GUINT_TO_POINTER (i);
+
+ g_hash_table_insert (str_refs, str, p);
+
+ g_static_mutex_unlock (&str_mutex);
+
+ return str;
+}
+
+static void
+str_unref (gchar *str)
+{
+ gpointer p;
+ guint i;
+
+ g_static_mutex_lock (&str_mutex);
+
+ p = g_hash_table_lookup (str_refs, str);
+
+ i = GPOINTER_TO_UINT (p);
+ i--;
+ p = GUINT_TO_POINTER (i);
+
+ if (i > 0)
+ g_hash_table_insert (str_refs, str, p);
+ else {
+ g_hash_table_remove (str_refs, str);
+ g_free (str);
+ }
+
+ g_static_mutex_unlock (&str_mutex);
+}
diff --git a/src/yelp-document.h b/src/yelp-document.h
new file mode 100644
index 00000000..e8a1ffca
--- /dev/null
+++ b/src/yelp-document.h
@@ -0,0 +1,132 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_DOCUMENT_H__
+#define __YELP_DOCUMENT_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#define YELP_TYPE_DOCUMENT (yelp_document_get_type ())
+#define YELP_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_DOCUMENT, YelpDocument))
+#define YELP_DOCUMENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_DOCUMENT, YelpDocumentClass))
+#define YELP_IS_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_DOCUMENT))
+#define YELP_IS_DOCUMENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_DOCUMENT))
+#define YELP_DOCUMENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_DOCUMENT, YelpDocumentClass))
+
+typedef struct _YelpDocument YelpDocument;
+typedef struct _YelpDocumentClass YelpDocumentClass;
+typedef struct _YelpDocumentPriv YelpDocumentPriv;
+
+/* This needs to be after the typedefs. */
+#include "yelp-page.h"
+
+typedef enum {
+ YELP_DOCUMENT_SIGNAL_PAGE,
+ YELP_DOCUMENT_SIGNAL_TITLE,
+ YELP_DOCUMENT_SIGNAL_ERROR
+} YelpDocumentSignal;
+
+enum {
+ YELP_DOCUMENT_COLUMN_ID = 0,
+ YELP_DOCUMENT_COLUMN_TITLE,
+ YELP_DOCUMENT_NUM_COLUMNS
+};
+
+typedef void (*YelpDocumentFunc) (YelpDocument *document,
+ YelpDocumentSignal signal,
+ gint req_id,
+ gpointer func_data,
+ gpointer user_data);
+
+struct _YelpDocument {
+ GObject parent;
+ YelpDocumentPriv *priv;
+};
+
+struct _YelpDocumentClass {
+ GObjectClass parent_class;
+
+ /* Virtual Functions */
+ void (*request) (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+ void (*cancel) (YelpDocument *document,
+ gint req_id);
+
+ gint (*get_page) (YelpDocument *document,
+ gchar *page_id,
+ gpointer user_data);
+ void (*release_page) (YelpDocument *document,
+ YelpPage *page);
+ gpointer (*get_sections) (YelpDocument *document);
+};
+
+
+GType yelp_document_get_type (void);
+
+gint yelp_document_get_page (YelpDocument *document,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+void yelp_document_cancel_page (YelpDocument *document,
+ gint req_id);
+
+/* Only called by yelp_page_free */
+void yelp_document_release_page (YelpDocument *document,
+ YelpPage *page);
+
+/* Only called by subclasses */
+void yelp_document_set_root_id (YelpDocument *document,
+ gchar *root_id);
+void yelp_document_add_page_id (YelpDocument *document,
+ gchar *id,
+ gchar *page_id);
+void yelp_document_add_prev_id (YelpDocument *document,
+ gchar *page_id,
+ gchar *prev_id);
+void yelp_document_add_next_id (YelpDocument *document,
+ gchar *page_id,
+ gchar *next_id);
+void yelp_document_add_up_id (YelpDocument *document,
+ gchar *page_id,
+ gchar *up_id);
+void yelp_document_add_title (YelpDocument *document,
+ gchar *page_id,
+ gchar *title);
+void yelp_document_add_page (YelpDocument *document,
+ gchar *page_id,
+ const gchar *contents);
+gboolean yelp_document_has_page (YelpDocument *document,
+ gchar *page_id);
+void yelp_document_error_request (YelpDocument *document,
+ gint req_id,
+ YelpError *error);
+void yelp_document_error_pending (YelpDocument *document,
+ YelpError *error);
+GtkTreeModel *yelp_document_get_sections (YelpDocument *document);
+
+
+#endif /* __YELP_DOCUMENT_H__ */
diff --git a/src/yelp-error.c b/src/yelp-error.c
index b32bd5e5..fcb21425 100644
--- a/src/yelp-error.c
+++ b/src/yelp-error.c
@@ -1,6 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2002 Mikael Hallendal <micke@imendio.com>
+ * Copyright (C) 2007 Shaun McCance <shaunm@gnome.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -20,12 +21,101 @@
#include <config.h>
+#include <glib.h>
#include <glib/gi18n.h>
#include "yelp-error.h"
+struct _YelpError {
+ gchar *title;
+ gchar *message;
+};
+
+static YelpError *
+yelp_error_new_valist (gchar *title, gchar *format, va_list args)
+{
+ YelpError *error;
+
+ error = g_slice_new (YelpError);
+ error->title = g_strdup (title);
+ error->message = g_strdup_vprintf (format, args);
+
+ return error;
+}
+
+YelpError *
+yelp_error_new (gchar *title, gchar *format, ...)
+{
+ YelpError *error;
+ va_list args;
+
+ va_start (args, format);
+ error = yelp_error_new_valist (title, format, args);
+ va_end (args);
+
+ return error;
+}
+
+void
+yelp_error_set (YelpError **error, gchar *title, gchar *format, ...)
+{
+ YelpError *new;
+ va_list args;
+
+ va_start (args, format);
+ new = yelp_error_new_valist (title, format, args);
+ va_end (args);
+
+ if (*error == NULL)
+ *error = new;
+ else
+ g_warning
+ ("YelpError set over the top of a previous YelpError or uninitialized\n"
+ "memory. This indicates a bug in someone's code. You must ensure an\n"
+ "error is NULL before it's set. The overwriting error message was:\n"
+ "%s",
+ new->message);
+}
+
+YelpError *
+yelp_error_copy (YelpError *error)
+{
+ YelpError *new;
+
+ new = g_slice_new (YelpError);
+ new->title = g_strdup (error->title);
+ new->message = g_strdup (error->message);
+
+ return error;
+}
+
+const gchar *
+yelp_error_get_title (YelpError *error)
+{
+ g_return_val_if_fail (error != NULL, NULL);
+ return error->title;
+}
+
+const gchar *
+yelp_error_get_message (YelpError *error)
+{
+ g_return_val_if_fail (error != NULL, NULL);
+ return error->message;
+}
+
+void
+yelp_error_free (YelpError *error)
+{
+ g_return_if_fail (error != NULL);
+ g_free (error->title);
+ g_free (error->message);
+ g_slice_free (YelpError, error);
+}
+
+/******************************************************************************/
+
GQuark
-yelp_error_quark (void)
+yelp_gerror_quark (void)
{
static GQuark q = 0;
@@ -36,34 +126,24 @@ yelp_error_quark (void)
}
const gchar *
-yelp_error_get_primary (GError *error)
+yelp_gerror_get_title (GError *error)
{
- if (!error || error->domain != YELP_ERROR)
- return _("An unknown error occured");
+ if (!error || error->domain != YELP_GERROR)
+ return _("Unknown Error");
switch (error->code) {
- case YELP_ERROR_NO_DOC:
- return _("Could not load document");
- case YELP_ERROR_NO_PAGE:
- return _("Could not load section");
- case YELP_ERROR_NO_TOC:
- return _("Could not read the table of contents");
- case YELP_ERROR_FORMAT:
- return _("Unsupported Format");
- case YELP_ERROR_IO:
- return _("Could not read document");
- case YELP_ERROR_PROC:
- return _("Could not process document");
- default:
- return _("An unknown error occured");
+ case YELP_GERROR_IO:
+ return _("Could Not Read File");
}
+
+ return _("Unknown Error");
}
const gchar *
-yelp_error_get_secondary (GError *error)
+yelp_gerror_get_message (GError *error)
{
if (!error || !error->message)
- return _("No information is available about the error.");
+ return _("No information is available about this error.");
else
return error->message;
}
diff --git a/src/yelp-error.h b/src/yelp-error.h
index 02a1dc46..91a5bda2 100644
--- a/src/yelp-error.h
+++ b/src/yelp-error.h
@@ -1,6 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2002 Mikael Hallendal <micke@imendio.com>
+ * Copyright (C) 2007 Shaun McCance <shaunm@gnome.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -23,20 +24,31 @@
#include <glib.h>
-#define YELP_ERROR yelp_error_quark ()
+typedef struct _YelpError YelpError;
-typedef enum {
- YELP_ERROR_NO_DOC, /* Selected document not found */
- YELP_ERROR_NO_PAGE, /* Selected page not found */
- YELP_ERROR_NO_TOC, /* Could not read the TOC */
- YELP_ERROR_FORMAT, /* Format is not supported */
- YELP_ERROR_IO, /* Error in IO */
- YELP_ERROR_PROC /* Error processing the document */
-} YelpError;
+YelpError * yelp_error_new (gchar *title,
+ gchar *format,
+ ...);
+void yelp_error_set (YelpError **error,
+ gchar *title,
+ gchar *format,
+ ...);
+YelpError * yelp_error_copy (YelpError *error);
-GQuark yelp_error_quark (void) G_GNUC_CONST;
+const gchar * yelp_error_get_title (YelpError *error);
+const gchar * yelp_error_get_message (YelpError *error);
-const gchar * yelp_error_get_primary (GError *error);
-const gchar * yelp_error_get_secondary (GError *error);
+void yelp_error_free (YelpError *error);
+
+
+#define YELP_GERROR yelp_gerror_quark ()
+
+enum {
+ YELP_GERROR_IO
+};
+
+GQuark yelp_gerror_quark (void) G_GNUC_CONST;
+const gchar * yelp_gerror_get_title (GError *error);
+const gchar * yelp_gerror_get_message (GError *error);
#endif /* __YELP_ERROR_H__ */
diff --git a/src/yelp-info-pager.c b/src/yelp-info-pager.c
index 98843615..2c674c22 100644
--- a/src/yelp-info-pager.c
+++ b/src/yelp-info-pager.c
@@ -171,7 +171,7 @@ info_pager_parse (YelpPager *pager)
GError *error = NULL;
YelpInfoPagerPriv *priv;
- g_return_val_if_fail (YELP_IS_INFO_PAGER (pager), NULL);
+ g_return_val_if_fail (YELP_IS_INFO_PAGER (pager), FALSE);
priv = YELP_INFO_PAGER (pager)->priv;
doc_info = yelp_pager_get_doc_info (pager);
diff --git a/src/yelp-info-parser.c b/src/yelp-info-parser.c
index c6eb89a0..1dafea0d 100644
--- a/src/yelp-info-parser.c
+++ b/src/yelp-info-parser.c
@@ -93,8 +93,8 @@ page_type (char *page)
return PAGE_OTHER;
}
-static char *
-open_info_file (char *file)
+static char
+*open_info_file (char *file)
{
GIOChannel *channel = NULL;
int i;
@@ -157,8 +157,8 @@ find_info_part (gchar *part_name, gchar *base)
}
-static char *
-process_indirect_map (char *page, gchar * file)
+static char
+*process_indirect_map (char *page, gchar * file)
{
char **lines;
char **ptr;
@@ -253,8 +253,8 @@ static GHashTable
return table;
}
-static char *
-get_value_after (char *source, char *required)
+static char
+*get_value_after (char *source, char *required)
{
char *ret, *ret_cp;
char *source_cp;
@@ -486,11 +486,14 @@ process_page (GtkTreeStore *tree, GHashTable *nodes2offsets,
}
d (if (iter) debug_print (DB_DEBUG, "Have a valid iter, storing for %s\n", node));
+
g_hash_table_insert (nodes2iters, g_strdup (node), iter);
debug_print (DB_DEBUG, "size: %i\n", g_hash_table_size (nodes2iters));
- tmp = g_strdup_printf ("%i",
- node2page (nodes2offsets, offsets2pages, node));
+ /*tmp = g_strdup_printf ("%i",
+ node2page (nodes2offsets, offsets2pages, node));*/
+ tmp = g_strdup (node);
+ tmp = g_strdelimit (tmp, " ", '_');
gtk_tree_store_set (tree, iter,
COLUMN_PAGE_NO, tmp,
COLUMN_PAGE_NAME, node,
@@ -785,7 +788,9 @@ resolve_frag_id (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
-1);
if (g_str_equal (page_name, *xref)) {
g_free (*xref);
- *xref = g_strdup (page_no);
+ *xref = g_strdup (page_name);
+ *xref = g_strdelimit (*xref, " ", '_');
+
g_free (page_name);
g_free (page_no);
return TRUE;
diff --git a/src/yelp-info.c b/src/yelp-info.c
new file mode 100644
index 00000000..2783ebc6
--- /dev/null
+++ b/src/yelp-info.c
@@ -0,0 +1,433 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007 Don Scorgie <dscorgie@svn.gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Don Scorgie <dscorgie@svn.gnome.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libxml/tree.h>
+
+#include "yelp-error.h"
+#include "yelp-info.h"
+#include "yelp-info-parser.h"
+#include "yelp-transform.h"
+#include "yelp-debug.h"
+
+#define STYLESHEET DATADIR"/yelp/xslt/info2html.xsl"
+
+#define YELP_INFO_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_INFO, YelpInfoPriv))
+
+typedef enum {
+ INFO_STATE_BLANK, /* Brand new, run transform as needed */
+ INFO_STATE_PARSING, /* Parsing/transforming document, please wait */
+ INFO_STATE_PARSED, /* All done, if we ain't got it, it ain't here */
+ INFO_STATE_STOP /* Stop everything now, object to be disposed */
+} InfoState;
+
+struct _YelpInfoPriv {
+ gchar *filename;
+ InfoState state;
+
+ GMutex *mutex;
+ GThread *thread;
+
+ xmlDocPtr xmldoc;
+ GtkTreeModel *sections;
+
+ gboolean process_running;
+ gboolean transform_running;
+
+ YelpTransform *transform;
+};
+
+
+static void info_class_init (YelpInfoClass *klass);
+static void info_init (YelpInfo *info);
+static void info_try_dispose (GObject *object);
+static void info_dispose (GObject *object);
+
+/* YelpDocument */
+static void info_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+
+/* YelpTransform */
+static void transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpInfo *info);
+static void transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpInfo *info);
+static void transform_final_func (YelpTransform *transform,
+ YelpInfo *info);
+static gpointer info_get_sections (YelpDocument *document);
+
+/* Threaded */
+static void info_process (YelpInfo *info);
+
+static YelpDocumentClass *parent_class;
+
+GType
+yelp_info_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpInfoClass),
+ NULL, NULL,
+ (GClassInitFunc) info_class_init,
+ NULL, NULL,
+ sizeof (YelpInfo),
+ 0,
+ (GInstanceInitFunc) info_init,
+ };
+ type = g_type_register_static (YELP_TYPE_DOCUMENT,
+ "YelpInfo",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+info_class_init (YelpInfoClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = info_try_dispose;
+
+ document_class->request = info_request;
+ document_class->cancel = NULL;
+ document_class->get_sections = info_get_sections;
+
+ g_type_class_add_private (klass, sizeof (YelpInfoPriv));
+}
+
+static void
+info_init (YelpInfo *info)
+{
+ YelpInfoPriv *priv;
+
+ priv = info->priv = YELP_INFO_GET_PRIVATE (info);
+
+ priv->state = INFO_STATE_BLANK;
+
+ priv->xmldoc = NULL;
+
+ priv->mutex = g_mutex_new ();
+}
+
+static void
+info_try_dispose (GObject *object)
+{
+ YelpInfoPriv *priv;
+
+ g_assert (object != NULL && YELP_IS_INFO (object));
+ priv = YELP_INFO (object)->priv;
+
+ g_mutex_lock (priv->mutex);
+ if (priv->process_running || priv->transform_running) {
+ priv->state = INFO_STATE_STOP;
+ g_idle_add ((GSourceFunc) info_try_dispose, object);
+ g_mutex_unlock (priv->mutex);
+ } else {
+ g_mutex_unlock (priv->mutex);
+ info_dispose (object);
+ }
+}
+
+static void
+info_dispose (GObject *object)
+{
+ YelpInfo *info = YELP_INFO (object);
+
+ g_free (info->priv->filename);
+
+ if (info->priv->xmldoc)
+ xmlFreeDoc (info->priv->xmldoc);
+
+ g_mutex_free (info->priv->mutex);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_info_new (gchar *filename)
+{
+ YelpInfo *info;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ info = (YelpInfo *) g_object_new (YELP_TYPE_INFO, NULL);
+ info->priv->filename = g_strdup (filename);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " filename = \"%s\"\n", filename);
+
+ yelp_document_add_page_id (YELP_DOCUMENT (info), "x-yelp-index", "index");
+
+ return (YelpDocument *) info;
+}
+
+
+/******************************************************************************/
+/** YelpDocument **************************************************************/
+
+static void
+info_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpInfo *info;
+ YelpInfoPriv *priv;
+ YelpError *error;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " req_id = %i\n", req_id);
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+
+ g_assert (document != NULL && YELP_IS_INFO (document));
+
+ if (handled)
+ return;
+
+ info = YELP_INFO (document);
+ priv = info->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ switch (priv->state) {
+ case INFO_STATE_BLANK:
+ priv->state = INFO_STATE_PARSING;
+ priv->process_running = TRUE;
+ priv->thread = g_thread_create ((GThreadFunc) info_process, info, FALSE, NULL);
+ break;
+ case INFO_STATE_PARSING:
+ break;
+ case INFO_STATE_PARSED:
+ case INFO_STATE_STOP:
+ error = yelp_error_new (_("Page not found"),
+ _("The page %s was not found in the document %s."),
+ page_id, priv->filename);
+ yelp_document_error_request (document, req_id, error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpInfo *info)
+{
+ YelpInfoPriv *priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (info != NULL && YELP_IS_INFO (info));
+
+ priv = info->priv;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == INFO_STATE_STOP) {
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ g_free (func_data);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_error_free ((YelpError *) func_data);
+ break;
+ case YELP_TRANSFORM_FINAL:
+ break;
+ }
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ return;
+ }
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ transform_page_func (transform, (gchar *) func_data, info);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_document_error_pending (YELP_DOCUMENT (info), (YelpError *) func_data);
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ break;
+ case YELP_TRANSFORM_FINAL:
+ transform_final_func (transform, info);
+ break;
+ }
+}
+
+static void
+transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpInfo *info)
+{
+ YelpInfoPriv *priv;
+ gchar *content;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = info->priv;
+ g_mutex_lock (priv->mutex);
+
+ content = yelp_transform_eat_chunk (transform, page_id);
+
+ yelp_document_add_page (YELP_DOCUMENT (info), page_id, content);
+
+ g_free (page_id);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+static void
+transform_final_func (YelpTransform *transform, YelpInfo *info)
+{
+ YelpError *error;
+ YelpInfoPriv *priv = info->priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_mutex_lock (priv->mutex);
+
+ error = yelp_error_new (_("Page not found"),
+ _("The requested page was not found in the document %s."),
+ priv->filename);
+ yelp_document_error_pending (YELP_DOCUMENT (info), error);
+
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+
+ if (priv->xmldoc)
+ xmlFreeDoc (priv->xmldoc);
+ priv->xmldoc = NULL;
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** Threaded ******************************************************************/
+
+static void
+info_process (YelpInfo *info)
+{
+ YelpInfoPriv *priv;
+ YelpError *error = NULL;
+ YelpDocument *document;
+ GtkTreeModel *model;
+
+ gint params_i = 0;
+ gint params_max = 10;
+ gchar **params = NULL;
+
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (info != NULL && YELP_IS_INFO (info));
+ g_object_ref (info);
+ priv = info->priv;
+ document = YELP_DOCUMENT (info);
+
+ if (!g_file_test (priv->filename, G_FILE_TEST_IS_REGULAR)) {
+ error = yelp_error_new (_("File not found"),
+ _("The file ‘%s’ does not exist."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ priv->sections = (GtkTreeModel *) yelp_info_parser_parse_file (priv->filename);
+ if (!model) {
+ /* TODO: Handle errors - exit out somehow */
+ }
+
+ priv->xmldoc = yelp_info_parser_parse_tree ((GtkTreeStore *) priv->sections);
+
+ if (priv->xmldoc == NULL) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because it is"
+ " not a well-formed info page."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ }
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == INFO_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+
+ priv->transform = yelp_transform_new (STYLESHEET,
+ (YelpTransformFunc) transform_func,
+ info);
+ priv->transform_running = TRUE;
+
+ params = g_new0 (gchar *, params_max);
+ yelp_settings_params (&params, &params_i, &params_max);
+
+ params[params_i] = NULL;
+
+
+ yelp_transform_start (priv->transform,
+ priv->xmldoc,
+ params);
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ priv->process_running = FALSE;
+ g_object_unref (info);
+}
+
+static gpointer
+info_get_sections (YelpDocument *document)
+{
+ YelpInfo *info = (YelpInfo *) document;
+
+ return (gpointer) (info->priv->sections);
+}
diff --git a/src/yelp-info.h b/src/yelp-info.h
new file mode 100644
index 00000000..d592dd72
--- /dev/null
+++ b/src/yelp-info.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007 Don Scorgie <dscorgie@svn.gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Don Scorgie <dscorgie@svn.gnome.org>
+ */
+
+#ifndef __YELP_INFO_H__
+#define __YELP_INFO_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_INFO (yelp_info_get_type ())
+#define YELP_INFO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_INFO, YelpInfo))
+#define YELP_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_INFO, YelpInfoClass))
+#define YELP_IS_INFO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_INFO))
+#define YELP_IS_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_INFO))
+#define YELP_INFO_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_INFO, YelpInfoClass))
+
+typedef struct _YelpInfo YelpInfo;
+typedef struct _YelpInfoClass YelpInfoClass;
+typedef struct _YelpInfoPriv YelpInfoPriv;
+
+struct _YelpInfo {
+ YelpDocument parent;
+ YelpInfoPriv *priv;
+};
+
+struct _YelpInfoClass {
+ YelpDocumentClass parent_class;
+};
+
+GType yelp_info_get_type (void);
+YelpDocument * yelp_info_new (gchar *uri);
+
+#endif /* __YELP_INFO_H__ */
diff --git a/src/yelp-io-channel.c b/src/yelp-io-channel.c
index 85f26d60..16c57509 100644
--- a/src/yelp-io-channel.c
+++ b/src/yelp-io-channel.c
@@ -103,7 +103,7 @@ yelp_io_channel_new_file (gchar *file,
if (!channel) {
if (error) {
- g_set_error (error, YELP_ERROR, YELP_ERROR_IO,
+ g_set_error (error, YELP_GERROR, YELP_GERROR_IO,
_("The file ‘%s’ could not be read and decoded. "
"The file may be compressed in an unsupported "
"format."),
diff --git a/src/yelp-main.c b/src/yelp-main.c
index d4a1dd11..66be4baa 100644
--- a/src/yelp-main.c
+++ b/src/yelp-main.c
@@ -268,7 +268,7 @@ slowly_and_stupidly_obtain_timestamp (Display *xdisplay)
0,
CopyFromParent,
CopyFromParent,
- (Visual *)CopyFromParent,
+ CopyFromParent,
CWOverrideRedirect | CWEventMask,
&attrs);
@@ -294,7 +294,7 @@ slowly_and_stupidly_obtain_timestamp (Display *xdisplay)
return event.xproperty.time;
}
-static DBusGProxy *
+DBusGProxy *
main_dbus_get_proxy (void)
{
if (!connection)
@@ -306,7 +306,7 @@ main_dbus_get_proxy (void)
"org.gnome.YelpService");
}
-static gboolean
+gboolean
main_is_running (void)
{
DBusGProxy *proxy = NULL;
diff --git a/src/yelp-man-pager.c b/src/yelp-man-pager.c
index 150bd7ae..a7d7ba71 100644
--- a/src/yelp-man-pager.c
+++ b/src/yelp-man-pager.c
@@ -228,7 +228,7 @@ man_pager_parse (YelpPager *pager)
GError *error = NULL;
gint i;
- g_return_val_if_fail (YELP_IS_MAN_PAGER (pager), NULL);
+ g_return_val_if_fail (YELP_IS_MAN_PAGER (pager), FALSE);
doc_info = yelp_pager_get_doc_info (pager);
filename = yelp_doc_info_get_filename (doc_info);
diff --git a/src/yelp-man-parser.c b/src/yelp-man-parser.c
index 0b7e97cd..edba95c5 100644
--- a/src/yelp-man-parser.c
+++ b/src/yelp-man-parser.c
@@ -26,15 +26,12 @@
#include <glib.h>
#include <glib/gi18n.h>
-#include <glib/gprintf.h>
#include <libxml/tree.h>
#include <string.h>
+#include "yelp-debug.h"
#include "yelp-io-channel.h"
#include "yelp-man-parser.h"
-#include "yelp-utils.h"
-
-#define d(x)
#define PARSER_CUR (g_utf8_get_char (parser->cur) != '\0' \
&& (parser->cur - parser->buffer < parser->length))
@@ -172,34 +169,6 @@ yelp_man_parser_parse_file (YelpManParser *parser,
return parser->doc;
}
-xmlDocPtr
-yelp_man_parser_parse_doc (YelpManParser *parser,
- YelpDocInfo *doc_info)
-{
- gchar *file;
- gchar *encoding = NULL;
- xmlDocPtr doc = NULL;
-
- g_return_val_if_fail (parser != NULL, NULL);
- g_return_val_if_fail (doc_info != NULL, NULL);
- g_return_val_if_fail (yelp_doc_info_get_type (doc_info) != YELP_DOC_TYPE_MAN, NULL);
-
- file = yelp_doc_info_get_filename (doc_info);
-
- if (!file)
- return NULL;
-
- encoding = (gchar *)g_getenv("MAN_ENCODING");
- if (encoding == NULL)
- encoding = "ISO-8859-1";
-
- doc = yelp_man_parser_parse_file (parser, file, encoding);
-
- g_free (file);
-
- return doc;
-}
-
void
yelp_man_parser_free (YelpManParser *parser)
{
@@ -605,7 +574,7 @@ macro_url_handler (YelpManParser *parser, gchar *macro, GSList *args)
tmpNode = parser_stack_pop_node (parser, "UR");
if (tmpNode == NULL)
- d (g_warning ("Found unexpected tag: '%s'\n", macro));
+ debug_print (DB_WARN, "Found unexpected tag: '%s'\n", macro);
else
parser->ins = tmpNode->parent;
} else
@@ -702,7 +671,7 @@ macro_mandoc_list_handler (YelpManParser *parser, gchar *macro, GSList *args)
tmpNode = parser_stack_pop_node (parser, "Bl");
if (tmpNode == NULL)
- d (g_warning ("Found unexpected tag: '%s'\n", macro));
+ debug_print (DB_WARN, "Found unexpected tag: '%s'\n", macro);
else
parser->ins = tmpNode->parent;
}
@@ -721,7 +690,7 @@ macro_verbatim_handler (YelpManParser *parser, gchar *macro, GSList *args)
tmpNode = parser_stack_pop_node (parser, "Verbatim");
if (tmpNode == NULL)
- d (g_warning ("Found unexpected tag: '%s'\n", macro));
+ debug_print (DB_WARN, "Found unexpected tag: '%s'\n", macro);
else
parser->ins = tmpNode->parent;
}
@@ -1266,7 +1235,7 @@ get_argument:
}
else if (g_str_equal (str, "TE")) {
/* We should only see this from within parser_parse_table */
- d (g_warning ("Found unexpected tag: '%s'\n", str));
+ debug_print (DB_WARN, "Found unexpected tag: '%s'\n", str);
g_free (str);
}
/* "ie" and "if" are conditional macros in groff
@@ -1451,7 +1420,7 @@ parser_append_given_text_handle_escapes (YelpManParser *parser, gchar *text, gbo
if (g_str_equal (str, "fI") || g_str_equal (str, "fB"))
parser->ins = parser_append_node (parser, str);
else if (!g_str_equal (str, "fR") && !g_str_equal (str, "fP"))
- d (g_warning ("No rule matching the tag '%s'\n", str));
+ debug_print (DB_WARN, "No rule matching the tag '%s'\n", str);
g_free (str);
anc = ptr;
@@ -1798,7 +1767,7 @@ parser_parse_table (YelpManParser *parser)
if (*(parser->buffer + 1) == 'T'
&& *(parser->buffer + 2) == 'E') {
if (parser_stack_pop_node (parser, "TABLE") == NULL)
- d (g_warning ("Found unexpected tag: 'TE'\n"));
+ debug_print (DB_WARN, "Found unexpected tag: 'TE'\n");
else {
parser->ins = table_start;
diff --git a/src/yelp-man-parser.h b/src/yelp-man-parser.h
index 26553e0a..26976d2a 100644
--- a/src/yelp-man-parser.h
+++ b/src/yelp-man-parser.h
@@ -26,16 +26,12 @@
#include <glib.h>
#include <libxml/tree.h>
-#include "yelp-utils.h"
-
typedef struct _YelpManParser YelpManParser;
YelpManParser * yelp_man_parser_new (void);
xmlDocPtr yelp_man_parser_parse_file (YelpManParser *parser,
gchar *file,
const gchar *encoding);
-xmlDocPtr yelp_man_parser_parse_doc (YelpManParser *parser,
- YelpDocInfo *doc);
void yelp_man_parser_free (YelpManParser *parser);
#endif /* __YELP_MAN_PARSER_H__ */
diff --git a/src/yelp-man.c b/src/yelp-man.c
new file mode 100644
index 00000000..5d40f895
--- /dev/null
+++ b/src/yelp-man.c
@@ -0,0 +1,490 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libxml/tree.h>
+
+#include "yelp-error.h"
+#include "yelp-man.h"
+#include "yelp-man-parser.h"
+#include "yelp-transform.h"
+#include "yelp-debug.h"
+
+#define STYLESHEET DATADIR"/yelp/xslt/man2html.xsl"
+
+#define YELP_MAN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_MAN, YelpManPriv))
+
+typedef enum {
+ MAN_STATE_BLANK, /* Brand new, run transform as needed */
+ MAN_STATE_PARSING, /* Parsing/transforming document, please wait */
+ MAN_STATE_PARSED, /* All done, if we ain't got it, it ain't here */
+ MAN_STATE_STOP /* Stop everything now, object to be disposed */
+} ManState;
+
+struct _YelpManPriv {
+ gchar *filename;
+ ManState state;
+
+ GMutex *mutex;
+ GThread *thread;
+
+ xmlDocPtr xmldoc;
+
+ gboolean process_running;
+ gboolean transform_running;
+
+ YelpTransform *transform;
+};
+
+typedef struct _YelpLangEncodings YelpLangEncodings;
+struct _YelpLangEncodings {
+ gchar *language;
+ gchar *encoding;
+};
+/* http://www.w3.org/International/O-charset-lang.html */
+static const YelpLangEncodings langmap[] = {
+ { "C", "ISO-8859-1" },
+ { "af", "ISO-8859-1" },
+ { "ar", "ISO-8859-6" },
+ { "bg", "ISO-8859-5" },
+ { "be", "ISO-8859-5" },
+ { "ca", "ISO-8859-1" },
+ { "cs", "ISO-8859-2" },
+ { "da", "ISO-8859-1" },
+ { "de", "ISO-8859-1" },
+ { "el", "ISO-8859-7" },
+ { "en", "ISO-8859-1" },
+ { "eo", "ISO-8859-3" },
+ { "es", "ISO-8859-1" },
+ { "et", "ISO-8859-15" },
+ { "eu", "ISO-8859-1" },
+ { "fi", "ISO-8859-1" },
+ { "fo", "ISO-8859-1" },
+ { "fr", "ISO-8859-1" },
+ { "ga", "ISO-8859-1" },
+ { "gd", "ISO-8859-1" },
+ { "gl", "ISO-8859-1" },
+ { "hu", "ISO-8859-2" },
+ { "id", "ISO-8859-1" }, /* is this right */
+ { "mt", "ISO-8859-3" },
+ { "is", "ISO-8859-1" },
+ { "it", "ISO-8859-1" },
+ { "iw", "ISO-8859-8" },
+ { "ja", "EUC-JP" },
+ { "ko", "EUC-KR" },
+ { "lt", "ISO-8859-13" },
+ { "lv", "ISO-8859-13" },
+ { "mk", "ISO-8859-5" },
+ { "mt", "ISO-8859-3" },
+ { "no", "ISO-8859-1" },
+ { "pl", "ISO-8859-2" },
+ { "pt_BR", "ISO-8859-1" },
+ { "ro", "ISO-8859-2" },
+ { "ru", "KOI8-R" },
+ { "sl", "ISO-8859-2" },
+ { "sr", "ISO-8859-2" }, /* Latin, not cyrillic */
+ { "sk", "ISO-8859-2" },
+ { "sv", "ISO-8859-1" },
+ { "tr", "ISO-8859-9" },
+ { "uk", "ISO-8859-5" },
+ { "zh_CN", "BIG5" },
+ { "zh_TW", "BIG5" },
+ { NULL, NULL },
+};
+
+static void man_class_init (YelpManClass *klass);
+static void man_init (YelpMan *man);
+static void man_try_dispose (GObject *object);
+static void man_dispose (GObject *object);
+
+/* YelpDocument */
+static void man_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+
+/* YelpTransform */
+static void transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpMan *man);
+static void transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpMan *man);
+static void transform_final_func (YelpTransform *transform,
+ YelpMan *man);
+
+/* Threaded */
+static void man_process (YelpMan *man);
+
+static YelpDocumentClass *parent_class;
+
+GType
+yelp_man_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpManClass),
+ NULL, NULL,
+ (GClassInitFunc) man_class_init,
+ NULL, NULL,
+ sizeof (YelpMan),
+ 0,
+ (GInstanceInitFunc) man_init,
+ };
+ type = g_type_register_static (YELP_TYPE_DOCUMENT,
+ "YelpMan",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+man_class_init (YelpManClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = man_try_dispose;
+
+ document_class->request = man_request;
+ document_class->cancel = NULL;
+
+ g_type_class_add_private (klass, sizeof (YelpManPriv));
+}
+
+static void
+man_init (YelpMan *man)
+{
+ YelpManPriv *priv;
+
+ priv = man->priv = YELP_MAN_GET_PRIVATE (man);
+
+ priv->state = MAN_STATE_BLANK;
+
+ priv->mutex = g_mutex_new ();
+}
+
+static void
+man_try_dispose (GObject *object)
+{
+ YelpManPriv *priv;
+
+ g_assert (object != NULL && YELP_IS_MAN (object));
+ priv = YELP_MAN (object)->priv;
+
+ g_mutex_lock (priv->mutex);
+ if (priv->process_running || priv->transform_running) {
+ priv->state = MAN_STATE_STOP;
+ g_idle_add ((GSourceFunc) man_try_dispose, object);
+ g_mutex_unlock (priv->mutex);
+ } else {
+ g_mutex_unlock (priv->mutex);
+ man_dispose (object);
+ }
+}
+
+static void
+man_dispose (GObject *object)
+{
+ YelpMan *man = YELP_MAN (object);
+
+ g_free (man->priv->filename);
+
+ if (man->priv->xmldoc)
+ xmlFreeDoc (man->priv->xmldoc);
+
+ g_mutex_free (man->priv->mutex);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_man_new (gchar *filename)
+{
+ YelpMan *man;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ man = (YelpMan *) g_object_new (YELP_TYPE_MAN, NULL);
+ man->priv->filename = g_strdup (filename);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " filename = \"%s\"\n", filename);
+
+ yelp_document_add_page_id (YELP_DOCUMENT (man), "x-yelp-index", "index");
+
+ return (YelpDocument *) man;
+}
+
+
+/******************************************************************************/
+/** YelpDocument **************************************************************/
+
+static void
+man_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpMan *man;
+ YelpManPriv *priv;
+ YelpError *error;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " req_id = %i\n", req_id);
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+
+ g_assert (document != NULL && YELP_IS_MAN (document));
+
+ if (handled)
+ return;
+
+ man = YELP_MAN (document);
+ priv = man->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ switch (priv->state) {
+ case MAN_STATE_BLANK:
+ priv->state = MAN_STATE_PARSING;
+ priv->process_running = TRUE;
+ priv->thread = g_thread_create ((GThreadFunc) man_process, man, FALSE, NULL);
+ break;
+ case MAN_STATE_PARSING:
+ break;
+ case MAN_STATE_PARSED:
+ case MAN_STATE_STOP:
+ error = yelp_error_new (_("Page not found"),
+ _("The page %s was not found in the document %s."),
+ page_id, priv->filename);
+ yelp_document_error_request (document, req_id, error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpMan *man)
+{
+ YelpManPriv *priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (man != NULL && YELP_IS_MAN (man));
+
+ priv = man->priv;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == MAN_STATE_STOP) {
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ g_free (func_data);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_error_free ((YelpError *) func_data);
+ break;
+ case YELP_TRANSFORM_FINAL:
+ break;
+ }
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ return;
+ }
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ transform_page_func (transform, (gchar *) func_data, man);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_document_error_pending (YELP_DOCUMENT (man), (YelpError *) func_data);
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ break;
+ case YELP_TRANSFORM_FINAL:
+ transform_final_func (transform, man);
+ break;
+ }
+}
+
+static void
+transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpMan *man)
+{
+ YelpManPriv *priv;
+ gchar *content;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = man->priv;
+ g_mutex_lock (priv->mutex);
+
+ content = yelp_transform_eat_chunk (transform, page_id);
+
+ yelp_document_add_page (YELP_DOCUMENT (man), page_id, content);
+
+ g_free (page_id);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+static void
+transform_final_func (YelpTransform *transform, YelpMan *man)
+{
+ YelpError *error;
+ YelpManPriv *priv = man->priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_mutex_lock (priv->mutex);
+
+ error = yelp_error_new (_("Page not found"),
+ _("The requested page was not found in the document %s."),
+ priv->filename);
+ yelp_document_error_pending (YELP_DOCUMENT (man), error);
+
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+
+ if (priv->xmldoc)
+ xmlFreeDoc (priv->xmldoc);
+ priv->xmldoc = NULL;
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** Threaded ******************************************************************/
+
+static void
+man_process (YelpMan *man)
+{
+ YelpManPriv *priv;
+ const gchar *language;
+ const gchar *encoding;
+ YelpManParser *parser;
+ YelpError *error = NULL;
+ YelpDocument *document;
+ gint i;
+
+ gint params_i = 0;
+ gint params_max = 10;
+ gchar **params = NULL;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (man != NULL && YELP_IS_MAN (man));
+ g_object_ref (man);
+ priv = man->priv;
+ document = YELP_DOCUMENT (man);
+
+ if (!g_file_test (priv->filename, G_FILE_TEST_IS_REGULAR)) {
+ error = yelp_error_new (_("File not found"),
+ _("The file ‘%s’ does not exist."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ /* FIXME: get the language */
+ language = "C";
+
+ /* default encoding if the language doesn't match below */
+ encoding = g_getenv("MAN_ENCODING");
+ if (encoding == NULL)
+ encoding = "ISO-8859-1";
+
+ if (language != NULL) {
+ for (i = 0; langmap[i].language != NULL; i++) {
+ if (g_str_equal (language, langmap[i].language)) {
+ encoding = langmap[i].encoding;
+ break;
+ }
+ }
+ }
+
+ parser = yelp_man_parser_new ();
+ priv->xmldoc = yelp_man_parser_parse_file (parser, priv->filename, encoding);
+ yelp_man_parser_free (parser);
+
+ if (priv->xmldoc == NULL) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because it is"
+ " not a well-formed man page."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ }
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == MAN_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+
+ priv->transform = yelp_transform_new (STYLESHEET,
+ (YelpTransformFunc) transform_func,
+ man);
+ priv->transform_running = TRUE;
+
+ params = g_new0 (gchar *, params_max);
+ yelp_settings_params (&params, &params_i, &params_max);
+
+ params[params_i] = NULL;
+
+ yelp_transform_start (priv->transform,
+ priv->xmldoc,
+ params);
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ priv->process_running = FALSE;
+ g_object_unref (man);
+}
diff --git a/src/yelp-man.h b/src/yelp-man.h
new file mode 100644
index 00000000..844c44ab
--- /dev/null
+++ b/src/yelp-man.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_MAN_H__
+#define __YELP_MAN_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_MAN (yelp_man_get_type ())
+#define YELP_MAN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_MAN, YelpMan))
+#define YELP_MAN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_MAN, YelpManClass))
+#define YELP_IS_MAN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_MAN))
+#define YELP_IS_MAN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_MAN))
+#define YELP_MAN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_MAN, YelpManClass))
+
+typedef struct _YelpMan YelpMan;
+typedef struct _YelpManClass YelpManClass;
+typedef struct _YelpManPriv YelpManPriv;
+
+struct _YelpMan {
+ YelpDocument parent;
+ YelpManPriv *priv;
+};
+
+struct _YelpManClass {
+ YelpDocumentClass parent_class;
+};
+
+GType yelp_man_get_type (void);
+YelpDocument * yelp_man_new (gchar *uri);
+
+#endif /* __YELP_MAN_H__ */
diff --git a/src/yelp-page.c b/src/yelp-page.c
new file mode 100644
index 00000000..c0ad894e
--- /dev/null
+++ b/src/yelp-page.c
@@ -0,0 +1,164 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2006 Brent Smith <gnome@nextreality.net>
+ * Copyright (C) 2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Brent Smith <gnome@nextreality.net>
+ * Shaun McCance <shaunm@gnome.org>
+ */
+
+#include <glib.h>
+#include <string.h>
+
+#include "yelp-page.h"
+
+static GIOStatus page_read_string (YelpPage *page,
+ gchar *buffer,
+ gsize count,
+ gsize *bytes_read,
+ YelpError **error);
+static GIOStatus page_read_file (YelpPage *page,
+ gchar *buffer,
+ gsize count,
+ gsize *bytes_read,
+ YelpError **error);
+
+YelpPage *
+yelp_page_new_string (YelpDocument *document,
+ gchar *id,
+ const gchar *content,
+ YelpPageMime mime)
+{
+ YelpPage *page;
+
+ page = g_slice_new0 (YelpPage);
+
+ page->mime = mime;
+
+ if (document)
+ page->document = g_object_ref (document);
+ page->source = YELP_PAGE_SOURCE_STRING;
+ page->id = g_strdup (id);
+
+ page->content = (gchar *) content;
+ page->content_len = strlen (content);
+
+ return page;
+}
+
+gsize
+yelp_page_get_length (YelpPage *page)
+{
+ g_return_val_if_fail (page != NULL, 0);
+
+ return page->content_len;
+}
+
+GIOStatus
+yelp_page_read (YelpPage *page,
+ gchar *buffer,
+ gsize count,
+ gsize *bytes_read,
+ YelpError **error)
+{
+ /* FIXME: set error */
+ g_return_val_if_fail (page != NULL, G_IO_STATUS_ERROR);
+
+ if (page->source == YELP_PAGE_SOURCE_STRING)
+ return page_read_string (page, buffer, count, bytes_read, error);
+ else
+ return page_read_file (page, buffer, count, bytes_read, error);
+}
+
+static GIOStatus
+page_read_string (YelpPage *page,
+ gchar *buffer,
+ gsize count,
+ gsize *bytes_read,
+ YelpError **error)
+{
+ gint real_count = 0;
+ g_return_val_if_fail (page != NULL, G_IO_STATUS_ERROR);
+
+ if (count < 0) {
+ real_count = (page->content_len - page->content_offset) + 1;
+ } else {
+ real_count = count;
+ }
+
+
+ if (page->content_offset == page->content_len) {
+ /* FIXME: set the error */
+ return G_IO_STATUS_EOF;
+ }
+ else if (page->content_offset > page->content_len) {
+ /* FIXME: set the error */
+ return G_IO_STATUS_ERROR;
+ }
+ else if (page->content_offset + real_count <= page->content_len) {
+ strncpy (buffer, page->content + page->content_offset, count);
+ page->content_offset += count;
+ *bytes_read = count;
+ return G_IO_STATUS_NORMAL;
+ }
+ else {
+ strcpy (buffer, page->content + page->content_offset);
+ *bytes_read = strlen (buffer);
+ page->content_offset += *bytes_read;
+ return G_IO_STATUS_NORMAL;
+ }
+}
+
+static GIOStatus
+page_read_file (YelpPage *page,
+ gchar *buffer,
+ gsize count,
+ gsize *bytes_read,
+ YelpError **error)
+{
+ g_return_val_if_fail (page != NULL, G_IO_STATUS_ERROR);
+ /* FIXME: just use yelp-io-channel? */
+ return G_IO_STATUS_ERROR;
+}
+
+void
+yelp_page_free (YelpPage *page)
+{
+ g_return_if_fail (page != NULL);
+
+ if (page->document) {
+ yelp_document_release_page (page->document, page);
+ g_object_unref (page->document);
+ }
+
+ if (page->title)
+ g_free (page->title);
+
+ if (page->id)
+ g_free (page->id);
+ if (page->prev_id)
+ g_free (page->prev_id);
+ if (page->next_id)
+ g_free (page->next_id);
+ if (page->up_id)
+ g_free (page->up_id);
+ if (page->root_id)
+ g_free (page->root_id);
+
+ g_slice_free (YelpPage, page);
+}
diff --git a/src/yelp-page.h b/src/yelp-page.h
new file mode 100644
index 00000000..30a45bf7
--- /dev/null
+++ b/src/yelp-page.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2006 Brent Smith <gnome@nextreality.net>
+ * Copyright (C) 2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Brent Smith <gnome@nextreality.net>
+ * Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_PAGE_H__
+#define __YELP_PAGE_H__
+
+#include <glib.h>
+
+#include "yelp-error.h"
+
+G_BEGIN_DECLS
+
+typedef enum {
+ YELP_PAGE_MIME_HTML,
+ YELP_PAGE_MIME_XHTML
+} YelpPageMime;
+
+typedef enum {
+ YELP_PAGE_SOURCE_STRING,
+ YELP_PAGE_SOURCE_FILE
+} YelpPageSource;
+
+typedef struct _YelpPage YelpPage;
+
+/* This needs to be right here to compile. */
+#include "yelp-document.h"
+
+struct _YelpPage {
+ YelpDocument *document;
+ YelpPageSource source;
+ YelpPageMime mime;
+
+ gchar *title;
+
+ /* Do not free content. The string is owned by the YelpDocument,
+ * and it does some internal reference counting to make sure it's
+ * only reed when it's no longer referenced. These strings are
+ * just too big to strdup all over the place.
+ */
+ gchar *content;
+ gsize content_len;
+ gsize content_offset;
+
+ gchar *id;
+ gchar *prev_id;
+ gchar *next_id;
+ gchar *up_id;
+ gchar *root_id;
+};
+
+YelpPage * yelp_page_new_string (YelpDocument *document,
+ gchar *id,
+ const gchar *content,
+ YelpPageMime mime);
+
+GIOStatus yelp_page_read (YelpPage *page,
+ gchar *buffer,
+ gsize count,
+ gsize *bytes_read,
+ YelpError **error);
+gsize yelp_page_get_length (YelpPage *page);
+
+void yelp_page_free (YelpPage *page);
+
+G_END_DECLS
+
+#endif
diff --git a/src/yelp-print.c b/src/yelp-print.c
index 42989b8f..7ce42c4a 100644
--- a/src/yelp-print.c
+++ b/src/yelp-print.c
@@ -159,7 +159,7 @@ print_present_config_dialog (YelpPrintInfo *info)
}
static gboolean
-print_jobs_run (void)
+print_jobs_run ()
{
YelpPrintInfo * info = current_jobs->data;
info->started = TRUE;
@@ -172,7 +172,7 @@ print_jobs_run (void)
}
static GtkPrintSettings *
-yelp_print_load_config_from_file (void)
+yelp_print_load_config_from_file ()
{
GtkPrintSettings *settings;
@@ -222,8 +222,8 @@ yelp_print_info_free (YelpPrintInfo *info)
}
-static YelpPrintInfo *
-yelp_print_get_print_info (void)
+YelpPrintInfo *
+yelp_print_get_print_info ()
{
YelpPrintInfo *info;
diff --git a/src/yelp-search-pager.c b/src/yelp-search-pager.c
index 77209f09..63aa8edc 100644
--- a/src/yelp-search-pager.c
+++ b/src/yelp-search-pager.c
@@ -1022,7 +1022,7 @@ sk_characters (void *empty, const xmlChar *ch,
}
}
-static void s_startElement(void *data,
+void s_startElement(void *data,
const xmlChar * name,
const xmlChar ** attrs)
{
@@ -1093,7 +1093,7 @@ static void s_startElement(void *data,
return;
}
-static void s_endElement(void * data,
+void s_endElement(void * data,
const xmlChar * name)
{
SearchContainer *c = (SearchContainer *) data;
@@ -1116,7 +1116,7 @@ static void s_endElement(void * data,
return;
}
-static void s_characters(void * data,
+void s_characters(void * data,
const xmlChar * ch,
int len)
{
@@ -1133,7 +1133,6 @@ static void s_characters(void * data,
if (c->html && c->search_status != SEARCH_DOC)
c->search_status = SEARCH_DOC;
if (c->search_status != NOT_SEARCHING) {
- gchar *location;
gchar *tmp = g_utf8_casefold ((gchar *) ch, len);
gint i = 0;
gchar *s_term = c->search_term[i];
@@ -1144,7 +1143,7 @@ static void s_characters(void * data,
continue;
}
- location = strstr (tmp, s_term);
+ gchar *location = strstr (tmp, s_term);
if (location) {
gchar before = *(location-1);
gchar after = *(location+strlen(s_term));
@@ -1197,7 +1196,7 @@ static void s_characters(void * data,
return;
}
-static void s_declEntity (void *data, const xmlChar *name, int type,
+void s_declEntity (void *data, const xmlChar *name, int type,
const xmlChar *pID, const xmlChar *sID,
xmlChar *content)
{
@@ -1211,8 +1210,7 @@ static void s_declEntity (void *data, const xmlChar *name, int type,
return;
}
-static xmlEntityPtr
-s_getEntity (void *data, const xmlChar *name)
+xmlEntityPtr s_getEntity (void *data, const xmlChar *name)
{
SearchContainer *c = (SearchContainer *) data;
xmlEntityPtr t = xmlGetPredefinedEntity(name);
@@ -1446,7 +1444,7 @@ slow_search_setup (YelpSearchPager *pager)
gint terms_number = 0;
gint required_no = 0;
- static xmlSAXHandler sk_sax_handler = { NULL, };
+ static xmlSAXHandler sk_sax_handler = { 0, };
xmlParserCtxtPtr parser;
if (langs && langs[0])
lang = (gchar *) langs[0];
@@ -1736,7 +1734,7 @@ slow_search_process (YelpSearchPager *pager)
}
}
-static gchar *
+gchar *
search_clean_snippet (gchar *snippet, gchar **terms)
{
/* This is probably what you want to change */
@@ -1830,7 +1828,7 @@ search_clean_snippet (gchar *snippet, gchar **terms)
return result;
}
-static void
+void
search_parse_result (YelpSearchPager *pager, SearchContainer *c)
{
xmlNode *child;
@@ -1864,7 +1862,7 @@ search_parse_result (YelpSearchPager *pager, SearchContainer *c)
xmlFreeDoc (snippet_doc);
}
-static void
+void
process_man_result (YelpSearchPager *pager, gchar *result, gchar **terms)
{
gchar ** split = g_strsplit (result, "\n", -1);
@@ -1989,7 +1987,7 @@ process_info_result (YelpSearchPager *pager, gchar *result, gchar **terms)
}
-static void
+void
search_process_man (YelpSearchPager *pager, gchar **terms)
{
gchar *command;
@@ -2017,7 +2015,7 @@ search_process_man (YelpSearchPager *pager, gchar **terms)
return;
}
-static void
+void
search_process_info (YelpSearchPager *pager, gchar **terms)
{
gchar *command;
diff --git a/src/yelp-search-parser.c b/src/yelp-search-parser.c
new file mode 100644
index 00000000..646f5d41
--- /dev/null
+++ b/src/yelp-search-parser.c
@@ -0,0 +1,1459 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007 Don Scorgie <Don@Scorgie.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlreader.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/tree.h>
+#include <libxslt/xslt.h>
+#include <libxslt/templates.h>
+#include <libxslt/transform.h>
+#include <libxslt/extensions.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/xsltutils.h>
+#include <rarian.h>
+
+#ifdef ENABLE_BEAGLE
+#include <beagle/beagle.h>
+#endif /* ENABLE_BEAGLE */
+
+#include "yelp-error.h"
+#include "yelp-settings.h"
+#include "yelp-search-parser.h"
+#include "yelp-utils.h"
+#include "yelp-debug.h"
+
+#define DESKTOP_ENTRY_GROUP "Desktop Entry"
+#define KDE_DESKTOP_ENTRY_GROUP "KDE Desktop Entry"
+
+#define YELP_NAMESPACE "http://www.gnome.org/yelp/ns"
+
+typedef gboolean (*ProcessFunction) (YelpSearchParser *parser);
+
+typedef struct _SearchContainer SearchContainer;
+
+#define ONLINE_URL "http://api.gnome.org/yelp/forums?query=%s"
+
+#define ONLINE_NAME N_("the GNOME Support Forums")
+
+enum {
+ NOT_SEARCHING = 0,
+ SEARCH_1,
+ SEARCH_CHILD,
+ SEARCH_DOC = 99
+};
+
+struct _SearchContainer {
+ gchar * current_subsection;
+ gchar * result_subsection;
+ gchar * doc_title;
+ gchar * base_path;
+ gchar * base_filename;
+ gchar * snippet;
+ GSList * components;
+ GHashTable *entities;
+ gchar ** search_term;
+ gint required_words;
+ gint * dup_of;
+ gboolean * found_terms;
+ gboolean * stop_word;
+ gfloat * score_per_word;
+ gchar * top_element;
+ gint search_status;
+ gchar * elem_type;
+ GSList * elem_stack;
+ gfloat score;
+ gfloat snippet_score;
+ gboolean html;
+ gchar * sect_name;
+ gboolean grab_text;
+ gchar * default_snippet;
+};
+
+typedef struct {
+ YelpSearchParser *parser;
+ gint required_no;
+ gint terms_number;
+ gboolean *stop_list;
+ gint *dup_list;
+ gchar **terms_list;
+ SearchContainer *container;
+} SearchDocData;
+
+
+struct _YelpSearchParser {
+ gchar *search_terms;
+ xmlDocPtr search_doc;
+ xmlNodePtr root;
+
+ GPtrArray *hits;
+ int snippet_request_count;
+ GSList * pending_searches;
+
+ guint search_process_id;
+ guint slow_search_setup_process_id;
+ guint slow_search_process_id;
+
+ gboolean finished;
+
+};
+
+
+static gboolean search_parser_process_idle (YelpSearchParser *parser);
+
+static void s_startElement (void *data,
+ const xmlChar *name,
+ const xmlChar **attrs);
+static void s_endElement (void *data,
+ const xmlChar *name);
+static void s_characters (void *data,
+ const xmlChar *ch,
+ int len);
+static void s_declEntity (void *data,
+ const xmlChar *name,
+ int type,
+ const xmlChar *pID,
+ const xmlChar *sID,
+ xmlChar *content);
+static xmlEntityPtr s_getEntity (void *data,
+ const xmlChar *name);
+static gboolean slow_search_setup (YelpSearchParser *parser);
+static gboolean slow_search_process (RrnReg *reg,
+ SearchDocData *data);
+static void search_parse_result (YelpSearchParser *parser,
+ SearchContainer *c);
+static gchar * search_clean_snippet (gchar *snippet,
+ gchar **terms);
+static void search_process_man (YelpSearchParser *parser,
+ gchar **terms);
+static void search_process_info (YelpSearchParser *parser,
+ gchar **terms);
+static void process_man_result (YelpSearchParser *parser,
+ gchar *result,
+ gchar **terms);
+void process_info_result (YelpSearchParser *parser,
+ gchar *result,
+ gchar **terms);
+gchar * string_append (gchar *current,
+ gchar *new,
+ gchar *suffix);
+static void search_free_container (SearchContainer *c);
+
+
+#ifdef ENABLE_BEAGLE
+static BeagleClient *beagle_client;
+#endif /* ENABLE_BEAGLE */
+
+YelpSearchParser *
+yelp_search_parser_new (void)
+{
+ YelpSearchParser *parser = g_new0 (YelpSearchParser, 1);
+
+ return parser;
+}
+
+void
+yelp_search_parser_free (YelpSearchParser *parser)
+{
+ g_free (parser);
+}
+
+static gboolean
+check_hex (char check)
+{
+ if (check >= '0' && check <= '9')
+ return TRUE;
+ if (check >= 'a' && check <= 'f')
+ return TRUE;
+ if (check >= 'A' && check <= 'F')
+ return TRUE;
+ return FALSE;
+}
+
+static int
+conv_hex (char conv)
+{
+ if (conv >= '0' && conv <= '9')
+ return conv - '0';
+ if (conv >= 'a' && conv <= 'f')
+ return conv - 'a' + 10;
+ if (conv >= 'A' && conv <= 'F')
+ return conv - 'A' + 10;
+ return 0;
+}
+
+static char *
+decode_uri (const char *uri)
+{
+ char *decoded = g_strdup (uri);
+ char *iterator;
+
+ for (iterator = decoded; *iterator; iterator ++) {
+ if (*iterator == '%' && check_hex (iterator[1]) && check_hex(iterator[2])) {
+ *iterator = conv_hex (iterator[1]) * 16 + conv_hex (iterator[2]);
+ memmove (iterator + 1, iterator + 3, strlen (iterator + 3));
+ }
+ }
+
+ return decoded;
+}
+
+xmlDocPtr
+yelp_search_parser_process (YelpSearchParser *parser, gchar *search_terms)
+{
+ debug_print (DB_FUNCTION, "entering\n");
+
+ parser->search_terms = decode_uri (search_terms);
+
+ parser->search_process_id =
+ g_idle_add_full (G_PRIORITY_LOW,
+ (GSourceFunc) search_parser_process_idle,
+ parser, NULL);
+
+ while (!parser->finished)
+ g_thread_yield ();
+ return parser->search_doc;
+}
+
+/******************************************************************************/
+static void
+check_finished (YelpSearchParser *parser)
+{
+ gchar *tmp;
+ gchar **split;
+ xmlNodePtr online = NULL;
+ gchar *check;
+ gchar *title;
+ gchar *text = NULL;
+ xmlXPathContextPtr results_xpath_ctx = NULL;
+ xmlXPathObjectPtr results_xpath = NULL;
+ gint number_of_results = 0;
+
+ results_xpath_ctx = xmlXPathNewContext(parser->search_doc);
+ results_xpath = xmlXPathEvalExpression(BAD_CAST "/search/result", results_xpath_ctx);
+ if (results_xpath && results_xpath->nodesetval && results_xpath->nodesetval->nodeNr) {
+ number_of_results = results_xpath->nodesetval->nodeNr;
+ } else {
+ number_of_results = 0;
+ }
+ xmlXPathFreeObject(results_xpath);
+ xmlXPathFreeContext(results_xpath_ctx);
+
+ if (number_of_results == 0) {
+ title = g_strdup_printf( _("No results for \"%s\""), parser->search_terms);
+ text = g_strdup(_("Try using different words to describe the problem "
+ "you're having or the topic you want help with."));
+ } else {
+ title = g_strdup_printf( _("Search results for \"%s\""), parser->search_terms);
+ }
+ xmlNewTextChild (parser->root, NULL, BAD_CAST "title", BAD_CAST title);
+
+ if (text) {
+ xmlNewTextChild (parser->root, NULL, BAD_CAST "text", BAD_CAST text);
+ g_free(text);
+ }
+
+ /* TRANSLATORS: Please don't do anything funny with the
+ * format arguement. It isn't really going through a printf
+ * The %s is used to indicate where the name of the site (linked)
+ * should be. This is done in the XSLT
+ */
+ tmp = g_strdup (_("Repeat the search online at %s"));
+ split = g_strsplit (tmp, "%s", 2);
+ check = g_strdup_printf (ONLINE_URL, parser->search_terms);
+
+ online = xmlNewTextChild (parser->root, NULL, BAD_CAST "online", BAD_CAST split[0]);
+ g_free (tmp);
+ xmlNewProp (online, BAD_CAST "name",
+ BAD_CAST ONLINE_NAME);
+ xmlNewProp (online, BAD_CAST "href",
+ BAD_CAST check);
+ g_free (check);
+ xmlNewTextChild (parser->root, NULL, BAD_CAST "online1", BAD_CAST split[1]);
+
+ parser->finished = TRUE;
+
+}
+
+#ifdef ENABLE_BEAGLE
+typedef struct
+{
+ YelpSearchParser *parser;
+ xmlNode *node;
+} SnippetLocation;
+
+static void snippet_closed (BeagleSnippetRequest *request,
+ SnippetLocation *snippet_location);
+static void snippet_response (BeagleSnippetRequest *request,
+ BeagleSnippetResponse *response,
+ SnippetLocation *snippet_location);
+static void snippet_error (BeagleSnippetRequest *request,
+ GError *error,
+ SnippetLocation *snippet_location);
+
+static void
+snippet_closed (BeagleSnippetRequest *request, SnippetLocation *snippet_location)
+{
+ YelpSearchParser *parser = snippet_location->parser;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ parser->snippet_request_count --;
+ check_finished (parser);
+
+ g_signal_handlers_disconnect_by_func (request,
+ G_CALLBACK (snippet_response),
+ snippet_location);
+ g_signal_handlers_disconnect_by_func (request,
+ G_CALLBACK (snippet_error),
+ snippet_location);
+ g_signal_handlers_disconnect_by_func (request,
+ G_CALLBACK (snippet_closed),
+ snippet_location);
+
+ g_free (snippet_location);
+ g_object_unref (request);
+}
+
+static void
+snippet_response (BeagleSnippetRequest *request, BeagleSnippetResponse *response, SnippetLocation *snippet_location)
+{
+ xmlDoc *snippet_doc;
+ xmlNode *node;
+ char *xmldoc;
+
+ const char *xml = beagle_snippet_response_get_snippet (response);
+
+ if (xml == NULL) {
+ debug_print (DB_DEBUG, "snippet_response empty\n");
+ return;
+ }
+ debug_print (DB_DEBUG, "snippet_response: %s\n", xml);
+
+ xmldoc = g_strdup_printf ("<snippet>%s</snippet>", xml);
+ snippet_doc = xmlParseDoc (BAD_CAST xmldoc);
+ g_free (xmldoc);
+ if (!snippet_doc)
+ return;
+ node = xmlDocGetRootElement (snippet_doc);
+ xmlUnlinkNode (node);
+ xmlAddChild (snippet_location->node, node);
+ xmlFreeDoc (snippet_doc);
+}
+
+static void
+snippet_error (BeagleSnippetRequest *request, GError *error, SnippetLocation *snippet_location)
+{
+ debug_print (DB_FUNCTION, "entering\n");
+}
+
+
+static void
+hits_added_cb (BeagleQuery *query, BeagleHitsAddedResponse *response, YelpSearchParser *parser)
+{
+ GSList *hits, *l;
+
+ debug_print (DB_FUNCTION, "hits_added\n");
+
+ hits = beagle_hits_added_response_get_hits (response);
+
+ for (l = hits; l; l = l->next) {
+ BeagleHit *hit = l->data;
+ beagle_hit_ref (hit);
+ debug_print (DB_DEBUG, "%f\n", beagle_hit_get_score (hit));
+ g_ptr_array_add (parser->hits, hit);
+ }
+}
+
+static gboolean
+check_lang (const char *lang) {
+ int i;
+ for (i = 0; langs[i]; i++) {
+ if (!strncmp (lang, langs[i], 2)) {
+ debug_print (DB_DEBUG, "%s preferred\n", lang);
+ return TRUE;
+ }
+ }
+ debug_print (DB_DEBUG, "%s not preferred\n", lang);
+ return FALSE;
+}
+
+static gint
+compare_hits (gconstpointer a,
+ gconstpointer b)
+{
+ BeagleHit **hita = (BeagleHit **) a;
+ BeagleHit **hitb = (BeagleHit **) b;
+ const char *langa, *langb;
+ gboolean a_preferred = TRUE, b_preferred = TRUE;
+
+ if (beagle_hit_get_one_property (*hita, "fixme:language", &langa))
+ a_preferred = check_lang(langa);
+ if (beagle_hit_get_one_property (*hitb, "fixme:language", &langb))
+ b_preferred = check_lang(langb);
+
+ if (a_preferred != b_preferred) {
+ if (a_preferred)
+ return -1;
+ if (b_preferred)
+ return 1;
+ }
+
+ double scorea = beagle_hit_get_score (*hita);
+ double scoreb = beagle_hit_get_score (*hitb);
+
+ /* The values here are inverted so that it's a descending sort. */
+ if (scorea < scoreb)
+ return 1;
+ if (scoreb < scorea)
+ return -1;
+ return 0;
+}
+
+static void
+finished_cb (BeagleQuery *query,
+ BeagleFinishedResponse *response,
+ YelpSearchParser *parser)
+{
+ int i;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_ptr_array_sort (parser->hits, compare_hits);
+
+ for (i = 0; i < 10 && i < parser->hits->len; i++) {
+ BeagleHit *hit = g_ptr_array_index (parser->hits, i);
+ xmlNode *child;
+ /* static float score_fake = 0; */
+ char *score;
+ const char *property;
+ BeagleSnippetRequest *request;
+ SnippetLocation *snippet_location;
+
+ child = xmlNewTextChild (parser->root, NULL, BAD_CAST "result", NULL);
+ xmlSetProp (child, BAD_CAST "uri", BAD_CAST beagle_hit_get_uri (hit));
+ xmlSetProp (child, BAD_CAST "parent_uri",
+ BAD_CAST beagle_hit_get_parent_uri (hit));
+ if (beagle_hit_get_one_property (hit, "dc:title", &property))
+ xmlSetProp (child, BAD_CAST "title", BAD_CAST property);
+ if (beagle_hit_get_one_property (hit, "fixme:base_title", &property))
+ xmlSetProp (child, BAD_CAST "base_title", BAD_CAST property);
+
+ score = g_strdup_printf ("%f", beagle_hit_get_score (hit));
+ debug_print (DB_DEBUG, "%f\n", beagle_hit_get_score (hit));
+ /*xmlSetProp (child, BAD_CAST "score", BAD_CAST score);*/
+ g_free (score);
+
+ parser->snippet_request_count ++;
+
+ snippet_location = g_new (SnippetLocation, 1);
+
+ snippet_location->parser = parser;
+ snippet_location->node = child;
+
+ request = beagle_snippet_request_new ();
+ beagle_snippet_request_set_hit (request, hit);
+ beagle_snippet_request_set_query (request, query);
+
+ g_signal_connect (request, "response",
+ G_CALLBACK (snippet_response), snippet_location);
+ g_signal_connect (request, "error",
+ G_CALLBACK (snippet_error), snippet_location);
+ g_signal_connect (request, "closed",
+ G_CALLBACK (snippet_closed), snippet_location);
+
+ debug_print (DB_DEBUG, "Requesting snippet\n");
+ beagle_client_send_request_async (beagle_client, BEAGLE_REQUEST (request),
+ NULL);
+ }
+
+ g_signal_handlers_disconnect_by_func (query,
+ G_CALLBACK (hits_added_cb),
+ parser);
+ g_signal_handlers_disconnect_by_func (query,
+ G_CALLBACK (finished_cb),
+ parser);
+ g_object_unref (query);
+
+ g_ptr_array_foreach (parser->hits, (GFunc) beagle_hit_unref, NULL);
+ g_ptr_array_free (parser->hits, TRUE);
+ parser->hits = NULL;
+
+ check_finished (parser);
+}
+#endif /* ENABLE_BEAGLE */
+
+static gboolean
+search_parser_process_idle (YelpSearchParser *parser)
+{
+#ifdef ENABLE_BEAGLE
+ BeagleQuery *query;
+ GError *error = NULL;
+#endif /* ENABLE_BEAGLE */
+
+ parser->search_doc = xmlNewDoc (BAD_CAST "1.0");
+ parser->root = xmlNewNode (NULL, BAD_CAST "search");
+ xmlSetProp (parser->root, BAD_CAST "title", BAD_CAST parser->search_terms);
+ xmlDocSetRootElement (parser->search_doc, parser->root);
+
+#ifdef ENABLE_BEAGLE
+ if (beagle_client != NULL) {
+ query = beagle_query_new ();
+
+ beagle_query_set_max_hits (query, 10000);
+ beagle_query_add_text (query, parser->search_terms);
+ beagle_query_add_source (query, "documentation");
+
+ parser->hits = g_ptr_array_new ();
+
+ g_signal_connect (query, "hits-added",
+ G_CALLBACK (hits_added_cb),
+ parser);
+
+ g_signal_connect (query, "finished",
+ G_CALLBACK (finished_cb),
+ parser);
+
+ beagle_client_send_request_async (beagle_client, BEAGLE_REQUEST (query), &error);
+
+ if (error) {
+ debug_print (DB_DEBUG, "error: %s\n", error->message);
+ }
+
+ g_clear_error (&error);
+ } else {
+ g_warning ("beagled not running, using basic search support.");
+ }
+#endif /* ENABLE_BEAGLE */
+
+#ifdef ENABLE_BEAGLE
+ if (beagle_client == NULL) {
+#endif
+ g_return_val_if_fail (parser->slow_search_setup_process_id == 0, FALSE);
+
+ parser->slow_search_setup_process_id =
+ g_idle_add ((GSourceFunc) slow_search_setup,
+ parser);
+#ifdef ENABLE_BEAGLE
+ }
+#endif
+
+ /* returning false removes this idle function from the main loop;
+ * we also set our search process id to zero */
+ parser->search_process_id = 0;
+ return FALSE;
+}
+
+void s_startElement(void *data,
+ const xmlChar * name,
+ const xmlChar ** attrs)
+{
+ SearchContainer *c = (SearchContainer *) data;
+
+ if (g_str_equal (name, "xi:include") || g_str_equal (name, "include")) {
+ gint i=0;
+ while (attrs[i]) {
+ if (g_str_equal (attrs[i], "href")) {
+
+ c->components = g_slist_append (c->components,
+ g_strconcat (c->base_path,
+ "/",
+ attrs[i+1],
+ NULL));
+ break;
+ }
+ i+=2;
+ }
+ }
+
+ if (attrs) {
+ gint i=0;
+ while (attrs[i]) {
+ if (g_str_equal (attrs[i], "id")) {
+ g_free (c->current_subsection);
+ c->current_subsection = g_strdup ((gchar *) attrs[i+1]);
+ }
+ i+=2;
+ }
+ }
+ /* Do we need to grab the title of the document?
+ * used in snippets when displaying results from an indexterm etc.
+ */
+ if (c->search_status != NOT_SEARCHING && g_str_equal (name, "title")) {
+ c->grab_text = TRUE;
+ }
+
+ /* Are we allowed to search this element? */
+ if (c->search_status == NOT_SEARCHING) {
+ if (c->html && g_str_equal (name, "html")) {
+ c->search_status = SEARCH_DOC;
+ return;
+ }
+
+ if (g_str_equal (name, "title")) {
+ c->search_status = SEARCH_1;
+ }
+ else if (g_str_equal (name, "indexterm"))
+ c->search_status = SEARCH_1;
+ else if (g_str_equal (name, "sect1") ||
+ g_str_equal (name, "section") ||
+ g_str_equal (name, "chapter") ||
+ g_str_equal (name, "body"))
+ c->search_status = SEARCH_DOC;
+ } else if (c->search_status == SEARCH_1) {
+ c->search_status = SEARCH_CHILD;
+ }
+
+ if (c->elem_type) {
+ c->elem_stack = g_slist_prepend (c->elem_stack,
+ g_strdup (c->elem_type));
+ g_free (c->elem_type);
+ }
+
+ c->elem_type = g_strdup ((gchar *) name);
+
+ return;
+}
+
+void s_endElement(void * data,
+ const xmlChar * name)
+{
+ SearchContainer *c = (SearchContainer *) data;
+
+ if (c->search_status == SEARCH_CHILD) {
+ c->search_status = SEARCH_1;
+ } else if (c->search_status == SEARCH_1) {
+ c->search_status = NOT_SEARCHING;
+ }
+
+ g_free (c->elem_type);
+ c->elem_type = NULL;
+
+ if (c->elem_stack) {
+ GSList *top = c->elem_stack;
+ c->elem_type = g_strdup ((gchar *) top->data);
+ c->elem_stack = g_slist_delete_link (c->elem_stack, top);
+ }
+ c->grab_text = FALSE;
+ return;
+}
+
+void s_characters(void * data,
+ const xmlChar * ch,
+ int len)
+{
+ SearchContainer *c = (SearchContainer *) data;
+ if (c->grab_text) {
+ g_free (c->sect_name);
+ c->sect_name = g_strndup ((gchar *) ch, len);
+ }
+
+ /* Sometimes html docs don't trigger the "startElement" method
+ * I don't know why. Instead, we just search the entire
+ * html file, hoping to find something.
+ */
+ if (c->html && c->search_status != SEARCH_DOC)
+ c->search_status = SEARCH_DOC;
+ if (c->search_status != NOT_SEARCHING) {
+ gchar *tmp = g_utf8_casefold ((gchar *) ch, len);
+ gint i = 0;
+ gchar *s_term = c->search_term[i];
+ while (s_term && c->score_per_word[i] < 1.0) {
+ if (c->stop_word[i] || c->score_per_word[c->dup_of[i]] == 1.0) {
+ i++;
+ s_term = c->search_term[i];
+ continue;
+ }
+
+ gchar *location = strstr (tmp, s_term);
+ if (location) {
+ gchar before = *(location-1);
+ gchar after = *(location+strlen(s_term));
+ gfloat local_score = 0.0;
+ gboolean use_text = TRUE;
+ if (location == tmp)
+ before = ' ';
+ if (strlen(location) == strlen(s_term))
+ after = ' ';
+
+ if ((g_ascii_ispunct (before) || g_ascii_isspace (before))
+ && (g_ascii_ispunct (after) || g_ascii_isspace (after))) {
+ if (!c->elem_type) {
+ /* Stupid HTML. Treat like its a normal tag */
+ local_score = 0.1;
+ } else if (g_str_equal(c->elem_type, "primary")) {
+ local_score = 1.0;
+ use_text = FALSE;
+ } else if (g_str_equal (c->elem_type, "secondary")) {
+ local_score = 0.9;
+ use_text = FALSE;
+ } else if (g_str_equal (c->elem_type, "title") ||
+ g_str_equal (c->elem_type, "titleabbrev")) {
+ local_score = 0.8;
+ } else {
+ local_score = 0.1;
+ }
+ c->score += local_score;
+ c->found_terms[c->dup_of[i]] = TRUE;
+ if (local_score > c->snippet_score) {
+ g_free (c->snippet);
+ if (use_text) {
+ c->snippet = g_strndup (g_utf8_casefold ((gchar *) ch,
+ len),
+ len);
+ } else {
+ c->snippet = g_strdup (c->sect_name);
+ }
+ c->result_subsection = g_strdup (c->current_subsection);
+ c->snippet_score = local_score;
+ c->score_per_word[c->dup_of[i]] = local_score;
+ }
+ }
+ }
+ i++;
+ s_term = c->search_term[i];
+ }
+ g_free (tmp);
+ }
+ return;
+}
+
+void s_declEntity (void *data, const xmlChar *name, int type,
+ const xmlChar *pID, const xmlChar *sID,
+ xmlChar *content)
+{
+ SearchContainer *c = (SearchContainer *) data;
+ if (type == 2) {
+ g_hash_table_insert (c->entities,
+ g_strdup ((gchar *) name),
+ g_strdup ((gchar *) sID));
+
+ }
+ return;
+}
+
+xmlEntityPtr s_getEntity (void *data, const xmlChar *name)
+{
+ SearchContainer *c = (SearchContainer *) data;
+ xmlEntityPtr t = xmlGetPredefinedEntity(name);
+
+ if (!t) {
+ gchar * lookup = g_hash_table_lookup (c->entities, name);
+ if (lookup) {
+ c->components = g_slist_append (c->components,
+ g_strconcat (c->base_path,
+ "/",
+ lookup, NULL));
+ }
+ }
+
+ return t;
+
+}
+
+
+
+
+
+static xmlSAXHandler handlers = {
+ NULL, NULL, NULL, NULL, NULL,
+ s_getEntity,
+ s_declEntity, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ s_startElement, s_endElement, NULL, s_characters,
+ NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+
+/* Parse the omfs and build the list of files to be searched */
+
+/* A common bit of code used below. Chucked in a function for easy */
+gchar *
+string_append (gchar *current, gchar *new, gchar *suffix)
+{
+ gchar *ret;
+
+ if (suffix) {
+ ret = g_strconcat (current, ":", new, suffix, NULL);
+ } else {
+ ret = g_strconcat (current, ":", new, NULL);
+ }
+ g_free (current);
+ return ret;
+}
+
+static gint
+build_lists (gchar *search_terms, gchar ***terms, gint **dups,
+ gboolean ** stops, gint *req)
+{
+ gchar *ignore_words, *common_prefixes, *common_suffixes;
+ gchar **prefixes, **suffixes, **ignore;
+ gchar **list_copy;
+ gchar **iter, **iter1 = NULL;
+ gchar *term_str = NULL;
+ gchar *dup_str = NULL;
+ gint n_terms = 0, i=-1;
+ gint orig_term = 0;
+ gint non_stop = 0;
+
+
+ /* Translators: Do not translate this list exactly. These are
+ * colon-separated words that aren't useful for choosing search
+ * results; they will be different for each language. Include
+ * pronouns, articles, very common verbs and prepositions,
+ * words from question structures like "tell me about" and
+ * "how do I", and words for functional states like "not",
+ * "work", and "broken".
+ */
+ ignore_words = g_strdup (_("a:about:an:are:as:at:be:broke:broken:by"
+ ":can:can't:dialog:dialogue:do:doesn't"
+ ":doesnt:don't:dont:explain:for:from:get"
+ ":gets:got:make:makes:not:when:has"
+ ":have:help:how:i:in:is:it:item:me:my:of"
+ ":on:or:tell:that:the:thing:this:to:what"
+ ":where:who:will:with:won't:wont:why:work"
+ ":working:works"));
+ /* Translators: This is a list of common prefixes for words.
+ * Do not translate this directly. Instead, use a colon
+ * seperated list of word-starts. In English, an example
+ * is re-. If there is none, please use the term NULL
+ * If there is only one, please put a colon after.
+ * E.g. if the common prefix is re then the string would be
+ * "re:"
+ */
+ common_prefixes = g_strdup (_("re"));
+
+ /* Translators: This is a list of (guess what?) common suffixes
+ * to words. Things that may be put at ends of words to slightly
+ * alter their meaning (like -ing and -s in English). This is a
+ * colon seperated list (I like colons). If there are none,
+ * please use the strig NULL. If there is only 1, please
+ * add a colon at the end of the list
+ */
+ common_suffixes = g_strdup (_("ers:er:ing:es:s:'s"));
+
+ ignore = g_strsplit (ignore_words, ":", -1);
+ if (strchr (common_prefixes, ':')) {
+ prefixes = g_strsplit (common_prefixes, ":", -1);
+ } else {
+ prefixes = NULL;
+ }
+ if (strchr (common_suffixes, ':')) {
+ suffixes = g_strsplit (common_suffixes, ":", -1);
+ } else {
+ suffixes = NULL;
+ }
+ search_terms = g_strdelimit (search_terms, ":", ' ');
+ list_copy = g_strsplit (g_utf8_casefold (g_strstrip (
+ search_terms), -1),
+ " ", -1);
+
+ for (iter = list_copy; *iter != NULL; iter++) {
+ gboolean ignoring = FALSE;
+ if (strlen (*iter) == 0) {
+ continue;
+ }
+ if (g_str_has_suffix (*iter, "?")) {
+ gchar *tmp;
+ tmp = g_strndup (*iter, strlen (*iter) - 1);
+ g_free (*iter);
+ *iter = g_strdup (tmp);
+ g_free (tmp);
+ }
+ if (!term_str) {
+ term_str = g_strdup (*iter);
+ } else {
+ term_str = string_append (term_str, *iter, NULL);
+ }
+
+ for (iter1 = ignore; *iter1; iter1++) {
+ if (g_str_equal (*iter, *iter1)) {
+ ignoring = TRUE;
+ break;
+ }
+ }
+ if (ignoring) {
+ if (!dup_str) {
+ dup_str = g_strdup ("I");
+ } else {
+ dup_str = string_append (dup_str, "I", NULL);
+ }
+ continue;
+ }
+ non_stop++;
+
+ if (!dup_str) {
+ dup_str = g_strdup ("O");
+ } else {
+ dup_str = string_append (dup_str, "O", NULL);
+ }
+ (*req)++;
+ if (prefixes) {
+ for (iter1 = prefixes; *iter1; iter1++) {
+ if (g_str_has_prefix (*iter, *iter1)) {
+ term_str = string_append (term_str,
+ (*iter+strlen(*iter1)), NULL);
+ } else {
+ term_str = string_append (term_str, *iter, *iter1);
+ }
+ dup_str = string_append (dup_str, "D", NULL);
+ }
+ }
+ if (suffixes) {
+ for (iter1 = suffixes; *iter1; iter1++) {
+ if (g_str_has_suffix (*iter, *iter1)) {
+ gchar *tmp;
+ tmp = g_strndup (*iter, (strlen(*iter)-strlen(*iter1)));
+ term_str = string_append (term_str, tmp, NULL);
+ g_free (tmp);
+ } else {
+ term_str = string_append (term_str, *iter, *iter1);
+ }
+ dup_str = string_append (dup_str, "D", NULL);
+ }
+ }
+ }
+ g_strfreev (list_copy);
+ *terms = g_strsplit (term_str, ":", -1);
+ n_terms = g_strv_length (*terms);
+ (*dups) = g_new0 (gint, n_terms);
+ (*stops) = g_new0 (gboolean, n_terms);
+ list_copy = g_strsplit (dup_str, ":", -1);
+
+ for (iter = *terms; *iter; iter++) {
+ i++;
+ if (g_str_equal (list_copy[i], "O")) {
+ orig_term = i;
+ }
+ (*dups)[i] = orig_term;
+
+ for (iter1 = ignore; *iter1; iter1++) {
+ if (non_stop > 0 && g_str_equal (*iter, *iter1)) {
+ (*stops)[i] = TRUE;
+ (*dups)[i] = -2;
+ break;
+ }
+ }
+ }
+
+ /* Clean up all those pesky strings */
+ g_free (ignore_words);
+ g_free (common_prefixes);
+ g_free (common_suffixes);
+ g_free (term_str);
+ g_free (dup_str);
+ g_strfreev (prefixes);
+ g_strfreev (suffixes);
+ g_strfreev (ignore);
+ g_strfreev (list_copy);
+
+ return n_terms;
+}
+
+static gboolean
+slow_search_setup (YelpSearchParser *parser)
+{
+ gchar **terms_list = NULL;
+ gint *dup_list = NULL;
+ gboolean *stop_list = NULL;
+ gint terms_number = 0;
+ gint required_no = 0;
+ SearchDocData *data;
+
+
+ terms_number = build_lists (parser->search_terms,&terms_list,
+ &dup_list, &stop_list,
+ &required_no);
+ data = g_new0 (SearchDocData, 1);
+ data->container = g_new0 (SearchContainer, 1);
+ data->parser = parser;
+ data->required_no = required_no;
+ data->terms_number = terms_number;
+ data->stop_list = stop_list;
+ data->dup_list = dup_list;
+ data->terms_list = terms_list;
+ data->terms_number = terms_number;
+
+ rrn_for_each ((RrnForeachFunc) slow_search_process, data);
+
+ search_process_man (parser, terms_list);
+ search_process_info (parser, terms_list);
+
+ check_finished (parser);
+
+ return FALSE;
+}
+
+
+static gboolean
+slow_search_process (RrnReg *reg, SearchDocData *data)
+{
+ gint i, j=0;
+ SearchContainer *container = data->container;
+ gchar *ptr, *path;
+ gchar *fname;
+
+ /* Set up the container with the new data */
+ if (g_str_has_prefix (reg->uri, "file:")) {
+ fname = &(reg->uri[5]);
+ } else {
+ fname = reg->uri;
+ }
+
+ while (fname[0] == '/' && fname[1] == '/') {
+ fname++;
+ }
+
+ container->base_filename = g_strdup (fname);
+ fname = g_strdup (container->base_filename);
+
+ container->entities = g_hash_table_new (g_str_hash, g_str_equal);
+ container->doc_title = g_strdup ((gchar *) reg->name);
+ container->score=0;
+ container->html = FALSE;
+ container->default_snippet = g_strdup ((gchar *) reg->comment);
+ container->current_subsection = NULL;
+ container->elem_type = NULL;
+
+ ptr = g_strrstr (container->base_filename, "/");
+
+ path = g_strndup (container->base_filename,
+ ptr - container->base_filename);
+
+ /* BEGIN HTML special block */
+ if (g_str_equal (reg->type, "text/html") ||
+ g_str_has_suffix (fname, "html")) {
+ GDir *dir;
+ gchar *filename;
+ container->html = TRUE;
+ ptr++;
+
+ dir = g_dir_open (path, 0, NULL);
+
+ while ((filename = (gchar *) g_dir_read_name (dir))) {
+ if ((g_str_has_suffix (filename, ".html") ||
+ g_str_has_suffix (filename, ".htm")) &&
+ !g_str_equal (filename, ptr)) {
+ container->components =
+ g_slist_append (container->components,
+ g_strconcat (path, "/", filename,
+ NULL));
+
+ }
+ }
+ /* END HTML special blcok */
+ }
+
+ container->base_path = g_strdup (path);
+
+ container->required_words = data->required_no;
+ container->grab_text = FALSE;
+ container->sect_name = NULL;
+
+ container->search_term = g_strdupv (data->terms_list);
+ container->stop_word = g_new0 (gboolean, data->terms_number);
+ container->dup_of = g_new0 (gint, data->terms_number);
+ container->found_terms = g_new0 (gboolean, data->terms_number);
+ container->score_per_word = g_new0 (gfloat, data->terms_number);
+ container->found_terms = g_new0 (gboolean, data->terms_number);
+ container->result_subsection = NULL;
+ container->search_status = NOT_SEARCHING;
+ container->snippet_score = 0;
+ container->snippet = NULL;
+
+ for (i=0; i< data->terms_number; i++) {
+ container->stop_word[i] = data->stop_list[i];
+ container->dup_of[i] = data->dup_list[i];
+ }
+
+
+ xmlSAXUserParseFile (&handlers, container, fname);
+ for (i=0; i< g_strv_length (container->search_term); ++i) {
+ if (container->found_terms[i]) {
+ j++;
+ }
+ }
+ if (j >= container->required_words) {
+ search_parse_result (data->parser, container);
+ } else while (container->components) {
+ GSList *next = container->components;
+ container->components = g_slist_remove_link (container->components, next);
+ container->search_status = NOT_SEARCHING;
+ xmlSAXUserParseFile (&handlers, container, (gchar *) next->data);
+ j = 0;
+ for (i=0; i< g_strv_length (container->search_term); ++i) {
+ if (container->found_terms[i])
+ j++;
+ }
+ if (j >= container->required_words) {
+ search_parse_result (data->parser, container);
+ break;
+ }
+ }
+
+ search_free_container (container);
+ g_free (path);
+ return TRUE;
+
+}
+
+static void
+search_free_container (SearchContainer *c)
+{
+ g_strfreev (c->search_term);
+ g_free (c->dup_of);
+ g_free (c->found_terms);
+ g_free (c->stop_word);
+ g_free (c->score_per_word);
+ g_free (c->top_element);
+ g_free (c->elem_type);
+ g_free (c->sect_name);
+ g_free (c->default_snippet);
+ g_free (c->current_subsection);
+ g_free (c->result_subsection);
+ g_free (c->doc_title);
+ g_free (c->base_path);
+ g_free (c->base_filename);
+ g_free (c->snippet);
+ g_hash_table_destroy (c->entities);
+}
+
+gchar *
+search_clean_snippet (gchar *snippet, gchar **terms)
+{
+ /* This is probably what you want to change */
+ gint len_before_term = 47;
+ gint len_after_term = 47;
+ gchar **iteration;
+ gboolean am_cutting = FALSE;
+ gchar *result = NULL;
+ gboolean found_terms = FALSE;
+
+
+ if (!snippet)
+ return NULL;
+
+ if (strlen(snippet) > (len_before_term+len_after_term)) {
+ am_cutting = TRUE;
+ }
+ result = g_strdup (snippet);
+
+ for (iteration = terms; *iteration; iteration++) {
+ gchar *before, *after, *tmp;
+ gchar *str;
+ gchar before_c, after_c;
+ gint count = 0;
+
+ while ((str = strstr (result, (*iteration)))) {
+ gboolean breaking = FALSE;
+ gint i;
+ for (i=0; i< count; i++) {
+ str++;
+ str = strstr (str, (*iteration));
+ if (!str) {
+ breaking = TRUE;
+ break;
+ }
+ }
+ count++;
+ if (breaking)
+ break;
+
+ before_c = *(str-1);
+ after_c = *(str+strlen(*iteration));
+
+ if (g_ascii_isalpha (before_c) || g_ascii_isalpha (after_c)) {
+ continue;
+ }
+
+ tmp = g_strndup (result, (str-result));
+ /* If we have to chop the snippet down to size, here is the
+ * place to do it. Only the first time through though
+ */
+ if (am_cutting && !found_terms && strlen (tmp) > len_before_term) {
+ gchar *tmp1;
+ gchar *tmp2;
+ gint cut_by;
+
+ tmp1 = tmp;
+ cut_by = strlen(tmp) - len_before_term;
+
+ tmp1 += cut_by;
+ tmp2 = g_strdup (tmp1);
+ g_free (tmp);
+ tmp = g_strconcat ("...",tmp2, NULL);
+ g_free (tmp2);
+ }
+
+ before = g_strconcat (tmp, "<em>", NULL);
+ g_free (tmp);
+
+ str += strlen (*iteration);
+
+ if (am_cutting && !found_terms && strlen (str) > len_after_term) {
+ gchar *tmp1;
+
+ tmp1 = g_strndup (str, len_after_term);
+ tmp = g_strconcat (tmp1, "...", NULL);
+ g_free (tmp1);
+ } else {
+ tmp = g_strdup (str);
+ }
+
+ after = g_strconcat ((*iteration), "</em>", tmp, NULL);
+
+
+
+ g_free (result);
+ result = g_strconcat (before, after, NULL);
+ found_terms = TRUE;
+ }
+ }
+ return result;
+}
+
+void
+search_parse_result (YelpSearchParser *parser, SearchContainer *c)
+{
+ xmlNode *child;
+ gchar *new_uri;
+ xmlDoc *snippet_doc;
+ xmlNode *node;
+ char *xmldoc;
+
+ new_uri = g_strconcat (c->base_filename, "#", c->result_subsection,
+ NULL);
+ child = xmlNewTextChild (parser->root, NULL,
+ BAD_CAST "result", NULL);
+ xmlSetProp (child, BAD_CAST "uri", BAD_CAST new_uri);
+ xmlSetProp (child, BAD_CAST "title", BAD_CAST g_strstrip (c->doc_title));
+ xmlSetProp (child, BAD_CAST "score",
+ BAD_CAST g_strdup_printf ("%f", c->score));
+ /* Fix up the snippet to show the break_term in bold */
+ if (!c->snippet)
+ c->snippet = g_strdup (c->default_snippet);
+ xmldoc = g_strdup_printf ("<snippet>%s</snippet>",
+ search_clean_snippet (c->snippet, c->search_term));
+ snippet_doc = xmlParseDoc (BAD_CAST xmldoc);
+ g_free (xmldoc);
+
+ if (!snippet_doc)
+ return;
+
+ node = xmlDocGetRootElement (snippet_doc);
+ xmlUnlinkNode (node);
+ xmlAddChild (child, node);
+ xmlFreeDoc (snippet_doc);
+}
+
+void
+process_man_result (YelpSearchParser *parser, gchar *result, gchar **terms)
+{
+ gchar ** split = g_strsplit (result, "\n", -1);
+ gint i;
+
+ for (i=0;split[i];i++) {
+ gchar ** line = g_strsplit (split[i], "(", 2);
+ gchar *filename = NULL;
+ gchar *desc = NULL;
+ xmlNode *child;
+ gchar *tmp = NULL;
+ gchar *after = NULL;
+ /*gchar *before = NULL;*/
+ gchar *title = NULL;
+ /*gint i;*/
+
+ if (line == NULL || line[0] == NULL || line[1] == NULL)
+ continue;
+
+ title = g_strdup (g_strstrip (line[0]));
+ after = strstr (line[1], ")");
+
+ tmp = g_strndup (line[1], after-line[1]);
+
+ filename = g_strconcat ("man:", title, "(", tmp,")", NULL);
+
+ after++;
+ g_free (tmp);
+
+ tmp = g_strdup (g_strchug (after));
+ after = tmp; after++;
+ desc = g_strdup (g_strchug (after));
+
+ child = xmlNewTextChild (parser->root, NULL,
+ BAD_CAST "result", NULL);
+ xmlSetProp (child, BAD_CAST "uri", BAD_CAST filename);
+ xmlSetProp (child, BAD_CAST "title",
+ BAD_CAST g_strconcat (title,
+ " manual page", NULL));
+
+ xmlNewChild (child, NULL, BAD_CAST "snippet",
+ BAD_CAST desc);
+ xmlNewChild (child, NULL, BAD_CAST "score",
+ BAD_CAST "0.1");
+ g_free (tmp);
+ g_strfreev (line);
+ }
+
+}
+
+void
+process_info_result (YelpSearchParser *parser, gchar *result, gchar **terms)
+{
+ gchar ** split = NULL;
+ gint i;
+
+ split = g_strsplit (result, "\n", -1);
+ if (split == NULL)
+ return;
+
+ for (i=0;split[i];i++) {
+ gchar ** line = NULL;
+ gchar *filename = NULL;
+ gchar *desc = NULL;
+ gchar *title = NULL;
+ xmlNode *child;
+ gchar *tmp;
+ gchar *tmp1;
+ gchar *file_name;
+
+ line = g_strsplit (split[i], "--", 3);
+ if (g_strv_length (line) != 2) {
+ g_strfreev (line);
+ continue;
+ }
+
+ /* First is the filename
+ * We gotta do some fiddling to get the actual filename
+ * we can use
+ */
+ tmp = g_strdup (g_strchomp (line[0]));
+ tmp++;
+ tmp1 = strstr (tmp, "\"");
+ if (!tmp1) {
+ g_strfreev (line);
+ g_free (tmp);
+ continue;
+ }
+ file_name = g_strndup (tmp, tmp1-tmp);
+ tmp++;
+ tmp1 = strstr (tmp, ")");
+ if (tmp1)
+ title = g_strndup (tmp, tmp1-tmp);
+ else {
+ title = g_strdup (++file_name);
+ --file_name;
+ }
+ tmp--;
+ tmp--;
+ filename = g_strconcat ("info:", file_name, NULL);
+ g_free (tmp);
+ g_free (file_name);
+
+ /* Then the description */
+ desc = g_strdup (g_strchug (line[1]));
+
+ /* Now we add the result to the page */
+ child = xmlNewTextChild (parser->root, NULL,
+ BAD_CAST "result", NULL);
+ xmlSetProp (child, BAD_CAST "uri", BAD_CAST filename);
+ xmlSetProp (child, BAD_CAST "title",
+ BAD_CAST g_strconcat (title,
+ " info page", NULL));
+
+ xmlNewChild (child, NULL, BAD_CAST "snippet",
+ BAD_CAST desc);
+ xmlNewChild (child, NULL, BAD_CAST "score",
+ BAD_CAST "0.05");
+ g_strfreev (line);
+ g_free (title);
+ }
+
+}
+
+void
+search_process_man (YelpSearchParser *parser, gchar **terms)
+{
+ gchar *command;
+ gchar *stdout_str = NULL;
+ gint exit_code;
+ gchar *tmp = NULL;
+ gchar *search = NULL;
+
+ tmp = g_strescape (parser->search_terms, NULL);
+ tmp = g_strdelimit (tmp, "\'", '\'');
+ search = g_strconcat ("\"",tmp,"\"", NULL);
+
+ command = g_strconcat("apropos ", search, NULL);
+
+ if (g_spawn_command_line_sync (command, &stdout_str, NULL,
+ &exit_code, NULL) && exit_code == 0) {
+ process_man_result (parser, stdout_str, terms);
+
+ }
+ g_free (tmp);
+ g_free (search);
+ g_free (stdout_str);
+ g_free (command);
+
+ return;
+}
+
+void
+search_process_info (YelpSearchParser *parser, gchar **terms)
+{
+ gchar *command;
+ gchar *stdout_str = NULL;
+ gchar *stderr_str = NULL;
+ gchar *tmp;
+ gint exit_code;
+
+ gchar *search = NULL;
+
+ tmp = g_strescape (parser->search_terms, NULL);
+ tmp = g_strdelimit (tmp, "\'", '\'');
+ search = g_strconcat ("\"",tmp,"\"", NULL);
+ command = g_strconcat("info --apropos ", search, NULL);
+
+ if (g_spawn_command_line_sync (command, &stdout_str, &stderr_str,
+ &exit_code, NULL) &&
+ stdout_str != NULL) {
+ process_info_result (parser, stdout_str, terms);
+ }
+ g_free (tmp);
+ g_free (stdout_str);
+ g_free (stderr_str);
+ g_free (command);
+
+ return;
+}
diff --git a/src/yelp-search-parser.h b/src/yelp-search-parser.h
new file mode 100644
index 00000000..d0d25ac7
--- /dev/null
+++ b/src/yelp-search-parser.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007 Don Scorgie <Don@Scorgie.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifndef __YELP_SEARCH_PARSER_H__
+#define __YELP_SEARCH_PARSER_H__
+
+#include <glib.h>
+#include <libxml/tree.h>
+
+typedef struct _YelpSearchParser YelpSearchParser;
+
+YelpSearchParser * yelp_search_parser_new (void);
+xmlDocPtr yelp_search_parser_process (YelpSearchParser *parser,
+ gchar *terms);
+void yelp_search_parser_free (YelpSearchParser *parser);
+
+#endif /* __YELP_SEARCH_PARSER_H__ */
diff --git a/src/yelp-search.c b/src/yelp-search.c
new file mode 100644
index 00000000..ef2ca9ff
--- /dev/null
+++ b/src/yelp-search.c
@@ -0,0 +1,391 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007 Don Scorgie <Don@Scorgie.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libxml/tree.h>
+
+#include "yelp-error.h"
+#include "yelp-search.h"
+#include "yelp-search-parser.h"
+#include "yelp-transform.h"
+#include "yelp-debug.h"
+
+#define STYLESHEET DATADIR"/yelp/xslt/search2html.xsl"
+
+#define YELP_SEARCH_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_SEARCH, YelpSearchPriv))
+
+typedef enum {
+ SEARCH_STATE_BLANK, /* Brand new, run transform as needed */
+ SEARCH_STATE_PARSING, /* Parsing/transforming document, please wait */
+ SEARCH_STATE_PARSED, /* All done, if we ain't got it, it ain't here */
+ SEARCH_STATE_STOP /* Stop everything now, object to be disposed */
+} SearchState;
+
+struct _YelpSearchPriv {
+ gchar *search_terms;
+ SearchState state;
+
+ GMutex *mutex;
+ GThread *thread;
+
+ xmlDocPtr xmldoc;
+
+ gboolean process_running;
+ gboolean transform_running;
+
+ YelpTransform *transform;
+};
+
+
+static void search_class_init (YelpSearchClass *klass);
+static void search_init (YelpSearch *search);
+static void search_try_dispose (GObject *object);
+static void search_dispose (GObject *object);
+
+/* YelpDocument */
+static void search_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+
+/* YelpTransform */
+static void transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpSearch *search);
+static void transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpSearch *search);
+static void transform_final_func (YelpTransform *transform,
+ YelpSearch *search);
+
+/* Threaded */
+static void search_process (YelpSearch *search);
+
+static YelpDocumentClass *parent_class;
+
+GType
+yelp_search_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpSearchClass),
+ NULL, NULL,
+ (GClassInitFunc) search_class_init,
+ NULL, NULL,
+ sizeof (YelpSearch),
+ 0,
+ (GInstanceInitFunc) search_init,
+ };
+ type = g_type_register_static (YELP_TYPE_DOCUMENT,
+ "YelpSearch",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+search_class_init (YelpSearchClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = search_try_dispose;
+
+ document_class->request = search_request;
+ document_class->cancel = NULL;
+
+ g_type_class_add_private (klass, sizeof (YelpSearchPriv));
+}
+
+static void
+search_init (YelpSearch *search)
+{
+ YelpSearchPriv *priv;
+
+ priv = search->priv = YELP_SEARCH_GET_PRIVATE (search);
+
+ priv->state = SEARCH_STATE_BLANK;
+
+ priv->mutex = g_mutex_new ();
+}
+
+static void
+search_try_dispose (GObject *object)
+{
+ YelpSearchPriv *priv;
+
+ g_assert (object != NULL && YELP_IS_SEARCH (object));
+ priv = YELP_SEARCH (object)->priv;
+
+ g_mutex_lock (priv->mutex);
+ if (priv->process_running || priv->transform_running) {
+ priv->state = SEARCH_STATE_STOP;
+ g_idle_add ((GSourceFunc) search_try_dispose, object);
+ g_mutex_unlock (priv->mutex);
+ } else {
+ g_mutex_unlock (priv->mutex);
+ search_dispose (object);
+ }
+}
+
+static void
+search_dispose (GObject *object)
+{
+ YelpSearch *search = YELP_SEARCH (object);
+
+ g_free (search->priv->search_terms);
+
+ if (search->priv->xmldoc)
+ xmlFreeDoc (search->priv->xmldoc);
+
+ g_mutex_free (search->priv->mutex);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_search_new (gchar *filename)
+{
+ YelpSearch *search;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ search = (YelpSearch *) g_object_new (YELP_TYPE_SEARCH, NULL);
+ search->priv->search_terms = g_strdup (filename);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " filename = \"%s\"\n", filename);
+
+ yelp_document_add_page_id (YELP_DOCUMENT (search), "x-yelp-index", "index");
+
+ return (YelpDocument *) search;
+}
+
+
+/******************************************************************************/
+/** YelpDocument **************************************************************/
+
+static void
+search_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpSearch *search;
+ YelpSearchPriv *priv;
+ YelpError *error;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " req_id = %i\n", req_id);
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+
+ g_assert (document != NULL && YELP_IS_SEARCH (document));
+
+ if (handled)
+ return;
+
+ search = YELP_SEARCH (document);
+ priv = search->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ switch (priv->state) {
+ case SEARCH_STATE_BLANK:
+ priv->state = SEARCH_STATE_PARSING;
+ priv->process_running = TRUE;
+ priv->thread = g_thread_create ((GThreadFunc) search_process, search, FALSE, NULL);
+ break;
+ case SEARCH_STATE_PARSING:
+ break;
+ case SEARCH_STATE_PARSED:
+ case SEARCH_STATE_STOP:
+ /* Much bigger problems */
+ error = yelp_error_new (_("Page not found"),
+ _("Could not process search"));
+ yelp_document_error_request (document, req_id, error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpSearch *search)
+{
+ YelpSearchPriv *priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (search != NULL && YELP_IS_SEARCH (search));
+
+ priv = search->priv;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == SEARCH_STATE_STOP) {
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ g_free (func_data);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_error_free ((YelpError *) func_data);
+ break;
+ case YELP_TRANSFORM_FINAL:
+ break;
+ }
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ return;
+ }
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ transform_page_func (transform, (gchar *) func_data, search);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_document_error_pending (YELP_DOCUMENT (search), (YelpError *) func_data);
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ break;
+ case YELP_TRANSFORM_FINAL:
+ transform_final_func (transform, search);
+ break;
+ }
+}
+
+static void
+transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpSearch *search)
+{
+ YelpSearchPriv *priv;
+ gchar *content;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = search->priv;
+ g_mutex_lock (priv->mutex);
+
+ content = yelp_transform_eat_chunk (transform, page_id);
+
+ yelp_document_add_page (YELP_DOCUMENT (search), page_id, content);
+
+ g_free (page_id);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+static void
+transform_final_func (YelpTransform *transform, YelpSearch *search)
+{
+ YelpSearchPriv *priv = search->priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_mutex_lock (priv->mutex);
+
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+
+ if (priv->xmldoc)
+ xmlFreeDoc (priv->xmldoc);
+ priv->xmldoc = NULL;
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** Threaded ******************************************************************/
+
+static void
+search_process (YelpSearch *search)
+{
+ YelpSearchPriv *priv;
+ YelpSearchParser *parser;
+ YelpError *error = NULL;
+ YelpDocument *document;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (search != NULL && YELP_IS_SEARCH (search));
+ g_object_ref (search);
+ priv = search->priv;
+ document = YELP_DOCUMENT (search);
+
+ parser = yelp_search_parser_new ();
+ priv->xmldoc = yelp_search_parser_process (parser, priv->search_terms);
+ yelp_search_parser_free (parser);
+
+ if (priv->xmldoc == NULL) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("Bigger problems still"));
+ yelp_document_error_pending (document, error);
+ }
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == SEARCH_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+
+ priv->transform = yelp_transform_new (STYLESHEET,
+ (YelpTransformFunc) transform_func,
+ search);
+ priv->transform_running = TRUE;
+
+ /* FIXME: we probably need to set our own params */
+ yelp_transform_start (priv->transform,
+ priv->xmldoc,
+ NULL);
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ priv->process_running = FALSE;
+ g_object_unref (search);
+}
diff --git a/src/yelp-search.h b/src/yelp-search.h
new file mode 100644
index 00000000..a6cec17e
--- /dev/null
+++ b/src/yelp-search.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007 Don Scorgie <Don@Scorgie.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifndef __YELP_SEARCH_H__
+#define __YELP_SEARCH_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_SEARCH (yelp_search_get_type ())
+#define YELP_SEARCH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_SEARCH, YelpSearch))
+#define YELP_SEARCH_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_SEARCH, YelpSearchClass))
+#define YELP_IS_SEARCH(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_SEARCH))
+#define YELP_IS_SEARCH_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_SEARCH))
+#define YELP_SEARCH_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_SEARCH, YelpSearchClass))
+
+typedef struct _YelpSearch YelpSearch;
+typedef struct _YelpSearchClass YelpSearchClass;
+typedef struct _YelpSearchPriv YelpSearchPriv;
+
+struct _YelpSearch {
+ YelpDocument parent;
+ YelpSearchPriv *priv;
+};
+
+struct _YelpSearchClass {
+ YelpDocumentClass parent_class;
+};
+
+GType yelp_search_get_type (void);
+YelpDocument * yelp_search_new (gchar *uri);
+
+#endif /* __YELP_SEARCH_H__ */
diff --git a/src/yelp-settings.c b/src/yelp-settings.c
index 3fc2b45d..a5d1aa94 100644
--- a/src/yelp-settings.c
+++ b/src/yelp-settings.c
@@ -46,35 +46,24 @@
#define KEY_YELP_FIXED_FONT KEY_YELP_DIR "/fixed_font"
static const gchar * const color_params[YELP_NUM_COLORS] = {
- "yelp.color.fg",
- "yelp.color.bg",
- "yelp.color.anchor",
- "yelp.color.rule",
- "yelp.color.gray.fg",
- "yelp.color.gray.bg",
- "yelp.color.gray.bg.dark1",
- "yelp.color.gray.bg.dark2",
- "yelp.color.gray.bg.dark3",
- "yelp.color.selected.fg",
- "yelp.color.selected.bg",
- "yelp.color.selected.bg.dark1",
- "yelp.color.selected.bg.dark2",
- "yelp.color.selected.bg.dark3",
- "yelp.color.admon.fg",
- "yelp.color.admon.bg",
- "yelp.color.admon.bg.dark1",
- "yelp.color.admon.bg.dark2",
- "yelp.color.admon.bg.dark3"
+ "yelp.color.text",
+ "yelp.color.background",
+ "yelp.color.text_light",
+ "yelp.color.link",
+ "yelp.color.link_visited",
+ "yelp.color.gray_background",
+ "yelp.color.gray_border",
+ "theme.color.blue_background",
+ "theme.color.blue_border",
+ "theme.color.red_background",
+ "theme.color.red_border",
+ "theme.color.yellow_background",
+ "theme.color.yelllow_border"
};
static const gchar * const icon_params[YELP_NUM_ICONS] = {
- "yelp.icon.blockquote",
- "yelp.icon.caution",
- "yelp.icon.important",
- "yelp.icon.note",
- "yelp.icon.programlisting",
- "yelp.icon.tip",
- "yelp.icon.warning"
+ "theme.icon.admon.path",
+ "theme.icon.admon.size"
};
static void settings_update (YelpSettingsType type);
@@ -106,7 +95,6 @@ static GHookList *hook_lists[YELP_SETTINGS_NUM_TYPES];
static GtkSettings *gtk_settings;
static GtkIconTheme *icon_theme;
static gchar colors[YELP_NUM_COLORS][10];
-static gchar *icon_names[YELP_NUM_ICONS] = {NULL,};
static GtkWidget *prefs_dialog = NULL;
static GtkWidget *system_fonts_widget = NULL;
@@ -124,55 +112,6 @@ yelp_settings_init (void)
{
gint i;
- for (i = 0; i < YELP_NUM_ICONS; i++) {
- switch (i) {
- case YELP_ICON_BLOCKQUOTE:
- /* TRANSLATORS:
- This is an image of the opening quote character used to watermark
- blockquote elements. Different languages use different opening
- quote characters, so the icon name is translatable. The name of
- the icon should be "yelp-watermark-blockquote-XXXX", where XXXX
- is the Unicode code point of the opening quote character. For
- example, some languages use the double angle quotation mark, so
- those would use "yelp-watermark-blockquote-00AB". However, the
- image is not automagically created. Do not translate this to a
- value if there isn't a corresponding icon in yelp/data/icons.
- If you need an image created, contact the maintainers.
-
- Phew, now some notes on which character to use. Languages that
- use guillemets (angle quotations) should use either 00AB or 00BB,
- depending on whether the opening quotation is the left guillemet
- or the right guillemet. Languages that use inverted comma style
- quotations should use 201C, 201D, or 201E. Note that single
- quotation marks don't make very nice watermarks. So if you use
- single quotes as your primary (outer) quotation marks, you should
- just use the corresponding double quote watermark.
- */
- icon_names[i] = _("yelp-watermark-blockquote-201C");
- break;
- case YELP_ICON_CAUTION:
- icon_names[i] = "yelp-icon-caution";
- break;
- case YELP_ICON_IMPORTANT:
- icon_names[i] = "yelp-icon-important";
- break;
- case YELP_ICON_NOTE:
- icon_names[i] = "yelp-icon-note";
- break;
- case YELP_ICON_PROGRAMLISTING:
- icon_names[i] = "yelp-watermark-programlisting";
- break;
- case YELP_ICON_TIP:
- icon_names[i] = "yelp-icon-tip";
- break;
- case YELP_ICON_WARNING:
- icon_names[i] = "yelp-icon-warning";
- break;
- default:
- g_assert_not_reached ();
- }
- }
-
gconf_client = gconf_client_get_default ();
gconf_client_add_dir (gconf_client, KEY_GNOME_DIR,
GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
@@ -350,9 +289,9 @@ yelp_settings_get_icon (YelpIconType icon)
g_return_val_if_fail (icon < YELP_NUM_ICONS, NULL);
- info = gtk_icon_theme_lookup_icon (icon_theme,
+ /*info = gtk_icon_theme_lookup_icon (icon_theme,
icon_names[icon],
- 36, 0);
+ 36, 0);*/
return info;
}
@@ -665,68 +604,71 @@ settings_update (YelpSettingsType type)
color->blue >> 8);
if (color != &blue)
gdk_color_free (color);
+
+ color = NULL;
+ gtk_widget_style_get (widget, "visited-link-color", &color, NULL);
+ if (color) {
+ g_snprintf (colors[YELP_COLOR_ANCHOR], 8,
+ "#%02X%02X%02X",
+ color->red >> 8,
+ color->green >> 8,
+ color->blue >> 8);
+ gdk_color_free (color);
+ }
+
gtk_object_sink (GTK_OBJECT (widget));
- /* YELP_COLOR_RULE */
- g_snprintf (colors[YELP_COLOR_RULE], 8,
+ /* YELP_COLOR_FG_LIGHT */
+ g_snprintf (colors[YELP_COLOR_FG_LIGHT], 8,
"#%02X%02X%02X",
- ((style->base[GTK_STATE_NORMAL].red >> 8) +
- (style->bg[GTK_STATE_NORMAL].red >> 8) ) / 2,
- ((style->base[GTK_STATE_NORMAL].green >> 8) +
- (style->bg[GTK_STATE_NORMAL].green >> 8) ) / 2,
- ((style->base[GTK_STATE_NORMAL].blue >> 8) +
- (style->bg[GTK_STATE_NORMAL].blue >> 8) ) / 2);
-
- /* YELP_COLOR_GRAY_BG */
- for (i = 0; i < 4; i++) {
- rval = ((4 - i) * (style->bg[GTK_STATE_NORMAL].red >> 8) +
- i * max_text) / 4;
- gval = ((4 - i) * (style->bg[GTK_STATE_NORMAL].green >> 8) +
- i * max_text) / 4;
- bval = ((4 - i) * (style->bg[GTK_STATE_NORMAL].blue >> 8) +
- i * max_text) / 4;
+ style->text[GTK_STATE_PRELIGHT].red >> 8,
+ style->text[GTK_STATE_PRELIGHT].green >> 8,
+ style->text[GTK_STATE_PRELIGHT].blue >> 8);
+
+ /* YELP_COLOR_GRAY_BG and border */
+ for (i = 0; i < 2; i++) {
+ rval = ((2 - i) * (style->bg[GTK_STATE_NORMAL].red >> 8) +
+ i * max_text) / 2;
+ gval = ((2 - i) * (style->bg[GTK_STATE_NORMAL].green >> 8) +
+ i * max_text) / 2;
+ bval = ((2 - i) * (style->bg[GTK_STATE_NORMAL].blue >> 8) +
+ i * max_text) / 2;
g_snprintf (colors[YELP_COLOR_GRAY_BG + i], 8,
"#%02X%02X%02X", rval, gval, bval);
}
- /* YELP_COLOR_GRAY_FG */
- g_snprintf (colors[YELP_COLOR_GRAY_FG], 8, "%s",
- colors[YELP_COLOR_GRAY_BG_DARK3]);
-
- /* YELP_COLOR_SELECTED_FG */
- g_snprintf (colors[YELP_COLOR_SELECTED_FG], 8,
- "#%02X%02X%02X",
- style->text[GTK_STATE_SELECTED].red >> 8,
- style->text[GTK_STATE_SELECTED].green >> 8,
- style->text[GTK_STATE_SELECTED].blue >> 8);
-
- /* YELP_COLOR_SELECTED_BG */
- for (i = 0; i < 4; i++) {
- rval = ((4 - i) * (style->bg[GTK_STATE_SELECTED].red >> 8) +
- i * max_text) / 4;
- gval = ((4 - i) * (style->bg[GTK_STATE_SELECTED].green >> 8) +
- i * max_text) / 4;
- bval = ((4 - i) * (style->bg[GTK_STATE_SELECTED].blue >> 8) +
- i * max_text) / 4;
- g_snprintf (colors[YELP_COLOR_SELECTED_BG + i], 8,
+ /* YELP_COLOR_BLUE_BG and border */
+ for (i = 0; i < 2; i++) {
+ rval = (i * max_base) / 2;
+ gval = (i * max_base) / 2;
+ bval = ((2 - i) * (style->bg[GTK_STATE_NORMAL].blue >> 8) +
+ i * max_base) / 2;
+ g_snprintf (colors[YELP_COLOR_BLUE_BG + (2 - i)], 8,
"#%02X%02X%02X", rval, gval, bval);
}
- /* YELP_COLOR_ADMON_FG */
- g_snprintf (colors[YELP_COLOR_ADMON_FG], 8, "%s",
- colors[YELP_COLOR_GRAY_BG_DARK3]);
-
- /* YELP_COLOR_ADMON_BG */
- for (i = 0; i < 4; i++) {
- gint mult = max_base + ((i * (max_base - max_text)) / 3);
- rval = ((255 * mult) / 255);
- gval = ((245 * mult) / 255);
- bval = ((207 * mult) / 255);
+ /* YELP_COLOR_RED_BG and border */
+ for (i = 0; i < 2; i++) {
+ rval = ((2 - i) * (style->bg[GTK_STATE_NORMAL].red >> 8) +
+ i * max_base) / 2;
+ gval = (i * max_base) / 2;
+ bval = (i * max_base) / 2;
+ g_snprintf (colors[YELP_COLOR_RED_BG + (2 - i)], 8,
+ "#%02X%02X%02X", rval, gval, bval);
+ }
- g_snprintf (colors[YELP_COLOR_ADMON_BG + i], 8,
+ /* YELP_COLOR_YELLOW_BG and border */
+ for (i = 0; i < 2; i++) {
+ rval = ((2 - i) * (style->bg[GTK_STATE_NORMAL].red >> 8) +
+ i * max_base) / 2;
+ gval = ((2 - i) * (style->bg[GTK_STATE_NORMAL].green >> 8) +
+ i * max_base) / 2;
+ bval = (i * max_base) / 2;
+ g_snprintf (colors[YELP_COLOR_YELLOW_BG + (2 - i)], 8,
"#%02X%02X%02X", rval, gval, bval);
}
+
g_object_unref (G_OBJECT (style));
}
@@ -740,34 +682,27 @@ yelp_settings_params (gchar ***params,
gint *params_i,
gint *params_max)
{
- GtkIconInfo *icon_info;
- gchar *icon_file;
- gint colors_i, icons_i;
+ /*GtkIconInfo *icon_info;
+ gchar *icon_file;*/
+ gint colors_i /*, icons_i*/;
if ((*params_i + 2 * (YELP_NUM_COLORS + YELP_NUM_ICONS)) >= *params_max) {
*params_max += 2 * (YELP_NUM_COLORS + YELP_NUM_ICONS);
*params = g_renew (gchar *, *params, *params_max);
}
- for (colors_i = 0; colors_i < YELP_NUM_COLORS; colors_i++) {
+ for (colors_i = 0; colors_i < YELP_NUM_COLORS - 1; colors_i++) {
(*params)[(*params_i)++] = (gchar *) color_params[colors_i];
(*params)[(*params_i)++] = g_strdup_printf ("\"%s\"",
yelp_settings_get_color (colors_i));
}
- for (icons_i = 0; icons_i < YELP_NUM_ICONS; icons_i++) {
- (*params)[(*params_i)++] = (gchar *) icon_params[icons_i];
-
- icon_info = yelp_settings_get_icon (icons_i);
- if (icon_info) {
- icon_file = (gchar *) gtk_icon_info_get_filename (icon_info);
- if (icon_file)
- (*params)[(*params_i)++] = g_strdup_printf ("\"%s\"", icon_file);
- else
- (*params)[(*params_i)++] = g_strdup ("\"\"");
- gtk_icon_info_free (icon_info);
- } else {
- (*params)[(*params_i)++] = g_strdup ("\"\"");
- }
- }
+ /* Icon Path */
+ (*params)[(*params_i)++] = (gchar *) icon_params[0];
+ (*params)[(*params_i)++] = (gchar *) g_strdup_printf ("\"%s\"", GDU_ICON_PATH);
+
+ /* Icon Size */
+ (*params)[(*params_i)++] = (gchar *) icon_params[1];
+ (*params)[(*params_i)++] = (gchar *) g_strdup_printf ("\"%d\"", 48);
+
}
diff --git a/src/yelp-settings.h b/src/yelp-settings.h
index 8d6f1a30..6c3cf97d 100644
--- a/src/yelp-settings.h
+++ b/src/yelp-settings.h
@@ -53,34 +53,24 @@ typedef enum {
typedef enum {
YELP_COLOR_FG = 0,
YELP_COLOR_BG,
+ YELP_COLOR_FG_LIGHT,
YELP_COLOR_ANCHOR,
- YELP_COLOR_RULE,
- YELP_COLOR_GRAY_FG,
+ YELP_COLOR_ANCHOR_VISITED,
YELP_COLOR_GRAY_BG,
- YELP_COLOR_GRAY_BG_DARK1,
- YELP_COLOR_GRAY_BG_DARK2,
- YELP_COLOR_GRAY_BG_DARK3,
- YELP_COLOR_SELECTED_FG,
- YELP_COLOR_SELECTED_BG,
- YELP_COLOR_SELECTED_BG_DARK1,
- YELP_COLOR_SELECTED_BG_DARK2,
- YELP_COLOR_SELECTED_BG_DARK3,
- YELP_COLOR_ADMON_FG,
- YELP_COLOR_ADMON_BG,
- YELP_COLOR_ADMON_BG_DARK1,
- YELP_COLOR_ADMON_BG_DARK2,
- YELP_COLOR_ADMON_BG_DARK3,
+ YELP_COLOR_GRAY_BORDER,
+ YELP_COLOR_BLUE_BG,
+ YELP_COLOR_BLUE_BORDER,
+ YELP_COLOR_RED_BG,
+ YELP_COLOR_RED_BORDER,
+ YELP_COLOR_YELLOW_BG,
+ YELP_COLOR_YELLOW_BORDER,
+ YELP_FORCE,
YELP_NUM_COLORS
} YelpColorType;
typedef enum {
- YELP_ICON_BLOCKQUOTE = 0,
- YELP_ICON_CAUTION,
- YELP_ICON_IMPORTANT,
- YELP_ICON_NOTE,
- YELP_ICON_PROGRAMLISTING,
- YELP_ICON_TIP,
- YELP_ICON_WARNING,
+ YELP_ICON_ADMON_PATH,
+ YELP_ICON_ADMON_SIZE,
YELP_NUM_ICONS
} YelpIconType;
diff --git a/src/yelp-toc-pager.c b/src/yelp-toc-pager.c
index 0f1a1852..624a6ebf 100644
--- a/src/yelp-toc-pager.c
+++ b/src/yelp-toc-pager.c
@@ -45,6 +45,10 @@
#include <libxslt/extensions.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/xsltutils.h>
+#include <spoon.h>
+#include <spoon-reg-utils.h>
+#include <spoon-info.h>
+#include <spoon-man.h>
#include "yelp-debug.h"
#include "yelp-error.h"
@@ -122,6 +126,7 @@ static gboolean toc_process_pending (YelpTocPager *pager);
static gboolean process_read_menu (YelpTocPager *pager);
+static gboolean process_xslt (YelpTocPager *pager);
static gboolean process_read_scrollkeeper (YelpTocPager *pager,
gchar *content_list);
static gboolean process_omf_pending (YelpTocPager *pager);
@@ -460,13 +465,14 @@ toc_process_pending (YelpTocPager *pager)
YelpTocPagerPriv *priv = pager->priv;
static ProcessFunction process_funcs[] = {
process_read_menu,
- process_omf_pending,
+ /*process_omf_pending,*/
#ifdef ENABLE_MAN
process_mandir_pending,
#endif
#ifdef ENABLE_INFO
process_info_pending,
#endif
+ /* process_xslt, */
process_cleanup,
NULL
};
@@ -565,7 +571,7 @@ sk_characters (void *pager,
static gboolean
process_read_scrollkeeper (YelpTocPager *pager, gchar *content_list)
{
- static xmlSAXHandler sk_sax_handler = { NULL, };
+ static xmlSAXHandler sk_sax_handler = { 0, };
if (!sk_sax_handler.startElement) {
sk_sax_handler.startElement = sk_startElement;
@@ -811,13 +817,12 @@ process_omf_pending (YelpTocPager *pager)
* it doesn't exist, then we create a list of omf files to process
* with the process_read_scrollkeeper() function */
if (first_call) {
- const gchar * const * langs = g_get_language_names ();
-
first_call = FALSE;
sk_file = g_build_filename (yelp_dot_dir(), "sk-content-list.last", NULL);
/* get current language */
+ const gchar * const * langs = g_get_language_names ();
if (langs && langs[0])
lang = (gchar *) langs[0];
else
@@ -1326,9 +1331,65 @@ create_toc_from_index (YelpTocPager *pager, gchar *index_file)
return 1;
}
+static int
+spoon_add_man_document (SpoonManEntry *entry, void *user_data)
+{
+ xmlNodePtr node = (xmlNodePtr) user_data;
+ xmlNodePtr new;
+ gchar tmp[255];
+ new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL);
+ g_sprintf (&tmp, "man:%s", entry->path);
+
+ xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST tmp);
+ xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST entry->name);
+ if (entry->comment)
+ xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST entry->comment);
+ return TRUE;
+}
+
static gboolean
process_mandir_pending (YelpTocPager *pager)
{
+ xmlNodePtr node = NULL;
+ xmlNodePtr cat_node = NULL;
+ xmlNodePtr mynode = NULL;
+ char **categories = NULL;
+ char **cat_iter = NULL;
+ int sectno = 0;
+ YelpTocPagerPriv * priv = pager->priv;
+ int i, j;
+ xmlXPathContextPtr xpath;
+ xmlXPathObjectPtr obj;
+
+ priv->man_doc = xmlCtxtReadFile (priv->parser, DATADIR "/yelp/man.xml", NULL,
+ XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NOERROR |
+ XML_PARSE_NONET );
+
+ xpath = xmlXPathNewContext (priv->man_doc);
+ obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath);
+
+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+ xmlNodePtr node = obj->nodesetval->nodeTab[i];
+ xmlChar *sect = xmlGetProp (node, BAD_CAST "sect");
+
+ if (sect) {
+ gchar **sects = g_strsplit ((gchar *)sect, " ", 0);
+
+ cat_node = xmlNewChild (node, NULL, BAD_CAST "toc",
+ NULL);
+ for (j = 0; sects[j] != NULL; j++)
+ spoon_man_for_each_in_category (sects[j], spoon_add_man_document, node);
+ g_strfreev (sects);
+ }
+ xmlFree (sect);
+ xml_trim_titles (node, BAD_CAST "title");
+ xml_trim_titles (node, BAD_CAST "description");
+ }
+ xmlXPathFreeObject (obj);
+ xmlXPathFreeContext (xpath);
+
+#if 0
static gchar *index_file = NULL;
gchar *filename = NULL;
gchar *dirname = NULL;
@@ -1341,6 +1402,7 @@ process_mandir_pending (YelpTocPager *pager)
xmlXPathContextPtr xpath;
xmlXPathObjectPtr obj;
+ /* NOTE: this document is free()'d at the end of the process_xslt function */
priv->man_doc = xmlCtxtReadFile (priv->parser, DATADIR "/yelp/man.xml", NULL,
XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA |
XML_PARSE_NOENT | XML_PARSE_NOERROR |
@@ -1606,13 +1668,103 @@ process_mandir_pending (YelpTocPager *pager)
}
return TRUE;
+#endif
+
+ mynode = xmlCopyNode (xmlDocGetRootElement (priv->man_doc), 1);
+ xmlAddChild (xmlDocGetRootElement (priv->toc_doc), mynode);
+
+ xmlFreeDoc (priv->man_doc);
+
+ return FALSE;
}
#endif // ENABLE_MAN
#ifdef ENABLE_INFO
+
+static int
+spoon_info_add_document (SpoonInfoEntry *entry, void *user_data)
+{
+ xmlNodePtr node = (xmlNodePtr) user_data;
+ xmlNodePtr new;
+ gchar tmp[255];
+ new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL);
+ if (entry->section)
+ g_sprintf(&tmp, "info:%s#%s", entry->name, entry->section);
+ else
+ g_sprintf(&tmp, "info:%s", entry->name);
+ xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST tmp);
+ xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST entry->name);
+ xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST entry->comment);
+ return TRUE;
+
+}
+
+
static gboolean
process_info_pending (YelpTocPager *pager)
{
+ xmlNodePtr node = NULL;
+ xmlNodePtr cat_node = NULL;
+ xmlNodePtr mynode = NULL;
+ char **categories = NULL;
+ char **cat_iter = NULL;
+ int sectno = 0;
+ YelpTocPagerPriv * priv = pager->priv;
+ int i;
+ xmlXPathContextPtr xpath;
+ xmlXPathObjectPtr obj;
+
+ priv->info_doc = xmlCtxtReadFile (priv->parser,
+ DATADIR "/yelp/info.xml", NULL,
+ XML_PARSE_NOBLANKS |
+ XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT |
+ XML_PARSE_NOERROR |
+ XML_PARSE_NONET );
+
+ xpath = xmlXPathNewContext (priv->info_doc);
+ obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath);
+ node = obj->nodesetval->nodeTab[0];
+ for (i=0; i < obj->nodesetval->nodeNr; i++) {
+ xmlNodePtr tmpnode = obj->nodesetval->nodeTab[i];
+ xml_trim_titles (tmpnode, BAD_CAST "title");
+ xml_trim_titles (tmpnode, BAD_CAST "description");
+ }
+ xmlXPathFreeObject (obj);
+ xmlXPathFreeContext (xpath);
+
+ categories = spoon_info_get_categories ();
+ cat_iter = categories;
+
+ while (cat_iter && *cat_iter) {
+ char *tmp;
+
+ cat_node = xmlNewChild (node, NULL, BAD_CAST "toc",
+ NULL);
+ tmp = g_strdup_printf ("%d", sectno);
+ xmlNewNsProp (cat_node, NULL, BAD_CAST "sect",
+ BAD_CAST tmp);
+ g_free (tmp);
+ tmp = g_strdup_printf ("infosect%d", sectno);
+ xmlNewNsProp (cat_node, NULL, BAD_CAST "id",
+ BAD_CAST tmp);
+ g_free (tmp);
+ sectno++;
+ xmlNewTextChild (cat_node, NULL, BAD_CAST "title",
+ BAD_CAST *cat_iter);
+
+ spoon_info_for_each_in_category (*cat_iter, spoon_info_add_document,
+ cat_node);
+ cat_iter++;
+ }
+
+ mynode = xmlCopyNode (xmlDocGetRootElement (priv->info_doc), 1);
+ xmlAddChild (xmlDocGetRootElement (priv->toc_doc), mynode);
+
+ xmlFreeDoc (priv->info_doc);
+
+
+#if 0
gchar ** info_paths = yelp_get_info_paths ();
int i = 0;
gchar *filename = NULL;
@@ -1625,7 +1777,7 @@ process_info_pending (YelpTocPager *pager)
YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv;
xmlNodePtr node = NULL;
-
+ printf ("Info parsing\n");
for (i=0; info_paths[i]; i++) {
filename = g_strconcat (info_paths[i], "/dir", NULL);
@@ -1790,10 +1942,28 @@ process_info_pending (YelpTocPager *pager)
xmlFreeDoc (priv->info_doc);
+#endif
return FALSE;
}
#endif /* ENABLE_INFO */
+static int
+spoon_add_document (void *reg, void * user_data)
+{
+ xmlNodePtr node = (xmlNodePtr) user_data;
+ SpoonReg *r = (SpoonReg *) reg;
+ xmlNodePtr new;
+ gchar tmp[10];
+
+ new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL);
+ xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST r->uri);
+ xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST r->name);
+ xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST r->comment);
+ g_sprintf (&tmp, "%d", r->weight);
+ xmlNewNsProp (new, NULL, BAD_CAST "weight", BAD_CAST tmp);
+ return FALSE;
+}
+
static gboolean
process_read_menu (YelpTocPager *pager)
{
@@ -1906,9 +2076,12 @@ process_read_menu (YelpTocPager *pager)
BAD_CAST "subject")) {
xmlChar *cat = xmlTextReaderGetAttribute (reader,
BAD_CAST "category");
- g_hash_table_insert (priv->category_hash,
+ /*g_hash_table_insert (priv->category_hash,
g_strdup ((gchar *) cat),
- node);
+ node);*/
+ spoon_for_each_in_category (spoon_add_document,
+ (char *) cat,
+ (void *) node);
xmlFree (cat);
}
else if (!xmlStrcmp (xmlTextReaderConstLocalName (reader),
@@ -1931,6 +2104,92 @@ process_read_menu (YelpTocPager *pager)
}
static gboolean
+process_xslt (YelpTocPager *pager)
+{
+ GError *error = NULL;
+ xmlDocPtr outdoc = NULL;
+ YelpTocPagerPriv *priv = pager->priv;
+ gchar **params = NULL;
+ gint params_i = 0;
+ gint params_max = 10;
+ GtkIconInfo *info;
+ GtkIconTheme *theme = (GtkIconTheme *) yelp_settings_get_icon_theme ();
+
+ if (!priv->toc_doc)
+ return FALSE;
+
+ /* only create and parse the stylesheet on the first call to this function */
+ if (!priv->stylesheet) {
+ priv->stylesheet = xsltParseStylesheetFile (BAD_CAST TOC_STYLESHEET);
+ }
+
+ if (!priv->stylesheet) {
+ g_set_error (&error, YELP_ERROR, YELP_ERROR_PROC,
+ _("The table of contents could not be processed. The "
+ "file ‘%s’ is either missing or is not a valid XSLT "
+ "stylesheet."),
+ TOC_STYLESHEET);
+ yelp_pager_error (YELP_PAGER (pager), error);
+ goto done;
+ }
+
+ priv->transformContext = xsltNewTransformContext (priv->stylesheet,
+ priv->toc_doc);
+ priv->transformContext->_private = pager;
+ xsltRegisterExtElement (priv->transformContext,
+ BAD_CAST "document",
+ BAD_CAST YELP_NAMESPACE,
+ (xsltTransformFunction) xslt_yelp_document);
+
+ params = g_new0 (gchar *, params_max);
+ yelp_settings_params (&params, &params_i, &params_max);
+
+ if ((params_i + 10) >= params_max - 1) {
+ params_max += 10;
+ params = g_renew (gchar *, params, params_max);
+ }
+
+ info = gtk_icon_theme_lookup_icon (theme, "yelp-icon-big", 192, 0);
+ if (info) {
+ params[params_i++] = "help_icon";
+ params[params_i++] = g_strdup_printf ("\"%s\"",
+ gtk_icon_info_get_filename (info));
+ params[params_i++] = "help_icon_size";
+ params[params_i++] = g_strdup_printf ("%i",
+ gtk_icon_info_get_base_size (info));
+ gtk_icon_info_free (info);
+ }
+
+ params[params_i++] = NULL;
+
+ outdoc = xsltApplyStylesheetUser (priv->stylesheet,
+ priv->toc_doc,
+ (const gchar **)params, NULL, NULL,
+ priv->transformContext);
+ /* Don't do this */
+ g_signal_emit_by_name (pager, "finish");
+
+ done:
+ if (params) {
+ for (params_i = 0; params[params_i] != NULL; params_i++)
+ if (params_i % 2 == 1)
+ g_free ((gchar *) params[params_i]);
+ }
+ if (outdoc)
+ xmlFreeDoc (outdoc);
+ if (priv->toc_doc) {
+ xmlFreeDoc (priv->toc_doc);
+ priv->toc_doc = NULL;
+ }
+ if (priv->transformContext) {
+ xsltFreeTransformContext (priv->transformContext);
+ priv->transformContext = NULL;
+ }
+
+ return FALSE;
+}
+
+static gboolean
process_cleanup (YelpTocPager *pager)
{
YelpTocPagerPriv *priv = pager->priv;
@@ -1974,8 +2233,7 @@ toc_add_doc_info (YelpTocPager *pager, YelpDocInfo *doc_info)
xmlNodePtr node;
xmlNodePtr new;
gchar *text;
- const gchar *category;
- YelpTocPagerPriv *priv = pager->priv;
+ gchar *category;
g_return_if_fail (pager != NULL);
if (doc_info == NULL)
@@ -1990,6 +2248,8 @@ toc_add_doc_info (YelpTocPager *pager, YelpDocInfo *doc_info)
return;
}
+ YelpTocPagerPriv *priv = pager->priv;
+
g_hash_table_insert (priv->unique_hash,
(gchar *) yelp_doc_info_get_id (doc_info),
doc_info);
diff --git a/src/yelp-toc.c b/src/yelp-toc.c
new file mode 100644
index 00000000..973aa12a
--- /dev/null
+++ b/src/yelp-toc.c
@@ -0,0 +1,833 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ * 2007 Don Scorgie <Don@Scorgie.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ * Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xinclude.h>
+#include <libxml/xmlreader.h>
+#include <rarian.h>
+#include <rarian-info.h>
+#include <rarian-man.h>
+
+#include "yelp-error.h"
+#include "yelp-toc.h"
+#include "yelp-settings.h"
+#include "yelp-transform.h"
+#include "yelp-debug.h"
+
+#define STYLESHEET DATADIR"/yelp/xslt/toc2html.xsl"
+
+#define YELP_TOC_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_TOC, YelpTocPriv))
+
+typedef enum {
+ TOC_STATE_BLANK, /* Brand new, run transform as needed */
+ TOC_STATE_PARSING, /* Parsing/transforming document, please wait */
+ TOC_STATE_PARSED, /* All done, if we ain't got it, it ain't here */
+ TOC_STATE_STOP /* Stop everything now, object to be disposed */
+} TocState;
+
+struct _YelpTocPriv {
+ TocState state;
+
+ GMutex *mutex;
+ GThread *thread;
+
+ gboolean process_running;
+ gboolean transform_running;
+ gboolean man_processed;
+ gboolean info_processed;
+
+ YelpTransform *transform;
+
+ xmlDocPtr xmldoc;
+ xmlNodePtr xmlcur;
+ gchar *cur_page_id;
+ gchar *cur_prev_id;
+};
+
+
+static YelpDocument *toc_doc = NULL;
+
+static void toc_class_init (YelpTocClass *klass);
+static void toc_init (YelpToc *toc);
+static void toc_try_dispose (GObject *object);
+static void toc_dispose (GObject *object);
+
+/* YelpDocument */
+static void toc_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+
+/* YelpTransform */
+static void transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpToc *toc);
+static void transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpToc *toc);
+static void transform_final_func (YelpTransform *transform,
+ YelpToc *toc);
+
+/* Threaded */
+static void toc_process (YelpToc *toc);
+static void toc_process_info (YelpToc *toc);
+static void toc_process_man (YelpToc *toc);
+static void xml_trim_titles (xmlNodePtr node,
+ xmlChar * nodetype);
+
+static YelpDocumentClass *parent_class;
+
+GType
+yelp_toc_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpTocClass),
+ NULL, NULL,
+ (GClassInitFunc) toc_class_init,
+ NULL, NULL,
+ sizeof (YelpToc),
+ 0,
+ (GInstanceInitFunc) toc_init,
+ };
+ type = g_type_register_static (YELP_TYPE_DOCUMENT,
+ "YelpToc",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+toc_class_init (YelpTocClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = toc_try_dispose;
+
+ document_class->request = toc_request;
+ document_class->cancel = NULL;
+
+ g_type_class_add_private (klass, sizeof (YelpTocPriv));
+}
+
+static void
+toc_init (YelpToc *toc)
+{
+ YelpTocPriv *priv;
+ priv = toc->priv = YELP_TOC_GET_PRIVATE (toc);
+
+ priv->state = TOC_STATE_BLANK;
+
+ priv->man_processed = FALSE;
+ priv->info_processed = FALSE;
+
+ priv->mutex = g_mutex_new ();
+}
+
+static void
+toc_try_dispose (GObject *object)
+{
+ YelpTocPriv *priv;
+
+ g_assert (object != NULL && YELP_IS_TOC (object));
+
+ priv = YELP_TOC (object)->priv;
+
+ g_mutex_lock (priv->mutex);
+ if (priv->process_running || priv->transform_running) {
+ priv->state = TOC_STATE_STOP;
+ g_idle_add ((GSourceFunc) toc_try_dispose, object);
+ g_mutex_unlock (priv->mutex);
+ } else {
+ g_mutex_unlock (priv->mutex);
+ toc_dispose (object);
+ }
+}
+
+static void
+toc_dispose (GObject *object)
+{
+ YelpToc *toc = YELP_TOC (object);
+
+ if (toc->priv->xmldoc)
+ xmlFreeDoc (toc->priv->xmldoc);
+
+ g_free (toc->priv->cur_page_id);
+ g_free (toc->priv->cur_prev_id);
+
+ g_mutex_free (toc->priv->mutex);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_toc_new (void)
+{
+ debug_print (DB_FUNCTION, "entering\n");
+
+ if (toc_doc == NULL) {
+ toc_doc = (YelpDocument *) g_object_new (YELP_TYPE_TOC, NULL);
+ }
+
+ return (YelpDocument *) toc_doc;
+}
+
+YelpDocument *
+yelp_toc_get (void)
+{
+ debug_print (DB_FUNCTION, "entering\n");
+
+ if (toc_doc == NULL) {
+ toc_doc = (YelpDocument *) g_object_new (YELP_TYPE_TOC, NULL);
+ }
+
+ return (YelpDocument *) toc_doc;
+}
+
+
+/******************************************************************************/
+/** YelpDocument **************************************************************/
+
+static void
+toc_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpToc *toc;
+ YelpTocPriv *priv;
+ YelpError *error;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " req_id = %i\n", req_id);
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+
+ g_assert (document != NULL && YELP_IS_TOC (document));
+
+ if (handled)
+ return;
+
+ toc = YELP_TOC (document);
+ priv = toc->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ switch (priv->state) {
+ case TOC_STATE_BLANK:
+ priv->state = TOC_STATE_PARSING;
+ priv->process_running = TRUE;
+ priv->thread = g_thread_create ((GThreadFunc) toc_process,
+ toc, FALSE, NULL);
+ break;
+ case TOC_STATE_PARSING:
+ break;
+ case TOC_STATE_PARSED:
+ case TOC_STATE_STOP:
+ error = yelp_error_new (_("Page not found"),
+ _("The page %s was not found in the TOC."),
+ page_id);
+ yelp_document_error_request (document, req_id, error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpToc *toc)
+{
+ YelpTocPriv *priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (toc != NULL && YELP_IS_TOC (toc));
+
+ priv = toc->priv;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == TOC_STATE_STOP) {
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ g_free (func_data);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_error_free ((YelpError *) func_data);
+ break;
+ case YELP_TRANSFORM_FINAL:
+ break;
+ }
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ return;
+ }
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ transform_page_func (transform, (gchar *) func_data, toc);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_document_error_pending (YELP_DOCUMENT (toc), (YelpError *) func_data);
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ break;
+ case YELP_TRANSFORM_FINAL:
+ transform_final_func (transform, toc);
+ break;
+ }
+}
+
+static void
+transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpToc *toc)
+{
+ YelpTocPriv *priv;
+ gchar *content;
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = toc->priv;
+ g_mutex_lock (priv->mutex);
+
+ content = yelp_transform_eat_chunk (transform, page_id);
+
+#if 0 /* Used for debugging */
+ gchar * filename = NULL;
+ filename = g_strdup_printf ("out/%s.html", page_id);
+ g_file_set_contents (filename, content, -1, NULL);
+#endif
+
+ yelp_document_add_page (YELP_DOCUMENT (toc), page_id, content);
+
+ g_free (page_id);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+static void
+transform_final_func (YelpTransform *transform, YelpToc *toc)
+{
+ YelpError *error;
+ YelpTocPriv *priv = toc->priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ g_mutex_lock (priv->mutex);
+
+ error = yelp_error_new (_("Page not found"),
+ _("The requested page was not found in the TOC."));
+ yelp_document_error_pending (YELP_DOCUMENT (toc), error);
+
+ yelp_transform_release (priv->transform);
+ priv->transform = NULL;
+
+ priv->transform_running = FALSE;
+
+ if (priv->xmldoc) {
+ xmlFreeDoc (priv->xmldoc);
+ }
+ priv->xmldoc = NULL;
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** Threaded ******************************************************************/
+
+static int
+rrn_add_document (void *reg, void * user_data)
+{
+ xmlNodePtr node = (xmlNodePtr) user_data;
+ RrnReg *r = (RrnReg *) reg;
+ xmlNodePtr new;
+ gchar *tmp;
+ new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL);
+ xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST r->uri);
+ xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST r->name);
+ xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST r->comment);
+ tmp = g_strdup_printf ("%d", r->weight);
+ xmlNewNsProp (new, NULL, BAD_CAST "weight", BAD_CAST tmp);
+ g_free (tmp);
+ return FALSE;
+}
+
+static void
+toc_process (YelpToc *toc)
+{
+ YelpTocPriv *priv;
+ YelpError *error = NULL;
+ xmlParserCtxtPtr parserCtxt = NULL;
+ YelpDocument *document;
+ gint params_i = 0;
+ gint params_max = 10;
+ gchar **params = NULL;
+ GtkIconInfo *info = NULL ;
+ GtkIconTheme *theme = (GtkIconTheme *) yelp_settings_get_icon_theme ();
+
+ GThread *info_thread;
+ GThread *man_thread;
+ xmlTextReaderPtr reader;
+ xmlXPathContextPtr xpath;
+ xmlXPathObjectPtr obj;
+ gint i, ret;
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (toc != NULL && YELP_IS_TOC (toc));
+ g_object_ref (toc);
+ priv = toc->priv;
+ document = YELP_DOCUMENT (toc);
+
+ parserCtxt = xmlNewParserCtxt ();
+ priv->xmldoc = xmlCtxtReadFile (parserCtxt,
+ (const char *) DATADIR "/yelp/toc.xml", NULL,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+
+ if (priv->xmldoc == NULL) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The ‘âTOC file€™ "
+ "could not be parsed because it is"
+ " not a well-formed XML document."));
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ xpath = xmlXPathNewContext (priv->xmldoc);
+ obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath);
+
+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+ xmlNodePtr node = obj->nodesetval->nodeTab[i];
+ xmlChar *icon = NULL;
+
+ xml_trim_titles (node, BAD_CAST "title");
+ xml_trim_titles (node, BAD_CAST "description");
+
+ icon = xmlGetProp (node, BAD_CAST "icon");
+ if (icon) {
+ info = gtk_icon_theme_lookup_icon (theme, (gchar *) icon, 48, 0);
+ if (info) {
+ xmlNodePtr new = xmlNewChild (node, NULL, BAD_CAST "icon",
+ NULL);
+ xmlNewNsProp (new, NULL, BAD_CAST "file",
+ BAD_CAST gtk_icon_info_get_filename (info));
+ gtk_icon_info_free (info);
+ }
+ }
+ xmlFree (icon);
+
+ }
+ xmlXPathFreeObject (obj);
+
+ reader = xmlReaderForFile (DATADIR "/yelp/scrollkeeper.xml", NULL,
+ XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NOERROR |
+ XML_PARSE_NONET );
+ ret = xmlTextReaderRead (reader);
+ while (ret == 1) {
+ if (!xmlStrcmp (xmlTextReaderConstLocalName (reader),
+ BAD_CAST "toc")) {
+ xmlChar *id = xmlTextReaderGetAttribute (reader, BAD_CAST "id");
+ xmlNodePtr node;
+ gchar *xpath_s;
+ if (!id) {
+ ret = xmlTextReaderRead (reader);
+ continue;
+ }
+
+ g_mutex_lock (priv->mutex);
+
+ yelp_document_add_page_id (YELP_DOCUMENT (toc), (gchar *) id, (gchar *) id);
+ g_mutex_unlock (priv->mutex);
+ xpath_s = g_strdup_printf ("//toc[@id = '%s']", id);
+ obj = xmlXPathEvalExpression (BAD_CAST xpath_s, xpath);
+ g_free (xpath_s);
+
+ node = obj->nodesetval->nodeTab[0];
+ xmlXPathFreeObject (obj);
+
+ ret = xmlTextReaderRead (reader);
+ while (ret == 1) {
+ if (!xmlStrcmp (xmlTextReaderConstLocalName (reader),
+ BAD_CAST "subject")) {
+ xmlChar *cat = xmlTextReaderGetAttribute (reader,
+ BAD_CAST "category");
+ rrn_for_each_in_category (rrn_add_document,
+ (char *) cat,
+ (void *) node);
+ xmlFree (cat);
+ }
+ else if (!xmlStrcmp (xmlTextReaderConstLocalName (reader),
+ BAD_CAST "toc")) {
+ break;
+ }
+ ret = xmlTextReaderRead (reader);
+ }
+
+ xmlFree (id);
+ ret = xmlTextReaderRead (reader);
+ } else {
+ ret = xmlTextReaderRead (reader);
+ }
+ }
+ xmlFreeTextReader (reader);
+ xmlXPathFreeContext (xpath);
+
+
+ man_thread = g_thread_create ((GThreadFunc) toc_process_man, toc, TRUE, NULL);
+ if (!man_thread) {
+ g_warning ("Could not create Man page thread");
+ priv->man_processed = TRUE;
+ }
+
+ info_thread = g_thread_create ((GThreadFunc) toc_process_info, toc, TRUE, NULL);
+ if (!info_thread) {
+ g_warning ("Could not create Info page thread");
+ priv->info_processed = TRUE;
+ }
+
+ params = g_new0 (gchar *, params_max);
+ yelp_settings_params (&params, &params_i, &params_max);
+
+ if ((params_i + 10) >= params_max - 1) {
+ params_max += 10;
+ params = g_renew (gchar *, params, params_max);
+ }
+
+ info = gtk_icon_theme_lookup_icon (theme, "yelp-icon-big", 192, 0);
+ if (info) {
+ params[params_i++] = "help_icon";
+ params[params_i++] = g_strdup_printf ("\"%s\"",
+ gtk_icon_info_get_filename (info));
+ params[params_i++] = "help_icon_size";
+ params[params_i++] = g_strdup_printf ("%i",
+ gtk_icon_info_get_base_size (info));
+ gtk_icon_info_free (info);
+ }
+
+ params[params_i] = NULL;
+
+ while (!priv->info_processed || !priv->man_processed) {
+ g_thread_yield ();
+ }
+
+ g_mutex_lock (priv->mutex);
+
+ priv->transform = yelp_transform_new (STYLESHEET,
+ (YelpTransformFunc) transform_func,
+ toc);
+ priv->transform_running = TRUE;
+
+ yelp_transform_start (priv->transform,
+ priv->xmldoc,
+ params);
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ if (parserCtxt)
+ xmlFreeParserCtxt (parserCtxt);
+
+ g_object_unref (toc);
+}
+
+
+static void
+xml_trim_titles (xmlNodePtr node, xmlChar * nodetype)
+{
+ xmlNodePtr cur, keep = NULL;
+ xmlChar *keep_lang = NULL;
+ int j, keep_pri = INT_MAX;
+
+ const gchar * const * langs = g_get_language_names ();
+
+ for (cur = node->children; cur; cur = cur->next) {
+ if (!xmlStrcmp (cur->name, nodetype)) {
+ xmlChar *cur_lang = NULL;
+ int cur_pri = INT_MAX;
+ cur_lang = xmlNodeGetLang (cur);
+ if (cur_lang) {
+ for (j = 0; langs[j]; j++) {
+ if (g_str_equal (cur_lang, langs[j])) {
+ cur_pri = j;
+ break;
+ }
+ }
+ } else {
+ cur_pri = INT_MAX - 1;
+ }
+ if (cur_pri <= keep_pri) {
+ if (keep_lang)
+ xmlFree (keep_lang);
+ keep_lang = cur_lang;
+ keep_pri = cur_pri;
+ keep = cur;
+ } else {
+ if (cur_lang)
+ xmlFree (cur_lang);
+ }
+ }
+ }
+ cur = node->children;
+ while (cur) {
+ xmlNodePtr this = cur;
+ cur = cur->next;
+ if (!xmlStrcmp (this->name, nodetype)) {
+ if (this != keep) {
+ xmlUnlinkNode (this);
+ xmlFreeNode (this);
+ }
+ }
+ }
+ xmlFree (keep_lang);
+}
+
+static int
+rrn_info_add_document (RrnInfoEntry *entry, void *user_data)
+{
+ xmlNodePtr node = (xmlNodePtr) user_data;
+ xmlNodePtr new;
+ gchar *tmp;
+
+ new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL);
+ if (entry->section)
+ tmp = g_strdup_printf("info:%s#%s", entry->name, entry->section);
+ else
+ tmp = g_strdup_printf("info:%s", entry->name);
+ xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST tmp);
+ xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST entry->doc_name);
+ xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST entry->comment);
+ g_free(tmp);
+ return TRUE;
+
+}
+
+static void
+toc_process_info (YelpToc *toc)
+{
+ xmlNodePtr node = NULL;
+ xmlNodePtr cat_node = NULL;
+ xmlNodePtr mynode = NULL;
+ char **categories = NULL;
+ char **cat_iter = NULL;
+ int sectno = 0;
+ YelpTocPriv * priv = toc->priv;
+ int i;
+ xmlXPathContextPtr xpath;
+ xmlXPathObjectPtr obj;
+ xmlDocPtr info_doc;
+ xmlParserCtxtPtr parserCtxt = NULL;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ parserCtxt = xmlNewParserCtxt ();
+
+ info_doc = xmlCtxtReadFile (parserCtxt,
+ DATADIR "/yelp/info.xml", NULL,
+ XML_PARSE_NOBLANKS |
+ XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT |
+ XML_PARSE_NOERROR |
+ XML_PARSE_NONET );
+
+ if (!info_doc) {
+ g_warning ("Could not process info TOC");
+ goto done;
+ }
+
+ g_mutex_lock (priv->mutex);
+ yelp_document_add_page_id (YELP_DOCUMENT (toc), (gchar *) "Info", (gchar *) "Info");
+ g_mutex_unlock (priv->mutex);
+
+ xpath = xmlXPathNewContext (info_doc);
+ obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath);
+ node = obj->nodesetval->nodeTab[0];
+ for (i=0; i < obj->nodesetval->nodeNr; i++) {
+ xmlNodePtr tmpnode = obj->nodesetval->nodeTab[i];
+ xml_trim_titles (tmpnode, BAD_CAST "title");
+ xml_trim_titles (tmpnode, BAD_CAST "description");
+ }
+ xmlXPathFreeObject (obj);
+ xmlXPathFreeContext (xpath);
+
+ categories = rrn_info_get_categories ();
+ cat_iter = categories;
+
+ while (cat_iter && *cat_iter) {
+ char *tmp;
+
+ cat_node = xmlNewChild (node, NULL, BAD_CAST "toc",
+ NULL);
+ tmp = g_strdup_printf ("%d", sectno);
+ xmlNewNsProp (cat_node, NULL, BAD_CAST "sect",
+ BAD_CAST tmp);
+ g_free (tmp);
+ tmp = g_strdup_printf ("infosect%d", sectno);
+ g_mutex_lock (priv->mutex);
+ yelp_document_add_page_id (YELP_DOCUMENT (toc), (gchar *) tmp, (gchar *) tmp);
+ g_mutex_unlock (priv->mutex);
+
+ xmlNewNsProp (cat_node, NULL, BAD_CAST "id",
+ BAD_CAST tmp);
+ g_free (tmp);
+ sectno++;
+ xmlNewTextChild (cat_node, NULL, BAD_CAST "title",
+ BAD_CAST *cat_iter);
+
+ rrn_info_for_each_in_category (*cat_iter, (RrnInfoForeachFunc) rrn_info_add_document,
+ cat_node);
+ cat_iter++;
+ }
+
+ mynode = xmlCopyNode (xmlDocGetRootElement (info_doc), 1);
+
+ g_mutex_lock (priv->mutex);
+ xmlAddChild (xmlDocGetRootElement (priv->xmldoc), mynode);
+ g_mutex_unlock (priv->mutex);
+
+ xmlFreeDoc (info_doc);
+
+
+ done:
+ if (parserCtxt)
+ xmlFreeParserCtxt (parserCtxt);
+ g_mutex_lock (priv->mutex);
+ priv->info_processed = TRUE;
+ g_mutex_unlock (priv->mutex);
+}
+
+static int
+rrn_add_man_document (RrnManEntry *entry, void *user_data)
+{
+ xmlNodePtr node = (xmlNodePtr) user_data;
+ xmlNodePtr new;
+ gchar *tmp;
+
+ new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL);
+ tmp = g_strdup_printf ("man:%s", entry->path);
+
+ xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST tmp);
+ xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST entry->name);
+ if (entry->comment)
+ xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST entry->comment);
+ g_free(tmp);
+
+ return TRUE;
+}
+
+void
+toc_process_man (YelpToc *toc)
+{
+ xmlNodePtr cat_node = NULL;
+ xmlNodePtr mynode = NULL;
+ YelpTocPriv * priv = toc->priv;
+ int i, j;
+ xmlXPathContextPtr xpath;
+ xmlXPathObjectPtr obj;
+ xmlDocPtr man_doc;
+ xmlParserCtxtPtr parserCtxt = NULL;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ parserCtxt = xmlNewParserCtxt ();
+
+ man_doc = xmlCtxtReadFile (parserCtxt, DATADIR "/yelp/man.xml", NULL,
+ XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NOERROR |
+ XML_PARSE_NONET );
+ if (!man_doc) {
+ g_warning ("Could not process man TOC");
+ goto done;
+ }
+
+ xpath = xmlXPathNewContext (man_doc);
+ obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath);
+
+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+ xmlNodePtr node = obj->nodesetval->nodeTab[i];
+ xmlChar *sect = xmlGetProp (node, BAD_CAST "sect");
+ xmlChar *id = xmlGetProp (node, BAD_CAST "id");
+
+ if (sect) {
+ gchar **sects = g_strsplit ((gchar *)sect, " ", 0);
+
+ g_mutex_lock (priv->mutex);
+ yelp_document_add_page_id (YELP_DOCUMENT (toc), (gchar *) id, (gchar *) id);
+ g_mutex_unlock (priv->mutex);
+
+ cat_node = xmlNewChild (node, NULL, BAD_CAST "toc",
+ NULL);
+ for (j = 0; sects[j] != NULL; j++) {
+ rrn_man_for_each_in_category (sects[j], (RrnManForeachFunc) rrn_add_man_document, node);
+ }
+ g_strfreev (sects);
+ }
+ xmlFree (sect);
+ xmlFree (id);
+ xml_trim_titles (node, BAD_CAST "title");
+ xml_trim_titles (node, BAD_CAST "description");
+ }
+ xmlXPathFreeObject (obj);
+ xmlXPathFreeContext (xpath);
+
+ mynode = xmlCopyNode (xmlDocGetRootElement (man_doc), 1);
+
+ g_mutex_lock (priv->mutex);
+ xmlAddChild (xmlDocGetRootElement (priv->xmldoc), mynode);
+ g_mutex_unlock (priv->mutex);
+
+ xmlFreeDoc (man_doc);
+
+ done:
+ if (parserCtxt)
+ xmlFreeParserCtxt (parserCtxt);
+ g_mutex_lock (priv->mutex);
+ priv->man_processed = TRUE;
+ g_mutex_unlock (priv->mutex);
+}
diff --git a/src/yelp-toc.h b/src/yelp-toc.h
new file mode 100644
index 00000000..83b6e919
--- /dev/null
+++ b/src/yelp-toc.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Don Scorgie <Don@Scorgie.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifndef __YELP_TOC_H__
+#define __YELP_TOC_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_TOC (yelp_toc_get_type ())
+#define YELP_TOC(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_TOC, YelpToc))
+#define YELP_TOC_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_TOC, YelpTocClass))
+#define YELP_IS_TOC(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_TOC))
+#define YELP_IS_TOC_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_TOC))
+#define YELP_TOC_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_TOC, YelpTocClass))
+
+typedef struct _YelpToc YelpToc;
+typedef struct _YelpTocClass YelpTocClass;
+typedef struct _YelpTocPriv YelpTocPriv;
+
+struct _YelpToc {
+ YelpDocument parent;
+ YelpTocPriv *priv;
+};
+
+struct _YelpTocClass {
+ YelpDocumentClass parent_class;
+};
+
+GType yelp_toc_get_type (void);
+YelpDocument * yelp_toc_new (void);
+YelpDocument * yelp_toc_get (void);
+
+#endif /* __YELP_TOC_H__ */
diff --git a/src/yelp-transform.c b/src/yelp-transform.c
new file mode 100644
index 00000000..1e6f8f5b
--- /dev/null
+++ b/src/yelp-transform.c
@@ -0,0 +1,416 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xinclude.h>
+#include <libxslt/xslt.h>
+#include <libxslt/templates.h>
+#include <libxslt/transform.h>
+#include <libxslt/extensions.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/xsltutils.h>
+
+#include "yelp-debug.h"
+#include "yelp-error.h"
+#include "yelp-transform.h"
+
+#define YELP_NAMESPACE "http://www.gnome.org/yelp/ns"
+
+static void transform_run (YelpTransform *transform);
+static gboolean transform_free (YelpTransform *transform);
+static void transform_set_error (YelpTransform *transform,
+ YelpError *error);
+
+static gboolean transform_chunk (YelpTransform *transform);
+static gboolean transform_error (YelpTransform *transform);
+static gboolean transform_final (YelpTransform *transform);
+
+static void xslt_yelp_document (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp);
+static void xslt_yelp_cache (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp);
+
+/******************************************************************************/
+
+YelpTransform
+*yelp_transform_new (gchar *stylesheet,
+ YelpTransformFunc func,
+ gpointer user_data)
+{
+ YelpTransform *transform;
+
+ transform = g_new0 (YelpTransform, 1);
+
+ transform->stylesheet = xsltParseStylesheetFile (BAD_CAST stylesheet);
+ if (!transform->stylesheet) {
+ transform->error =
+ yelp_error_new (_("Invalid Stylesheet"),
+ _("The XSLT stylesheet ‘%s’ is either missing, or it is "
+ "not valid."),
+ stylesheet);
+ transform_error (transform);
+ return NULL;
+ }
+
+ transform->func = func;
+
+ transform->queue = g_async_queue_new ();
+ transform->chunks = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+
+ transform->user_data = user_data;
+
+ return transform;
+}
+
+void
+yelp_transform_start (YelpTransform *transform,
+ xmlDocPtr document,
+ gchar **params)
+{
+ transform->inputDoc = document;
+
+ transform->context = xsltNewTransformContext (transform->stylesheet,
+ transform->inputDoc);
+ if (!transform->context) {
+ YelpError *error =
+ yelp_error_new (_("Broken Transformation"),
+ _("An unknown error occurred while attempting to "
+ "transform the document."));
+ transform_set_error (transform, error);
+ return;
+ }
+
+ transform->params = g_strdupv (params);
+
+ transform->context->_private = transform;
+ xsltRegisterExtElement (transform->context,
+ BAD_CAST "document",
+ BAD_CAST YELP_NAMESPACE,
+ (xsltTransformFunction) xslt_yelp_document);
+ xsltRegisterExtElement (transform->context,
+ BAD_CAST "cache",
+ BAD_CAST YELP_NAMESPACE,
+ (xsltTransformFunction) xslt_yelp_cache);
+
+ transform->mutex = g_mutex_new ();
+ g_mutex_lock (transform->mutex);
+ transform->running = TRUE;
+ transform->thread = g_thread_create ((GThreadFunc) transform_run,
+ transform, FALSE, NULL);
+ g_mutex_unlock (transform->mutex);
+}
+
+gchar *
+yelp_transform_eat_chunk (YelpTransform *transform, gchar *chunk_id)
+{
+ gchar *buf;
+
+ g_mutex_lock (transform->mutex);
+
+ buf = g_hash_table_lookup (transform->chunks, chunk_id);
+ if (buf)
+ g_hash_table_remove (transform->chunks, chunk_id);
+
+ g_mutex_unlock (transform->mutex);
+
+ /* The caller assumes ownership of this memory. */
+ return buf;
+}
+
+void
+yelp_transform_release (YelpTransform *transform)
+{
+ g_mutex_lock (transform->mutex);
+ if (transform->running) {
+ /* We can't free it just now, because the thread is running.
+ * Instead, we'll tell libxslt to stop and mark the transform
+ * as released.
+ */
+ transform->released = TRUE;
+ transform->context->state = XSLT_STATE_STOPPED;
+ } else {
+ /* We might still have pending pops from the queue, so just
+ * schedule transform_free.
+ */
+ g_idle_add ((GSourceFunc) transform_free, transform);
+ }
+ g_mutex_unlock (transform->mutex);
+}
+
+/******************************************************************************/
+
+static void
+transform_run (YelpTransform *transform)
+{
+ transform->outputDoc = xsltApplyStylesheetUser (transform->stylesheet,
+ transform->inputDoc,
+ (const char **) transform->params,
+ NULL, NULL,
+ transform->context);
+
+ /* FIXME: do something with outputDoc? */
+ transform->idle_funcs++;
+ g_idle_add ((GSourceFunc) transform_final, transform);
+
+ g_mutex_lock (transform->mutex);
+ transform->running = FALSE;
+ if (transform->released) {
+ /* The transform was released by its owner, but it couldn't
+ * be freed because this thread was running. But we're in
+ * a thread, and the main thread might still be popping stuff
+ * off the asynchronous queue. Schedule this for freeing.
+ */
+ g_idle_add ((GSourceFunc) transform_free, transform);
+ }
+ g_mutex_unlock (transform->mutex);
+}
+
+static gboolean
+transform_free (YelpTransform *transform)
+{
+ gchar *chunk_id;
+
+ /* If the queue isn't empty yet, try again later. But because
+ * threads scare me and I don't want runaway code, stop trying
+ * after an insane number of attempts and just leak.
+ */
+ if (transform->idle_funcs > 0) {
+ transform->free_attempts++;
+ if (transform->free_attempts < 1000) {
+ return TRUE;
+ } else {
+ g_warning ("Runaway free attempt detected. Memory is about to leak.\n");
+ return FALSE;
+ }
+ }
+
+ g_mutex_lock (transform->mutex);
+ if (transform->outputDoc)
+ xmlFreeDoc (transform->outputDoc);
+ if (transform->stylesheet)
+ xsltFreeStylesheet (transform->stylesheet);
+ if (transform->context)
+ xsltFreeTransformContext (transform->context);
+
+ g_strfreev (transform->params);
+
+ /* FIXME: destroy data */
+ while ((chunk_id = (gchar *) g_async_queue_try_pop (transform->queue)))
+ g_free (chunk_id);
+ g_async_queue_unref (transform->queue);
+ g_mutex_unlock (transform->mutex);
+ g_mutex_free (transform->mutex);
+
+ if (transform->error)
+ yelp_error_free (transform->error);
+
+ g_free (transform);
+ return FALSE;
+}
+
+static void
+transform_set_error (YelpTransform *transform,
+ YelpError *error)
+{
+ g_mutex_lock (transform->mutex);
+ if (transform->released) {
+ yelp_error_free (error);
+ g_mutex_unlock (transform->mutex);
+ return;
+ }
+ if (transform->error)
+ yelp_error_free (transform->error);
+ transform->error = error;
+ transform->idle_funcs++;
+ g_idle_add ((GSourceFunc) transform_error, transform);
+ g_mutex_unlock (transform->mutex);
+}
+
+static gboolean
+transform_chunk (YelpTransform *transform)
+{
+ gchar *chunk_id;
+
+ transform->idle_funcs--;
+ if (transform->released)
+ return FALSE;
+
+ chunk_id = (gchar *) g_async_queue_try_pop (transform->queue);
+
+ if (chunk_id) {
+ if (transform->func)
+ transform->func (transform,
+ YELP_TRANSFORM_CHUNK,
+ chunk_id,
+ transform->user_data);
+ else
+ g_free (chunk_id);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+transform_error (YelpTransform *transform)
+{
+ YelpError *error;
+
+ transform->idle_funcs--;
+ if (transform->released)
+ return FALSE;
+
+ g_mutex_lock (transform->mutex);
+
+ error = transform->error;
+ transform->error = NULL;
+
+ g_mutex_unlock (transform->mutex);
+
+ if (transform->func)
+ transform->func (transform,
+ YELP_TRANSFORM_ERROR,
+ error, transform->user_data);
+ else
+ yelp_error_free (error);
+
+ return FALSE;
+}
+
+static gboolean
+transform_final (YelpTransform *transform)
+{
+ transform->idle_funcs--;
+ if (transform->released)
+ return FALSE;
+
+ /* FIXME: check for anything remaining on the queue */
+ if (transform->func)
+ transform->func (transform,
+ YELP_TRANSFORM_FINAL,
+ NULL, transform->user_data);
+
+ return FALSE;
+}
+
+/******************************************************************************/
+
+static void
+xslt_yelp_document (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp)
+{
+ YelpTransform *transform;
+ xmlChar *page_id = NULL;
+ xmlChar *page_buf;
+ gint buf_size;
+ xsltStylesheetPtr style = NULL;
+ const char *old_outfile;
+ xmlDocPtr new_doc = NULL;
+ xmlDocPtr old_doc;
+ xmlNodePtr old_insert;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ if (ctxt->state == XSLT_STATE_STOPPED)
+ return;
+
+ if (!ctxt || !node || !inst || !comp)
+ return;
+
+ transform = (YelpTransform *) ctxt->_private;
+
+ page_id = xsltEvalAttrValueTemplate (ctxt, inst,
+ (const xmlChar *) "href",
+ NULL);
+ if (page_id == NULL) {
+ xsltTransformError (ctxt, NULL, inst,
+ _("No href attribute found on yelp:document"));
+ /* FIXME: put a real error here */
+ goto done;
+ }
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+
+ old_outfile = ctxt->outputFile;
+ old_doc = ctxt->output;
+ old_insert = ctxt->insert;
+ ctxt->outputFile = (const char *) page_id;
+
+ style = xsltNewStylesheet ();
+ if (style == NULL) {
+ xsltTransformError (ctxt, NULL, inst,
+ _("Out of memory"));
+ goto done;
+ }
+
+ style->omitXmlDeclaration = TRUE;
+
+ new_doc = xmlNewDoc (BAD_CAST "1.0");
+ new_doc->charset = XML_CHAR_ENCODING_UTF8;
+ new_doc->dict = ctxt->dict;
+ xmlDictReference (new_doc->dict);
+
+ ctxt->output = new_doc;
+ ctxt->insert = (xmlNodePtr) new_doc;
+
+ xsltApplyOneTemplate (ctxt, node, inst->children, NULL, NULL);
+ xsltSaveResultToString (&page_buf, &buf_size, new_doc, style);
+
+ ctxt->outputFile = old_outfile;
+ ctxt->output = old_doc;
+ ctxt->insert = old_insert;
+
+ g_mutex_lock (transform->mutex);
+ g_hash_table_insert (transform->chunks, page_id, page_buf);
+ g_async_queue_push (transform->queue, g_strdup ((gchar *) page_id));
+ transform->idle_funcs++;
+ g_idle_add ((GSourceFunc) transform_chunk, transform);
+ g_mutex_unlock (transform->mutex);
+
+ done:
+ if (new_doc)
+ xmlFreeDoc (new_doc);
+ if (style)
+ xsltFreeStylesheet (style);
+}
+
+static void
+xslt_yelp_cache (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp)
+{
+}
diff --git a/src/yelp-transform.h b/src/yelp-transform.h
new file mode 100644
index 00000000..e1262e39
--- /dev/null
+++ b/src/yelp-transform.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_TRANSFORM_H__
+#define __YELP_TRANSFORM_H__
+
+#include <glib.h>
+#include <libxml/tree.h>
+#include <libxslt/xslt.h>
+#include <libxslt/transform.h>
+
+#include "yelp-error.h"
+
+typedef struct _YelpTransform YelpTransform;
+
+typedef enum {
+ YELP_TRANSFORM_CHUNK,
+ YELP_TRANSFORM_ERROR,
+ YELP_TRANSFORM_FINAL
+} YelpTransformSignal;
+
+typedef void (*YelpTransformFunc) (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ gpointer user_data);
+
+struct _YelpTransform {
+ xmlDocPtr inputDoc;
+ xmlDocPtr outputDoc;
+ xsltStylesheetPtr stylesheet;
+ xsltTransformContextPtr context;
+
+ YelpTransformFunc func;
+
+ gchar **params;
+
+ GThread *thread;
+ GMutex *mutex;
+ GAsyncQueue *queue;
+ GHashTable *chunks;
+
+ gboolean running;
+ gboolean released;
+ gint idle_funcs;
+ gint free_attempts;
+
+ gpointer user_data;
+
+ YelpError *error;
+};
+
+YelpTransform *yelp_transform_new (gchar *stylesheet,
+ YelpTransformFunc func,
+ gpointer user_data);
+void yelp_transform_start (YelpTransform *transform,
+ xmlDocPtr document,
+ gchar **params);
+gchar * yelp_transform_eat_chunk (YelpTransform *transform,
+ gchar *chunk_id);
+void yelp_transform_release (YelpTransform *transform);
+
+#endif /* __YELP_TRANSFORM_H__ */
diff --git a/src/yelp-utils.c b/src/yelp-utils.c
index d1d92da9..59a0fad4 100644
--- a/src/yelp-utils.c
+++ b/src/yelp-utils.c
@@ -29,1036 +29,393 @@
#include <glib/gi18n.h>
#include <libgnomevfs/gnome-vfs.h>
#include <libgnomevfs/gnome-vfs-mime-utils.h>
-#include <libgnome/gnome-program.h>
-#include <libgnome/gnome-init.h>
-
-#include "yelp-utils.h"
-#include "yelp-debug.h"
#include <string.h>
+#include <rarian-info.h>
+#include <rarian-man.h>
+#include <rarian.h>
-static GHashTable *doc_info_table;
-
-typedef struct {
- gchar *uri;
- YelpURIType type;
-} DocInfoURI;
-
-struct _YelpDocInfo {
- gchar *id;
- gchar *title;
- gchar *description;
- gchar *category;
- gchar *lang;
- gint lang_priority;
-
- DocInfoURI *uris;
- gint num_uris;
- gint max_uris;
-
- YelpDocType type;
-
- YelpPager *pager;
-
- gint ref_count;
-};
-
-static gchar *mandirs[] = {
- "man0p",
- "man1",
- "man1p",
- "man2",
- "man3",
- "man3p",
- "man4",
- "man5",
- "man6",
- "man7",
- "man8",
- "man9",
- "mann",
- NULL
-};
-
-static YelpDocType get_doc_type (gchar *uri);
-static gchar * convert_ghelp_uri (gchar *uri);
-
-static gchar * convert_man_uri (gchar *uri, gboolean trust_uri);
-static gchar * convert_info_uri (gchar *uri);
-
-static gchar *dot_dir = NULL;
+#include "yelp-utils.h"
+#include "yelp-debug.h"
-static gchar **infopath = NULL;
-static gchar *infopath_d[] = {"/usr/info", "/usr/share/info",
- "/usr/local/info", "/usr/local/share/info",
- NULL};
+YelpRrnType resolve_process_ghelp (char *uri,
+ gchar **result);
+gchar * resolve_get_section (const gchar *uri);
+gboolean resolve_is_man_path (const gchar *path,
+ const gchar *encoding);
+YelpRrnType resolve_full_file (const gchar *path);
+YelpRrnType resolve_man_page (const gchar *name,
+ gchar **result,
+ gchar **section);
+gchar * resolve_remove_section (const gchar *uri,
+ const gchar *sect);
+YelpRrnType yelp_uri_resolve (gchar *uri,
+ gchar **result,
+ gchar **section);
+
+YelpRrnType
+resolve_process_ghelp (char *uri, gchar **result)
+{
+ RrnReg *reg = rrn_find_from_ghelp (&uri[6]);
+ YelpRrnType type = YELP_RRN_TYPE_ERROR;
+
+ if (reg) {
+ gchar *mime = NULL;
+ if (g_str_has_prefix (reg->uri, "file:"))
+ *result = g_strdup (&reg->uri[5]);
+ else
+ *result = g_strdup (reg->uri);
-const char *
-yelp_dot_dir (void)
-{
- if (dot_dir == NULL) {
- dot_dir = g_build_filename (g_get_home_dir(), GNOME_DOT_GNOME,
- "yelp.d", NULL);
+ /* mime types are horrible in omf-translated files */
+ if (reg->type && *(reg->type))
+ mime = g_strdup (reg->type);
+ else
+ mime = gnome_vfs_get_mime_type (*result);
- if (!g_file_test (dot_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
- mkdir (dot_dir, 0750);
+ if (g_str_equal (mime, "text/xml") ||
+ g_str_equal (mime, "application/docbook+xml") ||
+ g_str_equal (mime, "application/xml"))
+ type = YELP_RRN_TYPE_DOC;
+ else if (g_str_equal (mime, "text/html"))
+ type = YELP_RRN_TYPE_HTML;
+ else if (g_str_equal (mime, "application/xhtml+xml"))
+ type = YELP_RRN_TYPE_XHTML;
+
}
- return dot_dir;
+ return type;
}
-/* @uri: the uri to interpret for the new YelpDocInfo struct
- * @trust_uri: if the uri is absolute and is known to exist,
- * then this should be set. Only makes sense for local
- * files. This is here for performance reasons, adding
- * 40,000 man pages and accessing the disk for each one
- * can get pretty expensive.
- */
-YelpDocInfo *
-yelp_doc_info_new (const gchar *uri, gboolean trust_uri)
+gchar *
+resolve_get_section (const gchar *uri)
{
- YelpDocInfo *doc;
- gchar *doc_uri = NULL;
- gchar *full_uri = NULL;
- YelpDocType doc_type = YELP_DOC_TYPE_ERROR;
- YelpURIType uri_type;
- gchar *cur;
-
- g_return_val_if_fail (uri != NULL, NULL);
+ gchar *sect_delimit;
+ gchar *sect;
- debug_print (DB_FUNCTION, "entering\n");
- debug_print (DB_ARG, " uri = \"%s\"\n", uri);
-
- if (trust_uri)
- full_uri = gnome_vfs_make_uri_from_input (uri);
- else
- full_uri =
- gnome_vfs_make_uri_from_input_with_dirs (uri,
- GNOME_VFS_MAKE_URI_DIR_CURRENT);
-
- if (g_str_has_prefix (full_uri, "file:")) {
- if ((cur = strchr (full_uri, '#')))
- doc_uri = g_strndup (full_uri, cur - full_uri);
- else
- doc_uri = g_strdup (full_uri);
- doc_type = get_doc_type (doc_uri);
- uri_type = YELP_URI_TYPE_FILE;
- }
- else if (g_str_has_prefix (full_uri, "ghelp:") ||
- g_str_has_prefix (full_uri, "gnome-help:")) {
- doc_uri = convert_ghelp_uri (full_uri);
- if (doc_uri)
- doc_type = get_doc_type (doc_uri);
- uri_type = YELP_URI_TYPE_GHELP;
- }
- else if (g_str_has_prefix (full_uri, "man:")) {
- doc_uri = convert_man_uri (full_uri, trust_uri);
- doc_type = YELP_DOC_TYPE_MAN;
- uri_type = YELP_URI_TYPE_MAN;
- }
- else if (g_str_has_prefix (full_uri, "info:")) {
- doc_uri = convert_info_uri (full_uri);
- if (!g_str_has_prefix (doc_uri, "man:")) {
- doc_type = YELP_DOC_TYPE_INFO;
- uri_type = YELP_URI_TYPE_INFO;
- } else {
- gchar *tmp;
- tmp = g_strdup (doc_uri);
- g_free (doc_uri);
- doc_uri = convert_man_uri (tmp, trust_uri);
- g_free (tmp);
- doc_type = YELP_DOC_TYPE_MAN;
- uri_type = YELP_URI_TYPE_MAN;
- }
- }
- else if (g_str_has_prefix (full_uri, "x-yelp-toc:")) {
- doc_uri = g_strdup ("file://" DATADIR "/yelp/toc.xml");
- doc_type = YELP_DOC_TYPE_TOC;
- uri_type = YELP_URI_TYPE_TOC;
- }
- else if (g_str_has_prefix (full_uri, "x-yelp-search:")) {
- doc_uri = g_strconcat ("file://" DATADIR "/yelp/xslt/search2html.xsl?", full_uri + strlen ("x-yelp-search:"), NULL);
- doc_type = YELP_DOC_TYPE_SEARCH;
- uri_type = YELP_URI_TYPE_SEARCH;
- }
- else {
- doc_uri = g_strdup (uri);
- doc_type = YELP_DOC_TYPE_EXTERNAL;
- uri_type = YELP_URI_TYPE_EXTERNAL;
+ sect_delimit = strrchr (uri, '#');
+ if (!sect_delimit) {
+ sect_delimit = strrchr (uri, '?');
}
-
- debug_print (DB_ARG, " full_uri = \"%s\"\n", full_uri);
- debug_print (DB_ARG, " doc_uri = \"%s\"\n", doc_uri);
-
- g_free (full_uri);
-
- if (doc_uri) {
- doc = g_new0 (YelpDocInfo, 1);
- doc->uris = g_new (DocInfoURI, 8);
- doc->num_uris = 0;
- doc->max_uris = 8;
-
- yelp_doc_info_add_uri (doc, doc_uri, YELP_URI_TYPE_FILE);
- if (uri_type && uri_type != YELP_URI_TYPE_FILE)
- yelp_doc_info_add_uri (doc, uri, uri_type);
- g_free (doc_uri);
-
- doc->type = doc_type;
- doc->ref_count = 1;
- return doc;
- } else {
+ if (!sect_delimit) {
return NULL;
}
+ sect = g_strdup (sect_delimit+1);
+
+ return sect;
}
-YelpDocInfo *
-yelp_doc_info_get (const gchar *uri, gboolean trust_uri)
+gboolean
+resolve_is_man_path (const gchar *path, const gchar *encoding)
{
- YelpDocInfo *doc;
- gint i;
- gchar *c, *doc_uri;
-
- g_return_val_if_fail (uri != NULL, NULL);
-
- debug_print (DB_FUNCTION, "entering\n");
- debug_print (DB_ARG, " uri = \"%s\"\n", uri);
+ gchar **cats;
+ gchar **iter;
- if (!doc_info_table)
- doc_info_table =
- g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- (GDestroyNotify) yelp_doc_info_unref);
+ cats = rrn_man_get_categories ();
- c = strchr (uri, '?');
- if (c == NULL)
- c = strchr (uri, '#');
+ iter = cats;
- if (c != NULL)
- doc_uri = g_strndup (uri, c - uri);
- else
- doc_uri = g_strdup (uri);
-
- doc = (YelpDocInfo *) g_hash_table_lookup (doc_info_table, doc_uri);
-
- if (!doc) {
- doc = yelp_doc_info_new (uri, trust_uri);
- if (doc && doc->type != YELP_DOC_TYPE_EXTERNAL) {
- YelpDocInfo *old_doc = NULL;
-
- for (i = 0; i < doc->num_uris; i++) {
- old_doc = g_hash_table_lookup (doc_info_table,
- (doc->uris + i)->uri);
- if (old_doc)
- break;
- }
-
- if (old_doc) {
- for (i = 0; i < doc->num_uris; i++) {
- yelp_doc_info_add_uri (old_doc,
- (doc->uris + i)->uri,
- (doc->uris + i)->type);
- g_hash_table_insert (doc_info_table,
- g_strdup ((doc->uris + i)->uri),
- yelp_doc_info_ref (old_doc));
- }
- yelp_doc_info_free (doc);
- doc = old_doc;
- } else {
- for (i = 0; i < doc->num_uris; i++) {
- g_hash_table_insert (doc_info_table,
- g_strdup ((doc->uris + i)->uri),
- yelp_doc_info_ref (doc));
- }
+ if (encoding && *encoding) {
+ while (iter) {
+ gchar *ending = g_strdup_printf ("%s.%s", *iter, encoding);
+ if (g_str_has_suffix (path, ending)) {
+ g_free (ending);
+ return TRUE;
}
+ g_free (ending);
+ iter++;
}
- }
-
- g_free (doc_uri);
- return doc;
-}
-
-YelpDocInfo *
-yelp_doc_info_ref (YelpDocInfo *doc)
-{
- g_return_val_if_fail (doc != NULL, NULL);
- (doc->ref_count)++;
- return doc;
-}
-
-void
-yelp_doc_info_unref (YelpDocInfo *doc)
-{
- g_return_if_fail (doc != NULL);
-
- if (--(doc->ref_count) < 1)
- yelp_doc_info_free (doc);
-}
-
-void
-yelp_doc_info_free (YelpDocInfo *doc)
-{
- gint i;
-
- debug_print (DB_FUNCTION, "entering\n");
- debug_print (DB_ARG, " uri = \"%s\"\n", doc->uris->uri);
-
- if (!doc)
- return;
-
- if (doc->pager)
- g_object_unref (doc->pager);
-
- g_free (doc->title);
- for (i = 0; i < doc->num_uris; i++)
- g_free ((doc->uris + i)->uri);
- g_free (doc->uris);
- g_free (doc);
-}
-
-YelpPager *
-yelp_doc_info_get_pager (YelpDocInfo *doc)
-{
- g_return_val_if_fail (doc != NULL, NULL);
-
- return doc->pager;
-}
-
-void
-yelp_doc_info_set_pager (YelpDocInfo *doc, YelpPager *pager)
-{
- g_return_if_fail (doc != NULL);
-
- if (doc->pager)
- g_object_unref (doc->pager);
-
- if (pager)
- g_object_ref (pager);
-
- doc->pager = pager;
-}
-
-const gchar *
-yelp_doc_info_get_id (YelpDocInfo *doc)
-{
- return (const gchar *) doc->id;
-}
-
-void
-yelp_doc_info_set_id (YelpDocInfo *doc, gchar *id)
-{
- if (doc->id)
- g_free (doc->id);
-
- doc->id = g_strdup (id);
-}
-
-const gchar *
-yelp_doc_info_get_title (YelpDocInfo *doc)
-{
- return (const gchar *) doc->title;
-}
-
-void
-yelp_doc_info_set_title (YelpDocInfo *doc, gchar *title)
-{
- if (doc->title)
- g_free (doc->title);
-
- doc->title = g_strdup (title);
-}
-
-const gchar *
-yelp_doc_info_get_description (YelpDocInfo *doc)
-{
- return (const gchar *) doc->description;
-}
-
-void
-yelp_doc_info_set_description (YelpDocInfo *doc, gchar *desc)
-{
- if (doc->description)
- g_free (doc->description);
-
- doc->description = g_strdup (desc);
-}
-
-const gchar *
-yelp_doc_info_get_category (YelpDocInfo *doc)
-{
- return (const gchar *) doc->category;
-}
-
-void
-yelp_doc_info_set_category (YelpDocInfo *doc, gchar *category)
-{
- if (doc->category)
- g_free (doc->category);
-
- doc->category = g_strdup (category);
-}
-
-const gchar *
-yelp_doc_info_get_language (YelpDocInfo *doc)
-{
- return (const gchar *) doc->lang;
-}
-
-void
-yelp_doc_info_set_language (YelpDocInfo *doc, gchar *language)
-{
- gint i;
- const gchar * const * langs = g_get_language_names ();
-
- if (doc->lang)
- g_free (doc->lang);
-
- doc->lang = g_strdup (language);
-
- doc->lang_priority = INT_MAX;
- for (i = 0; langs[i] != NULL; i++) {
- if (g_str_equal (language, langs[i])) {
- doc->lang_priority = i;
- break;
+ } else {
+ while (iter) {
+ if (g_str_has_suffix (path, *iter)) {
+ return TRUE;
+ }
+ iter++;
}
}
+ return FALSE;
}
-gint
-yelp_doc_info_cmp_language (YelpDocInfo *doc1, YelpDocInfo *doc2)
-{
- return CLAMP (doc1->lang_priority - doc2->lang_priority, -1, 1);
-}
-
-YelpDocType
-yelp_doc_info_get_type (YelpDocInfo *doc)
-{
- g_return_val_if_fail (doc != NULL, YELP_DOC_TYPE_ERROR);
-
- return doc->type;
-}
-
-gchar *
-yelp_doc_info_get_uri (YelpDocInfo *doc,
- gchar *frag_id,
- YelpURIType uri_type)
-{
- gchar *base = NULL;
- gint i;
-
- g_return_val_if_fail (doc != NULL, NULL);
-
- for (i = 0; i < doc->num_uris; i++)
- if ((doc->uris + i)->type & uri_type) {
- base = (doc->uris + i)->uri;
- break;
- }
-
- if (!base)
- return NULL;
-
- if (!frag_id || *frag_id == '\0')
- return g_strdup (base);
-
- return g_strconcat (base, "#", frag_id, NULL);
-}
-
-gchar *
-yelp_doc_info_get_filename (YelpDocInfo *doc) {
- gchar *filename = NULL;
- gchar *base = NULL;
- gint i;
-
- g_return_val_if_fail (doc != NULL, NULL);
-
- for (i = 0; i < doc->num_uris; i++)
- if ((doc->uris + i)->type == YELP_URI_TYPE_FILE) {
- base = (doc->uris + i)->uri;
- break;
- }
-
- if (g_str_has_prefix (base, "file://"))
- filename = g_strdup (base + 7);
-
- return filename;
-}
-
-gboolean
-yelp_doc_info_equal (YelpDocInfo *doc1, YelpDocInfo *doc2)
-{
- gboolean equal = TRUE;
-
- g_return_val_if_fail (doc1 != NULL, FALSE);
- g_return_val_if_fail (doc2 != NULL, FALSE);
-
- /* FIXME: this sucks */
- if (!g_str_equal (doc1->uris->uri, doc2->uris->uri))
- equal = FALSE;
-
- return equal;
-}
-
-void
-yelp_doc_page_free (YelpDocPage *page)
-{
- if (!page)
- return;
-
- g_free (page->page_id);
- g_free (page->title);
- g_free (page->contents);
-
- g_free (page->prev_id);
- g_free (page->next_id);
- g_free (page->toc_id);
-
- g_free (page);
-}
-
-gchar *
-yelp_uri_get_fragment (const gchar *uri)
-{
- gchar *cur;
- gchar *frag_id = NULL;
-
- g_return_val_if_fail (uri != NULL, NULL);
-
- if (g_str_has_prefix (uri, "ghelp:"))
- if ((cur = strchr (uri, '?')))
- if (*(++cur) != '\0')
- frag_id = g_strdup (cur);
-
- if (g_str_has_prefix (uri, "x-yelp-toc:"))
- if ((cur = strchr (uri, ':')))
- if (*(++cur) != '\0')
- frag_id = g_strdup (cur);
- if (g_str_has_prefix (uri, "info:"))
- if ((cur = strchr (uri, ')')))
- if (*(++cur) != '\0')
- frag_id = g_strdup (cur);
- if ((cur = strchr (uri, '#')))
- if (*(++cur) != '\0') {
- if (frag_id)
- g_free (frag_id);
- frag_id = g_strdup (cur);
- }
-
- return frag_id;
-}
-
-gchar *
-yelp_uri_get_relative (gchar *base, gchar *ref)
-{
- GnomeVFSURI *vfs_base, *vfs_uri;
- gchar *uri;
-
- vfs_base = gnome_vfs_uri_new (base);
- vfs_uri = gnome_vfs_uri_resolve_relative (vfs_base, ref);
-
- uri = gnome_vfs_uri_to_string (vfs_uri, GNOME_VFS_URI_HIDE_NONE);
-
- gnome_vfs_uri_unref (vfs_base);
- gnome_vfs_uri_unref (vfs_uri);
-
- return uri;
-}
-
-static YelpDocType
-get_doc_type (gchar *uri)
+YelpRrnType
+resolve_full_file (const gchar *path)
{
gchar *mime_type;
- YelpDocType type;
-
- g_return_val_if_fail (uri != NULL, YELP_DOC_TYPE_ERROR);
+ YelpRrnType type = YELP_RRN_TYPE_ERROR;
- if (strncmp (uri, "file:", 5))
- return YELP_DOC_TYPE_EXTERNAL;
-
- mime_type = gnome_vfs_get_mime_type (uri);
- if (mime_type == NULL)
- return YELP_DOC_TYPE_ERROR;
+ if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+ return YELP_RRN_TYPE_ERROR;
+ }
+ mime_type = gnome_vfs_get_mime_type (path);
+ if (mime_type == NULL) {
+ return YELP_RRN_TYPE_ERROR;
+ }
if (g_str_equal (mime_type, "text/xml") || g_str_equal (mime_type, "application/docbook+xml") || g_str_equal (mime_type, "application/xml"))
- type = YELP_DOC_TYPE_DOCBOOK_XML;
- else if (g_str_equal (mime_type, "text/sgml"))
- type = YELP_DOC_TYPE_DOCBOOK_SGML;
+ type = YELP_RRN_TYPE_DOC;
else if (g_str_equal (mime_type, "text/html"))
- type = YELP_DOC_TYPE_HTML;
+ type = YELP_RRN_TYPE_HTML;
else if (g_str_equal (mime_type, "application/xhtml+xml"))
- type = YELP_DOC_TYPE_XHTML;
- else
- type = YELP_DOC_TYPE_EXTERNAL;
-
- g_free (mime_type);
- return type;
-}
-
-void
-yelp_doc_info_add_uri (YelpDocInfo *doc_info,
- const gchar *uri,
- YelpURIType type)
-{
- DocInfoURI *info_uri;
-
- debug_print (DB_FUNCTION, "entering\n");
-
- g_assert (doc_info->num_uris <= doc_info->max_uris);
-
- if (doc_info->num_uris == doc_info->max_uris) {
- doc_info->max_uris += 8;
- doc_info->uris = g_renew (DocInfoURI,
- doc_info->uris,
- doc_info->max_uris);
- }
-
- info_uri = doc_info->uris + doc_info->num_uris;
-
- info_uri->uri = g_strdup (uri);
- info_uri->type = type;
-
- doc_info->num_uris++;
-
- debug_print (DB_ARG, " uri = \"%s\"\n", uri);
- debug_print (DB_ARG, " num_uris = %i\n", doc_info->num_uris);
- debug_print (DB_ARG, " max_uris = %i\n", doc_info->max_uris);
-}
-
-/******************************************************************************/
-/** Convert fancy URIs to file URIs *******************************************/
-
-static gchar *
-locate_file_lang (gchar *path, gchar *file, const gchar *lang)
-{
- gchar *exts[] = {".xml", ".docbook", ".sgml", ".html", "", NULL};
- gint i;
- gchar *full, *uri = NULL;
-
- for (i = 0; exts[i] != NULL; i++) {
- full = g_strconcat (path, "/", lang, "/", file, exts[i], NULL);
- if (g_file_test (full, G_FILE_TEST_IS_REGULAR))
- uri = g_strconcat ("file://", full, NULL);
- g_free (full);
- if (uri)
- return uri;
- }
- return NULL;
-}
-
-static gchar *
-convert_ghelp_uri (gchar *uri)
-{
- GSList *locations = NULL;
- GSList *node;
- gchar *path, *cur;
- gchar *doc_id = NULL;
- gchar *doc_name = NULL;
- gchar *doc_uri = NULL;
-
- GnomeProgram *program = gnome_program_get ();
-
- if ((path = strchr(uri, ':')))
- path++;
- else
- goto done;
-
- if (path && path[0] == '/') {
- if ((cur = strchr (path, '?')) || (cur = strchr (path, '#')))
- *cur = '\0';
- doc_uri = g_strconcat ("file://", path, NULL);
- if (cur)
- *cur = '#';
-
- goto done;
- }
-
- if ((cur = strchr (path, '/'))) {
- doc_id = g_strndup (path, cur - path);
- path = cur + 1;
- }
-
- if ((cur = strchr (path, '?')) || (cur = strchr (path, '#')))
- doc_name = g_strndup (path, cur - path);
- else
- doc_name = g_strdup (path);
-
- if (doc_id)
- gnome_program_locate_file (program,
- GNOME_FILE_DOMAIN_HELP,
- doc_id,
- FALSE,
- &locations);
- else
- gnome_program_locate_file (program,
- GNOME_FILE_DOMAIN_HELP,
- doc_name,
- FALSE,
- &locations);
-
- if (!locations)
- goto done;
-
- for (node = locations; node; node = node->next) {
- gint i;
- const gchar * const * langs;
- gchar *location = (gchar *) node->data;
-
- langs = g_get_language_names ();
-
- for (i = 0; langs[i] != NULL; i++) {
-
- /* This has to be a valid language AND a language with
- * no encoding postfix. The language will come up without
- * encoding next */
- if (strchr (langs[i], '.') != NULL)
- continue;
-
- doc_uri = locate_file_lang (location, doc_name, langs[i]);
-
- if (!doc_uri)
- doc_uri = locate_file_lang (location, "index", langs[i]);
-
- if (doc_uri)
- goto done;
+ type = YELP_RRN_TYPE_XHTML;
+ else if (g_str_equal (mime_type, "application/x-gzip")) {
+ if (g_str_has_suffix (path, ".info.gz")) {
+ type = YELP_RRN_TYPE_INFO;
+ } else if (resolve_is_man_path (path, "gz")) {
+ type = YELP_RRN_TYPE_MAN;
}
- /* Look in C locale since that exists for almost all docs */
- doc_uri = locate_file_lang (location, doc_name, "C");
- if (doc_uri)
- goto done;
-
- /* Last chance, look for index-file with C lang */
- doc_uri = locate_file_lang (location, "index", "C");
- }
-
- done:
- if (locations) {
- g_slist_foreach (locations, (GFunc) g_free, NULL);
- g_slist_free (locations);
+ } else if (g_str_equal (mime_type, "application/x-bzip")) {
+ if (g_str_has_suffix (path, ".info.bz2")) {
+ type = YELP_RRN_TYPE_INFO;
+ } else if (resolve_is_man_path (path, "bz2")) {
+ type = YELP_RRN_TYPE_MAN;
+ }
+ } else if (g_str_equal (mime_type, "text/plain")) {
+ if (g_str_has_suffix (path, ".info")) {
+ type = YELP_RRN_TYPE_INFO;
+ } else if (resolve_is_man_path (path, NULL)) {
+ type = YELP_RRN_TYPE_MAN;
+ }
+ } else {
+ type = YELP_RRN_TYPE_EXTERNAL;
}
- g_free (doc_id);
- g_free (doc_name);
- if (!doc_uri)
- g_warning ("Could not resolve ghelp URI: %s", uri);
+ g_free (mime_type);
+ return type;
- return doc_uri;
}
-static gchar *
-convert_man_uri (gchar *uri, gboolean trust_uri)
-{
- gchar *path, *cur;
- gchar *doc_uri = NULL;
- gchar *man_name = NULL;
- gchar *man_num = NULL;
- gchar *man_dir = NULL;
- const gchar * const * langs = g_get_language_names ();
- gint langs_i;
-
- static gchar **manpath = NULL;
- gint i, j;
-
- GDir *dir;
- gchar *dirname;
- const gchar *filename;
- gchar *pattern;
- GPatternSpec *pspec = NULL;
-
- if ((path = strchr(uri, ':')))
- path++;
- else
- goto done;
-
- /* An absolute file path after man: */
- if (path[0] == '/') {
- if (trust_uri)
- doc_uri = g_strconcat ("file://", path, NULL);
- else if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
- doc_uri = g_strconcat ("file://", path, NULL);
- goto done;
- }
-
- /* Get the manpath, either from the 'manpath' command, for from the
- MANPATH envar. manpath is static, so this should only run once
- for each program invocation.
- */
- if (!manpath) {
- gchar *manp;
-
- if (!g_spawn_command_line_sync ("manpath", &manp, NULL, NULL, NULL))
- manp = g_strdup (g_getenv ("MANPATH"));
- if (!manp) {
- return NULL;
- }
- g_strstrip (manp);
- manpath = g_strsplit (manp, ":", -1);
-
- g_free (manp);
- }
-
- /* The URI is either man:frobnicate or man:frobnicate(1). If the former,
- set man_name to everything after man:. If the latter, set man_name to
- everything leading to (1), and man_num to the section number.
- */
- if ((cur = strchr (path, '('))) {
- man_name = g_strndup (path, cur - path);
- path = cur + 1;
- if ((cur = strchr (path, ')')))
- man_num = g_strndup (path, cur - path);
- if (man_num[0]) {
- man_dir = g_new (gchar, 5);
- g_snprintf (man_dir, 5, "man%c", man_num[0]);
+YelpRrnType
+resolve_man_page (const gchar *name, gchar **result, gchar **section)
+{
+ /* Various ways the path could be presented:
+ * filename - full filename after man:
+ * name(section) - resolve to a particular section
+ * name.section - ditto. This must be tested twice. Once for full filename and
+ * once for section
+ * name#section - ditto, though this is never used, just added for completeness
+ * name - resolve to the first one found
+ */
+ gchar *lbrace = NULL;
+ gchar *rbrace = NULL;
+ gchar *sect = NULL;
+ gchar *real_name = NULL;
+ gboolean repeat = FALSE;
+ RrnManEntry *entry = NULL;
+
+ lbrace = strrchr (name, '(');
+ if (lbrace) {
+ rbrace = strrchr (name, ')');
+ if (rbrace) {
+ /*sect = g_strndup (lbrace+1, rbrace - lbrace - 1);*/
+ real_name = g_strndup (name, lbrace - name);
+ } else {
+ sect = NULL;
+ real_name = strdup (name);
}
} else {
- man_name = g_strdup (path);
- }
-
- /* Create the glob pattern. If we have man_num, then look for
- man_name.man_num*. Otherwise, looks for man_name.*
- */
- if (man_num && man_num[0])
- pattern = g_strdup_printf ("%s.%s*", man_name, man_num);
- else
- pattern = g_strdup_printf ("%s.*", man_name);
- pspec = g_pattern_spec_new (pattern);
- g_free (pattern);
-
- for (i = 0; manpath[i]; i++) {
- for (langs_i = 0; langs[langs_i]; langs_i++) {
- for (j = 0; man_dir ? (j < 1) : (mandirs[j] != NULL); j++) {
- if (g_str_equal (langs[langs_i], "C"))
- dirname = g_build_filename (manpath[i],
- man_dir ? man_dir : mandirs[j],
- NULL);
- else
- dirname = g_build_filename (manpath[i],
- langs[langs_i],
- man_dir ? man_dir : mandirs[j],
- NULL);
- dir = g_dir_open (dirname, 0, NULL);
- if (dir) {
- while ((filename = g_dir_read_name (dir))) {
- if (g_pattern_match_string (pspec, filename)) {
- doc_uri = g_strconcat ("file://",
- dirname, "/",
- filename,
- NULL);
- g_dir_close (dir);
- g_free (dirname);
- goto done;
- }
- }
- g_dir_close (dir);
- }
- g_free (dirname);
+ lbrace = strrchr (name, '.');
+ if (lbrace) {
+ repeat = TRUE;
+ /*sect = strdup (lbrace+1);*/
+ real_name = g_strndup (name, lbrace - name);
+ } else {
+ lbrace = strrchr (name, '#');
+ if (lbrace) {
+ /*sect = strdup (lbrace+1);*/
+ real_name = g_strndup (name, lbrace - name);
+ } else {
+ real_name = strdup (name);
+ sect = NULL;
}
}
}
+ if (g_file_test (real_name, G_FILE_TEST_EXISTS)) {
+ /* Full filename */
+ *result = g_strdup (real_name);
+ return YELP_RRN_TYPE_MAN;
+ } else if (g_file_test (name, G_FILE_TEST_EXISTS)) {
+ /* Full filename */
+ *result = g_strdup (name);
+ return YELP_RRN_TYPE_MAN;
+ }
- done:
- if (pspec)
- g_pattern_spec_free (pspec);
- g_free (man_dir);
- g_free (man_num);
- g_free (man_name);
-
- return doc_uri;
-}
-
-gchar **
-yelp_get_info_paths (void)
-{
- /* Get the infopath, either from the INFOPATH envar,
- or from the default infopath_d.
- */
- if (!infopath) {
- gchar *infop;
-
- infop = g_strdup (g_getenv ("INFOPATH"));
- if (infop) {
- g_strstrip (infop);
- infopath = g_strsplit (infop, ":", -1);
- g_free (infop);
- } else {
- infopath = infopath_d;
+ entry = rrn_man_find_from_name (real_name, sect);
+
+ if (entry) {
+ *result = strdup (entry->path);
+ /**section = strdup (entry->section);*/
+ return YELP_RRN_TYPE_MAN;
+ } else if (repeat) {
+ entry = rrn_man_find_from_name ((char *) name, NULL);
+ if (entry) {
+ *result = strdup (entry->path);
+ /**section = strdup (entry->section);*/
+ return YELP_RRN_TYPE_MAN;
}
}
-
-
- return infopath;
+ return YELP_RRN_TYPE_ERROR;
}
-gchar **
-yelp_get_man_paths (void)
+gchar *
+resolve_remove_section (const gchar *uri, const gchar *sect)
{
- return mandirs;
+ if (sect)
+ return (g_strndup (uri, (strlen(uri) - strlen(sect) - 1 /*for the delimiter char */)));
+ else
+ return (g_strdup (uri));
}
-static gchar *
-convert_info_uri (gchar *uri)
+YelpRrnType
+yelp_uri_resolve (gchar *uri, gchar **result, gchar **section)
{
- gchar *path, *cur;
- gchar *doc_uri = NULL;
- gchar *info_name = NULL;
- gchar *info_dot_info = NULL;
- gchar **infopaths = NULL;
- gboolean need_subdir = FALSE;
- gchar *test_filename = NULL;
-
- gint i;
-
- GDir *dir;
- const gchar *filename;
- gchar *pattern;
- GPatternSpec *pspec = NULL;
- GPatternSpec *pspec1 = NULL;
- gchar *subdir = NULL;
-
- if ((path = strchr(uri, ':')))
- path++;
- else
- goto done;
-
- /* An absolute path after info: */
- if (path[0] == '/') {
- if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
- doc_uri = g_strconcat ("file://", path, NULL);
- goto done;
+ YelpRrnType ret = YELP_RRN_TYPE_ERROR;
+ gchar *intern_section = NULL;
+ gchar *intern_uri = NULL;
+ g_assert (result != NULL);
+ if (*result != NULL) {
+ g_warning ("result is not empty: %s.", *result);
+ return ret;
}
-
-
- /* The URI is one of the following:
- info:info_name
- info:info_name#node
- info:(info_name)
- info:(info_name)node
- In the first two, spaces are replaced with underscores. In the other
- two, they're preserved. That should really only matter for the node
- identifier, which we're not concerned with here. All we need is to
- extract info_name.
- */
- if (path[0] == '(') {
- path++;
- cur = strchr (path, ')');
- if (!cur)
- goto done;
- info_name = g_strndup (path, cur - path);
+ g_assert (section != NULL);
+ if (*section != NULL) {
+ g_warning ("section is not empty: %s.", *section);
+ return ret;
}
- else if ((cur = strchr (path, '#')))
- info_name = g_strndup (path, cur - path);
- else
- info_name = g_strdup (path);
-
- if (strstr (info_name, "/")) {
- gchar *tmp = NULL;
- gchar *real_name = NULL;
- tmp = strstr (info_name, "/");
- tmp++;
- real_name = g_strdup (tmp);
- subdir = g_strndup (info_name, (strstr (info_name, "/") - info_name));
- g_free (info_name);
- info_name = g_strdup (real_name);
- g_free (real_name);
- need_subdir = TRUE;
+ if (uri == NULL) {
+ g_warning ("URI is NULL");
+ return ret;
}
+ intern_section = resolve_get_section(uri);
+ intern_uri = resolve_remove_section (uri, intern_section);
+ if (intern_section && g_str_equal (intern_section, "")) {
+ intern_section = NULL;
+ }
- pattern = g_strdup_printf ("%s.info.*", info_name);
- pspec = g_pattern_spec_new (pattern);
- g_free (pattern);
- pattern = g_strdup_printf ("%s.?z*", info_name);
- pspec1 = g_pattern_spec_new (pattern);
- g_free (pattern);
-
- info_dot_info = g_strconcat (info_name, ".info", NULL);
-
- infopaths = yelp_get_info_paths ();
-
- for (i = 0; infopaths[i]; i++) {
- dir = g_dir_open (infopath[i], 0, NULL);
- if (dir) {
- while ((filename = g_dir_read_name (dir))) {
- g_free (test_filename);
- test_filename = g_strconcat (infopath[i], "/", filename, NULL);
- if (need_subdir && g_str_equal (filename, subdir)) {
- gchar *dirname = NULL;
- g_dir_close (dir);
- dirname = g_strconcat (infopath[i], "/", subdir, NULL);
- dir = g_dir_open (dirname, 0, NULL);
- g_free (dirname);
- filename = g_dir_read_name (dir);
- need_subdir = FALSE;
- }
- else if (g_str_equal (filename,info_name) &&
- g_file_test (test_filename, G_FILE_TEST_IS_DIR)) {
- /* In dir, they've specified the subdir but not the
- * info file name. Here, do some work to get the name
- * ...*/
- const gchar *real_filename;
-
- g_dir_close (dir);
- dir = g_dir_open (test_filename, 0, NULL);
-
- while ((real_filename = g_dir_read_name (dir))) {
- if ((g_str_equal (info_dot_info, real_filename) ||
- g_pattern_match_string (pspec, real_filename) ||
- g_pattern_match_string (pspec1, real_filename) ||
- g_str_equal (info_name, real_filename))) {
- doc_uri = g_strconcat ("file://",
- test_filename, "/",
- real_filename,
- NULL);
- g_dir_close (dir);
- goto done;
- }
- }
-
- }
- else if (!need_subdir &&
- (g_str_equal (info_dot_info, filename) ||
- g_pattern_match_string (pspec, filename) ||
- g_pattern_match_string (pspec1, filename) ||
- g_str_equal (info_name, filename))) {
- if (subdir) {
- doc_uri = g_strconcat ("file://",
- infopath[i], "/", subdir, "/",
- filename,
- NULL);
- } else {
- doc_uri = g_strconcat ("file://",
- infopath[i], "/",
- filename,
- NULL);
-
- }
- g_dir_close (dir);
- goto done;
- }
+ if (!strncmp (uri, "ghelp:", 6) || !strncmp (uri, "gnome-help:", 11)) {
+ ret = resolve_process_ghelp (intern_uri, result);
+ if (*result) {
+ *section = intern_section;
+ }
+ } else if (!strncmp (uri, "man:", 4)) {
+ ret = resolve_man_page (&uri[4], result, section);
+ if (ret == YELP_RRN_TYPE_ERROR) {
+ *result = NULL;
+ *section = NULL;
+ }
+ /* Man page */
+ } else if (!strncmp (uri, "info:", 5)) {
+ /* info page */
+
+ gchar *info_name = intern_uri;
+ gchar *info_sect = intern_section;
+ gboolean free_stuff = FALSE;
+ RrnInfoEntry *entry = NULL;
+
+ if (g_str_equal (&uri[5], "dir")) {
+ *section = g_strdup ("info");
+ *result = NULL;
+ ret = YELP_RRN_TYPE_TOC;
+ return ret;
+ }
+
+ if (!intern_section) {
+ gchar *lbrace = NULL;
+ gchar *rbrace = NULL;
+ lbrace = strchr (info_name, '(');
+ rbrace = strchr (info_name, ')');
+ if (lbrace && rbrace) {
+ info_name = g_strndup (lbrace+1, (rbrace-lbrace-1));
+ info_sect = g_strdup (rbrace+1);
+ free_stuff = TRUE;
+ } else {
+ info_name += 5;
}
- g_dir_close (dir);
+ } else {
+ info_name += 5;
}
- }
- /* If we got this far and doc_uri is still NULL, we resort to looking
- * for a man page. Let above handle that. We just let it know that
- * somethings gotta be done */
- if (doc_uri == NULL) {
- gchar *tmp;
- tmp = strchr (uri, ':');
- doc_uri = g_strconcat ("man",tmp,NULL);
+ entry = rrn_info_find_from_uri (info_name, info_sect);
+ if (entry) {
+ ret = YELP_RRN_TYPE_INFO;
+ if (entry->section)
+ *section = g_strdup (entry->section);
+ else
+ *section = g_strdup (intern_section);
+ *result = g_strdup (entry->base_filename);
+ } else {
+ ret = resolve_man_page (&uri[5], result, section);
+ if (!ret) {
+ ret = YELP_RRN_TYPE_ERROR;
+ *section = NULL;
+ *result = NULL;
+ }
+ }
+ if (free_stuff) {
+ g_free (info_name);
+ g_free (info_sect);
+ }
+ } else if (!strncmp (uri, "file:", 5)) {
+ int file_cut = 5;
+ while (uri[file_cut+1] == '/')
+ file_cut++;
+ ret = resolve_full_file (&intern_uri[file_cut]);
+ if (ret == YELP_RRN_TYPE_EXTERNAL) {
+ *section = NULL;
+ *result = g_strdup (uri);
+ }
+ else if (ret == YELP_RRN_TYPE_ERROR) {
+ *section = NULL;
+ *result = NULL;
+ } else {
+ *result = g_strdup (&intern_uri[file_cut]);
+ *section = intern_section;
+ }
+ /* full file path. Ensure file exists and determine type */
+ } else if (!strncmp (uri, "x-yelp-toc:", 11)) {
+ ret = YELP_RRN_TYPE_TOC;
+ if (strlen (uri) > 11) {
+ *section = g_strdup (&uri[11]);
+ } else {
+ *section = g_strdup("index");
+ }
+ *result = g_strdup ("x-yelp-toc:");
+ /* TOC page */
+ } else if (!strncmp (uri, "x-yelp-search:", 14)) {
+ /* Search pager request. *result contains the search terms */
+ *result = g_strdup (uri);
+ *section = g_strdup ("results");
+ ret = YELP_RRN_TYPE_SEARCH;
+ } else if (g_file_test (intern_uri, G_FILE_TEST_EXISTS)) {
+ /* Full path */
+ ret = resolve_full_file (intern_uri);
+ if (ret == YELP_RRN_TYPE_EXTERNAL) {
+ *section = NULL;
+ *result = g_strdup (uri);
+ }
+ else if (ret == YELP_RRN_TYPE_ERROR) {
+ *section = NULL;
+ *result = NULL;
+ } else {
+ *result = g_strdup (intern_uri);
+ *section = g_strdup (intern_section);
+ }
+ } else if (*uri == '/' || g_str_has_suffix (uri, ".xml")) {
+ /* Quite probable it was supposed to be ours, but
+ * the file doesn't exist. Hence, we should bin it
+ */
+ ret = YELP_RRN_TYPE_ERROR;
+ *result = NULL;
+ *section = NULL;
+ } else {
+ /* We really don't care what it is. It's not ours. Let
+ * someone else handle it
+ */
+ ret = YELP_RRN_TYPE_EXTERNAL;
+ *result = g_strdup (uri);
+ *section = NULL;
}
- done:
- if (pspec)
- g_pattern_spec_free (pspec);
- if (pspec1)
- g_pattern_spec_free (pspec1);
- g_free (test_filename);
- g_free (subdir);
- g_free (info_dot_info);
- g_free (info_name);
-
- return doc_uri;
+ return ret;
}
diff --git a/src/yelp-utils.h b/src/yelp-utils.h
index a2fede29..faf08e74 100644
--- a/src/yelp-utils.h
+++ b/src/yelp-utils.h
@@ -25,106 +25,32 @@
#include <glib/gi18n.h>
-typedef struct _YelpDocInfo YelpDocInfo;
-typedef struct _YelpDocPage YelpDocPage;
-
-typedef enum {
- YELP_DOC_TYPE_ERROR = 0,
- YELP_DOC_TYPE_DOCBOOK_XML,
- YELP_DOC_TYPE_DOCBOOK_SGML,
- YELP_DOC_TYPE_HTML,
- YELP_DOC_TYPE_XHTML,
- YELP_DOC_TYPE_MAN,
- YELP_DOC_TYPE_INFO,
- YELP_DOC_TYPE_TOC,
- YELP_DOC_TYPE_EXTERNAL,
- YELP_DOC_TYPE_SEARCH
-} YelpDocType;
-
typedef enum {
- YELP_URI_TYPE_ERROR = 0,
- YELP_URI_TYPE_FILE = 1 << 0,
- YELP_URI_TYPE_GHELP = 1 << 1,
- YELP_URI_TYPE_MAN = 1 << 2,
- YELP_URI_TYPE_INFO = 1 << 3,
- YELP_URI_TYPE_TOC = 1 << 4,
- YELP_URI_TYPE_EXTERNAL = 1 << 5,
- YELP_URI_TYPE_SEARCH = 1 << 6,
-
- YELP_URI_TYPE_NO_FILE =
- YELP_URI_TYPE_GHELP |
- YELP_URI_TYPE_MAN |
- YELP_URI_TYPE_INFO |
- YELP_URI_TYPE_TOC |
- YELP_URI_TYPE_EXTERNAL |
- YELP_URI_TYPE_SEARCH,
- YELP_URI_TYPE_ANY =
- YELP_URI_TYPE_FILE |
- YELP_URI_TYPE_NO_FILE
-} YelpURIType;
-
-#include "yelp-pager.h"
-
-struct _YelpDocPage {
- YelpDocInfo *document;
- gchar *page_id;
- gchar *title;
- gchar *contents;
-
- gchar *prev_id;
- gchar *next_id;
- gchar *toc_id;
-};
-
-const char * yelp_dot_dir (void);
-YelpDocInfo * yelp_doc_info_new (const gchar *uri,
- gboolean trust_uri);
-YelpDocInfo * yelp_doc_info_get (const gchar *uri,
- gboolean trust_uri);
-void yelp_doc_info_add_uri (YelpDocInfo *doc_info,
- const gchar *uri,
- YelpURIType type);
-YelpDocInfo * yelp_doc_info_ref (YelpDocInfo *doc);
-void yelp_doc_info_unref (YelpDocInfo *doc);
-void yelp_doc_info_free (YelpDocInfo *doc);
-
-YelpPager * yelp_doc_info_get_pager (YelpDocInfo *doc);
-void yelp_doc_info_set_pager (YelpDocInfo *doc,
- YelpPager *pager);
-
-const gchar * yelp_doc_info_get_id (YelpDocInfo *doc);
-void yelp_doc_info_set_id (YelpDocInfo *doc,
- gchar *id);
-const gchar * yelp_doc_info_get_title (YelpDocInfo *doc);
-void yelp_doc_info_set_title (YelpDocInfo *doc,
- gchar *title);
-const gchar * yelp_doc_info_get_description (YelpDocInfo *doc);
-void yelp_doc_info_set_description (YelpDocInfo *doc,
- gchar *desc);
-const gchar * yelp_doc_info_get_language (YelpDocInfo *doc);
-void yelp_doc_info_set_language (YelpDocInfo *doc,
- gchar *language);
-const gchar * yelp_doc_info_get_category (YelpDocInfo *doc);
-void yelp_doc_info_set_category (YelpDocInfo *doc,
- gchar *category);
-gint yelp_doc_info_cmp_language (YelpDocInfo *doc1,
- YelpDocInfo *doc2);
-
-YelpDocType yelp_doc_info_get_type (YelpDocInfo *doc);
-gchar * yelp_doc_info_get_uri (YelpDocInfo *doc,
- gchar *frag_id,
- YelpURIType uri_type);
-gchar * yelp_doc_info_get_filename (YelpDocInfo *doc);
-gboolean yelp_doc_info_equal (YelpDocInfo *doc1,
- YelpDocInfo *doc2);
-
-void yelp_doc_page_free (YelpDocPage *page);
-
-gchar * yelp_uri_get_fragment (const gchar *uri);
-gchar * yelp_uri_get_relative (gchar *base,
- gchar *ref);
-gchar ** yelp_get_info_paths (void);
-
-gchar ** yelp_get_man_paths (void);
+ YELP_RRN_TYPE_DOC = 0,
+ YELP_RRN_TYPE_MAN,
+ YELP_RRN_TYPE_INFO,
+ YELP_RRN_TYPE_HTML,
+ YELP_RRN_TYPE_XHTML,
+ YELP_RRN_TYPE_TOC,
+ YELP_RRN_TYPE_SEARCH,
+ YELP_RRN_TYPE_NOT_FOUND,
+ YELP_RRN_TYPE_EXTERNAL,
+ YELP_RRN_TYPE_ERROR
+} YelpRrnType;
+
+
+/* Generic resolver function. Takes in the uri (which can be
+ * anything) and returns the type (enum above)
+ * The result is filled with a new string that the callee
+ * must free, except when returning YELP_TYPE_ERROR, when it will
+ * be NULL. The result is the base filename for the document.
+ * The section will be filled when the requested uri has a section
+ * otherwise, it will be NULL
+ * Both *result and *section must be NULL when calling (otherwise
+ * we throw an error
+ */
+YelpRrnType yelp_uri_resolve (gchar *uri,
+ gchar **result,
+ gchar **section);
#endif /* __YELP_UTILS_H__ */
diff --git a/src/yelp-window.c b/src/yelp-window.c
index 4bf5764e..05f64ca2 100644
--- a/src/yelp-window.c
+++ b/src/yelp-window.c
@@ -37,27 +37,21 @@
#include <libgnome/gnome-url.h>
#include "yelp-bookmarks.h"
-#include "yelp-db-pager.h"
-#include "yelp-db-print-pager.h"
-#include "yelp-error.h"
+#include "yelp-utils.h"
#include "yelp-html.h"
-#include "yelp-pager.h"
#include "yelp-settings.h"
-#include "yelp-toc-pager.h"
+#include "yelp-toc.h"
+#include "yelp-docbook.h"
+#include "yelp-db-print.h"
#include "yelp-window.h"
#include "yelp-print.h"
#include "yelp-debug.h"
-#ifdef ENABLE_MAN
-#include "yelp-man-pager.h"
-#endif
-#ifdef ENABLE_INFO
-#include "yelp-info-pager.h"
-#endif
-#ifdef ENABLE_SEARCH
-#include "yelp-search-pager.h"
+
+#include "yelp-man.h"
+#include "yelp-info.h"
+#include "yelp-search.h"
#include "gtkentryaction.h"
-#endif
#define YELP_CONFIG_WIDTH "/yelp/Geometry/width"
#define YELP_CONFIG_HEIGHT "/yelp/Geometry/height"
@@ -67,14 +61,13 @@
#define BUFFER_SIZE 16384
typedef struct {
- YelpWindow *window;
- gchar *uri;
-} YelpLoadData;
-
-typedef struct {
- YelpDocInfo *doc_info;
+ YelpDocument *doc;
+ YelpRrnType type;
+ gchar *uri;
+ gchar *req_uri;
gchar *frag_id;
+ gchar *base_uri;
GtkWidget *menu_entry;
YelpWindow *window;
gint callback;
@@ -83,49 +76,46 @@ typedef struct {
gchar *frag_title;
} YelpHistoryEntry;
+typedef struct {
+ YelpPage *page;
+ YelpWindow *window;
+
+} YelpLoadData;
+
static void window_init (YelpWindow *window);
static void window_class_init (YelpWindowClass *klass);
static void window_error (YelpWindow *window,
- GError *error,
+ gchar *title,
+ gchar *message,
gboolean pop);
static void window_populate (YelpWindow *window);
static void window_populate_find (YelpWindow *window,
GtkWidget *find_bar);
static void window_set_sections (YelpWindow *window,
GtkTreeModel *sections);
-static void window_do_load (YelpWindow *window,
- YelpDocInfo *doc_info,
- gchar *frag_id);
-static gboolean window_do_load_pager (YelpWindow *window,
- YelpDocInfo *doc_info,
- gchar *frag_id);
+static void window_set_section_cursor (YelpWindow *window,
+ GtkTreeModel *model);
+
static gboolean window_do_load_html (YelpWindow *window,
- YelpDocInfo *doc_info,
- gchar *frag_id);
+ gchar *uri,
+ gchar *frag_id,
+ YelpRrnType type,
+ gboolean need_history);
static void window_set_loading (YelpWindow *window);
-static void window_handle_page (YelpWindow *window,
- YelpPage *page);
-static void window_disconnect (YelpWindow *window);
+static void window_setup_window (YelpWindow *window,
+ YelpRrnType type,
+ gchar *loading_uri,
+ gchar *frag,
+ gchar *req_uri,
+ gchar *base_uri,
+ gboolean add_history);
/** Window Callbacks **/
static gboolean window_configure_cb (GtkWidget *widget,
GdkEventConfigure *event,
gpointer data);
-/** Pager Callbacks **/
-static void pager_start_cb (YelpPager *pager,
- gpointer user_data);
-static void pager_page_cb (YelpPager *pager,
- gchar *page_id,
- gpointer user_data);
-static void pager_error_cb (YelpPager *pager,
- gpointer user_data);
-static void pager_cancel_cb (YelpPager *pager,
- gpointer user_data);
-static void pager_finish_cb (YelpPager *pager,
- gpointer user_data);
-
/** Gecko Callbacks **/
static void html_uri_selected_cb (YelpHtml *html,
gchar *uri,
@@ -186,8 +176,6 @@ static void window_open_link_cb (GtkAction *action, YelpWindow *window);
static void window_open_link_new_cb (GtkAction *action, YelpWindow *window);
static void window_copy_mail_cb (GtkAction *action, YelpWindow *window);
-static gboolean window_load_async (YelpLoadData *data);
-
/** History Functions **/
static void history_push_back (YelpWindow *window);
static void history_push_forward (YelpWindow *window);
@@ -200,8 +188,8 @@ static void history_back_to (GtkMenuItem *menuitem,
YelpHistoryEntry *entry);
static void history_forward_to (GtkMenuItem *menuitem,
YelpHistoryEntry *entry);
-
-static void load_data_free (YelpLoadData *data);
+static void history_load_entry (YelpWindow *window,
+ YelpHistoryEntry *entry);
static void location_response_cb (GtkDialog *dialog,
gint id,
@@ -227,6 +215,9 @@ static void window_find_previous_cb (GtkAction *action,
YelpWindow *window);
static gboolean tree_model_iter_following (GtkTreeModel *model,
GtkTreeIter *iter);
+static gboolean window_write_html (YelpLoadData *data);
+static void window_write_print_html (YelpHtml *html,
+ YelpPage *page);
enum {
NEW_WINDOW_REQUESTED,
@@ -263,15 +254,20 @@ struct _YelpWindowPriv {
GtkWidget *popup;
gint merge_id;
GtkWidget *maillink;
- gchar *uri;
/* Location Information */
- YelpDocInfo *current_doc;
+ gchar *uri;
+ YelpRrnType current_type;
+ gchar *req_uri;
+ gchar *base_uri;
+ gint current_request;
+ YelpDocument *current_document;
gchar *current_frag;
GSList *history_back;
GSList *history_forward;
GtkWidget *back_menu;
GtkWidget *forward_menu;
+ GtkTreeModel *current_sidebar;
/* Callbacks and Idles */
gulong start_handler;
@@ -279,9 +275,9 @@ struct _YelpWindowPriv {
gulong error_handler;
gulong cancel_handler;
gulong finish_handler;
- guint idle_write;
gint toc_pause;
+ guint html_idle_handle;
GtkActionGroup *action_group;
GtkUIManager *ui_manager;
@@ -292,22 +288,6 @@ struct _YelpWindowPriv {
gchar *toc_id;
};
-typedef struct _IdleWriterContext IdleWriterContext;
-struct _IdleWriterContext {
- YelpWindow *window;
-
- enum {
- IDLE_WRITER_MEMORY,
- IDLE_WRITER_VFS
- } type;
-
- const gchar *buffer;
- gint cur;
- gint length;
-};
-
-static gboolean idle_write (IdleWriterContext *context);
-
#define TARGET_TYPE_URI_LIST "text/uri-list"
enum {
TARGET_URI_LIST
@@ -326,12 +306,12 @@ static const GtkActionEntry entries[] = {
NULL,
G_CALLBACK (window_new_window_cb) },
{ "PrintDocument", NULL,
- N_("Print This Document"),
+ N_("Print This Document ..."),
NULL,
NULL,
G_CALLBACK (window_print_document_cb) },
{ "PrintPage", NULL,
- N_("Print This Page"),
+ N_("Print This Page ..."),
NULL,
NULL,
G_CALLBACK (window_print_page_cb) },
@@ -519,10 +499,6 @@ window_init (YelpWindow *window)
static void
window_dispose (GObject *object)
{
- YelpWindow *window = YELP_WINDOW (object);
-
- window_disconnect (YELP_WINDOW (window));
-
parent_class->dispose (object);
}
@@ -537,8 +513,6 @@ window_finalize (GObject *object)
g_free (priv->find_string);
- if (priv->current_doc)
- yelp_doc_info_unref (priv->current_doc);
g_free (priv->current_frag);
/* FIXME there are many more things to free */
@@ -569,6 +543,13 @@ window_class_init (YelpWindowClass *klass)
g_type_class_add_private (klass, sizeof (YelpWindowPriv));
}
+const gchar *
+yelp_window_get_uri (YelpWindow *window)
+{
+
+ return ((const gchar *) window->priv->uri);
+}
+
/** History Functions *********************************************************/
static void
@@ -580,13 +561,18 @@ history_push_back (YelpWindow *window)
gchar *title;
g_return_if_fail (YELP_IS_WINDOW (window));
- g_return_if_fail (window->priv->current_doc != NULL);
priv = window->priv;
entry = g_new0 (YelpHistoryEntry, 1);
- entry->doc_info = yelp_doc_info_ref (priv->current_doc);
+
entry->frag_id = g_strdup (priv->current_frag);
+ entry->uri = g_strdup (priv->uri);
+ entry->req_uri = priv->req_uri;
+ entry->doc = priv->current_document;
+ entry->type = priv->current_type;
+ entry->base_uri = g_strdup (priv->base_uri);
+
/* page_title, frag_title */
priv->history_back = g_slist_prepend (priv->history_back, entry);
@@ -596,8 +582,8 @@ history_push_back (YelpWindow *window)
g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
title = (gchar *) gtk_window_get_title (GTK_WINDOW (window));
- if (g_str_equal (title, "Loading..."))
- entry->page_title = g_strdup ("Unknown Page");
+ if (g_str_equal (title, _("Loading...")))
+ entry->page_title = g_strdup (_("Unknown Page"));
else
entry->page_title = g_strdup (title);
@@ -626,14 +612,19 @@ history_push_forward (YelpWindow *window)
gchar *title;
g_return_if_fail (YELP_IS_WINDOW (window));
- g_return_if_fail (window->priv->current_doc != NULL);
priv = window->priv;
entry = g_new0 (YelpHistoryEntry, 1);
- entry->doc_info = yelp_doc_info_ref (priv->current_doc);
+
entry->frag_id = g_strdup (priv->current_frag);
- /* page_title, frag_title */
+ entry->uri = g_strdup (priv->uri);
+ entry->req_uri = priv->req_uri;
+ entry->doc = priv->current_document;
+ entry->type = priv->current_type;
+ entry->base_uri = g_strdup (priv->base_uri);
+
+ /* page_title, frag_title */
priv->history_forward = g_slist_prepend (priv->history_forward, entry);
@@ -643,8 +634,8 @@ history_push_forward (YelpWindow *window)
title = (gchar *) gtk_window_get_title (GTK_WINDOW (window));
- if (g_str_equal (title, "Loading..."))
- entry->page_title = g_strdup ("Unknown Page");
+ if (g_str_equal (title, _("Loading...")))
+ entry->page_title = g_strdup (_("Unknown Page"));
else
entry->page_title = g_strdup (title);
@@ -698,17 +689,12 @@ history_step_back (YelpWindow *window)
priv = window->priv;
entry = history_pop_back (window);
- if (priv->current_doc) {
- yelp_doc_info_unref (priv->current_doc);
- priv->current_doc = NULL;
- }
if (priv->current_frag) {
g_free (priv->current_frag);
priv->current_frag = NULL;
}
if (entry) {
- priv->current_doc = yelp_doc_info_ref (entry->doc_info);
priv->current_frag = g_strdup (entry->frag_id);
history_entry_free (entry);
} else {
@@ -771,10 +757,10 @@ history_entry_free (YelpHistoryEntry *entry)
{
g_return_if_fail (entry != NULL);
- yelp_doc_info_unref (entry->doc_info);
g_free (entry->frag_id);
g_free (entry->page_title);
g_free (entry->frag_title);
+ g_free (entry->base_uri);
if (entry->menu_entry) {
gtk_widget_destroy (entry->menu_entry);
@@ -821,16 +807,7 @@ history_back_to (GtkMenuItem *menuitem, YelpHistoryEntry *entry)
latest->menu_entry = NULL;
}
- if (priv->current_doc)
- yelp_doc_info_unref (priv->current_doc);
- if (priv->current_frag)
- g_free (priv->current_frag);
-
- priv->current_doc = yelp_doc_info_ref (entry->doc_info);
- priv->current_frag = g_strdup (entry->frag_id);
-
- window_do_load (window, entry->doc_info, entry->frag_id);
-
+ history_load_entry (window, entry);
}
static void
@@ -870,118 +847,245 @@ history_forward_to (GtkMenuItem *menuitem, YelpHistoryEntry *entry)
latest->menu_entry = NULL;
}
- if (priv->current_doc)
- yelp_doc_info_unref (priv->current_doc);
- if (priv->current_frag)
- g_free (priv->current_frag);
+ history_load_entry (window, entry);
+
+}
- priv->current_doc = yelp_doc_info_ref (entry->doc_info);
- priv->current_frag = g_strdup (entry->frag_id);
+/******************************************************************************/
- window_do_load (window, entry->doc_info, entry->frag_id);
+GtkWidget *
+yelp_window_new (GNode *doc_tree, GList *index)
+{
+ return GTK_WIDGET (g_object_new (YELP_TYPE_WINDOW, NULL));
}
static void
-load_data_free (YelpLoadData *data)
+page_request_cb (YelpDocument *document,
+ YelpDocumentSignal signal,
+ gint req_id,
+ gpointer *func_data,
+ YelpWindow *window)
{
- g_return_if_fail (data != NULL);
+ YelpError *error;
+ YelpLoadData *data;
- g_object_unref (data->window);
- g_free (data->uri);
+ switch (signal) {
+ case YELP_DOCUMENT_SIGNAL_PAGE:
+ window_set_sections (window, yelp_document_get_sections (document));
- g_free (data);
-}
+ data = g_new0 (YelpLoadData, 1);
+ data->window = window;
+ data->page = (YelpPage *) func_data;
-/******************************************************************************/
+ window->priv->html_idle_handle = g_idle_add ((GSourceFunc)window_write_html, data);
-GtkWidget *
-yelp_window_new (GNode *doc_tree, GList *index)
-{
- return GTK_WIDGET (g_object_new (YELP_TYPE_WINDOW, NULL));
+ window->priv->current_request = -1;
+ yelp_page_free ((YelpPage *) func_data);
+ gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL);
+ break;
+ case YELP_DOCUMENT_SIGNAL_TITLE:
+ /* We don't need to actually handle title signals as gecko
+ * is wise enough to not annoy me by not handling it
+ */
+ g_free (func_data);
+ break;
+ case YELP_DOCUMENT_SIGNAL_ERROR:
+ error = (YelpError *) func_data;
+ window_error (window, (gchar *) yelp_error_get_title (error),
+ (gchar *) yelp_error_get_message (error), FALSE);
+ yelp_error_free (error);
+ gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL);
+ break;
+ default:
+ g_assert_not_reached();
+ }
}
-void
-yelp_window_load (YelpWindow *window, const gchar *uri)
+static void
+window_setup_window (YelpWindow *window, YelpRrnType type,
+ gchar *loading_uri, gchar *frag, gchar *req_uri,
+ gchar *base_uri, gboolean add_history)
{
+ /* Before asking the YelpDocument to find
+ * a page, this should be called to set up various
+ * things (such as fixing history, setting
+ * menu items to sensitive etc.)
+ * These are all read from the YelpWindow struct
+ * so they must be set BEFORE calling this.
+ */
YelpWindowPriv *priv;
- YelpDocInfo *doc_info;
- gchar *frag_id;
GtkAction *action;
- gchar *real_uri;
+
g_return_if_fail (YELP_IS_WINDOW (window));
- if (g_str_has_prefix (uri, "info:") && g_str_has_suffix (uri, "dir")) {
- real_uri = g_strdup ("x-yelp-toc:#Info");
- } else {
- real_uri = g_strdup (uri);
+ priv = window->priv;
+
+ if (priv->current_request != -1) {
+ yelp_document_cancel_page (priv->current_document, priv->current_request);
+ priv->current_request = -1;
+ } else if (add_history) {
+ gchar *tmp = window->priv->base_uri;
+ window->priv->base_uri = base_uri;
+ history_push_back(window);
+ window->priv->base_uri = tmp;
}
- debug_print (DB_FUNCTION, "entering\n");
- debug_print (DB_ARG, " uri = \"%s\"\n", uri);
- if (!real_uri) {
- GError *error = NULL;
- g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_DOC,
- _("The Uniform Resource Identifier for the file is "
- "invalid."));
- window_error (window, error, FALSE);
- return;
+ if (window->priv->html_idle_handle) {
+ g_source_remove (window->priv->html_idle_handle);
+ window->priv->html_idle_handle = 0;
}
- priv = window->priv;
+ window_set_loading (window);
- doc_info = yelp_doc_info_get (real_uri, FALSE);
- if (!doc_info) {
- GError *error = NULL;
- g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_DOC,
- _("The Uniform Resource Identifier ‘%s’ is invalid "
- "or does not point to an actual file."),
- real_uri);
- window_error (window, error, FALSE);
- return;
+ priv->current_type = type;
+ priv->uri = loading_uri;
+ priv->current_frag = g_strdup (frag);
+ priv->req_uri = g_strdup (req_uri);
+
+ switch (priv->current_type) {
+ case YELP_RRN_TYPE_DOC:
+ action = gtk_action_group_get_action (window->priv->action_group,
+ "PrintDocument");
+ g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
+
+ action = gtk_action_group_get_action (window->priv->action_group,
+ "AboutDocument");
+ g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
+ break;
+ default:
+ action = gtk_action_group_get_action (window->priv->action_group,
+ "PrintDocument");
+ g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
+
+ action = gtk_action_group_get_action (window->priv->action_group,
+ "AboutDocument");
+ g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
+ break;
+
}
- frag_id = yelp_uri_get_fragment (real_uri);
+}
- if (priv->current_doc && yelp_doc_info_equal (priv->current_doc, doc_info)) {
- if (priv->current_frag) {
- if (frag_id && g_str_equal (priv->current_frag, frag_id))
- goto load;
- }
- else if (!frag_id)
- goto load;
- }
- if (priv->current_doc)
- history_push_back (window);
- history_clear_forward (window);
+void
+yelp_window_load (YelpWindow *window, const gchar *uri)
+{
+ YelpWindowPriv *priv;
+ gchar *frag_id = NULL;
+ gchar *real_uri = NULL;
+ gchar *trace_uri = NULL;
+ YelpRrnType type = YELP_RRN_TYPE_ERROR;
+ YelpDocument *doc = NULL;
+ gchar *current_base = NULL;
- if (priv->current_doc)
- yelp_doc_info_unref (priv->current_doc);
- if (priv->current_frag)
- g_free (priv->current_frag);
+ g_return_if_fail (YELP_IS_WINDOW (window));
- action = gtk_action_group_get_action (priv->action_group,
- "PrintDocument");
- g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
+ priv = window->priv;
+ current_base = g_strdup (priv->base_uri);
+
+ /* If someone asks for info:dir, they WILL get redirected to
+ * our index. Tough.
+ */
+ if (g_str_has_prefix (uri, "info:") && g_str_has_suffix (uri, "dir")) {
+ trace_uri = g_strdup ("x-yelp-toc:#Info");
+ } else {
+ trace_uri = g_strdup (uri);
+ }
- priv->current_doc = yelp_doc_info_ref (doc_info);
- priv->current_frag = g_strdup (frag_id);
+ /* The way this route was taken, we need to clear the
+ * forward history now
+ */
+ history_clear_forward (window);
- load:
- window_do_load (window, doc_info, frag_id);
+ type = yelp_uri_resolve (trace_uri, &real_uri, &frag_id);
+ if (type == YELP_RRN_TYPE_ERROR) {
+ gchar *message = g_strdup_printf (_("The requested URI \"%s\" is invalid"), trace_uri);
+ window_error (window, _("Unable to load page"), message, FALSE);
+ g_free (message);
+ return;
+ }
- if (priv->current_frag != frag_id)
- g_free (frag_id);
- g_free (real_uri);
-}
+ if (priv->uri && g_str_equal (real_uri, priv->uri)) {
+ doc = priv->current_document;
+ } else {
+ g_free (priv->base_uri);
+ switch (type) {
+ case YELP_RRN_TYPE_TOC:
+ doc = yelp_toc_get ();
+ priv->base_uri = g_strdup ("file:///fakefile");
+ break;
+ case YELP_RRN_TYPE_MAN:
+ priv->base_uri = g_strdup_printf ("file:/%s", real_uri);
+ doc = yelp_man_new (real_uri);
+ break;
+ case YELP_RRN_TYPE_INFO:
+ priv->base_uri = g_strdup_printf ("file:/%s", real_uri);
+ if (!frag_id) {
+ frag_id = g_strdup ("Top");
+ } else {
+ g_strdelimit (frag_id, " ", '_');
+ }
+ doc = yelp_info_new (real_uri);
+ break;
+ case YELP_RRN_TYPE_DOC:
+ priv->base_uri = g_strdup_printf ("file:/%s", real_uri);
+ doc = yelp_docbook_new (real_uri);
+ break;
+ case YELP_RRN_TYPE_SEARCH:
+ doc = yelp_search_new (&real_uri[14]); /* to remove x-yelp-search:*/
+ break;
+ case YELP_RRN_TYPE_HTML:
+ case YELP_RRN_TYPE_XHTML:
+ window_do_load_html (window, real_uri, frag_id, type, TRUE);
+ break;
+ case YELP_RRN_TYPE_EXTERNAL:
+ {
+ gchar *stdout = NULL;
+ gchar *stderr = NULL;
+ gchar *cmd = NULL;
+ gint status = 0;
+ GError *error = NULL;
+ cmd = g_strdup_printf ("gnome-open %s", uri);
+ if (!g_spawn_command_line_sync (cmd, &stdout, &stderr, &status, &error)) {
+ g_free (error);
+ error = NULL;
+ g_free (cmd);
+ cmd = g_strdup_printf ("xdg-open %s", uri);
+ if (!g_spawn_command_line_sync (cmd, &stdout, &stderr, &status, &error)) {
+ window_error(window, _("Error executing \"gnome-open\""), error->message, FALSE);
+ return;
+ }
+ }
+ if (status) {
+ gchar *message = g_strdup_printf (_("The requested URI \"%s\" is invalid"), trace_uri);
+ window_error (window, _("Unable to load page"), message, FALSE);
+ return;
+ }
+ }
-YelpDocInfo *
-yelp_window_get_doc_info (YelpWindow *window)
-{
- g_return_val_if_fail (YELP_IS_WINDOW (window), NULL);
+ default:
+ break;
+ }
+ }
+
+ if (doc) {
+ gboolean need_hist = FALSE;
+ if (!frag_id)
+ frag_id = g_strdup ("index");
+
+ if (priv->current_document || (priv->current_type == YELP_RRN_TYPE_HTML ||
+ priv->current_type == YELP_RRN_TYPE_XHTML))
+ need_hist = TRUE;
+ window_setup_window (window, type, real_uri, frag_id,
+ (gchar *) uri, current_base, need_hist);
- return window->priv->current_doc;
+ priv->current_request = yelp_document_get_page (doc,
+ frag_id,
+ (YelpDocumentFunc) page_request_cb,
+ (void *) window);
+ }
+ priv->current_document = doc;
}
GtkUIManager *
@@ -992,109 +1096,10 @@ yelp_window_get_ui_manager (YelpWindow *window)
return window->priv->ui_manager;
}
-static void
-window_do_load (YelpWindow *window,
- YelpDocInfo *doc_info,
- gchar *frag_id)
-{
- GtkAction *action;
- GtkAction *about;
- GError *error = NULL;
- gchar *uri;
-
- g_return_if_fail (YELP_IS_WINDOW (window));
- g_return_if_fail (doc_info != NULL);
-
- debug_print (DB_FUNCTION, "entering\n");
-
- action = gtk_action_group_get_action (window->priv->action_group,
- "PrintDocument");
- g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
-
- about = gtk_action_group_get_action (window->priv->action_group,
- "AboutDocument");
- g_object_set (G_OBJECT (about), "sensitive", FALSE, NULL);
-
- switch (yelp_doc_info_get_type (doc_info)) {
- case YELP_DOC_TYPE_MAN:
-#ifdef ENABLE_MAN
- window_do_load_pager (window, doc_info, frag_id);
- break;
-#else
- g_set_error (&error, YELP_ERROR, YELP_ERROR_FORMAT,
- _("Man pages are not supported in this version."));
- break;
-#endif
-
- case YELP_DOC_TYPE_INFO:
-#ifdef ENABLE_INFO
- window_do_load_pager (window, doc_info, frag_id);
- break;
-#else
- g_set_error (&error, YELP_ERROR, YELP_ERROR_FORMAT,
- _("GNU info pages are not supported in this version"));
- break;
-#endif
-
- case YELP_DOC_TYPE_DOCBOOK_XML:
- g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
- g_object_set (G_OBJECT (about), "sensitive", TRUE, NULL);
- case YELP_DOC_TYPE_TOC:
- window_do_load_pager (window, doc_info, frag_id);
- break;
- case YELP_DOC_TYPE_SEARCH:
-#ifdef ENABLE_SEARCH
- window_do_load_pager (window, doc_info, frag_id);
- break;
-#else
- g_set_error (&error, YELP_ERROR, YELP_ERROR_FORMAT,
- _("Search is not supported in this version."));
- break;
-#endif
- case YELP_DOC_TYPE_DOCBOOK_SGML:
- g_set_error (&error, YELP_ERROR, YELP_ERROR_FORMAT,
- _("SGML documents are no longer supported. Please ask "
- "the author of the document to convert to XML."));
- break;
- case YELP_DOC_TYPE_HTML:
- case YELP_DOC_TYPE_XHTML:
- window_do_load_html (window, doc_info, frag_id);
- break;
- case YELP_DOC_TYPE_EXTERNAL:
- history_step_back (window);
- uri = yelp_doc_info_get_uri (doc_info, NULL, YELP_URI_TYPE_ANY);
- gnome_url_show (uri, &error);
- g_free (uri);
- break;
- case YELP_DOC_TYPE_ERROR:
- default:
- uri = yelp_doc_info_get_uri (doc_info, NULL, YELP_URI_TYPE_NO_FILE);
- if (!uri)
- uri = yelp_doc_info_get_uri (doc_info, NULL, YELP_URI_TYPE_FILE);
- if (uri)
- g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_DOC,
- _("The Uniform Resource Identifier ‘%s’ is invalid "
- "or does not point to an actual file."),
- uri);
- else
- g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_DOC,
- _("The Uniform Resource Identifier for the file is "
- "invalid."));
- g_free (uri);
- break;
- }
-
- if (error) {
- window_error (window, error, TRUE);
- }
-
- window_find_buttons_set_sensitive (window, TRUE, TRUE);
-}
-
/******************************************************************************/
static void
-window_error (YelpWindow *window, GError *error, gboolean pop)
+window_error (YelpWindow *window, gchar *title, gchar *message, gboolean pop)
{
YelpWindowPriv *priv;
GtkWidget *dialog;
@@ -1120,17 +1125,14 @@ window_error (YelpWindow *window, GError *error, gboolean pop)
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
- "%s", yelp_error_get_primary (error));
+ title);
gtk_message_dialog_format_secondary_markup
- (GTK_MESSAGE_DIALOG (dialog), "%s",
- yelp_error_get_secondary (error));
- gtk_dialog_run (GTK_DIALOG (dialog));
+ (GTK_MESSAGE_DIALOG (dialog), message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
- g_error_free (error);
gtk_widget_destroy (dialog);
}
-#ifdef ENABLE_SEARCH
static char *
encode_search_uri (const char *search_terms)
{
@@ -1158,15 +1160,28 @@ search_activated (GtkAction *action,
!strstr (&(search_terms[4])," ")) {
uri = g_strdup (search_terms);
uri[3]=':';
+ } else if (g_str_has_prefix (search_terms, "info ")) {
+ gint count = 0;
+ gchar *spaces;
+
+ spaces = strchr (search_terms, ' ');
+ while (spaces) {
+ count++;
+ spaces = strchr (search_terms, ' ');
+ }
+ if (count == 1) {
+ uri = g_strdup (search_terms);
+ uri[4] = ':';
+ } else {
+ uri = encode_search_uri (search_terms);
+ }
} else {
uri = encode_search_uri (search_terms);
}
-
yelp_window_load (window, uri);
g_free (uri);
}
-#endif
static void
@@ -1185,6 +1200,8 @@ window_populate (YelpWindow *window)
priv = window->priv;
+ priv->current_request = -1;
+
priv->main_box = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), priv->main_box);
@@ -1217,7 +1234,6 @@ window_populate (YelpWindow *window)
gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (f_proxy),
priv->forward_menu);
-#ifdef ENABLE_SEARCH
action = gtk_entry_action_new ("Search",
_("_Search:"),
_("Search for other documentation"),
@@ -1225,7 +1241,6 @@ window_populate (YelpWindow *window)
g_signal_connect (G_OBJECT (action), "activate",
G_CALLBACK (search_activated), window);
gtk_action_group_add_action (priv->action_group, action);
-#endif
priv->ui_manager = gtk_ui_manager_new ();
gtk_ui_manager_insert_action_group (priv->ui_manager, priv->action_group, 0);
@@ -1240,16 +1255,14 @@ window_populate (YelpWindow *window)
if (!gtk_ui_manager_add_ui_from_file (priv->ui_manager,
DATADIR "/yelp/ui/yelp-ui.xml",
&error)) {
- window_error (window, error, FALSE);
+ window_error (window, _("Cannot create window"), error->message, FALSE);
}
-#ifdef ENABLE_SEARCH
if (!gtk_ui_manager_add_ui_from_file (priv->ui_manager,
DATADIR "/yelp/ui/yelp-search-ui.xml",
&error)) {
- window_error (window, error, FALSE);
+ window_error (window, _("Cannot create search component"), error->message, FALSE);
}
-#endif
yelp_bookmarks_register (window);
@@ -1299,7 +1312,7 @@ window_populate (YelpWindow *window)
gtk_tree_view_insert_column_with_attributes
(GTK_TREE_VIEW (priv->side_sects), -1,
NULL, gtk_cell_renderer_text_new (),
- "text", YELP_PAGER_COLUMN_TITLE,
+ "text", YELP_DOCUMENT_COLUMN_TITLE,
NULL);
/* DISABLE FOR NOW
@@ -1367,7 +1380,6 @@ window_populate (YelpWindow *window)
gtk_widget_show (priv->main_box);
gtk_container_set_focus_child (GTK_CONTAINER (window),
GTK_WIDGET (priv->html_view));
-
}
static void
@@ -1447,197 +1459,67 @@ window_set_sections (YelpWindow *window,
g_return_if_fail (YELP_IS_WINDOW (window));
priv = window->priv;
- gtk_tree_view_set_model (GTK_TREE_VIEW (priv->side_sects), sections);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->side_sects), sections);
+
+ if (sections) {
+ gtk_widget_show_all (priv->side_sw);
+ window_set_section_cursor (window, sections);
+ } else
+ gtk_widget_hide (priv->side_sw);
- if (sections)
- gtk_widget_show_all (priv->side_sw);
- else
- gtk_widget_hide (priv->side_sw);
}
-static gboolean
-window_do_load_pager (YelpWindow *window,
- YelpDocInfo *doc_info,
- gchar *frag_id)
+static void
+window_set_section_cursor (YelpWindow * window, GtkTreeModel *model)
{
- YelpWindowPriv *priv;
- YelpPagerState state;
- YelpPager *pager;
- GError *error = NULL;
- YelpPage *page = NULL;
- gboolean loadnow = FALSE;
- gboolean startnow = TRUE;
- gboolean handled = FALSE;
-
- gchar *uri;
-
- g_return_val_if_fail (YELP_IS_WINDOW (window), FALSE);
- g_return_val_if_fail (doc_info != NULL, FALSE);
-
- priv = window->priv;
-
- uri = yelp_doc_info_get_uri (doc_info, frag_id, YELP_URI_TYPE_FILE);
-
- window_disconnect (window);
-
- pager = yelp_doc_info_get_pager (doc_info);
-
- if (!pager) {
- switch (yelp_doc_info_get_type (doc_info)) {
- case YELP_DOC_TYPE_DOCBOOK_XML:
- pager = yelp_db_pager_new (doc_info);
- break;
- case YELP_DOC_TYPE_INFO:
-#ifdef ENABLE_INFO
- pager = yelp_info_pager_new (doc_info);
- break;
-#else
- g_set_error (&error, YELP_ERROR, YELP_ERROR_FORMAT,
- _("GNU info pages are not supported in this version"));
-#endif
-
- case YELP_DOC_TYPE_MAN:
-#ifdef ENABLE_MAN
- pager = yelp_man_pager_new (doc_info);
- break;
-#else
- g_set_error (&error, YELP_ERROR, YELP_ERROR_FORMAT,
- _("Man pages are not supported in this version."));
- break;
-#endif
-
- case YELP_DOC_TYPE_TOC:
- pager = YELP_PAGER (yelp_toc_pager_get ());
- break;
- case YELP_DOC_TYPE_SEARCH:
-#ifdef ENABLE_SEARCH
- pager = YELP_PAGER (yelp_search_pager_get (doc_info));
- break;
-#else
- g_set_error (&error, YELP_ERROR, YELP_ERROR_FORMAT,
- _("Search is not supported in this version."));
- break;
-#endif
- default:
- break;
- }
- if (pager)
- yelp_doc_info_set_pager (doc_info, pager);
- }
-
- if (!pager) {
- if (!error)
- g_set_error (&error, YELP_ERROR, YELP_ERROR_PROC,
- _("A transformation context could not be created for "
- "the file ‘%s’. The format may not be supported."),
- uri);
- window_error (window, error, TRUE);
- handled = FALSE;
- goto done;
- }
-
- g_object_ref (pager);
-
- loadnow = FALSE;
- startnow = FALSE;
-
- state = yelp_pager_get_state (pager);
- debug_print (DB_DEBUG, "pager state=%d\n", state);
- switch (state) {
- case YELP_PAGER_STATE_ERROR:
- error = yelp_pager_get_error (pager);
- if (error)
- window_error (window, error, TRUE);
- handled = FALSE;
- goto done;
- case YELP_PAGER_STATE_RUNNING:
- case YELP_PAGER_STATE_FINISHED:
- /* Check if the page exists */
- pager_start_cb (pager, window);
-
- page = (YelpPage *) yelp_pager_get_page (pager, frag_id);
- if (!page && (state == YELP_PAGER_STATE_FINISHED)) {
- g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_PAGE,
- _("The section ‘%s’ does not exist in this document. "
- "If you were directed to this section from a Help "
- "button in an application, please report this to "
- "the maintainers of that application."),
- frag_id);
- window_error (window, error, TRUE);
- handled = FALSE;
- goto done;
- }
- loadnow = (page ? TRUE : FALSE);
- startnow = FALSE;
- break;
- case YELP_PAGER_STATE_NEW:
- case YELP_PAGER_STATE_INVALID:
- startnow = TRUE;
- /* no break */
- case YELP_PAGER_STATE_STARTED:
- case YELP_PAGER_STATE_PARSING:
- priv->start_handler =
- g_signal_connect (pager,
- "start",
- G_CALLBACK (pager_start_cb),
- window);
- break;
- default:
- g_assert_not_reached ();
- }
-
- window_set_sections (window,
- yelp_pager_get_sections (pager));
-
- if (loadnow) {
- window_handle_page (window, page);
- handled = TRUE;
- goto done;
- } else {
- window_set_loading (window);
-
- priv->page_handler =
- g_signal_connect (pager,
- "page",
- G_CALLBACK (pager_page_cb),
- window);
- priv->error_handler =
- g_signal_connect (pager,
- "error",
- G_CALLBACK (pager_error_cb),
- window);
- priv->cancel_handler =
- g_signal_connect (pager,
- "error",
- G_CALLBACK (pager_cancel_cb),
- window);
- priv->finish_handler =
- g_signal_connect (pager,
- "finish",
- G_CALLBACK (pager_finish_cb),
- window);
-
- if (startnow) {
- handled = yelp_pager_start (pager);
- if (handled) {
- yelp_toc_pager_pause (yelp_toc_pager_get ());
- priv->toc_pause++;
+ gboolean valid;
+ gchar *id = NULL;
+ GtkTreeIter iter;
+ YelpWindowPriv *priv = window->priv;
+ GtkTreeSelection *selection =
+ gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->side_sects));
+ g_signal_handlers_block_by_func (selection,
+ tree_selection_changed_cb,
+ window);
+ gtk_tree_selection_unselect_all (selection);
+
+ valid = gtk_tree_model_get_iter_first (model, &iter);
+ while (valid) {
+ gtk_tree_model_get (model, &iter,
+ YELP_DOCUMENT_COLUMN_ID, &id,
+ -1);
+ if (g_str_equal (id, priv->current_frag)) {
+ GtkTreePath *path = NULL;
+ GtkTreeIter parent;
+ if (gtk_tree_model_iter_parent (model, &parent, &iter)) {
+ path = gtk_tree_model_get_path (model, &parent);
+ gtk_tree_view_expand_to_path (GTK_TREE_VIEW (priv->side_sects),
+ path);
+ gtk_tree_path_free(path);
}
+ path = gtk_tree_model_get_path (model, &iter);
+ gtk_tree_selection_select_path (selection, path);
+
+ gtk_tree_path_free (path);
+ g_free (id);
+ break;
}
-
- /* FIXME: error if !handled */
+
+ g_free (id);
+
+ valid = tree_model_iter_following (model, &iter);
}
-
- done:
- g_free (uri);
-
- return handled;
+ g_signal_handlers_unblock_by_func (selection,
+ tree_selection_changed_cb,
+ window);
}
static gboolean
window_do_load_html (YelpWindow *window,
- YelpDocInfo *doc_info,
- gchar *frag_id)
+ gchar *uri,
+ gchar *frag_id,
+ YelpRrnType type,
+ gboolean need_history)
{
YelpWindowPriv *priv;
GnomeVFSHandle *handle;
@@ -1645,17 +1527,14 @@ window_do_load_html (YelpWindow *window,
GnomeVFSFileSize n;
gchar buffer[BUFFER_SIZE];
GtkAction *action;
+ gchar *real_uri = NULL;
gboolean handled = TRUE;
- gchar *uri;
g_return_val_if_fail (YELP_IS_WINDOW (window), FALSE);
- g_return_val_if_fail (doc_info != NULL, FALSE);
priv = window->priv;
- uri = yelp_doc_info_get_uri (doc_info, frag_id, YELP_URI_TYPE_FILE);
-
window_set_sections (window, NULL);
action = gtk_action_group_get_action (priv->action_group, "GoPrevious");
@@ -1667,28 +1546,34 @@ window_do_load_html (YelpWindow *window,
action = gtk_action_group_get_action (priv->action_group, "GoContents");
if (action)
g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
+
+ window_setup_window (window, type, uri, frag_id, uri, priv->base_uri, need_history);
result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
if (result != GNOME_VFS_OK) {
- GError *error = NULL;
- g_set_error (&error, YELP_ERROR, YELP_ERROR_IO,
- _("The file ‘%s’ could not be read. This file might "
- "be missing, or you might not have permissions to "
- "read it."),
- uri);
- window_error (window, error, TRUE);
+ gchar *message;
+
+ message = g_strdup_printf (_("The file ‘%s’ could not be read. This file might "
+ "be missing, or you might not have permissions to "
+ "read it."), uri);
+ window_error (window, _("Could Not Read File"), message, TRUE);
+ g_free (message);
handled = FALSE;
goto done;
}
- yelp_html_set_base_uri (priv->html_view, uri);
+ if (frag_id)
+ real_uri = g_strdup_printf ("file:/%s#%s", uri, frag_id);
+ else
+ real_uri = g_strdup_printf ("file:/%s", uri);
+ yelp_html_set_base_uri (priv->html_view, real_uri);
- switch (yelp_doc_info_get_type (doc_info)) {
- case YELP_DOC_TYPE_HTML:
+ switch (type) {
+ case YELP_RRN_TYPE_HTML:
yelp_html_open_stream (priv->html_view, "text/html");
break;
- case YELP_DOC_TYPE_XHTML:
+ case YELP_RRN_TYPE_XHTML:
yelp_html_open_stream (priv->html_view, "application/xhtml+xml");
break;
default:
@@ -1698,22 +1583,21 @@ window_do_load_html (YelpWindow *window,
while ((result = gnome_vfs_read
(handle, buffer, BUFFER_SIZE, &n)) == GNOME_VFS_OK) {
gchar *tmp;
-
tmp = g_utf8_strup (buffer, n);
- if (strstr (tmp, "<FRAMESET"))
+ if (strstr (tmp, "<FRAMESET")) {
yelp_html_frames (priv->html_view, TRUE);
+ }
g_free (tmp);
yelp_html_write (priv->html_view, buffer, n);
}
-
yelp_html_close (priv->html_view);
done:
if (handle)
gnome_vfs_close (handle);
-
- g_free (uri);
+ g_free (real_uri);
+ gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL);
return handled;
}
@@ -1747,193 +1631,6 @@ window_set_loading (YelpWindow *window)
gtk_window_set_title (GTK_WINDOW (window),
(const gchar *) loading);
- /*
- yelp_html_set_base_uri (priv->html_view, NULL);
- yelp_html_clear (priv->html_view);
- yelp_html_printf
- (priv->html_view,
- "<html><head><meta http-equiv='Content-Type'"
- " content='text/html=; charset=utf-8'>"
- "<title>%s</title></head>"
- "<body><center>%s</center></body>"
- "</html>",
- loading, loading);
- yelp_html_close (priv->html_view);
- */
-}
-
-static void
-window_handle_page (YelpWindow *window,
- YelpPage *page)
-{
- YelpWindowPriv *priv;
- YelpPager *pager;
- GtkAction *action;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- gchar *id;
- gchar *uri;
- gboolean valid;
-
- IdleWriterContext *context;
-
- g_return_if_fail (YELP_IS_WINDOW (window));
- priv = window->priv;
- window_disconnect (window);
-
- debug_print (DB_FUNCTION, "entering\n");
- debug_print (DB_ARG, " page->page_id = \"%s\"\n", page->page_id);
- debug_print (DB_ARG, " page->title = \"%s\"\n", page->title);
- debug_print (DB_ARG, " page->contents = %i bytes\n", strlen (page->contents));
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->side_sects));
- pager = yelp_doc_info_get_pager (priv->current_doc);
-
- if (model) {
- GtkTreeSelection *selection =
- gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->side_sects));
- g_signal_handlers_block_by_func (selection,
- tree_selection_changed_cb,
- window);
- gtk_tree_selection_unselect_all (selection);
-
- valid = gtk_tree_model_get_iter_first (model, &iter);
- while (valid) {
- gtk_tree_model_get (model, &iter,
- YELP_PAGER_COLUMN_ID, &id,
- -1);
- if (yelp_pager_page_contains_frag (pager,
- id,
- priv->current_frag)) {
- GtkTreePath *path = NULL;
- GtkTreeIter parent;
- if (gtk_tree_model_iter_parent (model, &parent, &iter)) {
- path = gtk_tree_model_get_path (model, &parent);
- gtk_tree_view_expand_to_path (GTK_TREE_VIEW (priv->side_sects),
- path);
- gtk_tree_path_free(path);
- }
- path = gtk_tree_model_get_path (model, &iter);
- gtk_tree_selection_select_path (selection, path);
-
- gtk_tree_path_free (path);
- g_free (id);
- break;
- }
-
- g_free (id);
-
- valid = tree_model_iter_following (model, &iter);
- }
- g_signal_handlers_unblock_by_func (selection,
- tree_selection_changed_cb,
- window);
- }
-
- priv->prev_id = page->prev_id;
- action = gtk_action_group_get_action (priv->action_group, "GoPrevious");
- if (action)
- g_object_set (G_OBJECT (action),
- "sensitive",
- priv->prev_id ? TRUE : FALSE,
- NULL);
- priv->next_id = page->next_id;
- action = gtk_action_group_get_action (priv->action_group, "GoNext");
- if (action)
- g_object_set (G_OBJECT (action),
- "sensitive",
- priv->next_id ? TRUE : FALSE,
- NULL);
- priv->toc_id = page->toc_id;
- action = gtk_action_group_get_action (priv->action_group, "GoContents");
- if (action)
- g_object_set (G_OBJECT (action),
- "sensitive",
- priv->toc_id ? TRUE : FALSE,
- NULL);
-
- context = g_new0 (IdleWriterContext, 1);
- context->window = window;
- context->type = IDLE_WRITER_MEMORY;
- context->buffer = page->contents;
- context->length = strlen (page->contents);
-
- uri = yelp_doc_info_get_uri (priv->current_doc,
- priv->current_frag,
- YELP_URI_TYPE_FILE);
-
- debug_print (DB_ARG, " uri = %s\n", uri);
-
- yelp_html_set_base_uri (priv->html_view, uri);
- yelp_html_open_stream (priv->html_view, "application/xhtml+xml");
-
- priv->idle_write = g_idle_add ((GtkFunction) idle_write, context);
-
- /*
- if (gnome_vfs_uri_get_fragment_identifier (uri->uri)) {
- yelp_html_jump_to_anchor
- (priv->html_view,
- (gchar *) gnome_vfs_uri_get_fragment_identifier (uri->uri));
- }
- */
-
- g_free (uri);
-}
-
-static void
-window_disconnect (YelpWindow *window)
-{
- YelpWindowPriv *priv;
- YelpPager *pager = NULL;
-
- g_return_if_fail (YELP_IS_WINDOW (window));
-
- priv = window->priv;
-
- if (priv && priv->current_doc) {
- pager = yelp_doc_info_get_pager (priv->current_doc);
- }
-
- if (GTK_WIDGET (window)->window)
- gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL);
-
- if (priv && priv->toc_pause > 0) {
- priv->toc_pause--;
- yelp_toc_pager_unpause (yelp_toc_pager_get ());
- }
-
- if (priv && priv->current_doc) {
- if (priv->start_handler) {
- g_signal_handler_disconnect (pager,
- priv->start_handler);
- priv->start_handler = 0;
- }
- if (priv->page_handler) {
- g_signal_handler_disconnect (pager,
- priv->page_handler);
- priv->page_handler = 0;
- }
- if (priv->error_handler) {
- g_signal_handler_disconnect (pager,
- priv->error_handler);
- priv->error_handler = 0;
- }
- if (priv->cancel_handler) {
- g_signal_handler_disconnect (pager,
- priv->cancel_handler);
- priv->cancel_handler = 0;
- }
- if (priv->finish_handler) {
- g_signal_handler_disconnect (pager,
- priv->finish_handler);
- priv->finish_handler = 0;
- }
- }
- if (priv && priv->idle_write) {
- g_source_remove (priv->idle_write);
- priv->idle_write = 0;
- }
}
/** Window Callbacks **********************************************************/
@@ -1952,125 +1649,6 @@ window_configure_cb (GtkWidget *widget,
return FALSE;
}
-/** Pager Callbacks ***********************************************************/
-
-static void
-pager_start_cb (YelpPager *pager,
- gpointer user_data)
-{
- YelpWindow *window = YELP_WINDOW (user_data);
- GError *error = NULL;
- const gchar *page_id;
-
- page_id = yelp_pager_resolve_frag (pager,
- window->priv->current_frag);
-
- debug_print (DB_FUNCTION, "entering\n");
- debug_print (DB_ARG, " page_id=\"%s\"\n", page_id);
-
- window_set_sections (window,
- yelp_pager_get_sections (pager));
-
- if (!page_id && window->priv->current_frag &&
- strcmp (window->priv->current_frag, "")) {
-
- window_disconnect (window);
-
- g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_PAGE,
- _("The section ‘%s’ does not exist in this document. "
- "If you were directed to this section from a Help "
- "button in an application, please report this to "
- "the maintainers of that application."),
- window->priv->current_frag);
- window_error (window, error, TRUE);
- }
-}
-
-static void
-pager_page_cb (YelpPager *pager,
- gchar *page_id,
- gpointer user_data)
-{
- YelpWindow *window = YELP_WINDOW (user_data);
- YelpPage *page;
-
- debug_print (DB_FUNCTION, "entering\n");
- debug_print (DB_ARG, " page_id=\"%s\"\n", page_id);
-
- if (yelp_pager_page_contains_frag (pager,
- page_id,
- window->priv->current_frag)) {
- page = (YelpPage *) yelp_pager_get_page (pager, page_id);
-
- /* now that yelp automatically inserts the id="index" attribute
- * on the root element of a document, the _contains_frag function
- * is no longer a good indication of whether a section exists.
- * Therefore if the returned page is NULL, then the stylesheets
- * were not able to create a "page" from this document through the
- * exsl:document extension (see yelp_xslt_document())
- * -Brent Smith, 1/4/2006 */
- if (page) {
- window_disconnect (window);
- window_handle_page (window, page);
- }
- }
-}
-
-static void
-pager_error_cb (YelpPager *pager,
- gpointer user_data)
-{
- YelpWindow *window = YELP_WINDOW (user_data);
- GError *error = yelp_pager_get_error (pager);
-
- debug_print (DB_FUNCTION, "entering\n");
-
- window_disconnect (window);
- window_error (window, error, TRUE);
-
- history_step_back (window);
-}
-
-static void
-pager_cancel_cb (YelpPager *pager,
- gpointer user_data)
-{
- YelpWindow *window = YELP_WINDOW (user_data);
- debug_print (DB_FUNCTION, "entering\n");
-
- window_disconnect (window);
-}
-
-static void
-pager_finish_cb (YelpPager *pager,
- gpointer user_data)
-{
- GError *error = NULL;
- YelpWindow *window = YELP_WINDOW (user_data);
- const gchar *page_id;
-
- page_id = yelp_pager_resolve_frag (pager,
- window->priv->current_frag);
-
- debug_print (DB_FUNCTION, "entering\n");
-
- if (!page_id && window->priv->current_frag &&
- strcmp (window->priv->current_frag, "")) {
-
- window_disconnect (window);
-
- g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_PAGE,
- _("The section ‘%s’ does not exist in this document. "
- "If you were directed to this section from a Help "
- "button in an application, please report this to "
- "the maintainers of that application."),
- window->priv->current_frag);
- window_error (window, error, TRUE);
- }
-
- /* FIXME: Remove the URI from the history and go back */
-}
-
/** Gecko Callbacks ***********************************************************/
static void
@@ -2095,10 +1673,10 @@ html_frame_selected_cb (YelpHtml *html, gchar *uri, gboolean handled,
{
YelpWindow *window = YELP_WINDOW (user_data);
gboolean handle;
- YelpDocInfo *info = yelp_doc_info_get (uri, FALSE);
- switch (yelp_doc_info_get_type (info)) {
- case YELP_DOC_TYPE_HTML:
- case YELP_DOC_TYPE_XHTML:
+
+ switch (window->priv->current_type) {
+ case YELP_RRN_TYPE_XHTML:
+ case YELP_RRN_TYPE_HTML:
handle = TRUE;
break;
default:
@@ -2165,9 +1743,9 @@ tree_selection_changed_cb (GtkTreeSelection *selection,
if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->side_sects));
gtk_tree_model_get (model, &iter,
- YELP_PAGER_COLUMN_ID, &id,
+ YELP_DOCUMENT_COLUMN_ID, &id,
-1);
- uri = yelp_doc_info_get_uri (priv->current_doc, id, YELP_URI_TYPE_ANY);
+ uri = g_strdup_printf ("%s#%s", priv->base_uri, id);
yelp_window_load (window, uri);
g_free (uri);
}
@@ -2181,6 +1759,8 @@ tree_drag_data_get_cb (GtkWidget *widget,
guint32 time,
YelpWindow *window)
{
+ /* TODO: This is disabled by default anyway */
+#if 0
YelpWindowPriv *priv;
GtkTreeSelection *tree_selection;
GtkTreeModel *model;
@@ -2199,7 +1779,7 @@ tree_drag_data_get_cb (GtkWidget *widget,
if (gtk_tree_selection_get_selected (tree_selection, NULL, &iter)) {
model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->side_sects));
gtk_tree_model_get (model, &iter,
- YELP_PAGER_COLUMN_ID, &id,
+ YELP_DOCUMENT_COLUMN_ID, &id,
-1);
uri = yelp_doc_info_get_uri (priv->current_doc, id,
YELP_URI_TYPE_NO_FILE);
@@ -2219,9 +1799,10 @@ tree_drag_data_get_cb (GtkWidget *widget,
}
g_free (uri);
+#endif
}
-static void
+void
tree_row_expand_cb (GtkTreeView *view, GtkTreePath *path,
GtkTreeViewColumn *column, YelpWindow *window)
{
@@ -2252,181 +1833,102 @@ window_new_window_cb (GtkAction *action, YelpWindow *window)
g_signal_emit (window, signals[NEW_WINDOW_REQUESTED], 0, NULL);
}
+
typedef struct {
- gulong page_handler;
- gulong error_handler;
- gulong cancel_handler;
- gulong finish_handler;
- YelpPager *pager;
YelpWindow *window;
+ GtkWindow *gtk_win;
+ GtkVBox *vbox;
+ YelpHtml *html;
} PrintStruct;
static void
-print_disconnect (PrintStruct *data)
-{
- debug_print (DB_FUNCTION, "entering\n");
- if (data->page_handler) {
- g_signal_handler_disconnect (data->pager,
- data->page_handler);
- data->page_handler = 0;
- }
- if (data->error_handler) {
- g_signal_handler_disconnect (data->pager,
- data->error_handler);
- data->error_handler = 0;
- }
- if (data->cancel_handler) {
- g_signal_handler_disconnect (data->pager,
- data->cancel_handler);
- data->cancel_handler = 0;
- }
- if (data->finish_handler) {
- g_signal_handler_disconnect (data->pager,
- data->finish_handler);
- data->finish_handler = 0;
- }
- g_free (data);
-}
-
-static void
-print_pager_page_cb (YelpPager *pager,
- gchar *page_id,
- gpointer user_data)
+window_print_signal (YelpDocument *document,
+ YelpDocumentSignal signal,
+ gint req_id,
+ gpointer *func_data,
+ PrintStruct *print)
{
- PrintStruct *data = user_data;
- YelpPage *page;
- debug_print (DB_FUNCTION, "entering\n");
- debug_print (DB_ARG, " page_id=\"%s\"\n", page_id);
-
- page = (YelpPage *) yelp_pager_get_page (pager, page_id);
-
- if (page) {
- YelpHtml *html;
- GtkWidget *gtk_window;
- int length, offset;
- char *uri;
- GtkWidget *vbox = gtk_vbox_new (FALSE, FALSE);
- debug_print (DB_DEBUG, page->contents);
-
- gtk_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- html = yelp_html_new ();
+ YelpError *error;
- gtk_container_add (GTK_CONTAINER (gtk_window), GTK_WIDGET (vbox));
- gtk_box_pack_end (GTK_BOX (vbox), GTK_WIDGET (html), TRUE, TRUE, 0);
+ switch (signal) {
+ case YELP_DOCUMENT_SIGNAL_PAGE:
+ window_write_print_html (print->html, (YelpPage *) func_data);
- gtk_widget_show (gtk_window);
- gtk_widget_show (GTK_WIDGET (html));
- gtk_widget_show (vbox);
- gtk_widget_hide (gtk_window);
- uri = yelp_doc_info_get_uri (yelp_pager_get_doc_info (pager),
- page_id,
- YELP_URI_TYPE_FILE);
-
- debug_print (DB_ARG, " uri = %s\n", uri);
-
- yelp_html_set_base_uri (html, uri);
- g_free (uri);
-
- yelp_html_open_stream (html, "application/xhtml+xml");
- for (length = strlen (page->contents), offset = 0; length > 0; length -= BUFFER_SIZE, offset += BUFFER_SIZE) {
- debug_print (DB_DEBUG, "data: %.*s\n", MIN (length, BUFFER_SIZE), page->contents + offset);
- yelp_html_write (html, page->contents + offset, MIN (length, BUFFER_SIZE));
- }
- yelp_html_close (html);
-
- yelp_print_run (data->window, html, gtk_window, vbox);
-
- print_disconnect (data);
+ yelp_page_free ((YelpPage *) func_data);
+ yelp_print_run (print->window, print->html, print->gtk_win, print->vbox);
+ break;
+ case YELP_DOCUMENT_SIGNAL_TITLE:
+ g_free (func_data);
+ break;
+ case YELP_DOCUMENT_SIGNAL_ERROR:
+ error = (YelpError *) func_data;
+ window_error (print->window, (gchar *) yelp_error_get_title (error),
+ (gchar *) yelp_error_get_message (error), FALSE);
+ yelp_error_free (error);
+ break;
+ default:
+ g_assert_not_reached();
}
-}
-
-static void
-print_pager_error_cb (YelpPager *pager,
- gpointer user_data)
-{
- PrintStruct *data = user_data;
- /* GError *error = yelp_pager_get_error (pager);*/
-
- debug_print (DB_FUNCTION, "entering\n");
- print_disconnect (data);
}
-static void
-print_pager_cancel_cb (YelpPager *pager,
- gpointer user_data)
-{
- PrintStruct *data = user_data;
- debug_print (DB_FUNCTION, "entering\n");
-
- print_disconnect (data);
-}
-
-static void
-print_pager_finish_cb (YelpPager *pager,
- gpointer user_data)
-{
- PrintStruct *data = user_data;
-
- debug_print (DB_FUNCTION, "entering\n");
-
- print_disconnect (data);
-}
static void
window_print_document_cb (GtkAction *action, YelpWindow *window)
{
- PrintStruct *data;
- YelpPager *pager;
+ YelpWindowPriv *priv;
+ GtkWidget *gtk_win;
+ YelpHtml *html;
+ GtkWidget *vbox = gtk_vbox_new (FALSE, FALSE);
+ PrintStruct *print;
+ YelpDocument *doc = NULL;
+
+ priv = window->priv;
- if (!window->priv->current_doc)
+ switch (priv->current_type) {
+ case YELP_RRN_TYPE_DOC:
+ doc = yelp_dbprint_new (priv->uri);
+ break;
+ default:
+ g_assert_not_reached ();
return;
+ }
- pager = yelp_db_print_pager_new (window->priv->current_doc);
- if (!pager) {
- return;
- }
+ gtk_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ html = yelp_html_new ();
+
+ gtk_container_add (GTK_CONTAINER (gtk_win), GTK_WIDGET (vbox));
+ gtk_box_pack_end (GTK_BOX (vbox), GTK_WIDGET (html), TRUE, TRUE, 0);
+ gtk_widget_show (gtk_win);
+ gtk_widget_show (vbox);
+ gtk_widget_show (GTK_WIDGET (html));
+ gtk_widget_hide (gtk_win);
- data = g_new0 (PrintStruct, 1);
- data->pager = pager;
- data->window = window;
-
- data->page_handler =
- g_signal_connect (data->pager,
- "page",
- G_CALLBACK (print_pager_page_cb),
- data);
- data->error_handler =
- g_signal_connect (data->pager,
- "error",
- G_CALLBACK (print_pager_error_cb),
- data);
- data->cancel_handler =
- g_signal_connect (data->pager,
- "error",
- G_CALLBACK (print_pager_cancel_cb),
- data);
- data->finish_handler =
- g_signal_connect (data->pager,
- "finish",
- G_CALLBACK (print_pager_finish_cb),
- data);
-
- /* handled = */ yelp_pager_start (data->pager);
+ print = g_new0 (PrintStruct, 1);
+
+ print->window = window;
+ print->gtk_win = (GtkWindow *) gtk_win;
+ print->vbox = (GtkVBox *) vbox;
+ print->html = html;
+
+ yelp_document_get_page (doc,
+ "index",
+ (YelpDocumentFunc) window_print_signal,
+ (void *) print);
}
static void
window_print_page_cb (GtkAction *action, YelpWindow *window)
{
+ YelpWindowPriv *priv;
GtkWidget *gtk_win;
- YelpPager *pager;
- YelpPage *page = NULL;
YelpHtml *html;
- int length, offset;
- gchar *uri;
GtkWidget *vbox = gtk_vbox_new (FALSE, FALSE);
+ PrintStruct *print;
+
+ priv = window->priv;
gtk_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
html = yelp_html_new ();
@@ -2438,48 +1940,51 @@ window_print_page_cb (GtkAction *action, YelpWindow *window)
gtk_widget_show (GTK_WIDGET (html));
gtk_widget_hide (gtk_win);
- pager = yelp_doc_info_get_pager (window->priv->current_doc);
-
- uri = yelp_doc_info_get_uri (window->priv->current_doc, NULL, YELP_URI_TYPE_FILE);
+ print = g_new0 (PrintStruct, 1);
- yelp_html_set_base_uri (html, uri);
+ print->window = window;
+ print->gtk_win = (GtkWindow *) gtk_win;
+ print->vbox = (GtkVBox *) vbox;
+ print->html = html;
+
+
+ if (priv->current_document) {
+ /* Need to go through the paging system */
+ yelp_document_get_page (priv->current_document,
+ priv->current_frag,
+ (YelpDocumentFunc) window_print_signal,
+ (void *) print);
+
+ } else {
+ /* HTML file */
- if (pager) {
- page = (YelpPage *) yelp_pager_get_page (pager, window->priv->current_frag);
-
- yelp_html_open_stream (html, "application/xhtml+xml");
- for (length = strlen (page->contents), offset = 0; length > 0; length -= BUFFER_SIZE, offset += BUFFER_SIZE) {
- debug_print (DB_DEBUG, "data: %.*s\n", MIN (length, BUFFER_SIZE), page->contents + offset);
- yelp_html_write (html, page->contents + offset, MIN (length, BUFFER_SIZE));
- }
- yelp_html_close (html);
- } else { /*html file. Dump file to window the easy way*/
GnomeVFSHandle *handle;
GnomeVFSResult result;
GnomeVFSFileSize n;
gchar buffer[BUFFER_SIZE];
-
- result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+
+ result = gnome_vfs_open (&handle, priv->uri, GNOME_VFS_OPEN_READ);
if (result != GNOME_VFS_OK) {
- GError *error = NULL;
+ /*GError *error = NULL;
g_set_error (&error, YELP_ERROR, YELP_ERROR_IO,
_("The file ‘%s’ could not be read. This file might "
"be missing, or you might not have permissions to "
"read it."),
uri);
- window_error (window, error, TRUE);
+ window_error (window, error, TRUE);*/
+ /* TODO: Proper errors */
return;
}
/* Assuming the file exists. If it doesn't how did we get this far?
* There are more sinister forces at work...
*/
- switch (yelp_doc_info_get_type (window->priv->current_doc)) {
- case YELP_DOC_TYPE_HTML:
+ switch (priv->current_type) {
+ case YELP_RRN_TYPE_HTML:
yelp_html_open_stream (html, "text/html");
break;
- case YELP_DOC_TYPE_XHTML:
+ case YELP_RRN_TYPE_XHTML:
yelp_html_open_stream (html, "application/xhtml+xml");
break;
default:
@@ -2492,12 +1997,10 @@ window_print_page_cb (GtkAction *action, YelpWindow *window)
}
yelp_html_close (html);
-
-
+ yelp_print_run (window, html, gtk_win, vbox);
+
}
- g_free (uri);
- yelp_print_run (window, html, gtk_win, vbox);
}
static void
@@ -2510,9 +2013,8 @@ window_about_document_cb (GtkAction *action, YelpWindow *window)
priv = window->priv;
- uri = yelp_doc_info_get_uri (priv->current_doc,
- "x-yelp-titlepage",
- YELP_URI_TYPE_ANY);
+ uri = g_strdup_printf("%s#__yelp_info", priv->uri);
+
yelp_window_load (window, uri);
g_free (uri);
}
@@ -2524,24 +2026,12 @@ window_open_location_cb (GtkAction *action, YelpWindow *window)
GladeXML *glade;
GtkWidget *dialog;
GtkWidget *entry;
- gchar *uri;
+ gchar *uri = NULL;
g_return_if_fail (YELP_IS_WINDOW (window));
priv = window->priv;
- if (priv->current_doc) {
- uri = yelp_doc_info_get_uri (priv->current_doc,
- priv->current_frag,
- YELP_URI_TYPE_NO_FILE);
- if (!uri)
- uri = yelp_doc_info_get_uri (priv->current_doc,
- priv->current_frag,
- YELP_URI_TYPE_FILE);
- } else {
- uri = NULL;
- }
-
glade = glade_xml_new (DATADIR "/yelp/ui/yelp.glade",
"location_dialog",
NULL);
@@ -2557,6 +2047,7 @@ window_open_location_cb (GtkAction *action, YelpWindow *window)
priv->location_dialog = dialog;
priv->location_entry = entry;
+ uri = priv->req_uri;
if (uri) {
gtk_entry_set_text (GTK_ENTRY (entry), uri);
gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
@@ -2638,29 +2129,13 @@ window_preferences_cb (GtkAction *action, YelpWindow *window)
static void
window_reload_cb (GtkAction *action, YelpWindow *window)
{
- YelpPager *pager;
-
- g_return_if_fail (YELP_IS_WINDOW (window));
-
- debug_print (DB_FUNCTION, "entering\n");
-
- if (window->priv->current_doc) {
- YelpLoadData *data;
- gchar *uri;
- pager = yelp_doc_info_get_pager (window->priv->current_doc);
-
- if (!pager)
- return;
-
- yelp_pager_cancel (pager);
-
- uri = yelp_doc_info_get_uri (window->priv->current_doc,
- window->priv->current_frag,
- YELP_URI_TYPE_ANY);
- data = g_new0 (YelpLoadData, 1);
- data->window = g_object_ref (window);
- data->uri = uri;
- g_idle_add ((GSourceFunc) window_load_async, data);
+ if (window->priv->current_document) {
+ if (window->priv->current_request > -1) {
+ yelp_document_cancel_page (window->priv->current_document, window->priv->current_request);
+ }
+ //g_object_unref (window->priv->current_document);
+ window->priv->current_document = NULL;
+ yelp_window_load (window, window->priv->req_uri);
}
}
@@ -2670,16 +2145,29 @@ window_enable_cursor_cb (GtkAction *action, YelpWindow *window)
yelp_settings_toggle_caret ();
}
-static gboolean
-window_load_async (YelpLoadData *data)
+static void
+history_load_entry (YelpWindow *window, YelpHistoryEntry *entry)
{
- yelp_window_load (data->window, data->uri);
+ g_return_if_fail (YELP_IS_WINDOW (window));
- load_data_free (data);
+ if (entry->type == YELP_RRN_TYPE_HTML || entry->type == YELP_RRN_TYPE_XHTML) {
+ window_do_load_html (window, entry->uri, entry->frag_id, entry->type, FALSE);
+ } else {
+ g_assert (entry->doc != NULL);
+ window_setup_window (window, entry->type, entry->uri, entry->frag_id, entry->req_uri,
+ window->priv->base_uri, FALSE);
+ g_free (window->priv->base_uri);
+ window->priv->base_uri = g_strdup (entry->base_uri);
+ window->priv->current_document = entry->doc;
+ window->priv->current_request = yelp_document_get_page (entry->doc,
+ entry->frag_id,
+ (YelpDocumentFunc) page_request_cb,
+ (void *) window);
+ }
- return FALSE;
}
+
static void
window_go_back_cb (GtkAction *action, YelpWindow *window)
{
@@ -2695,15 +2183,7 @@ window_go_back_cb (GtkAction *action, YelpWindow *window)
entry = history_pop_back (window);
- if (priv->current_doc)
- yelp_doc_info_unref (priv->current_doc);
- if (priv->current_frag)
- g_free (priv->current_frag);
-
- priv->current_doc = yelp_doc_info_ref (entry->doc_info);
- priv->current_frag = g_strdup (entry->frag_id);
-
- window_do_load (window, entry->doc_info, entry->frag_id);
+ history_load_entry (window, entry);
history_entry_free (entry);
}
@@ -2723,15 +2203,7 @@ window_go_forward_cb (GtkAction *action, YelpWindow *window)
entry = history_pop_forward (window);
- if (priv->current_doc)
- yelp_doc_info_unref (priv->current_doc);
- if (priv->current_frag)
- g_free (priv->current_frag);
-
- priv->current_doc = yelp_doc_info_ref (entry->doc_info);
- priv->current_frag = g_strdup (entry->frag_id);
-
- window_do_load (window, entry->doc_info, entry->frag_id);
+ history_load_entry (window, entry);
history_entry_free (entry);
}
@@ -2747,6 +2219,8 @@ window_go_home_cb (GtkAction *action, YelpWindow *window)
static void
window_go_previous_cb (GtkAction *action, YelpWindow *window)
{
+ printf ("Prev: %s\n", window->priv->prev_id);
+#if 0
YelpWindowPriv *priv;
gchar *base, *uri;
@@ -2762,11 +2236,14 @@ window_go_previous_cb (GtkAction *action, YelpWindow *window)
g_free (uri);
g_free (base);
+#endif
}
static void
window_go_next_cb (GtkAction *action, YelpWindow *window)
{
+ printf ("Next: %s\n", window->priv->next_id);
+#if 0
YelpWindowPriv *priv;
gchar *base, *uri;
@@ -2782,11 +2259,14 @@ window_go_next_cb (GtkAction *action, YelpWindow *window)
g_free (uri);
g_free (base);
+#endif
}
static void
window_go_toc_cb (GtkAction *action, YelpWindow *window)
{
+ printf ("index toc: %s\n", window->priv->toc_id);
+#if 0
YelpWindowPriv *priv;
gchar *base, *uri;
@@ -2802,28 +2282,21 @@ window_go_toc_cb (GtkAction *action, YelpWindow *window)
g_free (uri);
g_free (base);
+#endif
}
static void
window_add_bookmark_cb (GtkAction *action, YelpWindow *window)
{
- gchar *uri;
YelpWindowPriv *priv = window->priv;
debug_print (DB_FUNCTION, "entering\n");
- uri = yelp_doc_info_get_uri (priv->current_doc, priv->current_frag,
- YELP_URI_TYPE_NO_FILE);
- if (!uri)
- uri = yelp_doc_info_get_uri (priv->current_doc, priv->current_frag,
- YELP_URI_TYPE_FILE);
-
- if (!uri)
+ if (!priv->req_uri)
return;
- yelp_bookmarks_add (uri, window);
+ yelp_bookmarks_add (priv->req_uri, window);
- g_free (uri);
}
static void window_copy_link_cb (GtkAction *action, YelpWindow *window)
@@ -2850,6 +2323,7 @@ window_open_link_new_cb (GtkAction *action, YelpWindow *window)
g_free (window->priv->uri);
}
+/* TODO: This doesn't work... */
static void
window_copy_mail_cb (GtkAction *action, YelpWindow *window)
{
@@ -2892,7 +2366,7 @@ window_about_cb (GtkAction *action, YelpWindow *window)
"Mikael Hallendal <micke@imendio.com>",
"Alexander Larsson <alexl@redhat.com>",
"Shaun McCance <shaunm@gnome.org>",
- "Don Scorgie <DonScorgie@Blueyonder.co.uk>",
+ "Don Scorgie <Don@Scorgie.org>",
"Brent Smith <gnome@nextreality.net>",
NULL
};
@@ -3151,53 +2625,39 @@ tree_model_iter_following (GtkTreeModel *model,
return FALSE;
}
-/* Writing incrementally in an idle function has a number of advantages. First,
- * it keeps the interface responsive for really big pages. Second, it prevents
- * some weird rendering artifacts in gtkhtml2. Third, and most important, it
- * helps me beat the relayout race condition that I discuss at length in a big
- * comment in yelp-html-gtkhtml2.c.
- */
-
static gboolean
-idle_write (IdleWriterContext *context)
+window_write_html (YelpLoadData *data)
{
- YelpWindowPriv *priv;
-
- g_return_val_if_fail (context != NULL, FALSE);
- g_return_val_if_fail (context->window != NULL, FALSE);
-
- debug_print (DB_FUNCTION, "entering\n");
-
- priv = context->window->priv;
-
- switch (context->type) {
- case IDLE_WRITER_MEMORY:
- debug_print (DB_DEBUG, " context->buffer = %i bytes\n", strlen (context->buffer));
- debug_print (DB_DEBUG, " context->cur = %i\n", context->cur);
- debug_print (DB_DEBUG, " context->length = %i\n", context->length);
-
- if (context->cur + BUFFER_SIZE < context->length) {
- yelp_html_write (priv->html_view,
- context->buffer + context->cur,
- BUFFER_SIZE);
- context->cur += BUFFER_SIZE;
- return TRUE;
- } else {
- if (context->length > context->cur)
- yelp_html_write (priv->html_view,
- context->buffer + context->cur,
- context->length - context->cur);
- yelp_html_close (priv->html_view);
- g_free (context);
- priv->idle_write = 0;
- return FALSE;
- }
- break;
- case IDLE_WRITER_VFS:
- default:
- g_assert_not_reached ();
- }
- priv->idle_write = 0;
+ gsize read;
+ YelpHtml *html = data->window->priv->html_view;
+ gchar contents[BUFFER_SIZE];
+
+ /* Use a silly fake URI to stop gecko doing silly things */
+ yelp_html_set_base_uri (html, data->window->priv->base_uri);
+ yelp_html_open_stream (html, "application/xhtml+xml");
+
+ do {
+ yelp_page_read (data->page, contents, BUFFER_SIZE, &read, NULL);
+ yelp_html_write (html, contents, read);
+ } while (read == BUFFER_SIZE);
+ yelp_html_close (html);
+ data->window->priv->html_idle_handle = 0;
return FALSE;
}
+static void
+window_write_print_html (YelpHtml *html, YelpPage * page)
+{
+ gsize read;
+ gchar contents[BUFFER_SIZE];
+
+ /* Use a silly fake URI to stop gecko doing silly things */
+ yelp_html_set_base_uri (html, "file:///foobar");
+ yelp_html_open_stream (html, "application/xhtml+xml");
+
+ do {
+ yelp_page_read (page, contents, BUFFER_SIZE, &read, NULL);
+ yelp_html_write (html, contents, read);
+ } while (read == BUFFER_SIZE);
+ yelp_html_close (html);
+}
diff --git a/src/yelp-window.h b/src/yelp-window.h
index 0f45fa3e..89364a68 100644
--- a/src/yelp-window.h
+++ b/src/yelp-window.h
@@ -25,6 +25,7 @@
#include <gtk/gtktreemodel.h>
#include <gtk/gtkwindow.h>
+#include <gtk/gtk.h>
#include "yelp-base.h"
#include "yelp-utils.h"
@@ -61,7 +62,7 @@ GtkWidget * yelp_window_new (GNode *doc_tree,
GList *index);
void yelp_window_load (YelpWindow *window,
const gchar *uri);
-YelpDocInfo * yelp_window_get_doc_info (YelpWindow *window);
+const gchar * yelp_window_get_uri (YelpWindow *window);
GtkUIManager * yelp_window_get_ui_manager (YelpWindow *window);
#endif /* __YELP_WINDOW_H__ */
diff --git a/src/yelp-xslt-pager.c b/src/yelp-xslt-pager.c
index 84de6c28..0439a411 100644
--- a/src/yelp-xslt-pager.c
+++ b/src/yelp-xslt-pager.c
@@ -326,7 +326,7 @@ xslt_pager_finish (YelpPager *pager)
/** XSLT Extension Elements ***************************************************/
-static void
+void
xslt_yelp_document (xsltTransformContextPtr ctxt,
xmlNodePtr node,
xmlNodePtr inst,
@@ -456,7 +456,7 @@ xslt_yelp_document (xsltTransformContextPtr ctxt,
xsltFreeStylesheet (style);
}
-static void
+void
xslt_yelp_cache (xsltTransformContextPtr ctxt,
xmlNodePtr node,
xmlNodePtr inst,
diff --git a/stylesheets/toc2html.xsl b/stylesheets/toc2html.xsl
index 5be5b544..26cb7727 100644
--- a/stylesheets/toc2html.xsl
+++ b/stylesheets/toc2html.xsl
@@ -28,8 +28,6 @@
<xsl:param name="yelp.color.admon.bg.dark2"/>
<xsl:param name="yelp.color.admon.bg.dark3"/>
-<xsl:param name="yelp.toc.id" select="'Man-man6'"/>
-
<xsl:template match="toc">
<yelp:document href="{@id}">
<html>
@@ -151,6 +149,8 @@
<div class="docs">
<dl>
<xsl:for-each select="doc">
+ <xsl:sort order="ascending" data-type="number"
+ select="normalize-space(@weight)"/>
<xsl:sort select="normalize-space(title)"/>
<dt class="doc">
<a href="{@href}" title="{@href}">
@@ -237,7 +237,7 @@
<xsl:template mode="leftbar.mode" match="toc">
<xsl:param name="curid" select="0"/>
<ul>
- <xsl:for-each select="toc[.//doc[1]]">
+ <xsl:for-each select="toc[.//doc[1] or @protected]">
<li class="toclist">
<xsl:choose>
<xsl:when test="@id != $curid">
@@ -260,7 +260,7 @@
</xsl:template>
<xsl:template match="/">
- <xsl:apply-templates select="//toc[@id = $yelp.toc.id]" />
+ <xsl:apply-templates select="//toc" />
</xsl:template>
</xsl:stylesheet>
diff --git a/stylesheets/yelp-common.xsl b/stylesheets/yelp-common.xsl
index abea4566..c4625fd9 100644
--- a/stylesheets/yelp-common.xsl
+++ b/stylesheets/yelp-common.xsl
@@ -54,13 +54,13 @@
h6 span[class~="title"] { border-bottom: none; }
h7 span[class~="title"] { border-bottom: none; }
- /* Gecko seems to get selection color wrong on some themes */
+ <!--/* Gecko seems to get selection color wrong on some themes */
::-moz-selection {
background-color: </xsl:text>
<xsl:value-of select="$yelp.color.selected.bg"/><xsl:text>;
color: </xsl:text>
<xsl:value-of select="$yelp.color.selected.fg"/><xsl:text>;
- }
+ } -->
div[class~="linktrail"] {
-moz-box-sizing: border-box;
diff --git a/yelp.desktop.in.in b/yelp.desktop.in.in
index a203a7de..b8010b61 100644
--- a/yelp.desktop.in.in
+++ b/yelp.desktop.in.in
@@ -7,7 +7,7 @@ Icon=gnome-help.png
StartupNotify=true
Terminal=false
Type=Application
-Categories=GNOME;GTK;Core;
+Categories=GNOME;GTK;Application;Core;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=Yelp
X-GNOME-Bugzilla-Component=general