Commit graph

2488 commits

Author SHA1 Message Date
Salvador Cuñat
0a75ae63bf Fix warning on g_signal_connect() for radio4
Gtk complains if there is no  GCallback to connect.

Fixes too a bug with gtk_toggle_button_set_active for radio5.

Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-19 12:43:28 -07:00
Salvador Cuñat
9d6ddc24e9 Add user definible options to the print menu - slider version
Define a new frame wich will englobe the layout options.
1.-  Move to this frame the color profile printing by Amit
2.-  Add an option which switches the position of the profile and a
     predefined block comprensive of header, tanks data and notes.
             - Divide print() in two macros PROFILE_BLOCK and NOTES_BLOCK
             - Add a gboolean to print_options. If unselected (default) we
               get the actual disposition. If selected, switches blocks.
3.-  Add two buttons with labels to set the height of the profile, and tanks.
     We select the percentage of layout occupied by each option, reserving
     7% for the header (non adjustable), and assign the rest to notes.
            - Values in % have got hardcoded min/max (e.g. being the
              profile a major feature of subsurface, would be meaningless
              make it < 37%)
            - The values are initialised to the actual ones, so leaving
              them untouched defaults to the old printout.

Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-19 12:42:27 -07:00
Dirk Hohndel
14b6551a6a Manually remove events in the profile context menu
As logical extension of the ability to add bookmarks and gas changes this
adds the ability to remove (any arbitrary) event that happens at the mouse
position (specifically, that is within +/- six (scaled) pixels around the
x-position (time) of the mouse). That's the same width that the triangle
marker occupies which was moved to be centered around the event time in
commit 5752e9742e86 ("Finetune event triangle position to have the top
point at the event time").

Fixes #60

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-18 19:46:17 -07:00
Dirk Hohndel
471b944704 Finetune event triangle position to have the top point at the event time
This should make it easier to then delete events from the context menu.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-18 13:23:16 -07:00
Robert C. Helling
1e37fa99ed Manually add bookmarks in the profile context menu
Use the infrastructure created for manually adding gas change events to
also be able to add bookmarks.

[Dirk Hohndel: This combines two commits for clarity. I also cleaned up
               the indentation and changed the code to no longer print the
               exact same text twice.]

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-18 09:59:20 -07:00
Miika Turkia
daac2d6e43 Generate heading event on DM4 import
Previously the heading information was on bookmark event, but now we
trigger a heading event when direction info is available.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-18 09:46:57 -07:00
Robert C. Helling
959dc942be Correctly handle first gas when deciding if gas is used
Gas with index 0 is assumed to be the first gas only if there is no
gaschage event in the first 30 seconds of the dive.

[Dirk Hohndel: minor formatting change in a logical expression]

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-18 08:08:02 -07:00
Robert C. Helling
ae4bd802af Take only used gases into account when showing gas in divelist
Here is a patch that restricts the gases listed in the divelist to those
that are actually used. I seem to have the indentation now under control
but I am not sure about the logic:

1) First gas (with index 0) is always used.

2) If there is a gas switch event, the new gas is also used (determined by
walking the list of dive computers and then the list of events).

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-18 07:37:08 -07:00
Dirk Hohndel
8a5792d473 Manually add gas changes to a dive
Create a little widget that lists all the gases / tanks we know about and
allow the user to pick one of them.

Turns out that add_event only added events at the end of the list - but we
treat that list as chronologically sorted. So I fixed that little
mis-feature as well.

This does raise the question whether we need the inverse operation
(removing a gas change). And if there are other things that we should be
able to manually edit, now that we have the infrastructure for this neat
little context menu...

See #60 -- this doesn't address all of the issues mentioned there, but at
least deals with the 'headline' of the feature request...

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-17 20:04:25 -07:00
Dirk Hohndel
bfa37c3cac First step towards a context menu in the profile view
This is completely bogus as all it does is print out the corresponding
time for the spot we right-clicked on the profile. But that at least shows
that the infrastructure is working as intended...

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-17 16:15:36 -07:00
Miika Turkia
a094b2b88a Terminate decode at end of string and fix mem leak
Seems that we have to NULL terminate the buffer for
xmlStringLenDecodeEntitites() as otherwise we might end up having extra
data at the end of returned buffer.  (Somehow the length parameter is
not respected always, even if it is the proper size returned by the
zip_fread() - header_skip).

