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