Further work on animated GIF export: XDG Pictures

Using XDG's user dir settings to determine where pictures are
stored for a user (e.g., "~/Pictures" -- used as a fallback).
May be overridden using "--exportdir".

Also, while I was updating some docs, replace references to
"Mac OS X" with "macOS", the new name of that OS these days.
This commit is contained in:
Bill Kendrick 2020-07-25 16:45:17 -07:00
parent 683bbf5f19
commit f8cce36435
13 changed files with 329 additions and 68 deletions

View file

@ -8,7 +8,7 @@ http://www.tuxpaint.org/
$Id$ $Id$
2020.July.24 (0.9.25) 2020.July.25 (0.9.25)
* New Features * New Features
------------ ------------
* [WIP] GIF export option from Open -> Slideshow dialog. * [WIP] GIF export option from Open -> Slideshow dialog.
@ -17,6 +17,9 @@ $Id$
* Depends on "libimagequant", from the "pngquant2" project: * Depends on "libimagequant", from the "pngquant2" project:
https://github.com/ImageOptim/libimagequant https://github.com/ImageOptim/libimagequant
(GPL v3 or later, for Free/Libre Open Source Software) (GPL v3 or later, for Free/Libre Open Source Software)
* Uses XDG user dirs settings, if available, to determine
where to store them, or "~/Pictures", otherwise.
"--exportdir" option can be used to override this.
* Ports & Building * Ports & Building
---------------- ----------------

View file

@ -2,11 +2,11 @@ INSTALL.txt for Tux Paint
Tux Paint - A simple drawing program for children. Tux Paint - A simple drawing program for children.
Copyright (c) 2002-2018 Copyright (c) 2002-2020
Various contributors (see below, and AUTHORS.txt) Various contributors (see below, and AUTHORS.txt)
http://www.tuxpaint.org/ http://www.tuxpaint.org/
June 27, 2002 - December 8, 2018 June 27, 2002 - July 25, 2020
$Id$ $Id$
@ -119,6 +119,14 @@ Requirements:
Also depends on: Also depends on:
libxml2 libxml2
Animated GIF Export feature
---------------------------
So support export of animated GIFs (slideshows), the
"libimagequant" library (from the "pngquant2" project)
is required.
https://github.com/ImageOptim/libimagequant
NetPBM Tools [OPTIONAL] [No longer used, by default] NetPBM Tools [OPTIONAL] [No longer used, by default]
------------------------ ------------------------
Under Linux and Unix, the NetPBM tools are what are currently Under Linux and Unix, the NetPBM tools are what are currently

View file

@ -6,7 +6,7 @@ Options Documentation
Copyright (c) 2002-2020 by various contributors; see AUTHORS.txt Copyright (c) 2002-2020 by various contributors; see AUTHORS.txt
http://www.tuxpaint.org/ http://www.tuxpaint.org/
June 22, 2020 July 25, 2020
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -187,7 +187,7 @@ Windows Users
printcfg=yes printcfg=yes
(Windows and Mac OS X only) (Windows and macOS only)
Tux Paint will use a printer configuration file when printing. Tux Paint will use a printer configuration file when printing.
Push the [Alt] key while clicking the 'Print' button in Push the [Alt] key while clicking the 'Print' button in
@ -224,7 +224,7 @@ Windows Users
papersize=PAPERSIZE papersize=PAPERSIZE
(Platforms that use Tux Paint's internal PostScript generator (Platforms that use Tux Paint's internal PostScript generator
— not Windows, Mac OS X or BeOS.) — not Windows, macOS, BeOS, or Haiku.)
Tell Tux Paint what size PostScript to generate. If none is Tell Tux Paint what size PostScript to generate. If none is
specified, Tux Paint first checks your $PAPER environment specified, Tux Paint first checks your $PAPER environment
@ -560,7 +560,7 @@ Windows Users
Example: Example:
"C:\Documents and Settings\Username\Application Data\TuxPaint\saved\" "C:\Documents and Settings\Username\Application Data\TuxPaint\saved\"
* Mac OS X — Inside a folder named "TuxPaint" in your * macOS — Inside a folder named "TuxPaint" in your
"Application Support" folder. "Application Support" folder.
Example: Example:
"/Users/Username/Library/Application Support/TuxPaint/saved/" "/Users/Username/Library/Application Support/TuxPaint/saved/"
@ -576,15 +576,40 @@ Windows Users
Example: savedir=Z:\tuxpaint\ Example: savedir=Z:\tuxpaint\
exportdir=DIRECTORY
Use this option to change where Tux Paint exports files —
single images, or animated GIF slideshows — for external use.
If you do not override it, the default location is:
* Linux & Unix — If available, wherever your desktop
environment is configured for pictures to be stored,
based on your XDG (X Desktop Group) configuration. (Try
running the command-line "xdg-user-dir PICTURES" to find
out.)
Typically (in an English locale), this will be a
"Pictures/" subdirectory in your home directory (i.e.,
"$HOME/Pictures/" aka "~/Pictures").
Tux Paint will fall back to using that typical directory,
of no XDG configuration can be read, or nothing is set
for "XDG_PICTURES_DIR".
* Windows — TBD!
* macOS — TBD!
Example: exportdir=/home/penguin/TuxPaintExports
datadir=DIRECTORY datadir=DIRECTORY
Use this option to change where Tux Paint looks for personal Use this option to change where Tux Paint looks for personal
data files (brushes, stamps, starters and fonts specific to data files (brushes, stamps, starters, templates, and fonts
the current user). specific to the current user).
Tux Paint will search for subdirectories/subfolders named Tux Paint will search for subdirectories/subfolders named
"brushes", "stamps", "starters" and "fonts" under the data "brushes", "stamps", "starters", "templates", and "fonts"
directory. under the specified data directory.
If you do not override it, the default location is: If you do not override it, the default location is:
* Linux & Unix — Under a hidden directory named ".tuxpaint" * Linux & Unix — Under a hidden directory named ".tuxpaint"
@ -596,7 +621,7 @@ Windows Users
Example: Example:
"C:\Documents and Settings\Username\Application Data\TuxPaint\brushes\" "C:\Documents and Settings\Username\Application Data\TuxPaint\brushes\"
* Mac OS X — Inside a folder named "TuxPaint" in your * macOS — Inside a folder named "TuxPaint" in your
"Application Support" folder. "Application Support" folder.
Example: Example:
"/Users/Username/Library/Application Support/TuxPaint/brushes/" "/Users/Username/Library/Application Support/TuxPaint/brushes/"

