;**************************************************************************
;*																								  *
;* 	If you are a previous user of ABBREV (previous to ABBREV4),			  *
;* 	you will need to replace the autoload's that were provided			  *
;* 	with that version	with the ones specified below.						  *
;* 																							  *
;* 	ABBREV5 allows abbrev to work in conjunction with Brief's			  *
;* 	file name completion facility (i.e. if <Tab> is pressed				  *
;* 	while an abbrevion is on the command line, the command				  *
;* 	will be expanded by abbrev, and then handed over to Brief's			  *
;* 	file completion facility).  For user's of ABBREV4, simply			  *
;* 	compile this file and the new ablookup.cb, and the new facility	  *
;*    will be in place.																	  *
;* 																							  *
;* 	For users of previous versions, follow the instructions				  *
;* 	below.																				  *
;*																								  *
;**************************************************************************

;**************************************************************************
;*																								  *
;* 	 ABBREV.CB	(Version 5)															  *
;* 																							  *
;* 	 This macro provides a replacement for edit_file and read_file.  It *
;* 	 allows arbitrary abbreviation of drive and path combinations in	  *
;* 	 file names (and may even be used to abbreviate full file names).	  *
;* 																							  *
;* 	 The if there is a slash or backslash in the path (after column 1), *
;* 	 then abbrev looks up a replacement for what preceeds the			  *
;* 	 1st slash (backslash) and passes it on to the next					  *
;* 	 program in the chain.	 If there is no slash or backslash,			  *
;* 	 abbrev checks for a replacement of the entire name					  *
;* 	 specified.  (This is for using an abbreviation for a					  *
;* 	 file name.)  It is not necessary to use the last						  *
;* 	 directory name as the abbreviation, and you may						  *
;* 	 supply several abbreviations for a single directory.					  *
;* 																							  *
;* 	 Finally, if you wish to pass a name through without being			  *
;* 	 altered by abbrev, then precede it with an exclaimation point.	  *
;* 																							  *
;* 	 If "foo" was the abbreviation for "c:\new\dos\foo"					  *
;* 																							  *
;* 	 then (edit_file "foo\filename") would pass on:							  *
;* 																							  *
;* 			 (edit_file "c:\new\dos\foo\filename").							  *
;* 																							  *
;* 	 The abbreviations are kept in a file called "abbrev.dat".			  *
;* 	 This file goes in the last directory specified by your				  *
;* 	 BPATH environment variable.	If you would like it in a				  *
;* 	 different directory, then you may specify this with the				  *
;* 	 BABBREV environment variable.  The macro "abbrev" (invoked with	  *
;* 	 F10) will bring the abbrev.dat file into a Brief buffer to be		  *
;* 	 edited.																				  *
;* 																							  *
;* 	 Each abbreviation is specified on 1 line of the file.				  *
;* 	 The line is of the form:														  *
;* 																							  *
;* 	 <abbreviation> <whitespace> <substitution>								  *
;* 																							  *
;* 	 The <abbreviation> must begin in column 1.	The line					  *
;* 	 for the above example would be:												  *
;* 																							  *
;* 	 foo		 c:\new\dos\foo														  *
;* 																							  *
;* 	 To inspire you of its usefulness, part of my current file is		  *
;* 	 setup as follows:																  *
;* 																							  *
;* 	 autoexec c:\autoexec.bat														  *
;* 	 exec 	 c:\autoexec.bat														  *
;* 	 config	 c:\config.sys															  *
;* 	 ap		 d:\pinball\apple														  *
;* 	 apple	 d:\pinball\apple														  *
;* 	 util 	 d:\util																	  *
;* 	 u 		 d:\util																	  *
;* 	 uni		 d:\util\uni															  *
;* 	 mine 	 c:\soft\brief\macros\mine											  *
;* 	 m 		 c:\soft\brief\macros\mine											  *
;* 	 macros	 c:\soft\brief\macros												  *
;* 	 mac		 c:\soft\brief\macros												  *
;* 	 macs 	 c:\soft\brief\macros												  *
;* 	 inc		 c:\soft\c\include													  *
;* 	 include  c:\soft\c\include													  *
;* 																							  *
;* 	 To install, add the following to your initials macro					  *
;* 	 (after any other replacements to edit_file or read_file):			  *
;* 																							  *
;*   	 (autoload "abbrev.cm" "edit_file" "read_file" "abbrev")			  	  *
;* 	 (autoload "ablookup.cm" "ab_lookup","get_abbrev_file")			  	  *
;* 																							  *
;* 	 Place "abbrev.cm" and "ablookup.cm" in a BPATH directory			  *
;* 	 (e.g. c:\brief\macros).														  *
;* 																							  *
;* 	 Abbrev keeps the abbreviation file in a system buffer.				  *
;* 	 The 1st call will create the system buffer.   Subsequent calls	  *
;* 	 will run faster.																	  *
;* 																							  *
;* 	 Larry DeMar	 July, 1989														  *
;* 																							  *
;* 	 Updated for FILE_ED3 compatability,  August, 1989.   -Led			  *
;* 																							  *
;* 	 Updated to allow suffix.cb to use the utilities without loading	  *
;* 	 replacement macros (ABBREV4) October, 1989  -Led.						  *
;*																								  *
;**************************************************************************
;*																								  *
;* 	 Version 5 has the following improvements:								  *
;* 																							  *
;* 	 Updated to work with Brief's File completion facility.				  *
;* 																							  *
;* 	 Supresses command line jibberish generated by							  *
;* 	    called primitives.															  *
;* 																							  *
;* 	 Automatically Invokes Brief's file completion if * or ?				  *
;*    	 is on command	line when <Enter> is pressed.  Please note		  *
;* 		 that the time "Expanding Wildcard..." is displayed,				  *
;* 		 Brief is doing its file completion.  Abbrev does very			  *
;* 		 little during this delay (compare to the time required			  *
;* 		 without abbrev installed).												  *
;* 																							  *
;* 	 January, 1990 -Led																  *
;*																								  *
;**************************************************************************
#define ABBREV_FILE_NAME "abbrev.dat"

