home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / CSSRC / SDGFLD.C < prev    next >
C/C++ Source or Header  |  1990-03-29  |  8KB  |  272 lines

  1. /*
  2.     sdgfld.c
  3.  
  4.     % sed_MoveGField: grid movement function
  5.  
  6.     Provides grid movement between fields.
  7.     Combines up, down, right, and left.
  8.  
  9.     If the sed is active, calls the fenter and fexit functions.
  10.  
  11.     C-scape 3.2
  12.     Copyright (c) 1986, 1987, by Oakland Group, Inc.
  13.     ALL RIGHTS RESERVED.
  14.  
  15.     Revision History:
  16.     -----------------
  17.     11/18/86 jmd    created
  18.      3/11/87 jmd    always calls scroll_adjust now.
  19.      4/01/87 jmd    added active mode check
  20.     11/18/87 jmd     changed names of some low-level funcs
  21.      8/24/88 jmd     added bob object support
  22.      8/25/88 jmd     changed to true geographical operation
  23.      9/12/88 jmd    Added in and out data to objects
  24.     12/13/88 jmd    Added many divers changes to affect the field motion
  25.  
  26.      2/07/89 jmd    initialized depend to avoid warning
  27.      4/13/89 jmd    added sed_GetCurrField macro
  28.      5/25/89 jmd    added tests for protected field to bob handling
  29.      5/27/89 jmd    removed unnecessary call to goto_field
  30.      8/11/89 jmd    de-bobbed
  31.  
  32.      3/17/90 jmd    added Cache/Flush
  33.      3/28/90 jmd    ansi-fied
  34. */
  35.  
  36. #include "sed.h"
  37. #include "fldpriv.h"        /* for field_ operations */
  38.  
  39. #define gfield_func(fname)            int fname(menu_type, int)
  40. typedef gfield_func ((*gfield_fptr));
  41.  
  42. int sed_MoveGField(sed_type sed, int direction)
  43. /*
  44.     Attempts to find the "best" up, down, left, right motion
  45.     between fields.
  46.     In some detail it does the following.
  47.     First it uses the grid to find the "nearest" field in the desired
  48.     direction (in the case of up and down, nearest means a field
  49.     with the same grid column number).  If the current field is a bob,
  50.     a field representing its current location is temporarily placed into
  51.     the field grid in order to use the grid operations.
  52.     After a field has been found, a search is made for the closest bob
  53.     object in the given direction.  In this case straight line distance is
  54.     used.  If a bob is found that is closer then the field found in the grid
  55.     it becomes the new field.  The correct location to jump within it
  56.     is determined.  whew.
  57. */
  58. {
  59.     register int newfield;
  60.     bob_type      bob;
  61.     menu_type     menu;
  62.     ocbox           oldbox, newbox;
  63.     boolean          isabob;
  64.     field_type      field;
  65.     int             frow, fcol, fwid;
  66.     int             bobno, child, dist, mindist;
  67.     int             guess = -1;
  68.     ocpos_struct  ocpos;
  69.     ocsize_struct ocsize;
  70.     winsfp_struct winsfp;
  71.     gfield_fptr      get_field;    /* pointer to get field function */
  72.  
  73.     cs_Assert(sed_Ok(sed), CS_SD_MGF_SED, 0);
  74.  
  75.     ocpos.row = 0;
  76.     ocpos.col = 0;
  77.  
  78.     ocsize.height = 0;
  79.     ocsize.width = 0;
  80.  
  81.     menu = sed_GetMenu(sed);
  82.  
  83.     switch (direction) {
  84.     case OAK_UP:
  85.         get_field = menu_FindUpField;
  86.         break;
  87.     case OAK_DOWN:
  88.         get_field = menu_FindDownField;
  89.         break;
  90.     case OAK_RIGHT:
  91.         get_field = menu_FindRightField;
  92.         break;
  93.     case OAK_LEFT:
  94.         get_field = menu_FindLeftField;
  95.         break;
  96.     default:
  97.         cs_Assert(FALSE, CS_SD_MGF_DIR, 0);
  98.         break;
  99.     }
  100.  
  101.     /*    if the current field has a dependent bob,
  102.         temporarily set the field location to the position within the bob
  103.     */
  104.  
  105.     isabob = FALSE;
  106.     if ((bob = menu_GetFieldBob(menu, sed_GetFieldNo(sed))) != NULL) {
  107.         isabob = bob_IsDepend(bob);
  108.     }
  109.  
  110.     if (!isabob) {
  111.         /* get field's location */
  112.         menu_GetFieldBox(menu, sed_GetFieldNo(sed), &oldbox);
  113.     }
  114.     else {
  115.         /* remember old field location */
  116.         field = sed_GetCurrField(sed);
  117.         frow = field_GetRow(field);
  118.         fcol = field_GetCol(field);
  119.         fwid = field_GetWidth(field);
  120.  
  121.         /* find the position WITHIN the bob */
  122.         /* Note: this code will not be called for non-window bobs 
  123.            because of Depend Check
  124.         */
  125.  
  126.         bob_Do(bob, WINM_GETFLDPOS, NULL, (VOID *) &oldbox);
  127.         ocpos.row = bord_GetTopRow(bob);
  128.         ocpos.col = bord_GetLeftCol(bob);
  129.  
  130.         /* translate bob coords into menu coords */
  131.         oldbox.toprow   += ocpos.row - win_GetTopRow(sed) + sed_GetYoffset(sed);
  132.         oldbox.botrow   += ocpos.row - win_GetTopRow(sed) + sed_GetYoffset(sed);
  133.         oldbox.leftcol  += ocpos.col - win_GetLeftCol(sed) + sed_GetXoffset(sed);
  134.         oldbox.rightcol += ocpos.col - win_GetLeftCol(sed) + sed_GetXoffset(sed);
  135.  
  136.         /* move the field to a new, temporary spot */
  137.         menu_TakeFieldFromGrid(menu, sed_GetFieldNo(sed));
  138.         menu_AddFieldToGrid(menu, sed_GetFieldNo(sed), oldbox.toprow, oldbox.leftcol);
  139.         field_SetWidth(field, oldbox.rightcol - oldbox.leftcol + 1);
  140.     }
  141.  
  142.     /* find nearest, unprotected, unvirtual field */
  143.     /* remember first unprotected, virtual field, we may need it later */
  144.     newfield = sed_GetFieldNo(sed);
  145.     do {
  146.         if ((newfield = (*get_field)(menu, newfield)) < 0) {
  147.             break;
  148.         }
  149.         if (guess == -1 && menu_GetFieldWidth(menu, newfield) <= 0 &&
  150.             !menu_IsProtected(menu, newfield)) {
  151.             guess = newfield;
  152.         }
  153.     } while (menu_IsProtected(menu, newfield) ||
  154.              menu_GetFieldWidth(menu, newfield) <= 0);
  155.  
  156.     if (isabob) {
  157.         /* restore the current field's location */
  158.         menu_TakeFieldFromGrid(menu, sed_GetFieldNo(sed));
  159.         menu_AddFieldToGrid(menu, sed_GetFieldNo(sed), frow, fcol);
  160.         field_SetWidth(field, fwid);
  161.     }
  162.  
  163.     /* find closest unprotected dependent bob, skip current field */
  164.  
  165.     child = -1;
  166.     mindist = -1;
  167.     for (bobno = 0; bobno < menu_GetBobCount(menu); bobno++) {
  168.         if ((bob = menu_GetBob(menu, bobno)) != NULL &&
  169.             menu_GetBobFieldNo(menu, bobno) != sed_GetFieldNo(sed) &&
  170.             !menu_IsProtected(menu, menu_GetBobFieldNo(menu, bobno))) {
  171.  
  172.             if (bob_IsDepend(bob)) {
  173.                 ocpos.row = bord_GetTopRow(bob);
  174.                 ocpos.col = bord_GetLeftCol(bob);
  175.  
  176.                 ocsize.height = bord_GetHeight(bob);
  177.                 ocsize.width = bord_GetWidth(bob);
  178.  
  179.                 /* get bob box, translate to menu coords */
  180.                 newbox.toprow  = ocpos.row - win_GetTopRow(sed) + sed_GetYoffset(sed);
  181.                 newbox.botrow  = newbox.toprow + ocsize.height - 1;
  182.                 newbox.leftcol = ocpos.col - win_GetLeftCol(sed) + sed_GetXoffset(sed);
  183.                 newbox.rightcol = newbox.leftcol + ocsize.width - 1;
  184.  
  185.                 /* compare distances */
  186.                 if ((dist = ocbox_FindDist(&oldbox, &newbox, direction)) >= 0) {
  187.                     if (mindist < 0 || dist < mindist) {
  188.                         child = bobno;
  189.                         mindist = dist;
  190.                     }
  191.                 }
  192.             }
  193.         }
  194.     }
  195.  
  196.     if (newfield < 0) {
  197.         if (child < 0) {
  198.             if (guess < 0) {
  199.                 return(SED_STUCK);
  200.             }
  201.             else {
  202.                 /* nothing else looks good, let's use that guess we made */
  203.                 newfield = guess;
  204.             }
  205.         }
  206.         else {
  207.             newfield = menu_GetBobFieldNo(menu, child);
  208.         }
  209.     }
  210.     else if (child >= 0) {
  211.         /* compare distance of new field with child */
  212.         menu_GetFieldBox(menu, newfield, &newbox);
  213.     
  214.         dist = ocbox_FindDist(&oldbox, &newbox, direction);
  215.         if (dist < 0 || mindist < dist ) { 
  216.             newfield = menu_GetBobFieldNo(menu, child);
  217.         }
  218.         else {
  219.             /* reset child */
  220.             child = -1;
  221.         }
  222.     }
  223.  
  224.     /* If we're jumping to a bob, tell it the best place to be jump to */
  225.     if (child >= 0) {
  226.         /* find the child's box (relative to the child) */
  227.         bob = menu_GetBob(menu, child);
  228.         if (bob_IsDepend(bob)) {
  229.             ocpos.row = bord_GetTopRow(bob);
  230.             ocpos.col = bord_GetLeftCol(bob);
  231.  
  232.             ocsize.height = bord_GetHeight(bob);
  233.             ocsize.width = bord_GetWidth(bob);
  234.         }
  235.  
  236.         /* get setcurpos box in child bob coords */
  237.         if (direction == OAK_RIGHT || direction == OAK_LEFT) {
  238.             newbox.toprow = oldbox.toprow + win_GetTopRow(sed)  - sed_GetYoffset(sed) - ocpos.row;
  239.             newbox.botrow = oldbox.botrow + win_GetTopRow(sed)  - sed_GetYoffset(sed)- ocpos.row;
  240.             newbox.leftcol = 0;
  241.             newbox.rightcol = ocsize.width - 1;
  242.         }
  243.         else {
  244.             newbox.toprow  = 0;
  245.             newbox.botrow  = ocsize.height - 1;
  246.             newbox.leftcol  = oldbox.leftcol  + win_GetLeftCol(sed) - sed_GetXoffset(sed) - ocpos.col;
  247.             newbox.rightcol = oldbox.rightcol + win_GetLeftCol(sed) - sed_GetXoffset(sed)- ocpos.col;
  248.         }
  249.  
  250.         /* set child's current pos */
  251.         winsfp.ocboxp = &newbox;
  252.         winsfp.pref = direction;
  253.  
  254.         bob_Do(bob, WINM_SETFLDPOS, &winsfp, NULL);
  255.     }
  256.  
  257.     if (!sd_exitfield(sed)) {
  258.         return(SED_INVALID);
  259.     }
  260.  
  261.     disp_Cache();
  262.     sd_scroll_adjust(sed, newfield);
  263.     sd_goto_field(sed, newfield);
  264.  
  265.     if (sed_IsActive(sed)) {
  266.         sed_DoFieldFenter(sed, sed_GetFieldNo(sed));
  267.     }
  268.     disp_Flush();
  269.  
  270.     return(SED_MOVED);
  271. }    
  272.