Cmenu

 view release on metacpan or  search on metacpan

Cmenu.pm  view on Meta::CPAN

#             $sel_text = &menu_display("Select using arrow keys");
#             ...
#             &menu_terminate();
#
#
# Cmenu - Perl library module for curses-based menus & data-entry 
# Copyright (C) 2001     Andy Ferguson, AFC Commercial, Bangor BT19 1PF, UK
#
#    This Perl library module is free software; you can redistribute it
#    and/or modify it under the terms of the GNU Library General Public
#    License (as published by the Free Software Foundation) or the
#    Artistic License.
#
#    This library is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of 
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    Library General Public License for more details.
#
#    You should have received a copy of the GNU Library General Public
#    License along with this library; if not, write to the Free
#    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#****************************************************************************
#
#****************************************************************************
# BUGS
#
# 1.   Refresh does not redraw top and bottom few lines of the backdrop
#      if the display gets totally trashed
#      Tried defining "screen" as a "window" to no avail
#
# 2.   Cannot find the ncurses BACK-TAB key so there is no default BACK
#      function. User needs to map this to another key
#
# 3.   Does not resize when called as a subshell or whatever, eg. as when called
#      from within "mc". Rsize works OK in a basic xterm.
#
# 4.   No line checking with multi-line subtitles; subtitle or pane may
#      overflow window
#****************************************************************************

package Cmenu;

use Curses;
use Text::Wrap;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;

@ISA = qw(Exporter);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@EXPORT = qw(
	     menu_initialise 
	     menu_init
	     menu_item
	     menu_display
	     menu_show
	     menu_popup
	     menu_button_set
	     menu_terminate
	    );

@EXPORT_OK = qw (
		 $menu_sep
		 $menu_sepn
	       );

$Cmenu::VERSION ='1.01';

use vars qw($VERSION $menu_sep $menu_sepn);

BEGIN {
  # Field seperator characters returned after menu activity
  # menu_sep seperates individual fields
  # menu_sepn breaks up field name from field contents
  $menu_sep="¬";
  $menu_sepn="~";
}
  
# ##################################################################################
# Public variables and functions
# ==============================
# These variables and functions are available for user programs
# While others may be accessed, they are in fact surreal
# and may cease to exist in later releases
# ---< variables >------------------------------------------------------------------
# $menu_screen          : the base curses screen
# $menu_screen_lines    : current logical depth of the screen
# $menu_screen_cols     : current logical width of the screen
# $menu_inlay           : the main display
# $menu_inlay_lines     : depth of the menu inlay
# $menu_inlay_cols      : width of the menu inlay
# $menu_inlay_y         : y offset of inlay from screen top 0
# $menu_inlay_x         : x offset of inlay from screen left 0
# $menu_advice          : standard text for display at foot
# ---< functions >------------------------------------------------------------------
# All menu functions generally apply keypad, echo and other Curses ops, on
# return from any function Curses settings can be guaranteed as if these calls 
# had been made directly
#    &echo();
#    &nocbreak();
#    &curs_set(1);
# keypad control is only applied to new windows which should always be destroyed
# before returning.
# ----------------------------------------------------------------------------------
# &menu_initialise      : sets up all menu variables and constructs
# &menu_button_set      : swicthes menu buttons on and off
# &menu_item            : create a menu item
# &menu_display         : display a menu and get a response from it
# &menu_popup           : flash a busy window
# &menu_show            : gives a full screen text display
# &menu_terminate       : close the menu environment down
# ----------------------------------------------------------------------------------
# All Curses functions can of course be used in user programs but be aware that
# management of all windows then becomes the users responsibility and behaviour
# of the menuing environment may be unpredictable
# ##################################################################################

# ##################################################################################
# Variable Definitions
# ##################################################################################

my $did_initterm = 0;	# We already got escape sequences for arrows, etc.

# Keystroke arrays
my %kseq=();               # hash for function key translation
my $key_max=0;             # longest keystroke

# Windows
my $menu_screen;           # the backdrop
my $menu_inlay;            # background for the menu window with shadow etc
my $menu_window;           # menu window with text elements
my $menu_pane;             # where the menu options actually get drawn
my $menu_popup;            # special for popup and splash displays

