3

I want to create a menu with max 10 line window, and display in this window all items from a xml file ( containing more than 10 items), by scrolling up/down line in window to view all content of file.

Questions: How make this possible in my API (like in ncurses scroll menu):

"If the sub window given for a window is not big enough to show all the items, then the menu will be scrollable. When you are on the last item in the present list, if you send REQ_DOWN_ITEM, it gets translated into REQ_SCR_DLINE and the menu scrolls by one item. You can manually give REQ_SCR_ operations to do scrolling. Let's see how it can be done."

Part of my code for this feature:

static void menu( commands_t *cmd )
{
    /* this display only first 10 line */
    int i; 
    char string[ 128 ];
    for( i = 0; i < 10; i++ ) {
        snprintf( string, sizeof (string), "%s", list_get_name( cmd->listmgr, i ) );
        menu_list_set_text( cmd->menu, i, string );
    }
}

Currently, this function can display only the first 10 items from list.

                       A
                       B
                       C  
                       D
                       E
                -----------------
Line 01         |      F        |   
Line 02         |      G        |
Line 03         |      H        |
Line 04         |      I        |
Line 05         |      J        |    
Line 06         |      K        |   
Line 07         |      L        |
Line 08         |      M        |
Line 09         |      N        |
Line 10         |      O        |   
                -----------------
                       P
                       Q
                       R
                       S
                       T
                    .......
                       Z

For this I try to create API capable to set text in menu line from list, move up/down cursor in menu but I don't now how to make to move lines up or down.

typedef struct list_info_s list_info_t;
struct list_info_s
{
    int position;
    char name[ 50 ];

    list_info_t *next;
    list_info_t *prev;
};

const list_info_t *list_get_list( list_mgr_t *mgr, int pos)
{
    const list_info_t *tmp = mgr->first;
    int i;
    for (i = 0; tmp && i < pos; i++)
        tmp = tmp->next;
    return tmp;
}

const char *list_get_name( list_mgr_t *mgr, int position )
{
    const list_info_t *list = list_get_list(mgr, position);
    if( (list) && (*list->name) ) {
        return list->name;
    } else {
        return 0;
    }
}

TO MOVE UP/DOWN:

void commands_handle( commands_t *cmd, int prog_cmd )
{
    switch( prog_cmd ) {
    case MENU_UP:
        cmd->menu_position = (cmd->menu_position + cmd->menu_size - 1) % (cmd->menu_size);
        menu( cmd );
        break;
    case MENU_DOWN:
        cmd->menu_position = (cmd->menu_position + 1) % (cmd->menu_size);
        menu( cmd );
        break;
    return;
    }
} 


MENU:


static void menu( commands_t *cmd )
{
    /* this display only first 10 line */
    int i; 
    char string[ 128 ];
    for( i = 0; i < 10; i++ ) {
        snprintf( string, sizeof (string), "%s", list_get_name( cmd->listmgr, i ) );
        menu_list_set_text( cmd->menu, i, string );
    }
}

Windows of menu is for max 10 items lines because xml may contain a large number of items. What programming options have to display all lines from file to be visible on menu by presing UP/DOWN button?

This is actual API for menu:

#define MENU_MAX 10

struct menu_s
{
    char *name;
    char text[ MENU_MAX ][ 128 ];
    char arguments[ MENU_MAX ][ 128 ];
    int commands[ MENU_MAX ];
    char back_argument[ 128 ];
    int back_command;
    int numlines;
    int cursor;
    int defaultcursor;
};

menu_t *menu_new( const char *name )
{
    menu_t *menu = malloc( sizeof( menu_t ) );
    if( !menu ) {
    return 0;
    }

    menu->numlines = 0;
    menu->cursor = 0;
    menu->defaultcursor = 0;
    menu->name = strdup( name );
    if( !menu->name ) {
        free( menu );
        return 0;
    }

    return menu;
}

void menu_delete( menu_t *menu )
{
    free( menu->name );
    free( menu );
}

void menu_reset_num_lines( menu_t *menu )
{
    menu->numlines = 0;
}

void menu_set_text( menu_t *menu, int line, const char *text )
{
    snprintf( menu->text[ line ], sizeof( menu->text[ 0 ] ), "%s", text );
    if( line >= menu->numlines ) menu->numlines = line + 1;
}

