home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
p2demo21.exe
/
PEL
/
LINECMDS.PEL
< prev
next >
Wrap
Text File
|
1995-04-20
|
52KB
|
1,916 lines
# $Header: P:\source\wmacros\linecmds.pev 1.69.1.0 20 Apr 1995 11:32:54 WALKER $
##############################################################################
#
# Compuware Corporation
# 31440 Northwestern Highway
# Farmington Hills, Michigan 48334-2564
#
# This source code listing contains information that is
# proprietary to Compuware Corporation and may not be copied
# duplicated, translated, transmitted, stored, retrieved
# or in any manner or by any method conveyed or disclosed
# to a third party or parties without express written
# permission from Compuware Corporation.
#
#
##############################################################################
#### $Workfile: linecmds.pel $: Support for Line Commands
#
# Values returned by functions that process Line Commands
#
global LC_OK = 1 # = Line Command processed Sucessfully
global LC_DEL = 2 # = Line(s) were deleted
global LC_INS = 3 # = Line(s) were inserted
global LC_MOD = 4 # = Line(s) were modified, restart LC processing
global LC_REDRAW = 5 # = Line(s) were modified, redraw the window
global LC_TRASHED = 6 # = Line Command Processing was interrupted - start over
global LC_KEEP = 7 # = Keep the Line Command
global LC_NOTOK = 8 # = Error in Line Command - DO NOT display lc_error_msg
global LC_ERROR = 9 # = Error in Line Command - display lc_error_msg
# Note: for LC_DEL & LC_INS lc_arg contains the # of lines inserted/deleted.
#
# Global variables for Line Command Processing
#
global lc # Table of valid Line Commands -> functions.
global lc_arg = 0 # Numeric argument for the current command
global lc_line = 0 # Line the current command is on
global lc_command = 0 # The current command.
global lc_restore = 1 # Set to Zero when a Line Commands positions cursor.
global lc_error_msg = "" # Error message to display in an error
global lc_message = "" # Message to display after processing line commands.
global lc_count = 0 # Number of lines marked by a block command.
global lc_last = 0 # Last line of a mark_1_line command (lc_line+lc_count)
#
# Global variables for Transfer Processing
#
local lc_mark # Table of block Line Command -> line #.
local lc_transfer # Table of valid Transfer Commands -> functions
global tr_command = "" # Transfer Destination command that's pending
global tr_pending = "" # Transfer Source (Block) command that's pending
global tr_incomplete = "" # Transfer Source (Block) command that's incomplete
global tr_count = 0 # Number of lines in source block
global tr_after = 1 # TRUE = transfer after tr_line else before tr_line
global tr_src_start = 0 # Bookmark marking the start to the source block
global tr_src_end = 0 # Bookmark marking the end of the source block
global tr_src_buffer = 0 # Buffer the source block is in
global tr_dest_mark = 0 # Bookmark marking the destination Line
global tr_dest_buffer = 0 # Buffer destination line is in
global tr_write_file = "" # File to write_marked_lines to
#
# Values used by mark_lines
#
local LC_SEP = "_"
local LC_1_LINE = "_1"
local LC_END_BLOCK = "_2"
#
# Function to clear the Line Commands tables
#
global function delete_lc()
{
delete lc
delete lc_transfer
}
#
# Function to assign actions to Line Commands
#
global function assign_lc(command, action)
{
lc[command] = action
}
#
# Function to assign actions to Transfer Commands
#
global function assign_transfer(command, action)
{
lc_transfer[command] = action
}
#
# Function to reset Line Commands,
#
global function reset_line_commands(include_labels, fid)
{
local line
local start_buffer
if (current_buffer)
{
start_buffer = current_buffer
do # delete all cmds in all buffers
{
if (!(and(buffer_flags, BUFFER_SYSTEM)))
{
if (argcount() > 1 && fid)
execute_function( fid )
else
{
if (argcount() && include_labels)
delete line_command # delete all line-commands.
else
{ # delete line-commands, but not
for (line in line_command) # labels.
{
if (substr(trim(ltrim(line_command[line])),1,1) != ".")
delete_line_command(line)
}
}
linecommands_changed = 0 # reset changed flag.
}
}
} while( next_buffer("", 1, 1) != start_buffer)
}
if (argcount() > 1 && fid) # process any leftover commands
process_line_commands()
else
{
delete lc_mark # delete all marks.
reset_transfer() # Reset any pending transfers
}
display_update() # make sure redraw works
display_redraw() # redraw all windows
}
#
# Global Function to reset the transfer variables.
#
global function reset_transfer(result, dest_only, source_only, kill_marks)
{
local pass2
local start_line
local lost_mark
local save_buffer = current_buffer
if (argcount() < 2 || !source_only)
{
if (tr_dest_buffer && tr_dest_mark)
{
current_buffer = tr_dest_buffer
if (argcount() == 0 || result != LC_KEEP)
delete_line_command(mark_line(tr_dest_mark))
delete_mark(tr_dest_mark)
tr_dest_mark = 0
}
tr_after = 1
tr_dest_buffer = 0
tr_command = ""
}
if (argcount() < 3 || !dest_only)
{
if (tr_src_buffer && tr_src_start)
{
current_buffer = tr_src_buffer
if (argcount() == 0 || result != LC_KEEP)
delete_line_command(mark_line(tr_src_start))
delete_mark(tr_src_start)
tr_src_start = 0
}
if (tr_src_buffer && tr_src_end)
{
current_buffer = tr_src_buffer
if (argcount() == 0 || result != LC_KEEP)
delete_line_command(mark_line(tr_src_end))
delete_mark(tr_src_end)
tr_src_end = 0
}
tr_src_buffer = 0
tr_pending = ""
tr_incomplete = ""
}
if (argcount() > 3 && kill_marks)
delete lc_mark
tr_count = 0
current_buffer = save_buffer
show_message()
}
#
# Function to process Line Commands,
#
# For each line_command, it is looked up in the lc table to find the
# PEL function to execute. That function is executed, it's return
# code is validated and the appropriate action is executed.
#
global function process_line_commands(find_source)
{
local i
local len
local line
local cmnd
local char
local command
local deleted
local modified
local adjustment
local ex_command
local redraw_flag = FALSE
local lines_added = FALSE
local last_line = "0"
local numbers = "0123456789-" # allow - numbers (enhancement to ISPF)
local result = LC_OK
lc_message = ""
lc_error_msg = ""
find_source = (argcount() && find_source)
if (!find_source)
{
if (linecommands_changed)
update_marks()
else
return TRUE
}
lc_restore = 1
save_position()
do
{
modified = FALSE
adjustment = 0
lc_last = 0
for (lc_line in line_command)
{
if (lc_line < last_line)
continue
else
{
lc_line += adjustment
do # if a line is deleted, check it again in
{ # case the next line has a command on it
deleted = FALSE
command = toupper(trim(ltrim(line_command[lc_line])))
lc_command = trim(trim(command, numbers))
len = length(lc_command)
if (length(command) == 0) # Nothing here.
{
if (length(line_command[lc_line]))
delete_line_command(lc_line)
continue
}
else if (len == 0)
{
line_command[lc_line] = command
refresh_display()
restore_position(1)
if (current_column < 1)
goto_bol()
goto_line(lc_line)
goto_bolc()
error("Invalid line command %s on line %d", command, lc_line)
return
}
else
{
lc_count = 1
if (len != length(command))
lc_arg = substr(command, len + 1) + 0
else
lc_arg = 0
# Check for special commands
char = substr(command, 1, 1)
if (char == "=")
ex_command = "=flag"
else if (char == ".")
{
if (compress(command, ".") == ".")
ex_command = ".insert"
else
ex_command = ".label"
}
else
ex_command = lc_command
if (ex_command in lc)
{
if (lc[ex_command])
{
if (ex_command == ".label")
result = execute_function(lc[ex_command])
else if (length(tr_incomplete) && lc_command != tr_incomplete)
{
lc_error_msg = "Unable to execute %s on line %d, " tr_incomplete " Incomplete"
result = LC_ERROR
}
else if (lc_line+0 <= lc_last)
{
lc_error_msg = "Unable to execute %s on line %d, Inside a " tr_pending " range."
result = LC_ERROR
}
else
{
delete_line_command(lc_line)
result = execute_function(lc[ex_command])
}
}
else
result = LC_KEEP
}
else
{
lc_error_msg = "Invalid Line Command %s on line %d"
result = LC_ERROR
}
# Performing any line command on the first line of
# the buffer screws up the window, so redraw it.
if (result <= LC_KEEP && (lc_line + 0 <= 1 ||
lc_line + lc_count <= 1))
{
redraw_flag = TRUE
}
if (result == LC_INS)
{
adjustment += lc_count
lines_added = TRUE
}
else if (result == LC_DEL)
{
adjustment -= lc_count
deleted = TRUE
}
else if (result == LC_MOD)
{
modified = TRUE
last_line = lc_line
break
}
else if (result == LC_REDRAW)
{
modified = TRUE
redraw_flag = TRUE
last_line = lc_line
break
}
else if (result == LC_TRASHED)
{
modified = TRUE
last_line = "0" # Start Over!
break
}
else if (result == LC_KEEP)
{
redraw_flag = TRUE # If the command is KEPT,
line_command[lc_line] = command # redraw the window since
update_line_command(lc_line) # this sometimes causes
} # display problems.
else if (result != LC_OK)
{
line_command[lc_line] = command
update_line_command(lc_line)
refresh_display()
restore_position(1)
if (current_column < 1)
goto_bol()
goto_line(lc_line)
goto_bolc()
if (result == LC_ERROR)
{
if (length(lc_error_msg))
error(lc_error_msg, command, lc_line)
else
error("Error in Line Command %s on Line %d",
command, lc_line)
}
else if (result == 0)
error("Error: Unable to execute %s(%d) on Line %d", \
lc[lc_command], lc_arg, lc_line)
else if (result != LC_NOTOK)
error("Error %d in Line Command %s(%s) on Line %d", \
result, lc[lc_command], command, lc_line)
return
}
}
} while (deleted)
}
}
} while (modified)
restore_position(lc_restore)
if (lc_restore && current_column < 1)
goto_bol()
if (!find_source && (tr_count || length(tr_command)))
perform_transfer()
if (!lines_added && linecommands_changed) # if lines were added they might
update_marks() # have commands
if (redraw_flag)
refresh_display()
if (!find_source)
show_message()
return (result > 0 && result < LC_NOTOK)
}
#
# Function to update the message line.
#
global function show_message(clear)
{
local msg
local inBuffer
local cbuffer
if (length(lc_message))
message(lc_message)
else
{
if (length(tr_incomplete))
{
msg = sprintf("%s Incomplete", tr_incomplete)
inBuffer = tr_src_buffer
}
else if (length(tr_pending))
{
msg = sprintf("%s Pending", tr_pending)
inBuffer = tr_src_buffer
}
else if (length(tr_command))
{
msg = sprintf("%s Pending", tr_command)
inBuffer = tr_dest_buffer
}
if (length(msg))
{
if (inBuffer && inBuffer != current_buffer)
{
cbuffer = current_buffer
current_buffer = inBuffer
msg = sprintf("%s in %s", msg, buffer_name)
current_buffer = cbuffer
}
notify(msg)
}
else if (!argcount() || clear)
message("")
}
}
#
# Function to completely re-draw the display to correct for the bug that
# causes the window to re-drawn incorrectly if there is a line command left
# on the first line.
#
local function refresh_display()
{
display_update()
display_redraw()
display_redraw()
}
#
# Function to clear any deleted or altered marks.
#
local function update_marks()
{
local command
local cmnd
local line
local i
for (command in lc_mark)
{
if ( lc_mark[command].buffer == current_buffer )
{
i = index(command, LC_SEP)
if (i)
cmnd = substr(command, 1, i-1)
else
cmnd = command
line = mark_line(lc_mark[command].mark)
if (trim(line_command[line], " 0123456789") != cmnd)
{
delete lc_mark[command]
if (tr_pending == cmnd)
{
tr_pending = ""
reset_transfer(0, FALSE, TRUE)
}
else if (tr_incomplete == cmnd)
{
tr_incomplete = ""
show_message()
}
}
}
}
#
# check the destination (if any)
#
if (tr_dest_mark && length(tr_command) && tr_dest_buffer == current_buffer)
{
line = mark_line(tr_dest_mark)
if (trim(line_command[line], " 0123456789") != tr_command)
{
tr_command = ""
reset_transfer(0, TRUE, FALSE)
}
}
linecommands_changed = 0
}
#
# Function to perform the actual line transfer.
#
global function perform_transfer(func)
{
local i
local result
local buffer
local command
local command2
local start_buffer = current_buffer
local found = FALSE
while (TRUE)
{
for (command in lc_mark)
{
i = index(command, LC_1_LINE)
if (i)
{
command2 = substr(command, 1, i-1)
if (command2 in lc_transfer)
{
found = TRUE
tr_src_buffer = lc_mark[command].buffer
tr_src_start = lc_mark[command].mark
tr_count = lc_mark[command].num
current_buffer = tr_src_buffer
tr_src_end = create_mark(pick_unused_mark(),
mark_line(tr_src_start) + tr_count - 1,
0x7FFFFFFF)
if (check_transfer())
{
delete_line_command(mark_line(tr_src_start))
delete lc_mark[command]
if (tr_dest_buffer)
{
current_buffer = tr_dest_buffer
delete_line_command(mark_line(tr_dest_mark))
}
if (argcount() && length(func))
result = execute_function(lc_transfer[command2] " " func)
else
result = execute_function(lc_transfer[command2])
}
else
result = LC_ERROR
break
}
}
else if (!index(command, LC_END_BLOCK))
{
if (command in lc_transfer)
{
command2 = command LC_END_BLOCK
if (command2 in lc_mark)
{
found = TRUE
tr_src_buffer = lc_mark[command].buffer
tr_src_start = lc_mark[command].mark
tr_src_end = lc_mark[command2].mark
tr_count = mark_line(tr_src_end) -
mark_line(tr_src_start) + 1
if (check_transfer())
{
current_buffer = tr_src_buffer
delete_line_command(mark_line(tr_src_start))
delete_line_command(mark_line(tr_src_end))
delete lc_mark[command]
delete lc_mark[command2]
if (tr_dest_buffer)
{
current_buffer = tr_dest_buffer
delete_line_command(mark_line(tr_dest_mark))
}
if (argcount() && length(func))
result = execute_function(lc_transfer[command] " " func)
else
result = execute_function(lc_transfer[command])
}
else
result = LC_ERROR
break
}
}
}
}
if (found)
break
else if (prev_buffer() == start_buffer)
break
else if (!process_line_commands(1))
return LC_ERROR;
}
if (found)
{
if (result < LC_NOTOK)
{
if (argcount() && length(func))
reset_transfer(result, FALSE, TRUE) # Source Only
else
reset_transfer(result) # Source & Dest
}
}
current_buffer = start_buffer
display_update() # make sure redraw works
display_redraw() # redraw all windows.
return result
}
#
# Function to ensure a transfer is valid
#
local function check_transfer()
{
local dest_line
local save_buffer
if (tr_dest_buffer == tr_src_buffer)
{
save_buffer = current_buffer
current_buffer = tr_dest_buffer
dest_line = mark_line(tr_dest_mark)
if (dest_line < mark_line(tr_src_start) ||
dest_line > mark_line(tr_src_end))
{
current_buffer = save_buffer
return TRUE
}
else
{
if (lc_last && tr_pending)
{
lc_error_msg = sprintf("The %s MUST be outside the %s range.",
tr_command, tr_pending)
}
else
{
lc_error_msg = sprintf("The %s MUST be outside the %s's",
tr_command, lc_command)
}
if (tr_dest_mark)
{
delete_mark(tr_dest_mark)
tr_dest_mark = 0
}
tr_dest_buffer = 0
tr_command = ""
tr_count = 0
current_buffer = save_buffer
return FALSE
}
}
else
return TRUE
}
#
# Line Command function to mark the ends of a block.
#
global function mark_lines(exec)
{
if (argcount())
return mark_cols(0, 0, exec)
else
return mark_cols()
}
global function mark_cols(col1, col2, exec)
{
local mark
local start
local result
local buffer
local command2
local useCols = (argcount() >= 1 && (col1 || col2))
local fromcol = (argcount() >= 1 && col1) ? col1 : 1
local tocol = (argcount() >= 2 && col2) ? col2 : 0x7FFFFFFF
if (lc_command in lc_mark)
{
buffer = lc_mark[lc_command].buffer
if (buffer == current_buffer)
{
mark = lc_mark[lc_command].mark
if (mark_line(mark) == lc_line+0 && !useCols)
return LC_KEEP
else
{
if (tr_incomplete == lc_command)
{
tr_incomplete = ""
show_message()
}
command2 = lc_command LC_END_BLOCK
if (command2 in lc_mark)
{
mark = lc_mark[command2].mark
if (mark_line(mark) == lc_line+0)
return LC_KEEP
else
{
lc_error_msg = "Too Many %s's!"
return LC_ERROR
}
}
else
{
lc_mark[command2].arg = lc_arg
lc_mark[command2].num = lc_count
lc_mark[command2].buffer = current_buffer
lc_mark[command2].mark = create_mark(pick_unused_mark(),
lc_line, tocol)
if (argcount() > 2 && length(exec))
{
start = mark_line(lc_mark[lc_command].mark)
lc_arg = max(lc_arg+0, lc_mark[lc_command].arg+0)
lc_count = start - lc_line - 1
tr_command = lc_command
result = execute_function(exec)
if (result < LC_KEEP)
{
delete_line_command(mark_line(lc_mark[lc_command].mark))
delete_line_command(mark_line(lc_mark[command2].mark))
}
delete_mark(lc_mark[lc_command].mark)
delete_mark(lc_mark[command2].mark)
delete lc_mark[lc_command]
delete lc_mark[command2]
tr_command = ""
return result
}
else
{
tr_pending = lc_command
tr_src_buffer = current_buffer
return LC_KEEP
}
}
}
}
else
{
lc_error_msg = "Both %s's MUST be in the same buffer!"
return LC_ERROR
}
}
else
{
tr_incomplete = lc_command
tr_src_buffer = current_buffer
lc_mark[lc_command].arg = lc_arg
lc_mark[lc_command].num = lc_count
lc_mark[lc_command].buffer = current_buffer
lc_mark[lc_command].mark = create_mark(pick_unused_mark(),
lc_line, fromcol)
return LC_KEEP
}
}
#
# Line Command function to mark one line
#
global function mark_1_line()
{
local mark
local buffer
local command = lc_command LC_1_LINE
if (command in lc_mark)
{
buffer = lc_mark[command].buffer
mark = lc_mark[command].mark
if (buffer == current_buffer && mark_line(mark) == lc_line+0)
return LC_KEEP
else
{
lc_error_msg = "Too Many %s's!"
return LC_ERROR
}
}
else
{
if (lc_arg+0 != 0)
lc_count = lc_arg+0
else if (lc_count+0 == 0)
lc_count = 1
lc_mark[command].buffer = current_buffer
lc_mark[command].mark = create_mark(pick_unused_mark(), lc_line, 1)
lc_mark[command].num = lc_count
tr_src_buffer = current_buffer
tr_pending = lc_command
lc_last = lc_line + lc_count > 0 ? lc_count - 1 \
: lc_count + 1
return LC_KEEP
}
}
#
#
# Line Command function to transfer lines.
#
global function transfer_lines(where)
{
local ch
if (tr_dest_mark && mark_line(tr_dest_mark) != lc_line+0)
{
lc_error_msg = sprintf("ERROR: %s already pending!", tr_command)
return LC_ERROR
}
else
{
if (!tr_dest_mark)
tr_dest_mark = create_mark(pick_unused_mark(), lc_line, 1)
tr_dest_buffer = current_buffer
tr_src_buffer = 0
tr_src_start = 0
tr_src_end = 0
tr_count = 1 # indicate a pending transfer
tr_command = lc_command
tr_after = FALSE
if (argcount() && length(where))
{
ch = toupper(substr(where, 1, 1))
if (ch == "1" || ch == "A" || ch == "F")
tr_after = TRUE
}
return LC_KEEP
}
}
#
# Transfer function to copy lines
#
global function copy_to_dest(func)
{
local ret
local pos
local line
local old_flags
local start, end
local src_on_last_line = FALSE
local dest_on_last_line = FALSE
local kill_last_src_line = FALSE
if (tr_src_buffer && tr_src_start && tr_src_end)
{
save_position()
if (argcount() && length(func))
tr_count = execute_function(func)
else if (tr_dest_buffer && tr_dest_mark)
{
current_buffer = tr_src_buffer
if (mark_line(tr_src_end) >= buffer_last_line)
{
if (and(buffer_flags, BUFFER_READ_ONLY))
{
src_on_last_line = TRUE
# We can't avoid the nasty bug in transfer() that scrambles
# data when the source block hits the end of the file so,
# it's an error!
tr_count = 0
lc_error_msg = "Unable to copy the last line of a Read only file."
restore_position(TRUE)
return LC_ERROR
}
else
{
# Avoid a nasty bug in transfer() that scrambles data when
# the source block hits the end of the file.
old_flags = buffer_flags
buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
goto_buffer_bottom()
open_line()
buffer_flags = old_flags
kill_last_src_line = TRUE
}
}
current_buffer = tr_dest_buffer
# make sure the dest buffer is NOT read-only so it won't play
# havok with the newline games we might need to play.
if ( and(buffer_flags, BUFFER_READ_ONLY) )
{
tr_count = 0
lc_error_msg = "Read only file."
restore_position(TRUE)
return LC_ERROR
}
goto_mark(tr_dest_mark)
if (current_line >= buffer_last_line)
{
dest_on_last_line = tr_after
if (dest_on_last_line)
{
# if we insert something AFTER the last line, we need to move
# to the end of the line and save that position so we can
# insert a newline there if the copy is sucessful.
goto_eol()
pos = create_mark(pick_unused_mark())
}
}
else if (tr_after)
down()
if (src_on_last_line && !dest_on_last_line)
{
# mark the next_char which will be the first char after the read.
# (if we mark this char, it won't be moved by the transfer)
next_char()
pos = create_mark(pick_unused_mark())
prev_char()
}
if ((tr_count = transfer(tr_src_buffer, tr_src_start, tr_src_end)))
{
if (dest_on_last_line || src_on_last_line)
{
if (dest_on_last_line)
{
if (tr_after)
goto_mark(pos) # restore saved pos
}
else
{
goto_mark(pos) # restore saved pos
prev_char() # backup since we saved the pos of the NEXT char.
}
# insert a newline in the buffer since the file we read probaby
# doesn't have a new as the last char, which would cause the last
# line of the file and the next line in the buffer to be joined.
# OR - we just inserted the file at the end and the last line of
# the buffer just got joined to the first line of the file.
old_flags = buffer_flags
buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
insert_newline()
buffer_flags = old_flags
# if we were copying after the last line, we need to move the
# dest mark there since the line_command will have been pushed
# there by the transfer.
if (dest_on_last_line)
{
goto_buffer_bottom()
if (tr_after)
{
old_flags = buffer_flags
buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
backspace()
buffer_flags = old_flags
}
delete_mark(tr_dest_mark)
tr_dest_mark = create_mark(pick_unused_mark())
}
else if (!tr_after)
{
# if we read the data BEFORE the mark, we need to move the mark
# so that reset_transfer() will delete the correct line-command.
delete_mark(tr_dest_mark)
tr_dest_mark = pos
}
}
}
if (kill_last_src_line)
{
current_buffer = tr_src_buffer
old_flags = buffer_flags
buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
goto_buffer_bottom()
backspace()
buffer_flags = old_flags
}
}
else
{
tr_count = 0
lc_error_msg = "Transfer destination not setup properly!"
ret = LC_ERROR
}
if (tr_count)
{
lc_message = "Lines Copied"
ret = LC_INS
}
else
ret = LC_NOTOK
restore_position(TRUE)
return ret
}
else
{
tr_count = 0
lc_error_msg = "Transfer source not setup properly!"
return LC_ERROR
}
}
#
# Transfer function to move lines
#
global function move_to_dest(func)
{
local ret
if (tr_src_buffer == tr_dest_buffer && \
tr_after ? mark_line(tr_src_start) == mark_line(tr_dest_mark) + 1 \
: mark_line(tr_src_end) == mark_line(tr_dest_mark) - 1)
{
tr_count = 0
return LC_OK # Lines would be copied to the same place!
}
else if (tr_src_buffer && tr_src_start && tr_src_end)
{
if (argcount() && length(func))
{
tr_count = execute_function(func)
ret = LC_NOTOK
}
else
ret = copy_to_dest()
if (tr_count)
{
delete_marked_lines()
lc_message = "Lines Moved"
ret = LC_MOD
}
return ret
}
else
{
tr_count = 0
lc_error_msg = "Transfer source not setup properly!"
return LC_ERROR
}
}
#
# Transfer Function to delete marked lines when move_to_dest uses transfer().
#
global function delete_marked_lines()
{
local line
local end_line
local old_flags
local num_lines
local start_line
local old_buffer = current_buffer
current_buffer = tr_src_buffer
start_line = mark_line(tr_src_start)
end_line = mark_line(tr_src_end)
if (start_line && end_line)
{
num_lines = abs(end_line - start_line)
old_flags = buffer_flags
buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
save_position()
if (start_line <= end_line)
goto_mark(tr_src_start)
else
{
goto_mark(tr_src_end)
goto_bol()
}
for(line = 0; line <= num_lines; line++)
{
if (current_line == buffer_last_line)
{
delete_line()
backspace()
}
else
delete_line()
}
restore_position(TRUE)
buffer_flags = old_flags
current_buffer = old_buffer
return LC_DEL
}
else
{
current_buffer = old_buffer
lc_error_msg = "No lines marked or incomplete block"
return LC_ERROR
}
}
#
# Transfer Function to write marked lines to the tr_write_file file.
#
global function write_marked_lines()
{
local fh
local retval
if (tr_src_start && tr_src_end)
{
current_buffer = tr_src_buffer
fh = fopen(tr_write_file, 1)
if (fh > -1)
{
if (fwrite(fh, tr_src_start, distance_between_marks(tr_src_start,
tr_src_end)) > -1)
{
fclose(fh)
retval = LC_OK
}
else
{
fclose(fh)
sprintf( lc_error_msg, "Unable to write %s", tr_write_file)
retval = LC_ERROR
}
}
else
{
sprintf( lc_error_msg, "Unable to open %s", tr_write_file)
retval = LC_ERROR
}
return retval
}
else
{
lc_error_msg = "No lines marked or incomplete block"
return LC_ERROR
}
}
#
# Transfer Function to cut/copy marked lines to the scrap
#
global function cut_marked_lines()
{
if (tr_src_start && tr_src_end)
{
current_buffer = tr_src_buffer
begin_selection(LINE_SELECTION, tr_src_start)
end_selection(tr_src_end)
if (copy_to_scrap())
return abs(mark_line(tr_src_end) - mark_line(tr_src_start)) + 1
else
{
sprintf( lc_error_msg, "Unable to CUT lines to the scrap")
return 0
}
}
else
{
lc_error_msg = "No lines marked or incomplete block"
return 0
}
}
#
# Global Transfer function to create source marks when called from a
# function called from mark_cols (or mark_lines).
#
global function create_source_marks(useCols, one_line_only)
{
local command2
tr_src_buffer = current_buffer
if (argcount() && useCols && tr_command)
{
command2 = tr_command LC_END_BLOCK
tr_src_start = lc_mark[tr_command].mark
tr_src_end = lc_mark[command2].mark
}
else if (lc_count >= 0)
{
tr_src_start = create_mark(pick_unused_mark(), lc_line, 1)
if (one_line_only)
tr_src_end = create_mark(pick_unused_mark(), lc_line, 0x7FFFFFFF)
else
tr_src_end = create_mark(pick_unused_mark(), lc_line + lc_count - 1,
0x7FFFFFFF)
}
else
{
tr_src_start = create_mark(pick_unused_mark(), lc_line + lc_count + 1, 1)
tr_src_end = create_mark(pick_unused_mark(), lc_line, 0x7FFFFFFF)
}
}
#
# Line Command function to repeat lines
#
global function repeat_lines()
{
local count
local result
if (lc_arg+0 != 0)
lc_count = lc_arg+0
else if (lc_count+0 == 0)
lc_count = 1
tr_after = 1
tr_dest_buffer = current_buffer
tr_dest_mark = create_mark(pick_unused_mark(), lc_line, 1)
if (lc_count > 0)
{
tr_count = 1
for (count = 1; count <= lc_count; count++)
{
create_source_marks(0, 1)
result = copy_to_dest()
if (result == LC_INS)
{
delete_mark(tr_src_start); tr_src_start = 0
delete_mark(tr_src_end); tr_src_end = 0
}
else
break
}
}
else
{
create_source_marks(0, 1)
tr_count = lc_count
result = copy_to_dest()
}
reset_transfer()
return result
}
#
# Line Command function to delete lines
#
global function old_delete_lines()
{
local rc
local col
local line
local count
local old_flags
local on_last_line
local retval
if (lc_arg+0 != 0)
lc_count = lc_arg+0
else if (lc_count+0 == 0)
lc_count = 1
retval = lines_empty()
if (retval == LC_OK)
{
col = current_column
line = current_line
retval = LC_DEL
goto_bolc()
goto_line(lc_count >= 0 ? lc_line : lc_line + lc_count + 1)
for (count = abs(lc_count); count > 0; count--)
{
on_last_line = (current_line >= buffer_last_line)
rc = delete_line()
if (on_last_line)
{
old_flags = buffer_flags
buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
goto_buffer_bottom()
backspace()
buffer_flags = old_flags
break
}
else if (current_line > buffer_last_line)
break
else if (!rc)
{
retval = LC_NOTOK
break
}
}
goto_pos(line,col)
}
return retval
}
#
# Line Command function to delete lines
#
global function delete_lines()
{
local retval
local old_flags
if (lc_arg+0 != 0)
lc_count = lc_arg+0
else if (lc_count+0 == 0)
lc_count = 1
retval = lines_empty()
if (retval == LC_OK)
{
select_lines(0)
delete_chars()
if (lc_line >= buffer_last_line)
{
old_flags = buffer_flags
buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
goto_buffer_bottom()
backspace()
buffer_flags = old_flags
}
retval = LC_DEL
}
return retval
}
# Line Command function to determine if lines have no line commands on them.
#
global function lines_empty()
{
local num
local line
local command
local first
local last
if (lc_count < 0)
{
first = lc_line + lc_count + 1
last = lc_line + 0
}
else
{
first = lc_line + 0
last = lc_line + lc_count - 1
}
for (line in line_command)
{
num = atoi(line)
if (num >= last)
break
else if (num > first)
{
command = ltrim(trim(line_command[line], ". "))
if (length(command))
{
lc_error_msg = sprintf("%s Pending on line %d", command, line)
return LC_ERROR
}
}
}
return LC_OK
}
#
# Line Command function to insert lines
#
global function insert_lines(auto_cleanup)
{
local on_last_line
local count
local line = lc_line
local retval = LC_INS
local old_flags = buffer_flags
buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE ))
if (lc_arg+0 != 0)
lc_count = lc_arg+0
else if (lc_count+0 == 0)
lc_count = 1
if (!argcount())
auto_cleanup = (".insert" in lc) # Default is on if .insert is a command
if (line)
{
goto_line(line)
goto_eol()
}
else
{
goto_line(1)
goto_bol()
}
# This for loop is like this so that the .... line commands won't all be
# pushed to the last line inserted by the insert_newline.
for (count = lc_count; count >= 0; count--)
{
if (count > 0)
{
if (!insert_auto_indent(count == lc_count))
{
retval = LC_NOTOK
break
}
}
if (auto_cleanup)
{
if (count < lc_count)
{
line_command[line] = strrepeat(".", linenumber_width);
update_line_command(line)
}
line++
}
}
goto_pos(lc_line + 1, current_column)
lc_restore = 0
buffer_flags = old_flags
display_redraw()
return retval
}
#
# Line Command function to cleanup inserted lines
#
global function cleanup_insert()
{
local continue_insert
local command
save_position()
goto_line(lc_line)
if (current_line_length == 0) # if the line is empty,
{ # it will be deleted.
if (delete_line())
{
restore_position(1)
return LC_DEL
}
else if (current_line == buffer_last_line && backspace())
{
restore_position(1)
return LC_DEL
}
else
{
restore_position(0)
return LC_NOTOK;
}
}
else
{
delete_line_command(lc_line)
if (lc_restore)
{
restore_position(0) # toss the position we saved &
restore_position(1) # get the position saved earlier
save_position()
if (lc_line+0 == current_line)
{
if (current_line == buffer_last_line)
continue_insert = TRUE
else
{
command = line_command[lc_line+1]
continue_insert = (compress(command, ".") != ".")
}
if (continue_insert)
{
lc_count = 1 # if cursor is on last line inserted,
lc_restore = 0
return insert_lines(1) # insert another line
}
lc_line++
}
}
else
restore_position(1) # put the cursor back wher it was!
}
return LC_OK
}
#
# Line Command Function to validate line labels.
#
global function validate_label()
{
local line
if ( index(lc_command, " ") ) # Labels can't have spaces in them.
{
lc_error_msg = "Invalid label \"%s\" placed on line %d"
return LC_ERROR
}
else
{
for (line in line_command)
{
if ( index(line_command[line], lc_command) && line != lc_line)
{
lc_error_msg = "Duplicate line label \"%s\" placed in line %d"
return LC_ERROR
}
}
}
return LC_KEEP
}
#
# Line Command function to select lines
#
global function select_lines(adjust_count)
{
local endline
if ((!argcount() || adjust_count) && lc_arg)
lc_count = lc_arg
if (lc_count >= 0)
endline = lc_line + lc_count - 1
else
endline = lc_line + lc_count + 1
if (lc_line < endline)
{
create_linecol_selection(LINE_SELECTION, lc_line, 1, endline, 1)
goto_line(lc_line)
}
else
{
create_linecol_selection(LINE_SELECTION, endline, 1, lc_line, 1)
goto_line(endline)
}
return LC_OK
}
#
# Line Command function to select cols
#
global function select_cols(adjust_count)
{
local startoff
local endoff
if ((!argcount() || adjust_count) && lc_arg)
lc_count = lc_arg
create_source_marks(1)
startoff = mark_to_offset(tr_src_start)
endoff = mark_to_offset(tr_src_end)
create_offset_selection(COLUMN_SELECTION, startoff, endoff)
goto_mark(tr_src_start) # Leave the cursor at the start of the block
reset_transfer(LC_KEEP, 0, 1)
return LC_OK
}
## shift lines in the current buffer left
#
global function lshift_cols()
{
return lshift_lines(1)
}
global function lshift_data()
{
return lshift_lines(0)
}
local function lshift_lines(shift_cols)
{
if ( and(buffer_flags, BUFFER_READ_ONLY) )
{
lc_error_msg = "Read only file."
return LC_ERROR
}
else
{
select_lines(0)
outdent_columns(lc_arg ? lc_arg : 2) # , shift_cols)
remove_selection()
return LC_OK
}
}
## shift lines in the current buffer right
#
global function rshift_cols()
{
return rshift_lines(1)
}
global function rshift_data()
{
return rshift_lines(0)
}
local function rshift_lines(shift_cols)
{
if ( and(buffer_flags, BUFFER_READ_ONLY) )
{
lc_error_msg = "Read only file."
return LC_ERROR
}
else
{
select_lines(0)
indent_columns(lc_arg ? lc_arg : 2) # , shift_cols)
remove_selection()
return LC_OK
}
}
## alter case sense of lines in the current buffer
# non-alphabetic characters are unaffected
#
global function ucase_lines()
{
local ch
if ( and(buffer_flags, BUFFER_READ_ONLY) )
{
lc_error_msg = "Read only file."
return LC_ERROR
}
else
{
message("Uppercasing Lines...")
lgetc_init()
while(( ch = lgetc() ))
{
if( islower( ch ))
{
ch = toupper( ch )
lputc( ch )
}
}
lgetc_done()
if (lc_line <= 1 || lc_line + lc_count <= 1) # Fix strange bug that causes
{ # the window to redraw screwy
display_update()
display_redraw()
}
show_message()
return LC_OK
}
}
function lcase_lines()
{
local ch
if ( and(buffer_flags, BUFFER_READ_ONLY) )
{
lc_error_msg = "Read only file."
return LC_ERROR
}
else
{
message("Lowercasing Lines...")
lgetc_init()
while(( ch = lgetc() ))
{
if( isupper( ch ))
{
ch = tolower( ch )
lputc( ch )
}
}
lgetc_done()
if (lc_line <= 1 || lc_line + lc_count <= 1) # Fix strange bug that causes
{ # the window to redraw screwy
display_update()
display_redraw()
}
show_message()
return LC_OK
}
}
## lgetc(), lputc( ch ), lgetc_init(), lgetc_done()
#
# This collection of functions facilitates the sequential replacement
# of all characters within a marked block of lines.
#
# Normal usage:
#
# lgetc_init()
# while (( ch = lgetc())
# if ( P( ch ))
# lputc( F( ch ))
# lgetc_done()
#
local lgetc_y0, lgetc_y1, lgetc_offset
local function lgetc()
{
local ch
restore_position( 0 ) # pop previously saved
# test for past end of selection
if( buffer_offset >= lgetc_offset )
return ""
ch = read_buffer( 1 )
save_position()
next_char()
if( !ch )
ch = "\n"
return ch
}
# replace the character in the buffer most recently returned by lgetc
#
local function lputc( ch )
{
restore_position( 1 )
insert_string( ch )
delete_chars(1)
save_position()
}
# initialize a collection of variables for lgetc()/lputc() usage.
# Places the cursor at the upper left corner, and saves the
# original position on the save_position stack.
#
local function lgetc_init()
{
local tmp
save_position() # original position of selection
# get and remember starting & ending marks & normalize
# their locations
#
if ( tr_src_start && tr_src_end )
{
goto_mark( tr_src_start )
lgetc_y0 = current_line
goto_mark( tr_src_end )
goto_bol()
lgetc_y1 = current_line
}
else
{
if (lc_arg+0 != 0)
lc_count = lc_arg+0
else if (lc_count+0 == 0)
lc_count = 1
lgetc_y0 = lc_line + 0
lgetc_y1 = lgetc_y0 + lc_count + ((lc_count+0 > 0) ? -1 : +1)
}
if (lgetc_y0 > lgetc_y1)
{
tmp = lgetc_y0
lgetc_y0 = lgetc_y1
lgetc_y1 = tmp
}
# save first byte offset past selection
if (lgetc_y1 >= buffer_last_line)
lgetc_offset = buffer_size
else
{
goto_pos( lgetc_y1 + 1, 1 )
lgetc_offset = buffer_offset
}
goto_pos( lgetc_y0, 1 )
if ( and( buffer_flags, BUFFER_IN_VIRTUAL_SPACE ))
next_char()
# lgetc() expects to discard a previously saved position:
save_position()
}
# clean up the save_position stack and restore the original cursor position
#
local function lgetc_done()
{
restore_position( 1 )
}
#
# Debugging Function to display the contents of the mark stack
#
global function dump_marks()
{
local command
local i
for(command in lc_mark)
{
cvdebug("Mark[%s] -> Buffer = %d, Mark = %d, Line = %d, Num = %d",
command, lc_mark[command].buffer, lc_mark[command].mark,
mark_line(lc_mark[command].mark), lc_mark[command].num)
for(i in lc_mark[command])
{
if (i != "buffer" && i != "mark" && i != "num")
cvdebug("Mark[%s][%s] = %s", command, i, lc_mark[command][i])
}
}
}