;#
;#	@(#)complete.pl	1.0 (sun!waynet) 11/11/88
;#
;# Author: Wayne Thompson
;#
;# Description:
;#     This routine provides word completion.
;#     (TAB) attempts word completion.
;#     (^D)  prints completion list.
;#	(These may be changed by setting $Complete'complete, etc.)
;#
;# Diagnostics:
;#     Bell when word completion fails.
;#
;# Bugs:
;#
;# Usage:
;#     $input = do Complete('prompt_string', @completion_list);
;#

CONFIG: {
    package Complete;

    $complete =	"\004";
    $kill =	"\025";
    $erase1 =	"\177";
    $erase2 =	"\010";
}

sub Complete {
    package Complete;

    local ($prompt) = shift (@_);
    local ($c, $cmp, $l, $r, $ret, $return, $test);
    @_cmp_lst = sort @_;
    local($[) = 0;
    loop: {
	print $prompt, $return;
	while (($c = &kernel_getc()) ne "\r") {
	    if ($c eq "\t") {			# (TAB) attempt completion
		@_match = ();
		foreach $cmp (@_cmp_lst) {
		    push (@_match, $cmp) if $cmp =~ /^$return/;
		}
    	    	$test = $_match[0];
    	    	$l = length ($test);
		unless ($#_match == 0) {
    	    	    shift (@_match);
    	    	    foreach $cmp (@_match) {
    	    	    	until (substr ($cmp, 0, $l) eq substr ($test, 0, $l)) {
    	    	    	    $l--;
    	    	    	}
    	    	    }
    	    	    &kernel_bell;
    	    	}
    	    	print $test = substr ($test, $r, $l - $r);
    	    	$r = length ($return .= $test);
	    }
	    elsif ($c eq $complete) {		# (^D) completion list
		print "\r\n";
		foreach $cmp (@_cmp_lst) {
		    print "$cmp\r\n" if $cmp =~ /^$return/;
		}
		redo loop;
	    }
    	    elsif ($c eq $kill && $r) {	# (^U) kill
    	    	$return = '';
    	    	$r = 0;
    	    	print "\r\n";
    	    	redo loop;
    	    }
	    	    	    	    	    	# (DEL) || (BS) erase
	    elsif ($c eq $erase1 || $c eq $erase2) {
		if($r) {
		    print "\b \b";
		    chop ($return);
		    $r--;
		}
	    }
	    elsif ($c =~ /\S/) {    	    	# printable char
		$return .= $c;
		$r++;
		print $c;
	    }
	}
    }
    print "\n";
    $return;
}

sub kernel_bell {
    syscall(256+7);
}

sub kernel_getc {
    local ($ch, $regs);
    if ($regs = syscall("OS_ReadC")) {
	($ch) = unpack("C",$regs);
	pack("c",$ch);
    }
    else {
	undef;
    }
}

1;
