void call_list_destroy(PANEL *panel) { call_list_info_t *info; // Free its status data if ((info = call_list_info(panel))) { // Deallocate forms data if (info->form) { unpost_form(info->form); free_form(info->form); free_field(info->fields[FLD_LIST_FILTER]); } // Deallocate group data call_group_destroy(info->group); // Deallocate panel windows delwin(info->list_win); sng_free(info); } // Deallocate panel window delwin(panel_window(panel)); // Deallocate panel pointer del_panel(panel); }
void column_select_update_columns(ui_t *ui) { int column, attr_id; // Get panel information column_select_info_t *info = column_select_info(ui); // Set enabled fields ui_t *ui_list = ui_find_by_type(PANEL_CALL_LIST); call_list_info_t *list_info = call_list_info(ui_list); // Reset column count list_info->columncnt = 0; // Add all selected columns for (column = 0; column < item_count(info->menu); column++) { // If column is active if (!strncmp(item_name(info->items[column]), "[ ]", 3)) continue; // Get column attribute attr_id = sip_attr_from_name(item_userptr(info->items[column])); // Add a new column to the list call_list_add_column(ui_list, attr_id, sip_attr_get_name(attr_id), sip_attr_get_title(attr_id), sip_attr_get_width(attr_id)); } }
void call_list_draw_header(PANEL *panel) { const char *infile, *coldesc; int height, width, colpos, collen, i; // Get panel info call_list_info_t *info = call_list_info(panel); // Let's draw the fixed elements of the screen WINDOW *win = panel_window(panel); getmaxyx(win, height, width); // Draw panel title draw_title(panel, "sngrep - SIP messages flow viewer"); // Draw a Panel header lines clear_line(win, 1); if ((infile = capture_get_infile())) mvwprintw(win, 1, width - strlen(infile) - 11, "Filename: %s", infile); mvwprintw(win, 2, 2, "Display Filter: "); mvwprintw(win, 1, 2, "Current Mode: %s", capture_get_status_desc()); // Reverse colors on monochrome terminals if (!has_colors()) wattron(win, A_REVERSE); // Draw columns titles wattron(win, A_BOLD | COLOR_PAIR(CP_DEF_ON_CYAN)); mvwprintw(win, 3, 0, "%*s", width, ""); for (colpos = 6, i = 0; i < info->columncnt; i++) { // Get current column width collen = info->columns[i].width; // Get current column title coldesc = sip_attr_get_title(info->columns[i].id); // Check if the column will fit in the remaining space of the screen if (colpos + strlen(coldesc) >= width) break; mvwprintw(win, 3, colpos, "%.*s", collen, coldesc); colpos += collen + 1; } // Print Autoscroll indicator if (info->autoscroll) mvwprintw(win, 3, 0, "A"); wattroff(win, A_BOLD | A_REVERSE | COLOR_PAIR(CP_DEF_ON_CYAN)); // Get filter call counters sip_calls_stats(&info->callcnt, &info->dispcallcnt); // Print calls count (also filtered) mvwprintw(win, 1, 35, "%*s", 35, ""); if (info->callcnt != info->dispcallcnt) { mvwprintw(win, 1, 35, "Dialogs: %d (%d displayed)", info->callcnt, info->dispcallcnt); } else { mvwprintw(win, 1, 35, "Dialogs: %d", info->callcnt); } }
const char * call_list_line_text(PANEL *panel, sip_call_t *call, char *text) { int i, collen; char call_attr[256]; char coltext[256]; int colid; int width; WINDOW *win = panel_window(panel); // Get window width width = getmaxx(win); // Get panel info call_list_info_t *info = call_list_info(panel); // Print requested columns for (i = 0; i < info->columncnt; i++) { // Get current column id colid = info->columns[i].id; // Get current column width collen = info->columns[i].width; // Check if next column fits on window width if (strlen(text) + collen >= width) collen = width - strlen(text); // If no space left on the screen stop processing columns if (collen <= 0) break; // Initialize column text memset(coltext, 0, sizeof(coltext)); memset(call_attr, 0, sizeof(call_attr)); // Get call attribute for current column if (call_get_attribute(call, colid, call_attr)) { sprintf(coltext, "%.*s", collen, call_attr); } // Add the column text to the existing columns sprintf(text + strlen(text), "%-*s ", collen, coltext); } return text; }
int call_list_add_column(PANEL *panel, enum sip_attr_id id, const char* attr, const char *title, int width) { call_list_info_t *info; if (!(info = call_list_info(panel))) return 1; info->columns[info->columncnt].id = id; info->columns[info->columncnt].attr = attr; info->columns[info->columncnt].title = title; info->columns[info->columncnt].width = width; info->columncnt++; return 0; }
void call_list_clear(PANEL *panel) { call_list_info_t *info; // Get panel info if (!(info = call_list_info(panel))) return; // Initialize structures info->first_call = info->cur_call = -1; info->first_line = info->cur_line = 0; vector_clear(info->group->calls); // Clear Displayed lines werase(info->list_win); }
int call_list_resize(PANEL *panel) { int maxx, maxy; // Get panel info call_list_info_t *info = call_list_info(panel); // Get current screen dimensions getmaxyx(stdscr, maxy, maxx); // Change the main window size wresize(panel_window(panel), maxy, maxx); // Calculate available printable area wresize(info->list_win, maxy - 5, maxx - 4); // Force list redraw call_list_clear(panel); return 0; }
void call_list_form_activate(PANEL *panel, int active) { call_list_info_t *info = call_list_info(panel); // Store form state info->form_active = active; if (active) { set_current_field(info->form, info->fields[FLD_LIST_FILTER]); // Show cursor curs_set(1); // Change current field background set_field_back(info->fields[FLD_LIST_FILTER], A_REVERSE); } else { set_current_field(info->form, NULL); // Hide cursor curs_set(0); // Change current field background set_field_back(info->fields[FLD_LIST_FILTER], A_NORMAL); } post_form(info->form); form_driver(info->form, REQ_END_LINE); }
void column_select_create(ui_t *ui) { int attr_id, column; MENU *menu; column_select_info_t *info; // Cerate a new indow for the panel and form ui_panel_create(ui, 20, 60); // Initialize Filter panel specific data info = sng_malloc(sizeof(column_select_info_t)); // Store it into panel userptr set_panel_userptr(ui->panel, (void*) info); // Initialize the fields info->fields[FLD_COLUMNS_ACCEPT] = new_field(1, 10, ui->height - 2, 13, 0, 0); info->fields[FLD_COLUMNS_SAVE] = new_field(1, 10, ui->height - 2, 25, 0, 0); info->fields[FLD_COLUMNS_CANCEL] = new_field(1, 10, ui->height - 2, 37, 0, 0); info->fields[FLD_COLUMNS_COUNT] = NULL; // Field Labels set_field_buffer(info->fields[FLD_COLUMNS_ACCEPT], 0, "[ Accept ]"); set_field_buffer(info->fields[FLD_COLUMNS_SAVE], 0, "[ Save ]"); set_field_buffer(info->fields[FLD_COLUMNS_CANCEL], 0, "[ Cancel ]"); // Create the form and post it info->form = new_form(info->fields); set_form_sub(info->form, ui->win); post_form(info->form); // Create a subwin for the menu area info->menu_win = derwin(ui->win, 10, ui->width - 2, 7, 0); // Initialize one field for each attribute for (attr_id = 0; attr_id < SIP_ATTR_COUNT; attr_id++) { // Create a new field for this column info->items[attr_id] = new_item("[ ]", sip_attr_get_description(attr_id)); set_item_userptr(info->items[attr_id], (void*) sip_attr_get_name(attr_id)); } info->items[SIP_ATTR_COUNT] = NULL; // Create the columns menu and post it info->menu = menu = new_menu(info->items); // Set current enabled fields // FIXME Stealing Call list columns :/ call_list_info_t *list_info = call_list_info(ui_find_by_type(PANEL_CALL_LIST)); // Enable current enabled fields and move them to the top for (column = 0; column < list_info->columncnt; column++) { const char *attr = list_info->columns[column].attr; for (attr_id = 0; attr_id < item_count(menu); attr_id++) { if (!strcmp(item_userptr(info->items[attr_id]), attr)) { column_select_toggle_item(ui, info->items[attr_id]); column_select_move_item(ui, info->items[attr_id], column); break; } } } // Set main window and sub window set_menu_win(menu, ui->win); set_menu_sub(menu, derwin(ui->win, 10, ui->width - 5, 7, 2)); set_menu_format(menu, 10, 1); set_menu_mark(menu, ""); set_menu_fore(menu, COLOR_PAIR(CP_DEF_ON_BLUE)); menu_opts_off(menu, O_ONEVALUE); post_menu(menu); // Draw a scrollbar to the right info->scroll = ui_set_scrollbar(info->menu_win, SB_VERTICAL, SB_RIGHT); info->scroll.max = item_count(menu) - 1; ui_scrollbar_draw(info->scroll); // Set the window title and boxes mvwprintw(ui->win, 1, ui->width / 2 - 14, "Call List columns selection"); wattron(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); title_foot_box(ui->panel); mvwhline(ui->win, 6, 1, ACS_HLINE, ui->width - 1); mvwaddch(ui->win, 6, 0, ACS_LTEE); mvwaddch(ui->win, 6, ui->width - 1, ACS_RTEE); wattroff(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); // Some brief explanation abotu what window shows wattron(ui->win, COLOR_PAIR(CP_CYAN_ON_DEF)); mvwprintw(ui->win, 3, 2, "This windows show the list of columns displayed on Call"); mvwprintw(ui->win, 4, 2, "List. You can enable/disable using Space Bar and reorder"); mvwprintw(ui->win, 5, 2, "them using + and - keys."); wattroff(ui->win, COLOR_PAIR(CP_CYAN_ON_DEF)); info->form_active = 0; }
int call_list_handle_form_key(PANEL *panel, int key) { int field_idx; char dfilter[256]; int action = -1; // Get panel information call_list_info_t *info = call_list_info(panel); // Get current field id field_idx = field_index(current_field(info->form)); // Check actions for this key while ((action = key_find_action(key, action)) != ERR) { // Check if we handle this action switch (action) { case ACTION_PRINTABLE: // If this is a normal character on input field, print it form_driver(info->form, key); break; case ACTION_PREV_SCREEN: case ACTION_NEXT_FIELD: case ACTION_CONFIRM: case ACTION_SELECT: case ACTION_UP: case ACTION_DOWN: // Activate list call_list_form_activate(panel, 0); break; case ACTION_RIGHT: form_driver(info->form, REQ_RIGHT_CHAR); break; case ACTION_LEFT: form_driver(info->form, REQ_LEFT_CHAR); break; case ACTION_BEGIN: form_driver(info->form, REQ_BEG_LINE); break; case ACTION_END: form_driver(info->form, REQ_END_LINE); break; case ACTION_CLEAR: form_driver(info->form, REQ_BEG_LINE); form_driver(info->form, REQ_CLR_EOL); break; case ACTION_DELETE: form_driver(info->form, REQ_DEL_CHAR); break; case ACTION_BACKSPACE: form_driver(info->form, REQ_DEL_PREV); break; default: // Parse next action continue; } // We've handled this key, stop checking actions break; } // Filter has changed, re-apply filter to displayed calls if (action == ACTION_PRINTABLE || action == ACTION_BACKSPACE || action == ACTION_DELETE || action == ACTION_CLEAR) { // Updated displayed results call_list_clear(panel); // Reset filters on each key stroke filter_reset_calls(); } // Validate all input data form_driver(info->form, REQ_VALIDATION); // Store dfilter input // We trim spaces with sscanf because and empty field is stored as space characters memset(dfilter, 0, sizeof(dfilter)); strcpy(dfilter, field_buffer(info->fields[FLD_LIST_FILTER], 0)); strtrim(dfilter); // Set display filter filter_set(FILTER_CALL_LIST, strlen(dfilter) ? dfilter : NULL); // Return if this panel has handled or not the key return (action == ERR) ? key : 0; }
int call_list_handle_key(PANEL *panel, int key) { int i, height, width, rnpag_steps = setting_get_intvalue(SETTING_CL_SCROLLSTEP); call_list_info_t *info; ui_t *next_panel; sip_call_group_t *group; int action = -1; sip_call_t *call; // Sanity check, this should not happen if (!(info = call_list_info(panel))) return -1; // Handle form key if (info->form_active) return call_list_handle_form_key(panel, key); // Get window of call list panel WINDOW *win = info->list_win; getmaxyx(win, height, width); // Reset iterator position to current call vector_iterator_set_current(&info->calls, info->cur_call); // Check actions for this key while ((action = key_find_action(key, action)) != ERR) { // Check if we handle this action switch (action) { case ACTION_DOWN: // Check if there is a call below us if (!vector_iterator_next(&info->calls)) break; info->cur_call = vector_iterator_current(&info->calls); info->cur_line++; // If we are out of the bottom of the displayed list // refresh it starting in the next call if (info->cur_line > height) { vector_iterator_set_current(&info->calls, info->first_call); vector_iterator_next(&info->calls); info->first_call = vector_iterator_current(&info->calls); info->first_line++; info->cur_line = height; } // Disable Autoscroll info->autoscroll = 0; break; case ACTION_UP: // Check if there is a call above us if (!vector_iterator_prev(&info->calls)) break; info->cur_call = vector_iterator_current(&info->calls); info->cur_line--; // If we are out of the top of the displayed list // refresh it starting in the previous (in fact current) call if (info->cur_line <= 0) { info->first_call = info->cur_call; info->first_line--; info->cur_line = 1; } // Disable Autoscroll info->autoscroll = 0; break; case ACTION_HNPAGE: rnpag_steps = rnpag_steps / 2; /* no break */ case ACTION_NPAGE: // Next page => N key down strokes for (i = 0; i < rnpag_steps; i++) call_list_handle_key(panel, KEY_DOWN); // Disable Autoscroll info->autoscroll = 0; break; case ACTION_HPPAGE: rnpag_steps = rnpag_steps / 2; /* no break */ case ACTION_PPAGE: // Prev page => N key up strokes for (i = 0; i < rnpag_steps; i++) call_list_handle_key(panel, KEY_UP); // Disable Autoscroll info->autoscroll = 0; break; case ACTION_BEGIN: // Initialize structures info->first_call = info->cur_call = -1; info->first_line = info->cur_line = 0; // Disable Autoscroll info->autoscroll = 0; break; case ACTION_END: // Check if there is a call below us while (vector_iterator_next(&info->calls)) { info->cur_call = vector_iterator_current(&info->calls); info->cur_line++; // If we are out of the bottom of the displayed list // refresh it starting in the next call if (info->cur_line > height) { vector_iterator_set_current(&info->calls, info->first_call); vector_iterator_next(&info->calls); info->first_call = vector_iterator_current(&info->calls); info->first_line++; info->cur_line = height; vector_iterator_set_current(&info->calls, info->cur_call); } } break; case ACTION_DISP_FILTER: // Activate Form call_list_form_activate(panel, 1); // Disable Autoscroll info->autoscroll = 0; break; case ACTION_SHOW_FLOW: case ACTION_SHOW_FLOW_EX: case ACTION_SHOW_RAW: // Check we have calls in the list if (info->cur_call == -1) break; // Create a new group of calls group = call_group_clone(info->group); // If not selected call, show current call flow if (call_group_count(info->group) == 0) call_group_add(group, sip_find_by_index(info->cur_call)); // Add xcall to the group if (action == ACTION_SHOW_FLOW_EX) call_group_add(group, call_get_xcall(sip_find_by_index(info->cur_call))); if (action == ACTION_SHOW_RAW) { // Create a Call Flow panel ui_create_panel(PANEL_CALL_RAW); call_raw_set_group(group); } else { // Display current call flow (normal or extended) ui_create_panel(PANEL_CALL_FLOW); call_flow_set_group(group); } break; case ACTION_SHOW_FILTERS: ui_create_panel(PANEL_FILTER); break; case ACTION_SHOW_COLUMNS: ui_create_panel(PANEL_COLUMN_SELECT); break; case ACTION_SHOW_STATS: ui_create_panel(PANEL_STATS); break; case ACTION_SAVE: next_panel = ui_create_panel(PANEL_SAVE); save_set_group(ui_get_panel(next_panel), info->group); break; case ACTION_CLEAR: // Clear group calls vector_clear(info->group->calls); break; case ACTION_CLEAR_CALLS: // Remove all stored calls sip_calls_clear(); // Clear List call_list_clear(panel); break; case ACTION_AUTOSCROLL: info->autoscroll = (info->autoscroll) ? 0 : 1; break; case ACTION_SHOW_SETTINGS: ui_create_panel(PANEL_SETTINGS); break; case ACTION_SELECT: call = vector_item(vector_iterator_vector(&info->calls), info->cur_call); if (call_group_exists(info->group, call)) { call_group_del(info->group, call); } else { call_group_add(info->group, call); } break; case ACTION_PREV_SCREEN: // Handle quit from this screen unless requested if (setting_enabled(SETTING_EXITPROMPT)) { if (dialog_confirm("Confirm exit", "Are you sure you want to quit?", "Yes,No") == 0) { return KEY_ESC; } else { return 0; } } else { return KEY_ESC; } break; default: // Parse next action continue; } // This panel has handled the key successfully break; } // Return if this panel has handled or not the key return (action == ERR) ? key : 0; }
void call_list_draw_list(PANEL *panel) { WINDOW *win; int height, width, cline = 0; struct sip_call *call; int i, collen; char coltext[256]; int colid; int colpos; int color; // Get panel info call_list_info_t *info = call_list_info(panel); // Get window of call list panel win = info->list_win; getmaxyx(win, height, width); // If autoscroll is enabled, select the last dialog if (info->autoscroll) { call_list_handle_key(panel, key_action_key(ACTION_END)); } // If no active call, use the fist one (if exists) if (info->first_call == -1 && vector_iterator_count(&info->calls)) { vector_iterator_reset(&info->calls); call = vector_iterator_next(&info->calls); info->cur_call = info->first_call = vector_index(vector_iterator_vector(&info->calls), call); info->cur_line = info->first_line = 1; } // Clear call list before redrawing werase(win); // Set the iterator position to the first call vector_iterator_set_current(&info->calls, info->first_call - 1 ); // Fill the call list while ((call = vector_iterator_next(&info->calls))) { // Stop if we have reached the bottom of the list if (cline == height) break; // We only print calls with messages (In fact, all call should have msgs) if (!call_msg_count(call)) continue; // Show bold selected rows if (call_group_exists(info->group, call)) wattron(win, A_BOLD | COLOR_PAIR(CP_DEFAULT)); // Highlight active call if (call->index == info->cur_call + 1) { wattron(win, COLOR_PAIR(CP_WHITE_ON_BLUE)); // Reverse colors on monochrome terminals if (!has_colors()) wattron(win, A_REVERSE); } // Set current line background clear_line(win, cline); // Set current line selection box mvwprintw(win, cline, 2, call_group_exists(info->group, call) ? "[*]" : "[ ]"); // Print requested columns colpos = 6; for (i = 0; i < info->columncnt; i++) { // Get current column id colid = info->columns[i].id; // Get current column width collen = info->columns[i].width; // Check if next column fits on window width if (colpos + collen >= width) break; // Initialize column text memset(coltext, 0, sizeof(coltext)); // Get call attribute for current column if (!call_get_attribute(call, colid, coltext)) { colpos += collen + 1; continue; } // Enable attribute color (if not current one) color = 0; if (call->index != info->cur_call + 1 && (color = sip_attr_get_color(colid, coltext)) > 0) wattron(win, color); // Add the column text to the existing columns mvwprintw(win, cline, colpos, "%.*s", collen, coltext); colpos += collen + 1; // Disable attribute color if (color > 0) wattroff(win, color); } cline++; wattroff(win, COLOR_PAIR(CP_DEFAULT)); wattroff(win, COLOR_PAIR(CP_DEF_ON_BLUE)); wattroff(win, A_BOLD | A_REVERSE); } // Draw scrollbar to the right draw_vscrollbar(win, info->first_line, info->dispcallcnt, 1); wnoutrefresh(info->list_win); }