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

  1. /* editcommands.c -- Lisp functions for editing
  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 <string.h>
  24. #include <ctype.h>
  25.  
  26. _PR void edit_init(void);
  27.  
  28. static VALUE sym_upcase_table, sym_downcase_table;
  29. /* These are actually 256-byte-long Lisp strings, they're initialised in
  30.    edit_init().     If struct String changes these will have to as well.  */
  31. static u_char UpCaseTable[257], DownCaseTable[257];
  32.  
  33. _PR VALUE cmd_split_line(void);
  34. DEFUN("split-line", cmd_split_line, subr_split_line, (void), V_Subr0, DOC_split_line) /*
  35. ::doc:split_line::
  36. (split-line)
  37. Splits the line into two at the cursor position, if the auto-indent option
  38. is enabled the cursor will be placed at the same level of indentation as
  39. the previous line.
  40. ::end:: */
  41. {
  42.     VW *vw = CurrVW;
  43.     TX *tx = vw->vw_Tx;
  44.     if(!readonly(tx))
  45.     {
  46.     POS old = vw->vw_CursorPos;
  47.     if(padcursor(vw))
  48.     {
  49.         if(splitline(tx, &vw->vw_CursorPos))
  50.         {
  51.         flaginsertion(tx, &old, &vw->vw_CursorPos);
  52.         return(sym_t);
  53.         }
  54.     }
  55.     }
  56.     return(sym_nil);
  57. }
  58.  
  59. _PR VALUE cmd_insert(VALUE string, VALUE pos, VALUE buff);
  60. DEFUN("insert", cmd_insert, subr_insert, (VALUE string, VALUE lpos, VALUE buff), V_Subr3, DOC_insert) /*
  61. ::doc:insert::
  62. (insert STRING [POS] [BUFFER])
  63. Inserts STRING into BUFFER at POS.
  64. ::end:: */
  65. {
  66.     POS pos;
  67.     DECLARE1(string, STRINGP);
  68.     if(POSP(lpos))
  69.     pos = VPOS(lpos);
  70.     else
  71.     pos = CurrVW->vw_CursorPos;
  72.     if(!BUFFERP(buff))
  73.     buff = CurrVW->vw_Tx;
  74.     if(!readonly(VTX(buff)) && padpos(VTX(buff), &pos))
  75.     {
  76.     if(insertstring(VTX(buff), VSTR(string), VTX(buff)->tx_TabSize, &pos))
  77.         return(sym_t);
  78.     else
  79.         settitle(NoMemMsg);
  80.     }
  81.     return(sym_nil);
  82. }
  83.  
  84. _PR VALUE cmd_insert_rect(VALUE str, VALUE pos, VALUE buff);
  85. DEFUN("insert-rect", cmd_insert_rect, subr_insert_rect, (VALUE str, VALUE lpos, VALUE buff), V_Subr3, DOC_insert_rect) /*
  86. ::doc:insert_rect::
  87. (insert-rect STRING [POS] [BUFFER])
  88. Inserts STRING into BUFFER at POS treating it as a ``rectangle'' of
  89. text -- that is, each separate line in STRING (separated by newlines) is
  90. inserted at the *same* column in successive lines.
  91. ::end:: */
  92. {
  93.     POS pos;
  94.     DECLARE1(str, STRINGP);
  95.     if(POSP(lpos))
  96.     pos = VPOS(lpos);
  97.     else
  98.     pos = CurrVW->vw_CursorPos;
  99.     if(!BUFFERP(buff))
  100.     buff = CurrVW->vw_Tx;
  101.     if(!readonly(VTX(buff)) && padpos(VTX(buff), &pos))
  102.     {
  103.     if(rectinsertstring(VTX(buff), VSTR(str), &pos))
  104.         return(sym_t);
  105.     else
  106.         settitle(NoMemMsg);
  107.     }
  108.     return(sym_nil);
  109. }
  110.  
  111. _PR VALUE cmd_delete_area(VALUE start, VALUE end, VALUE buff);
  112. DEFUN("delete-area", cmd_delete_area, subr_delete_area, (VALUE lstart, VALUE lend, VALUE buff), V_Subr3, DOC_delete_area) /*
  113. ::doc:delete_area::
  114. (delete-area START-POS END-POS [BUFFER])
  115. Deletes from START-POS up to (but not including) END-POS.
  116. ::end:: */
  117. {
  118.     POS start, end;
  119.     DECLARE1(lstart, POSP);
  120.     DECLARE2(lend, POSP);
  121.     start = VPOS(lstart);
  122.     end = VPOS(lend);
  123.     if(!BUFFERP(buff))
  124.     buff = CurrVW->vw_Tx;
  125.     if(!readonly(VTX(buff)) && checksect(VTX(buff), &start, &end))
  126.     {
  127.     deletesection(VTX(buff), &start, &end);
  128.     return(sym_t);
  129.     }
  130.     return(sym_nil);
  131. }
  132.  
  133. _PR VALUE cmd_delete_rect(VALUE lstart, VALUE lend, VALUE buff);
  134. DEFUN("delete-rect", cmd_delete_rect, subr_delete_rect, (VALUE lstart, VALUE lend, VALUE buff), V_Subr3, DOC_delete_rect) /*
  135. ::doc:delete_rect::
  136. (delete-rect START-POS END-POS [BUFFER])
  137. Deletes the rectangle of text from one corner, START-POS, to the opposite
  138. corner, END-POS.
  139. ::end:: */
  140. {
  141.     POS start, end;
  142.     DECLARE1(lstart, POSP);
  143.     DECLARE2(lend, POSP);
  144.     if(!BUFFERP(buff))
  145.     buff = CurrVW->vw_Tx;
  146.     orderrect(&start, &end, &VPOS(lstart), &VPOS(lend));
  147.     if(!readonly(VTX(buff)) && checkline(VTX(buff), &end))
  148.     {
  149.     rectdeletesection(VTX(buff), &start, &end);
  150.     return(sym_t);
  151.     }
  152.     return(sym_nil);
  153. }
  154.  
  155. _PR VALUE cmd_copy_area(VALUE lstart, VALUE lend, VALUE buff);
  156. DEFUN("copy-area", cmd_copy_area, subr_copy_area, (VALUE lstart, VALUE lend, VALUE buff), V_Subr3, DOC_copy_area) /*
  157. ::doc:copy_area::
  158. (copy-area START-POS END-POS [BUFFER])
  159. Returns the string from START-POS up to END-POS.
  160. ::end:: */
  161. {
  162.     POS start, end;
  163.     DECLARE1(lstart, POSP);
  164.     DECLARE2(lend, POSP);
  165.     start = VPOS(lstart);
  166.     end = VPOS(lend);
  167.     if(!BUFFERP(buff))
  168.     buff = CurrVW->vw_Tx;
  169.     if(checksect(VTX(buff), &start, &end))
  170.     {
  171.     long tlen = sectionlength(VTX(buff), &start, &end) + 1;
  172.     VALUE str = valstralloc(tlen);
  173.     if(str)
  174.     {
  175.         copysection(VTX(buff), &start, &end, VSTR(str));
  176.         VSTR(str)[tlen - 1] = 0;
  177.         return(str);
  178.     }
  179.     }
  180.     return(sym_nil);
  181. }
  182.  
  183. _PR VALUE cmd_copy_rect(VALUE lstart, VALUE lend, VALUE buff);
  184. DEFUN("copy-rect", cmd_copy_rect, subr_copy_rect, (VALUE lstart, VALUE lend, VALUE buff), V_Subr3, DOC_copy_rect) /*
  185. ::doc:copy_rect::
  186. (copy-rect START-POS END-POS [BUFFER])
  187. Returns the rectangle of text marked out by START-POS and END-POS.
  188. ::end:: */
  189. {
  190.     POS start, end;
  191.     DECLARE1(lstart, POSP);
  192.     DECLARE2(lend, POSP);
  193.     if(!BUFFERP(buff))
  194.     buff = CurrVW->vw_Tx;
  195.     orderrect(&start, &end, &VPOS(lstart), &VPOS(lend));
  196.     if(checkline(VTX(buff), &end))
  197.     {
  198.     long tlen = rectsectionlength(VTX(buff), &start, &end) + 1;
  199.     VALUE str = valstralloc(tlen);
  200.     if(str)
  201.     {
  202.         rectcopysection(VTX(buff), &start, &end, VSTR(str));
  203.         VSTR(str)[tlen - 1] = 0;
  204.         return(str);
  205.     }
  206.     }
  207.     return(sym_nil);
  208. }
  209.  
  210. _PR VALUE cmd_cut_area(VALUE lstart, VALUE lend, VALUE buff);
  211. DEFUN("cut-area", cmd_cut_area, subr_cut_area, (VALUE lstart, VALUE lend, VALUE buff), V_Subr3, DOC_cut_area) /*
  212. ::doc:cut_area::
  213. (cut-area START-POS END-POS [BUFFER])
  214. The same as `copy-area' except that the section of text copied (START-POS to
  215. END-POS) is deleted from the file after being duplicated.
  216. ::end:: */
  217. {
  218.     POS start, end;
  219.     DECLARE1(lstart, POSP);
  220.     DECLARE2(lend, POSP);
  221.     start = VPOS(lstart);
  222.     end = VPOS(lend);
  223.     if(!BUFFERP(buff))
  224.     buff = CurrVW->vw_Tx;
  225.     if(!readonly(VTX(buff)) && checksect(VTX(buff), &start, &end))
  226.     {
  227.     long tlen = sectionlength(VTX(buff), &start, &end) + 1;
  228.     VALUE str = valstralloc(tlen);
  229.     if(str)
  230.     {
  231.         copysection(VTX(buff), &start, &end, VSTR(str));
  232.         VSTR(str)[tlen - 1] = 0;
  233.         deletesection(VTX(buff), &start, &end);
  234.         return(str);
  235.     }
  236.     }
  237.     return(sym_nil);
  238. }
  239.  
  240. _PR VALUE cmd_cut_rect(VALUE lstart, VALUE lend, VALUE buff);
  241. DEFUN("cut-rect", cmd_cut_rect, subr_cut_rect, (VALUE lstart, VALUE lend, VALUE buff), V_Subr3, DOC_cut_rect) /*
  242. ::doc:cut_rect::
  243. (cut-rect START-POS END-POS [BUFFER])
  244. The same as `copy-rect' except that the section of text copied (START-POS
  245. to END-POS) is deleted from the file after being duplicated.
  246. ::end:: */
  247. {
  248.     POS start, end;
  249.     DECLARE1(lstart, POSP);
  250.     DECLARE2(lend, POSP);
  251.     if(!BUFFERP(buff))
  252.     buff = CurrVW->vw_Tx;
  253.     orderrect(&start, &end, &VPOS(lstart), &VPOS(lend));
  254.     if(!readonly(VTX(buff)) && checkline(VTX(buff), &end))
  255.     {
  256.     long tlen = rectsectionlength(VTX(buff), &start, &end) + 1;
  257.     VALUE str = valstralloc(tlen);
  258.     if(str)
  259.     {
  260.         rectcopysection(VTX(buff), &start, &end, VSTR(str));
  261.         VSTR(str)[tlen - 1] = 0;
  262.         rectdeletesection(VTX(buff), &start, &end);
  263.         return(str);
  264.     }
  265.     }
  266.     return(sym_nil);
  267. }
  268.  
  269. _PR VALUE cmd_block_toggle(void);
  270. DEFUN("block-toggle", cmd_block_toggle, subr_block_toggle, (void), V_Subr0, DOC_block_toggle) /*
  271. ::doc:block_toggle::
  272. (block-toggle)
  273. ::end:: */
  274. {
  275.     VW *vw = CurrVW;
  276.     switch(vw->vw_BlockStatus)
  277.     {
  278.     case 0:
  279.         vw->vw_BlockStatus = -1;
  280.         setblockrefresh(vw);
  281.         break;
  282.     case 1:
  283.         vw->vw_BlockE = vw->vw_CursorPos;
  284.         vw->vw_BlockStatus = 0;
  285.         orderblock(vw);
  286.         setblockrefresh(vw);
  287.         break;
  288.     case 2:
  289.         vw->vw_BlockS = vw->vw_CursorPos;
  290.         vw->vw_BlockStatus = 0;
  291.         orderblock(vw);
  292.         setblockrefresh(vw);
  293.         break;
  294.     case -1:
  295.         vw->vw_BlockS = vw->vw_CursorPos;
  296.         vw->vw_BlockStatus = 1;
  297.         break;
  298.     }
  299.     return(sym_t);
  300. }
  301.  
  302. _PR VALUE cmd_block_start(VALUE pos);
  303. DEFUN("block-start", cmd_block_start, subr_block_start, (VALUE pos), V_Subr1, DOC_block_start) /*
  304. ::doc:block_start::
  305. (block-start [POS])
  306. Always returns the position of the block-start as it is, if POS is given
  307. it is used as the new position of the start of the block.
  308. ::end:: */
  309. {
  310.     VW *vw = CurrVW;
  311.     VALUE res;
  312.     if(!vw->vw_BlockStatus || (vw->vw_BlockStatus == 1))
  313.     res = newlpos(&vw->vw_BlockS);
  314.     else
  315.     res = sym_nil;
  316.     if(POSP(pos) && checkline(vw->vw_Tx, &VPOS(pos)))
  317.     {
  318.     switch(vw->vw_BlockStatus)
  319.     {
  320.         case 0:
  321.         setblockrefresh(vw);
  322.         vw->vw_BlockS = VPOS(pos);
  323.         orderblock(vw);
  324.         setblockrefresh(vw);
  325.         break;
  326.         case 2:
  327.         vw->vw_BlockS = VPOS(pos);
  328.         vw->vw_BlockStatus = 0;
  329.         orderblock(vw);
  330.         setblockrefresh(vw);
  331.         break;
  332.         case -1:
  333.         vw->vw_BlockStatus = 1;
  334.         /* FALL THROUGH */
  335.         case 1:
  336.         vw->vw_BlockS = VPOS(pos);
  337.         break;
  338.     }
  339.     }
  340.     return(res);
  341. }
  342.  
  343. _PR VALUE cmd_block_end(VALUE pos);
  344. DEFUN("block-end", cmd_block_end, subr_block_end, (VALUE pos), V_Subr1, DOC_block_end) /*
  345. ::doc:block_end::
  346. (block-end [POS])
  347. Always returns the position of the block-end as it is, if POS is given
  348. it is used as the new position of the end of the block.
  349. ::end:: */
  350. {
  351.     VW *vw = CurrVW;
  352.     VALUE res;
  353.     if(!vw->vw_BlockStatus || (vw->vw_BlockStatus == 2))
  354.     res = newlpos(&vw->vw_BlockE);
  355.     else
  356.     res = sym_nil;
  357.     if(POSP(pos) && checkline(vw->vw_Tx, &VPOS(pos)))
  358.     {
  359.     switch(vw->vw_BlockStatus)
  360.     {
  361.         case 0:
  362.         setblockrefresh(vw);
  363.         vw->vw_BlockE = VPOS(pos);
  364.         orderblock(vw);
  365.         setblockrefresh(vw);
  366.         break;
  367.         case 1:
  368.         vw->vw_BlockE = VPOS(pos);
  369.         vw->vw_BlockStatus = 0;
  370.         orderblock(vw);
  371.         setblockrefresh(vw);
  372.         break;
  373.         case -1:
  374.         vw->vw_BlockStatus = 2;
  375.         /* FALL THROUGH */
  376.         case 2:
  377.         vw->vw_BlockE = VPOS(pos);
  378.         break;
  379.     }
  380.     }
  381.     return(res);
  382. }
  383.  
  384. _PR VALUE cmd_block_kill(void);
  385. DEFUN("block-kill", cmd_block_kill, subr_block_kill, (void), V_Subr0, DOC_block_kill) /*
  386. ::doc:block_kill::
  387. (block-kill)
  388. Unmarks the block.
  389. ::end:: */
  390. {
  391.     VW *vw = CurrVW;
  392.     if(vw->vw_BlockStatus == 0)
  393.     {
  394.     setblockrefresh(vw);
  395.     vw->vw_BlockStatus = -1;
  396.     }
  397.     return(sym_t);
  398. }
  399.  
  400. _PR VALUE cmd_blockp(void);
  401. DEFUN("blockp", cmd_blockp, subr_blockp, (void), V_Subr0, DOC_blockp) /*
  402. ::doc:blockp::
  403. (blockp)
  404. Returns true if a block is currently marked.
  405. ::end:: */
  406. {
  407.     if(CurrVW->vw_BlockStatus == 0)
  408.     return(sym_t);
  409.     return(sym_nil);
  410. }
  411.  
  412. _PR VALUE cmd_translate_area(VALUE vstart, VALUE vend, VALUE table, VALUE tx);
  413. DEFUN("translate-area", cmd_translate_area, subr_translate_area, (VALUE vstart, VALUE vend, VALUE table, VALUE tx), V_Subr4, DOC_translate_area) /*
  414. ::doc:translate_area:
  415. (translate-area START-POS END-POS TRANSLATION-TABLE [BUFFER])
  416. Applies the TRANSLATION-TABLE to the text between START-POS and END-POS.
  417. TRANSLATION-TABLE is a string, each character represents the translation
  418. for an ascii character of that characters position in the string. If the
  419. string is less than 256 chars long any undefined characters will remain
  420. unchanged.
  421. ::end:: */
  422. {
  423.     POS start, end;
  424.     if(!BUFFERP(tx))
  425.     tx = CurrVW->vw_Tx;
  426.     DECLARE1(vstart, POSP);
  427.     DECLARE2(vend, POSP);
  428.     DECLARE3(table, STRINGP);
  429.     start = VPOS(vstart);
  430.     end = VPOS(vend);
  431.     if(!readonly(VTX(tx)) && checksect(VTX(tx), &start, &end))
  432.     {
  433.     LINE *line = VTX(tx)->tx_Lines + start.pos_Line;
  434.     int tablen = strlen(VSTR(table));
  435.     register u_char *str;
  436.     flagmodification(VTX(tx), &start, &end);
  437.     while(start.pos_Line < end.pos_Line)
  438.     {
  439.         int llen = line->ln_Strlen - 1;
  440.         str = line->ln_Line + start.pos_Col;
  441.         while(start.pos_Col++ < llen)
  442.         {
  443.         register u_char c = *str;
  444.         *str++ = (c < tablen) ? VSTR(table)[c] : c;
  445.         }
  446.         start.pos_Col = 0;
  447.         start.pos_Line++;
  448.         line++;
  449.     }
  450.     str = line->ln_Line + start.pos_Col;
  451.     while(start.pos_Col++ < end.pos_Col)
  452.     {
  453.         register u_char c = *str;
  454.         *str++ = (c < tablen) ? VSTR(table)[c] : c;
  455.     }
  456.     return(sym_t);
  457.     }
  458.     return(NULL);
  459. }
  460.  
  461. _PR VALUE cmd_alpha_char_p(VALUE ch);
  462. DEFUN("alpha-char-p", cmd_alpha_char_p, subr_alpha_char_p, (VALUE ch), V_Subr1, DOC_alpha_char_p) /*
  463. ::doc:alpha_char_p::
  464. (alpha-char-p CHAR)
  465. Returns t if CHAR is an alphabetic character.
  466. ::end:: */
  467. {
  468.     DECLARE1(ch, CHARP);
  469.     if(isalpha(VCHAR(ch)))
  470.     return(sym_t);
  471.     return(sym_nil);
  472. }
  473. _PR VALUE cmd_upper_case_p(VALUE ch);
  474. DEFUN("upper-case-p", cmd_upper_case_p, subr_upper_case_p, (VALUE ch), V_Subr1, DOC_upper_case_p) /*
  475. ::doc:upper_case_p::
  476. (upper-case-p CHAR)
  477. Returns t if CHAR is upper case.
  478. ::end:: */
  479. {
  480.     DECLARE1(ch, CHARP);
  481.     if(isupper(VCHAR(ch)))
  482.     return(sym_t);
  483.     return(sym_nil);
  484. }
  485. _PR VALUE cmd_lower_case_p(VALUE ch);
  486. DEFUN("lower-case-p", cmd_lower_case_p, subr_lower_case_p, (VALUE ch), V_Subr1, DOC_lower_case_p) /*
  487. ::doc:lower_case_p::
  488. (lower-case-p CHAR)
  489. Returns t if CHAR is lower case.
  490. ::end:: */
  491. {
  492.     DECLARE1(ch, CHARP);
  493.     if(islower(VCHAR(ch)))
  494.     return(sym_t);
  495.     return(sym_nil);
  496. }
  497. _PR VALUE cmd_digit_char_p(VALUE ch);
  498. DEFUN("digit-char-p", cmd_digit_char_p, subr_digit_char_p, (VALUE ch), V_Subr1, DOC_digit_char_p) /*
  499. ::doc:digit_char_p::
  500. (digit-char-p CHAR)
  501. Returns t if CHAR is a digit.
  502. ::end:: */
  503. {
  504.     DECLARE1(ch, CHARP);
  505.     if(isdigit(VCHAR(ch)))
  506.     return(sym_t);
  507.     return(sym_nil);
  508. }
  509. _PR VALUE cmd_alphanumericp(VALUE ch);
  510. DEFUN("alphanumericp", cmd_alphanumericp, subr_alphanumericp, (VALUE ch), V_Subr1, DOC_alphanumericp) /*
  511. ::doc:alphanumericp::
  512. (alphanumericp CHAR)
  513. Returns t if CHAR is alpha-numeric.
  514. ::end:: */
  515. {
  516.     DECLARE1(ch, CHARP);
  517.     if(isalnum(VCHAR(ch)))
  518.     return(sym_t);
  519.     return(sym_nil);
  520. }
  521. _PR VALUE cmd_space_char_p(VALUE ch);
  522. DEFUN("space-char-p", cmd_space_char_p, subr_space_char_p, (VALUE ch), V_Subr1, DOC_space_char_p) /*
  523. ::doc:space_char_p::
  524. (space-char-p CHAR)
  525. Returns t if CHAR is whitespace.
  526. ::end:: */
  527. {
  528.     DECLARE1(ch, CHARP);
  529.     if(isspace(VCHAR(ch)))
  530.     return(sym_t);
  531.     return(sym_nil);
  532. }
  533. _PR VALUE cmd_char_upcase(VALUE ch);
  534. DEFUN("char-upcase", cmd_char_upcase, subr_char_upcase, (VALUE ch), V_Subr1, DOC_char_upcase) /*
  535. ::doc:char_upcase::
  536. (char-upcase CHAR)
  537. Returns the upper-case equivalent of CHAR.
  538. ::end:: */
  539. {
  540.     DECLARE1(ch, CHARP);
  541.     return(newnumber(toupper(VCHAR(ch))));
  542. }
  543. _PR VALUE cmd_char_downcase(VALUE ch);
  544. DEFUN("char-downcase", cmd_char_downcase, subr_char_downcase, (VALUE ch), V_Subr1, DOC_char_downcase) /*
  545. ::doc:char_downcase::
  546. (char-downcase CHAR)
  547. Returns the lower-case equivalent of CHAR.
  548. ::end:: */
  549. {
  550.     DECLARE1(ch, CHARP);
  551.     return(newnumber(toupper(VCHAR(ch))));
  552. }
  553.  
  554. _PR VALUE cmd_pos_line(VALUE pos);
  555. DEFUN("pos-line", cmd_pos_line, subr_pos_line, (VALUE pos), V_Subr1, DOC_pos_line) /*
  556. ::doc:pos_line::
  557. (pos-line POS)
  558. Returns the line number which POS points to.
  559. ::end:: */
  560. {
  561.     DECLARE1(pos, POSP);
  562.     return(newnumber(VPOS(pos).pos_Line + 1));
  563. }
  564. _PR VALUE cmd_pos_col(VALUE pos);
  565. DEFUN("pos-col", cmd_pos_col, subr_pos_col, (VALUE pos), V_Subr1, DOC_pos_col) /*
  566. ::doc:pos_col::
  567. (pos-col POS)
  568. Return the column number which POS points to.
  569. ::end:: */
  570. {
  571.     DECLARE1(pos, POSP);
  572.     return(newnumber(VPOS(pos).pos_Col + 1));
  573. }
  574. _PR VALUE cmd_set_pos_line(VALUE pos, VALUE line);
  575. DEFUN("set-pos-line", cmd_set_pos_line, subr_set_pos_line, (VALUE pos, VALUE line), V_Subr2, DOC_set_pos_line) /*
  576. ::doc:set_pos_line::
  577. (set-pos-line POS LINE)
  578. Sets the line number of POS to LINE.
  579. ::end:: */
  580. {
  581.     DECLARE1(pos, POSP);
  582.     DECLARE2(line, NUMBERP);
  583.     VPOS(pos).pos_Line = VNUM(line) - 1;
  584.     return(line);
  585. }
  586. _PR VALUE cmd_set_pos_col(VALUE pos, VALUE col);
  587. DEFUN("set-pos-col", cmd_set_pos_col, subr_set_pos_col, (VALUE pos, VALUE col), V_Subr2, DOC_set_pos_col) /*
  588. ::doc:set_pos_col::
  589. (set-pos-col POS COL)
  590. Sets the column number of POS to COL.
  591. ::end:: */
  592. {
  593.     DECLARE1(pos, POSP);
  594.     DECLARE2(col, NUMBERP);
  595.     VPOS(pos).pos_Col = VNUM(col) - 1;
  596.     return(col);
  597. }
  598.  
  599. _PR VALUE cmd_posp(VALUE arg);
  600. DEFUN("posp", cmd_posp, subr_posp, (VALUE arg), V_Subr1, DOC_posp) /*
  601. ::doc:posp::
  602. (posp ARG)
  603. Returns t if ARG is a position object.
  604. ::end:: */
  605. {
  606.     if(POSP(arg))
  607.     return(sym_t);
  608.     return(sym_nil);
  609. }
  610.  
  611. _PR VALUE cmd_cursor_pos(void);
  612. DEFUN("cursor-pos", cmd_cursor_pos, subr_cursor_pos, (void), V_Subr0, DOC_cursor_pos) /*
  613. ::doc:cursor_pos::
  614. (cursor-pos)
  615. Returns the position of the cursor in the current window.
  616. ::end:: */
  617. {
  618.     return(newlpos(&CurrVW->vw_CursorPos));
  619. }
  620.  
  621. _PR VALUE cmd_empty_line_p(VALUE lpos, VALUE tx);
  622. DEFUN("empty-line-p", cmd_empty_line_p, subr_empty_line_p, (VALUE lpos, VALUE tx), V_Subr2, DOC_empty_line_p) /*
  623. ::doc:empty_line_p::
  624. (empty-line-p [POS] [BUFFER])
  625. Returns t if the line pointer to by POS (or the cursor) in BUFFER is
  626. empty, ie, blank or only containing spaces.
  627. ::end:: */
  628. {
  629.     VW *vw = CurrVW;
  630.     POS pos;
  631.     LINE *line;
  632.     if(POSP(lpos))
  633.     pos = VPOS(lpos);
  634.     else
  635.     pos = vw->vw_CursorPos;
  636.     if(!BUFFERP(tx))
  637.     tx = vw->vw_Tx;
  638.     line = VTX(tx)->tx_Lines + pos.pos_Line;
  639.     if(line->ln_Strlen == 1)
  640.     return(sym_t);
  641.     else
  642.     {
  643.     u_char *s = line->ln_Line;
  644.     while(*s && isspace(*s))
  645.         s++;
  646.     if(!(*s))
  647.         return(sym_t);
  648.     }
  649.     return(sym_nil);
  650. }
  651.  
  652. _PR VALUE cmd_indent_pos(VALUE lpos, VALUE tx);
  653. DEFUN("indent-pos", cmd_indent_pos, subr_indent_pos, (VALUE lpos, VALUE tx), V_Subr2, DOC_indent_pos) /*
  654. ::doc:indent_pos::
  655. (indent-pos [POS] [BUFFER])
  656. Returns the position of the first non-space character in the line pointer
  657. to by POS (or the cursor), in BUFFER.
  658. ::end:: */
  659. {
  660.     VW *vw = CurrVW;
  661.     POS pos;
  662.     long len;
  663.     u_char *line;
  664.     if(!BUFFERP(tx))
  665.     tx = vw->vw_Tx;
  666.     if(POSP(lpos) && checkline(VTX(tx), &VPOS(lpos)))
  667.     pos = VPOS(lpos);
  668.     else
  669.     pos = vw->vw_CursorPos;
  670.     line = VTX(tx)->tx_Lines[pos.pos_Line].ln_Line;
  671.     for(len = 0; *line && isspace(*line); len++, line++)
  672.     ;
  673.     return(newlpos2(len, pos.pos_Line));
  674. }
  675.  
  676. _PR VALUE cmd_set_indent_pos(VALUE indpos, VALUE tx);
  677. DEFUN("set-indent-pos", cmd_set_indent_pos, subr_set_indent_pos, (VALUE indpos, VALUE tx), V_Subr2, DOC_set_indent_pos) /*
  678. ::doc:set_indent_pos::
  679. (set-indent-pos POS [BUFFER])
  680. Sets the indentation of the line pointed to by POS to the column pointed
  681. to by POS by either deleting characters from the start of the line, or
  682. inserting spaces.
  683. ::end:: */
  684. {
  685.     DECLARE1(indpos, POSP);
  686.     if(!BUFFERP(tx))
  687.     tx = CurrVW->vw_Tx;
  688.     if((!readonly(VTX(tx))) && checkline(VTX(tx), &VPOS(indpos)))
  689.     {
  690.     LINE *line = VTX(tx)->tx_Lines + VPOS(indpos).pos_Line;
  691.     u_char *s = line->ln_Line;
  692.     POS pos = VPOS(indpos), end;
  693.     long oldind, diff;
  694.     bool empty = FALSE;
  695.     while(*s && isspace(*s))
  696.         s++;
  697.     oldind = s - line->ln_Line;
  698.     if(!(*s))
  699.         empty = TRUE;
  700.     diff = oldind - pos.pos_Col;
  701.     if(diff > 0)
  702.     {
  703.         deletechars(VTX(tx), &pos, diff);
  704.         end.pos_Line = pos.pos_Line;
  705.         end.pos_Col = pos.pos_Col + diff;
  706.         flagdeletion(VTX(tx), &pos, &end);
  707.     }
  708.     else if(diff < 0)
  709.     {
  710.         diff = -diff;
  711.         pos.pos_Col = oldind;
  712.         insertgap(VTX(tx), diff, &pos);
  713.         end.pos_Line = pos.pos_Line;
  714.         end.pos_Col = pos.pos_Col + diff;
  715.         flaginsertion(VTX(tx), &pos, &end);
  716.         memset(line->ln_Line + oldind, ' ', diff);
  717.     }
  718.     return(indpos);
  719.     }
  720.     return(sym_nil);
  721. }
  722.  
  723. _PR VALUE cmd_clear_buffer(VALUE tx);
  724. DEFUN("clear-buffer", cmd_clear_buffer, subr_clear_buffer, (VALUE tx), V_Subr1, DOC_clear_buffer) /*
  725. ::doc:clear_buffer::
  726. (clear-buffer [BUFFER])
  727. Remove all text from BUFFER, leaving just one empty line.
  728. ::end:: */
  729. {
  730.     if(!BUFFERP(tx))
  731.     tx = CurrVW->vw_Tx;
  732.     if(clearlinelist(VTX(tx)))
  733.     {
  734.     resetallviews(VTX(tx));
  735.     return(tx);
  736.     }
  737.     return(sym_nil);
  738. }
  739.  
  740. void
  741. edit_init(void)
  742. {
  743.     int i;
  744.     ADD_SUBR(subr_split_line);
  745.     ADD_SUBR(subr_insert);
  746.     ADD_SUBR(subr_insert_rect);
  747.     ADD_SUBR(subr_delete_area);
  748.     ADD_SUBR(subr_delete_rect);
  749.     ADD_SUBR(subr_copy_area);
  750.     ADD_SUBR(subr_copy_rect);
  751.     ADD_SUBR(subr_cut_area);
  752.     ADD_SUBR(subr_cut_rect);
  753.     ADD_SUBR(subr_block_toggle);
  754.     ADD_SUBR(subr_block_start);
  755.     ADD_SUBR(subr_block_end);
  756.     ADD_SUBR(subr_block_kill);
  757.     ADD_SUBR(subr_blockp);
  758.     ADD_SUBR(subr_translate_area);
  759.     ADD_SUBR(subr_alpha_char_p);
  760.     ADD_SUBR(subr_upper_case_p);
  761.     ADD_SUBR(subr_lower_case_p);
  762.     ADD_SUBR(subr_digit_char_p);
  763.     ADD_SUBR(subr_alphanumericp);
  764.     ADD_SUBR(subr_space_char_p);
  765.     ADD_SUBR(subr_char_upcase);
  766.     ADD_SUBR(subr_char_downcase);
  767.     ADD_SUBR(subr_pos_line);
  768.     ADD_SUBR(subr_pos_col);
  769.     ADD_SUBR(subr_set_pos_line);
  770.     ADD_SUBR(subr_set_pos_col);
  771.     ADD_SUBR(subr_posp);
  772.     ADD_SUBR(subr_cursor_pos);
  773.     ADD_SUBR(subr_empty_line_p);
  774.     ADD_SUBR(subr_indent_pos);
  775.     ADD_SUBR(subr_set_indent_pos);
  776.     ADD_SUBR(subr_clear_buffer);
  777.  
  778.     UpCaseTable[0] = DownCaseTable[0] = V_StaticString;
  779.     /* jade can't handle zeros in strings :-(  */
  780.     UpCaseTable[1] = DownCaseTable[1] = ' ';
  781.     for(i = 1; i < 256; i++)
  782.     UpCaseTable[i+1] = toupper(i);
  783.     for(i = 1; i < 256; i++)
  784.     DownCaseTable[i+1] = tolower(i);
  785.     INTERN(sym_upcase_table, "upcase-table");
  786.     VSYM(sym_upcase_table)->sym_Value = (String *)UpCaseTable;
  787.     INTERN(sym_downcase_table, "downcase-table");
  788.     VSYM(sym_downcase_table)->sym_Value = (String *)DownCaseTable;
  789. }
  790.