Also free the buffer returned by xmlStringLenDecodeEntitites().

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-17 14:55:53 -07:00
Miika Turkia
38d224a335 Only print separator when really needed on import
The separator was printed if SITE had data, even if LOCATION was empty.
Now print the separator only if both of these contain data.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-16 15:16:41 -07:00
Dirk Hohndel
fbb260aeb5 Use a generic 64bit int type
The zip_int64_t type appears to be missing with mingw so it breaks my cross
builds - and this is clearly equivalent.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-15 16:36:41 -07:00
Miika Turkia
757791335f Support divelogs.de exports that include Cyrillic characters
divelogs.de sends us XML files that explicitly state that they are in
ISO-8859-1 encoding (which is true). These files contain the HTML encoded
Cyrillic characters. Once we decode those characters the resulting file is
actually UTF-8 encoded (which is a superset of ISO-8859-1). That seriously
confuses libxml when it tries to parse things.

So instead recognize divelogs.de files and skip the encoding declaration
for them before decoding the HTML encoded non-ISO-8859-1 characters.

This does show, however, that divelogs.de incorrectly truncates the
encoded strings (at least in some sample data that I created the parsing
throws errors because of that).

Reported-by: Sergey Starosek <sergey.starosek@gmail.com>
Based-on-code-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-15 16:29:37 -07:00
Miika Turkia
98d769a02f Correct ending pressure for .DLD export
We grab the pressure information from samples, if available. Otherwise,
we use information from first cylinder.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-14 12:20:05 -07:00
Amit Chaudhuri
d6e77cd168 Fix bug in colour print initialisation.
The callback function for switching colour printing on/off was
registered after the initial activation of the button. This meant the
first attempt to print was compromised. We move the registration so that
printing works as the user specifies from the first attempt.

Tested by printing both B/W and colour images to file with minimal mouse
clicks.

Spotted by Salva - thanks.

Signed-off-by: Amit Chaudhuri <amit.k.chaudhuri@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-14 11:30:23 -07:00
Miika Turkia
03c21b0a92 Fix free form text fields on .DLD upload
We need to have CDATA around text fields to support e.g. Cyrillic
alphabet.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-14 08:28:55 -07:00
Henrik Brautaset Aronsen
9187415124 Revert "Only include .po files that has a companion .aliases file"
Commit 6044c22741 wrongly assumed that a disabled .po file had a companion
.disabled file instead of an .aliases file.

Running make after "tx pull -af" generated errors which I tried to fix.  I
shouldn't have, because the Makefile did the right thing. It warned about a
missing .aliases file for a brand new translation.

So, I'm reverting the commit and use "tx pull -f" instead the next time I
need to test existing translations.

Signed-off-by: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-14 06:55:24 -07:00
Henrik Brautaset Aronsen
6044c22741 Only include .po files that has a companion .aliases file
Disabled translations have a .disabled file instead of
an .aliases file.  Without this patch I couldn't make
subsurface after a tx pull (when testing translations).

This patch makes the .aliases file an explicit requirement
for a valid translation.

Signed-off-by: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-13 23:27:01 -07:00
Dirk Hohndel
faf7b28b20 Simple dialog to obtain user/password for divelogs.de
The password is handled in clear text and stored in the config as such.
Some people might object to that...

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-13 22:46:05 -07:00
Dirk Hohndel
bd9f8ad7f8 First simplistic implementation of a divelogs.de upload
This has no user interface and hardcodes a testing username / password.
But it can successfully create a DLD file (thanks to Miika and Lubomir)
and then uses libsoup to upload that to the server.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-13 20:37:38 -07:00
Amit Chaudhuri
3e1098bd03 Hook up color printing with print dialog.
- Add a button and callback to the print dialog to let the user select
  color printing.
- Add a state variable to the options struct to track the users choice.
- Use a darker color for the grid on dive plot; that way we can see it.
- Default to use color printing.

Signed-off-by: Amit Chaudhuri <amit.k.chaudhuri@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-13 02:53:35 -07:00
Lubomir I. Ivanov
099953e776 DLD upload: Avoid using open_memstream() and non-portable functions
patch contains:
- replacement for open_memstream()
- storage of the temporary zip file in the OS temporary directory
- replacement usage of mktemp() with g_mkstemp()

patch based on work by Miika Turkia.

[Dirk Hohndel: as suggested by Miika I commented out the deletion of the
               DLD file]

Acked-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-12 22:17:20 -07:00
Sylvestre Ledru
87fe20600f Fix the build under Kfreebsd & HURD.
Ensure that Kfreebsd and HURD are recognized as "like Linux"