(extern ab_lookup
		 get_abbrev_file
		 _bad_key)

(replacement edit_file
   (
      (string e_parm)
      (if (!= (inq_called) "")
         (return (edit_file))
      )
      (if (! (get_parm 0 e_parm "File: "))
         (return)
      )

      ;		Before passing our value down...see if there are any wildcard
      ;		characters.

      (if (== (= e_parm (wild e_parm "File: ")) "")
         (return)
      )
      (edit_file (abbr e_parm))
   )
)
(replacement read_file
   (
      (string r_parm)
      (if (!= (inq_called) "")
         (return (read_file))
      )
      (if (! (get_parm 0 r_parm "File to read: "))
         (return)
      )
      (if (== (= r_parm (wild r_parm "File to read: ")) "")
         (return)
      )
      (read_file (abbr r_parm))
   )
)
;**************************************************************************
;*																								  *
;* 	WILD																					  *
;* 																							  *
;* 	This is called to check for wildcard characters in the				  *
;* 	prompt and force file name completion if wildcard						  *
;* 	characters are detected.														  *
;* 																							  *
;* 	It returns the final prompt result, or "" if the						  *
;* 	user escapes.																		  *
;*																								  *
;**************************************************************************
(macro wild
   (
      (string e_parm
              our_prompt
      )
      (get_parm 0 e_parm)
      (get_parm 1 our_prompt)
      (while (|| (index e_parm "*") (index e_parm "?"))
         (

            ;		Put this public service message up.
            ;		Brief takes tremendous amounts of time expanding
            ;		Wildcards.

            (message "Expanding wildcard...")
            (push_back (key_to_int "<Tab>"))   ; Put a tab out to tell Brief to expand
            (if (! (get_parm NULL e_parm our_prompt NULL e_parm))
               (return "")
            )
         )
      )
      (return e_parm)
   )
)
;**************************************************************************
;*																								  *
;* 	 ABBR																					  *
;* 																							  *
;* 	 This is called to expand an abbreviation if necessary.				  *
;* 																							  *
;* 	 It returns the string that should be passed on.						  *
;*																								  *
;**************************************************************************
(macro abbr
   (
      (int slash_index)
      (int ab_buf)
      (global ab_buf)
      (string abbreviation
              file_name
              first_char   ; allow leading slash or backslash as a courtesy
      )
      (get_parm 0 file_name)
      (if (== (substr file_name 1 1) "!")   ; check for bang
         (return (substr file_name 2))   ; strip it and we're done.
      )
      ; 
      ;   As a courtesy, if the user preceeded his abbreviation
      ;   with slash or backslash (from using dos too much)
      ;   lookup what follows the leading seperator
      ; 
      ;   If you want to use that leading slash or backslash
      ;   to shut off abbrev, then comment out the next 2
      ;   Brief statements (next 6 lines).
      ; 
      (= first_char (substr file_name 1 1))    ; get 1st char
      (if (|| (== first_char "/") (== first_char "\\"))
         (= file_name (substr file_name 2))   ; lookup rest
      ;else
         (= first_char "")   ; nothing stripped
      )
      ; 
      ;   now we have to see if there is a path separator.
      ; 
      (= slash_index (get_first_seperator file_name))
      ; 	  slash_index is now zero if there are now separators
      ; 	  and has the position of the 1st seperator if non-zero.
      ; 
      (if slash_index
         (= abbreviation (substr file_name 1 (- slash_index 1)))
      ;else
         (= abbreviation file_name)
      )
      (if (|| (index abbreviation "*") (index abbreviation "?"))   ; for FILE_ED3 if it has a star
         (= abbreviation (+ first_char abbreviation))   ; don't look up!
      ;else
         (if (! (ab_lookup ABBREV_FILE_NAME abbreviation ab_buf "abbrev.$b$"))
            (= abbreviation (+ first_char abbreviation))   ; not found..put 1st char back.
         )
         ; 
         ;   now....if there was a path...we must concatonate whats beyond 1st seperator
         ; 
      )
      (if slash_index
         (= abbreviation (+ abbreviation (substr file_name slash_index)))
      )
      (return abbreviation)
   )
)
;**************************************************************************
;*																								  *
;* 	 ABBREV																				  *
;* 																							  *
;* 	 This is called to bring the abbreviation file into the				  *
;* 	 editor.  It first deletes the system buffer such that				  *
;* 	 changes (that are written) will be used on the next					  *
;* 	 request.																			  *
;*																								  *
;**************************************************************************
(macro abbrev
   (
      (if ab_buf
         (delete_buffer ab_buf)
      )
      (= ab_buf 0)
      (edit_file (get_abbrev_file "abbrev.dat"))
   )
)
;**************************************************************************
;*																								  *
;* 	 GET_FIRST_SEPERATOR																  *
;* 																							  *
;* 	 This is called to return the position of the 1st seperator			  *
;* 	 (slash or backslash) in a file name.	It returns 0 if				  *
;* 	 no seperators exist, or the index of the 1st one it					  *
;* 	 finds.																				  *
;*																								  *
;**************************************************************************
(macro get_first_seperator
   (
      (int slash_index
           bslash_index
      )
      (string file_name)
      (get_parm 0 file_name)
      (= slash_index (index file_name "/"))
      (= bslash_index (index file_name "\\"))
      (if (&& slash_index bslash_index)   ; if both seperators are there
         (if (< bslash_index slash_index)
            (= slash_index bslash_index)   ; then take the lower
         ;else
         )
      ;else
         (if bslash_index   ; is 1st zero?
            (= slash_index bslash_index)   ; yep...use 2nd.
         )
      )
      (return slash_index)
   )
)
;**************************************************************************
;*																								  *
;* 	_BAD_KEY																				  *
;* 																							  *
;* 	This replacement for bad key allows Abbrev and Brief's				  *
;* 	file name completion to happily co-exist.									  *
;* 																							  *
;* 	If the current command is edit_file or read_file, and					  *
;* 	the bad key is <Tab>, then we see if there is a substitution		  *
;* 	to make on the command line.  If there is, we make the				  *
;* 	substitution, and push a <Tab> back on the keyboard stack.			  *
;* 																							  *
;* 	The <Tab> is necessary because Brief's _bad_key file completion	  *
;* 	routine reads directly from the command line (as opposed to			  *
;* 	passing the command string up and down the chain).  We then			  *
;* 	ignore the 2nd <Tab> and let the file completion facility			  *
;* 	do its thing.																		  *
;*																								  *
;**************************************************************************
(replacement _bad_key
   (
      (int ab_flag)
      (global ab_flag)
      (int key_pressed)
      (= key_pressed (read_char))
      (string cmd_lin
              command
      )
      (= command (inq_command))

      ; 	No matter what key it was we put it back.
      ;		If its a tab, it also goes back because we need to
      ;		do a file name completion.

      (push_back key_pressed)
      (if (&& (|| (== command "edit_file"
         ) (== command "read_file")) (== key_pressed (key_to_int "<Tab>")))
         (

            ;		If our flag is set, we have already processed.
            ;		Clear the flag and let it through

            (if ab_flag
               (
                  (= ab_flag 0)
                  (return (_bad_key))
               )
            )
            (= cmd_lin (abbr (inq_cmd_line)))   ; abbreviate what's there
            (if (== cmd_lin (inq_cmd_line))   ; if it didn't change
               (return (_bad_key))   ; 	we're done...pass it down.
            )

            ;		We made a change.....we have to get it back to the command line

            (= ab_flag 1)   ; Cause us to ignore this req.
            (return cmd_lin)   ; Pass back completed string.
         )
      )

      ;		Not of interest to us....pass the bad key down.

      (return (_bad_key))
   )
)
