From 3c5303563a506a8a9066ae26c2bf072655ce4826 Mon Sep 17 00:00:00 2001 From: Bill Kendrick Date: Thu, 6 Jun 2024 23:00:36 -0700 Subject: [PATCH] WIP Dropping in code for Haiku trash can support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit h/t Jérôme Duval for pointing us to this (see https://github.com/haikuports/haikuports/issues/10568) Code used is copyright (c) 2004, Francois Revol , provided under the MIT licence. (Also, ran `indent.sh`) --- docs/AUTHORS.txt | 6 ++- docs/CHANGES.txt | 7 +++ magic/src/mirror_f.c | 57 ++++++++++++---------- src/haiku_trash.c | 112 +++++++++++++++++++++++++++++++++++++++++++ src/i18n.c | 3 +- src/tuxpaint.c | 26 ++++++---- 6 files changed, 172 insertions(+), 39 deletions(-) create mode 100644 src/haiku_trash.c diff --git a/docs/AUTHORS.txt b/docs/AUTHORS.txt index 0bf51b19d..5fddb8569 100644 --- a/docs/AUTHORS.txt +++ b/docs/AUTHORS.txt @@ -6,7 +6,7 @@ Copyright (c) 2002-2024 Various contributors (see below, and CHANGES.txt) https://tuxpaint.org/ -June 17, 2002 - May 28, 2024 +June 17, 2002 - June 6, 2024 * Design and Coding: @@ -1274,6 +1274,10 @@ June 17, 2002 - May 28, 2024 Marcin 'Shard' Konicki [retired] Gerasim Troeglazov <3dEyes@gmail.com> + * Haiku trash from Haiku "trash.cpp" + Copyright (c) 2004, Francois Revol , + provided under the MIT licence + * Debian Linux packages Ben Armstrong diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt index 1a631de41..4ea7f708b 100644 --- a/docs/CHANGES.txt +++ b/docs/CHANGES.txt @@ -95,6 +95,13 @@ https://tuxpaint.org/ or animated GIF (via Open->Slideshow). Bill Kendrick + * WIP Add Trash support when using Erase option in Open dialog + on Haiku. + h/t Jérôme Duval for pointing us to this + (see https://github.com/haikuports/haikuports/issues/10568) + Code used is copyright (c) 2004, Francois Revol , + provided under the MIT licence. + * Removed unnecessary (and now unhelpful) button label text vertical position nudging (had only been used by Khmer locale). Bill Kendrick diff --git a/magic/src/mirror_f.c b/magic/src/mirror_f.c index ce04028b2..f9264331b 100644 --- a/magic/src/mirror_f.c +++ b/magic/src/mirror_f.c @@ -57,18 +57,19 @@ TX_EXTERN void mirror_f_release(magic_api *, int, SDL_Surface *, SDL_Surface *, TX_EXTERN void mirror_f_click(magic_api *, int, int, SDL_Surface *, SDL_Surface *, int, int, SDL_Rect *); TX_EXTERN void mirror_f_shutdown(magic_api *); TX_EXTERN void mirror_f_set_color(magic_api * api, int which, SDL_Surface * canvas, - SDL_Surface * last, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect); + SDL_Surface * last, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect); TX_EXTERN int mirror_f_requires_colors(magic_api *, int); TX_EXTERN void mirror_f_switchin(magic_api *, int, int, SDL_Surface *); TX_EXTERN void mirror_f_switchout(magic_api *, int, int, SDL_Surface *); TX_EXTERN int mirror_f_modes(magic_api *, int); TX_EXTERN Uint8 mirror_f_accepted_sizes(magic_api * api, int which, int mode); TX_EXTERN Uint8 mirror_f_default_size(magic_api * api, int which, int mode); -TX_EXTERN void mirror_f_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * last, Uint8 size, - SDL_Rect * update_rect); +TX_EXTERN void mirror_f_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * last, + Uint8 size, SDL_Rect * update_rect); // No setup required: -TX_EXTERN int mirror_f_init(magic_api * api, Uint8 disabled_features ATTRIBUTE_UNUSED, Uint8 complexity_level ATTRIBUTE_UNUSED) +TX_EXTERN int mirror_f_init(magic_api * api, Uint8 disabled_features ATTRIBUTE_UNUSED, + Uint8 complexity_level ATTRIBUTE_UNUSED) { char fname[1024]; @@ -145,29 +146,29 @@ TX_EXTERN char *mirror_f_get_description(magic_api * api ATTRIBUTE_UNUSED, int w // We affect the whole canvas, so only do things on click, not drag: TX_EXTERN void mirror_f_drag(magic_api * api ATTRIBUTE_UNUSED, - int which ATTRIBUTE_UNUSED, - SDL_Surface * canvas ATTRIBUTE_UNUSED, - SDL_Surface * last ATTRIBUTE_UNUSED, - int ox ATTRIBUTE_UNUSED, int oy ATTRIBUTE_UNUSED, - int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED) + int which ATTRIBUTE_UNUSED, + SDL_Surface * canvas ATTRIBUTE_UNUSED, + SDL_Surface * last ATTRIBUTE_UNUSED, + int ox ATTRIBUTE_UNUSED, int oy ATTRIBUTE_UNUSED, + int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED) { // No-op } TX_EXTERN void mirror_f_release(magic_api * api ATTRIBUTE_UNUSED, - int which ATTRIBUTE_UNUSED, - SDL_Surface * canvas ATTRIBUTE_UNUSED, - SDL_Surface * last ATTRIBUTE_UNUSED, - int ox ATTRIBUTE_UNUSED, int oy ATTRIBUTE_UNUSED, - int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED) + int which ATTRIBUTE_UNUSED, + SDL_Surface * canvas ATTRIBUTE_UNUSED, + SDL_Surface * last ATTRIBUTE_UNUSED, + int ox ATTRIBUTE_UNUSED, int oy ATTRIBUTE_UNUSED, + int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED) { // No-op } // Affect the canvas on click: TX_EXTERN void mirror_f_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED, - SDL_Surface * canvas, SDL_Surface * last, - int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect) + SDL_Surface * canvas, SDL_Surface * last, + int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect) { int xx, yy; SDL_Rect src, dest; @@ -226,9 +227,9 @@ TX_EXTERN void mirror_f_shutdown(magic_api * api ATTRIBUTE_UNUSED) // We don't use colors: TX_EXTERN void mirror_f_set_color(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, - SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * last ATTRIBUTE_UNUSED, - Uint8 r ATTRIBUTE_UNUSED, Uint8 g ATTRIBUTE_UNUSED, Uint8 b ATTRIBUTE_UNUSED, - SDL_Rect * update_rect ATTRIBUTE_UNUSED) + SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * last ATTRIBUTE_UNUSED, + Uint8 r ATTRIBUTE_UNUSED, Uint8 g ATTRIBUTE_UNUSED, Uint8 b ATTRIBUTE_UNUSED, + SDL_Rect * update_rect ATTRIBUTE_UNUSED) { } @@ -239,12 +240,14 @@ TX_EXTERN int mirror_f_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int whi } TX_EXTERN void mirror_f_switchin(magic_api * api ATTRIBUTE_UNUSED, - int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED) + int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, + SDL_Surface * canvas ATTRIBUTE_UNUSED) { } TX_EXTERN void mirror_f_switchout(magic_api * api ATTRIBUTE_UNUSED, - int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED) + int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, + SDL_Surface * canvas ATTRIBUTE_UNUSED) { } @@ -255,18 +258,20 @@ TX_EXTERN int mirror_f_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBU TX_EXTERN Uint8 mirror_f_accepted_sizes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, - int mode ATTRIBUTE_UNUSED) + int mode ATTRIBUTE_UNUSED) { return 0; } -TX_EXTERN Uint8 mirror_f_default_size(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED) +TX_EXTERN Uint8 mirror_f_default_size(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, + int mode ATTRIBUTE_UNUSED) { return 0; } -TX_EXTERN void mirror_f_set_size(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, - SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * last ATTRIBUTE_UNUSED, - Uint8 size ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED) +TX_EXTERN void mirror_f_set_size(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, + int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED, + SDL_Surface * last ATTRIBUTE_UNUSED, Uint8 size ATTRIBUTE_UNUSED, + SDL_Rect * update_rect ATTRIBUTE_UNUSED) { } diff --git a/src/haiku_trash.c b/src/haiku_trash.c new file mode 100644 index 000000000..d1de99263 --- /dev/null +++ b/src/haiku_trash.c @@ -0,0 +1,112 @@ +/* + * Place a file in the Trash under Haiku. + * + * From Haiku `trash.cpp` + * (https://github.com/haiku/haiku/blob/3e910e720f3408a2ccf7dae9019621a390f3527b/src/bin/trash.cpp) + * + * Copyright (c) 2004 by Francois Revol + * provided under the MIT licence: + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the “Software”), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF + * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * h/t Jérôme Duval for pointing us to this + * (https://github.com/haikuports/haikuports/issues/10568) + * + * Last modified 2024-06-06 +*/ + +/* FIXME: Not sure how many of these are strictly necessary for + _just_ the `haiku_trash()` function. Luc, please check! + -bjk 2024-06-06 */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +status_t haiku_trash(const char *f) +{ + status_t err; + attr_info ai; + dev_t dev = -1; + int nr; + const char *original_path; + char trash_dir[B_PATH_NAME_LENGTH]; + char trashed_file[B_PATH_NAME_LENGTH]; + + dev = dev_for_path(f); + err = find_directory(B_TRASH_DIRECTORY, dev, false, trash_dir, B_PATH_NAME_LENGTH); + if (err < 0) + return err; + BNode node(f); + + err = node.InitCheck(); + if (err < 0) + return err; + err = node.GetAttrInfo(kAttrOriginalPath, &ai); + if (err == B_OK) + return EALREADY; + if (!strncmp(f, trash_dir, strlen(trash_dir))) + return EALREADY; + entry_ref er; + + err = get_ref_for_path(f, &er); + if (err < 0) + return err; + BPath orgPath(&er); + + err = orgPath.InitCheck(); + if (err < 0) + return err; + original_path = orgPath.Path(); + BDirectory trashDir(trash_dir); + + err = trashDir.InitCheck(); + if (err < 0) + return err; + for (nr = 0;; nr++) + { + if (nr > INT_MAX - 1) + return B_ERROR; + if (nr) + snprintf(trashed_file, B_PATH_NAME_LENGTH - 1, "%s/%s %d", trash_dir, er.name, nr); + else + snprintf(trashed_file, B_PATH_NAME_LENGTH - 1, "%s/%s", trash_dir, er.name); + if (!trashDir.Contains(trashed_file)) + break; + } + err = rename(original_path, trashed_file); + if (err < 0) + return err; + + err = node.WriteAttr(kAttrOriginalPath, B_STRING_TYPE, 0LL, original_path, strlen(original_path) + 1); + if (err < 0) + return err; + return 0; +} diff --git a/src/i18n.c b/src/i18n.c index 1032f0998..9fb0da0be 100644 --- a/src/i18n.c +++ b/src/i18n.c @@ -1242,8 +1242,7 @@ static void set_current_language(const char *restrict loc, int *ptr_num_wished_l need_right_to_left = wished_langs[0].need_right_to_left; #ifdef DEBUG - fprintf(stderr, "DEBUG: Language is %s (%d) %s\n", - lang_prefix, langint, need_right_to_left ? "(RTL)" : ""); + fprintf(stderr, "DEBUG: Language is %s (%d) %s\n", lang_prefix, langint, need_right_to_left ? "(RTL)" : ""); fflush(stderr); #endif diff --git a/src/tuxpaint.c b/src/tuxpaint.c index 1aaf2cd7e..55cc7d7e4 100644 --- a/src/tuxpaint.c +++ b/src/tuxpaint.c @@ -331,6 +331,8 @@ typedef struct safer_dirent char d_name[FILENAME_MAX]; } safer_dirent; +extern status_t haiku_trash(const char *f); + #define dirent safer_dirent #else /* __BEOS__ */ @@ -652,7 +654,7 @@ int TP_EventFilter(void *data, EVENT_FILTER_EVENT_TYPE * event); /* #define fmemopen_alternative *//* Uncomment this to test the fmemopen alternative in systems were fmemopen exists */ /* *INDENT-ON* */ -#if defined (WIN32) || defined (__APPLE__) || defined(__NetBSD__) || defined(__sun) || defined(__OS2__) || defined(__ANDROID__) /* MINGW/MSYS, NetBSD, and MacOSX need it, at least for now */ +#if defined (WIN32) || defined (__APPLE__) || defined(__NetBSD__) || defined(__sun) || defined(__OS2__) || defined(__ANDROID__) /* MINGW/MSYS, NetBSD, and MacOSX need it, at least for now */ #define fmemopen_alternative #endif @@ -2220,7 +2222,8 @@ 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 draw_selection_digits(int right, int bottom, int n); -static int export_gif(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed, char **dest_fname); +static int export_gif(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed, + char **dest_fname); int export_gif_monitor_events(void); /* Locations where export_pict() can save */ @@ -17377,13 +17380,13 @@ static int do_open(void) { instructions = gettext_noop - ("Choose a picture and then click “Open”, “Export”, “Template“, or “Erase”. Click “Slides” to create a slideshow animation or “Back“ to return to your current picture."); + ("Choose a picture and then click “Open”, “Export”, “Template“, or “Erase”. Click “Slides” to create a slideshow animation or “Back“ to return to your current picture."); } else { instructions = gettext_noop - ("Choose a picture and then click “Open”, “Export”, or “Erase”. Click “Slides” to create a slideshow animation or “Back“ to return to your current picture."); + ("Choose a picture and then click “Open”, “Export”, or “Erase”. Click “Slides” to create a slideshow animation or “Back“ to return to your current picture."); } draw_tux_text(TUX_BORED, instructions, 1); @@ -18133,7 +18136,7 @@ static int do_open(void) if (want_export) { int res; - char * dest_fname; + char *dest_fname; want_export = 0; @@ -18144,7 +18147,7 @@ static int do_open(void) if (res == EXPORT_SUCCESS) { int n; - char * msg; + char *msg; if (dest_fname != NULL) { @@ -19079,7 +19082,7 @@ static int do_slideshow(void) } else { - char * dest_fname; + char *dest_fname; export_successful = export_gif(selected, num_selected, dirname, d_names, d_exts, speed, &dest_fname); @@ -19093,7 +19096,7 @@ static int do_slideshow(void) if (export_successful) { int n; - char * msg; + char *msg; if (dest_fname != NULL) { @@ -30962,6 +30965,8 @@ static int trash(char *path) return win32_trash(path); #elif defined(__APPLE__) return apple_trash(path); +#elif defined __BEOS__ || defined __HAIKU__ + return haiku_trash(path); #else char fname[MAX_PATH], trashpath[MAX_PATH], dest[MAX_PATH], infoname[MAX_PATH], bname[MAX_PATH + 1], ext[MAX_PATH]; char deldate[32]; @@ -31713,7 +31718,8 @@ char *get_xdg_user_dir(const char *dir_type, const char *fallback) * @param int speed -- how fast to play the slideshow (0 and 1 both = slowest, 10 = fasted) * @return int -- 0 if export failed or was aborted, 1 if successful */ -static int export_gif(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed, char **dest_fname) +static int export_gif(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed, + char **dest_fname) { char *tmp_starter_id, *tmp_template_id, *tmp_file_id; int tmp_starter_mirrored, tmp_starter_flipped, tmp_starter_personal; @@ -31995,7 +32001,7 @@ int export_gif_monitor_events(void) * + unused by EXPORT_LOC_PICTURES (just send NULL) * @return EXPORT_SUCCESS on success, or one of the EXPORT_ERR_... values on failure */ -static int export_pict(char *fname, int where, char *orig_fname, char ** dest_fname) +static int export_pict(char *fname, int where, char *orig_fname, char **dest_fname) { FILE *fi, *fo; size_t len;