home *** CD-ROM | disk | FTP | other *** search
- /*
- sdgfld.c
-
- % sed_MoveGField: grid movement function
-
- Provides grid movement between fields.
- Combines up, down, right, and left.
-
- If the sed is active, calls the fenter and fexit functions.
-
- C-scape 3.2
- Copyright (c) 1986, 1987, by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 11/18/86 jmd created
- 3/11/87 jmd always calls scroll_adjust now.
- 4/01/87 jmd added active mode check
- 11/18/87 jmd changed names of some low-level funcs
- 8/24/88 jmd added bob object support
- 8/25/88 jmd changed to true geographical operation
- 9/12/88 jmd Added in and out data to objects
- 12/13/88 jmd Added many divers changes to affect the field motion
-
- 2/07/89 jmd initialized depend to avoid warning
- 4/13/89 jmd added sed_GetCurrField macro
- 5/25/89 jmd added tests for protected field to bob handling
- 5/27/89 jmd removed unnecessary call to goto_field
- 8/11/89 jmd de-bobbed
-
- 3/17/90 jmd added Cache/Flush
- 3/28/90 jmd ansi-fied
- */
-
- #include "sed.h"
- #include "fldpriv.h" /* for field_ operations */
-
- #define gfield_func(fname) int fname(menu_type, int)
- typedef gfield_func ((*gfield_fptr));
-
- int sed_MoveGField(sed_type sed, int direction)
- /*
- Attempts to find the "best" up, down, left, right motion
- between fields.
- In some detail it does the following.
- First it uses the grid to find the "nearest" field in the desired
- direction (in the case of up and down, nearest means a field
- with the same grid column number). If the current field is a bob,
- a field representing its current location is temporarily placed into
- the field grid in order to use the grid operations.
- After a field has been found, a search is made for the closest bob
- object in the given direction. In this case straight line distance is
- used. If a bob is found that is closer then the field found in the grid
- it becomes the new field. The correct location to jump within it
- is determined. whew.
- */
- {
- register int newfield;
- bob_type bob;
- menu_type menu;
- ocbox oldbox, newbox;
- boolean isabob;
- field_type field;
- int frow, fcol, fwid;
- int bobno, child, dist, mindist;
- int guess = -1;
- ocpos_struct ocpos;
- ocsize_struct ocsize;
- winsfp_struct winsfp;
- gfield_fptr get_field; /* pointer to get field function */
-
- cs_Assert(sed_Ok(sed), CS_SD_MGF_SED, 0);
-
- ocpos.row = 0;
- ocpos.col = 0;
-
- ocsize.height = 0;
- ocsize.width = 0;
-
- menu = sed_GetMenu(sed);
-
- switch (direction) {
- case OAK_UP:
- get_field = menu_FindUpField;
- break;
- case OAK_DOWN:
- get_field = menu_FindDownField;
- break;
- case OAK_RIGHT:
- get_field = menu_FindRightField;
- break;
- case OAK_LEFT:
- get_field = menu_FindLeftField;
- break;
- default:
- cs_Assert(FALSE, CS_SD_MGF_DIR, 0);
- break;
- }
-
- /* if the current field has a dependent bob,
- temporarily set the field location to the position within the bob
- */
-
- isabob = FALSE;
- if ((bob = menu_GetFieldBob(menu, sed_GetFieldNo(sed))) != NULL) {
- isabob = bob_IsDepend(bob);
- }
-
- if (!isabob) {
- /* get field's location */
- menu_GetFieldBox(menu, sed_GetFieldNo(sed), &oldbox);
- }
- else {
- /* remember old field location */
- field = sed_GetCurrField(sed);
- frow = field_GetRow(field);
- fcol = field_GetCol(field);
- fwid = field_GetWidth(field);
-
- /* find the position WITHIN the bob */
- /* Note: this code will not be called for non-window bobs
- because of Depend Check
- */
-
- bob_Do(bob, WINM_GETFLDPOS, NULL, (VOID *) &oldbox);
- ocpos.row = bord_GetTopRow(bob);
- ocpos.col = bord_GetLeftCol(bob);
-
- /* translate bob coords into menu coords */
- oldbox.toprow += ocpos.row - win_GetTopRow(sed) + sed_GetYoffset(sed);
- oldbox.botrow += ocpos.row - win_GetTopRow(sed) + sed_GetYoffset(sed);
- oldbox.leftcol += ocpos.col - win_GetLeftCol(sed) + sed_GetXoffset(sed);
- oldbox.rightcol += ocpos.col - win_GetLeftCol(sed) + sed_GetXoffset(sed);
-
- /* move the field to a new, temporary spot */
- menu_TakeFieldFromGrid(menu, sed_GetFieldNo(sed));
- menu_AddFieldToGrid(menu, sed_GetFieldNo(sed), oldbox.toprow, oldbox.leftcol);
- field_SetWidth(field, oldbox.rightcol - oldbox.leftcol + 1);
- }
-
- /* find nearest, unprotected, unvirtual field */
- /* remember first unprotected, virtual field, we may need it later */
- newfield = sed_GetFieldNo(sed);
- do {
- if ((newfield = (*get_field)(menu, newfield)) < 0) {
- break;
- }
- if (guess == -1 && menu_GetFieldWidth(menu, newfield) <= 0 &&
- !menu_IsProtected(menu, newfield)) {
- guess = newfield;
- }
- } while (menu_IsProtected(menu, newfield) ||
- menu_GetFieldWidth(menu, newfield) <= 0);
-
- if (isabob) {
- /* restore the current field's location */
- menu_TakeFieldFromGrid(menu, sed_GetFieldNo(sed));
- menu_AddFieldToGrid(menu, sed_GetFieldNo(sed), frow, fcol);
- field_SetWidth(field, fwid);
- }
-
- /* find closest unprotected dependent bob, skip current field */
-
- child = -1;
- mindist = -1;
- for (bobno = 0; bobno < menu_GetBobCount(menu); bobno++) {
- if ((bob = menu_GetBob(menu, bobno)) != NULL &&
- menu_GetBobFieldNo(menu, bobno) != sed_GetFieldNo(sed) &&
- !menu_IsProtected(menu, menu_GetBobFieldNo(menu, bobno))) {
-
- if (bob_IsDepend(bob)) {
- ocpos.row = bord_GetTopRow(bob);
- ocpos.col = bord_GetLeftCol(bob);
-
- ocsize.height = bord_GetHeight(bob);
- ocsize.width = bord_GetWidth(bob);
-
- /* get bob box, translate to menu coords */
- newbox.toprow = ocpos.row - win_GetTopRow(sed) + sed_GetYoffset(sed);
- newbox.botrow = newbox.toprow + ocsize.height - 1;
- newbox.leftcol = ocpos.col - win_GetLeftCol(sed) + sed_GetXoffset(sed);
- newbox.rightcol = newbox.leftcol + ocsize.width - 1;
-
- /* compare distances */
- if ((dist = ocbox_FindDist(&oldbox, &newbox, direction)) >= 0) {
- if (mindist < 0 || dist < mindist) {
- child = bobno;
- mindist = dist;
- }
- }
- }
- }
- }
-
- if (newfield < 0) {
- if (child < 0) {
- if (guess < 0) {
- return(SED_STUCK);
- }
- else {
- /* nothing else looks good, let's use that guess we made */
- newfield = guess;
- }
- }
- else {
- newfield = menu_GetBobFieldNo(menu, child);
- }
- }
- else if (child >= 0) {
- /* compare distance of new field with child */
- menu_GetFieldBox(menu, newfield, &newbox);
-
- dist = ocbox_FindDist(&oldbox, &newbox, direction);
- if (dist < 0 || mindist < dist ) {
- newfield = menu_GetBobFieldNo(menu, child);
- }
- else {
- /* reset child */
- child = -1;
- }
- }
-
- /* If we're jumping to a bob, tell it the best place to be jump to */
- if (child >= 0) {
- /* find the child's box (relative to the child) */
- bob = menu_GetBob(menu, child);
- if (bob_IsDepend(bob)) {
- ocpos.row = bord_GetTopRow(bob);
- ocpos.col = bord_GetLeftCol(bob);
-
- ocsize.height = bord_GetHeight(bob);
- ocsize.width = bord_GetWidth(bob);
- }
-
- /* get setcurpos box in child bob coords */
- if (direction == OAK_RIGHT || direction == OAK_LEFT) {
- newbox.toprow = oldbox.toprow + win_GetTopRow(sed) - sed_GetYoffset(sed) - ocpos.row;
- newbox.botrow = oldbox.botrow + win_GetTopRow(sed) - sed_GetYoffset(sed)- ocpos.row;
- newbox.leftcol = 0;
- newbox.rightcol = ocsize.width - 1;
- }
- else {
- newbox.toprow = 0;
- newbox.botrow = ocsize.height - 1;
- newbox.leftcol = oldbox.leftcol + win_GetLeftCol(sed) - sed_GetXoffset(sed) - ocpos.col;
- newbox.rightcol = oldbox.rightcol + win_GetLeftCol(sed) - sed_GetXoffset(sed)- ocpos.col;
- }
-
- /* set child's current pos */
- winsfp.ocboxp = &newbox;
- winsfp.pref = direction;
-
- bob_Do(bob, WINM_SETFLDPOS, &winsfp, NULL);
- }
-
- if (!sd_exitfield(sed)) {
- return(SED_INVALID);
- }
-
- disp_Cache();
- sd_scroll_adjust(sed, newfield);
- sd_goto_field(sed, newfield);
-
- if (sed_IsActive(sed)) {
- sed_DoFieldFenter(sed, sed_GetFieldNo(sed));
- }
- disp_Flush();
-
- return(SED_MOVED);
- }
-