diff --git a/main.c b/main.c index 1ded239..811c765 100644 --- a/main.c +++ b/main.c @@ -32,7 +32,7 @@ void signals(int signo){ closedev(); deinit_ncurses(); deinit_readline(); - DBG("Exit"); + DBG("Exit by signal %d", signo); exit(signo); } @@ -82,16 +82,16 @@ int main(int argc, char **argv){ while(1){ if(0 == pthread_mutex_lock(&conndev.mutex)){ int l; - char *buf = ReadData(&l); + uint8_t *buf = ReadData(&l); if(buf && l > 0){ - ShowData(buf); + AddData(buf, l); }else if(l < 0){ pthread_mutex_unlock(&conndev.mutex); ERRX("Device disconnected"); } pthread_mutex_unlock(&conndev.mutex); - usleep(1000); } + usleep(1000); } // never reached return 0; diff --git a/ncurses_and_readline.c b/ncurses_and_readline.c index 3873f36..9b3e2de 100644 --- a/ncurses_and_readline.c +++ b/ncurses_and_readline.c @@ -30,6 +30,8 @@ #include #include +//#include + #include "dbg.h" #include "ttysocket.h" #include "ncurses_and_readline.h" @@ -44,6 +46,7 @@ enum { // using colors }; #define COLOR(x) COLOR_PAIR(x ## _NO) + // Keeps track of the terminal mode so we can reset the terminal if needed on errors static bool visual_mode = false; // insert commands when true; roll upper screen when false @@ -68,15 +71,33 @@ static WINDOW *msg_win; // Message window static WINDOW *sep_win; // Separator line above the command (readline) window static WINDOW *cmd_win; // Command (readline) window -// string list -typedef struct _Line{ - int Nline; - char *contents; - struct _Line *prev, *next; -} Line; -// head of list, current item and first line on screen -Line *head = NULL, *curr = NULL, *firstline = NULL; -int nr_lines = 0; // total anount of data portions @ input +// amount of lines in line_arary +//#define LINEARRSZ (BUFSIZ/100) +#define LINEARRSZ 3 +// formatted buffer initial size +#define FBUFSIZ 30 +// raw buffer initial size +#define RBUFSIZ 30 +// amount of spaces and delimeters in hexview string (address + 2 lines + 3 additional spaces) +#define HEXDSPACES (13) +// maximal columns in line +#define MAXCOLS (512) + +typedef struct{ + char *formatted_buffer; // formatted buffer, ptrtobuf(i) returns i'th string + size_t fbuf_size; // size of `formatted_buffer` in bytes (zero-terminated lines) + size_t fbuf_curr; // current size of data in buffer + size_t *line_array_idx; // indexes of starting symbols of each line in `formatted_buffer` + size_t lnarr_size; // full size of `line_array_idx` + size_t lnarr_curr; // current index in `line_array_idx` (last string) + size_t linelen; // max length of one line (excluding terminated 0) + size_t lastlen; // length of last string +} linebuf_t; + +static linebuf_t *linebuffer = NULL; // string buffer for current representation +static uint8_t *raw_buffer = NULL; // raw buffer for incoming data +static size_t rawbufsz = 0, rawbufcur = 0; // full raw buffer size and current bytes amount +static size_t firstdisplineno = 0; // current first displayed line number (when scrolling) static unsigned char input; // Input character for readline @@ -100,6 +121,23 @@ static void forward_to_readline(char c){ rl_callback_read_char(); } +/** + * @brief ptrtobuf - get n'th string of `formatted_buffer` + * @param lineno - line number + * @return pointer to n'th string in formatted buffer + */ +static char *ptrtobuf(size_t lineno){ + if(!linebuffer->line_array_idx){ + WARNX("line_array_idx not inited"); + return NULL; + } + if(lineno > linebuffer->lnarr_curr) return NULL; + size_t idx = linebuffer->line_array_idx[lineno]; + if(idx > linebuffer->fbuf_curr) return NULL; + return (linebuffer->formatted_buffer + idx); +} + +#if 0 // functions to modify output data static char *text_putchar(char *next){ char c = *next++; @@ -123,39 +161,36 @@ static char *hex_putchar(char *next){ waddch(msg_win, *next); return next+1; } +#endif -static void msg_win_redisplay(bool for_resize){ +/** + * @brief msg_win_redisplay - redisplay message window + * @param group_refresh - true for grouping refresh (don't call doupdate()) + */ +static void msg_win_redisplay(bool group_refresh){ + if(!linebuffer) return; werase(msg_win); - Line *l = firstline; - //static char *buf = NULL; - int nlines = 0; // total amount of lines @ output int linemax = LINES - 2; - char *(*putfn)(char *); - switch(disp_type){ - case DISP_RAW: - putfn = raw_putchar; - break; - case DISP_HEX: - putfn = hex_putchar; - break; - default: - putfn = text_putchar; + if(firstdisplineno >= linebuffer->lnarr_curr){ + size_t l = (linemax > 1) ? linemax / 2 : 1; + if(linebuffer->lnarr_curr < l) firstdisplineno = 0; + else firstdisplineno = linebuffer->lnarr_curr - l; } - for(; l && (nlines < linemax); l = l->next){ - wmove(msg_win, nlines, 0); - //size_t contlen = strlen(l->contents) + 128; - //buf = realloc(buf, contlen); - char *ptr = l->contents; - while((ptr = putfn(ptr)) && *ptr && nlines < linemax){ - nlines = msg_win->_cury; - } - ++nlines; + size_t lastl = firstdisplineno + linemax; + if(lastl > linebuffer->lnarr_curr+1) lastl = linebuffer->lnarr_curr+1; + int i = 0; + for(size_t curline = firstdisplineno; curline < lastl; ++curline, ++i){ + mvwprintw(msg_win, i, 0, "%s", linebuffer->formatted_buffer + linebuffer->line_array_idx[curline]); } - if(for_resize) wnoutrefresh(msg_win); + if(group_refresh) wnoutrefresh(msg_win); else wrefresh(msg_win); } -static void cmd_win_redisplay(bool for_resize){ +/** + * @brief cmd_win_redisplay - redisplay command (input) window + * @param group_refresh - true for grouping refresh (don't call doupdate()) + */ +static void cmd_win_redisplay(bool group_refresh){ int cursor_col = 3 + strlen(dispnames[input_type]) + rl_point; // " > " width is 3 werase(cmd_win); int x = 0, maxw = COLS-2; @@ -167,7 +202,7 @@ static void cmd_win_redisplay(bool for_resize){ snprintf(abuf, 4096, "%s > %s", dispnames[input_type], rl_line_buffer); waddstr(cmd_win, abuf+x); wmove(cmd_win, 0, cursor_col); - if(for_resize) wnoutrefresh(cmd_win); + if(group_refresh) wnoutrefresh(cmd_win); else wrefresh(cmd_win); keypad(cmd_win, TRUE); if(insert_mode) curs_set(2); @@ -178,7 +213,11 @@ static void readline_redisplay(){ cmd_win_redisplay(false); } -static void show_mode(bool for_resize){ +/** + * @brief show_mode - redisplay middle string (with work mode and settings) + call cmd_win_redisplay + * @param group_refresh - true for grouping refresh (don't call doupdate()) + */ +static void show_mode(bool group_refresh){ static const char *insmodetext = "INSERT (F1 - help)"; wclear(sep_win); char buf[128]; @@ -213,44 +252,231 @@ static void show_mode(bool for_resize){ wprintw(sep_win, "%s ", dispnames[disp_type]); wattroff(sep_win, COLOR(BKGMARKED)); wprintw(sep_win, "%s", buf); - if(for_resize) wnoutrefresh(sep_win); + if(group_refresh) wnoutrefresh(sep_win); else wrefresh(sep_win); - cmd_win_redisplay(for_resize); + cmd_win_redisplay(group_refresh); } /** - * @brief ShowData - show string on display - * @param text - text string + * @brief redisplay_addline - redisplay after line adding + * @param group_refresh - true for grouping refresh (don't call doupdate()) */ -void ShowData(const char *text){ - if(!text) return; - if(!*text) text = " "; // empty string - Line *lp = malloc(sizeof(Line)); - lp->contents = strdup(text); - lp->prev = curr; - lp->next = NULL; - lp->Nline = nr_lines++; - if(!curr || !head){ - head = curr = firstline = lp; - }else - curr->next = lp; - curr = lp; - // roll back to show last input - if(curr->prev){ - firstline = curr; - int totalln = (strlen(firstline->contents) - 1)/COLS + 1; - while(firstline->prev){ - totalln += (strlen(firstline->prev->contents) - 1)/COLS + 1; - if(totalln > LINES-2) break; - firstline = firstline->prev; - } +static void redisplay_addline(){ + // redisplay only if previous line was on screen + size_t lastno = firstdisplineno + LINES - 2; // number of first line out of screen + if(lastno < linebuffer->lnarr_curr){ + return; + } + else if(lastno == linebuffer->lnarr_curr){ // scroll text by one line up + ++firstdisplineno; } msg_win_redisplay(true); show_mode(true); doupdate(); } +/** + * @brief linebuf_free - clear memory of `linebuffer` + */ +static void linebuf_free(){ + if(!linebuffer) return; + FREE(linebuffer->formatted_buffer); + FREE(linebuffer->line_array_idx); + FREE(linebuffer); +} + +/** + * @brief chksizes - check sizes of buffers and enlarge them if need + */ +static void chksizes(){ + size_t addportion = MAXCOLS*3; + if(rawbufsz - rawbufcur < addportion){ // raw buffer always should be big enough + rawbufsz += (addportion > RBUFSIZ) ? addportion : RBUFSIZ; + DBG("Enlarge raw buffer to %zd", rawbufsz); + raw_buffer = realloc(raw_buffer, rawbufsz); + } + if(linebuffer->fbuf_size - linebuffer->fbuf_curr < addportion){ // realloc buffer if need + linebuffer->fbuf_size += (addportion > FBUFSIZ) ? addportion : FBUFSIZ; + DBG("Enlarge formatted buffer to %zd", linebuffer->fbuf_size); + linebuffer->formatted_buffer = realloc(linebuffer->formatted_buffer, linebuffer->fbuf_size); + } + if(linebuffer->lnarr_size - linebuffer->lnarr_curr < 3){ + linebuffer->lnarr_size += LINEARRSZ; + DBG("Enlarge line array buffer to %zd", linebuffer->lnarr_size); + linebuffer->line_array_idx = realloc(linebuffer->line_array_idx, linebuffer->lnarr_size * sizeof(size_t)); + } +} + +/** + * @brief linebuf_new - allocate data for new linebuffer + */ +static void linebuf_new(){ + linebuf_free(); + linebuffer = MALLOC(linebuf_t, 1); + linebuffer->fbuf_size = FBUFSIZ; + linebuffer->formatted_buffer = MALLOC(char, linebuffer->fbuf_size); + linebuffer->lnarr_size = LINEARRSZ; + linebuffer->line_array_idx = MALLOC(size_t, linebuffer->lnarr_size); + linebuffer->fbuf_curr = 0; + linebuffer->lnarr_curr = 0; + linebuffer->lastlen = 0; + int maxcols = (COLS > MAXCOLS) ? MAXCOLS : COLS; + // in hexdump view linelen is amount of symbols in one string, lastlen - amount of already printed symbols + if(disp_type == DISP_HEX){ // calculate minimal line width and ; + int n = maxcols - HEXDSPACES; // space for data + n -= n/8; // spaces after each 8 symbols + n /= 4; // hex XX + space + symbol view + // n should be 1..4, 8 or 16x + if(n < 1) n = 1; // minimal - one symbol per string + else if(n > 4){ + if(n < 8) n = 4; + //else if(n < 16) n = 8; + else n -= n % 8; + } + linebuffer->linelen = n; + }else linebuffer->linelen = maxcols; + DBG("=====>> COLS=%d, maxcols=%d, linelen=%zd", COLS, maxcols, linebuffer->linelen); + linebuffer->line_array_idx[0] = 0; // initialize first line + chksizes(); +} + +/** + * @brief finalize_line - finalize last line in linebuffer & increase buffer sizes if nesessary + */ +static void finalize_line(){ + chksizes(); + linebuffer->formatted_buffer[linebuffer->fbuf_curr++] = 0; // finalize line + linebuffer->formatted_buffer[linebuffer->fbuf_curr] = 0; // and clear new line (`realloc` can generate some trash) + DBG("Current line is %s, no=%zd, len=%zd", linebuffer->formatted_buffer + linebuffer->line_array_idx[linebuffer->lnarr_curr], linebuffer->lnarr_curr, linebuffer->lastlen); + ++linebuffer->lnarr_curr; + linebuffer->lastlen = 0; + linebuffer->line_array_idx[linebuffer->lnarr_curr] = linebuffer->fbuf_curr; + redisplay_addline(); +} + +/** + * @brief FormatData - get new data portion and format it into displayed buffer + * @param data - data start pointer in `raw_buffer` + * @param len - length of data portion + */ +void FormatData(const uint8_t *data, int len){ + if(COLS > MAXCOLS-1) ERRX("Too wide column"); + if(!data || len < 1) return; + chksizes(); + DBG("Got %d bytes to process", len); + while(len){ + // count amount of symbols in `data` to display until line is over + int Nsymbols = 0, curidx = 0; + int nrest = linebuffer->linelen - linebuffer->lastlen; // n symbols left in string for text/raw + switch(disp_type){ + case DISP_TEXT: // 1 or 4 bytes per symbol + while(nrest > 0 && curidx < len){ + uint8_t c = data[curidx++]; + if(c == '\n'){ // finish string + ++Nsymbols; + break; + } + if(c < 32 || c > 126) nrest -= 4; // "\xXX" + else --nrest; + if(nrest > -1) ++Nsymbols; + } + break; + case DISP_RAW: // 3 bytes per symbol + Nsymbols = nrest / 3; + break; + case DISP_HEX: + Nsymbols = nrest; + break; + default: + break; + } + if(Nsymbols > len) Nsymbols = len; + if(Nsymbols == 0){ + DBG("No more plase in line - finalize"); + finalize_line(); + continue; + } + DBG("Process %d symbols", Nsymbols); + if(disp_type != DISP_HEX){ + char *curptr = linebuffer->formatted_buffer+linebuffer->fbuf_curr; + for(int i = 0; i < Nsymbols; ++i){ + uint8_t c = data[i]; + int nadd = 0; + switch(disp_type){ + case DISP_TEXT: + if(c == '\n'){ // finish line + DBG("Finish line, nadd=%d, i=%d!", nadd, i); + finalize_line(); + break; + } + if(c < 32 || c > 126) nadd = sprintf(curptr, "\\x%.2X", c); + else{ + nadd = 1; + *curptr = c; + } + break; + case DISP_RAW: + nadd = sprintf(curptr, "%-3.2X", c); + break; + default: + break; + } + linebuffer->fbuf_curr += nadd; + linebuffer->lastlen += nadd; + curptr += nadd; + } + }else{ // HEXDUMP: refill full string buffer + char ascii[MAXCOLS]; // buffer for ASCII printing + char *ptr = ptrtobuf(linebuffer->lnarr_curr); + if(!ptr) ERRX("Can't get current line"); + size_t address = linebuffer->linelen * linebuffer->lnarr_curr; // string starting address + const uint8_t *start = data - linebuffer->lastlen; // starting byte in hexdump string + linebuffer->lastlen += Nsymbols; + int nadd = sprintf(ptr, "%-10.8zX", address); + ptr += nadd; + size_t i = 0; + for(; i < linebuffer->lastlen; ++i){ + if(0 == (i % 8)){ + sprintf(ptr, " "); ++ptr; ++nadd; + } + uint8_t c = start[i]; + int x = sprintf(ptr, "%-3.2X", c); + if(c > 31 && c < 127) ascii[i] = c; + else ascii[i] = '.'; + ptr += x; + nadd += x; + } + ascii[i] = 0; + int emptyvals = (int)(linebuffer->linelen - linebuffer->lastlen); + nadd += sprintf(ptr, "%*s|%*s|", 3*emptyvals+emptyvals/8, "", -((int)linebuffer->linelen), ascii); + linebuffer->fbuf_curr = linebuffer->line_array_idx[linebuffer->lnarr_curr] + nadd; + DBG("---- Total added symbols: %zd, fbuf_curr=%zd (%zd + %zd)", nadd, linebuffer->fbuf_curr, + linebuffer->line_array_idx[linebuffer->lnarr_curr], nadd); + } + DBG("last=%d, line=%d", linebuffer->lastlen, linebuffer->linelen); + if(linebuffer->lastlen == linebuffer->linelen) finalize_line(); + len -= Nsymbols; + data += Nsymbols; + } +} + +/** + * @brief AddData - add new data buffer to global buffer and last displayed string + * @param data - data + * @param len - length of `data` + */ +void AddData(const uint8_t *data, int len){ + // now print all symbols into buff + chksizes(); + memcpy(raw_buffer + rawbufcur, data, len); + DBG("Got %d bytes, now buffer have %d", len, rawbufcur+len); + FormatData(raw_buffer + rawbufcur, len); + rawbufcur += len; + redisplay_addline(); // display last symbols if can +} + static void resize(){ + DBG("RESIZE WINDOW"); if(LINES > 2){ wresize(msg_win, LINES - 2, COLS); wresize(sep_win, 1, COLS); @@ -258,10 +484,19 @@ static void resize(){ mvwin(sep_win, LINES - 2, 0); mvwin(cmd_win, LINES - 1, 0); } + pthread_mutex_lock(&dtty->mutex); + linebuf_new(); // free old and alloc new + FormatData(raw_buffer, rawbufcur); // reformat all data + pthread_mutex_unlock(&dtty->mutex); msg_win_redisplay(true); show_mode(true); doupdate(); } +/* +void swinch(_U_ int sig){ + //signal(SIGWINCH, swinch); + DBG("got resize"); +}*/ void init_ncurses(){ if (!initscr()) @@ -275,7 +510,6 @@ void init_ncurses(){ noecho(); nonl(); intrflush(NULL, FALSE); - keypad(cmd_win, TRUE); curs_set(2); if(LINES > 2){ msg_win = newwin(LINES - 2, COLS, 0, 0); @@ -289,6 +523,8 @@ void init_ncurses(){ } if(!msg_win || !sep_win || !cmd_win) fail_exit("Failed to allocate windows"); + wtimeout(cmd_win, 4); + keypad(cmd_win, TRUE); if(has_colors()){ init_pair(BKG_NO, COLOR_WHITE, COLOR_BLUE); init_pair(BKGMARKED_NO, 1, COLOR_BLUE); // COLOR_RED used in my usefull_macros @@ -300,10 +536,16 @@ void init_ncurses(){ } show_mode(false); mousemask(BUTTON4_PRESSED|BUTTON5_PRESSED, NULL); + DBG("INIT raw buffer"); + rawbufsz = RBUFSIZ; + raw_buffer = MALLOC(uint8_t, rawbufsz); + linebuf_new(); + //signal(SIGWINCH, swinch); } void deinit_ncurses(){ visual_mode = false; + linebuf_free(); delwin(msg_win); delwin(sep_win); delwin(cmd_win); @@ -342,12 +584,14 @@ void init_readline(){ * @param in, out - types for input and display */ static void change_disp(disptype in, disptype out){ - if(in >= DISP_TEXT && in < DISP_UNCHANGED){ + if(in >= DISP_TEXT && in < DISP_UNCHANGED && in != input_type){ input_type = in; DBG("input -> %s", dispnames[in]); } - if(out >= DISP_TEXT && out < DISP_UNCHANGED){ + if(out >= DISP_TEXT && out < DISP_UNCHANGED && out != disp_type){ disp_type = out; + DBG("output -> %s", dispnames[out]); + resize(); // reformat everything } show_mode(false); } @@ -356,22 +600,34 @@ void deinit_readline(){ rl_callback_handler_remove(); } -static void rolldown(){ - if(firstline && firstline->prev){ - firstline = firstline->prev; - msg_win_redisplay(false); - show_mode(false); - doupdate(); - } +/** + * @brief rolldown/rollup - roll text by `N` strings + * @param N - amount of strings + */ +static void rolldown(size_t N){ // if N==0 goto first line + DBG("rolldown for %zd, first was %zd", N, firstdisplineno); + size_t old = firstdisplineno; + if(firstdisplineno < N || N == 0) firstdisplineno = 0; + else firstdisplineno -= N; + DBG("old was %zd, become %zd", old, firstdisplineno); + if(old == firstdisplineno) return; + msg_win_redisplay(false); + //msg_win_redisplay(true); show_mode(true); doupdate(); } - -static void rollup(){ - if(firstline && firstline->next){ - firstline = firstline->next; - msg_win_redisplay(false); - show_mode(false); - doupdate(); +static void rollup(size_t N){ // if N==0 goto last line + DBG("scroll up for %d", N); + size_t half = (LINES+1)/2; + if(firstdisplineno + half >= linebuffer->lnarr_curr){ + DBG("Don't need: %zd+%zd >= %zd", firstdisplineno, half, linebuffer->lnarr_curr); + return; // don't scroll over a half of viewed area } + size_t old = firstdisplineno; + firstdisplineno += N; + if(firstdisplineno + half > linebuffer->lnarr_curr || N == 0) firstdisplineno = linebuffer->lnarr_curr - half; + DBG("old was %zd, become %zd", old, firstdisplineno); + if(old == firstdisplineno) return; + msg_win_redisplay(false); + //msg_win_redisplay(true); show_mode(true); doupdate(); } static const char *help[] = { @@ -412,13 +668,15 @@ void *cmdline(void* arg){ show_mode(false); do{ int c = wgetch(cmd_win); + if(c < 0) continue; bool processed = true; - //DBG("wgetch got %d", c); + DBG("wgetch got %d", c); disptype dt = DISP_UNCHANGED; switch(c){ // common keys for both modes case KEY_F(1): // help DBG("\n\nASK for help\n\n"); popup_msg(msg_win, help); + resize(); // call `resize` to enshure that no problems would be later break; case KEY_F(2): // TEXT mode DBG("\n\nIN TEXT mode\n\n"); @@ -434,8 +692,8 @@ void *cmdline(void* arg){ break; case KEY_MOUSE: if(getmouse(&event) == OK){ - if(event.bstate & (BUTTON4_PRESSED)) rolldown(); // wheel up - else if(event.bstate & (BUTTON5_PRESSED)) rollup(); // wheel down + if(event.bstate & (BUTTON4_PRESSED)) rolldown(1); // wheel up + else if(event.bstate & (BUTTON5_PRESSED)) rollup(1); // wheel down } break; case '\t': // tab switch between scroll and edit mode @@ -501,25 +759,23 @@ void *cmdline(void* arg){ } }else{ switch(c){ // TODO: add home/end + case KEY_HOME: + rolldown(0); + break; + case KEY_END: + rollup(0); + break; case KEY_UP: // roll down for one item - rolldown(); + rolldown(1); break; case KEY_DOWN: // roll up for one item - rollup(); + rollup(1); break; - case KEY_PPAGE: // PageUp: roll down for 10 items - for(int i = 0; i < 10; ++i){ - if(firstline && firstline->prev) firstline = firstline->prev; - else break; - } - msg_win_redisplay(false); + case KEY_PPAGE: // PageUp: roll down for 2/3 of screen + rolldown((2*LINES)/3); break; - case KEY_NPAGE: // PageUp: roll up for 10 items - for(int i = 0; i < 10; ++i){ - if(firstline && firstline->next) firstline = firstline->next; - else break; - } - msg_win_redisplay(false); + case KEY_NPAGE: // PageUp: roll up for 2/3 of screen + rollup((2*LINES)/3); break; default: if(c == 'q' || c == 'Q') should_exit = true; // quit diff --git a/ncurses_and_readline.h b/ncurses_and_readline.h index 6fa693f..ad1a40d 100644 --- a/ncurses_and_readline.h +++ b/ncurses_and_readline.h @@ -34,6 +34,6 @@ void deinit_readline(); void init_ncurses(); void deinit_ncurses(); void *cmdline(void* arg); -void ShowData(const char *text); +void AddData(const uint8_t *data, int len); #endif // NCURSES_AND_READLINE_H__ diff --git a/popup_msg.c b/popup_msg.c index e958726..a112c8f 100644 --- a/popup_msg.c +++ b/popup_msg.c @@ -75,12 +75,14 @@ static void end_popup(void){ * Display a temporary window, e.g., to display a help-message. */ void popup_msg(WINDOW *parent, const char *const *msg){ - int x0 = 4; - int y0 = 2; - int y1 = 0, x1 = 0; - int y2 = 0; - int wide = getmaxx(parent) - ((x0 + 1) * 2); - int high = getmaxy(parent) - ((y0 + 1) * 2); + int maxx, maxy, x0, y0, x1 = 0, y1 = 0, y2 = 0; + getmaxyx(parent, maxy, maxx); + // borders + //x0 = (maxx > 12) ? 2 : ((maxx > 9) ? 1 : 0); + x0 = (maxx > 80) ? maxx/2-40 : maxx / 32; + y0 = (maxy > 20) ? 2 : ((maxy > 16) ? 1 : 0); + int wide = maxx - 2*x0; + int high = maxy - 2*y0; WINDOW *help; WINDOW *data; int n; @@ -96,17 +98,14 @@ void popup_msg(WINDOW *parent, const char *const *msg){ length = n; last_x = width - wide + 4; - if ((help = newwin(high, wide, y0, x0)) == 0) - return; - if ((data = newpad(length + 1, width + 1)) == 0) { - delwin(help); - return; + if((help = newwin(high, wide, y0, x0)) == 0) return; + if((data = newpad(length + 1, width + 1)) == 0){ + delwin(help); + return; } begin_popup(); - keypad(data, TRUE); - for (n = 0; n < length; ++n){ waddstr(data, msg[n]); if ((n + 1) < length) waddch(data, '\n'); @@ -175,7 +174,7 @@ void popup_msg(WINDOW *parent, const char *const *msg){ werase(help); box(help, 0, 0); wnoutrefresh(help); - pnoutrefresh(data, y1, x1, y0 + 1, x0 + 1, high, wide); + pnoutrefresh(data, y1, x1, y0+1, x0+1, y0+high-2, x0+wide-2); doupdate(); } while ((ch = wgetch(data)) != ERR && ch != QUIT && ch != ESCAPE); werase(help); diff --git a/string_functions.c b/string_functions.c index ba9c219..70b7aed 100644 --- a/string_functions.c +++ b/string_functions.c @@ -166,10 +166,11 @@ static inline const char *getspec(const char *line, int *ch){ * @return amount of bytes sent, 0 if error or -1 if disconnect */ int convert_and_send(disptype input_type, const char *line){ - static char *buf = NULL; + static uint8_t *buf = NULL; static size_t bufsiz = 0; size_t curpos = 0; // position in `buf` line = omit_nonletters(input_type, line); + DBG("got: '%s' to send", line); while(*line){ if(curpos >= bufsiz){ // out ouptut buffer can't be larger than input bufsiz += BUFSIZ; @@ -218,10 +219,9 @@ int convert_and_send(disptype input_type, const char *line){ bufsiz += BUFSIZ; buf = realloc(buf, bufsiz); } - snprintf(buf+curpos, eollen+1, "%s", eol); + memcpy(buf+curpos, eol, eollen); curpos += eollen; - /*snprintf(buf+curpos, 7, "_TEST_"); - curpos += 6;*/ + DBG("Add EOL"); } return SendData(buf, curpos); } diff --git a/ttysocket.c b/ttysocket.c index c9a87a5..aefeba5 100644 --- a/ttysocket.c +++ b/ttysocket.c @@ -79,13 +79,13 @@ static int waittoread(int fd){ } // get data drom TTY -static char *getttydata(int *len){ +static uint8_t *getttydata(int *len){ if(!device || !device->dev) return NULL; TTY_descr2 *D = device->dev; if(D->comfd < 0) return NULL; int L = 0; - int length = D->bufsz; - char *ptr = D->buf; + int length = D->bufsz - 1; // -1 for terminating zero + uint8_t *ptr = D->buf; int s = 0; do{ if(!(s = waittoread(D->comfd))) break; @@ -102,18 +102,18 @@ static char *getttydata(int *len){ length -= l; }while(length); D->buflen = L; - D->buf[L] = 0; + D->buf[L] = 0; // for text buffers if(len) *len = L; if(!L) return NULL; DBG("buffer len: %zd, content: =%s=", D->buflen, D->buf); return D->buf; } -static char *getsockdata(int *len){ +static uint8_t *getsockdata(int *len){ if(!device || !device->dev) return NULL; TTY_descr2 *D = device->dev; if(D->comfd < 0) return NULL; - char *ptr = NULL; + uint8_t *ptr = NULL; int n = waittoread(D->comfd); if(n == 1){ n = read(D->comfd, D->buf, D->bufsz-1); @@ -137,10 +137,10 @@ static char *getsockdata(int *len){ * @param len (o) - length of data read (-1 if device disconnected) * @return NULL or string */ -char *ReadData(int *len){ +uint8_t *ReadData(int *len){ if(!device || !device->dev) return NULL; if(len) *len = -1; - char *r = NULL; + uint8_t *r = NULL; switch(device->type){ case DEV_TTY: r = getttydata(len); @@ -165,14 +165,15 @@ char *ReadData(int *len){ * @param data - buffer with data * @return 0 if error or empty string, -1 if disconnected */ -int SendData(const char *data, size_t len){ +int SendData(const uint8_t *data, size_t len){ if(!device) return -1; if(!data || len == 0) return 0; int ret = 0; + DBG("Send %d bytes", len); if(0 == pthread_mutex_lock(&device->mutex)){ switch(device->type){ case DEV_TTY: - if(write_tty(device->dev->comfd, data, len)) ret = 0; + if(write_tty(device->dev->comfd, (const char*)data, len)) ret = 0; else ret = len; break; case DEV_NETSOCKET: @@ -199,7 +200,7 @@ static const int socktypes[] = {SOCK_STREAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, static TTY_descr2* opensocket(){ if(!device) return FALSE; TTY_descr2 *descr = MALLOC(TTY_descr2, 1); // only for `buf` and bufsz/buflen - descr->buf = MALLOC(char, BUFSIZ); + descr->buf = MALLOC(uint8_t, BUFSIZ); descr->bufsz = BUFSIZ; // now try to open a socket descr->comfd = -1; @@ -334,7 +335,7 @@ static TTY_descr2* opentty(){ tcflag_t flags; descr->format = parse_format(device->port, &flags); if(!descr->format) goto someerr; - descr->buf = MALLOC(char, BUFSIZ); + descr->buf = MALLOC(uint8_t, BUFSIZ); descr->bufsz = BUFSIZ-1; if((descr->comfd = open(descr->portname, O_RDWR|O_NOCTTY)) < 0){ WARN(_("Can't use port %s"), descr->portname); diff --git a/ttysocket.h b/ttysocket.h index c6f8a6c..39cb81f 100644 --- a/ttysocket.h +++ b/ttysocket.h @@ -39,7 +39,7 @@ typedef struct { struct termios2 oldtty; // TTY flags for previous port settings struct termios2 tty; // TTY flags for current settings int comfd; // TTY file descriptor - char *buf; // buffer for data read + uint8_t *buf; // buffer for data read size_t bufsz; // size of buf size_t buflen; // length of data read into buf } TTY_descr2; @@ -55,8 +55,8 @@ typedef struct{ char seol[5]; // `eol` with doubled backslash (for print @ screen) } chardevice; -char *ReadData(int *l); -int SendData(const char *data, size_t len); +uint8_t *ReadData(int *l); +int SendData(const uint8_t *data, size_t len); void settimeout(int tms); int opendev(chardevice *d, char *path); void closedev();