void menu_set_enter_command( menu_t *menu, int line, int command,
                         const char *argument )
{
    menu->commands[ line ] = command;
    snprintf( menu->argum#define MENU_MAX 10

struct menu_s
{
    char *name;
    char text[ MENU_MAX ][ 128 ];
    char arguments[ MENU_MAX ][ 128 ];
    int commands[ MENU_MAX ];
    char back_argument[ 128 ];
    int back_command;
    int numlines;
    int cursor;
    int defaultcursor;
};

menu_t *menu_new( const char *name )
{
    menu_t *menu = malloc( sizeof( menu_t ) );
    if( !menu ) {
    return 0;
    }

    menu->numlines = 0;
    menu->cursor = 0;
    menu->defaultcursor = 0;
    menu->name = strdup( name );
    if( !menu->name ) {
        free( menu );
        return 0;
    }

    return menu;
}

void menu_delete( menu_t *menu )
{
    free( menu->name );
    free( menu );
}

void menu_reset_num_lines( menu_t *menu )
{
    menu->numlines = 0;
}

void menu_set_text( menu_t *menu, int line, const char *text )
{
    snprintf( menu->text[ line ], sizeof( menu->text[ 0 ] ), "%s", text );
    if( line >= menu->numlines ) menu->numlines = line + 1;
}

void menu_set_enter_command( menu_t *menu, int line, int command,
                         const char *argument )
{
    menu->commands[ line ] = command;
    snprintf( menu->arguments[ line ], sizeof( menu->arguments[ 0 ] ),
          "%s", argument );
}

void menu_set_back_command( menu_t *menu, int command,
                        const char *argument )
{
    menu->back_command = command;
    snprintf( menu->back_argument, sizeof( menu->back_argument ),
          "%s", argument );
}

void menu_set_cursor( menu_t *menu, int cursor )
{
    menu->cursor = cursor;
}

const char *menu_get_name( menu_t *menu )
{
    return menu->name;
}

int menu_get_num_lines( menu_t *menu )
{
    return menu->numlines;
}

const char *menu_get_text( menu_t *menu, int line )
{
    return menu->text[ line ];
}

int menu_get_enter_command( menu_t *menu, int line )
{
    return menu->commands[ line ];
}

const char *menu_get_enter_argument( menu_t *menu, int line )
{
    return menu->arguments[ line ];
}

int menu_get_back_command( menu_t *menu )
{
    return menu->back_command;
}

const char *menu_get_back_argument( menu_t *menu )
{
    return menu->back_argument;
}

int menu_get_cursor( menu_t *menu )
{
    return menu->cursor;
}

int menu_get_default_cursor( menu_t *menu )
{
    return menu->defaultcursor;
}

I tried a ugly solution:

static void menu( commands_t *cmd )
{
    int i;
    for( i = 0; i < 10; i++ ) {
        char string[ 128 ];
        snprintf( string, sizeof (string), "%s", list_get_name( cmd->listmgr, i )
        menu_list_set_text( cmd->menu, i, string );
        int scroll;
        for( scroll = 0; scroll < list_size; scroll++ ) {
            if( cmd->curmenupos == 10 + scroll ) {
                snprintf( string, sizeof (string), "%s", list_get_name( cmd->listmgr, i + scroll + 1 )
                menu_list_set_text( cmd->menu, i, string );
            }
         }
      }
   }

where "cmd->curmenupos" is command to get menu line position and "list_size" is number of items from xml

4

1 に答える 1

0

リング バッファーの配列ベースの実装を使用して、ソリューションをいくらか単純化し、左上隅のヘッド/テールからのみメニューを印刷できます。次に、スクロールは頭/尾を進めるだけになり、消えている行を新しい行で上書きします。とにかく行番号が一定であるため、配列ベースの実装を使用しても問題ありません。

IO の速度に応じて、ソフトウェアが使用する IO リソースが少なくなり、古い行の単純なキャッシュによってパフォーマンスが向上する場合があります。時期尚早に最適化しないように注意してください。これは、リング バッファに画面上の行数よりも多くのエントリを持たせ、特定のポイントを過ぎてスクロールするときにのみ上書きすることで実行できます。

于 2013-02-15T12:13:02.463 に答える