/* Draws possibly centered formatted message with specified title and control * message on error_win. */ static void draw_msg(const char title[], const char msg[], const char ctrl_msg[], int centered, int recommended_width) { enum { margin = 1 }; int sw, sh; int w, h; int len; size_t ctrl_msg_n; size_t wctrl_msg; size_t i; curs_set(FALSE); getmaxyx(stdscr, sh, sw); ctrl_msg_n = MAX(measure_sub_lines(ctrl_msg, &wctrl_msg), 1U); h = sh - 2 - ctrl_msg_n + !cfg.display_statusline; /* The outermost condition is for VLA below (to calm static analyzers). */ w = MAX(2 + 2*margin, MIN(sw - 2, MAX(MAX(recommended_width, sw/3), (int)MAX(wctrl_msg, determine_width(msg)) + 4))); wresize(error_win, h, w); werase(error_win); len = strlen(msg); if(len <= w - 2 && strchr(msg, '\n') == NULL) { h = 5 + ctrl_msg_n; wresize(error_win, h, w); mvwin(error_win, (sh - h)/2, (sw - w)/2); checked_wmove(error_win, 2, (w - len)/2); wprint(error_win, msg); } else { int i; int cy = 2; i = 0; while(i < len) { int j; char buf[w - 2 - 2*margin + 1]; int cx; copy_str(buf, sizeof(buf), msg + i); for(j = 0; buf[j] != '\0'; j++) if(buf[j] == '\n') break; if(buf[j] != '\0') i++; buf[j] = '\0'; i += j; if(buf[0] == '\0') continue; h = cy + 4; wresize(error_win, h, w); mvwin(error_win, (sh - h)/2, (sw - w)/2); cx = centered ? (w - utf8_strsw(buf))/2 : (1 + margin); checked_wmove(error_win, cy++, cx); wprint(error_win, buf); } } box(error_win, 0, 0); if(title[0] != '\0') { mvwprintw(error_win, 0, (w - strlen(title) - 2)/2, " %s ", title); } /* Print control message line by line. */ for(i = ctrl_msg_n; i > 0U; --i) { const size_t len = strcspn(ctrl_msg, "\n"); mvwaddnstr(error_win, h - i - 1, MAX(0, (w - (int)len)/2), ctrl_msg, len); ctrl_msg = skip_char(ctrl_msg + len + 1U, '/'); } }
/* Draws possibly centered formatted message with specified title and control * message on error_win. */ static void draw_msg(const char title[], const char msg[], const char ctrl_msg[], int centered, int recommended_width) { enum { margin = 1 }; int sw, sh; int w, h; int max_h; int len; size_t ctrl_msg_n; size_t wctrl_msg; size_t i; int first_line_x = 1; const int first_line_y = 2; curs_set(0); getmaxyx(stdscr, sh, sw); ctrl_msg_n = MAX(measure_sub_lines(ctrl_msg, &wctrl_msg), 1U); max_h = sh - 2 - ctrl_msg_n + !cfg.display_statusline; h = max_h; /* The outermost condition is for VLA below (to calm static analyzers). */ w = MAX(2 + 2*margin, MIN(sw - 2, MAX(MAX(recommended_width, sw/3), (int)MAX(wctrl_msg, determine_width(msg)) + 4))); wresize(error_win, h, w); werase(error_win); len = strlen(msg); if(len <= w - 2 && strchr(msg, '\n') == NULL) { first_line_x = (w - len)/2; h = 5 + ctrl_msg_n; wresize(error_win, h, w); mvwin(error_win, (sh - h)/2, (sw - w)/2); checked_wmove(error_win, first_line_y, first_line_x); wprint(error_win, msg); } else { int i = 0; int cy = first_line_y; while(i < len) { int j; char buf[w - 2 - 2*margin + 1]; int cx; copy_str(buf, sizeof(buf), msg + i); for(j = 0; buf[j] != '\0'; j++) if(buf[j] == '\n') break; if(buf[j] != '\0') i++; buf[j] = '\0'; i += j; if(buf[0] == '\0') continue; if(cy >= max_h - (int)ctrl_msg_n - 3) { /* Skip trailing part of the message if it's too long, just print how * many lines we're omitting. */ size_t max_len; const int more_lines = 1U + measure_sub_lines(msg + i, &max_len); snprintf(buf, sizeof(buf), "<<%d more line%s not shown>>", more_lines, (more_lines == 1) ? "" : "s"); /* Make sure this is the last iteration of the loop. */ i = len; } h = 1 + cy + 1 + ctrl_msg_n + 1; wresize(error_win, h, w); mvwin(error_win, (sh - h)/2, (sw - w)/2); cx = centered ? (w - utf8_strsw(buf))/2 : (1 + margin); if(cy == first_line_y) { first_line_x = cx; } checked_wmove(error_win, cy++, cx); wprint(error_win, buf); } } box(error_win, 0, 0); if(title[0] != '\0') { mvwprintw(error_win, 0, (w - strlen(title) - 2)/2, " %s ", title); } /* Print control message line by line. */ for(i = ctrl_msg_n; i > 0U; --i) { const size_t len = strcspn(ctrl_msg, "\n"); mvwaddnstr(error_win, h - i - 1, MAX(0, (w - (int)len)/2), ctrl_msg, len); ctrl_msg = skip_char(ctrl_msg + len + 1U, '/'); } checked_wmove(error_win, first_line_y, first_line_x); }