home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / thesrc15.zip / comm1.c < prev    next >
C/C++ Source or Header  |  1993-11-21  |  50KB  |  1,661 lines

  1. /***********************************************************************/
  2. /* COMM1.C - Commands A-D                                              */
  3. /* This file contains all commands that can be assigned to function    */
  4. /* keys or typed on the command line.                                  */
  5. /***********************************************************************/
  6. /*
  7.  * THE - The Hessling Editor. A text editor similar to VM/CMS xedit.
  8.  * Copyright (C) 1991-1993 Mark Hessling
  9.  *
  10.  * This program is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License as
  12.  * published by the Free Software Foundation; either version 2 of
  13.  * the License, or any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18.  * General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to:
  22.  *
  23.  *    The Free Software Foundation, Inc.
  24.  *    675 Mass Ave,
  25.  *    Cambridge, MA 02139 USA.
  26.  *
  27.  *
  28.  * If you make modifications to this software that you feel increases
  29.  * it usefulness for the rest of the community, please email the
  30.  * changes, enhancements, bug fixes as well as any and all ideas to me.
  31.  * This software is going to be maintained and enhanced as deemed
  32.  * necessary by the community.
  33.  *
  34.  * Mark Hessling                     email: M.Hessling@gu.edu.au
  35.  * 36 David Road                     Phone: +61 7 849 7731
  36.  * Holland Park                      Fax:   +61 7 875 5314
  37.  * QLD 4121
  38.  * Australia
  39.  */
  40.  
  41. /*
  42. $Header: C:\THE\RCS\comm1.c 1.4 1993/09/01 16:25:34 MH Interim MH $
  43. */
  44.  
  45. #include <stdio.h>
  46.  
  47. #include "the.h"
  48. #include "proto.h"
  49.  
  50. /*#define DEBUG 1*/
  51.  
  52. /*-------------------------- external data ----------------------------*/
  53. extern LINE *next_line,*curr_line;
  54. extern VIEW_DETAILS *vd_current,*vd_first,*vd_mark;
  55. extern char current_screen;
  56. extern SCREEN_DETAILS screen[MAX_SCREENS];        /* screen structures */
  57. extern WINDOW *foot,*error_window,*divider;
  58. extern bool error_on_screen;
  59. extern char *rec;
  60. extern unsigned short rec_len;
  61. extern char *cmd_rec;
  62. extern unsigned short cmd_rec_len;
  63. extern char mode_insert;        /* defines insert mode toggle */
  64. extern char in_profile;    /* indicates if processing profile */
  65.  
  66. extern char *temp_cmd;
  67. extern char dir_filename[10];
  68. extern char dir_pathname[MAX_FILE_NAME+1];
  69. extern char sp_path[MAX_FILE_NAME+1] ;
  70. extern char sp_fname[MAX_FILE_NAME+1] ;
  71. extern char dir_path[MAX_FILE_NAME+1] ;    /* for dir and ls commands */
  72. /*man-start*********************************************************************
  73. COMMAND
  74.      add - add blank line
  75.  
  76. SYNTAX
  77.      ADD [n]
  78.  
  79. DESCRIPTION
  80.      The ADD command inserts the specified number of blank lines after
  81.      the current_line (if issued from the command line) or after the
  82.      focus_line (if issued in the main of prefix windows).
  83.      The cursor is positioned in the column corresponding to the first
  84.      column not containing a space in the line above.
  85.  
  86. COMPATIBILITY
  87.      XEDIT: Compatible.
  88.      KEDIT: Compatible.
  89.  
  90. DEFAULT
  91.      With no parameters, 1 line is added.
  92.  
  93. SEE ALSO
  94.      SOS ADDLINE
  95.  
  96. STATUS
  97.      Complete
  98. **man-end**********************************************************************/
  99. #ifdef PROTO
  100. int Add(char *params)
  101. #else
  102. int Add(params)
  103. char *params;
  104. #endif
  105. /***********************************************************************/
  106. {
  107. /*--------------------------- local data ------------------------------*/
  108. #define ADD_PARAMS  1
  109.  char *word[ADD_PARAMS+1];
  110.  char parm[ADD_PARAMS];
  111.  unsigned short num_params;
  112.  long num_lines;
  113. /*--------------------------- processing ------------------------------*/
  114. #ifdef TRACE
  115.  trace_function("comm1.c:   Add");
  116. #endif
  117. /*---------------------------------------------------------------------*/
  118. /* Validate the parameters that have been supplied. The one and only   */
  119. /* parameter should be a positive integer greater than zero.           */
  120. /* If no parameter is supplied, 1 is assumed.                          */
  121. /*---------------------------------------------------------------------*/
  122.  num_params = param_split(params,word,ADD_PARAMS,WORD_DELIMS,TEMP_PARAM);
  123.  if (num_params == 0)
  124.     {
  125.      num_params = 1;
  126.      word[0] = (char *)"1";
  127.     }
  128.  if (num_params != 1)
  129.     {
  130.      display_error(1,word[1]);
  131. #ifdef TRACE
  132.      trace_return();
  133. #endif
  134.      return(RC_INVALID_OPERAND);
  135.     }
  136.  if (!valid_positive_integer(word[0]))
  137.     {
  138.      display_error(4,word[0]);
  139. #ifdef TRACE
  140.      trace_return();
  141. #endif
  142.      return(RC_INVALID_OPERAND);
  143.     }
  144.  num_lines = atol(word[0]);
  145.  post_process_line(CURRENT_VIEW->focus_line);
  146.  insert_new_line((char *)"",0,num_lines,get_true_line(),FALSE,FALSE);
  147. #ifdef TRACE
  148.  trace_return();
  149. #endif
  150.  return(RC_OK);
  151. }
  152. /*man-start*********************************************************************
  153. COMMAND
  154.      all - select and display restricted set of lines
  155.  
  156. SYNTAX
  157.      ALL [string target]
  158.  
  159. DESCRIPTION
  160.  
  161. COMPATIBILITY
  162.      XEDIT: Compatible.
  163.      KEDIT: Compatible.
  164.  
  165. DEFAULT
  166.  
  167. SEE ALSO
  168.  
  169. STATUS
  170.      Not Started
  171. **man-end**********************************************************************/
  172. #ifdef PROTO
  173. int All(char *params)
  174. #else
  175. int All(params)
  176. char *params;
  177. #endif
  178. /***********************************************************************/
  179. {
  180. /*--------------------------- local data ------------------------------*/
  181. /*--------------------------- processing ------------------------------*/
  182. #ifdef TRACE
  183.  trace_function("comm1.c:   All");
  184. #endif
  185.  display_error(0,(char *)"This function has not yet been implemented");
  186. #ifdef TRACE
  187.  trace_return();
  188. #endif
  189.  return(RC_OK);
  190. }
  191. /*man-start*********************************************************************
  192. COMMAND
  193.      backward - scroll backwards one screen
  194.  
  195. SYNTAX
  196.      BAckward [n|*]
  197.  
  198. DESCRIPTION
  199.      The BACKWARD command scrolls the file contents backwards through
  200.      the file [n|*] screens.
  201.  
  202. COMPATIBILITY
  203.      XEDIT: Compatible.
  204.      KEDIT: Does not support HALF or Lines options.
  205.  
  206. DEFAULT
  207.      With no parameters, 1 screen is scrolled.
  208.  
  209. SEE ALSO
  210.      forward,top
  211.  
  212. STATUS
  213.      Complete
  214. **man-end**********************************************************************/
  215. #ifdef PROTO
  216. int Backward(char *params)
  217. #else
  218. int Backward(params)
  219. char *params;
  220. #endif
  221. /***********************************************************************/
  222. {
  223. /*--------------------------- local data ------------------------------*/
  224. #define BAC_PARAMS  1
  225.  char *word[BAC_PARAMS+1];
  226.  char parm[BAC_PARAMS];
  227.  register int i;
  228.  unsigned short num_params;
  229.  long num_pages,num_lines;
  230.  unsigned short x,y;
  231.  int rc;
  232. /*--------------------------- processing ------------------------------*/
  233. #ifdef TRACE
  234.  trace_function("comm1.c:   Backward");
  235. #endif
  236.  num_params = param_split(params,word,BAC_PARAMS,WORD_DELIMS,TEMP_PARAM);
  237.  if (num_params == 0)
  238.     {
  239.      num_params = 1;
  240.      word[0] = (char *)"1";
  241.     }
  242.  if (num_params != 1)
  243.     {
  244.      display_error(1,(char *)word[1]);
  245. #ifdef TRACE
  246.     trace_return();
  247. #endif
  248.      return(RC_INVALID_OPERAND);
  249.     }
  250.  if (strcmp(word[0],"*") == 0)
  251.    {
  252.     CURRENT_VIEW->current_line = 0L;
  253.     post_process_line(CURRENT_VIEW->focus_line);
  254.     CURRENT_VIEW->focus_line = 0L;
  255.     pre_process_line(CURRENT_VIEW->focus_line);
  256.     if (!in_profile)
  257.       {
  258.        if (CURRENT_VIEW->current_window == WINDOW_COMMAND)
  259.           getyx(PREVIOUS_WINDOW,y,x);
  260.        else
  261.           getyx(CURRENT_WINDOW,y,x);
  262.        show_page();
  263.        y = get_row_for_focus_line(CURRENT_VIEW->current_row,
  264.                                CURRENT_VIEW->focus_line,
  265.                                CURRENT_VIEW->current_line);
  266.        if (CURRENT_VIEW->current_window == WINDOW_COMMAND)
  267.           wmove(PREVIOUS_WINDOW,y,x);
  268.        else
  269.           wmove(CURRENT_WINDOW,y,x);
  270.       }
  271. #ifdef TRACE
  272.     trace_return();
  273. #endif
  274.     return(RC_TOF_EOF_REACHED);
  275.    }
  276.  if ((num_pages = atol(word[0])) == 0L)
  277.    {
  278.     display_error(4,(char *)word[0]);
  279. #ifdef TRACE
  280.     trace_return();
  281. #endif
  282.     return(RC_INVALID_OPERAND);
  283.    }
  284.  num_lines = CURRENT_VIEW->current_line - ((CURRENT_SCREEN.rows-1)*num_pages);
  285.  if (num_lines < 0)  /* set return code to indicate reaching TOF */
  286.     rc = RC_TOF_EOF_REACHED;
  287.  else
  288.     rc = RC_OK;
  289.  CURRENT_VIEW->current_line = max(num_lines,0);
  290.  
  291.  post_process_line(CURRENT_VIEW->focus_line);
  292.  CURRENT_VIEW->focus_line = calculate_focus_line(CURRENT_VIEW->current_row,
  293.                                                 CURRENT_VIEW->focus_line,
  294.                                                 CURRENT_VIEW->current_line);
  295.  pre_process_line(CURRENT_VIEW->focus_line);
  296.  if (in_profile)
  297.    {
  298. #ifdef TRACE
  299.     trace_return();
  300. #endif
  301.     return(rc);
  302.    }
  303. /* getyx(CURRENT_WINDOW_MAIN,y,x);*/
  304.  getyx(CURRENT_WINDOW,y,x);
  305.  show_page();
  306.  if (CURRENT_VIEW->current_window != WINDOW_COMMAND)
  307.    {
  308.     y = get_row_for_focus_line(CURRENT_VIEW->current_row,
  309.                                CURRENT_VIEW->focus_line,
  310.                                CURRENT_VIEW->current_line);
  311.     wmove(CURRENT_WINDOW,y,x);
  312.    }
  313. #ifdef TRACE
  314.  trace_return();
  315. #endif
  316.  return(rc);
  317. }
  318. /*man-start*********************************************************************
  319. COMMAND
  320.      bottom - move to the bottom of the file
  321.  
  322. SYNTAX
  323.      BOTtom
  324.  
  325. DESCRIPTION
  326.      The BOTTOM command moves to the very end of the current file.
  327.      The last line of the file is set to the current_line.
  328.  
  329. COMPATIBILITY
  330.      XEDIT: Compatible.
  331.      KEDIT: Compatible.
  332.  
  333. SEE ALSO
  334.      forward,top
  335.  
  336. STATUS
  337.      Complete
  338. **man-end**********************************************************************/
  339. #ifdef PROTO
  340. int Bottom(char *params)
  341. #else
  342. int Bottom(params)
  343. char *params;
  344. #endif
  345. /***********************************************************************/
  346. {
  347. /*--------------------------- local data ------------------------------*/
  348.  short rc;
  349.  char cmd[10];
  350. /*--------------------------- processing ------------------------------*/
  351. #ifdef TRACE
  352.  trace_function("comm1.c:   Bottom");
  353. #endif
  354.  sprintf(cmd,":%d",CURRENT_FILE->number_lines);
  355.  rc = command_line(cmd,COMMAND_ONLY_FALSE);
  356. #ifdef TRACE
  357.  trace_return();
  358. #endif
  359.  return(rc);
  360. }
  361. /*man-start*********************************************************************
  362. COMMAND
  363.      cancel - quickly exit from THE
  364.  
  365. SYNTAX
  366.      CANcel
  367.  
  368. DESCRIPTION
  369.      The CANCEL command exits from THE quickly by QQUITting out of all
  370.      files currently in the ring that do not have any outstanding
  371.      alterations.
  372.  
  373. COMPATIBILITY
  374.      XEDIT: Compatible.
  375.      KEDIT: Compatible.
  376.  
  377. SEE ALSO
  378.      ccancel
  379.  
  380. STATUS
  381.      Complete.
  382. **man-end**********************************************************************/
  383. #ifdef PROTO
  384. int Cancel(char *params)
  385. #else
  386. int Cancel(params)
  387. char *params;
  388. #endif
  389. /***********************************************************************/
  390. {
  391. /*--------------------------- local data ------------------------------*/
  392.  VIEW_DETAILS *save_current_view=(VIEW_DETAILS *)NULL;
  393. /*--------------------------- processing ------------------------------*/
  394. #ifdef TRACE
  395.  trace_function("comm1.c:   Cancel");
  396. #endif
  397.  CURRENT_VIEW = vd_first;
  398.  while (CURRENT_VIEW != (VIEW_DETAILS *)NULL)
  399.    {
  400.     if (CURRENT_FILE->save_alt == 0)
  401.        Qquit((char *)"");
  402.     else
  403.       {
  404.        save_current_view = CURRENT_VIEW;
  405.        CURRENT_VIEW = CURRENT_VIEW->next;
  406.       }
  407.    }
  408.  if (save_current_view != (VIEW_DETAILS *)NULL)
  409.    {
  410.     CURRENT_VIEW = save_current_view;
  411.     pre_process_line(CURRENT_VIEW->focus_line);
  412.     show_page();
  413.     if (CURRENT_VIEW->prefix)
  414.        touchwin(CURRENT_WINDOW_PREFIX);
  415.     touchwin(CURRENT_WINDOW_COMMAND);
  416.     touchwin(CURRENT_WINDOW_MAIN);
  417.     touchwin(CURRENT_WINDOW);
  418.    }
  419. #ifdef TRACE
  420.  trace_return();
  421. #endif
  422.  return(QUIT);
  423. }
  424. /*man-start*********************************************************************
  425. COMMAND
  426.      ccancel - quickly exit from THE
  427.  
  428. SYNTAX
  429.      CCancel
  430.  
  431. DESCRIPTION
  432.      The CCANCEL command exits from THE quickly by QQUITting out of all
  433.      files currently in the ring. Any changes made to any of the files
  434.      will be lost.
  435.  
  436. COMPATIBILITY
  437.      XEDIT: N/A
  438.      KEDIT: N/A
  439.  
  440. SEE ALSO
  441.      cancel
  442.  
  443. STATUS
  444.      Complete.
  445. **man-end**********************************************************************/
  446. #ifdef PROTO
  447. int Ccancel(char *params)
  448. #else
  449. int Ccancel(params)
  450. char *params;
  451. #endif
  452. /***********************************************************************/
  453. {
  454. /*--------------------------- local data ------------------------------*/
  455. /*--------------------------- processing ------------------------------*/
  456. #ifdef TRACE
  457.  trace_function("comm1.c:   Ccancel");
  458. #endif
  459.  CURRENT_VIEW = vd_first;
  460.  while (CURRENT_VIEW != (VIEW_DETAILS *)NULL)
  461.    {
  462.     Qquit((char *)"");
  463.    }
  464. #ifdef TRACE
  465.  trace_return();
  466. #endif
  467.  return(QUIT);
  468. }
  469. /*man-start*********************************************************************
  470. COMMAND
  471.      change - change file text
  472.  
  473. SYNTAX
  474.      Change /string1/string2/ [target] [n] [m]
  475.  
  476. DESCRIPTION
  477.      The CHANGE command changes one string of text to another.
  478.  
  479.      The first parameter to the change command is the old and new
  480.      string values, seperated by delimiters.
  481.      The allowable delimiters are '/' '\' and '@'.
  482.  
  483.      The second parameter is the target; how many lines are to be
  484.      searched for occurrences of the first string to be changed.
  485.  
  486.      The third parameter determines how many occurrences of 'string1'
  487.      are to be changed on each line.
  488.  
  489.      The fourth parameter determines at which occurrences of 'string1'
  490.      on the line are changes to commence.
  491.  
  492. COMPATIBILITY
  493.      XEDIT: Compatible.
  494.      KEDIT: Compatible.
  495.  
  496. DEFAULT
  497.      1 1 1
  498.  
  499. SEE ALSO
  500.      schange
  501.  
  502. STATUS
  503.      Complete.
  504. **man-end**********************************************************************/
  505. #ifdef PROTO
  506. int Change(char *params)
  507. #else
  508. int Change(params)
  509. char *params;
  510. #endif
  511. /***********************************************************************/
  512. {
  513. /*--------------------------- local data ------------------------------*/
  514.  short rc;
  515. /*--------------------------- processing ------------------------------*/
  516. #ifdef TRACE
  517.  trace_function("comm1.c:   Change");
  518. #endif
  519.  
  520.  rc = execute_change_command(params,FALSE);
  521.  
  522. #ifdef TRACE
  523.  trace_return();
  524. #endif
  525.  return(rc);
  526. }
  527. /*man-start*********************************************************************
  528. COMMAND
  529.      cmatch - find matching bracket character
  530.  
  531. SYNTAX
  532.      ** effective only if bound to a key **
  533.  
  534. DESCRIPTION
  535.      The CMATCH command searches for the matching bracket character to
  536.      the character under the cursor.
  537.  
  538.      It handles nested sets of matching pairs.
  539.      The matching character pairs are '[]{}<>()'.
  540.  
  541. COMPATIBILITY
  542.      XEDIT: N/A
  543.      KEDIT: Compatible.
  544.  
  545. STATUS
  546.      Complete.
  547. **man-end**********************************************************************/
  548. #ifdef PROTO
  549. int Cmatch(char *params)
  550. #else
  551. int Cmatch(params)
  552. char *params;
  553. #endif
  554. /***********************************************************************/
  555. {
  556. /*--------------------------- local data ------------------------------*/
  557.  static char *match = (char *)"[]{}<>()";
  558.  unsigned short x,y;
  559.  char ch,match_ch;
  560.  register int i;
  561.  int direction_backward;
  562.  short matches=1,match_col=(-1),start_col;
  563.  long offset=0;
  564.  LINE *curr;
  565.  WINDOW *w;
  566. /*--------------------------- processing ------------------------------*/
  567. #ifdef TRACE
  568.  trace_function("comm1.c:   Cmatch");
  569. #endif
  570. /*---------------------------------------------------------------------*/
  571. /* This command only allowed to be issued from with the MAIN window.   */
  572. /*---------------------------------------------------------------------*/
  573.  if (CURRENT_VIEW->current_window != WINDOW_MAIN
  574.  || in_profile)
  575.    {
  576.     display_error(66,(char *)"");
  577. #ifdef TRACE
  578.     trace_return();
  579. #endif
  580.     return(RC_INVALID_ENVIRON);
  581.    }
  582.  if (CURRENT_VIEW->focus_line == 0
  583.  ||  CURRENT_VIEW->focus_line == CURRENT_FILE->number_lines+1)
  584.    {
  585.     display_error(66,(char *)"");
  586. #ifdef TRACE
  587.     trace_return();
  588. #endif
  589.     return(RC_TOF_EOF_REACHED);
  590.    }
  591.  getyx(CURRENT_WINDOW,y,x);
  592. /*---------------------------------------------------------------------*/
  593. /* Check if the character under the cursor is a valid match character. */
  594. /*---------------------------------------------------------------------*/
  595.  w = CURRENT_WINDOW;
  596.  ch = (char)winch(w) & A_CHARTEXT;
  597.  match_ch = 0;
  598.  for (i=0;i<strlen(match);i++)
  599.     if (ch == *(match+i))
  600.       {
  601.        direction_backward = (i % 2);
  602.        match_ch = (direction_backward) ? *(match+i-1) : *(match+i+1);
  603.        break;
  604.       }
  605.  if (match_ch == 0)
  606.    {
  607.     display_error(67,(char *)"");
  608. #ifdef TRACE
  609.     trace_return();
  610. #endif
  611.     return(RC_INVALID_OPERAND);
  612.    }
  613. /*---------------------------------------------------------------------*/
  614. /* Calculate the actual position of the character in the LINE.         */
  615. /*---------------------------------------------------------------------*/
  616.  start_col = CURRENT_VIEW->verify_col + x - 1;
  617.  start_col += (direction_backward) ? (-1) : 1;
  618. /*---------------------------------------------------------------------*/
  619. /* Find the focus line linked list entry.                              */
  620. /*---------------------------------------------------------------------*/
  621.  post_process_line(CURRENT_VIEW->focus_line);
  622. #ifdef USE_VOID
  623.  curr = (LINE *)ll_find((void *)CURRENT_FILE->first_line,CURRENT_VIEW->focus_line);
  624. #else
  625.  curr = lll_find(CURRENT_FILE->first_line,CURRENT_VIEW->focus_line);
  626. #endif
  627.  while (curr->next != NULL && curr->prev != NULL)
  628.    {
  629.     if (direction_backward)
  630.       {
  631.        for (i=start_col;i>(-1);i--)
  632.           {
  633.            if (*(curr->line+i) == ch)
  634.              matches++;
  635.            else
  636.               if (*(curr->line+i) == match_ch)
  637.                 matches--;
  638.            if (matches == 0)       /* found matching one */
  639.              {
  640.               match_col = i;
  641.               break;
  642.              }
  643.           }
  644.        if (match_col != (-1))
  645.          break;
  646.        curr = curr->prev;
  647.        offset--;
  648.        start_col = curr->length;
  649.       }
  650.     else
  651.       {
  652.        for (i=start_col;i<curr->length;i++)
  653.           {
  654.            if (*(curr->line+i) == ch)
  655.              matches++;
  656.            else
  657.               if (*(curr->line+i) == match_ch)
  658.                 matches--;
  659.            if (matches == 0)       /* found matching one */
  660.              {
  661.               match_col = i;
  662.               break;
  663.              }
  664.           }
  665.        if (match_col != (-1))
  666.          break;
  667.        curr = curr->next;
  668.        offset++;
  669.        start_col = 0;
  670.       }
  671.    }
  672.  if (match_col == (-1))  /* no match found */
  673.    {
  674.     display_error(68,(char *)"");
  675. #ifdef TRACE
  676.     trace_return();
  677. #endif
  678.     return(RC_TARGET_NOT_FOUND);
  679.    }
  680. /*---------------------------------------------------------------------*/
  681. /* If we get here, we have found the matching character, so we have to */
  682. /*  move the cursor to the new column and/or line.                     */
  683. /*---------------------------------------------------------------------*/
  684.  if (offset == 0L)
  685.    {
  686.     if (match_col >= CURRENT_VIEW->verify_col-1
  687.     &&  match_col <= (CURRENT_SCREEN.cols+(CURRENT_VIEW->verify_col-1))-1)
  688. /*---------------------------------------------------------------------*/
  689. /* If the new cursor position is in the same panel and on the same line*/
  690. /* just move the cursor there and get out.                             */
  691. /*---------------------------------------------------------------------*/
  692.       {
  693.        wmove(CURRENT_WINDOW,y,match_col-(CURRENT_VIEW->verify_col-1));
  694. #ifdef TRACE
  695.        trace_return();
  696. #endif
  697.        return(RC_OK);
  698.       }
  699.    else
  700.       {
  701.        x = CURRENT_SCREEN.cols / 2;
  702.        CURRENT_VIEW->verify_col = max(1,match_col-(short)x);
  703.        show_page();
  704.        wmove(CURRENT_WINDOW,y,(match_col-(CURRENT_VIEW->verify_col-1)));
  705. #ifdef TRACE
  706.        trace_return();
  707. #endif
  708.        return(RC_OK);
  709.       }
  710.    }
  711.  
  712.  CURRENT_VIEW->focus_line += offset;
  713.  pre_process_line(CURRENT_VIEW->focus_line);
  714.  if (offset + y <= 0
  715.  ||  offset + y >= CURRENT_SCREEN.rows)
  716.    {
  717.     CURRENT_VIEW->current_line = CURRENT_VIEW->focus_line;
  718.     y = CURRENT_VIEW->current_row;
  719.    }
  720.  else
  721.     y = get_row_for_focus_line(CURRENT_VIEW->current_row,
  722.                                CURRENT_VIEW->focus_line,
  723.                                CURRENT_VIEW->current_line);
  724.  if (match_col >= CURRENT_VIEW->verify_col-1
  725.  &&  match_col <= (CURRENT_SCREEN.cols+(CURRENT_VIEW->verify_col-1))-1)
  726.     x = match_col-(CURRENT_VIEW->verify_col-1);
  727.  else
  728.    {
  729.     x = CURRENT_SCREEN.cols / 2;
  730.     CURRENT_VIEW->verify_col = max(1,match_col-(short)x);
  731.     x = (match_col-(CURRENT_VIEW->verify_col-1));
  732.    }
  733.  
  734.  show_page();
  735.  wmove(CURRENT_WINDOW,y,x);
  736. #ifdef TRACE
  737.  trace_return();
  738. #endif
  739.  return(RC_OK);
  740. }
  741. /*man-start*********************************************************************
  742. COMMAND
  743.      cmsg - display text on command line
  744.  
  745. SYNTAX
  746.      CMSG [text]
  747.  
  748. DESCRIPTION
  749.      The CMSG command, primarily used in macros, displays text on the
  750.      command line.
  751.  
  752. COMPATIBILITY
  753.      XEDIT: Compatible.
  754.      KEDIT: Compatible.
  755.  
  756. SEE ALSO
  757.      EMSG, MSG
  758.  
  759. STATUS
  760.      Complete.
  761. **man-end**********************************************************************/
  762. #ifdef PROTO
  763. int Cmsg(char *params)
  764. #else
  765. int Cmsg(params)
  766. char *params;
  767. #endif
  768. /***********************************************************************/
  769. {
  770. /*------------------------- external data -----------------------------*/
  771.  extern bool clear_command;
  772.  extern bool extended_display_mode;
  773.  register int i;
  774. /*--------------------------- local data ------------------------------*/
  775. /*--------------------------- processing ------------------------------*/
  776. #ifdef TRACE
  777.  trace_function("comm1.c:   Cmsg");
  778. #endif
  779.  memset(cmd_rec,' ',COLS);
  780.  cmd_rec_len = strlen(params);
  781.  memcpy(cmd_rec,params,cmd_rec_len);
  782.  wmove(CURRENT_WINDOW_COMMAND,0,0);
  783.  my_wclrtoeol(CURRENT_WINDOW_COMMAND);
  784. /*---------------------------------------------------------------------*/
  785. /* If the terminal is in ETMODE, display all characters as is, else    */
  786. /* display message with translation of non-displaying characters.      */
  787. /*---------------------------------------------------------------------*/
  788.  if (extended_display_mode)
  789.    {
  790.     for (i=0;i<cmd_rec_len;i++)
  791.         mvwaddch(CURRENT_WINDOW_COMMAND,0,i,cmd_rec[i]);
  792.    }
  793.  else
  794.     put_string(CURRENT_WINDOW_COMMAND,0,0,cmd_rec,cmd_rec_len);
  795.  clear_command = FALSE;
  796. #ifdef TRACE
  797.  trace_return();
  798. #endif
  799.  return(RC_OK);
  800. }
  801. /*man-start*********************************************************************
  802. COMMAND
  803.      command - execute a command without synonym translation
  804.  
  805. SYNTAX
  806.      COMMAND command [options]
  807.  
  808. DESCRIPTION
  809.      The COMMAND command executes the specified command without
  810.      synonym translation. THE does not attempt to execute the command
  811.      as a macro even if IMPMACRO is ON. The command will be passed
  812.      to the operating system if IMPOS is ON.
  813.  
  814. COMPATIBILITY
  815.      XEDIT: Compatible.
  816.      KEDIT: Compatible.
  817.  
  818. STATUS
  819.      Complete.
  820. **man-end**********************************************************************/
  821. #ifdef PROTO
  822. int Command(char *params)
  823. #else
  824. int Command(params)
  825. char *params;
  826. #endif
  827. /***********************************************************************/
  828. {
  829. /*------------------------- external data -----------------------------*/
  830. /*--------------------------- local data ------------------------------*/
  831.  int rc;
  832. /*--------------------------- processing ------------------------------*/
  833. #ifdef TRACE
  834.  trace_function("comm1.c:   Command");
  835. #endif
  836.  rc = command_line(params,COMMAND_ONLY_TRUE);
  837. #ifdef TRACE
  838.  trace_return();
  839. #endif
  840.  return(rc);
  841. }
  842. /*man-start*********************************************************************
  843. COMMAND
  844.      control_char - allow control characters to be entered
  845.  
  846. SYNTAX
  847.      ** effective only if bound to a key **
  848.  
  849. DESCRIPTION
  850.      The CONTROL_CHAR command prompts the user to enter a control character.
  851.  
  852. COMPATIBILITY
  853.      XEDIT: N/A
  854.      KEDIT: N/A
  855.  
  856. STATUS
  857.      Complete.
  858. **man-end**********************************************************************/
  859. #ifdef PROTO
  860. int Control_char(char *params)
  861. #else
  862. int Control_char(params)
  863. char *params;
  864. #endif
  865. /***********************************************************************/
  866. {
  867. /*--------------------------- local data ------------------------------*/
  868.  unsigned short key;
  869. /*--------------------------- processing ------------------------------*/
  870. #ifdef TRACE
  871.  trace_function("comm1.c:   Control_char");
  872. #endif
  873.  display_error(0,(char *)"Press the character you require.");
  874.  touchwin(error_window);
  875.  doupdate();
  876.  key = my_getch(CURRENT_WINDOW);
  877.  if (islower(key))
  878.     key = toupper(key);
  879.  if (key >= '@'
  880.  &&  key <= '_')
  881.    {
  882.     error_on_screen = FALSE;
  883.     touchwin(foot);
  884. #ifdef TRACE
  885.     trace_return();
  886. #endif
  887.     return((RAW_KEY*2)+key-'@');
  888.    }
  889.  display_error(69,(char *)"- must be between '@' and '_'");
  890. #ifdef TRACE
  891.  trace_return();
  892. #endif
  893.  return(RC_INVALID_OPERAND);
  894. }
  895. /*man-start*********************************************************************
  896. COMMAND
  897.      copy - copies text from one position to another
  898.  
  899. SYNTAX
  900.      COPY target1 target2
  901.       or
  902.      COPY BLOCK [RESET]
  903.  
  904. DESCRIPTION
  905.      With the first form of the COPY command, text is copied from the
  906.      first target area to the line specified by target2. Text can
  907.      only be copied within the same view of the file.
  908.  
  909.      The second form of the COPY command copies text within the
  910.      currently marked block to the current cursor position.
  911.      The text can be in the same file or a different file.
  912.  
  913. COMPATIBILITY
  914.      The first form of the COPY command has not yet been implemented.
  915.      XEDIT: Not implemented.
  916.      KEDIT: Adds extra functionality with [RESET] option.
  917.             With the cursor in the marked block this command in KEDIT
  918.             acts like DUPLICATE BLOCK.
  919.  
  920. STATUS
  921.      Complete.
  922. **man-end**********************************************************************/
  923. #ifdef PROTO
  924. int Copy(char *params)
  925. #else
  926. int Copy(params)
  927. char *params;
  928. #endif
  929. /***********************************************************************/
  930. {
  931. /*--------------------------- local data ------------------------------*/
  932. #define COP_PARAMS 2
  933.  char *word[COP_PARAMS+1];
  934.  unsigned short num_params;
  935.  long num_lines;
  936.  LINE *curr_dst,*curr_src;
  937.  register int i,j;
  938.  unsigned short y,x;
  939.  long true_line,off;
  940.  char reset_block=0;
  941.  bool dst_inside_src;
  942.  int rc;
  943. /*--------------------------- processing ------------------------------*/
  944. #ifdef TRACE
  945.  trace_function("comm1.c:   Copy");
  946. #endif
  947.  num_params = param_split(params,word,COP_PARAMS,WORD_DELIMS,TEMP_PARAM);
  948.  if (num_params == 0)
  949.     {
  950.      display_error(3,(char *)"");
  951. #ifdef TRACE
  952.      trace_return();
  953. #endif
  954.      return(RC_INVALID_OPERAND);
  955.     }
  956.  if (num_params > 2)
  957.     {
  958.      display_error(2,(char *)"");
  959. #ifdef TRACE
  960.      trace_return();
  961. #endif
  962.      return(RC_INVALID_OPERAND);
  963.     }
  964. /*---------------------------------------------------------------------*/
  965. /* Test for second form of COPY; block operation.                      */
  966. /*---------------------------------------------------------------------*/
  967.  if (num_params == 1
  968.  &&  equal((char *)"block",word[0],5))
  969.     reset_block = SOURCE_BLOCK;
  970.  if (num_params == 2
  971.  &&  equal((char *)"block",word[0],5)
  972.  &&  equal((char *)"reset",word[1],5))
  973.     reset_block = SOURCE_BLOCK_RESET;
  974.  if (reset_block == 0)
  975.     {
  976.      display_error(0,(char *)"This option has not yet been implemented");
  977. #ifdef TRACE
  978.      trace_return();
  979. #endif
  980.      return(RC_INVALID_OPERAND);
  981.     }
  982. /*---------------------------------------------------------------------*/
  983. /* If no marked block in any view, return error.                       */
  984. /*---------------------------------------------------------------------*/
  985.  if (marked_block(FALSE) != RC_OK)
  986.    {
  987. #ifdef TRACE
  988.     trace_return();
  989. #endif
  990.     return(RC_INVALID_ENVIRON);
  991.    }
  992. /*---------------------------------------------------------------------*/
  993. /* For box blocks, call the appropriate function...                    */
  994. /*---------------------------------------------------------------------*/
  995.  if (MARK_VIEW->mark_type != M_LINE)
  996.    {
  997.     box_operations(BOX_C,reset_block,FALSE,' ');
  998. #ifdef TRACE
  999.     trace_return();
  1000. #endif
  1001.     return(RC_OK);
  1002.    }
  1003. /*---------------------------------------------------------------------*/
  1004. /* Determine the target line. If on the command line, target is current*/
  1005. /* line, else target line is focus line.                               */
  1006. /*---------------------------------------------------------------------*/
  1007.  true_line = get_true_line();
  1008. /*---------------------------------------------------------------------*/
  1009. /* If the true  line is the bottom of file line, subtract 1 from it.   */
  1010. /*---------------------------------------------------------------------*/
  1011.  if (BOF(true_line))
  1012.      true_line--;
  1013.  
  1014.  
  1015.  post_process_line(CURRENT_VIEW->focus_line);
  1016.  rc = rearrange_line_blocks(COMMAND_COPY,(char)reset_block,MARK_VIEW->mark_start_line,
  1017.                             MARK_VIEW->mark_end_line,true_line,1,MARK_VIEW,CURRENT_VIEW);
  1018.  
  1019.  
  1020. #ifdef TRACE
  1021.  trace_return();
  1022. #endif
  1023.  return(rc);
  1024. }
  1025. /*man-start*********************************************************************
  1026. COMMAND
  1027.      define - assign one or many commands to a key
  1028.  
  1029. SYNTAX
  1030.      DEFine key-name [command [args] [[#command [args]...]]]
  1031.  
  1032. DESCRIPTION
  1033.      The DEFINE command allows the user to assign one or many 
  1034.      commands and optional parameter(s) to a key. 
  1035.  
  1036.      Commands may be abbreviated.
  1037.  
  1038.      If multiple commands are assigned, then the LINEND setting
  1039.      must be ON and the LINEND character must match the character
  1040.      that delimits the commands at the time that the DEFINE command
  1041.      is executed and at the time the key is pressed.
  1042.  
  1043.      With no arguments, any existing definition for that key is
  1044.      removed and the key reverts back to its default assignation (if
  1045.      it had any).
  1046.  
  1047.      key-names correspond to the key name shown with the SHOW command.
  1048.  
  1049. COMPATIBILITY
  1050.      XEDIT: N/A
  1051.      KEDIT: Minimal. No support for in-memory macro commands.
  1052.             KEDIT does not allow multiple commands except as KEXX
  1053.             macros.
  1054.  
  1055. SEE ALSO
  1056.      SHOW
  1057.  
  1058. STATUS
  1059.      Complete.
  1060. **man-end**********************************************************************/
  1061. #ifdef PROTO
  1062. int Define(char *params)
  1063. #else
  1064. int Define(params)
  1065. char *params;
  1066. #endif
  1067. /***********************************************************************/
  1068. {
  1069. /*--------------------------- local data ------------------------------*/
  1070. #define DEF_PARAMS  2
  1071.  char *word[DEF_PARAMS+1];
  1072.  char parm[DEF_PARAMS];
  1073.  unsigned short num_params;
  1074.  short key_value;
  1075.  int rc=RC_OK;
  1076. /*--------------------------- processing ------------------------------*/
  1077. #ifdef TRACE
  1078.  trace_function("comm1.c:   Define");
  1079. #endif
  1080.  num_params = param_split(params,word,DEF_PARAMS,WORD_DELIMS,TEMP_PARAM);
  1081.  if (num_params ==0)
  1082.    {
  1083.     display_error(3,(char *)"");
  1084. #ifdef TRACE
  1085.     trace_return();
  1086. #endif
  1087.     return(RC_INVALID_OPERAND);
  1088.    }
  1089. /*---------------------------------------------------------------------*/
  1090. /* The first parameter is the key name mnemonic , the next is one or   */
  1091. /* more commands and/or parameters.                                    */
  1092. /* First check the mnemonic for decimal string value. ie begins with \ */
  1093. /*---------------------------------------------------------------------*/
  1094.  if (word[0][0] == '\\')
  1095.    {
  1096.     if ((key_value = atoi(word[0]+1)) == 0)
  1097.       {
  1098.        display_error(13,word[0]);
  1099.        rc = RC_INVALID_OPERAND;
  1100.       }
  1101.    }
  1102.  else
  1103.    {
  1104.     if ((key_value = find_key_value(word[0])) == (-1))
  1105.       {
  1106.        display_error(13,word[0]);
  1107.        rc = RC_INVALID_OPERAND;
  1108.        }
  1109.    }
  1110.  if (rc == RC_OK)
  1111.     rc = add_define(key_value,word[1]);
  1112. #ifdef TRACE
  1113.  trace_return();
  1114. #endif
  1115.  return(rc);
  1116. }
  1117. /*man-start*********************************************************************
  1118. COMMAND
  1119.      delete - delete lines from a file
  1120.  
  1121. SYNTAX
  1122.      DELete [target|BLOCK]
  1123.  
  1124. DESCRIPTION
  1125.      The DELETE command allows the user remove lines from the current
  1126.      file. The number of lines removed depends on the target specified.
  1127.      Lines are removed starting with the current_line.
  1128.  
  1129. COMPATIBILITY
  1130.      XEDIT: BLOCK option not supported in XEDIT.
  1131.      KEDIT: Compatible.
  1132.  
  1133. DEFAULT
  1134.      1 (the current line)
  1135.  
  1136. SEE ALSO
  1137.      SOS DELETE
  1138.  
  1139. STATUS
  1140.      Complete.
  1141. **man-end**********************************************************************/
  1142. #ifdef PROTO
  1143. int DeleteLine(char *params)
  1144. #else
  1145. int DeleteLine(params)
  1146. char *params;
  1147. #endif
  1148. /***********************************************************************/
  1149. {
  1150. /*--------------------------- local data ------------------------------*/
  1151. #define DEL_PARAMS  1
  1152.  char *word[DEL_PARAMS+1];
  1153.  char parm[DEL_PARAMS];
  1154.  register int i;
  1155.  unsigned short num_params;
  1156.  long num_lines,true_line;
  1157.  unsigned short x,y;
  1158.  int direction;
  1159.  LINE *curr;
  1160.  bool block_delete=FALSE;
  1161.  int rc;
  1162. /*--------------------------- processing ------------------------------*/
  1163. #ifdef TRACE
  1164.  trace_function("comm1.c:   DeleteLine");
  1165. #endif
  1166. /*---------------------------------------------------------------------*/
  1167. /* Validate the parameters that have been supplied.                    */
  1168. /* Valid values are: a target or "block".                              */
  1169. /* If no parameter is supplied, 1 is assumed.                          */
  1170. /*---------------------------------------------------------------------*/
  1171.  num_params = param_split(params,word,DEL_PARAMS,WORD_DELIMS,TEMP_PARAM);
  1172.  if (num_params == 0)
  1173.     {
  1174.      num_params = 1;
  1175.      word[0] = (char *)"1";
  1176.     }
  1177. /*---------------------------------------------------------------------*/
  1178. /* Set up and validate parameters for "block" deletes.                 */
  1179. /*---------------------------------------------------------------------*/
  1180.  if (equal((char *)"block",word[0],5))
  1181.    {
  1182.     block_delete = TRUE;
  1183.     if (marked_block(TRUE) != RC_OK)
  1184.       {
  1185. #ifdef TRACE
  1186.        trace_return();
  1187. #endif
  1188.        return(RC_INVALID_ENVIRON);
  1189.       }
  1190.     if (MARK_VIEW->mark_type != M_LINE)
  1191.       {
  1192.        box_operations(BOX_D,SOURCE_BLOCK_RESET,FALSE,' ');
  1193. #ifdef TRACE
  1194.        trace_return();
  1195. #endif
  1196.        return(RC_OK);
  1197.       }
  1198.     num_lines = CURRENT_VIEW->mark_end_line-CURRENT_VIEW->mark_start_line+1L;
  1199.     true_line = CURRENT_VIEW->mark_start_line;
  1200.     direction = DIRECTION_FORWARD;
  1201.    }
  1202.  else
  1203. /*---------------------------------------------------------------------*/
  1204. /* Set up and validate parameters for deletes from command line or     */
  1205. /* sos delline.                                                        */
  1206. /*---------------------------------------------------------------------*/
  1207.    {
  1208.     if (equal((char *)"all",word[0],3))
  1209.        true_line = 1L;
  1210.     else
  1211.        true_line = get_true_line();
  1212.     if ((num_lines = valid_target(word[0],true_line)) == TARGET_ERROR)
  1213.       {
  1214.        display_error(4,(char *)word[0]);
  1215. #ifdef TRACE
  1216.        trace_return();
  1217. #endif
  1218.        return(RC_TARGET_NOT_FOUND);
  1219.       }
  1220.     if (num_lines == TARGET_NOT_FOUND)
  1221.       {
  1222.        display_error(17,(char *)"");
  1223. #ifdef TRACE
  1224.        trace_return();
  1225. #endif
  1226.        return(RC_TARGET_NOT_FOUND);
  1227.       }
  1228. /*---------------------------------------------------------------------*/
  1229. /* Determine in which direction we are deleting.                       */
  1230. /*---------------------------------------------------------------------*/
  1231.     if (num_lines < 0)
  1232.       {
  1233.        direction = DIRECTION_BACKWARD;
  1234.        num_lines = num_lines * (-1L);
  1235.       }
  1236.     else
  1237.       direction = DIRECTION_FORWARD;
  1238. /*---------------------------------------------------------------------*/
  1239. /* Check from which window the command was issued and make adjustments */
  1240. /* as required.                                                        */
  1241. /* Commands issued from the command window relate to the current line, */
  1242. /* commands issued from either the prefix or main window relate to the */
  1243. /* focus line.                                                         */
  1244. /*---------------------------------------------------------------------*/
  1245.     if (equal((char *)"all",word[0],3))
  1246.        ;
  1247.     else
  1248.        if (CURRENT_VIEW->current_window == WINDOW_COMMAND
  1249.        || in_profile)
  1250.          {
  1251.           if (true_line == 0L)
  1252.             {
  1253.              true_line++;
  1254.              if (!valid_integer(word[0]))
  1255.                 num_lines--;
  1256.             }
  1257.           if (BOF(true_line))
  1258.             {
  1259.              true_line--;
  1260.              if (!valid_integer(word[0]))
  1261.                 num_lines--;
  1262.             }
  1263.          }
  1264.        else
  1265.          {
  1266.           if (BOF(true_line) || TOF(true_line))
  1267.             {
  1268.              display_error(38,(char *)"");
  1269. #ifdef TRACE
  1270.              trace_return();
  1271. #endif
  1272.              return(RC_INVALID_ENVIRON);
  1273.             }
  1274.           post_process_line(true_line);
  1275.          }
  1276.    }
  1277.  
  1278.  rc = rearrange_line_blocks(COMMAND_DELETE,TRUE,true_line,
  1279.                             (direction == DIRECTION_FORWARD ? true_line+num_lines-1L : true_line-num_lines+1L),
  1280.                             true_line,1,CURRENT_VIEW,CURRENT_VIEW);
  1281.  
  1282. #ifdef TRACE
  1283.  trace_return();
  1284. #endif
  1285.  if (CURRENT_BOF || CURRENT_TOF)
  1286.     return(RC_TOF_EOF_REACHED);
  1287.  else
  1288.     return(RC_OK);
  1289. }
  1290. /*man-start*********************************************************************
  1291. COMMAND
  1292.      directory - list the specified directory
  1293.  
  1294. SYNTAX
  1295.      DIRectory [directory]
  1296.  
  1297. DESCRIPTION
  1298.      The DIRECTORY command displays all files in the specified directory.
  1299.      When no parameter is supplied, the current directory is displayed.
  1300.  
  1301. COMPATIBILITY
  1302.      XEDIT: N/A
  1303.      KEDIT: Compatible.
  1304.  
  1305. STATUS
  1306.      Complete.
  1307. **man-end**********************************************************************/
  1308. #ifdef PROTO
  1309. int Directory(char *params)
  1310. #else
  1311. int Directory(params)
  1312. char *params;
  1313. #endif
  1314. /***********************************************************************/
  1315. {
  1316. /*--------------------------- local data ------------------------------*/
  1317. #define DIR_PARAMS  1
  1318.  char *word[DIR_PARAMS+1];
  1319.  unsigned short num_params;
  1320.  int rc;
  1321. /*--------------------------- processing ------------------------------*/
  1322. #ifdef TRACE
  1323.  trace_function("comm1.c:   Directory");
  1324. #endif
  1325. /*---------------------------------------------------------------------*/
  1326. /* Validate the parameters that have been supplied. The one and only   */
  1327. /* parameter should be the directory to display.                       */
  1328. /*---------------------------------------------------------------------*/
  1329.  num_params = param_split(params,word,DIR_PARAMS,WORD_DELIMS,TEMP_PARAM);
  1330.  if (num_params > 1)
  1331.    {
  1332.     display_error(1,(char *)word[1]);
  1333. #ifdef TRACE
  1334.     trace_return();
  1335. #endif
  1336.     return(RC_INVALID_OPERAND);
  1337.    }
  1338. /*---------------------------------------------------------------------*/
  1339. /* Validate that the supplied directory is valid.                      */
  1340. /*---------------------------------------------------------------------*/
  1341.  if ((rc = splitpath(strtrans(word[0],OSLASH,ISLASH))) != RC_OK)
  1342.    {
  1343.     display_error(10,(char *)word[0]);
  1344. #ifdef TRACE
  1345.     trace_return();
  1346. #endif
  1347.     return(rc);
  1348.    }
  1349.  if ((rc = read_directory()) != RC_OK)
  1350.    {
  1351.     display_error(10,(char *)word[0]);
  1352. #ifdef TRACE
  1353.     trace_return();
  1354. #endif
  1355.     return(rc);
  1356.    }
  1357.  strcpy(temp_cmd,dir_pathname);
  1358.  strcat(temp_cmd,dir_filename);
  1359.  Xedit(temp_cmd);
  1360. #ifdef TRACE
  1361.  trace_return();
  1362. #endif
  1363.  return(RC_OK);
  1364. }
  1365. /*man-start*********************************************************************
  1366. COMMAND
  1367.      down_arrow - move the cursor down one line
  1368.  
  1369. SYNTAX
  1370.      ** effective only if bound to a key **
  1371.  
  1372. DESCRIPTION
  1373.      The down_arrow command moves the cursor down one line in the main
  1374.      window. Scrolling of the window occurs if the cursor is on the last
  1375.      line of the window and CMDARROWS ... SCROLL is set (the default),
  1376.      otherwise the cursor returns to the command line.
  1377.  
  1378.      When on the command line, this command moves forward through the
  1379.      list of previous command line commands if CMDARROWS RETRIEVE ...
  1380.      is set or tabs to the first line of the main window if 
  1381.      CMDARROWS TAB ... is set.
  1382.  
  1383. COMPATIBILITY
  1384.      XEDIT: N/A
  1385.      KEDIT: Equivalent of CURSOR DOWN.
  1386.  
  1387. SEE ALSO
  1388.      Up_arrow
  1389.  
  1390. STATUS
  1391.      Complete.
  1392. **man-end**********************************************************************/
  1393. #ifdef PROTO
  1394. int Down_arrow(char *params)
  1395. #else
  1396. int Down_arrow(params)
  1397. char *params;
  1398. #endif
  1399. /***********************************************************************/
  1400. {
  1401. /*------------------------- external data -----------------------------*/
  1402. extern char CMDARROWSTABCMDx;
  1403. extern char CMDARROWSTABTXTx;
  1404. /*--------------------------- local data ------------------------------*/
  1405.  unsigned short x,y;
  1406. /*--------------------------- processing ------------------------------*/
  1407. #ifdef TRACE
  1408.  trace_function("comm1.c:   Down_arrow");
  1409. #endif
  1410.  switch(CURRENT_VIEW->current_window)
  1411.   {
  1412.    case WINDOW_PREFIX:
  1413.    case WINDOW_MAIN:
  1414.         getyx(CURRENT_WINDOW,y,x);
  1415. /*---------------------------------------------------------------------*/
  1416. /* If the cursor is on the first line of the window or on the first    */
  1417. /* line of the file and tabbibg to the command line is set, tab to the */
  1418. /* command line.                                                       */
  1419. /*---------------------------------------------------------------------*/
  1420.         if (CMDARROWSTABTXTx
  1421.         && (FOCUS_BOF || y == CURRENT_SCREEN.rows-1))
  1422.           {
  1423.            Tabcmd("");
  1424.            break;
  1425.           }
  1426. /*---------------------------------------------------------------------*/
  1427. /* If the cursor is on the last line of the file...                    */
  1428. /*---------------------------------------------------------------------*/
  1429.         if (CURRENT_VIEW->current_line+y-
  1430.            CURRENT_VIEW->current_row == CURRENT_FILE->number_lines+1)
  1431.            {
  1432. /*---------------------------------------------------------------------*/
  1433. /* ... and the last line of the file is on the current row, stay there.*/
  1434. /*---------------------------------------------------------------------*/
  1435.             if (CURRENT_VIEW->current_line ==
  1436.                 CURRENT_FILE->number_lines+1)
  1437.                 break;
  1438. /*---------------------------------------------------------------------*/
  1439. /* ... and the last line of the file is below the current row,         */
  1440. /* scroll the window up one line.                                      */
  1441. /*---------------------------------------------------------------------*/
  1442.             CURRENT_VIEW->current_line++;
  1443.             show_page();
  1444.             wmove(CURRENT_WINDOW,y-1,x);
  1445.             break;
  1446.            }
  1447. /*---------------------------------------------------------------------*/
  1448. /* If on the bottom of the window, scroll the window up 1 line.        */
  1449. /*---------------------------------------------------------------------*/
  1450.         if (y == CURRENT_SCREEN.rows-1) /* on bottom of window */
  1451.            {
  1452.             CURRENT_VIEW->current_line++;
  1453.             post_process_line(CURRENT_VIEW->focus_line);
  1454.             CURRENT_VIEW->focus_line++;
  1455.             pre_process_line(CURRENT_VIEW->focus_line);
  1456.             show_page();
  1457.             wmove(CURRENT_WINDOW,y,x);
  1458.             break;
  1459.            }
  1460. /*---------------------------------------------------------------------*/
  1461. /* We are in the middle of the window, so just move the cursor down    */
  1462. /* 1 line.                                                             */
  1463. /*---------------------------------------------------------------------*/
  1464.         wmove(CURRENT_WINDOW,y+1,x);
  1465.         post_process_line(CURRENT_VIEW->focus_line);
  1466.         CURRENT_VIEW->focus_line++;
  1467.         pre_process_line(CURRENT_VIEW->focus_line);
  1468.         break;
  1469.    case WINDOW_COMMAND:
  1470. /*---------------------------------------------------------------------*/
  1471. /* Cycle forward  through the command list or tab to first line.       */
  1472. /*---------------------------------------------------------------------*/
  1473.         if (CMDARROWSTABCMDx)
  1474.           {
  1475.            getyx(CURRENT_WINDOW,y,x);
  1476.            if (CURRENT_VIEW->prefix != PREFIX_LEFT)
  1477.               x += 6;
  1478.            if (CURRENT_VIEW->current_line > CURRENT_VIEW->current_row)
  1479.              {
  1480.               CURRENT_VIEW->focus_line = CURRENT_VIEW->current_line -
  1481.                                         CURRENT_VIEW->current_row ;
  1482.               y = 0;
  1483.              }
  1484.            else
  1485.              {
  1486.               CURRENT_VIEW->focus_line = 0;
  1487.               y = CURRENT_VIEW->current_row -
  1488.                                         CURRENT_VIEW->current_line ;
  1489.              }
  1490.            pre_process_line(CURRENT_VIEW->focus_line);
  1491.            CURRENT_VIEW->current_window = WINDOW_MAIN;
  1492.            wmove(CURRENT_WINDOW,y,x);
  1493.           }
  1494.         else
  1495.            Retrieve("+");
  1496.         break;
  1497.    default:
  1498.         display_error(2,(char *)"");
  1499.         break;
  1500.   }
  1501. #ifdef TRACE
  1502.  trace_return();
  1503. #endif
  1504.  return(RC_OK);
  1505. }
  1506. /*man-start*********************************************************************
  1507. COMMAND
  1508.      duplicate - duplicate lines
  1509.  
  1510. SYNTAX
  1511.      DUPlicate [n [target|BLOCK]]
  1512.  
  1513. DESCRIPTION
  1514.      The DUPLICATE command copies the number of lines extrapolated from
  1515.      target, n times.
  1516.  
  1517. COMPATIBILITY
  1518.      XEDIT: Equivalent of DUPLICAT command.
  1519.      KEDIT: Compatible.
  1520.  
  1521. STATUS
  1522.      Complete.
  1523. **man-end**********************************************************************/
  1524. #ifdef PROTO
  1525. int Duplicate(char *params)
  1526. #else
  1527. int Duplicate(params)
  1528. char *params;
  1529. #endif
  1530. /***********************************************************************/
  1531. {
  1532. /*------------------------- external data -----------------------------*/
  1533. /*--------------------------- local data ------------------------------*/
  1534.  unsigned short x,y;
  1535. #define DUP_PARAMS  2
  1536.  char *word[DUP_PARAMS+1];
  1537.  unsigned short num_params;
  1538.  int rc,num_occ;
  1539.  long num_lines,true_line,start_line,end_line,dest_line;
  1540.  char command_source;
  1541. /*--------------------------- processing ------------------------------*/
  1542. #ifdef TRACE
  1543.  trace_function("comm1.c:   Duplicate");
  1544. #endif
  1545.  num_params = param_split(params,word,DUP_PARAMS,WORD_DELIMS,TEMP_PARAM);
  1546. /*---------------------------------------------------------------------*/
  1547. /* If no parameters, default to 1 1                                    */
  1548. /*---------------------------------------------------------------------*/
  1549.  if (num_params == 0)
  1550.    {
  1551.     word[0] = (char *)"1";
  1552.     word[1] = (char *)"1";
  1553.    }
  1554. /*---------------------------------------------------------------------*/
  1555. /* If 1 parameter, default 2nd parameter to 1                          */
  1556. /*---------------------------------------------------------------------*/
  1557.  if (num_params == 1)
  1558.     word[1] = (char *)"1";
  1559. /*---------------------------------------------------------------------*/
  1560. /* If first parameter is not an integer, error.                        */
  1561. /*---------------------------------------------------------------------*/
  1562.  if (!valid_integer(word[0]))
  1563.    {
  1564.     display_error(4,word[0]);
  1565. #ifdef TRACE
  1566.     trace_return();
  1567. #endif
  1568.     return(RC_INVALID_OPERAND);
  1569.    }
  1570.  num_occ = atoi(word[0]);
  1571. /*---------------------------------------------------------------------*/
  1572. /* If second parameter is BLOCK, don't check for valid_target...       */
  1573. /*---------------------------------------------------------------------*/
  1574.  if (equal((char *)"block",word[1],5))
  1575.    {
  1576.     if (marked_block(TRUE) != RC_OK)
  1577.       {
  1578.        display_error(44,(char *)"");
  1579. #ifdef TRACE
  1580.        trace_return();
  1581. #endif
  1582.        return(RC_INVALID_ENVIRON);
  1583.       }
  1584. /*---------------------------------------------------------------------*/
  1585. /* This function not valid for box  blocks.                            */
  1586. /*---------------------------------------------------------------------*/
  1587.     if (MARK_VIEW->mark_type == M_BOX)
  1588.       {
  1589.        display_error(48,(char *)"");
  1590. #ifdef TRACE
  1591.        trace_return();
  1592. #endif
  1593.        return(RC_INVALID_ENVIRON);
  1594.       }
  1595.     command_source = SOURCE_BLOCK;
  1596.     start_line = MARK_VIEW->mark_start_line;
  1597.     end_line = dest_line = MARK_VIEW->mark_end_line;
  1598.    }
  1599.  else
  1600.    {
  1601. /*---------------------------------------------------------------------*/
  1602. /* If second parameter is not a valid target, error.                   */
  1603. /*---------------------------------------------------------------------*/
  1604.     true_line = get_true_line();
  1605.     num_lines = valid_target(word[1],true_line);
  1606.     if (num_lines == TARGET_ERROR)
  1607.       {
  1608.        display_error(4,word[1]);
  1609. #ifdef TRACE
  1610.        trace_return();
  1611. #endif
  1612.        return(RC_INVALID_OPERAND);
  1613.       }
  1614.     if (num_lines == TARGET_NOT_FOUND)
  1615.       {
  1616.        display_error(17,word[1]);
  1617. #ifdef TRACE
  1618.        trace_return();
  1619. #endif
  1620.        return(RC_TARGET_NOT_FOUND);
  1621.       }
  1622. /*---------------------------------------------------------------------*/
  1623. /* If the number of lines to the target is negative, make it positive  */
  1624. /* and change the true_line to be arget is negative, make it positive  */
  1625. /*---------------------------------------------------------------------*/
  1626.     if (num_lines < 0)
  1627.       {
  1628.        true_line += num_lines;
  1629.        num_lines = -num_lines;
  1630.       }
  1631. /*---------------------------------------------------------------------*/
  1632. /* If we are on the top of file line, start from the next line...      */
  1633. /*---------------------------------------------------------------------*/
  1634.     if (TOF(true_line)
  1635.     && num_lines > 0L)
  1636.       {
  1637.        true_line++;
  1638.        num_lines--;
  1639.       }
  1640. /*---------------------------------------------------------------------*/
  1641. /* If we are on the bottom of file line, start from the previous line..*/
  1642. /*---------------------------------------------------------------------*/
  1643.     if (BOF(true_line)
  1644.     && num_lines < 0L)
  1645.       {
  1646.        true_line--;
  1647.        num_lines++;
  1648.       }
  1649.     command_source = SOURCE_COMMAND;
  1650.     start_line = true_line;
  1651.     end_line = dest_line = true_line + num_lines -1L;
  1652.    }
  1653.  post_process_line(CURRENT_VIEW->focus_line);
  1654.  rc = rearrange_line_blocks(COMMAND_DUPLICATE,command_source,start_line,end_line,dest_line,num_occ,CURRENT_VIEW,CURRENT_VIEW);
  1655.  
  1656. #ifdef TRACE
  1657.  trace_return();
  1658. #endif
  1659.  return(rc);
  1660. }
  1661.