Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Cameron Cawley
Browse
Commits
2c969f45
Commit
2c969f45
authored
27 years ago
by
Andrew Hodgkinson
Browse files
Options
Download
Email Patches
Plain Diff
Tidied up Hotlist source a bit
parent
f2a7d4b0
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
4141 additions
and
0 deletions
+4141
-0
c/Hotlist
c/Hotlist
+3937
-0
h/Hotlist
h/Hotlist
+204
-0
No files found.
c/Hotlist
0 → 100644
View file @
2c969f45
/* Copyright 1997 Acorn Computers Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/***************************************************/
/* File : Hotlist.c */
/* */
/* Purpose: Managing a hotlist in the browser. */
/* */
/* Author : D.T.A.Brown */
/* */
/* History: 06-Aug-97: Created. */
/* 22-Aug-97: (ADH/DTAB) Integrated into */
/* main browser code. */
/***************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "swis.h"
#include "toolbox.h"
#include "wimp.h"
#include "wimplib.h"
#include "menu.h"
#include "event.h"
#include "gadgets.h"
#include "svcprint.h"
#include "Global.h"
#include "FromROSLib.h"
#include "Utils.h"
#include "FetchPage.h"
#include "Save.h"
#include "Toolbars.h"
#include "Windows.h"
#include "Hotlist.h"
/* Local definitions */
#define HotlistWrite(fn) {written = (fn); if (written < 0) return _kernel_last_oserror();}
/* Local statics */
static
hotlist_item
*
hotlist_root
=
NULL
;
/* Pointer to the hotlist root directory item */
static
int
hotlist_windowid
;
/* Object ID of the hotlist window */
static
hotlist_item
*
hotlist_newitem
;
/* When ever a new item is created this points to it */
static
int
menu_itemno
=
0
;
/* Item over which menu was pressed */
static
hotlist_item
*
selected_parent
=
NULL
;
/* The parent directory of all selected items */
static
int
number_selected
=
0
;
/* The number of items selected */
static
unsigned
int
last_selected_item
=
0xffffffff
;
/* The last item which was selected */
static
int
hotlist_dragging
=
0
;
/* Holds a set of values for different dragging cases (see Hotlist.h) */
static
unsigned
int
highlighted_itemno
;
/* During dragging, the number of a directory item using the '...+' sprite */
static
hotlist_item
*
hotlist_current_highlighted
=
NULL
;
/* To save scanning lists, pointer to the highlighted item */
static
unsigned
int
hotlist_bbar_size
=
0
;
/* Height in OS units of the button bar */
static
unsigned
int
alter_new
;
/* Remembers if the edit dialogue is Alter or New; see */
/* HOTLIST_MENUSECTION_NEW and HOTLIST_MENUSECTION_ALTER */
static
unsigned
int
item_number
;
/* Current item being considered for drawing */
/* Event handler prototypes */
static
_kernel_oserror
*
hotlist_selection_box_start
(
void
);
static
WimpEventHandler
hotlist_redraw_handler
;
static
WimpEventHandler
hotlist_mouse_click_handler
;
static
WimpEventHandler
hotlist_drag_completed_handler
;
static
WimpEventHandler
hotlist_null_handler
;
static
WimpEventHandler
hotlist_null_drag_select_handler
;
static
ToolboxEventHandler
hotlist_menuopen_handler
;
static
ToolboxEventHandler
hotlist_menuclose_handler
;
static
ToolboxEventHandler
hotlist_menu_selectall_handler
;
static
ToolboxEventHandler
hotlist_menu_clearselect_handler
;
static
ToolboxEventHandler
hotlist_menu_openall_handler
;
static
ToolboxEventHandler
hotlist_menu_closeall_handler
;
static
ToolboxEventHandler
hotlist_menu_delete_handler
;
static
ToolboxEventHandler
hotlist_show_editurl_handler
;
static
ToolboxEventHandler
hotlist_show_rendirectory_handler
;
static
ToolboxEventHandler
hotlist_show_newurl_handler
;
static
ToolboxEventHandler
hotlist_show_newdirectory_handler
;
static
ToolboxEventHandler
hotlist_newedit_url_handler
;
static
ToolboxEventHandler
hotlist_newren_directory_handler
;
static
ToolboxEventHandler
hotlist_reset_url_handler
;
static
ToolboxEventHandler
hotlist_reset_directory_handler
;
/* Debug functions */
#ifdef TRACE
static
void
hotlist_display_item
(
hotlist_item
*
item
);
static
void
hotlist_display_tree
(
hotlist_item
*
list
,
int
indent
);
#endif
/* 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
(
hotlist_item
*
list
,
unsigned
int
item_no
);
static
hotlist_item
*
hotlist_find_item
(
hotlist_item
*
list
,
unsigned
int
item_no
);
static
int
_hotlist_find_no_from_item
(
hotlist_item
*
list
,
hotlist_item
*
item
);
static
int
hotlist_find_no_from_item
(
hotlist_item
*
item
);
static
hotlist_item
*
_hotlist_find_selected_item
(
hotlist_item
*
list
);
static
hotlist_item
*
hotlist_find_selected_item
(
void
);
static
void
_hotlist_count_displayed_items
(
hotlist_item
*
list
);
static
unsigned
int
hotlist_count_displayed_items
(
hotlist_item
*
list
);
static
void
_hotlist_draw
(
hotlist_item
*
list
,
unsigned
int
first_item
,
unsigned
int
last_item
,
unsigned
int
indent
);
static
void
hotlist_draw
(
hotlist_item
*
list
,
unsigned
int
first_item
,
unsigned
int
last_item
);
static
void
_hotlist_get_max_width
(
hotlist_item
*
list
,
unsigned
int
indent
);
static
void
_hotlist_redraw_now
(
hotlist_item
*
list
);
static
void
hotlist_redraw_now
(
void
);
static
unsigned
int
hotlist_get_max_width
(
hotlist_item
*
list
);
static
void
hotlist_get_shape
(
unsigned
int
*
xmin
,
unsigned
int
*
xmax
,
hotlist_item
*
item
);
static
void
hotlist_directory_open_close
(
hotlist_item
*
item
,
unsigned
int
itemno
);
static
void
hotlist_redraw_items
(
unsigned
int
firstitem
,
unsigned
int
lastitem
);
static
void
hotlist_clear_selection
(
void
);
static
void
hotlist_launch_url
(
hotlist_item
*
item
);
static
_kernel_oserror
*
hotlist_process_click_on_item
(
unsigned
int
itemno
,
hotlist_item
*
item
,
int
buttons
,
int
x
,
int
y
);
static
_kernel_oserror
*
hotlist_process_click
(
int
x
,
int
y
,
int
buttons
);
static
void
hotlist_window_preopen
(
hl_opentype
type
);
static
void
hotlist_setmenu_details
(
ObjectId
menuid
);
static
_kernel_oserror
*
hotlist_save_entries
(
FILE
*
fileptr
,
hotlist_item
*
list
);
static
void
hotlist_lower_tags
(
char
*
string
);
static
_kernel_oserror
*
hotlist_load_directory
(
FILE
*
fileptr
,
hotlist_item
*
target
);
static
void
hotlist_drag_renderer
(
hotlist_item
*
item
,
unsigned
int
item_height
,
unsigned
int
item_dir_width
,
unsigned
int
item_url_width
);
static
void
hotlist_start_drag
(
void
);
/* List manupulation */
static
void
hotlist_unlink
(
hotlist_item
*
item
);
static
_kernel_oserror
*
hotlist_link
(
hotlist_item
*
item
,
hotlist_item
*
target
,
unsigned
int
position
);
static
_kernel_oserror
*
hotlist_new_directory
(
hotlist_item
*
parent
,
char
*
directory_name
,
unsigned
int
position
,
hotlist_item
**
new
);
static
_kernel_oserror
*
hotlist_new_url
(
hotlist_item
*
parent
,
unsigned
int
position
,
char
*
url_description
,
char
*
url
);
static
void
hotlist_delete_item
(
hotlist_item
*
item
);
static
_kernel_oserror
*
hotlist_move_item
(
hotlist_item
*
source
,
hotlist_item
*
target
,
unsigned
int
position
);
static
_kernel_oserror
*
hotlist_copy_item
(
hotlist_item
*
source
,
hotlist_item
*
target
,
unsigned
int
position
,
hotlist_item
**
new_item
);
static
int
hotlist_set_flags
(
hotlist_item
*
list
,
hotlist_type
type
,
unsigned
int
flags
);
static
int
hotlist_clear_flags
(
hotlist_item
*
list
,
hotlist_type
type
,
unsigned
int
flags
);
#ifdef TRACE
/*************************************************/
/* hotlist_display_item() */
/* */
/* This function display the data held by a */
/* single hotlist_item */
/* */
/* Parameters: Pointer to a hotlist_item */
/*************************************************/
static
void
hotlist_display_item
(
hotlist_item
*
item
)
{
Printf
(
"
\n
hotlist_display_item for %p
\n
"
,
item
);
Printf
(
"--------------------
\n
"
);
Printf
(
"type = %d
\n
"
,
item
->
type
);
Printf
(
"name = %s
\n
"
,
item
->
name
);
Printf
(
"flags = %d
\n
"
,
item
->
flags
);
Printf
(
"parent = %p
\n
"
,
item
->
parent
);
Printf
(
"previous = %p
\n
"
,
item
->
previous
);
Printf
(
"next = %p
\n
"
,
item
->
next
);
Printf
(
"data.generic_data = %p "
,
item
->
data
.
generic_data
);
switch
(
item
->
type
)
{
case
hl_url
:
{
Printf
(
"URL(%s)
\n
"
,
item
->
data
.
url
);
}
break
;
case
hl_directory
:
{
Printf
(
"sub directory pointer
\n
"
);
}
break
;
default:
{
Printf
(
"
\n
"
);
}
break
;
}
}
/*************************************************/
/* hotlist_display_tree() */
/* */
/* Recursivly display the hotlist tree starting */
/* from the passed item */
/* */
/* Parameters: Pointer to a hotlist_item */
/* value to start indent at */
/* recommended 0 */
/*************************************************/
static
void
hotlist_display_tree
(
hotlist_item
*
list
,
int
indent
)
{
int
count
;
Printf
(
"
\n
hotlist_display_tree for %p, indent %d
\n
"
,
list
,
indent
);
Printf
(
"--------------------
\n\n
"
);
while
(
list
)
{
for
(
count
=
0
;
count
<
indent
;
count
++
)
Printf
(
"| "
);
switch
(
list
->
type
)
{
case
hl_url
:
{
Printf
(
"%s:URL(%s)
\n
"
,
list
->
name
,
list
->
data
.
url
);
}
break
;
case
hl_directory
:
{
Printf
(
"%s:DIRECTORY"
,
list
->
name
);
}
if
(
list
->
flags
&
HOTLIST_D_HAS_SUBDIRECTORY
)
Printf
(
" (Has sub directory)"
);
if
(
list
->
flags
&
HOTLIST_D_IS_OPEN
)
{
Printf
(
" (Open)
\n
"
);
hotlist_display_tree
(
list
->
data
.
directory_content
,
indent
+
1
);
}
else
{
Printf
(
" (Closed)
\n
"
);
hotlist_display_tree
(
list
->
data
.
directory_content
,
indent
+
1
);
}
break
;
default:
{
Printf
(
"%s:UNRECOGNISED TYPE
\n
"
,
list
->
name
);
}
break
;
}
list
=
list
->
next
;
}
}
#endif
/*************************************************/
/* hotlist_get_entry_sizes() */
/* */
/* This function reads the size of the sprites */
/* to be used by the hotlist and from them */
/* determines the size of the hotlist entries. */
/* */
/* Parameters: Pointer to an int, in which the */
/* height of an item is placed in */
/* OS units; */
/* */
/* Pointer to an int, in which the */
/* minimum width of a directory item */
/* is returned, in OS units; */
/* */
/* Pointer to an int, in which the */
/* minimum width of a URL item is */
/* returned, in OS units. */
/* */
/* Assumes: Any of the pointers may be NULL. */
/*************************************************/
static
_kernel_oserror
*
hotlist_get_entry_sizes
(
unsigned
int
*
item_height
,
unsigned
int
*
item_dir_width
,
unsigned
int
*
item_url_width
)
{
_kernel_oserror
*
e
;
int
width
,
height
;
/* Get the open directory sprite size */
RetError
(
read_sprite_size
(
OPEN_DIRECTORY_SPRITE
,
&
width
,
&
height
));
/* Use this for the minimum width of a directory entry */
/* and the height of an item. */
if
(
item_dir_width
)
*
item_dir_width
=
width
;
if
(
item_height
)
*
item_height
=
height
;
/* Now read the closed sprite; if the size is greater */
/* than the width or height found above, use the new */
/* sizes instead. */
RetError
(
read_sprite_size
(
CLOSED_DIRECTORY_SPRITE
,
&
width
,
&
height
));
if
(
item_height
&&
height
>
*
item_height
)
*
item_height
=
height
;
if
(
item_dir_width
&&
width
>
*
item_dir_width
)
*
item_dir_width
=
width
;
/* Similarly for the insert item sprite. */
RetError
(
read_sprite_size
(
INSERT_DIRECTORY_SPRITE
,
&
width
,
&
height
));
if
(
item_height
&&
height
>
*
item_height
)
*
item_height
=
height
;
if
(
item_dir_width
&&
width
>
*
item_dir_width
)
*
item_dir_width
=
width
;
/* Find the URL sprite size, and if required increase the */
/* minimum entry height again based on this. */
RetError
(
read_sprite_size
(
URL_SPRITE
,
&
width
,
&
height
));
if
(
item_height
&&
height
>
*
item_height
)
*
item_height
=
height
;
/* Set the URL width to the value found above and add 8 to */
/* all of them for aesthetics. */
if
(
item_url_width
)
*
item_url_width
=
width
+
8
;
/* +8 for aesthetics */
if
(
item_dir_width
)
*
item_dir_width
+=
8
;
if
(
item_height
)
*
item_height
+=
8
;
return
NULL
;
}
/*************************************************/
/* hotlist_unlink() */
/* */
/* This function unlinks the passed item from */
/* the items linked in before and after it. */
/* */
/* Parameters: Pointer to the hotlist_item */
/* struct to remove. */
/*************************************************/
static
void
hotlist_unlink
(
hotlist_item
*
item
)
{
if
(
item
->
parent
&&
item
->
parent
->
data
.
directory_content
==
item
)
item
->
parent
->
data
.
directory_content
=
item
->
next
;
if
(
item
->
previous
)
item
->
previous
->
next
=
item
->
next
;
if
(
item
->
next
)
item
->
next
->
previous
=
item
->
previous
;
/* Not strictly needed, but added to ensure robustness */
item
->
next
=
NULL
;
item
->
previous
=
NULL
;
item
->
parent
=
NULL
;
}
/*************************************************/
/* hotlist_link() */
/* */
/* This function links the passed item to the */
/* passed target. */
/* */
/* It can link the item in four different ways; */
/* before or after the target, or if the target */
/* is a directory, at the beginning or end of */
/* that directory's contents. */
/* */
/* Parameters: Pointer to the hotlist_item */
/* struct to link in; */
/* */
/* Pointer to the hotlist_item */
/* struct to link to; */
/* */
/* Position to link to - */
/* HOTLIST_POSITION_BEGINNING */
/* HOTLIST_POSITION_END */
/* HOTLIST_POSITION_BEFORE or */
/* HOTLIST_POSITION_AFTER. */
/* */
/* Assumes: The item and target pointers are */
/* not NULL and are valid; */
/* */
/* That if adding to the beginning */
/* or end, the target is a directory */
/* (in both cases, an error will be */
/* raised in TRACE builds if the */
/* assumptions are violated). */
/*************************************************/
static
_kernel_oserror
*
hotlist_link
(
hotlist_item
*
item
,
hotlist_item
*
target
,
unsigned
int
position
)
{
#ifdef TRACE
/* Test certain basic assumptions are not violated */
if
(
!
item
||
!
target
)
{
erb
.
errnum
=
Utils_Error_Custom_Normal
;
strcpy
(
erb
.
errmess
,
"NULL hotlist item or target pointer in hotlist_link"
);
show_error_ret
(
&
erb
);
return
NULL
;
}
if
(
(
position
==
HOTLIST_POSITION_BEGINNING
||
position
==
HOTLIST_POSITION_END
)
&&
target
->
type
!=
hl_directory
)
{
erb
.
errnum
=
Utils_Error_Custom_Normal
;
strcpy
(
erb
.
errmess
,
"Cannot insert at item at the beginning or end when the target is not a directory, in hotlist_link"
);
show_error_ret
(
&
erb
);
return
NULL
;
}
#endif
switch
(
position
)
{
case
HOTLIST_POSITION_BEFORE
:
{
/* Simple insertion above the target item */
item
->
next
=
target
;
item
->
previous
=
target
->
previous
;
item
->
parent
=
target
->
parent
;
target
->
previous
=
item
;
if
(
item
->
previous
)
item
->
previous
->
next
=
item
;
if
(
item
->
parent
&&
item
->
parent
->
data
.
directory_content
==
target
)
item
->
parent
->
data
.
directory_content
=
item
;
}
break
;
default:
/* We'll allow a default to adding after the target item */
case
HOTLIST_POSITION_AFTER
:
{
/* Again, a simple insertion after the target item */
item
->
previous
=
target
;
item
->
next
=
target
->
next
;
item
->
parent
=
target
->
parent
;
target
->
next
=
item
;
if
(
item
->
next
)
item
->
next
->
previous
=
item
;
}
break
;
case
HOTLIST_POSITION_BEGINNING
:
{
/* A bit harder - insert at the top of a directory. */
/* First a quick sanity check - TRACE builds will */
/* already have faulted this, but For non-TRACE */
/* builds, at least this will stop things dying. */
if
(
target
->
type
!=
hl_directory
)
return
NULL
;
/* This item is going to be at the beginning of a */
/* directory, so there is never a previous item. */
item
->
previous
=
NULL
;
/* The next item is the one that used to be at the top */
/* of the directory, and the parent for this item will */
/* obviously be the target. */
item
->
next
=
target
->
data
.
directory_content
;
item
->
parent
=
target
;
/* If we have a next item, make sure its previous field */
/* now points to the new item at the top. */
if
(
item
->
next
)
item
->
next
->
previous
=
item
;
/* The target should point to the new top item, too. */
target
->
data
.
directory_content
=
item
;
}
break
;
case
HOTLIST_POSITION_END
:
{
hotlist_item
*
last
;
/* Similarly, add to the end of the directory */
if
(
target
->
type
!=
hl_directory
)
return
NULL
;
/* As before the parent must be the target item */
item
->
parent
=
target
;
/* Now look from the start of the directory downwards for */
/* the last item currently present. */
last
=
target
->
data
.
directory_content
;
while
(
last
&&
last
->
next
)
last
=
last
->
next
;
/* The new item must point to that one as in its previous field, */
/* and has no next item to point to. */
item
->
previous
=
last
;
item
->
next
=
NULL
;
if
(
last
)
{
/* If there were any items in the directory, make sure that the */
/* last one points to the new bottom entry. */
last
->
next
=
item
;
}
else
{
/* Otherwise, the parent directory should point to this item */
target
->
data
.
directory_content
=
item
;
}
}
break
;
}
/* Finished... */
return
NULL
;
}
/*************************************************/
/* hotlist_new_directory() */
/* */
/* This function creates a new directory */
/* at the beginning of the given parent. */
/* */
/* */
/* Parameters: Pointer to a hotlist_item of type */
/* directory that represents the */
/* parent item for this new entry; */
/* */
/* Name of new directory to create; */
/* */
/* Position to create the new item */
/* relative to the parent (as for */
/* hotlist_link); */
/* */
/* Pointer to a pointer to a */
/* hotlist_item struct, which will */
/* be filled in with the address of */
/* the new item (unless there is an */
/* error returned). */
/* */
/* Assumes: That the pointer to a pointer to */
/* a hotlist_item struct is not NULL */
/* (it would make little sense to */
/* allow this...). */
/*************************************************/
static
_kernel_oserror
*
hotlist_new_directory
(
hotlist_item
*
parent
,
char
*
directory_name
,
unsigned
int
position
,
hotlist_item
**
new
)
{
char
*
perm_dirname
;
hotlist_item
*
item
;
_kernel_oserror
*
e
;
if
(
!
directory_name
)
return
NULL
;
/* Allocate space for the item and its name */
item
=
malloc
(
sizeof
(
hotlist_item
));
if
(
!
item
)
{
make_no_memory_error
(
4
);
return
&
erb
;
}
perm_dirname
=
malloc
(
strlen
(
directory_name
)
+
1
);
if
(
!
perm_dirname
)
{
free
(
item
);
make_no_memory_error
(
5
);
return
NULL
;
}
/* Copy the name into the new buffer */
strcpy
(
perm_dirname
,
directory_name
);
/* Initialise the new hotlist item */
item
->
type
=
hl_directory
;
item
->
flags
=
DIRECTORY_FLAGS
;
item
->
name
=
perm_dirname
;
item
->
data
.
directory_content
=
NULL
;
if
(
parent
)
{
/* If we have been given a parent item, link this new */
/* directory to it. */
e
=
hotlist_link
(
item
,
parent
,
position
);
/* If there's an error, free the item structure and name, */
/* and return that error. */
if
(
e
)
{
free
(
item
);
free
(
perm_dirname
);
return
e
;
}
}
else
{
/* If there's no parent item, fill the various pointers */
/* to other things in the list with NULL. */
item
->
next
=
NULL
;
item
->
previous
=
NULL
;
item
->
parent
=
NULL
;
}
/* Record the new item in the hotlist_newitem static */
hotlist_newitem
=
item
;
/* Return the address of the new item and exit */
*
new
=
item
;
return
NULL
;
}
/*************************************************/
/* hotlist_new_url() */
/* */
/* This function creates a new url */
/* at the end of the passed directory */
/* */
/* Parameters: Pointer to a hotlist_item struct */
/* representing a directory to add */
/* the URL to; */
/* */
/* Position within that directory */
/* to link to (number of items from */
/* the start); */
/* */
/* Description of the URL (e.g. from */
/* the page title); */
/* */
/* Pointer to the URL itself. */
/*************************************************/
static
_kernel_oserror
*
hotlist_new_url
(
hotlist_item
*
parent
,
unsigned
int
position
,
char
*
url_description
,
char
*
url
)
{
char
*
perm_url_desc
;
char
*
perm_url
;
hotlist_item
*
item
;
_kernel_oserror
*
e
;
/* Allocate a new hotlist_item structure */
if
((
item
=
malloc
(
sizeof
(
hotlist_item
)))
==
NULL
)
{
#ifdef TRACE
if
(
tl
&
(
1
<<
25
))
Printf
(
"Error: Could not allocate room for new URL item
\n
"
);
#endif
goto
hotlist_new_url_no_memory
;
/* See bottom of function */
}
/* Allocate space for the description string */
perm_url_desc
=
malloc
(
strlen
(
url_description
)
+
1
);
if
(
perm_url_desc
==
NULL
)
goto
hotlist_new_url_no_memory
;
/* See bottom of function */
/* Allocate space for the URL */
perm_url
=
malloc
(
strlen
(
url
)
+
1
);
if
(
perm_url
==
NULL
)
{
free
(
perm_url_desc
);
goto
hotlist_new_url_no_memory
;
/* See bottom of function */
}
/* Copy the given description and URL to the allocated space */
strcpy
(
perm_url_desc
,
url_description
);
strcpy
(
perm_url
,
url
);
/* Fill in miscellaneous parts of the hotlist_item structure */
item
->
type
=
hl_url
;
item
->
flags
=
URL_FLAGS
;
item
->
name
=
perm_url_desc
;
item
->
data
.
url
=
perm_url
;
/* Link the item to the rest of the hotlist */
e
=
hotlist_link
(
item
,
parent
,
position
);
if
(
e
)
{
free
(
item
);
free
(
perm_url_desc
);
free
(
perm_url
);
return
e
;
}
/* Remember which item was added in the hotlist_newitem static */
/* and exit with no error. */
hotlist_newitem
=
item
;
return
NULL
;
/* Code for a common error case */
hotlist_new_url_no_memory:
erb
.
errnum
=
Utils_Error_Custom_Normal
;
StrNCpy0
(
erb
.
errmess
,
lookup_token
(
"NoMemURL:There is not enough free memory to add another URL to the hotlist."
,
0
,
0
));
return
&
erb
;
}
/*************************************************/
/* hotlist_delete_item() */
/* */
/* This function deletes an item from the */
/* hotlist structure; it will recursively delete */
/* directories. */
/* */
/* Parameters: Pointer to the hotlist_item */
/* struct to delete. */
/*************************************************/
static
void
hotlist_delete_item
(
hotlist_item
*
item
)
{
if
(
item
)
{
switch
(
item
->
type
)
{
/* For a URL item, unlink it from the list */
/* and free associated memory. */
case
hl_url
:
{
hotlist_unlink
(
item
);
free
(
item
->
name
);
free
(
item
->
data
.
url
);
free
(
item
);
}
break
;
case
hl_directory
:
{
/* Recursively delete all items in the directory */
while
(
item
->
data
.
directory_content
)
{
hotlist_delete_item
(
item
->
data
.
directory_content
);
}
/* Now unlink the item */
hotlist_unlink
(
item
);
/* Free associated memory */
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
;
default:
{
#ifdef TRACE
/* A 'should never happen' case! */
erb
.
errnum
=
Utils_Error_Custom_Message
;
strcpy
(
erb
.
errmess
,
"Unrecognised item type in hotlist_delete_item - possibly memory corruption?"
);
show_error_ret
(
&
erb
);
#endif
}
break
;
}
}
}
/*************************************************/
/* hotlist_move_item() */
/* */
/* This function takes an item and moves its */
/* position within the directory tree. */
/* */
/* Parameters: Pointer to the hotlist_item */
/* struct to move; */
/* */
/* Pointer to the hotlist_item */
/* structure to move to; */
/* */
/* Position relative to that struct */
/* for the item to go to, as for */
/* hotlist_link. */
/* */
/* Assumes: It is assumed that if the object */
/* is a directory it is not being */
/* moved into it self or one of its */
/* children. If this is not the case */
/* then both it and its children */
/* will become unlinked from the */
/* hotlist structure (nasty...). */
/*************************************************/
static
_kernel_oserror
*
hotlist_move_item
(
hotlist_item
*
source
,
hotlist_item
*
target
,
unsigned
int
position
)
{
/* Unlink item from directory structure */
hotlist_unlink
(
source
);
/* Link into new position in directory structure */
return
hotlist_link
(
source
,
target
,
position
);
}
/*************************************************/
/* hotlist_copy_item() */
/* */
/* This function copies an item, and in the case */
/* of it being a directory, its children, to the */
/* specified place. */
/* */
/* Parameters: Pointer to the hotlist_item */
/* struct to copy; */
/* */
/* Pointer to the hotlist_item */
/* struct to copy to; */
/* */
/* Position relative to that item to */
/* copy to, as for hotlist_link; */
/* */
/* Pointer to a pointer to a */
/* hotlist_item struct, in which the */
/* address of the new item is */
/* returned. */
/* */
/* Assumes: It is assumed that if the object */
/* is a directory it is not being */
/* copied into it self or one of its */
/* children - if it is the function */
/* will keep recursing and */
/* eventually run out of stack; */
/* */
/* The pointer to the pointer to the */
/* hotlist_item struct may be NULL. */
/*************************************************/
static
_kernel_oserror
*
hotlist_copy_item
(
hotlist_item
*
source
,
hotlist_item
*
target
,
unsigned
int
position
,
hotlist_item
**
new_item
)
{
_kernel_oserror
*
e
;
hotlist_item
*
newdir
;
newdir
=
NULL
;
switch
(
source
->
type
)
{
/* For a URL, create a new item based on the source one */
case
hl_url
:
{
return
hotlist_new_url
(
target
,
position
,
source
->
name
,
source
->
data
.
url
);
}
break
;
/* For a directory, first create a new item based on the source one */
case
hl_directory
:
{
hotlist_item
*
content
;
RetError
(
hotlist_new_directory
(
target
,
source
->
name
,
position
,
&
newdir
));
/* Now copy the contents recursively */
content
=
source
->
data
.
directory_content
;
while
(
content
)
{
RetError
(
hotlist_copy_item
(
content
,
newdir
,
HOTLIST_POSITION_END
,
NULL
));
content
=
content
->
next
;
}
}
break
;
}
/* Fill in the new_item return value */
if
(
new_item
)
{
if
(
newdir
)
*
new_item
=
newdir
;
else
*
new_item
=
hotlist_newitem
;
}
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() */
/* */
/* This function does all the work for */
/* hotlist_find_item() */
/* */
/* Parameters: Pointer to a hotlist_item */
/* the n'th item to return */
/* */
/* Returns: Pointer to the requested item or */
/* NULL if it does not exist */
/*************************************************/
static
hotlist_item
*
_hotlist_find_item
(
hotlist_item
*
list
,
unsigned
int
item_no
)
{
hotlist_item
*
temp
;
while
(
list
)
{
if
(
item_no
==
item_number
)
return
list
;
/* Found the list item */
item_number
++
;
if
(
list
->
type
==
hl_directory
&&
list
->
flags
&
HOTLIST_D_IS_OPEN
)
{
temp
=
_hotlist_find_item
(
list
->
data
.
directory_content
,
item_no
);
if
(
temp
)
return
temp
;
}
list
=
list
->
next
;
}
return
NULL
;
/* List does not extend far enough */
}
/*************************************************/
/* hotlist_find_item() */
/* */
/* This function will recursivly scan through */
/* a hotlist structure and return a pointer to */
/* the n'th item. It will only recurse through */
/* open directories. */
/* */
/* Parameters: Pointer to a hotlist_item */
/* the n'th item to return */
/* */
/* Returns: Pointer to the requested item or */
/* NULL if it does not exist */
/* */
/* Note: This function doesn't actually */
/* do any of the real work but */
/* merely sets up a global variable */
/* and calls _hotlist_find_item() */
/*************************************************/
static
hotlist_item
*
hotlist_find_item
(
hotlist_item
*
list
,
unsigned
int
item_no
)
{
item_number
=
0
;
return
_hotlist_find_item
(
list
,
item_no
);
}
/*************************************************/
/* _hotlist_find_no_from_item() */
/* */
/* This function does all the work for */
/* hotlist_find_no_from_item() */
/* */
/* Parameters: Pointer to a hotlist_item */
/* the item whose position should be */
/* returned. */
/* */
/* Returns: The item position or */
/* -1 if it does not exist */
/*************************************************/
static
int
_hotlist_find_no_from_item
(
hotlist_item
*
list
,
hotlist_item
*
item
)
{
int
temp
;
while
(
list
)
{
if
(
item
==
list
)
return
item_number
;
/* Found the list item */
item_number
++
;
if
(
list
->
type
==
hl_directory
&&
list
->
flags
&
HOTLIST_D_IS_OPEN
)
{
temp
=
_hotlist_find_no_from_item
(
list
->
data
.
directory_content
,
item
);
if
(
temp
>=
0
)
return
temp
;
}
list
=
list
->
next
;
}
return
-
1
;
}
/*************************************************/
/* hotlist_find_no_from_item() */
/* */
/* This function will recursivly scan through */
/* a hotlist structure and return the position */
/* of the specified item. It will only recurse */
/* through open directories. */
/* */
/* Parameters: Pointer to a hotlist_item */
/* Pointer to the item to find */
/* */
/* Returns: Position of the requested item or */
/* -1 if it does not exist */
/* */
/* Note: This function doesn't actually */
/* do any of the real work but */
/* merely sets up a global variable */
/* and calls */
/* _hotlist_find_no_from_item() */
/*************************************************/
static
int
hotlist_find_no_from_item
(
hotlist_item
*
item
)
{
item_number
=
0
;
return
_hotlist_find_no_from_item
(
hotlist_root
->
data
.
directory_content
,
item
);
}
/************************************************/
/* _hotlist_find_selected_item() */
/* */
/* This function does the work for */
/* hotlist_find_selected_item() */
/************************************************/
hotlist_item
*
_hotlist_find_selected_item
(
hotlist_item
*
list
)
{
hotlist_item
*
temp
;
while
(
list
)
{
if
(
list
->
flags
&
HOTLIST_G_IS_SELECTED
)
return
list
;
if
(
list
->
type
==
hl_directory
)
{
temp
=
_hotlist_find_selected_item
(
list
->
data
.
directory_content
);
if
(
temp
)
return
temp
;
}
list
=
list
->
next
;
}
return
NULL
;
}
/*************************************************/
/* hotlist_find_selected_item() */
/* */
/* This function returns a pointer to the first */
/* selected item found */
/*************************************************/
static
hotlist_item
*
hotlist_find_selected_item
(
void
)
{
return
_hotlist_find_selected_item
(
hotlist_root
);
}
/*************************************************/
/* _hotlist_count_displayed_items() */
/* */
/* This routine does all the work for */
/* hotlist_count_displayed_items() */
/*************************************************/
static
void
_hotlist_count_displayed_items
(
hotlist_item
*
list
)
{
while
(
list
)
{
if
(
list
->
type
==
hl_directory
&&
list
->
flags
&
HOTLIST_D_IS_OPEN
)
{
_hotlist_count_displayed_items
(
list
->
data
.
directory_content
);
}
list
=
list
->
next
;
item_number
++
;
}
}
/*************************************************/
/* hotlist_count_displayed_items() */
/* */
/* This routine counts the number of items to be */
/* displayed in the hotlist window */
/* */
/* Parameters: Pointer to a hotlist_item */
/* */
/* Returns: the number of items visible in */
/* the list */
/*************************************************/
static
unsigned
int
hotlist_count_displayed_items
(
hotlist_item
*
list
)
{
item_number
=
0
;
_hotlist_count_displayed_items
(
list
);
return
item_number
;
}
/*************************************************/
/* hotlist_set_flags() */
/* */
/* This function will recursivly set flags for */
/* either a specified type of hotlist_item or */
/* all hotlist_items if hl_ALL is specified */
/* all items which are changed will also have */
/* their HOTLIST_G_REDRAW_NOW bit set */
/* */
/* Parameters: Pointer to a hotlist_item */
/* type of hotlist_item to set flags */
/* for */
/* flags to set */
/* */
/* Returns: 1 if any flags were set */
/* 0 if no flags were set */
/*************************************************/
static
int
hotlist_set_flags
(
hotlist_item
*
list
,
hotlist_type
type
,
unsigned
int
flags
)
{
int
changed
;
changed
=
0
;
while
(
list
)
{
if
(
type
==
hl_ALL
||
type
==
list
->
type
)
{
if
(
list
->
flags
|
flags
!=
list
->
flags
)
{
list
->
flags
|=
HOTLIST_G_REDRAW_NOW
;
changed
=
1
;
}
list
->
flags
|=
flags
;
}
if
(
list
->
type
==
hl_directory
)
{
if
(
hotlist_set_flags
(
list
->
data
.
directory_content
,
type
,
flags
))
changed
=
1
;
}
list
=
list
->
next
;
}
return
changed
;
}
/*************************************************/
/* hotlist_clear_flags() */
/* */
/* This function will recursivly clear flags for */
/* either a specified type of hotlist_item or */
/* all hotlist_items if hl_ALL is specified */
/* all items which are changed will also have */
/* their HOTLIST_G_REDRAW_NOW bit set except if */
/* the routine is set to clear the */
/* HOTLIST_G_REDRAW_NOW bit */
/* */
/* Parameters: Pointer to a hotlist_item */
/* type of hotlist_item to clear */
/* flags for */
/* flags to clear */
/* */
/* Returns: 1 if any flags were cleared */
/* 0 if no flags were cleared */
/*************************************************/
static
int
hotlist_clear_flags
(
hotlist_item
*
list
,
hotlist_type
type
,
unsigned
int
flags
)
{
int
changed
;
changed
=
0
;
while
(
list
)
{
if
(
type
==
hl_ALL
||
type
==
list
->
type
)
{
if
(
list
->
flags
&
~
flags
!=
list
->
flags
)
{
list
->
flags
|=
HOTLIST_G_REDRAW_NOW
;
changed
=
1
;
}
list
->
flags
&=
~
flags
;
}
if
(
list
->
type
==
hl_directory
)
{
if
(
hotlist_clear_flags
(
list
->
data
.
directory_content
,
type
,
flags
))
changed
=
1
;
}
list
=
list
->
next
;
}
return
changed
;
}
/*************************************************/
/* _hotlist_draw() */
/* */
/* This function does all the hard work for */
/* hotlist_draw() */
/* */
/* Parameters: Pointer to a hotlist_item */
/* First item number to draw */
/* Last item number to draw */
/* Level of indentation */
/*************************************************/
static
void
_hotlist_draw
(
hotlist_item
*
list
,
unsigned
int
first_item
,
unsigned
int
last_item
,
unsigned
int
indent
)
{
WimpIconBlock
hotlist_iconblock
;
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
unsigned
int
temp_width
;
_kernel_swi_regs
regs
;
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
while
(
list
)
{
if
(
item_number
>
last_item
)
return
;
/* Break out if done all items to be displayed */
if
(
item_number
>=
first_item
)
{
/* draw it */
hotlist_iconblock
.
flags
=
HOTLIST_SPRITE_ICON_FLAGS
;
if
(
list
->
flags
&
HOTLIST_G_IS_SELECTED
)
hotlist_iconblock
.
flags
|=
WimpIcon_Selected
;
hotlist_iconblock
.
data
.
is
.
sprite_area
=
(
void
*
)
sprite_block
;
switch
(
list
->
type
)
/* Set appropriate sprite and width of sprite */
{
case
hl_url
:
hotlist_iconblock
.
data
.
is
.
sprite
=
URL_SPRITE
;
hotlist_iconblock
.
data
.
is
.
sprite_name_length
=
strlen
(
URL_SPRITE
);
temp_width
=
item_url_width
;
break
;
case
hl_directory
:
temp_width
=
item_dir_width
;
if
(
list
->
flags
&
HOTLIST_D_IS_HIGHLIGHTED
)
{
hotlist_iconblock
.
data
.
is
.
sprite
=
INSERT_DIRECTORY_SPRITE
;
hotlist_iconblock
.
data
.
is
.
sprite_name_length
=
strlen
(
INSERT_DIRECTORY_SPRITE
);
}
else
{
if
(
list
->
flags
&
HOTLIST_D_IS_OPEN
)
{
hotlist_iconblock
.
data
.
is
.
sprite
=
OPEN_DIRECTORY_SPRITE
;
hotlist_iconblock
.
data
.
is
.
sprite_name_length
=
strlen
(
OPEN_DIRECTORY_SPRITE
);
}
else
{
hotlist_iconblock
.
data
.
is
.
sprite
=
CLOSED_DIRECTORY_SPRITE
;
hotlist_iconblock
.
data
.
is
.
sprite_name_length
=
strlen
(
CLOSED_DIRECTORY_SPRITE
);
}
}
break
;
default:
temp_width
=
0
;
/* Only here to stop warnings */
}
hotlist_iconblock
.
bbox
.
xmin
=
indent
;
hotlist_iconblock
.
bbox
.
xmax
=
indent
+
temp_width
;
hotlist_iconblock
.
bbox
.
ymax
=
(
-
item_height
*
item_number
);
hotlist_iconblock
.
bbox
.
ymin
=
((
-
item_height
*
item_number
)
-
item_height
);
wimp_plot_icon
(
&
hotlist_iconblock
);
/* Plot sprite icon */
regs
.
r
[
0
]
=
1
;
regs
.
r
[
1
]
=
(
int
)
list
->
name
;
regs
.
r
[
2
]
=
0
;
wimp_text_op
(
&
regs
);
/* Get width of text for text icon */
if
(
list
->
flags
&
HOTLIST_G_IS_SELECTED
)
hotlist_iconblock
.
flags
=
HOTLIST_TEXT_ICON_FLAGS_SELECTED
;
else
hotlist_iconblock
.
flags
=
HOTLIST_TEXT_ICON_FLAGS_UNSELECTED
;
hotlist_iconblock
.
bbox
.
xmin
=
indent
+
temp_width
+
2
;
hotlist_iconblock
.
bbox
.
xmax
=
indent
+
temp_width
+
2
+
regs
.
r
[
0
]
+
12
;
hotlist_iconblock
.
bbox
.
ymax
=
(
-
item_height
*
item_number
)
-
2
;
hotlist_iconblock
.
bbox
.
ymin
=
(
-
item_height
*
item_number
)
-
item_height
+
2
;
hotlist_iconblock
.
data
.
it
.
buffer
=
list
->
name
;
hotlist_iconblock
.
data
.
it
.
buffer_size
=
strlen
(
list
->
name
);
wimp_plot_icon
(
&
hotlist_iconblock
);
/*! drawit */
}
item_number
++
;
if
(
list
->
type
==
hl_directory
&&
list
->
flags
&
HOTLIST_D_IS_OPEN
)
{
_hotlist_draw
(
list
->
data
.
directory_content
,
first_item
,
last_item
,
indent
+
item_dir_width
);
}
list
=
list
->
next
;
}
}
/*************************************************/
/* hotlist_draw() */
/* */
/* This function will recursivly draw the */
/* hotlist */
/* */
/* Parameters: Pointer to a hotlist_item */
/* First item number to draw */
/* Last item number to draw */
/* */
/* Note: This function doesn't actually */
/* do any of the real work but */
/* merely sets up global variables */
/* and calls _hotlist_draw() */
/*************************************************/
static
void
hotlist_draw
(
hotlist_item
*
list
,
unsigned
int
first_item
,
unsigned
int
last_item
)
{
item_number
=
0
;
_hotlist_draw
(
list
,
first_item
,
last_item
,
0
);
}
/*************************************************/
/* _hotlist_get_max_width */
/* */
/* This function does all the work for */
/* hotlist_get_max_width */
/*************************************************/
static
void
_hotlist_get_max_width
(
hotlist_item
*
list
,
unsigned
int
indent
)
{
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
unsigned
int
temp_width
;
_kernel_swi_regs
regs
;
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
while
(
list
)
{
switch
(
list
->
type
)
{
case
hl_directory
:
temp_width
=
item_dir_width
;
break
;
case
hl_url
:
temp_width
=
item_url_width
;
break
;
default:
temp_width
=
0
;
break
;
}
regs
.
r
[
0
]
=
1
;
regs
.
r
[
1
]
=
(
int
)
list
->
name
;
regs
.
r
[
2
]
=
0
;
wimp_text_op
(
&
regs
);
temp_width
+=
indent
+
2
+
regs
.
r
[
0
]
+
12
;
if
(
temp_width
>
item_number
)
item_number
=
temp_width
;
if
(
list
->
type
==
hl_directory
&&
list
->
flags
&
HOTLIST_D_IS_OPEN
)
{
_hotlist_get_max_width
(
list
->
data
.
directory_content
,
indent
+
item_dir_width
);
}
list
=
list
->
next
;
item_number
++
;
}
}
/*************************************************/
/* hotlist_get_max_width() */
/* */
/* This function returns the maximum width of */
/* of the displayed hotlist entries */
/* */
/* */
/*************************************************/
static
unsigned
int
hotlist_get_max_width
(
hotlist_item
*
list
)
{
item_number
=
0
;
_hotlist_get_max_width
(
list
,
0
);
return
item_number
;
}
/*************************************************/
/* _hotlist_redraw_now() */
/* */
/* This function does the work for */
/* hotlist_redraw_now() */
/*************************************************/
static
void
_hotlist_redraw_now
(
hotlist_item
*
list
)
{
while
(
list
)
{
if
(
list
->
flags
&
HOTLIST_G_REDRAW_NOW
)
{
hotlist_redraw_items
(
item_number
,
item_number
);
list
->
flags
&=
~
HOTLIST_G_REDRAW_NOW
;
}
item_number
++
;
if
(
list
->
type
==
hl_directory
&&
list
->
flags
&
HOTLIST_D_IS_OPEN
)
{
_hotlist_redraw_now
(
list
->
data
.
directory_content
);
}
list
=
list
->
next
;
}
}
/*************************************************/
/* hotlist_redraw_now() */
/* */
/* This function redraws all visible items with */
/* the HOTLIST_G_REDRAW_NOW bit set */
/*************************************************/
static
void
hotlist_redraw_now
(
void
)
{
item_number
=
0
;
_hotlist_redraw_now
(
hotlist_root
->
data
.
directory_content
);
}
/*************************************************/
/* hotlist_add() */
/* */
/* Add a new URL to the hotlist. */
/* */
/* Parameters: Description of the URL (e.g. from */
/* the page title); */
/* */
/* Pointer to the URL itself; */
/* */
/* 0 to add to the top, 1 to add to */
/* the bottom. */
/*************************************************/
_kernel_oserror
*
hotlist_add
(
char
*
description
,
char
*
url
,
int
at_bottom
)
{
_kernel_oserror
*
e
=
NULL
;
int
position
;
position
=
at_bottom
?
HOTLIST_POSITION_END
:
HOTLIST_POSITION_BEGINNING
;
/* Add the item and ensure the window extent etc. is correct */
e
=
hotlist_new_url
(
hotlist_root
,
position
,
description
,
url
);
if
(
!
e
)
hotlist_window_preopen
(
already_open
);
/* Optimise the redraw to do as little as possible depending */
/* upon where in the list the item was added. */
switch
(
position
)
{
default:
case
HOTLIST_POSITION_END
:
{
hotlist_redraw_now
();
}
break
;
case
HOTLIST_POSITION_BEGINNING
:
{
hotlist_redraw_items
(
0
,
hotlist_count_displayed_items
(
hotlist_root
->
data
.
directory_content
));
}
break
;
}
return
e
;
}
/*************************************************/
/* hotlist_get_shape() */
/* */
/* This function calculates the xmin and xmax */
/* of the passed hotlist_item */
/* */
/* Parameters: *xmin */
/* *xmax */
/* item */
/*************************************************/
static
void
hotlist_get_shape
(
unsigned
int
*
xmin
,
unsigned
int
*
xmax
,
hotlist_item
*
item
)
{
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
int
count
=
0
,
temp_width
;
_kernel_swi_regs
regs
;
hotlist_item
*
tempitem
;
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
tempitem
=
item
;
while
(
tempitem
)
{
tempitem
=
tempitem
->
parent
;
count
++
;
}
count
-=
2
;
regs
.
r
[
0
]
=
1
;
regs
.
r
[
1
]
=
(
int
)
item
->
name
;
regs
.
r
[
2
]
=
0
;
wimp_text_op
(
&
regs
);
switch
(
item
->
type
)
{
case
hl_directory
:
temp_width
=
item_dir_width
;
break
;
case
hl_url
:
temp_width
=
item_url_width
;
break
;
default:
temp_width
=
0
;
break
;
}
*
xmin
=
count
*
item_dir_width
;
*
xmax
=
count
*
item_dir_width
+
temp_width
+
regs
.
r
[
0
]
+
2
+
12
;
}
/*************************************************/
/* hotlist_directory_open_close() */
/* */
/* This function opens or closes a directory */
/* along with all required redrawing */
/* */
/* Parameters: hotlist_item */
/* item number on screen */
/*************************************************/
static
void
hotlist_directory_open_close
(
hotlist_item
*
item
,
unsigned
int
itemno
)
{
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
int
top
,
window_handle
;
BBox
bbox
;
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
item
->
flags
^=
HOTLIST_D_IS_OPEN
;
hotlist_window_preopen
(
already_open
);
show_error
(
window_get_wimp_handle
(
0
,
hotlist_windowid
,
&
window_handle
));
window_get_extent
(
0
,
hotlist_windowid
,
&
bbox
);
top
=
-
itemno
*
item_height
;
/* Window relative coordinate */
if
(
item
->
data
.
directory_content
)
{
show_error
(
wimp_force_redraw
(
window_handle
,
bbox
.
xmin
,
bbox
.
ymin
,
bbox
.
xmax
,
top
));
}
else
{
show_error
(
wimp_force_redraw
(
window_handle
,
bbox
.
xmin
,
top
-
item_height
,
bbox
.
xmax
,
top
));
}
}
/*************************************************/
/* hotlist_redraw_items() */
/* */
/* This function forces the redraw of a set of */
/* items */
/* */
/* Parameters: itemno */
/*************************************************/
static
void
hotlist_redraw_items
(
unsigned
int
firstitem
,
unsigned
int
lastitem
)
{
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
BBox
bbox
;
int
window_handle
;
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
show_error
(
window_get_wimp_handle
(
0
,
hotlist_windowid
,
&
window_handle
));
window_get_extent
(
0
,
hotlist_windowid
,
&
bbox
);
wimp_force_redraw
(
window_handle
,
bbox
.
xmin
,
-
(
lastitem
+
1
)
*
item_height
,
bbox
.
xmax
,
-
firstitem
*
item_height
);
}
/*************************************************/
/* hotlist_clear_selection() */
/* */
/* This function unselects all items and redraws */
/* appropriate items */
/*************************************************/
static
void
hotlist_clear_selection
(
void
)
{
hotlist_clear_flags
(
hotlist_root
->
data
.
directory_content
,
hl_ALL
,
HOTLIST_G_IS_SELECTED
);
hotlist_redraw_now
();
number_selected
=
0
;
}
/*************************************************/
/* hotlist_launch_url() */
/* */
/* This function launches the url in the passed */
/* item */
/* */
/* Parameters: hotlist_item */
/*************************************************/
static
void
hotlist_launch_url
(
hotlist_item
*
item
)
{
#ifdef TRACE
if
(
tl
&
(
1u
<<
25
))
hotlist_display_item
(
item
);
#endif
windows_create_browser
(
item
->
data
.
url
,
NULL
,
NULL
,
NULL
,
0
);
}
/*************************************************/
/* hotlist_process_click_on_item() */
/* */
/* This function handles mouse clicks on hotlist */
/* items */
/*************************************************/
static
_kernel_oserror
*
hotlist_process_click_on_item
(
unsigned
int
itemno
,
hotlist_item
*
item
,
int
buttons
,
int
x
,
int
y
)
{
switch
(
buttons
)
{
case
Wimp_MouseButtonSelect
:
if
(
last_selected_item
==
itemno
)
{
switch
(
item
->
type
)
{
case
hl_directory
:
hotlist_directory_open_close
(
item
,
itemno
);
break
;
case
hl_url
:
hotlist_launch_url
(
item
);
break
;
}
item
->
flags
&=
~
HOTLIST_G_IS_SELECTED
;
number_selected
--
;
hotlist_redraw_items
(
itemno
,
itemno
);
}
break
;
/* Double click select */
case
Wimp_MouseButtonAdjust
:
if
(
last_selected_item
==
itemno
)
{
switch
(
item
->
type
)
{
case
hl_directory
:
hotlist_directory_open_close
(
item
,
itemno
);
break
;
case
hl_url
:
hotlist_launch_url
(
item
);
toolbox_hide_object
(
0
,
hotlist_windowid
);
break
;
}
item
->
flags
&=
~
HOTLIST_G_IS_SELECTED
;
number_selected
--
;
hotlist_redraw_items
(
itemno
,
itemno
);
}
break
;
/* Double click adjust */
case
64
:
/* Drag select */
hotlist_start_drag
();
break
;
case
16
:
/* Drag adjust */
if
(
!
(
item
->
flags
&
HOTLIST_G_IS_SELECTED
))
{
item
->
flags
|=
HOTLIST_G_IS_SELECTED
;
number_selected
++
;
selected_parent
=
item
->
parent
;
last_selected_item
=
itemno
;
}
hotlist_start_drag
();
hotlist_redraw_items
(
itemno
,
itemno
);
break
;
case
1024
:
/* Click select */
if
(
item
->
flags
&
HOTLIST_G_IS_SELECTED
)
{
/* Do nothing when selected */
}
else
{
hotlist_clear_selection
();
item
->
flags
|=
HOTLIST_G_IS_SELECTED
;
selected_parent
=
item
->
parent
;
number_selected
++
;
hotlist_redraw_items
(
itemno
,
itemno
);
}
last_selected_item
=
itemno
;
break
;
case
256
:
/* Click adjust */
if
(
selected_parent
!=
item
->
parent
&&
item
->
type
!=
hl_url
)
hotlist_clear_selection
();
item
->
flags
^=
HOTLIST_G_IS_SELECTED
;
if
(
item
->
flags
&
HOTLIST_G_IS_SELECTED
)
{
number_selected
++
;
}
else
{
number_selected
--
;
}
hotlist_redraw_items
(
itemno
,
itemno
);
selected_parent
=
item
->
parent
;
last_selected_item
=
itemno
;
break
;
}
return
NULL
;
}
/*************************************************/
/* hotlist_process_click() */
/* */
/* This function handles mouse clicks on the */
/* hotlist window */
/* */
/* Parameters: x position */
/* y position */
/* button state */
/*************************************************/
static
_kernel_oserror
*
hotlist_process_click
(
int
x
,
int
y
,
int
buttons
)
{
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
hotlist_item
*
item
;
unsigned
int
xmin
,
xmax
,
itemno
;
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
itemno
=
-
y
/
item_height
;
item
=
hotlist_find_item
(
hotlist_root
->
data
.
directory_content
,
itemno
);
if
(
item
)
hotlist_get_shape
(
&
xmin
,
&
xmax
,
item
);
if
(
item
&&
x
>=
xmin
&&
x
<=
xmax
)
{
return
hotlist_process_click_on_item
(
itemno
,
item
,
buttons
,
x
,
y
);
}
else
{
switch
(
buttons
)
{
case
Wimp_MouseButtonSelect
:
break
;
/* Double click select */
case
Wimp_MouseButtonAdjust
:
break
;
/* Double click adjust */
case
64
:
/* Drag select */
hotlist_clear_selection
();
hotlist_selection_box_start
();
break
;
case
16
:
/* Drag adjust */
hotlist_clear_selection
();
hotlist_selection_box_start
();
break
;
case
1024
:
hotlist_clear_selection
();
last_selected_item
=
0xffffffff
;
break
;
/* Click select */
case
256
:
last_selected_item
=
0xffffffff
;
break
;
/* Click adjust */
}
}
return
NULL
;
}
/*************************************************/
/* hotlist_window_preopen() */
/* */
/* This function should be called before opening */
/* the hotlist window. When opentype is */
/* not_open the window is opened as large as is */
/* required to show all items. When opentype is */
/* already_open the window size will grow enough */
/* to allow all items to fit but its screen size */
/* will not change, if the window needs to */
/* it will do so but its work area will not get */
/* any smaller than the current visible area */
/* */
/* Parameters: opentype */
/* */
/*************************************************/
static
void
hotlist_window_preopen
(
hl_opentype
type
)
{
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
unsigned
int
number
,
maxlen
;
BBox
bbox
;
WimpGetWindowStateBlock
state
;
int
height
,
width
;
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
number
=
hotlist_count_displayed_items
(
hotlist_root
->
data
.
directory_content
);
maxlen
=
hotlist_get_max_width
(
hotlist_root
->
data
.
directory_content
)
+
4
;
show_error
(
window_get_wimp_handle
(
0
,
hotlist_windowid
,
&
state
.
window_handle
));
wimp_get_window_state
(
&
state
);
if
(
number
<
HOTLIST_WINDOW_MIN_HEIGHT
)
number
=
HOTLIST_WINDOW_MIN_HEIGHT
;
if
(
maxlen
<
HOTLIST_WINDOW_MIN_WIDTH
)
maxlen
=
HOTLIST_WINDOW_MIN_WIDTH
;
if
(
type
==
already_open
)
window_get_extent
(
0
,
hotlist_windowid
,
&
bbox
);
bbox
.
ymin
=
-
number
*
item_height
;
bbox
.
xmax
=
maxlen
;
if
(
type
==
already_open
)
{
width
=
state
.
visible_area
.
xmax
-
state
.
visible_area
.
xmin
;
height
=
state
.
visible_area
.
ymax
-
state
.
visible_area
.
ymin
+
hotlist_bbar_size
;
if
(
bbox
.
ymin
>
-
height
)
bbox
.
ymin
=
-
height
;
if
(
bbox
.
xmax
<
width
)
bbox
.
xmax
=
width
;
}
bbox
.
ymax
=
hotlist_bbar_size
;
bbox
.
xmin
=
0
;
window_set_extent
(
0
,
hotlist_windowid
,
&
bbox
);
if
(
type
==
already_open
)
{
show_error
(
window_get_wimp_handle
(
0
,
hotlist_windowid
,
&
state
.
window_handle
));
wimp_get_window_state
(
&
state
);
wimp_open_window
((
WimpOpenWindowBlock
*
)
&
state
);
}
}
/*************************************************/
/* hotlist_redraw_handler() */
/* */
/* This function redraws the hotlist window */
/*************************************************/
static
int
hotlist_redraw_handler
(
int
event_code
,
WimpPollBlock
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
unsigned
int
first_item
,
last_item
;
int
more
;
WimpRedrawWindowBlock
block
;
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
block
.
window_handle
=
event
->
redraw_window_request
.
window_handle
;
wimp_redraw_window
(
&
block
,
&
more
);
while
(
more
)
{
first_item
=
-
(
block
.
redraw_area
.
ymax
-
(
block
.
visible_area
.
ymax
-
block
.
yscroll
))
/
item_height
;
last_item
=
(
-
(
block
.
redraw_area
.
ymin
-
(
block
.
visible_area
.
ymax
-
block
.
yscroll
))
/
item_height
)
+
1
;
hotlist_draw
(
hotlist_root
->
data
.
directory_content
,
first_item
,
last_item
);
wimp_get_rectangle
(
&
block
,
&
more
);
}
return
0
;
}
/*************************************************/
/* hotlist_mouse_click_handler() */
/* */
/* This function handles mouse clicks in the */
/* hotlist window */
/*************************************************/
static
int
hotlist_mouse_click_handler
(
int
event_code
,
WimpPollBlock
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
WimpGetWindowStateBlock
state
;
state
.
window_handle
=
event
->
mouse_click
.
window_handle
;
wimp_get_window_state
(
&
state
);
wimp_set_caret_position
(
state
.
window_handle
,
-
1
,
0
,
0
,
-
1
,
-
1
);
hotlist_process_click
(
event
->
mouse_click
.
mouse_x
+
(
state
.
xscroll
-
state
.
visible_area
.
xmin
),
event
->
mouse_click
.
mouse_y
+
(
state
.
yscroll
-
state
.
visible_area
.
ymax
),
event
->
mouse_click
.
buttons
);
return
0
;
}
/*************************************************/
/* hotlist_menuclose_handler() */
/* */
/* This function handles closed menu events */
/*************************************************/
static
int
hotlist_menuclose_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
ObjectId
submenu_id
;
if
(
number_selected
==
-
1
)
{
hotlist_clear_selection
();
number_selected
=
0
;
}
show_error
(
menu_get_sub_menu_show
(
0
,
id_block
->
self_id
,
HOTLIST_URL_MENUITEM
,
&
submenu_id
));
if
(
submenu_id
)
show_error
(
toolbox_delete_object
(
0
,
submenu_id
));
menu_set_sub_menu_show
(
0
,
id_block
->
self_id
,
HOTLIST_URL_MENUITEM
,
0
);
return
0
;
}
void
hotlist_setmenu_details
(
ObjectId
menuid
)
{
hotlist_item
*
item
;
char
entrytext
[
32
];
ObjectId
submenu_id
;
switch
(
number_selected
)
{
case
0
:
menu_set_entry_text
(
0
,
menuid
,
HOTLIST_URL_MENUITEM
,
"URL ''"
);
menu_set_fade
(
0
,
menuid
,
HOTLIST_URL_MENUITEM
,
1
);
menu_set_fade
(
0
,
menuid
,
HOTLIST_CLEARSELECTION_MENUITEM
,
1
);
/* Fade clear selection */
break
;
case
-
1
:
case
1
:
item
=
hotlist_find_selected_item
();
/* One item selected */
switch
(
item
->
type
)
{
case
hl_directory
:
strcpy
(
entrytext
,
"Dir. '"
);
toolbox_create_object
(
0
,
"HLDirmenu"
,
&
submenu_id
);
menu_set_sub_menu_show
(
0
,
menuid
,
HOTLIST_URL_MENUITEM
,
submenu_id
);
break
;
case
hl_url
:
strcpy
(
entrytext
,
"URL '"
);
toolbox_create_object
(
0
,
"HLURLmenu"
,
&
submenu_id
);
menu_set_sub_menu_show
(
0
,
menuid
,
HOTLIST_URL_MENUITEM
,
submenu_id
);
break
;
}
strncat
(
entrytext
,
item
->
name
,
10
);
if
(
strlen
(
item
->
name
)
>
10
)
strcat
(
entrytext
,
"..."
);
strcat
(
entrytext
,
"'"
);
menu_set_entry_text
(
0
,
menuid
,
HOTLIST_URL_MENUITEM
,
entrytext
);
menu_set_fade
(
0
,
menuid
,
HOTLIST_URL_MENUITEM
,
0
);
/* unfade URL '' */
menu_set_fade
(
0
,
menuid
,
HOTLIST_CLEARSELECTION_MENUITEM
,
0
);
/* unfade clear selection */
break
;
default:
menu_set_entry_text
(
0
,
menuid
,
HOTLIST_URL_MENUITEM
,
"Selection"
);
/* Multiple items selected */
menu_set_fade
(
0
,
menuid
,
HOTLIST_URL_MENUITEM
,
0
);
/* unfade URL '' */
menu_set_fade
(
0
,
menuid
,
HOTLIST_CLEARSELECTION_MENUITEM
,
0
);
/* unfade clear selection */
toolbox_create_object
(
0
,
"HLSlctmenu"
,
&
submenu_id
);
menu_set_sub_menu_show
(
0
,
menuid
,
HOTLIST_URL_MENUITEM
,
submenu_id
);
break
;
}
}
/*************************************************/
/* hotlist_menuopen_handler() */
/* */
/* This function handles opened menu events */
/*************************************************/
static
int
hotlist_menuopen_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
WimpGetWindowStateBlock
state
;
WimpGetPointerInfoBlock
pointerblock
;
hotlist_item
*
item
;
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
unsigned
int
xmin
,
xmax
;
int
window_handle
;
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
if
(
event_code
==
HotlistMenuOpened
)
{
window_get_wimp_handle
(
0
,
hotlist_windowid
,
&
window_handle
);
state
.
window_handle
=
window_handle
;
wimp_get_window_state
(
&
state
);
wimp_get_pointer_info
(
&
pointerblock
);
pointerblock
.
x
=
pointerblock
.
x
+
(
state
.
xscroll
-
state
.
visible_area
.
xmin
);
pointerblock
.
y
=
pointerblock
.
y
+
(
state
.
yscroll
-
state
.
visible_area
.
ymax
);
menu_itemno
=
-
pointerblock
.
y
/
item_height
;
}
if
(
number_selected
==
0
)
{
item
=
hotlist_find_item
(
hotlist_root
->
data
.
directory_content
,
menu_itemno
);
if
(
item
)
{
hotlist_get_shape
(
&
xmin
,
&
xmax
,
item
);
}
if
(
item
&&
pointerblock
.
x
>=
xmin
&&
pointerblock
.
x
<=
xmax
)
{
item
->
flags
|=
HOTLIST_G_IS_SELECTED
;
selected_parent
=
item
->
parent
;
number_selected
=
-
1
;
hotlist_redraw_items
(
menu_itemno
,
menu_itemno
);
}
}
hotlist_setmenu_details
(
id_block
->
self_id
);
return
0
;
}
/*************************************************/
/* hotlist_save_entries() */
/* */
/* This function recurses through the hotlist */
/* directory structure saving all directories */
/* and entries as it goes. */
/* */
/* Parameters: Pointer to a FILE struct for the */
/* file to write to; */
/* */
/* Pointer to a hotlist_item struct */
/* representing the first item in */
/* the directory to save (which may */
/* itself be a directory). */
/* */
/* Assumes: The FILE pointer must not be NULL */
/* however the hotlist_item pointer */
/* can be (e.g. an empty directory). */
/*************************************************/
static
_kernel_oserror
*
hotlist_save_entries
(
FILE
*
fileptr
,
hotlist_item
*
list
)
{
int
written
;
_kernel_oserror
*
e
;
/* Write the entry header */
HotlistWrite
(
fprintf
(
fileptr
,
"<ul>
\n
"
));
/* Follow the directory list */
while
(
list
)
{
switch
(
list
->
type
)
{
/* Write a link for URLs */
case
hl_url
:
{
HotlistWrite
(
fprintf
(
fileptr
,
"<li><a href=
\"
%s
\"
>%s</a>
\n
"
,
list
->
data
.
url
,
list
->
name
));
}
break
;
/* Write a heading for directories */
case
hl_directory
:
{
HotlistWrite
(
fprintf
(
fileptr
,
"<h4>%s</h4>
\n
"
,
list
->
name
));
/* Recursive call for the directory contents */
RetError
(
hotlist_save_entries
(
fileptr
,
list
->
data
.
directory_content
));
}
break
;
}
/* Continue down the list */
list
=
list
->
next
;
}
/* Write the entry footer */
HotlistWrite
(
fprintf
(
fileptr
,
"</ul>
\n
"
));
return
NULL
;
}
/*************************************************/
/* hotlist_save() */
/* */
/* This function saves the hotlist as an HTML */
/* file. */
/* */
/* Parameters: Pointer to the filename to load */
/* (null terminated). */
/*************************************************/
_kernel_oserror
*
hotlist_save
(
char
*
filename
)
{
FILE
*
fileptr
;
_kernel_oserror
*
e
;
int
written
;
/* Open the file for writng */
fileptr
=
fopen
(
filename
,
"wb"
);
/* Complain if it fails */
if
(
fileptr
==
NULL
)
return
_kernel_last_oserror
();
/* Write the file header */
HotlistWrite
(
fprintf
(
fileptr
,
"<html>
\n
"
));
HotlistWrite
(
fprintf
(
fileptr
,
"<head><title>Hotlist</title></head>
\n
"
));
HotlistWrite
(
fprintf
(
fileptr
,
"<body>
\n
"
));
/* Fill in the body */
e
=
hotlist_save_entries
(
fileptr
,
hotlist_root
->
data
.
directory_content
);
if
(
e
)
{
fclose
(
fileptr
);
return
e
;
}
/* Write the footer and close the file */
HotlistWrite
(
fprintf
(
fileptr
,
"</body>
\n
"
));
HotlistWrite
(
fprintf
(
fileptr
,
"</html>
\n
"
));
fclose
(
fileptr
);
/* Set the filetype to HTML (0xfaf) */
return
_swix
(
OS_File
,
_INR
(
0
,
2
),
18
,
filename
,
FileType_HTML
);
}
/*************************************************/
/* hotlist_lower_tags() */
/* */
/* This function processes the passed string */
/* turning all characters within a tag to lower */
/* case. It will detect characters within quotes */
/* and leave their case the same; this will */
/* preserve the case of URLs. */
/* */
/* Obviously, this assumes that the HTML file */
/* being fed in is not broken; tags and quoted */
/* text must always be correctly closed, and */
/* in both cases must not span multiple lines. */
/* */
/* Parameters: Pointer to the string to process. */
/*************************************************/
static
void
hotlist_lower_tags
(
char
*
string
)
{
int
intag
=
0
,
inquotes
=
0
;
while
(
*
string
)
{
if
(
intag
)
{
if
(
inquotes
)
{
if
(
*
string
==
'"'
)
inquotes
=
0
;
}
else
{
if
(
*
string
==
'"'
)
inquotes
=
1
;
if
(
*
string
==
'>'
)
intag
--
;
*
string
=
tolower
(
*
string
);
}
}
else
{
if
(
*
string
==
'<'
)
intag
++
;
}
string
++
;
}
}
/*************************************************/
/* hotlist_load_directory() */
/* */
/* This function loads the directory contents of */
/* a hotlist HTML file previously saved by */
/* hotlist_save or a compatible source. For */
/* example, at the time of creation this can */
/* correctly load and understand hotlist files */
/* from at least one other popular browser. */
/* */
/* Parameters: Pointer to a FILE struct through */
/* which data will be read; */
/* */
/* Pointer to a hotlist_item; new */
/* data structures generated from */
/* the file contents are added to */
/* the linked list that this struct */
/* lies in. */
/*************************************************/
static
_kernel_oserror
*
hotlist_load_directory
(
FILE
*
fileptr
,
hotlist_item
*
target
)
{
_kernel_oserror
*
e
=
NULL
;
static
char
*
next_directory_name
=
NULL
;
static
char
*
string_buffer
=
NULL
;
static
char
*
str_ptr
;
char
*
url
;
hotlist_item
*
new_dir
;
unsigned
int
unfollowed_uls
=
0
;
long
int
file_position
;
int
character
,
count
;
/* Go through the file in chunks */
while
(
!
feof
(
fileptr
))
/* In theory the code below means you'll never get this; but just to be safe... */
{
file_position
=
ftell
(
fileptr
);
/* Scan ahead to find the end of line - marked by any */
/* control character, in this case; need to include */
/* as many consecutive control chars as are present */
/* in the file, in the count. */
do
{
/* First, get to either a control char or EOF */
character
=
fgetc
(
fileptr
);
}
while
(
character
>
31
&&
character
!=
EOF
);
while
(
character
<
32
&&
character
!=
EOF
)
{
/* If we're not on EOF, continue until we're no longer */
/* on a control char or hit EOF. */
character
=
fgetc
(
fileptr
);
}
/* Work out how many bytes we've read */
count
=
(
int
)
(
ftell
(
fileptr
)
-
file_position
);
/* If count is zero, we're at the end of the file */
if
(
!
count
)
break
;
/* If we're not on EOF and don't have a control char, then */
/* we overshot by one; so we would want to subtract one */
/* from count. However, to ensure string manipulation */
/* works OK, we'll need one char to null terminate the */
/* string. So in that case, we need to *add* one to count */
/* if the above condition isn't true. */
if
(
!
(
character
>
31
&&
character
!=
EOF
))
count
++
;
/* Right, after all that messing around rewind to the stored */
/* file position and allocate a buffer for this string. */
if
(
fseek
(
fileptr
,
file_position
,
SEEK_SET
))
{
e
=
_kernel_last_oserror
();
goto
hotlist_load_directory_exit
;
/* (See near end of function) */
}
/* Note that string_buffer is a static, as this way only one */
/* of these buffers ever exists, even for recursive calls. */
if
(
string_buffer
)
free
(
string_buffer
);
string_buffer
=
malloc
(
count
);
/* Complain if the allocation fails */
if
(
!
string_buffer
)
{
make_no_memory_error
(
2
);
e
=
&
erb
;
goto
hotlist_load_directory_exit
;
/* (See near end of function) */
}
/* Read the data and force a terminator at the end of the buffer, */
/* just to be safe. */
if
(
fread
(
string_buffer
,
sizeof
(
char
),
count
-
1
,
fileptr
)
!=
count
-
1
)
{
e
=
_kernel_last_oserror
();
goto
hotlist_load_directory_exit
;
/* (See near end of function) */
}
string_buffer
[
count
-
1
]
=
0
;
/* Convert tags to lower case */
hotlist_lower_tags
(
string_buffer
);
/* Treat any opening '<h...>' tag (header) as the title to a directory */
str_ptr
=
strstr
(
string_buffer
,
"<h"
);
if
(
str_ptr
&&
str_ptr
[
2
]
>=
'1'
&&
str_ptr
[
2
]
<=
'6'
&&
str_ptr
[
3
]
==
'>'
)
{
/* Read the directory name (up to the closing '</h...>') */
str_ptr
=
strtok
(
str_ptr
+
4
,
"<"
);
/* Allocate space for it */
if
(
next_directory_name
)
free
(
next_directory_name
);
next_directory_name
=
malloc
(
strlen
(
str_ptr
)
+
1
);
/* Complain if the allocation fails */
if
(
!
next_directory_name
)
{
make_no_memory_error
(
3
);
e
=
&
erb
;
goto
hotlist_load_directory_exit
;
/* (See near end of function) */
}
/* Otherwise, copy the name in */
strcpy
(
next_directory_name
,
str_ptr
);
}
/* Treat any '<a href=...>' attribute contents (link) as a URL for the hotlist */
else
if
((
str_ptr
=
strstr
(
string_buffer
,
"<a href=
\"
"
))
!=
NULL
)
/* Using '!= NULL' stops a compiler warning... */
{
/* First extract the URL */
str_ptr
+=
9
;
/* Derived from strlen("<a href=\"") */
str_ptr
=
strtok
(
str_ptr
,
"
\"
"
);
/* Because we're about to use strtok() to extract the title, it'll */
/* put a convenient terminator into the string_buffer block at the */
/* end of the URL. So all we need to do is record the current */
/* pointer in the block, str_ptr, for use when we finally add the */
/* item to the hotlist. */
url
=
str_ptr
;
/* Extract the title - between the closing '>' of the '<a href=...' */
/* and the opening '<' of the '</a>'. */
str_ptr
=
strtok
(
NULL
,
"><"
);
/* Add this item */
e
=
hotlist_new_url
(
target
,
HOTLIST_POSITION_END
,
str_ptr
,
url
);
if
(
e
)
goto
hotlist_load_directory_exit
;
/* (See near end of function) */
}
/* Treat any '<ul>' tags as the start of a new directory. The name comes */
/* from a preceeding '<h...>' tag (see above). */
else
if
((
str_ptr
=
strstr
(
string_buffer
,
"<ul>"
))
!=
NULL
)
/* New directory */
{
if
(
!
next_directory_name
)
{
/* If we don't have a directory name for this one, apparently, flag it */
/* by incrementing the unmatched '<ul>' counter. */
unfollowed_uls
++
;
}
else
{
/* Otherwise, add the directory */
e
=
hotlist_new_directory
(
target
,
next_directory_name
,
HOTLIST_POSITION_END
,
&
new_dir
);
if
(
e
)
goto
hotlist_load_directory_exit
;
free
(
next_directory_name
);
next_directory_name
=
NULL
;
/* If the directory was added, recursively load the contents */
if
(
new_dir
)
{
/* Note this will invalidate string_buffer. The contents must */
/* not be used after the call! */
e
=
hotlist_load_directory
(
fileptr
,
new_dir
);
if
(
e
)
goto
hotlist_load_directory_exit
;
/* (See near end of function) */
}
else
{
/* If the directory was not added, flag it */
unfollowed_uls
++
;
}
}
}
/* Treat any '</ul>' tags as the end of a directory. */
else
if
((
str_ptr
=
strstr
(
string_buffer
,
"</ul>"
))
!=
NULL
)
/* Close directory */
{
/* If we have unfollowed '<ul>' tags, decrement the counter; */
/* otherwise, exit quietly. */
if
(
unfollowed_uls
)
unfollowed_uls
--
;
else
goto
hotlist_load_directory_exit
;
/* (See near end of function) */
}
}
/* This section is not necessarily an error exit condition, so */
/* the code falls through to it in normal running. If 'e' is */
/* NULL there's still no error returned in the end. Note */
/* though how the various buffers are freed, and thus */
/* invalidated, at this point; so during recursive routines, */
/* they must not be accessed after the recursive call has */
/* been made (unless, of course, they are reallocated). */
hotlist_load_directory_exit:
/* Free up the temporary buffers */
if
(
string_buffer
)
{
free
(
string_buffer
);
string_buffer
=
NULL
;
}
if
(
next_directory_name
)
{
free
(
next_directory_name
);
next_directory_name
=
NULL
;
}
// We could at this point give a warning if unfollowed_uls is non-zero.
return
e
;
}
/*************************************************/
/* hotlist_load() */
/* */
/* This function loads an HTML file previously */
/* saved by hotlist_save as the new hotlist. */
/* */
/* Parameters: Pointer to the filename to load */
/* (null terminated). */
/*************************************************/
_kernel_oserror
*
hotlist_load
(
char
*
filename
)
{
_kernel_oserror
*
e
;
FILE
*
fileptr
;
/* First delete all the existing hotlist items */
while
(
hotlist_root
->
data
.
directory_content
)
{
hotlist_delete_item
(
hotlist_root
->
data
.
directory_content
);
}
/* Open the file */
fileptr
=
fopen
(
filename
,
"r"
);
if
(
fileptr
==
NULL
)
{
erb
.
errnum
=
Utils_Error_Custom_Normal
;
StrNCpy0
(
erb
.
errmess
,
lookup_token
(
"HlCantLoad:Hotlist file could not be loaded"
,
0
,
0
));
return
&
erb
;
}
/* Load it (any errors are returned right at the end) */
e
=
hotlist_load_directory
(
fileptr
,
hotlist_root
);
fclose
(
fileptr
);
/* Clear all of the various flags for redraw, */
/* selection etc. now that we have a new */
/* hotlist. */
hotlist_clear_flags
(
hotlist_root
,
hl_ALL
,
HOTLIST_G_REDRAW_NOW
);
#ifdef TRACE
/* Show the tree now the file is loaded */
if
(
tl
&
(
1u
<<
25
))
hotlist_display_tree
(
hotlist_root
,
0
);
#endif
/* Finished; redraw issues are left to the caller */
return
e
;
}
/*************************************************/
/* hotlist_initialise() */
/* */
/* This function initialises the hotlist library */
/* routines, and must be called before any other */
/* hotlist functions. */
/*************************************************/
_kernel_oserror
*
hotlist_initialise
(
void
)
{
_kernel_oserror
*
e
;
ObjectId
toolbar
;
ObjectId
menu_id
;
BBox
bbox
;
/* Create root directory item */
RetError
(
hotlist_new_directory
(
NULL
,
"Root"
,
0
,
&
hotlist_root
));
/* Create the hotlist window */
RetError
(
toolbox_create_object
(
0
,
"HotlistWind"
,
&
hotlist_windowid
));
/* Is there a toolbar? */
RetError
(
window_get_tool_bars
(
InternalTopLeft
,
hotlist_windowid
,
NULL
,
&
toolbar
,
NULL
,
NULL
));
/* If so, read the size */
if
(
toolbar
!=
0
)
{
RetError
(
window_get_extent
(
0
,
toolbar
,
&
bbox
));
hotlist_bbar_size
=
bbox
.
ymax
-
bbox
.
ymin
;
}
else
hotlist_bbar_size
=
0
;
/* Register event handlers for redraw, clicks and drags in the */
/* main hotlist window. */
RetError
(
event_register_wimp_handler
(
hotlist_windowid
,
Wimp_ERedrawWindow
,
hotlist_redraw_handler
,
NULL
));
RetError
(
event_register_wimp_handler
(
hotlist_windowid
,
Wimp_EMouseClick
,
hotlist_mouse_click_handler
,
NULL
));
RetError
(
event_register_wimp_handler
(
-
1
,
Wimp_EUserDrag
,
hotlist_drag_completed_handler
,
NULL
));
/* Menu handlers */
RetError
(
window_get_menu
(
0
,
hotlist_windowid
,
&
menu_id
));
RetError
(
event_register_toolbox_handler
(
menu_id
,
HotlistMenuOpened
,
hotlist_menuopen_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
menu_id
,
HotlistMenuClosed
,
hotlist_menuclose_handler
,
NULL
));
/* Main menu items */
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistSelectAll
,
hotlist_menu_selectall_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistClearSelect
,
hotlist_menu_clearselect_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistOpenAll
,
hotlist_menu_openall_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistCloseAll
,
hotlist_menu_closeall_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistDelete
,
hotlist_menu_delete_handler
,
NULL
));
/* Submenu warning events */
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistShowEditURL
,
hotlist_show_editurl_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistShowRenameDirectory
,
hotlist_show_rendirectory_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistShowNewURL
,
hotlist_show_newurl_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistShowNewDirectory
,
hotlist_show_newdirectory_handler
,
NULL
));
/* Hotlist related dialogue events */
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistNewEditURLOk
,
hotlist_newedit_url_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistNewRenameDirectoryOk
,
hotlist_newren_directory_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistNewEditURLCancel
,
hotlist_reset_url_handler
,
NULL
));
RetError
(
event_register_toolbox_handler
(
-
1
,
HotlistNewRenameDirectoryCancel
,
hotlist_reset_directory_handler
,
NULL
));
return
NULL
;
}
/*************************************************/
/* hotlist_open() */
/* */
/* Opens the hotlist window. */
/* */
/* Parameters: Show type (as for a call to */
/* Toolbox_ShowObject); */
/* */
/* Show block (as for a call to */
/* Toolbox_ShowObject); */
/* */
/* 0 to open showing descriptions, */
/* or 1 to open showing URLs. */
/*************************************************/
_kernel_oserror
*
hotlist_open
(
int
show_type
,
void
*
type
,
int
show_urls
)
{
// Not implemented yet...
show_urls
=
show_urls
;
/* Set the size of the window etc. */
hotlist_window_preopen
(
not_open
);
/* Show the hotlist */
return
toolbox_show_object
(
0
,
hotlist_windowid
,
show_type
,
type
,
0
,
0
);
}
/*************************************************/
/* hotlist_close() */
/* */
/* Closes the hotlist window. */
/*************************************************/
_kernel_oserror
*
hotlist_close
(
void
)
{
return
toolbox_hide_object
(
0
,
hotlist_windowid
);
}
/*************************************************/
/* hotlist_menu_selectall_handler() */
/* */
/* This function handles the select all menu */
/* item */
/*************************************************/
static
int
hotlist_menu_selectall_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
hotlist_item
*
item
;
ObjectId
sub_menu
;
if
(
!
hotlist_root
->
data
.
directory_content
)
return
0
;
item
=
hotlist_find_item
(
hotlist_root
->
data
.
directory_content
,
menu_itemno
);
if
(
item
&&
item
->
parent
)
{
item
=
item
->
parent
->
data
.
directory_content
;
number_selected
=
0
;
while
(
item
)
{
item
->
flags
|=
HOTLIST_G_IS_SELECTED
|
HOTLIST_G_REDRAW_NOW
;
number_selected
++
;
item
=
item
->
next
;
}
hotlist_redraw_now
();
menu_get_sub_menu_show
(
0
,
id_block
->
self_id
,
HOTLIST_URL_MENUITEM
,
&
sub_menu
);
menu_set_sub_menu_show
(
0
,
id_block
->
self_id
,
HOTLIST_URL_MENUITEM
,
0
);
if
(
sub_menu
)
toolbox_delete_object
(
0
,
sub_menu
);
hotlist_setmenu_details
(
id_block
->
self_id
);
}
return
0
;
}
/*************************************************/
/* hotlist_menu_clearselection_handler() */
/* */
/* This function handles the clear selection */
/* menu item */
/*************************************************/
static
int
hotlist_menu_clearselect_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
hotlist_clear_selection
();
menu_set_entry_text
(
0
,
id_block
->
self_id
,
0x05
,
"URL ''"
);
menu_set_fade
(
0
,
id_block
->
self_id
,
0x05
,
1
);
/* Fade URL'' selection */
menu_set_fade
(
0
,
id_block
->
self_id
,
0x01
,
1
);
/* Fade clear selection */
return
0
;
}
/*************************************************/
/* hotlist_menu_openall_handler() */
/* */
/* This function handles the open all menu item */
/*************************************************/
static
int
hotlist_menu_openall_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
if
(
hotlist_root
->
data
.
directory_content
)
{
menu_itemno
=
0
;
hotlist_set_flags
(
hotlist_root
->
data
.
directory_content
,
hl_directory
,
HOTLIST_D_IS_OPEN
);
hotlist_clear_flags
(
hotlist_root
->
data
.
directory_content
,
hl_directory
,
HOTLIST_G_REDRAW_NOW
);
hotlist_redraw_items
(
0
,
hotlist_count_displayed_items
(
hotlist_root
->
data
.
directory_content
));
hotlist_window_preopen
(
already_open
);
}
return
0
;
}
/*************************************************/
/* hotlist_menu_closeall_handler() */
/* */
/* This function handles the close all menu */
/* item */
/*************************************************/
static
int
hotlist_menu_closeall_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
unsigned
int
noitems
;
if
(
hotlist_root
->
data
.
directory_content
)
{
menu_itemno
=
0
;
noitems
=
hotlist_count_displayed_items
(
hotlist_root
->
data
.
directory_content
);
hotlist_clear_flags
(
hotlist_root
->
data
.
directory_content
,
hl_directory
,
HOTLIST_D_IS_OPEN
|
HOTLIST_G_REDRAW_NOW
);
hotlist_clear_selection
();
hotlist_redraw_items
(
0
,
noitems
);
menu_set_entry_text
(
0
,
id_block
->
self_id
,
HOTLIST_URL_MENUITEM
,
"URL ''"
);
menu_set_fade
(
0
,
id_block
->
self_id
,
HOTLIST_URL_MENUITEM
,
1
);
/* Fade URL'' selection */
menu_set_fade
(
0
,
id_block
->
self_id
,
HOTLIST_CLEARSELECTION_MENUITEM
,
1
);
/* Fade clear selection */
hotlist_window_preopen
(
already_open
);
}
return
0
;
}
/*************************************************/
/* hotlist_menu_delete_handler() */
/* */
/* This function handles the delete menu item */
/*************************************************/
static
int
hotlist_menu_delete_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
hotlist_item
*
item
;
unsigned
int
noitems
;
noitems
=
hotlist_count_displayed_items
(
hotlist_root
->
data
.
directory_content
);
if
(
!
number_selected
)
return
0
;
while
((
item
=
hotlist_find_selected_item
())
!=
NULL
)
{
hotlist_delete_item
(
item
);
}
number_selected
=
0
;
hotlist_redraw_items
(
0
,
noitems
);
hotlist_window_preopen
(
already_open
);
toolbox_hide_object
(
0
,
id_block
->
ancestor_id
);
return
0
;
}
/*************************************************/
/* hotlist_show_editurl_handler() */
/* */
/* This function fills in the description and */
/* url fields of the edit url dialogue box */
/*************************************************/
static
int
hotlist_show_editurl_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
hotlist_item
*
item
;
ObjectId
dboxid
;
#ifdef TRACE
Printf
(
"hotlist_show_editurl_handler
\n
"
);
#endif
item
=
hotlist_find_selected_item
();
if
(
!
item
)
return
0
;
menu_get_sub_menu_show
(
0
,
id_block
->
self_id
,
id_block
->
self_component
,
&
dboxid
);
alter_new
=
HOTLIST_MENUSECTION_ALTER
;
window_set_title
(
0
,
dboxid
,
"Edit URL"
);
writablefield_set_value
(
0
,
dboxid
,
0x01
,
item
->
name
);
writablefield_set_value
(
0
,
dboxid
,
0x05
,
item
->
data
.
url
);
actionbutton_set_text
(
0
,
dboxid
,
0x02
,
"Alter"
);
return
0
;
}
/*************************************************/
/* hotlist_show_rendirectory_handler() */
/* */
/* This function fills in the name field of the */
/* rename directory dialogue box */
/*************************************************/
static
int
hotlist_show_rendirectory_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
hotlist_item
*
item
;
ObjectId
dboxid
;
#ifdef TRACE
Printf
(
"hotlist_show_rendirectory_handler
\n
"
);
#endif
item
=
hotlist_find_selected_item
();
if
(
!
item
)
return
0
;
menu_get_sub_menu_show
(
0
,
id_block
->
self_id
,
id_block
->
self_component
,
&
dboxid
);
alter_new
=
HOTLIST_MENUSECTION_ALTER
;
window_set_title
(
0
,
dboxid
,
"Rename Directory"
);
writablefield_set_value
(
0
,
dboxid
,
0x01
,
item
->
name
);
actionbutton_set_text
(
0
,
dboxid
,
0x02
,
"Rename"
);
return
0
;
}
/*************************************************/
/* hotlist_show_newurl_handler() */
/* */
/* This function emptys the description and url */
/* fields of the new url dialogue box */
/*************************************************/
static
int
hotlist_show_newurl_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
ObjectId
dboxid
;
#ifdef TRACE
Printf
(
"hotlist_show_newurl_handler
\n
"
);
#endif
menu_get_sub_menu_show
(
0
,
id_block
->
self_id
,
id_block
->
self_component
,
&
dboxid
);
alter_new
=
HOTLIST_MENUSECTION_NEW
;
writablefield_set_value
(
0
,
dboxid
,
0x01
,
""
);
writablefield_set_value
(
0
,
dboxid
,
0x05
,
""
);
window_set_title
(
0
,
dboxid
,
"Create new URL"
);
actionbutton_set_text
(
0
,
dboxid
,
0x02
,
"Create"
);
return
0
;
}
/*************************************************/
/* hotlist_show_newdirectory_handler() */
/* */
/* This function emptys the name field of the */
/* new directory dialogue box */
/*************************************************/
static
int
hotlist_show_newdirectory_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
ObjectId
dboxid
;
#ifdef TRACE
Printf
(
"hotlist_show_newdirectory_handler
\n
"
);
#endif
menu_get_sub_menu_show
(
0
,
id_block
->
self_id
,
id_block
->
self_component
,
&
dboxid
);
alter_new
=
HOTLIST_MENUSECTION_NEW
;
writablefield_set_value
(
0
,
dboxid
,
0x01
,
""
);
window_set_title
(
0
,
dboxid
,
"Create new Directory"
);
actionbutton_set_text
(
0
,
dboxid
,
0x02
,
"Create"
);
return
0
;
}
/*************************************************/
/* hotlist_newedit_url_handler() */
/* */
/* This function either alters the selected urls */
/* name and url fields or creates a new url in */
/* the directory the pointer was in when menu */
/* was clicked in the hotlist window. */
/*************************************************/
static
int
hotlist_newedit_url_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
hotlist_item
*
item
,
*
tempitem
;
char
*
tempdesc
,
*
tempurl
;
int
size
;
item
=
hotlist_find_selected_item
();
writablefield_get_value
(
0
,
id_block
->
self_id
,
HOTLIST_NEWURL_NAME
,
NULL
,
0
,
&
size
);
tempdesc
=
malloc
(
size
);
if
(
!
tempdesc
)
return
0
;
/* ERROR can't rename */
writablefield_get_value
(
0
,
id_block
->
self_id
,
HOTLIST_NEWURL_NAME
,
tempdesc
,
size
,
&
size
);
writablefield_get_value
(
0
,
id_block
->
self_id
,
HOTLIST_NEWURL_URL
,
NULL
,
0
,
&
size
);
tempurl
=
malloc
(
size
);
if
(
!
tempurl
)
{
free
(
tempdesc
);
return
0
;
/* ERROR can't rename */
}
writablefield_get_value
(
0
,
id_block
->
self_id
,
HOTLIST_NEWURL_URL
,
tempurl
,
size
,
&
size
);
switch
(
alter_new
)
{
case
HOTLIST_MENUSECTION_NEW
:
tempitem
=
hotlist_find_item
(
hotlist_root
->
data
.
directory_content
,
menu_itemno
);
if
(
!
tempitem
)
tempitem
=
hotlist_root
;
else
{
tempitem
=
tempitem
->
parent
;
}
show_error
(
hotlist_new_url
(
tempitem
,
HOTLIST_POSITION_END
,
tempdesc
,
tempurl
));
hotlist_window_preopen
(
already_open
);
hotlist_redraw_now
();
free
(
tempdesc
);
free
(
tempurl
);
break
;
case
HOTLIST_MENUSECTION_ALTER
:
free
(
item
->
name
);
free
(
item
->
data
.
url
);
item
->
name
=
tempdesc
;
item
->
data
.
url
=
tempurl
;
item
->
flags
|=
HOTLIST_G_REDRAW_NOW
;
hotlist_window_preopen
(
already_open
);
hotlist_redraw_now
();
//toolbox_hide_object(0, id_block->ancestor_id);
break
;
}
return
0
;
}
/*************************************************/
/* hotlist_newren_directory_handler() */
/* */
/* This function either alters the selected */
/* directorys name or creates a new directory in */
/* the directory the pointer was in when menu */
/* was clicked in the hotlist window. */
/*************************************************/
static
int
hotlist_newren_directory_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
int
size
;
hotlist_item
*
item
,
*
tempitem
;
char
*
tempname
;
item
=
hotlist_find_selected_item
();
writablefield_get_value
(
0
,
id_block
->
self_id
,
HOTLIST_NEWDIRECTORY_NAME
,
NULL
,
0
,
&
size
);
tempname
=
malloc
(
size
);
if
(
!
tempname
)
return
0
;
/* ERROR can't rename */
writablefield_get_value
(
0
,
id_block
->
self_id
,
HOTLIST_NEWDIRECTORY_NAME
,
tempname
,
size
,
&
size
);
switch
(
alter_new
)
{
case
HOTLIST_MENUSECTION_NEW
:
tempitem
=
hotlist_find_item
(
hotlist_root
->
data
.
directory_content
,
menu_itemno
);
if
(
!
tempitem
)
tempitem
=
hotlist_root
;
else
tempitem
=
tempitem
->
parent
;
hotlist_new_directory
(
tempitem
,
tempname
,
HOTLIST_POSITION_END
,
&
tempitem
);
hotlist_window_preopen
(
already_open
);
hotlist_redraw_now
();
free
(
tempname
);
break
;
case
HOTLIST_MENUSECTION_ALTER
:
free
(
item
->
name
);
item
->
name
=
tempname
;
item
->
flags
|=
HOTLIST_G_REDRAW_NOW
;
hotlist_window_preopen
(
already_open
);
hotlist_redraw_now
();
//toolbox_hide_object(0, id_block->ancestor_id);
break
;
}
return
0
;
}
/*************************************************/
/* hotlist_newren_directory_handler() */
/* */
/* This function is called when Cancel is */
/* clicked on in the new or edit urldialogue */
/* box. It resets the contents to their */
/* previous state. */
/*************************************************/
static
int
hotlist_reset_url_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
hotlist_item
*
item
;
switch
(
alter_new
)
{
case
HOTLIST_MENUSECTION_NEW
:
writablefield_set_value
(
0
,
id_block
->
self_id
,
0x01
,
""
);
writablefield_set_value
(
0
,
id_block
->
self_id
,
0x05
,
""
);
break
;
case
HOTLIST_MENUSECTION_ALTER
:
item
=
hotlist_find_selected_item
();
writablefield_set_value
(
0
,
id_block
->
self_id
,
0x01
,
item
->
name
);
writablefield_set_value
(
0
,
id_block
->
self_id
,
0x05
,
item
->
data
.
url
);
break
;
}
return
0
;
}
/*************************************************/
/* hotlist_reset_directory_handler() */
/* */
/* This function is called when Cancel is */
/* clicked on in the new or rename directory */
/* dialogue box. It resets the contents to */
/* their previous state. */
/*************************************************/
static
int
hotlist_reset_directory_handler
(
int
event_code
,
ToolboxEvent
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
hotlist_item
*
item
;
switch
(
alter_new
)
{
case
HOTLIST_MENUSECTION_NEW
:
writablefield_set_value
(
0
,
id_block
->
self_id
,
0x01
,
""
);
break
;
case
HOTLIST_MENUSECTION_ALTER
:
item
=
hotlist_find_selected_item
();
writablefield_set_value
(
0
,
id_block
->
self_id
,
0x01
,
item
->
name
);
break
;
}
return
0
;
}
/*************************************************/
/* hotlist_drag_renderer() */
/* */
/* renders a single hotlist item at 0,0 for use */
/* with draganobject */
/* */
/* Parameters: pointer to the item to render */
/*************************************************/
static
void
hotlist_drag_renderer
(
hotlist_item
*
item
,
unsigned
int
item_height
,
unsigned
int
item_dir_width
,
unsigned
int
item_url_width
)
{
/* DONT PUT Printf's in here, doesn't work (on pipefs anyway) */
WimpIconBlock
hotlist_iconblock
;
int
temp_width
;
_kernel_swi_regs
regs
;
hotlist_iconblock
.
flags
=
HOTLIST_SPRITE_ICON_FLAGS
;
hotlist_iconblock
.
data
.
is
.
sprite_area
=
(
void
*
)
sprite_block
;
switch
(
item
->
type
)
/* Set appropriate sprite and width of sprite */
{
case
hl_url
:
hotlist_iconblock
.
data
.
is
.
sprite
=
URL_SPRITE
;
hotlist_iconblock
.
data
.
is
.
sprite_name_length
=
strlen
(
URL_SPRITE
);
temp_width
=
item_url_width
;
break
;
case
hl_directory
:
temp_width
=
item_dir_width
;
hotlist_iconblock
.
data
.
is
.
sprite
=
CLOSED_DIRECTORY_SPRITE
;
hotlist_iconblock
.
data
.
is
.
sprite_name_length
=
strlen
(
CLOSED_DIRECTORY_SPRITE
);
break
;
default:
temp_width
=
0
;
/* Prevent warnings */
break
;
}
hotlist_iconblock
.
bbox
.
xmin
=
2
;
hotlist_iconblock
.
bbox
.
xmax
=
2
+
temp_width
;
hotlist_iconblock
.
bbox
.
ymax
=
2
+
item_height
;
hotlist_iconblock
.
bbox
.
ymin
=
2
;
if
(
wimp_plot_icon
(
&
hotlist_iconblock
))
/* Plot sprite icon */
{
/* Error has happened, don't know what to do about it */
}
regs
.
r
[
0
]
=
1
;
regs
.
r
[
1
]
=
(
int
)
item
->
name
;
regs
.
r
[
2
]
=
0
;
if
(
wimp_text_op
(
&
regs
))
/* Get width of text for text icon */
{
/* Error has happened, don't know what to do about it */
}
hotlist_iconblock
.
flags
=
HOTLIST_TEXT_ICON_FLAGS_DRAG
;
hotlist_iconblock
.
bbox
.
xmin
=
temp_width
+
4
;
hotlist_iconblock
.
bbox
.
xmax
=
temp_width
+
regs
.
r
[
0
]
+
16
;
hotlist_iconblock
.
bbox
.
ymax
=
item_height
;
hotlist_iconblock
.
bbox
.
ymin
=
4
;
hotlist_iconblock
.
data
.
it
.
buffer
=
item
->
name
;
hotlist_iconblock
.
data
.
it
.
buffer_size
=
strlen
(
item
->
name
);
if
(
wimp_plot_icon
(
&
hotlist_iconblock
))
{
/* Error has happened, don't know what to do about it */
}
}
/*************************************************/
/* hotlist_start_drag() */
/* */
/* This function is called to start a drag */
/* operation from the hotlist window. A drag */
/* box will be initiated bounding all selected */
/* items. */
/*************************************************/
static
_kernel_oserror
*
_hotlist_start_drag
(
void
)
{
_kernel_swi_regs
regs
;
_kernel_oserror
*
err
;
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
hotlist_item
*
item
;
WimpDragBox
box
;
WimpGetPointerInfoBlock
pointerblock
;
unsigned
int
xmin
,
xmax
,
xlow
,
xhigh
;
int
top
,
bottom
,
item_no
,
xorigin
,
yorigin
,
screenwidth
,
screenheight
,
tempint
;
WimpGetWindowStateBlock
state
;
int
redraw_params
[
4
];
int
width
,
height
;
wimp_get_pointer_info
(
&
pointerblock
);
/* Read pointer position */
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
item
=
hotlist_find_selected_item
();
item_no
=
hotlist_find_no_from_item
(
item
);
top
=
-
item_no
*
item_height
;
bottom
=
-
(
item_no
+
1
)
*
item_height
;
if
(
item_no
<
0
)
return
NULL
;
/* Selected item not found, this should never happen */
hotlist_get_shape
(
&
xmin
,
&
xmax
,
item
);
item
=
item
->
next
;
if
(
number_selected
>
1
)
{
while
(
item
)
{
item_no
++
;
hotlist_get_shape
(
&
xlow
,
&
xhigh
,
item
);
if
(
item
->
flags
&
HOTLIST_G_IS_SELECTED
)
{
if
(
xlow
<
xmin
)
xmin
=
xlow
;
/* Should never happen, left hand side should not be ragged */
if
(
xhigh
>
xmax
)
xmax
=
xhigh
;
bottom
=
-
(
item_no
+
1
)
*
item_height
;
}
item
=
item
->
next
;
}
}
show_error
(
window_get_wimp_handle
(
0
,
hotlist_windowid
,
&
state
.
window_handle
));
wimp_get_window_state
(
&
state
);
xorigin
=
state
.
xscroll
-
state
.
visible_area
.
xmin
;
yorigin
=
state
.
yscroll
-
state
.
visible_area
.
ymax
;
_swix
(
OS_ReadModeVariable
,
_INR
(
0
,
1
)
|
_OUT
(
2
),
-
1
,
11
,
&
screenwidth
);
_swix
(
OS_ReadModeVariable
,
_INR
(
0
,
1
)
|
_OUT
(
2
),
-
1
,
12
,
&
screenheight
);
_swix
(
OS_ReadModeVariable
,
_INR
(
0
,
1
)
|
_OUT
(
2
),
-
1
,
4
,
&
tempint
);
screenwidth
<<=
tempint
;
_swix
(
OS_ReadModeVariable
,
_INR
(
0
,
1
)
|
_OUT
(
2
),
-
1
,
5
,
&
tempint
);
screenheight
<<=
tempint
;
if
(
_kernel_osbyte
(
161
,
28
,
0
)
&
(
1
<<
(
8
+
1
)))
/* solid drag */
{
if
(
number_selected
==
1
)
{
box
.
dragging_box
.
xmin
=
xmin
-
xorigin
;
/* box shape */
box
.
dragging_box
.
ymin
=
bottom
-
yorigin
;
box
.
dragging_box
.
xmax
=
xmax
-
xorigin
;
box
.
dragging_box
.
ymax
=
top
-
yorigin
;
redraw_params
[
0
]
=
(
int
)
hotlist_find_selected_item
();
redraw_params
[
1
]
=
(
int
)
item_height
;
redraw_params
[
2
]
=
(
int
)
item_dir_width
;
redraw_params
[
3
]
=
(
int
)
item_url_width
;
regs
.
r
[
0
]
=
(
2
<<
0
)
|
(
2
<<
2
)
|
(
1
<<
6
)
|
(
1
<<
7
)
|
(
1
<<
16
);
regs
.
r
[
1
]
=
(
int
)
hotlist_drag_renderer
;
regs
.
r
[
2
]
=
(
int
)
redraw_params
;
regs
.
r
[
3
]
=
(
int
)
&
(
box
.
dragging_box
);
if
(
!
_kernel_swi
(
DragAnObject_Start
,
&
regs
,
&
regs
))
{
hotlist_dragging
=
HOTLIST_SOLID_DRAG_OBJECT
;
/* Set global variable saying we are currently dragging */
/* so we know whether to process a user_drag_box event */
return
NULL
;
}
}
else
{
if
(
!
read_sprite_size
(
SELECTION_SPRITE
,
&
width
,
&
height
))
{
box
.
dragging_box
.
xmin
=
pointerblock
.
x
-
(
width
/
2
+
10
);
/* box shape */
box
.
dragging_box
.
ymin
=
pointerblock
.
y
-
(
height
/
2
+
10
);
box
.
dragging_box
.
xmax
=
pointerblock
.
x
+
(
width
/
2
+
10
);
box
.
dragging_box
.
ymax
=
pointerblock
.
y
+
(
height
/
2
+
10
);
regs
.
r
[
0
]
=
(
1
<<
0
)
|
(
1
<<
2
)
|
(
1
<<
6
)
|
(
1
<<
7
);
regs
.
r
[
1
]
=
(
int
)
sprite_block
;
/* browser sprite area */
regs
.
r
[
2
]
=
(
int
)
"package"
;
regs
.
r
[
3
]
=
(
int
)
&
(
box
.
dragging_box
);
if
(
!
_kernel_swi
(
DragASprite_Start
,
&
regs
,
&
regs
))
{
hotlist_dragging
=
HOTLIST_SOLID_DRAG_SPRITE
;
return
NULL
;
}
}
}
}
box
.
drag_type
=
Wimp_DragBox_DragFixedDash
;
box
.
dragging_box
.
xmin
=
xmin
-
xorigin
;
/* box shape */
box
.
dragging_box
.
xmax
=
xmax
-
xorigin
;
box
.
dragging_box
.
ymin
=
bottom
-
yorigin
;
box
.
dragging_box
.
ymax
=
top
-
yorigin
;
box
.
parent_box
.
xmin
=
-
(
pointerblock
.
x
-
box
.
dragging_box
.
xmin
);
/* Bounding box for dragged box */
box
.
parent_box
.
xmax
=
screenwidth
+
(
box
.
dragging_box
.
xmax
-
pointerblock
.
x
);
box
.
parent_box
.
ymin
=
-
(
pointerblock
.
y
-
box
.
dragging_box
.
ymin
);
box
.
parent_box
.
ymax
=
screenheight
+
(
box
.
dragging_box
.
ymax
-
pointerblock
.
y
);
err
=
wimp_drag_box
(
&
box
);
/* start drag box */
if
(
err
)
return
err
;
hotlist_dragging
=
HOTLIST_BOX_DRAG
;
/* Set global variable saying we are currently dragging */
/* so we know whether to process a user_drag_box event */
return
NULL
;
}
void
hotlist_start_drag
(
void
)
{
_kernel_oserror
*
err
;
err
=
_hotlist_start_drag
();
if
(
err
)
{
show_error_ret
(
err
);
return
;
}
/* Register NULL handler */
register_null_claimant
(
Wimp_ENull
,
hotlist_null_handler
,
NULL
);
}
/*************************************************/
/* hotlist_is_inside() */
/* */
/* Checks if one hotlist_item is held inside */
/* the directory structure of another */
/* hotlist_item */
/* */
/* Parameters: pointer to possibly inside item */
/* pointer to outside item */
/* */
/* 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
;
}
/*************************************************/
/* hotlist_drag_completed_handler() */
/* */
/* This function is called when a user_drag */
/* completes. If the drag is one started by the */
/* hotlist section it is processed. Dropping */
/* the drag in the hotlist window will move or */
/* copy the items being dragged. */
/* Dropping the drag in any other window is */
/* currently ignored */
/*************************************************/
static
int
hotlist_drag_completed_handler
(
int
event_code
,
WimpPollBlock
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
ObjectId
window_handle
;
ComponentId
comp
;
WimpGetPointerInfoBlock
pointerblock
;
WimpGetWindowStateBlock
state
;
int
winx
,
winy
,
shift
;
unsigned
int
top
,
bottom
,
bottom2
,
tempint
,
position
,
xmin
,
xmax
;
hotlist_item
*
targetitem
,
*
sourceitem
,
*
tempitem
;
_swix
(
OS_Byte
,
_INR
(
0
,
1
)
|
_OUT
(
1
),
121
,
128
,
&
shift
);
/* Check if SHIFT is pressed */
if
(
!
hotlist_dragging
)
return
0
;
switch
(
hotlist_dragging
)
{
case
HOTLIST_SOLID_DRAG_OBJECT
:
_swix
(
DragAnObject_Stop
,
0
);
break
;
case
HOTLIST_SOLID_DRAG_SPRITE
:
_swix
(
DragASprite_Stop
,
0
);
break
;
case
HOTLIST_BOX_DRAG_SELECTION
:
deregister_null_claimant
(
Wimp_ENull
,
hotlist_null_drag_select_handler
,
NULL
);
return
0
;
/* No action taken at end of drag, selection is done by null handler during drag */
break
;
default:
break
;
}
if
(
hotlist_current_highlighted
)
{
hotlist_current_highlighted
->
flags
&=
~
HOTLIST_D_IS_HIGHLIGHTED
;
hotlist_redraw_items
(
highlighted_itemno
,
highlighted_itemno
);
hotlist_current_highlighted
=
NULL
;
}
deregister_null_claimant
(
Wimp_ENull
,
hotlist_null_handler
,
NULL
);
hotlist_dragging
=
0
;
wimp_get_pointer_info
(
&
pointerblock
);
show_error
(
window_wimp_to_toolbox
(
0
,
pointerblock
.
window_handle
,
pointerblock
.
icon_handle
,
&
window_handle
,
&
comp
));
if
(
window_handle
==
hotlist_windowid
)
{
/* Drag was dropped in hotlist window */
if
(
pointerblock
.
icon_handle
!=
-
1
)
return
0
;
/* Only understand drops on workspace */
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
state
.
window_handle
=
pointerblock
.
window_handle
;
wimp_get_window_state
(
&
state
);
winx
=
pointerblock
.
x
+
(
state
.
xscroll
-
state
.
visible_area
.
xmin
);
winy
=
pointerblock
.
y
+
(
state
.
yscroll
-
state
.
visible_area
.
ymax
);
targetitem
=
hotlist_find_item
(
hotlist_root
->
data
.
directory_content
,
-
winy
/
item_height
);
top
=
-
winy
/
item_height
;
/* Decide where to put the items */
if
(
targetitem
)
{
hotlist_get_shape
(
&
xmin
,
&
xmax
,
targetitem
);
if
(
targetitem
->
type
==
hl_directory
&&
winx
>=
xmin
&&
winx
<=
xmin
+
item_dir_width
)
{
position
=
HOTLIST_POSITION_BEGINNING
;
/* Put in directory */
}
else
{
if
((
-
winy
%
item_height
)
>
item_height
/
2
)
position
=
HOTLIST_POSITION_AFTER
;
/* Put items after target item */
else
position
=
HOTLIST_POSITION_BEFORE
;
/* Put items before target item */
}
}
else
{
targetitem
=
hotlist_root
;
position
=
HOTLIST_POSITION_END
;
}
tempint
=
hotlist_find_no_from_item
(
hotlist_find_selected_item
());
if
(
tempint
<
top
)
top
=
tempint
;
bottom
=
hotlist_count_displayed_items
(
hotlist_root
->
data
.
directory_content
);
if
(
targetitem
->
flags
&
HOTLIST_G_IS_SELECTED
)
return
0
;
/* do nothing if dropped on selected items */
sourceitem
=
hotlist_find_selected_item
();
/* Check to see if moving the selection to this position is acceptable -----------------------*/
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
)
{
/* Move selected items */
hotlist_move_item
(
sourceitem
,
targetitem
,
position
);
/* Move first item to specified position */
/* before/after/in target */
targetitem
=
sourceitem
;
while
((
sourceitem
=
hotlist_find_selected_item
())
!=
NULL
)
{
sourceitem
->
flags
&=
~
HOTLIST_G_IS_SELECTED
;
hotlist_move_item
(
sourceitem
,
targetitem
,
HOTLIST_POSITION_AFTER
);
/* Move all subsequent items to follow */
/* first moved item */
targetitem
=
sourceitem
;
}
}
else
{
/* Copy selected items */
hotlist_copy_item
(
sourceitem
,
targetitem
,
position
,
&
targetitem
);
/* Copy first item to specified position */
/* before/after/in target */
while
((
sourceitem
=
hotlist_find_selected_item
())
!=
NULL
)
{
sourceitem
->
flags
&=
~
HOTLIST_G_IS_SELECTED
;
hotlist_copy_item
(
sourceitem
,
/* Copy all subsequent items to follow */
targetitem
,
/* first copied item */
HOTLIST_POSITION_AFTER
,
&
targetitem
);
}
}
number_selected
=
0
;
selected_parent
=
NULL
;
bottom2
=
hotlist_count_displayed_items
(
hotlist_root
->
data
.
directory_content
);
if
(
bottom2
>
bottom
)
bottom
=
bottom2
;
hotlist_redraw_items
(
top
,
bottom
);
hotlist_window_preopen
(
already_open
);
}
else
{
/* Drag was dropped in non-hotlist window */
}
return
0
;
}
void
hotlist_autoscroll
(
int
x
,
int
y
,
int
window_handle
)
{
int
scroll_changed
;
WimpGetWindowStateBlock
state
;
static
unsigned
int
hscroll_speed
,
vscroll_speed
;
/* Separate h/v velocities */
static
int
last_window_handle
=
0
;
state
.
window_handle
=
window_handle
;
if
(
last_window_handle
!=
window_handle
)
{
last_window_handle
=
window_handle
;
hscroll_speed
=
0
;
vscroll_speed
=
0
;
}
wimp_get_window_state
(
&
state
);
/* 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
;
}
else
if
((
y
<
state
.
visible_area
.
ymin
+
HOTLIST_SCROLL_BOUNDARY_SIZE
)
&&
y
>
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
;
}
else
if
((
x
<
state
.
visible_area
.
xmin
+
HOTLIST_SCROLL_BOUNDARY_SIZE
)
&&
x
>
state
.
visible_area
.
xmin
)
{
state
.
xscroll
-=
hscroll_speed
;
scroll_changed
|=
2
;
}
if
(
scroll_changed
)
{
wimp_open_window
((
WimpOpenWindowBlock
*
)
&
state
);
}
if
(
scroll_changed
&
1
)
{
vscroll_speed
+=
HOTLIST_SCROLL_SPEED_INC
;
if
(
vscroll_speed
>
HOTLIST_SCROLL_SPEED_MAX
)
vscroll_speed
=
HOTLIST_SCROLL_SPEED_MAX
;
}
else
{
vscroll_speed
=
HOTLIST_SCROLL_SPEED_MIN
;
}
if
(
scroll_changed
&
2
)
{
hscroll_speed
+=
HOTLIST_SCROLL_SPEED_INC
;
if
(
hscroll_speed
>
HOTLIST_SCROLL_SPEED_MAX
)
hscroll_speed
=
HOTLIST_SCROLL_SPEED_MAX
;
}
else
{
hscroll_speed
=
HOTLIST_SCROLL_SPEED_MIN
;
}
}
/*************************************************/
/* hotlist_null_handler() */
/* */
/* Called every null event while drag is in */
/* operation */
/*************************************************/
static
int
hotlist_null_handler
(
int
event_code
,
WimpPollBlock
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
int
x
,
y
,
buttons
;
unsigned
int
itemno
,
xmin
,
xmax
;
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
hotlist_item
*
item
;
ObjectId
window
;
ComponentId
component
;
WimpGetWindowStateBlock
state
;
window_get_pointer_info
(
0
,
&
x
,
&
y
,
&
buttons
,
&
window
,
&
component
);
if
(
window
==
hotlist_windowid
)
{
window_get_wimp_handle
(
0
,
window
,
&
state
.
window_handle
);
hotlist_autoscroll
(
x
,
y
,
state
.
window_handle
);
/* Display arrow pointing into directory to say that dropping */
/* here will put in directory rather than next to it */
wimp_get_window_state
(
&
state
);
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
x
+=
(
state
.
xscroll
-
state
.
visible_area
.
xmin
);
y
+=
(
state
.
yscroll
-
state
.
visible_area
.
ymax
);
itemno
=
-
y
/
item_height
;
item
=
hotlist_find_item
(
hotlist_root
->
data
.
directory_content
,
itemno
);
if
(
item
&&
item
->
type
==
hl_directory
&&
!
(
item
->
flags
&
HOTLIST_G_IS_SELECTED
))
{
hotlist_get_shape
(
&
xmin
,
&
xmax
,
item
);
if
(
x
>=
xmin
&&
x
<=
xmin
+
item_dir_width
)
{
if
(
hotlist_current_highlighted
!=
item
)
{
if
(
hotlist_current_highlighted
)
{
hotlist_current_highlighted
->
flags
&=
~
HOTLIST_D_IS_HIGHLIGHTED
;
hotlist_redraw_items
(
highlighted_itemno
,
highlighted_itemno
);
}
item
->
flags
|=
HOTLIST_D_IS_HIGHLIGHTED
;
hotlist_current_highlighted
=
item
;
highlighted_itemno
=
itemno
;
hotlist_redraw_items
(
highlighted_itemno
,
highlighted_itemno
);
}
}
else
{
if
(
hotlist_current_highlighted
)
{
hotlist_current_highlighted
->
flags
&=
~
HOTLIST_D_IS_HIGHLIGHTED
;
hotlist_redraw_items
(
highlighted_itemno
,
highlighted_itemno
);
hotlist_current_highlighted
=
NULL
;
}
}
}
else
{
if
(
hotlist_current_highlighted
)
{
hotlist_current_highlighted
->
flags
&=
~
HOTLIST_D_IS_HIGHLIGHTED
;
hotlist_redraw_items
(
highlighted_itemno
,
highlighted_itemno
);
hotlist_current_highlighted
=
NULL
;
}
}
}
else
{
/* non hotlist window */
if
(
hotlist_current_highlighted
)
{
hotlist_current_highlighted
->
flags
&=
~
HOTLIST_D_IS_HIGHLIGHTED
;
hotlist_redraw_items
(
highlighted_itemno
,
highlighted_itemno
);
hotlist_current_highlighted
=
NULL
;
}
}
return
0
;
}
/* Simple non-scrolling selection box, to be improved later */
int
selection_x
,
selection_y
;
/* Workarea relative corner of selection box */
_kernel_oserror
*
hotlist_selection_box_start
(
void
)
{
_kernel_oserror
*
err
;
WimpDragBox
box
;
WimpGetPointerInfoBlock
pointerblock
;
WimpGetWindowStateBlock
state
;
wimp_get_pointer_info
(
&
pointerblock
);
/* Read pointer position */
show_error
(
window_get_wimp_handle
(
0
,
hotlist_windowid
,
&
state
.
window_handle
));
wimp_get_window_state
(
&
state
);
selection_x
=
pointerblock
.
x
+
(
state
.
xscroll
-
state
.
visible_area
.
xmin
);
selection_y
=
pointerblock
.
y
+
(
state
.
yscroll
-
state
.
visible_area
.
ymax
);
box
.
drag_type
=
Wimp_DragBox_DragRubberDash
;
box
.
dragging_box
.
xmin
=
pointerblock
.
x
;
/* box shape */
box
.
dragging_box
.
xmax
=
pointerblock
.
x
;
box
.
dragging_box
.
ymin
=
pointerblock
.
y
;
box
.
dragging_box
.
ymax
=
pointerblock
.
y
;
box
.
parent_box
.
xmin
=
state
.
visible_area
.
xmin
;
/* Bounding box for dragged box */
box
.
parent_box
.
xmax
=
state
.
visible_area
.
xmax
;
box
.
parent_box
.
ymin
=
state
.
visible_area
.
ymin
;
box
.
parent_box
.
ymax
=
state
.
visible_area
.
ymax
;
err
=
wimp_drag_box
(
&
box
);
/* start drag box */
if
(
err
)
return
err
;
hotlist_dragging
=
HOTLIST_BOX_DRAG_SELECTION
;
/* Set global variable saying we are currently dragging */
/* so we know whether to process a user_drag_box event */
register_null_claimant
(
Wimp_ENull
,
hotlist_null_drag_select_handler
,
NULL
);
return
NULL
;
}
int
hotlist_null_drag_select_handler
(
int
event_code
,
WimpPollBlock
*
event
,
IdBlock
*
id_block
,
void
*
handle
)
{
WimpGetPointerInfoBlock
pointerblock
;
unsigned
int
item_height
,
item_dir_width
,
item_url_width
;
int
workx
,
worky
;
hotlist_item
*
item
;
WimpGetWindowStateBlock
state
;
unsigned
int
item_min
,
item_max
,
itemno
,
itemxmin
,
itemxmax
;
int
minx
,
maxx
;
int
last_item
;
wimp_get_pointer_info
(
&
pointerblock
);
/* Read pointer position */
show_error
(
window_get_wimp_handle
(
0
,
hotlist_windowid
,
&
state
.
window_handle
));
wimp_get_window_state
(
&
state
);
hotlist_get_entry_sizes
(
&
item_height
,
&
item_dir_width
,
&
item_url_width
);
workx
=
pointerblock
.
x
+
(
state
.
xscroll
-
state
.
visible_area
.
xmin
);
worky
=
pointerblock
.
y
+
(
state
.
yscroll
-
state
.
visible_area
.
ymax
);
item_min
=
-
worky
/
item_height
;
if
(
-
selection_y
/
item_height
<
item_min
)
item_min
=
-
selection_y
/
item_height
;
item_max
=
(
-
worky
/
item_height
);
if
((
-
selection_y
/
item_height
)
>
item_max
)
item_max
=
(
-
selection_y
/
item_height
);
if
(
selection_x
<
workx
)
{
minx
=
selection_x
;
maxx
=
workx
;
}
else
{
minx
=
workx
;
maxx
=
selection_x
;
}
/* Change from here onwards */
last_item
=
hotlist_count_displayed_items
(
hotlist_root
->
data
.
directory_content
);
for
(
itemno
=
0
;
itemno
<=
last_item
;
itemno
++
)
{
item
=
hotlist_find_item
(
hotlist_root
->
data
.
directory_content
,
itemno
);
if
(
item
)
{
if
(
itemno
>=
item_min
&&
itemno
<=
item_max
)
{
hotlist_get_shape
(
&
itemxmin
,
&
itemxmax
,
item
);
if
(
number_selected
==
0
)
{
if
(
!
(
maxx
<
itemxmin
||
minx
>
itemxmax
)
&&
(
!
(
item
->
flags
&
HOTLIST_G_IS_SELECTED
)))
{
item
->
flags
|=
HOTLIST_G_IS_SELECTED
;
hotlist_redraw_items
(
itemno
,
itemno
);
selected_parent
=
item
->
parent
;
number_selected
++
;
}
}
else
{
if
(
!
(
maxx
<
itemxmin
||
minx
>
itemxmax
))
{
if
((
selected_parent
==
item
->
parent
||
item
->
type
==
hl_url
)
&&
(
!
(
item
->
flags
&
HOTLIST_G_IS_SELECTED
)))
{
item
->
flags
|=
HOTLIST_G_IS_SELECTED
;
hotlist_redraw_items
(
itemno
,
itemno
);
number_selected
++
;
}
}
else
{
if
(
item
->
flags
&
HOTLIST_G_IS_SELECTED
)
{
item
->
flags
&=
~
HOTLIST_G_IS_SELECTED
;
hotlist_redraw_items
(
itemno
,
itemno
);
number_selected
--
;
}
}
}
}
else
{
if
(
item
->
flags
&
HOTLIST_G_IS_SELECTED
)
{
item
->
flags
&=
~
HOTLIST_G_IS_SELECTED
;
hotlist_redraw_items
(
itemno
,
itemno
);
number_selected
--
;
}
}
}
}
return
0
;
}
This diff is collapsed.
Click to expand it.
h/Hotlist
0 → 100644
View file @
2c969f45
/* Copyright 1997 Acorn Computers Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/***************************************************/
/* File : Hotlist.h */
/* */
/* Purpose: Managing a hotlist in the browser. */
/* */
/* Author : D.T.A.Brown */
/* */
/* History: 06-Aug-97: Created. */
/* 22-Aug-97: (ADH/DTAB) Integrated into */
/* main browser code. */
/* 25-Aug-97: (ADH) Definitions imported */
/* from TBEvents.h. */
/***************************************************/
#ifndef REMOTE_HOTLIST
/* Dialogue definitions (event codes) */
#define HotlistShowEditURL 0x300b
#define HotlistShowRenameDirectory 0x300c
#define HotlistShowNewURL 0x300d
#define HotlistShowNewDirectory 0x300e
#define HotlistNewEditURLOk 0x300f
#define HotlistNewRenameDirectoryOk 0x3010
#define HotlistNewEditURLCancel 0x3011
#define HotlistNewRenameDirectoryCancel 0x3012
/* Menu definitions (event codes) */
#define ShowHotlist 0x3000
#define AddThisPage 0x3001
#define RemoveThisPage 0x3002
#define SaveHotlist 0x3003
#define HotlistMenuOpened 0x3004
#define HotlistMenuClosed 0x3005
#define HotlistSelectAll 0x3006
#define HotlistClearSelect 0x3007
#define HotlistOpenAll 0x3008
#define HotlistCloseAll 0x3009
#define HotlistDelete 0x300a
/* Enumerations */
typedef
enum
hotlist_type
{
hl_directory
,
hl_url
,
/* Special case to allow range checking - must be the last item */
hl_ALL
}
hotlist_type
;
typedef
enum
hl_opentype
{
not_open
,
already_open
}
hl_opentype
;
/* Structures */
typedef
struct
hotlist_item
{
hotlist_type
type
;
/* Item type */
unsigned
int
flags
;
char
*
name
;
/* Leaf name (NULL terminated string) */
union
{
char
*
url
;
/* Pointer to url (NULL terminated string) */
struct
hotlist_item
*
directory_content
;
/* Pointer to directory contents */
void
*
generic_data
;
/* generic type */
}
data
;
struct
hotlist_item
*
parent
;
/* Points to parent directory or NULL if none */
struct
hotlist_item
*
previous
;
/* Points to previous hotlist_item or NULL if none */
struct
hotlist_item
*
next
;
/* Points to next hotlist_item or NULL if no more */
}
hotlist_item
;
/* Miscellaneous definitions */
#define HOTLIST_MAX_TYPE hl_url
#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 DIRECTORY_FLAGS HOTLIST_G_REDRAW_NOW
#define URL_FLAGS HOTLIST_G_REDRAW_NOW
#define HOTLIST_SPRITE_ICON_FLAGS (WimpIcon_Sprite | \
WimpIcon_HCentred | \
WimpIcon_VCentred | \
WimpIcon_Indirected | \
WimpIcon_FGColour * 7 | \
WimpIcon_BGColour * 0)
#define HOTLIST_TEXT_ICON_FLAGS_SELECTED (WimpIcon_Text | \
WimpIcon_Filled | \
WimpIcon_VCentred | \
WimpIcon_Indirected | \
WimpIcon_FGColour * 1 | \
WimpIcon_BGColour * 7)
#define HOTLIST_TEXT_ICON_FLAGS_UNSELECTED (WimpIcon_Text | \
WimpIcon_VCentred | \
WimpIcon_Indirected | \
WimpIcon_FGColour * 7 | \
WimpIcon_BGColour * 0)
#define HOTLIST_TEXT_ICON_FLAGS_DRAG (WimpIcon_Text | \
WimpIcon_Filled | \
WimpIcon_VCentred | \
WimpIcon_Indirected | \
WimpIcon_FGColour * 7 | \
WimpIcon_BGColour * 1)
#define HOTLIST_POSITION_BEFORE 0
/* before item */
#define HOTLIST_POSITION_AFTER 1
/* after item */
#define HOTLIST_POSITION_BEGINNING 2
/* beginning of directory */
#define HOTLIST_POSITION_END 3
/* end of directory */
#define HOTLIST_BOX_DRAG 1
#define HOTLIST_SOLID_DRAG_OBJECT 2
#define HOTLIST_SOLID_DRAG_SPRITE 3
#define HOTLIST_BOX_DRAG_SELECTION 4
#define HOTLIST_WINDOW_MIN_WIDTH 480
#define HOTLIST_WINDOW_MIN_HEIGHT 3
/* In items */
#define HOTLIST_MENUSECTION_NEW 1
#define HOTLIST_MENUSECTION_ALTER 2
#define OPEN_DIRECTORY_SPRITE "small_diro"
#define CLOSED_DIRECTORY_SPRITE "small_dir"
#define INSERT_DIRECTORY_SPRITE "small_dir+"
#define URL_SPRITE "small_b28"
#define SELECTION_SPRITE "package"
#define HOTLIST_SCROLL_BOUNDARY_SIZE 32
#define HOTLIST_SCROLL_SPEED_MIN 8
#define HOTLIST_SCROLL_SPEED_INC 8
#define HOTLIST_SCROLL_SPEED_MAX 128
/* Various component IDs */
#define HOTLIST_URL_MENUITEM 0x05
#define HOTLIST_SELECTALL_MENUITEM 0x00
#define HOTLIST_CLEARSELECTION_MENUITEM 0x01
#define HOTLIST_NEWDIRECTORY_MENUITEM 0x02
#define HOTLIST_NEWURL_MENUITEM 0x06
#define HOTLIST_OPENALL_MENUITEM 0x03
#define HOTLIST_CLOSEALL_MENUITEM 0x04
#define HOTLIST_SAVE_SUBMENUITEM 0x00
#define HOTLIST_RENAME_SUBMENUITEM 0x01
#define HOTLIST_DELETE_SUBMENUITEM 0x02
#define HOTLIST_NEWDIRECTORY_NAME 0x01
#define HOTLIST_NEWDIRECTORY_CANCEL 0x03
#define HOTLIST_NEWDIRECTORY_NEW 0x02
#define HOTLIST_NEWURL_NAME 0x01
#define HOTLIST_NEWURL_URL 0x05
#define HOTLIST_NEWURL_CANCEL 0x03
#define HOTLIST_NEWURL_NEW 0x02
/* Function prototypes */
_kernel_oserror
*
hotlist_initialise
(
void
);
_kernel_oserror
*
hotlist_open
(
int
show_type
,
void
*
type
,
int
show_urls
);
_kernel_oserror
*
hotlist_close
(
void
);
_kernel_oserror
*
hotlist_load
(
char
*
filename
);
_kernel_oserror
*
hotlist_save
(
char
*
filename
);
_kernel_oserror
*
hotlist_add
(
char
*
description
,
char
*
url
,
int
at_bottom
);
#endif
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment