略微加速

PHP官方手册 - 互联网笔记

PHP - Manual: Ncurses 函数

2024-12-27

Ncurses 函数

Table of Contents

add a note add a note

User Contributed Notes 16 notes

up
3
kermodebear at kermodebear dot org
14 years ago
Not calling ncurses_end() can (will) cause issues with terminals. Although registering a shutdown function which includes ncurses_end() may help, sometimes things go awry and you're stuck with a terminal that is acting in strange ways.

This can be fixed! *NIX systems (FreeBSD, Linux, UNIX, et al.) usually support the 'reset' command which resets the terminal settings and allows you to get things back to normal.
up
2
Anonymous
16 years ago
In the example above, if you run resize from a C shell it will output the sizes in C shell syntax, run resize with -u to force Bourne syntax:
The $win parameter is just for future compatibility.

function ncurses_getmaxyx($win, &$y, &$x)
{
        exec("/usr/X11R6/bin/resize -u", $output);
        $cols = explode("=", $output[0]);
        $rows = explode("=", $output[1]);
        $x = intval($cols[1]);
        $y = intval($rows[1]);
}
up
1
krzysztof dot gorzelak at gmail dot com
13 years ago
Here is a small example, how to use STDIN to read keys combinations in console.

$stdin = fopen('php://stdin', 'r');
stream_set_timeout($stdin, 1);
while (1) {
  $temp="";
    while (1) {
      if(stream_select($read = array($stdin), $write = NULL, $except = NULL, 0))
        $temp .= ord(fgetc($stdin));
      else break;
    }

    // F1 : $temp == 27914949126
    // ALT+F1 : $temp = 2727914949126
    // ....
   
    usleep("50000");
}
up
1
kermodebear at kermodebear dot org
14 years ago
Here is a function that takes an associative array, presents a menu in a new window, allows the user to make a choice using up and down arrows and the enter key, and returns the value of the menu item.

Limitations include:
No way of scrolling a long list, either horiontally or vertically;
No arguments for placement on screen, although this is easy to add;
No multiple selection;
Will produce all kinds of errors and warnings if the terminal is smaller than is necessary to create the window.

I'm very new at using the ncurses library; Comments and improvements would be greatly appreciated!

<?php
/**
* Create a simple selection menu
* @param array Associative array; The value will be shown on the menu, while the key will be returned when the associated value is selected.
* @return mixed
*/
function ncurses_menu_select( $menu ) {
       
$keys = array_keys( $menu );
       
$values = array_values( $menu );

       
$height = $width = 0;
       
$height = count( $menu ) + 2;
        foreach(
$values as $value ) {
               
$width = max( $width, strlen( $value ) + 2 );
        }

       
$menu_window = ncurses_newwin( $height, $width, 5, 5 );
       
ncurses_wborder( $menu_window, 0,0, 0,0, 0,0, 0,0 );

       
$current = 0;
        for(
$a = 0; $a < count( $values ); $a++ ) {
                if (
$a == $current ) {
                       
ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
                       
ncurses_mvwaddstr( $menu_window, 1 + $a, 1, $values[ $a ] );
                       
ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
                } else {
                       
ncurses_mvwaddstr( $menu_window, 1 + $a, 1, $values[ $a ] );
                }
        }
       
ncurses_wrefresh( $menu_window );

        while( !
in_array( $key = ncurses_getch( $menu_window ), array( 13, 10 ) ) ) {
                if (
$key == NCURSES_KEY_UP AND $current > 0 ) {
                       
$move = -1;
                } else if (
$key == NCURSES_KEY_DOWN and $current < count( $values ) - 1 ) {
                       
$move = 1;
                } else {
                       
$move = 0;
                }
               
ncurses_mvwaddstr( $menu_window, 1 + $current, 1, $values[ $current ] );
               
$current += $move;
               
ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
               
ncurses_mvwaddstr( $menu_window, 1 + $current, 1, $values[ $current ] );
               
ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
               
ncurses_wrefresh( $menu_window );
        }
       
ncurses_delwin( $menu_window );
        return
$keys[ $current ];
}
?>

