Assorted saving-related changes (WIP)

svn path=/trunk/netsurf/; revision=6010
This commit is contained in:
Adrian Lees 2009-01-10 00:18:34 +00:00
parent 4e3951660f
commit d67a57c1e9
8 changed files with 368 additions and 85 deletions

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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();
}