3655 lines · 94.3 KB · C
RawDownload
/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved	by Bram Moolenaar * * Do ":help uganda"  in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * hardcopy.c: printing to paper */ #include "vim.h"#include "version.h" #if defined(FEAT_PRINTER) || defined(PROTO)/* * To implement printing on a platform, the following functions must be * defined: * * int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) * Called once.  Code should display printer dialogue (if appropriate) and * determine printer font and margin settings.  Reset has_color if the printer * doesn't support colors at all. * Returns FAIL to abort. * * int mch_print_begin(prt_settings_T *settings) * Called to start the print job. * Return FALSE to abort. * * int mch_print_begin_page(char_u *msg) * Called at the start of each page. * "msg" indicates the progress of the print job, can be NULL. * Return FALSE to abort. * * int mch_print_end_page() * Called at the end of each page. * Return FALSE to abort. * * int mch_print_blank_page() * Called to generate a blank page for collated, duplex, multiple copy * document.  Return FALSE to abort. * * void mch_print_end(prt_settings_T *psettings) * Called at normal end of print job. * * void mch_print_cleanup() * Called if print job ends normally or is abandoned. Free any memory, close * devices and handles.  Also called when mch_print_begin() fails, but not * when mch_print_init() fails. * * void mch_print_set_font(int Bold, int Italic, int Underline); * Called whenever the font style changes. * * void mch_print_set_bg(long_u bgcol); * Called to set the background color for the following text. Parameter is an * RGB value. * * void mch_print_set_fg(long_u fgcol); * Called to set the foreground color for the following text. Parameter is an * RGB value. * * mch_print_start_line(int margin, int page_line) * Sets the current position at the start of line "page_line". * If margin is TRUE start in the left margin (for header and line number). * * int mch_print_text_out(char_u *p, int len); * Output one character of text p[len] at the current position. * Return TRUE if there is no room for another character in the same line. * * Note that the generic code has no idea of margins. The machine code should * simply make the page look smaller!  The header and the line numbers are * printed in the margin. */ #ifdef FEAT_SYN_HLstatic const long_u  cterm_color_8[8] ={    (long_u)0x000000L, (long_u)0xff0000L, (long_u)0x00ff00L, (long_u)0xffff00L,    (long_u)0x0000ffL, (long_u)0xff00ffL, (long_u)0x00ffffL, (long_u)0xffffffL}; static const long_u  cterm_color_16[16] ={    (long_u)0x000000L, (long_u)0x0000c0L, (long_u)0x008000L, (long_u)0x004080L,    (long_u)0xc00000L, (long_u)0xc000c0L, (long_u)0x808000L, (long_u)0xc0c0c0L,    (long_u)0x808080L, (long_u)0x6060ffL, (long_u)0x00ff00L, (long_u)0x00ffffL,    (long_u)0xff8080L, (long_u)0xff40ffL, (long_u)0xffff00L, (long_u)0xffffffL}; static int		current_syn_id;#endif #define PRCOLOR_BLACK	(long_u)0#define PRCOLOR_WHITE	(long_u)0xFFFFFFL static int	curr_italic;static int	curr_bold;static int	curr_underline;static long_u	curr_bg;static long_u	curr_fg;static int	page_count; #if defined(FEAT_MBYTE) && defined(FEAT_POSTSCRIPT)# define OPT_MBFONT_USECOURIER  0# define OPT_MBFONT_ASCII       1# define OPT_MBFONT_REGULAR     2# define OPT_MBFONT_BOLD	3# define OPT_MBFONT_OBLIQUE     4# define OPT_MBFONT_BOLDOBLIQUE 5# define OPT_MBFONT_NUM_OPTIONS 6 static option_table_T mbfont_opts[OPT_MBFONT_NUM_OPTIONS] ={    {"c",	FALSE, 0, NULL, 0, FALSE},    {"a",	FALSE, 0, NULL, 0, FALSE},    {"r",	FALSE, 0, NULL, 0, FALSE},    {"b",	FALSE, 0, NULL, 0, FALSE},    {"i",	FALSE, 0, NULL, 0, FALSE},    {"o",	FALSE, 0, NULL, 0, FALSE},};#endif /* * These values determine the print position on a page. */typedef struct{    int		lead_spaces;	    /* remaining spaces for a TAB */    int		print_pos;	    /* virtual column for computing TABs */    colnr_T	column;		    /* byte column */    linenr_T	file_line;	    /* line nr in the buffer */    long_u	bytes_printed;	    /* bytes printed so far */    int		ff;		    /* seen form feed character */} prt_pos_T; static char_u *parse_list_options __ARGS((char_u *option_str, option_table_T *table, int table_size)); #ifdef FEAT_SYN_HLstatic long_u darken_rgb __ARGS((long_u rgb));static long_u prt_get_term_color __ARGS((int colorindex));#endifstatic void prt_set_fg __ARGS((long_u fg));static void prt_set_bg __ARGS((long_u bg));static void prt_set_font __ARGS((int bold, int italic, int underline));static void prt_line_number __ARGS((prt_settings_T *psettings, int page_line, linenr_T lnum));static void prt_header __ARGS((prt_settings_T *psettings, int pagenum, linenr_T lnum));static void prt_message __ARGS((char_u *s));static colnr_T hardcopy_line __ARGS((prt_settings_T *psettings, int page_line, prt_pos_T *ppos));#ifdef FEAT_SYN_HLstatic void prt_get_attr __ARGS((int hl_id, prt_text_attr_T* pattr, int modec));#endif /* * Parse 'printoptions' and set the flags in "printer_opts". * Returns an error message or NULL; */    char_u *parse_printoptions(){    return parse_list_options(p_popt, printer_opts, OPT_PRINT_NUM_OPTIONS);} #if (defined(FEAT_MBYTE) && defined(FEAT_POSTSCRIPT)) || defined(PROTO)/* * Parse 'printoptions' and set the flags in "printer_opts". * Returns an error message or NULL; */    char_u *parse_printmbfont(){    return parse_list_options(p_pmfn, mbfont_opts, OPT_MBFONT_NUM_OPTIONS);}#endif /* * Parse a list of options in the form * option:value,option:value,option:value * * "value" can start with a number which is parsed out, e.g.  margin:12mm * * Returns an error message for an illegal option, NULL otherwise. * Only used for the printer at the moment... */    static char_u *parse_list_options(option_str, table, table_size)    char_u		*option_str;    option_table_T	*table;    int			table_size;{    char_u	*stringp;    char_u	*colonp;    char_u	*commap;    char_u	*p;    int		idx = 0;		/* init for GCC */    int		len;     for (idx = 0; idx < table_size; ++idx)	table[idx].present = FALSE;     /*     * Repeat for all comma separated parts.     */    stringp = option_str;    while (*stringp)    {	colonp = vim_strchr(stringp, ':');	if (colonp == NULL)	    return (char_u *)N_("E550: Missing colon");	commap = vim_strchr(stringp, ',');	if (commap == NULL)	    commap = option_str + STRLEN(option_str); 	len = (int)(colonp - stringp); 	for (idx = 0; idx < table_size; ++idx)	    if (STRNICMP(stringp, table[idx].name, len) == 0)		break; 	if (idx == table_size)	    return (char_u *)N_("E551: Illegal component"); 	p = colonp + 1;	table[idx].present = TRUE; 	if (table[idx].hasnum)	{	    if (!VIM_ISDIGIT(*p))		return (char_u *)N_("E552: digit expected"); 	    table[idx].number = getdigits(&p); /*advances p*/	} 	table[idx].string = p;	table[idx].strlen = (int)(commap - p); 	stringp = commap;	if (*stringp == ',')	    ++stringp;    }     return NULL;}  #ifdef FEAT_SYN_HL/* * If using a dark background, the colors will probably be too bright to show * up well on white paper, so reduce their brightness. */    static long_udarken_rgb(rgb)    long_u	rgb;{    return	((rgb >> 17) << 16)	    +	(((rgb & 0xff00) >> 9) << 8)	    +	((rgb & 0xff) >> 1);}     static long_uprt_get_term_color(colorindex)    int	    colorindex;{    /* TODO: Should check for xterm with 88 or 256 colors. */    if (t_colors > 8)	return cterm_color_16[colorindex % 16];    return cterm_color_8[colorindex % 8];}     static voidprt_get_attr(hl_id, pattr, modec)    int			hl_id;    prt_text_attr_T	*pattr;    int			modec;{    int     colorindex;    long_u  fg_color;    long_u  bg_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);    pattr->underline = (highlight_has_attr(hl_id, HL_UNDERLINE, modec) != NULL);    pattr->undercurl = (highlight_has_attr(hl_id, HL_UNDERCURL, modec) != NULL); # ifdef FEAT_GUI    if (gui.in_use)    {	bg_color = highlight_gui_color_rgb(hl_id, FALSE);	if (bg_color == PRCOLOR_BLACK)	    bg_color = PRCOLOR_WHITE; 	fg_color = highlight_gui_color_rgb(hl_id, TRUE);    }    else# endif    {	bg_color = PRCOLOR_WHITE; 	color = (char *)highlight_color(hl_id, (char_u *)"fg", modec);	if (color == NULL)	    colorindex = 0;	else	    colorindex = atoi(color); 	if (colorindex >= 0 && colorindex < t_colors)	    fg_color = prt_get_term_color(colorindex);	else	    fg_color = PRCOLOR_BLACK;    }     if (fg_color == PRCOLOR_WHITE)	fg_color = PRCOLOR_BLACK;    else if (*p_bg == 'd')	fg_color = darken_rgb(fg_color);     pattr->fg_color = fg_color;    pattr->bg_color = bg_color;}#endif /* FEAT_SYN_HL */     static voidprt_set_fg(fg)    long_u fg;{    if (fg != curr_fg)    {	curr_fg = fg;	mch_print_set_fg(fg);    }}     static voidprt_set_bg(bg)    long_u bg;{    if (bg != curr_bg)    {	curr_bg = bg;	mch_print_set_bg(bg);    }}     static voidprt_set_font(bold, italic, underline)    int		bold;    int		italic;    int		underline;{    if (curr_bold != bold	    || curr_italic != italic	    || curr_underline != underline)    {	curr_underline = underline;	curr_italic = italic;	curr_bold = bold;	mch_print_set_font(bold, italic, underline);    }} /* * Print the line number in the left margin. */    static voidprt_line_number(psettings, page_line, lnum)    prt_settings_T *psettings;    int		page_line;    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);     /* 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++)	(void)mch_print_text_out(&tbuf[i], 1); #ifdef FEAT_SYN_HL    if (psettings->do_syntax)	/* Set colors for next character. */	current_syn_id = -1;    else#endif    {	/* Set colors and font back to normal. */	prt_set_fg(PRCOLOR_BLACK);	prt_set_bg(PRCOLOR_WHITE);	prt_set_font(FALSE, FALSE, FALSE);    }} /* * Get the currently effective header height. */    intprt_header_height(){    if (printer_opts[OPT_PRINT_HEADERHEIGHT].present)	return printer_opts[OPT_PRINT_HEADERHEIGHT].number;    return 2;} /* * Return TRUE if using a line number for printing. */    intprt_use_number(){    return (printer_opts[OPT_PRINT_NUMBER].present	    && TOLOWER_ASC(printer_opts[OPT_PRINT_NUMBER].string[0]) == 'y');} /* * Return the unit used in a margin item in 'printoptions'. * Returns PRT_UNIT_NONE if not recognized. */    intprt_get_unit(idx)    int		idx;{    int		u = PRT_UNIT_NONE;    int		i;    static char *(units[4]) = PRT_UNIT_NAMES;     if (printer_opts[idx].present)	for (i = 0; i < 4; ++i)	    if (STRNICMP(printer_opts[idx].string, units[i], 2) == 0)	    {		u = i;		break;	    }    return u;} /* * Print the page header. *//*ARGSUSED*/    static voidprt_header(psettings, pagenum, lnum)    prt_settings_T  *psettings;    int		pagenum;    linenr_T	lnum;{    int		width = psettings->chars_per_line;    int		page_line;    char_u	*tbuf;    char_u	*p;#ifdef FEAT_MBYTE    int		l;#endif     /* Also use the space for the line number. */    if (prt_use_number())	width += PRINT_NUMBER_WIDTH;     tbuf = alloc(width + IOSIZE);    if (tbuf == NULL)	return; #ifdef FEAT_STL_OPT    if (*p_header != NUL)    {	linenr_T	tmp_lnum, tmp_topline, tmp_botline;	int		use_sandbox = FALSE; 	/*	 * Need to (temporarily) set current line number and first/last line	 * number on the 'window'.  Since we don't know how long the page is,	 * set the first and current line number to the top line, and guess	 * that the page length is 64.	 */	tmp_lnum = curwin->w_cursor.lnum;	tmp_topline = curwin->w_topline;	tmp_botline = curwin->w_botline;	curwin->w_cursor.lnum = lnum;	curwin->w_topline = lnum;	curwin->w_botline = lnum + 63;	printer_page_num = pagenum; # ifdef FEAT_EVAL	use_sandbox = was_set_insecurely((char_u *)"printheader", 0);# endif	build_stl_str_hl(curwin, tbuf, (size_t)(width + IOSIZE),						  p_header, use_sandbox,						  ' ', width, NULL, NULL); 	/* Reset line numbers */	curwin->w_cursor.lnum = tmp_lnum;	curwin->w_topline = tmp_topline;	curwin->w_botline = tmp_botline;    }    else

Lines 1–500 of 3655.