View file

@ -121,7 +121,7 @@ Loading Tux Paint
---------------------------------------------------------------------- ----------------------------------------------------------------------
Mac OS X Users macOS Users
Simply double-click the "Tux Paint" icon. Simply double-click the "Tux Paint" icon.
@ -604,7 +604,7 @@ Available Tools
Printer Settings Printer Settings
(Windows and Mac OS X) (Windows and macOS)
By default, Tux Paint simply prints to the By default, Tux Paint simply prints to the
default printer with default settings when the default printer with default settings when the
@ -753,7 +753,7 @@ Available Tools
Inside the user's "Application Data" folder, e.g.: "C:\Documents Inside the user's "Application Data" folder, e.g.: "C:\Documents
and Settings\(user name)\Application Data\TuxPaint\saved\" and Settings\(user name)\Application Data\TuxPaint\saved\"
Mac OS X macOS
Inside the user's "Library" folder: Inside the user's "Library" folder:
"/Users/(user name)/Library/Application "/Users/(user name)/Library/Application
Support/Tux Paint/saved/" Support/Tux Paint/saved/"
@ -799,7 +799,7 @@ Using 'tuxpaint-import'
Doing it Manually Doing it Manually
Windows, Mac OS X and BeOS users must currently do the conversion Windows, macOS, BeOS, and Haiku users must currently do the conversion
manually. manually.
Load a graphics program that is capable of both loading your picture Load a graphics program that is capable of both loading your picture

View file