# Window elements
my $menu_title;            # title of script in backdrop
my $menu_top_title;        # title of menu
my $menu_sub_title;        # sub-title of a menu
my $menu_sub_title_lines;  # depth of sub-title
my $menu_advice;           # message at foot of backdrop
my $menu_item_pos;         # where menu items will start 
my $menu_indent;           # where menu item labels will start

my $menu_index;            # counter of menu items

# Extent of display screen - fixed - unchangeable - from TERM settings
# Always starts at 0,0
my $menu_screen_cols=0;         # - COLS from Curses   } size of the full screen
my $menu_screen_lines=0;        # - LINES from Curses  }

# Extent of Menu Inlay - size and position of main window
# Amendable via preferences
# Mono screens lose the shadow so get a bigger inlay
my $menu_inlay_lines=0;
my $menu_inlay_cols=0;
my $menu_inlay_y=3;         # 2 for mono
my $menu_inlay_x=6;         # 4 for mono

# Extent of Menu text pane
# All defined at runtime depending on the menu items
my $menu_pane_lines=0;
my $menu_pane_cols=0;
my $menu_pane_y=0;
my $menu_pane_x=0;
my $menu_pane_scroll; 

my $menu_resized=0;          # trigger for terminal resizing
my $menu_style=0;            # 
my $max_item_len=0;          # longest menu item
my $max_sel_len=0;           # longest label length
my $menu_top_option=0;       # current menu item at the top of the display
my $menu_cur_option=0;       # the active menu option during navigation
   
# define global colour variables
my %menu_attributes=();      # load and hold color definitions
my $menu_hascolor;           # terminal colour capability flag

# Initialise menu item arrays
my @menu_sel_text =();             # Menu item text
my @menu_sel_style =();            # Menu item type
my @menu_sel_label = ();           # Menu item label
my @menu_sel_flag = ();            # Menu item special
my @menu_sel_return = ();          # value to be returned on selection
my @menu_sel_pos = ();             # Menu item position (data fields)
                                   #   max length + dec.places + 0

# User hacks
my($menu_hack25)=0;                # hack to make a small screen bigger


# Set the default file for help display
my $menu_help="help.txt";
my $menu_help_root="/etc/Cmenu/";

Cmenu.pm  view on Meta::CPAN

# either termcap or terminfo
# --------------------------------------------------------------------------------
   $kseq{scalar(KEY_HOME)}="HOME";    # home
   $kseq{scalar(KEY_END)}="END";      # end
   $kseq{scalar(KEY_PPAGE)}="PREV";   # page up
   $kseq{scalar(KEY_NPAGE)}="NEXT";   # page down
   $kseq{scalar(KEY_IC)}="INS";       # insert toggle
   $kseq{scalar(KEY_DC)}="DEL";       # delete
   $kseq{scalar(KEY_BACKSPACE)}="BS"; # backspace
   $kseq{"\cI"}="TAB";                # tab
   $kseq{scalar(KEY_BTAB)}="BTAB";    # shifted tab
   $kseq{scalar(KEY_UP)}="UP";        # up arrow
   $kseq{scalar(KEY_DOWN)}="DOWN";    # down arrow
   $kseq{scalar(KEY_LEFT)}="LYNXL";   # left arrow
   $kseq{scalar(KEY_RIGHT)}="LYNXR";  # right arrow
   $kseq{scalar(KEY_ENTER)}="RET";    # enter key
   $kseq{scalar(KEY_BREAK)}="EXIT";   # break
   $kseq{"\cJ"}="RET";                # normal return key

   # Functions keys have no special meaning - user mapable
   # some helpful defaults are set here but are not necessary
   $kseq{scalar(KEY_F(1))}="HELP";    # Func key 1
   $kseq{scalar(KEY_F(2))}="NOP";     # Func key 2
   $kseq{scalar(KEY_F(3))}="NOP";     # Func key 3
   $kseq{scalar(KEY_F(4))}="NOP";     # Func key 4
   $kseq{scalar(KEY_F(5))}="NOP";     # Func key 5
   $kseq{scalar(KEY_F(6))}="NOP";     # Func key 6
   $kseq{scalar(KEY_F(7))}="NOP";     # Func key 7
   $kseq{scalar(KEY_F(8))}="QUIT";    # Func key 8
   $kseq{scalar(KEY_F(9))}="EXIT";    # Func key 9
   $kseq{scalar(KEY_F(10))}="NOP";    # Func key 10
   $kseq{scalar(KEY_F(11))}="NOP";    # Func key 11
   $kseq{scalar(KEY_F(12))}="EXIT";   # Func key 12

