/* display status functions * * (C) 2020 by Andreas Eversberg * All Rights Reserved * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include "../libdebug/debug.h" #include "call.h" #include "display.h" static int status_on = 0; static int line_count = 0; static int lines_total = 0; static char screen[MAX_HEIGHT_STATUS][MAX_DISPLAY_WIDTH]; static char screen_color[MAX_HEIGHT_STATUS][MAX_DISPLAY_WIDTH]; static void print_status(int on) { int i, j; int w, h; char color, last_color = -1; get_win_size(&w, &h); if (w > MAX_DISPLAY_WIDTH - 1) w = MAX_DISPLAY_WIDTH - 1; if (w > MAX_DISPLAY_WIDTH) w = MAX_DISPLAY_WIDTH; h--; if (h > lines_total) h = lines_total; printf("\0337\033[H"); for (i = 0; i < h; i++) { j = 0; if (on) { for (j = 0; j < w; j++) { color = screen_color[i][j]; if (screen[i][j] > ' ' && last_color != color) { printf("\033[%d;3%dm", color / 10, color % 10); last_color = color; } putchar(screen[i][j]); } } else { for (j = 0; j < w; j++) putchar(' '); } putchar('\n'); } printf("\033[0;39m\0338"); fflush(stdout); } void display_status_on(int on) { if (status_on) print_status(0); if (on < 0) status_on = 1 - status_on; else status_on = on; if (status_on) print_status(1); if (status_on) debug_limit_scroll = lines_total; else debug_limit_scroll = 0; } /* start status display */ void display_status_start(void) { memset(screen, ' ', sizeof(screen)); memset(screen_color, 7, sizeof(screen_color)); memset(screen[0], '-', sizeof(screen[0])); memcpy(screen[0] + 4, "Call Status", 11); line_count = 1; } void display_status_line(const char *from_if, int from_count, const char *from_id, int to_count, const char *to_if, const char *to_id, enum call_state to_state) { char line[MAX_DISPLAY_WIDTH + 4096]; char color[MAX_DISPLAY_WIDTH + 4096]; static int from_id_pos, to_if_pos; memset(color, 7, sizeof(color)); // make valgrind happy if (line_count == MAX_HEIGHT_STATUS) return; if (!from_if) from_if = ""; /* at first interface or when it changes */ if (!from_count && !to_count) { from_id_pos = strlen(from_if) + 1; line_count++; } /* at first call */ if (from_id && !to_count) { to_if_pos = from_id_pos + 1 + strlen(from_id) + 1 + 4; /* quote,id,quote,arrow */ } /* check line count again */ if (line_count == MAX_HEIGHT_STATUS) return; if (!from_id) { /* only interface is given, since there is no call */ strcpy(line, from_if); memset(color, 3, strlen(from_if)); } else { /* originating call */ memset(line, ' ', to_if_pos); if (!from_count && !to_count) { /* */ memcpy(line, from_if, strlen(from_if)); memset(color, 3, strlen(from_if)); } if (!to_count) { /* '' */ line[from_id_pos] = '\''; memcpy(line + from_id_pos + 1, from_id, strlen(from_id)); line[from_id_pos + 1 + strlen(from_id)] = '\''; memset(color + from_id_pos, 1, 1 + strlen(from_id) + 1); } line[to_if_pos] = '\0'; /* terminating call */ if (to_if && to_id) { int to_id_pos, to_state_pos; /* arrow in the first line of a call */ if (!to_count) { /* -> '' */ line[to_if_pos - 3] = '-'; line[to_if_pos - 2] = '>'; color[to_if_pos - 3] = 7; color[to_if_pos - 2] = 7; } sprintf(line + to_if_pos, "%s '%s' ", to_if, to_id); memset(color + to_if_pos, 3, strlen(to_if)); to_id_pos = to_if_pos + strlen(to_if) + 1; memset(color + to_id_pos, 2, 1 + strlen(to_id) + 1); to_state_pos = to_id_pos + 1 + strlen(to_id) + 1 + 1; switch (to_state) { case CALL_STATE_SETUP: strcpy(line + to_state_pos, "[setup]"); /* magenta */ memset(color + to_state_pos + 1, 15, 5); break; case CALL_STATE_OVERLAP: strcpy(line + to_state_pos, "[overlap]"); /* green */ memset(color + to_state_pos + 1, 12, 7); break; case CALL_STATE_PROCEEDING: strcpy(line + to_state_pos, "[proceeding]"); /* cyan */ memset(color + to_state_pos + 1, 16, 10); break; case CALL_STATE_ALERTING: strcpy(line + to_state_pos, "[alerting]"); /* yellow */ memset(color + to_state_pos + 1, 13, 8); break; case CALL_STATE_CONNECT: strcpy(line + to_state_pos, "[connect]"); /* white */ memset(color + to_state_pos + 1, 17, 7); break; case CALL_STATE_DISC_FROM_ORIG: strcpy(line + to_state_pos, "[out disconnect]"); /* red */ memset(color + to_state_pos + 1, 11, 14); break; case CALL_STATE_DISC_FROM_TERM: strcpy(line + to_state_pos, "[in disconnect]"); /* red */ memset(color + to_state_pos + 1, 11, 13); break; default: ; } } } /* store line without CR, but not more than MAX_DISPLAY_WIDTH - 1 */ line[MAX_DISPLAY_WIDTH - 1] = '\0'; memcpy(screen[line_count], line, strlen(line)); memcpy(screen_color[line_count], color, strlen(line)); line_count++; } void display_status_end(void) { if (line_count < MAX_HEIGHT_STATUS) line_count++; if (line_count < MAX_HEIGHT_STATUS) { memset(screen[line_count], '-', sizeof(screen[line_count])); line_count++; } /* if last total lines exceed current line count, keep it, so removed lines are overwritten with spaces */ if (line_count > lines_total) lines_total = line_count; if (status_on) print_status(1); /* set new total lines */ lines_total = line_count; if (status_on) debug_limit_scroll = lines_total; }