@ -19,7 +19,7 @@ version
<p>Copyright (c) 2002-2020 by various contributors; see AUTHORS.txt<br/> <p>Copyright (c) 2002-2020 by various contributors; see AUTHORS.txt<br/>
<a href="http://www.tuxpaint.org/">http://www.tuxpaint.org/</a></p> <a href="http://www.tuxpaint.org/">http://www.tuxpaint.org/</a></p>
<p>June 22, 2020</p> <p>July 25, 2020</p>
</center> </center>
@ -244,7 +244,7 @@ version
<dt><code><b>printcfg=yes</b></code></dt> <dt><code><b>printcfg=yes</b></code></dt>
<dd> <dd>
<p><i>(Windows and Mac OS X only)</i></p> <p><i>(Windows and macOS only)</i></p>
<p>Tux&nbsp;Paint will use a printer configuration file when printing. <p>Tux&nbsp;Paint will use a printer configuration file when printing.
Push the <b>[Alt]</b> key while clicking the 'Print' button in Push the <b>[Alt]</b> key while clicking the 'Print' button in
@ -284,7 +284,7 @@ version
<dt><code><b>papersize=<i>PAPERSIZE</i></b></code></dt> <dt><code><b>papersize=<i>PAPERSIZE</i></b></code></dt>
<dd> <dd>
<p><i>(Platforms that use Tux&nbsp;Paint's internal PostScript <p><i>(Platforms that use Tux&nbsp;Paint's internal PostScript
generator &mdash; not Windows, Mac OS X or BeOS.)</i></p> generator &mdash; not Windows, macOS, BeOS, or Haiku.)</i></p>
<p>Tell Tux&nbsp;Paint what size PostScript to generate. <p>Tell Tux&nbsp;Paint what size PostScript to generate.
If none is specified, Tux&nbsp;Paint first checks If none is specified, Tux&nbsp;Paint first checks
@ -692,7 +692,7 @@ version
Example: "<code>C:\Documents&nbsp;and&nbsp;Settings\<i>Username</i>\Application&nbsp;Data\TuxPaint\saved\</code>"<br> Example: "<code>C:\Documents&nbsp;and&nbsp;Settings\<i>Username</i>\Application&nbsp;Data\TuxPaint\saved\</code>"<br>
<br> <br>
<li>Mac OS X &mdash; Inside a folder named "<code>TuxPaint</code>" in your <li>macOS &mdash; Inside a folder named "<code>TuxPaint</code>" in your
"<code>Application&nbsp;Support</code>" folder.<br> "<code>Application&nbsp;Support</code>" folder.<br>
Example: "<code>/Users/<i>Username</i>/Library/Application&nbsp;Support/TuxPaint/saved/</code>"<br> Example: "<code>/Users/<i>Username</i>/Library/Application&nbsp;Support/TuxPaint/saved/</code>"<br>
</ul> </ul>
@ -710,15 +710,46 @@ version
<p><b>Example:</b> <code>savedir=Z:\tuxpaint\</code></p> <p><b>Example:</b> <code>savedir=Z:\tuxpaint\</code></p>
</dd> </dd>
<dt><code><b>exportdir=<i>DIRECTORY</i></b></code></dt>
<dd>
<p>Use this option to change where Tux&nbsp;Paint exports files &mdash; single
images, or animated GIF slideshows &mdash; for external use.
<p>If you do not override it, the <b><i>default</i></b> location is:
<ul>
<li>Linux &amp; Unix &mdash; If available, wherever your desktop environment
is configured for pictures to be stored, based on your XDG
(X&nbsp;Desktop&nbsp;Group) configuration. (Try running the command-line
"<nobr><code>xdg-user-dir PICTURES</code></nobr>" to find out.)<br>
<br>
Typically (in an English locale), this will be a "<code>Pictures/</code>"
subdirectory in your home directory (i.e., "<code>$HOME/Pictures/</code>"
aka "<code>~/Pictures</code>").<br>
<br>
Tux&nbsp;Paint will fall back to using that typical directory, of no
XDG configuration can be read, or nothing is set for
"<code>XDG_PICTURES_DIR</code>".<br>
<br>
<li>Windows &mdash; TBD! <!-- FIXME -->
<li>macOS &mdash; TBD! <!-- FIXME -->
</ul>
</p>
<p><b>Example:</b> <code>exportdir=/home/penguin/TuxPaintExports</code></p>
</dd>
<dt><code><b>datadir=<i>DIRECTORY</i></b></code></dt> <dt><code><b>datadir=<i>DIRECTORY</i></b></code></dt>
<dd> <dd>
<p>Use this option to change where Tux&nbsp;Paint looks for personal <p>Use this option to change where Tux&nbsp;Paint looks for personal
data files (brushes, stamps, starters and fonts specific to the data files (brushes, stamps, starters, templates, and fonts specific to
current user).</p> the current user).</p>
<p>Tux&nbsp;Paint will search for subdirectories/subfolders named <p>Tux&nbsp;Paint will search for subdirectories/subfolders named
"<code>brushes</code>", "<code>stamps</code>", "<code>starters</code>" "<code>brushes</code>", "<code>stamps</code>", "<code>starters</code>",
and "<code>fonts</code>" under the data directory.</p> "<code>templates</code>", and "<code>fonts</code>" under the specified
data directory.</p>
<p>If you do not override it, the <b><i>default</i></b> location is: <p>If you do not override it, the <b><i>default</i></b> location is:
<ul> <ul>
@ -733,7 +764,7 @@ version
Example: "<code>C:\Documents&nbsp;and&nbsp;Settings\<i>Username</i>\Application&nbsp;Data\TuxPaint\brushes\</code>"<br> Example: "<code>C:\Documents&nbsp;and&nbsp;Settings\<i>Username</i>\Application&nbsp;Data\TuxPaint\brushes\</code>"<br>
<br> <br>
<li>Mac OS X &mdash; Inside a folder named "<code>TuxPaint</code>" in your <li>macOS &mdash; Inside a folder named "<code>TuxPaint</code>" in your
"<code>Application&nbsp;Support</code>" folder.<br> "<code>Application&nbsp;Support</code>" folder.<br>
Example: "<code>/Users/<i>Username</i>/Library/Application&nbsp;Support/TuxPaint/brushes/</code>"<br> Example: "<code>/Users/<i>Username</i>/Library/Application&nbsp;Support/TuxPaint/brushes/</code>"<br>
</ul> </ul>

View file