Example Use:

<?php
// Initialie ncurses
$ncurse = ncurses_init();
// A full screen window
$fullscreen = ncurses_newwin ( 0, 0, 0, 0);
// Add a pretty border
ncurses_border(0,0, 0,0, 0,0, 0,0);
// Draw everything so far
ncurses_refresh();

// Set up menu array
$menu_items = array(
       
'one'   => 'Menu Item #1',
       
'two'   => 'Menu Item #2',
       
'three' => 'Menu Item #3' );
// Display menu and return selection
$selection = ncurses_menu_select( $menu_items );

// Print selection
ncurses_mvaddstr( 1, 1, 'You selected ' . $menu_items[$selection] . ' with the value ' . $selection );

// Draw updates
ncurses_refresh( $fullscreen );
// End
ncurses_end();
?>
up
1
Habib Valanejad
15 years ago
What if you want to draw a new window and after removing it, showing the pervious screen again? Unfortunately, there is no such a thing in php/ncurses as there is in original curses library (touchwin if I'm not mistaken - It has been a long time!).
However, you can do this by a simple trick! You can
dump the screen to a temp file and then restore it back
again!
Take a look at this function:

# Function: show_a_win()
# - Displays a small window and writes something in it.
# - waits for a key
# - shows the pervious screen again
function show_a_win()
{
   # Dump the current screen into a temp file:
   $tmpfile = tempnam("/tmp", "dump.");
   # Create a new window.
   $newwin = ncurses_newwin(4, 60, 10, 10);
   # Write something and then refresh it
   ncurses_mvwaddstr($newwin, 1, 1, "This is a test.");
   ncurses_wrefresh($newwin);
   # Wait for a key
   ncurses_wgetch($newwin);
   ncurses_delwin($newwin);  /* delete the window */
   /* Restore the screen the same way it was before entering
    * into the function:
    */
   ncurses_scr_restore($tmpfile);
   unlink($tmpfile);   /* Remove temp file */
}
up
1
Habib Valanejad
15 years ago
Here is a function which would do the job for missing
ncurses_wclrtoeol() function:
/* wclrtoeol()
* Erases  the  current line to the right of the cursor
*/
function wclrtoeol($win)
{
   # get current position
   ncurses_getyx($win, &$crow, &$ccol);
   # get maximum row and col for this window:
   ncurses_getmaxyx($win, &$max_row, &$max_col);
   for ($col = $ccol; $col < $max_col; $col ++){
      ncurses_wmove($win, $crow, $col);
      ncurses_waddch($win, 32);
   }
}
up
1
rainman at darkwired dot org
15 years ago
This is not meant as spam to get people to use my client.

I have been working on a PHP4 IRC client with ncurses interface and I think it is a useful example of how ncurses with php could be used.
It is GPL licensed so you can just go and take a loot at it.

It can be found at http://torc.sourceforge.net or http://www.darkwired.org/projects/torc/

I hope this will help out some of you because php ncurses can be quite difficult I experienced :]

For any questions about the code you can ofcourse just mail me.
up
1
Habib Valanejad
15 years ago
I had a small problem building php+ncurses support.
ncurses include files were installed in:
ncurses_installed_dir/include/ncurses
This caused problems when building php with ncurse support.
php was looking for include files in:
ncurses_installed_dir/include
However, include files were located in include/ncurses

I had to make symbolic links of files in ncurses directory so php could see them:
# cd ncurses_insalled_directory/include
# ln -s ncurses/* .
After that it worked.
up
1
joeldegan AT yahoo.com
16 years ago
See the documentation for ncurses_border and ncurses_wrefresh for some more examples of doing windowing and dynamic sizing.. I also posted some information to the zend.com code-gallery for doing ncurses under php.
up
1
joeldegan AT yahoo.com
16 years ago
I noticed a lack of a getxy() function so I wrote one.
You may need to change the path for your resize cmd.

