1 /***********************************************************************/
2 /* COMM3.C - Commands K-O                                              */
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-2013 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, mark@rexx.org  http://www.rexx.org/
35  */
36 
37 
38 #include <the.h>
39 #include <proto.h>
40 
41 /*man-start*********************************************************************
42 COMMAND
43      kedit - edit another file or switch to next file
44 
45 SYNTAX
46      Kedit [file]
47 
48 DESCRIPTION
49      The KEDIT command allows the user to edit another 'file'. The new file
50      is placed in the file <ring>. The previous file being edited remains
51      in memory and can be returned to by issuing a KEDIT command without
52      any parameters. Several files can be edited at once, and all files
53      are arranged in a ring, with subsequent KEDIT commands moving through
54      the ring, one file at a time.
55 
56 COMPATIBILITY
57      XEDIT: Does not provide options switches.
58      KEDIT: Does not provide options switches.
59 
60 SEE ALSO
61      <EDIT>, <THE>, <XEDIT>
62 
63 STATUS
64      Complete.
65 **man-end**********************************************************************/
66 
67 /*man-start*********************************************************************
68 COMMAND
69      left - scroll the screen to the left
70 
71 SYNTAX
72      LEft [n|HALF|FULL]
73 
74 DESCRIPTION
75      The LEFT command scrolls the screen to the left.
76 
77      If 'n' is supplied, the screen scrolls by that many columns.
78 
79      LEFT 0 is equivalent to <SET VERIFY> 1
80 
81      If 'HALF' is specified the screen is scrolled by half the number
82      of columns in the <filearea>.
83 
84      If 'FULL' is specified the screen is scrolled by the number
85      of columns in the <filearea>.
86 
87      If no parameter is supplied, the screen is scrolled by one
88      column.
89 
90 COMPATIBILITY
91      XEDIT: Compatible.
92      KEDIT: Compatible.
93 
94 SEE ALSO
95      <RIGHT>, <RGTLEFT>, <SET VERIFY>
96 
97 STATUS
98      Complete.
99 **man-end**********************************************************************/
100 #ifdef HAVE_PROTO
Left(CHARTYPE * params)101 short Left(CHARTYPE *params)
102 #else
103 short Left(params)
104 CHARTYPE *params;
105 #endif
106 /***********************************************************************/
107 {
108    short rc=RC_OK;
109    LINETYPE shift_val;
110    CHARTYPE _THE_FAR buffer[100];
111 
112    TRACE_FUNCTION("comm3.c:   Left");
113    /*
114     * Validate only parameter, HALF or positive integer. 1 if no argument.
115     */
116    if ( equal( (CHARTYPE *)"half", params, 4 ) )
117       shift_val = CURRENT_SCREEN.cols[WINDOW_FILEAREA]/2;
118    else if ( equal( (CHARTYPE *)"full", params, 4 ) )
119       shift_val = CURRENT_SCREEN.cols[WINDOW_FILEAREA];
120    else if ( blank_field( params ) )
121       shift_val = 1L;
122    else
123    {
124       if ( ( rc = valid_positive_integer_against_maximum( params, MAX_WIDTH_NUM ) ) != 0 )
125       {
126          if ( rc == 4 )
127             sprintf( (DEFCHAR *)buffer, "%s", params );
128          else
129             sprintf( (DEFCHAR *)buffer, "- MUST be <= %ld", MAX_WIDTH_NUM );
130          display_error( rc, buffer, FALSE );
131          TRACE_RETURN();
132          return(RC_INVALID_OPERAND);
133       }
134       shift_val = atol( (DEFCHAR *)params );
135    }
136    /*
137     * If the argument is 0, set verify column to 1
138     */
139    if ( shift_val == 0L )
140    {
141       CURRENT_VIEW->verify_col = 1;
142    }
143    else
144    {
145       CURRENT_VIEW->verify_col = max( 1, CURRENT_VIEW->verify_col-shift_val );
146    }
147 #ifdef MSWIN
148    Win31HScroll( CURRENT_VIEW->verify_col );
149 #endif
150    build_screen( current_screen );
151    display_screen( current_screen );
152    TRACE_RETURN();
153    return(rc);
154 }
155 /*man-start*********************************************************************
156 COMMAND
157      locate - search for a target
158 
159 SYNTAX
160      [Locate] target [command]
161 
162 DESCRIPTION
163      The LOCATE command searches for the next or previous occurrence
164      of the specified <'target'>.  If no parameter is supplied, LOCATE
165      uses the the last target specified. If no prior target has been
166      specified, an error message is displayed.
167 
168      <target> can also be specified as a regular expression. The syntax of
169      this is "Regexp /re/". eg LOCATE RE /[0-9].*$/
170 
171      With an optional 'command', this command is executed after finding
172      the <'target'>.
173 
174 COMPATIBILITY
175      XEDIT: Compatible.
176      KEDIT: Compatible.
177 
178 STATUS
179      Complete.
180 **man-end**********************************************************************/
181 #ifdef HAVE_PROTO
Locate(CHARTYPE * params)182 short Locate(CHARTYPE *params)
183 #else
184 short Locate(params)
185 CHARTYPE *params;
186 #endif
187 /***********************************************************************/
188 {
189    short rc=RC_OK;
190 
191    TRACE_FUNCTION("comm3.c:   Locate");
192    /*
193     * If no parameter is specified, use the last_target. If that doesn't
194     * exist, error.
195     */
196    if (blank_field(params))
197    {
198       if (blank_field(lastop[LASTOP_LOCATE].value))
199       {
200          display_error(39,(CHARTYPE *)"",FALSE);
201          TRACE_RETURN();
202          return(RC_INVALID_OPERAND);
203       }
204       rc = execute_locate( lastop[LASTOP_LOCATE].value, TRUE, THE_NOT_SEARCH_SEMANTICS, NULL );
205       TRACE_RETURN();
206       return(rc);
207    }
208    /*
209     * Here we have some parameters.
210     */
211    rc = execute_locate( params, TRUE, THE_NOT_SEARCH_SEMANTICS, NULL );
212    TRACE_RETURN();
213    return(rc);
214 }
215 /*man-start*********************************************************************
216 COMMAND
217      lowercase - change uppercase characters to lowercase
218 
219 SYNTAX
220      LOWercase [target]
221 
222 DESCRIPTION
223      The LOWERCASE command changes all uppercase characters in all
224      lines up to the <'target'> line to lowercase. All other characters
225      remain untouched.
226 
227 COMPATIBILITY
228      XEDIT: Equivalent of LOWERCAS command.
229      KEDIT: Compatible.
230 
231 SEE ALSO
232      <UPPERCASE>
233 
234 STATUS
235      Complete.
236 **man-end**********************************************************************/
237 #ifdef HAVE_PROTO
Lowercase(CHARTYPE * params)238 short Lowercase(CHARTYPE *params)
239 #else
240 short Lowercase(params)
241 CHARTYPE *params;
242 #endif
243 /***********************************************************************/
244 {
245    short rc=RC_OK;
246 
247    TRACE_FUNCTION("comm3.c:   Lowercase");
248    rc = execute_change_case(params,CASE_LOWER);
249    TRACE_RETURN();
250    return(rc);
251 }
252 /*man-start*********************************************************************
253 COMMAND
254      ls - list the specified directory as an editable file
255 
256 SYNTAX
257      LS [file specification]
258 
259 DESCRIPTION
260      The LS command displays all files matching the specified
261      'file specification'.
262 
263      When no parameter is supplied, all files in the current directory
264      are displayed subject to any <SET DIRINCLUDE> restrictions.
265 
266 COMPATIBILITY
267      XEDIT: N/A
268      KEDIT: Compatible.
269 
270 SEE ALSO
271      <DIRECTORY>, <SET DIRINCLUDE>
272 
273 STATUS
274      Complete.
275 **man-end**********************************************************************/
276 
277 /*man-start*********************************************************************
278 COMMAND
279      macro - execute a macro command file
280 
281 SYNTAX
282      MACRO [?] filename [arguments ...]
283 
284 DESCRIPTION
285      The MACRO command executes the contents of the specified 'filename'
286      as command line commands. The 'filename' can contain either a series
287      of THE commands, or can be a Rexx program. The 'filename' is considered
288      a <macro>.
289 
290      Rexx macros can be passed optional 'arguments'.
291 
292      With the optional '?' parameter, interactive tracing of the Rexx
293      macro is possible, but this does not set interactive tracing on;
294 
295 COMPATIBILITY
296      XEDIT: Compatible.
297      KEDIT: Compatible.
298 
299 STATUS
300      Complete.
301 **man-end**********************************************************************/
302 #ifdef HAVE_PROTO
Macro(CHARTYPE * params)303 short Macro(CHARTYPE *params)
304 #else
305 short Macro(params)
306 CHARTYPE *params;
307 #endif
308 /***********************************************************************/
309 {
310    short rc=RC_OK;
311    short macrorc=0;
312 
313    TRACE_FUNCTION( "comm3.c:   Macro" );
314 #ifdef THE_TRACE
315    trace_string( "params: \"%s\"\n", params );
316 #endif
317    rc = execute_macro( params, TRUE, &macrorc );
318    TRACE_RETURN();
319    return( (rc == RC_SYSTEM_ERROR) ? rc : macrorc );
320 }
321 /*man-start*********************************************************************
322 COMMAND
323      mark - mark a portion of text
324 
325 SYNTAX
326      MARK Box [line1 col1 line2 col2]
327      MARK Line [line1 line2]
328      MARK Stream [line1 col1 line2 col2]
329      MARK Column [col1 col2]
330      MARK Word [line1 col1]
331      MARK CUA [LEFT|RIGHT|UP|DOWN|START|END|FOrward|BAckward|TOP|Bottom|MOUSE]
332 
333 DESCRIPTION
334      The MARK command marks a portion of text for later processing
335      by a <COPY>, <MOVE> or <DELETE> command. This marked area is
336      known as a <block>.
337 
338      When the MARK command is executed with the optional line/column
339      arguments, these values are used to specify the position of the
340      marked <block>.  Without the optional arguments, the position of
341      the cursor is used to determine which portion of text is marked.
342 
343      'line1' and 'line2' specify the first or last line of the
344      marked block.
345 
346      'col1' and 'col2' specify the first or last column of the
347      marked block.
348 
349      Any currently marked block will be unmarked or extended depending on
350      the arguments supplied.
351 
352      When marking a <word block>, 'line1' and 'col1' refer to any position
353      within the word.
354 
355 COMPATIBILITY
356      XEDIT: N/A
357      KEDIT: Adds CUA, WORD, and COLUMN options and position specifiers.
358 
359 STATUS
360      Complete.
361 **man-end**********************************************************************/
362 #ifdef HAVE_PROTO
Mark(CHARTYPE * params)363 short Mark(CHARTYPE *params)
364 #else
365 short Mark(params)
366 CHARTYPE *params;
367 #endif
368 /***********************************************************************/
369 {
370 #define MAR_PARAMS    5
371 #define CUA_NONE      0
372 #define CUA_LEFT      1
373 #define CUA_RIGHT     2
374 #define CUA_UP        3
375 #define CUA_DOWN      4
376 #define CUA_START     5
377 #define CUA_END       6
378 #define CUA_TOP       7
379 #define CUA_BOTTOM    8
380 #define CUA_FORWARD   9
381 #define CUA_BACKWARD 10
382 #define CUA_MOUSE    11
383    LINETYPE true_line=0L;
384    unsigned short y=0,x=0;
385    LENGTHTYPE real_col=0;
386    CHARTYPE *word[MAR_PARAMS+1];
387    CHARTYPE strip[MAR_PARAMS];
388    register short i=0;
389    short num_params=0;
390    short mark_type=0;
391    short cua_type=CUA_NONE;
392    short rc;
393    LINETYPE tmp_line;
394    LENGTHTYPE tmp_col;
395    int numparms[7];
396    LINETYPE nummax[7][5];
397    LENGTHTYPE first_col=0,last_col=0;
398    LINE *curr=NULL;
399    CHARTYPE *cont=NULL;
400    LENGTHTYPE cont_len=0;
401    int num[5]; /* must be at least as big as maximum number of args */
402    CHARTYPE _THE_FAR buffer[100];
403 
404    TRACE_FUNCTION("comm3.c:   Mark");
405    /*
406     * Do this rather than define numparams[6] = {0,3,5,5,3,3} so that
407     * non-ansi compilers won't barf.
408     */
409    numparms[0] = 0;
410    numparms[1] = 3;
411    numparms[2] = 5;
412    numparms[3] = 5;
413    numparms[4] = 3;
414    numparms[5] = 3;
415    numparms[6] = 2;
416    /*
417     * Marking text sets the following variables:
418     * LINE:
419     *         CURRENT_VIEW->marked_line:       TRUE
420     *         CURRENT_VIEW->marked_start_line: line number of first line
421     *         CURRENT_VIEW->marked_end_line:   line number of last line
422     *         CURRENT_VIEW->marked_col:        FALSE
423     *         CURRENT_VIEW->marked_start_col:  1 (ignored)
424     *         CURRENT_VIEW->marked_end_col:    max width of line(ignored)
425     * BOX:
426     * STREAM:
427     * WORD:
428     *         CURRENT_VIEW->marked_line:       TRUE
429     *         CURRENT_VIEW->marked_start_line: line number of first line
430     *         CURRENT_VIEW->marked_end_line:   line number of last line
431     *         CURRENT_VIEW->marked_col:        TRUE
432     *         CURRENT_VIEW->marked_start_col:  first column
433     *         CURRENT_VIEW->marked_end_col:    last column
434     * CUA:
435     *         CURRENT_VIEW->marked_line:       TRUE
436     *         CURRENT_VIEW->marked_start_line: line number of anchor line
437     *         CURRENT_VIEW->marked_end_line:   line number of last line
438     *         CURRENT_VIEW->marked_col:        TRUE
439     *         CURRENT_VIEW->marked_start_col:  anchor column
440     *         CURRENT_VIEW->marked_end_col:    last column
441     * COLUMN:
442     *         CURRENT_VIEW->marked_line:       FALSE
443     *         CURRENT_VIEW->marked_start_line: (ignored)
444     *         CURRENT_VIEW->marked_end_line:   (ignored)
445     *         CURRENT_VIEW->marked_col:        TRUE
446     *         CURRENT_VIEW->marked_start_col:  first column
447     *         CURRENT_VIEW->marked_end_col:    last column
448     */
449    strip[0]=STRIP_BOTH;
450    strip[1]=STRIP_BOTH;
451    strip[2]=STRIP_BOTH;
452    strip[3]=STRIP_BOTH;
453    strip[4]=STRIP_BOTH;
454    num_params = param_split(params,word,MAR_PARAMS,WORD_DELIMS,TEMP_PARAM,strip,FALSE);
455    /*
456     * Validate the first parameter: must be Box, Line, Stream, Column, Word
457     */
458    if (equal((CHARTYPE *)"box",word[0],1))
459       mark_type = M_BOX;
460    else if (equal((CHARTYPE *)"line",word[0],1))
461       mark_type = M_LINE;
462    else if (equal((CHARTYPE *)"stream",word[0],1))
463       mark_type = M_STREAM;
464    else if (equal((CHARTYPE *)"column",word[0],1))
465       mark_type = M_COLUMN;
466    else if (equal((CHARTYPE *)"word",word[0],1))
467       mark_type = M_WORD;
468    else if (equal((CHARTYPE *)"cua",word[0],3))
469       mark_type = M_CUA;
470    else
471    {
472       display_error(1,(CHARTYPE *)word[0],FALSE);
473       TRACE_RETURN();
474       return(RC_INVALID_OPERAND);
475    }
476    /*
477     * For CUA, validate the optional parameter...
478     */
479    if ( mark_type == M_CUA
480    &&  num_params == 2 )
481    {
482       if (equal((CHARTYPE *)"left",word[1],4))
483          cua_type = CUA_LEFT;
484       else if (equal((CHARTYPE *)"right",word[1],5))
485          cua_type = CUA_RIGHT;
486       else if (equal((CHARTYPE *)"up",word[1],2))
487          cua_type = CUA_UP;
488       else if (equal((CHARTYPE *)"down",word[1],4))
489          cua_type = CUA_DOWN;
490       else if (equal((CHARTYPE *)"top",word[1],3))
491          cua_type = CUA_TOP;
492       else if (equal((CHARTYPE *)"bottom",word[1],1))
493          cua_type = CUA_BOTTOM;
494       else if (equal((CHARTYPE *)"forward",word[1],2))
495          cua_type = CUA_FORWARD;
496       else if (equal((CHARTYPE *)"backward",word[1],2))
497          cua_type = CUA_BACKWARD;
498       else if (equal((CHARTYPE *)"start",word[1],5))
499          cua_type = CUA_START;
500       else if (equal((CHARTYPE *)"end",word[1],3))
501          cua_type = CUA_END;
502       else if (equal((CHARTYPE *)"mouse",word[1],5))
503          cua_type = CUA_MOUSE;
504       else
505       {
506          display_error(1,(CHARTYPE *)word[1],FALSE);
507          TRACE_RETURN();
508          return(RC_INVALID_OPERAND);
509       }
510       /*
511        * Reset the previous marked view if its not the current view...
512        */
513       if (MARK_VIEW != (VIEW_DETAILS *)NULL
514       &&  MARK_VIEW != CURRENT_VIEW)
515       {
516          MARK_VIEW->marked_line = MARK_VIEW->marked_col = FALSE;
517          if (display_screens > 1
518          &&  MARK_VIEW == OTHER_VIEW)
519          {
520             MARK_VIEW = (VIEW_DETAILS *)NULL;
521             build_screen( (CHARTYPE)(other_screen) );
522             display_screen( (CHARTYPE)(other_screen) );
523          }
524       }
525       MARK_VIEW = CURRENT_VIEW;
526       /*
527        * If we don't have a CUA marked block already, call ourselves
528        * as MARK CUA, so that the anchor point is set.  Then we can call
529        * the appropriate cursor movement function, and then mark the
530        * block at the newly positioned place.
531        */
532       if ( CURRENT_VIEW->mark_type != M_CUA )
533       {
534          MARK_VIEW->marked_line = MARK_VIEW->marked_col = FALSE;
535          Mark( (CHARTYPE *)"CUA" );
536       }
537       /*
538        * We can now move the cursor (if required) and then mark the end
539        * point of the block
540        */
541       switch( cua_type )
542       {
543          case CUA_LEFT:
544             rc = THEcursor_left( CURSOR_CUA, FALSE );
545             break;
546          case CUA_RIGHT:
547             rc = THEcursor_right( CURSOR_CUA, FALSE );
548             break;
549          case CUA_UP:
550             rc = THEcursor_up( CURSOR_CUA );
551             break;
552          case CUA_DOWN:
553             rc = THEcursor_down( current_screen, CURRENT_VIEW, CURSOR_CUA );
554             break;
555          case CUA_FORWARD:
556             rc = scroll_page(DIRECTION_FORWARD,1,FALSE);
557             break;
558          case CUA_BACKWARD:
559             rc = scroll_page(DIRECTION_BACKWARD,1,FALSE);
560             break;
561          case CUA_TOP:
562             rc = Top((CHARTYPE *)"");
563             break;
564          case CUA_BOTTOM:
565             rc = Bottom((CHARTYPE *)"");
566             break;
567          case CUA_END:
568             rc = Sos_endchar((CHARTYPE *)"");
569             break;
570          case CUA_START:
571             rc = Sos_firstchar((CHARTYPE *)"");
572             break;
573          case CUA_MOUSE:
574             rc = THEcursor_mouse();
575             break;
576          default:
577             break;
578       }
579       true_line = get_true_line(FALSE);
580       /*
581        * If we are on 'Top of File' or 'Bottom of File' lines, error.
582        */
583       if (TOF(true_line) || BOF(true_line))
584       {
585          display_error(38,(CHARTYPE *)"",FALSE);
586          TRACE_RETURN();
587          return(RC_INVALID_ENVIRON);
588       }
589       /*
590        * If we are in the file area or prefix area and the focus line is not
591        * a real line, error.
592        */
593       getyx(CURRENT_WINDOW,y,x);
594       if (CURRENT_VIEW->current_window == WINDOW_FILEAREA
595       ||  CURRENT_VIEW->current_window == WINDOW_PREFIX)
596       {
597          if (CURRENT_SCREEN.sl[y].line_type != LINE_LINE)
598          {
599             display_error(38,(CHARTYPE *)"",FALSE);
600             TRACE_RETURN();
601             return(RC_INVALID_ENVIRON);
602          }
603       }
604       real_col = x + CURRENT_VIEW->verify_col;
605 
606       CURRENT_VIEW->mark_type = mark_type;
607       CURRENT_VIEW->mark_end_line = true_line;
608       CURRENT_VIEW->mark_end_col = real_col;
609       build_screen( current_screen );
610       display_screen(current_screen);
611       wmove(CURRENT_WINDOW,y,x);
612    }
613    /*
614     * With one parameter determine position of block...
615     */
616    else if ( num_params == 1 )
617    {
618       true_line = get_true_line(FALSE);
619       /*
620        * If we are on 'Top of File' or 'Bottom of File' lines, error.
621        */
622       if (TOF(true_line) || BOF(true_line))
623       {
624          display_error(38,(CHARTYPE *)"",FALSE);
625          TRACE_RETURN();
626          return(RC_INVALID_ENVIRON);
627       }
628       /*
629        * If we are in the file area or prefix area and the focus line is not
630        * a real line, error.
631        */
632       getyx(CURRENT_WINDOW,y,x);
633       if (CURRENT_VIEW->current_window == WINDOW_FILEAREA
634       ||  CURRENT_VIEW->current_window == WINDOW_PREFIX)
635       {
636          if (CURRENT_SCREEN.sl[y].line_type != LINE_LINE)
637          {
638             display_error(38,(CHARTYPE *)"",FALSE);
639             TRACE_RETURN();
640             return(RC_INVALID_ENVIRON);
641          }
642       }
643       /*
644        * Reset the previous marked view if its not the current view...
645        */
646       if (MARK_VIEW != (VIEW_DETAILS *)NULL
647       &&  MARK_VIEW != CURRENT_VIEW)
648       {
649          MARK_VIEW->marked_line = MARK_VIEW->marked_col = FALSE;
650          if (display_screens > 1
651          &&  MARK_VIEW == OTHER_VIEW)
652          {
653             MARK_VIEW = (VIEW_DETAILS *)NULL;
654             build_screen( (CHARTYPE)(other_screen) );
655             display_screen( (CHARTYPE)(other_screen) );
656          }
657       }
658       MARK_VIEW = CURRENT_VIEW;
659       CURRENT_VIEW->mark_type = mark_type;
660       /*
661        * Set the new values for top and bottom lines marked.
662        * For all marked blocks, other than CUA, the block will
663        * extend either side of the first position.
664        * For CUA blocks, the first position is an anchor position
665        * and will not change.
666        */
667       if (CURRENT_VIEW->marked_line)
668       {
669          if ( mark_type == M_CUA )
670          {
671             CURRENT_VIEW->mark_end_line = true_line;
672          }
673          else
674          {
675             if (true_line > CURRENT_VIEW->mark_end_line)
676                CURRENT_VIEW->mark_end_line = true_line;
677             if (true_line < CURRENT_VIEW->mark_start_line)
678                CURRENT_VIEW->mark_start_line = true_line;
679             if (true_line < CURRENT_VIEW->mark_end_line
680             &&  true_line > CURRENT_VIEW->mark_start_line)
681             {
682                if (true_line-CURRENT_VIEW->mark_end_line >
683                    CURRENT_VIEW->mark_start_line-true_line)
684                   CURRENT_VIEW->mark_end_line = true_line;
685                else
686                   CURRENT_VIEW->mark_start_line = true_line;
687             }
688          }
689       }
690       else
691       {
692          CURRENT_VIEW->mark_start_line = CURRENT_VIEW->mark_end_line = true_line;
693       }
694       /*
695        * Set the new values for first and last columns marked.
696        */
697       real_col = x + CURRENT_VIEW->verify_col;
698       if (CURRENT_VIEW->marked_col)
699       {
700          if ( mark_type == M_CUA )
701          {
702             CURRENT_VIEW->mark_end_col = real_col;
703          }
704          else
705          {
706             if (mark_type == M_STREAM
707             &&  CURRENT_VIEW->mark_start_line != CURRENT_VIEW->mark_end_line)
708             {
709                if (CURRENT_VIEW->mark_end_line == true_line)
710                   CURRENT_VIEW->mark_end_col = (real_col);
711                if (CURRENT_VIEW->mark_start_line == true_line)
712                   CURRENT_VIEW->mark_start_col = (real_col);
713             }
714             else
715             {
716                if ((real_col) > CURRENT_VIEW->mark_end_col)
717                   CURRENT_VIEW->mark_end_col = (real_col);
718                if ((real_col) < CURRENT_VIEW->mark_start_col)
719                   CURRENT_VIEW->mark_start_col = (real_col);
720                if ((real_col) < CURRENT_VIEW->mark_end_col
721                &&  (real_col) > CURRENT_VIEW->mark_start_col)
722                {
723                   if ((real_col)-CURRENT_VIEW->mark_end_col > CURRENT_VIEW->mark_start_col-(real_col))
724                      CURRENT_VIEW->mark_end_col = (real_col);
725                   else
726                      CURRENT_VIEW->mark_start_col = (real_col);
727                }
728             }
729          }
730       }
731       else
732       {
733          CURRENT_VIEW->mark_start_col = CURRENT_VIEW->mark_end_col = real_col;
734       }
735 
736       /*
737        * Set flags for various marked text types...
738        */
739       switch(mark_type)
740       {
741          case M_LINE:
742             CURRENT_VIEW->marked_col = FALSE;
743             CURRENT_VIEW->marked_line = TRUE;
744             CURRENT_VIEW->mark_start_col = 1;
745             CURRENT_VIEW->mark_end_col = max_line_length;
746             break;
747          case M_BOX:
748             CURRENT_VIEW->marked_col = TRUE;
749             CURRENT_VIEW->marked_line = TRUE;
750             break;
751          case M_WORD:
752             if (get_word(rec,rec_len,real_col-1,&first_col,&last_col) == 0)
753               {
754                CURRENT_VIEW->marked_line = CURRENT_VIEW->marked_col = FALSE;
755                MARK_VIEW = (VIEW_DETAILS *)NULL;
756                break;
757               }
758             CURRENT_VIEW->marked_col = TRUE;
759             CURRENT_VIEW->marked_line = TRUE;
760             CURRENT_VIEW->mark_start_line = CURRENT_VIEW->mark_end_line = true_line;
761             CURRENT_VIEW->mark_start_col = first_col+1;
762             CURRENT_VIEW->mark_end_col = last_col+1;
763             break;
764          case M_COLUMN:
765             CURRENT_VIEW->marked_line = FALSE;
766             CURRENT_VIEW->marked_col = TRUE;
767             CURRENT_VIEW->mark_start_line = 1L;
768             CURRENT_VIEW->mark_end_line = MAX_LONG;
769             break;
770          case M_STREAM:
771          case M_CUA:
772             CURRENT_VIEW->marked_col = TRUE;
773             CURRENT_VIEW->marked_line = TRUE;
774             break;
775       }
776       build_screen( current_screen );
777       display_screen(current_screen);
778       wmove(CURRENT_WINDOW,y,x);
779    }
780    else
781    {
782       nummax[M_LINE][1] = nummax[M_LINE][2] = nummax[M_BOX][1] =
783          nummax[M_BOX][3] = nummax[M_STREAM][1] = nummax[M_STREAM][3] =
784          nummax[M_WORD][1] = CURRENT_FILE->number_lines;
785       nummax[M_BOX][2] = nummax[M_BOX][4] = nummax[M_COLUMN][1] =
786          nummax[M_COLUMN][2] = nummax[M_STREAM][2] = nummax[M_STREAM][4] =
787          nummax[M_WORD][2] = max_line_length;
788       /*
789        * Validate the number of parameters...
790        */
791       if (num_params < numparms[mark_type])
792       {
793          display_error(3,(CHARTYPE *)"",FALSE);
794          TRACE_RETURN();
795          return(RC_INVALID_OPERAND);
796       }
797       if (num_params > numparms[mark_type])
798       {
799          display_error(2,(CHARTYPE *)"",FALSE);
800          TRACE_RETURN();
801          return(RC_INVALID_OPERAND);
802       }
803       /*
804        * Validate the arguments...
805        */
806       for ( i = 1; i < numparms[mark_type]; i++ )
807       {
808          if ( ( rc = valid_positive_integer_against_maximum( word[i], nummax[mark_type][i] ) ) == 0 )
809          {
810             num[i] = atol((DEFCHAR *)word[i]);
811          }
812          else
813          {
814             if ( rc == 4 )
815                sprintf( (DEFCHAR *)buffer, "%s", word[i] );
816             else
817                sprintf( (DEFCHAR *)buffer, "- MUST be <= %ld", nummax[mark_type][i] );
818             display_error( rc, buffer, FALSE );
819             TRACE_RETURN();
820             return(RC_INVALID_OPERAND);
821          }
822       }
823       /*
824        * Reset the previous marked view...
825        */
826       if (MARK_VIEW != (VIEW_DETAILS *)NULL
827       &&  MARK_VIEW != CURRENT_VIEW)
828       {
829          MARK_VIEW->marked_line = MARK_VIEW->marked_col = FALSE;
830          if (display_screens > 1
831          &&  MARK_VIEW == OTHER_VIEW)
832          {
833             MARK_VIEW = (VIEW_DETAILS *)NULL;
834             build_screen( (CHARTYPE)(other_screen) );
835             display_screen( (CHARTYPE)(other_screen) );
836          }
837       }
838       /*
839        * Set the new values of the marked block.
840        */
841       MARK_VIEW = CURRENT_VIEW;
842       CURRENT_VIEW->mark_type = mark_type;
843       switch(mark_type)
844       {
845          case M_BOX:
846          case M_STREAM:
847             CURRENT_VIEW->mark_start_line = num[1];
848             CURRENT_VIEW->mark_end_line = num[3];
849             CURRENT_VIEW->mark_start_col = (LENGTHTYPE)num[2];
850             CURRENT_VIEW->mark_end_col = (LENGTHTYPE)num[4];
851             CURRENT_VIEW->marked_line = TRUE;
852             CURRENT_VIEW->marked_col = TRUE;
853             if (CURRENT_VIEW->mark_start_line > CURRENT_VIEW->mark_end_line)
854             {
855                tmp_line = CURRENT_VIEW->mark_end_line;
856                CURRENT_VIEW->mark_end_line = CURRENT_VIEW->mark_start_line;
857                CURRENT_VIEW->mark_start_line = tmp_line;
858                tmp_col = CURRENT_VIEW->mark_end_col;
859                CURRENT_VIEW->mark_end_col = CURRENT_VIEW->mark_start_col;
860                CURRENT_VIEW->mark_start_col = tmp_col;
861             }
862             else if (CURRENT_VIEW->mark_start_line == CURRENT_VIEW->mark_end_line
863                  &&  CURRENT_VIEW->mark_start_col > CURRENT_VIEW->mark_end_col)
864             {
865                tmp_col = CURRENT_VIEW->mark_end_col;
866                CURRENT_VIEW->mark_end_col = CURRENT_VIEW->mark_start_col;
867                CURRENT_VIEW->mark_start_col = tmp_col;
868             }
869             break;
870          case M_LINE:
871             CURRENT_VIEW->mark_start_line = num[1];
872             CURRENT_VIEW->mark_end_line = num[2];
873             CURRENT_VIEW->marked_col = FALSE;
874             CURRENT_VIEW->mark_start_col = 1;
875             CURRENT_VIEW->mark_end_col = max_line_length;
876             if (CURRENT_VIEW->mark_start_line > CURRENT_VIEW->mark_end_line)
877             {
878                tmp_line = CURRENT_VIEW->mark_end_line;
879                CURRENT_VIEW->mark_end_line = CURRENT_VIEW->mark_start_line;
880                CURRENT_VIEW->mark_start_line = tmp_line;
881             }
882             break;
883          case M_COLUMN:
884             CURRENT_VIEW->mark_start_col = (LENGTHTYPE)num[1];
885             CURRENT_VIEW->mark_end_col = (LENGTHTYPE)num[2];
886             CURRENT_VIEW->marked_line = FALSE;
887             CURRENT_VIEW->marked_col = TRUE;
888             CURRENT_VIEW->mark_start_line = 1;
889             CURRENT_VIEW->mark_end_line = MAX_LONG;
890             if (CURRENT_VIEW->mark_start_col > CURRENT_VIEW->mark_end_col)
891             {
892                tmp_col = CURRENT_VIEW->mark_end_col;
893                CURRENT_VIEW->mark_end_col = CURRENT_VIEW->mark_start_col;
894                CURRENT_VIEW->mark_start_col = tmp_col;
895             }
896             break;
897          case M_WORD:
898             if (CURRENT_VIEW->current_window == WINDOW_FILEAREA
899             &&  CURRENT_VIEW->focus_line == num[1])
900             {
901                cont = rec;
902                cont_len = rec_len;
903             }
904             else
905             {
906                curr = lll_find(CURRENT_FILE->first_line,CURRENT_FILE->last_line,num[1],CURRENT_FILE->number_lines);
907                cont = curr->line;
908                cont_len = curr->length;
909             }
910             if (get_word(cont,cont_len,num[2],&first_col,&last_col) == 0)
911             {
912                CURRENT_VIEW->marked_line = CURRENT_VIEW->marked_col = FALSE;
913                MARK_VIEW = (VIEW_DETAILS *)NULL;
914                break;
915             }
916             CURRENT_VIEW->marked_col = TRUE;
917             CURRENT_VIEW->marked_line = TRUE;
918             CURRENT_VIEW->mark_start_line = CURRENT_VIEW->mark_end_line = num[1];
919             CURRENT_VIEW->mark_start_col = first_col+1;
920             CURRENT_VIEW->mark_end_col = last_col+1;
921             break;
922          default:
923             break;
924       }
925       build_screen( current_screen );
926       display_screen(current_screen);
927    }
928    TRACE_RETURN();
929    return(RC_OK);
930 }
931 /*man-start*********************************************************************
932 COMMAND
933      modify - display current SET command for alteration
934 
935 SYNTAX
936      MODify set-command
937 
938 DESCRIPTION
939      The MODIFY command displays the current setting of a <SET> command
940      on the command line enabling the user to change that setting.
941 
942 COMPATIBILITY
943      XEDIT: Compatible.
944      KEDIT: Compatible.
945 
946 SEE ALSO
947      <SET>, <QUERY>
948 
949 STATUS
950      Complete.
951 **man-end**********************************************************************/
952 #ifdef HAVE_PROTO
Modify(CHARTYPE * params)953 short Modify(CHARTYPE *params)
954 #else
955 short Modify(params)
956 CHARTYPE *params;
957 #endif
958 /***********************************************************************/
959 {
960    short rc=RC_OK;
961 
962    TRACE_FUNCTION( "comm3.c:   Modify" );
963    if ( ( rc = execute_modify_command( params ) ) == RC_OK )
964    {
965       Cmsg( temp_cmd );
966    }
967    TRACE_RETURN();
968    return( rc );
969 }
970 /*man-start*********************************************************************
971 COMMAND
972      move - move a portion of text
973 
974 SYNTAX
975      MOVE target1 target2
976      MOVE BLOCK [RESET]
977 
978 DESCRIPTION
979      The MOVE command copies the contents of a portion of the file to
980      the same or a different file, and deletes the marked portion from
981      the original file.
982 
983      The first form of the MOVE command, moves the portion of the file
984      specified by 'target1' to the line specified by 'target2' in the
985      same file.
986 
987      The second form of the MOVE command moves the contents of the marked
988      <block> to the current cursor position. If the optional ['RESET']
989      argument is supplied, the marked block is reset as though a
990      <RESET> BLOCK command had been issued.
991 
992 COMPATIBILITY
993      XEDIT: N/A
994      KEDIT: Adds extra functionality with [RESET] option.
995 
996 STATUS
997      Incomplete. First form is not supported.
998 **man-end**********************************************************************/
999 #ifdef HAVE_PROTO
THEMove(CHARTYPE * params)1000 short THEMove(CHARTYPE *params)
1001 #else
1002 short THEMove(params)
1003 CHARTYPE *params;
1004 #endif
1005 /***********************************************************************/
1006 {
1007 #define MOV_PARAMS 2
1008    CHARTYPE *word[MOV_PARAMS+1];
1009    CHARTYPE strip[MOV_PARAMS];
1010    unsigned short num_params=0;
1011    unsigned short y=0,x=0;
1012    LINETYPE true_line=0L;
1013    CHARTYPE reset_block=SOURCE_UNKNOWN;
1014    CHARTYPE copy_command=0,delete_command=0;
1015    short rc=RC_OK;
1016    LINETYPE start_line=0L,end_line=0L,num_lines=0L,dest_line=0L,lines_affected=0L;
1017    VIEW_DETAILS *old_mark_view=NULL;
1018 
1019    TRACE_FUNCTION("comm3.c:   THEMove");
1020    /*
1021     * This command invalid if source file is readonly...
1022     */
1023    if (!MARK_VIEW)
1024    {
1025       display_error(44,(CHARTYPE *)"",FALSE);
1026       TRACE_RETURN();
1027       return(RC_INVALID_ENVIRON);
1028    }
1029    if (ISREADONLY(MARK_FILE))
1030    {
1031       display_error(56,(CHARTYPE *)"",FALSE);
1032       TRACE_RETURN();
1033       return(RC_INVALID_ENVIRON);
1034    }
1035    strip[0]=STRIP_BOTH;
1036    strip[1]=STRIP_BOTH;
1037    num_params = param_split(params,word,MOV_PARAMS,WORD_DELIMS,TEMP_PARAM,strip,FALSE);
1038    if (num_params == 0)
1039    {
1040       display_error(3,(CHARTYPE *)"",FALSE);
1041       TRACE_RETURN();
1042       return(RC_INVALID_OPERAND);
1043    }
1044    if (num_params > 2)
1045    {
1046       display_error(2,(CHARTYPE *)"",FALSE);
1047       TRACE_RETURN();
1048       return(RC_INVALID_OPERAND);
1049    }
1050    /*
1051     * Test for valid parameters...
1052     */
1053    if (num_params == 1
1054    &&  equal((CHARTYPE *)"block",word[0],5))
1055       reset_block = SOURCE_BLOCK;
1056    if (num_params == 2
1057    &&  equal((CHARTYPE *)"block",word[0],5)
1058    &&  equal((CHARTYPE *)"reset",word[1],5))
1059       reset_block = SOURCE_BLOCK_RESET;
1060    if (reset_block == SOURCE_UNKNOWN)
1061    {
1062       display_error(1,params,FALSE);
1063       TRACE_RETURN();
1064       return(RC_INVALID_OPERAND);
1065    }
1066    /*
1067     * Validate marked block, can be in any view.
1068     */
1069    if (marked_block(FALSE) != RC_OK)
1070    {
1071       TRACE_RETURN();
1072       return(RC_INVALID_ENVIRON);
1073    }
1074    /*
1075     * If the cursor is in the marked block...error.
1076     */
1077    if (MARK_VIEW == CURRENT_VIEW)
1078    {
1079       getyx(CURRENT_WINDOW_FILEAREA,y,x);
1080       switch(MARK_VIEW->mark_type)
1081       {
1082          case M_LINE:
1083          case M_WORD:
1084          case M_COLUMN:
1085          case M_STREAM:
1086          case M_BOX:
1087             if ((CURRENT_VIEW->focus_line >= MARK_VIEW->mark_start_line)
1088             &&  (CURRENT_VIEW->focus_line <= MARK_VIEW->mark_end_line)
1089             &&  (x + CURRENT_VIEW->verify_col >= MARK_VIEW->mark_start_col)
1090             &&  (x + CURRENT_VIEW->verify_col <= MARK_VIEW->mark_end_col))
1091             {
1092                display_error(50,(CHARTYPE *)"",FALSE);
1093                TRACE_RETURN();
1094                return(RC_INVALID_ENVIRON);
1095             }
1096             break;
1097          default:
1098             break;
1099       }
1100    }
1101    /*
1102     * If block is a box, call its function.
1103     */
1104    if (MARK_VIEW->mark_type == M_BOX
1105    ||  MARK_VIEW->mark_type == M_WORD
1106    ||  MARK_VIEW->mark_type == M_STREAM
1107    ||  MARK_VIEW->mark_type == M_COLUMN)
1108    {
1109       box_operations(BOX_M,reset_block,FALSE,' ');/* don't reset and don't overlay */
1110       TRACE_RETURN();
1111       return(RC_OK);
1112    }
1113    /*
1114     * Determine the target line. If on the command line, target is current
1115     * line, else target line is focus line.
1116     */
1117    true_line = get_true_line(FALSE);
1118    /*
1119     * If the true  line is the bottom of file line, subtract 1 from it.
1120     */
1121    if (BOF(true_line))
1122       true_line--;
1123 
1124    post_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL,TRUE);
1125    start_line = MARK_VIEW->mark_start_line;
1126    end_line = MARK_VIEW->mark_end_line;
1127    num_lines = end_line - start_line + 1L;
1128    dest_line = true_line;
1129    old_mark_view = MARK_VIEW;
1130    if (MARK_VIEW == CURRENT_VIEW)
1131    {
1132       copy_command = COMMAND_MOVE_COPY_SAME;
1133       delete_command = COMMAND_MOVE_DELETE_SAME;
1134    }
1135    else
1136    {
1137       copy_command = COMMAND_MOVE_COPY_DIFF;
1138       delete_command = COMMAND_MOVE_DELETE_DIFF;
1139    }
1140 
1141    rc = rearrange_line_blocks(copy_command,reset_block,start_line,
1142                               end_line,dest_line,1,MARK_VIEW,CURRENT_VIEW,FALSE,
1143                               &lines_affected);
1144    if (rc == RC_OK)
1145    {
1146       if (old_mark_view == CURRENT_VIEW)
1147       {
1148          if (dest_line < start_line)
1149          {
1150             start_line += num_lines;
1151             end_line += num_lines;
1152             dest_line += num_lines;
1153          }
1154       }
1155       post_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL,TRUE);
1156       rc = rearrange_line_blocks(delete_command,reset_block,start_line,
1157                               end_line,start_line,1,old_mark_view,old_mark_view,FALSE,
1158                               &lines_affected);
1159    }
1160    TRACE_RETURN();
1161    return(rc);
1162 }
1163 /*man-start*********************************************************************
1164 COMMAND
1165      msg - display message on error line
1166 
1167 SYNTAX
1168      MSG [message]
1169 
1170 DESCRIPTION
1171      The MSG command displays a 'message' on the <message line>.
1172      This command is usually issued from a macro file.
1173      This is similar to <EMSG>, but MSG does not sound the bell if
1174      <SET BEEP> is on.
1175 
1176      If the number of messages displayed on the <message line> exceeds
1177      the number of lines defined in the <message line> as set by
1178      <SET MSGLINE>, a prompt will be displayed. If a macro is being
1179      executed, the prompt will indicate that the user may terminate the macro
1180      by pressing the SPACE bar or any other key to continue execution of
1181      the macro.
1182 
1183 COMPATIBILITY
1184      XEDIT: Compatible.
1185      KEDIT: Compatible.
1186 
1187 SEE ALSO
1188      <CMSG>, <EMSG>, <SET MSGLINE>
1189 
1190 STATUS
1191      Complete.
1192 **man-end**********************************************************************/
1193 #ifdef HAVE_PROTO
Msg(CHARTYPE * params)1194 short Msg(CHARTYPE *params)
1195 #else
1196 short Msg(params)
1197 CHARTYPE *params;
1198 #endif
1199 /***********************************************************************/
1200 {
1201    int rc;
1202    TRACE_FUNCTION("comm3.c:   Msg");
1203    rc = display_error(0,params,TRUE);
1204    TRACE_RETURN();
1205    return rc;
1206 }
1207 /*man-start*********************************************************************
1208 COMMAND
1209      next - move forward in the file a number of lines
1210 
1211 SYNTAX
1212      Next [relative target]
1213 
1214 DESCRIPTION
1215      The NEXT command moves the <current line> forwards the number of
1216      lines specified by the <relative target>. This <relative target> can
1217      only be a positive integer or the character "*".
1218 
1219 COMPATIBILITY
1220      XEDIT: Compatible.
1221      KEDIT: Compatible.
1222 
1223 DEFAULT
1224      1
1225 
1226 SEE ALSO
1227      <DOWN>, <UP>
1228 
1229 STATUS
1230      Complete.
1231 **man-end**********************************************************************/
1232 #ifdef HAVE_PROTO
THENext(CHARTYPE * params)1233 short THENext(CHARTYPE *params)
1234 #else
1235 short THENext(params)
1236 CHARTYPE *params;
1237 #endif
1238 /***********************************************************************/
1239 {
1240    short rc=RC_OK;
1241    LINETYPE num_lines=0L,true_line=0L;
1242 
1243    TRACE_FUNCTION("comm3.c:   THENext");
1244    params = MyStrip(params,STRIP_BOTH,' ');
1245    if (strcmp("",(DEFCHAR *)params) == 0)
1246       params = (CHARTYPE *)"1";
1247    true_line = get_true_line(TRUE);
1248    if (strcmp("*",(DEFCHAR *)params) == 0)
1249       num_lines = CURRENT_FILE->number_lines - true_line + 1L;
1250    else
1251    {
1252       if (!valid_integer(params))
1253       {
1254          display_error(4,params,FALSE);
1255          TRACE_RETURN();
1256          return(RC_INVALID_OPERAND);
1257       }
1258       num_lines = atol((DEFCHAR *)params);
1259       if (num_lines < 0L)
1260       {
1261          display_error(5,params,FALSE);
1262          TRACE_RETURN();
1263          return(RC_INVALID_OPERAND);
1264       }
1265    }
1266    rc = advance_current_or_focus_line(num_lines);
1267    TRACE_RETURN();
1268    return(rc);
1269 }
1270 /*man-start*********************************************************************
1271 COMMAND
1272      nextwindow - switch focus of editing session to another file
1273 
1274 SYNTAX
1275      NEXTWindow
1276 
1277 DESCRIPTION
1278      The NEXTWINDOW command moves the focus of the editing session to
1279      the other screen (if <SET SCREEN> 2 is in effect) or to the next
1280      file in the <ring>.
1281 
1282 COMPATIBILITY
1283      XEDIT: N/A
1284      KEDIT: N/A
1285 
1286 SEE ALSO
1287      <PREVWINDOW>, <EDIT>, <SET SCREEN>
1288 
1289 STATUS
1290      Complete.
1291 **man-end**********************************************************************/
1292 #ifdef HAVE_PROTO
Nextwindow(CHARTYPE * params)1293 short Nextwindow(CHARTYPE *params)
1294 #else
1295 short Nextwindow(params)
1296 CHARTYPE *params;
1297 #endif
1298 /***********************************************************************/
1299 {
1300    short rc=RC_OK;
1301 
1302    TRACE_FUNCTION("comm3.c:   Nextwindow");
1303    if (strcmp((DEFCHAR *)params,"") != 0)
1304    {
1305       display_error(1,params,FALSE);
1306       TRACE_RETURN();
1307       return(RC_INVALID_OPERAND);
1308    }
1309    if (display_screens == 1)
1310    {
1311       rc = Xedit((CHARTYPE *)"");
1312       TRACE_RETURN();
1313       return(rc);
1314    }
1315    post_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL,TRUE);
1316    current_screen = (current_screen == 0) ? 1 : 0;
1317    CURRENT_VIEW = CURRENT_SCREEN.screen_view;
1318    if (curses_started)
1319    {
1320       if (CURRENT_WINDOW_COMMAND != (WINDOW *)NULL)
1321       {
1322          wattrset(CURRENT_WINDOW_COMMAND,set_colour(CURRENT_FILE->attr+ATTR_CMDLINE));
1323          touchwin(CURRENT_WINDOW_COMMAND);
1324          wnoutrefresh(CURRENT_WINDOW_COMMAND);
1325       }
1326       if (CURRENT_WINDOW_ARROW != (WINDOW *)NULL)
1327       {
1328          wattrset(CURRENT_WINDOW_ARROW,set_colour(CURRENT_FILE->attr+ATTR_ARROW));
1329          redraw_window(CURRENT_WINDOW_ARROW);
1330          wnoutrefresh(CURRENT_WINDOW_ARROW);
1331       }
1332       if (statarea != (WINDOW *)NULL)
1333       {
1334          wattrset(statarea,set_colour(CURRENT_FILE->attr+ATTR_STATAREA));
1335          redraw_window(statarea);
1336       }
1337       if (CURRENT_WINDOW_IDLINE != (WINDOW *)NULL)
1338       {
1339          wattrset(CURRENT_WINDOW_IDLINE,set_colour(CURRENT_FILE->attr+ATTR_IDLINE));
1340          redraw_window(CURRENT_WINDOW_IDLINE);
1341       }
1342       if (display_screens > 1
1343       &&  !horizontal)
1344       {
1345          wattrset(divider,set_colour(CURRENT_FILE->attr+ATTR_DIVIDER));
1346          draw_divider();
1347          wnoutrefresh(divider);
1348       }
1349    }
1350 /*   pre_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL);  GFUC2 deleted */
1351 /*   build_screen(current_screen);                                          GFUC2 deleted */
1352    if (!line_in_view(current_screen,CURRENT_VIEW->focus_line))
1353    {
1354       CURRENT_VIEW->focus_line = CURRENT_VIEW->current_line;
1355 /*      build_screen(current_screen);                                       GFUC2 deleted */
1356    }
1357    pre_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL); /* GFUC2 added */
1358    build_screen( current_screen );                                         /* GFUC2 added */
1359    display_screen(current_screen);
1360 
1361    TRACE_RETURN();
1362    return(RC_OK);
1363 }
1364 /*man-start*********************************************************************
1365 COMMAND
1366      nfind - locate forwards the line which does NOT begin with the supplied string
1367 
1368 SYNTAX
1369      NFind [string]
1370 
1371 DESCRIPTION
1372      The NFIND command attempts to locate a line towards the end of
1373      the file that does NOT begin with 'string'.
1374      If the optional 'string' is not supplied the last 'string' used
1375      in any of the family of find commands is used.
1376 
1377      'string' can contain two special characters:
1378 
1379           space - this will match any single character in the target line
1380           underscore - this will match any single space in the target line
1381 
1382 COMPATIBILITY
1383      XEDIT: Compatible.
1384      KEDIT: Compatible.
1385 
1386 SEE ALSO
1387      <FIND>, <FINDUP>, <NFINDUP>
1388 
1389 STATUS
1390      Complete
1391 **man-end**********************************************************************/
1392 #ifdef HAVE_PROTO
Nfind(CHARTYPE * params)1393 short Nfind(CHARTYPE *params)
1394 #else
1395 short Nfind(params)
1396 CHARTYPE *params;
1397 #endif
1398 /***********************************************************************/
1399 {
1400    short rc=RC_OK;
1401 
1402    TRACE_FUNCTION("comm2.c:   Nfind");
1403    rc = execute_find_command(params,TARGET_NFIND);
1404    TRACE_RETURN();
1405    return(rc);
1406 }
1407 /*man-start*********************************************************************
1408 COMMAND
1409      nfindup - locate backwards the line which does NOT begin with the supplied string
1410 
1411 SYNTAX
1412      NFINDUp [string]
1413 
1414 DESCRIPTION
1415      The NFINDUP command attempts to locate a line towards the start of
1416      the file that does NOT begin with 'string'.
1417      If the optional 'string' is not supplied the last 'string' used
1418      in any of the family of find commands is used.
1419 
1420      'string' can contain two special characters:
1421 
1422           space - this will match any single character in the target line
1423           underscore - this will match any single space in the target line
1424 
1425 COMPATIBILITY
1426      XEDIT: Compatible.
1427      KEDIT: Compatible.
1428 
1429 SEE ALSO
1430      <FIND>, <FINDUP>, <NFIND>, <NFUP>
1431 
1432 STATUS
1433      Complete
1434 **man-end**********************************************************************/
1435 #ifdef HAVE_PROTO
Nfindup(CHARTYPE * params)1436 short Nfindup(CHARTYPE *params)
1437 #else
1438 short Nfindup(params)
1439 CHARTYPE *params;
1440 #endif
1441 /***********************************************************************/
1442 {
1443    short rc=RC_OK;
1444 
1445    TRACE_FUNCTION("comm2.c:   Nfindup");
1446    rc = execute_find_command(params,TARGET_NFINDUP);
1447    TRACE_RETURN();
1448    return(rc);
1449 }
1450 /*man-start*********************************************************************
1451 COMMAND
1452      nfup - locate backwards the line which does NOT begin with the supplied string
1453 
1454 SYNTAX
1455      NFUp [string]
1456 
1457 DESCRIPTION
1458      The NFUP command is a synonym for the <NFINDUP> command.
1459 
1460 COMPATIBILITY
1461      XEDIT: Compatible.
1462      KEDIT: Compatible.
1463 
1464 SEE ALSO
1465      <FIND>, <FINDUP>, <NFIND>, <NFINDUP>
1466 
1467 STATUS
1468      Complete
1469 **man-end**********************************************************************/
1470 
1471 /*man-start*********************************************************************
1472 COMMAND
1473      nomsg - execute a command suppressing any messages
1474 
1475 SYNTAX
1476      NOMSG command [arguments]
1477 
1478 DESCRIPTION
1479      The NOMSG command executes the supplied 'command' but suppresses
1480      messages that would normally be displayed as a result of the
1481      command.
1482 
1483      Optional 'arguments' may be passed to the 'command'.
1484 
1485 COMPATIBILITY
1486      XEDIT: N/A
1487      KEDIT: Compatible.
1488 
1489 STATUS
1490      Complete.
1491 **man-end**********************************************************************/
1492 #ifdef HAVE_PROTO
Nomsg(CHARTYPE * params)1493 short Nomsg(CHARTYPE *params)
1494 #else
1495 short Nomsg(params)
1496 CHARTYPE *params;
1497 #endif
1498 /***********************************************************************/
1499 {
1500    short rc=RC_OK;
1501 
1502    TRACE_FUNCTION( "comm3.c:   Nomsg" );
1503    in_nomsg = TRUE;
1504    rc = command_line( params, COMMAND_ONLY_FALSE );
1505    in_nomsg = FALSE;
1506    TRACE_RETURN();
1507    return(rc);
1508 }
1509 /*man-start*********************************************************************
1510 COMMAND
1511      nop - no operation command
1512 
1513 SYNTAX
1514      NOP
1515 
1516 DESCRIPTION
1517      The NOP command does nothing. It is used as a means of turning
1518      off an assignment to a key.
1519 
1520 COMPATIBILITY
1521      XEDIT: N/A
1522      KEDIT: N/A
1523 
1524 SEE ALSO
1525      <DEFINE>
1526 
1527 STATUS
1528      Complete.
1529 **man-end**********************************************************************/
1530 #ifdef HAVE_PROTO
Nop(CHARTYPE * params)1531 short Nop(CHARTYPE *params)
1532 #else
1533 short Nop(params)
1534 CHARTYPE *params;
1535 #endif
1536 /***********************************************************************/
1537 {
1538    TRACE_FUNCTION("comm3.c:   Nop");
1539    /*
1540     * No arguments are allowed; error if any are present.
1541     */
1542    if (strcmp((DEFCHAR *)params,"") != 0)
1543    {
1544       display_error(1,(CHARTYPE *)params,FALSE);
1545       TRACE_RETURN();
1546       return(RC_INVALID_OPERAND);
1547    }
1548    TRACE_RETURN();
1549    return(RC_OK);
1550 }
1551 /*man-start*********************************************************************
1552 COMMAND
1553      os - execute an operating system command
1554 
1555 SYNTAX
1556      OS [command]
1557 
1558 DESCRIPTION
1559      The OS command executes the supplied operating system 'command'
1560      or runs an interactive shell if no 'command' is supplied.
1561 
1562 COMPATIBILITY
1563      XEDIT: N/A
1564      KEDIT: Equivalent to DOS command.
1565 
1566 SEE ALSO
1567      <DOS>, <!>
1568 
1569 STATUS
1570      Complete.
1571 **man-end**********************************************************************/
1572 #ifdef HAVE_PROTO
Os(CHARTYPE * params)1573 short Os(CHARTYPE *params)
1574 #else
1575 short Os(params)
1576 CHARTYPE *params;
1577 #endif
1578 /***********************************************************************/
1579 {
1580    short rc=RC_OK;
1581 
1582    TRACE_FUNCTION( "comm3.c:   Os" );
1583    /*
1584     * Execute the supplied parameters as OS commands. Run with output
1585     * displayed and pause before redrawing the windows.
1586     */
1587    rc = execute_os_command( params, FALSE, TRUE );
1588    TRACE_RETURN();
1589    return(rc);
1590 }
1591 /*man-start*********************************************************************
1592 COMMAND
1593      osnowait - execute an operating system command - no prompt
1594 
1595 SYNTAX
1596      OSNowait command
1597 
1598 DESCRIPTION
1599      The OSNOWAIT command executes the supplied operating system
1600      'command' not waiting for the user to be prompted once the
1601      command has completed.
1602 
1603 COMPATIBILITY
1604      XEDIT: N/A
1605      KEDIT: Equivalent of <DOSNOWAIT> command.
1606 
1607 SEE ALSO
1608      <DOSNOWAIT>
1609 
1610 STATUS
1611      Complete.
1612 **man-end**********************************************************************/
1613 #ifdef HAVE_PROTO
Osnowait(CHARTYPE * params)1614 short Osnowait(CHARTYPE *params)
1615 #else
1616 short Osnowait(params)
1617 CHARTYPE *params;
1618 #endif
1619 /***********************************************************************/
1620 {
1621    short rc=RC_OK;
1622 
1623    TRACE_FUNCTION( "comm3.c:   Osnowait" );
1624    /*
1625     * Execute the supplied parameters as OS commands. Run with output
1626     * displayed but no pause before redrawing the windows.
1627     */
1628    if ( strcmp( (DEFCHAR *)params, "" ) == 0 )          /* no params....error */
1629    {
1630       display_error( 3, (CHARTYPE *)"", FALSE );
1631       TRACE_RETURN();
1632       return(RC_INVALID_OPERAND);
1633    }
1634    rc = execute_os_command( params, FALSE, FALSE );
1635    TRACE_RETURN();
1636    return(rc);
1637 }
1638 /*man-start*********************************************************************
1639 COMMAND
1640      osquiet - execute an operating system command quietly
1641 
1642 SYNTAX
1643      OSQuiet command
1644 
1645 DESCRIPTION
1646      The OSQUIET command executes the supplied operating system 'command'
1647      as quietly as possible.
1648 
1649 COMPATIBILITY
1650      XEDIT: N/A
1651      KEDIT: Equivalent of <DOSQUIET> command.
1652 
1653 SEE ALSO
1654      <DOSQUIET>
1655 
1656 STATUS
1657      Complete.
1658 **man-end**********************************************************************/
1659 #ifdef HAVE_PROTO
Osquiet(CHARTYPE * params)1660 short Osquiet(CHARTYPE *params)
1661 #else
1662 short Osquiet(params)
1663 CHARTYPE *params;
1664 #endif
1665 /***********************************************************************/
1666 {
1667    short rc=RC_OK;
1668 
1669    TRACE_FUNCTION( "comm3.c:   Osquiet" );
1670    /*
1671     * Execute the supplied parameters as OS commands. Run with no output
1672     * displayed and no pause before redrawing the windows.
1673     */
1674    if ( strcmp( (DEFCHAR *)params, "" ) == 0 )          /* no params....error */
1675    {
1676       display_error( 3, (CHARTYPE *)"", FALSE );
1677       TRACE_RETURN();
1678       return(RC_INVALID_OPERAND);
1679    }
1680    rc = execute_os_command( params, TRUE, FALSE );
1681    TRACE_RETURN();
1682    return(rc);
1683 }
1684 /*man-start*********************************************************************
1685 COMMAND
1686      osredir - execute an operating system command and capture output
1687 
1688 SYNTAX
1689      OSRedir filename command [arguments ...]
1690 
1691 DESCRIPTION
1692      The OSREDIR command executes the supplied operating system 'command'
1693      and redirects output destined for STDOUT and STDERR to the specified
1694      'filename'.
1695 
1696      Optional 'arguments' may be supplied to the 'command'.
1697 
1698 COMPATIBILITY
1699      XEDIT: N/A
1700      KEDIT: N/A
1701 
1702 SEE ALSO
1703      <OS>, <OSQUIET>, <OSNOWAIT>
1704 
1705 STATUS
1706      Complete.
1707 **man-end**********************************************************************/
1708 #ifdef HAVE_PROTO
Osredir(CHARTYPE * params)1709 short Osredir(CHARTYPE *params)
1710 #else
1711 short Osredir(params)
1712 CHARTYPE *params;
1713 #endif
1714 /***********************************************************************/
1715 {
1716    short rc=RC_OK,rrc=0;
1717 #define OSR_PARAMS 2
1718    CHARTYPE err[1000];
1719    CHARTYPE strip[OSR_PARAMS];
1720    CHARTYPE quoted[OSR_PARAMS];
1721    CHARTYPE *word[OSR_PARAMS+1];
1722    unsigned short num_params=0;
1723    int save_stdout=0,save_stderr=0;
1724 #ifdef UNIX1
1725    int save_stdin=0;
1726 #endif
1727    int fd=0;
1728 
1729    TRACE_FUNCTION( "comm3.c:   Osredir" );
1730    /*
1731     * Execute the supplied parameters as OS commands. Run with no output
1732     * displayed and no pause before redrawing the windows.
1733     */
1734    err[0] = '\0';
1735    strip[0]=STRIP_BOTH;
1736    strip[1]=STRIP_BOTH;
1737    quoted[0]='"';
1738    quoted[1]='\0';
1739    num_params = quoted_param_split( params, word, OSR_PARAMS, WORD_DELIMS, TEMP_PARAM, strip, FALSE, quoted );
1740    if ( num_params == 0 )
1741    {
1742       display_error( 3, (CHARTYPE *)"", FALSE );
1743       TRACE_RETURN();
1744       return(RC_INVALID_OPERAND);
1745    }
1746    if ( num_params > 2 )
1747    {
1748       display_error( 2, (CHARTYPE *)"", FALSE );
1749       TRACE_RETURN();
1750       return(RC_INVALID_OPERAND);
1751    }
1752    /*
1753     * Delete the file to be on the safe side
1754     */
1755    remove_file( word[0] );
1756    /*
1757     * Save the "real" stdout and stderr handles so we can restore them later
1758     */
1759    save_stdout = dup( fileno( stdout ) );
1760    save_stderr = dup( fileno( stderr ) );
1761 #ifdef UNIX1
1762    save_stdin  = dup( fileno( stdin ) );
1763 #endif
1764 
1765 #if defined(S_IWRITE) && defined(S_IREAD)
1766    fd = open( (DEFCHAR *)word[0], O_WRONLY|O_CREAT, S_IWRITE|S_IREAD );
1767 #else
1768    fd = open( (DEFCHAR *)word[0], O_WRONLY|O_CREAT );
1769 #endif
1770    if ( fd == (-1) )
1771    {
1772       display_error( 8, word[0], FALSE );
1773       TRACE_RETURN();
1774       return(RC_INVALID_OPERAND);
1775    }
1776 #ifdef UNIX
1777    chmod( (DEFCHAR *)word[0], S_IRUSR|S_IWUSR );
1778 #endif
1779    /*
1780     * Redirect stdout and stderr to the supplied file handle
1781     */
1782    if ( dup2( fd, fileno( stdout ) ) == (-1) )
1783    {
1784       strcat( (DEFCHAR *)err, "Error dup2() on stdout: " );
1785       strcat( (DEFCHAR *)err, strerror( errno ) );
1786       rc = RC_INVALID_OPERAND;
1787    }
1788    if ( dup2( fd, fileno( stderr ) ) == (-1) )
1789    {
1790       strcat( (DEFCHAR *)err, "Error dup2() on stderr: " );
1791       strcat( (DEFCHAR *)err, strerror( errno ) );
1792       rc = RC_INVALID_OPERAND;
1793    }
1794 #ifdef UNIX1
1795    if ( rc == RC_OK )
1796    &&   dup2( fd, fileno( stdin ) ) == (-1) )
1797    {
1798       sprintf( err, "Error dup2() on stdin: %s", strerror( errno ) );
1799       rc = RC_INVALID_OPERAND;
1800    }
1801 #endif
1802 #ifdef USE_PROG_MODE
1803    def_prog_mode();
1804 #endif
1805    /*
1806     * Run the supplied OS command with stdout and stderr going to the
1807     * supplied redirection file
1808     */
1809    if ( rc == RC_OK )
1810       rrc = system( (DEFCHAR *)word[1] );
1811 #ifdef USE_PROG_MODE
1812    reset_prog_mode();
1813 #endif
1814    /*
1815     * Close the redirected file
1816     */
1817    if ( close( fd ) == (-1) )
1818    {
1819       strcat( (DEFCHAR *)err, "Error closing fd: " );
1820       strcat( (DEFCHAR *)err, strerror( errno ) );
1821       rc = RC_INVALID_OPERAND;
1822    }
1823    /*
1824     * Reset the stdout and stderr handles to the "real" handles.
1825     */
1826    if ( dup2( save_stdout, fileno( stdout ) ) == (-1) )
1827    {
1828       strcat( (DEFCHAR *)err, "Error resetting stdout: " );
1829       strcat( (DEFCHAR *)err, strerror( errno ) );
1830       rc = RC_INVALID_OPERAND;
1831    }
1832    if ( dup2( save_stderr, fileno( stderr ) ) == (-1) )
1833    {
1834       strcat( (DEFCHAR *)err, "Error resetting stderr: " );
1835       strcat( (DEFCHAR *)err, strerror( errno ) );
1836       rc = RC_INVALID_OPERAND;
1837    }
1838 #ifdef UNIX1
1839    dup2( save_stdin, fileno( stdin ) );
1840    close( save_stdin );
1841 #endif
1842 
1843 #if 1
1844    if ( close( save_stdout ) == (-1) )
1845    {
1846       strcat( (DEFCHAR *)err, "Error closing save_stdout: " );
1847       strcat( (DEFCHAR *)err, strerror( errno ) );
1848       rc = RC_INVALID_OPERAND;
1849    }
1850    if ( close( save_stderr ) == (-1) )
1851    {
1852       strcat( (DEFCHAR *)err, "Error closing save_stderr: " );
1853       strcat( (DEFCHAR *)err, strerror( errno ) );
1854       rc = RC_INVALID_OPERAND;
1855    }
1856 #endif
1857 
1858    TRACE_RETURN();
1859    if ( rc == RC_OK )
1860       return(rrc);
1861    else
1862    {
1863       display_error( 8, err, FALSE );
1864       return(rc);
1865    }
1866 }
1867 /*man-start*********************************************************************
1868 COMMAND
1869      overlaybox - overlay marked block on current cursor position
1870 
1871 SYNTAX
1872      OVERLAYBox
1873 
1874 DESCRIPTION
1875      The OVERLAYBOX command overlays the contents of the marked <block>;
1876      <box block> or <line block>, over the characters or lines at the
1877      <focus line> and <focus column>.
1878 
1879      This command implies that only <box block>s are handled.  This used
1880      to be the case, and for compatibility reasons the name remains.
1881 
1882 COMPATIBILITY
1883      XEDIT: N/A
1884      KEDIT: Compatible.
1885 
1886 SEE ALSO
1887      <MOVE>, <COPY>
1888 
1889 STATUS
1890      Complete.
1891 **man-end**********************************************************************/
1892 #ifdef HAVE_PROTO
Overlaybox(CHARTYPE * params)1893 short Overlaybox(CHARTYPE *params)
1894 #else
1895 short Overlaybox(params)
1896 CHARTYPE *params;
1897 #endif
1898 /***********************************************************************/
1899 {
1900    unsigned short y=0,x=0;
1901    LINETYPE true_line=0L,start_line=0L,end_line=0L,num_lines=0L,dest_line=0L,lines_affected=0L;
1902    VIEW_DETAILS *old_mark_view=NULL;
1903    short rc=RC_OK;
1904    LINE *curr=NULL;
1905    LINETYPE save_current_line=CURRENT_VIEW->current_line;
1906 
1907    TRACE_FUNCTION("comm3.c:   Overlaybox");
1908    /*
1909     * Ensure there are no parameters.
1910     */
1911    if (strcmp((DEFCHAR *)params,"") != 0)
1912    {
1913       display_error(1,params,FALSE);
1914       TRACE_RETURN();
1915     return(RC_INVALID_OPERAND);
1916    }
1917    /*
1918     * Validate marked block, can be in any view.
1919     */
1920    if (marked_block(FALSE) != RC_OK)
1921    {
1922       TRACE_RETURN();
1923       return(RC_INVALID_ENVIRON);
1924    }
1925    /*
1926     * Don't allow for multi-line STREAM blocks.
1927     */
1928    if (MARK_VIEW->mark_type == M_STREAM
1929    &&  MARK_VIEW->mark_start_line != MARK_VIEW->mark_end_line)
1930    {
1931       display_error(62,(CHARTYPE *)"",FALSE);
1932       TRACE_RETURN();
1933       return(RC_INVALID_ENVIRON);
1934    }
1935    /*
1936     * If the command is executed from the filearea, the focus line must be
1937     * in scope...
1938     */
1939    if (curses_started)
1940    {
1941       if (CURRENT_VIEW->current_window != WINDOW_COMMAND)
1942       {
1943          getyx(CURRENT_WINDOW,y,x);
1944          if (!IN_SCOPE(CURRENT_VIEW,CURRENT_SCREEN.sl[y].current)
1945          && !CURRENT_VIEW->scope_all)
1946          {
1947             display_error(87,(CHARTYPE *)"",FALSE);
1948             TRACE_RETURN();
1949             return(RC_INVALID_ENVIRON);
1950          }
1951       }
1952    }
1953    /*
1954     * If block is a box, call its function.
1955     */
1956    if (MARK_VIEW->mark_type != M_LINE)
1957    {
1958       box_operations(BOX_C,SOURCE_BLOCK,TRUE,' ');  /* no reset, overlay */
1959       TRACE_RETURN();
1960       return(RC_OK);
1961    }
1962    /*
1963     * Determine the target line. If on the command line, target is current
1964     * line, else target line is focus line.
1965     */
1966    true_line = get_true_line(TRUE);
1967 
1968    post_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL,TRUE);
1969    start_line = MARK_VIEW->mark_start_line;
1970    end_line = MARK_VIEW->mark_end_line;
1971    num_lines = end_line - start_line + 1L;
1972    dest_line = true_line-1L;
1973    old_mark_view = MARK_VIEW;
1974 
1975    rc = rearrange_line_blocks(COMMAND_OVERLAY_COPY,SOURCE_BLOCK,start_line,
1976                             end_line,dest_line,1,MARK_VIEW,CURRENT_VIEW,FALSE,
1977                             &lines_affected);
1978    if (rc == RC_OK
1979    &&  lines_affected != 0)
1980    {
1981       start_line = end_line = true_line + lines_affected;
1982       curr = lll_find(CURRENT_FILE->first_line,CURRENT_FILE->last_line,start_line,CURRENT_FILE->number_lines);
1983       for ( ; ; )
1984       {
1985          if (CURRENT_VIEW->scope_all
1986          ||  IN_SCOPE(CURRENT_VIEW,curr))
1987             lines_affected--;
1988          curr = curr->next;
1989          if (curr == NULL
1990          ||  lines_affected == 0L
1991          ||  end_line == CURRENT_FILE->number_lines)
1992             break;
1993          end_line++;
1994       }
1995       dest_line = true_line;
1996       post_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL,TRUE);
1997       rc = rearrange_line_blocks(COMMAND_OVERLAY_DELETE,SOURCE_BLOCK,start_line,
1998                             end_line,dest_line,1,CURRENT_VIEW,CURRENT_VIEW,FALSE,
1999                             &lines_affected);
2000       if (old_mark_view != MARK_VIEW)
2001          old_mark_view->marked_line = old_mark_view->marked_col = FALSE;
2002    }
2003    CURRENT_VIEW->current_line = save_current_line;
2004    build_screen( current_screen );
2005    display_screen(current_screen);
2006    if (curses_started
2007    && CURRENT_VIEW->current_window != WINDOW_COMMAND)
2008       wmove(CURRENT_WINDOW,y,x);
2009 
2010    TRACE_RETURN();
2011    return(rc);
2012 }
2013