mirror of
https://github.com/netsurf-browser/netsurf
synced 2025-01-08 20:12:01 +03:00
Assorted saving-related changes (WIP)
svn path=/trunk/netsurf/; revision=6010
This commit is contained in:
parent
4e3951660f
commit
d67a57c1e9
@ -70,8 +70,8 @@ static bool ro_gui_configure_click(wimp_pointer *pointer);
|
||||
static void ro_gui_configure_open_window(wimp_open *open);
|
||||
static void ro_gui_configure_close(wimp_w w);
|
||||
static bool ro_gui_configure_translate(void);
|
||||
static void ro_gui_configure_register(const char *window,
|
||||
bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w));
|
||||
static void ro_gui_configure_register(const char *window,
|
||||
bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w));
|
||||
|
||||
void ro_gui_configure_initialise(void)
|
||||
{
|
||||
|
@ -311,13 +311,13 @@ wimp_window * ro_gui_dialog_load_template(const char *template_name)
|
||||
|
||||
|
||||
/**
|
||||
* Open a dialog box, centered on the screen.
|
||||
* Open a dialog box, centred on the screen.
|
||||
*/
|
||||
|
||||
void ro_gui_dialog_open(wimp_w w)
|
||||
{
|
||||
int screen_x, screen_y, dx, dy;
|
||||
wimp_window_state open;
|
||||
wimp_window_state state;
|
||||
os_error *error;
|
||||
|
||||
/* find screen centre in os units */
|
||||
@ -326,31 +326,24 @@ void ro_gui_dialog_open(wimp_w w)
|
||||
screen_y /= 2;
|
||||
|
||||
/* centre and open */
|
||||
open.w = w;
|
||||
error = xwimp_get_window_state(&open);
|
||||
state.w = w;
|
||||
error = xwimp_get_window_state(&state);
|
||||
if (error) {
|
||||
LOG(("xwimp_get_window_state: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
warn_user("WimpError", error->errmess);
|
||||
return;
|
||||
}
|
||||
dx = (open.visible.x1 - open.visible.x0) / 2;
|
||||
dy = (open.visible.y1 - open.visible.y0) / 2;
|
||||
open.visible.x0 = screen_x - dx;
|
||||
open.visible.x1 = screen_x + dx;
|
||||
open.visible.y0 = screen_y - dy;
|
||||
open.visible.y1 = screen_y + dy;
|
||||
open.next = wimp_TOP;
|
||||
error = xwimp_open_window((wimp_open *) &open);
|
||||
if (error) {
|
||||
LOG(("xwimp_open_window: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
warn_user("WimpError", error->errmess);
|
||||
return;
|
||||
}
|
||||
dx = (state.visible.x1 - state.visible.x0) / 2;
|
||||
dy = (state.visible.y1 - state.visible.y0) / 2;
|
||||
state.visible.x0 = screen_x - dx;
|
||||
state.visible.x1 = screen_x + dx;
|
||||
state.visible.y0 = screen_y - dy;
|
||||
state.visible.y1 = screen_y + dy;
|
||||
state.next = wimp_TOP;
|
||||
ro_gui_open_window_request((wimp_open*)&state);
|
||||
|
||||
/* Set the caret position
|
||||
*/
|
||||
/* Set the caret position */
|
||||
ro_gui_set_caret_first(w);
|
||||
}
|
||||
|
||||
@ -486,8 +479,6 @@ bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar,
|
||||
|
||||
void ro_gui_dialog_open_at_pointer(wimp_w w)
|
||||
{
|
||||
int dx, dy;
|
||||
wimp_window_state state;
|
||||
wimp_pointer ptr;
|
||||
os_error *error;
|
||||
|
||||
@ -500,6 +491,20 @@ void ro_gui_dialog_open_at_pointer(wimp_w w)
|
||||
return;
|
||||
}
|
||||
|
||||
ro_gui_dialog_open_xy(w, ptr.pos.x - 64, ptr.pos.y);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open window at a specified location.
|
||||
*/
|
||||
|
||||
void ro_gui_dialog_open_xy(wimp_w w, int x, int y)
|
||||
{
|
||||
wimp_window_state state;
|
||||
os_error *error;
|
||||
int dx, dy;
|
||||
|
||||
/* move the window */
|
||||
state.w = w;
|
||||
error = xwimp_get_window_state(&state);
|
||||
@ -511,10 +516,10 @@ void ro_gui_dialog_open_at_pointer(wimp_w w)
|
||||
}
|
||||
dx = (state.visible.x1 - state.visible.x0);
|
||||
dy = (state.visible.y1 - state.visible.y0);
|
||||
state.visible.x0 = ptr.pos.x - 64;
|
||||
state.visible.x1 = ptr.pos.x - 64 + dx;
|
||||
state.visible.y0 = ptr.pos.y - dy;
|
||||
state.visible.y1 = ptr.pos.y;
|
||||
state.visible.x0 = x;
|
||||
state.visible.x1 = x + dx;
|
||||
state.visible.y0 = y - dy;
|
||||
state.visible.y1 = y;
|
||||
|
||||
/* if the window is already open, close it first so that it opens fully
|
||||
* on screen */
|
||||
@ -598,7 +603,7 @@ void ro_gui_dialog_open_centre_parent(wimp_w parent, wimp_w child) {
|
||||
void ro_gui_dialog_open_persistent(wimp_w parent, wimp_w w, bool pointer) {
|
||||
|
||||
if (pointer)
|
||||
ro_gui_dialog_open_at_pointer(w);
|
||||
ro_gui_dialog_open_at_pointer(w);
|
||||
else
|
||||
ro_gui_dialog_open_centre_parent(parent, w);
|
||||
|
||||
@ -608,7 +613,6 @@ void ro_gui_dialog_open_persistent(wimp_w parent, wimp_w w, bool pointer) {
|
||||
wimp_WINDOW_CLOSE_ICON);
|
||||
ro_gui_dialog_add_persistent(parent, w);
|
||||
ro_gui_set_caret_first(w);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -650,8 +654,8 @@ void ro_gui_dialog_close_persistent(wimp_w parent) {
|
||||
for (i = 0; i < MAX_PERSISTENT; i++) {
|
||||
if (persistent_dialog[i].parent == parent &&
|
||||
persistent_dialog[i].dialog != NULL) {
|
||||
if (!ro_gui_wimp_event_close_window(persistent_dialog[i].dialog))
|
||||
ro_gui_dialog_close(persistent_dialog[i].dialog);
|
||||
ro_gui_dialog_close(persistent_dialog[i].dialog);
|
||||
ro_gui_wimp_event_close_window(persistent_dialog[i].dialog);
|
||||
persistent_dialog[i].parent = NULL;
|
||||
persistent_dialog[i].dialog = NULL;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ void ro_gui_dialog_close(wimp_w close);
|
||||
bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar,
|
||||
int width, int height);
|
||||
void ro_gui_dialog_open_at_pointer(wimp_w w);
|
||||
void ro_gui_dialog_open_xy(wimp_w, int x, int y);
|
||||
void ro_gui_dialog_open_centre_parent(wimp_w parent, wimp_w w);
|
||||
|
||||
void ro_gui_dialog_open_persistent(wimp_w parent, wimp_w w, bool pointer);
|
||||
|
@ -125,6 +125,9 @@ static int download_progress_x0;
|
||||
static int download_progress_y0;
|
||||
static int download_progress_y1;
|
||||
|
||||
/** Current download directory. */
|
||||
static char *download_dir = NULL;
|
||||
static size_t download_dir_len;
|
||||
|
||||
|
||||
static const char *ro_gui_download_temp_name(struct gui_download_window *dw);
|
||||
@ -136,6 +139,7 @@ static bool ro_gui_download_check_space(struct gui_download_window *dw,
|
||||
const char *dest_file, const char *orig_file);
|
||||
static os_error *ro_gui_download_move(struct gui_download_window *dw,
|
||||
const char *dest_file, const char *src_file);
|
||||
static void ro_gui_download_remember_dir(const char *path);
|
||||
static bool ro_gui_download_save(struct gui_download_window *dw,
|
||||
const char *file_name, bool force_overwrite);
|
||||
static void ro_gui_download_send_dataload(struct gui_download_window *dw);
|
||||
@ -221,6 +225,7 @@ struct gui_download_window *gui_download_window_create(const char *url,
|
||||
url_func_result res;
|
||||
char *local_path;
|
||||
utf8_convert_ret err;
|
||||
size_t leaf_ofst;
|
||||
size_t i;
|
||||
|
||||
dw = malloc(sizeof *dw);
|
||||
@ -329,20 +334,36 @@ struct gui_download_window *gui_download_window_create(const char *url,
|
||||
download_template->icons[ICON_DOWNLOAD_ICON].data.indirected_sprite.id =
|
||||
(osspriteop_id) dw->sprite_name;
|
||||
|
||||
if (download_dir) {
|
||||
memcpy(dw->path, download_dir, download_dir_len);
|
||||
dw->path[download_dir_len] = '.';
|
||||
leaf_ofst = download_dir_len + 1;
|
||||
}
|
||||
else
|
||||
leaf_ofst = 0;
|
||||
|
||||
if ((res = url_nice(url, &nice, option_strip_extensions)) ==
|
||||
URL_FUNC_OK) {
|
||||
for (i = 0; nice[i]; i++) {
|
||||
int imax = sizeof dw->path - (leaf_ofst + 1);
|
||||
for (i = 0; i < imax && nice[i]; i++) {
|
||||
if (nice[i] == '.')
|
||||
nice[i] = '/';
|
||||
else if (nice[i] <= ' ' ||
|
||||
strchr(":*#$&@^%\\", nice[i]))
|
||||
nice[i] = '_';
|
||||
}
|
||||
strncpy(dw->path, nice, sizeof dw->path);
|
||||
memcpy(dw->path + leaf_ofst, nice, i);
|
||||
dw->path[leaf_ofst + i] = '\0';
|
||||
free(nice);
|
||||
}
|
||||
else
|
||||
strcpy(dw->path, messages_get("SaveObject"));
|
||||
else {
|
||||
const char *leaf = messages_get("SaveObject");
|
||||
size_t len = strlen(leaf);
|
||||
if (len >= sizeof dw->path - leaf_ofst)
|
||||
len = sizeof dw->path - leaf_ofst - 1;
|
||||
memcpy(dw->path + leaf_ofst, leaf, len);
|
||||
dw->path[leaf_ofst + len] = '\0';
|
||||
}
|
||||
|
||||
err = utf8_to_local_encoding(dw->path, 0, &local_path);
|
||||
if (err != UTF8_CONVERT_OK) {
|
||||
@ -772,9 +793,21 @@ bool ro_gui_download_click(wimp_pointer *pointer)
|
||||
if (pointer->i == ICON_DOWNLOAD_ICON && !dw->error &&
|
||||
!dw->saved) {
|
||||
const char *sprite = ro_gui_get_icon_string(pointer->w, pointer->i);
|
||||
int x = pointer->pos.x, y = pointer->pos.y;
|
||||
wimp_window_state wstate;
|
||||
wimp_icon_state istate;
|
||||
/* start the drag from the icon's exact location, rather than the pointer */
|
||||
istate.w = wstate.w = pointer->w;
|
||||
istate.i = pointer->i;
|
||||
if (!xwimp_get_window_state(&wstate) && !xwimp_get_icon_state(&istate)) {
|
||||
x = (istate.icon.extent.x1 + istate.icon.extent.x0)/2 +
|
||||
wstate.visible.x0 - wstate.xscroll;
|
||||
y = (istate.icon.extent.y1 + istate.icon.extent.y0)/2 +
|
||||
wstate.visible.y1 - wstate.yscroll;
|
||||
}
|
||||
gui_current_drag_type = GUI_DRAG_DOWNLOAD_SAVE;
|
||||
download_window_current = dw;
|
||||
ro_gui_drag_icon(pointer->pos.x, pointer->pos.y, sprite);
|
||||
ro_gui_drag_icon(x, y, sprite);
|
||||
|
||||
} else if (pointer->i == ICON_DOWNLOAD_DESTINATION) {
|
||||
strncpy(command + 14, dw->path, 242);
|
||||
@ -1152,6 +1185,34 @@ os_error *ro_gui_download_move(struct gui_download_window *dw,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remember the directory containing the given file,
|
||||
* for use in further downloads.
|
||||
*
|
||||
* \param path pathname of downloaded file
|
||||
* \return none
|
||||
*/
|
||||
|
||||
void ro_gui_download_remember_dir(const char *path)
|
||||
{
|
||||
char *lastdot = NULL;
|
||||
char *p = path;
|
||||
while (*p >= 0x20) {
|
||||
if (*p == '.') lastdot = p;
|
||||
p++;
|
||||
}
|
||||
if (lastdot) {
|
||||
/* remember the directory */
|
||||
char *new_dir = realloc(download_dir, (lastdot+1)-path);
|
||||
if (new_dir) {
|
||||
download_dir_len = lastdot - path;
|
||||
memcpy(new_dir, path, download_dir_len);
|
||||
new_dir[download_dir_len] = '\0';
|
||||
download_dir = new_dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start of save operation, user has specified where the file should be saved.
|
||||
*
|
||||
@ -1174,7 +1235,7 @@ bool ro_gui_download_save(struct gui_download_window *dw,
|
||||
temp_name = ro_gui_download_temp_name(dw);
|
||||
|
||||
/* does the user want to check for collisions when saving? */
|
||||
if (true && !force_overwrite) {
|
||||
if (!force_overwrite) {
|
||||
/* check whether the destination file/dir already exists */
|
||||
error = xosfile_read_stamped(file_name, &obj_type,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
@ -1236,6 +1297,8 @@ bool ro_gui_download_save(struct gui_download_window *dw,
|
||||
dw->saved = true;
|
||||
strncpy(dw->path, file_name, sizeof dw->path);
|
||||
|
||||
ro_gui_download_remember_dir(file_name);
|
||||
|
||||
/* grey out file icon */
|
||||
error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON,
|
||||
wimp_ICON_SHADED, wimp_ICON_SHADED);
|
||||
|
13
riscos/gui.c
13
riscos/gui.c
@ -1292,10 +1292,17 @@ void ro_gui_drag_end(wimp_dragged *drag)
|
||||
|
||||
void ro_gui_keypress(wimp_key *key)
|
||||
{
|
||||
os_error *error;
|
||||
if (key->c == wimp_KEY_ESCAPE &&
|
||||
(gui_current_drag_type == GUI_DRAG_SAVE ||
|
||||
gui_current_drag_type == GUI_DRAG_DOWNLOAD_SAVE)) {
|
||||
|
||||
if (!ro_gui_wimp_event_keypress(key)) {
|
||||
error = xwimp_process_key(key->c);
|
||||
/* Allow Escape key to be used for cancelling a drag save
|
||||
(easier than finding somewhere safe to abort the drag) */
|
||||
ro_gui_drag_box_cancel();
|
||||
gui_current_drag_type = GUI_DRAG_NONE;
|
||||
}
|
||||
else if (!ro_gui_wimp_event_keypress(key)) {
|
||||
os_error *error = xwimp_process_key(key->c);
|
||||
if (error) {
|
||||
LOG(("xwimp_process_key: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
|
@ -94,7 +94,9 @@ struct gui_query_window *ro_gui_query_window_lookup_id(query_id id)
|
||||
|
||||
|
||||
/**
|
||||
* Display a query to the user, requesting a response.
|
||||
* Display a query to the user, requesting a response, near the current
|
||||
* pointer position to keep the required mouse travel small, but also
|
||||
* protecting against spurious mouse clicks.
|
||||
*
|
||||
* \param query message token of query
|
||||
* \param detail parameter used in expanding tokenised message
|
||||
@ -108,6 +110,37 @@ struct gui_query_window *ro_gui_query_window_lookup_id(query_id id)
|
||||
query_id query_user(const char *query, const char *detail,
|
||||
const query_callback *cb, void *pw,
|
||||
const char *yes, const char *no)
|
||||
{
|
||||
wimp_pointer pointer;
|
||||
if (xwimp_get_pointer_info(&pointer))
|
||||
pointer.pos.y = pointer.pos.x = -1;
|
||||
|
||||
return query_user_xy(query, detail, cb, pw, yes, no,
|
||||
pointer.pos.x, pointer.pos.y);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display a query to the user, requesting a response, at a specified
|
||||
* screen position (x,y). The window is positioned relative to the given
|
||||
* location such that the required mouse travel is small, but non-zero
|
||||
* for protection spurious double-clicks.
|
||||
*
|
||||
* \param query message token of query
|
||||
* \param detail parameter used in expanding tokenised message
|
||||
* \param cb table of callback functions to be called when user responds
|
||||
* \param pw handle to be passed to callback functions
|
||||
* \param yes text to use for 'Yes' button' (or NULL for default)
|
||||
* \param no text to use for 'No' button (or NULL for default)
|
||||
* \param x x position in screen coordinates (-1 = centred on screen)
|
||||
* \param y y position in screen coordinates (-1 = centred on screen)
|
||||
* \return id number of the query (or QUERY_INVALID if it failed)
|
||||
*/
|
||||
|
||||
query_id query_user_xy(const char *query, const char *detail,
|
||||
const query_callback *cb, void *pw,
|
||||
const char *yes, const char *no,
|
||||
int x, int y)
|
||||
{
|
||||
struct gui_query_window *qw;
|
||||
char query_buffer[300];
|
||||
@ -115,7 +148,7 @@ query_id query_user(const char *query, const char *detail,
|
||||
wimp_icon *icn;
|
||||
int width;
|
||||
int len;
|
||||
int x;
|
||||
int tx;
|
||||
char *local_text = NULL;
|
||||
utf8_convert_ret err;
|
||||
|
||||
@ -164,7 +197,7 @@ query_id query_user(const char *query, const char *detail,
|
||||
width += 44;
|
||||
if (width < query_yes_width)
|
||||
width = query_yes_width;
|
||||
icn->extent.x0 = x = icn->extent.x1 - width;
|
||||
icn->extent.x0 = tx = icn->extent.x1 - width;
|
||||
|
||||
/* set the text of the 'No' button and size accordingly */
|
||||
err = utf8_to_local_encoding(no, 0, &local_text);
|
||||
@ -185,7 +218,7 @@ query_id query_user(const char *query, const char *detail,
|
||||
local_text = NULL;
|
||||
|
||||
if (!query_no_width) query_no_width = icn->extent.x1 - icn->extent.x0;
|
||||
icn->extent.x1 = x - 16;
|
||||
icn->extent.x1 = tx - 16;
|
||||
error = xwimptextop_string_width(icn->data.indirected_text.text, len, &width);
|
||||
if (error) {
|
||||
LOG(("xwimptextop_string_width: 0x%x:%s",
|
||||
@ -214,7 +247,13 @@ query_id query_user(const char *query, const char *detail,
|
||||
xwimp_set_icon_state(qw->window, ICON_QUERY_HELP,
|
||||
wimp_ICON_DELETED, wimp_ICON_DELETED);
|
||||
|
||||
ro_gui_dialog_open(qw->window);
|
||||
if (x >= 0 && y >= 0) {
|
||||
x -= tx - 8;
|
||||
y += (query_template->visible.y1 - query_template->visible.y0) / 2;
|
||||
ro_gui_dialog_open_xy(qw->window, x, y);
|
||||
}
|
||||
else
|
||||
ro_gui_dialog_open(qw->window);
|
||||
|
||||
ro_gui_wimp_event_set_user_data(qw->window, qw);
|
||||
ro_gui_wimp_event_register_mouse_click(qw->window, ro_gui_query_click);
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include "oslib/wimp.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
query_id query_user_xy(const char *query, const char *detail,
|
||||
const query_callback *cb, void *pw, const char *yes, const char *no,
|
||||
int x, int y);
|
||||
void ro_gui_query_init(void);
|
||||
void ro_gui_query_window_bring_to_front(query_id id);
|
||||
|
||||
|
244
riscos/save.c
244
riscos/save.c
@ -46,6 +46,7 @@
|
||||
#include "riscos/menus.h"
|
||||
#include "riscos/message.h"
|
||||
#include "riscos/options.h"
|
||||
#include "riscos/query.h"
|
||||
#include "riscos/save.h"
|
||||
#include "riscos/save_complete.h"
|
||||
#include "riscos/save_draw.h"
|
||||
@ -61,11 +62,25 @@
|
||||
#include "utils/utf8.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
//typedef enum
|
||||
//{
|
||||
// QueryRsn_Quit,
|
||||
// QueryRsn_Abort,
|
||||
// QueryRsn_Overwrite
|
||||
//} query_reason;
|
||||
|
||||
|
||||
/**todo - much of the state information for a save should probably be moved into a structure
|
||||
now since we could have multiple saves outstanding */
|
||||
|
||||
static gui_save_type gui_save_current_type;
|
||||
static struct content *gui_save_content = NULL;
|
||||
static struct selection *gui_save_selection = NULL;
|
||||
static int gui_save_filetype;
|
||||
static query_id gui_save_query;
|
||||
static bool gui_save_send_dataload;
|
||||
static wimp_message gui_save_message;
|
||||
static bool gui_save_close_after = true;
|
||||
|
||||
static bool dragbox_active = false; /** in-progress Wimp_DragBox/DragASprite op */
|
||||
static bool using_dragasprite = true;
|
||||
@ -75,16 +90,29 @@ static wimp_w gui_save_sourcew = (wimp_w)-1;
|
||||
#define LEAFNAME_MAX 200
|
||||
static char save_leafname[LEAFNAME_MAX];
|
||||
|
||||
/** Current save directory (updated by and used for dialog-based saving) */
|
||||
static char *save_dir = NULL;
|
||||
static size_t save_dir_len;
|
||||
|
||||
typedef enum { LINK_ACORN, LINK_ANT, LINK_TEXT } link_format;
|
||||
|
||||
static bool ro_gui_save_complete(struct content *c, char *path);
|
||||
static bool ro_gui_save_content(struct content *c, char *path);
|
||||
static bool ro_gui_save_content(struct content *c, char *path, bool force_overwrite);
|
||||
static void ro_gui_save_done(void);
|
||||
static void ro_gui_save_bounced(wimp_message *message);
|
||||
static void ro_gui_save_object_native(struct content *c, char *path);
|
||||
static bool ro_gui_save_link(struct content *c, link_format format, char *path);
|
||||
static void ro_gui_save_set_state(struct content *c, gui_save_type save_type,
|
||||
char *leaf_buf, char *icon_buf);
|
||||
static bool ro_gui_save_create_thumbnail(struct content *c, const char *name);
|
||||
static void ro_gui_save_overwrite_confirmed(query_id, enum query_response res, void *p);
|
||||
static void ro_gui_save_overwrite_cancelled(query_id, enum query_response res, void *p);
|
||||
|
||||
static const query_callback overwrite_funcs =
|
||||
{
|
||||
ro_gui_save_overwrite_confirmed,
|
||||
ro_gui_save_overwrite_cancelled
|
||||
};
|
||||
|
||||
|
||||
/** An entry in gui_save_table. */
|
||||
@ -180,7 +208,7 @@ wimp_w ro_gui_saveas_create(const char *template_name)
|
||||
|
||||
|
||||
/**
|
||||
* Clean-up function that releases our sprite area.
|
||||
* Clean-up function that releases our sprite area and memory.
|
||||
*/
|
||||
|
||||
void ro_gui_saveas_quit(void)
|
||||
@ -193,6 +221,9 @@ void ro_gui_saveas_quit(void)
|
||||
}
|
||||
saveas_area = NULL;
|
||||
}
|
||||
|
||||
free(save_dir);
|
||||
save_dir = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -209,7 +240,8 @@ void ro_gui_saveas_quit(void)
|
||||
|
||||
void ro_gui_save_prepare(gui_save_type save_type, struct content *c)
|
||||
{
|
||||
char name_buf[LEAFNAME_MAX];
|
||||
char name_buf[FILENAME_MAX];
|
||||
size_t leaf_offset = 0;
|
||||
char icon_buf[20];
|
||||
|
||||
assert((save_type == GUI_SAVE_HOTLIST_EXPORT_HTML) ||
|
||||
@ -218,7 +250,13 @@ void ro_gui_save_prepare(gui_save_type save_type, struct content *c)
|
||||
gui_save_current_type = save_type;
|
||||
gui_save_content = c;
|
||||
|
||||
ro_gui_save_set_state(c, save_type, name_buf, icon_buf);
|
||||
if (save_dir) {
|
||||
leaf_offset = save_dir_len;
|
||||
memcpy(name_buf, save_dir, leaf_offset);
|
||||
name_buf[leaf_offset++] = '.';
|
||||
}
|
||||
|
||||
ro_gui_save_set_state(c, save_type, name_buf + leaf_offset, icon_buf);
|
||||
|
||||
ro_gui_set_icon_sprite(dialog_saveas, ICON_SAVE_ICON, saveas_area,
|
||||
icon_buf);
|
||||
@ -234,12 +272,25 @@ void ro_gui_save_prepare(gui_save_type save_type, struct content *c)
|
||||
*/
|
||||
void ro_gui_save_start_drag(wimp_pointer *pointer)
|
||||
{
|
||||
if (pointer->buttons == wimp_DRAG_SELECT) {
|
||||
if (pointer->buttons & (wimp_DRAG_SELECT | wimp_DRAG_ADJUST)) {
|
||||
const char *sprite = ro_gui_get_icon_string(pointer->w, pointer->i);
|
||||
int x = pointer->pos.x, y = pointer->pos.y;
|
||||
wimp_window_state wstate;
|
||||
wimp_icon_state istate;
|
||||
/* start the drag from the icon's exact location, rather than the pointer */
|
||||
istate.w = wstate.w = pointer->w;
|
||||
istate.i = pointer->i;
|
||||
if (!xwimp_get_window_state(&wstate) && !xwimp_get_icon_state(&istate)) {
|
||||
x = (istate.icon.extent.x1 + istate.icon.extent.x0)/2 +
|
||||
wstate.visible.x0 - wstate.xscroll;
|
||||
y = (istate.icon.extent.y1 + istate.icon.extent.y0)/2 +
|
||||
wstate.visible.y1 - wstate.yscroll;
|
||||
}
|
||||
gui_current_drag_type = GUI_DRAG_SAVE;
|
||||
gui_save_sourcew = pointer->w;
|
||||
saving_from_dialog = true;
|
||||
ro_gui_drag_icon(pointer->pos.x, pointer->pos.y, sprite);
|
||||
gui_save_close_after = !(pointer->buttons & wimp_DRAG_ADJUST);
|
||||
ro_gui_drag_icon(x, y, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,6 +304,7 @@ void ro_gui_save_start_drag(wimp_pointer *pointer)
|
||||
bool ro_gui_save_ok(wimp_w w)
|
||||
{
|
||||
const char *name = ro_gui_get_icon_string(w, ICON_SAVE_PATH);
|
||||
wimp_pointer pointer;
|
||||
char path[256];
|
||||
|
||||
if (!strrchr(name, '.')) {
|
||||
@ -263,7 +315,14 @@ bool ro_gui_save_ok(wimp_w w)
|
||||
ro_gui_convert_save_path(path, sizeof path, name);
|
||||
gui_save_sourcew = w;
|
||||
saving_from_dialog = true;
|
||||
return ro_gui_save_content(gui_save_content, path);
|
||||
gui_save_close_after = xwimp_get_pointer_info(&pointer)
|
||||
|| !(pointer.buttons & wimp_CLICK_ADJUST);
|
||||
if (!ro_gui_save_content(gui_save_content, path, !option_confirm_overwrite)) {
|
||||
memcpy(&gui_save_message.data.data_xfer.file_name, path, 1 + strlen(path));
|
||||
gui_save_send_dataload = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -626,13 +685,15 @@ void ro_gui_save_bounced(wimp_message *message)
|
||||
|
||||
|
||||
/**
|
||||
* Handle Message_DataSaveAck for a drag from the save dialog or browser window.
|
||||
* Handle Message_DataSaveAck for a drag from the save dialog or browser window,
|
||||
* or Clipboard protocol.
|
||||
*/
|
||||
|
||||
void ro_gui_save_datasave_ack(wimp_message *message)
|
||||
{
|
||||
char *path = message->data.data_xfer.file_name;
|
||||
struct content *c = gui_save_content;
|
||||
bool force_overwrite;
|
||||
|
||||
switch (gui_save_current_type) {
|
||||
case GUI_SAVE_HOTLIST_EXPORT_HTML:
|
||||
@ -653,31 +714,18 @@ void ro_gui_save_datasave_ack(wimp_message *message)
|
||||
ro_gui_set_icon_string(gui_save_sourcew, ICON_SAVE_PATH,
|
||||
path, true);
|
||||
|
||||
if (ro_gui_save_content(c, path)) {
|
||||
os_error *error;
|
||||
gui_save_send_dataload = true;
|
||||
memcpy(&gui_save_message, message, sizeof(gui_save_message));
|
||||
|
||||
/* Ack successful save with message_DATA_LOAD */
|
||||
message->action = message_DATA_LOAD;
|
||||
message->your_ref = message->my_ref;
|
||||
error = xwimp_send_message(wimp_USER_MESSAGE, message,
|
||||
message->sender);
|
||||
if (error) {
|
||||
LOG(("xwimp_send_message: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
warn_user("SaveError", error->errmess);
|
||||
}
|
||||
/* if saving/pasting to another application, don't request user
|
||||
confirmation; a ScrapFile almost certainly exists already */
|
||||
if (message->data.data_xfer.est_size == -1)
|
||||
force_overwrite = true;
|
||||
else
|
||||
force_overwrite = !option_confirm_overwrite;
|
||||
|
||||
/* Close the save window */
|
||||
ro_gui_dialog_close(dialog_saveas);
|
||||
error = xwimp_create_menu(wimp_CLOSE_MENU, 0, 0);
|
||||
if (error) {
|
||||
LOG(("xwimp_create_menu: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
warn_user("MenuError", error->errmess);
|
||||
}
|
||||
|
||||
gui_save_content = 0;
|
||||
}
|
||||
if (ro_gui_save_content(c, path, force_overwrite))
|
||||
ro_gui_save_done();
|
||||
}
|
||||
|
||||
|
||||
@ -685,15 +733,48 @@ void ro_gui_save_datasave_ack(wimp_message *message)
|
||||
/**
|
||||
* Does the actual saving
|
||||
*
|
||||
* \param c content to save (or NULL for other)
|
||||
* \param path path to save as
|
||||
* \return true on success, false on error and error reported
|
||||
* \param c content to save (or NULL for other)
|
||||
* \param path path to save as
|
||||
* \param force_overwrite true iff required to overwrite without prompting
|
||||
* \return true on success,
|
||||
* false on (i) error and error reported
|
||||
* or (ii) deferred awaiting user confirmation
|
||||
*/
|
||||
|
||||
bool ro_gui_save_content(struct content *c, char *path)
|
||||
bool ro_gui_save_content(struct content *c, char *path, bool force_overwrite)
|
||||
{
|
||||
os_error *error;
|
||||
|
||||
/* does the user want to check for collisions when saving? */
|
||||
if (!force_overwrite) {
|
||||
fileswitch_object_type obj_type;
|
||||
/* check whether the destination file/dir already exists */
|
||||
error = xosfile_read_stamped(path, &obj_type,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
if (error) {
|
||||
LOG(("xosfile_read_stamped: 0x%x:%s", error->errnum, error->errmess));
|
||||
warn_user("SaveError", error->errmess);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (obj_type) {
|
||||
case osfile_NOT_FOUND:
|
||||
break;
|
||||
|
||||
case osfile_IS_FILE:
|
||||
gui_save_query = query_user("OverwriteFile", NULL, &overwrite_funcs, NULL,
|
||||
messages_get("Replace"), messages_get("DontReplace"));
|
||||
// gui_save_query_rsn = QueryRsn_Overwrite;
|
||||
return false;
|
||||
|
||||
default:
|
||||
error = xosfile_make_error(path, obj_type);
|
||||
assert(error);
|
||||
warn_user("SaveError", error->errmess);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (gui_save_current_type) {
|
||||
#ifdef WITH_DRAW_EXPORT
|
||||
case GUI_SAVE_DRAW:
|
||||
@ -783,6 +864,67 @@ bool ro_gui_save_content(struct content *c, char *path)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save completed, inform recipient and close our 'save as' dialog.
|
||||
*/
|
||||
|
||||
void ro_gui_save_done(void)
|
||||
{
|
||||
os_error *error;
|
||||
|
||||
if (gui_save_send_dataload) {
|
||||
/* Ack successful save with message_DATA_LOAD */
|
||||
wimp_message *message = &gui_save_message;
|
||||
message->action = message_DATA_LOAD;
|
||||
message->your_ref = message->my_ref;
|
||||
error = xwimp_send_message(wimp_USER_MESSAGE, message,
|
||||
message->sender);
|
||||
if (error) {
|
||||
LOG(("xwimp_send_message: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
warn_user("SaveError", error->errmess);
|
||||
}
|
||||
}
|
||||
|
||||
if (saving_from_dialog) {
|
||||
/* */
|
||||
char *sp = gui_save_message.data.data_xfer.file_name;
|
||||
char *ep = sp + sizeof(gui_save_message.data.data_xfer.file_name);
|
||||
char *lastdot = NULL;
|
||||
char *p = sp;
|
||||
|
||||
while (p < ep && *p >= 0x20) {
|
||||
if (*p == '.') lastdot = p;
|
||||
p++;
|
||||
}
|
||||
if (lastdot) {
|
||||
/* remember the directory */
|
||||
char *new_dir = realloc(save_dir, (lastdot+1)-sp);
|
||||
if (new_dir) {
|
||||
save_dir_len = lastdot - sp;
|
||||
memcpy(new_dir, sp, save_dir_len);
|
||||
new_dir[save_dir_len] = '\0';
|
||||
save_dir = new_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (gui_save_close_after) {
|
||||
/* Close the save window */
|
||||
ro_gui_dialog_close(dialog_saveas);
|
||||
error = xwimp_create_menu(wimp_CLOSE_MENU, 0, 0);
|
||||
if (error) {
|
||||
LOG(("xwimp_create_menu: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
warn_user("MenuError", error->errmess);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!saving_from_dialog || gui_save_close_after)
|
||||
gui_save_content = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepare an application directory and save_complete() to it.
|
||||
*
|
||||
@ -808,7 +950,7 @@ bool ro_gui_save_complete(struct content *c, char *path)
|
||||
char *dot;
|
||||
int i;
|
||||
|
||||
/* Create dir */
|
||||
/* Create dir */
|
||||
error = xosfile_create_dir(path, 0);
|
||||
if (error) {
|
||||
LOG(("xosfile_create_dir: 0x%x: %s",
|
||||
@ -817,7 +959,7 @@ bool ro_gui_save_complete(struct content *c, char *path)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Save !Run file */
|
||||
/* Save !Run file */
|
||||
snprintf(buf, sizeof buf, "%s.!Run", path);
|
||||
fp = fopen(buf, "w");
|
||||
if (!fp) {
|
||||
@ -850,8 +992,8 @@ bool ro_gui_save_complete(struct content *c, char *path)
|
||||
memcpy(sprite->name, dot, len);
|
||||
memset(sprite->name + len, 0, 12 - len);
|
||||
for (i = 0; i < 12; i++) /* convert to lower case */
|
||||
if (sprite->name[i] != '\0')
|
||||
sprite->name[i] = tolower(sprite->name[i]);
|
||||
if (sprite->name[i] != '\0')
|
||||
sprite->name[i] = tolower(sprite->name[i]);
|
||||
|
||||
/* Create !Sprites */
|
||||
snprintf(buf, sizeof buf, "%s.!Sprites", path);
|
||||
@ -1140,3 +1282,27 @@ bool ro_gui_save_create_thumbnail(struct content *c, const char *name)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* User has opted not to overwrite the existing file.
|
||||
*/
|
||||
|
||||
void ro_gui_save_overwrite_cancelled(query_id id, enum query_response res, void *p)
|
||||
{
|
||||
if (!saving_from_dialog) {
|
||||
// ro_gui_save_prepare(gui_save_current_type, gui_save_content);
|
||||
// ro_gui_dialog_open_persistent(g->window, dialog_saveas, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overwrite of existing file confirmed, proceed with the save.
|
||||
*/
|
||||
|
||||
void ro_gui_save_overwrite_confirmed(query_id id, enum query_response res, void *p)
|
||||
{
|
||||
if (ro_gui_save_content(gui_save_content, gui_save_message.data.data_xfer.file_name, true))
|
||||
ro_gui_save_done();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user