curses mouse cut/paste on solaris2.9, hangs on select(). Works fine on aix and linux

From: Ajay (ajay.rathaur_at_wipro.com)
Date: 11/30/03


Date: 30 Nov 2003 06:56:45 -0800

Hi ,

I am facing problem with a curses program which does not work on
Solaris(2.9),
if the user inputs a strings using mouse. The string is not visible on
the window and it hangs on the select() system call

The program works fine on solaris, if the user inputs the string from
the keyboard.

The same program works fine with both mouse and keyboard input on
AIX433 and linux.

Here is the brief description of the program named test.c

main () : initialises a window
TST_GetInput() : gets input from stdin and collects it into a buffer
tstGetInput() : collect characters typed on the stdin
TST_PrintInput() : prints the string on the window.
tstWprintw() : outputs character by character on the output window

To compile :
g++ -fPIC test.c -lcurses

P.S: if the user paste only one character at a time using mouse, the
program works.

Here is the complete program :

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <curses.h>

#define LINE_BUF_SIZE 256

const char RMI_ATTRIBUTE = '~';
const char *defaultText = NULL;
const char gcReturn = '\r';
//const char gcReturn = 0xd;

const char gcBackSpace = 8;
const char gcDelete = 127;

void TST_GetInput( char* aosBuffer,
                   const char *defaultText=0,
                   const char dispChar=0);

int tstGetInput ( fd_set *fdSet );
void TST_PrintInput ( const char *text, const char *prompt = 0);
void tstWprintw(WINDOW* win, const char* string);

void TST_ClearInput ( void );

WINDOW *win;

int main()
{

   char input_buffer[512];
   chtype ch;
   int i ;
   initscr();
   noecho();
   nonl();
   leaveok(stdscr, TRUE);
   clearok(stdscr, FALSE);
   keypad(stdscr, TRUE);
   cbreak();
   halfdelay(5);

   win = subwin(stdscr,1,66,23,13);
   box(win, 'l', '-');
   wrefresh(win);
   TST_GetInput(input_buffer);

   endwin();

}

void TST_GetInput( char* aosBuffer,
                   const char *defaultText,
                   const char dispChar)
{

      const int liInputBufferSize = LINE_BUF_SIZE;
   char lsInputBuffer[liInputBufferSize];
   char lsDispBuffer[liInputBufferSize * 2];

   int inputChar = 0;
   int liInputPos = 0,
        liDispPos = 0;
   int doneInput = 0;
   int inPrompt = 0; // declaration on inPrompt
   fd_set fdSet;
   int i;
   memset(lsInputBuffer, 0, sizeof(char) * liInputBufferSize);
   memset(lsDispBuffer, 0, sizeof(char) * liInputBufferSize);
   TST_PrintInput(NULL);

  FD_ZERO( &fdSet );
   inPrompt = 1;
   flushinp();

   while( ! doneInput )
   {
       inputChar = tstGetInput( &fdSet );

       if( isprint(inputChar) ||
            inputChar == gcBackSpace ||
            inputChar == gcDelete )
       {
         switch(inputChar)
         {
            case gcBackSpace:
            case gcDelete:
               if(liInputPos > 0)
               {
                  liDispPos--;
                  if( liDispPos > 0 &&
                      lsDispBuffer[liDispPos] == RMI_ATTRIBUTE )
                    lsDispBuffer[liDispPos--] = 0;
                  lsInputBuffer[--liInputPos] = 0;
                  lsDispBuffer[liDispPos] = 0;

                  // Print the modified buffer
                  // The following function locks and unlocks the
curses mutex
                  TST_PrintInput(lsDispBuffer);

               }

                break;

            default:

               if(liInputPos < liInputBufferSize - 1)
               {
                  lsDispBuffer[liDispPos++] = dispChar ? dispChar :
inputChar;
                  if( ! dispChar && inputChar == RMI_ATTRIBUTE )
                    {
                    lsDispBuffer[liDispPos++] = RMI_ATTRIBUTE;
                    }
                  lsInputBuffer[liInputPos++] = inputChar;
                  TST_PrintInput(lsDispBuffer);

               }
              break;
         }
       }
        else
       {
         switch( inputChar )
         {
             case gcReturn:
               if( liInputPos == 0 )
               {
                 if( defaultText )
                 {
                   strcpy( lsInputBuffer, defaultText );
                   liInputPos = strlen( lsInputBuffer );
                   doneInput = 1;
                 }
               }
               else
                 doneInput = 1;
               break;
            default:
               printf("\n non printable value 0x%x %d\n", inputChar,
inputChar );
        }
     }
  }

   if(aosBuffer!=NULL)
   {
      strcpy(aosBuffer, lsInputBuffer);
   }

   TST_ClearInput();

}

void TST_ClearInput ( void )
{
   TST_PrintInput( "", "" );
}

int tstGetInput ( fd_set *fdSet )
{

   int inputFd = fileno( stdin ),
       maxFd,
       selectRc,
       lockResult,
       cancelState;

   maxFd = inputFd + 1;
   FD_SET( inputFd, fdSet );
   selectRc = select( maxFd, fdSet, 0, 0, 0 );
   if( ( selectRc > 0 ) &&
       FD_ISSET( inputFd, fdSet ) )
   {

      // Get input - non-blocking
     selectRc = wgetch(win);
     // selectRc = getc(stdin);
   }

   return selectRc;
}

void TST_PrintInput ( const char *text, const char *prompt)
{
   const char *DEFAULT_PROMPT = ">";
   size_t text_length = 0;
   size_t prompt_length = 0;

   if(text!=NULL)
      text_length = (*text != 0 );

   if(prompt!=NULL)
      prompt_length = (*prompt != 0);
   wmove(win, 0, 0);

   // If prompt is NULL, use the default prompt
   // If prompt is non-NULL and greater than zero length, print it
instead
   if( prompt == NULL )
      tstWprintw( win, DEFAULT_PROMPT );
    else if( prompt_length )
      tstWprintw( win, (char *)prompt );

   // If text is non-NULL and greater than zero length, print it
   if( text_length )
   {
      tstWprintw( win, (char *)text );
   }

   // Clear the rest of the line
   wclrtoeol(win);

   //Copy window structure to the terminal
   wnoutrefresh(win);

   // Redisplay the terminal
   doupdate();

}

void tstWprintw(WINDOW* win, const char* string)
{
   unsigned int attribute = A_NORMAL;
   chtype outputChar;
   int i, j;
   int stringLength;

   stringLength = strlen(string);
   i = 0;
   while( i < stringLength )
   {
      switch( string[i] )
      {
      case RMI_ATTRIBUTE:
         i += 2;
         switch( string[i-1] )
         {
         case 's':
            attribute = attribute & ~A_STANDOUT;
            break;

         case 'S':
            attribute = attribute | A_STANDOUT;
            break;
         case '~':
            outputChar = '~' | attribute;
            waddch(win, outputChar);
            break;
         default:
            break;
         }

         break;

      case '\n':
         if( i == stringLength - 1 )
         {
           wclrtoeol(win);
           i++;
           break;
         }
      default:
         outputChar = string[i] | attribute;
          waddch(win, outputChar);
         i++;
         break;
      }

   }
}


Quantcast