<?
function getxy(){
    $rez = `/usr/X11R6/bin/resize`;
    $rez = explode("\n",$rez);
    while(list($key,$val)=each($rez)){
        $a=explode("=",$val);
        if(trim($a[0])=="COLUMNS"){ $COLUMNS = $a[1]; }
        if(trim($a[0])=="LINES"){ $LINES = $a[1]; }
    }//
    $retval[0]=$COLUMNS;
    $retval[1]=$LINES;
   return $retval;
}

print_r(getxy());
?>
up
1
joeldegan AT yahoo.com
16 years ago
This is from the examples that come with the latest release.

From:
php-4.3.0RC3/ext/ncurses/example1.php

I found this useful...

<?php
$n
=0;
ncurses_init();
if(
ncurses_has_colors()){
ncurses_start_color();
       
ncurses_init_pair(1,NCURSES_COLOR_RED,NCURSES_COLOR_BLACK);
       
ncurses_init_pair(2,NCURSES_COLOR_GREEN,NCURSES_COLOR_BLACK);
       
ncurses_init_pair(3,NCURSES_COLOR_YELLOW,NCURSES_COLOR_BLACK);
       
ncurses_init_pair(4,NCURSES_COLOR_BLUE,NCURSES_COLOR_BLACK);
       
ncurses_init_pair(5,NCURSES_COLOR_MAGENTA,NCURSES_COLOR_BLACK);
       
ncurses_init_pair(6,NCURSES_COLOR_CYAN,NCURSES_COLOR_BLACK);
       
ncurses_init_pair(7,NCURSES_COLOR_WHITE,NCURSES_COLOR_BLACK);
}
while(
1){
for (
$x=0; $x<80; $x++) {
for (
$y=0; $y<24; $y++) {
 
$n++;
 
ncurses_move($y,$x);
 
ncurses_addch($n+64);
 
ncurses_color_set($n%8);
 
ncurses_refresh();
  if(
$n>26)$n=0;
}
}
ncurses_getch();
}
?>
up
1
nweeks at utas dot edu dot au
16 years ago
With your CGI version of PHP compiled with ncurses support, console apps are amazingly easy!

For example:
whack the following into a file, chmod +x it, and run it.

#!/usr/local/bin/php -q
<?php
ncurses_init
();
ncurses_border(25,25,18,18,24,24,23,23); // Do a lovely border
ncurses_move(1,1); // Start top left(inside border)
ncurses_addstr("Welcome to NCurses");
ncurses_addstr(" with PHP!");
ncurses_refresh(); // Send buffer to screen
ncurses_end(); // Clean up, and quit
?&gt;

You'll notice the second addstr simply tacks onto the first.
up
0
g_a at freemail dot deletethispart dot hu
13 years ago
To determine screen width and height without any external (OS specific) commands, I use:

<?php
ncurses_init
();
$fullscreen = ncurses_newwin ( 0, 0, 0, 0);
ncurses_getmaxyx($fullscreen,&$a,&$b);
ncurses_end();
echo
"Width:$b\nHeight:$a\n";
?>
up
0
kermodebear at kermodebear dot org
14 years ago
An implementation of a scrolling selection box:

