diff options
Diffstat (limited to 'src/nvim/hardcopy.c')
-rw-r--r-- | src/nvim/hardcopy.c | 282 |
1 files changed, 149 insertions, 133 deletions
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index 1c9b8e18ef..983dbb7bbe 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * hardcopy.c: printing to paper */ @@ -23,7 +26,6 @@ #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" -#include "nvim/misc2.h" #include "nvim/garray.h" #include "nvim/option.h" #include "nvim/path.h" @@ -132,9 +134,9 @@ static int current_syn_id; #define PRCOLOR_BLACK 0 #define PRCOLOR_WHITE 0xffffff -static int curr_italic; -static int curr_bold; -static int curr_underline; +static TriState curr_italic; +static TriState curr_bold; +static TriState curr_underline; static uint32_t curr_bg; static uint32_t curr_fg; static int page_count; @@ -270,17 +272,25 @@ char_u *parse_printmbfont(void) * Returns an error message for an illegal option, NULL otherwise. * Only used for the printer at the moment... */ -static char_u *parse_list_options(char_u *option_str, option_table_T *table, int table_size) +static char_u *parse_list_options(char_u *option_str, option_table_T *table, + size_t table_size) { + option_table_T *old_opts; + char_u *ret = NULL; char_u *stringp; char_u *colonp; char_u *commap; char_u *p; - int idx = 0; /* init for GCC */ + size_t idx = 0; // init for GCC int len; - for (idx = 0; idx < table_size; ++idx) - table[idx].present = FALSE; + // Save the old values, so that they can be restored in case of an error. + old_opts = (option_table_T *)xmalloc(sizeof(option_table_T) * table_size); + + for (idx = 0; idx < table_size; idx++) { + old_opts[idx] = table[idx]; + table[idx].present = false; + } /* * Repeat for all comma separated parts. @@ -288,8 +298,10 @@ static char_u *parse_list_options(char_u *option_str, option_table_T *table, int stringp = option_str; while (*stringp) { colonp = vim_strchr(stringp, ':'); - if (colonp == NULL) - return (char_u *)N_("E550: Missing colon"); + if (colonp == NULL) { + ret = (char_u *)N_("E550: Missing colon"); + break; + } commap = vim_strchr(stringp, ','); if (commap == NULL) commap = option_str + STRLEN(option_str); @@ -300,15 +312,19 @@ static char_u *parse_list_options(char_u *option_str, option_table_T *table, int if (STRNICMP(stringp, table[idx].name, len) == 0) break; - if (idx == table_size) - return (char_u *)N_("E551: Illegal component"); + if (idx == table_size) { + ret = (char_u *)N_("E551: Illegal component"); + break; + } p = colonp + 1; table[idx].present = TRUE; if (table[idx].hasnum) { - if (!ascii_isdigit(*p)) - return (char_u *)N_("E552: digit expected"); + if (!ascii_isdigit(*p)) { + ret = (char_u *)N_("E552: digit expected"); + break; + } table[idx].number = getdigits_int(&p); } @@ -321,7 +337,15 @@ static char_u *parse_list_options(char_u *option_str, option_table_T *table, int ++stringp; } - return NULL; + if (ret != NULL) { + // Restore old options in case of error + for (idx = 0; idx < table_size; idx++) { + table[idx] = old_opts[idx]; + } + } + + xfree(old_opts); + return ret; } @@ -348,7 +372,6 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec) { int colorindex; uint32_t fg_color; - char *color; pattr->bold = (highlight_has_attr(hl_id, HL_BOLD, modec) != NULL); pattr->italic = (highlight_has_attr(hl_id, HL_ITALIC, modec) != NULL); @@ -356,11 +379,12 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec) pattr->undercurl = (highlight_has_attr(hl_id, HL_UNDERCURL, modec) != NULL); { - color = (char *)highlight_color(hl_id, (char_u *)"fg", modec); - if (color == NULL) + const char *color = highlight_color(hl_id, "fg", modec); + if (color == NULL) { colorindex = 0; - else + } else { colorindex = atoi(color); + } if (colorindex >= 0 && colorindex < t_colors) fg_color = prt_get_term_color(colorindex); @@ -393,7 +417,8 @@ static void prt_set_bg(uint32_t bg) } } -static void prt_set_font(int bold, int italic, int underline) +static void prt_set_font(const TriState bold, const TriState italic, + const TriState underline) { if (curr_bold != bold || curr_italic != italic @@ -405,34 +430,32 @@ static void prt_set_font(int bold, int italic, int underline) } } -/* - * Print the line number in the left margin. - */ -static void prt_line_number(prt_settings_T *psettings, int page_line, linenr_T lnum) +// Print the line number in the left margin. +static void prt_line_number(prt_settings_T *const psettings, + const int page_line, const linenr_T lnum) { - int i; - char_u tbuf[20]; - prt_set_fg(psettings->number.fg_color); prt_set_bg(psettings->number.bg_color); prt_set_font(psettings->number.bold, psettings->number.italic, - psettings->number.underline); - mch_print_start_line(TRUE, page_line); + psettings->number.underline); + mch_print_start_line(true, page_line); - /* Leave two spaces between the number and the text; depends on - * PRINT_NUMBER_WIDTH. */ - sprintf((char *)tbuf, "%6ld", (long)lnum); - for (i = 0; i < 6; i++) + // Leave two spaces between the number and the text; depends on + // PRINT_NUMBER_WIDTH. + char_u tbuf[20]; + snprintf((char *)tbuf, sizeof(tbuf), "%6ld", (long)lnum); + for (int i = 0; i < 6; i++) { (void)mch_print_text_out(&tbuf[i], 1); + } - if (psettings->do_syntax) - /* Set colors for next character. */ + if (psettings->do_syntax) { + // Set colors for next character. current_syn_id = -1; - else { - /* Set colors and font back to normal. */ + } else { + // Set colors and font back to normal. prt_set_fg(PRCOLOR_BLACK); prt_set_bg(PRCOLOR_WHITE); - prt_set_font(FALSE, FALSE, FALSE); + prt_set_font(kFalse, kFalse, kFalse); } } @@ -475,22 +498,20 @@ int prt_get_unit(int idx) return u; } -/* - * Print the page header. - */ -static void prt_header(prt_settings_T *psettings, int pagenum, linenr_T lnum) +// Print the page header. +static void prt_header(prt_settings_T *const psettings, const int pagenum, + const linenr_T lnum) { int width = psettings->chars_per_line; - int page_line; - char_u *tbuf; - char_u *p; - /* Also use the space for the line number. */ - if (prt_use_number()) + // Also use the space for the line number. + if (prt_use_number()) { width += PRINT_NUMBER_WIDTH; + } assert(width >= 0); - tbuf = xmalloc((size_t)width + IOSIZE); + const size_t tbuf_size = (size_t)width + IOSIZE; + char_u *tbuf = xmalloc(tbuf_size); if (*p_header != NUL) { linenr_T tmp_lnum, tmp_topline, tmp_botline; @@ -519,38 +540,40 @@ static void prt_header(prt_settings_T *psettings, int pagenum, linenr_T lnum) curwin->w_cursor.lnum = tmp_lnum; curwin->w_topline = tmp_topline; curwin->w_botline = tmp_botline; - } else - sprintf((char *)tbuf, _("Page %d"), pagenum); + } else { + snprintf((char *)tbuf, tbuf_size, _("Page %d"), pagenum); + } prt_set_fg(PRCOLOR_BLACK); prt_set_bg(PRCOLOR_WHITE); - prt_set_font(TRUE, FALSE, FALSE); + prt_set_font(kTrue, kFalse, kFalse); - /* Use a negative line number to indicate printing in the top margin. */ - page_line = 0 - prt_header_height(); - mch_print_start_line(TRUE, page_line); - for (p = tbuf; *p != NUL; ) { - int l = (*mb_ptr2len)(p); + // Use a negative line number to indicate printing in the top margin. + int page_line = 0 - prt_header_height(); + mch_print_start_line(true, page_line); + for (char_u *p = tbuf; *p != NUL; ) { + const int l = (*mb_ptr2len)(p); assert(l >= 0); if (mch_print_text_out(p, (size_t)l)) { - ++page_line; - if (page_line >= 0) /* out of room in header */ + page_line++; + if (page_line >= 0) { // out of room in header break; - mch_print_start_line(TRUE, page_line); + } + mch_print_start_line(true, page_line); } p += l; } xfree(tbuf); - if (psettings->do_syntax) - /* Set colors for next character. */ + if (psettings->do_syntax) { + // Set colors for next character. current_syn_id = -1; - else { - /* Set colors and font back to normal. */ + } else { + // Set colors and font back to normal. prt_set_fg(PRCOLOR_BLACK); prt_set_bg(PRCOLOR_WHITE); - prt_set_font(FALSE, FALSE, FALSE); + prt_set_font(kFalse, kFalse, kFalse); } } @@ -559,8 +582,9 @@ static void prt_header(prt_settings_T *psettings, int pagenum, linenr_T lnum) */ static void prt_message(char_u *s) { - screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); - screen_puts(s, (int)Rows - 1, 0, hl_attr(HLF_R)); + grid_fill(&default_grid, (int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', + 0); + grid_puts(&default_grid, s, (int)Rows - 1, 0, HL_ATTR(HLF_R)); ui_flush(); } @@ -616,21 +640,19 @@ void ex_hardcopy(exarg_T *eap) else settings.do_syntax = settings.has_color; - /* Set up printing attributes for line numbers */ + // Set up printing attributes for line numbers settings.number.fg_color = PRCOLOR_BLACK; settings.number.bg_color = PRCOLOR_WHITE; - settings.number.bold = FALSE; - settings.number.italic = TRUE; - settings.number.underline = FALSE; - /* - * Syntax highlighting of line numbers. - */ - if (prt_use_number() && settings.do_syntax) { - int id; + settings.number.bold = kFalse; + settings.number.italic = kTrue; + settings.number.underline = kFalse; - id = syn_name2id((char_u *)"LineNr"); - if (id > 0) + // Syntax highlighting of line numbers. + if (prt_use_number() && settings.do_syntax) { + int id = syn_name2id((char_u *)"LineNr"); + if (id > 0) { id = syn_get_final_id(id); + } prt_get_attr(id, &settings.number, settings.modec); } @@ -648,13 +670,13 @@ void ex_hardcopy(exarg_T *eap) /* Set colors and font to normal. */ curr_bg = 0xffffffff; curr_fg = 0xffffffff; - curr_italic = MAYBE; - curr_bold = MAYBE; - curr_underline = MAYBE; + curr_italic = kNone; + curr_bold = kNone; + curr_underline = kNone; prt_set_fg(PRCOLOR_BLACK); prt_set_bg(PRCOLOR_WHITE); - prt_set_font(FALSE, FALSE, FALSE); + prt_set_font(kFalse, kFalse, kFalse); current_syn_id = -1; jobsplit = (printer_opts[OPT_PRINT_JOBSPLIT].present @@ -817,19 +839,17 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T tab_spaces = ppos->lead_spaces; } - mch_print_start_line(0, page_line); + mch_print_start_line(false, page_line); line = ml_get(ppos->file_line); /* * Loop over the columns until the end of the file line or right margin. */ for (col = ppos->column; line[col] != NUL && !need_break; col += outputlen) { - outputlen = 1; - if (has_mbyte && (outputlen = (*mb_ptr2len)(line + col)) < 1) + if ((outputlen = (*mb_ptr2len)(line + col)) < 1) { outputlen = 1; - /* - * syntax highlighting stuff. - */ + } + // syntax highlighting stuff. if (psettings->do_syntax) { id = syn_get_id(curwin, ppos->file_line, col, 1, NULL, FALSE); if (id > 0) @@ -873,10 +893,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T need_break = 1; } else { need_break = mch_print_text_out(line + col, (size_t)outputlen); - if (has_mbyte) - print_pos += (*mb_ptr2cells)(line + col); - else - print_pos++; + print_pos += utf_ptr2cells(line + col); } } @@ -1244,8 +1261,8 @@ static int prt_do_moveto; static int prt_need_font; static int prt_font; static int prt_need_underline; -static int prt_underline; -static int prt_do_underline; +static TriState prt_underline; +static TriState prt_do_underline; static int prt_need_fgcol; static uint32_t prt_fgcol; static int prt_need_bgcol; @@ -1523,8 +1540,8 @@ static int prt_find_resource(char *name, struct prt_ps_resource_S *resource) /* Look for named resource file in runtimepath */ STRCPY(buffer, "print"); add_pathsep((char *)buffer); - vim_strcat(buffer, (char_u *)name, MAXPATHL); - vim_strcat(buffer, (char_u *)".ps", MAXPATHL); + xstrlcat((char *)buffer, name, MAXPATHL); + xstrlcat((char *)buffer, ".ps", MAXPATHL); resource->filename[0] = NUL; retval = (do_in_runtimepath(buffer, 0, prt_resource_name, resource->filename) && resource->filename[0] != NUL); @@ -2106,7 +2123,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) props = enc_canon_props(p_encoding); if (!(props & ENC_8BIT) && ((*p_pmcs != NUL) || !(props & ENC_UNICODE))) { p_mbenc_first = NULL; - int effective_cmap; + int effective_cmap = 0; for (cmap = 0; cmap < (int)ARRAY_SIZE(prt_ps_mbfonts); cmap++) if (prt_match_encoding((char *)p_encoding, &prt_ps_mbfonts[cmap], &p_mbenc)) { @@ -2557,13 +2574,12 @@ int mch_print_begin(prt_settings_T *psettings) prt_conv.vc_type = CONV_NONE; if (!(enc_canon_props(p_enc) & enc_canon_props(p_encoding) & ENC_8BIT)) { - /* Set up encoding conversion if required */ - if (FAIL == convert_setup(&prt_conv, p_enc, p_encoding)) { - EMSG2(_("E620: Unable to convert to print encoding \"%s\""), - p_encoding); - return FALSE; + // Set up encoding conversion if required + if (convert_setup(&prt_conv, p_enc, p_encoding) == FAIL) { + emsgf(_("E620: Unable to convert to print encoding \"%s\""), + p_encoding); + return false; } - prt_do_conv = TRUE; } prt_do_conv = prt_conv.vc_type != CONV_NONE; @@ -2834,7 +2850,7 @@ int mch_print_begin_page(char_u *str) /* We have reset the font attributes, force setting them again. */ curr_bg = 0xffffffff; curr_fg = 0xffffffff; - curr_bold = MAYBE; + curr_bold = kNone; return !prt_file_error; } @@ -2847,11 +2863,12 @@ int mch_print_blank_page(void) static double prt_pos_x = 0; static double prt_pos_y = 0; -void mch_print_start_line(int margin, int page_line) +void mch_print_start_line(const bool margin, const int page_line) { prt_pos_x = prt_left_margin; - if (margin) + if (margin) { prt_pos_x -= prt_number_width; + } prt_pos_y = prt_top_margin - prt_first_line_height - page_line * prt_line_height; @@ -2861,17 +2878,13 @@ void mch_print_start_line(int margin, int page_line) prt_half_width = FALSE; } -int mch_print_text_out(char_u *p, size_t len) +int mch_print_text_out(char_u *const textp, size_t len) { - int need_break; + char_u *p = textp; char_u ch; char_u ch_buff[8]; - double char_width; - double next_pos; - int in_ascii; - int half_width; - - char_width = prt_char_width; + char_u *tofree = NULL; + double char_width = prt_char_width; /* Ideally VIM would create a rearranged CID font to combine a Roman and * CJKV font to do what VIM is doing here - use a Roman font for characters @@ -2881,7 +2894,7 @@ int mch_print_text_out(char_u *p, size_t len) * years! If they ever do, a lot of this code will disappear. */ if (prt_use_courier) { - in_ascii = (len == 1 && *p < 0x80); + const bool in_ascii = (len == 1 && *p < 0x80); if (prt_in_ascii) { if (!in_ascii) { /* No longer in ASCII range - need to switch font */ @@ -2897,9 +2910,10 @@ int mch_print_text_out(char_u *p, size_t len) } } if (prt_out_mbyte) { - half_width = ((*mb_ptr2cells)(p) == 1); - if (half_width) + const bool half_width = (utf_ptr2cells(p) == 1); + if (half_width) { char_width /= 2; + } if (prt_half_width) { if (!half_width) { prt_half_width = FALSE; @@ -2972,23 +2986,24 @@ int mch_print_text_out(char_u *p, size_t len) } if (prt_do_conv) { - /* Convert from multi-byte to 8-bit encoding */ - p = string_convert(&prt_conv, p, &len); - if (p == NULL) - p = (char_u *)xstrdup(""); + // Convert from multi-byte to 8-bit encoding + tofree = p = string_convert(&prt_conv, p, &len); + if (p == NULL) { + p = (char_u *)""; + len = 0; + } } if (prt_out_mbyte) { - /* Multi-byte character strings are represented more efficiently as hex - * strings when outputting clean 8 bit PS. - */ - do { + // Multi-byte character strings are represented more efficiently as hex + // strings when outputting clean 8 bit PS. + while (len-- > 0) { ch = prt_hexchar[(unsigned)(*p) >> 4]; ga_append(&prt_ps_buffer, (char)ch); ch = prt_hexchar[(*p) & 0xf]; ga_append(&prt_ps_buffer, (char)ch); p++; - } while (--len); + } } else { /* Add next character to buffer of characters to output. * Note: One printed character may require several PS characters to @@ -3022,25 +3037,26 @@ int mch_print_text_out(char_u *p, size_t len) ga_append(&prt_ps_buffer, (char)ch); } - /* Need to free any translated characters */ - if (prt_do_conv) - xfree(p); + // Need to free any translated characters + xfree(tofree); prt_text_run += char_width; prt_pos_x += char_width; // The downside of fp - use relative error on right margin check - next_pos = prt_pos_x + prt_char_width; - need_break = ((next_pos > prt_right_margin) - && ((next_pos - prt_right_margin) > (prt_right_margin * 1e-5))); + const double next_pos = prt_pos_x + prt_char_width; + const bool need_break = (next_pos > prt_right_margin) + && ((next_pos - prt_right_margin) > (prt_right_margin * 1e-5)); - if (need_break) + if (need_break) { prt_flush_buffer(); + } return need_break; } -void mch_print_set_font(int iBold, int iItalic, int iUnderline) +void mch_print_set_font(const TriState iBold, const TriState iItalic, + const TriState iUnderline) { int font = 0; |