home *** CD-ROM | disk | FTP | other *** search
-
- /* iconmgr.c */
-
- #include <stdlib.h>
- #include "OS:os.h"
- #include "OS:osmodule.h"
- #include "OS:wimp.h"
- #include "OS:toolbox.h"
- #include "OS:window.h"
- #include "OS:taskmanager.h"
- #include "Dreamscape:task.h"
- #include "Dreamscape:wimpevent.h"
- #include "Dreamscape:wimpmsg.h"
- #include "Dreamscape:x.h"
-
- #ifdef MemCheck_MEMCHECK
- #include "MemCheck:MemCheck.h"
- #endif
-
- #include "iconmgr.h"
- #include "debug.h"
- #include "options.h"
- #include "various.h"
-
-
- /* Private structures */
-
- typedef struct iconbar_manager_icon iconbar_manager_icon;
- typedef struct iconbar_manager_node iconbar_manager_node;
-
- struct iconbar_manager_icon {
- ibarpatch_add_info *ibarpatch_block; /* To update later. */
- iconbar_gadget *gadget;
- void *external_handle; /* Used by the icon arranger. */
-
- /* Information about icon from IconbarPatch. */
- int icon_handle;
- wimp_t task;
- wimp_icon_flags flags;
- wimp_icon_data data;
-
- /* Data we've worked out. */
- int priority;
- unsigned update_poll_id;
- };
-
- struct iconbar_manager_node {
- iconbar_manager_icon i;
- iconbar_manager_node *next;
- };
-
- struct iconbar_manager_task {
- ibarpatch_block *module;
- iconbar_manager_node *icons;
-
- iconbar_arranger *arranger;
- unsigned poll_id;
- iconbar_manager_icon *pointer_icon; /* Icon under pointer is cached. */
- };
-
-
- /* Internal function prototypes */
-
- #define MODULE_NAME "iconbar_manager"
-
- /* Event handlers */
- static bool click_handler(const wimp_block *event,
- const toolbox_block *ids, void *handle);
- static bool pollword_handler(const wimp_block *event,
- const toolbox_block *ids, void *handle);
- static bool null_event_handler(const wimp_block *event,
- const toolbox_block *ids, void *handle);
- static bool task_quitting_handler(const wimp_message *message, void *handle);
-
- static iconbar_manager_icon *icon_from_pointer(iconbar_manager_task *task,
- const os_coord *pos, toolbox_o window, wimp_w wimp_window);
- static bool process_ibarpatch_event(iconbar_manager_task *task,
- ibarpatch_element *e);
-
- static void add_icon(iconbar_manager_task *task, ibarpatch_add_info *i,
- const char *task_name);
- static void update_icon(iconbar_manager_task *task,
- iconbar_manager_icon *icon);
- static void remove_icon(iconbar_manager_task *task,
- iconbar_manager_node **node_ptr);
-
-
- /* Initialisation and finalisation */
-
- iconbar_manager_task *iconbar_manager_initialise(iconbar_arranger *arranger)
- {
- iconbar_manager_task *task = malloc(sizeof(iconbar_manager_task));
- LOGFUNC(initialise);
- if(!task) return 0;
-
- /* Initialise variables. */
- task->icons = 0;
- task->arranger = arranger;
- task->poll_id = 0;
- task->pointer_icon = 0;
-
- /* Find module's block and increment usage count. */
- osmodule_lookup("IconbarPatch", 0, 0, (void **) &task->module, 0);
- #ifdef MemCheck_MEMCHECK
- MemCheck_RegisterMiscBlock(task->module, sizeof(ibarpatch_block));
- #endif
- ++task->module->usage_count;
-
- /* Wimp event handlers. */
- dscape_wimpevent_register_handler(wimp_MOUSE_CLICK, 0,
- click_handler, task);
- dscape_wimpevent_register_handler(wimp_NULL_REASON_CODE, 0,
- null_event_handler, task);
- /* Set up our poll word non-zero handler (with low priority) */
- dscape_task_set_poll_word((int *) &task->module->list.begin, 0);
- dscape_wimpevent_register_handler(wimp_POLLWORD_NON_ZERO,
- 0, pollword_handler, task);
-
- /* Wimp message handlers. */
- dscape_wimpmsg_register_handler(message_TASK_CLOSE_DOWN,
- task_quitting_handler, task);
-
- /* Read list of previous icons set up. */
- {
- ibarpatch_element *e = task->module->list_keep.begin, *next;
- while(e) {
- #ifdef MemCheck_MEMCHECK
- MemCheck_RegisterMiscBlock(e, sizeof(ibarpatch_element));
- #endif
- process_ibarpatch_event(task, e); /* Ignore return value */
- next = e->next;
- #ifdef MemCheck_MEMCHECK
- MemCheck_UnRegisterMiscBlock(e);
- #endif
- e = next;
- }
- }
- return task;
- }
-
- void iconbar_manager_finalise(iconbar_manager_task *task)
- {
- LOGFUNC(finalise);
- if(!task) return;
-
- /* Delete all icons. */
- while(task->icons) {
- iconbar_manager_node *old = task->icons;
- task->icons = old->next;
-
- /* Finalise this icon, and free the node. */
- task->arranger->remove_icon(task->arranger, old->i.gadget,
- old->i.external_handle);
- iconbar_gadget_destroy(old->i.gadget);
- /* Don't remove icon from keep list. */
- free(old);
- }
-
- /* Reset pointer values if necessary. */
- if(task_handle_from_window(task->module->window, -1) ==
- dscape_task_get_handle()) {
- task->module->window = 0;
- task->module->pointer_icon = -1;
- task->module->pointer_task = 0;
- }
-
- /* Wimp message handlers. */
- dscape_wimpmsg_deregister_handler(message_TASK_CLOSE_DOWN,
- task_quitting_handler, task);
-
- /* Wimp event handlers. */
- dscape_wimpevent_deregister_handler(wimp_MOUSE_CLICK, 0,
- click_handler, task);
- dscape_wimpevent_deregister_handler(wimp_NULL_REASON_CODE, 0,
- null_event_handler, task);
- /* Poll word non-zero handler. */
- dscape_task_set_poll_word(0, 0);
- dscape_wimpevent_deregister_handler(wimp_POLLWORD_NON_ZERO,
- 0, pollword_handler, task);
-
- /* We have finished with the module. */
- --task->module->usage_count;
- #ifdef MemCheck_MEMCHECK
- MemCheck_UnRegisterMiscBlock(task->module);
- #endif
-
- free(task);
- }
-
-
- /* Event handlers */
-
- /* Handle clicks on icons. */
- static bool click_handler(const wimp_block *event,
- const toolbox_block *ids, void *xhandle)
- {
- iconbar_manager_task *task = xhandle;
- iconbar_manager_icon *icon;
- LOGFUNC(click_handler);
-
- /* Ignore if Menu was clicked at the very bottom of the screen. This
- allows the `Toggle' module to still work. */
- if(event->pointer.buttons == 2 && event->pointer.pos.y == 0)
- return 0; /* Pass event on */
-
- icon = icon_from_pointer(task, &event->pointer.pos, ids->this_obj,
- event->pointer.w);
- if(icon) {
- /* Re-send the mouse click event to the task in question. */
- wimp_block message = *event;
- DEBUGF1("Sending mouse click to task (buttons %i)\n",
- event->pointer.buttons);
- message.pointer.w = wimp_ICON_BAR;
- message.pointer.i = icon->icon_handle;
- wimp_send_message(wimp_MOUSE_CLICK,
- (wimp_message *) &message, icon->task);
-
- /* If Menu was clicked, alter where the menu will appear. */
- if(event->pointer.buttons == 2) {
- /* Open the base of the menu a given distance below the top of the
- icon. (NB. 96 is the position menu bases would otherwise be
- opened at.) */
- os_box bbox;
- wimp_window_state state;
-
- iconbar_gadget_get_bbox(icon->gadget, &bbox);
- state.w = window_get_wimp_handle(0,
- iconbar_gadget_get_window(icon->gadget));
- wimp_get_window_state(&state);
-
- task->module->y_offset = (bbox.y1 + state.visible.y1 - state.yscroll)
- - (96 + options->menu_y_offset);
- }
- return 1; /* Claim event */
- }
- return 0; /* Pass event on */
- }
-
- /* For a given mouse state (the pointer position and window it is over),
- returns which icon the pointer is over, if any. If no pointer position is
- given, it reads the current state (including window). */
- static iconbar_manager_icon *icon_from_pointer(iconbar_manager_task *task,
- const os_coord *pos, toolbox_o window, wimp_w wimp_window)
- {
- iconbar_manager_node *node;
- os_coord pos_read,
- work_pos; /* Work area pointer position */
- LOGFUNC(icon_from_pointer);
-
- /* Read the mouse state if none was passed. */
- if(!pos) {
- wimp_w current;
- wimp_pointer ptr;
- /* We have to tell IconbarPatch not to fiddle with returned data. This
- might be necessary for Window_WimpToToolbox too, since it *could*
- send a message to the window to find its owning task first (not
- likely, but possible). */
- iconbar_manager_get_pointer_info(task, &ptr);
-
- /* Pointer position. */
- pos_read = ptr.pos;
- pos = &pos_read;
- /* Pointer window. */
- wimp_window = ptr.w;
- /* This next call was giving me address exceptions at seemingly random
- times. This could either be a Toolbox bug, or it could be returning
- an error and the error handler went pear-shaped (although this SWI
- should not give an error). As X-form, it seems to work. Also, don't
- tell it the icon handle (why should we?). */
- current = task->module->window;
- task->module->window = 0;
- if(xwindow_wimp_to_toolbox(0, ptr.w, -1, &window, 0))
- window = 0; /* Just in case. */
- task->module->window = current;
- }
-
- /* Only care about this task's Toolbox windows. */
- if(!window) return task->pointer_icon = 0; /* Not over icon */
-
- /* Find pointer position in window's work area. */
- {
- wimp_window_state state;
- state.w = wimp_window;
- wimp_get_window_state(&state);
- work_pos.x = pos->x - state.visible.x0 + state.xscroll;
- work_pos.y = pos->y - state.visible.y1 + state.yscroll;
- }
-
- /* Check last cached icon under pointer. */
- if(task->pointer_icon &&
- iconbar_gadget_get_window(task->pointer_icon->gadget) == window) {
- os_box bbox;
- iconbar_gadget_get_bbox(task->pointer_icon->gadget, &bbox);
- if(work_pos.x >= bbox.x0 && work_pos.x < bbox.x1 &&
- work_pos.y >= bbox.y0 && work_pos.y < bbox.y1)
- return task->pointer_icon;
- }
-
- /* Go through list of icons to find a match for both window and bbox. */
- for(node = task->icons; node; node = node->next) {
- if(iconbar_gadget_get_window(node->i.gadget) == window) {
- os_box bbox;
- iconbar_gadget_get_bbox(node->i.gadget, &bbox);
- if(work_pos.x >= bbox.x0 && work_pos.x < bbox.x1 &&
- work_pos.y >= bbox.y0 && work_pos.y < bbox.y1) {
- DEBUGF1("Icon under pointer is number %i\n", node->i.icon_handle);
- return task->pointer_icon = &node->i;
- }
- }
- }
- return task->pointer_icon = 0; /* Not over icon */
- }
-
- /* Does wimp_get_pointer_info without fudging window handles, etc. */
- void iconbar_manager_get_pointer_info(iconbar_manager_task *task,
- wimp_pointer *pointer)
- {
- wimp_w current;
- LOGFUNC(get_pointer_info);
- if(!task) return;
-
- /* Unsets the iconbar window temporarily so that it looks like a
- normal window. */
- current = task->module->window;
- task->module->window = 0;
- wimp_get_pointer_info(pointer);
- task->module->window = current;
- }
-
- /* Defines a function and macro to check the integrity of one of the
- IconbarPatch module's event lists. The check is done for MemCheck and
- debug builds, and is typically done after the list has been modified.
- It is impossible to use MemCheck to check our handling of the lists
- (because we don't create the blocks), and I would like peace of mind that
- they aren't being corrupted. */
- #if defined MemCheck_MEMCHECK || defined DEBUG
- # define PFX "List-check: "
- static void check_module_list_integrity(ibarpatch_list *list,
- const char *name)
- {
- char *rma;
- int rma_size, count = 0;
- ibarpatch_element **e;
- bool fail = 0;
- DEBUGF2(PFX "Checking list `%s' (%i blocks recorded)\n",
- name, list->count);
-
- /* Find where the module area is (all blocks must be in the RMA). */
- rma = (char *) os_read_dynamic_area(os_DYNAMIC_AREA_RMA, &rma_size, 0);
-
- #ifdef MemCheck_MEMCHECK
- /* It is easiest to turn checking off throughout this. */
- MemCheck_SetChecking(0, 0);
- #endif
- /* Go through the list. */
- e = &list->begin;
- while(1) {
- if(!*e) {
- /* The last element: make sure this tallies. */
- if(e != list->end) {
- fprintf(stderr, PFX "List end doesn't tally (%i blocks found)\n",
- count);
- fail = 1;
- }
- break;
- }
- /* Check that the block pointer is in the module area. */
- if((char *) *e < rma || (char *) *e >= (rma + rma_size)) {
- /* End the check since it will lead to never-never land. */
- fprintf(stderr, PFX "Block %i not in module area (check aborted)\n",
- count);
- fail = 1;
- break;
- }
- ++count;
- e = &(*e)->next;
- }
- #ifdef MemCheck_MEMCHECK
- MemCheck_SetChecking(1, 1);
- #endif
- /* Check that block counts match. */
- if(count != list->count) {
- fprintf(stderr, PFX "Block count mismatch (%i recorded, %i found)\n",
- list->count, count);
- fail = 1;
- }
- if(fail) {
- fprintf(stderr, PFX "List `%s' failed check\n", name);
- abort();
- }
- }
- # undef PFX
- # define CHECK_INTEGRITY(list, name) check_module_list_integrity(list, name)
- #else
- # define CHECK_INTEGRITY(list, name) ((void) 0)
- #endif
- #define CHECK_EVENT_LIST(mod) CHECK_INTEGRITY(&mod->list, "event")
- #define CHECK_KEEP_LIST(mod) CHECK_INTEGRITY(&mod->list_keep, "keep")
-
- /* Handle any new events from IconbarPatch. */
- static bool pollword_handler(const wimp_block *event,
- const toolbox_block *ids, void *xhandle)
- {
- iconbar_manager_task *task = xhandle;
- LOGFUNC(pollword_handler);
- ++task->poll_id;
-
- CHECK_EVENT_LIST(task->module);
- CHECK_KEEP_LIST(task->module);
-
- /* Handle any events queued by the module */
- while(task->module->list.begin) {
- bool remove;
- ibarpatch_element *e = task->module->list.begin;
- #ifdef MemCheck_MEMCHECK
- MemCheck_RegisterMiscBlock(e, sizeof(ibarpatch_element));
- #endif
-
- /* Handle the event. */
- remove = process_ibarpatch_event(task, e);
-
- /* An add event is a useful record, so move it to the keep list.
- It goes at the end of the list so that icons can be re-created in
- order. (Unless the task died, in which case throw it away. */
- if(e->type == ibarpatch_add_type && !remove) {
- /* Unlink event from list. */
- task->module->list.begin = e->next;
- if(task->module->list.end == &e->next)
- task->module->list.end = &task->module->list.begin;
- /* Add it to the keep list. */
- #ifdef MemCheck_MEMCHECK
- MemCheck_RegisterMiscBlock(task->module->list_keep.end, 4);
- #endif
- *task->module->list_keep.end = e;
- #ifdef MemCheck_MEMCHECK
- MemCheck_UnRegisterMiscBlock(task->module->list_keep.end);
- #endif
- e->next = 0;
- task->module->list_keep.end = &e->next;
- --task->module->list.count;
- ++task->module->list_keep.count;
- CHECK_EVENT_LIST(task->module);
- CHECK_KEEP_LIST(task->module);
- }
-
- /* Update and remove events will be deleted from list. Mostly add events
- will be kept, but out-of-date ones are deleted. */
- if(remove) {
- /* Remove event from list. */
- task->module->list.begin = e->next;
- if(task->module->list.end == &e->next)
- task->module->list.end = &task->module->list.begin;
- osmodule_free(e);
- --task->module->list.count;
- CHECK_EVENT_LIST(task->module);
- }
-
- #ifdef MemCheck_MEMCHECK
- MemCheck_UnRegisterMiscBlock(e);
- #endif
- }
- return 1;
- }
-
- /* Deals with an IconbarPatch event. Does not unlink the event from the
- list of events (this is the task of the caller), but returns true if the
- event should be deleted. */
- static bool process_ibarpatch_event(iconbar_manager_task *task,
- ibarpatch_element *e)
- {
- bool remove = 0;
- x_declare(error);
- LOGFUNC(process_ibarpatch_event);
- x_try switch(e->type) {
-
- /* Add an iconbar icon. */
- case ibarpatch_add_type: {
- /* Check to see if the task still exists. If it doesn't, it's likely
- that it died as soon as it started up, so we don't want to display
- its icon. */
- char *task_name;
- os_error *x = xtaskmanager_task_name_from_handle(e->data.add.task,
- &task_name);
- /* The error number the Task Manager seems to return for `Task not
- found' is 3. We don't want to fail for any old error, because
- the Task Manager might not be present (eg. on an NC). */
- #ifdef MemCheck_MEMCHECK
- if(x) MemCheck_RegisterMiscBlock(x, sizeof(os_error));
- #endif
- if(!(x && x->errnum == 3)) {
- if(!x) {
- /* Copy the task name. I wish the PRMs would say how strings are
- terminated. I have to copy it on the off-chance it isn't
- null-terminated. */
- int len = 0;
- char *b;
- #ifdef MemCheck_MEMCHECK
- MemCheck_RegisterMiscBlock(task_name, 256);
- #endif
- while(task_name[len] >= 32 && len < 256) ++len;
- b = malloc(len + 1);
- if(!b) x_throw_message(x_msg_memory());
- memcpy(b, task_name, len);
- #ifdef MemCheck_MEMCHECK
- MemCheck_UnRegisterMiscBlock(task_name);
- #endif
- b[len] = 0;
- task_name = b;
- }
- else {
- task_name = 0;
- }
- DEBUGF2("Adding new icon, number %i (task `%s')\n",
- e->data.add.icon_handle, task_name ? task_name : "");
- add_icon(task, &e->data.add, task_name);
- free(task_name);
- }
- else {
- DEBUGF1("Icon number %i not added (task has died)\n",
- e->data.add.icon_handle);
- remove = 1;
- }
- #ifdef MemCheck_MEMCHECK
- if(x) MemCheck_UnRegisterMiscBlock(x);
- #endif
- } break;
-
- /* Remove an iconbar icon. */
- case ibarpatch_remove_type: {
- iconbar_manager_node **find;
- remove = 1;
- DEBUGF1("Removing icon, number %i\n", e->data.remove.icon_handle);
- for(find = &task->icons; *find; find = &(*find)->next)
- if((*find)->i.icon_handle == e->data.remove.icon_handle)
- { remove_icon(task, find); break; }
- } break;
-
- /* Update an iconbar icon. */
- case ibarpatch_update_type: {
- iconbar_manager_node *find;
- remove = 1;
- DEBUGF1("Updating icon, number %i\n", e->data.update.icon_handle);
- for(find = task->icons; find; find = find->next)
- if(find->i.icon_handle == e->data.update.icon_handle) {
- /* Don't bother updating the icon again if it was just updated. */
- if(!e->data.update.bic && !e->data.update.eor &&
- find->i.update_poll_id == task->poll_id) break;
- find->i.flags = (find->i.flags &~ e->data.update.bic)
- ^ e->data.update.eor;
- /* Copy flags back, for the record. */
- #ifdef MemCheck_MEMCHECK
- MemCheck_RegisterMiscBlock(find->i.ibarpatch_block,
- sizeof(ibarpatch_add_info));
- #endif
- find->i.ibarpatch_block->flags = find->i.flags;
- #ifdef MemCheck_MEMCHECK
- MemCheck_UnRegisterMiscBlock(find->i.ibarpatch_block);
- #endif
- update_icon(task, &find->i);
- break;
- }
- } break;
-
- /* Remove unknown events to stop them wasting our time. */
- default:
- remove = 1;
- break;
- }
- x_catch(error) {
- dscape_task_report_error(error->errmess);
- }
- return remove;
- }
-
- /* Keep IconbarPatch up-to-date about which icon the pointer is over so that
- it can return modified info. */
- static bool null_event_handler(const wimp_block *event,
- const toolbox_block *ids, void *xhandle)
- {
- iconbar_manager_task *task = xhandle;
- iconbar_manager_icon *icon;
- LOGFUNC(null_event_handler);
-
- /* Tell IconbarPatch which icon handle the pointer is over. */
- icon = icon_from_pointer(task, 0, 0, 0);
- if(icon) {
- /* Pointer is over icon, so set details. */
- wimp_w wimp_window = window_get_wimp_handle(0,
- iconbar_gadget_get_window(icon->gadget));
- wimp_window_state state;
-
- /* Copy window state (for Wimp_GetWindowState on iconbar). */
- state.w = wimp_window;
- wimp_get_window_state(&state);
- task->module->iconbar_state = state;
-
- /* Copy rest of data. */
- task->module->window = wimp_window;
- task->module->pointer_icon = icon->icon_handle;
- task->module->pointer_task = icon->task;
- }
- else if(task->module->window) {
- /* The pointer is not over an icon, but do we have to unset details? */
- wimp_t owning_task;
- wimp_w owning_window = task->module->window;
-
- /* Find out which task owns the current window. */
- wimp_message msg;
- msg.size = 5*4;
- msg.my_ref = msg.your_ref = 0;
- msg.action = -1;
- /* Unset this so that message gets through to Wimp. */
- task->module->window = 0;
- if(!owning_window ||
- xwimp_send_message_to_window(wimp_USER_MESSAGE_ACKNOWLEDGE,
- &msg, owning_window, -1, &owning_task))
- owning_task = 0;
-
- /* If that task was us, unset details. */
- if(owning_task == dscape_task_get_handle()) {
- task->module->window = 0;
- task->module->pointer_icon = -1;
- task->module->pointer_task = 0;
- }
- else task->module->window = owning_window; /* Set it back again */
- }
-
- return 0; /* Pass event on */
- }
-
- /* When a task quits, this removes all icons on the iconbar owned by it. */
- static bool task_quitting_handler(const wimp_message *message, void *xhandle)
- {
- iconbar_manager_task *task = xhandle;
- iconbar_manager_node **find;
- LOGFUNC(task_quitting_handler);
-
- /* Search has to be restarted because list may be reshuffled. */
- restart:
- for(find = &task->icons; *find; find = &(*find)->next)
- if((*find)->i.task == message->sender)
- { remove_icon(task, find); goto restart; }
-
- return 0; /* Pass event on */
- }
-
-
- /* Talk to the icon arranger component */
-
- /* Add an icon. */
- static void add_icon(iconbar_manager_task *task, ibarpatch_add_info *i,
- const char *task_name)
- {
- iconbar_manager_node *node;
- iconbar_manager_icon *icon;
- iconbar_gadget *gadget;
- ibarpatch_icon_properties *icon_info;
- iconbar_arranger_add_info add_info;
- LOGFUNC(add_icon);
-
- /* Create new list node. */
- node = malloc(sizeof(iconbar_manager_node));
- if(!node) x_throw_message(x_msg_memory());
- icon = &node->i;
-
- /* Copy across the simple details. */
- icon->icon_handle = i->icon_handle;
- icon->task = i->task;
- icon->flags = i->flags;
- icon->data = i->data;
- /* Set last update time. */
- icon->update_poll_id = task->poll_id;
- /* Keep block address (allows later updates). */
- icon->ibarpatch_block = i;
-
- /* Convert the icon's priority, and see if it goes next to another icon.
- Fill out the add_info block. */
- if((i->position == wimp_ICON_BAR_LEFT_RELATIVE ||
- i->position == wimp_ICON_BAR_RIGHT_RELATIVE) &&
- i->extra.priority != -1 /* Means extreme left/right */ ) {
- /* The app wants its icon placed next to another icon. */
- iconbar_manager_node *find;
- for(find = task->icons; find; find = find->next) {
- if(i->extra.next_to == find->i.icon_handle) {
- /* Our new icon inherits the priority of the other icon. */
- add_info.priority = find->i.priority;
- add_info.tend_higher =
- (i->position == wimp_ICON_BAR_RIGHT_RELATIVE);
- add_info.next_to = find->i.external_handle;
- /* Copy these details back to record (useful later). */
- if(find->i.priority >= 0) {
- i->position = wimp_ICON_BAR_RIGHT_LOW_PRIORITY;
- i->extra.priority = (find->i.priority - 0x80000) * 0x10000;
- }
- else {
- i->position = wimp_ICON_BAR_LEFT_LOW_PRIORITY;
- i->extra.priority = (-find->i.priority - 0x80000) * 0x10000;
- }
- break;
- }
- }
- /* If the other icon wasn't found, give this one a default position. */
- if(!find) {
- i->position = wimp_ICON_BAR_RIGHT;
- goto by_priority;
- }
- }
- else {
- /* The app has specified a side (and maybe a priority). */
- bool left_side;
- int priority;
- by_priority:
- priority = i->extra.priority;
-
- /* Which side shall it go on? */
- left_side =
- i->position == wimp_ICON_BAR_LEFT ||
- i->position == wimp_ICON_BAR_LEFT_RELATIVE /* Not a mistake */ ||
- i->position == wimp_ICON_BAR_LEFT_HIGH_PRIORITY ||
- i->position == wimp_ICON_BAR_LEFT_LOW_PRIORITY;
-
- /* Handle case where icon goes on extreme left or right. */
- if(i->extra.next_to == -1) { priority = 0x78000000; }
- /* Set priority to zero in simple case. */
- if(i->position == wimp_ICON_BAR_LEFT ||
- i->position == wimp_ICON_BAR_RIGHT) { priority = 0; }
-
- /* Depending on the scan direction, some icons will be to the right of
- other icons with the same priority. */
- add_info.tend_higher =
- i->position == wimp_ICON_BAR_LEFT ||
- i->position == wimp_ICON_BAR_RIGHT_RELATIVE || /* Not a mistake */
- i->position == wimp_ICON_BAR_LEFT_LOW_PRIORITY || /* Left reversed */
- i->position == wimp_ICON_BAR_RIGHT_HIGH_PRIORITY;
-
- /* Now we fudge the original icon priorities into a set of values that
- are easier to compare. Negative numbers are towards the left,
- positive numbers towards the right. */
- DEBUGF2("Original priorities: %x, %x\n", priority,
- (priority / 0x10000) + 0x80000);
- add_info.priority = (priority / 0x10000) + 0x80000;
- if(left_side) add_info.priority = -add_info.priority;
- add_info.next_to = 0;
- }
- icon->priority = add_info.priority;
- DEBUGF2("Icon priority is %i (%x)\n",
- add_info.priority, add_info.priority);
-
- /* Find icon's details and give them to a newly-spawned gadget. */
- icon_info = ibarpatch_extract_info(icon->task, icon->flags, &icon->data);
- icon->gadget = gadget = iconbar_gadget_create();
- iconbar_gadget_set_sprite(gadget, &icon_info->sprite);
- iconbar_gadget_set_text(gadget, icon_info->text);
- iconbar_gadget_set_task_name(gadget, task_name);
- ibarpatch_free_info(icon_info);
-
- /* Link node into list. */
- node->next = task->icons;
- task->icons = node;
-
- icon->external_handle = task->arranger->add_icon(task->arranger,
- gadget, &add_info);
- }
-
- /* Update an icon gadget (icon arranger gets event indirectly). */
- static void update_icon(iconbar_manager_task *task,
- iconbar_manager_icon *icon)
- {
- iconbar_gadget *gadget = icon->gadget;
- ibarpatch_icon_properties *icon_info;
- LOGFUNC(update_icon);
-
- /* Tell the gadget the new icon info. */
- icon_info = ibarpatch_extract_info(icon->task, icon->flags, &icon->data);
- iconbar_gadget_set_sprite(gadget, &icon_info->sprite);
- iconbar_gadget_set_text(gadget, icon_info->text);
- ibarpatch_free_info(icon_info);
- icon->update_poll_id = task->poll_id;
- }
-
- /* Remove an icon. */
- static void remove_icon(iconbar_manager_task *task,
- iconbar_manager_node **node_ptr)
- {
- iconbar_manager_node *node = *node_ptr;
- iconbar_manager_icon *icon = &node->i;
- iconbar_gadget *gadget = icon->gadget;
- int icon_handle = icon->icon_handle;
- LOGFUNC(remove_icon);
-
- task->arranger->remove_icon(task->arranger, gadget, icon->external_handle);
- iconbar_gadget_destroy(gadget);
-
- /* Remove the corresponding add record from IconbarPatch's keep list. */
- {
- ibarpatch_element **rem;
- #ifdef MemCheck_MEMCHECK
- /* It is easiest to turn checking off throughout this. */
- MemCheck_SetChecking(0, 0);
- #endif
- for(rem = &task->module->list_keep.begin; *rem; rem = &(*rem)->next) {
- if((*rem)->type == ibarpatch_add_type &&
- (*rem)->data.add.icon_handle == icon_handle) {
- /* We have found the matching add event. Now remove it. */
- ibarpatch_element *old = *rem;
- /* Make sure to handle the special case of this being
- the last in the list. */
- if(task->module->list_keep.end == &(*rem)->next)
- task->module->list_keep.end = rem;
- *rem = (*rem)->next;
- osmodule_free(old);
- --task->module->list_keep.count;
- CHECK_KEEP_LIST(task->module);
- break;
- }
- }
- #ifdef MemCheck_MEMCHECK
- MemCheck_SetChecking(1, 1);
- #endif
- }
-
- /* If the pointer was over the icon, restore IconbarPatch's values to a
- safer setting. This prevents interactive help from dying after an
- app is quit. */
- if(task->module->pointer_icon == icon->icon_handle) {
- task->module->window = 0;
- task->module->pointer_icon = -1;
- task->module->pointer_task = 0;
- }
- if(task->pointer_icon == icon) task->pointer_icon = 0;
-
- /* Remove node from list. */
- *node_ptr = node->next;
- free(node);
- }
-
- /* The arranger's method for telling us that it will no longer be handling
- the given gadget. */
- void iconbar_manager_losing_icon(iconbar_manager_task *task,
- iconbar_gadget *gadget)
- {
- iconbar_manager_node **node;
- LOGFUNC(losing_icon);
-
- /* Search for the corresponding node in the list and remove it. */
- for(node = &task->icons; *node; node = &(*node)->next)
- if((*node)->i.gadget == gadget) {
- iconbar_manager_node *old = *node;
- *node = old->next;
-
- /* Make pointer values safe. */
- if(task->module->pointer_icon == old->i.icon_handle) {
- task->module->window = 0;
- task->module->pointer_icon = -1;
- task->module->pointer_task = 0;
- }
- if(task->pointer_icon == &old->i) task->pointer_icon = 0;
- /* Free the node. */
- free(old);
- break;
- }
- /* Destroy the gadget. */
- iconbar_gadget_destroy(gadget);
- }
-