home *** CD-ROM | disk | FTP | other *** search
- // Zinc Interface Library - WINDOW.CPP
- // COPYRIGHT (C) 1990, 1991. All Rights Reserved.
- // Zinc Software Incorporated. Pleasant Grove, Utah USA
-
- #include "ui_win.hpp"
- #include <string.h>
-
- int UI_WINDOW_MANAGER::FindNumberID(void *object, void *matchName)
- {
- return ((((UI_WINDOW_OBJECT *)object)->search.numberID == *(USHORT *)matchName) ? 0 : -1);
- }
-
- int UI_WINDOW_MANAGER::FindStringID(void *object, void *matchName)
- {
- return (strcmpi(((UI_WINDOW_OBJECT *)object)->search.stringID, (char *)matchName));
- }
-
- UI_WINDOW_MANAGER::UI_WINDOW_MANAGER(UI_DISPLAY *_display,
- UI_EVENT_MANAGER *_eventManager,
- int (*_exitFunction)(UI_DISPLAY *display, UI_EVENT_MANAGER *eventManager,
- UI_WINDOW_MANAGER *windowManager)) :
- UI_LIST(), display(_display), eventManager(_eventManager),
- exitFunction(_exitFunction)
- {
- }
-
- UI_WINDOW_MANAGER::~UI_WINDOW_MANAGER(void)
- {
- // Remove all non-destroy objects from the window manager.
- for (UI_WINDOW_OBJECT *object = First(); object; )
- {
- UI_EVENT event;
- event.type = S_CLEAR;
- object->Event(event);
- object->display = 0;
- object->eventManager = 0;
- object->windowManager = 0;
- object = (FlagSet(object->woAdvancedFlags, WOAF_NO_DESTROY)) ?
- (UI_WINDOW_OBJECT *)UI_LIST::Subtract(object) : object->Next();
- }
-
- // Delete the temporary holding window and any extra objects on it.
- }
-
- #pragma argsused
- void UI_WINDOW_MANAGER::Add(UI_WINDOW_OBJECT *object)
- {
- // Fix the coordinate system.
- int offset;
- UI_REGION region = object->true;
- display->RegionConvert(object->true, &object->woStatus, WOS_GRAPHICS);
-
- // Only new window objects have a screenID of 0.
- if (object->screenID == 0)
- {
- int tLeft = region.left;
- region.left = (region.left >= 0) ? object->true.left :
- display->columns + region.left * display->cellWidth - 1;
- int tTop = region.top;
- region.top = (region.top >= 0) ? object->true.top :
- display->lines + region.top * display->cellHeight - 1;
- if (tLeft >= 0 && region.right > 0)
- region.right = object->true.right;
- else if (region.right <= 0)
- region.right = display->columns + region.right * display->cellWidth - 1;
- else
- region.right = region.left + region.right * display->cellWidth - 1;
- if (tTop >= 0 && region.bottom > 0)
- region.bottom = object->true.bottom;
- else if (region.bottom <= 0)
- region.bottom = display->lines + region.bottom * display->cellHeight - 1;
- else
- region.bottom = region.top + region.bottom * display->cellHeight - 1;
- if (region.left < 0)
- offset = -region.left;
- else if (region.right >= display->columns)
- offset = display->columns - region.right;
- else
- offset = 0;
- if (region.left + offset >= 0)
- {
- region.left += offset;
- region.right += offset;
- }
- if (region.top < 0)
- offset = -region.top;
- else if (region.bottom >= display->lines)
- offset = display->lines - region.bottom;
- else
- offset = 0;
- if (region.top + offset >= 0)
- {
- region.top += offset;
- region.bottom += offset;
- }
- object->true = object->relative = region;
- }
-
- // Make sure the window object is on the screen.
- region = object->true;
- if (region.left >= display->columns)
- {
- offset = region.left - display->columns + 1;
- region.left -= offset;
- region.right -= offset;
- }
- if (region.top >= display->lines)
- {
- offset = region.top - display->lines + 1;
- region.top -= offset;
- region.bottom -= offset;
- }
-
- // Initialize the window object and bring it to the screen front.
- object->display = display;
- object->eventManager = eventManager;
- object->windowManager = this;
- object->woFlags |= WOF_NON_FIELD_REGION;
- object->woAdvancedStatus &= ~WOAS_INVALID_REGION;
- object->relative = object->true = region;
-
- // Paint the new window object.
- UI_EVENT event;
- event.type = S_CREATE;
- object->Event(event);
- ToFront(object, TRUE, TRUE);
- }
-
- #pragma argsused
- void UI_WINDOW_MANAGER::Erase(UI_WINDOW_OBJECT *object,
- const UI_REGION *newRegion)
- {
- // Redraw the affected screen objects.
- UI_WINDOW_OBJECT *tObject;
- UI_EVENT event;
- event.region = object->true;
-
- // Update the front window object.
- event.type = S_CURRENT;
- if (object == First() && object->next && !newRegion)
- {
- object = object->Next();
- object->Event(event);
- if (object->true.left <= event.region.left &&
- object->true.top <= event.region.top &&
- object->true.right >= event.region.right &&
- object->true.bottom >= event.region.bottom)
- return;
- }
-
- event.type = FlagSet(object->woAdvancedFlags, WOAF_TEMPORARY) ?
- S_DISPLAY_ACTIVE : S_DISPLAY_INACTIVE;
- for (tObject = object->Next(); tObject; tObject = tObject->Next())
- {
- if (tObject->Overlap(event.region))
- tObject->Event(event);
- if (tObject->true.left <= event.region.left &&
- tObject->true.top <= event.region.top &&
- tObject->true.right >= event.region.right &&
- tObject->true.bottom >= event.region.bottom)
- return;
- if (event.type == S_DISPLAY_ACTIVE &&
- !FlagSet(tObject->woAdvancedFlags, WOAF_TEMPORARY))
- event.type = S_DISPLAY_INACTIVE;
- }
- }
-
- #pragma argsused
- int UI_WINDOW_MANAGER::Event(const UI_EVENT &event)
- {
- // Make sure there is an object.
- int ccode = MapEvent(eventMapTable, event, ID_WINDOW_MANAGER,
- ID_WINDOW_MANAGER, ID_WINDOW_MANAGER, ID_WINDOW_MANAGER,
- ID_WINDOW_MANAGER, ID_WINDOW_MANAGER);
- UI_WINDOW_OBJECT *firstObject = First();
- if (!firstObject && ccode == L_EXIT)
- return (L_EXIT);
- else if (!firstObject && ccode != S_REDISPLAY && ccode != L_EXIT_FUNCTION)
- return (S_NO_OBJECT);
-
- // Switch on the event type.
- UI_EVENT tEvent = event;
- UI_WINDOW_OBJECT *object = 0;
- switch (ccode)
- {
- case S_RESET_DISPLAY:
- while (firstObject && FlagSet(firstObject->woAdvancedFlags, WOAF_TEMPORARY))
- {
- UI_WINDOW_MANAGER::Subtract(firstObject);
- if (!FlagSet(firstObject->woAdvancedFlags, WOAF_NO_DESTROY))
- delete firstObject;
- firstObject = First();
- }
- if (!event.data)
- break;
- display = (UI_DISPLAY *)event.data;
- UI_WINDOW_OBJECT *tObject = Last();
- first = current = last = NULL;
- while (tObject)
- {
- object = tObject;
- tObject = object->Previous();
- UI_WINDOW_MANAGER::Add(object);
- }
- break;
-
- case L_MOVE:
- case L_SIZE:
- while (firstObject && FlagSet(firstObject->woAdvancedFlags, WOAF_TEMPORARY))
- {
- UI_WINDOW_MANAGER::Subtract(firstObject);
- if (!FlagSet(firstObject->woAdvancedFlags, WOAF_NO_DESTROY))
- delete firstObject;
- firstObject = First();
- }
- object = First();
- if (ccode == L_MOVE)
- {
- tEvent.type = S_MOVE;
- tEvent.position.column = object->true.left;
- tEvent.position.line = object->true.top;
- }
- else
- {
- tEvent.type = S_SIZE;
- tEvent.rawCode = M_RIGHT_CHANGE | M_BOTTOM_CHANGE;
- tEvent.position.column = object->true.right;
- tEvent.position.line = object->true.bottom;
- }
- Modify(object, tEvent);
- break;
-
- case S_MOVE:
- case S_SIZE:
- case S_CHANGE:
- object = First();
- if (ccode == S_MOVE && event.rawCode == 0xFFFF)
- {
- tEvent.position.column = object->true.left;
- tEvent.position.line = object->true.top;
- }
- else if (ccode == S_SIZE && event.rawCode == 0xFFFF)
- {
- tEvent.rawCode = M_RIGHT_CHANGE | M_BOTTOM_CHANGE;
- tEvent.position.column = object->true.right;
- tEvent.position.line = object->true.bottom;
- }
- Modify(object, event);
- break;
-
- case S_MAXIMIZE:
- case S_MINIMIZE:
- object = First();
- object->Event(event);
- break;
-
- case S_CLOSE:
- case S_CLOSE_TEMPORARY:
- // Delete any temporary windows.
- while (firstObject && FlagSet(firstObject->woAdvancedFlags, WOAF_TEMPORARY))
- {
- UI_WINDOW_MANAGER::Subtract(firstObject);
- if (!FlagSet(firstObject->woAdvancedFlags, WOAF_NO_DESTROY))
- delete firstObject;
- if (ccode == S_CLOSE_TEMPORARY)
- return (ccode);
- firstObject = First();
- }
- if (ccode == S_CLOSE_TEMPORARY)
- return (ccode);
-
- // Try to delete the top window.
- object = First();
- if (!object)
- return (S_ERROR);
- else if (FlagSet(object->woAdvancedFlags, WOAF_LOCKED))
- return (ccode);
- UI_WINDOW_MANAGER::Subtract(object);
- if (!FlagSet(object->woAdvancedFlags, WOAF_NO_DESTROY))
- delete object;
- ccode = First() ? S_CLOSE : S_NO_OBJECT;
- break;
-
- case S_CLEAR:
- for (object = First(); object; )
- {
- UI_WINDOW_OBJECT *tObject = object->Next();
- if (!FlagSet(object->woAdvancedFlags, WOAF_LOCKED))
- UI_LIST::Subtract(object);
- if (!FlagSet(object->woAdvancedFlags, WOAF_LOCKED | WOAF_NO_DESTROY))
- delete object;
- object = tObject;
- }
- // Continue to S_CASCADE.
-
- case S_CASCADE:
- {
- firstObject = First();
- while (firstObject && FlagSet(firstObject->woAdvancedFlags, WOAF_TEMPORARY))
- {
- UI_WINDOW_MANAGER::Subtract(firstObject);
- if (!FlagSet(firstObject->woAdvancedFlags, WOAF_NO_DESTROY))
- delete firstObject;
- firstObject = First();
- }
- int column = 0;
- int line = 0;
- UI_EVENT tEvent;
- for (object = Last(); object; object = object->Previous())
- {
- if (!FlagSet(object->woAdvancedStatus, WOAS_MINIMIZED))
- {
- if (column + object->true.right - object->true.left > display->columns)
- column = 0;
- if (line + object->true.bottom - object->true.top > display->lines)
- line = 0;
- tEvent.type = S_MOVE;
- tEvent.position.column = column - object->true.left;
- tEvent.position.line = line - object->true.top;
- object->true.left += tEvent.position.column;
- object->true.top += tEvent.position.line;
- object->true.right += tEvent.position.column;
- object->true.bottom += tEvent.position.line;
- object->relative = object->true;
- object->Event(tEvent);
- column += display->cellWidth * 3;
- line += display->cellHeight * 3 / 2;
- }
- }
- }
- // Continue to S_REDISPLAY.
-
- case S_REDISPLAY:
- firstObject = First();
- while (firstObject && FlagSet(firstObject->woAdvancedFlags, WOAF_TEMPORARY))
- {
- UI_WINDOW_MANAGER::Subtract(firstObject);
- if (!FlagSet(firstObject->woAdvancedFlags, WOAF_NO_DESTROY))
- delete firstObject;
- firstObject = First();
- }
- for (object = Last(); object; object = object->Previous())
- {
- tEvent.type = S_CREATE;
- object->Event(tEvent);
- tEvent.type = (object == First()) ? S_CURRENT : S_DISPLAY_INACTIVE;
- tEvent.region = object->true;
- object->Event(tEvent);
- }
- break;
-
- case L_EXIT_FUNCTION:
- while (firstObject && FlagSet(firstObject->woAdvancedFlags, WOAF_TEMPORARY))
- {
- UI_WINDOW_MANAGER::Subtract(firstObject);
- if (!FlagSet(firstObject->woAdvancedFlags, WOAF_NO_DESTROY))
- delete firstObject;
- firstObject = First();
- }
- if (exitFunction)
- {
- ccode = (*exitFunction)(display, eventManager, this);
- break;
- }
- else
- ccode = L_EXIT;
- break;
-
- case L_EXIT:
- break;
-
- case L_NEXT:
- // See if it is a modal window.
- if (FlagSet(firstObject->woAdvancedFlags, WOAF_MODAL))
- {
- _errorSystem->Beep();
- break;
- }
-
- // Move to the proper window.
- object = Last();
- while (object->Previous() &&
- (FlagSet(object->woFlags, WOF_NON_SELECTABLE) ||
- FlagSet(object->woAdvancedFlags, WOAF_NON_CURRENT)))
- object = object->Previous();
- if (First() != object &&
- !FlagSet(object->woFlags, WOF_NON_SELECTABLE) &&
- !FlagSet(object->woAdvancedFlags, WOAF_NON_CURRENT))
- ToFront(object, TRUE, FALSE);
- break;
-
- case L_HELP:
- _helpSystem->DisplayHelp(this, NO_HELP_CONTEXT);
- break;
-
- case L_VIEW:
- case L_BEGIN_SELECT:
- case L_CONTINUE_SELECT:
- case L_END_SELECT:
- // Find the proper screen object.
- for (object = First(); object; object = object->Next())
- if (object->Overlap(event.position))
- break;
- else if (FlagSet(object->woAdvancedFlags, WOAF_MODAL))
- {
- if (ccode == L_BEGIN_SELECT)
- _errorSystem->Beep();
- object = NULL;
- break;
- }
-
- // See which object should be current, if any.
- if (object != firstObject &&
- FlagSet(firstObject->woAdvancedFlags, WOAF_MODAL))
- {
- eventManager->DeviceState(event.type, DM_VIEW);
- break;
- }
- else if (ccode == L_BEGIN_SELECT && object && object != First() &&
- !FlagSet(object->woFlags, WOF_NON_SELECTABLE) &&
- !FlagSet(object->woAdvancedFlags, WOAF_NON_CURRENT))
- ToFront(object, TRUE, FALSE);
- else if (ccode != L_BEGIN_SELECT && event.rawCode != 0)
- object = First();
- if (!object)
- {
- eventManager->DeviceState(event.type, DM_VIEW);
- break;
- }
- // Continue to default.
-
- default:
- // Get the front object.
- if (!object)
- object = First();
- ccode = object->Event(event);
- if (ccode != S_UNKNOWN && ccode != S_ERROR)
- break;
-
- // Check for hot key matches.
- int tHotKey = E_KEY;
- if (!FlagSet(firstObject->woAdvancedFlags, WOAF_MODAL) &&
- event.type == E_KEY && FlagSet(event.key.shiftState, S_ALT) &&
- (tHotKey = MapEvent(_hotKeyMapTable, tEvent, ID_WINDOW_OBJECT)) != E_KEY)
- {
- tEvent.type = S_CHECK_HOT_KEY;
- tEvent.key.value = tHotKey;
- for (object = firstObject->Next(); object; object = object->Next())
- if (object->hotKey != 0 &&
- (tHotKey == object->hotKey ||
- (object->hotKey == HOT_KEY_SUB_WINDOW && object->Event(tEvent))))
- {
- ToFront(object, TRUE, FALSE);
- ccode = object->Event(event);
- break;
- }
- }
- break;
- }
-
- // Return the control code.
- return (ccode);
- }
-
- #pragma argsused
- void UI_WINDOW_MANAGER::Modify(UI_WINDOW_OBJECT *object, const UI_EVENT &event)
- {
- // Make sure the object can be sized or moved.
- int ccode = event.type;
- if (ccode == S_SIZE && FlagSet(object->woAdvancedFlags, WOAF_NO_SIZE) ||
- ccode == S_MOVE && FlagSet(object->woAdvancedFlags, WOAF_NO_MOVE))
- return;
-
- // Process S_CHANGE messages. This will result in a SIZE message also
- // being sent to the window.
- for (object = First(); object; object = object->Next())
- if (object->hWnd == event.rawCode)
- break;
-
- if (object && object->hWnd)
- {
- if (ccode == S_SIZE || ccode == S_MOVE)
- PostMessage(object->hWnd, WM_SYSCOMMAND, (ccode == S_MOVE) ? SC_MOVE : SC_SIZE, 0L);
- else
- {
- RECT windowSize;
- GetWindowRect(object->hWnd, &windowSize);
- if (event.region.left != windowSize.left || event.region.top != windowSize.top ||
- event.region.right != windowSize.right || event.region.bottom != windowSize.bottom)
- {
- MoveWindow(object->hWnd, event.region.left, event.region.top,
- event.region.right - event.region.left,
- event.region.bottom - event.region.top, 0);
- }
- else if (event.region.left != object->true.left || event.region.top != object->true.top ||
- event.region.right != object->true.right || event.region.bottom != object->true.bottom)
- {
- UI_EVENT tEvent;
- tEvent.type = S_SIZE;
- tEvent.region = event.region;
- object->relative = event.region;
- object->true = event.region;
- object->Event(tEvent);
- ToFront(object, FALSE, TRUE);
- }
- }
- }
- }
-
- #pragma argsused
- void UI_WINDOW_MANAGER::Subtract(UI_WINDOW_OBJECT *object)
- {
- // Make sure the object is in the window list.
- if (UI_LIST::Index(object) != -1)
- {
- UI_LIST::Subtract(object);
- if (object == current)
- current = NULL;
- }
- eventManager->DeviceState(E_DEVICE, DM_VIEW);
-
- UI_EVENT event;
- event.type = S_CLEAR;
- object->Event(event);
- object->display = 0;
- object->eventManager = 0;
- object->windowManager = 0;
-
- // Redraw the affected screen objects.
- UI_WINDOW_OBJECT *tObject = First();
- if (!tObject)
- return;
-
- // Update the front window object.
- event.region = object->true;
- event.type = S_CURRENT;
- object->Event(event);
-
- event.type = S_DISPLAY_INACTIVE;
- for (tObject = First(); tObject; tObject = tObject->Next())
- if (tObject->Overlap(event.region))
- tObject->Event(event);
- }
-
- #pragma argsused
- void UI_WINDOW_MANAGER::ToFront(UI_WINDOW_OBJECT *object, int refreshOld,
- int newWindow)
- {
- // Find the Maximum update region.
- UI_REGION region = { 0x0FFF, 0x0FFF, 0x0000, 0x0000 };
- for (UI_WINDOW_OBJECT *tObject = First();
- tObject && tObject != object; tObject = tObject->Next())
- if (object->Overlap(tObject->true))
- {
- region.left = Min(region.left, tObject->true.left);
- region.top = Min(region.top, tObject->true.top);
- region.right = Max(region.right, tObject->true.right);
- region.bottom = Max(region.bottom, tObject->true.bottom);
- }
-
- // Delete any temporary windows.
- UI_WINDOW_OBJECT *firstObject = First();
- if (firstObject && FlagSet(firstObject->woAdvancedFlags, WOAF_TEMPORARY))
- {
- firstObject->woStatus &= ~WOS_CURRENT;
- UI_WINDOW_MANAGER::Erase(firstObject, 0);
- UI_LIST::Subtract(firstObject);
- firstObject = First();
- if (!firstObject)
- return;
- }
-
- // Bring the object to the front of the object queue.
- if (firstObject != object)
- {
- if (UI_LIST::Index(object) != -1)
- UI_LIST::Subtract(object);
- UI_LIST::Add(firstObject, object);
- }
-
- // Inactivate the old object, then activate the new object.
- UI_EVENT event;
- if (refreshOld && firstObject && firstObject != object &&
- !FlagSet(object->woAdvancedFlags, WOAF_TEMPORARY))
- {
- event.type = S_DISPLAY_INACTIVE;
- event.region.left = event.region.top = event.region.right =
- event.region.bottom = -1;
- firstObject->Event(event);
- }
- object->woStatus |= WOS_CURRENT;
- event.type = S_CURRENT;
- event.region = object->true;
- object->Event(event);
- }
-
-