home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / util / jade-3.0.lha / Jade / src / movement.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-19  |  20.9 KB  |  794 lines

  1. /* movement.c -- Positioning the cursor
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4. This file is part of Jade.
  5.  
  6. Jade is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. Jade is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with Jade; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. #include <ctype.h>
  24.  
  25. _PR long movedownpages(long);
  26. _PR long moveuppages(long);
  27. static int findmatchingbracket(POS *, TX *);
  28. _PR void movement_init(void);
  29.  
  30. _PR VALUE cmd_screen_top_line(void);
  31. DEFUN("screen-top-line", cmd_screen_top_line, subr_screen_top_line, (void), V_Subr0, DOC_screen_top_line) /*
  32. ::doc:screen_top_line::
  33. (screen-top-line)
  34. Returns the line number of the first line being shown in the current window.
  35. ::end:: */
  36. {
  37.     return(newnumber(CurrVW->vw_StartLine + 1));
  38. }
  39.  
  40. _PR VALUE cmd_screen_bottom_line(void);
  41. DEFUN("screen-bottom-line", cmd_screen_bottom_line, subr_screen_bottom_line, (void), V_Subr0, DOC_screen_bottom_line) /*
  42. ::doc:screen_bottom_line::
  43. (screen-bottom-line)
  44. Returns the line number of the last line being shown in the current window.
  45. ::end:: */
  46. {
  47.     return(newnumber(CurrVW->vw_StartLine + CurrVW->vw_MaxY));
  48. }
  49.  
  50. _PR VALUE cmd_screen_first_column(void);
  51. DEFUN("screen-first-column", cmd_screen_first_column, subr_screen_first_column, (void), V_Subr0, DOC_screen_first_column) /*
  52. ::doc:screen_first_column::
  53. (screen-first-column)
  54. Returns the line number of the first column being shown in the current window.
  55. ::end:: */
  56. {
  57.     return(newnumber(CurrVW->vw_StartCol + 1));
  58. }
  59.  
  60. _PR VALUE cmd_screen_last_column(void);
  61. DEFUN("screen-last-column", cmd_screen_last_column, subr_screen_last_column, (void), V_Subr0, DOC_screen_last_column) /*
  62. ::doc:screen_last_column::
  63. (screen-last-column)
  64. Returns the line number of the last column being shown in the current window.
  65. ::end:: */
  66. {
  67.     return(newnumber(CurrVW->vw_StartCol + CurrVW->vw_MaxX));
  68. }
  69.  
  70. _PR VALUE cmd_goto(VALUE pos);
  71. DEFUN("goto", cmd_goto, subr_goto, (VALUE pos), V_Subr1, DOC_goto) /*
  72. ::doc:goto::
  73. (goto POS)
  74. Set the cursor position in the current window to POS.
  75. ::end:: */
  76. {
  77.     VW *vw = CurrVW;
  78.     DECLARE1(pos, POSP);
  79.     if(checkline(vw->vw_Tx, &VPOS(pos)))
  80.     {
  81.     vw->vw_CursorPos = VPOS(pos);
  82.     return(pos);
  83.     }
  84.     return(sym_nil);
  85. }
  86.  
  87. _PR VALUE cmd_next_screen(VALUE number);
  88. DEFUN("next-screen", cmd_next_screen, subr_next_screen, (VALUE number), V_Subr1, DOC_next_screen) /*
  89. ::doc:next_screen::
  90. (next-screen [NUMBER])
  91. Move NUMBER (default: 1) screens forwards in the current window.
  92. ::end:: */
  93. {
  94.     if(movedownpages(NUMBERP(number) ? VNUM(number) : 1))
  95.     return(sym_t);
  96.     return(sym_nil);
  97. }
  98.  
  99. _PR VALUE cmd_prev_screen(VALUE number);
  100. DEFUN("prev-screen", cmd_prev_screen, subr_prev_screen, (VALUE number), V_Subr1, DOC_prev_screen) /*
  101. ::doc:prev_screen::
  102. (prev-screen [NUMBER])
  103. Move NUMBER (default: 1) screens backwards in the current window.
  104. ::end:: */
  105. {
  106.     if(moveuppages(NUMBERP(number) ? VNUM(number) : 1))
  107.     return(sym_t);
  108.     return(sym_nil);
  109. }
  110.  
  111. _PR VALUE cmd_file_end(VALUE tx);
  112. DEFUN("file-end", cmd_file_end, subr_file_end, (VALUE tx), V_Subr1, DOC_file_end) /*
  113. ::doc:file_end::
  114. (file-end [BUFFER])
  115. Return the position of the last character in BUFFER.
  116. ::end:: */
  117. {
  118.     long x, y;
  119.     if(!BUFFERP(tx))
  120.     tx = CurrVW->vw_Tx;
  121.     y = VTX(tx)->tx_NumLines - 1;
  122.     x = VTX(tx)->tx_Lines[y].ln_Strlen - 1;
  123.     return(newlpos2(x, y));
  124. }
  125.  
  126. _PR VALUE cmd_goto_file_end(void);
  127. DEFUN("goto-file-end", cmd_goto_file_end, subr_goto_file_end, (void), V_Subr0, DOC_goto_file_end) /*
  128. ::doc:goto_file_end::
  129. (goto-file-end)
  130. Move to the last character in the current window.
  131. ::end:: */
  132. {
  133.     VW *vw = CurrVW;
  134.     vw->vw_CursorPos.pos_Line = vw->vw_Tx->tx_NumLines - 1;
  135.     vw->vw_CursorPos.pos_Col = vw->vw_Tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen - 1;
  136.     return(sym_t);
  137. }
  138.  
  139. _PR VALUE cmd_file_start(void);
  140. DEFUN("file-start", cmd_file_start, subr_file_start, (void), V_Subr0, DOC_file_start) /*
  141. ::doc:file_start::
  142. (file-start)
  143. Return the position of the start of the file.
  144. ::end:: */
  145. {
  146.     return(newlpos2(0, 0));
  147. }
  148.  
  149. _PR VALUE cmd_goto_file_start(void);
  150. DEFUN("goto-file-start", cmd_goto_file_start, subr_goto_file_start, (void), V_Subr0, DOC_goto_file_start) /*
  151. ::doc:goto_file_start::
  152. (goto-file-start)
  153. Move to the first character in the buffer displayed in the current window.
  154. ::end:: */
  155. {
  156.     CurrVW->vw_CursorPos.pos_Col = 0;
  157.     CurrVW->vw_CursorPos.pos_Line = 0;
  158.     return(sym_t);
  159. }
  160.  
  161. _PR VALUE cmd_line_end(VALUE pos, VALUE tx);
  162. DEFUN("line-end", cmd_line_end, subr_line_end, (VALUE pos, VALUE tx), V_Subr2, DOC_line_end) /*
  163. ::doc:line_end::
  164. (line-end [POS] [BUFFER])
  165. Return the position of the last character in the line pointed to by POS (or
  166. the cursor).
  167. ::end:: */
  168. {
  169.     POS res;
  170.     if(!BUFFERP(tx))
  171.     tx = CurrVW->vw_Tx;
  172.     if(POSP(pos))
  173.     res.pos_Line = VPOS(pos).pos_Line;
  174.     else
  175.     res.pos_Line = gettxcurspos(VTX(tx))->pos_Line;
  176.     if(res.pos_Line < VTX(tx)->tx_NumLines)
  177.     {
  178.     res.pos_Col = VTX(tx)->tx_Lines[res.pos_Line].ln_Strlen - 1;
  179.     return(newlpos(&res));
  180.     }
  181.     return(sym_nil);
  182. }
  183.  
  184. _PR VALUE cmd_goto_line_end(void);
  185. DEFUN("goto-line-end", cmd_goto_line_end, subr_goto_line_end, (void), V_Subr0, DOC_goto_line_end) /*
  186. ::doc:goto_line_end::
  187. (goto-line-end)
  188. Move to the last character in the line.
  189. ::end:: */
  190. {
  191.     VW *vw = CurrVW;
  192.     vw->vw_CursorPos.pos_Col = vw->vw_Tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen - 1;
  193.     return(sym_t);
  194. }
  195.  
  196. _PR VALUE cmd_line_start(VALUE pos);
  197. DEFUN("line-start", cmd_line_start, subr_line_start, (VALUE pos), V_Subr1, DOC_line_start) /*
  198. ::doc:line_start::
  199. (line-start [POS])
  200. Return the position of the first character in the line pointed to by POS
  201. (or the cursor).
  202. ::end:: */
  203. {
  204.     POS res;
  205.     if(POSP(pos))
  206.     res.pos_Line = VPOS(pos).pos_Line;
  207.     else
  208.     res.pos_Line = CurrVW->vw_CursorPos.pos_Line;
  209.     res.pos_Col = 0;
  210.     return(newlpos(&res));
  211. }
  212.  
  213. _PR VALUE cmd_goto_line_start(void);
  214. DEFUN("goto-line-start", cmd_goto_line_start, subr_goto_line_start, (void), V_Subr0, DOC_goto_line_start) /*
  215. ::doc:goto_line_start::
  216. (goto-line-start)
  217. Move to the start of the current line.
  218. ::end:: */
  219. {
  220.     VW *vw = CurrVW;
  221.     vw->vw_CursorPos.pos_Col = 0;
  222.     return(sym_t);
  223. }
  224.  
  225. _PR VALUE cmd_next_line(VALUE lines, VALUE pos);
  226. DEFUN("next-line", cmd_next_line, subr_next_line, (VALUE lines, VALUE pos), V_Subr2, DOC_next_line) /*
  227. ::doc:next_line::
  228. (next-line [NUMBER] [POS])
  229. Return the position of the NUMBERth (def: 1) line down from that pointed to
  230. by POS (or the cursor). POS is altered.
  231. ::end:: */
  232. {
  233.     if(!POSP(pos))
  234.     pos = newlpos(&CurrVW->vw_CursorPos);
  235.     VPOS(pos).pos_Line += NUMBERP(lines) ? VNUM(lines) : 1;
  236.     if(VPOS(pos).pos_Line > 0)
  237.     return(pos);
  238.     return(sym_nil);
  239. }
  240.  
  241. _PR VALUE cmd_goto_next_line(VALUE lines);
  242. DEFUN("goto-next-line", cmd_goto_next_line, subr_goto_next_line, (VALUE lines), V_Subr1, DOC_goto_next_line) /*
  243. ::doc:goto_next_line::
  244. (goto-next-line [NUMBER])
  245. Move NUMBER lines (def: 1) downwards.
  246. ::end:: */
  247. {
  248.     VW *vw = CurrVW;
  249.     vw->vw_CursorPos.pos_Line += NUMBERP(lines) ? VNUM(lines) : 1;
  250.     if(vw->vw_CursorPos.pos_Line >= vw->vw_Tx->tx_NumLines)
  251.     {
  252.     vw->vw_CursorPos.pos_Line = vw->vw_Tx->tx_NumLines - 1;
  253.     return(sym_nil);
  254.     }
  255.     else if(vw->vw_CursorPos.pos_Line < 0)
  256.     {
  257.     vw->vw_CursorPos.pos_Line = 0;
  258.     return(sym_nil);
  259.     }
  260.     return(sym_t);
  261. }
  262.  
  263. _PR VALUE cmd_prev_line(VALUE lines, VALUE pos);
  264. DEFUN("prev-line", cmd_prev_line, subr_prev_line, (VALUE lines, VALUE pos), V_Subr2, DOC_prev_line) /*
  265. ::doc:prev_line::
  266. (prev-line [NUMBER] [POS])
  267. Return the position of the NUMBERth (def: 1) line up from that pointed to
  268. by POS (or the cursor). POS is altered.
  269. ::end:: */
  270. {
  271.     if(!POSP(pos))
  272.     pos = newlpos(&CurrVW->vw_CursorPos);
  273.     VPOS(pos).pos_Line -= NUMBERP(lines) ? VNUM(lines) : 1;
  274.     if(VPOS(pos).pos_Line >= 0)
  275.     return(pos);
  276.     return(sym_nil);
  277. }
  278.  
  279. _PR VALUE cmd_goto_prev_line(VALUE lines);
  280. DEFUN("goto-prev-line", cmd_goto_prev_line, subr_goto_prev_line, (VALUE lines), V_Subr1, DOC_goto_prev_line) /*
  281. ::doc:goto_prev_line::
  282. (goto-next-line [NUMBER])
  283. Move NUMBER lines (def: 1) upwards.
  284. ::end:: */
  285. {
  286.     VW *vw = CurrVW;
  287.     vw->vw_CursorPos.pos_Line -= NUMBERP(lines) ? VNUM(lines) : 1;
  288.     if(vw->vw_CursorPos.pos_Line >= vw->vw_Tx->tx_NumLines)
  289.     {
  290.     vw->vw_CursorPos.pos_Line = vw->vw_Tx->tx_NumLines - 1;
  291.     return(sym_nil);
  292.     }
  293.     else if(vw->vw_CursorPos.pos_Line < 0)
  294.     {
  295.     vw->vw_CursorPos.pos_Line = 0;
  296.     return(sym_nil);
  297.     }
  298.     return(sym_t);
  299. }
  300.  
  301. _PR VALUE cmd_left_char(VALUE chars, VALUE pos);
  302. DEFUN("left-char", cmd_left_char, subr_left_char, (VALUE chars, VALUE pos), V_Subr2, DOC_left_char) /*
  303. ::doc:left_char::
  304. (left-char [NUMBER] [POS])
  305. Return the position of the NUMBERth character (def: 1) to the left of the
  306. one pointed to by POS (or the cursor). If that position is before the
  307. beginning of the line, returns nil. POS is altered.
  308. ::end:: */
  309. {
  310.     if(!POSP(pos))
  311.     pos = newlpos(&CurrVW->vw_CursorPos);
  312.     VPOS(pos).pos_Col -= NUMBERP(chars) ? VNUM(chars) : 1;
  313.     if(VPOS(pos).pos_Col >= 0)
  314.     return(pos);
  315.     return(sym_nil);
  316. }
  317.  
  318. _PR VALUE cmd_goto_left_char(VALUE chars);
  319. DEFUN("goto-left-char", cmd_goto_left_char, subr_goto_left_char, (VALUE chars), V_Subr1, DOC_goto_left_char) /*
  320. ::doc:goto_left_char::
  321. (goto-left-char [NUMBER])
  322. Move NUMBER chars (def: 1) to the left.
  323. ::end:: */
  324. {
  325.     VW *vw = CurrVW;
  326.     vw->vw_CursorPos.pos_Col -= NUMBERP(chars) ? VNUM(chars) : 1;
  327.     if(vw->vw_CursorPos.pos_Col > 0)
  328.     return(sym_t);
  329.     vw->vw_CursorPos.pos_Col = 0;
  330.     return(sym_nil);
  331. }
  332.  
  333. _PR VALUE cmd_right_char(VALUE chars, VALUE pos);
  334. DEFUN("right-char", cmd_right_char, subr_right_char, (VALUE chars, VALUE pos), V_Subr2, DOC_right_char) /*
  335. ::doc:right_char::
  336. (right-char [NUMBER] [POS])
  337. Return the position of the NUMBERth character (def: 1) to the right of the
  338. one pointed to by POS (or the cursor). Doesn't pay any attention to newlines.
  339. POS is altered.
  340. ::end:: */
  341. {
  342.     if(!POSP(pos))
  343.     pos = newlpos(&CurrVW->vw_CursorPos);
  344.     VPOS(pos).pos_Col += NUMBERP(chars) ? VNUM(chars) : 1;
  345.     if(VPOS(pos).pos_Col >= 0)
  346.     return(pos);
  347.     return(sym_nil);
  348. }
  349.  
  350. _PR VALUE cmd_goto_right_char(VALUE chars);
  351. DEFUN("goto-right-char", cmd_goto_right_char, subr_goto_right_char, (VALUE chars), V_Subr1, DOC_goto_right_char) /*
  352. ::doc:goto_right_char::
  353. (goto-right-char [NUMBER])
  354. Move NUMBER chars (def: 1) to the right
  355. ::end:: */
  356. {
  357.     VW *vw = CurrVW;
  358.     vw->vw_CursorPos.pos_Col += NUMBERP(chars) ? VNUM(chars) : 1;
  359.     if(vw->vw_CursorPos.pos_Col > 0)
  360.     return(sym_t);
  361.     vw->vw_CursorPos.pos_Col = 0;
  362.     return(sym_nil);
  363. }
  364.  
  365. _PR VALUE cmd_prev_tab(VALUE num, VALUE pos);
  366. DEFUN("prev-tab", cmd_prev_tab, subr_prev_tab, (VALUE num, VALUE pos), V_Subr2, DOC_prev_tab) /*
  367. ::doc:prev_tab::
  368. (prev-tab [NUMBER] [POS])
  369. Return the position of the NUMBERth (def: 1) tab stop to the left of POS (or
  370. the cursor). Returns nil if that position is past the beginning of the line.
  371. POS is altered.
  372. ::end:: */
  373. {
  374.     int tabs = 1;
  375.     VW *vw = CurrVW;
  376.     if(!POSP(pos))
  377.     pos = newlpos(&CurrVW->vw_CursorPos);
  378.     if(NUMBERP(num))
  379.     tabs = VNUM(num);
  380.     if(tabs > 0)
  381.     {
  382.     while(tabs--)
  383.         VPOS(pos).pos_Col = (((VPOS(pos).pos_Col - 1) / vw->vw_Tx->tx_TabSize)) * vw->vw_Tx->tx_TabSize;
  384.     }
  385.     else if(tabs < 0)
  386.     {
  387.     while(tabs++)
  388.         VPOS(pos).pos_Col = ((VPOS(pos).pos_Col / vw->vw_Tx->tx_TabSize) + 1) * vw->vw_Tx->tx_TabSize;
  389.     }
  390.     if(VPOS(pos).pos_Col >= 0)
  391.     return(pos);
  392.     VPOS(pos).pos_Col = 0;
  393.     return(sym_nil);
  394. }
  395.  
  396. _PR VALUE cmd_goto_prev_tab(VALUE num);
  397. DEFUN("goto-prev-tab", cmd_goto_prev_tab, subr_goto_prev_tab, (VALUE num), V_Subr1, DOC_goto_prev_tab) /*
  398. ::doc:goto_prev_tab::
  399. (goto-prev-tab [NUMBER])
  400. Move NUMBER (def: 1) tab stops to the left.
  401. ::end:: */
  402. {
  403.     int tabs = 1;
  404.     VW *vw = CurrVW;
  405.     if(NUMBERP(num))
  406.     tabs = VNUM(num);
  407.     if(tabs > 0)
  408.     {
  409.     while(tabs--)
  410.         vw->vw_CursorPos.pos_Col = (((vw->vw_CursorPos.pos_Col - 1) / vw->vw_Tx->tx_TabSize)) * vw->vw_Tx->tx_TabSize;
  411.     }
  412.     else if(tabs < 0)
  413.     {
  414.     while(tabs++)
  415.         vw->vw_CursorPos.pos_Col = ((vw->vw_CursorPos.pos_Col / vw->vw_Tx->tx_TabSize) + 1) * vw->vw_Tx->tx_TabSize;
  416.     }
  417.     if(vw->vw_CursorPos.pos_Col >= 0)
  418.     return(sym_t);
  419.     vw->vw_CursorPos.pos_Col = 0;
  420.     return(sym_nil);
  421. }
  422.  
  423. _PR VALUE cmd_next_tab(VALUE num, VALUE pos);
  424. DEFUN("next-tab", cmd_next_tab, subr_next_tab, (VALUE num, VALUE pos), V_Subr2, DOC_next_tab) /*
  425. ::doc:next_tab::
  426. (next-tab [NUMBER] [POS])
  427. Return the position of the NUMBERth (def: 1) tab stop to the right of POS (or
  428. the cursor). POS is altered.
  429. ::end:: */
  430. {
  431.     int tabs = 1;
  432.     VW *vw = CurrVW;
  433.     if(!POSP(pos))
  434.     pos = newlpos(&CurrVW->vw_CursorPos);
  435.     if(NUMBERP(num))
  436.     tabs = VNUM(num);
  437.     if(tabs > 0)
  438.     {
  439.     while(tabs--)
  440.         VPOS(pos).pos_Col = ((VPOS(pos).pos_Col / vw->vw_Tx->tx_TabSize) + 1) * vw->vw_Tx->tx_TabSize;
  441.     }
  442.     else if(tabs < 0)
  443.     {
  444.     while(tabs++)
  445.         VPOS(pos).pos_Col = (((VPOS(pos).pos_Col - 1) / vw->vw_Tx->tx_TabSize)) * vw->vw_Tx->tx_TabSize;
  446.     }
  447.     if(VPOS(pos).pos_Col >= 0)
  448.     return(pos);
  449.     VPOS(pos).pos_Col = 0;
  450.     return(sym_nil);
  451. }
  452.  
  453. _PR VALUE cmd_goto_next_tab(VALUE num);
  454. DEFUN("goto-next-tab", cmd_goto_next_tab, subr_goto_next_tab, (VALUE num), V_Subr1, DOC_goto_next_tab) /*
  455. ::doc:goto_next_tab::
  456. (goto-next-tab [NUMBER])
  457. Move NUMBER (def: 1) tab stops to the right
  458. ::end:: */
  459. {
  460.     int tabs = 1;
  461.     VW *vw = CurrVW;
  462.     if(NUMBERP(num))
  463.     tabs = VNUM(num);
  464.     if(tabs > 0)
  465.     {
  466.     while(tabs--)
  467.         vw->vw_CursorPos.pos_Col = ((vw->vw_CursorPos.pos_Col / vw->vw_Tx->tx_TabSize) + 1) * vw->vw_Tx->tx_TabSize;
  468.     }
  469.     else if(tabs < 0)
  470.     {
  471.     while(tabs++)
  472.         vw->vw_CursorPos.pos_Col = (((vw->vw_CursorPos.pos_Col - 1) / vw->vw_Tx->tx_TabSize)) * vw->vw_Tx->tx_TabSize;
  473.     }
  474.     if(vw->vw_CursorPos.pos_Col >= 0)
  475.     return(sym_t);
  476.     vw->vw_CursorPos.pos_Col = 0;
  477.     return(sym_nil);
  478. }
  479.  
  480. static INLINE int
  481. prevchar(POS *pos, TX *tx)
  482. {
  483.     if(--pos->pos_Col < 0)
  484.     {
  485.     if(--pos->pos_Line >= 0)
  486.     {
  487.         pos->pos_Col = tx->tx_Lines[pos->pos_Line].ln_Strlen - 1;
  488.         return(TRUE);
  489.     }
  490.     else
  491.         pos->pos_Col = pos->pos_Line = 0;
  492.     }
  493.     else
  494.     return(TRUE);
  495.     return(FALSE);
  496. }
  497. static INLINE int
  498. nextchar(POS *pos, TX *tx)
  499. {
  500.     if(++pos->pos_Col >= tx->tx_Lines[pos->pos_Line].ln_Strlen)
  501.     {
  502.     if(++pos->pos_Line < tx->tx_NumLines)
  503.     {
  504.         pos->pos_Col = 0;
  505.         return(TRUE);
  506.     }
  507.     else
  508.     {
  509.         pos->pos_Line = tx->tx_NumLines - 1;
  510.         pos->pos_Col = tx->tx_Lines[pos->pos_Line].ln_Strlen - 1;
  511.     }
  512.     }
  513.     else
  514.     return(TRUE);
  515.     return(FALSE);
  516. }
  517.  
  518. _PR VALUE cmd_next_char(VALUE pos, VALUE tx);
  519. DEFUN("next-char", cmd_next_char, subr_next_char, (VALUE pos, VALUE tx), V_Subr2, DOC_next_char) /*
  520. ::doc:next_char::
  521. (next-char [POS])
  522. Returns the position of the next character after POS (or the cursor).
  523. Will move to the start of the next line after the end of the current line.
  524. POS is altered.
  525. ::end:: */
  526. {
  527.     if(!BUFFERP(tx))
  528.     tx = CurrVW->vw_Tx;
  529.     if(!POSP(pos))
  530.     pos = newlpos(gettxcurspos(VTX(tx)));
  531.     else
  532.     checkpos(VTX(tx), &VPOS(pos));
  533.     if(nextchar(&VPOS(pos), VTX(tx)))
  534.     return(pos);
  535.     return(sym_nil);
  536. }
  537.  
  538. _PR VALUE cmd_goto_next_char(void);
  539. DEFUN("goto-next-char", cmd_goto_next_char, subr_goto_next_char, (void), V_Subr0, DOC_goto_next_char) /*
  540. ::doc:goto_next_char::
  541. (goto-next-char)
  542. Moves to the next character. Will move to the start of the next line after
  543. the end of the current line.
  544. ::end:: */
  545. {
  546.     VW *vw = CurrVW;
  547.     if(nextchar(&vw->vw_CursorPos, vw->vw_Tx))
  548.     return(sym_t);
  549.     return(sym_nil);
  550. }
  551.  
  552. _PR VALUE cmd_prev_char(VALUE pos, VALUE tx);
  553. DEFUN("prev-char", cmd_prev_char, subr_prev_char, (VALUE pos, VALUE tx), V_Subr2, DOC_prev_char) /*
  554. ::doc:prev_char::
  555. (prev-char [POS])
  556. Returns the position of the character before POS (or the cursor). Will move
  557. to the start of the next line after the end of the current line.
  558. POS is altered.
  559. ::end:: */
  560. {
  561.     if(!BUFFERP(tx))
  562.     tx = CurrVW->vw_Tx;
  563.     if(!POSP(pos))
  564.     pos = newlpos(gettxcurspos(VTX(tx)));
  565.     else
  566.     checkpos(VTX(tx), &VPOS(pos));
  567.     if(prevchar(&VPOS(pos), VTX(tx)))
  568.     return(pos);
  569.     return(sym_nil);
  570. }
  571.  
  572. _PR VALUE cmd_goto_prev_char(void);
  573. DEFUN("goto-prev-char", cmd_goto_prev_char, subr_goto_prev_char, (void), V_Subr0, DOC_goto_prev_char) /*
  574. ::doc:goto_prev_char::
  575. (goto-prev-char)
  576. Moves to the previous character. Will move to the start of the next line
  577. after the end of the current line.
  578. ::end:: */
  579. {
  580.     VW *vw = CurrVW;
  581.     if(prevchar(&vw->vw_CursorPos, vw->vw_Tx))
  582.     return(sym_t);
  583.     return(sym_nil);
  584. }
  585.  
  586. _PR VALUE cmd_match_brackets(VALUE pos, VALUE tx);
  587. DEFUN("match-brackets", cmd_match_brackets, subr_match_brackets, (VALUE pos, VALUE tx), V_Subr2, DOC_match_brackets) /*
  588. ::doc:match_brackets::
  589. (match-brackets [POS] [BUFFER])
  590. Find a bracket matching the one at POS (or the cursor). The things that match
  591. each other are,  { }, ( ), [ ], ` ', < >. POS is altered.
  592. ::end:: */
  593. {
  594.     if(!BUFFERP(tx))
  595.     tx = CurrVW->vw_Tx;
  596.     if(!POSP(pos))
  597.     pos = newlpos(gettxcurspos(VTX(tx)));
  598.     else
  599.     checkpos(VTX(tx), &VPOS(pos));
  600.     if(findmatchingbracket(&VPOS(pos), VTX(tx)))
  601.     return(pos);
  602.     return(sym_nil);
  603. }
  604.  
  605. _PR VALUE cmd_mouse_pos(void);
  606. DEFUN("mouse-pos", cmd_mouse_pos, subr_mouse_pos, (void), V_Subr0, DOC_mouse_pos) /*
  607. ::doc:mouse_pos::
  608. (mouse-pos)
  609. Return the position of the mouse pointer, relative to the display origin of
  610. the buffer in the current window.
  611. ::end:: */
  612. {
  613.     VALUE pos;
  614.     if((pos = newlpos2(0, 0)) && makemousepos(&VPOS(pos), CurrVW))
  615.     return(pos);
  616.     return(sym_nil);
  617. }
  618.  
  619. long
  620. movedownpages(long pages)
  621. {
  622.     VW *vw = CurrVW;
  623.     long newline, rc;
  624.     newline = vw->vw_CursorPos.pos_Line + (pages * vw->vw_MaxY);
  625.     if(newline >= vw->vw_Tx->tx_NumLines)
  626.     {
  627.     newline = vw->vw_Tx->tx_NumLines - 1;
  628.     rc = FALSE;
  629.     }
  630.     else
  631.     {
  632.     vw->vw_StartLine += (pages * vw->vw_MaxY);
  633.     vw->vw_Flags |= VWFF_FORCE_REFRESH;
  634.     rc = TRUE;
  635.     }
  636.     vw->vw_CursorPos.pos_Line = newline;
  637.     return(rc);
  638. }
  639.  
  640. long
  641. moveuppages(long pages)
  642. {
  643.     VW *vw = CurrVW;
  644.     long newline, rc;
  645.     newline = vw->vw_CursorPos.pos_Line - (pages * vw->vw_MaxY);
  646.     if(newline < 0)
  647.     {
  648.     newline = 0;
  649.     rc = FALSE;
  650.     }
  651.     else
  652.     {
  653.     vw->vw_StartLine -= (pages * vw->vw_MaxY);
  654.     if(vw->vw_StartLine < 0)
  655.         vw->vw_StartLine = 0;
  656.     vw->vw_Flags |= VWFF_FORCE_REFRESH;
  657.     rc = TRUE;
  658.     }
  659.     vw->vw_CursorPos.pos_Line = newline;
  660.     return(rc);
  661. }
  662.  
  663. static int
  664. findmatchingbracket(POS *pos, TX *tx)
  665. {
  666. #define NUM_BRAC_TYPES 10
  667.     static u_char bracs[] =
  668.     {
  669.     '{', '}',
  670.     '(', ')',
  671.     '[', ']',
  672.     '`', '\'',
  673.     '<', '>'
  674.     };
  675.  
  676.     LINE *line = tx->tx_Lines + pos->pos_Line;
  677.     if(pos->pos_Col < line->ln_Strlen)
  678.     {
  679.     u_char startc = line->ln_Line[pos->pos_Col];
  680.     long i;
  681.     for(i = 0; i < NUM_BRAC_TYPES; i++)
  682.     {
  683.         if(startc == bracs[i])
  684.         break;
  685.     }
  686.     if(i < NUM_BRAC_TYPES)
  687.     {
  688.         long x = pos->pos_Col;
  689.         long y = pos->pos_Line;
  690.         long braccount = 1;
  691.         bool found = FALSE;
  692.         if(i & 1)
  693.         {
  694.         /* search backwards
  695.          */
  696.         u_char endc = bracs[i - 1];
  697.         while(!found)
  698.         {
  699.             u_char c;
  700.             if(--x < 0)
  701.             {
  702.             if(--y < 0)
  703.             {
  704.                 cmd_signal(sym_error, LIST_1(MKSTR("No matching bracket")));
  705.                 return(FALSE);
  706.             }
  707.             line--;
  708.             x = line->ln_Strlen - 1;
  709.             }
  710.             c = line->ln_Line[x];
  711.             if(c == startc)
  712.             braccount++;
  713.             else if(c == endc)
  714.             {
  715.             if(!(--braccount))
  716.                 found = TRUE;
  717.             }
  718.         }
  719.         }
  720.         else
  721.         {
  722.         /* search forwards
  723.          */
  724.         u_char endc = bracs[i + 1];
  725.         while(!found)
  726.         {
  727.             u_char c;
  728.             if(++x >= line->ln_Strlen)
  729.             {
  730.             if(++y >= tx->tx_NumLines)
  731.             {
  732.                 cmd_signal(sym_error, LIST_1(MKSTR("No matching bracket")));
  733.                 return(FALSE);
  734.             }
  735.             line++;
  736.             x = 0;
  737.             }
  738.             c = line->ln_Line[x];
  739.             if(c == startc)
  740.             braccount++;
  741.             else if(c == endc)
  742.             {
  743.             if(!(--braccount))
  744.                 found = TRUE;
  745.             }
  746.         }
  747.         }
  748.         pos->pos_Col = x;
  749.         pos->pos_Line = y;
  750.         return(TRUE);
  751.     }
  752.     }
  753.     cmd_signal(sym_error, LIST_1(MKSTR("No opening bracket")));
  754.     return(FALSE);
  755. }
  756.  
  757. void
  758. movement_init(void)
  759. {
  760.     ADD_SUBR(subr_screen_top_line);
  761.     ADD_SUBR(subr_screen_bottom_line);
  762.     ADD_SUBR(subr_screen_first_column);
  763.     ADD_SUBR(subr_screen_last_column);
  764.     ADD_SUBR(subr_goto);
  765.     ADD_SUBR(subr_next_screen);
  766.     ADD_SUBR(subr_prev_screen);
  767.     ADD_SUBR(subr_file_end);
  768.     ADD_SUBR(subr_goto_file_end);
  769.     ADD_SUBR(subr_file_start);
  770.     ADD_SUBR(subr_goto_file_start);
  771.     ADD_SUBR(subr_line_end);
  772.     ADD_SUBR(subr_goto_line_end);
  773.     ADD_SUBR(subr_line_start);
  774.     ADD_SUBR(subr_goto_line_start);
  775.     ADD_SUBR(subr_next_line);
  776.     ADD_SUBR(subr_goto_next_line);
  777.     ADD_SUBR(subr_prev_line);
  778.     ADD_SUBR(subr_goto_prev_line);
  779.     ADD_SUBR(subr_left_char);
  780.     ADD_SUBR(subr_goto_left_char);
  781.     ADD_SUBR(subr_right_char);
  782.     ADD_SUBR(subr_goto_right_char);
  783.     ADD_SUBR(subr_prev_tab);
  784.     ADD_SUBR(subr_goto_prev_tab);
  785.     ADD_SUBR(subr_next_tab);
  786.     ADD_SUBR(subr_goto_next_tab);
  787.     ADD_SUBR(subr_next_char);
  788.     ADD_SUBR(subr_goto_next_char);
  789.     ADD_SUBR(subr_prev_char);
  790.     ADD_SUBR(subr_goto_prev_char);
  791.     ADD_SUBR(subr_match_brackets);
  792.     ADD_SUBR(subr_mouse_pos);
  793. }
  794.