Input bar at console bottom in C

后端 未结 4 1207
Happy的楠姐
Happy的楠姐 2021-02-04 03:20

Window bottom

Some applications like vim, mutt, aptitude contain

  • a top window section for output and
  • a bottom section for the user to type in
4条回答
  •  醉酒成梦
    2021-02-04 03:27

    I had a similar issue a few weeks ago while writing an IRC client that runs in the terminal. I wrote it using the Windows conio library, but I'm fairly sure this should be applicable to curses. The idea is that console output is handled by a single thread, and console input is handled in a separate thread. Basically, all you need is a loop that pushes the return of getch() onto a mutexed FIFO that runs for the duration of the program. In the display thread, you can pop the keypresses off the FIFO and handle them however you like. You can't use a standard function like fgets(), but it's a very solid solution to your problem. I can provide the full (messy) source on request.

    Edit: alright, well here's the relevant code from the FIFO pushing:

    bool keyqueuewriting = false;
    std::deque keyqueue;
    void grabkey( void* in )
    {
        int t;
        while( true ){
            t = getch();
            #ifdef _WIN32
            if( t == 224 || t == 0 )
            {
                t += getch() << 8;
            }
            #else
                int off = 8;
                if( t == 27 ){
                    int e = getch();
                    t += e << off;
                    off += 8;
                    while( e ==91 || (e >= '0' && e <= '9') || e == ';' )
                    {
                        e = getch();
                        t += e << off;
                        off += 8;
                    }
                }
            #endif
            while( keyqueuewriting ){}
            keyqueuewriting = true;
            keyqueue.push_back( t );
            keyqueuewriting = false;
        }
    }
    

    And Handling:

    while( keyqueuewriting ){}
    keyqueuewriting = true;
    while( keyqueue.size() > 0 )
    {
        shouldsleep = false;
        int t = keyqueue.front();
        keyqueue.pop_front();
        switch( t )
        {
            case K_BACKSPACE:
                if( pos > 0 ){
                    for( int i = pos-1; input[i] != 0; i++ ){input[i] = input[i+1];}
                    movecursorback( 1 );
                    pos -= 1;
    
                    } break;
            case K_LEFT: if( pos > 0 ){ movecursorback( 1 ); pos -= 1; } break;
            case K_RIGHT: if( input[pos] != 0 ) {movecursorforward( 1 ); pos += 1;} break;
            case K_HOME: { gotoxy(0,SCREENHIG-1); pos = 0; } break;
            case K_END: { int a = strlen( input ); /*gotoxy( 79,39 );*/ pos = a;} break;
            case 3: exit(3); break;
    
            default: if( t >= 0x20 && t < 0x80 ){
                    int a = strlen( input );
                    if( a > 998 )
                        a = 998;
                    int deadcode = 1;
                    input[999] = 0;
                    for( int i = a+1; i > pos; i-- ){input[i] = input[i-1];}
                    input[ pos ] = t;
                    movecursorforward( 1 );
                    pos++;
                    } break;
        }
        change = bufpos[curroom] - bufprev;
        if( pos > 998 ) pos = 998;
        if( pos - mescroll < 1 ) {mescroll += (pos-mescroll-1); gotoxy( pos-mescroll, SCREENHIG-1 );}
        if( pos - mescroll > 78 ) {mescroll += (pos-mescroll-78); gotoxy( pos-mescroll, SCREENHIG-1 );}
        if( mescroll < 0 ) {mescroll = 0; gotoxy( 0, SCREENHIG-1 ); }
        savexy();
        gotoxy( 0, SCREENHIG-1 );
        char y = (input+mescroll)[79];
        (input+mescroll)[79] = 0;
        printf( "%s   ", input+mescroll );
        (input+mescroll)[79] = y;
    
        returntosaved();
        change2 = change;
        bufprev = bufpos[curroom];
    }
    keyqueuewriting = false;
    

    Yes, it uses std::deque. That should be the only C++ specific thing though. Just replace it with a C compatible FIFO.

    The entire client can be found here. Yes, it DOES compile in Linux, but it doesn't work. I never bothered to figure out how ncurses should be used before I started work on it.

提交回复
热议问题