home *** CD-ROM | disk | FTP | other *** search
- /******************* start of original comments ********************/
- /*
- * Written by Douglas Thomson (1989/1990)
- *
- * This source code is released into the public domain.
- */
-
- /*
- * Name: dte - Doug's Text Editor program - find/replace module
- * Purpose: This file contains the functions relating to finding text
- * and replacing text.
- * It also contains the code for moving the cursor to various
- * other positions in the file.
- * File: findrep.c
- * Author: Douglas Thomson
- * System: this file is intended to be system-independent
- * Date: October 1, 1989
- */
- /********************* end of original comments ********************/
-
- /*
- * The search and replace routines have been EXTENSIVELY rewritten. The
- * "brute force" search algorithm has been replaced by the Boyer-Moore
- * string search algorithm. This search algorithm really speeds up search
- * and replace operations.
- *
- * If I am not mistook, seems like Boyer developed the array and Moore
- * developed the search. For those interested, the algorithm is published in:
- *
- * R. S. Boyer and J. S. Moore, "A fast string searching algorithm."
- * _Communications of the ACM_ 20 (No. 10): 762-772, 1977.
- *
- * I am not very fond of the Wordstar/TURBO type search and replace prompting.
- * Once the search pattern has been defined, one only needs to press a key
- * to search forwards or backwards. The forward or backward search key may
- * be pressed at any time in any file once the pattern has been entered. Also,
- * the search case may be toggled at any time in any file once the pattern has
- * has been entered.
- *
- * New editor name: tde, the Thomson-Davis Editor.
- * Author: Frank Davis
- * Date: June 5, 1991
- *
- * This modification of Douglas Thomson's code is released into the
- * public domain, Frank Davis. You may distribute it freely.
- */
-
- #include "tdestr.h"
- #include "common.h"
- #include "tdefunc.h"
- #include "define.h"
-
- /*
- * Name: get_replacement_flags
- * Purpose: To input find and replace flags.
- * Date: June 5, 1991
- * Passed: line: prompt line
- * Returns: OK if flags were entered, ERROR if user wanted to abort
- */
- int get_replacement_flags( int line )
- {
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- char *find_opt = "Options (P)rompt before replace (N)o prompt: ";
- register int c;
- int rc, func;
-
- c = strlen( find_opt );
- save_screen_line( 0, line, line_buff );
- s_output( find_opt, line, 0, g_display.message_color );
- eol_clear( c, line, g_display.text_color );
- c += 2;
- xygoto( c, line );
- c = getkey( );
- func = getfunc( c );
- while (c != 'P' && c != 'p' && c != 'N' && c != 'n' && c != RTURN &&
- c != ESC && func != AbortCommand) {
- c = getkey( );
- func = getfunc( c );
- }
- restore_screen_line( 0, line, line_buff );
- switch (c) {
- case 'P' :
- case 'p' :
- case RTURN :
- g_status.replace_flag = PROMPT;
- rc = OK;
- break;
- case 'N' :
- case 'n' :
- g_status.replace_flag = NOPROMPT;
- rc = OK;
- break;
- default :
- rc = ERROR;
- }
- bm.search_defined = rc;
- return( rc );
- }
-
-
- /*
- * Name: ask_replace
- * Purpose: Ask user if he want to (r)place, (s)kip, or (e)xit.
- * Date: June 5, 1991
- * Returns: TRUE if user wants to replace, ERROR otherwise.
- * Passed: window: information allowing access to current window etc
- * finished: TRUE if user pressed ESC or (e)xit.
- */
- int ask_replace( windows *window, int *finished )
- {
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- char *ask_opt = "(R)eplace (S)kip (E)xit";
- register int c;
- int rc, prompt_line, func;
-
- prompt_line = window->cline - 1;
- c = 39 - (strlen( ask_opt ) >> 1);
- save_screen_line( 0, prompt_line, line_buff );
- s_output( ask_opt, prompt_line, c, g_display.message_color );
- c = getkey( );
- func = getfunc( c );
- while (c != 'R' && c != 'r' && c != 'S' && c != 's' && c != 'E' && c != 'e'
- && c != ESC && func != AbortCommand) {
- c = getkey( );
- func = getfunc( c );
- }
- restore_screen_line( 0, prompt_line, line_buff );
- switch (c) {
- case 'R' :
- case 'r' :
- rc = OK;
- break;
- case 'E' :
- case 'e' :
- *finished = TRUE;
- break;
- case 'S' :
- case 's' :
- rc = ERROR;
- break;
- default :
- *finished = TRUE;
- rc = ERROR;
- break;
- }
- return( rc );
- }
-
-
- /*
- * Name: do_replace
- * Purpose: To replace text once match has been found.
- * Date: June 5, 1991
- * Passed: window: information allowing access to current window etc
- * start: location of start of matched text
- * direction: direction of search
- */
- void do_replace( windows *window, text_ptr start, int direction )
- {
- int old_len; /* length of original text */
- int new_len; /* length of replacement text */
- int net_change;
- text_ptr source; /* source of block move */
- text_ptr dest; /* destination of block move */
- long number; /* number of characters moved */
-
- old_len = strlen( g_status.pattern );
- new_len = strlen( g_status.subst );
-
- /*
- * move the text to either make room for the extra replacement text
- * or to close up the gap left
- */
- start = cpf( start );
- source = start + old_len;
- dest = start + new_len;
- number = ptoul( g_status.end_mem ) - ptoul( source );
- hw_move( dest, source, number );
-
- /*
- * insert the replacement text
- */
- for (dest=start, source=g_status.subst; *source;)
- *dest++ = *source++;
-
- net_change = new_len - old_len;
- adjust_start_end( window->file_info, net_change );
- if (direction == FORWARD)
- window->rcol += net_change;
- addorsub_all_cursors( window, net_change );
- g_status.end_mem = addltop( (long)net_change, g_status.end_mem );
- show_avail_mem( );
- }
-
-
- /*
- * Name: find_string
- * Purpose: To set up and perform a find operation.
- * Date: June 5, 1991
- * Passed: window: information allowing access to current window etc
- * direction: find FORWARD or BACKWARD - determined by pressed key
- * new_string: search for new string to be entered by user
- * Notes: If user presses search string key then keep boyer-moore stuff.
- * To find the next occurrence either forwards or backwards all the
- * user has to do is press the "RepeatFindForward" or
- * "RepeatFindBackward" key at any time.
- */
- void find_string( windows *window )
- {
- int direction;
- int new_string;
- char pattern[MAX_COLS]; /* text to be found */
- int prompt_line;
- text_ptr pattern_location;
- char *snf = "string not found";
-
- switch (g_status.command) {
- case FindForward :
- direction = FORWARD;
- new_string = TRUE;
- break;
- case FindBackward :
- direction = BACKWARD;
- new_string = TRUE;
- break;
- case RepeatFindForward :
- direction = FORWARD;
- new_string = FALSE;
- break;
- case RepeatFindBackward :
- direction = BACKWARD;
- new_string = FALSE;
- break;
- }
- un_copy_line( window->cursor, window, TRUE );
- prompt_line = window->bottom_line;
- /*
- * get search text, using previous as default
- */
- if (new_string == TRUE) {
- strcpy( pattern, bm.pattern );
- if (get_name( "String to find: ", prompt_line, pattern,
- g_display.message_color ) != OK)
- return;
- bm.search_defined = OK;
- strcpy( bm.pattern, pattern );
-
- build_boyer_array( );
- }
-
- if (bm.search_defined == OK) {
- if (direction == FORWARD) {
- if ((pattern_location = forward_boyer_moore_search( window )) != NULL)
- find_adjust( window, pattern_location );
- else
- error( WARNING, prompt_line, snf );
- } else {
- if ((pattern_location = backward_boyer_moore_search( window )) != NULL)
- find_adjust( window, pattern_location );
- else
- error( WARNING, prompt_line, snf );
- }
- } else
- error( WARNING, prompt_line, "find pattern not defined" );
- }
-
-
- /*
- * Name: build_boyer_array
- * Purpose: To set up the boyer array for forward and backward searches.
- * Date: June 5, 1991
- * Notes: Set up one array for forward searches and another for backward
- * searches. If user decides to ignore case then fill in array
- * with reverse case characters so both upper and lower case
- * characters are defined.
- */
- void build_boyer_array( void )
- {
- int pl;
- register int i;
- register unsigned char *p;
-
- /*
- * set up for forward search
- */
- i = pl = bm.pattern_length = strlen( bm.pattern );
-
- /*
- * set skip index of all characters to length of string
- */
- memset( bm.skip_forward, i, 256 );
- i--;
-
- /*
- * for each character in string, set the skip index
- */
- for (p=bm.pattern; i>=0; i--, p++)
- bm.skip_forward[*p] = i;
- if (bm.search_case == IGNORE) {
- i = pl - 1;
- for (p=bm.pattern; i>=0; i--, p++) {
- if (*p >= 'A' && *p <= 'Z')
- bm.skip_forward[*p+32] = i;
- else if (*p >= 'a' && *p <= 'z')
- bm.skip_forward[*p-32] = i;
- }
- }
-
- /*
- * set up for backward search
- */
- i = -pl;
- memset( bm.skip_backward, i, 256 );
- i++;
- for (p=bm.pattern+pl-1; i<=0; i++, p--)
- bm.skip_backward[*p] = i;
- if (bm.search_case == IGNORE) {
- i = -pl + 1;
- for (p=bm.pattern+pl-1; i<=0; i++, p--) {
- if (*p >= 'A' && *p <= 'Z')
- bm.skip_backward[*p+32] = i;
- else if (*p >= 'a' && *p <= 'z')
- bm.skip_backward[*p-32] = i;
- }
- }
- }
-
-
- /*
- * Name: forward_boyer_moore_search
- * Purpose: search forward for pattern using boyer array
- * Passed: window: information allowing access to current window etc
- * Returns: position in file if found else return NULL
- * Date: June 5, 1991
- * Notes: Start searching from cursor position to end of file. If we hit
- * end of file without a match, start searching from the beginning
- * of file to cursor position. (do wrapped searches)
- */
- text_ptr forward_boyer_moore_search( windows *window )
- {
- register int i;
- int pl;
- text_ptr p, q, s, search_start;
- long search_length;
-
- /*
- * if cursor is beyond end of line then start at end of line
- */
- un_copy_line( window->cursor, window, TRUE );
- window->cursor = cpf( window->cursor );
- search_start = window->cursor;
- i = window->rcol + 1;
- pl = linelen( window->cursor );
- if (i > pl)
- i = pl;
-
- /*
- * make start of search 1 character greater than current position so
- * we don't repeatedly find the pattern at current position.
- */
- search_start += i;
- s = search_start;
- pl = bm.pattern_length;
- i = pl - 1;
-
- /*
- * find out how many character to search. do standard Boyer-Moore search
- */
- search_length = (ptoul( window->file_info->end_text ) - 1) - ptoul( s );
- p = bm.pattern;
- for (search_length -= i; search_length >= 0; search_length -= i) {
- s = s + i;
- i = bm.skip_forward[(unsigned char)*s];
- if (i == 0) {
- q = addltop( 1 - pl, s );
- q = cpf( q );
- if (bm.search_case == MATCH)
- i = _fstrncmp( q, p, pl );
- else
- i = _fstrnicmp( q, p, pl );
- if (i == 0)
- return( q );
- i = 1;
- }
- s = cpf( s );
- }
-
- /*
- * haven't found pattern yet - now search from beginning of file
- */
- s_output( "wrapped...", g_display.mode_line, 63, g_display.diag_color );
- s = cpf( window->file_info->start_text );
- search_length = ptoul( search_start ) + 1 - ptoul( s );
- i = pl - 1;
- for (search_length -= i; search_length >= 0; search_length -= i) {
- s = s + i;
- i = bm.skip_forward[(unsigned char)*s];
- if (i == 0) {
- q = addltop( 1 - pl, s );
- q = cpf( q );
- if (bm.search_case == MATCH)
- i = _fstrncmp( q, p, pl );
- else
- i = _fstrnicmp( q, p, pl );
- if (i == 0)
- return( q );
- i = 1;
- }
- s = cpf( s );
- }
- /*
- * pattern not found - return NULL pointer
- */
- return( NULL );
- }
-
-
- /*
- * Name: backward_boyer_moore_search
- * Purpose: search backward for pattern using boyer array
- * Passed: window: information allowing access to current window etc
- * Returns: position in file if found else return NULL
- * Date: June 5, 1991
- * Notes: Start searching from cursor position to beginning of file. If we
- * hit beginning end of file without a match, start searching from the
- * end of file to cursor position. (do wrapped searches)
- */
- text_ptr backward_boyer_moore_search( windows *window )
- {
- register int i;
- int pl;
- text_ptr p, s, search_start;
- long search_length;
-
- un_copy_line( window->cursor, window, TRUE );
- i = window->rcol - 1;
- i += bm.pattern_length - 1;
- pl = linelen( window->cursor );
- if (i > pl)
- i = pl;
- search_start = addltop( i, window->cursor );
- s = cpb( search_start );
- pl = bm.pattern_length;
- i = -pl + 1;
- search_length = ptoul( search_start ) -
- ptoul( window->file_info->start_text );
- p = bm.pattern;
- for (search_length += i; search_length >= 0; search_length += i) {
- s = s + i;
- i = bm.skip_backward[(unsigned char)*s];
- if (i == 0) {
- if (bm.search_case == MATCH)
- i = _fstrncmp( s, p, pl );
- else
- i = _fstrnicmp( s, p, pl );
- if (i == 0)
- return( s );
- i = -1;
- }
- s = cpb( s );
- }
-
- /*
- * haven't found pattern yet - now search from end of file
- */
- s_output( "wrapped...", g_display.mode_line, 63, g_display.diag_color );
- s = addltop( -1, window->file_info->end_text );
- s = cpb( s );
- i = -pl + 1;
- search_length = ptoul( s ) - ptoul( search_start );
- for (search_length += i; search_length >= 0; search_length += i) {
- s = s + i;
- i = bm.skip_backward[(unsigned char)*s];
- if (i == 0) {
- if (bm.search_case == MATCH)
- i = _fstrncmp( s, p, pl );
- else
- i = _fstrnicmp( s, p, pl );
- if (i == 0)
- return( s );
- i = -1;
- }
- s = cpb( s );
- }
-
- /*
- * pattern not found - return NULL pointer
- */
- return( NULL );
- }
-
-
- /*
- * Name: find_adjust
- * Purpose: place cursor on screen given a position in file - default cline
- * Passed: window: information allowing access to current window etc
- * found: position anywhere in file
- * Date: June 5, 1991
- * Notes: found could be anywhere in file. Find the start of line that
- * found is on. Determine if start of line is behind or ahead of
- * current line. Once that is done, it is easy to determine if found
- * is on screen. Lastly, current cursor position becomes start of
- * found line - reposition and display.
- */
- void find_adjust( windows *window, text_ptr found )
- {
- int rcol;
- long pattern_line, rline, test_line;
- text_ptr p, q;
- file_infos *file;
-
- file = window->file_info;
- /*
- * find start of line found is on.
- */
- found = cpb( found );
- if (*(found - 1) != '\n' && *(found - 1) != CONTROL_Z)
- p = find_prev( found );
- else
- p = found;
-
- /*
- * find real column found is on.
- */
- rcol = (int)(ptoul( found ) - ptoul( p ));
- rline = pattern_line = window->rline;
- q = window->cursor = cpf( window->cursor );
-
- /*
- * if p, start of found line, is greater than current line, see if
- * p is between current line and bottom line on screen.
- */
- if (ptoul( q ) < ptoul( p )) {
- while (ptoul( q ) != ptoul( p )) {
- q = find_next( q );
- ++pattern_line;
- }
- test_line = pattern_line - rline;
- if ((long)window->cline + test_line <= (long)window->bottom_line)
- window->cline += test_line;
- else
- file->dirty = LOCAL;
-
- /*
- * if p, start of found line, is less than current line, see if
- * p is between current line and top line on screen.
- */
- } else if (ptoul( q ) > ptoul( p )) {
- q = cpb( q );
- while (ptoul( q ) != ptoul( p )) {
- q = find_prev( q );
- --pattern_line;
- }
- test_line = rline - pattern_line;
- if ((long)window->cline - test_line > (long)(window->top_line-1))
- window->cline -= test_line;
- else
- file->dirty = LOCAL;
- if (pattern_line < (long)(window->cline - (window->top_line-1)))
- window->cline = (int)pattern_line + window->top_line - 1;
- }
-
- /*
- * cursor line becomes found line. check if column is on screen.
- */
- window->cursor = p;
- window->rline = pattern_line;
- if (file->dirty == LOCAL && (window->cline == window->bottom_line ||
- window->cline == window->top_line)) {
- g_status.command = CenterLine;
- center_window( window );
- }
- check_virtual_col( window, rcol, rcol );
- }
-
-
- /*
- * Name: replace_string
- * Purpose: To set up and perform a replace operation.
- * Date: June 5, 1991
- * Passed: window: information allowing access to current window etc
- * direction: replace forward or backward in file
- */
- void replace_string( windows *window )
- {
- int direction;
- char pattern[MAX_COLS]; /* the old and replacement text */
- int prompt_line;
- int net_change;
- int sub_len;
- int file_changed;
- int finished;
- int rc;
- text_ptr pattern_location;
- text_ptr replace_start;
- unsigned long rs, pl;
- windows wp;
- int color;
- char *snf = "string not found";
-
- if (g_status.command == ReplaceForward)
- direction = FORWARD;
- else
- direction = BACKWARD;
- un_copy_line( window->cursor, window, TRUE );
- prompt_line = window->bottom_line;
- color = g_display.message_color;
- /*
- * get the old text, using the previous as the default
- */
- strcpy( pattern, g_status.pattern );
- if (get_name( "String to find: ", prompt_line, pattern, color ) != OK)
- return;
- strcpy( g_status.pattern, pattern );
-
- /*
- * get the replacement text, using the previous as the default
- */
- strcpy( pattern, g_status.subst );
- if (get_name( "Replacement: ", prompt_line, pattern, color ) != OK)
- return;
- strcpy( g_status.subst, pattern );
- sub_len = strlen( pattern );
- strcpy( bm.pattern, g_status.pattern );
- net_change = sub_len - strlen( g_status.pattern );
-
- /*
- * get the replace flags
- */
- if (get_replacement_flags( prompt_line ) != OK)
- return;
-
- build_boyer_array( );
- dup_window_info( &wp, window );
-
- finished = FALSE;
- file_changed = FALSE;
- if (direction == FORWARD) {
- if ((replace_start = forward_boyer_moore_search( &wp )) != NULL) {
- rs = ptoul( replace_start );
- replace_and_display( &wp, replace_start, &finished, &file_changed,
- direction );
- } else {
- error( WARNING, prompt_line, snf );
- finished = TRUE;
- }
- while (finished == FALSE) {
- if ((pattern_location = forward_boyer_moore_search( &wp )) != NULL) {
- pl = ptoul( pattern_location );
- if (rs == pl)
- finished = TRUE;
- else {
- rc = replace_and_display( &wp, pattern_location, &finished,
- &file_changed, direction );
- if (rc == OK && rs > pl)
- rs += net_change;
- }
- } else {
- error( WARNING, prompt_line, snf );
- finished = TRUE;
- }
- }
- } else {
- if ((replace_start = backward_boyer_moore_search( &wp )) != NULL) {
- rs = ptoul( replace_start );
- replace_and_display( &wp, replace_start, &finished, &file_changed,
- direction );
- } else {
- error( WARNING, prompt_line, snf );
- finished = TRUE;
- }
- while (finished == FALSE) {
- if ((pattern_location = backward_boyer_moore_search( &wp )) != NULL) {
- pl = ptoul( pattern_location );
- if (rs == pl || (pl > rs && rs > pl - sub_len))
- finished = TRUE;
- else {
- rc = replace_and_display( &wp, pattern_location, &finished,
- &file_changed, direction );
- if (rc == OK && rs > pl)
- rs += net_change;
- }
- } else {
- finished = TRUE;
- error( WARNING, prompt_line, snf );
- }
- }
- }
- dup_window_info( window, &wp );
- if (file_changed)
- window->file_info->modified = TRUE;
- }
-
-
- /*
- * Name: replace_and_display
- * Purpose: To make room for replacement string
- * Date: June 5, 1991
- * Passed: window: information allowing access to current window etc
- * pattern_location: pointer to position of pattern in file
- * finished: boolean - stop replacing on this occurrence
- * modified: boolean - user may decide to skip this replacement
- * direction: direction of search
- * Notes: Show user where pattern_location is on screen if needed.
- * Replace and display if needed.
- */
- int replace_and_display( windows *window, text_ptr pattern_location,
- int *finished, int *modified, int direction )
- {
- int ask_user;
- register int rc;
- file_infos *file;
-
- file = window->file_info;
- ask_user = g_status.replace_flag;
- find_adjust( window, pattern_location );
- xygoto( window->ccol, window->cline );
- if (file->dirty) {
- display_current_window( window );
- file->dirty = FALSE;
- }
- rc = OK;
- if (ask_user == PROMPT) {
- show_line_col( window );
- rc = ask_replace( window, finished );
- }
- if (rc == OK) {
- do_replace( window, pattern_location, direction );
- *modified = TRUE;
- file->dirty = GLOBAL;
- show_changed_line( window );
- file->dirty = FALSE;
- }
- return( rc );
- }
-
-
- /*
- * Name: goto_top_file
- * Purpose: To move the cursor to the top of the file.
- * Date: June 5, 1991
- * Passed: window: information allowing access to current window etc
- */
- void goto_top_file( windows *window )
- {
- text_ptr next; /* successive lines above the cursor */
- int i;
-
- un_copy_line( window->cursor, window, TRUE );
- if (window->rline != window->cline - (window->top_line-1)) {
- next = cpf( window->file_info->start_text );
- for (i=window->cline; i>window->top_line; i--)
- next = find_next( next );
- window->cursor = next;
- window->rline = window->cline - (window->top_line-1);
- display_current_window( window );
- }
- }
-
- /*
- * Name: goto_end_file
- * Purpose: To move the cursor to the end of the file.
- * Date: June 5, 1991
- * Passed: window: information allowing access to current window etc
- */
- void goto_end_file( windows *window )
- {
- text_ptr prev;
- int i;
- register int j;
- file_infos *file;
-
- un_copy_line( window->cursor, window, TRUE );
- file = window->file_info;
- if (file->length > window->rline + window->bottom_line - window->cline) {
- prev = cpb( window->file_info->end_text ) - 1;
- for (j=0,i=window->bottom_line; i>window->cline; i--, j++)
- prev = find_prev( prev );
- window->cursor = prev;
- window->rline = file->length - j + 1;
- display_current_window( window );
- }
- }
-
- /*
- * Name: scan_forward
- * Purpose: To find the corresponding occurrence of target, ignoring
- * embedded pairs of opp and target, searching forwards.
- * Date: June 5, 1991
- * Passed: start: position of character to be paired
- * opp: the opposite to target, if any
- * target: the string to be found
- * Returns: the location of the corresponding target in the text buffer
- * Notes: Every 8,000 characters, check pointer forward.
- */
- text_ptr scan_forward( text_ptr start, char opp, char target )
- {
- text_ptr orig;
- int count = 0; /* number of unmatched opposites found */
- register int check = 0;
- char c;
-
- orig = start = cpf( start );
- while ((c = *++start) && (c != CONTROL_Z)) {
- check++;
- if (opp == c)
- count++;
- else if (target == c) {
- if (count == 0)
- break;
- --count;
- }
- if (check > 8000) {
- start = cpf( start );
- check = 0;
- }
- }
- if (c == CONTROL_Z)
- start = orig;
- return( start );
- }
-
- /*
- * Name: scan_backward
- * Purpose: To find the corresponding occurrence of target, ignoring
- * embedded pairs of opp and target, searching backwards.
- * Date: June 5, 1991
- * Passed: start: position of character to be paired
- * opp: the opposite to target, if any
- * target: the string to be found
- * Returns: the location of the corresponding target in the text buffer
- */
- text_ptr scan_backward( text_ptr start, char opp, char target )
- {
- text_ptr orig;
- int count = 0; /* number of unmatched opposites found */
- register int check = 0;
- char c;
-
- orig = start = cpb( start );
- while ((c = *--start) && (c != CONTROL_Z)) {
- check++;
- if (opp == c)
- count++;
- else if (target == c) {
- if (count == 0)
- break;
- --count;
- }
- if (check > 8000) {
- start = cpb( start );
- check = 0;
- }
- }
- if (c == CONTROL_Z)
- start = orig;
- return( start );
- }
-
- /*
- * Name: match_pair
- * Purpose: To find the corresponding pair to the character under the
- * cursor.
- * Date: June 5, 1991
- * Passed: window: information allowing access to current window etc
- * Notes: Searching is very simple-minded, and does not cope with things
- * like brackets embedded within quoted strings.
- */
- void match_pair( windows *window )
- {
- text_ptr orig; /* cursor location in text */
- int c;
-
- un_copy_line( window->cursor, window, TRUE );
- /*
- * make sure the character under the cursor is one that has a
- * matched pair
- */
- if (window->rcol >= linelen( window->cursor ))
- return;
- window->cursor = cpf( window->cursor );
- orig = window->cursor + window->rcol;
- c = *orig;
- if (strchr( "[]{}()", c ) == NULL)
- return;
-
- /*
- * find the matching pair
- */
- switch (c) {
- case '[':
- orig = scan_forward( orig, '[', ']' );
- break;
- case '(':
- orig = scan_forward( orig, '(', ')' );
- break;
- case '{':
- orig = scan_forward( orig, '{', '}' );
- break;
- case ']':
- orig = scan_backward( orig, ']', '[' );
- break;
- case ')':
- orig = scan_backward( orig, ')', '(' );
- break;
- case '}':
- orig = scan_backward( orig, '}', '{' );
- break;
- }
-
- /*
- * now show the user what we have found
- */
- find_adjust( window, orig );
- }
-
- /*
- * Name: goto_line
- * Purpose: To move the cursor to a particular line in the file
- * Date: June 5, 1991
- * Passed: window: information allowing access to current window etc
- */
- void goto_line( windows *window )
- {
- long number; /* line number selected */
- long i; /* line counter */
- char num_str[MAX_COLS]; /* line number as string */
- text_ptr p; /* used to scan through file counting lines */
- int prompt_line;
-
- un_copy_line( window->cursor, window, TRUE );
- prompt_line = window->bottom_line;
- /*
- * find out where we are going
- */
- num_str[0] = '\0';
- if (get_name( "Line number: ", prompt_line, num_str,
- g_display.message_color ) != OK)
- return;
- number = atol( num_str );
-
- if (number > 0 && number <= window->file_info->length) {
- p = window->cursor;
- i = window->rline;
- if (number < window->rline) {
- p = cpb( p );
- for (; i>number; i--)
- p = find_prev( p );
- } else {
- cpf( p );
- for (; i<number; i++)
- p = find_next( p );
- }
- find_adjust( window, p );
- } else {
- strcat( num_str, "must be in the range 1 - " );
- ltoa( window->file_info->length, num_str+25, 10 );
- error( WARNING, prompt_line, num_str );
- }
- }