@ -171,7 +171,7 @@ version
<hr size=1 noshade> <hr size=1 noshade>
<h3>Mac OS X Users</h3> <h3>macOS Users</h3>
<blockquote> <blockquote>
Simply double-click the "Tux&nbsp;Paint" icon.<p> Simply double-click the "Tux&nbsp;Paint" icon.<p>
</blockquote> </blockquote>
@ -825,7 +825,7 @@ version
<dt>Printer Settings</dt> <dt>Printer Settings</dt>
<dd> <dd>
<p><i>(Windows and Mac&nbsp;OS&nbsp;X)</i></p> <p><i>(Windows and macOS)</i></p>
<p>By default, Tux&nbsp;Paint simply prints to the default <p>By default, Tux&nbsp;Paint simply prints to the default
printer with default settings when the 'Print' button is printer with default settings when the 'Print' button is
@ -998,7 +998,7 @@ version
e.g.: <code>"C:\Documents and Settings\<i>(user&nbsp;name)</i>\Application e.g.: <code>"C:\Documents and Settings\<i>(user&nbsp;name)</i>\Application
Data\TuxPaint\saved\</code>"</dd> Data\TuxPaint\saved\</code>"</dd>
<dt>Mac OS X</dt> <dt>macOS</dt>
<dd>Inside the user's "<code>Library</code>" folder: <dd>Inside the user's "<code>Library</code>" folder:
<code>"/Users/<i>(user&nbsp;name)</i>/Library/Application Support/Tux&nbsp;Paint/saved/</code>"</dd> <code>"/Users/<i>(user&nbsp;name)</i>/Library/Application Support/Tux&nbsp;Paint/saved/</code>"</dd>
@ -1052,7 +1052,7 @@ version
<h2>Doing it Manually</h2> <h2>Doing it Manually</h2>
<blockquote> <blockquote>
<p>Windows, Mac OS X and BeOS users must currently do the conversion <p>Windows, macOS, BeOS, and Haiku users must currently do the conversion
manually.</p> manually.</p>
<p>Load a graphics program that is capable of both loading your picture <p>Load a graphics program that is capable of both loading your picture

View file

@ -1,7 +1,7 @@
/* /*
get_fname.c get_fname.c
Copyright (c) 2009 Copyright (c) 2009 - 2020
http://www.tuxpaint.org/ http://www.tuxpaint.org/
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -30,26 +30,39 @@
#include "debug.h" #include "debug.h"
#include "compiler.h" #include "compiler.h"
/* DIR_SAVE: Where is the user's saved directory? /*
This is where their saved files are stored See tuxpaint.c for the OS-specific defaults.
and where the "current_id.txt" file is saved.
Windows predefines "savedir" as: * DIR_SAVE: Where does the user's drawings get saved?
"C:\Documents and Settings\%USERNAME%\Application Data\TuxPaint"
though it may get overridden with "--savedir" option
BeOS similarly predefines "savedir" as "./userdata"... This is where their saved files (PNG) are stored, and where the
"current_id.txt" file is saved (so we can re-load the latest
picture upon a subsequent launch). Generally, end users aren't
expected to access the files in here directly, but they can.
Macintosh: It's under ~/Library/Application Support/TuxPaint The defaults may be overridden with the "--savedir" option.
Linux & Unix: It's under ~/.tuxpaint * DIR_DATA: Where is the user's data directory?
DIR_DATA: Where is the user's data directory? This is where local (user-specific) fonts, brushes, stamps,
This is where local fonts, brushes and stamps can be found. */ starter images, etc., can be found. End users only put things
here if they wish to extend their Tux Paint experience.
The defaults may be overridden with the "--datadir" option.
* DIR_EXPORT: Where does Tux Paint export drawings / animations?
This is where single images, or animated GIF slideshows,
will be exported. It is expected that this is an obvious,
and easily-accessible place for end users to retrieve the exports.
The defaults may be overridden with the "--exportdir" option.
*/
const char *savedir; const char *savedir;
const char *datadir; const char *datadir;
const char *exportdir;
// FIXME: We shouldn't be allocating memory all the time. // FIXME: We shouldn't be allocating memory all the time.
// There should be distinct functions for each directory. // There should be distinct functions for each directory.
@ -62,16 +75,28 @@ const char *datadir;
* (data file, or saved images?) * (data file, or saved images?)
* *
* @param name Filaneme * @param name Filaneme
* @param kind What kind of file? (DIR_SAVE or DIR_DATA?) * @param kind What kind of file? (DIR_SAVE, DIR_DATA, or DIR_EXPORT?)
* @return Full fillpath * @return Full fillpath
*/ */
char *get_fname(const char *const name, int kind) char *get_fname(const char *const name, int kind)
{ {
char f[512]; char f[512];
const char *restrict const dir = (kind == DIR_SAVE) ? savedir : datadir; // const char *restrict const dir;
const char * dir;
// Some mkdir()'s don't like trailing slashes if (kind == DIR_SAVE) {
snprintf(f, sizeof(f), "%s%c%s", dir, (*name) ? '/' : '\0', name); dir = savedir;
} else if (kind == DIR_DATA) {
dir = datadir;
} else if (kind == DIR_EXPORT) {
dir = exportdir;
}
snprintf(f, sizeof(f),
"%s%c%s",
dir, (*name) ? '/' : '\0', /* Some mkdir()'s don't like trailing slashes */
name);
return strdup(f); return strdup(f);
} }

View file