<?php
function ncurses_menu_select( $options, $values, $max_height = 7, $max_width = 20, $y = 2, $x = 2 ) {
       
// Size inside of borders
       
$height = $max_height - 2;
       
$width  = $max_width  - 2;

       
// Number of options
       
$num_options = count( $options );

       
// Trim all values to fit
       
foreach( $options as $key => $value ) {
               
$options[ $key ] = substr( $value, 0, $width );
        }

       
// Create Window
       
$menu_window = ncurses_newwin( $max_height, $max_width, $y, $x );
       
ncurses_wborder( $menu_window, 0, 0, 0, 0, 0, 0, 0, 0 );

       
// Initialize Window
       
$current = 0; // Currently selected
       
$position = 1; // Position in list
       
$topitem = 0; // Top menu item
       
for ( $a = 0; $a < min( $height, $num_options ); $a++ ) {
                if (
$a == $current ) {
                       
ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
                       
ncurses_mvwaddstr( $menu_window, 1 + $a, 1, $options[ $a ] );
                       
ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
                } else {
                       
ncurses_mvwaddstr( $menu_window, 1 + $a, 1, $options[ $a ] );
                }
        }
       
ncurses_mvwaddstr( $menu_window, 1, 0, '*' );
       
ncurses_wrefresh( $menu_window );
       
// Loop until a selection is made
       
while( ! in_array( $key = ncurses_getch( $menu_window ), array( 13, 10 ) ) ) {
                if (
$key == NCURSES_KEY_UP && $current > 0 ) {
                       
$move = -1;
                } else if (
$key == NCURSES_KEY_DOWN && $current < $num_options - 1 ) {
                       
$move = 1;
                } else {
                        continue;
                }

               
$current += $move;
               
$position += $move;
               
// If we scroll off the window, redraw items.
               
if ( $position < 1 || $position > $height ) {
                        if (
$position < 1 ) {
                               
$position = 1;
                        } else {
                               
$position = $height;
                        }
                       
$topitem += $move;
                        for (
$a = 1; $a <= $height; $a++ ) {
                               
ncurses_mvwaddstr( $menu_window, $a, 1, str_repeat( ' ', $width ) );
                                if (
$a == $position ) {
                                       
ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
                                       
ncurses_mvwaddstr( $menu_window, $a, 1, $options[ $topitem + $a - 1 ] );
                                       
ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
                                } else {
                                       
ncurses_mvwaddstr( $menu_window, $a, 1, $options[ $topitem + $a - 1 ] );
                                }
                        }
                } else {
// Just update changed items
                       
ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
                       
ncurses_mvwaddstr( $menu_window, $position, 1, $options[ $current ] );
                       
ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
                       
ncurses_mvwaddstr( $menu_window, $position - $move, 1, $options[ $current - $move ] );
                }
               
// Update 'scroll bar dot'
               
ncurses_wborder( $menu_window, 0, 0, 0, 0, 0, 0, 0, 0 );
               
$dot_position = round ( ( $current / $num_options ) * ( $height - 1 ) );
               
ncurses_mvwaddstr( $menu_window, 1 + $dot_position, 0, '*' );

               
ncurses_wrefresh( $menu_window );
        }
        return
$values[ $current ];
}

?>
up
0
Habib Valanejad
16 years ago
For those of you who want to check if <ENTER> key is passed,
you have to check the key agains both NL and CR keys:

function get_str()
{
   for ($str = "";;){
      $key = ncurses_getch();
      switch ($key){
        case 10:   // newline
        case 13:   // Carrige Return
           return($str);
        default:
           $str .= chr($key);
            ncurses_refresh();
      } // switch
   } // for
} // get_str()

Hope that would help.
up
0
joeldegan AT yahoo.com
16 years ago
actually *that* example does not work...
here is one that I took and trimmed down from the ncurses examples.
I will do some more and post them here..

<?
ncurses_init();
##############################################
ncurses_noecho();

    $large = ncurses_newwin(20, 60, 2, 10);
    $small = ncurses_newwin(10, 30, 7, 25);
   
    ncurses_refresh();
    ncurses_wrefresh($large);
    ncurses_wrefresh($small);

    ncurses_mvwaddstr($small, 5, 5, "   Test  String   ");
    ncurses_wrefresh($small);
    ncurses_getch();

##############################################
ncurses_end(); // Clean up, and quit
?>

This is from PHP 4.3.0RC0 compiled with the following flags..
./configure --prefix=/wwwroot/php --with-config-file-path=/wwwroot/php --with-mysql --enable-pcntl --with-tsrm-pthreads --enable-sysvsem --enable-sysvshm --with-curl --enable-bcmath --enable-sigchild --enable-sockets --with-ncurses

官方地址:https://www.php.net/manual/en/ref.ncurses.php

北京半月雨文化科技有限公司.版权所有 京ICP备12026184号-3