home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / the25.zip / thesrc251.zip / target.c < prev    next >
C/C++ Source or Header  |  1998-06-08  |  76KB  |  2,095 lines

  1. /***********************************************************************/
  2. /* TARGET.C - Functions related to targets.                            */
  3. /***********************************************************************/
  4. /*
  5.  * THE - The Hessling Editor. A text editor similar to VM/CMS xedit.
  6.  * Copyright (C) 1991-1997 Mark Hessling
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License as
  10.  * published by the Free Software Foundation; either version 2 of
  11.  * the License, or any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16.  * General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to:
  20.  *
  21.  *    The Free Software Foundation, Inc.
  22.  *    675 Mass Ave,
  23.  *    Cambridge, MA 02139 USA.
  24.  *
  25.  *
  26.  * If you make modifications to this software that you feel increases
  27.  * it usefulness for the rest of the community, please email the
  28.  * changes, enhancements, bug fixes as well as any and all ideas to me.
  29.  * This software is going to be maintained and enhanced as deemed
  30.  * necessary by the community.
  31.  *
  32.  * Mark Hessling                 Email:             M.Hessling@qut.edu.au
  33.  * PO Box 203                    Phone:                    +617 3802 0800
  34.  * Bellara                       http://www.gu.edu.au/gext/the/markh.html
  35.  * QLD 4507                      **** Maintainer PDCurses & REXX/SQL ****
  36.  * Australia                     ************* Author of THE ************
  37.  */
  38.  
  39. /*
  40. $Id: target.c 2.1 1995/06/24 16:31:20 MH Rel MH $
  41. */
  42.  
  43. #include <the.h>
  44. #include <proto.h>
  45.  
  46. #define STATE_START    0
  47. #define STATE_DELIM    1
  48. #define STATE_STRING   2
  49. #define STATE_BOOLEAN  3
  50. #define STATE_NEXT     4
  51. #define STATE_POINT    5
  52. #define STATE_ABSOLUTE 6
  53. #define STATE_RELATIVE 7
  54. #define STATE_POSITIVE 8
  55. #define STATE_NEGATIVE 9
  56. #define STATE_SPARE    10
  57. #define STATE_QUIT     98
  58. #define STATE_ERROR    99
  59.  
  60. #ifdef HAVE_PROTO
  61. static bool is_blank(LINE *);
  62. #else
  63. static bool is_blank();
  64. #endif
  65.  
  66. /***********************************************************************/
  67. #ifdef HAVE_PROTO
  68. short split_change_params(CHARTYPE *cmd_line,CHARTYPE **old_str,CHARTYPE **new_str,
  69.                           TARGET *target,LINETYPE *num,LINETYPE *occ)
  70. #else
  71. short split_change_params(cmd_line,old_str,new_str,target,num,occ)
  72. CHARTYPE *cmd_line,**old_str,**new_str;
  73. TARGET *target;
  74. LINETYPE *num,*occ;
  75. #endif
  76. /***********************************************************************/
  77. {
  78. /*-------------------------- external data ----------------------------*/
  79. /*--------------------------- local data ------------------------------*/
  80. #define SCP_PARAMS  2
  81.  CHARTYPE *word[SCP_PARAMS+1];
  82.  CHARTYPE strip[SCP_PARAMS];
  83.  register short i=0,j=0;
  84.  CHARTYPE *target_start=NULL;
  85.  short rc=RC_OK;
  86.  CHARTYPE delim=' ';
  87.  short idx=0;
  88.  short target_type = TARGET_NORMAL|TARGET_BLOCK_CURRENT|TARGET_ALL|TARGET_SPARE;
  89.  unsigned short num_params=0;
  90. /*--------------------------- processing ------------------------------*/
  91. #ifdef TRACE
  92.  trace_function("target.c:  split_change_params");
  93. #endif
  94. /*---------------------------------------------------------------------*/
  95. /* First, determine the delimiter; the first character in the argument */
  96. /* string.                                                             */
  97. /*---------------------------------------------------------------------*/
  98.  delim = *(cmd_line);
  99. /*---------------------------------------------------------------------*/
  100. /* Set up default values for the return values...                      */
  101. /*---------------------------------------------------------------------*/
  102.  *old_str = cmd_line+1;
  103.  *new_str = (CHARTYPE *)"";
  104.  target_start = (CHARTYPE *)"";
  105.  *num = *occ = 1L;
  106.  target->num_lines = 1L;
  107.  target->true_line = get_true_line(TRUE);
  108. /*---------------------------------------------------------------------*/
  109. /* Set up default values for the return values...                      */
  110. /*---------------------------------------------------------------------*/
  111.  idx = strlen((DEFCHAR *)cmd_line);
  112.  for (i=1,j=0;i<idx;i++)
  113.    {
  114.     if (*(cmd_line+i) == delim)
  115.       {
  116.        j++;
  117.        switch(j)
  118.          {
  119.           case 1:
  120.                *(cmd_line+i) = '\0';
  121.                *new_str = cmd_line+i+1;
  122.                break;
  123.           case 2:
  124.                *(cmd_line+i) = '\0';
  125.                target_start = cmd_line+i+1;
  126.                break;
  127.           default:
  128.                break;
  129.          }
  130.       }
  131.     if (j == 2)
  132.        break;
  133.    }
  134. /*---------------------------------------------------------------------*/
  135. /* Check to see if there is a target, if not return here.              */
  136. /*---------------------------------------------------------------------*/
  137.  if (blank_field(target_start))
  138.    {
  139. #ifdef TRACE
  140.     trace_return();
  141. #endif
  142.     return(RC_OK);
  143.    }
  144. /*---------------------------------------------------------------------*/
  145. /* Parse and validate the target...                                    */
  146. /*---------------------------------------------------------------------*/
  147.  if ((rc = validate_target(target_start,target,target_type,get_true_line(TRUE),TRUE,TRUE)) != RC_OK)
  148.    {
  149. #ifdef TRACE
  150.     trace_return();
  151. #endif
  152.     return(rc);
  153.    }
  154. /*---------------------------------------------------------------------*/
  155. /* Check to see if there are further arguments after the target...     */
  156. /*---------------------------------------------------------------------*/
  157.  if (target->spare == (-1))
  158.    {
  159. #ifdef TRACE
  160.     trace_return();
  161. #endif
  162.     return(RC_OK);
  163.    }
  164. /*---------------------------------------------------------------------*/
  165. /* Validate the arguments following the target...                      */
  166. /*---------------------------------------------------------------------*/
  167.  strip[0]=STRIP_BOTH;
  168.  strip[1]=STRIP_BOTH;
  169.  num_params = param_split(strtrunc(target->rt[target->spare].string),word,SCP_PARAMS,WORD_DELIMS,TEMP_PARAM,strip,FALSE);
  170.  if (num_params == 1
  171.  ||  num_params == 2)
  172.    {
  173.     if (strcmp((DEFCHAR *)word[0],"*") == 0)
  174.        *num = max_line_length;
  175. /*       *num = MAX_LONG;*/
  176.     else
  177.        if (!valid_positive_integer(word[0]))
  178.          {
  179.           display_error(4,word[0],FALSE);
  180. #ifdef TRACE
  181.           trace_return();
  182. #endif
  183.           return(RC_INVALID_OPERAND);
  184.          }
  185.        else
  186.           *num = min(atol((DEFCHAR *)word[0]),max_line_length);
  187.    }
  188.  if (num_params == 2)
  189.    {
  190.     if (!valid_positive_integer(word[1]))
  191.       {
  192.        display_error(4,word[1],FALSE);
  193. #ifdef TRACE
  194.        trace_return();
  195. #endif
  196.        return(RC_INVALID_OPERAND);
  197.       }
  198.     else
  199.        *occ = atol((DEFCHAR *)word[1]);
  200.    }
  201.  
  202. #ifdef TRACE
  203.  trace_return();
  204. #endif
  205.  return(RC_OK);
  206. }
  207. /***********************************************************************/
  208. #ifdef HAVE_PROTO
  209. short parse_target(CHARTYPE *target_spec,LINETYPE true_line,TARGET *target,
  210.                    short target_types,bool display_parse_error,
  211.                    bool allow_error_display,bool column_target)
  212. #else
  213. short parse_target(target_spec,true_line,target,target_types,
  214.                    display_parse_error,allow_error_display,column_target)
  215. CHARTYPE *target_spec;
  216. LINETYPE true_line;
  217. TARGET *target;
  218. short target_types;
  219. bool display_parse_error,allow_error_display,column_target;
  220. #endif
  221. /***********************************************************************/
  222. {
  223. /*-------------------------- external data ----------------------------*/
  224.  extern bool UNTAAx;
  225. /*--------------------------- local data ------------------------------*/
  226.  short num_targets=0;
  227.  CHARTYPE boolean=' ';
  228.  short state=STATE_NEXT;
  229.  short len=0,inc=0,target_length=strlen((DEFCHAR *)target_spec),off=0;
  230.  CHARTYPE delim=' ';
  231.  register short i=0;
  232.  register short j=0;
  233.  short str_start=0,str_end=0;
  234.  short rc=RC_OK;
  235.  short potential_spare_start=0;
  236.  bool negative=FALSE;
  237.  CHARTYPE *ptr=NULL;
  238.  LINETYPE lineno=0L;
  239. /*--------------------------- processing ------------------------------*/
  240. #ifdef TRACE
  241.  trace_function("target.c:  parse_target");
  242. #endif
  243. /*---------------------------------------------------------------------*/
  244. /* Copy the incoming target specification...                           */
  245. /*---------------------------------------------------------------------*/
  246.  if ((target->string = (CHARTYPE *)my_strdup(target_spec)) == NULL)
  247.    {
  248.     if (allow_error_display)
  249.        display_error(30,(CHARTYPE *)"",FALSE);
  250. #ifdef TRACE
  251.     trace_return();
  252. #endif
  253.     return(RC_OUT_OF_MEMORY);
  254.    }
  255.  ptr = target->string;
  256. /*---------------------------------------------------------------------*/
  257. /* Parse the target...                                                 */
  258. /*---------------------------------------------------------------------*/
  259.  switch(target_types)
  260.    {
  261.     case TARGET_FIND:
  262.     case TARGET_NFIND:
  263.     case TARGET_FINDUP:
  264.     case TARGET_NFINDUP:
  265.          for (i=0;i<target_length;i++)
  266.            {
  267.             if (*(ptr+i) == ' ')
  268.                *(ptr+i) = CURRENT_VIEW->arbchar_single;
  269.             else
  270.                if (*(ptr+i) == '_')
  271.                   *(ptr+i) = ' ';
  272.            }
  273.          target->rt = (RTARGET *)(*the_malloc)(sizeof(RTARGET));
  274.          if (target->rt == NULL)
  275.            {
  276.             if (allow_error_display)
  277.                display_error(30,(CHARTYPE *)"",FALSE);
  278. #ifdef TRACE
  279.             trace_return();
  280. #endif
  281.             return(RC_OUT_OF_MEMORY);
  282.            }
  283.          target->num_targets = 1;
  284.          target->rt[0].not = (target_types == TARGET_NFIND || target_types == TARGET_NFINDUP)?TRUE:FALSE;
  285.          target->rt[0].negative = (target_types == TARGET_FINDUP || target_types == TARGET_NFINDUP)?TRUE:FALSE;
  286.          target->rt[0].boolean = ' ';
  287.          target->rt[0].length = target_length;
  288.          target->rt[0].target_type = TARGET_STRING;
  289.          target->rt[0].numeric_target = 0L;
  290.          target->rt[0].string = (CHARTYPE *)(*the_malloc)((target_length*sizeof(CHARTYPE))+1);
  291.          if (target->rt[0].string == (CHARTYPE *)NULL)
  292.            {
  293.             if (allow_error_display)
  294.                display_error(30,(CHARTYPE *)"",FALSE);
  295. #ifdef TRACE
  296.             trace_return();
  297. #endif
  298.             return(RC_OUT_OF_MEMORY);
  299.            }
  300.          strcpy((DEFCHAR *)target->rt[0].string,(DEFCHAR *)ptr);
  301. #ifdef TRACE
  302.          trace_return();
  303. #endif
  304.          return(RC_OK);
  305.          break;
  306.     default:
  307.          break;
  308.    }
  309.  while(1)
  310.    {
  311.     inc = 1;
  312.     switch(state)
  313.       {
  314.        case STATE_NEXT:
  315.             if (target->rt == NULL)
  316.                target->rt = (RTARGET *)(*the_malloc)((num_targets+1)*sizeof(RTARGET));
  317.             else
  318.                target->rt = (RTARGET *)(*the_realloc)(target->rt,(num_targets+1)*sizeof(RTARGET));
  319.             if (target->rt == NULL)
  320.               {
  321.                if (allow_error_display)
  322.                   display_error(30,(CHARTYPE *)"",FALSE);
  323. #ifdef TRACE
  324.                trace_return();
  325. #endif
  326.                return(RC_OUT_OF_MEMORY);
  327.               }
  328.             target->rt[num_targets].not = FALSE;
  329.             target->rt[num_targets].boolean = boolean;
  330.             target->rt[num_targets].length = 0;
  331.             target->rt[num_targets].string = NULL;
  332.             target->rt[num_targets].negative = FALSE;
  333.             target->rt[num_targets].target_type = TARGET_ERR;
  334.             if (target->spare != (-1))
  335.                state = STATE_SPARE;
  336.             else
  337.                state = STATE_START;
  338.             inc = 0;
  339.             break;
  340.        case STATE_START:
  341.             switch(*(ptr+i))
  342.               {
  343.                case '~': case '^':
  344.                     if (target->rt[num_targets].not)
  345.                       {
  346.                        state = STATE_ERROR;
  347.                        inc = 0;
  348.                        break;
  349.                       }
  350.                     target->rt[num_targets].not = TRUE;
  351.                     break;
  352.                case ' ': 
  353.                case '\t':
  354.                     break;
  355.                case '-':
  356.                     if (target->rt[num_targets].negative)
  357.                       {
  358.                        state = STATE_ERROR;
  359.                        inc = 0;
  360.                        break;
  361.                       }
  362.                     target->rt[num_targets].negative = TRUE;
  363.                     state = STATE_NEGATIVE;
  364.                     break;
  365.                case '+':
  366.                     if (target->rt[num_targets].negative)
  367.                       {
  368.                        state = STATE_ERROR;
  369.                        inc = 0;
  370.                        break;
  371.                       }
  372. /*                    inc = 1; */
  373.                     target->rt[num_targets].negative = FALSE;
  374.                     state = STATE_POSITIVE;
  375.                     break;
  376.                case '.':
  377.                     if (target->rt[num_targets].negative)
  378.                       {
  379.                        state = STATE_ERROR;
  380.                        inc = 0;
  381.                        break;
  382.                       }
  383.                     state = STATE_POINT;
  384.                     str_start = i;
  385.                     break;
  386.                case '*':
  387.                     state = STATE_BOOLEAN;
  388.                     target->rt[num_targets].target_type = TARGET_RELATIVE;
  389.                     target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(3);
  390.                     if (target->rt[num_targets].string == NULL)
  391.                       {
  392.                        if (allow_error_display)
  393.                           display_error(30,(CHARTYPE *)"",FALSE);
  394. #ifdef TRACE
  395.                        trace_return();
  396. #endif
  397.                        return(RC_OUT_OF_MEMORY);
  398.                       }
  399.                     if (target->rt[num_targets].negative)
  400.                       {
  401.                        if (column_target)
  402.                          target->rt[num_targets].numeric_target = (LINETYPE)CURRENT_VIEW->zone_start - true_line - 1L;
  403.                        else
  404.                          target->rt[num_targets].numeric_target = true_line*(-1L);
  405.                        strcpy((DEFCHAR *)target->rt[num_targets].string,"-*");
  406.                       }
  407.                     else
  408.                       {
  409.                        if (column_target)
  410.                          target->rt[num_targets].numeric_target = (LINETYPE)((LINETYPE)CURRENT_VIEW->zone_end - true_line) + 1L;
  411.                        else
  412.                          target->rt[num_targets].numeric_target = (CURRENT_FILE->number_lines - true_line) + 2L;
  413.                        strcpy((DEFCHAR *)target->rt[num_targets].string,"*");
  414.                       }
  415.                     inc = 1;
  416.                     potential_spare_start = i+1;
  417.                     num_targets++;
  418.                     break;
  419.                case ':': case ';':
  420.                     state = STATE_ABSOLUTE;
  421.                     delim = *(ptr+i);
  422.                     str_start = i+1;
  423.                     break;
  424.                case '/': case '\\': case '@': case '`': case '#': case '$':
  425.                case '%': case '(': case ')': case '{': case '}': case '[': case ']':
  426.                case '"': case '\'': case '<': case '>': 
  427.                case ',':
  428.                     state = STATE_STRING;
  429.                     str_start = i+1;
  430.                     delim = *(ptr+i);
  431.                     break;
  432.                case 'a': case 'A':
  433.                     if (target->rt[num_targets].not
  434.                     ||  target->rt[num_targets].negative)
  435.                       {
  436.                        state = STATE_ERROR;
  437.                        inc = 0;
  438.                        break;
  439.                       }
  440.                     if (target_length-i < 3)
  441.                       {
  442.                        target->rt[num_targets].target_type = TARGET_ERR;
  443.                        state = STATE_ERROR;
  444.                        inc = 0;
  445.                        break;
  446.                       }
  447.                     if (memcmpi((CHARTYPE *)"all",ptr+i,3) == 0
  448.                     && (*(ptr+(i+3)) == ' ' 
  449.                         || *(ptr+(i+3)) == '\0'
  450.                         || *(ptr+(i+3)) == '\t'))
  451.                       {
  452.                        target->rt[num_targets].target_type = TARGET_ALL;
  453.                        inc = 3;
  454.                        state = STATE_BOOLEAN;
  455.                        num_targets++;
  456.                        potential_spare_start = i+3;
  457.                        break;
  458.                       }
  459.                     state = STATE_ERROR;
  460.                     inc = 0;
  461.                     break;
  462.                case 'b': case 'B':
  463.                     if (target_length-i < 5)
  464.                       {
  465.                        state = STATE_ERROR;
  466.                        inc = 0;
  467.                        break;
  468.                       }
  469.                     if (memcmpi((CHARTYPE *)"blank",ptr+i,5) == 0
  470.                     && (*(ptr+(i+5)) == ' ' 
  471.                         || *(ptr+(i+5)) == '\0'
  472.                         || *(ptr+(i+5)) == '\t'))
  473.                       {
  474.                        target->rt[num_targets].target_type = TARGET_BLANK;
  475.                        inc = 5;
  476.                        potential_spare_start = i+5;
  477.                        state = STATE_BOOLEAN;
  478.                        num_targets++;
  479.                        break;
  480.                       }
  481.                     if (target->rt[num_targets].not
  482.                     ||  target->rt[num_targets].negative)
  483.                       {
  484.                        state = STATE_ERROR;
  485.                        inc = 0;
  486.                        break;
  487.                       }
  488.                     if (memcmpi((CHARTYPE *)"block",ptr+i,5) == 0
  489.                     && (*(ptr+(i+5)) == ' ' 
  490.                         || *(ptr+(i+5)) == '\0'
  491.                         || *(ptr+(i+5)) == '\t'))
  492.                       {
  493.                        target->rt[num_targets].target_type = TARGET_BLOCK;
  494.                        inc = 5;
  495.                        potential_spare_start = i+5;
  496.                        state = STATE_BOOLEAN;
  497.                        num_targets++;
  498.                        break;
  499.                       }
  500.                     state = STATE_ERROR;
  501.                     inc = 0;
  502.                     break;
  503.                case '0': case '1': case '2': case '3': case '4': 
  504.                case '5': case '6': case '7': case '8': case '9':      
  505.                     if (UNTAAx)
  506.                        state = STATE_ABSOLUTE;
  507.                     else
  508.                        state = STATE_RELATIVE;
  509.                     str_start = i;
  510.                     delim = '\0';
  511.                     inc = 0;
  512.                     break;
  513.                default:
  514.                     state = STATE_ERROR;
  515.                     inc = 0;
  516.                     break;
  517.               }
  518.             break;
  519.        case STATE_STRING:
  520.             switch(*(ptr+i))
  521.               {
  522.                case '/': case '\\': case '@': case '`': case '#': case '$':
  523.                case '%': case '(': case ')': case '{': case '}': case '[': case ']':
  524.                case '"': case '\'': case '<': case '>': 
  525.                case '\0':
  526.                     if (*(ptr+i) == delim
  527.                     ||  *(ptr+i) == '\0')
  528.                       {
  529.                        state = STATE_BOOLEAN;
  530.                        str_end = i;
  531.                        len = str_end-str_start;
  532.                        target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(len+1);
  533.                        if (target->rt[num_targets].string == NULL)
  534.                          {
  535.                           if (allow_error_display)
  536.                              display_error(30,(CHARTYPE *)"",FALSE);
  537. #ifdef TRACE
  538.                           trace_return();
  539. #endif
  540.                           return(RC_OUT_OF_MEMORY);
  541.                          }
  542.                        memcpy(target->rt[num_targets].string,ptr+str_start,len);
  543.                        target->rt[num_targets].string[len] = '\0';
  544.                        target->rt[num_targets].length = len;
  545.                        target->rt[num_targets].target_type = TARGET_STRING;
  546.                        potential_spare_start = i+1;
  547.                        num_targets++;
  548.                       }
  549.                     break;
  550.                default:
  551.                     break;
  552.               }
  553.             break;
  554.        case STATE_BOOLEAN:
  555.             switch(*(ptr+i))
  556.               {
  557.                case '\0':
  558.                     break;
  559.                case ' ': 
  560.                case '\t':
  561.                     break;
  562.                case '&': 
  563.                case '|':
  564.                     state = STATE_NEXT;
  565.                     boolean = *(ptr+i);
  566.                     break;
  567.                default:
  568.                     if (target_types & TARGET_SPARE)
  569.                       {
  570. /*                       str_start = i;*/
  571.                        str_start = potential_spare_start;
  572.                        state = STATE_NEXT;
  573.                        target->spare = 0; /* just to ensure state is set */
  574.                        break;
  575.                       }
  576.                     state = STATE_ERROR;
  577.                     inc = 0;
  578.                     break;
  579.               }
  580.             break;
  581.        case STATE_SPARE:
  582.             switch(*(ptr+i))
  583.               {
  584.                case '\0':
  585.                     str_end = i;
  586.                     len = str_end-str_start;
  587.                     target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(len+1);
  588.                     if (target->rt[num_targets].string == NULL)
  589.                       {
  590.                        if (allow_error_display)
  591.                           display_error(30,(CHARTYPE *)"",FALSE);
  592. #ifdef TRACE
  593.                        trace_return();
  594. #endif
  595.                        return(RC_OUT_OF_MEMORY);
  596.                       }
  597.                     memcpy(target->rt[num_targets].string,ptr+str_start,len);
  598.                     target->rt[num_targets].string[len] = '\0';
  599.                     target->rt[num_targets].length = len;
  600.                     target->rt[num_targets].target_type = TARGET_SPARE;
  601.                     target->spare = num_targets;
  602.                     num_targets++;
  603.                     *(ptr+str_start) = '\0'; /* so target string does not include spare */
  604.                     break;
  605.                default:
  606.                     break;
  607.               }
  608.             break;
  609.        case STATE_ABSOLUTE:
  610.        case STATE_RELATIVE:
  611.             if (target->rt[num_targets].not)
  612.               {
  613.                state = STATE_ERROR;
  614.                inc = 0;
  615.                break;
  616.               }
  617.             switch(*(ptr+i))
  618.               {
  619.                case '\0':
  620.                case ' ':
  621.                case '\t':
  622.                     str_end = i;
  623.                     len = str_end-str_start;
  624.                     target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(len+2);
  625.                     if (target->rt[num_targets].string == NULL)
  626.                       {
  627.                        if (allow_error_display)
  628.                           display_error(30,(CHARTYPE *)"",FALSE);
  629. #ifdef TRACE
  630.                        trace_return();
  631. #endif
  632.                        return(RC_OUT_OF_MEMORY);
  633.                       }
  634.                     if (delim != '\0')
  635.                       {
  636.                        target->rt[num_targets].string[0] = delim;
  637.                        off = 1;
  638.                       }
  639.                     else
  640.                        off = 0;
  641.                     memcpy(target->rt[num_targets].string+off,ptr+str_start,len);
  642.                     target->rt[num_targets].string[len+off] = '\0';
  643.                     target->rt[num_targets].length = len+off;
  644.                     target->rt[num_targets].target_type = (state == STATE_ABSOLUTE) ? TARGET_ABSOLUTE : TARGET_RELATIVE;
  645.                     target->rt[num_targets].numeric_target = atol((DEFCHAR *)target->rt[num_targets].string+off);
  646.                     if (target->rt[num_targets].negative)
  647.                        target->rt[num_targets].numeric_target *= (-1L);
  648.                     if (state == STATE_ABSOLUTE)
  649.                       {
  650.                        if (column_target)
  651.                          {
  652. /*                          if (target->rt[num_targets].numeric_target < CURRENT_VIEW->current_column)*/
  653.                           if (target->rt[num_targets].numeric_target < true_line)
  654.                             {
  655.                              target->rt[num_targets].negative = TRUE;
  656.                              target->rt[num_targets].numeric_target = max(target->rt[num_targets].numeric_target,max(1,CURRENT_VIEW->zone_start-1));
  657.                             }
  658.                           else
  659.                              target->rt[num_targets].numeric_target = min(target->rt[num_targets].numeric_target,min(max_line_length+1,CURRENT_VIEW->zone_end+1));
  660.                          }
  661.                        else
  662.                          {
  663.                           if (target->rt[num_targets].numeric_target < true_line)
  664.                              target->rt[num_targets].negative = TRUE;
  665.                           else
  666.                              target->rt[num_targets].numeric_target = min(target->rt[num_targets].numeric_target,(CURRENT_FILE->number_lines+1L));
  667.                          }
  668.                       }
  669.                     else
  670.                       {
  671.                        if (column_target)
  672.                          {
  673.                           if (target->rt[num_targets].negative)
  674.                              target->rt[num_targets].numeric_target = max(target->rt[num_targets].numeric_target,((LINETYPE)CURRENT_VIEW->zone_start - true_line - 1L));
  675.                           else
  676.                              target->rt[num_targets].numeric_target = min(target->rt[num_targets].numeric_target,((LINETYPE)CURRENT_VIEW->zone_end - true_line + 1L));
  677.                          }
  678.                        else
  679.                          {
  680.                           if (target->rt[num_targets].negative)
  681.                              target->rt[num_targets].numeric_target = max((target->rt[num_targets].numeric_target),(true_line == 0L) ? (0L) : (true_line*(-1L)));
  682.                           else
  683.                              target->rt[num_targets].numeric_target = min(target->rt[num_targets].numeric_target,(CURRENT_FILE->number_lines - true_line+1L));
  684.                          }
  685.                       }
  686.                     potential_spare_start = i;
  687.                     num_targets++;
  688.                     state = STATE_BOOLEAN;
  689.                     break;
  690.                case '0': case '1': case '2': case '3': case '4':
  691.                case '5': case '6': case '7': case '8': case '9':
  692.                     break;
  693.                default:
  694.                     state = STATE_ERROR;
  695.                     inc = 0;
  696.                     break;
  697.               }
  698.             break;
  699.        case STATE_NEGATIVE:
  700.        case STATE_POSITIVE:
  701.             switch(*(ptr+i))
  702.               {
  703.                case '0': case '1': case '2': case '3': case '4':
  704.                case '5': case '6': case '7': case '8': case '9':
  705.                     state = STATE_RELATIVE;
  706.                     delim = (state==STATE_NEGATIVE) ? '-' : '+';
  707.                     str_start = i;
  708.                     inc = 0;
  709.                     break;
  710.                case '/': case '\\': case '@': case '`': case '#': case '$':
  711.                case '%': case '(': case ')': case '{': case '}': case '[': case ']':
  712.                case '"': case '\'': case '<': case '>': 
  713.                     state = STATE_START;
  714.                     inc = 0;
  715.                     break;
  716.                case '*':
  717.                     state = STATE_START;
  718.                     inc = 0;
  719.                     break;
  720.                case 'b': case 'B':
  721.                     state = STATE_START;
  722.                     inc = 0;
  723.                     break;
  724.                default:
  725.                     state = STATE_ERROR;
  726.                     inc = 0;
  727.                     break;
  728.               }
  729.             break;
  730.        case STATE_POINT:
  731.             switch(*(ptr+i))
  732.               {
  733.                case ' ':
  734.                case '\t':
  735.                     state = STATE_BOOLEAN;
  736.                     /* fall through */
  737.                case '&':
  738.                case '|':
  739.                case '\0':
  740.                     target->rt[num_targets].target_type = TARGET_POINT;
  741.                     str_end = i;
  742.                     len = str_end-str_start;
  743.                     target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(len+1);
  744.                     if (target->rt[num_targets].string == NULL)
  745.                       {
  746.                        if (allow_error_display)
  747.                           display_error(30,(CHARTYPE *)"",FALSE);
  748. #ifdef TRACE
  749.                        trace_return();
  750. #endif
  751.                        return(RC_OUT_OF_MEMORY);
  752.                       }
  753.                     memcpy(target->rt[num_targets].string,ptr+str_start,len);
  754.                     target->rt[num_targets].string[len] = '\0';
  755.                     target->rt[num_targets].length = len;
  756.                     if (find_named_line(target->rt[num_targets].string,&lineno,TRUE) == NULL)
  757.                       {
  758.                        if (allow_error_display)
  759.                           display_error(17,(CHARTYPE *)target->rt[num_targets].string,FALSE);
  760. #ifdef TRACE
  761.                        trace_return();
  762. #endif
  763.                        return(RC_TARGET_NOT_FOUND);
  764.                       }
  765.                     target->rt[num_targets].numeric_target = lineno;
  766.                     if (target->rt[num_targets].numeric_target < true_line)
  767.                        target->rt[num_targets].negative = TRUE;
  768.                     else
  769.                        target->rt[num_targets].numeric_target = min(target->rt[num_targets].numeric_target,(CURRENT_FILE->number_lines+1L));
  770.                     num_targets++;
  771.                     potential_spare_start = i;
  772.                     if (*(ptr+i) == ' ' || *(ptr+i) == '\t')
  773.                        break;
  774.                     boolean = *(ptr+i);
  775.                     state = STATE_NEXT;
  776.                     break;
  777.                default:
  778.                     break;
  779.               }
  780.             break;
  781.        case STATE_ERROR:
  782.             for (j=0;j<num_targets;j++)
  783.                target->rt[j].target_type = TARGET_ERR;
  784.             state = STATE_QUIT;
  785.             break;
  786.       }
  787.     if (state == STATE_QUIT)
  788.        break;
  789.     i += inc;
  790.     if (i > target_length) /* this allows for testing '\0' as delimiter */
  791.        break;
  792.    }
  793.  target->num_targets = num_targets;
  794.  if (num_targets == 0
  795.  ||  target->rt[0].target_type == TARGET_ERR)
  796.    {
  797.     if (display_parse_error
  798.     && allow_error_display)
  799.        display_error(1,ptr,FALSE);
  800. #ifdef TRACE
  801.     trace_return();
  802. #endif
  803.     return(RC_INVALID_OPERAND);
  804.    }
  805. /*---------------------------------------------------------------------*/
  806. /* Time to validate the targets we have parsed...                      */
  807. /*---------------------------------------------------------------------*/
  808. /* Valid combinations are:                                             */
  809. /* TARGET_ALL       (1 target only)                                    */
  810. /*                  ALL  only                                          */
  811. /* TARGET_BLOCK     (1 target only)                                    */
  812. /*                  BLOCK  only                                        */
  813. /*                  this section sets target_type to TARGET_BLOCK_ANY  */
  814. /*                  or TARGET_BLOCK_CURRENT                            */
  815. /* TARGET_BLANK     (BLANK can be upper or lower case)                 */
  816. /*                  BLANK                                              */
  817. /*                  -BLANK                                             */
  818. /*                  ~BLANK                                             */
  819. /*                  ~-BLANK                                            */
  820. /* TARGET_STRING    (valid delimiters are / \ or @                     */
  821. /*                  /string/                                           */
  822. /*                  -/string/                                          */
  823. /*                  ~/string/                                          */
  824. /*                  ~-/string/                                         */
  825. /* TARGET_POINT                                                        */
  826. /*                  .xxxxxx                                            */
  827. /*                  ~.xxxxxx                                           */
  828. /* TARGET_ABSOLUTE                                                     */
  829. /*                  :99                                                */
  830. /*                  ;99                                                */
  831. /* TARGET_RELATIVE                                                     */
  832. /*                  99                                                 */
  833. /*                  +99                                                */
  834. /*                  -99                                                */
  835. /*                  *                                                  */
  836. /*                  +*                                                 */
  837. /*                  -*                                                 */
  838. /*                                                                     */
  839. /* Any of the above target types may be or'd together.                 */
  840. /*---------------------------------------------------------------------*/
  841. /*---------------------------------------------------------------------*/
  842. /* For each of the targets, check its validity...                      */
  843. /*---------------------------------------------------------------------*/
  844.  negative = target->rt[0].negative;
  845.  for (i=0;i<num_targets-((target->spare == (-1)) ? 0 : 1);i++)
  846.    {
  847.     switch(target->rt[i].target_type)
  848.       {
  849.        case TARGET_BLOCK:
  850.             if (num_targets-((target->spare == (-1)) ? 0 : 1) != 1)
  851.               {
  852.                rc = RC_INVALID_OPERAND;
  853.                break;
  854.               }
  855.             if (target_types & TARGET_BLOCK_ANY)
  856.                target->rt[i].target_type = TARGET_BLOCK_ANY;
  857.             else
  858.                if (target_types & TARGET_BLOCK_CURRENT)
  859.                   target->rt[i].target_type = TARGET_BLOCK_CURRENT;
  860.                else
  861.                   rc = RC_INVALID_OPERAND;
  862.             break;
  863.        case TARGET_ALL:
  864.             if (num_targets-((target->spare == (-1)) ? 0 : 1) != 1)
  865.               {
  866.                rc = RC_INVALID_OPERAND;
  867.                break;
  868.               }
  869.             if (target_types & target->rt[i].target_type)
  870.                break;
  871.             rc = RC_INVALID_OPERAND;
  872.             break;
  873.        default:
  874.             if (target->rt[i].negative != negative)
  875.               {
  876.                rc = RC_INVALID_OPERAND;
  877.                break;
  878.               }
  879.             if (target_types & target->rt[i].target_type)
  880.                break;
  881.             rc = RC_INVALID_OPERAND;
  882.             break;
  883.       }
  884.     if (rc == RC_INVALID_OPERAND)
  885.        break;
  886.    }
  887. /*---------------------------------------------------------------------*/
  888. /* Display an error if anything found amiss and we are directed to     */
  889. /* display an error...                                                 */
  890. /*---------------------------------------------------------------------*/
  891.  if (rc != RC_OK
  892.  && display_parse_error
  893.  && allow_error_display)
  894.     display_error(1,ptr,FALSE);
  895. #ifdef TRACE
  896.  trace_return();
  897. #endif
  898.  return(rc);
  899. }
  900. /***********************************************************************/
  901. #ifdef HAVE_PROTO
  902. void initialise_target(TARGET *target)
  903. #else
  904. void initialise_target(target)
  905. TARGET *target;
  906. #endif
  907. /***********************************************************************/
  908. {
  909. /*--------------------------- local data ------------------------------*/
  910. /*--------------------------- processing ------------------------------*/
  911. #ifdef TRACE
  912.  trace_function("target.c:  initialise_target");
  913. #endif
  914.  target->rt=NULL;
  915.  target->string=NULL;
  916.  target->num_lines = target->true_line = target->last_line = 0L;
  917.  target->num_targets = 0;
  918.  target->spare = (-1);
  919.  target->ignore_scope = FALSE;
  920. #ifdef TRACE
  921.  trace_return();
  922. #endif
  923.  return;
  924. }
  925. /***********************************************************************/
  926. #ifdef HAVE_PROTO
  927. void free_target(TARGET *target)
  928. #else
  929. void free_target(target)
  930. TARGET *target;
  931. #endif
  932. /***********************************************************************/
  933. {
  934. /*--------------------------- local data ------------------------------*/
  935.  register short i=0;
  936. /*--------------------------- processing ------------------------------*/
  937. #ifdef TRACE
  938.  trace_function("target.c:  free_target");
  939. #endif
  940.  if (target->string == NULL
  941.  &&  target->num_targets == 0
  942.  &&  target->rt == NULL)
  943.    {
  944. #ifdef TRACE
  945.     trace_return();
  946. #endif
  947.     return;
  948.    }
  949.  for (i=0;i<target->num_targets;i++)
  950.    {
  951.     if (target->rt[i].string != NULL)
  952.        (*the_free)(target->rt[i].string);
  953.    }
  954.  if (target->string != NULL)
  955.     (*the_free)(target->string);
  956.  if (target->rt != NULL)
  957.     (*the_free)(target->rt);
  958. #ifdef TRACE
  959.  trace_return();
  960. #endif
  961.  return;
  962. }
  963. /***********************************************************************/
  964. #ifdef HAVE_PROTO
  965. short find_target(TARGET *target,LINETYPE true_line,bool display_parse_error,bool allow_error_display)
  966. #else
  967. short find_target(target,true_line,display_parse_error,allow_error_display)
  968. TARGET *target;
  969. LINETYPE true_line;
  970. bool display_parse_error,allow_error_display;
  971. #endif
  972. /***********************************************************************/
  973. {
  974. /*-------------------------- external data ----------------------------*/
  975.  extern VIEW_DETAILS *vd_mark;
  976. /*--------------------------- local data ------------------------------*/
  977.  short rc=RC_OK;
  978.  LINE *curr=NULL;
  979.  LINETYPE num_lines=0L;
  980.  LINETYPE line_number=0L;
  981.  short status=RC_OK;
  982. /*--------------------------- processing ------------------------------*/
  983. #ifdef TRACE
  984.  trace_function("target.c:  find_target");
  985. #endif
  986. /*---------------------------------------------------------------------*/
  987. /* Check single targets first (ALL and BLOCK)                          */
  988. /*---------------------------------------------------------------------*/
  989. /*---------------------------------------------------------------------*/
  990. /* Check if first, and only target, is BLOCK...                        */
  991. /*---------------------------------------------------------------------*/
  992.  switch(target->rt[0].target_type)
  993.    {
  994.     case TARGET_ALL:
  995.          target->true_line = 1L;
  996.          target->last_line = CURRENT_FILE->number_lines;
  997.          target->num_lines = CURRENT_FILE->number_lines;
  998. #ifdef TRACE
  999.          trace_return();
  1000. #endif
  1001.          return(RC_OK);
  1002.          break;
  1003.     case TARGET_BLOCK_ANY:
  1004.          if (MARK_VIEW == NULL)
  1005.            {
  1006.             if (allow_error_display)
  1007.                display_error(44,(CHARTYPE *)"",FALSE);
  1008.             rc = RC_TARGET_NOT_FOUND;
  1009.            }
  1010.          else
  1011.            {
  1012.             target->num_lines = MARK_VIEW->mark_end_line - MARK_VIEW->mark_start_line + 1L;
  1013.             target->true_line = MARK_VIEW->mark_start_line;
  1014.             target->last_line = MARK_VIEW->mark_end_line;
  1015.            }
  1016. #ifdef TRACE
  1017.          trace_return();
  1018. #endif
  1019.          return(rc);
  1020.          break;
  1021.     case TARGET_BLOCK_CURRENT:
  1022.          if (MARK_VIEW == NULL)
  1023.            {
  1024.             if (allow_error_display)
  1025.                display_error(44,(CHARTYPE *)"",FALSE);
  1026.             rc = RC_TARGET_NOT_FOUND;
  1027.            }
  1028.          else
  1029.            {
  1030.             if (MARK_VIEW != CURRENT_VIEW)
  1031.               {
  1032.                if (allow_error_display)
  1033.                   display_error(45,(CHARTYPE *)"",FALSE);
  1034.                rc = RC_TARGET_NOT_FOUND;
  1035.               }
  1036.             else
  1037.               {
  1038.                target->num_lines = MARK_VIEW->mark_end_line - MARK_VIEW->mark_start_line + 1L;
  1039.                target->true_line = MARK_VIEW->mark_start_line;
  1040.                target->last_line = MARK_VIEW->mark_end_line;
  1041.               }
  1042.            }
  1043. #ifdef TRACE
  1044.          trace_return();
  1045. #endif
  1046.          return(rc);
  1047.          break;
  1048.     default:
  1049.          break;
  1050.    }
  1051. /*---------------------------------------------------------------------*/
  1052. /* All other targets are potentially repeating targets...              */
  1053. /*---------------------------------------------------------------------*/
  1054.  rc = RC_TARGET_NOT_FOUND;
  1055.  line_number = true_line;
  1056.  curr = lll_find(CURRENT_FILE->first_line,CURRENT_FILE->last_line,true_line,CURRENT_FILE->number_lines);
  1057.  num_lines = 0L;
  1058.  while(1)
  1059.    {
  1060.     status = find_rtarget_target(curr,target,true_line,line_number,&num_lines);
  1061.     if (status != RC_TARGET_NOT_FOUND)
  1062.        break;
  1063. /*---------------------------------------------------------------------*/
  1064. /* We can determine the direction of execution based on the first      */
  1065. /* target, as all targets must have the same direction to have reached */
  1066. /* here.                                                               */
  1067. /*---------------------------------------------------------------------*/
  1068.     if (target->rt[0].negative)
  1069.       {
  1070.        curr = curr->prev;
  1071.        line_number--;
  1072.       }
  1073.     else
  1074.       {
  1075.        curr = curr->next;
  1076.        line_number++;
  1077.       }
  1078.     if (curr == NULL)
  1079.        break;
  1080.    }
  1081.  if (status == RC_OK)
  1082.    {
  1083.     num_lines = ((target->rt[0].negative) ? -num_lines : num_lines);
  1084.     target->num_lines = num_lines;
  1085.     target->true_line = true_line;
  1086.     if (target->rt[0].negative)
  1087.       {
  1088.        curr = curr->next;
  1089.        target->last_line = find_next_in_scope(CURRENT_VIEW,curr,++line_number,DIRECTION_FORWARD);
  1090.       }
  1091.     else
  1092.       {
  1093.        curr = curr->prev;
  1094.        target->last_line = find_next_in_scope(CURRENT_VIEW,curr,--line_number,DIRECTION_BACKWARD);
  1095.       }
  1096.     rc = RC_OK;
  1097.    }
  1098.  else if (status == RC_TARGET_NOT_FOUND)
  1099.    {
  1100.     if (allow_error_display)
  1101.        display_error(17,target->string,FALSE);
  1102.     rc = RC_TARGET_NOT_FOUND;
  1103.    }
  1104.  else
  1105.     rc = status;
  1106. #ifdef TRACE
  1107.  trace_return();
  1108. #endif
  1109.  return(rc);
  1110. }
  1111. /***********************************************************************/
  1112. #ifdef HAVE_PROTO
  1113. short find_column_target(CHARTYPE *line,LENGTHTYPE len,TARGET *target,LENGTHTYPE true_column,bool display_parse_error,bool allow_error_display)
  1114. #else
  1115. short find_column_target(line,len,target,true_column,display_parse_error,allow_error_display)
  1116. CHARTYPE *line;
  1117. LENGTHTYPE len;
  1118. TARGET *target;
  1119. LENGTHTYPE true_column;
  1120. bool display_parse_error,allow_error_display;
  1121. #endif
  1122. /***********************************************************************/
  1123. {
  1124. /*-------------------------- external data ----------------------------*/
  1125. /*--------------------------- local data ------------------------------*/
  1126.  short rc=RC_OK;
  1127.  LINETYPE column_number=0L;
  1128.  LINETYPE num_columns=0L;
  1129.  bool status=FALSE;
  1130. /*--------------------------- processing ------------------------------*/
  1131. #ifdef TRACE
  1132.  trace_function("target.c:  find_column_target");
  1133. #endif
  1134. /*---------------------------------------------------------------------*/
  1135. /* All column targets are potentially repeating targets...             */
  1136. /*---------------------------------------------------------------------*/
  1137.  rc = RC_TARGET_NOT_FOUND;
  1138.  status = FALSE;
  1139.  column_number = true_column;
  1140.  num_columns = 0;
  1141.  while(1)
  1142.    {
  1143.     status = find_rtarget_column_target(line,len,target,true_column,column_number,&num_columns);
  1144.     if (status)
  1145.        break;
  1146. /*---------------------------------------------------------------------*/
  1147. /* We can determine the direction of execution based on the first      */
  1148. /* target, as all targets must have the same direction to have reached */
  1149. /* here.                                                               */
  1150. /*---------------------------------------------------------------------*/
  1151.     if (target->rt[0].negative)
  1152.       {
  1153.        if (column_number-- == (LINETYPE)CURRENT_VIEW->zone_start - 2L)
  1154.          {
  1155.           status = FALSE;
  1156.           break;
  1157.          }
  1158.       }
  1159.     else
  1160.       {
  1161.        if (column_number++ == (LINETYPE)CURRENT_VIEW->zone_end + 2L)
  1162.          {
  1163.           status = FALSE;
  1164.           break;
  1165.          }
  1166.       }
  1167.    }
  1168.  if (status)
  1169.    {
  1170.     num_columns = ((target->rt[0].negative) ? -num_columns : num_columns);
  1171.     target->num_lines = num_columns;
  1172.     target->true_line = (LINETYPE)true_column;
  1173.     target->last_line = (LINETYPE)column_number;
  1174.     rc = RC_OK;
  1175.    }
  1176.  else
  1177.    {
  1178.     if (allow_error_display)
  1179.        display_error(17,target->string,FALSE);
  1180.     rc = RC_TARGET_NOT_FOUND;
  1181.    }
  1182. #ifdef TRACE
  1183.  trace_return();
  1184. #endif
  1185.  return(rc);
  1186. }
  1187. /***********************************************************************/
  1188. #ifdef HAVE_PROTO
  1189. static bool is_blank(LINE *curr)
  1190. #else
  1191. static bool is_blank(curr)
  1192. LINE *curr;
  1193. #endif
  1194. /***********************************************************************/
  1195. {
  1196. /*-------------------------- external data ----------------------------*/
  1197. /*--------------------------- local data ------------------------------*/
  1198.  register short i=0;
  1199.  bool rc=TRUE;
  1200. /*--------------------------- processing ------------------------------*/
  1201. #ifdef TRACE
  1202.  trace_function("target.c:  is_blank");
  1203. #endif
  1204.  if (CURRENT_VIEW->zone_start > curr->length)
  1205.    {
  1206. #ifdef TRACE
  1207.     trace_return();
  1208. #endif
  1209.     return(TRUE);
  1210.    }
  1211.  for (i=CURRENT_VIEW->zone_start-1;i<min(CURRENT_VIEW->zone_end,curr->length);i++)
  1212.    {
  1213.     if (*(curr->line+i) != ' ')
  1214.       {
  1215.        rc = FALSE;
  1216.        break;
  1217.       }
  1218.    }
  1219. #ifdef TRACE
  1220.  trace_return();
  1221. #endif
  1222.  return(rc);
  1223. }
  1224. /***********************************************************************/
  1225. #ifdef HAVE_PROTO
  1226. LINE *find_named_line(CHARTYPE *name,LINETYPE *retline,bool respect_scope)
  1227. #else
  1228. LINE *find_named_line(name,retline,respect_scope)
  1229. CHARTYPE *name;
  1230. LINETYPE *retline;
  1231. bool respect_scope;
  1232. #endif
  1233. /***********************************************************************/
  1234. {
  1235. /*-------------------------- external data ----------------------------*/
  1236. /*--------------------------- local data ------------------------------*/
  1237.  LINETYPE lineno=0;
  1238.  LINE *curr=NULL;
  1239. /*--------------------------- processing ------------------------------*/
  1240. #ifdef TRACE
  1241.  trace_function("target.c:  find_named_line");
  1242. #endif
  1243. /*---------------------------------------------------------------------*/
  1244. /* Find the line number in the current file of the named line specified*/
  1245. /*---------------------------------------------------------------------*/
  1246.  curr = CURRENT_FILE->first_line;
  1247.  while(curr != (LINE *)NULL)
  1248.    {
  1249. /*---------------------------------------------------------------------*/
  1250. /* Check the line's name if we are not respecting scope or if we are   */
  1251. /* respecting scope and the line is in scope.                          */
  1252. /*---------------------------------------------------------------------*/
  1253.     if (!respect_scope
  1254.     || (respect_scope && (in_scope(CURRENT_VIEW,curr) || CURRENT_VIEW->scope_all)))
  1255.       {
  1256.        if (curr->name != (CHARTYPE *)NULL)
  1257.           if (strcmp((DEFCHAR *)curr->name,(DEFCHAR *)name) == 0)
  1258.             {
  1259. #ifdef TRACE
  1260.              trace_return();
  1261. #endif
  1262.              *retline = lineno;
  1263.              return(curr);
  1264.             }
  1265.       }
  1266.     lineno++;
  1267.     curr = curr->next;
  1268.    }
  1269. #ifdef TRACE
  1270.  trace_return();
  1271. #endif
  1272.  return((LINE *)NULL);
  1273. }
  1274. /***********************************************************************/
  1275. #ifdef HAVE_PROTO
  1276. short find_string_target(LINE *curr,RTARGET *rt)
  1277. #else
  1278. short find_string_target(curr,rt)
  1279. LINE *curr;
  1280. RTARGET *rt;
  1281. #endif
  1282. /***********************************************************************/
  1283. {
  1284. /*-------------------------- external data ----------------------------*/
  1285.  extern CHARTYPE *trec;
  1286. /*--------------------------- local data ------------------------------*/
  1287.  CHARTYPE *haystack=curr->line;
  1288.  CHARTYPE temp_str[MAX_COMMAND_LENGTH];
  1289.  CHARTYPE *needle=temp_str;
  1290.  LENGTHTYPE needle_length=0,haystack_length=0,real_start=0,real_end=0;
  1291.  bool use_trec=FALSE;
  1292.  short rc=RC_OK;
  1293.  short loc=0;
  1294. /*--------------------------- processing ------------------------------*/
  1295. #ifdef TRACE
  1296.  trace_function("target.c:  find_string_target");
  1297. #endif
  1298. /*---------------------------------------------------------------------*/
  1299. /* Copy the supplied string target rather than point to it, as we don't*/
  1300. /* want to change the value of the target if it is a HEX string.       */
  1301. /*---------------------------------------------------------------------*/
  1302.  strcpy((DEFCHAR*)temp_str,(DEFCHAR*)rt->string);
  1303. /*---------------------------------------------------------------------*/
  1304. /* If HEX is on, convert the target from a HEX format to CHARTYPE.     */
  1305. /*---------------------------------------------------------------------*/
  1306.  if (CURRENT_VIEW->hex == TRUE)
  1307.    {
  1308.     rc = convert_hex_strings(needle);
  1309.     if (rc == (-1))
  1310.       {
  1311.        display_error(32,needle,FALSE);
  1312. #ifdef TRACE
  1313.        trace_return();
  1314. #endif
  1315.        return(RC_INVALID_OPERAND);
  1316.       }
  1317.     else
  1318.       needle_length = rc;
  1319.    }
  1320.  else
  1321.    needle_length = strlen((DEFCHAR *)needle);
  1322. /*---------------------------------------------------------------------*/
  1323. /* Determine if we need to copy the contents of the line into trec.    */
  1324. /* The reasons we need to do this are:                                 */
  1325. /* - the length of the needle is 0                                     */
  1326. /* - the last character of needle is a space                           */
  1327. /*---------------------------------------------------------------------*/
  1328.  if (needle_length == 0)
  1329.     use_trec = TRUE;
  1330.  else
  1331.     if (*(needle+(needle_length-1)) == ' ')
  1332.        use_trec = TRUE;
  1333.  
  1334.  if (use_trec)
  1335.    {
  1336.     memset(trec,' ',max_line_length);
  1337.     memcpy(trec,curr->line,curr->length);
  1338.     haystack = trec;
  1339. /*    haystack_length = max_line_length;*/
  1340.     haystack_length = min(max_line_length,max(CURRENT_VIEW->zone_start,curr->length)+needle_length);
  1341.    }
  1342.  else
  1343.    {
  1344.     haystack = curr->line;
  1345.     haystack_length = curr->length;
  1346.    }
  1347. /*---------------------------------------------------------------------*/
  1348. /* Calculate the bounds to search in based on length of haystack and   */
  1349. /* ZONE settings.                                                      */
  1350. /*---------------------------------------------------------------------*/
  1351.  real_end = min(haystack_length-1,CURRENT_VIEW->zone_end-1);
  1352.  real_start = max(0,CURRENT_VIEW->zone_start-1);
  1353. /*---------------------------------------------------------------------*/
  1354. /* Find the needle in the haystack.                                    */
  1355. /*---------------------------------------------------------------------*/
  1356.  loc = memfind(haystack+real_start,needle,(real_end-real_start+1),
  1357. /* loc = memfind(haystack+real_start,needle,(real_end-real_start), */
  1358.                   needle_length,(CURRENT_VIEW->case_locate == CASE_IGNORE) ? TRUE : FALSE,
  1359.                   CURRENT_VIEW->arbchar_status,
  1360.                   CURRENT_VIEW->arbchar_single,
  1361.                   CURRENT_VIEW->arbchar_multiple);
  1362.  if (loc == (-1))
  1363.     rc = RC_TARGET_NOT_FOUND;
  1364.  else
  1365.     rc = RC_OK;
  1366. /*---------------------------------------------------------------------*/
  1367. /* Copy contents of linked list into rec if we have used rec as a work */
  1368. /* area. NOT NOW WE DON'T, we are using trec instead of rec.            */
  1369. /*---------------------------------------------------------------------*/
  1370. #if 0
  1371.  if (use_rec)
  1372.     pre_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL);
  1373. #endif
  1374.  
  1375. #ifdef TRACE
  1376.  trace_return();
  1377. #endif
  1378.  return(rc);
  1379. }
  1380. /***********************************************************************/
  1381. #ifdef HAVE_PROTO
  1382. short find_rtarget_target(LINE *curr,TARGET *target,LINETYPE true_line,LINETYPE line_number,LINETYPE *num_lines)
  1383. #else
  1384. short find_rtarget_target(curr,target,true_line,line_number,num_lines)
  1385. LINE *curr;
  1386. TARGET *target;
  1387. LINETYPE true_line,line_number;
  1388. LINETYPE *num_lines;
  1389. #endif
  1390. /***********************************************************************/
  1391. {
  1392. /*-------------------------- external data ----------------------------*/
  1393. /*--------------------------- local data ------------------------------*/
  1394.  register short i=0;
  1395.  bool target_found=FALSE,status=FALSE;
  1396.  LINETYPE multiplier=0;
  1397.  short rc=RC_OK;
  1398. /*--------------------------- processing ------------------------------*/
  1399. #ifdef TRACE
  1400.  trace_function("target.c:  find_rtarget_target");
  1401. #endif
  1402. /*---------------------------------------------------------------------*/
  1403. /* If the line is not in scope and scope is respected, return FALSE.   */
  1404. /*---------------------------------------------------------------------*/
  1405.  if (!(in_scope(CURRENT_VIEW,curr))
  1406.  &&  !target->ignore_scope)
  1407.    {
  1408.     if (!CURRENT_VIEW->scope_all
  1409.     && !TOF(line_number)
  1410.     && !BOF(line_number))
  1411.       {
  1412. #ifdef TRACE
  1413.        trace_return();
  1414. #endif
  1415.        return(RC_TARGET_NOT_FOUND);
  1416.       }
  1417.    }
  1418.  if (line_number != true_line)
  1419.     *num_lines = *num_lines + 1L;
  1420.  for (i=0;i<target->num_targets-((target->spare == (-1)) ? 0 : 1);i++)
  1421.    {
  1422.     target_found = FALSE;
  1423.     multiplier = (target->rt[i].negative) ? -1L : 1L;
  1424.     switch(target->rt[i].target_type)
  1425.       {
  1426.        case TARGET_BLANK:
  1427.             if (true_line == line_number)
  1428.               {
  1429.                target_found = ((target->rt[i].not) ? TRUE : FALSE);
  1430.                break;
  1431.               }
  1432.             if (target->rt[0].negative)
  1433.               {
  1434.                if (curr->prev == NULL)
  1435.                   break;
  1436.               }
  1437.             else
  1438.               {
  1439.                if (curr->next == NULL)
  1440.                   break;
  1441.               }
  1442.             target_found = is_blank(curr);
  1443.             break;
  1444.        case TARGET_POINT:
  1445. #if 0
  1446.             if (true_line == line_number)
  1447.               {
  1448.                target_found = ((target->rt[i].not) ? TRUE : FALSE);
  1449.                break;
  1450.               }
  1451. #endif
  1452.             if (curr->name == (CHARTYPE *)NULL)
  1453.                break;
  1454.             if (strcmp((DEFCHAR *)curr->name,(DEFCHAR *)target->rt[i].string) == 0)
  1455.                target_found = TRUE;
  1456.             break;
  1457.        case TARGET_STRING:
  1458.             if (true_line == line_number)
  1459.               {
  1460.                target_found = ((target->rt[i].not) ? TRUE : FALSE);
  1461.                break;
  1462.               }
  1463.             if (target->rt[0].negative)
  1464.               {
  1465.                if (curr->prev == NULL)
  1466.                   break;
  1467.               }
  1468.             else
  1469.               {
  1470.                if (curr->next == NULL)
  1471.                   break;
  1472.               }
  1473.             rc = find_string_target(curr,&target->rt[i]);
  1474.             switch(rc)
  1475.               {
  1476.                case RC_OK:
  1477.                     target_found = TRUE;
  1478.                     break;
  1479.                case RC_TARGET_NOT_FOUND:
  1480.                     break;
  1481.                default:
  1482. #ifdef TRACE
  1483.                     trace_return();
  1484. #endif
  1485.                     return(rc);
  1486.                     break;
  1487.               }
  1488.             break;
  1489.        case TARGET_RELATIVE:
  1490.             if ((*num_lines * multiplier) == target->rt[i].numeric_target)
  1491.                   target_found = TRUE;
  1492.             if (target->rt[0].negative)
  1493.               {
  1494.                if (curr->prev == NULL)
  1495.                  {
  1496.                   target_found = TRUE;
  1497.                   break;
  1498.                  }
  1499.               }
  1500.             else
  1501.               {
  1502.                if (curr->next == NULL)
  1503.                  {
  1504.                   target_found = TRUE;
  1505.                   break;
  1506.                  }
  1507.               }
  1508.             break;
  1509.        case TARGET_ABSOLUTE:
  1510.             if (line_number == target->rt[i].numeric_target)
  1511.                   target_found = TRUE;
  1512.             break;
  1513.        default:
  1514.             break;
  1515.       }
  1516.     if (target->rt[i].not)
  1517.        target_found = (target_found) ? FALSE : TRUE;
  1518.     switch(target->rt[i].boolean)
  1519.       {
  1520.        case ' ':
  1521.             status = target_found;
  1522.             break;
  1523.        case '&':
  1524.             status &= target_found;
  1525.             break;
  1526.        case '|':
  1527.             status |= target_found;
  1528.             break;
  1529.       }
  1530.    }
  1531. #ifdef TRACE
  1532.  trace_return();
  1533. #endif
  1534.  return((status)?RC_OK:RC_TARGET_NOT_FOUND);
  1535. }
  1536. /***********************************************************************/
  1537. #ifdef HAVE_PROTO
  1538. bool find_rtarget_column_target(CHARTYPE *line,LENGTHTYPE len,TARGET *target,LENGTHTYPE true_column,LENGTHTYPE column_number,LINETYPE *num_columns)
  1539. #else
  1540. bool find_rtarget_column_target(line,len,target,true_column,column_number,num_columns)
  1541. CHARTYPE *line;
  1542. LENGTHTYPE len;
  1543. TARGET *target;
  1544. LENGTHTYPE true_column,column_number;
  1545. LINETYPE *num_columns;
  1546. #endif
  1547. /***********************************************************************/
  1548. {
  1549. /*-------------------------- external data ----------------------------*/
  1550. /*--------------------------- local data ------------------------------*/
  1551.  register short i=0;
  1552.  bool target_found=FALSE,status=FALSE;
  1553.  LINETYPE multiplier=0;
  1554. /*--------------------------- processing ------------------------------*/
  1555. #ifdef TRACE
  1556.  trace_function("target.c:  find_rtarget_column_target");
  1557. #endif
  1558.  if (column_number != true_column)
  1559.     *num_columns = *num_columns + 1L;
  1560.  for (i=0;i<target->num_targets-((target->spare == (-1)) ? 0 : 1);i++)
  1561.    {
  1562.     target_found = FALSE;
  1563.     multiplier = (target->rt[i].negative) ? -1L : 1L;
  1564.     switch(target->rt[i].target_type)
  1565.       {
  1566.        case TARGET_BLANK:
  1567.             if (true_column == column_number)
  1568.               {
  1569.                target_found = ((target->rt[i].not) ? TRUE : FALSE);
  1570.                break;
  1571.               }
  1572.             if (column_number < CURRENT_VIEW->zone_start
  1573.             ||  column_number > CURRENT_VIEW->zone_end)
  1574.                {
  1575.                 target_found = FALSE;
  1576.                 break;
  1577.                }
  1578.             if (column_number > len)
  1579.               {
  1580.                target_found = TRUE;
  1581.                break;
  1582.               }
  1583.             if (*(line+column_number-1) == ' ') /* should be blank word */
  1584.                target_found = TRUE;
  1585.             else
  1586.                target_found = FALSE;
  1587.             break;
  1588.        case TARGET_STRING:
  1589. #if NOTYET
  1590.             if (true_line == line_number)
  1591.               {
  1592.                target_found = ((target->rt[i].not) ? TRUE : FALSE);
  1593.                break;
  1594.               }
  1595.             if (target->rt[0].negative)
  1596.               {
  1597.                if (curr->prev == NULL)
  1598.                   break;
  1599.               }
  1600.             else
  1601.               {
  1602.                if (curr->next == NULL)
  1603.                   break;
  1604.               }
  1605.             if (find_string_target(curr,&target->rt[i]) == RC_OK)
  1606.                target_found = TRUE;
  1607. #endif
  1608.             break;
  1609.             break;
  1610.        case TARGET_ABSOLUTE:
  1611.             if (column_number == target->rt[i].numeric_target)
  1612.                   target_found = TRUE;
  1613.             break;
  1614.        case TARGET_RELATIVE:
  1615.             if ((*num_columns * multiplier) == target->rt[i].numeric_target)
  1616.                   target_found = TRUE;
  1617.             break;
  1618.        default:
  1619.             break;
  1620.       }
  1621.     if (target->rt[i].not)
  1622.        target_found = (target_found) ? FALSE : TRUE;
  1623.     switch(target->rt[i].boolean)
  1624.       {
  1625.        case ' ':
  1626.             status = target_found;
  1627.             break;
  1628.        case '&':
  1629.             status &= target_found;
  1630.             break;
  1631.        case '|':
  1632.             status |= target_found;
  1633.             break;
  1634.       }
  1635.    }
  1636. #ifdef TRACE
  1637.  trace_return();
  1638. #endif
  1639.  return(status);
  1640. }
  1641. /***********************************************************************/
  1642. #ifdef HAVE_PROTO
  1643. LINETYPE find_next_in_scope(VIEW_DETAILS *view,LINE *in_curr,LINETYPE line_number,short direction)
  1644. #else
  1645. LINETYPE find_next_in_scope(view,in_curr,line_number,direction)
  1646. VIEW_DETAILS *view;
  1647. LINE *in_curr;
  1648. LINETYPE line_number;
  1649. short direction;
  1650. #endif
  1651. /***********************************************************************/
  1652. {
  1653. /*-------------------------- external data ----------------------------*/
  1654. /*--------------------------- local data ------------------------------*/
  1655.  LINE *curr=in_curr;
  1656. /*--------------------------- processing ------------------------------*/
  1657. #ifdef TRACE
  1658.  trace_function("target.c:  find_next_in_scope");
  1659. #endif
  1660.  if (in_curr == NULL)
  1661.      curr = lll_find(CURRENT_FILE->first_line,CURRENT_FILE->last_line,line_number,CURRENT_FILE->number_lines);
  1662.  for (;;line_number+=(LINETYPE)direction)
  1663.    {
  1664.     if (in_scope(view,curr))
  1665.        break;
  1666.     if (direction == DIRECTION_FORWARD)
  1667.        curr = curr->next;
  1668.     else
  1669.        curr = curr->prev;
  1670.     if (curr == NULL)
  1671.        break;
  1672.    }
  1673. #ifdef TRACE
  1674.  trace_return();
  1675. #endif
  1676.  return(line_number);
  1677. }
  1678. /***********************************************************************/
  1679. #ifdef HAVE_PROTO
  1680. LINETYPE find_last_not_in_scope(VIEW_DETAILS *view,LINE *in_curr,LINETYPE line_number,short direction)
  1681. #else
  1682. LINETYPE find_last_not_in_scope(view,in_curr,line_number,direction)
  1683. VIEW_DETAILS *view;
  1684. LINE *in_curr;
  1685. LINETYPE line_number;
  1686. short direction;
  1687. #endif
  1688. /***********************************************************************/
  1689. {
  1690. /*-------------------------- external data ----------------------------*/
  1691. /*--------------------------- local data ------------------------------*/
  1692.  LINE *curr=in_curr;
  1693.  LINETYPE offset=0L;
  1694. /*--------------------------- processing ------------------------------*/
  1695. #ifdef TRACE
  1696.  trace_function("target.c:  find_last_not_in_scope");
  1697. #endif
  1698.  if (in_curr == NULL)
  1699.      curr = lll_find(CURRENT_FILE->first_line,CURRENT_FILE->last_line,line_number,CURRENT_FILE->number_lines);
  1700.  for (;;line_number+=(LINETYPE)direction)
  1701.    {
  1702.     if (in_scope(view,curr))
  1703.        break;
  1704.     if (direction == DIRECTION_FORWARD)
  1705.       {
  1706.        curr = curr->next;
  1707.        offset = (-1L);
  1708.       }
  1709.     else
  1710.       {
  1711.        curr = curr->prev;
  1712.        offset = 1L;
  1713.       }
  1714.     if (curr == NULL)
  1715.        break;
  1716.    }
  1717. #ifdef TRACE
  1718.  trace_return();
  1719. #endif
  1720.  return(line_number+offset);
  1721. }
  1722. /***********************************************************************/
  1723. #ifdef HAVE_PROTO
  1724. short validate_target(CHARTYPE *string,TARGET *target,short target_type,LINETYPE true_line,bool display_parse_error,bool allow_error_display)
  1725. #else
  1726. short validate_target(string,target,target_type,true_line,display_parse_error,allow_error_display)
  1727. CHARTYPE *string;
  1728. TARGET *target;
  1729. short target_type;
  1730. LINETYPE true_line;
  1731. bool display_parse_error,allow_error_display;
  1732. #endif
  1733. /***********************************************************************/
  1734. {
  1735. /*-------------------------- external data ----------------------------*/
  1736. /*--------------------------- local data ------------------------------*/
  1737.  short rc=RC_OK;
  1738. /*--------------------------- processing ------------------------------*/
  1739. #ifdef TRACE
  1740.  trace_function("target.c:  validate_target");
  1741. #endif
  1742.  rc = parse_target(string,true_line,target,target_type,display_parse_error,allow_error_display,FALSE);
  1743.  if (rc != RC_OK)
  1744.    {
  1745. #ifdef TRACE
  1746.     trace_return();
  1747. #endif
  1748.     return(rc);
  1749.    }
  1750.  rc = find_target(target,true_line,display_parse_error,allow_error_display);
  1751.  if (rc != RC_OK)
  1752.    {
  1753. #ifdef TRACE
  1754.     trace_return();
  1755. #endif
  1756.     return(RC_TARGET_NOT_FOUND);
  1757.    }
  1758. #ifdef TRACE
  1759.  trace_return();
  1760. #endif
  1761.  return(RC_OK);
  1762. }
  1763. /***********************************************************************/
  1764. #ifdef HAVE_PROTO
  1765. bool in_scope(VIEW_DETAILS *view,LINE *curr)
  1766. #else
  1767. bool in_scope(view,curr)
  1768. VIEW_DETAILS *view;
  1769. LINE *curr;
  1770. #endif
  1771. /***********************************************************************/
  1772. {
  1773. /*-------------------------- external data ----------------------------*/
  1774. /*--------------------------- local data ------------------------------*/
  1775.  bool rc=RC_OK;
  1776. /*--------------------------- processing ------------------------------*/
  1777. #ifdef TRACE
  1778.  trace_function("target.c:  in_scope");
  1779. #endif
  1780.  if (curr->select < view->display_low
  1781.  ||  curr->select > view->display_high)
  1782.     rc = FALSE;
  1783.  else
  1784.     rc = TRUE;
  1785. #ifdef TRACE
  1786.  trace_return();
  1787. #endif
  1788.  return(rc);
  1789. }
  1790. /***********************************************************************/
  1791. #ifdef HAVE_PROTO
  1792. void calculate_scroll_values(short *number_focus_rows,LINETYPE *new_focus_line,
  1793.                              LINETYPE *new_current_line,bool *limit_of_screen,
  1794.                              bool *limit_of_file,bool *leave_cursor,
  1795.                              short direction)
  1796. #else
  1797. void calculate_scroll_values(number_focus_rows,new_focus_line,new_current_line,
  1798.                              limit_of_screen,limit_of_file,leave_cursor,direction)
  1799. short *number_focus_rows;
  1800. LINETYPE *new_focus_line,*new_current_line;
  1801. bool *limit_of_screen,*limit_of_file,*leave_cursor;
  1802. short direction;
  1803. #endif
  1804. /***********************************************************************/
  1805. {
  1806. /*------------------------- external data -----------------------------*/
  1807. /*--------------------------- local data ------------------------------*/
  1808.  register short i=0;
  1809.  unsigned short y=0;
  1810. /*--------------------------- processing ------------------------------*/
  1811. #ifdef TRACE
  1812.  trace_function("target.c:  calculate_scroll_values");
  1813. #endif
  1814.  *limit_of_screen = *limit_of_file = FALSE;
  1815.  *number_focus_rows = 0;
  1816.  *new_focus_line = (-1L);
  1817.  y = CURRENT_SCREEN.rows[WINDOW_FILEAREA];
  1818.  switch(direction)
  1819.    {
  1820.     case DIRECTION_FORWARD:
  1821. /*---------------------------------------------------------------------*/
  1822. /* Determine the new focus line and the number of rows to adjust the   */
  1823. /* cursor position.                                                    */
  1824. /*---------------------------------------------------------------------*/
  1825.          for (i=0;i<CURRENT_SCREEN.rows[WINDOW_FILEAREA];i++)
  1826.            {
  1827.             if (CURRENT_SCREEN.sl[i].line_number == CURRENT_VIEW->focus_line)
  1828.               {
  1829.                y = i;
  1830.                continue;
  1831.               }
  1832.             if (CURRENT_SCREEN.sl[i].line_number != (-1L)
  1833.             && y != CURRENT_SCREEN.rows[WINDOW_FILEAREA])
  1834.               {
  1835.                *number_focus_rows = i-y;
  1836.                *new_focus_line = CURRENT_SCREEN.sl[i].line_number;
  1837.                break;
  1838.               }
  1839.            }
  1840. /*---------------------------------------------------------------------*/
  1841. /* If we have NOT set a new focus line (because we are on the bottom   */
  1842. /* of the screen) the new focus line is the next line in scope (if     */
  1843. /* SHADOW is OFF). If SHADOW is ON, the new focus line is determined by*/
  1844. /* the status of the current focus line.                               */
  1845. /*---------------------------------------------------------------------*/
  1846.          if (*new_focus_line == (-1L))
  1847.            {
  1848.             if (CURRENT_VIEW->shadow)
  1849.               {
  1850.                *new_focus_line = CURRENT_SCREEN.sl[y].line_number +
  1851.                                  ((CURRENT_SCREEN.sl[y].number_lines_excluded == 0) ?
  1852.                                  1L :
  1853.                                  (LINETYPE)CURRENT_SCREEN.sl[y].number_lines_excluded);
  1854.               }
  1855.             else
  1856.               {
  1857.                if (CURRENT_SCREEN.sl[y].current->next != NULL)
  1858.                   *new_focus_line = find_next_in_scope(CURRENT_VIEW,CURRENT_SCREEN.sl[y].current->next,
  1859.                                    CURRENT_SCREEN.sl[y].line_number+1L,direction);
  1860.               }
  1861.            }
  1862. /*---------------------------------------------------------------------*/
  1863. /* Determine the new current line and the number of rows to adjust the */
  1864. /* cursor position.                                                    */
  1865. /*---------------------------------------------------------------------*/
  1866.          *leave_cursor = TRUE;
  1867.          *new_current_line = (-1L);
  1868.          for (i=CURRENT_VIEW->current_row+1;i<CURRENT_SCREEN.rows[WINDOW_FILEAREA];i++)
  1869.            {
  1870.             if (CURRENT_SCREEN.sl[i].line_type == LINE_LINE
  1871.             ||  CURRENT_SCREEN.sl[i].line_type == LINE_TOF   /* MH12 */
  1872.             ||  CURRENT_SCREEN.sl[i].line_type == LINE_EOF)  /* MH12 */
  1873.               {
  1874.                *new_current_line = CURRENT_SCREEN.sl[i].line_number;
  1875.                break;
  1876.               }
  1877.             if (CURRENT_SCREEN.sl[i].line_type == LINE_SHADOW)
  1878.                *leave_cursor = FALSE;
  1879.            }
  1880. /*---------------------------------------------------------------------*/
  1881. /* If we have NOT set a new current line (only way this can happen is  */
  1882. /* if all lines after the current line are RESERVED, SCALE or TABLINE) */
  1883. /* and the cursor is on the current line) the new current line is the  */
  1884. /* next line in scope.                                                 */
  1885. /*---------------------------------------------------------------------*/
  1886.          if (*new_current_line == (-1L))
  1887.            {
  1888.             if (CURRENT_SCREEN.sl[y].current->next != NULL)
  1889.                *new_current_line = find_next_in_scope(CURRENT_VIEW,CURRENT_SCREEN.sl[y].current->next,
  1890.                                    CURRENT_SCREEN.sl[y].line_number+1L,direction);
  1891.            }
  1892. /*---------------------------------------------------------------------*/
  1893. /* Set flags for bottom_of_screen and bottom_of_file as appropriate.   */
  1894. /*---------------------------------------------------------------------*/
  1895.          if (*number_focus_rows == 0)
  1896.             *limit_of_screen = TRUE;
  1897. /*         if (CURRENT_SCREEN.sl[y].line_type == LINE_TOF_EOF MH12 */
  1898. /*         &&  CURRENT_SCREEN.sl[y].current->next == NULL) MH12 */
  1899.          if (CURRENT_SCREEN.sl[y].line_type == LINE_EOF)
  1900.             *limit_of_file = TRUE;
  1901.          break;
  1902.     case DIRECTION_BACKWARD:
  1903. /*---------------------------------------------------------------------*/
  1904. /* Determine the new focus line and the number of rows to adjust the   */
  1905. /* cursor position.                                                    */
  1906. /*---------------------------------------------------------------------*/
  1907.          for (i=CURRENT_SCREEN.rows[WINDOW_FILEAREA]-1;i>-1;i--)
  1908.            {
  1909.             if (CURRENT_SCREEN.sl[i].line_number == CURRENT_VIEW->focus_line)
  1910.               {
  1911.                y = i;
  1912.                continue;
  1913.               }
  1914.             if (CURRENT_SCREEN.sl[i].line_number != (-1L)
  1915.             && y != CURRENT_SCREEN.rows[WINDOW_FILEAREA])
  1916.               {
  1917.                *number_focus_rows = y-i;
  1918.                *new_focus_line = CURRENT_SCREEN.sl[i].line_number;
  1919.                break;
  1920.               }
  1921.            }
  1922. /*---------------------------------------------------------------------*/
  1923. /* If we have NOT set a new focus line (because we are on the top      */
  1924. /* of the screen) the new focus line is the prev line in scope (if     */
  1925. /* SHADOW is OFF). If SHADOW is ON, the new focus line is determined by*/
  1926. /* the status of the current focus line.                               */
  1927. /*---------------------------------------------------------------------*/
  1928.          if (*new_focus_line == (-1L))
  1929.            {
  1930.             if (CURRENT_VIEW->shadow)
  1931.               {
  1932.                if (CURRENT_SCREEN.sl[y].line_type == LINE_SHADOW)
  1933.                   *new_focus_line = CURRENT_SCREEN.sl[y].line_number - 1L;
  1934.                else
  1935.                  {
  1936.                   if (CURRENT_SCREEN.sl[y].current->prev != NULL)
  1937.                     {
  1938.                      *new_focus_line = find_next_in_scope(CURRENT_VIEW,CURRENT_SCREEN.sl[y].current->prev,
  1939.                                        CURRENT_SCREEN.sl[y].line_number-1L,direction);
  1940.                      if (*new_focus_line != CURRENT_SCREEN.sl[y].line_number-1L)
  1941.                         *new_focus_line = *new_focus_line + 1;
  1942.                     }
  1943.                  }
  1944.               }
  1945.             else
  1946.               {
  1947.                if (CURRENT_SCREEN.sl[y].current->prev != NULL)
  1948.                   *new_focus_line = find_next_in_scope(CURRENT_VIEW,CURRENT_SCREEN.sl[y].current->prev,
  1949.                                    CURRENT_SCREEN.sl[y].line_number-1L,direction);
  1950.               }
  1951.            }
  1952. /*---------------------------------------------------------------------*/
  1953. /* Determine the new current line and the number of rows to adjust the */
  1954. /* cursor position.                                                    */
  1955. /*---------------------------------------------------------------------*/
  1956.          *leave_cursor = TRUE;
  1957.          *new_current_line = (-1L);
  1958.          for (i=CURRENT_VIEW->current_row-1;i>-1;i--)
  1959.            {
  1960.             if (CURRENT_SCREEN.sl[i].line_type == LINE_LINE
  1961.             ||  CURRENT_SCREEN.sl[i].line_type == LINE_TOF /* MH12 */
  1962.             ||  CURRENT_SCREEN.sl[i].line_type == LINE_EOF) /* MH12 */
  1963.               {
  1964.                *new_current_line = CURRENT_SCREEN.sl[i].line_number;
  1965.                break;
  1966.               }
  1967.             if (CURRENT_SCREEN.sl[i].line_type == LINE_SHADOW)
  1968.                *leave_cursor = FALSE;
  1969.            }
  1970. /*---------------------------------------------------------------------*/
  1971. /* If we have NOT set a new current line (only way this can happen is  */
  1972. /* if all lines before the current line are RESERVED, SCALE or TABLINE)*/
  1973. /* and the cursor is on the current line) the new current line is the  */
  1974. /* previous line in scope.                                             */
  1975. /*---------------------------------------------------------------------*/
  1976.          if (*new_current_line == (-1L))
  1977.            {
  1978.             if (CURRENT_SCREEN.sl[y].current->prev != NULL)
  1979.                *new_current_line = find_next_in_scope(CURRENT_VIEW,CURRENT_SCREEN.sl[y].current->prev,
  1980.                                   CURRENT_SCREEN.sl[y].line_number-1L,direction);
  1981.            }
  1982. /*---------------------------------------------------------------------*/
  1983. /* Set flags for top_of_screen and top_of_file as appropriate.         */
  1984. /*---------------------------------------------------------------------*/
  1985.          if (*number_focus_rows == 0)
  1986.             *limit_of_screen = TRUE;
  1987. /*         if (CURRENT_SCREEN.sl[y].line_type == LINE_TOF_EOF MH12 */
  1988. /*         &&  CURRENT_SCREEN.sl[y].current->prev == NULL) MH12 */
  1989.          if (CURRENT_SCREEN.sl[y].line_type == LINE_TOF)
  1990.             *limit_of_file = TRUE;
  1991.          break;
  1992.    }
  1993. #ifdef TRACE
  1994.  trace_return();
  1995. #endif
  1996.  return;
  1997. }
  1998. /***********************************************************************/
  1999. #ifdef HAVE_PROTO
  2000. short find_last_focus_line(unsigned short *newrow)
  2001. #else
  2002. short find_last_focus_line(newrow)
  2003. unsigned short *newrow;
  2004. #endif
  2005. /***********************************************************************/
  2006. {
  2007. /*------------------------- external data -----------------------------*/
  2008. /*--------------------------- local data ------------------------------*/
  2009.  register short i=0;
  2010.  short row=(-1);
  2011.  short rc=RC_OK;
  2012. /*--------------------------- processing ------------------------------*/
  2013. #ifdef TRACE
  2014.  trace_function("target.c:  find_last_focus_line");
  2015. #endif
  2016.  for (i=CURRENT_SCREEN.rows[WINDOW_FILEAREA]-1;i>-1;i--)
  2017.    {
  2018.     if (CURRENT_SCREEN.sl[i].line_number != (-1L))
  2019.       {
  2020.        *newrow = row = i;
  2021.        break;
  2022.       }
  2023.    }
  2024.  if (row == (-1))
  2025.     rc = RC_INVALID_OPERAND;
  2026. #ifdef TRACE
  2027.  trace_return();
  2028. #endif
  2029.  return(rc);
  2030. }
  2031. /***********************************************************************/
  2032. #ifdef HAVE_PROTO
  2033. short find_first_focus_line(unsigned short *newrow)
  2034. #else
  2035. short find_first_focus_line(newrow)
  2036. unsigned short *newrow;
  2037. #endif
  2038. /***********************************************************************/
  2039. {
  2040. /*------------------------- external data -----------------------------*/
  2041. /*--------------------------- local data ------------------------------*/
  2042.  register short i=0;
  2043.  short row=(-1);
  2044.  short rc=RC_OK;
  2045. /*--------------------------- processing ------------------------------*/
  2046. #ifdef TRACE
  2047.  trace_function("target.c:  find_first_focus_line");
  2048. #endif
  2049.  for (i=0;i<CURRENT_SCREEN.rows[WINDOW_FILEAREA];i++)
  2050.    {
  2051.     if (CURRENT_SCREEN.sl[i].line_number != (-1L))
  2052.       {
  2053.        *newrow = row = i;
  2054.        break;
  2055.       }
  2056.    }
  2057.  if (row == (-1))
  2058.     rc = RC_INVALID_OPERAND;
  2059. #ifdef TRACE
  2060.  trace_return();
  2061. #endif
  2062.  return(rc);
  2063. }
  2064. /***********************************************************************/
  2065. #ifdef HAVE_PROTO
  2066. CHARTYPE find_unique_char(CHARTYPE *str)
  2067. #else
  2068. CHARTYPE find_unique_char(str)
  2069. CHARTYPE *str;
  2070. #endif
  2071. /***********************************************************************/
  2072. {
  2073. /*------------------------- external data -----------------------------*/
  2074. /*--------------------------- local data ------------------------------*/
  2075.  register short i=0;
  2076. /*--------------------------- processing ------------------------------*/
  2077. #ifdef TRACE
  2078.  trace_function("target.c:  find_unique_char");
  2079. #endif
  2080.  for (i=254;i>0;i--)
  2081.    {
  2082.     if (strzeq(str,(CHARTYPE)i) == (-1))
  2083.       {
  2084. #ifdef TRACE
  2085.        trace_return();
  2086. #endif
  2087.        return((CHARTYPE)i);
  2088.       }
  2089.    }
  2090. #ifdef TRACE
  2091.  trace_return();
  2092. #endif
  2093.  return(0);
  2094. }
  2095.