Signed-off-by: Sylvestre Ledru <sylvestre@debian.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-12 21:50:45 -07:00
Miika Turkia
f22527fdaf Fix XSLT when no weight system is given
Summing up weights ended only when there was one parameter left. With no
parameters we ended up in an infinite loop. Now we end also in case of
no parameters.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-10 13:43:02 -07:00
Miika Turkia
42ea5e3510 .DLD generation for uploading to divelogs.de
This generates a .DLD file of selected dives to be uploaded to
divelogs.de. The actual upload functionality along with sensible user
interface is still to be implemented. However, the resulting file from
this patch is tested to work (as far as I can tell) using upload API of
divelogs.de.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-10 09:29:12 -07:00
Miika Turkia
7c6ff9f957 Convert Subsurface XML to divelogs.de format
The resulting divelogs.de formatted XML is then to be zipped and
uploaded to divelogs.de website.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-10 09:27:53 -07:00
Lubomir I. Ivanov
cb30d6d864 Table print: Ignore a dive instead of breaking the dive loop
draw_table():
When get_dive_for_printing() returns NULL, instead of
breaking, we should 'continue' trough the entire loop. Otherwise
the paginate() handler will be called dive_table.nr times, until
it returns TRUE.

Fixes a bug where, for example one selected dive can end up allocating
dive_table.nr pages for printing.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-10 09:22:34 -07:00
Lubomir I. Ivanov
e8d582dbd4 Table print: Add an extra line bellow the table header
In 'table print' for some launguages the table header titles can span
on two lines and the text on the second line ends up overlapping with
the table border. With this patch two lines are reserved for the table
header instead of one.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-10 09:22:29 -07:00
Lubomir I. Ivanov
a9d613640d Table print: Only show a table header when not 'paginating'
Strangely on Linux everything looks fine, but Windows shows the header
two times on the first page, which is due to the pango_cairo_show_layout()
function being called both for the 'paginating' and 'regular' stages
in show_table_header().

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-10 09:22:26 -07:00
Lubomir I. Ivanov
6c7e2f9ffa Info dialog: print coordinates using an ASCII 'dtoa' type of method
dac29e7bc4 introduced changes to how the GPS coordinate string
is parsed; we now prefer to parse decimal numbers using the '.'
character.

This patch makes modifications to info.c:print_gps_coordinates(),
where we are still using a locale dependent method for converting
a double to string - snprintf(). Instead, we attempt to use GLib's
g_ascii_formatd(), and store the resulted strings into two
buffers named 'dbuf_lat' and 'dbuf_lon'. We then pass the buffers
to the final snprintf() formatting with '%s'.

Reported-and-tested-by: Sergey Starosek <sergey.starosek@gmail.com>
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-10 09:21:55 -07:00
Lubomir I. Ivanov
6dd31a6cc6 Bring back support for GTK versions pre 2.24
The introduction of GtkComboBoxText usage for selecting a map provider,
removed support for older versions of GTK on distros like Debian 6.0.4.

Parent class (GtkComboBox) methods have to be used instead, around
more pre-processor branching.

This patch also fixes a small memory leak when retrieving text from said
combo box.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-09 10:28:54 -08:00
Miika Turkia
e362272edc Use information from proper table on DM4 import
Seems that DM4 has useless cylinder size data on global level and real
data on DiveMixture table. So using the correct data instead of the
global un-used value.

Similarly the DiveMixture table contains cylinder pressures. However, it
appears this information is available on DiveMixture table only in some
cases. So we use start and end pressures from DM table if available,
otherwise we use the global pressures. (My guess is that the DM table
has the pressure info only when the pressure has dropped from the
initial pressure reading that is reported in Dive table before the dive
is considered to have started.)

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-08 11:54:11 -08:00
Dirk Hohndel
b5cd46aa39 Sanity check on temperature values
The range is still very wide (as we get both air and water temperatures),
but it will at least eliminate some completely bogus outliers.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-08 11:52:10 -08:00
Miika Turkia
4297d931a3 Identify converted files as imported
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-08 10:17:33 -08:00
Dirk Hohndel
473bc91c8a Don't strdup(NULL)
merge_text() could call strdup(NULL) if one pointer was "" and the other
NULL. This commit fixes that.

Reported-by: fhuberts
Analyzed-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-08 10:09:57 -08:00
Dirk Hohndel
dac29e7bc4 Never use localized floating point numbers
The GPS entry incorrectly used strtod

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-08 09:57:53 -08:00
Linus Torvalds
f1f667c96f Warn about commas in floating point values
Localization could be causing floating point numbers to have a comma
instead of a decimal point (in a file format that is really stupid).
If we detect this we replace the comma with a decimal point instead, and
try to re-parse the number, and see if we get further.

The downside of that is that we're changing the buffer we get passed in.
Nobody cares, but still, it's kind of ugly. It's simple, though.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-08 09:51:49 -08:00
Amit Chaudhuri
29be221bd8 Reorganise view menus and file import.
Move the view submenu to a top level location.

Alter the wording of File|Import to drop XML qualifier; we import more
formats than this.

