home *** CD-ROM | disk | FTP | other *** search
/ TopWare Tools / TOOLS.iso / tools / top1242 / basic.c next >
Encoding:
C/C++ Source or Header  |  1992-01-06  |  12.0 KB  |  544 lines

  1. /*
  2. *      Basic cursor motion commands.
  3. * The routines in this file are the basic
  4. * command functions for moving the cursor around on
  5. * the screen, setting mark, and swapping dot with
  6. * mark. Only moves between lines, which might make the
  7. * current buffer framing bad, are hard.
  8. */
  9.  
  10. #include    "def.h"
  11.  
  12. bool    move_ptr ();
  13. bool    forwchar ();
  14. bool    wind_on_dot ();
  15. bool    backline ();
  16.  
  17. extern    char    MSG_mark_set[];
  18. extern    char    MSG_no_mark[];
  19. extern    char    MSG_go_b_n[];
  20. extern    char    MSG_bad_num[];
  21. #if RUNCHK
  22. extern    char    ERR_bas_1[];
  23. #endif
  24. extern    char    MSG_lX[];
  25. extern    char    MSG_lO[];
  26. extern    char    MSG_lD[];
  27.  
  28.  
  29. extern  bool    rplc_mode;
  30.  
  31. /*  pvr
  32. * Move cursor backwards. Do the
  33. * right thing if the count is less than
  34. * 0. Error if you try to move back from
  35. * the beginning of the buffer.
  36. */
  37. bool backchar (f, n, k)
  38. register int  f, n, k;
  39. {
  40.     if (n < 0)
  41.         return (forwchar (f, -n, KRANDOM));
  42.  
  43.     while (n--)
  44.     {
  45.         if (curwp -> w_unit_offset == 0)
  46.         {
  47.             if (!move_ptr (curwp,  -(long)R_B_PER_U(curwp),
  48.                 TRUE, TRUE, TRUE))
  49.                 return (FALSE);
  50.  
  51.             /* step to previous unit */
  52.             curwp -> w_unit_offset = R_CHR_PER_U(curwp) - 1;
  53.  
  54.             /* if before first line in window then move window */
  55.             wind_on_dot (curwp);
  56.         }
  57.         else
  58.             curwp -> w_unit_offset--;
  59.     }
  60.     curwp -> w_flag |= WFMODE;  /* update mode line */
  61.     return (TRUE);
  62. }
  63.  
  64. /*  pvr
  65. * Move cursor forwards. Do the
  66. * right thing if the count is less than
  67. * 0. Error if you try to move forward
  68. * from the end of the buffer.
  69. */
  70. bool forwchar (f, n, k)
  71. register int f, n, k;
  72. {
  73.     if (n < 0)
  74.         return (backchar (f, -n, KRANDOM));
  75.  
  76.     curwp -> w_flag |= WFMODE;  /* update mode line */
  77.     while (n--)
  78.     {
  79.         if (curwp -> w_unit_offset >= (R_CHR_PER_U(curwp) - 1))
  80.         {
  81.             /* move to the mext unit */
  82.             curwp -> w_unit_offset = 0;
  83.  
  84.             if (!move_ptr (curwp,  (long)R_B_PER_U(curwp),
  85.                 TRUE, TRUE, TRUE))
  86.             {
  87.                 /* I am at the the end of the buffer */
  88.                 return (FALSE);
  89.             }
  90.  
  91.             /* if after the last line in window then move window */
  92.             wind_on_dot (curwp);
  93.         }
  94.         else if/* if at last byte of buffer then do not step  */
  95.         (DOT_POS(curwp) < BUF_SIZE(curwp))
  96.             curwp -> w_unit_offset++;/* step within unit */
  97.     }
  98.     return (TRUE);
  99. }
  100.  
  101. /*  pvr
  102. *   This function moves the specified pointer by the ammount specified
  103. *   in 'len'.   Move the dot pointer is 'dot' is true, else move
  104. *   the window pointer.  Do the fix up if 'fix' is TRUE.
  105. *   This is a relative move if 'rel' is TRUE, else it is an
  106. *   absolute move.
  107. */
  108.  
  109. bool    move_ptr (wp, len, dot, fix, rel)
  110. WINDOW  *wp;
  111. long    len;
  112. bool    dot, fix, rel;
  113. {
  114.     A32     cur_pos, dest_pos, fix_val, last_pos;
  115.     long    rel_pos;
  116.     A32     last_fixed_pos, align;
  117.     LINE    **line;
  118.     int     *l_off;
  119.     char    shift;
  120.     bool    no_limit;
  121.  
  122.     no_limit = TRUE;
  123.     if (dot)
  124.     {                       /* move dot position */
  125.         l_off = (int *)&wp -> w_doto;
  126.         line = &wp -> w_dotp;
  127.         align = R_SIZE(wp);  /* bytes -1 in a unit */
  128.     }
  129.     else
  130.     {                       /* move window position */
  131.         l_off = (int *)&wp -> w_loff;
  132.         line = &wp -> w_linep;
  133.         align = R_ALIGN(wp) - 1; /* interval of bytes to align window */
  134.     }
  135.  
  136.     /* get the current position in the buffer */
  137.     cur_pos = (*line) -> l_file_offset + *l_off;
  138.  
  139.     if (rel)
  140.     {
  141.         rel_pos = len;
  142.         dest_pos = len + cur_pos;   /* destination position */
  143.     }
  144.     else
  145.     {
  146.         rel_pos = len - cur_pos;   /* relative move amount */
  147.         dest_pos = len;   /* destination position */
  148.     }
  149.     if (fix)
  150.     {
  151.         shift = wp -> w_disp_shift;
  152.  
  153.         /* limit at begining */
  154.         if ((long)dest_pos < (long)shift)
  155.         {
  156.             rel_pos = shift - cur_pos;
  157.             no_limit = FALSE;
  158.         }
  159.         else
  160.         {
  161.             /* calculate fixed up destination position */
  162.             fix_val = dest_pos &= ~align;
  163.             fix_val += shift;
  164.  
  165.             /* calculate the last position in the buffer */
  166.             last_pos = BUF_SIZE(wp);
  167.             if (last_pos < (last_fixed_pos = (last_pos & ~align) + shift))
  168.                 last_pos = last_fixed_pos - align - 1;
  169.  
  170.             /* if we are going to limit at the end of the buffer */
  171.             if (last_pos < fix_val)
  172.             {
  173.                 fix_val = last_pos;
  174.                 no_limit = FALSE;
  175.             }
  176.             rel_pos = fix_val - cur_pos;
  177.         }
  178.     }
  179.     while (TRUE)
  180.     {
  181.         if (rel_pos < 0)       /* move  backward through buffer */
  182.         {
  183.             /* current line? */
  184.             if (*l_off + rel_pos >= 0)
  185.             {
  186.                 *l_off += (short) rel_pos;
  187.                 return (no_limit);
  188.             }
  189.             /* are we at the first line */
  190.             if ((*line) -> l_bp -> l_size != 0)
  191.             {               /* no, so step back */
  192.                 rel_pos += *l_off;
  193.                 (*line) = (*line) -> l_bp;/* move back one line */
  194.                 *l_off = (*line) -> l_used;
  195.             }
  196.             else
  197.             {               /* yes, limit at the begining */
  198.                 *l_off = 0;
  199.                 return (FALSE);
  200.             }
  201.         }
  202.         else /* move forward through buffer */
  203.         {
  204.             /* is in current line? */
  205.             if (((A32)(*l_off) + rel_pos) < ((A32)((*line) -> l_used)))
  206.             {
  207.                 *l_off += (short) rel_pos;
  208.                 return (no_limit);
  209.             }
  210.             if ((*line) -> l_fp -> l_size != 0)
  211.             {
  212.                 rel_pos -= (*line) -> l_used - *l_off;
  213.                 *l_off = 0;
  214.                 (*line) = (*line) -> l_fp;/* move forward one line */
  215.             }
  216.             else
  217.             {
  218.                 *l_off = (*line) -> l_used;/* at last line so limit it */
  219.                 return (FALSE);
  220.             }
  221.         }
  222.     }
  223.     return (TRUE);
  224. }
  225.  
  226. /*  pvr
  227. *   Move the window so that the dot is within it's
  228. *   area.   Return TRUE if window was moved.
  229. */
  230.  
  231. bool wind_on_dot (wp)
  232.  
  233. WINDOW * wp;
  234. {
  235.     long    diff, incr;
  236.     A32     d_offs, w_start, bytes, align;
  237.  
  238.     /* number of bytes in a row */
  239.     bytes = R_BYTES(wp);
  240.     /* number of bytes to align on */
  241.     align = R_ALIGN(wp);
  242.     /* offset of window from start of the buffer */
  243.     w_start = WIND_POS(wp);
  244.     /* offset of dot from start of the buffer */
  245.     d_offs = DOT_POS(wp);
  246.     /* calculate the amount to move that is 1/3 of the window */
  247.     incr = bytes * wp -> w_ntrows / 3;
  248.     /* if dot is before first line in window */
  249.     if ((diff = (d_offs - w_start)) < 0)/* diff used later */
  250.     {
  251.         move_ptr (wp, diff - incr, FALSE, TRUE, TRUE);
  252.         wp -> w_flag |= WFHARD;
  253.         return (TRUE);
  254.     }
  255.     /* if dot is after the last line in window */
  256.     if (0 < (diff -= (wp -> w_ntrows * bytes - 1)))
  257.     {
  258.         if (align != 1)
  259.             diff = (diff & ~(align - 1)) + align;
  260.         move_ptr (wp, diff + incr, FALSE, TRUE, TRUE);
  261.         wp -> w_flag |= WFHARD;
  262.         return (TRUE);
  263.     }
  264.     /* is window aligned? */
  265.     if (w_start != ((w_start & ~(align - 1)) + wp -> w_disp_shift))
  266.     {                       /* if no then move into alignment */
  267.         move_ptr (wp, 0L, FALSE, TRUE, TRUE);
  268.         wp -> w_flag |= WFHARD;
  269.         return (TRUE);
  270.     }
  271.     return (FALSE);
  272. }
  273.  
  274. /*  pvr
  275. * Go to the beginning of the
  276. * buffer. Setting WFHARD is conservative,
  277. * but almost always the case.
  278. */
  279. bool gotobob ()
  280. {
  281.     move_ptr (curwp, 0L, TRUE, TRUE, FALSE);    /* move dot */
  282.     move_ptr (curwp, 0L, FALSE, TRUE, FALSE);   /* move window */
  283.     curwp -> w_unit_offset = 0;
  284.     curwp -> w_flag |= WFHARD;
  285.     return (TRUE);
  286. }
  287.  
  288.  
  289. /*  pvr
  290. * Go to the end of the buffer.
  291. * Setting WFHARD is conservative, but
  292. * almost always the case.
  293. * Dot is one byte past the end of the buffer.
  294. */
  295. bool gotoeob ()
  296. {
  297.     move_ptr (curwp, BUF_SIZE(curwp), TRUE, TRUE, FALSE);  /* move dot */
  298.     curwp -> w_unit_offset = 0;
  299.     wind_on_dot (curwp);
  300.     return (TRUE);
  301. }
  302.  
  303.  
  304. /*  pvr
  305. * Move forward by full lines.
  306. * If the number of lines to move is less
  307. * than zero, call the backward line function to
  308. * actually do it. The last command controls how
  309. * the goal column is set.
  310. */
  311. bool forwline (f, n, k)
  312. int f, n, k;
  313. {
  314.     if (n < 0)
  315.         return (backline (f, -n, KRANDOM));
  316.  
  317.     if (rplc_mode)
  318.     {
  319.         next_pat ();
  320.     }
  321.     else
  322.     {
  323.         /* move dot */
  324.         if (!move_ptr (curwp,  (long)R_BYTES(curwp) * n,
  325.             TRUE, TRUE, TRUE))
  326.             curwp -> w_unit_offset = 0;
  327.         wind_on_dot (curwp);
  328.         curwp -> w_flag |= WFMODE;  /* update mode line */
  329.     }
  330.     return (TRUE);
  331. }
  332.  
  333.  
  334. /*  pvr
  335. * This function is like "forwline", but
  336. * goes backwards. The scheme is exactly the same.
  337. * Check for arguments that are less than zero and
  338. * call your alternate. Figure out the new line and
  339. * call "movedot" to perform the motion.
  340. */
  341. bool backline (f, n, k)
  342. int f, n, k;
  343. {
  344.     if (n < 0)
  345.         return (forwline (f, -n, KRANDOM));
  346.  
  347.     if (rplc_mode)
  348.     {
  349.         next_pat ();
  350.     }
  351.     else
  352.     {
  353.         if (!move_ptr (curwp,  -((long)(R_BYTES(curwp) * n)),
  354.             TRUE, TRUE, TRUE))
  355.             curwp -> w_unit_offset = 0;
  356.  
  357.         /* is dot before the top of window? */
  358.         wind_on_dot (curwp);
  359.         curwp -> w_flag |= WFMODE;  /* update mode line */
  360.     }
  361.     return (TRUE);
  362. }
  363.  
  364. /*  pvr
  365. * Scroll forward by a specified number
  366. * of lines, or by a full page if no argument.
  367. * (KRW) Added cursor (dot) weighting to force cursor
  368. *       to same position on new page.
  369. */
  370. bool forwpage (f, n, k)
  371. register int f, n, k;
  372. {
  373.     long    mov_lines;
  374.  
  375.     if (rplc_mode)
  376.         next_pat ();
  377.     else
  378.     {
  379.         if (curwp -> w_ntrows <= 2)
  380.             mov_lines = 2;
  381.         else
  382.             mov_lines = curwp -> w_ntrows - 2;
  383.  
  384.         /* check if last line is already displayed */
  385.         if (WIND_POS(curwp) + (R_BYTES(curwp) * curwp -> w_ntrows) <
  386.             curwp -> w_bufp -> b_linep -> l_bp -> l_file_offset +
  387.             curwp -> w_bufp -> b_linep -> l_bp -> l_used)
  388.         {
  389.             move_ptr (curwp, (long)(R_BYTES(curwp) * mov_lines),
  390.                 FALSE, TRUE, TRUE);
  391.         }
  392.         /* move dot by same amount */
  393.         if (!move_ptr (curwp, (long)(R_BYTES(curwp) * mov_lines),
  394.             TRUE, TRUE, TRUE))
  395.             curwp -> w_unit_offset = 0;
  396.  
  397.         curwp -> w_flag |= WFHARD;
  398.     }
  399.     return (TRUE);
  400. }
  401.  
  402.  
  403. /*  pvr
  404. * This command is like "forwpage",
  405. * but it goes backwards.
  406. */
  407. bool backpage (f, n, k)
  408. register int f, n, k;
  409. {
  410.     long    mov_lines;
  411.  
  412.     if (rplc_mode)
  413.         next_pat ();
  414.     else
  415.     {
  416.         if (curwp -> w_ntrows <= 2)
  417.             mov_lines = 2;
  418.         else
  419.             mov_lines = curwp -> w_ntrows - 2;
  420.  
  421.         /* move window */
  422.         move_ptr (curwp, -(long)(R_BYTES(curwp) * mov_lines),
  423.             FALSE, TRUE, TRUE);
  424.         /* move dot by same amount */
  425.         if (!move_ptr (curwp, -(long)(R_BYTES(curwp) * mov_lines),
  426.             TRUE, TRUE, TRUE))
  427.             curwp -> w_unit_offset = 0;
  428.  
  429.         curwp -> w_flag |= WFHARD;
  430.     }
  431.     return (TRUE);
  432. }
  433.  
  434.  
  435. /*
  436. * Set the mark in the current window
  437. * to the value of dot. A message is written to
  438. * the echo line unless we are running in a keyboard
  439. * macro, when it would be silly.
  440. */
  441. bool setmark ()
  442. {
  443.  
  444.     if (curbp == blistp)        /* jam - hack to do goto/kill */
  445.         pickone ();
  446.     else
  447.     {
  448.         curwp -> w_markp = curwp -> w_dotp;
  449.         curwp -> w_marko = curwp -> w_doto;
  450.         if (kbdmop == NULL)
  451.         {
  452.             writ_echo (MSG_mark_set);
  453.         }
  454.     }
  455.     return (TRUE);
  456. }
  457.  
  458.  
  459. /*  pvr
  460. * Swap the values of "dot" and "mark" in
  461. * the current window. This is pretty easy, because
  462. * all of the hard work gets done by the standard routine
  463. * that moves the mark about. The only possible
  464. * error is "no mark".
  465. */
  466. bool swapmark ()
  467. {
  468.     register short  odoto;
  469.     register    LINE * odotp;
  470.  
  471.     if (curwp -> w_markp == NULL)
  472.     {
  473.         writ_echo (MSG_no_mark);
  474.         return (FALSE);
  475.     }
  476.  
  477.     odotp = curwp -> w_dotp;
  478.     curwp -> w_dotp = curwp -> w_markp;
  479.     curwp -> w_markp = odotp;
  480.     odoto = curwp -> w_doto;
  481.     curwp -> w_doto = curwp -> w_marko;
  482.     curwp -> w_marko = odoto;
  483.     wind_on_dot (curwp);
  484.     curwp -> w_flag |= WFMODE;  /* update mode line */
  485.     return (TRUE);
  486. }
  487.  
  488. /*  pvr
  489. * Go to a specific byte position in buffer.
  490. * If an argument is present, then
  491. * it is the byte number, else prompt for a byte number
  492. * to use.
  493. */
  494. bool gotoline (f, n, k)
  495. int f, n, k;
  496. {
  497.     A32      index;
  498.     register int    s;
  499.     char    buf[32];
  500.  
  501.     if (f == FALSE)
  502.     {
  503.  
  504.         if ((s = ereply (MSG_go_b_n, buf, sizeof (buf), 0) != TRUE))
  505.             return (s);
  506.         switch (R_TYPE(curwp))
  507.         {
  508.         case TEXT:
  509.         case ASCII:
  510.         case EBCDIC:
  511.         case BINARY:
  512.         case HEX:
  513.             sscanf (buf, MSG_lX, &index);
  514.             break;
  515.         case OCTAL:
  516.             sscanf (buf, MSG_lO, &index);
  517.             break;
  518.         case DECIMAL:
  519.             sscanf (buf, MSG_lD, &index);
  520.             break;
  521. #if RUNCHK
  522.         default:
  523.             writ_echo (ERR_bas_1);
  524.             break;
  525. #endif
  526.         }
  527.     }
  528.  
  529.     if (n <= 0)
  530.     {
  531.         writ_echo (MSG_bad_num);
  532.         return (FALSE);
  533.     }
  534.  
  535.     move_ptr (curwp, index, TRUE, TRUE, FALSE);
  536.     curwp -> w_unit_offset = 0;
  537.  
  538.     curwp -> w_flag |= WFMODE;  /* update mode line */
  539.  
  540.     wind_on_dot (curwp);
  541.     return (TRUE);
  542. }
  543.  
  544.