aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/hardcopy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/hardcopy.c')
-rw-r--r--src/nvim/hardcopy.c282
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;