# ##################################################################################
# BLOCK 3
# =======
# Load defaults from a config file if it exists
# ##################################################################################

   # Does the terminal have colour?
   $menu_hascolor = eval { has_colors() };

   if($menu_hascolor==1) {
	 # Set default colours for init_pairs
	 $menu_attributes{"backdrop"}="6.4.NORMAL";
	 $menu_attributes{"advice"}="6.4.BOLD";
	 $menu_attributes{"text"}="0.7.NORMAL";
	 $menu_attributes{"title"}="3.7.BOLD";
	 $menu_attributes{"option"}="1.7.BOLD";
	 $menu_attributes{"button"}="7.7.BOLD";
	 $menu_attributes{"scroll"}="2.7.BOLD";
	 $menu_attributes{"rtext"}="7.4.BOLD";
	 $menu_attributes{"rtitle"}="6.4.BOLD";
	 $menu_attributes{"roption"}="3.4.BOLD";
	 $menu_attributes{"edge"}="7.7.BOLD";
	 $menu_attributes{"dull"}="0.7.BOLD";
	 $menu_attributes{"help"}="0.2.BOLD";
	 $menu_attributes{"warn"}="7.3.NORMAL";
	 $menu_attributes{"error"}="7.1.NORMAL";
	 $menu_attributes{"popup"}="3.2.BOLD";
	 $menu_attributes{"shadow"}="0.0.NORMAL";
   } else {
	 # Set mono defaults
	 $menu_attributes{"backdrop"}="DIM";
	 $menu_attributes{"advice"}="NORMAL";
	 $menu_attributes{"text"}="NORMAL";
	 $menu_attributes{"title"}="NORMAL";
	 $menu_attributes{"option"}="BOLD";
	 $menu_attributes{"button"}="DIM";
	 $menu_attributes{"scroll"}="NORMAL";
	 $menu_attributes{"rtext"}="REVERSE";
	 $menu_attributes{"rtitle"}="REVERSE";
	 $menu_attributes{"roption"}="REVERSE|BLINK";
	 $menu_attributes{"edge"}="DIM";
	 $menu_attributes{"dull"}="DIM";
	 $menu_attributes{"help"}="REVERSE";
	 $menu_attributes{"warn"}="REVERSE";
	 $menu_attributes{"error"}="REVERSE";
	 $menu_attributes{"popup"}="NORMAL";
   }
   if(-e "/etc/Cmenu/cmenurc") {
     # load system wide preferences
     &menu_config_file("/etc/Cmenu/cmenurc");
   }
   if(-e "~/.cmenurc") {
     # Load the users specific preferences
     &menu_config_file("~/.cmenurc");
   }
   if(-e "cmenurc") {
     # Load the application specific preferences
     &menu_config_file("cmenurc");
   }

   # Now setup colour rendering
   menu_set_colours();

# ##################################################################################
# BLOCK 4
# =======
# Draw the screens backdrop and establish dimensions
# ##################################################################################

   &menu_redraw_backdrop();

   $did_initterm = 1;
 }

 # Calculate the longest keystroke sequence
 $key_max=0;
 foreach $key(sort(keys(%kseq))) {
   if(length($key)>$key_max) { $key_max=length($key); }
    }
}

