home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
wps
/
editor
/
epmtools
/
epmsmp
/
balance.e
< prev
next >
Wrap
Text File
|
1992-08-26
|
9KB
|
237 lines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Character Balancing Routine (for EOS2 and EPM) ;;
;; by Jonathan Kaye ;;
;; ;;
;; Upon entering a closing matching character, the balance ;;
;; routine shows the caller the matching opening character. ;;
;; If it is on the screen, it highlights the character in ;;
;; the color of the current commandline. If it's not on ;;
;; the screen at the time, it reports in the message area ;;
;; the line of the opening character, giving line number ;;
;; and text that follows the character. ;;
;; ;;
;; In EOS2, it keeps the opening character highlighted until ;;
;; the next key is pressed. In EPM, it only flashes the ;;
;; opening character a few times. ;;
;; ;;
;; Basically, it does what EMACS does. But I don't think ;;
;; we can mention that word around here. ;;
;; ;;
;; To use: Include BALANCE.E (include 'balance.e') in one ;;
;; of the MY*.E files, such as MYSTUFF.E. Since ;;
;; I wanted the keys to be part of the base keyset, ;;
;; I moved the key definitions (the def ')', etc.) to ;;
;; MYKEYS.E, leaving the procedure included in ;;
;; MYSTUFF.E. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Define matching keys ----------------------
def ')'=
call balance("parenthesis", "(", ")", 550)
def ']'=
call balance("square bracket", "[", "]", 660)
def '}'=
call balance("curly bracket", "{", "}", 880)
def '>'=
call balance("angle bracket", "<", ">", 770)
;; -------------------------------------------
defproc balance (type, open_char, close_char, fail_beep_Hz)
keyin close_char
refresh -- Get closing character on screen to start
compile if (NOT EPM) -- No commandstate() function for EPM
if (commandstate() = 0) then
compile endif
getsearch user_pattern -- Hold user's pattern to restore when done
display 0
compile if EPM
display -3 -- Don't show user cursor is jumping around
-- Also turn off non-critical error messages
compile else
display 0 -- Don't show user cursor is jumping around
compile endif
call psave_pos(screenpos) -- Freeze our relative position on screen
-- Set search keys we use to find opening and closing characters
compile if EVERSION >= '4.12B' -- Versions of E before 4.12B needs
loc_opts = 'R-' -- different grep locate options
compile else
loc_opts = 'R-G'
compile endif
open_pat = 'XCOM L /'open_char'/'loc_opts
clos_pat = 'XCOM L /'close_char'/'loc_opts
-- Initialize for start of search right before closing character
close_col = .COL - 1
close_line = .LINE
call minus_one(close_col, close_line)
open_col = .COL -- We can start here because we know there isn't
open_line = .LINE -- an opening character past what user just typed
found = 0
loop
call minus_one(open_col, open_line) -- so we don't find last open again
call last_char(open_pat, open_line, open_col, open_col, open_line)
call last_char(clos_pat, close_line, close_col, close_col, close_line)
if (open_line = -1) then leave -- No opening character
else
if (more_recent(open_col, open_line, close_col, close_line)) then
-- Found our opening character
found = 1
leave
else
-- keep searching; the opening & closing we found (if we found any)
-- cancel each other (note that the opening & closing
-- chars don't necessarily match each other, but we
-- don't care for our purposes)
call minus_one(close_col, close_line)
endif
endif
endloop
prestore_pos(screenpos) -- Restore relative screen position
compile if EPM
-- Turn back on non-critical error messages and screen updates
display 3
compile else
sayerror 0 -- Clear any pending error
-- Turn back on screen updates
display 1
compile endif
setsearch user_pattern -- Restore user's search pattern
if (found = 1) then
-- Calculate Screen Boundaries
top_line = .LINE - .CURSORY + 1
left_col = .COL - .CURSORX + 1
rite_col = left_col + .WINDOWWIDTH - 1
if (on_screen(open_col, open_line, top_line, left_col, rite_col)) then
-- The open character is on the screen, so highlight it
call show_char(open_char, open_col, open_line, top_line, left_col)
-- The open character is not on the screen, so display its position
else call show_at_bottom(open_col, open_line)
endif
else
sayerror "No matching opening" type
call beep(fail_beep_Hz, 100)
endif
compile if (NOT EPM) -- end of 'if commandstate()' (not for EPM)
endif
compile endif
defproc minus_one (var col, var line)
-- Subtracts one from the column position. If we hit the left column in
-- doing so, we go up to the line above us.
col = col - 1
if (col = 0) then
line = line - 1
getline x, line
col = length(x)
endif
defproc last_char (search_pat, line_no, col_no, var new_x, var new_y)
-- Return the cursor position where the search ends, starting at given
-- position. '-1' means that the search was unsuccessful
if (col_no <> -1) then
.COL = col_no
.LINE = line_no
search_pat
endif
if (col_no = -1 OR rc = sayerror('String not found')) then
new_x = -1
new_y = -1
else
new_x = .COL
new_y = .LINE
endif
defproc more_recent (c1_x, c1_y, c2_x, c2_y)
-- Says which set of coordinates (c1 or c2) is closer to the current pos
-- in the backwards direction. 1 means c1 is closer, 0 means c2 is.
if (c2_y = -1) then return 1; endif
if (c1_y = -1) then return 0; endif
if (c1_y > c2_y) then return 1
else
if (c2_y > c1_y OR c2_x > c1_x) then return 0
else return 1
endif
endif
defproc show_char(open_char, x_pos, y_pos, top_line, left_col)
compile if EPM
;; -------------------------------------------------------------------- ;;
;; For EPM: flash character on the screen for a moment. ;;
;; -------------------------------------------------------------------- ;;
-- ***
-- *** EPM function
-- ***
-- The opening character is on the screen, so we highlight it
y_coord = y_pos-top_line+1
x_coord = x_pos-left_col+1
display 0 -- Turn off refreshing until we get a key
do j = 1 to 5
sayat open_char, y_coord, x_coord, .MARKCOLOR, 1
do i = 1 to 100
end
sayat open_char, y_coord, x_coord, .STATUSCOLOR, 1
do i = 1 to 100
end
end
display 1
refresh
compile else
;; -------------------------------------------------------------------- ;;
;; For EOS2: highlight character on the screen until user presses key. ;;
;; -------------------------------------------------------------------- ;;
-- ***
-- *** EOS2 function
-- ***
-- The opening character is on the screen, so we highlight it
y_coord = y_pos-top_line+1+.BOXY
x_coord = x_pos-left_col+1+.BOXX
sayat open_char, y_coord, x_coord, .COMMANDCOLOR, 1
display 0 -- Turn off refreshing until we get a key
k = mgetkey() -- Wait for keypress to unhighlight it
display 1
refresh -- Let screen refresh unhighlight it
executekey k
refresh -- Let screen refresh unhighlight it
compile endif
defproc on_screen(x_pos, y_pos, top_line, left_col, right_col)
if ((y_pos < top_line) OR (x_pos < left_col) OR (x_pos > right_col)) then
return (0)
else
return (1)
endif
defproc show_at_bottom (open_col, open_line)
-- Opening character not on screen, so tell user in message area where it is
getline line_str, open_line
if (.LINE = open_line) then
report_len = .COL - open_col - 1
else
report_len = length(line_str) - open_col + 1
endif
report_line = substr(line_str, open_col, report_len)
if (length(report_line) > 20) then
report_line = substr(report_line, 1, 20) "..."
endif
sayerror "Line" open_line":" report_line