! ABEL_UTIL.TPU ! ! Table of Contents as of 27-Mar-1988 ! ! Procedure name Page Description ! -------------- ---- ----------- ! ! eve$what_line 1 Internal "what line am I on" ! eve$compress_whitespace 2 Delete whitespace around current char ! eve$split_line 3 Hook for auto-indent function ! abl$abs 5 Perform absolute-value function ! abl$mod 5 Perform modulus function ! abl$notab_line 6 Return current line without tabs ! abl$extract_integer 7 Extract signed integer from string ! abl$ascii 8 Convert #'s to string of ascii ! abl$undelimit 9 Undelimits a delimited string ! abl$notab_offset 10 Offset if tabs were spaces ! abl$virtual_mark 11 Mark without a mark ! abl$virtual_position 11 Go to mark that wasn't ! Page 1 procedure eve$what_line ! Internal "what line am I on" ! Returns the line number of the current line in the current buffer. ! ! Source: ! Eveplus local high_line, low_line, start_of_buffer, this_line, this_position, total_lines; this_position := mark (none); start_of_buffer := beginning_of (current_buffer); total_lines := get_info (current_buffer, "record_count") + 1; high_line := total_lines; if this_position = end_of (current_buffer) then low_line := total_lines; else low_line := 1; endif; ! Binary search loop exitif high_line - low_line <= 1; this_line := low_line + ((high_line - low_line) / 2); position (start_of_buffer); move_vertical (this_line - 1); if mark (none) > this_position then high_line := this_line; else low_line := this_line; if mark (none) = this_position then high_line := this_line; endif; endif; endloop; position (this_position); return low_line; endprocedure ! Page 2 procedure eve$compress_whitespace ! Delete whitespace around current char ! Delete all whitespace surrounding the current character, except for ! the first whitespace character (delete that too if at start of line). ! Position cursor at beginning of next word. No-op if current character ! is not whitespace. Trim spaces if at end of line. ! ! Don't do anything if in overstrike mode. ! ! Source: ! Eve if get_info(current_buffer,"mode")=overstrike then return endif; if current_character = eve$kt_null then eve$trim_line; return; endif; if index (eve$x_whitespace, current_character) = 0 then return; endif; loop exitif current_offset = 0; move_horizontal (-1); if index (eve$x_whitespace, current_character) = 0 then move_horizontal(1); erase_character(1); copy_text(" "); ! leave space (not first whitespace) if not at start of line exitif 1; endif; endloop; if index (eve$x_whitespace, current_character) <> 0 then erase (search (eve$pattern_whitespace, forward)); endif; endprocedure; ! Page 3 procedure eve$split_line ! Hook for auto-indent function ! Split line at current cursor location, perform autoindent if on. ! ! Globals: ! abl$autoindent boolean if 1 then perform autoindent ! ! Source: ! Eva2 local starting_offset, ! The offset where we started previous_whitespace, ! Whitespace from previous line starting_position; ! User's starting position on_error endon_error ! ! Only copy whitespace up to our current cursor position ! starting_offset := current_offset; if (abl$autoindent) and (starting_offset<>0) then starting_position:=mark(none); move_horizontal(-current_offset); previous_whitespace := search(anchor & span(eve$x_whitespace),forward); position(starting_position); split_line; if previous_whitespace <> 0 then copy_text(substr(previous_whitespace,1,starting_offset)) endif; else split_line; endif; endprocedure ! Page 4 ! General-purpose Abel routines ! Results of calling these routines may be passed back to the caller in one ! of two ways. To properly use these routines, you must determine which ! method the routine you want is using. Note: %'s and $'s are used to ! prefix parameters in these descriptions; the % refers to an integer ! parameter while the $ refers to a string. ! The most general purpose method is parameter passing with a return-status. ! Using this method, parameters from and to the caller are passed in the ! parameter list of the call, and the routine itself is set to success (1) or ! failure (0). An example of this is the abl$mod(%1,%2,%3) = S/F call; the ! first two parameters (%1 and %2) are the numerator and denominator for ! the mod function, the last parameter (%3) is the result of the mod, and S/F ! (success/failure) is the result of the call. A typical use might be: ! if not abl$mod(numerator,denominator,answer) then ...error routine... ! The other method is result passing. This method implies that there is only ! one parameter to return to the caller, and the called routine cannot ! error; the result of the call is the requested parameter. An example of ! this type of routine is the abl$abs(%1) = %2 call; %1 is the number to find ! the absolute value of, and %2 is the answer; this routine cannot result in ! an error. A typical use of this call might be: ! x := x + abl$abs(y); ! Following is a description of each of the routines and their parameters. ! When a routine equals S/F, the routine returns as its value success (1) or ! failure (0). Examine the individual routines for possible causes of ! failures. ! abl$abs(%1) = %2 returns the absolute value of %1 in %2 ! abl$mod(%1,%2,%3) = S/F returns the mod of %1 / %2 in %3 ! abl$notab_line($1) = S/F returns the current line with tabs removed in $1 ! abl$extract_integer($1,%2) = S/F ! returns the first signed integer from $1 in %2 ! with number removed from $1 ! abl$ascii($1,$2) = S/F converts a string of numbers from $1 to a ! string with those ascii characters in $2 ! abl$undelimit($1,$2,$3) = S/F ! undelimits string $1, returning first string ! in $2 and second string in $3 ! abl$notab_offset(%1) = S/F returns what would be the current offset if ! tabs were replaced with spaces ! abl$virtual_mark = S/F remembers the current buffer, line, and offset ! abl$virtual_position = S/F moves to the position saved by abl$virtual_mark ! Page 5 procedure abl$abs(number) ! Perform absolute-value function ! Performs the ABS function. Always returns a non-negative number. ! ! Parameters: ! number integer number to return absolute value of ! ! Source: ! Abel if number < 0 then abl$abs := -number else abl$abs := number endif; endprocedure procedure abl$mod ! Perform modulus function (numerator,denominator,answer) ! Performs the MOD function. If 0 denominator then return bad. ! ! Parameters: ! numerator integer numerator of expression ! denominator integer denominator of expression ! answer integer result of MOD function ! ! Source: ! Abel if denominator = 0 then return 0 endif; answer := numerator - ((numerator / denominator) * denominator); return 1; endprocedure ! Page 6 procedure abl$notab_line($line) ! Return current line without tabs ! Returns the current line without any tabs. Returns bad if tabs are uneven. ! ! Parameters: ! $line string returned no-tab string ! ! Source: ! Abel local len, ! Length of current line line, ! Current line tab_offset, ! Offset of found tab in line tab_spaces, ! Number of spaces to use for tab tab_interval; ! Current tab settings ! ! Init's...currently can't sub uneven tabs ! tab_interval := get_info(current_buffer,"tab_stops"); if get_info(tab_interval,"type") = string then return 0 endif; line := current_line; len := length(line); ! ! Find each tab in the line ! loop ! ! Find first tab, exit if none found ! tab_offset := index(line,ascii(9)); !not a true offset exitif tab_offset = 0; tab_offset := tab_offset - 1; !now it's an offset ! ! Determine number of spaces to use in place of tab ! if not abl$mod(tab_offset,tab_interval,tab_spaces) then return 0; endif; tab_spaces := tab_interval - tab_spaces; ! ! Substitute tab with spaces ! line := substr(line,1,tab_offset) + substr(eve$x_spaces,1,tab_spaces) + substr(line,tab_offset+2,len); endloop; $line := line; return 1; endprocedure ! Page 7 procedure abl$extract_integer ! Extract signed integer from string ($strng,$number) ! Extracts a space or comma delimited signed integer number from a string. ! Routine returns 1 if successful, 0 otherwise. ! ! Parameters: ! $strng string string to find number in ! $number integer found number ! ! Source: ! Abel local number_end, number_start, numerics, strng, strng_length, x; ! Initializations strng:=$strng; translate(strng," ",","); edit(strng,trim,compress); strng_length:=length(strng); numerics:="0123456789"; number:=""; x:=1; ! Take care of leading sign, if any if index("+-",substr(strng,1,1))<>0 then number := substr(strng,1,1); x:=2; endif; ! Loop through strng loop exitif x > strng_length; c:=substr(strng,x,1); if index(numerics,c) <> 0 then number := number + c; else exitif 1 endif; x:=x+1; endloop; if number = "" then return 0 else $number := int(number); $strng := substr(strng,x,256); return 1; endif; endprocedure ! Page 8 procedure abl$ascii ! Convert #'s to string of ascii ($number_strng,$strng) ! Converts a list of numbers in a string to a string with those ascii ! characters. Returns bad if non-numerics in string, or number in string ! > 255 or < 0. ! ! Parameters: ! $number_strng string list of numbers ! $strng string string with above list of ascii characters ! ! Source: ! Abel local number_strng, strng, number; number_strng := $number_strng; strng := ""; loop exitif number_strng = ""; if not abl$extract_integer(number_strng,number) then return 0 endif; if (number < 0) or (number > 255) then return 0 endif; strng := strng + ascii(number); endloop; $strng := strng; return 1; endprocedure ! Page 9 procedure abl$undelimit ! Undelimits a delimited string ($delim_string,$string1,$string2) ! Breaks apart a two part delimited string, returning each string in separate ! variables. Returns bad if given a bad delimited string. ! ! Parameters ! $delim_string delimited string of format "-string1-string-" where the ! "-" represents the delimiter; the delimiter may be any ! any character, but may appear only 3 times ! $string1 the first string ! $string2 the second string ! ! Source: ! Abel local delim_string, delimiter, d1, d2; delim_string := $delim_string; edit(delim_string,trim,off); delimiter := substr(delim_string,1,1); d1 := index(substr(delim_string,2,256),delimiter)+1; d2 := index(substr(delim_string,d1+1,256),delimiter)+d1; if d2 <> length(delim_string) then return 0 endif; $string1 := substr(delim_string,2,d1-2); $string2 := substr(delim_string,d1+1,d2-d1-1); return 1; endprocedure ! Page 10 procedure abl$notab_offset($offset) ! Offset if tabs were spaces ! Returns in $offset what the current character offset would be if tabs were ! really spaces. Returns bad if tabs are uneven. ! ! Parameters: ! $offset integer what current offset would be ! ! Source: ! Abel local i,line,col,interval; interval:=get_info(current_buffer,"tab_stops"); if get_info(interval,"type")=string then return 0; endif; if mark(none) >= end_of(current_buffer) then $offset := 0 else line := current_line; if index(line,ascii(9)) = 0 then $offset := current_offset else i := 1; col := 0; loop exitif i > current_offset; if substr(line,i,1) = ascii(9) then col := ((col + interval)/interval)*interval else col := col + 1 endif; i := i + 1 endloop; $offset := col endif; endif; return 1; endprocedure ! Page 11 procedure abl$virtual_mark ! Mark without a mark ! The virtual_mark routine remembers the current buffer, line and offset in ! global variables. Companion routine to abl$virtual_position. Returns bad ! if tabs are uneven. ! ! Globals: ! abl$x_virtual_offset integer no-tab offset in current line ! abl$x_virtual_line integer line number we're on ! abl$x_virtual_buffer buffer current buffer ! ! Source: ! Eva2 if not abl$notab_offset(abl$x_virtual_offset) then return 0 endif; abl$x_virtual_line := eve$what_line; abl$x_virtual_buffer := current_buffer; return 1; endprocedure procedure abl$virtual_position ! Go to mark that wasn't ! Virtual_position returns us to the buffer, line and offset saved by ! virtual_mark. Companion procedure to abl$virtual_mark. Returns bad if ! abl$virtual_mark hasn't been used. ! ! Globals: ! abl$x_virtual_offset integer no-tab offset in current line ! abl$x_virtual_line integer line number we're on ! abl$x_virtual_buffer buffer current buffer ! ! Source: ! Eva2 local starting_position, ! our starting position before we move line; ! text of the destination line on_error position(starting_position); return 0; endon_error ! ! Remember our starting position, go to destination buffer and line ! if abl$x_virtual_buffer = 0 then return 0 endif; starting_position := mark(none); position(beginning_of(abl$x_virtual_buffer)); move_vertical(abl$x_virtual_line - 1); !if not abl$notab_line(line) then ! position(starting_position); ! return 0; !endif; !if length(current_line) <> length(line) then !must have imbedded tabs ! move_horizontal(-current_offset); ! erase_character(length(current_line)); ! copy_text(line); !else ! position(search(line_end,forward)); !endif; if length(current_line) < abl$x_virtual_offset then copy_text(substr(eve$x_spaces,1,abl$x_virtual_offset - length(line))); position(search(line_end,forward)); endif; move_horizontal(-current_offset + abl$x_virtual_offset); return 1; endprocedure