@ -1,7 +1,7 @@
/* /*
get_fname.h get_fname.h
Copyright (c) 2009 Copyright (c) 2009 - July 25, 2020
http://www.tuxpaint.org/ http://www.tuxpaint.org/
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -27,11 +27,14 @@
extern const char *savedir; extern const char *savedir;
extern const char *datadir; extern const char *datadir;
extern const char *exportdir;
enum enum
{ {
/* (See get_fname.c for details) */
DIR_SAVE, DIR_SAVE,
DIR_DATA DIR_DATA,
DIR_EXPORT
}; };
char *get_fname(const char *const name, int kind); char *get_fname(const char *const name, int kind);

View file

@ -112,6 +112,7 @@ datadir, MULTI(datadir)
disablescreensaver, POSBOOL(disable_screensaver) disablescreensaver, POSBOOL(disable_screensaver)
dontgrab, NEGBOOL(grab_input) dontgrab, NEGBOOL(grab_input)
dontmirrorstamps, NEGBOOL(mirrorstamps) dontmirrorstamps, NEGBOOL(mirrorstamps)
exportdir, MULTI(exportdir)
fancycursors, NEGBOOL(no_fancy_cursors) fancycursors, NEGBOOL(no_fancy_cursors)
fullscreen, MULTI(parsertmp_fullscreen_native) fullscreen, MULTI(parsertmp_fullscreen_native)
grab, POSBOOL(grab_input) grab, POSBOOL(grab_input)

View file

@ -22,6 +22,7 @@ struct cfginfo
const char *disable_stamp_controls; const char *disable_stamp_controls;
const char *dont_do_xor; const char *dont_do_xor;
const char *dont_load_stamps; const char *dont_load_stamps;
const char *exportdir;
const char *fullscreen; const char *fullscreen;
const char *grab_input; const char *grab_input;
const char *hide_cursor; const char *hide_cursor;

View file

@ -3,6 +3,8 @@
# Bill Kendrick <bill@newbreedsoftware.com>; http://www.tuxpaint.org/ # Bill Kendrick <bill@newbreedsoftware.com>; http://www.tuxpaint.org/
# Based on inkscape's completion file, by allali@univ-mlv.fr # Based on inkscape's completion file, by allali@univ-mlv.fr
# #
# Last modified 2020-07-25
#
# $Id$ # $Id$
# FIXME: See http://www.debian-administration.org/articles/316 for an intro # FIXME: See http://www.debian-administration.org/articles/316 for an intro
@ -57,7 +59,7 @@ _tuxpaint()
--saveoverask --saveover --saveovernew \ --saveoverask --saveover --saveovernew \
--nosave --save \ --nosave --save \
--autosave --noautosave \ --autosave --noautosave \
--savedir --datadir \ --savedir --datadir --exportdir \
--printdelay= \ --printdelay= \
--altprintmod --altprintalways --altprintnever \ --altprintmod --altprintalways --altprintnever \
--papersize \ --papersize \

View file

