diff --git a/c/Hotlist b/c/Hotlist index 33f17d8887a7d85e2e7b5935e03d6b8e03d7d2d3..99e0b2bce06c1a05b6ad2be71b011889849de0d9 100644 --- a/c/Hotlist +++ b/c/Hotlist @@ -47,6 +47,7 @@ #include "FetchPage.h" #include "Save.h" #include "Toolbars.h" +#include "URLUtils.h" #include "Windows.h" #include "Hotlist.h" @@ -57,6 +58,10 @@ /* Local statics */ +static int autoopen_delay = 100; /* Time in centiseconds before directory is autoopened */ + + +static int autoopen_oldtime; /* Base time for autoopen directory */ static hotlist_item * hotlist_root = NULL; /* Pointer to the hotlist root directory item */ static int hotlist_windowid; /* Object ID of the hotlist window */ @@ -79,6 +84,10 @@ static unsigned int alter_new; /* Remembers if the ed static unsigned int item_number; /* Current item being considered for drawing */ +static hotlist_item * hotlist_save_item = NULL; /* Item whose URL is being saved */ +static int hotlist_ram_transfer_sent; /* Number of bytes which have already been sent by ram transfer */ +static int hotlist_save_type = HL_SAVE_NONE; /* Variety of save currently in progress */ + /* Event handler prototypes */ static _kernel_oserror * hotlist_selection_box_start(void); @@ -107,6 +116,9 @@ static ToolboxEventHandler hotlist_reset_directory_handler; static ToolboxEventHandler hotlist_show_descriptions_handler; static ToolboxEventHandler hotlist_show_urls_handler; +static WimpMessageHandler hotlist_data_save_ack_handler; +static WimpMessageHandler hotlist_ram_fetch_handler; + /* Debug functions */ #ifdef TRACE @@ -119,7 +131,6 @@ static ToolboxEventHandler hotlist_show_urls_handler; /* Miscellaneous function prototypes */ static _kernel_oserror * hotlist_get_entry_sizes (unsigned int * item_height, unsigned int * item_dir_width, unsigned int * item_url_width); -static void hotlist_scan_for_subdirectories (hotlist_item * item); static hotlist_item * hotlist_find_item_r (hotlist_item * list, unsigned int item_no); static hotlist_item * hotlist_find_item (hotlist_item * list, unsigned int item_no); @@ -155,6 +166,10 @@ static void hotlist_drag_renderer (hotlist_item * item, u static void hotlist_start_drag (void); static _kernel_oserror * hotlist_modified (unsigned int type); +/* Save Protocol */ + +_kernel_oserror * hotlist_initiate_uri_save (hotlist_item *sourceitem); + /* List manupulation */ static void hotlist_unlink (hotlist_item * item); @@ -246,7 +261,6 @@ static int hotlist_clear_flags (hotlist_item * list, h { Printf("%s:DIRECTORY", list->name); } - if (list->flags & HOTLIST_D_HAS_SUBDIRECTORY) Printf(" (Has sub directory)"); if (list->flags & HOTLIST_D_IS_OPEN) { @@ -796,11 +810,6 @@ static void hotlist_delete_item(hotlist_item * item) free(item); free(item->name); - /* The deletions will affect whether or not other */ - /* items have subdirectories, so update the */ - /* relevant parts of all items in the list. */ - - hotlist_scan_for_subdirectories(item->parent); } break; @@ -977,52 +986,6 @@ static _kernel_oserror * hotlist_copy_item(hotlist_item * source, hotlist_item * return NULL; } -/*************************************************/ -/* hotlist_scan_for_subdirectories() */ -/* */ -/* This function will scan a directory contents */ -/* for any subdirectories. If it finds one it */ -/* will set the directory's */ -/* HOTLIST_HAS_SUBDIRECTORY bit, else it unsets */ -/* the bit. */ -/* */ -/* Parameters: Pointer to the hotlist_item */ -/* struct representing the directory */ -/* to scan. */ -/*************************************************/ - -static void hotlist_scan_for_subdirectories(hotlist_item * item) -{ - hotlist_item * list; - - /* Only proceed if we've been given an item and it */ - /* is a directory */ - - if (item && item->type == hl_directory) - { - list = item->data.directory_content; - - /* Go through the contents looking for a directory */ - /* within - as soon as one is found we can set the */ - /* bit and exit */ - - while(list) - { - if (list->type == hl_directory) - { - item->flags |= HOTLIST_D_HAS_SUBDIRECTORY; - return; - } - list = list->next; - } - - /* If the loop exits there were no directories inside */ - /* the given one, so unset the bit. */ - - item->flags &= ~HOTLIST_D_HAS_SUBDIRECTORY; - } -} - /*************************************************/ /* hotlist_find_item() */ /* */ @@ -1967,6 +1930,8 @@ static void hotlist_window_preopen(hl_opentype type) WimpGetWindowStateBlock state; int height, width; unsigned int objectstate; + ObjectId parent_id; + ComponentId parent_component; if (type == already_open) { @@ -2009,7 +1974,13 @@ static void hotlist_window_preopen(hl_opentype type) { show_error(window_get_wimp_handle(0, hotlist_windowid, &state.window_handle)); wimp_get_window_state(&state); - wimp_open_window((WimpOpenWindowBlock*)&state); + toolbox_get_parent(0, hotlist_windowid, &parent_id, &parent_component); + toolbox_show_object(0, + hotlist_windowid, + Toolbox_ShowObject_FullSpec, + &(state.visible_area), + parent_id, parent_component); +// wimp_open_window((WimpOpenWindowBlock*)&state); } } @@ -2865,6 +2836,14 @@ _kernel_oserror * hotlist_initialise(void) hotlist_show_urls_handler, NULL)); + RetError(event_register_message_handler(Wimp_MDataSaveAck, + hotlist_data_save_ack_handler, + NULL)); + + RetError(event_register_message_handler(Wimp_MRAMFetch, + hotlist_ram_fetch_handler, + NULL)); + return NULL; } @@ -3608,15 +3587,17 @@ void hotlist_start_drag(void) /* Returns: 1 if item is inside, 0 otherwise */ /*************************************************/ -static int hotlist_is_inside(hotlist_item *inside, hotlist_item *outside) -{ - while(inside) - { - if (inside == outside) return 1; - inside = inside->parent; - } - return 0; -} +/* This routine is no longer used but the code will be left incase it is needed */ + +// static int hotlist_is_inside(hotlist_item *inside, hotlist_item *outside) +// { +// while(inside) +// { +// if (inside == outside) return 1; +// inside = inside->parent; +// } +// return 0; +// } /*************************************************/ /* hotlist_drag_completed_handler() */ @@ -3639,7 +3620,7 @@ static int hotlist_drag_completed_handler(int event_code, WimpPollBlock *event, WimpGetWindowStateBlock state; int winx, winy, shift; unsigned int top, bottom, bottom2, tempint, position, xmin, xmax; - hotlist_item *targetitem, *sourceitem, *tempitem; + hotlist_item *targetitem, *sourceitem; _swix(OS_Byte, _INR(0,1) | _OUT(1), 121, 128, &shift); /* Check if SHIFT is pressed */ @@ -3725,31 +3706,6 @@ static int hotlist_drag_completed_handler(int event_code, WimpPollBlock *event, sourceitem = hotlist_find_selected_item(); - /* Check to see if moving the selection to this position is acceptable -----------------------*/ - - /* This section is not sufficient for the new selection model ///////// */ - - tempitem = sourceitem; - while(tempitem) - { - if (tempitem->flags & HOTLIST_G_IS_SELECTED && tempitem->type == hl_directory) - { - if (hotlist_is_inside(targetitem, tempitem)) - { - StrNCpy0(erb.errmess, - lookup_token("NotIntoself:A directory cannot be copied or moved into itself.", - 0, - 0)); - erb.errnum = Utils_Error_Custom_Message; - show_error_ret(&erb); - return 0; - } - } - tempitem = tempitem->next; - } - - /* Only get this far if it is ----------------------------------------------------------------*/ - sourceitem->flags &= ~HOTLIST_G_IS_SELECTED; if (!shift) @@ -3801,6 +3757,20 @@ static int hotlist_drag_completed_handler(int event_code, WimpPollBlock *event, } else { + if (hotlist_count_selected_items() == 1) + { + /* Dropped in non hotlist window - save as a URI file */ + + sourceitem = hotlist_find_selected_item(); + if (sourceitem->type == hl_url) + { + hotlist_initiate_uri_save(sourceitem); + } + } + else + { + /* Can't save URI file when saving more than one URL */ + } /* Drag was dropped in non-hotlist window */ } @@ -3809,10 +3779,18 @@ static int hotlist_drag_completed_handler(int event_code, WimpPollBlock *event, void hotlist_autoscroll(int x, int y, int window_handle) { + ObjectId object, parent; + ComponentId component; int scroll_changed; WimpGetWindowStateBlock state; + BBox extent; static unsigned int hscroll_speed, vscroll_speed; /* Separate h/v velocities */ static int last_window_handle = 0; + _kernel_oserror *e; + + object = 0; + show_error_ret(window_wimp_to_toolbox(0, window_handle, -1, &object, NULL)); + if (!object) return; state.window_handle = window_handle; @@ -3825,36 +3803,56 @@ void hotlist_autoscroll(int x, int y, int window_handle) wimp_get_window_state(&state); + window_get_extent(0, object, &extent); + /* Auto scrolling of hotlist window when dragging */ scroll_changed = 0; if ((y > state.visible_area.ymax - HOTLIST_SCROLL_BOUNDARY_SIZE) && y < state.visible_area.ymax) { - state.yscroll += vscroll_speed; - scroll_changed |= 1; + /* Don't scroll if already at bottom edge */ + if (state.yscroll < extent.ymax) + { + state.yscroll += vscroll_speed; + scroll_changed |= 1; + } } else if ((y < state.visible_area.ymin + HOTLIST_SCROLL_BOUNDARY_SIZE) && y > state.visible_area.ymin) { - state.yscroll -= vscroll_speed; - scroll_changed |= 1; + /* Don't scroll if already at top edge */ + if (state.yscroll > extent.ymin + (state.visible_area.ymax - state.visible_area.ymin)) /////// + { + state.yscroll -= vscroll_speed; + scroll_changed |= 1; + } } if ((x > state.visible_area.xmax - HOTLIST_SCROLL_BOUNDARY_SIZE) && x < state.visible_area.xmax) { - state.xscroll += hscroll_speed; - scroll_changed |= 2; + /* Don't scroll if already at right hand edge */ + if (state.xscroll < extent.xmax - (state.visible_area.xmax - state.visible_area.xmin)) /////// + { + state.xscroll += hscroll_speed; + scroll_changed |= 2; + } } else if ((x < state.visible_area.xmin + HOTLIST_SCROLL_BOUNDARY_SIZE) && x > state.visible_area.xmin) { - state.xscroll -= hscroll_speed; - scroll_changed |= 2; + /* Don't scroll if already at left hand edge */ + if (state.xscroll > extent.xmin) + { + state.xscroll -= hscroll_speed; + scroll_changed |= 2; + } } if (scroll_changed) { - wimp_open_window((WimpOpenWindowBlock*)&state); + toolbox_get_parent(0, object, &parent, &component); + toolbox_show_object(0, object, Toolbox_ShowObject_FullSpec, &(state.visible_area), parent, component); } + if (scroll_changed & 1) { vscroll_speed += HOTLIST_SCROLL_SPEED_INC; @@ -3888,6 +3886,7 @@ static int hotlist_null_handler(int event_code, WimpPollBlock *event, IdBlock *i int x, y, buttons; unsigned int itemno, xmin, xmax; unsigned int item_height, item_dir_width, item_url_width; + int new_time; hotlist_item *item; ObjectId window; ComponentId component; @@ -3928,6 +3927,20 @@ static int hotlist_null_handler(int event_code, WimpPollBlock *event, IdBlock *i hotlist_current_highlighted = item; highlighted_itemno = itemno; hotlist_redraw_items(highlighted_itemno, highlighted_itemno); + _swix(OS_ReadMonotonicTime, _OUTR(0, 0), &autoopen_oldtime); + } + else + { + _swix(OS_ReadMonotonicTime, _OUTR(0, 0), &new_time); + /* Auto open directories */ + if (autoopen_delay && + !(item->flags & HOTLIST_D_IS_OPEN) && + (new_time - autoopen_oldtime) > autoopen_delay) + { + item->flags |= HOTLIST_D_IS_OPEN; + hotlist_window_preopen(already_open); + hotlist_redraw_items(highlighted_itemno, hotlist_count_displayed_items(hotlist_root->data.directory_content)); + } } } else @@ -4271,3 +4284,166 @@ static _kernel_oserror *hotlist_modified(unsigned int type) { return NULL; } + + + +_kernel_oserror *hotlist_initiate_uri_save(hotlist_item *item) +{ + WimpGetPointerInfoBlock block; + WimpMessage message; + int new_task_handle; + + wimp_get_pointer_info(&block); + + message.hdr.size = sizeof(WimpMessage); + message.hdr.your_ref = 0; + message.hdr.action_code = Wimp_MDataSave; + + message.data.data_save.destination_window = block.window_handle; + message.data.data_save.destination_icon = block.icon_handle; + message.data.data_save.destination_x = block.x; + message.data.data_save.destination_y = block.y; + message.data.data_save.estimated_size = strlen(item->data.url)+1; + message.data.data_save.file_type = 0xf91; /* URI file - to be replaced with a defined value */ + urlutils_leafname_from_url(item->data.url, message.data.data_save.leaf_name, 212); + + wimp_send_message(Wimp_EUserMessageRecorded, + &message, + block.window_handle, + block.icon_handle, + &new_task_handle); + + hotlist_save_item = item; + hotlist_ram_transfer_sent = 0; + hotlist_save_type = HL_SAVE_URI; + + return NULL; +} + +int hotlist_data_save_ack_handler(WimpMessage *message, void *handle) +{ + FILE *fileptr; + int new_task_handle; + _kernel_oserror *e; + + switch(hotlist_save_type) + { + case HL_SAVE_URI: + if (hotlist_save_item) + { + fileptr = fopen(message->data.data_save_ack.leaf_name, "w"); + if (fileptr) + { + fprintf(fileptr, hotlist_save_item->data.url); + + if (fclose(fileptr)) + { + show_error_ret(_kernel_last_oserror()); + hotlist_save_item = NULL; + hotlist_save_type = HL_SAVE_NONE; + return 1; + } + + show_error_ret(_swix(OS_File, + _INR(0,2), + 18, + message->data.data_save_ack.leaf_name, + 0xf91)); + + message->hdr.action_code = Wimp_MDataLoad; + message->hdr.your_ref = message->hdr.my_ref; + + e = wimp_send_message(Wimp_EUserMessageRecorded, + message, + message->hdr.sender, + 0, + &new_task_handle); + + if (e) + { + show_error_ret(e); + if (remove(message->data.data_save_ack.leaf_name)) + { + show_error_ret(_kernel_last_oserror()); + } + hotlist_save_item = NULL; + hotlist_save_type = HL_SAVE_NONE; + return 1; + } + } + else + { + show_error_ret(_kernel_last_oserror()); + } + + hotlist_save_item = NULL; + hotlist_save_type = HL_SAVE_NONE; + return 1; + } + break; + default: + break; + } + + return 0; +} + + +int hotlist_ram_fetch_handler(WimpMessage *message, void *handle) +{ + int left, towrite, new_task_handle; + _kernel_oserror *e; + + if (hotlist_save_item) + { + /* Calculate the number of bytes left to send */ + /* Don't include the terminating null as it is not required for URI files*/ + left = (strlen(hotlist_save_item->data.url)) - hotlist_ram_transfer_sent; + /* Use the smaller of the buffer size and the number of bytes to write */ + towrite = message->data.ram_fetch.buffer_size > left ? left : message->data.ram_fetch.buffer_size; + + e = wimp_transfer_block(task_handle, + (char*)(hotlist_save_item->data.url) + hotlist_ram_transfer_sent, + message->hdr.sender, + message->data.ram_fetch.buffer, + towrite); + + if (e) + { + hotlist_save_item = NULL; + show_error_ret(e); + return 1; + } + + message->hdr.your_ref = message->hdr.my_ref; + message->hdr.action_code = Wimp_MRAMTransmit; + message->data.ram_transmit.nbytes = towrite; + + e = wimp_send_message(Wimp_EUserMessage, + message, + message->hdr.sender, + 0, + &new_task_handle); + + if (e) + { + hotlist_save_item = NULL; + show_error_ret(e); + return 1; + } + + /* If no bytes were transmitted this is the last part of the ram transfer */ + if (!left) + { + hotlist_save_item = NULL; + hotlist_ram_transfer_sent = 0; + return 1; + } + + /* Increase the total number of bytes send by the number just send */ + hotlist_ram_transfer_sent += towrite; + + return 1; + } + return 0; +} diff --git a/h/Hotlist b/h/Hotlist index 792a09c0d6ca5fb84ea1155804d6f90e2be13314..ba9369d2dc48a9b8ca50e6b18e03bbe69a07c3a8 100644 --- a/h/Hotlist +++ b/h/Hotlist @@ -107,9 +107,8 @@ #define HOTLIST_G_IS_SELECTED (1<<0) #define HOTLIST_G_REDRAW_NOW (1<<1) - #define HOTLIST_D_HAS_SUBDIRECTORY (1<<16) - #define HOTLIST_D_IS_OPEN (1<<17) - #define HOTLIST_D_IS_HIGHLIGHTED (1<<18) + #define HOTLIST_D_IS_OPEN (1<<16) + #define HOTLIST_D_IS_HIGHLIGHTED (1<<17) #define DIRECTORY_FLAGS HOTLIST_G_REDRAW_NOW @@ -176,6 +175,9 @@ #define HL_MODIFIED_LOAD 4 #define HL_MODIFIED_ALTER 5 + #define HL_SAVE_NONE 0 + #define HL_SAVE_URI 1 + /* Various component IDs */ #define HOTLIST_URL_MENUITEM 0x05