home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-04-13 | 30.9 KB | 1,074 lines |
- Newsgroups: comp.lang.perl
- Path: cis.ohio-state.edu!zaphod.mps.ohio-state.edu!qt.cs.utexas.edu!cs.utexas.edu!uunet!snorkelwacker.mit.edu!bloom-picayune.mit.edu!math.mit.edu!drw
- From: drw@kronecker.mit.edu (Dale R. Worley)
- Subject: Forms-oriented input system, code
- Message-ID: <DRW.92Apr14115514@kronecker.mit.edu>
- Sender: news@athena.mit.edu (News system)
- Nntp-Posting-Host: kronecker.mit.edu
- Organization: MIT Dept. of Tetrapilotomy, Cambridge, MA, USA
- Date: Tue, 14 Apr 1992 16:55:14 GMT
- Lines: 1061
-
- # Perl forms system, version 1.0.
-
- # Written by Dale R. Worley (drw@math.mit.edu).
-
- # WARRANTY DISCLAIMER
-
- # This software was created by Dale R. Worley and is
- # distributed free of charge. It is placed in the public domain and
- # permission is granted to anyone to use, duplicate, modify and redistribute
- # it provided that this notice is attached.
-
- # Dale R. Worley provides absolutely NO WARRANTY OF ANY KIND
- # with respect to this software. The entire risk as to the quality and
- # performance of this software is with the user. IN NO EVENT WILL DALE
- # R. WORLEY BE LIABLE TO ANYONE FOR ANY DAMAGES ARISING OUT THE
- # USE OF THIS SOFTWARE, INCLUDING, WITHOUT LIMITATION, DAMAGES RESULTING FROM
- # LOST DATA OR LOST PROFITS, OR FOR ANY SPECIAL, INCIDENTAL OR CONSEQUENTIAL
- # DAMAGES.
-
- package forms;
-
- # The pattern to match field and attribute names
- # Must match Perl qualified names, at least, and not match whitespace
- $name_pat = '[^.=:\s]+';
-
- # $debug Controls debugging:
- # 1 print field values as installed by process_representation
- # 2 print subroutine definitions that are evalled by
- # process_representation
-
- # The sequence number of generated names
- $generated_name_seq = 0;
-
- sub generate_name {
- "forms_generated_" . $generated_name_seq++;
- }
-
- sub process_representation {
- local(*form, @input) = @_;
- local(@fields, $i);
-
- # Clear the form array
- %form = ();
- # Process the input
- for ($i = 0; $i <= $#input; $i++) {
- $_ = $input[$i];
- # Trim leading and trailing whitespace
- s/^\s+//;
- s/\s+$//;
- if (/^$/ || /^#/) {
- # Ignore comment lines
- } elsif (/^($name_pat)\s*:$/o) {
- # This is a "field:" line, setting the default field name
- $default_field = $1;
- } elsif (/^:$/) {
- # This is a ":" line, setting the default to a constructed
- # field name.
- $default_field = &generate_name;
- } elsif (/^($name_pat)\s*\.\s*($name_pat)\s*=\s*(.*)$/o) {
- # This is an attribute setting line
- &set_attribute($1, $2, $3) || return undef;
- } elsif (/^\.\s*($name_pat)\s*=\s*(.*)$/o) {
- # This is an attribute setting line for the form as a whole
- &set_attribute('', $1, $2) || return undef;
- } elsif (/^($name_pat)\s*=\s*(.*)$/o) {
- # This is an attribute setting line for the default field
- &set_attribute($default_field, $1, $2) || return undef;
- } elsif (/^sub\s+($name_pat)\s+{$/) {
- # This is a subroutine definition
- &define_subroutine || return undef;
- } elsif (/^\*(.*)$/) {
- # This is an expression to be evaluated
- print STDERR "Evalling: *$1\n" if $debug & 2;
- {
- package forms_user;
- eval($1);
- }
- if ($@) {
- # Error during eval
- $error = "Error in freestanding expression at line $i: $@";
- return undef;
- }
- } else {
- # Invalid format
- $error = "Invalid format at line $i: $_";
- return undef;
- }
- }
- # Perform the post-processing
- # Set attribute initially_invisible from attribute invisible
- grep(($form{$_, 'initially_invisible'} = $form{$_, 'invisible'}, 0),
- @fields);
- # Set the fields global attribute
- $form{'', 'fields'} = join(',', @fields);
- # Return success
- 1;
- }
-
- sub set_attribute {
- local($field, $attribute, $value) = @_;
-
- if ($value =~ /^&($name_pat)$/o) {
- # It is "&function"; transform it into symbol table pointer
- print STDERR "Evalling: *$1\n" if $debug & 2;
- {
- package forms_user;
- $forms'value = eval("*$1");
- }
- if ($@) {
- # Error during eval
- $error = "Error in function name at line $i: $@";
- return undef;
- }
- } elsif ($value =~ /^@($name_pat)$/o) {
- # It is "@function"; transform it into symbol table pointer
- print STDERR "Evalling: *$1\n" if $debug & 2;
- $value = eval("*$1");
- if ($@) {
- # Error during eval
- $error = "Error in function name at line $i: $@";
- return undef;
- }
- } elsif ($value =~ /^"(.*)"$/) {
- # It is a quoted string. Extract the contents.
- $value = $1;
- } elsif ($value eq '{') {
- # It is "{"; read and define the subroutine
- $name = &generate_name;
- $value = "sub $name {\n";
- # Get further input lines until end is seen
- for ($i++; $i <= $#input; $i++) {
- $_ = $input[$i];
- s/\n//;
- last if /^\s*};\s*$/;
- $value .= $_ . "\n";
- }
- $value .= "}\n*$name";
- print STDERR "Defining subroutine:\n", $value if $debug & 2;
- {
- package forms_user;
- $forms'value = eval($forms'value);
- }
- if ($@) {
- # Error during eval
- $error = "Error in subroutine definition at line $i: $@";
- return undef;
- }
- } elsif ($value =~ /^\*(.*)$/) {
- # It is "*expression"; evaluate it
- print STDERR "Evalling: *$1\n" if $debug & 2;
- {
- package forms_user;
- $forms'value = eval($1);
- }
- if ($@) {
- # Error during eval
- $error = "Error in expression at line $i: $@";
- return undef;
- }
- } else {
- # The value is to be taken literally
- }
- print STDERR "\$form{$field, $attribute} = ", $value, "\n" if $debug & 1;
- $form{$field, $attribute} = $value;
- # Add the field to the @forms array, if it is not already there
- push(@fields, $field) unless grep($_ eq $field, @fields);
- # Return success
- 1;
- }
-
- sub define_subroutine {
- $value = $_ . "\n";
- # Get further input lines until end is seen
- for ($i++; $i <= $#input; $i++) {
- $_ = $input[$i];
- s/\n//;
- last if /^\s*};\s*$/;
- $value .= $_ . "\n";
- }
- $value .= "}\n";
- print STDERR "Defining subroutine:\n", $value if $debug & 2;
- {
- package forms_user;
- $forms'value = eval($forms'value);
- }
- if ($@) {
- # Error during eval
- $error = "Error in subroutine definition at line $i: $@";
- return undef;
- }
- 1;
- }
-
- sub dump_form {
- local(*form, $filehandle) = @_;
- local($field, $attr);
-
- $filehandle = 'STDOUT' unless $filehandle;
- foreach (sort keys %form) {
- ($field, $attr) = /^(.*)$;(.*)$/o;
- print $filehandle "$field.$attr = ", $form{$field, $attr}, "\n";
- }
- 1;
- }
-
- sub clear_values {
- local(*form) = @_;
-
- foreach (split(',', $form{'', 'fields'})) {
- $form{$_, 'value'} = undef;
- }
- }
-
- sub clear_values_and_redisplay {
- foreach (split(',', $form{'', 'fields'})) {
- $form{$_, 'value'} = undef;
- &changed_value($_);
- }
- }
-
- sub reset_visibility {
- local(*form) = @_;
-
- foreach (split(',', $form{'', 'fields'})) {
- $form{$_, 'invisible'} = $form{$_, 'initially_invisible'};
- }
- }
-
- sub process_form {
- local(*form) = @_;
- local($exit_value, @fields, $x, $cursor_location, $y, $entered_field,
- $current_field_no, $last_c);
-
- # Check that it's not empty
- die "Empty form" unless $form{'', 'fields'};
-
- # Call initialize, if necessary
- $y = $form{'', 'initialize'};
- if ($y) {
- local(*x) = $y;
- &undefined_function('', 'initialize') unless defined(&x);
- &x;
- }
- # Construct displayed fields
- @fields = split(',', $form{'', 'fields'});
- foreach (@fields) {
- if ($form{$_, 'field_length'}) {
- $y = $form{$_, 'construct_displayed_value'};
- local(*x) = $y;
- &undefined_function($_, 'construct_displayed_value')
- unless defined(&x);
- $form{$_, 'displayed_value'} = &x($_, $form{$_, 'value'});
- $y = $form{$_, 'initialize_displayed_field'};
- local(*x) = $y;
- &undefined_function($_, 'initialize_displayed_field')
- unless defined(&x);
- $form{$_, 'displayed_field'} =
- &x($_, $form{$_, 'displayed_value'});
- }
- }
- # Initialize screen
- &'initscr;
- &'leaveok($'stdscr, 0);
- &'standend;
- # Set terminal in the mode we like
- &'nocbreak;
- &'raw;
- &'nonl;
- &'noecho;
- # Get the F keys loaded
- &load_function_keys unless $function_keys_loaded;
- # Redisplay screen
- &'clear;
- foreach (@fields) {
- if (!$form{$_, 'invisible'}) {
- # Write the label of the field, if there is one
- if ($form{$_, 'label_text'}) {
- local($r, $c) = split(',', $form{$_, 'label_location'});
- &'move($r, $c);
- &'addstr($form{$_, 'label_text'});
- }
- # Write the contents of the field, if there is one
- if ($form{$_, 'field_length'}) {
- local($r, $c) = split(',', $form{$_, 'field_location'});
- &'move($r, $c);
- &'standout;
- &'addstr($form{$_, 'displayed_field'});
- &'standend;
- }
- }
- }
- # Set cursor on first field
- $entered_field = undef;
- $current_field_no = $[ - 1;
- &next_field;
- # Set cursor location
- if ($current_field_no >= $[) {
- # Get $cursor_location
- $_ = $fields[$current_field_no];
- $y = $form{$_, 'initialize_displayed_field'};
- local(*x) = $y;
- &undefined_function($_, 'initialize_displayed_field')
- unless defined(&x);
- &x($_, $form{$_, 'displayed_value'});
- local($r, $c) = split(',', $form{$_, 'field_location'});
- &'move($r, $c + $cursor_location);
- } else {
- # No writable fields; put cursor in UL corner
- &'move(0, 0);
- }
- # Loop waiting for a character
- INPUT_LOOP: while (1) {
- # Refresh the screen
- &'refresh;
- # Get a character
- $c = &'getch;
- # If it is ESC, get the whole escape sequence
- if ($c eq "\e") {
- local($d) = '0';
- while ((length($c) < 6 && $d gt ' ' && $d lt '@') ||
- (length($c) == 2 && ($d eq 'O' || $d eq '['))) {
- $d = &'getch;
- $c .= $d;
- }
- # Check if it is valid
- $c = $function_key{$c};
- if (!($c &&
- ($form{'', $c} || ($current_field_no >= $[ &&
- $form{$fields[$current_field_no], $c})))) {
- &report_error("Invalid escape sequence");
- next INPUT_LOOP;
- }
- }
- # Process it
- # Exit or enter the field as appropriate
- if ($c eq "\n" || $c eq "\r" || $c eq "\t" ||
- (length($c) > 1 &&
- !$form{$fields[$current_field_no], $c})) {
- # LFD, RET, TAB, and function keys that are not local to
- # the field exit the field first
- next INPUT_LOOP if $entered_field && !&exit_field;
- } elsif ($c eq "\031" || $c eq "\026") {
- # C-y and C-v require to be in field
- if (!$entered_field) {
- &report_error("Must have entered field");
- next INPUT_LOOP;
- }
- } elsif ($c eq "\f" || $c eq "\020" || $c eq "\003" || $c eq "\007" ||
- $c eq "\e") {
- # C-l, C-p, C-c, C-g, and ESC have no constraint
- } else {
- # All others enter the field first
- &enter_field if !$entered_field;
- }
- # Process the character
- if ($c eq "\n") {
- # LFD - accept contents of form
- # Call finalize, if necessary
- $y = $form{'', 'finalize'};
- if ($y) {
- local(*x) = $y;
- &undefined_function('', 'finalize') unless defined(&x);
- # If finalize fails, it should have produced a message
- next INPUT_LOOP if !&x;
- }
- # Exit successfully
- $exit_value = 1;
- last INPUT_LOOP;
- } elsif ($c eq "\003" || $c eq "\007") {
- # C-c, C-g - abort the form
- if ($entered_field) {
- $entered_field = undef;
- $form{$entered_field, 'value'} = $previous_value;
- $form{$entered_field, 'displayed_value'} =
- $previous_displayed_value;
- $form{$entered_field, 'displayed_field'} =
- $previous_displayed_field;
- $cursor_location= $previous_cursor_location;
- # Redisplay the field
- local($r, $c) =
- split(',', $form{$entered_field, 'field_location'});
- &'move($r, $c);
- &'standout;
- &'addstr($form{$entered_field, 'displayed_field'});
- &'standend;
- &'move($r, $c + $cursor_location);
- }
- $exit_value = 0;
- last INPUT_LOOP;
- } elsif ($c eq "\r") {
- # RET - go to next field
- &next_field;
- # Set cursor location
- if ($current_field_no >= $[) {
- # Get $cursor_location
- $_ = $fields[$current_field_no];
- $y = $form{$_, 'initialize_displayed_field'};
- local(*x) = $y;
- &undefined_function($_, 'initialize_displayed_field')
- unless defined(&x);
- &x($_, $form{$_, 'displayed_value'});
- local($r, $c) = split(',', $form{$_, 'field_location'});
- &'move($r, $c + $cursor_location);
- } else {
- # No writable fields; put cursor in UL corner
- &'move(0, 0);
- }
- } elsif ($c eq "\t") {
- # TAB - go to previous field
- &previous_field;
- # Set cursor location
- if ($current_field_no >= $[) {
- # Get $cursor_location
- $_ = $fields[$current_field_no];
- $y = $form{$_, 'initialize_displayed_field'};
- local(*x) = $y;
- &undefined_function($_, 'initialize_displayed_field')
- unless defined(&x);
- &x($_, $form{$_, 'displayed_value'});
- local($r, $c) = split(',', $form{$_, 'field_location'});
- &'move($r, $c + $cursor_location);
- } else {
- # No writable fields; put cursor in UL corner
- &'move(0, 0);
- }
- } elsif ($c eq "\031") {
- # C-y - restore previous value of the field and exit from field
- $form{$entered_field, 'value'} = $previous_value;
- $form{$entered_field, 'displayed_value'} =
- $previous_displayed_value;
- $form{$entered_field, 'displayed_field'} =
- $previous_displayed_field;
- $cursor_location= $previous_cursor_location;
- # Redisplay the field
- local($r, $c) =
- split(',', $form{$entered_field, 'field_location'});
- &'move($r, $c);
- &'standout;
- &'addstr($form{$entered_field, 'displayed_field'});
- &'standend;
- &'move($r, $c + $cursor_location);
- # Only once we're done with all this, forget the field
- $entered_field = undef;
- } elsif ($c eq "\026") {
- if ($last_c eq "\026") {
- # C-v C-v - exit valid field
- &exit_field;
- } else {
- # C-v - perform validity check on field or exit field
- $y = $form{$entered_field, 'validate_displayed_value'};
- local(*x) = $y;
- &undefined_function($entered_field, 'validate_displayed_value')
- unless defined(&x);
- if (&x($entered_field,
- $form{$entered_field, 'displayed_value'})) {
- &report_message("Field OK");
- } else {
- # validate_displayed_value routine should produce error
- # message
- # Do not give C-v C-v effect if he types C-v again.
- $c = "\e";
- }
- }
- } elsif ($c eq "\f") {
- # C-l - redraw screen
- &'clearok($'stdscr, 1);
- } elsif ($c eq "\020") {
- # C-p - give help
- local($message);
- if ($current_field_no >= $[ &&
- ($message =
- $form{$fields[$current_field_no], 'help_message'}) &&
- $last_c ne "\020" &&
- $form{'MSG', 'field_length'}) {
- # There is a current field, it has a help message, user
- # has not typed C-p twice in a row, and there is a MSG
- # field, so display field help message
- &report_message($message);
- } else {
- # Display help screen
- &display_help_screen;
- # If he types C-p after this, he gets field help again.
- $c = "\e";
- }
- } elsif ($c eq "\e") {
- # ESC - invalid escape sequence
- } elsif (length($c) > 1) {
- # function key - do the appropriate function
- $y = $form{$entered_field || '', $c};
- local(*x) = $y;
- &undefined_function($entered_field, $c) unless defined(&x);
- &x;
- } elsif (($c ge "\001" && $c lt " ") || $c gt "~") {
- # Other control character
- $y = $form{$_, 'edit'};
- local(*x) = $y;
- &undefined_function($_, 'edit') unless defined(&x);
- &x($entered_field, $c);
- # Redisplay the field
- local($r, $c) =
- split(',', $form{$entered_field, 'field_location'});
- &'move($r, $c);
- &'standout;
- &'addstr($form{$entered_field, 'displayed_field'});
- &'standend;
- &'move($r, $c + $cursor_location);
- } else {
- # It is a printing character
- $y = $form{$_, 'insert'};
- local(*x) = $y;
- &undefined_function($_, 'insert') unless defined(&x);
- &x($entered_field, $c);
- # Redisplay the field
- local($r, $c) =
- split(',', $form{$entered_field, 'field_location'});
- &'move($r, $c);
- &'standout;
- &'addstr($form{$entered_field, 'displayed_field'});
- &'standend;
- &'move($r, $c + $cursor_location);
- }
- } continue {
- # Record the last key
- $last_c = $c;
- }
- # Delete the help screen window if necessary
- if ($help_screen_window) {
- &'delwin($help_screen_window);
- $help_screen_window = undef;
- }
- # Move cursor to LL corner
- &'move($'LINES-1, 0);
- &'refresh;
- &'endwin;
- $exit_value;
- }
-
- # Find next field that is visible, has a data area, and is writable.
- sub next_field {
- local($old_field_no) = $current_field_no;
-
- # Look for a field after the current field
- for ($current_field_no++; $current_field_no <= $#fields;
- $current_field_no++) {
- $_ = $fields[$current_field_no];
- return if !$form{$_, 'invisible'} &&
- $form{$_, 'field_length'} &&
- !$form{$_, 'read_only'};
- }
- # Look for a field before the current field
- for ($current_field_no = $[; $current_field_no <= $old_field_no;
- $current_field_no++) {
- $_ = $fields[$current_field_no];
- return if !$form{$_, 'invisible'} &&
- $form{$_, 'field_length'} &&
- !$form{$_, 'read_only'};
- }
- # No field was found at all
- $current_field_no = $[ - 1;
- }
-
- # Find previous field that is visible, has a data area, and is writable.
- sub previous_field {
- local($old_field_no) = $current_field_no;
-
- # Look for a field before the current field
- for ($current_field_no--; $current_field_no >= $[; $current_field_no--) {
- $_ = $fields[$current_field_no];
- return if !$form{$_, 'invisible'} &&
- $form{$_, 'field_length'} &&
- !$form{$_, 'read_only'};
- }
- # Look for a field after the current field
- for ($current_field_no = $#fields; $current_field_no >= $old_field_no;
- $current_field_no--) {
- $_ = $fields[$current_field_no];
- return if !$form{$_, 'invisible'} &&
- $form{$_, 'field_length'} &&
- !$form{$_, 'read_only'};
- }
- # No field was found at all
- $current_field_no = $[ - 1;
- }
-
- # Enter the current field
- sub enter_field {
- $entered_field = $fields[$current_field_no];
- $previous_value = $form{$entered_field, 'value'};
- $previous_displayed_value = $form{$entered_field, 'displayed_value'};
- $previous_displayed_field = $form{$entered_field, 'displayed_field'};
- $previous_cursor_location = $cursor_location;
- }
-
- # Exit the current field
- sub exit_field {
- local($y);
-
- # Perform validity checking
- $y = $form{$entered_field, 'validate_displayed_value'};
- local(*x) = $y;
- &undefined_function($entered_field, 'validate_displayed_value')
- unless defined(&x);
- return 0
- unless &x($entered_field, $form{$entered_field, 'displayed_value'});
- $y = $form{$entered_field, 'interpret_displayed_value'};
-
- # Interpret the value
- local(*x) = $y;
- &undefined_function($entered_field, 'interpret_displayed_value')
- unless defined(&x);
- $form{$entered_field, 'value'} =
- &x($entered_field, $form{$entered_field, 'displayed_value'});
-
- # Canonicalize the value, if necessary
- if ($form{$entered_field, 'canonicalize'}) {
- local($cursor_location);
- local($old_r, $old_c);
-
- $y = $form{$entered_field, 'construct_displayed_value'};
- local(*x) = $y;
- &undefined_function($entered_field, 'construct_displayed_value')
- unless defined(&x);
- $form{$entered_field, 'displayed_value'} =
- &x($entered_field, $form{$entered_field, 'value'});
- $y = $form{$entered_field, 'initialize_displayed_field'};
- local(*x) = $y;
- &undefined_function($entered_field, 'initialize_displayed_field')
- unless defined(&x);
- $form{$entered_field, 'displayed_field'} =
- &x($entered_field, $form{$entered_field, 'displayed_value'});
-
- # Save the cursor position
- &'getyx($'stdscr, $old_r, $old_c);
- # Rewrite the field
- local($r, $c) =
- split(',', $form{$entered_field, 'field_location'});
- &'move($r, $c);
- &'standout;
- &'addstr($form{$entered_field, 'displayed_field'});
- &'standend;
- # Restore the cursor
- &'move($old_r, $old_c);
- }
-
- # Clean up and exit
- $entered_field = undef;
- return 1;
- }
-
- sub display_help_screen {
- # Create help screen window if necessary
- if (!$help_screen_window) {
- local($i);
-
- $help_screen_window = &'newwin(0, 0, 0, 0);
- $i = 0;
- foreach (split(/\n/, <<'EOF')) {
- Forms 1.0 help screen
-
- LFD or C-j Accept contents of form C-c or C-g Abort the form
- RET or C-m Go to next field TAB or C-i Go to previous field
-
- C-y Restore previous value of the field and exit from field
- C-v Perform validity check on field
- C-v C-v Exit from valid field
-
- C-u Clear field
- C-k Clear to end of field
- C-r Clear to beginning of field
-
- C-a Go to beginning of field C-e Go to end of field
- C-b Go back one character C-f Go forward one character
- C-d Delete next character DEL or C-h Delete previous character
-
- C-p Give help on this field (or show help screen if no help for field)
- C-p C-p Show this help screen
-
- Function keys 1 through 10 can be used as commands if allowed by the
- particular form.
-
- Hit any key (other than C-p) to continue...
- EOF
- &'wmove($help_screen_window, $i, 0);
- &'waddstr($help_screen_window, $_);
- $i++;
- }
- }
-
- # Write it to the terminal
- &'clearok($help_screen_window, 1);
- &'wrefresh($help_screen_window);
- # Wait for a character that is not C-p
- 1 while &'getch eq "\020";
- # Refresh the form
- &'clearok($'stdscr, 1);
- }
-
- # Report an error
- sub report_error {
- local($message) = @_;
-
- &report_message($message);
- print "\007";
- }
-
- sub report_message {
- local($message) = @_;
- local($length) = $form{'MSG', 'field_length'};
-
- if ($length) {
- $form{'MSG', 'value'} = substr($message, 0, $length) .
- ' ' x ($length - length($message));
- &changed_value('MSG');
- }
- }
-
- sub undefined_function {
- local($field, $attr) = @_;
- local($package, $filename, $line) = caller;
-
- die sprintf("Bad value of attribute function %s.%s: %s at %s line %s\n",
- $field, $attr, $form{$field, $attr}, $filename, $line);
- }
-
- sub changed_visibility {
- local($_) = @_;
- local($r, $c);
-
- # Record where the cursor is
- &'getyx($'stdscr, $r, $c);
- # Update the screen
- if ($form{$_, 'invisible'}) {
- # Erase the field from the screen
- # Erase the label of the field, if there is one
- if ($form{$_, 'label_text'}) {
- local($r, $c) = split(',', $form{$_, 'label_location'});
- &'move($r, $c);
- &'addstr(' ' x length($form{$_, 'label_text'}));
- }
- # Erase the contents of the field, if there is one
- if ($form{$_, 'field_length'}) {
- local($r, $c) = split(',', $form{$_, 'field_location'});
- &'move($r, $c);
- &'addstr(' ' x length($form{$_, 'displayed_field'}));
- }
- } else {
- # Show the field on the screen
- # Write the label of the field, if there is one
- if ($form{$_, 'label_text'}) {
- local($r, $c) = split(',', $form{$_, 'label_location'});
- &'move($r, $c);
- &'addstr($form{$_, 'label_text'});
- }
- # Write the contents of the field, if there is one
- # Assumes that the contents have already been calculated
- if ($form{$_, 'field_length'}) {
- local($r, $c) = split(',', $form{$_, 'field_location'});
- &'move($r, $c);
- &'standout;
- &'addstr($form{$_, 'displayed_field'});
- &'standend;
- }
- }
- # Restore the cursor
- &'move($r, $c);
- }
-
- sub changed_value {
- local($_) = @_;
- local($y, $c);
-
- # Do nothing if the field has no data
- if ($form{$_, 'field_length'}) {
- $y = $form{$_, 'construct_displayed_value'};
- local(*x) = $y;
- &undefined_function($_, 'construct_displayed_value')
- unless defined(&x);
- $form{$_, 'displayed_value'} = &x($_, $form{$_, 'value'});
- $y = $form{$_, 'initialize_displayed_field'};
- local(*x) = $y;
- &undefined_function($_, 'initialize_displayed_field')
- unless defined(&x);
- {
- local($cursor_location);
- $form{$_, 'displayed_field'} =
- &x($_, $form{$_, 'displayed_value'});
- $c = $cursor_location;
- }
- if ($_ eq $fields[$current_field_no]) {
- # Have to move cursor to correct place
- $cursor_location = $c;
- local($r, $c) = split(',', $form{$_, 'field_location'});
- &'move($r, $c + $cursor_location);
- }
- # Write the contents of the field, if it is visible
- if (!$form{$_, 'invisible'}) {
- local($old_r, $old_c);
-
- # Save the cursor position
- &'getyx($'stdscr, $old_r, $old_c);
- # Rewrite the field
- local($r, $c) = split(',', $form{$_, 'field_location'});
- &'move($r, $c);
- &'standout;
- &'addstr($form{$_, 'displayed_field'});
- &'standend;
- # Restore the cursor
- &'move($old_r, $old_c);
- }
- }
- }
-
- # Field support routines
-
- # Routines for ordinary text fields
-
- # inititlize_displayed_field: Put cursor after last nonblank character.
- sub id_cursor_after {
- local($field, $value) = @_;
-
- $value =~ /(\s*)$/;
- $cursor_location = $form{$field, 'field_length'} - length($1);
- $value;
- }
-
- # construct_displayed_value: Pad value to field length on right with spaces.
- sub char_field {
- local($field, $value) = @_;
- local($length) = $form{$field, 'field_length'};
-
- $length < length($value) ? substr($value, 0, $length) :
- $length > length($value) ? $value . ' ' x ($length - length($value)) :
- $value;
- }
-
- # validate_displayed_value: Always return true.
- sub true {
- 1;
- }
-
- # interpret_displayed_value: Truncate trailing spaces.
- sub trim_trailing_space {
- local($field, $displayed) = @_;
-
- $displayed =~ s/\s+$//;
- $displayed;
- }
-
- # insert: Insert character into string at current location.
- sub text_insert {
- local($field, $c) = @_;
- local($v) = $form{$field, 'displayed_value'};
-
- substr($v, $cursor_location, 0) = $c;
- if (chop $v eq ' ') {
- $form{$field, 'displayed_field'} = $v;
- $form{$field, 'displayed_value'} = $v;
- $cursor_location++;
- } else {
- &forms'report_error("Character will not fit");
- }
- }
-
- # edit: Edit character string
- sub text_edit {
- local($field, $c) = @_;
- local($v) = $form{$field, 'displayed_value'};
- local($length) = $form{$field, 'field_length'};
-
- if ($c eq "\025") {
- # C-u - clear field
- $v = ' ' x $length;
- $cursor_location = 0;
- } elsif ($c eq "\013") {
- # C-k - clear to end of field
- substr($v, $cursor_location) = ' ' x ($length - $cursor_location);
- } elsif ($c eq "\022") {
- # C-r - clear to beginning of field
- substr($v, 0, $cursor_location) = '';
- $v .= ' ' x $cursor_location;
- $cursor_location = 0;
- } elsif ($c eq "\001") {
- # C-a - go to beginning of field
- $cursor_location = 0;
- } elsif ($c eq "\005") {
- # C-e - go to end of field
- $v =~ /(\s*)$/;
- $cursor_location = $length - length($1);
- } elsif ($c eq "\002") {
- # C-b - go back one character
- if ($cursor_location > 0) {
- $cursor_location--;
- } else {
- &forms'report_error("Beginning of field");
- }
- } elsif ($c eq "\006") {
- # C-f - go forward one character
- if ($cursor_location < $length) {
- $cursor_location++;
- } else {
- &forms'report_error("End of field");
- }
- } elsif ($c eq "\004") {
- # C-d - delete next character
- if ($cursor_location < $length) {
- substr($v, $cursor_location, 1) = '';
- $v .= ' ';
- }
- } elsif ($c eq "\177" || $c eq "\b") {
- # DEL, C-h - delete previous character
- if ($cursor_location > 0) {
- substr($v, $cursor_location-1, 1) = '';
- $v .= ' ';
- $cursor_location--;
- }
- } else {
- &forms'report_error("Invalid editing character");
- }
- $form{$field, 'displayed_field'} = $v;
- $form{$field, 'displayed_value'} = $v;
- }
-
- # Routines for hidden fields
-
- # inititlize_displayed_field: Put cursor after last nonblank character.
- sub id_cursor_after_hidden {
- local($value) = &id_cursor_after(@_);
-
- $value =~ /(\s*)$/;
- ('.' x length($`)) . (' ' x length($1));
- }
-
- # insert: Insert character into string at current location.
- sub text_insert_hidden {
- local($field, $c) = @_;
-
- &text_insert($field, $c);
- $form{$field, 'displayed_field'} =~ /(\s*)$/;
- $form{$field, 'displayed_field'} = ('.' x length($`)) . (' ' x length($1));
- }
-
- # edit: Edit character string
- sub text_edit_hidden {
- local($field, $c) = @_;
-
- &text_edit($field, $c);
- $form{$field, 'displayed_field'} =~ /(\s*)$/;
- $form{$field, 'displayed_field'} = ('.' x length($`)) . (' ' x length($1));
- }
-
- # Routines for enumerated fields
-
- # construct_displayed_value: Translate value from table
- sub enum_field {
- local($field, $value) = @_;
- local($length) = $form{$field, 'field_length'};
- local($table) = $form{$field, 'translate_table'};
-
- $value = ($table =~ m#(^|\\)([^=\\]*)=$value($|\\)#)[$[+1];
-
- $length < length($value) ? substr($value, 0, $length) :
- $length > length($value) ? $value . ' ' x ($length - length($value)) :
- $value;
- }
-
- # validate_displayed_value: Check that value is in table
- sub enum_validate {
- local($field, $value) = @_;
- local($table) = $form{$field, 'translate_table'};
- local($result);
-
- $value =~ s/\s+$//;
- if ($table =~ m#(^|\\)$value=([^=\\]*)($|\\)#i) {
- $result = 1;
- $enum_value_temporary = $2;
- } else {
- $result = 0;
- &report_error("Invalid value");
- }
- $result;
- }
-
- # interpret_displayed_value: Retrieve value saved by enum_validate.
- sub enum_interpret {
- $enum_value_temporary;
- }
-
- # Function key table
-
- # Freestanding X window on Sun
- $function_key{"\e[224z"} = 'F1';
- $function_key{"\e[225z"} = 'F2';
- $function_key{"\e[226z"} = 'F3';
- $function_key{"\e[227z"} = 'F4';
- $function_key{"\e[228z"} = 'F5';
- $function_key{"\e[229z"} = 'F6';
- $function_key{"\e[230z"} = 'F7';
- $function_key{"\e[231z"} = 'F8';
- $function_key{"\e[232z"} = 'F9';
- $function_key{"\e[-1z"} = 'F10';
-
- # X terminal on Sun
- $function_key{"\e[11~"} = 'F1';
- $function_key{"\e[12~"} = 'F2';
- $function_key{"\e[13~"} = 'F3';
- $function_key{"\e[14~"} = 'F4';
- $function_key{"\e[15~"} = 'F5';
- $function_key{"\e[17~"} = 'F6';
- $function_key{"\e[18~"} = 'F7';
- $function_key{"\e[19~"} = 'F8';
- $function_key{"\e[20~"} = 'F9';
- $function_key{"\e[21~"} = 'F10';
-
- # VT100
- $function_key{"\eOP"} = 'F1';
- $function_key{"\eOQ"} = 'F2';
- $function_key{"\eOR"} = 'F3';
- $function_key{"\eOS"} = 'F4';
-
- # Easy to type by hand
- $function_key{"\e1f"} = 'F1';
- $function_key{"\e2f"} = 'F2';
- $function_key{"\e3f"} = 'F3';
- $function_key{"\e4f"} = 'F4';
- $function_key{"\e5f"} = 'F5';
- $function_key{"\e6f"} = 'F6';
- $function_key{"\e7f"} = 'F7';
- $function_key{"\e8f"} = 'F8';
- $function_key{"\e9f"} = 'F9';
- $function_key{"\e0f"} = 'F10';
- $function_key{"\e10f"} = 'F10';
- $function_key{"\e1F"} = 'F1';
- $function_key{"\e2F"} = 'F2';
- $function_key{"\e3F"} = 'F3';
- $function_key{"\e4F"} = 'F4';
- $function_key{"\e5F"} = 'F5';
- $function_key{"\e6F"} = 'F6';
- $function_key{"\e7F"} = 'F7';
- $function_key{"\e8F"} = 'F8';
- $function_key{"\e9F"} = 'F9';
- $function_key{"\e0F"} = 'F10';
- $function_key{"\e10F"} = 'F10';
-
- # Load the function key definitions provided by termcap, but only after
- # curses has been intitialized. Called during initialization the first
- # time process_form is executed.
- sub load_function_keys {
- $function_key{&'getcap('k1')} = 'F1';
- $function_key{&'getcap('k2')} = 'F2';
- $function_key{&'getcap('k3')} = 'F3';
- $function_key{&'getcap('k4')} = 'F4';
- $function_key{&'getcap('k5')} = 'F5';
- $function_key{&'getcap('k6')} = 'F6';
- $function_key{&'getcap('k7')} = 'F7';
- $function_key{&'getcap('k8')} = 'F8';
- $function_key{&'getcap('k9')} = 'F9';
- $function_key{&'getcap('k;') || &'getcap('k0')} = 'F10';
- $function_keys_loaded = 1;
- }
-
- 1;
-
-