;;=============================================================================
;;AUTOLOAD: expand-tabs
;;=============================================================================
;;AUTODOC: expand-tabs "expands tabs into spaces, unix style, in strings"
;;(expand-tabs string)
;;
;;returns a copy of string with tabs expansed into spaces
;;e.g.:
;;    (expand-tabs "a\tb")         ==>   "a       b"
;;A tab expands to 8 spaces (unix default), this value can be redefined with 
;;the global variable expand-tabs:tab-size
;;e.g.:
;;    (with (expand-tabs:tab-size 4)(expand-tabs "a\tb"))  ==> "a   b"

(defvar expand-tabs:re (regcomp "^(.*)(\n?)"))

(defun expand-tabs (source &aux
    line
    (res (copy ""))
    (offset 0)
    (len (length source))
    tab-pos
  )
  ;; this is needed for some nasty interaction between let and autoload
  (if (not (boundp 'expand-tabs:tab-size))(setq expand-tabs:tab-size 8))
  (if (seek source #\tab)
    (while (< offset len)
      (regexec expand-tabs:re source offset)
      (setq line (regsub expand-tabs:re 1))
      (setq offset (get (get expand-tabs:re 2) 1))
      (while (setq tab-pos (seek line #\tab))
	(delete line tab-pos)
	(insert line tab-pos (make-string
	    (if (= 0 (mod tab-pos expand-tabs:tab-size))
	      expand-tabs:tab-size
	      (- expand-tabs:tab-size (mod tab-pos expand-tabs:tab-size))
	    )
      )))
      (nconc res line (regsub expand-tabs:re 2))
    )
    (setq res source)				;no tabs to expand
  )    
  res
)