Signed-off-by: Amit Chaudhuri <amit.k.chaudhuri@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-08 08:48:52 -08:00
Lubomir I. Ivanov
4401132836 Fix potentially broken white space truncation on certain Windows versions
Testing the Planner in Subsurface on a Windows XP SP3 installation,
shows corrupted UTF-8 strings in the case of Cyrillic locales, but
possibly others as well. Instead limited to the Planner, this affects
the entire application.

After some examination it appears that <ctype>'s isspace() in MSVC
on the tested version of Windows is broken for some UTF-8 characters,
after enabling the user locale using: setlocale(LC_ALL, "");

For example, characters such as the Cyrillic capital "BE" are defined as:
0xD091, where isspace() for the first byte returns 0x08, which is the
bytemask for C1_SPACE and the character is treated as space.
After a byte is treated as space, it is usually discarded from a UTF-8
character/string, where if only one byte left, corrupting the entire
string.

In Subsurface, usages of string trimming are present in multiple
locations, so to make this work try to use GLib's g_ascii_isspace(),
which is a locale agnostic version of isspace().

Affected versions of Windows could be everything up to XP SP3,
but not apparently Vista.

Reported-by: Sergey Starosek <sergey.starosek@gmail.com>
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-07 12:01:47 -08:00
Miika Turkia
9f6b8ca89a Translate comma to colon on XML import
Translate decimal commas on XML import to decimal points. (As detected
from available sample files using Linus' debug printing.)

Also check for empty values on MacDive temperature import.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-07 11:58:57 -08:00
Miika Turkia
eee29f2187 DM4 import user documentation update
Instructions how to find the effective database file from DM4, using
this method there is no need to rename the backup as the original file
works as is when found from a random directory structure.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-07 10:27:52 -08:00
Miika Turkia
27ab7c7707 DM4 import pressure detection fix
Seems that the database can contain either null or empty string when
there is no pressure data available. Changing the pressureblob
validation to reflect this new information.

Since the temperature profile is binary data, we most likely should
accept 0 as a valid value. My samples have null in this blob if there is
no data so it seems to be different than the pressure blob. But of
course there are no guarantees...

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-07 10:27:42 -08:00
Miika Turkia
3e27e49415 Test if .bak file is supported database dive log
Even though the documentation states to rename DM4 backup to .db file
extension, accept the default .bak extension as well. This, however,
does not enable the .bak extension in file selection dialog (so .bak
files must be given as command line parameters).

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-07 10:27:31 -08:00
Miika Turkia
a9cc7f9b10 Fix import when locale set to decimal comma
This should take care of locale caused problems when the input uses decimal
point but locale uses decimal comma. Also the sample I have of Suunto DM3
format weight is represented with comma instead of dot so converting that as
well.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-07 10:27:20 -08:00
Miika Turkia
2120bc3a9e More events from Suunto DM4 added
I got a few more events from a new sample database. Bookmark heading is
now shown if such information is stored. Also the unknown events display
the event number for easier identification.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-07 10:21:55 -08:00
Lubomir I. Ivanov
30e10183ca windows.c: Use a zeroed buffer when retrieving the module path
There is a small API note on GetModuleFileName(), which says:
"Windows XP: The string is truncated to nSize characters
and is not null-terminated."

Which means that on XP it will be only safe if we pass a zeroed
buffer to it, otherwise the next call to wcsrchr (which is
a strchr for wchar_t) may not find a relative terminating \0 in
the buffer, returning a wrong pointer and resulting in a corrupted
string.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-05 12:27:32 -08:00
Dirk Hohndel
07b2c204c9 Remove ancient (and unwanted) Debian packaging directory
The Debian maintainers prefer this to be separate from the upstream
sources

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-05 12:05:42 -08:00
Lubomir I. Ivanov
4cd222eae7 windows.c: Change the current process path to the module path
When an executable is started on Windows, it has a "Working
directory". This directory for a program shortcut stored on the
Desktop can be different than the actual executable directory.
This also applies if a shell extension is registered to that
executable (in the case of Subsurface that could be a .DLD file).

When another process simply "executes" a file with a certain extension
(e.g. when you double click on a .DLD file), a method ShellExecute
is called, which without explicit parameters sets the "Working
directory" to the .DLD file directory. This can be a bit of a trouble
if the executed module depends on relative paths (e.g. ./xslt, ./share).

To solve that we obtain our module full path and filename using
GetModuleFileName(), strip the filename from it (e.g. subsurface.exe)
and then pass the resulted string to SetCurrentDirectory(), which
updates the "Working directory".

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-05 12:04:26 -08:00
Miika Turkia
08f438a2c9 Suunto DM4 sample dive
Both in .db and exported XMK format.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-03-05 11:08:08 -08:00