;**  Sort
;**
;**      Brief macro by Keith Harp
;**
;**   Sort the marked lines, using the marked columns as keys.
;**   Works best if a COL_MARK is used instead of a normal mark.
;**   I.e.  You can see what's going on better.

;**		Modified to account for a block specified by lower right-hand
;** corner to upper left-hand corner and visa versa and to allow for
;** tabs preceding the block to sort on.
;** Lew Paper
;** 6/5/87

(macro sort
   (
		(int			start_line
						start_col
						stop_line
						stop_col
                  string_len
		)
 		(if (! (inq_marked))
			(message "No marked area.")
		;else
			(
            (save_position)

            ;** Figure out boundaries

            (inq_position start_line start_col)
				(swap_anchor)
				(inq_position stop_line stop_col)

;	LP modification to correct error in next line and to allow for all 4
;	possible column block specifications
;            (= string_len (- stop_col start_col) 1)
				(if (> start_col stop_col)
;  End LP modification
	            (= string_len (- start_col stop_col))
				;else
	            (= string_len (- stop_col start_col))
				)
				(++ string_len)				; LP modification
            (raise_anchor)
            (message "Sorting...")

            (if (!= start_line stop_line)
				   (if (|| 
                      (< stop_line start_line)
                      (&& (== stop_line start_line) (< stop_col start_col))
                   )  
;	LP modification to allow for all 4 possible column block specifications
;                  (_dosort stop_line start_line stop_col (- 1 string_len))
                  (_dosort stop_line start_line stop_col string_len)
;  End LP modification
               ;else
;	LP modification to allow for all 4 possible column block specifications
;                  (_dosort start_line stop_line start_col (+ 1 string_len))
                  (_dosort start_line stop_line start_col string_len)
;  End LP modification
				   );endif
            );endif

            (restore_position)
            (message "Sort Done")
         ) ;end else
      ); end if
   )
)

;** _dosort
;**
;**  Do insertion sort on the current buffer.
#define FALSE 0
#define TRUE 1
(macro _dosort
   (
      (int        start_line
                  stop_line
                  start_col
                  string_len

                  notfound
                  total_len
                  next_line
                  next_linex100   
                  stop_linex100
                  cur_line
      )
      (string     first_key
                  first_line
      )
      
      (get_parm 0 start_line)
      (get_parm 1 stop_line)
      (get_parm 2 start_col)
      (get_parm 3 string_len)

      (= next_line stop_line)
      (= total_len (- start_line stop_line))
      (= next_linex100  (* next_line 100))
      (= stop_linex100 next_linex100)
      (while (>= (= cur_line (-- next_line)) start_line)
         (
            (move_abs cur_line 1)
            (= first_line (read))
; LP modification to correct for tabs
;            (= first_key (substr first_line start_col string_len))
				(move_abs cur_line start_col)
				(= first_key (read string_len))
; End LP modification
            (move_abs (++ cur_line) start_col)
            (if (> first_key (read string_len))
               (
                  (= notfound TRUE)
                  (while (&& (<= (++ cur_line) stop_line) notfound)
                     (
                        (move_abs cur_line start_col)
                        (= notfound (> first_key (read string_len)))
                     )
                  );end while
                  (if (! notfound) (-- cur_line))
                  (move_abs cur_line 1)
                  (insert first_line)
                  (move_abs next_line 1)
                  (delete_line)
               )
            );end if
            (message "Sorted %d%s" 
               (/ (- (-= next_linex100 100) stop_linex100) total_len)
               "%"
            )
         )
      ); end while

   )
); macro _dosort