@ -22,7 +22,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt) (See COPYING.txt)
June 14, 2002 - May 23, 2020 June 14, 2002 - July 25, 2020
*/ */
@ -1317,6 +1317,8 @@ static void handle_motioners(int oldpos_x, int oldpos_y, int motioner, int hatmo
static void handle_joybuttonupdownscl(SDL_Event event, int oldpos_x, int oldpos_y, SDL_Rect real_r_tools); static void handle_joybuttonupdownscl(SDL_Event event, int oldpos_x, int oldpos_y, SDL_Rect real_r_tools);
char * get_xdg_user_dir(const char * dir_type, const char * fallback);
/* Magic tools API and tool handles: */ /* Magic tools API and tool handles: */
@ -1977,9 +1979,14 @@ static int do_new_dialog_add_colors(SDL_Surface * *thumbs, int num_files, int *d
char * *d_exts, int *white_in_palette); char * *d_exts, int *white_in_palette);
static int do_color_picker(void); static int do_color_picker(void);
static int do_color_sel(void); static int do_color_sel(void);
static int do_slideshow(void); static int do_slideshow(void);
static void play_slideshow(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed); static void play_slideshow(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed);
static void draw_selection_digits(int right, int bottom, int n); static void draw_selection_digits(int right, int bottom, int n);
void do_export_gif(void);
char * get_export_filepath(void);
static void wait_for_sfx(void); static void wait_for_sfx(void);
static void rgbtohsv(Uint8 r8, Uint8 g8, Uint8 b8, float *h, float *s, float *v); static void rgbtohsv(Uint8 r8, Uint8 g8, Uint8 b8, float *h, float *s, float *v);
static void hsvtorgb(float h, float s, float v, Uint8 * r8, Uint8 * g8, Uint8 * b8); static void hsvtorgb(float h, float s, float v, Uint8 * r8, Uint8 * g8, Uint8 * b8);
@ -6518,6 +6525,9 @@ void show_usage(int exitcode)
" [--nolockfile]\n" " [--nolockfile]\n"
" [--datadir DIRECTORY]\n" " [--datadir DIRECTORY]\n"
"\n" "\n"
" Exporting:\n"
" [--exportdir DIRECTORY]\n"
"\n"
" Accessibility:\n" " Accessibility:\n"
" [--mouse-accessibility]\n" " [--mouse-accessibility]\n"
" [--mouse | --keyboard]\n" " [--mouse | --keyboard]\n"
@ -11799,12 +11809,12 @@ static void load_current(void)
* FIXME * FIXME
*/ */
/* Make sure we have a 'path' directory */ /* Make sure we have a 'path' directory */
static int make_directory(const char *path, const char *errmsg) static int make_directory(int dir_type, const char *path, const char *errmsg)
{ {
char *fname; char *fname;
int res; int res;
fname = get_fname(path, DIR_SAVE); fname = get_fname(path, dir_type);
res = mkdir(fname, 0755); res = mkdir(fname, 0755);
if (res != 0 && errno != EEXIST) if (res != 0 && errno != EEXIST)
{ {
@ -11826,7 +11836,7 @@ static void save_current(void)
char *fname; char *fname;
FILE *fi; FILE *fi;
if (!make_directory("", "Can't create user data directory")) if (!make_directory(DIR_SAVE, "", "Can't create user data directory"))
{ {
draw_tux_text(TUX_OOPS, strerror(errno), 0); draw_tux_text(TUX_OOPS, strerror(errno), 0);
return; return;
@ -13109,7 +13119,7 @@ static int do_save(int tool, int dont_show_success_results)
show_progress_bar(screen); show_progress_bar(screen);
do_setcursor(cursor_watch); do_setcursor(cursor_watch);
if (!make_directory("", "Can't create user data directory")) if (!make_directory(DIR_SAVE, "", "Can't create user data directory"))
{ {
fprintf(stderr, "Cannot save the any pictures! SORRY!\n\n"); fprintf(stderr, "Cannot save the any pictures! SORRY!\n\n");
draw_tux_text(TUX_OOPS, strerror(errno), 0); draw_tux_text(TUX_OOPS, strerror(errno), 0);
@ -13121,7 +13131,7 @@ static int do_save(int tool, int dont_show_success_results)
/* Make sure we have a ~/.tuxpaint/saved directory: */ /* Make sure we have a ~/.tuxpaint/saved directory: */
if (!make_directory("saved", "Can't create user data directory")) if (!make_directory(DIR_SAVE, "saved", "Can't create user data directory"))
{ {
fprintf(stderr, "Cannot save any pictures! SORRY!\n\n"); fprintf(stderr, "Cannot save any pictures! SORRY!\n\n");
draw_tux_text(TUX_OOPS, strerror(errno), 0); draw_tux_text(TUX_OOPS, strerror(errno), 0);
@ -13133,7 +13143,7 @@ static int do_save(int tool, int dont_show_success_results)
/* Make sure we have a ~/.tuxpaint/saved/.thumbs/ directory: */ /* Make sure we have a ~/.tuxpaint/saved/.thumbs/ directory: */
if (!make_directory("saved/.thumbs", "Can't create user data thumbnail directory")) if (!make_directory(DIR_SAVE, "saved/.thumbs", "Can't create user data thumbnail directory"))
{ {
fprintf(stderr, "Cannot save any pictures! SORRY!\n\n"); fprintf(stderr, "Cannot save any pictures! SORRY!\n\n");
draw_tux_text(TUX_OOPS, strerror(errno), 0); draw_tux_text(TUX_OOPS, strerror(errno), 0);
@ -13144,7 +13154,7 @@ static int do_save(int tool, int dont_show_success_results)
/* Make sure we have a ~/.tuxpaint/saved/.label/ directory: */ /* Make sure we have a ~/.tuxpaint/saved/.label/ directory: */
if (!make_directory("saved/.label", "Can't create label information directory")) if (!make_directory(DIR_SAVE, "saved/.label", "Can't create label information directory"))
{ {
fprintf(stderr, "Cannot save label information! SORRY!\n\n"); fprintf(stderr, "Cannot save label information! SORRY!\n\n");
draw_tux_text(TUX_OOPS, strerror(errno), 0); draw_tux_text(TUX_OOPS, strerror(errno), 0);
@ -14181,10 +14191,10 @@ static int do_open(void)
/* No thumbnail - load original: */ /* No thumbnail - load original: */
/* Make sure we have a ~/.tuxpaint/saved directory: */ /* Make sure we have a ~/.tuxpaint/saved directory: */
if (make_directory("saved", "Can't create user data directory")) if (make_directory(DIR_SAVE, "saved", "Can't create user data directory"))
{ {
/* (Make sure we have a .../saved/.thumbs/ directory:) */ /* (Make sure we have a .../saved/.thumbs/ directory:) */
make_directory("saved/.thumbs", "Can't create user data thumbnail directory"); make_directory(DIR_SAVE, "saved/.thumbs", "Can't create user data thumbnail directory");
} }
@ -15202,10 +15212,10 @@ static int do_slideshow(void)
/* No thumbnail - load original: */ /* No thumbnail - load original: */
/* Make sure we have a ~/.tuxpaint/saved directory: */ /* Make sure we have a ~/.tuxpaint/saved directory: */
if (make_directory("saved", "Can't create user data directory")) if (make_directory(DIR_SAVE, "saved", "Can't create user data directory"))
{ {
/* (Make sure we have a .../saved/.thumbs/ directory:) */ /* (Make sure we have a .../saved/.thumbs/ directory:) */
make_directory("saved/.thumbs", "Can't create user data thumbnail directory"); make_directory(DIR_SAVE, "saved/.thumbs", "Can't create user data thumbnail directory");
} }
snprintf(fname, sizeof(fname), "%s/%s", dirname, f->d_name); snprintf(fname, sizeof(fname), "%s/%s", dirname, f->d_name);
@ -15676,7 +15686,7 @@ static int do_slideshow(void)
} }
else else
{ {
/* FIXME: Do it */ do_export_gif();
} }
} }
else if (event.button.x >= (WINDOW_WIDTH - 96 - 48) && else if (event.button.x >= (WINDOW_WIDTH - 96 - 48) &&
@ -18998,11 +19008,11 @@ static int do_new_dialog(void)
/* No thumbnail - load original: */ /* No thumbnail - load original: */
/* Make sure we have a ~/.tuxpaint/[starters|templates] directory: */ /* Make sure we have a ~/.tuxpaint/[starters|templates] directory: */
if (make_directory(dirname[d_places[num_files]], "Can't create user data directory")) if (make_directory(DIR_SAVE, dirname[d_places[num_files]], "Can't create user data directory"))
{ {
/* (Make sure we have a .../[starters|templates]/.thumbs/ directory:) */ /* (Make sure we have a .../[starters|templates]/.thumbs/ directory:) */
snprintf(fname, sizeof(fname), "%s/.thumbs", dirname[d_places[num_files]]); snprintf(fname, sizeof(fname), "%s/.thumbs", dirname[d_places[num_files]]);
make_directory(fname, "Can't create user data thumbnail directory"); make_directory(DIR_SAVE, fname, "Can't create user data thumbnail directory");
} }
img = NULL; img = NULL;
@ -19103,10 +19113,10 @@ static int do_new_dialog(void)
snprintf(fname, sizeof(fname), "%s/.thumbs/%s-t.png", snprintf(fname, sizeof(fname), "%s/.thumbs/%s-t.png",
dirname[d_places[num_files]], d_names[num_files]); dirname[d_places[num_files]], d_names[num_files]);
if (!make_directory("starters", "Can't create user data directory") || if (!make_directory(DIR_SAVE, "starters", "Can't create user data directory") ||
!make_directory("templates", "Can't create user data directory") || !make_directory(DIR_SAVE, "templates", "Can't create user data directory") ||
!make_directory("starters/.thumbs", "Can't create user data directory") || !make_directory(DIR_SAVE, "starters/.thumbs", "Can't create user data directory") ||
!make_directory("templates/.thumbs", "Can't create user data directory")) !make_directory(DIR_SAVE, "templates/.thumbs", "Can't create user data directory"))
fprintf(stderr, "Cannot save any pictures! SORRY!\n\n"); fprintf(stderr, "Cannot save any pictures! SORRY!\n\n");
else else
{ {
@ -22565,6 +22575,7 @@ static void setup_config(char *argv[])
} }
#endif #endif
/* == SAVEDIR == */
if (tmpcfg_cmd.savedir) if (tmpcfg_cmd.savedir)
savedir = strdup(tmpcfg_cmd.savedir); savedir = strdup(tmpcfg_cmd.savedir);
else else
@ -22595,6 +22606,23 @@ static void setup_config(char *argv[])
#endif #endif
} }
/* == EXPORTDIR == */
if (tmpcfg_cmd.exportdir)
exportdir = strdup(tmpcfg_cmd.exportdir);
else
{
/* FIXME: Need assist for:
* _WIN32
* __BEOS__
* __HAIKU__
* __APPLE__
*/
exportdir = get_xdg_user_dir("PICTURES", "Pictures");
}
printf("Export Dir = %s\n", exportdir);
exit(0);
/* Load options from user's own configuration (".rc" / ".cfg") file: */ /* Load options from user's own configuration (".rc" / ".cfg") file: */
#if defined(_WIN32) #if defined(_WIN32)
@ -24635,6 +24663,7 @@ static int trash(char *path)
/* Move file into Trash folder */ /* Move file into Trash folder */
/* FIXME: Use xdg function */
if (getenv("XDG_DATA_HOME") != NULL) if (getenv("XDG_DATA_HOME") != NULL)
{ {
sprintf(trashpath, "%s/Trash", getenv("XDG_DATA_HOME")); sprintf(trashpath, "%s/Trash", getenv("XDG_DATA_HOME"));
@ -25114,3 +25143,129 @@ static void handle_joybuttonupdownscl(SDL_Event event, int oldpos_x, int oldpos_
if (!ignore) if (!ignore)
SDL_PushEvent(&ev); SDL_PushEvent(&ev);
} }
/**
* Grab the user's XDG user dir for something (e.g., ~/Pictures)
*
* @param char * dir_type -- the thing to query, e.g. "PICTURES" or "VIDEOS"
* (note: currently, Tux Paint only puts things in the PICTURES one)
* @param char * fallback -- path, under $HOME, to use instead (e.g., "Pictures")
* @return char * path (caller is expected to free() it)
*/
char * get_xdg_user_dir(const char * dir_type, const char * fallback) {
FILE * fi;
char * config_home, * found;
char tmp_path[MAX_PATH], config_path[MAX_PATH], line[MAX_PATH], search[MAX_PATH], return_path[MAX_PATH];
int found_it;
found_it = FALSE;
/* Figure out where XDG user-dirs config exists, and use it if possible */
if (getenv("XDG_CONFIG_HOME") != NULL) {
config_home = strdup(getenv("XDG_CONFIG_HOME"));
} else {
#ifdef DEBUG
fprintf(stderr, "XDG_CONFIG_HOME not set, checking $HOME/.config/\n");
#endif
if (getenv("HOME") != NULL) {
snprintf(tmp_path, MAX_PATH, "%s/.config", getenv("HOME"));
config_home = strdup(tmp_path);
} else {
#ifdef DEBUG
fprintf(stderr, "No HOME, either?! Returing fallback in current directory\n");
#endif
return strdup(fallback);
}
}
if (config_home[strlen(config_home) - 1] == '/') {
config_home[strlen(config_home) - 1] = '\0';
}
snprintf(config_path, MAX_PATH, "%s/user-dirs.dirs", config_home);
free(config_home);
#ifdef DEBUG
fprintf(stderr, "User dirs config = %s\n", config_path);
#endif
snprintf(search, MAX_PATH, "XDG_%s_DIR=\"", dir_type);
/* Read the config to find the path we want */
fi = fopen(config_path, "r");
if (fi != NULL) {
/* Search for a line in the form of either
either XDG_PICTURES_DIR="$HOME/Pictures"
or XDG_PICTURES_DIR="/Path/To/Pictures"
*/
#ifdef DEBUG
fprintf(stderr, "Searching it for: %s\n", search);
#endif
while (fgets(line, MAX_PATH, fi) && !found_it) {
/* Trim trailing CR/LF */
if (line[strlen(line) - 1] == '\n' ||
line[strlen(line) - 1] == '\r') {
line[strlen(line) - 1] = '\0';
}
if (strstr(line, search) == line) {
found = line + strlen(search);
#ifdef DEBUG
fprintf(stderr, "Found it: %s\n", found);
#endif
if (strstr(found, "$HOME/") == found) {
snprintf(return_path, MAX_PATH, "%s/%s", getenv("HOME"), found + 6 /* skip '$HOME/' */);
} else {
strcpy(return_path, found);
}
/* Trim trailing " */
if (return_path[strlen(return_path) - 1] == '\"') {
return_path[strlen(return_path) - 1] = '\0';
}
found_it = TRUE;
}
}
fclose(fi);
#ifdef DEBUG
} else {
fprintf(stderr, "%s doesn't exist\n", config_path);
#endif
}
if (!found_it) {
#ifdef DEBUG
fprintf(stderr, "Using fallback of $HOME/%s\n", fallback);
#endif
snprintf(return_path, MAX_PATH, "%s/%s", getenv("HOME"), fallback);
}
#ifdef DEBUG
fprintf(stderr, "Location for %s => %s\n", dir_type, return_path);
#endif
return strdup(return_path);
}
/**
* After 2+ images have been selected in the Open->Slideshow
* dialog, they can be exported as an animated GIF.
*/
void do_export_gif(void) {
}
/**
* Returns the user's chosen export directory
* for animated GIFs, via Open->Slideshow dialog,
* and static PNGs, via Open dialog */
char * get_export_filepath(void) {
char *rname;
char fname[FILENAME_MAX];
rname = NULL;
/*
snprintf(fname, sizeof(fname), "saved/%s.dat", saved_id);
rname = get_fname(fname, DIR_SAVE);
*/
}

View file

@ -7,7 +7,7 @@
# http://www.tuxpaint.org/ # http://www.tuxpaint.org/
# #
# Default distribution version last modified: # Default distribution version last modified:
# September 21, 2019 # July 25, 2020
# #
# $Id$ # $Id$
@ -251,6 +251,13 @@
# savedir=~/.tuxpaint # savedir=~/.tuxpaint
### Export images and animated GIF slideshows somewhere different?
### (Uses xdg-user-dirs config setting for PICTURES, if available!)
### --------------------------------------------------------------
#
# exportdir=~/Pictures
### Use a different language? ### Use a different language?
### ------------------------- ### -------------------------
### Note: Where the language is a known language name (e.g., "spanish") ### Note: Where the language is a known language name (e.g., "spanish")