2004-05-12 03:40:07 +04:00
|
|
|
/*
|
|
|
|
* This file is part of NetSurf, http://netsurf.sourceforge.net/
|
|
|
|
* Licensed under the GNU General Public License,
|
|
|
|
* http://www.opensource.org/licenses/gpl-license
|
2005-03-19 02:52:38 +03:00
|
|
|
* Copyright 2004, 2005 Richard Wilson <info@tinct.net>
|
2004-05-12 03:40:07 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
* Interactive help (implementation).
|
|
|
|
*/
|
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
#include <stdbool.h>
|
2004-05-12 03:40:07 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "oslib/help.h"
|
2004-05-23 15:22:10 +04:00
|
|
|
#include "oslib/os.h"
|
2004-05-14 23:59:09 +04:00
|
|
|
#include "oslib/taskmanager.h"
|
2004-05-12 03:40:07 +04:00
|
|
|
#include "oslib/wimp.h"
|
2005-04-08 00:46:22 +04:00
|
|
|
#include "netsurf/desktop/tree.h"
|
2005-03-19 02:52:38 +03:00
|
|
|
#include "netsurf/riscos/global_history.h"
|
2004-05-12 03:40:07 +04:00
|
|
|
#include "netsurf/riscos/gui.h"
|
|
|
|
#include "netsurf/riscos/help.h"
|
2005-04-08 00:46:22 +04:00
|
|
|
#include "netsurf/riscos/menus.h"
|
2004-08-31 01:03:48 +04:00
|
|
|
#include "netsurf/riscos/theme.h"
|
2004-07-22 00:02:13 +04:00
|
|
|
#include "netsurf/riscos/wimp.h"
|
2004-05-12 03:40:07 +04:00
|
|
|
#include "netsurf/utils/messages.h"
|
|
|
|
#include "netsurf/utils/log.h"
|
2005-04-08 00:46:22 +04:00
|
|
|
#include "netsurf/utils/utils.h"
|
2004-05-12 03:40:07 +04:00
|
|
|
|
|
|
|
|
2004-05-14 21:36:30 +04:00
|
|
|
/* Recognised help keys
|
|
|
|
====================
|
|
|
|
|
2005-03-19 02:52:38 +03:00
|
|
|
HelpIconbar Iconbar (no icon suffix is used)
|
|
|
|
|
|
|
|
HelpAppInfo Application info window
|
|
|
|
HelpBrowser Browser window [*]
|
|
|
|
HelpHistory History window [*]
|
|
|
|
HelpObjInfo Object info window
|
|
|
|
HelpPageInfo Page info window
|
|
|
|
HelpSaveAs Save as window
|
|
|
|
HelpScaleView Scale view window
|
|
|
|
HelpStatus Status window
|
|
|
|
HelpToolbar Toolbar window
|
|
|
|
HelpHotlist Hotlist window [*]
|
|
|
|
HelpHotToolbar Hotlist window toolbar
|
|
|
|
HelpHotEntry Hotlist entry window
|
|
|
|
HelpHotFolder Hotlist entry window
|
|
|
|
HelpGHistory Global history window [*]
|
2005-04-08 00:46:22 +04:00
|
|
|
HelpGHistToolbar Global history window toolbar
|
|
|
|
HelpEditToolbar Toolbars in edit mode
|
2005-03-19 02:52:38 +03:00
|
|
|
|
|
|
|
HelpIconMenu Iconbar menu
|
2005-04-08 00:46:22 +04:00
|
|
|
HelpBrowserMenu Browser window menu
|
|
|
|
HelpHotlistMenu Hotlist window menu
|
|
|
|
HelpGHistoryMenu Global history window menu
|
|
|
|
|
|
|
|
The prefixes are followed by either the icon number (eg 'HelpToolbar7'),
|
|
|
|
or a series of numbers representing the menu structure (eg
|
|
|
|
'HelpBrowserMenu3-1-2').
|
|
|
|
If '<key><identifier>' is not available, then simply '<key>' is then
|
|
|
|
used. For example if 'HelpToolbar7' is not available then 'HelpToolbar'
|
|
|
|
is then tried.
|
|
|
|
If an item is greyed out then a suffix of 'g' is added (eg
|
|
|
|
'HelpToolbar7g'). For this to work, windows must have bit 4 of the
|
|
|
|
window flag byte set and the user must be running RISC OS 5.03 or
|
|
|
|
greater.
|
|
|
|
For items marked with an asterisk [*] a call must be made to determine
|
|
|
|
the required help text as the window does not contain any icons. An
|
|
|
|
example of this is the hotlist window where ro_gui_hotlist_help() is
|
|
|
|
called.
|
2004-05-12 03:40:07 +04:00
|
|
|
*/
|
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
|
|
|
|
static void ro_gui_interactive_help_broadcast(wimp_message *message,
|
|
|
|
char *token);
|
2004-05-23 15:22:10 +04:00
|
|
|
static os_t help_time = 0;
|
2004-05-12 03:40:07 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
|
2004-05-12 03:40:07 +04:00
|
|
|
/**
|
|
|
|
* Attempts to process an interactive help message request
|
|
|
|
*
|
|
|
|
* \param message the request message
|
|
|
|
*/
|
|
|
|
void ro_gui_interactive_help_request(wimp_message *message) {
|
|
|
|
char message_token[32];
|
|
|
|
char menu_buffer[4];
|
|
|
|
wimp_selection menu_tree;
|
2004-05-14 21:36:30 +04:00
|
|
|
help_full_message_request *message_data;
|
|
|
|
wimp_w window;
|
|
|
|
wimp_i icon;
|
2004-07-17 17:00:38 +04:00
|
|
|
struct gui_window *g;
|
2005-04-08 00:46:22 +04:00
|
|
|
struct toolbar *toolbar = NULL;
|
2004-05-14 21:36:30 +04:00
|
|
|
unsigned int index;
|
2004-07-22 00:02:13 +04:00
|
|
|
bool greyed = false;
|
|
|
|
wimp_menu *test_menu;
|
2005-04-08 00:46:22 +04:00
|
|
|
os_error *error;
|
2004-05-12 03:40:07 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* only accept help requests */
|
|
|
|
if ((!message) || (message->action != message_HELP_REQUEST))
|
|
|
|
return;
|
2004-07-06 00:19:52 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* remember the time of the request so we can track them */
|
2004-05-23 15:22:10 +04:00
|
|
|
xos_read_monotonic_time(&help_time);
|
2004-05-12 03:40:07 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* set up our state */
|
2004-05-12 03:40:07 +04:00
|
|
|
message_token[0] = 0x00;
|
|
|
|
message_data = (help_full_message_request *)message;
|
|
|
|
window = message_data->w;
|
|
|
|
icon = message_data->i;
|
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* do the basic window checks */
|
|
|
|
if (window == wimp_ICON_BAR)
|
2004-05-14 21:36:30 +04:00
|
|
|
sprintf(message_token, "HelpIconbar");
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (window == dialog_info)
|
2004-05-14 21:36:30 +04:00
|
|
|
sprintf(message_token, "HelpAppInfo%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (window == history_window)
|
2004-05-14 21:36:30 +04:00
|
|
|
sprintf(message_token, "HelpHistory%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (window == dialog_objinfo)
|
2004-05-14 21:36:30 +04:00
|
|
|
sprintf(message_token, "HelpObjInfo%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (window == dialog_pageinfo)
|
2004-05-14 21:36:30 +04:00
|
|
|
sprintf(message_token, "HelpPageInfo%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (window == dialog_saveas)
|
2004-05-14 21:36:30 +04:00
|
|
|
sprintf(message_token, "HelpSaveAs%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (window == dialog_zoom)
|
2004-05-14 21:36:30 +04:00
|
|
|
sprintf(message_token, "HelpScaleView%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (window == dialog_folder)
|
2004-07-16 20:33:45 +04:00
|
|
|
sprintf(message_token, "HelpHotFolder%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (window == dialog_entry)
|
2004-07-16 20:33:45 +04:00
|
|
|
sprintf(message_token, "HelpHotEntry%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
else if ((hotlist_tree) && (window == (wimp_w)hotlist_tree->handle))
|
2004-07-16 20:33:45 +04:00
|
|
|
sprintf(message_token, "HelpHotlist%i",
|
2004-07-17 17:00:38 +04:00
|
|
|
ro_gui_hotlist_help(message_data->pos.x,
|
|
|
|
message_data->pos.y));
|
2005-04-08 00:46:22 +04:00
|
|
|
else if ((global_history_tree) &&
|
|
|
|
(window == (wimp_w)global_history_tree->handle))
|
2005-03-19 02:52:38 +03:00
|
|
|
sprintf(message_token, "HelpGHistory%i",
|
|
|
|
ro_gui_global_history_help(message_data->pos.x,
|
|
|
|
message_data->pos.y));
|
2005-04-08 00:46:22 +04:00
|
|
|
else if ((hotlist_tree) && (hotlist_tree->toolbar) &&
|
|
|
|
((window == hotlist_tree->toolbar->toolbar_handle) ||
|
|
|
|
((hotlist_tree->toolbar->editor) &&
|
|
|
|
(window == hotlist_tree->toolbar->
|
|
|
|
editor->toolbar_handle)))) {
|
|
|
|
toolbar = hotlist_tree->toolbar;
|
|
|
|
sprintf(message_token, "HelpHotToolbar%i", (int)icon);
|
2005-03-19 02:52:38 +03:00
|
|
|
} else if ((global_history_tree) && (global_history_tree->toolbar) &&
|
2005-04-08 00:46:22 +04:00
|
|
|
((window == global_history_tree->toolbar->
|
|
|
|
toolbar_handle) ||
|
|
|
|
((global_history_tree->toolbar->editor) &&
|
|
|
|
(window == global_history_tree->toolbar->
|
|
|
|
editor->toolbar_handle)))) {
|
|
|
|
toolbar = global_history_tree->toolbar;
|
|
|
|
sprintf(message_token, "HelpGHistToolbar%i", (int)icon);
|
|
|
|
} else if ((g = ro_gui_window_lookup(window)) != NULL)
|
2004-07-17 17:00:38 +04:00
|
|
|
sprintf(message_token, "HelpBrowser%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
else if ((g = ro_gui_toolbar_lookup(window)) != NULL) {
|
|
|
|
toolbar = g->toolbar;
|
2004-07-17 17:00:38 +04:00
|
|
|
sprintf(message_token, "HelpToolbar%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
} else if ((g = ro_gui_status_lookup(window)) != NULL)
|
2004-07-17 17:00:38 +04:00
|
|
|
sprintf(message_token, "HelpStatus%i", (int)icon);
|
2005-04-08 00:46:22 +04:00
|
|
|
|
|
|
|
/* change toolbars to editors where appropriate */
|
|
|
|
if ((toolbar) && (toolbar->editor))
|
|
|
|
sprintf(message_token, "HelpEditToolbar%i", (int)icon);
|
|
|
|
|
|
|
|
/* if we've managed to find something so far then we broadcast it */
|
|
|
|
if (message_token[0]) {
|
|
|
|
if ((icon >= 0) &&
|
|
|
|
(ro_gui_get_icon_shaded_state(window, icon)))
|
|
|
|
strcat(message_token, "g");
|
|
|
|
ro_gui_interactive_help_broadcast(message,
|
|
|
|
(char *)message_token);
|
|
|
|
return;
|
2004-05-12 03:40:07 +04:00
|
|
|
}
|
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* if we are not on an icon, we can't be in a menu (which stops
|
|
|
|
* separators giving help for their parent) so we abort */
|
|
|
|
if (icon == wimp_ICON_WINDOW)
|
|
|
|
return;
|
2004-08-14 18:30:12 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* get the current menu tree */
|
|
|
|
error = xwimp_get_menu_state(wimp_GIVEN_WINDOW_AND_ICON,
|
|
|
|
&menu_tree, window, icon);
|
|
|
|
if (error) {
|
|
|
|
LOG(("xwimp_get_menu_state: 0x%x: %s",
|
|
|
|
error->errnum, error->errmess));
|
|
|
|
warn_user("WimpError", error->errmess);
|
2004-05-12 03:40:07 +04:00
|
|
|
return;
|
|
|
|
}
|
2005-04-08 00:46:22 +04:00
|
|
|
if (menu_tree.items[0] == -1)
|
|
|
|
return;
|
2004-05-12 03:40:07 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* get the menu prefix */
|
|
|
|
if (current_menu == iconbar_menu)
|
2004-05-14 21:36:30 +04:00
|
|
|
sprintf(message_token, "HelpIconMenu");
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (current_menu == browser_menu)
|
2004-05-14 21:36:30 +04:00
|
|
|
sprintf(message_token, "HelpBrowserMenu");
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (current_menu == hotlist_menu)
|
2004-07-16 20:33:45 +04:00
|
|
|
sprintf(message_token, "HelpHotlistMenu");
|
2005-04-08 00:46:22 +04:00
|
|
|
else if (current_menu == global_history_menu)
|
|
|
|
sprintf(message_token, "HelpGHistoryMenu");
|
|
|
|
else
|
2004-05-12 03:40:07 +04:00
|
|
|
return;
|
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* decode the menu */
|
2004-05-12 03:40:07 +04:00
|
|
|
index = 0;
|
2004-07-22 00:02:13 +04:00
|
|
|
test_menu = current_menu;
|
2004-05-12 03:40:07 +04:00
|
|
|
while (menu_tree.items[index] != -1) {
|
2005-04-08 00:46:22 +04:00
|
|
|
greyed |= test_menu->entries[menu_tree.items[index]].icon_flags
|
|
|
|
& wimp_ICON_SHADED;
|
2004-07-22 00:02:13 +04:00
|
|
|
test_menu = test_menu->entries[menu_tree.items[index]].sub_menu;
|
2005-04-08 00:46:22 +04:00
|
|
|
if (index == 0)
|
2004-05-12 03:40:07 +04:00
|
|
|
sprintf(menu_buffer, "%i", menu_tree.items[index]);
|
2005-04-08 00:46:22 +04:00
|
|
|
else
|
2004-05-12 03:40:07 +04:00
|
|
|
sprintf(menu_buffer, "-%i", menu_tree.items[index]);
|
|
|
|
strcat(message_token, menu_buffer);
|
|
|
|
index++;
|
|
|
|
}
|
2005-04-08 00:46:22 +04:00
|
|
|
if (greyed)
|
|
|
|
strcat(message_token, "g");
|
|
|
|
ro_gui_interactive_help_broadcast(message, (char *)message_token);
|
2004-05-12 03:40:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Broadcasts a help reply
|
|
|
|
*
|
|
|
|
* \param message the original request message
|
|
|
|
* \param token the token to look up
|
|
|
|
*/
|
2005-04-08 00:46:22 +04:00
|
|
|
static void ro_gui_interactive_help_broadcast(wimp_message *message,
|
|
|
|
char *token) {
|
2004-07-22 00:02:13 +04:00
|
|
|
const char *translated_token;
|
2004-05-14 21:36:30 +04:00
|
|
|
help_full_message_reply *reply;
|
2004-07-22 00:02:13 +04:00
|
|
|
char *base_token;
|
2005-04-08 00:46:22 +04:00
|
|
|
os_error *error;
|
2004-05-12 03:40:07 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* start off with an empty reply */
|
2004-07-26 00:45:16 +04:00
|
|
|
reply = (help_full_message_reply *)message;
|
|
|
|
reply->reply[0] = '\0';
|
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* check if the message exists */
|
2004-07-22 00:02:13 +04:00
|
|
|
translated_token = messages_get(token);
|
2004-05-14 23:59:09 +04:00
|
|
|
if (translated_token == token) {
|
2005-04-08 00:46:22 +04:00
|
|
|
/* no default help for 'g' suffix */
|
2004-07-26 00:45:16 +04:00
|
|
|
if (token[strlen(token) - 1] != 'g') {
|
2005-04-08 00:46:22 +04:00
|
|
|
/* find the base key from the token */
|
2004-07-22 00:02:13 +04:00
|
|
|
base_token = token;
|
|
|
|
while (base_token[0] != 0x00) {
|
|
|
|
if ((base_token[0] == '-') ||
|
2005-04-08 00:46:22 +04:00
|
|
|
((base_token[0] >= '0') &&
|
|
|
|
(base_token[0] <= '9')))
|
2004-07-22 00:02:13 +04:00
|
|
|
base_token[0] = 0x00;
|
2005-04-08 00:46:22 +04:00
|
|
|
else
|
2004-07-22 00:02:13 +04:00
|
|
|
++base_token;
|
2004-05-14 23:59:09 +04:00
|
|
|
}
|
2004-07-22 00:02:13 +04:00
|
|
|
translated_token = messages_get(token);
|
|
|
|
}
|
2004-05-14 23:59:09 +04:00
|
|
|
}
|
2004-08-14 18:30:12 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* copy our message string */
|
2004-07-26 00:45:16 +04:00
|
|
|
if (translated_token != token) {
|
|
|
|
reply->reply[235] = 0;
|
|
|
|
strncpy(reply->reply, translated_token, 235);
|
|
|
|
}
|
2004-05-12 03:40:07 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* broadcast the help reply */
|
2004-05-12 03:40:07 +04:00
|
|
|
reply->size = 256;
|
|
|
|
reply->action = message_HELP_REPLY;
|
|
|
|
reply->your_ref = reply->my_ref;
|
2005-04-08 00:46:22 +04:00
|
|
|
error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message *)reply,
|
|
|
|
reply->sender);
|
|
|
|
if (error) {
|
|
|
|
LOG(("xwimp_send_message: 0x%x: %s",
|
|
|
|
error->errnum, error->errmess));
|
|
|
|
warn_user("WimpError", error->errmess);
|
|
|
|
}
|
2004-05-12 03:40:07 +04:00
|
|
|
}
|
2004-05-14 23:59:09 +04:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if interactive help is running
|
|
|
|
*
|
2004-05-23 15:22:10 +04:00
|
|
|
* \return non-zero if interactive help is available, or 0 if not available
|
2004-05-14 23:59:09 +04:00
|
|
|
*/
|
2005-04-08 00:46:22 +04:00
|
|
|
bool ro_gui_interactive_help_available(void) {
|
2004-05-14 23:59:09 +04:00
|
|
|
taskmanager_task task;
|
|
|
|
int context = 0;
|
2004-05-23 15:22:10 +04:00
|
|
|
os_t time;
|
2005-04-08 00:46:22 +04:00
|
|
|
os_error *error;
|
2004-07-06 00:19:52 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* generic test: any help request within the last 100cs */
|
2004-05-23 15:22:10 +04:00
|
|
|
xos_read_monotonic_time(&time);
|
2005-04-08 00:46:22 +04:00
|
|
|
if ((help_time + 100) > time)
|
|
|
|
return true;
|
2004-05-15 00:23:52 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/* special cases: check known application names */
|
2004-05-14 23:59:09 +04:00
|
|
|
do {
|
2005-04-08 00:46:22 +04:00
|
|
|
error = xtaskmanager_enumerate_tasks(context, &task,
|
|
|
|
sizeof(taskmanager_task), &context, 0);
|
|
|
|
if (error) {
|
|
|
|
LOG(("xtaskmanager_enumerate_tasks: 0x%x: %s",
|
|
|
|
error->errnum, error->errmess));
|
|
|
|
warn_user("MiscError", error->errmess);
|
2004-05-14 23:59:09 +04:00
|
|
|
}
|
2005-04-08 00:46:22 +04:00
|
|
|
|
|
|
|
/* we can't just use strcmp due to string termination issues */
|
|
|
|
if (!strncmp(task.name, "Help", 4) &&
|
|
|
|
(task.name[4] < 32))
|
|
|
|
return true;
|
|
|
|
else if (!strncmp(task.name, "Bubble Help", 11) &&
|
|
|
|
(task.name[11] < 32))
|
|
|
|
return true;
|
|
|
|
else if (!strncmp(task.name, "Floating Help", 13) &&
|
|
|
|
(task.name[13] < 32))
|
|
|
|
return true;
|
2004-05-15 00:23:52 +04:00
|
|
|
} while (context >= 0);
|
2005-04-08 00:46:22 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2004-05-15 00:23:52 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
/**
|
|
|
|
* Launches interactive help.
|
|
|
|
*/
|
|
|
|
void ro_gui_interactive_help_start(void) {
|
|
|
|
char *help_start;
|
|
|
|
wimp_t task = 0;
|
|
|
|
os_error *error;
|
|
|
|
|
|
|
|
/* launch <Help$Start> */
|
|
|
|
help_start = getenv("Help$Start");
|
|
|
|
if ((help_start) && (help_start[0])) {
|
|
|
|
error = xwimp_start_task("<Help$Start>", &task);
|
|
|
|
if (error) {
|
|
|
|
LOG(("xwimp_start_tast: 0x%x: %s",
|
|
|
|
error->errnum, error->errmess));
|
|
|
|
warn_user("WimpError", error->errmess);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* first attempt failed, launch !Help */
|
|
|
|
if (!task) {
|
|
|
|
error = xwimp_start_task("Resources:$.Apps.!Help", &task);
|
|
|
|
if (error) {
|
|
|
|
LOG(("xwimp_start_tast: 0x%x: %s",
|
|
|
|
error->errnum, error->errmess));
|
|
|
|
warn_user("WimpError", error->errmess);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pretend we got a help request straight away */
|
|
|
|
if (task) {
|
|
|
|
error = xos_read_monotonic_time(&help_time);
|
|
|
|
if (error) {
|
|
|
|
LOG(("xwimp_read_monotonic_time: 0x%x: %s",
|
|
|
|
error->errnum, error->errmess));
|
|
|
|
warn_user("WimpError", error->errmess);
|
|
|
|
}
|
|
|
|
}
|
2004-05-14 23:59:09 +04:00
|
|
|
}
|