#**********
#  MENU_CONFIG_FILE
#
#  Function:	Loads user over-rides from a config file
#
#  Call format:	&menu_config_file("filename");
#
#  Notes:       See the modules sample file for data structure
#**********
sub menu_config_file {
  my ($filename) = @_;
  my ($type,$key,$action);

  open(IN,"<$filename");
  while(<IN>) {
    if(length($_)>1) {
      chop;
	  # Remove all spaces
	  s/ //g;
      ($type,undef,$key,$action)=split(/:/);
      if(($type eq "C")&&($menu_hascolor)) { $menu_attributes{$key}=$action; }
      if(($type eq "M")&&(!$menu_hascolor)){ $menu_attributes{$key}=$action; }
      if($type eq "H") { $menu_help_root=$action; }
      if($type eq "K") { $kseq{$key}=$action; }
      if($type eq "X") {

Cmenu.pm  view on Meta::CPAN

      $b[3]=$menu_inlay_cols-$b[1];
    };
  }

  # clear the button bar and redraw it as required
  $j=1;
  for($i=1;$i<=3;$i++) {
    $x=length($menu_button[$i]);
    if($x!=0) {
      if($menu_hot_button==$i) {
	&menu_hot_button($b[$j]-1-$x/2,$menu_button[$i]);
      } else {
	&menu_draw_button($b[$j]-1-$x/2,$menu_button[$i]);
      }
      $j++;
    }
  }
  &noutrefresh($menu_inlay);
  &doupdate();
}

# Draw the active button
sub menu_hot_button {
  my ($h_indent,$text) = @_;
  my ($cap);
  
  # Pick out the capital letter
  $cap=ord(uc($text));
  &attrset($menu_inlay,$menu_attributes{"rtext"});
  &move($menu_inlay,$menu_inlay_lines-2,$h_indent);
  addstr($menu_inlay,"<");
  &attrset($menu_inlay,$menu_attributes{"rtitle"});
  addstr($menu_inlay,$text);
  &attrset($menu_inlay,$menu_attributes{"rtext"});
  addstr($menu_inlay,">");
  &attrset($menu_inlay,$menu_attributes{"roption"});
  &move($menu_inlay,$menu_inlay_lines-2,$h_indent+1);
  addch($menu_inlay,$cap);
}

# Draw an inactive button
sub menu_draw_button {
  my ($h_indent,$text) = @_;

  &attrset($menu_inlay,$menu_attributes{"button"});
  &move($menu_inlay,$menu_inlay_lines-2,$h_indent);
  addstr($menu_inlay,"<");
  addstr($menu_inlay,$text);
  addstr($menu_inlay,">");
}

# ##################################################################################
# Splash screen for Popups and Text displays
# ##################################################################################

#**********
#  MENU_POPUP
#
#  Function:	Pops up a single line text message
#               Can be used to keep users interested while a lengthy process
#               completes; popup remains on screen until destroyed by
#               calling the routine again with no message
#
#  Call format:	&menu_popup(message,title);   # create a popup
#               &menu_popup();                # destroy popup
#
#  Arguments:   - message - a text message to be displayed;
#                 should be single line only, will be truncated if too long
#                 If the message is empty an old popup will be destroyed
#               - title - title centred in the popup border
#                 defaults to "processing" if not provided
#
#  Returns:     nothing
#               
#  Notes:       popup may appear over a blank screen since the menu windows
#               may have been removed (not guaranteed)
#**********
sub menu_popup {
  my ($message,$ptitle) = @_;

  if(!$ptitle) {$ptitle="processing"; }

  &menu_advice(" ");

  if(!$message) {
    # no message so destroy the old popup
    # curses cookery
    echo();               # no input echo until enabled explicitly
    curs_set(1);            # turn the cursor on
    &delwin($menu_popup);
    &menu_redraw_backdrop();
  } else {
    # create a new popup
    noecho();               # no input echo until enabled explicitly
    curs_set(0);            # turn the cursor off
  
    while(length($message)>$menu_screen_cols-8) {
      chop $message;
    };
    # Initialise menu pane and control variables
    $menu_popup=newwin(3,$menu_screen_cols-6,($menu_screen_lines/2)-2,3);
    bkgd($menu_popup,$menu_attributes{"popup"});
    clear($menu_popup);
    &border($menu_popup,0,0,0,0,0,0,0,0);
    move($menu_popup,0,($menu_screen_cols-8-length($ptitle))/2);
    addstr($menu_popup," $ptitle ");

    move($menu_popup,1,($menu_screen_cols-6-length($message))/2);
    addstr($menu_popup,$message);

    &refresh($menu_popup);
    &doupdate();
  }
}

#**********
#  MENU_SHOW
#
#  Function:	Pops up a text message with a button bar
#               Used as a user confirmation advice before a process
#               is performed
#               Button bar defined according to current button settings
#               Help screen is called directly
#
#  Call format:	&menu_show(message);
#
#  Arguments:   - message - a text message to be displayed;
#                 can be multiline (left-just) or single (centred), choice
#                 depends on size of window
#
#  Returns:     a simple string either YES or NO
#               
#  Notes:       Uses Text::Wrap to fill the window if the text to be shown
#               is longer than a line - this allows some formatting to be 
#               performed
#                  \n   forces a line break
#               Check docs for Text::wrap for more info
#               At present only fills to current window depth and will lose
#               any additional text; no scrolling supported yet
#               
#               Useful as a debugging tool for your own scripts to see
#               what is going one since "print" will not work under
#               Curses. 
#               
#**********
sub menu_show {
  my ($temp_title,$message,$colour) = @_;
  my ($attributes,$work,$x,$i,$j);
  my ($menu_popup);
  my (@b);

  &menu_advice(" ");

  if(!$colour) { $colour="ERROR"; }
 SET_COLOR: for ($colour) {
    /WARN/ && do {
      $attributes=$menu_attributes{"warn"};
    };
    /HELP/ && do {
      $attributes=$menu_attributes{"help"};
    };
    /ERROR/ && do {
      $attributes=$menu_attributes{"error"};
    };
  };

  if(!$message) {
    # no message given so ignore the call
    return("NO");
  } else {
    # create a popup with button bar
    bkgd($menu_inlay,$attributes);
    erase($menu_inlay);
    &border($menu_inlay,0,0,0,0,0,0,0,0);
    move($menu_inlay,0,($menu_inlay_cols-length($temp_title)-2)/2);
    addstr($menu_inlay," $temp_title ");

    &noutrefresh($menu_inlay);
    # Initialise menu pane and control variables
    # First define window and draw border
    $menu_pane_y=$menu_inlay_y+1;
    $menu_pane_x=$menu_inlay_x+1;
    $menu_pane_lines=$menu_inlay_lines-3;
    $menu_pane_cols=$menu_inlay_cols-2;
    
    &noutrefresh($menu_inlay);

    $menu_popup=newwin($menu_pane_lines-2,$menu_pane_cols-2,$menu_pane_y,$menu_pane_x+1);
    bkgd($menu_popup,$attributes);
    erase($menu_popup);

    # curses cookery
    cbreak();               # permits keystroke examination
    noecho();               # no input echo until enabled explicitly
    curs_set(0);            # turn the cursor off
  
    if(length($message)<$menu_pane_cols) {
      move($menu_popup,$menu_pane_lines/2,($menu_pane_cols-length($message))/2);
      addstr($menu_popup,$message);
      &refresh($menu_popup);
    } else {
      $Text::Wrap::columns=$menu_pane_cols-2;
      addstr($menu_popup,wrap("","",$message));
      &refresh($menu_popup);
    }
    if($colour eq "HELP") {
      # We have to do this since HELP can be called while in a menu
      # when menu_show would otherwise trash the button labels
      move($menu_inlay,$menu_inlay_lines-2,($menu_inlay_cols/2)-7);
      &attrset($menu_inlay,$attributes|A_BOLD);
      addstr($menu_inlay,"<Press any Key>");
      &refresh($menu_inlay);
      getch($menu_inlay);
    } else {
      do {
	# Calculate position of buttons
      DO_BUTTONS: for ($menu_buttons) {
	  /1/ && do {
	    $b[1]=$menu_inlay_cols/2;
	  };
	  /2/ && do {
	    $b[1]=$menu_inlay_cols/3;
	    $b[2]=$menu_inlay_cols-$b[1];
	  };
	  /3/ && do {
	    $b[1]=$menu_inlay_cols/4;
	    $b[2]=$menu_inlay_cols/2;
	    $b[3]=$menu_inlay_cols-$b[1];
	  };
	}
	# Draw buttons
	$j=1;
	for($i=1;$i<=3;$i++) {
	  $x=length($menu_button[$i]);
	  if($x>0) {
	    # Draw Okay button
	    if($menu_hot_button==$i) {
	      # Make it hot
	      move($menu_inlay,$menu_inlay_lines-2,$b[$j]-($x/2)-1);
	      &attrset($menu_inlay,$attributes|A_BOLD);
	      addstr($menu_inlay,"<$menu_button[$i]>");
	    } else {
	      # make it cool
	      move($menu_inlay,$menu_inlay_lines-2,$b[$j]-($x/2)-1);
	      &attrset($menu_inlay,$attributes);
	      addstr($menu_inlay,"<$menu_button[$i]>");
	    }
	    $j++;
	  }
	}
	&refresh($menu_inlay);
	$work=&menu_key_seq($menu_inlay);
      CONFIRM: for ($work) {
	  /TAB/ && do {
	    $menu_hot_button++;
	    do {
	      $menu_hot_button++;
	      if($menu_hot_button>3) { $menu_hot_button=1; }
	    } until (length($menu_button[$menu_hot_button])>0);
	    $work="";
	    last CONFIRM;
	  };
	  /BACK/ && do {
	    do {
	      $menu_hot_button--;
	      if($menu_hot_button<1) { $menu_hot_button=$menu_buttons; }
	    } until (length($menu_button[$menu_hot_button])>0);
	    $work="";
	    last CONFIRM;
	  };
	  /RET/ && do {
	    if($menu_hot_button==1) { $work="YES"; }
	    if($menu_hot_button==2) { $work="HELP"; }
	    if($menu_hot_button==3) { $work="NO"; }
	    last CONFIRM;
	  };
	  $work="";
	};
      } until ($work ne "");
    }
    # curses cookery
    nocbreak();               # permits keystroke examination
    echo();               # no input echo until enabled explicitly
    curs_set(1);            # turn the cursor on
    &delwin($menu_popup);
    &menu_redraw_backdrop();
  }
  $work;
}


# ##################################################################################
# End of Module
# ##################################################################################

1;

__END__
# Below is the stub of documentation for the module.

=head1 NAME

Cmenu - Perl extension for menuing and data entry in perl scripts

=head1 SYNOPSIS

  use Cmenu;
  use Curses;
  use Text::Wrap;

  &menu_initialise($main_title,$advice);
  &menu_init($title,$sub-title,$topest,$menu_help);
   &menu_item($item_text,$item_label,$item_style,$item_data,$item_pos)
   &menu_item($item_text,$item_label,$item_style,$item_data,$item_pos)
    ...
   &menu_item($item_text,$item_label,$item_style,$item_data,$item_pos)

  $sel=&menu_display($advice,$start_item);

  &menu_button_set($button,$button_text);

  &menu_popup($title,$text);
   ...
  &menu_popup();

  &menu_show($title,$text,$colour);

  &menu_terminate($message);

=head1 DESCRIPTION

CMENU is a Perl Module designed to provide functions for the
creation of menus in perl scripts.

It follows on from perlmenu but uses a Curses interface for
screen manipulation. It also uses the Text::Wrap module to
process large chunks of text for display. These two modules
should be loaded by user scripts.

The sequence of menu processing is as follows;
  1. Initialise the module
    loop
      2. Define a menu structure 
      3. Define several menu options
      4. Call the menu
      5. Deal with the menu selections
    loop
  6. Terminate the module

The module also provide some extra functions.


=head2 menu_initialise

This routine initialises Curses and creates necessary structures
for the menu module. It accepts two parameters which may be empty;
  $main_title  A script-wide title displayed on all pages
  $advice      A short text advisory displayed at the foot
               of every screen (unless over-ridden by the
               module).
The routine returns nothing.

=head2 menu_init

The routine creates a graphic backdrop in the style of the 
command-line utility "dialog". It accepts 3 parameters
  $title        a menu title displayed at the top
  $sub_title    sub-title text used to give more description
  $menu_help    a help-file to be displayed when the Help key
                is pressed. The help file is located in a
                standard location as defined in the configuration
                file. (optional)

=head2 menu_item

Each line of a menu is created using this call.
  $item_text    The text to be displayed as the menu option
  $item_label   A text label which may be displayed beside
                the text
  $item_style   How the menu option should be drawn or behave
                Should be a number from 0 to 9
       0  (default) preceeds the text with a text label
          the label is returned if the item is selected
       1  use number instead of a text label; numbered in

Cmenu.pm  view on Meta::CPAN

                 2 decimal places

=head2 menu_display

Actually performs the menu display and navigation. Returns 
information relevant to the action selected. Accepts 2 parametrs;

  $menu_prompt   Displayed at the foot of the screen as advice
  $menu_start    Which item should be active from the start
                 This allows items other than the first declared
                 to be selected; useful when returning to a menu
                 after an earlier selection (optional)

This is the important call which returns the result of menu
navigation. Depending on the style of menu items defined, various results
will be returned. Generally all selections are a tokenised list seperated
by a standard character ($Cmenu::menu_sep - can be changed by user). For
simple menus, only the selected text label (0,1,4,5) or offset (8) will be
returned.

For radio and check lists (2 and 3) all the selected items will be returned
using each items text label

For edited data fields, more complex values are returned. All editable fields
on a menu will have a token (whether edited or not) returned. Each token has two
fields - the field label and the new field contents; these are seperated by
$Cmenu::menu_sepn.

Since any type of item can be included in a menu, return values may be
equally complex. For complex return values, tokens can be split out using
a command fragment such as

 chop($return_value=&menu_display("Menu Prompt",$start_on_menu_item));
 @selection=split(/$Cmenu::menu_sep/,$return_value);
 for($loop=1;$loop<=$#selection;$i++) {
   # deal with each token
   ($field_label,$field_content) = split(/$Cmenu::menu_sepn,$selection[$i]);
   # processing each field accordingly
   ...
   }

The first token returned ($selection[0]) is usually the key pressed to close the
menu was closed; this will rarely be a valid menu item - check it to make sure 
an "abort" was not requested.

=head2 menu_button_set

Each menu has up to 3 buttons which can be activated. Usually these give
options to either Accept a menu item or Abort the menu prematurely. A Help
facility may also be called.

This routine switches buttons on and off and, specifies the text label of the button
(button actions cannot be altered yielding "ACCEPT", "HELP" or "EXIT" although your 
scripts can interret these responses however you wish). The <TAB> key
traverses the buttons bar.

Parameters for this routine are;
  $button  a number 1, 2 or 3 specifying which button is to be set
  $label   the text label for the button; an empty string switches the button off

=head2 menu_popup

Allows a simple screen to pop-up if a lengthy process has been launched. The popup
has only one line of text to give an indication of what the system is doing; 
  To start a popup - call with $message
  To close a popup - call with NO message
Remember to close the popup or the menu display will get confused.

=head2 menu_show

Allows a variety of information to be shown on the screen; the display
generally replaces normal menu rendering until the user presses an approriate key.
The routines takes 3 parameters
  $title    the title of the display
  $message  the message to be displayed. If this is only one line it will be
            centred; if longer the external routine Text::wrap is used to
            manipulated the text to fit on the screen. Text formatting
            is quite primitive.
            The display cannot be scrolled if it exceeds the dimensions of
            the active window
  $colour   colour style to render the display chosen from HELP|WARN|ERROR
            HELP screens have an automatic button to continue; WARN and ERROR 
            can have multiple buttons (use menu_button_set to control these)

=head2 menu_terminate

Called as the script terminates to close down menu facilities and Curses.
The terminal should be left in a sane state. The $message parameter prints
to STDOUT as the script/routine finishes.

If a scripts aborts before calling this, the sanity of the tty will likely
get lost; use the command "reset" to restore sanity.

=head1 AUTHOR

Andy Ferguson andy@moil.demon.co.uk

=head1 FILES

cmenurc  configuration file to set terminal and screen defaults
          this file may be
             System Wide   - in /etc/Cmenu/.cmenurc
             User specific - ~/.cmenurc
             Run Specific  - ./cmenurc
          See the distributed file for contents.

vt100-wy60 A tic (terminfo) file for VT100 emulation on a Wyse 60
          terminal; this sets the functions keys appropriately

demo      A sample script showing how menus can be rendered with the module.

=head1 BUGS

* No continuation pages or checks for text displays overflowing the windows.
* Resize and Refresh functions can misbehave in spawned shells
* BACKTAB definition from Curses is lost so can only TAB forwards thru buttons

perl(1).

=cut



( run in 1.308 second using v1.01-cache-2.11-cpan-364913b4093 )