; GLOBAL.M
;
; What this progam does: 
;
;    Prompts for a search string.
;    Searches thru all active buffers for the search parameters.
;    Pops up a screen listing of all occurences found
;        (Displays buffer name, line#, and line text).
;    Allows selection of a line by hiliting with a lite bar.
;    Pressing Enter on a hilited selection instantly edits the
;        appropriate buffer and places cursor on the appropriate line.
;    Upon exiting (Alt-X), you return to the lite bar screen.
;    You can then select another line to edit or press Esc to
;        return to your original document, where you left off.
;    Or you can press the Insert key to return to the hilited position.
;
; This version modified by Mike Packard, San Diego, CA on 9/30/89 
;
; Original filename was NEWGREP.M
; Original source code modified by Zev Handler 5/19/89
; Obtained from the Solution Systems BBS on or about 8/89
;
;************************************************************************
; The following are notes by Zev Handler 5/19/89:
;  The following enhancements have been made to improve the functionality 
;  of the original GREP macro:
;   1. Uses existing Regular Expression flag  (RE on) (RE OFF)
;   2. Allows change of current search pattern at grep prompt
;   3. Allows ESC to cancel at grep prompt
;   4. Search can be aborted once started by hitting any key
;   5. Restores buffer to previous location in window
;   6. Added the following keys to permit viewing of lines which exceed
;      the width of the screen: right & left arrow keys, home & end keys.
;************************************************************************
; SUBSEQUENT REVISION HISTORY
;  Revised by Mike Packard 9/30/89  (revised lines clearly marked)
;  Original file timestamp: 7/2/89 12:23
;  Original file name: NEWGREP.M 
;  Acquired from Solution Systems Bulletin Board: 8/89
;  Revision List:
;   1. Revised indentation to single-space indent
;      (My apologies to those who believe this difficult to read)
;   2. Revised MACRO _SHOW_LIST to do the following:
;      (Note: previous MACRO _SHOW_LIST was display-only)
;      a. Display the buffer name on every line
;      b. Display a lite bar on every line
;      c. Use Up/Down Arrow keys to move lite bar
;      d. On pressing Enter:
;         (1) Pop the user's original keyboard
;         (2) Edit the highlited buffer and goto the highlited line
;      e. While editing, on pressing Exit (usually Alt-X), return to 
;         lite bar screen
;      f. Exit from lite bar screen with Escape (back to original file)
;      g. Added global flag to keep from running on top of itself
;      h. Added option to return (goto) to highlited buffer & line
;      i. Added option to delete lines in Global listing
;   3. Added option if block is marked when global macro is called then
;         search pattern is read in from marked block and used.
;
; Special thanks to Thomas Koschate for his ZOOM.M, from wence the
;  Global Window was conceived.
;
;************************************************************************
; START OF SOURCE CODE
;
(extern _dir _t_dir _reg_exp _block_search _s_pat _t_pat _r_pat)
(macro global
 (
  (extern toggle_re)
  (int _in_global)        ; global flag - mikep
  (global _in_global)
  (if _in_global          ; if in global, don't allow rerunning
   (
    (beep)
    (return)
   )
  )
  (= _in_global (! _in_global))    ; reset the flag - mikep
  (int msg_level ret_code found_one line_at end_col old_buffer list_buffer
   sta_buffer num_buffer cur_buffer 
   cursr_line cursr_col window_line window_col) ;mikep
  (string buf pattern prompt line_no)
  (global old_buffer list_buffer 
   cursr_line cursr_col window_line window_col) ;mikep
  ;;;;;;;;;;;;;;;;;;;;;;;;;; following by mikep  9/30/89 
  (if (inq_marked)  ;; read in marked block into search pattern
   (
    (int num_chars)
    (toggle_re 0)                 ; set Regular expressions off
    (= num_chars (inq_mark_size))
    (swap_anchor)                 ; go to beginning of block
    (= _s_pat (read num_chars))   ; read-in correct number of characters
    (raise_anchor)
   )
  )
  ;;;;;;;;;;;;;;;;;;;;;;;;; following is by Zev Handler or others
  ;** Initialize for grep.   ; note - now global  - mikep
  (= sta_buffer (= old_buffer (inq_buffer)))
  ;(save_position)                           ;** save the current position
  (inq_position cursr_line cursr_col) ; mikep
  ;** now get window position so buffer will be restored
  ;** to exact same position on screen
  (top_of_window)
  ; (save_position)                         ;** save the current position
  (inq_position window_line window_col)     ; mikep
  (while (!= sta_buffer cur_buffer)
   (
    (++ num_buffer)
    (= cur_buffer (next_buffer))
    (set_buffer cur_buffer)
   )
  )
  (if (! _reg_exp)
   (= prompt "GLOBAL Search (RE off): ")
   ;else
   (= prompt "GLOBAL Search (RE on): ")
  )
  (if (strlen _s_pat)
   (
    (_sprompt prompt _s_pat)
    (= ret_code (get_parm 0 pattern prompt NULL _s_pat))
    (if (strlen pattern)
     (= _s_pat pattern)
    )
   )
   ;else
   (= ret_code (get_parm 0 _s_pat prompt))
  )
  (if (&& ret_code (strlen _s_pat))
   (
    (= list_buffer (create_buffer "Global" "$global$.$$$" 1))
    (while (> num_buffer 0)
     (
      (inq_names NULL NULL buf)
      (message "Searching: %s   Remaining: %d" buf num_buffer)
      (-- num_buffer)
      (top_of_buffer)                       ;** start at the top
      ; don't write out the buffer name here - mikep
      ;(set_buffer list_buffer)
      ;(insert "\n")
      ;(insert (upper buf))
      ;(insert "\n\n")
      ;(set_buffer old_buffer)
      (while (search_fwd _s_pat _reg_exp)   ;** use the new provided search
       (
        (beginning_of_line)
        (inq_position line_at NULL)
        (end_of_line)
        (inq_position NULL end_col)
        (set_buffer list_buffer)              ;** switch to list buffer
        (move_abs 0 1)                        ; set col - mikep
        (insert buf)                          ; write buffer name - mikep
        (move_abs 0 14)                       ; set col - mikep
        (sprintf line_no "%5d  " line_at)    ; format buffer number - mikep
        (insert line_no)                      ; write buffer number mikep
        (move_abs 0 20)                       ; set col - mikep
        ; for a later revision - add ltrim function - mikep
        (transfer old_buffer line_at 1 line_at end_col) ;** copy in the line
        (set_buffer old_buffer)                         ;** return to buffer listing
        (move_abs (++ line_at) 1)
       )
      )
      (= old_buffer (next_buffer))
      (set_buffer old_buffer)
      (if (inq_kbd_char)                    ;** if key hit
       (
        (beep)
        (keyboard_flush)                    ;** get rid of key
        (= num_buffer -1)                   ;** set to error
        (set_buffer sta_buffer)             ;** return to buffer listing
        (attach_buffer sta_buffer)          ;** get back to normal
        (error "Search aborted.")
       )
      )
     )
    )
    ;** Now that we've read all of the buffers in memory, let's display
    (if (!= num_buffer -1)                  ;** if ESC wasn't hit
     (
      (_show_list)
      (message " ")                             ; mikep
     )
    )
    (delete_buffer list_buffer)             ;** get rid of the list buffer
   )
  )
  ; (restore_position 1)                    ;** restore the old top of window
  (move_abs window_line window_col)         ; mikep
  (refresh)                                 ;** will put window in old position
  ; (restore_position 1)                    ;** now we can restore the position of cursor
  (move_abs cursr_line cursr_col)         ; mikep
  (= _in_global (! _in_global))             ; reset the flag ; mikep
 )
)
; eom (end of global macro)

;**
;**  _sprompt:
;**
;**  This routine ensures that the prompt created by the previous pattern
;**  search code isn't too large for the display area.
;**
(macro _sprompt
 (
  (string part_1 part_2)
  (int len)
  (get_parm 0 part_1)
  (get_parm 1 part_2)
  (if (> (= len (strlen (+ part_1 part_2))) 47)
   (= part_2 (substr part_2 (- len 46)))
  )
  (returns (+ part_1 part_2))
 )
) ; eom

(macro _show_list   ;; modified by mikep 9/30/89 
 (
  (set_buffer list_buffer)                  ;** switch to list buffer
  (attach_buffer list_buffer)               ;** let's see our handiwork
  (top_of_buffer)
  (drop_anchor 3)  ; mikep
  (refresh)
  ;(message "Use PgUp, PgDn, or press Esc to exit")
  (litebar_setup) ;; mikep
  (process)
  (keyboard_pop)
  (set_buffer old_buffer)                         ;** return to buffer listing
  (attach_buffer old_buffer)                      ;** get back to normal
  ;(message "Search completed.")   ; mdp - never displays
 )
)
; eom

(macro up_litebar    ;;; mikep 9/30/89
 (
  (int barnum)
  (inq_position barnum)
  (if (== barnum 1)
   (
    (beep)
    (return)
   )
  )
  (raise_anchor)
  (beginning_of_line)
  (up)
  (drop_anchor 3)
 )
) ; eom

(macro down_litebar    ;;; mikep 9/30/89
 (
  (raise_anchor)
  (beginning_of_line)
  (down)
  (if (<= (read 1) " ")
   (
    (beep)
    (move_rel -1)
   )
  )
  (drop_anchor 3)
 )
) ; eom

(macro edit_global  ;;; mikep 9/30/89
 (
  (int lines cols bufnum buflines)
  (string selbuf curbuf begbuf linestr)
  (if (<= (read 1) " ")
   (
    (beep)
    (return)
   )
  )
  (save_position)
  ;;;;;;;;;; make the hilited buffer the current buffer
  (beginning_of_line)
  (= selbuf (trim(read 12)))
  (move_abs 0 14)                ;; goto spot where line # is
  (= linestr (read 5))           ;; read in the line #
  (= buflines (atoi linestr 1))
  (inq_names NULL NULL begbuf)
  (= curbuf " ")
  ;(pause_on_error) ; for debugging
  (while (&& (!= selbuf curbuf) (!= begbuf curbuf))
   (
    ;(error "selbuf: %s  curbuf: %s  begbuf: %s " selbuf curbuf begbuf) ; for debugging
    (= bufnum (next_buffer))
    (set_buffer bufnum)
    (inq_names NULL NULL curbuf)
   )
  )
  (message " ")
  (inq_screen_size lines cols)
  (create_window 0 (- lines 3) (- cols 3) 0 "Global Edit Window  (Exit=Return)")
  (attach_buffer bufnum)
  (move_abs buflines 0)
  (refresh)
  (keyboard_pop)                            ; get the standard keyboard
  (process)
  ;;;;;;;;;; come back
  (delete_window)                           ; get rid of the window
  (set_buffer list_buffer)                  ;** switch to list buffer
  (attach_buffer list_buffer)               ;** let's see our handiwork
  (litebar_setup)
  (restore_position)
  (drop_anchor 3)  ; mikep
  (refresh)
 )
) ; eom

(macro litebar_setup  ;; mikep
 (
  (message "/Home/End/Del Enter=Edit Ins=GoTo Esc=Cancel")
  (keyboard_push)                                 ;** allow only certain keys
  (assign_to_key "%#73" "pgup_litebar")           ;** PgUp  ; mikep
  (assign_to_key "%#81" "pgdn_litebar")           ;** PgDn  ; mikep
  (assign_to_key  "#27"  "exit")                  ;** Esc
  (assign_to_key  "#13"  "edit_global")           ;** Enter ; mikep
  (assign_to_key  "%#72" "up_litebar")            ;** Up    ; mikep
  (assign_to_key  "%#80" "down_litebar")          ;** Down  ; mikep
  (assign_to_key "%#75" "left")                   ;** Left Arrow
  (assign_to_key "%#77" "right")                  ;** Rt Arrow
  ;(assign_to_key "%#71" "beginning_of_line")     ;** Home
  ;(assign_to_key "%#79" "end_of_line")           ;** End
  (assign_to_key "%#71" "litebar_beg")            ;** Home
  (assign_to_key "%#79" "litebar_end")            ;** End
  (assign_to_key "<Ins>" "global_goto")           ;** Insert   ; mikep
  (assign_to_key "<Del>" "global_del")            ;** Delete   ; mikep
 )
) ; eom

(macro litebar_beg   ; mikep
 (
  (raise_anchor)
  (beginning_of_line)
  (drop_anchor 3)
 )
) ; eom

(macro litebar_end   ; mikep
 (
  (raise_anchor)
  (end_of_line)
  (drop_anchor 3)
 )
) ; eom

(macro pgup_litebar   ; mikep
 (
  (raise_anchor)
  (page_up)
  (drop_anchor 3)
 )
)

(macro pgdn_litebar   ; mikep
 (
  (raise_anchor)
  (page_down)
  (drop_anchor 3)
 )
) ; eom

(macro global_goto  ;;; mikep 9/30/89
 (
  (int lines cols bufnum buflines)
  (string selbuf curbuf begbuf linestr)
  (if (<= (read 1) " ")
   (
    (beep)
    (return)
   )
  )
  ;;;;;;;;;; make the hilited buffer the current buffer
  (beginning_of_line)
  (= selbuf (trim(read 12)))
  (move_abs 0 14)                ;; goto spot where line # is
  (= linestr (read 5))           ;; read in the line #
  (= buflines (atoi linestr 1))
  (inq_names NULL NULL begbuf)
  (= curbuf " ")
  ;(pause_on_error) ; for debugging
  (while (&& (!= selbuf curbuf) (!= begbuf curbuf))
   (
    ;(error "selbuf: %s  curbuf: %s  begbuf: %s " selbuf curbuf begbuf) ; for debugging
    (= bufnum (next_buffer))
    (set_buffer bufnum)
    (inq_names NULL NULL curbuf)
   )
  )
  (= old_buffer bufnum)
  (= cursr_line buflines)
  (= cursr_col 1)
  (exit)
 )
) ; eom

(macro global_del      ;; mikep
 (
  (raise_anchor)
  (delete_line)
  (drop_anchor 3)
 )
) ; eom

;;; eof global.m

