home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / p2demo21.exe / PEL / LINECMDS.PEL < prev    next >
Text File  |  1995-04-20  |  52KB  |  1,916 lines

  1. # $Header:   P:\source\wmacros\linecmds.pev   1.69.1.0   20 Apr 1995 11:32:54   WALKER  $
  2.  
  3. ##############################################################################
  4. #
  5. #       Compuware Corporation
  6. #         31440 Northwestern Highway
  7. #           Farmington Hills, Michigan 48334-2564
  8. #
  9. #   This source code listing contains information that is
  10. #   proprietary to Compuware Corporation and may not be copied
  11. #   duplicated, translated, transmitted, stored, retrieved
  12. #   or in any manner or by any method conveyed or disclosed
  13. #   to a third party or parties without express written
  14. #   permission from Compuware Corporation.
  15. #
  16. #  
  17. ##############################################################################
  18.  
  19. #### $Workfile:   linecmds.pel  $: Support for Line Commands
  20.  
  21. #
  22. # Values returned by functions that process Line Commands
  23. #
  24. global LC_OK      = 1 # = Line Command processed Sucessfully
  25. global LC_DEL     = 2 # = Line(s) were deleted
  26. global LC_INS     = 3 # = Line(s) were inserted
  27. global LC_MOD     = 4 # = Line(s) were modified, restart LC processing
  28. global LC_REDRAW  = 5 # = Line(s) were modified, redraw the window
  29. global LC_TRASHED = 6 # = Line Command Processing was interrupted - start over
  30. global LC_KEEP    = 7 # = Keep the Line Command
  31. global LC_NOTOK   = 8 # = Error in Line Command - DO NOT display lc_error_msg
  32. global LC_ERROR   = 9 # = Error in Line Command - display lc_error_msg
  33.  
  34. # Note: for LC_DEL & LC_INS lc_arg contains the # of lines inserted/deleted.
  35.  
  36. #
  37. # Global variables for Line Command Processing
  38. #
  39. global lc                # Table of valid Line Commands -> functions.
  40. global lc_arg       = 0  # Numeric argument for the current command
  41. global lc_line      = 0  # Line the current command is on
  42. global lc_command   = 0  # The current command.
  43. global lc_restore   = 1  # Set to Zero when a Line Commands positions cursor.
  44. global lc_error_msg = "" # Error message to display in an error
  45. global lc_message   = "" # Message to display after processing line commands.
  46. global lc_count     = 0  # Number of lines marked by a block command.
  47. global lc_last      = 0  # Last line of a mark_1_line command (lc_line+lc_count)
  48.  
  49. #
  50. # Global variables for Transfer Processing
  51. #
  52. local  lc_mark             # Table of block Line Command -> line #.
  53. local  lc_transfer         # Table of valid Transfer Commands -> functions
  54.  
  55. global tr_command     = "" # Transfer Destination    command that's pending
  56. global tr_pending     = "" # Transfer Source (Block) command that's pending
  57. global tr_incomplete  = "" # Transfer Source (Block) command that's incomplete
  58.  
  59. global tr_count       = 0  # Number of lines in source block
  60. global tr_after       = 1  # TRUE = transfer after tr_line else before tr_line
  61.  
  62. global tr_src_start   = 0  # Bookmark marking the start to the source block
  63. global tr_src_end     = 0  # Bookmark marking the end   of the source block
  64. global tr_src_buffer  = 0  # Buffer the source block is in
  65. global tr_dest_mark   = 0  # Bookmark marking the destination Line
  66. global tr_dest_buffer = 0  # Buffer destination line is in
  67. global tr_write_file  = "" # File to write_marked_lines to
  68.  
  69. #
  70. # Values used by mark_lines
  71. #
  72. local  LC_SEP       = "_"
  73. local  LC_1_LINE    = "_1"
  74. local  LC_END_BLOCK = "_2"
  75.  
  76. #
  77. # Function to clear the Line Commands tables
  78. #
  79. global function delete_lc()
  80. {
  81.    delete lc
  82.    delete lc_transfer
  83. }
  84.  
  85. #
  86. # Function to assign actions to Line Commands
  87. #
  88. global function assign_lc(command, action)
  89. {
  90.    lc[command] = action
  91. }
  92.  
  93. #
  94. # Function to assign actions to Transfer Commands
  95. #
  96. global function assign_transfer(command, action)
  97. {
  98.    lc_transfer[command] = action
  99. }
  100.  
  101. #
  102. # Function to reset Line Commands,
  103. #
  104. global function reset_line_commands(include_labels, fid)
  105. {
  106.    local line
  107.    local start_buffer
  108.  
  109.    if (current_buffer)
  110.    {
  111.       start_buffer = current_buffer
  112.       do                                     # delete all cmds in all buffers
  113.       {
  114.          if (!(and(buffer_flags, BUFFER_SYSTEM))) 
  115.          {
  116.             if (argcount() > 1 && fid)
  117.                execute_function( fid )
  118.             else
  119.             {
  120.                if (argcount() && include_labels)
  121.                   delete line_command        # delete all line-commands.
  122.                else
  123.                {                             # delete line-commands, but not
  124.                   for (line in line_command) # labels.
  125.                   {
  126.                      if (substr(trim(ltrim(line_command[line])),1,1) != ".")
  127.                         delete_line_command(line)
  128.                   }
  129.                }
  130.                linecommands_changed = 0      # reset changed flag.
  131.             }
  132.          }
  133.       } while( next_buffer("", 1, 1) != start_buffer)
  134.    }
  135.  
  136.    if (argcount() > 1 && fid)                # process any leftover commands
  137.       process_line_commands()
  138.    else
  139.    {
  140.       delete lc_mark                         # delete all marks.
  141.       reset_transfer()                       # Reset any pending transfers
  142.    }
  143.  
  144.    display_update()                          # make sure redraw works
  145.    display_redraw()                          # redraw all windows
  146. }
  147.  
  148. #
  149. # Global Function to reset the transfer variables.
  150. #
  151. global function reset_transfer(result, dest_only, source_only, kill_marks)
  152. {
  153.    local pass2
  154.    local start_line
  155.    local lost_mark
  156.    local save_buffer = current_buffer
  157.  
  158.    if (argcount() < 2 || !source_only)
  159.    {
  160.       if (tr_dest_buffer && tr_dest_mark)
  161.       {
  162.          current_buffer = tr_dest_buffer
  163.          if (argcount() == 0 || result != LC_KEEP)
  164.             delete_line_command(mark_line(tr_dest_mark))
  165.    
  166.          delete_mark(tr_dest_mark)
  167.          tr_dest_mark = 0
  168.       }
  169.    
  170.       tr_after       = 1
  171.       tr_dest_buffer = 0
  172.       tr_command     = ""
  173.    }
  174.  
  175.    if (argcount() < 3 || !dest_only)
  176.    {
  177.       if (tr_src_buffer && tr_src_start)
  178.       {
  179.          current_buffer = tr_src_buffer
  180.          if (argcount() == 0 || result != LC_KEEP)
  181.             delete_line_command(mark_line(tr_src_start))
  182.    
  183.          delete_mark(tr_src_start)
  184.          tr_src_start = 0
  185.       }
  186.    
  187.       if (tr_src_buffer && tr_src_end)
  188.       {
  189.          current_buffer = tr_src_buffer
  190.          if (argcount() == 0 || result != LC_KEEP)
  191.             delete_line_command(mark_line(tr_src_end))
  192.    
  193.          delete_mark(tr_src_end)
  194.          tr_src_end = 0
  195.       }
  196.    
  197.       tr_src_buffer  = 0
  198.       tr_pending     = ""
  199.       tr_incomplete  = ""
  200.    }
  201.  
  202.    if (argcount() > 3 && kill_marks)
  203.       delete lc_mark
  204.  
  205.    tr_count       = 0
  206.    current_buffer = save_buffer
  207.  
  208.    show_message()
  209. }
  210.  
  211. #
  212. # Function to process Line Commands,
  213. #
  214. #     For each line_command, it is looked up in the lc table to find the
  215. #     PEL function to execute.  That function is executed, it's return
  216. #     code is validated and the appropriate action is executed.
  217. #
  218. global function process_line_commands(find_source)
  219. {
  220.    local i
  221.    local len
  222.    local line
  223.    local cmnd
  224.    local char
  225.    local command
  226.    local deleted
  227.    local modified
  228.    local adjustment
  229.    local ex_command
  230.    local redraw_flag = FALSE
  231.    local lines_added = FALSE
  232.    local last_line   = "0"
  233.    local numbers     = "0123456789-" # allow - numbers (enhancement to ISPF)
  234.    local result      = LC_OK
  235.  
  236.    lc_message   = ""
  237.    lc_error_msg = ""
  238.    find_source  = (argcount() && find_source)
  239.  
  240.    if (!find_source)
  241.    {
  242.       if (linecommands_changed)
  243.          update_marks()
  244.       else
  245.          return TRUE
  246.    }
  247.  
  248.    lc_restore  = 1
  249.    save_position()
  250.  
  251.    do
  252.    {
  253.       modified   = FALSE
  254.       adjustment = 0
  255.       lc_last    = 0
  256.  
  257.       for (lc_line in line_command)
  258.       {
  259.          if (lc_line < last_line)
  260.             continue
  261.          else
  262.          {
  263.             lc_line += adjustment
  264.  
  265.             do            # if a line is deleted, check it again in
  266.             {             # case the next line has a command on it
  267.                deleted    = FALSE
  268.                command    = toupper(trim(ltrim(line_command[lc_line])))
  269.                lc_command = trim(trim(command, numbers))
  270.                len        = length(lc_command)
  271.  
  272.                if (length(command) == 0) # Nothing here.
  273.                {
  274.                   if (length(line_command[lc_line]))
  275.                      delete_line_command(lc_line)
  276.  
  277.                   continue
  278.                }
  279.                else if (len == 0)
  280.                {
  281.                   line_command[lc_line] = command
  282.          
  283.                   refresh_display()
  284.                   restore_position(1)
  285.                   if (current_column < 1)
  286.                      goto_bol()
  287.                   goto_line(lc_line)
  288.                   goto_bolc()
  289.                   error("Invalid line command %s on line %d", command, lc_line)
  290.                   return
  291.                }
  292.                else
  293.                {
  294.                   lc_count = 1
  295.                   if (len != length(command))
  296.                      lc_arg = substr(command, len + 1) + 0
  297.                   else
  298.                      lc_arg = 0
  299.  
  300.                   # Check for special commands
  301.                   char = substr(command, 1, 1)
  302.                   if (char == "=")
  303.                      ex_command = "=flag"
  304.  
  305.                   else if (char == ".")
  306.                   {
  307.                      if (compress(command, ".") == ".")
  308.                         ex_command = ".insert"
  309.                      else
  310.                         ex_command = ".label"
  311.                   }
  312.                   else
  313.                      ex_command = lc_command
  314.  
  315.                   if (ex_command in lc)
  316.                   {
  317.                      if (lc[ex_command])
  318.                      {
  319.                         if (ex_command == ".label")
  320.                            result = execute_function(lc[ex_command])
  321.                         else if (length(tr_incomplete) && lc_command != tr_incomplete)
  322.                         {
  323.                            lc_error_msg = "Unable to execute %s on line %d, " tr_incomplete " Incomplete"
  324.                            result       = LC_ERROR
  325.                         }
  326.                         else if (lc_line+0 <= lc_last)
  327.                         {
  328.                            lc_error_msg = "Unable to execute %s on line %d, Inside a " tr_pending " range."
  329.                            result       = LC_ERROR
  330.                         }
  331.                         else
  332.                         {
  333.                            delete_line_command(lc_line)
  334.                            result = execute_function(lc[ex_command])
  335.                         }
  336.                      }
  337.                      else
  338.                         result = LC_KEEP
  339.                   }
  340.                   else
  341.                   {
  342.                      lc_error_msg = "Invalid Line Command %s on line %d"
  343.                      result       = LC_ERROR
  344.                   }
  345.  
  346.                   # Performing any line command on the first line of
  347.                   # the buffer screws up the window, so redraw it.
  348.  
  349.                   if (result <= LC_KEEP && (lc_line + 0        <= 1 ||
  350.                                             lc_line + lc_count <= 1))
  351.                   {
  352.                      redraw_flag = TRUE
  353.                   }
  354.  
  355.                   if (result == LC_INS)
  356.                   {
  357.                      adjustment += lc_count
  358.                      lines_added = TRUE
  359.                   }
  360.                   else if (result == LC_DEL)
  361.                   {
  362.                      adjustment -= lc_count
  363.                      deleted     = TRUE
  364.                   }
  365.                   else if (result == LC_MOD)
  366.                   {
  367.                      modified  = TRUE
  368.                      last_line = lc_line
  369.                      break
  370.                   }
  371.                   else if (result == LC_REDRAW)
  372.                   {
  373.                      modified    = TRUE
  374.                      redraw_flag = TRUE
  375.                      last_line   = lc_line
  376.                      break
  377.                   }
  378.                   else if (result == LC_TRASHED)
  379.                   {
  380.                      modified  = TRUE
  381.                      last_line = "0" # Start Over!
  382.                      break
  383.                   }
  384.                   else if (result == LC_KEEP)
  385.                   {
  386.                      redraw_flag           = TRUE    # If the command is KEPT,
  387.                      line_command[lc_line] = command # redraw the window since
  388.                      update_line_command(lc_line)    # this sometimes causes
  389.                   }                                  # display problems.
  390.                   else if (result != LC_OK)
  391.                   {
  392.                      line_command[lc_line] = command
  393.                      update_line_command(lc_line)
  394.  
  395.                      refresh_display()
  396.                      restore_position(1)
  397.                      if (current_column < 1)
  398.                         goto_bol()
  399.                      goto_line(lc_line)
  400.                      goto_bolc()
  401.  
  402.                      if (result == LC_ERROR)
  403.                      {
  404.                         if (length(lc_error_msg))
  405.                            error(lc_error_msg, command, lc_line)
  406.                         else
  407.                            error("Error in Line Command %s on Line %d",
  408.                                  command, lc_line)
  409.                      }
  410.                      else if (result == 0)
  411.                         error("Error: Unable to execute %s(%d) on Line %d", \
  412.                               lc[lc_command], lc_arg, lc_line)
  413.  
  414.                      else if (result != LC_NOTOK)
  415.                         error("Error %d in Line Command %s(%s) on Line %d", \
  416.                                result, lc[lc_command], command, lc_line)
  417.                      return
  418.                   }
  419.                }
  420.             } while (deleted)
  421.          }
  422.       }
  423.    } while (modified)
  424.  
  425.    restore_position(lc_restore)
  426.    if (lc_restore && current_column < 1)
  427.       goto_bol()
  428.  
  429.    if (!find_source && (tr_count || length(tr_command)))
  430.       perform_transfer()
  431.  
  432.    if (!lines_added && linecommands_changed) # if lines were added they might
  433.       update_marks()                         # have commands
  434.  
  435.    if (redraw_flag)
  436.       refresh_display()
  437.  
  438.    if (!find_source)
  439.       show_message()
  440.  
  441.    return (result > 0 && result < LC_NOTOK)
  442. }
  443.  
  444. #
  445. # Function to update the message line.
  446. #
  447. global function show_message(clear)
  448. {
  449.    local msg
  450.    local inBuffer
  451.    local cbuffer
  452.  
  453.    if (length(lc_message))
  454.       message(lc_message)
  455.    else
  456.    {
  457.       if (length(tr_incomplete))
  458.       {
  459.          msg      = sprintf("%s Incomplete", tr_incomplete)
  460.          inBuffer = tr_src_buffer
  461.       }
  462.       else if (length(tr_pending))
  463.       {
  464.          msg      = sprintf("%s Pending", tr_pending)
  465.          inBuffer = tr_src_buffer
  466.       }
  467.       else if (length(tr_command))
  468.       {
  469.          msg      = sprintf("%s Pending", tr_command)
  470.          inBuffer = tr_dest_buffer
  471.       }
  472.  
  473.       if (length(msg))
  474.       {
  475.          if (inBuffer && inBuffer != current_buffer)
  476.          {
  477.             cbuffer = current_buffer
  478.             current_buffer = inBuffer
  479.             msg = sprintf("%s in %s", msg, buffer_name)
  480.             current_buffer = cbuffer
  481.          }
  482.          notify(msg)
  483.       }
  484.       else if (!argcount() || clear)
  485.          message("")
  486.    }
  487. }
  488.  
  489. #
  490. # Function to completely re-draw the display to correct for the bug that
  491. # causes the window to re-drawn incorrectly if there is a line command left
  492. # on the first line.
  493. #
  494. local function refresh_display()
  495. {
  496.    display_update()
  497.    display_redraw()
  498.    display_redraw()
  499. }
  500.  
  501. #
  502. # Function to clear any deleted or altered marks.
  503. #
  504. local function update_marks()
  505. {
  506.    local command
  507.    local cmnd
  508.    local line
  509.    local i
  510.  
  511.    for (command in lc_mark)
  512.    {
  513.       if ( lc_mark[command].buffer == current_buffer )
  514.       {
  515.          i = index(command, LC_SEP)
  516.          if (i)
  517.             cmnd = substr(command, 1, i-1)
  518.          else
  519.             cmnd = command
  520.  
  521.          line = mark_line(lc_mark[command].mark)
  522.  
  523.          if (trim(line_command[line], " 0123456789") != cmnd)
  524.          {
  525.             delete lc_mark[command]
  526.             if (tr_pending == cmnd)
  527.             {
  528.                 tr_pending = ""
  529.                 reset_transfer(0, FALSE, TRUE)
  530.             }
  531.             else if (tr_incomplete == cmnd)
  532.             {
  533.                 tr_incomplete = ""
  534.                 show_message()
  535.             }
  536.          }
  537.       }
  538.    }
  539.  
  540.    #
  541.    # check the destination (if any)
  542.    #
  543.    if (tr_dest_mark && length(tr_command) && tr_dest_buffer == current_buffer)
  544.    {
  545.       line = mark_line(tr_dest_mark)
  546.       if (trim(line_command[line], " 0123456789") != tr_command)
  547.       {
  548.          tr_command = ""
  549.          reset_transfer(0, TRUE, FALSE)
  550.       }
  551.    }
  552.    linecommands_changed = 0
  553. }
  554.  
  555. #
  556. # Function to perform the actual line transfer.
  557. #
  558. global function perform_transfer(func)
  559. {
  560.    local i
  561.    local result
  562.    local buffer
  563.    local command
  564.    local command2
  565.  
  566.    local start_buffer = current_buffer
  567.    local found        = FALSE
  568.  
  569.    while (TRUE)
  570.    {
  571.       for (command in lc_mark)
  572.       {
  573.          i = index(command, LC_1_LINE)
  574.          if (i)
  575.          {
  576.             command2 = substr(command, 1, i-1)
  577.             if (command2 in lc_transfer)
  578.             {
  579.                found          = TRUE
  580.                tr_src_buffer  = lc_mark[command].buffer
  581.                tr_src_start   = lc_mark[command].mark
  582.                tr_count       = lc_mark[command].num
  583.                current_buffer = tr_src_buffer
  584.                tr_src_end     = create_mark(pick_unused_mark(),
  585.                                             mark_line(tr_src_start) + tr_count - 1,
  586.                                             0x7FFFFFFF)
  587.  
  588.                if (check_transfer())
  589.                {
  590.                   delete_line_command(mark_line(tr_src_start))
  591.                   delete lc_mark[command]
  592.  
  593.                   if (tr_dest_buffer)
  594.                   {
  595.                      current_buffer = tr_dest_buffer
  596.                      delete_line_command(mark_line(tr_dest_mark))
  597.                   }
  598.  
  599.                   if (argcount() && length(func))
  600.                      result = execute_function(lc_transfer[command2] " " func)
  601.                   else
  602.                      result = execute_function(lc_transfer[command2])
  603.                }
  604.                else
  605.                   result = LC_ERROR
  606.  
  607.                break
  608.             }
  609.          }
  610.          else if (!index(command, LC_END_BLOCK))
  611.          {
  612.             if (command in lc_transfer)
  613.             {
  614.                command2 = command LC_END_BLOCK
  615.                if (command2 in lc_mark)
  616.                {
  617.                   found         = TRUE
  618.                   tr_src_buffer = lc_mark[command].buffer
  619.                   tr_src_start  = lc_mark[command].mark
  620.                   tr_src_end    = lc_mark[command2].mark
  621.                   tr_count      = mark_line(tr_src_end)   -
  622.                                   mark_line(tr_src_start) + 1
  623.  
  624.                   if (check_transfer())
  625.                   {
  626.                      current_buffer = tr_src_buffer
  627.                      delete_line_command(mark_line(tr_src_start))
  628.                      delete_line_command(mark_line(tr_src_end))
  629.                      delete lc_mark[command]
  630.                      delete lc_mark[command2]
  631.  
  632.                      if (tr_dest_buffer)
  633.                      {
  634.                         current_buffer = tr_dest_buffer
  635.                         delete_line_command(mark_line(tr_dest_mark))
  636.                      }
  637.  
  638.                      if (argcount() && length(func))
  639.                         result = execute_function(lc_transfer[command] " " func)
  640.                      else
  641.                         result = execute_function(lc_transfer[command])
  642.                   }
  643.                   else
  644.                      result = LC_ERROR
  645.  
  646.                   break
  647.                }
  648.             }
  649.          }
  650.       }
  651.  
  652.       if (found)
  653.          break
  654.       else if (prev_buffer() == start_buffer)
  655.          break
  656.       else if (!process_line_commands(1))
  657.          return LC_ERROR;
  658.    }
  659.  
  660.    if (found)
  661.    {
  662.       if (result < LC_NOTOK)
  663.       {
  664.          if (argcount() && length(func))
  665.             reset_transfer(result, FALSE, TRUE) # Source Only
  666.          else
  667.             reset_transfer(result)              # Source & Dest
  668.       }
  669.    }
  670.  
  671.    current_buffer = start_buffer
  672.    display_update()                      # make sure redraw works
  673.    display_redraw()                      # redraw all windows.
  674.    return result
  675. }
  676.  
  677. #
  678. # Function to ensure a transfer is valid
  679. #
  680. local function check_transfer()
  681. {
  682.    local dest_line
  683.    local save_buffer
  684.  
  685.    if (tr_dest_buffer == tr_src_buffer)
  686.    {
  687.       save_buffer    = current_buffer
  688.       current_buffer = tr_dest_buffer
  689.       dest_line      = mark_line(tr_dest_mark)
  690.       if (dest_line < mark_line(tr_src_start) ||
  691.           dest_line > mark_line(tr_src_end))
  692.       {
  693.          current_buffer = save_buffer
  694.          return TRUE
  695.       }
  696.       else
  697.       {
  698.          if (lc_last && tr_pending)
  699.          {
  700.             lc_error_msg = sprintf("The %s MUST be outside the %s range.",
  701.                                     tr_command, tr_pending)
  702.          }
  703.          else
  704.          {
  705.             lc_error_msg = sprintf("The %s MUST be outside the %s's",
  706.                                     tr_command, lc_command)
  707.          }
  708.  
  709.          if (tr_dest_mark)
  710.          {
  711.             delete_mark(tr_dest_mark)
  712.             tr_dest_mark = 0
  713.          }
  714.          tr_dest_buffer = 0
  715.          tr_command     = ""
  716.          tr_count       = 0
  717.          current_buffer = save_buffer
  718.          return FALSE
  719.       }
  720.    }
  721.    else
  722.       return TRUE
  723. }
  724.  
  725. #
  726. # Line Command function to mark the ends of a block.
  727. #
  728. global function mark_lines(exec)
  729. {
  730.    if (argcount())
  731.       return mark_cols(0, 0, exec)
  732.    else
  733.       return mark_cols()
  734. }
  735.  
  736. global function mark_cols(col1, col2, exec)
  737. {
  738.    local mark
  739.    local start
  740.    local result
  741.    local buffer
  742.    local command2
  743.    local useCols   = (argcount() >= 1 && (col1 || col2))
  744.    local fromcol   = (argcount() >= 1 && col1) ? col1 : 1
  745.    local tocol     = (argcount() >= 2 && col2) ? col2 : 0x7FFFFFFF
  746.  
  747.    if (lc_command in lc_mark)
  748.    {
  749.       buffer = lc_mark[lc_command].buffer
  750.    
  751.       if (buffer == current_buffer)
  752.       {
  753.          mark = lc_mark[lc_command].mark
  754.    
  755.          if (mark_line(mark) == lc_line+0 && !useCols)
  756.             return LC_KEEP
  757.          else
  758.          {
  759.             if (tr_incomplete == lc_command)
  760.             {
  761.                 tr_incomplete = ""
  762.                 show_message()
  763.             }
  764.    
  765.             command2 = lc_command LC_END_BLOCK
  766.       
  767.             if (command2 in lc_mark)
  768.             {
  769.                mark = lc_mark[command2].mark
  770.    
  771.                if (mark_line(mark) == lc_line+0)
  772.                   return LC_KEEP
  773.                else
  774.                {
  775.                   lc_error_msg = "Too Many %s's!"
  776.                   return LC_ERROR
  777.                }
  778.             }
  779.             else
  780.             {
  781.                lc_mark[command2].arg    = lc_arg
  782.                lc_mark[command2].num    = lc_count
  783.                lc_mark[command2].buffer = current_buffer
  784.                lc_mark[command2].mark   = create_mark(pick_unused_mark(),
  785.                                                       lc_line, tocol)
  786.    
  787.                if (argcount() > 2 && length(exec))
  788.                {
  789.                   start      = mark_line(lc_mark[lc_command].mark)
  790.                   lc_arg     = max(lc_arg+0, lc_mark[lc_command].arg+0)
  791.                   lc_count   = start - lc_line - 1
  792.                   tr_command = lc_command
  793.                   result     = execute_function(exec)
  794.  
  795.                   if (result < LC_KEEP)
  796.                   {
  797.                      delete_line_command(mark_line(lc_mark[lc_command].mark))
  798.                      delete_line_command(mark_line(lc_mark[command2].mark))
  799.                   }
  800.  
  801.                   delete_mark(lc_mark[lc_command].mark)
  802.                   delete_mark(lc_mark[command2].mark)
  803.  
  804.                   delete lc_mark[lc_command]
  805.                   delete lc_mark[command2]
  806.  
  807.                   tr_command = ""
  808.                   return result
  809.                }
  810.                else
  811.                {
  812.                   tr_pending    = lc_command
  813.                   tr_src_buffer = current_buffer
  814.                   return LC_KEEP
  815.                }
  816.             }
  817.          }
  818.       }
  819.       else
  820.       {
  821.          lc_error_msg = "Both %s's MUST be in the same buffer!"
  822.          return LC_ERROR
  823.       }
  824.    }
  825.    else
  826.    {
  827.       tr_incomplete              = lc_command
  828.       tr_src_buffer              = current_buffer
  829.       lc_mark[lc_command].arg    = lc_arg
  830.       lc_mark[lc_command].num    = lc_count
  831.       lc_mark[lc_command].buffer = current_buffer
  832.       lc_mark[lc_command].mark   = create_mark(pick_unused_mark(),
  833.                                                lc_line, fromcol)
  834.       return LC_KEEP
  835.    }
  836. }
  837.  
  838. #
  839. # Line Command function to mark one line
  840. #
  841. global function mark_1_line()
  842. {
  843.    local mark
  844.    local buffer
  845.    local command = lc_command LC_1_LINE
  846.  
  847.    if (command in lc_mark)
  848.    {
  849.       buffer = lc_mark[command].buffer
  850.       mark   = lc_mark[command].mark
  851.  
  852.       if (buffer == current_buffer && mark_line(mark) == lc_line+0)
  853.          return LC_KEEP
  854.       else
  855.       {
  856.          lc_error_msg = "Too Many %s's!"
  857.          return LC_ERROR
  858.       }
  859.    }
  860.    else
  861.    {
  862.       if (lc_arg+0 != 0)
  863.          lc_count = lc_arg+0
  864.       else if (lc_count+0 == 0)
  865.          lc_count = 1
  866.  
  867.       lc_mark[command].buffer = current_buffer
  868.       lc_mark[command].mark   = create_mark(pick_unused_mark(), lc_line, 1)
  869.       lc_mark[command].num    = lc_count
  870.       tr_src_buffer           = current_buffer
  871.       tr_pending              = lc_command
  872.       lc_last                 = lc_line + lc_count > 0 ? lc_count - 1 \
  873.                                                        : lc_count + 1
  874.       return LC_KEEP
  875.    }
  876. }
  877.  
  878. #
  879. #
  880. # Line Command function to transfer lines.
  881. #
  882. global function transfer_lines(where)
  883. {
  884.    local ch
  885.  
  886.    if (tr_dest_mark && mark_line(tr_dest_mark) != lc_line+0)
  887.    {
  888.       lc_error_msg = sprintf("ERROR: %s already pending!", tr_command)
  889.       return LC_ERROR
  890.    }
  891.    else
  892.    {
  893.       if (!tr_dest_mark)
  894.          tr_dest_mark = create_mark(pick_unused_mark(), lc_line, 1)
  895.  
  896.       tr_dest_buffer = current_buffer
  897.       tr_src_buffer  = 0
  898.       tr_src_start   = 0
  899.       tr_src_end     = 0
  900.  
  901.       tr_count       = 1                   # indicate a pending transfer
  902.       tr_command     = lc_command
  903.       tr_after       = FALSE
  904.  
  905.       if (argcount() && length(where))
  906.       {
  907.          ch = toupper(substr(where, 1, 1))
  908.          if (ch == "1" || ch == "A" || ch == "F")
  909.             tr_after = TRUE
  910.       }
  911.       return LC_KEEP
  912.    }
  913. }
  914.  
  915. #
  916. # Transfer function to copy lines
  917. #
  918. global function copy_to_dest(func)
  919. {
  920.    local ret
  921.    local pos
  922.    local line
  923.    local old_flags
  924.    local start, end
  925.    local src_on_last_line   = FALSE
  926.    local dest_on_last_line  = FALSE
  927.    local kill_last_src_line = FALSE
  928.  
  929.    if (tr_src_buffer && tr_src_start && tr_src_end)
  930.    {
  931.       save_position()
  932.  
  933.       if (argcount() && length(func))
  934.          tr_count = execute_function(func)
  935.       else if (tr_dest_buffer && tr_dest_mark)
  936.       {
  937.          current_buffer = tr_src_buffer
  938.          if (mark_line(tr_src_end) >= buffer_last_line)
  939.          {
  940.             if (and(buffer_flags, BUFFER_READ_ONLY))
  941.             {
  942.                src_on_last_line = TRUE
  943.                # We can't avoid the nasty bug in transfer() that scrambles
  944.                # data when the source block hits the end of the file so,
  945.                # it's an error!
  946.                tr_count     = 0
  947.                lc_error_msg = "Unable to copy the last line of a Read only file."
  948.                restore_position(TRUE)
  949.                return LC_ERROR
  950.             }
  951.             else
  952.             {
  953.                # Avoid a nasty bug in transfer() that scrambles data when
  954.                # the source block hits the end of the file.
  955.                old_flags    = buffer_flags
  956.                buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
  957.                goto_buffer_bottom()
  958.                open_line()
  959.                buffer_flags       = old_flags
  960.                kill_last_src_line = TRUE
  961.             }
  962.          }
  963.          current_buffer = tr_dest_buffer
  964.  
  965.          # make sure the dest buffer is NOT read-only so it won't play
  966.          # havok with the newline games we might need to play.
  967.          if ( and(buffer_flags, BUFFER_READ_ONLY) )
  968.          {
  969.             tr_count     = 0
  970.             lc_error_msg = "Read only file."
  971.             restore_position(TRUE)
  972.             return LC_ERROR
  973.          }
  974.  
  975.          goto_mark(tr_dest_mark)
  976.          if (current_line >= buffer_last_line)
  977.          {
  978.             dest_on_last_line = tr_after
  979.             if (dest_on_last_line)
  980.             {
  981.                # if we insert something AFTER the last line, we need to move
  982.                # to the end of the line and save that position so we can
  983.                # insert a newline there if the copy is sucessful.
  984.                goto_eol()
  985.                pos = create_mark(pick_unused_mark())
  986.             }
  987.          }
  988.          else if (tr_after)
  989.             down()
  990.  
  991.          if (src_on_last_line && !dest_on_last_line)
  992.          {
  993.             # mark the next_char which will be the first char after the read.
  994.             # (if we mark this char, it won't be moved by the transfer)
  995.             next_char()
  996.             pos = create_mark(pick_unused_mark())
  997.             prev_char()
  998.          }
  999.  
  1000.          if ((tr_count = transfer(tr_src_buffer, tr_src_start, tr_src_end)))
  1001.          {
  1002.             if (dest_on_last_line || src_on_last_line)
  1003.             {
  1004.                if (dest_on_last_line)
  1005.                {
  1006.                   if (tr_after)
  1007.                      goto_mark(pos) # restore saved pos
  1008.                }
  1009.                else
  1010.                {
  1011.                   goto_mark(pos) # restore saved pos
  1012.                   prev_char()    # backup since we saved the pos of the NEXT char.
  1013.                }
  1014.  
  1015.                # insert a newline in the buffer since the file we read probaby
  1016.                # doesn't have a new as the last char, which would cause the last
  1017.                # line of the file and the next line in the buffer to be joined.
  1018.                # OR - we just inserted the file at the end and the last line of
  1019.                # the buffer just got joined to the first line of the file.
  1020.                old_flags    = buffer_flags
  1021.                buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
  1022.                insert_newline()
  1023.                buffer_flags = old_flags
  1024.  
  1025.                # if we were copying after the last line, we need to move the
  1026.                # dest mark there since the line_command will have been pushed
  1027.                # there by the transfer.
  1028.                if (dest_on_last_line)
  1029.                {
  1030.                   goto_buffer_bottom()
  1031.                   if (tr_after)
  1032.                   {
  1033.                      old_flags    = buffer_flags
  1034.                      buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
  1035.                      backspace()
  1036.                      buffer_flags = old_flags
  1037.                   }
  1038.                   delete_mark(tr_dest_mark)
  1039.                   tr_dest_mark = create_mark(pick_unused_mark())
  1040.                }
  1041.                else if (!tr_after)
  1042.                {
  1043.                   # if we read the data BEFORE the mark, we need to move the mark
  1044.                   # so that reset_transfer() will delete the correct line-command.
  1045.                   delete_mark(tr_dest_mark)
  1046.                   tr_dest_mark = pos
  1047.                }
  1048.             }
  1049.          }
  1050.          if (kill_last_src_line)
  1051.          {
  1052.             current_buffer = tr_src_buffer
  1053.             old_flags      = buffer_flags
  1054.             buffer_flags   = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
  1055.             goto_buffer_bottom()
  1056.             backspace()
  1057.             buffer_flags = old_flags
  1058.          }
  1059.       }
  1060.       else
  1061.       {
  1062.          tr_count     = 0
  1063.          lc_error_msg = "Transfer destination not setup properly!"
  1064.          ret          = LC_ERROR
  1065.       }
  1066.  
  1067.       if (tr_count)
  1068.       {
  1069.          lc_message = "Lines Copied"
  1070.          ret        = LC_INS
  1071.       }
  1072.       else
  1073.          ret = LC_NOTOK
  1074.  
  1075.       restore_position(TRUE)
  1076.       return ret
  1077.    }
  1078.    else
  1079.    {
  1080.       tr_count     = 0
  1081.       lc_error_msg = "Transfer source not setup properly!"
  1082.       return LC_ERROR
  1083.    }
  1084. }
  1085.  
  1086. #
  1087. # Transfer function to move lines
  1088. #
  1089. global function move_to_dest(func)
  1090. {
  1091.    local ret
  1092.  
  1093.    if (tr_src_buffer == tr_dest_buffer && \
  1094.        tr_after ? mark_line(tr_src_start) == mark_line(tr_dest_mark) + 1 \
  1095.                 : mark_line(tr_src_end)   == mark_line(tr_dest_mark) - 1)
  1096.    {
  1097.       tr_count = 0
  1098.       return LC_OK # Lines would be copied to the same place!
  1099.    }
  1100.    else if (tr_src_buffer && tr_src_start && tr_src_end)
  1101.    {
  1102.       if (argcount() && length(func))
  1103.       {
  1104.          tr_count = execute_function(func)
  1105.          ret      = LC_NOTOK
  1106.       }
  1107.       else
  1108.          ret = copy_to_dest()
  1109.  
  1110.       if (tr_count)
  1111.       {
  1112.          delete_marked_lines()
  1113.          lc_message = "Lines Moved"
  1114.          ret        = LC_MOD
  1115.       }
  1116.       return ret
  1117.    }
  1118.    else
  1119.    {
  1120.       tr_count     = 0
  1121.       lc_error_msg = "Transfer source not setup properly!"
  1122.       return LC_ERROR
  1123.    }
  1124. }
  1125.  
  1126. #
  1127. # Transfer Function to delete marked lines when move_to_dest uses transfer().
  1128. #
  1129. global function delete_marked_lines()
  1130. {
  1131.    local line
  1132.    local end_line
  1133.    local old_flags
  1134.    local num_lines
  1135.    local start_line
  1136.    local old_buffer = current_buffer
  1137.  
  1138.    current_buffer   = tr_src_buffer
  1139.    start_line       = mark_line(tr_src_start)
  1140.    end_line         = mark_line(tr_src_end)
  1141.  
  1142.    if (start_line && end_line)
  1143.    {
  1144.       num_lines    = abs(end_line - start_line)
  1145.       old_flags    = buffer_flags
  1146.       buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
  1147.  
  1148.       save_position()
  1149.  
  1150.       if (start_line <= end_line)
  1151.          goto_mark(tr_src_start)
  1152.       else
  1153.       {
  1154.          goto_mark(tr_src_end)
  1155.          goto_bol()
  1156.       }
  1157.  
  1158.       for(line = 0; line <= num_lines; line++)
  1159.       {
  1160.          if (current_line == buffer_last_line)
  1161.          {
  1162.             delete_line()
  1163.             backspace()
  1164.          }
  1165.          else
  1166.             delete_line()
  1167.       }
  1168.  
  1169.       restore_position(TRUE)
  1170.  
  1171.       buffer_flags   = old_flags
  1172.       current_buffer = old_buffer
  1173.       return LC_DEL
  1174.    }
  1175.    else
  1176.    {
  1177.       current_buffer = old_buffer
  1178.       lc_error_msg   = "No lines marked or incomplete block"
  1179.       return LC_ERROR
  1180.    }
  1181. }
  1182.  
  1183. #
  1184. # Transfer Function to write marked lines to the tr_write_file file.
  1185. #
  1186. global function write_marked_lines()
  1187. {
  1188.    local fh
  1189.    local retval
  1190.  
  1191.    if (tr_src_start && tr_src_end)
  1192.    {
  1193.       current_buffer = tr_src_buffer
  1194.       fh             = fopen(tr_write_file, 1)
  1195.       if (fh > -1)
  1196.       {
  1197.          if (fwrite(fh, tr_src_start, distance_between_marks(tr_src_start,
  1198.                                                              tr_src_end)) > -1)
  1199.          {
  1200.             fclose(fh)
  1201.             retval = LC_OK
  1202.          }
  1203.          else
  1204.          {
  1205.             fclose(fh)
  1206.             sprintf( lc_error_msg, "Unable to write %s", tr_write_file)
  1207.             retval = LC_ERROR
  1208.          }
  1209.       }
  1210.       else
  1211.       {
  1212.          sprintf( lc_error_msg, "Unable to open %s", tr_write_file)
  1213.          retval = LC_ERROR
  1214.       }
  1215.       return retval
  1216.    }
  1217.    else
  1218.    {
  1219.       lc_error_msg = "No lines marked or incomplete block"
  1220.       return LC_ERROR
  1221.    }
  1222. }
  1223.  
  1224. #
  1225. # Transfer Function to cut/copy marked lines to the scrap
  1226. #
  1227. global function cut_marked_lines()
  1228. {
  1229.    if (tr_src_start && tr_src_end)
  1230.    {
  1231.       current_buffer = tr_src_buffer
  1232.       begin_selection(LINE_SELECTION, tr_src_start)
  1233.       end_selection(tr_src_end)
  1234.       if (copy_to_scrap())
  1235.          return abs(mark_line(tr_src_end) - mark_line(tr_src_start)) + 1
  1236.       else
  1237.       {
  1238.          sprintf( lc_error_msg, "Unable to CUT lines to the scrap")
  1239.          return 0
  1240.       }
  1241.    }
  1242.    else
  1243.    {
  1244.       lc_error_msg = "No lines marked or incomplete block"
  1245.       return 0
  1246.    }
  1247. }
  1248.  
  1249. #
  1250. # Global Transfer function to create source marks when called from a
  1251. # function called from mark_cols (or mark_lines).
  1252. #
  1253. global function create_source_marks(useCols, one_line_only)
  1254. {
  1255.    local command2
  1256.  
  1257.    tr_src_buffer = current_buffer
  1258.  
  1259.    if (argcount() && useCols && tr_command)
  1260.    {
  1261.       command2     = tr_command LC_END_BLOCK
  1262.       tr_src_start = lc_mark[tr_command].mark
  1263.       tr_src_end   = lc_mark[command2].mark
  1264.    }
  1265.    else if (lc_count >= 0)
  1266.    {
  1267.       tr_src_start = create_mark(pick_unused_mark(), lc_line, 1)
  1268.  
  1269.       if (one_line_only)
  1270.          tr_src_end = create_mark(pick_unused_mark(), lc_line, 0x7FFFFFFF)
  1271.       else
  1272.          tr_src_end = create_mark(pick_unused_mark(), lc_line + lc_count - 1,
  1273.                                                       0x7FFFFFFF)
  1274.    }
  1275.    else
  1276.    {
  1277.       tr_src_start = create_mark(pick_unused_mark(), lc_line + lc_count + 1, 1)
  1278.       tr_src_end   = create_mark(pick_unused_mark(), lc_line, 0x7FFFFFFF)
  1279.    }
  1280. }
  1281.  
  1282. #
  1283. # Line Command function to repeat lines
  1284. #
  1285. global function repeat_lines()
  1286. {
  1287.    local count
  1288.    local result
  1289.  
  1290.    if (lc_arg+0 != 0)
  1291.       lc_count = lc_arg+0
  1292.    else if (lc_count+0 == 0)
  1293.       lc_count = 1
  1294.  
  1295.    tr_after       = 1
  1296.    tr_dest_buffer = current_buffer
  1297.    tr_dest_mark   = create_mark(pick_unused_mark(), lc_line, 1)
  1298.  
  1299.    if (lc_count > 0)
  1300.    {
  1301.       tr_count = 1
  1302.       for (count = 1; count <= lc_count; count++)
  1303.       {
  1304.          create_source_marks(0, 1)
  1305.          result = copy_to_dest()
  1306.          if (result == LC_INS)
  1307.          {
  1308.             delete_mark(tr_src_start); tr_src_start = 0
  1309.             delete_mark(tr_src_end);   tr_src_end   = 0
  1310.          }
  1311.          else
  1312.             break
  1313.       }
  1314.    }
  1315.    else
  1316.    {
  1317.       create_source_marks(0, 1)
  1318.       tr_count = lc_count
  1319.       result   = copy_to_dest()
  1320.    }
  1321.  
  1322.    reset_transfer()
  1323.    return result
  1324. }
  1325.  
  1326. #
  1327. # Line Command function to delete lines
  1328. #
  1329. global function old_delete_lines()
  1330. {
  1331.    local rc
  1332.    local col
  1333.    local line
  1334.    local count
  1335.    local old_flags
  1336.    local on_last_line
  1337.    local retval
  1338.  
  1339.    if (lc_arg+0 != 0)
  1340.       lc_count = lc_arg+0
  1341.    else if (lc_count+0 == 0)
  1342.       lc_count = 1
  1343.  
  1344.    retval = lines_empty()
  1345.  
  1346.    if (retval == LC_OK)
  1347.    {
  1348.       col    = current_column
  1349.       line   = current_line
  1350.       retval = LC_DEL
  1351.  
  1352.       goto_bolc()
  1353.       goto_line(lc_count >= 0 ? lc_line : lc_line + lc_count + 1)
  1354.  
  1355.       for (count = abs(lc_count); count > 0; count--)
  1356.       {
  1357.          on_last_line = (current_line >= buffer_last_line)
  1358.          rc           = delete_line()
  1359.  
  1360.          if (on_last_line)
  1361.          {
  1362.             old_flags    = buffer_flags
  1363.             buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
  1364.             goto_buffer_bottom()
  1365.             backspace()
  1366.             buffer_flags = old_flags
  1367.             break
  1368.          }
  1369.          else if (current_line > buffer_last_line)
  1370.             break
  1371.          else if (!rc)
  1372.          {
  1373.             retval = LC_NOTOK
  1374.             break
  1375.          }
  1376.       }
  1377.       goto_pos(line,col)
  1378.    }
  1379.    return retval
  1380. }
  1381.  
  1382. #
  1383. # Line Command function to delete lines
  1384. #
  1385. global function delete_lines()
  1386. {
  1387.    local retval
  1388.    local old_flags
  1389.  
  1390.    if (lc_arg+0 != 0)
  1391.       lc_count = lc_arg+0
  1392.    else if (lc_count+0 == 0)
  1393.       lc_count = 1
  1394.  
  1395.    retval = lines_empty()
  1396.  
  1397.    if (retval == LC_OK)
  1398.    {
  1399.       select_lines(0)
  1400.       delete_chars()
  1401.       if (lc_line >= buffer_last_line)
  1402.       {
  1403.          old_flags    = buffer_flags
  1404.          buffer_flags = and(buffer_flags, not(BUFFER_OVERTYPE_MODE))
  1405.          goto_buffer_bottom()
  1406.          backspace()
  1407.          buffer_flags = old_flags
  1408.       }
  1409.       retval = LC_DEL
  1410.    }
  1411.    return retval
  1412. }
  1413.  
  1414. # Line Command function to determine if lines have no line commands on them.
  1415. #
  1416. global function lines_empty()
  1417. {
  1418.    local num
  1419.    local line
  1420.    local command
  1421.  
  1422.    local first
  1423.    local last
  1424.  
  1425.    if (lc_count < 0)
  1426.    {
  1427.       first = lc_line + lc_count + 1
  1428.       last  = lc_line + 0
  1429.    }
  1430.    else
  1431.    {
  1432.       first = lc_line + 0
  1433.       last  = lc_line + lc_count - 1
  1434.    }
  1435.  
  1436.    for (line in line_command)
  1437.    {
  1438.       num = atoi(line)
  1439.       if (num >= last)
  1440.          break
  1441.       else if (num > first)
  1442.       {
  1443.          command = ltrim(trim(line_command[line], ". "))
  1444.          if (length(command))
  1445.          {
  1446.             lc_error_msg = sprintf("%s Pending on line %d", command, line)
  1447.             return LC_ERROR
  1448.          }
  1449.       }
  1450.    }
  1451.    return LC_OK
  1452. }
  1453.  
  1454. #
  1455. # Line Command function to insert lines
  1456. #
  1457. global function insert_lines(auto_cleanup)
  1458. {
  1459.    local on_last_line
  1460.    local count
  1461.    local line       = lc_line
  1462.    local retval     = LC_INS
  1463.    local old_flags  = buffer_flags
  1464.    buffer_flags     = and(buffer_flags, not(BUFFER_OVERTYPE_MODE ))
  1465.  
  1466.    if (lc_arg+0 != 0)
  1467.       lc_count = lc_arg+0
  1468.    else if (lc_count+0 == 0)
  1469.       lc_count = 1
  1470.  
  1471.    if (!argcount())
  1472.       auto_cleanup = (".insert" in lc) # Default is on if .insert is a command
  1473.  
  1474.    if (line)
  1475.    {
  1476.       goto_line(line)
  1477.       goto_eol()
  1478.    }
  1479.    else
  1480.    {
  1481.       goto_line(1)
  1482.       goto_bol()
  1483.    }
  1484.  
  1485.    # This for loop is like this so that the .... line commands won't all be
  1486.    # pushed to the last line inserted by the insert_newline.
  1487.  
  1488.    for (count = lc_count; count >= 0; count--)
  1489.    {
  1490.       if (count > 0)
  1491.       {
  1492.          if (!insert_auto_indent(count == lc_count))
  1493.          {
  1494.             retval = LC_NOTOK
  1495.             break
  1496.          }
  1497.       }
  1498.  
  1499.       if (auto_cleanup)
  1500.       {
  1501.          if (count < lc_count)
  1502.          {
  1503.             line_command[line] = strrepeat(".", linenumber_width);
  1504.             update_line_command(line)
  1505.          }
  1506.          line++
  1507.       }
  1508.    }
  1509.  
  1510.    goto_pos(lc_line + 1, current_column)
  1511.    lc_restore = 0
  1512.  
  1513.    buffer_flags = old_flags
  1514.    display_redraw()
  1515.    return retval
  1516. }
  1517.  
  1518. #
  1519. # Line Command function to cleanup inserted lines
  1520. #
  1521. global function cleanup_insert()
  1522. {
  1523.    local continue_insert
  1524.    local command
  1525.  
  1526.    save_position()
  1527.    goto_line(lc_line)
  1528.    if (current_line_length == 0) # if the line is empty,
  1529.    {                             #    it will be deleted.
  1530.       if (delete_line())
  1531.       {
  1532.          restore_position(1)
  1533.          return LC_DEL
  1534.       }
  1535.       else if (current_line == buffer_last_line && backspace())
  1536.       {
  1537.          restore_position(1)
  1538.          return LC_DEL
  1539.       }
  1540.       else
  1541.       {
  1542.          restore_position(0)
  1543.          return LC_NOTOK;
  1544.       }
  1545.    }
  1546.    else
  1547.    {
  1548.       delete_line_command(lc_line)
  1549.  
  1550.       if (lc_restore)
  1551.       {
  1552.          restore_position(0)       # toss the position we saved &
  1553.          restore_position(1)       # get the position saved earlier
  1554.          save_position()
  1555.    
  1556.          if (lc_line+0 == current_line)
  1557.          {
  1558.             if (current_line == buffer_last_line)
  1559.                continue_insert = TRUE
  1560.             else
  1561.             {
  1562.                command         = line_command[lc_line+1]
  1563.                continue_insert = (compress(command, ".") != ".")
  1564.             }
  1565.  
  1566.             if (continue_insert)
  1567.             {
  1568.                lc_count   = 1         # if cursor is on last line inserted,
  1569.                lc_restore = 0
  1570.                return insert_lines(1) # insert another line
  1571.             }
  1572.             lc_line++
  1573.          }
  1574.       }
  1575.       else
  1576.          restore_position(1)          # put the cursor back wher it was!
  1577.    }
  1578.    return LC_OK
  1579. }
  1580.  
  1581. #
  1582. # Line Command Function to validate line labels.
  1583. #
  1584. global function validate_label()
  1585. {
  1586.    local line
  1587.  
  1588.    if ( index(lc_command, " ") ) # Labels can't have spaces in them.
  1589.    {
  1590.       lc_error_msg = "Invalid label \"%s\" placed on line %d"
  1591.       return LC_ERROR
  1592.    }
  1593.    else
  1594.    {
  1595.       for (line in line_command)
  1596.       {
  1597.          if ( index(line_command[line], lc_command) && line != lc_line)
  1598.          {
  1599.             lc_error_msg = "Duplicate line label \"%s\" placed in line %d"
  1600.             return LC_ERROR
  1601.          }
  1602.       }
  1603.    }
  1604.    return LC_KEEP
  1605. }
  1606.  
  1607. #
  1608. # Line Command function to select lines
  1609. #
  1610. global function select_lines(adjust_count)
  1611. {
  1612.    local endline
  1613.  
  1614.    if ((!argcount() || adjust_count) && lc_arg)
  1615.       lc_count = lc_arg
  1616.  
  1617.    if (lc_count >= 0) 
  1618.       endline = lc_line + lc_count - 1
  1619.    else
  1620.       endline = lc_line + lc_count + 1
  1621.  
  1622.    if (lc_line < endline)
  1623.    {
  1624.       create_linecol_selection(LINE_SELECTION, lc_line, 1, endline, 1)
  1625.       goto_line(lc_line)
  1626.    }
  1627.    else
  1628.    {
  1629.       create_linecol_selection(LINE_SELECTION, endline, 1, lc_line, 1)
  1630.       goto_line(endline)
  1631.    }
  1632.    return LC_OK
  1633. }
  1634.  
  1635. #
  1636. # Line Command function to select cols
  1637. #
  1638. global function select_cols(adjust_count)
  1639. {
  1640.    local startoff
  1641.    local endoff
  1642.  
  1643.    if ((!argcount() || adjust_count) && lc_arg)
  1644.       lc_count = lc_arg
  1645.  
  1646.    create_source_marks(1)
  1647.  
  1648.    startoff = mark_to_offset(tr_src_start)
  1649.    endoff   = mark_to_offset(tr_src_end)
  1650.  
  1651.    create_offset_selection(COLUMN_SELECTION, startoff, endoff)
  1652.    goto_mark(tr_src_start) # Leave the cursor at the start of the block
  1653.  
  1654.    reset_transfer(LC_KEEP, 0, 1)
  1655.    return LC_OK
  1656. }
  1657.  
  1658. ## shift lines in the current buffer left
  1659. #
  1660. global function lshift_cols()
  1661. {
  1662.    return lshift_lines(1)
  1663. }
  1664.  
  1665. global function lshift_data()
  1666. {
  1667.    return lshift_lines(0)
  1668. }
  1669.  
  1670. local  function lshift_lines(shift_cols)
  1671. {
  1672.    if ( and(buffer_flags, BUFFER_READ_ONLY) )
  1673.    {
  1674.       lc_error_msg = "Read only file."
  1675.       return LC_ERROR
  1676.    }
  1677.    else
  1678.    {
  1679.       select_lines(0)
  1680.       outdent_columns(lc_arg ? lc_arg : 2) # , shift_cols)
  1681.       remove_selection()
  1682.       return LC_OK
  1683.    }
  1684. }
  1685.  
  1686. ## shift lines in the current buffer right
  1687. #
  1688. global function rshift_cols()
  1689. {
  1690.    return rshift_lines(1)
  1691. }
  1692.  
  1693. global function rshift_data()
  1694. {
  1695.    return rshift_lines(0)
  1696. }
  1697.  
  1698. local  function rshift_lines(shift_cols)
  1699. {
  1700.    if ( and(buffer_flags, BUFFER_READ_ONLY) )
  1701.    {
  1702.       lc_error_msg = "Read only file."
  1703.       return LC_ERROR
  1704.    }
  1705.    else
  1706.    {
  1707.       select_lines(0)
  1708.       indent_columns(lc_arg ? lc_arg : 2) # , shift_cols)
  1709.       remove_selection()
  1710.       return LC_OK
  1711.    }
  1712. }
  1713.  
  1714. ## alter case sense of lines in the current buffer
  1715. #       non-alphabetic characters are unaffected
  1716. #
  1717. global function ucase_lines()
  1718. {
  1719.    local ch
  1720.  
  1721.    if ( and(buffer_flags, BUFFER_READ_ONLY) )
  1722.    {
  1723.       lc_error_msg = "Read only file."
  1724.       return LC_ERROR
  1725.    }
  1726.    else
  1727.    {
  1728.       message("Uppercasing Lines...")
  1729.  
  1730.       lgetc_init()
  1731.       while(( ch = lgetc() ))
  1732.       {
  1733.          if( islower( ch ))
  1734.          {
  1735.             ch = toupper( ch )
  1736.             lputc( ch )
  1737.          }
  1738.       }
  1739.       lgetc_done()
  1740.  
  1741.       if (lc_line <= 1 || lc_line + lc_count <= 1) # Fix strange bug that causes
  1742.       {                                            # the window to redraw screwy
  1743.          display_update()
  1744.          display_redraw()
  1745.       }
  1746.  
  1747.       show_message()
  1748.       return LC_OK
  1749.    }
  1750. }
  1751.  
  1752. function lcase_lines()
  1753. {
  1754.    local ch
  1755.  
  1756.    if ( and(buffer_flags, BUFFER_READ_ONLY) )
  1757.    {
  1758.       lc_error_msg = "Read only file."
  1759.       return LC_ERROR
  1760.    }
  1761.    else
  1762.    {
  1763.       message("Lowercasing Lines...")
  1764.    
  1765.       lgetc_init()
  1766.       while(( ch = lgetc() ))
  1767.       {
  1768.          if( isupper( ch ))
  1769.          {
  1770.             ch = tolower( ch )
  1771.             lputc( ch )
  1772.          }
  1773.       }
  1774.       lgetc_done()
  1775.  
  1776.       if (lc_line <= 1 || lc_line + lc_count <= 1) # Fix strange bug that causes
  1777.       {                                            # the window to redraw screwy
  1778.          display_update()
  1779.          display_redraw()
  1780.       }
  1781.  
  1782.       show_message()
  1783.       return LC_OK
  1784.    }
  1785. }
  1786.  
  1787. ## lgetc(), lputc( ch ), lgetc_init(), lgetc_done()
  1788. #
  1789. #  This collection of functions facilitates the sequential replacement
  1790. #  of all characters within a marked block of lines.
  1791. #
  1792. #  Normal usage:
  1793. #
  1794. #               lgetc_init()
  1795. #               while (( ch = lgetc())
  1796. #                       if ( P( ch ))
  1797. #                               lputc( F( ch ))
  1798. #               lgetc_done()
  1799. #
  1800. local   lgetc_y0, lgetc_y1, lgetc_offset
  1801.  
  1802. local function lgetc()
  1803. {
  1804.    local ch
  1805.    
  1806.    restore_position( 0 )   # pop previously saved
  1807.  
  1808.    # test for past end of selection
  1809.    if( buffer_offset >= lgetc_offset )
  1810.       return ""
  1811.  
  1812.    ch = read_buffer( 1 )
  1813.    save_position()
  1814.    next_char()
  1815.    if( !ch )
  1816.         ch = "\n"
  1817.  
  1818.    return ch
  1819. }
  1820.  
  1821. # replace the character in the buffer most recently returned by lgetc
  1822. #
  1823. local function lputc( ch )
  1824. {
  1825.    restore_position( 1 )
  1826.    insert_string( ch )
  1827.    delete_chars(1)
  1828.    save_position()
  1829. }
  1830.  
  1831. # initialize a collection of variables for lgetc()/lputc() usage.
  1832. #       Places the cursor at the upper left corner, and saves the 
  1833. #       original position on the save_position stack.
  1834. #
  1835. local function lgetc_init()
  1836. {
  1837.    local tmp
  1838.  
  1839.    save_position()         # original position of selection
  1840.            
  1841.    # get and remember starting & ending marks & normalize
  1842.    # their locations
  1843.    #
  1844.    if ( tr_src_start && tr_src_end )
  1845.    {
  1846.       goto_mark( tr_src_start )
  1847.       lgetc_y0 = current_line
  1848.  
  1849.       goto_mark( tr_src_end )
  1850.       goto_bol()
  1851.       lgetc_y1 = current_line
  1852.    }
  1853.    else
  1854.    {
  1855.       if (lc_arg+0 != 0)
  1856.          lc_count = lc_arg+0
  1857.       else if (lc_count+0 == 0)
  1858.          lc_count = 1
  1859.  
  1860.       lgetc_y0 = lc_line  + 0
  1861.       lgetc_y1 = lgetc_y0 + lc_count + ((lc_count+0 > 0) ? -1 : +1)
  1862.    }
  1863.  
  1864.    if (lgetc_y0 > lgetc_y1)
  1865.    {
  1866.       tmp      = lgetc_y0
  1867.       lgetc_y0 = lgetc_y1
  1868.       lgetc_y1 = tmp
  1869.    }
  1870.  
  1871.    # save first byte offset past selection
  1872.    if (lgetc_y1 >= buffer_last_line)
  1873.       lgetc_offset = buffer_size
  1874.    else
  1875.    {
  1876.       goto_pos( lgetc_y1 + 1, 1 )
  1877.       lgetc_offset = buffer_offset
  1878.    }
  1879.  
  1880.    goto_pos( lgetc_y0, 1 )
  1881.    if ( and( buffer_flags, BUFFER_IN_VIRTUAL_SPACE ))
  1882.       next_char()
  1883.  
  1884.    # lgetc() expects to discard a previously saved position:
  1885.    save_position()
  1886. }
  1887.  
  1888. # clean up the save_position stack and restore the original cursor position
  1889. #
  1890. local function lgetc_done()
  1891. {
  1892.    restore_position( 1 )
  1893. }
  1894.  
  1895. #
  1896. # Debugging Function to display the contents of the mark stack
  1897. #
  1898. global function dump_marks()
  1899. {
  1900.    local command
  1901.    local i
  1902.  
  1903.    for(command in lc_mark)
  1904.    {
  1905.       cvdebug("Mark[%s] -> Buffer = %d, Mark = %d, Line = %d, Num = %d",
  1906.                command, lc_mark[command].buffer, lc_mark[command].mark,
  1907.                mark_line(lc_mark[command].mark), lc_mark[command].num)
  1908.  
  1909.       for(i in lc_mark[command])
  1910.       {
  1911.          if (i != "buffer" && i != "mark" && i != "num")
  1912.             cvdebug("Mark[%s][%s] = %s", command, i, lc_mark[command][i])
  1913.       }
  1914.    }
  1915. }
  1916.