36#include <libwapcaplet/libwapcaplet.h>
38#include "oslib/mimemap.h"
39#include "oslib/osargs.h"
40#include "oslib/osfile.h"
41#include "oslib/osfind.h"
42#include "oslib/osfscontrol.h"
43#include "oslib/osgbpb.h"
44#include "oslib/wimp.h"
45#include "oslib/wimpspriteop.h"
70#define ICON_DOWNLOAD_ICON 0
71#define ICON_DOWNLOAD_URL 1
72#define ICON_DOWNLOAD_PATH 2
73#define ICON_DOWNLOAD_DESTINATION 3
74#define ICON_DOWNLOAD_PROGRESS 5
75#define ICON_DOWNLOAD_STATUS 6
77#define RO_DOWNLOAD_MAX_PATH_LEN 255
154 const char *dest_file,
const char *orig_file);
156 const char *dest_file,
const char *src_file);
159 const char *file_name,
bool force_overwrite);
213 static char temp_name[40];
214 snprintf(temp_name,
sizeof temp_name,
"<Wimp$ScrapDir>.ns%x",
230 if (scheme != NULL) {
232 if (lwc_string_isequal(scheme,
234 &filescheme) != lwc_error_ok) {
240 if (
path != NULL && lwc_string_length(
path) != 0) {
243 lwc_string_length(
path),
259 const char *mime_type;
262 error = xmimemaptranslate_mime_type_to_filetype(mime_type, &ftype);
265 "xmimemaptranslate_mime_type_to_filetype: 0x%x: %s",
290 const char *temp_name;
293 bool space_warning =
false;
299 dw = malloc(
sizeof *dw);
317 dw->
url[
sizeof(dw->
url) - 1] = 0;
340 space_warning =
true;
342 error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR,
343 temp_name, 0, &dw->
file);
345 NSLOG(netsurf, INFO,
"xosfind_openoutw: 0x%x: %s",
372 if (temp_name == NULL)
375 if (temp_name != NULL)
379 NSLOG(netsurf, INFO,
"Failed to establish download filename.");
385 for (i = 0, last_dot = (
size_t) -1;
filename[i] !=
'\0'; i++) {
391 }
else if (c <=
' ' || strchr(
":*#$&@^%\\", c) != NULL)
395 if (
nsoption_bool(strip_extensions) && last_dot != (
size_t) -1)
411 NSLOG(netsurf, INFO,
"utf8_to_local_encoding failed");
417 strncpy(dw->
path, local_path,
sizeof(dw->
path) - 1);
428 indirected_text.text = dw->
path;
430 indirected_text.size =
sizeof dw->
path;
438 NSLOG(netsurf, INFO,
"xwimp_create_window: 0x%x: %s",
476 const char *error_msg)
492 wimp_COLOUR_RED << wimp_ICON_FG_COLOUR_SHIFT,
493 wimp_ICON_FG_COLOUR);
495 NSLOG(netsurf, INFO,
"xwimp_set_icon_state: 0x%x: %s",
502 wimp_ICON_SHADED, 0);
504 NSLOG(netsurf, INFO,
"xwimp_set_icon_state: 0x%x: %s",
511 wimp_ICON_SHADED, wimp_ICON_SHADED);
513 NSLOG(netsurf, INFO,
"xwimp_set_icon_state: 0x%x: %s",
531 const char *data,
unsigned int size)
541 NSLOG(netsurf, INFO,
"xosgbpb_writew: 0x%x: %s",
543 msg =
error->errmess;
545 }
else if (unwritten) {
546 NSLOG(netsurf, INFO,
"xosgbpb_writew: unwritten %i",
568 wimp_ICON_SHADED, 0);
571 "xwimp_set_icon_state: 0x%x: %s",
578 wimp_ICON_DELETED, wimp_ICON_DELETED);
581 "xwimp_set_icon_state: 0x%x: %s",
590 "xwimp_set_icon_state: 0x%x: %s",
631 dt = (t.tv_sec + 0.000001 * t.tv_usec) - (dw->
last_time.tv_sec +
657 sprintf(time,
"%u:%.2u", left / 60, left % 60);
669 received, total_size, speed, time);
674 received, total_size, speed, time);
682 sprintf(time,
"%u:%.2u", left / 60, left % 60);
692 received, speed, time);
697 received, speed, time);
708 rate = (float) dw->
received / (
float) left;
709 sprintf(time,
"%u:%.2u", left / 60, left % 60);
720 total_size, speed, time);
724 total_size, speed, time);
741 NSLOG(netsurf, INFO,
"xwimp_resize_icon: 0x%x: %s",
742 error->errnum, error->errmess);
748 NSLOG(netsurf, INFO,
"xwimp_set_icon_state: 0x%x: %s",
749 error->errnum, error->errmess);
783 error = xwimp_get_caret_position(&caret);
785 NSLOG(netsurf, INFO,
"xwimp_get_caret_position: 0x%x : %s",
786 error->errnum, error->errmess);
789 else if (caret.w == dw->
window) {
790 error = xwimp_set_caret_position(dw->
window, (wimp_i)-1, 0, 0, 1 << 25, -1);
793 "xwimp_get_caret_position: 0x%x : %s",
819 error = xosfind_closew(dw->
file);
821 NSLOG(netsurf, INFO,
"xosfind_closew: 0x%x: %s",
822 error->errnum, error->errmess);
828 error = xosfile_set_type(dw->
path,
831 NSLOG(netsurf, INFO,
"xosfile_set_type: 0x%x: %s",
832 error->errnum, error->errmess);
856 if ((pointer->buttons & (wimp_DRAG_SELECT | wimp_DRAG_ADJUST)) &&
860 int x = pointer->pos.x, y = pointer->pos.y;
861 wimp_window_state wstate;
862 wimp_icon_state istate;
864 istate.w = wstate.w = pointer->w;
865 istate.i = pointer->i;
866 if (!xwimp_get_window_state(&wstate) && !xwimp_get_icon_state(&istate)) {
867 x = (istate.icon.extent.x1 + istate.icon.extent.x0)/2 +
868 wstate.visible.x0 - wstate.xscroll;
869 y = (istate.icon.extent.y1 + istate.icon.extent.y0)/2 +
870 wstate.visible.y1 - wstate.yscroll;
877 char command[
sizeof(dw->
path) + 14 + 1] =
"Filer_OpenDir ";
880 strncpy(command + 14, dw->
path,
sizeof(command) - 14 - 1);
881 command[
sizeof(command) - 1] = 0;
882 dot = strrchr(command,
'.');
886 error = xos_cli(command);
888 NSLOG(netsurf, INFO,
"xos_cli: 0x%x: %s",
912 case wimp_KEY_ESCAPE:
916 case wimp_KEY_RETURN: {
919 if (!strrchr(
name,
'.')) {
951 wimp_pointer pointer;
952 wimp_message message;
960 error = xwimp_get_pointer_info(&pointer);
962 NSLOG(netsurf, INFO,
"xwimp_get_pointer_info: 0x%x: %s",
969 if (pointer.w == dw->
window)
return;
971 leaf = strrchr(dw->
path,
'.');
978 message.your_ref = 0;
979 message.action = message_DATA_SAVE;
980 message.data.data_xfer.w = pointer.w;
981 message.data.data_xfer.i = pointer.i;
982 message.data.data_xfer.pos.x = pointer.pos.x;
983 message.data.data_xfer.pos.y = pointer.pos.y;
986 message.data.data_xfer.file_type = dw->
file_type;
987 message.size = 44 + ((strlen(message.data.data_xfer.file_name) + 4) &
990 error = xwimp_send_message_to_window(wimp_USER_MESSAGE, &message,
991 pointer.w, pointer.i, 0);
994 "xwimp_send_message_to_window: 0x%x: %s",
1015 memcpy(&dw->
save_message, message,
sizeof(wimp_message));
1046 error = xosfscontrol_canonicalise_path(
path, NULL, NULL, NULL, 0, &spare);
1048 NSLOG(netsurf, INFO,
1049 "xosfscontrol_canonicalise_path: 0x%x: %s",
1055 buf = malloc(1 - spare);
1057 error = xosfscontrol_canonicalise_path(
path, buf, NULL, NULL,
1060 NSLOG(netsurf, INFO,
1061 "xosfscontrol_canonicalise_path: 0x%x: %s",
1086 const char *dest_file,
const char *orig_file)
1089 int dest_len = strlen(dest_file);
1096 dir = malloc(dest_len + 1);
1097 if (!dir)
return true;
1099 while (dest_len > 0 && dest_file[--dest_len] !=
'.');
1101 memcpy(dir, dest_file, dest_len);
1102 dir[dest_len] =
'\0';
1105 error = xosfscontrol_free_space64(dir, &free_lo, &free_hi,
1106 &max_file, NULL, NULL);
1108 NSLOG(netsurf, INFO,
"xosfscontrol_free_space64: 0x%x: %s",
1112 error = xosfscontrol_free_space(dir, (
int*)&free_lo,
1115 NSLOG(netsurf, INFO,
1116 "xosfscontrol_free_space: 0x%x: %s",
1128 char *dest_canon, *orig_canon;
1131 if (!orig_file || !dw->
file) {
1136 space =
min((bits)max_file, free_lo);
1139 if (!dest_canon) dest_canon = (
char*)dest_file;
1142 if (!orig_canon) orig_canon = (
char*)orig_file;
1148 char *dot = strchr(orig_canon,
'.');
1149 if (dot && !strncasecmp(dest_canon, orig_canon, (dot + 1) - orig_canon)) {
1152 error = xosargs_read_allocation(dw->
file,
1155 NSLOG(netsurf, INFO,
1156 "xosargs_read_allocation: 0x%x : %s",
1161 space += allocation;
1165 if (dest_canon != dest_file) free(dest_canon);
1166 if (orig_canon != orig_file) free(orig_canon);
1188 const char *dest_file,
const char *src_file)
1197 NSLOG(netsurf, INFO,
"xosfind_closew: 0x%x: %s",
1204 error = xosfscontrol_rename(src_file, dest_file);
1207 if (
error && (
error->errnum == error_BAD_RENAME ||
1208 (
error->errnum & 0xFF00FFu) == 0x1009Fu)) {
1210 error = xosfscontrol_copy(src_file, dest_file,
1211 osfscontrol_COPY_FORCE |
1212 osfscontrol_COPY_DELETE |
1213 osfscontrol_COPY_LOOK,
1216 NSLOG(netsurf, INFO,
"xosfscontrol_copy: 0x%x: %s",
1221 NSLOG(netsurf, INFO,
"xosfscontrol_rename: 0x%x: %s",
1228 error = xosfile_write(dest_file, 0xdeaddead, 0xdeaddead,
1229 fileswitch_ATTR_OWNER_READ |
1230 fileswitch_ATTR_OWNER_WRITE);
1232 NSLOG(netsurf, INFO,
"xosfile_write: 0x%x: %s",
1237 error = xosfind_openupw(osfind_NO_PATH | osfind_ERROR_IF_DIR,
1238 dest_file, 0, &dw->
file);
1240 NSLOG(netsurf, INFO,
"xosfind_openupw: 0x%x: %s",
1247 NSLOG(netsurf, INFO,
"xosargs_set_ptrw: 0x%x: %s",
1254 error = xosfile_set_type(dest_file,
1257 NSLOG(netsurf, INFO,
"xosfile_set_type: 0x%x: %s",
1278 const char *lastdot = NULL;
1279 const char *p =
path;
1281 while (*p >= 0x20) {
1284 if (!lastdot && p ==
path + 12 &&
1285 !memcmp(
path,
"<Wimp$Scrap>", 12))
break;
1313 const char *file_name,
bool force_overwrite)
1315 fileswitch_object_type obj_type;
1316 const char *temp_name;
1325 if (!force_overwrite) {
1327 error = xosfile_read_stamped(file_name, &obj_type,
1328 NULL, NULL, NULL, NULL, NULL);
1330 NSLOG(netsurf, INFO,
"xosfile_read_stamped: 0x%x:%s",
1336 case osfile_NOT_FOUND:
1339 case osfile_IS_FILE:
1346 error = xosfile_make_error(file_name, obj_type);
1364 error = xosfind_openupw(osfind_NO_PATH | osfind_ERROR_IF_DIR,
1365 temp_name, 0, &dw->
file);
1367 NSLOG(netsurf, INFO,
"xosfind_openupw: 0x%x: %s",
1373 NSLOG(netsurf, INFO,
1374 "xosargs_set_ptrw: 0x%x: %s",
1389 strncpy(dw->
path, file_name,
sizeof(dw->
path) - 1);
1397 wimp_ICON_SHADED, wimp_ICON_SHADED);
1399 NSLOG(netsurf, INFO,
"xwimp_set_icon_state: 0x%x: %s",
1411 wimp_ICON_DELETED, wimp_ICON_DELETED);
1413 NSLOG(netsurf, INFO,
"xwimp_set_icon_state: 0x%x: %s",
1420 NSLOG(netsurf, INFO,
"xwimp_set_icon_state: 0x%x: %s",
1447 message->action = message_DATA_LOAD;
1448 message->your_ref = message->my_ref;
1449 error = xwimp_send_message_to_window(wimp_USER_MESSAGE, message,
1450 message->data.data_xfer.w,
1451 message->data.data_xfer.i, 0);
1466 if (
error &&
error->errnum != error_WIMP_BAD_HANDLE) {
1467 NSLOG(netsurf, INFO,
"xwimp_set_icon_state: 0x%x: %s",
1549 NSLOG(netsurf, INFO,
"xwimp_delete_window: 0x%x: %s",
1559 NSLOG(netsurf, INFO,
"xosfind_closew: 0x%x: %s",
1569 error = xosfile_delete(temp_name, 0, 0, 0, 0, 0);
1571 NSLOG(netsurf, INFO,
"xosfile_delete: 0x%x: %s",
Useful interned string pointers (interface).
void download_context_destroy(download_context *ctx)
Destroy a download context.
nsurl * download_context_get_url(const download_context *ctx)
Retrieve the URL for a download.
const char * download_context_get_filename(const download_context *ctx)
Retrieve the filename for a download.
void download_context_abort(download_context *ctx)
Abort a download fetch.
const char * download_context_get_mime_type(const download_context *ctx)
Retrieve the MIME type for a download.
unsigned long long int download_context_get_total_length(const download_context *ctx)
Retrieve total byte length of download.
Core download context (interface)
wimp_window * ro_gui_dialog_load_template(const char *template_name)
Load a template without creating a window.
void ro_gui_dialog_open(wimp_w w)
Open a dialog box, centred on the screen.
bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar, int width, int height)
Moves a window to the top of the stack.
nserror
Enumeration of error codes.
@ NSERROR_SAVE_FAILED
Failed to save data.
@ NSERROR_BAD_ENCODING
The character set is unknown.
nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
#define ICON_DOWNLOAD_DESTINATION
void ro_gui_download_init(void)
Load the download window template.
static os_error * ro_gui_download_move(struct gui_download_window *dw, const char *dest_file, const char *src_file)
Move the downloading file to a new location and continue downloading there.
#define RO_DOWNLOAD_MAX_PATH_LEN
#define ICON_DOWNLOAD_PATH
static void ro_gui_download_close_cancelled(query_id, enum query_response res, void *p)
User has opted to cancel the close, leaving the download to continue.
static struct gui_download_table download_table
static struct gui_download_window * download_window_list
List of all download windows.
static void ro_gui_download_close_confirmed(query_id, enum query_response res, void *p)
Download aborted, close window and tidy up.
static int download_progress_x0
Coordinates of progress bar.
static const char * ro_gui_download_temp_name(struct gui_download_window *dw)
Returns the pathname of a temporary file for this download.
static size_t download_dir_len
static int download_progress_y1
static const query_callback overwrite_funcs
static void ro_gui_download_overwrite_confirmed(query_id, enum query_response res, void *p)
Overwrite of existing file confirmed, proceed with the save.
static nserror gui_download_window_data(struct gui_download_window *dw, const char *data, unsigned int size)
Handle received download data.
static struct gui_download_window * gui_download_window_create(download_context *ctx, struct gui_window *gui)
Create and open a download progress window.
static void ro_gui_download_window_destroy_wrapper(void *p)
Wrapper for ro_gui_download_window_destroy(), suitable for riscos_schedule().
static void ro_gui_download_update_status_wrapper(void *p)
Wrapper for ro_gui_download_update_status(), suitable for riscos_schedule().
static bool ro_gui_download_keypress(wimp_key *key)
Handler Key_Press events in a download window.
#define ICON_DOWNLOAD_STATUS
static struct gui_download_window * download_window_current
Download window with current save operation.
static void ro_gui_download_send_dataload(struct gui_download_window *dw)
Send DataLoad message in response to DataSaveAck, informing the target application that the transfer ...
static void ro_gui_download_close(wimp_w w)
Handle closing of download window.
static char * download_dir
Current download directory.
static const query_callback close_funcs
#define ICON_DOWNLOAD_ICON
static void gui_download_window_error(struct gui_download_window *dw, const char *error_msg)
Handle failed downloads.
bool ro_gui_download_prequit(void)
Respond to PreQuit message, displaying a prompt message if we need the user to confirm the shutdown.
static wimp_window * download_template
Template for a download window.
struct gui_download_table * riscos_download_table
#define ICON_DOWNLOAD_URL
static int download_progress_y0
static void ro_gui_download_remember_dir(const char *path)
Remember the directory containing the given file, for use in further downloads.
static void ro_gui_download_overwrite_cancelled(query_id, enum query_response res, void *p)
User has opted not to overwrite the existing file.
static void ro_gui_download_window_hide_caret(struct gui_download_window *dw)
Hide the caret but preserve input focus.
static void ro_gui_download_update_status(struct gui_download_window *dw)
Update the status text and progress bar.
static nserror download_ro_filetype(download_context *ctx, bits *ftype_out)
Try and find the correct RISC OS filetype from a download context.
static bool ro_gui_download_save(struct gui_download_window *dw, const char *file_name, bool force_overwrite)
Start of save operation, user has specified where the file should be saved.
#define ICON_DOWNLOAD_PROGRESS
static void gui_download_window_done(struct gui_download_window *dw)
Handle completed downloads.
static int download_progress_width
Width of progress bar at 100%.
static void ro_gui_download_drag_end(wimp_dragged *drag, void *data)
Handle User_Drag_Box event for a drag from a download window.
static char * ro_gui_download_canonicalise(const char *path)
Return a pathname in canonical form.
static bool ro_gui_download_click(wimp_pointer *pointer)
Handle Mouse_Click events in a download window.
static bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit)
Close a download window and free any related resources.
static bool ro_gui_download_check_space(struct gui_download_window *dw, const char *dest_file, const char *orig_file)
Check the available space on the medium containing the destination file, taking into account any spac...
void ro_gui_download_datasave_ack(wimp_message *message)
Handle Message_DataSaveAck for a drag from a download window.
void ro_mouse_drag_start(void(*drag_end)(wimp_dragged *dragged, void *data), void(*drag_track)(wimp_pointer *pointer, void *data), void(*drag_cancel)(void *data), void *data)
Start a drag, providing a function to be called when the Wimp_DragEnd event is received and optionall...
Mouse dragging and tracking support interface for RISC OS.
Interface to platform-specific download operations.
#define NSLOG(catname, level, logmsg, args...)
const char * messages_get_errorcode(nserror code)
lookup of a message by errorcode from the standard Messages hash.
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Localised message support (interface).
NetSurf URL handling (interface).
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
lwc_string * nsurl_get_component(const nsurl *url, nsurl_component part)
Get part of a URL as a lwc_string, from a NetSurf URL object.
struct nsurl nsurl
NetSurf URL object.
void ro_gui_query_window_bring_to_front(query_id id)
void query_close(query_id id)
Close a query window without waiting for a response from the user.
query_id query_user(const char *query, const char *detail, const query_callback *cb, void *pw, const char *yes, const char *no)
Display a query to the user, requesting a response, near the current pointer position to keep the req...
bits ro_filetype_from_unix_path(const char *unix_path)
Determine the type of a local file.
RISC OS filetpe interface.
ro_gui_drag_type gui_current_drag_type
bool ro_gui_prequit(void)
Test whether it's okay to shutdown, prompting the user if not.
nserror ro_warn_user(const char *warning, const char *detail)
Display a warning for a serious problem (eg memory exhaustion).
nserror riscos_schedule(int t, void(*callback)(void *p), void *p)
Schedule a callback.
File/object/selection saving (Interface).
void ro_gui_drag_icon(int x, int y, const char *sprite)
Start drag of icon under the pointer.
void ro_gui_convert_save_path(char *dp, size_t len, const char *p)
Convert a ctrl-char terminated pathname possibly containing spaces to a NUL-terminated one containing...
Interface to utility string handling.
char * human_friendly_bytesize(unsigned long long int bytesize)
Create a human readable representation of a size in bytes.
A context for a download.
function table for download windows.
struct gui_download_window *(* create)(struct download_context *ctx, struct gui_window *parent)
context for each download.
struct ami_generic_window w
wimp_w window
RISC OS window handle.
os_fw file
RISC OS file handle, of temporary file when !saved, and of destination when saved.
struct timeval last_time
Time status was last updated.
unsigned int total_size
Size of resource, or 0 if unknown.
unsigned int received
Amount of data received so far.
unsigned int average_points
Number of points in the average.
char sprite_name[20]
Buffer for sprite icon.
nsatari_download_status status
struct gui_download_window * next
Next in linked list.
float average_rate
Moving average download rate.
unsigned int last_received
Value of received at last_time.
struct gui_download_window * prev
Previous in linked list.
char path[RO_DOWNLOAD_MAX_PATH_LEN]
Buffer for pathname icon.
bool error
Error occurred, aborted.
struct download_context * ctx
Associated context, or 0 if the fetch has completed or aborted.
bool saved
User has chosen the destination, and it is being written.
NSDownloadWindow * window
bits file_type
RISC OS file type.
bool send_dataload
Should send DataLoad message when finished.
wimp_message save_message
Copy of wimp DataSaveAck message.
first entry in window list
BSD style timeval macros.
Interface to time operations.
UCS conversion tables (interface) This is only used if nothing claims Service_International,...
nserror url_unescape(const char *str, size_t length, size_t *length_out, char **result_out)
Convert an escaped string to plain.
Interface to URL parsing and joining operations.
Option reading and saving interface.
#define nsoption_bool(OPTION)
Get the value of a boolean option.
UTF-8 manipulation functions (interface).
Interface to a number of general purpose functionality.
void ro_gui_force_redraw_icon(wimp_w w, wimp_i i)
Forces an icon to be redrawn entirely (ie not just updated).
bool ro_gui_wimp_sprite_exists(const char *sprite)
Check if a sprite is present in the Wimp sprite pool.
const char * ro_gui_get_icon_string(wimp_w w, wimp_i i)
Read the contents of a text or sprite icon.
General RISC OS WIMP/OS library functions (interface).
bool ro_gui_wimp_event_register_keypress(wimp_w w, bool(*callback)(wimp_key *key))
Register a function to be called for all keypresses within a particular window.
void ro_gui_wimp_event_finalise(wimp_w w)
Free any resources associated with a window.
void * ro_gui_wimp_event_get_user_data(wimp_w w)
Gets the user data associated with a window.
bool ro_gui_wimp_event_register_mouse_click(wimp_w w, bool(*callback)(wimp_pointer *pointer))
Register a function to be called for all mouse-clicks to icons in a window that don't have registered...
bool ro_gui_wimp_event_set_user_data(wimp_w w, void *user)
Sets the user data associated with a window.
bool ro_gui_wimp_event_register_close_window(wimp_w w, void(*callback)(wimp_w w))
Register a function to be called after the window has been closed.
Automated RISC OS WIMP event handling (interface).
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
static nserror text(const struct redraw_context *ctx, const struct plot_font_style *fstyle, int x, int y, const char *text, size_t length)
Text plotting.