home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2874 / basic.c next >
Encoding:
C/C++ Source or Header  |  1991-02-28  |  13.6 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. #include    "lintfunc.dec"
  29.  
  30. extern  bool    rplc_mode;
  31.  
  32. /*  pvr
  33. * Move cursor backwards. Do the
  34. * right thing if the count is less than
  35. * 0. Error if you try to move back from
  36. * the beginning of the buffer.
  37. */
  38. bool backchar (f, n, k)
  39. register int    n;
  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 forwchar (f, n, k)
  72. register int    n;
  73. {
  74.     if (n < 0)
  75.         return (backchar (f, -n, KRANDOM));
  76.  
  77.     curwp -> w_flag |= WFMODE;  /* update mode line */
  78.     while (n--)
  79.         {
  80.         if (curwp -> w_unit_offset >= (R_CHR_PER_U(curwp) - 1))
  81.             {
  82.         /* move to the mext unit */
  83.             curwp -> w_unit_offset = 0;
  84.  
  85.             if (!move_ptr (curwp,  (long)R_B_PER_U(curwp),
  86.                     TRUE, TRUE, TRUE))
  87.                 {
  88.             /* I am at the the end of the buffer */
  89.                 return (FALSE);
  90.                 }
  91.  
  92.         /* if after the last line in window then move window */
  93.             wind_on_dot (curwp);
  94.             }
  95.         else   /* if at last byte of buffer then do not step  */
  96.             if (DOT_POS(curwp) < BUF_SIZE(curwp))
  97.                 curwp -> w_unit_offset++;/* step within unit */
  98.         }
  99.     return (TRUE);
  100. }
  101.  
  102. /*  pvr
  103. *   This function moves the specified pointer by the ammount specified
  104. *   in 'len'.   Move the dot pointer is 'dot' is true, else move
  105. *   the window pointer.  Do the fix up if 'fix' is TRUE.
  106. *   This is a relative move if 'rel' is TRUE, else it is an
  107. *   absolute move.
  108. */
  109.  
  110. bool    move_ptr (wp, len, dot, fix, rel)
  111. WINDOW  *wp;
  112. long    len;
  113. bool    dot, fix, rel;  
  114. {
  115.     A32     cur_pos, dest_pos, fix_val, last_pos;
  116.     long    rel_pos;
  117.     A32     last_fixed_pos, align;
  118.     LINE    **line, *line_guess;
  119.     int     *l_off;
  120.     char    shift;
  121.     bool    no_limit;
  122.  
  123.     no_limit = TRUE;
  124.     if (dot)
  125.         {                       /* move dot position */
  126.         l_off = &wp -> w_doto;
  127.         line = &wp -> w_dotp;
  128.         align = R_SIZE(wp);  /* bytes -1 in a unit */
  129.         }
  130.     else
  131.         {                       /* move window position */
  132.         l_off = &wp -> w_loff;
  133.         line = &wp -> w_linep;
  134.         align = R_ALIGN(wp) - 1; /* interval of bytes to align window */
  135.         }
  136.  
  137.     /* get the current position in the buffer */
  138.     cur_pos = (*line) -> l_file_offset + *l_off;
  139.  
  140.     if (rel)
  141.         {
  142.         rel_pos = len;
  143.         dest_pos = len + cur_pos;   /* destination position */
  144.         }
  145.     else
  146.         {
  147.         rel_pos = len - cur_pos;   /* relative move amount */
  148.         dest_pos = len;   /* destination position */
  149.         }
  150.     if (fix)
  151.         {
  152.         shift = wp -> w_disp_shift;
  153.  
  154.         /* limit at begining */
  155.         if (dest_pos < shift)
  156.             {
  157.             rel_pos = shift - cur_pos;
  158.             no_limit = FALSE;
  159.             }
  160.         else
  161.             {
  162.             /* calculate fixed up destination position */
  163.             fix_val = dest_pos &= ~align;
  164.             fix_val += shift;
  165.  
  166.             /* calculate the last position in the buffer */
  167.             last_pos = BUF_SIZE(wp);
  168.             if (last_pos < (last_fixed_pos = (last_pos & ~align) + shift))
  169.                 last_pos = last_fixed_pos - align - 1;
  170.  
  171.             /* if we are going to limit at the end of the buffer */
  172.             if (last_pos < fix_val)
  173.                 {
  174.                 fix_val = last_pos;
  175.                 no_limit = FALSE;
  176.                 }
  177.             rel_pos = fix_val - cur_pos; 
  178.             }
  179.         }
  180.     while (TRUE)
  181.         {
  182.         if (rel_pos < 0)       /* move  backward through buffer */
  183.             {
  184.             /* current line? */
  185.             if (*l_off + rel_pos >= 0)
  186.                 {
  187.                 *l_off += (short) rel_pos;
  188.                 return (no_limit);
  189.                 }
  190.         /* are we at the first line */
  191.             if ((*line) -> l_bp -> l_size != 0)
  192.                 {               /* no, so step back */
  193.                 rel_pos += *l_off;
  194.                 (*line) = (*line) -> l_bp;/* move back one line */
  195.                 *l_off = (*line) -> l_used;
  196.                 }
  197.             else
  198.                 {               /* yes, limit at the begining */
  199.                 *l_off = 0;
  200.                 return (FALSE);
  201.                 }
  202.             }
  203.         else                    /* move forward through buffer */
  204.             {
  205.         /* is in current line? */
  206.             if (((A32)(*l_off) + rel_pos) < ((A32)((*line) -> l_used)))
  207.                 {
  208.                 *l_off += (short) rel_pos;
  209.                 return (no_limit);
  210.                 }
  211.             if ((*line) -> l_fp -> l_size != 0)
  212.                 {
  213.                 rel_pos -= (*line) -> l_used - *l_off;
  214.                 *l_off = 0;
  215.                 (*line) = (*line) -> l_fp;/* move forward one line */
  216.                 }
  217.             else
  218.                 {
  219.                 *l_off = (*line) -> l_used;/* at last line so limit it */
  220.                 return (FALSE);
  221.                 }
  222.             }
  223.         }
  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.     long    f_off;
  298.     long    index;
  299.  
  300.     move_ptr (curwp, BUF_SIZE(curwp), TRUE, TRUE, FALSE);  /* move dot */
  301.     curwp -> w_unit_offset = 0;
  302.     wind_on_dot (curwp);
  303.     return (TRUE);
  304. }
  305.  
  306.  
  307. /*  pvr
  308. * Move forward by full lines.
  309. * If the number of lines to move is less
  310. * than zero, call the backward line function to
  311. * actually do it. The last command controls how
  312. * the goal column is set.
  313. */
  314. bool forwline (f, n, k)
  315. {
  316.     if (n < 0)
  317.         return (backline (f, -n, KRANDOM));
  318.  
  319.     if (rplc_mode)
  320.     {
  321.         next_pat ();
  322.     }
  323.     else
  324.     {
  325.      /* move dot */
  326.         if (!move_ptr (curwp,  (long)R_BYTES(curwp) * n,
  327.                  TRUE, TRUE, TRUE))
  328.             curwp -> w_unit_offset = 0;
  329.         wind_on_dot (curwp);
  330.         curwp -> w_flag |= WFMODE;  /* update mode line */
  331.     }
  332.     return (TRUE);
  333. }
  334.  
  335.  
  336. /*  pvr
  337. * This function is like "forwline", but
  338. * goes backwards. The scheme is exactly the same.
  339. * Check for arguments that are less than zero and
  340. * call your alternate. Figure out the new line and
  341. * call "movedot" to perform the motion.
  342. */
  343. bool backline (f, n, k)
  344. {
  345.     if (n < 0)
  346.         return (forwline (f, -n, KRANDOM));
  347.  
  348.     if (rplc_mode)
  349.     {
  350.         next_pat ();
  351.     }
  352.     else
  353.     {
  354.         if (!move_ptr (curwp,  -((long)(R_BYTES(curwp) * n)),
  355.                  TRUE, TRUE, TRUE))
  356.             curwp -> w_unit_offset = 0;
  357.  
  358.      /* is dot before the top of window? */
  359.         wind_on_dot (curwp);
  360.         curwp -> w_flag |= WFMODE;  /* update mode line */
  361.     }   
  362.     return (TRUE);
  363. }
  364.  
  365. /*  pvr
  366. * Scroll forward by a specified number
  367. * of lines, or by a full page if no argument.
  368. * (KRW) Added cursor (dot) weighting to force cursor
  369. *       to same position on new page.
  370. */
  371. bool forwpage (f, n, k)
  372. register int    n;
  373. {
  374.     long    mov_lines;
  375.  
  376.     if (rplc_mode)
  377.         next_pat ();
  378.     else
  379.     {
  380.         if (curwp -> w_ntrows <= 2)
  381.             mov_lines = 2;
  382.         else
  383.             mov_lines = curwp -> w_ntrows - 2;
  384.  
  385.      /* check if last line is already displayed */
  386.         if (WIND_POS(curwp) + (R_BYTES(curwp) * curwp -> w_ntrows) <
  387.                 curwp -> w_bufp -> b_linep -> l_bp -> l_file_offset +
  388.                 curwp -> w_bufp -> b_linep -> l_bp -> l_used)
  389.             {
  390.             move_ptr (curwp, (long)(R_BYTES(curwp) * mov_lines),
  391.                  FALSE, TRUE, TRUE);
  392.             }
  393.      /* move dot by same amount */
  394.         if (!move_ptr (curwp, (long)(R_BYTES(curwp) * mov_lines),
  395.                  TRUE, TRUE, TRUE))
  396.             curwp -> w_unit_offset = 0;
  397.  
  398.         curwp -> w_flag |= WFHARD;
  399.     }
  400.     return (TRUE);
  401. }
  402.  
  403.  
  404. /*  pvr
  405. * This command is like "forwpage",
  406. * but it goes backwards. 
  407. */
  408. bool backpage (f, n, k)
  409. register int    n;
  410. {
  411.     long    mov_lines;
  412.  
  413.     if (rplc_mode)
  414.         next_pat ();
  415.     else
  416.     {
  417.         if (curwp -> w_ntrows <= 2)
  418.             mov_lines = 2;
  419.         else
  420.             mov_lines = curwp -> w_ntrows - 2;
  421.  
  422.      /* move window */
  423.         move_ptr (curwp, -(long)(R_BYTES(curwp) * mov_lines),
  424.                  FALSE, TRUE, TRUE);
  425.      /* move dot by same amount */
  426.         if (!move_ptr (curwp, -(long)(R_BYTES(curwp) * mov_lines),
  427.                  TRUE, TRUE, TRUE))
  428.             curwp -> w_unit_offset = 0;
  429.  
  430.         curwp -> w_flag |= WFHARD;
  431.     }
  432.     return (TRUE);
  433. }
  434.  
  435.  
  436. /*
  437. * Set the mark in the current window
  438. * to the value of dot. A message is written to
  439. * the echo line unless we are running in a keyboard
  440. * macro, when it would be silly.
  441. */
  442. bool setmark ()
  443. {
  444.  
  445.     if (curbp == blistp)        /* jam - hack to do goto/kill */
  446.         pickone ();
  447.     else
  448.         {
  449.         curwp -> w_markp = curwp -> w_dotp;
  450.         curwp -> w_marko = curwp -> w_doto;
  451.         if (kbdmop == NULL)
  452.             {
  453.             writ_echo (MSG_mark_set);
  454.             }
  455.         }
  456.     return (TRUE);
  457. }
  458.  
  459.  
  460. /*  pvr
  461. * Swap the values of "dot" and "mark" in
  462. * the current window. This is pretty easy, because
  463. * all of the hard work gets done by the standard routine
  464. * that moves the mark about. The only possible
  465. * error is "no mark".
  466. */
  467. bool swapmark ()
  468. {
  469.     register short  odoto;
  470.     register    LINE * odotp;
  471.  
  472.     if (curwp -> w_markp == NULL)
  473.         {
  474.         writ_echo (MSG_no_mark);
  475.         return (FALSE);
  476.         }
  477.  
  478.     odotp = curwp -> w_dotp;
  479.     curwp -> w_dotp = curwp -> w_markp;
  480.     curwp -> w_markp = odotp;
  481.     odoto = curwp -> w_doto;
  482.     curwp -> w_doto = curwp -> w_marko;
  483.     curwp -> w_marko = odoto;
  484.     wind_on_dot (curwp);
  485.     curwp -> w_flag |= WFMODE;  /* update mode line */
  486.     return (TRUE);
  487. }
  488.  
  489. /*  pvr
  490. * Go to a specific byte position in buffer.
  491. * If an argument is present, then
  492. * it is the byte number, else prompt for a byte number
  493. * to use.
  494. */
  495. bool gotoline (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.