diff options
author | Bram Moolenaar <Bram@vim.org> | 2004-07-10 09:47:34 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2004-07-10 09:47:34 +0000 |
commit | 8299df966a58236b31c0028fd7ce799c4ac6e625 (patch) | |
tree | 09250c8a4c22a4fb109a7b7a0265454b3c4d5bca /src | |
parent | 325b7a2fb5b970b77f7b9ec28ba15eb794f6edf8 (diff) | |
download | vim-git-8299df966a58236b31c0028fd7ce799c4ac6e625.tar.gz |
updated for version 7.0007v7.0007
Diffstat (limited to 'src')
-rw-r--r-- | src/auto/config.mk | 5 | ||||
-rw-r--r-- | src/eval.c | 118 | ||||
-rw-r--r-- | src/ex_cmds.c | 17 | ||||
-rw-r--r-- | src/ex_cmds2.c | 1419 | ||||
-rw-r--r-- | src/ex_getln.c | 97 | ||||
-rw-r--r-- | src/globals.h | 24 | ||||
-rw-r--r-- | src/if_mzsch.c | 34 | ||||
-rw-r--r-- | src/ops.c | 88 | ||||
-rw-r--r-- | src/option.c | 23 | ||||
-rw-r--r-- | src/option.h | 4 | ||||
-rw-r--r-- | src/os_mac.c | 116 | ||||
-rw-r--r-- | src/proto/ex_getln.pro | 1 | ||||
-rw-r--r-- | src/proto/ops.pro | 5 |
13 files changed, 1557 insertions, 394 deletions
diff --git a/src/auto/config.mk b/src/auto/config.mk new file mode 100644 index 000000000..fa7c10850 --- /dev/null +++ b/src/auto/config.mk @@ -0,0 +1,5 @@ +the first targets to make vim are: scratch config myself +srcdir = . +VIMNAME = vim +EXNAME = ex +VIEWNAME = view diff --git a/src/eval.c b/src/eval.c index faa097229..a95cbf6d8 100644 --- a/src/eval.c +++ b/src/eval.c @@ -370,6 +370,7 @@ static void f_substitute __ARGS((VAR argvars, VAR retvar)); static void f_tempname __ARGS((VAR argvars, VAR retvar)); static void f_tolower __ARGS((VAR argvars, VAR retvar)); static void f_toupper __ARGS((VAR argvars, VAR retvar)); +static void f_tr __ARGS((VAR argvars, VAR retvar)); static void f_type __ARGS((VAR argvars, VAR retvar)); static void f_virtcol __ARGS((VAR argvars, VAR retvar)); static void f_visualmode __ARGS((VAR argvars, VAR retvar)); @@ -2923,6 +2924,7 @@ static struct fst {"tempname", 0, 0, f_tempname}, {"tolower", 1, 1, f_tolower}, {"toupper", 1, 1, f_toupper}, + {"tr", 3, 3, f_tr}, {"type", 1, 1, f_type}, {"virtcol", 1, 1, f_virtcol}, {"visualmode", 0, 1, f_visualmode}, @@ -7438,6 +7440,122 @@ f_toupper(argvars, retvar) } /* + * "tr(string, fromstr, tostr)" function + */ + static void +f_tr(argvars, retvar) + VAR argvars; + VAR retvar; +{ + char_u *instr; + char_u *fromstr; + char_u *tostr; + char_u *p; +#ifdef FEAT_MBYTE + int inlen; + int fromlen; + int tolen; + int idx; + char_u *cpstr; + int cplen; + int first = TRUE; +#endif + char_u buf[NUMBUFLEN]; + char_u buf2[NUMBUFLEN]; + garray_T ga; + + instr = get_var_string(&argvars[0]); + fromstr = get_var_string_buf(&argvars[1], buf); + tostr = get_var_string_buf(&argvars[2], buf2); + + /* Default return value: empty string. */ + retvar->var_type = VAR_STRING; + retvar->var_val.var_string = NULL; + ga_init2(&ga, (int)sizeof(char), 80); + +#ifdef FEAT_MBYTE + if (!has_mbyte) +#endif + /* not multi-byte: fromstr and tostr must be the same length */ + if (STRLEN(fromstr) != STRLEN(tostr)) + { +error: + EMSG2(_(e_invarg2), fromstr); + ga_clear(&ga); + return; + } + + /* fromstr and tostr have to contain the same number of chars */ + while (*instr != NUL) + { +#ifdef FEAT_MBYTE + if (has_mbyte) + { + inlen = mb_ptr2len_check(instr); + cpstr = instr; + cplen = inlen; + idx = 0; + for (p = fromstr; *p != NUL; p += fromlen) + { + fromlen = mb_ptr2len_check(p); + if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0) + { + for (p = tostr; *p != NUL; p += tolen) + { + tolen = mb_ptr2len_check(p); + if (idx-- == 0) + { + cplen = tolen; + cpstr = p; + break; + } + } + if (*p == NUL) /* tostr is shorter than fromstr */ + goto error; + break; + } + ++idx; + } + + if (first && cpstr == instr) + { + /* Check that fromstr and tostr have the same number of + * (multi-byte) characters. Done only once when a character + * of instr doesn't appear in fromstr. */ + first = FALSE; + for (p = tostr; *p != NUL; p += tolen) + { + tolen = mb_ptr2len_check(p); + --idx; + } + if (idx != 0) + goto error; + } + + ga_grow(&ga, cplen); + mch_memmove(ga.ga_data + ga.ga_len, cpstr, (size_t)cplen); + ga.ga_len += cplen; + ga.ga_room -= cplen; + + instr += inlen; + } + else +#endif + { + /* When not using multi-byte chars we can do it faster. */ + p = vim_strchr(fromstr, *instr); + if (p != NULL) + ga_append(&ga, tostr[p - fromstr]); + else + ga_append(&ga, *instr); + ++instr; + } + } + + retvar->var_val.var_string = ga.ga_data; +} + +/* * "type(expr)" function */ static void diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 4f53f59d6..3a49b9a64 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3738,6 +3738,7 @@ do_sub(eap) unsigned len, needed_len; long nmatch_tl = 0; /* nr of lines matched below lnum */ int do_again; /* do it again after joining lines */ + int skip_match = FALSE; /* * The new text is build up step by step, to avoid too much @@ -3822,7 +3823,12 @@ do_sub(eap) && regmatch.endpos[0].lnum == 0 && matchcol == regmatch.endpos[0].col) { - ++matchcol; /* search for a match at next column */ + if (sub_firstline[matchcol] == NUL) + /* We already were at the end of the line. Don't look + * for a match in this line again. */ + skip_match = TRUE; + else + ++matchcol; /* search for a match at next column */ goto skip; } @@ -4114,9 +4120,12 @@ skip: /* We already know that we did the last subst when we are at * the end of the line, except that a pattern like * "bar\|\nfoo" may match at the NUL. */ - lastone = ((sub_firstline[matchcol] == NUL && nmatch <= 1 - && !re_multiline(regmatch.regprog)) - || got_int || got_quit || !(do_all || do_again)); + lastone = (skip_match + || got_int + || got_quit + || !(do_all || do_again) + || (sub_firstline[matchcol] == NUL && nmatch <= 1 + && !re_multiline(regmatch.regprog))); nmatch = -1; /* diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index ed7e08c00..9d760ea16 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -3731,11 +3731,19 @@ hardcopy_line(psettings, page_line, ppos) * Adobe technote 5003, 9th February 1996 * 6. Adobe Font Metrics File Format Specification, Version 4.1, * Adobe Technote 5007, 7th October 1998 + * 7. Adobe CMap and CIDFont Files Specification, Version 1.0, + * Adobe Technote 5014, 8th October 1996 + * 8. Adobe CJKV Character Collections and CMaps for CID-Keyed Fonts, + * Adoboe Technote 5094, 8th September, 2001 + * 9. CJKV Information Processing, 2nd Edition, + * O'Reilly, 2002, ISBN 1-56592-224-7 * * Some of these documents can be found in PDF form on Adobe's web site - * http://www.adobe.com */ +#define NUM_ELEMENTS(arr) (sizeof(arr)/sizeof((arr)[0])) + #define PRT_PS_DEFAULT_DPI (72) /* Default user space resolution */ #define PRT_PS_DEFAULT_FONTSIZE (10) #define PRT_PS_DEFAULT_BUFFER_SIZE (80) @@ -3783,7 +3791,8 @@ struct prt_ps_font_S #define PRT_PS_FONT_OBLIQUE (2) #define PRT_PS_FONT_BOLDOBLIQUE (3) -static struct prt_ps_font_S prt_ps_font = +/* Standard font metrics for Courier family */ +static struct prt_ps_font_S prt_ps_courier_font = { 600, -100, 50, @@ -3791,6 +3800,218 @@ static struct prt_ps_font_S prt_ps_font = {"Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique"} }; +/* Generic font metrics for multi-byte fonts */ +static struct prt_ps_font_S prt_ps_mb_font = +{ + 1000, + -100, 50, + -250, 805, + {NULL, NULL, NULL, NULL} +}; + +/* Pointer to current font set being used */ +static struct prt_ps_font_S* prt_ps_font; + +/* Structures to map user named encoding and mapping to PS equivalents for + * building CID font name */ +struct prt_ps_encoding_S +{ + char_u *encoding; + char_u *cmap_encoding; + int needs_charset; +}; + +struct prt_ps_charset_S +{ + char *charset; + char *cmap_charset; + int has_charset; +}; + +#define CS_JIS_C_1978 (0x01) +#define CS_JIS_X_1983 (0x02) +#define CS_JIS_X_1990 (0x04) +#define CS_NEC (0x08) +#define CS_MSWINDOWS (0x10) +#define CS_CP932 (0x20) +#define CS_KANJITALK6 (0x40) +#define CS_KANJITALK7 (0x80) + +/* Japanese encodings and charsets */ +static struct prt_ps_encoding_S j_encodings[] = +{ + {"iso-2022-jp", NULL, (CS_JIS_C_1978|CS_JIS_X_1983|CS_JIS_X_1990| + CS_NEC)}, + {"euc-jp", "EUC", (CS_JIS_C_1978|CS_JIS_X_1983|CS_JIS_X_1990)}, + {"sjis", "RKSJ", (CS_JIS_C_1978|CS_JIS_X_1983|CS_MSWINDOWS| + CS_KANJITALK6|CS_KANJITALK7)}, + {"cp932", "RKSJ", CS_JIS_X_1983}, + {"ucs-2", "UCS2", CS_JIS_X_1990}, + {"utf-8", "UTF8" , CS_JIS_X_1990} +}; +static struct prt_ps_charset_S j_charsets[] = +{ + {"JIS_C_1978", "78", CS_JIS_C_1978}, + {"JIS_X_1983", NULL, CS_JIS_X_1983}, + {"JIS_X_1990", "Hojo", CS_JIS_X_1990}, + {"NEC", "Ext", CS_NEC}, + {"MSWINDOWS", "90ms", CS_MSWINDOWS}, + {"CP932", "90ms", CS_JIS_X_1983}, + {"KANJITALK6", "83pv", CS_KANJITALK6}, + {"KANJITALK7", "90pv", CS_KANJITALK7} +}; + +#define CS_GB_2312_80 (0x01) +#define CS_GBT_12345_90 (0x02) +#define CS_GBK2K (0x04) +#define CS_SC_MAC (0x08) +#define CS_GBT_90_MAC (0x10) +#define CS_GBK (0x20) +#define CS_SC_ISO10646 (0x40) + +/* Simplified Chinese encodings and charsets */ +static struct prt_ps_encoding_S sc_encodings[] = +{ + {"iso-2022", NULL, (CS_GB_2312_80|CS_GBT_12345_90)}, + {"gb18030", NULL, CS_GBK2K}, + {"euc-cn", "EUC", (CS_GB_2312_80|CS_GBT_12345_90|CS_SC_MAC| + CS_GBT_90_MAC)}, + {"gbk", "EUC", CS_GBK}, + {"ucs-2", "UCS2", CS_SC_ISO10646}, + {"utf-8", "UTF8", CS_SC_ISO10646} +}; +static struct prt_ps_charset_S sc_charsets[] = +{ + {"GB_2312-80", "GB", CS_GB_2312_80}, + {"GBT_12345-90","GBT", CS_GBT_12345_90}, + {"MAC", "GBpc", CS_SC_MAC}, + {"GBT-90_MAC", "GBTpc", CS_GBT_90_MAC}, + {"GBK", "GBK", CS_GBK}, + {"GB18030", "GBK2K", CS_GBK2K}, + {"ISO10646", "UniGB", CS_SC_ISO10646} +}; + +#define CS_CNS_PLANE_1 (0x01) +#define CS_CNS_PLANE_2 (0x02) +#define CS_CNS_PLANE_1_2 (0x04) +#define CS_B5 (0x08) +#define CS_ETEN (0x10) +#define CS_HK_GCCS (0x20) +#define CS_HK_SCS (0x40) +#define CS_HK_SCS_ETEN (0x80) +#define CS_MTHKL (0x100) +#define CS_MTHKS (0x200) +#define CS_DLHKL (0x400) +#define CS_DLHKS (0x800) +#define CS_TC_ISO10646 (0x1000) + +/* Traditional Chinese encodings and charsets */ +static struct prt_ps_encoding_S tc_encodings[] = +{ + {"iso-2022", NULL, (CS_CNS_PLANE_1|CS_CNS_PLANE_2)}, + {"euc-tw", "EUC", CS_CNS_PLANE_1_2}, + {"big5", "B5", (CS_B5|CS_ETEN|CS_HK_GCCS|CS_HK_SCS| + CS_HK_SCS_ETEN|CS_MTHKL|CS_MTHKS|CS_DLHKL| + CS_DLHKS)}, + {"cp950", "B5", CS_B5}, + {"ucs-2", "UCS2", CS_TC_ISO10646}, + {"utf-8", "UTF8", CS_TC_ISO10646}, + {"utf-16", "UTF16", CS_TC_ISO10646}, + {"utf-32", "UTF32", CS_TC_ISO10646} +}; +static struct prt_ps_charset_S tc_charsets[] = +{ + {"CNS_1992_1", "CNS1", CS_CNS_PLANE_1}, + {"CNS_1992_2", "CNS2", CS_CNS_PLANE_2}, + {"CNS_1993", "CNS", CS_CNS_PLANE_1_2}, + {"BIG5", NULL, CS_B5}, + {"CP950", NULL, CS_B5}, + {"ETEN", "ETen", CS_ETEN}, + {"HK_GCCS", "HKgccs", CS_HK_GCCS}, + {"SCS", "HKscs", CS_HK_SCS}, + {"SCS_ETEN", "ETHK", CS_HK_SCS_ETEN}, + {"MTHKL", "HKm471", CS_MTHKL}, + {"MTHKS", "HKm314", CS_MTHKS}, + {"DLHKL", "HKdla", CS_DLHKL}, + {"DLHKS", "HKdlb", CS_DLHKS}, + {"ISO10646", "UniCNS", CS_TC_ISO10646} +}; + +#define CS_KR_X_1992 (0x01) +#define CS_KR_MAC (0x02) +#define CS_KR_X_1992_MS (0x04) +#define CS_KR_ISO10646 (0x08) + +/* Korean encodings and charsets */ +static struct prt_ps_encoding_S k_encodings[] = +{ + {"iso-2022-kr", NULL, CS_KR_X_1992}, + {"euc-kr", "EUC", (CS_KR_X_1992|CS_KR_MAC)}, + {"johab", "Johab", CS_KR_X_1992}, + {"cp1361", "Johab", CS_KR_X_1992}, + {"uhc", "UHC", CS_KR_X_1992_MS}, + {"cp949", "UHC", CS_KR_X_1992_MS}, + {"ucs-2", "UCS2", CS_KR_ISO10646}, + {"utf-8", "UTF8", CS_KR_ISO10646} +}; +static struct prt_ps_charset_S k_charsets[] = +{ + {"KS_X_1992", "KSC", CS_KR_X_1992}, + {"CP1361", "KSC", CS_KR_X_1992}, + {"MAC", "KSCpc", CS_KR_MAC}, + {"MSWINDOWS", "KSCms", CS_KR_X_1992_MS}, + {"CP949", "KSCms", CS_KR_X_1992_MS}, + {"WANSUNG", "KSCms", CS_KR_X_1992_MS}, + {"ISO10646", "UniKS", CS_KR_ISO10646} +}; + +/* Collections of encodings and charsets for multi-byte printing */ +struct prt_ps_mbfont_S +{ + int num_encodings; + struct prt_ps_encoding_S *encodings; + int num_charsets; + struct prt_ps_charset_S *charsets; + char *ascii_enc; + char *defcs; +}; + +static struct prt_ps_mbfont_S prt_ps_mbfonts[] = +{ + { + NUM_ELEMENTS(j_encodings), + j_encodings, + NUM_ELEMENTS(j_charsets), + j_charsets, + "jis_roman", + "JIS_X_1983" + }, + { + NUM_ELEMENTS(sc_encodings), + sc_encodings, + NUM_ELEMENTS(sc_charsets), + sc_charsets, + "gb_roman", + "GB_2312-80" + }, + { + NUM_ELEMENTS(tc_encodings), + tc_encodings, + NUM_ELEMENTS(tc_charsets), + tc_charsets, + "cns_roman", + "BIG5" + }, + { + NUM_ELEMENTS(k_encodings), + k_encodings, + NUM_ELEMENTS(k_charsets), + k_charsets, + "ks_roman", + "KS_X_1992" + } +}; + struct prt_ps_resource_S { char_u name[64]; @@ -3803,25 +4024,29 @@ struct prt_ps_resource_S /* Types of PS resource file currently used */ #define PRT_RESOURCE_TYPE_PROCSET (0) #define PRT_RESOURCE_TYPE_ENCODING (1) +#define PRT_RESOURCE_TYPE_CMAP (2) /* The PS prolog file version number has to match - if the prolog file is * updated, increment the number in the file and here. Version checking was * added as of VIM 6.2. + * The CID prolog file version number behaves as per PS prolog. * Table of VIM and prolog versions: * - * VIM Prolog + * VIM Prolog CIDProlog * 6.2 1.3 - * 7.0 1.4 + * 7.0 1.4 1.0 */ #define PRT_PROLOG_VERSION ((char_u *)"1.4") +#define PRT_CID_PROLOG_VERSION ((char_u *)"1.0") /* String versions of PS resource types - indexed by constants above so don't * re-order! */ -static char *resource_types[] = +static char *prt_resource_types[] = { "procset", - "encoding" + "encoding", + "cmap" }; /* Strings to look for in a PS resource file */ @@ -3829,8 +4054,44 @@ static char *resource_types[] = #define PRT_RESOURCE_RESOURCE "Resource-" #define PRT_RESOURCE_PROCSET "ProcSet" #define PRT_RESOURCE_ENCODING "Encoding" -#define PRT_RESOURCE_TITLE "%%Title:" -#define PRT_RESOURCE_VERSION "%%Version:" +#define PRT_RESOURCE_CMAP "CMap" + + +/* Data for table based DSC comment recognition, easy to extend if VIM needs to + * read more comments. */ +#define PRT_DSC_MISC_TYPE (-1) +#define PRT_DSC_TITLE_TYPE (1) +#define PRT_DSC_VERSION_TYPE (2) +#define PRT_DSC_ENDCOMMENTS_TYPE (3) + +#define PRT_DSC_TITLE "%%Title:" +#define PRT_DSC_VERSION "%%Version:" +#define PRT_DSC_ENDCOMMENTS "%%EndComments:" + +struct prt_dsc_comment_S +{ + char_u *string; + int len; + int type; +}; + +struct prt_dsc_line_S +{ + int type; + char_u *string; + int len; +}; + + +#define SIZEOF_CSTR(s) (sizeof(s) - 1) +struct prt_dsc_comment_S prt_dsc_table[] = +{ + {PRT_DSC_TITLE, SIZEOF_CSTR(PRT_DSC_TITLE), PRT_DSC_TITLE_TYPE}, + {PRT_DSC_VERSION, SIZEOF_CSTR(PRT_DSC_VERSION), + PRT_DSC_VERSION_TYPE}, + {PRT_DSC_ENDCOMMENTS, SIZEOF_CSTR(PRT_DSC_ENDCOMMENTS), + PRT_DSC_ENDCOMMENTS_TYPE} +}; static void prt_write_file_raw_len __ARGS((char_u *buffer, int bytes)); static void prt_write_file __ARGS((char_u *buffer)); @@ -3854,13 +4115,24 @@ static void prt_dsc_text __ARGS((char *comment, char *text)); static void prt_dsc_ints __ARGS((char *comment, int count, int *ints)); static void prt_dsc_requirements __ARGS((int duplex, int tumble, int collate, int color, int num_copies)); static void prt_dsc_docmedia __ARGS((char *paper_name, double width, double height, double weight, char *colour, char *type)); -static void prt_dsc_resources __ARGS((char *comment, char *type, int count, char **strings)); +static void prt_dsc_resources __ARGS((char *comment, char *type, char *strings)); +static void prt_dsc_font_resource __ARGS((char *resource, struct prt_ps_font_S *ps_font)); static float to_device_units __ARGS((int idx, double physsize, int def_number)); static void prt_page_margins __ARGS((double width, double height, double *left, double *right, double *top, double *bottom)); static void prt_font_metrics __ARGS((int font_scale)); static int prt_get_cpl __ARGS((void)); static int prt_get_lpp __ARGS((void)); static int prt_add_resource __ARGS((struct prt_ps_resource_S *resource)); +static int prt_resfile_next_line __ARGS((void)); +static int prt_resfile_strncmp __ARGS((int offset, char *string, int len)); +static int prt_resfile_skip_nonws __ARGS((int offset)); +static int prt_resfile_skip_ws __ARGS((int offset)); +static int prt_next_dsc __ARGS((struct prt_dsc_line_S *p_dsc_line)); +#ifdef FEAT_MBYTE +static void prt_def_cidfont __ARGS((char *new_name, int height, char *cidfont)); +static int prt_match_encoding __ARGS((char *p_encoding, struct prt_ps_mbfont_S *p_cmap, struct prt_ps_encoding_S **pp_mbenc)); +static int prt_match_charset __ARGS((char *p_charset, struct prt_ps_mbfont_S *p_cmap, struct prt_ps_charset_S **pp_mbchar)); +#endif /* * Variables for the output PostScript file. @@ -3905,8 +4177,9 @@ static int prt_do_bgcol; static int prt_bgcol; static int prt_new_bgcol; static int prt_attribute_change; -static int prt_text_count; +static float prt_text_run; static int prt_page_num; +static int prt_bufsiz; /* * Variables controlling physical printing. @@ -3927,6 +4200,15 @@ static garray_T prt_ps_buffer; # ifdef FEAT_MBYTE static int prt_do_conv; static vimconv_T prt_conv; + +static int prt_out_mbyte; +static int prt_custom_cmap; +static char prt_cmap[80]; +static int prt_use_courier; +static int prt_in_ascii; +static int prt_half_width; +static char *prt_ascii_encoding; +static char_u prt_hexchar[] = "0123456789abcdef"; # endif static void @@ -3995,7 +4277,7 @@ prt_write_boolean(b) } /* - * Write a line to define the font. + * Write PostScript to re-encode and define the font. */ static void prt_def_font(new_name, encoding, height, font) @@ -4004,13 +4286,51 @@ prt_def_font(new_name, encoding, height, font) int height; char *font; { - sprintf((char *)prt_line_buffer, "/_%s /VIM-%s /%s ref\n", new_name, encoding, font); + sprintf((char *)prt_line_buffer, "/_%s /VIM-%s /%s ref\n", + new_name, encoding, font); prt_write_file(prt_line_buffer); +#ifdef FEAT_MBYTE + if (prt_out_mbyte) + sprintf((char *)prt_line_buffer, "/%s %d %f /_%s sffs\n", + new_name, height, 500./prt_ps_courier_font.wx, new_name); + else +#endif sprintf((char *)prt_line_buffer, "/%s %d /_%s ffs\n", new_name, height, new_name); prt_write_file(prt_line_buffer); } +#ifdef FEAT_MBYTE +/* + * Write a line to define the CID font. + */ + static void +prt_def_cidfont(new_name, height, cidfont) + char *new_name; + int height; + char *cidfont; +{ + sprintf((char *)prt_line_buffer, "/_%s /%s[/%s] vim_composefont\n", + new_name, prt_cmap, cidfont); + prt_write_file(prt_line_buffer); + sprintf((char *)prt_line_buffer, "/%s %d /_%s ffs\n", new_name, height, + new_name); + prt_write_file(prt_line_buffer); +} + +/* + * Write a line to define a duplicate of a CID font + */ + static void +prt_dup_cidfont(original_name, new_name) + char *original_name; + char *new_name; +{ + sprintf((char *)prt_line_buffer, "/%s %s d\n", new_name, original_name); + prt_write_file(prt_line_buffer); +} +#endif + /* * Convert a real value into an integer and fractional part as integers, with * the fractional part being in the range [0,10^precision). The fractional part @@ -4110,7 +4430,7 @@ prt_flush_buffer() } /* Size of rect of background color on which text is printed */ - prt_write_real(prt_text_count * prt_char_width, 2); + prt_write_real(prt_text_run, 2); prt_write_real(prt_line_height, 2); /* Lastly add the color of the background */ @@ -4135,17 +4455,26 @@ prt_flush_buffer() prt_do_moveto = FALSE; } - /* Underlining is easy - just need the number of characters to - * print. */ - prt_write_real(prt_text_count * prt_char_width, 2); + /* Underline length of text run */ + prt_write_real(prt_text_run, 2); prt_write_string("ul\n"); } /* Draw the text * Note: we write text out raw - EBCDIC conversion is handled in the * PostScript world via the font encoding vector. */ - prt_write_string("("); +#ifdef FEAT_MBYTE + if (prt_out_mbyte) + prt_write_string("<"); + else +#endif + prt_write_string("("); prt_write_file_raw_len(prt_ps_buffer.ga_data, prt_ps_buffer.ga_len); - prt_write_string(")"); +#ifdef FEAT_MBYTE + if (prt_out_mbyte) + prt_write_string(">"); + else +#endif + prt_write_string(")"); /* Add a moveto if need be and use the appropriate show procedure */ if (prt_do_moveto) { @@ -4159,7 +4488,7 @@ prt_flush_buffer() prt_write_string("s\n"); ga_clear(&prt_ps_buffer); - ga_init2(&prt_ps_buffer, (int)sizeof(char), PRT_PS_DEFAULT_BUFFER_SIZE); + ga_init2(&prt_ps_buffer, (int)sizeof(char), prt_bufsiz); } } @@ -4198,17 +4527,155 @@ prt_find_resource(name, resource) #define PSLF (0x0a) #define PSCR (0x0d) -/* Very simple hand crafted parser to get the type, title, and version number of - * a PS resource file so the file details can be added to the DSC header - * comments. */ +/* Static buffer to read initial comments in a resource file, some can have a + * couple of KB of comments! */ +#define PRT_FILE_BUFFER_LEN (2048) +struct prt_resfile_buffer_S +{ + char_u buffer[PRT_FILE_BUFFER_LEN]; + int len; + int line_start; + int line_end; +}; + +static struct prt_resfile_buffer_S prt_resfile; + + static int +prt_resfile_next_line() +{ + int index; + + /* Move to start of next line and then find end of line */ + index = prt_resfile.line_end + 1; + while (index < prt_resfile.len) + { + if (prt_resfile.buffer[index] != PSLF && prt_resfile.buffer[index] + != PSCR) + break; + index++; + } + prt_resfile.line_start = index; + + while (index < prt_resfile.len) + { + if (prt_resfile.buffer[index] == PSLF || prt_resfile.buffer[index] + == PSCR) + break; + index++; + } + prt_resfile.line_end = index; + + return (index < prt_resfile.len); +} + + static int +prt_resfile_strncmp(offset, string, len) + int offset; + char *string; + int len; +{ + /* Force not equal if string is longer than remainder of line */ + if (len > (prt_resfile.line_end - (prt_resfile.line_start + offset))) + return 1; + + return STRNCMP(&prt_resfile.buffer[prt_resfile.line_start + offset], + string, len); +} + + static int +prt_resfile_skip_nonws(offset) + int offset; +{ + int index; + + index = prt_resfile.line_start + offset; + while (index < prt_resfile.line_end) + { + if (isspace(prt_resfile.buffer[index])) + return index - prt_resfile.line_start; + index++; + } + return -1; +} + + static int +prt_resfile_skip_ws(offset) + int offset; +{ + int index; + + index = prt_resfile.line_start + offset; + while (index < prt_resfile.line_end) + { + if (!isspace(prt_resfile.buffer[index])) + return index - prt_resfile.line_start; + index++; + } + return -1; +} + +/* prt_next_dsc() - returns detail on next DSC comment line found. Returns true + * if a DSC comment is found, else false */ + static int +prt_next_dsc(p_dsc_line) + struct prt_dsc_line_S *p_dsc_line; +{ + int comment; + int offset; + + /* Move to start of next line */ + if (!prt_resfile_next_line()) + return FALSE; + + /* DSC comments always start %% */ + if (prt_resfile_strncmp(0, "%%", 2) != 0) + return FALSE; + + /* Find type of DSC comment */ + for (comment = 0; comment < NUM_ELEMENTS(prt_dsc_table); comment++) + if (prt_resfile_strncmp(0, prt_dsc_table[comment].string, + prt_dsc_table[comment].len) == 0) + break; + + if (comment != NUM_ELEMENTS(prt_dsc_table)) + { + /* Return type of comment */ + p_dsc_line->type = prt_dsc_table[comment].type; + offset = prt_dsc_table[comment].len; + } + else + { + /* Unrecognised DSC comment, skip to ws after comment leader */ + p_dsc_line->type = PRT_DSC_MISC_TYPE; + offset = prt_resfile_skip_nonws(0); + if (offset == -1) + return FALSE; + } + + /* Skip ws to comment value */ + offset = prt_resfile_skip_ws(offset); + if (offset == -1) + return FALSE; + + p_dsc_line->string = &prt_resfile.buffer[prt_resfile.line_start + offset]; + p_dsc_line->len = prt_resfile.line_end - (prt_resfile.line_start + offset); + + return TRUE; +} + +/* Improved hand crafted parser to get the type, title, and version number of a + * PS resource file so the file details can be added to the DSC header comments. + */ static int prt_open_resource(resource) struct prt_ps_resource_S *resource; { + int offset; + int seen_all; + int seen_title; + int seen_version; FILE *fd_resource; - char_u buffer[128]; - char_u *ch = buffer; - char_u *ch2; + struct prt_dsc_line_S dsc_line; fd_resource = mch_fopen((char *)resource->filename, READBIN); if (fd_resource == NULL) @@ -4216,11 +4683,11 @@ prt_open_resource(resource) EMSG2(_("E624: Can't open file \"%s\""), resource->filename); return FALSE; } - vim_memset(buffer, NUL, sizeof(buffer)); + vim_memset(prt_resfile.buffer, NUL, PRT_FILE_BUFFER_LEN); /* Parse first line to ensure valid resource file */ - (void)fread((char *)buffer, sizeof(char_u), sizeof(buffer), - fd_resource); + prt_resfile.len = fread((char *)prt_resfile.buffer, sizeof(char_u), + PRT_FILE_BUFFER_LEN, fd_resource); if (ferror(fd_resource)) { EMSG2(_("E457: Can't read PostScript resource file \"%s\""), @@ -4229,7 +4696,15 @@ prt_open_resource(resource) return FALSE; } - if (STRNCMP(ch, PRT_RESOURCE_HEADER, STRLEN(PRT_RESOURCE_HEADER)) != 0) + prt_resfile.line_end = -1; + prt_resfile.line_start = 0; + if (!prt_resfile_next_line()) + return FALSE; + + offset = 0; + + if (prt_resfile_strncmp(offset, PRT_RESOURCE_HEADER, + STRLEN(PRT_RESOURCE_HEADER)) != 0) { EMSG2(_("E618: file \"%s\" is not a PostScript resource file"), resource->filename); @@ -4238,32 +4713,34 @@ prt_open_resource(resource) } /* Skip over any version numbers and following ws */ - ch += STRLEN(PRT_RESOURCE_HEADER); - while (!isspace(*ch)) - ch++; - while (isspace(*ch)) - ch++; + offset += STRLEN(PRT_RESOURCE_HEADER); + offset = prt_resfile_skip_nonws(offset); + if (offset == -1) + return FALSE; + offset = prt_resfile_skip_ws(offset); + if (offset == -1) + return FALSE; - if (STRNCMP(ch, PRT_RESOURCE_RESOURCE, STRLEN(PRT_RESOURCE_RESOURCE)) != 0) + if (prt_resfile_strncmp(offset, PRT_RESOURCE_RESOURCE, + STRLEN(PRT_RESOURCE_RESOURCE)) != 0) { EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"), resource->filename); fclose(fd_resource); return FALSE; } - ch += STRLEN(PRT_RESOURCE_RESOURCE); + offset += STRLEN(PRT_RESOURCE_RESOURCE); /* Decide type of resource in the file */ - if (STRNCMP(ch, PRT_RESOURCE_PROCSET, STRLEN(PRT_RESOURCE_PROCSET)) == 0) - { + if (prt_resfile_strncmp(offset, PRT_RESOURCE_PROCSET, + STRLEN(PRT_RESOURCE_PROCSET)) == 0) resource->type = PRT_RESOURCE_TYPE_PROCSET; - ch += STRLEN(PRT_RESOURCE_PROCSET); - } - else if (STRNCMP(ch, PRT_RESOURCE_ENCODING, STRLEN(PRT_RESOURCE_ENCODING)) == 0) - { + else if (prt_resfile_strncmp(offset, PRT_RESOURCE_ENCODING, + STRLEN(PRT_RESOURCE_ENCODING)) == 0) resource->type = PRT_RESOURCE_TYPE_ENCODING; - ch += STRLEN(PRT_RESOURCE_ENCODING); - } + else if (prt_resfile_strncmp(offset, PRT_RESOURCE_CMAP, + STRLEN(PRT_RESOURCE_CMAP)) == 0) + resource->type = PRT_RESOURCE_TYPE_CMAP; else { EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"), @@ -4272,53 +4749,50 @@ prt_open_resource(resource) return FALSE; } - /* Consume up to and including the CR/LF/CR_LF */ - while (*ch != PSCR && *ch != PSLF) - ch++; - while (*ch == PSCR || *ch == PSLF) - ch++; - - /* Match %%Title: */ - if (STRNCMP(ch, PRT_RESOURCE_TITLE, STRLEN(PRT_RESOURCE_TITLE)) != 0) - { - EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"), - resource->filename); - fclose(fd_resource); - return FALSE; - } - ch += STRLEN(PRT_RESOURCE_TITLE); - - /* Skip ws after %%Title: */ - while (isspace(*ch)) - ch++; - - /* Copy up to the CR/LF/CR_LF */ - ch2 = resource->title; - while (*ch != PSCR && *ch != PSLF) - *ch2++ = *ch++; - *ch2 = '\0'; - while (*ch == PSCR || *ch == PSLF) - ch++; - - /* Match %%Version: */ - if (STRNCMP(ch, PRT_RESOURCE_VERSION, STRLEN(PRT_RESOURCE_VERSION)) != 0) + /* Look for title and version of resource */ + resource->title[0] = '\0'; + resource->version[0] = '\0'; + seen_title = FALSE; + seen_version = FALSE; + seen_all = FALSE; + while (!seen_all && prt_next_dsc(&dsc_line)) + { + switch (dsc_line.type) + { + case PRT_DSC_TITLE_TYPE: + STRNCPY(resource->title, dsc_line.string, dsc_line.len); + resource->title[dsc_line.len] = '\0'; + seen_title = TRUE; + if (seen_version) + seen_all = TRUE; + break; + + case PRT_DSC_VERSION_TYPE: + STRNCPY(resource->version, dsc_line.string, dsc_line.len); + resource->version[dsc_line.len] = '\0'; + seen_version = TRUE; + if (seen_title) + seen_all = TRUE; + break; + + case PRT_DSC_ENDCOMMENTS_TYPE: + /* Wont find title or resource after this comment, stop searching */ + seen_all = TRUE; + break; + + case PRT_DSC_MISC_TYPE: + /* Not interested in whatever comment this line had */ + break; + } + } + + if (!seen_title || !seen_version) { EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"), resource->filename); fclose(fd_resource); return FALSE; } - ch += STRLEN(PRT_RESOURCE_VERSION); - - /* Skip ws after %%Version: */ - while (isspace(*ch)) - ch++; - - /* Copy up to the CR/LF/CR_LF */ - ch2 = resource->version; - while (*ch != PSCR && *ch != PSLF) - *ch2++ = *ch++; - *ch2 = '\0'; fclose(fd_resource); @@ -4398,27 +4872,33 @@ prt_dsc_ints(comment, count, ints) } static void -prt_dsc_resources(comment, type, count, strings) +prt_dsc_resources(comment, type, string) char *comment; /* if NULL add to previous */ char *type; - int count; - char **strings; + char *string; { - int i; - if (comment != NULL) sprintf((char *)prt_line_buffer, "%%%%%s: %s", comment, type); else sprintf((char *)prt_line_buffer, "%%%%+ %s", type); prt_write_file(prt_line_buffer); - for (i = 0; i < count; i++) - { - sprintf((char *)prt_line_buffer, " %s", strings[i]); - prt_write_file(prt_line_buffer); - } + sprintf((char *)prt_line_buffer, " %s\n", string); + prt_write_file(prt_line_buffer); +} - prt_write_string("\n"); + static void +prt_dsc_font_resource(resource, ps_font) + char *resource; + struct prt_ps_font_S *ps_font; +{ + int i; + + prt_dsc_resources(resource, "font", + ps_font->ps_fontname[PRT_PS_FONT_ROMAN]); + for (i = PRT_PS_FONT_BOLD ; i <= PRT_PS_FONT_BOLDOBLIQUE ; i++) + if (ps_font->ps_fontname[i] != NULL) + prt_dsc_resources(NULL, "font", ps_font->ps_fontname[i]); } static void @@ -4489,6 +4969,22 @@ prt_dsc_docmedia(paper_name, width, height, weight, colour, type) mch_print_cleanup() { #ifdef FEAT_MBYTE + if (prt_out_mbyte) + { + int i; + + /* Free off all CID font names created, but first clear duplicate + * pointers to the same string (when the same font is used for more than + * one style). + */ + for (i = PRT_PS_FONT_ROMAN; i <= PRT_PS_FONT_BOLDOBLIQUE; i++) + { + if (prt_ps_mb_font.ps_fontname[i] != NULL) + vim_free(prt_ps_mb_font.ps_fontname[i]); + prt_ps_mb_font.ps_fontname[i] = NULL; + } + } + if (prt_do_conv) { convert_setup(&prt_conv, NULL, NULL); @@ -4570,7 +5066,7 @@ prt_font_metrics(font_scale) int font_scale; { prt_line_height = (float)font_scale; - prt_char_width = (float)PRT_PS_FONT_TO_USER(font_scale, prt_ps_font.wx); + prt_char_width = (float)PRT_PS_FONT_TO_USER(font_scale, prt_ps_font->wx); } @@ -4580,6 +5076,13 @@ prt_get_cpl() if (prt_use_number()) { prt_number_width = PRINT_NUMBER_WIDTH * prt_char_width; +#ifdef FEAT_MBYTE + /* If we are outputting multi-byte characters then line numbers will be + * printed with half width characters + */ + if (prt_out_mbyte) + prt_number_width /= 2; +#endif prt_left_margin += prt_number_width; } else @@ -4588,6 +5091,24 @@ prt_get_cpl() return (int)((prt_right_margin - prt_left_margin) / prt_char_width); } + static int +prt_build_cid_fontname(font, name, name_len) + int font; + char *name; + int name_len; +{ + char *fontname; + + fontname = alloc(name_len + 1); + if (fontname == NULL) + return FALSE; + STRNCPY(fontname, name, name_len); + fontname[name_len] = '\0'; + prt_ps_mb_font.ps_fontname[font] = fontname; + + return TRUE; +} + /* * Get number of lines of text that fit on a page (excluding the header). */ @@ -4602,12 +5123,12 @@ prt_get_lpp() * case where the font height can exceed the line height. */ prt_bgcol_offset = (float)PRT_PS_FONT_TO_USER(prt_line_height, - prt_ps_font.bbox_min_y); - if ((prt_ps_font.bbox_max_y - prt_ps_font.bbox_min_y) < 1000.0) + prt_ps_font->bbox_min_y); + if ((prt_ps_font->bbox_max_y - prt_ps_font->bbox_min_y) < 1000.0) { prt_bgcol_offset -= (float)PRT_PS_FONT_TO_USER(prt_line_height, - (1000.0 - (prt_ps_font.bbox_max_y - - prt_ps_font.bbox_min_y)) / 2); + (1000.0 - (prt_ps_font->bbox_max_y - + prt_ps_font->bbox_min_y)) / 2); } /* Get height for topmost line based on background rect offset. */ @@ -4622,6 +5143,61 @@ prt_get_lpp() return lpp - prt_header_height(); } +#ifdef FEAT_MBYTE + static int +prt_match_encoding(p_encoding, p_cmap, pp_mbenc) + char *p_encoding; + struct prt_ps_mbfont_S *p_cmap; + struct prt_ps_encoding_S **pp_mbenc; +{ + int mbenc; + int enc_len; + struct prt_ps_encoding_S *p_mbenc; + + *pp_mbenc = NULL; + /* Look for recognised encoding */ + enc_len = STRLEN(p_encoding); + p_mbenc = p_cmap->encodings; + for (mbenc = 0; mbenc < p_cmap->num_encodings; mbenc++) + { + if (STRNICMP(p_mbenc->encoding, p_encoding, enc_len) == 0) + { + *pp_mbenc = p_mbenc; + return TRUE; + } + p_mbenc++; + } + return FALSE; +} + + static int +prt_match_charset(p_charset, p_cmap, pp_mbchar) + char *p_charset; + struct prt_ps_mbfont_S *p_cmap; + struct prt_ps_charset_S **pp_mbchar; +{ + int mbchar; + int char_len; + struct prt_ps_charset_S *p_mbchar; + + /* Look for recognised character set, using default if one is not given */ + if (*p_charset == NUL) + p_charset = p_cmap->defcs; + char_len = STRLEN(p_charset); + p_mbchar = p_cmap->charsets; + for (mbchar = 0; mbchar < p_cmap->num_charsets; mbchar++) + { + if (STRNICMP(p_mbchar->charset, p_charset, char_len) == 0) + { + *pp_mbchar = p_mbchar; + return TRUE; + } + p_mbchar++; + } + return FALSE; +} +#endif + /*ARGSUSED*/ int mch_print_init(psettings, jobname, forceit) @@ -4638,6 +5214,14 @@ mch_print_init(psettings, jobname, forceit) double right; double top; double bottom; +#ifdef FEAT_MBYTE + int cmap; + int pmcs_len; + char_u *p_encoding; + struct prt_ps_encoding_S *p_mbenc; + struct prt_ps_encoding_S *p_mbenc_first; + struct prt_ps_charset_S *p_mbchar; +#endif #if 0 /* @@ -4658,6 +5242,131 @@ mch_print_init(psettings, jobname, forceit) #endif /* + * Set up font and encoding. + */ +#ifdef FEAT_MBYTE + p_encoding = enc_skip(p_penc); + if (*p_encoding == NUL) + p_encoding = enc_skip(p_enc); + + /* Look for recognised multi-byte coding, and if the charset is recognised. + * This is to cope with the fact that various unicode encodings are + * supported in more than one of CJK. */ + p_mbenc = NULL; + p_mbenc_first = NULL; + p_mbchar = NULL; + for (cmap = 0; cmap < NUM_ELEMENTS(prt_ps_mbfonts); cmap++) + if (prt_match_encoding(p_encoding, &prt_ps_mbfonts[cmap], &p_mbenc)) + { + if (p_mbenc_first == NULL) + p_mbenc_first = p_mbenc; + if (prt_match_charset(p_pmcs, &prt_ps_mbfonts[cmap], &p_mbchar)) + break; + } + + /* Use first encoding matched if no charset matched */ + if (p_mbchar == NULL && p_mbenc_first != NULL) + p_mbenc = p_mbenc_first; + + prt_out_mbyte = (p_mbenc != NULL); + if (prt_out_mbyte) + { + /* Build CMap name - will be same for all multi-byte fonts used */ + prt_cmap[0] = '\0'; + + prt_custom_cmap = prt_out_mbyte && p_mbchar == NULL; + + if (!prt_custom_cmap) + { + /* Check encoding and character set are compatible */ + if ((p_mbenc->needs_charset&p_mbchar->has_charset) == 0) + { + EMSG(_("E673: Incompatible multi-byte encoding and character set.")); + return FALSE; + } + + /* Add charset name if not empty */ + if (p_mbchar->cmap_charset != NULL) + { + STRCAT(prt_cmap, p_mbchar->cmap_charset); + STRCAT(prt_cmap, "-"); + } + } + else + { + /* Add custom CMap character set name */ + pmcs_len = STRLEN(p_pmcs); + if (pmcs_len == 0) + { + EMSG(_("E674: printmbcharset cannot be empty with multi-byte encoding.")); + return FALSE; + } + STRNCPY(prt_cmap, p_pmcs, STRLEN(p_pmcs)); + prt_cmap[pmcs_len] = '\0'; + STRCAT(prt_cmap, "-"); + } + + /* CMap name ends with (optional) encoding name and -H for horizontal */ + if (p_mbenc->cmap_encoding != NULL) + { + STRCAT(prt_cmap, p_mbenc->cmap_encoding); + STRCAT(prt_cmap, "-"); + } + STRCAT(prt_cmap, "H"); + + if (!mbfont_opts[OPT_MBFONT_REGULAR].present) + { + EMSG(_("E675: No default font specfifed for multi-byte printing.")); + return FALSE; + } + + /* Derive CID font names with fallbacks if not defined */ + if (!prt_build_cid_fontname(PRT_PS_FONT_ROMAN, + mbfont_opts[OPT_MBFONT_REGULAR].string, + mbfont_opts[OPT_MBFONT_REGULAR].strlen)) + return FALSE; + if (mbfont_opts[OPT_MBFONT_BOLD].present) + if (!prt_build_cid_fontname(PRT_PS_FONT_BOLD, + mbfont_opts[OPT_MBFONT_BOLD].string, + mbfont_opts[OPT_MBFONT_BOLD].strlen)) + return FALSE; + if (mbfont_opts[OPT_MBFONT_OBLIQUE].present) + if (!prt_build_cid_fontname(PRT_PS_FONT_OBLIQUE, + mbfont_opts[OPT_MBFONT_OBLIQUE].string, + mbfont_opts[OPT_MBFONT_OBLIQUE].strlen)) + return FALSE; + if (mbfont_opts[OPT_MBFONT_BOLDOBLIQUE].present) + if (!prt_build_cid_fontname(PRT_PS_FONT_BOLDOBLIQUE, + mbfont_opts[OPT_MBFONT_BOLDOBLIQUE].string, + mbfont_opts[OPT_MBFONT_BOLDOBLIQUE].strlen)) + return FALSE; + + /* Check if need to use Courier for ASCII code range, and if so pick up + * the encoding to use */ + prt_use_courier = mbfont_opts[OPT_MBFONT_USECOURIER].present && + (TOLOWER_ASC(mbfont_opts[OPT_MBFONT_USECOURIER].string[0]) == 'y'); + if (prt_use_courier) + { + /* Use national ASCII variant unless ASCII wanted */ + if (mbfont_opts[OPT_MBFONT_ASCII].present && + (TOLOWER_ASC(mbfont_opts[OPT_MBFONT_ASCII].string[0]) == 'y')) + prt_ascii_encoding = "ascii"; + else + prt_ascii_encoding = prt_ps_mbfonts[cmap].ascii_enc; + } + + prt_ps_font = &prt_ps_mb_font; + } + else +#endif + { +#ifdef FEAT_MBYTE + prt_use_courier = FALSE; +#endif + prt_ps_font = &prt_ps_courier_font; + } + + /* * Find the size of the paper and set the margins. */ prt_portrait = (!printer_opts[OPT_PRINT_PORTRAIT].present @@ -4805,7 +5514,12 @@ mch_print_init(psettings, jobname, forceit) return FAIL; } - ga_init2(&prt_ps_buffer, (int)sizeof(char), PRT_PS_DEFAULT_BUFFER_SIZE); + prt_bufsiz = psettings->chars_per_line; +#ifdef FEAT_MBYTE + if (prt_out_mbyte) + prt_bufsiz *= 2; +#endif + ga_init2(&prt_ps_buffer, (int)sizeof(char), prt_bufsiz); prt_page_num = 0; @@ -4827,7 +5541,6 @@ prt_add_resource(resource) { FILE* fd_resource; char_u resource_buffer[512]; - char *resource_name[1]; size_t bytes_read; fd_resource = mch_fopen((char *)resource->filename, READBIN); @@ -4836,9 +5549,8 @@ prt_add_resource(resource) EMSG2(_("E456: Can't open file \"%s\""), resource->filename); return FALSE; } - resource_name[0] = (char *)resource->title; prt_dsc_resources("BeginResource", - resource_types[resource->type], 1, resource_name); + prt_resource_types[resource->type], resource->title); prt_dsc_textline("BeginDocument", (char *)resource->filename); @@ -4878,7 +5590,6 @@ mch_print_begin(psettings) time_t now; int bbox[4]; char *p_time; - char *resource[1]; double left; double right; double top; @@ -4888,7 +5599,8 @@ mch_print_begin(psettings) char_u buffer[256]; char_u *p_encoding; #ifdef FEAT_MBYTE - int props; + struct prt_ps_resource_S res_cidfont; + struct prt_ps_resource_S res_cmap; #endif /* @@ -4896,8 +5608,9 @@ mch_print_begin(psettings) */ prt_dsc_start(); prt_dsc_textline("Title", (char *)psettings->jobname); - /* TODO - platform dependent user name retrieval */ - prt_dsc_textline("For", "Unknown"); + if (!get_user_name(buffer, 256)) + STRCPY(buffer, "Unknown"); + prt_dsc_textline("For", buffer); prt_dsc_textline("Creator", VIM_VERSION_LONG); /* Note: to ensure Clean8bit I don't think we can use LC_TIME */ now = time(NULL); @@ -4946,10 +5659,22 @@ mch_print_begin(psettings) prt_mediasize[prt_media].width, prt_mediasize[prt_media].height, (double)0, NULL, NULL); - prt_dsc_resources("DocumentNeededResources", "font", 4, - prt_ps_font.ps_fontname); + /* Define fonts needed */ +#ifdef FEAT_MBYTE + if (!prt_out_mbyte || prt_use_courier) +#endif + prt_dsc_font_resource("DocumentNeededResources", &prt_ps_courier_font); +#ifdef FEAT_MBYTE + if (prt_out_mbyte) + { + prt_dsc_font_resource((prt_use_courier ? NULL + : "DocumentNeededResources"), &prt_ps_mb_font); + if (!prt_custom_cmap) + prt_dsc_resources(NULL, "cmap", prt_cmap); + } +#endif - /* Search for external resources we supply */ + /* Search for external resources VIM supplies */ if (!prt_find_resource("prolog", &res_prolog)) { EMSG(_("E456: Can't find PostScript resource file \"prolog.ps\"")); @@ -4959,66 +5684,139 @@ mch_print_begin(psettings) return FALSE; if (!prt_check_resource(&res_prolog, PRT_PROLOG_VERSION)) return FALSE; +#ifdef FEAT_MBYTE + if (prt_out_mbyte) + { + /* Look for required version of multi-byte printing procset */ + if (!prt_find_resource("cidfont", &res_cidfont)) + { + EMSG(_("E456: Can't find PostScript resource file \"cidfont.ps\"")); + return FALSE; + } + if (!prt_open_resource(&res_cidfont)) + return FALSE; + if (!prt_check_resource(&res_cidfont, PRT_CID_PROLOG_VERSION)) + return FALSE; + } +#endif + /* Find an encoding to use for printing. * Check 'printencoding'. If not set or not found, then use 'encoding'. If * that cannot be found then default to "latin1". * Note: VIM specific encoding header is always skipped. */ #ifdef FEAT_MBYTE - props = enc_canon_props(p_enc); -#endif - p_encoding = enc_skip(p_penc); - if (*p_encoding == NUL - || !prt_find_resource((char *)p_encoding, &res_encoding)) + if (!prt_out_mbyte) { - /* 'printencoding' not set or not supported - find alternate */ -#ifdef FEAT_MBYTE - p_encoding = enc_skip(p_enc); - if (!(props & ENC_8BIT) - || !prt_find_resource((char *)p_encoding, &res_encoding)) - { - /* 8-bit 'encoding' is not supported */ #endif - /* Use latin1 as default printing encoding */ - p_encoding = (char_u *)"latin1"; - if (!prt_find_resource((char *)p_encoding, &res_encoding)) - { - EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), - p_encoding); - return FALSE; - } + p_encoding = enc_skip(p_penc); + if (*p_encoding == NUL + || !prt_find_resource((char *)p_encoding, &res_encoding)) + { + /* 'printencoding' not set or not supported - find alternate */ #ifdef FEAT_MBYTE - } + int props; + + p_encoding = enc_skip(p_enc); + props = enc_canon_props(p_encoding); + if (!(props & ENC_8BIT) + || !prt_find_resource((char *)p_encoding, &res_encoding)) + /* 8-bit 'encoding' is not supported */ #endif - } - if (!prt_open_resource(&res_encoding)) - return FALSE; - /* For the moment there are no checks on encoding resource files to perform */ + { + /* Use latin1 as default printing encoding */ + p_encoding = (char_u *)"latin1"; + if (!prt_find_resource((char *)p_encoding, &res_encoding)) + { + EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), + p_encoding); + return FALSE; + } + } + } + if (!prt_open_resource(&res_encoding)) + return FALSE; + /* For the moment there are no checks on encoding resource files to + * perform */ #ifdef FEAT_MBYTE - /* Set up encoding conversion if starting from multi-byte */ - props = enc_canon_props(p_enc); - if (!(props & ENC_8BIT)) + } + else { + p_encoding = enc_skip(p_penc); + if (*p_encoding == NUL) + p_encoding = enc_skip(p_enc); + if (prt_use_courier) + { + /* Include ASCII range encoding vector */ + if (!prt_find_resource(prt_ascii_encoding, &res_encoding)) + { + EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), + prt_ascii_encoding); + return FALSE; + } + if (!prt_open_resource(&res_encoding)) + return FALSE; + /* For the moment there are no checks on encoding resource files to + * perform */ + } + } + + 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 from multi-byte to \"%s\" encoding"), + EMSG2(_("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; + + if (prt_out_mbyte && prt_custom_cmap) + { + /* Find user supplied CMap */ + if (!prt_find_resource(prt_cmap, &res_cmap)) + { + EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), + prt_cmap); + return FALSE; + } + if (!prt_open_resource(&res_cmap)) + return FALSE; + } #endif /* List resources supplied */ - resource[0] = (char *)buffer; STRCPY(buffer, res_prolog.title); STRCAT(buffer, " "); STRCAT(buffer, res_prolog.version); - prt_dsc_resources("DocumentSuppliedResources", "procset", 1, resource); - STRCPY(buffer, res_encoding.title); - STRCAT(buffer, " "); - STRCAT(buffer, res_encoding.version); - prt_dsc_resources(NULL, "encoding", 1, resource); + prt_dsc_resources("DocumentSuppliedResources", "procset", buffer); +#ifdef FEAT_MBYTE + if (prt_out_mbyte) + { + STRCPY(buffer, res_cidfont.title); + STRCAT(buffer, " "); + STRCAT(buffer, res_cidfont.version); + prt_dsc_resources(NULL, "procset", buffer); + + if (prt_custom_cmap) + { + STRCPY(buffer, res_cmap.title); + STRCAT(buffer, " "); + STRCAT(buffer, res_cmap.version); + prt_dsc_resources(NULL, "cmap", buffer); + } + } + if (!prt_out_mbyte || prt_use_courier) +#endif + { + STRCPY(buffer, res_encoding.title); + STRCAT(buffer, " "); + STRCAT(buffer, res_encoding.version); + prt_dsc_resources(NULL, "encoding", buffer); + } prt_dsc_requirements(prt_duplex, prt_tumble, prt_collate, #ifdef FEAT_SYN_HL psettings->do_syntax @@ -5034,7 +5832,20 @@ mch_print_begin(psettings) prt_dsc_noarg("BeginDefaults"); /* List font resources most likely common to all pages */ - prt_dsc_resources("PageResources", "font", 4, prt_ps_font.ps_fontname); +#ifdef FEAT_MBYTE + if (!prt_out_mbyte || prt_use_courier) +#endif + prt_dsc_font_resource("PageResources", &prt_ps_courier_font); +#ifdef FEAT_MBYTE + if (prt_out_mbyte) + { + prt_dsc_font_resource((prt_use_courier ? NULL : "PageResources"), + &prt_ps_mb_font); + if (!prt_custom_cmap) + prt_dsc_resources(NULL, "cmap", prt_cmap); + } +#endif + /* Paper will be used for all pages */ prt_dsc_textline("PageMedia", prt_mediasize[prt_media].name); @@ -5045,13 +5856,27 @@ mch_print_begin(psettings) */ prt_dsc_noarg("BeginProlog"); - /* For now there is just the one procset to be included in the PS file. */ + /* Add required procsets - NOTE: order is important! */ if (!prt_add_resource(&res_prolog)) return FALSE; +#ifdef FEAT_MBYTE + if (prt_out_mbyte) + { + /* Add CID font procset, and any user supplied CMap */ + if (!prt_add_resource(&res_cidfont)) + return FALSE; + if (prt_custom_cmap && !prt_add_resource(&res_cmap)) + return FALSE; + } +#endif - /* There will be only one font encoding to be included in the PS file. */ - if (!prt_add_resource(&res_encoding)) - return FALSE; +#ifdef FEAT_MBYTE + if (!prt_out_mbyte || prt_use_courier) +#endif + /* There will be only one Roman font encoding to be included in the PS + * file. */ + if (!prt_add_resource(&res_encoding)) + return FALSE; prt_dsc_noarg("EndProlog"); @@ -5074,28 +5899,93 @@ mch_print_begin(psettings) prt_write_string("c\n"); /* Font resource inclusion and definition */ - prt_dsc_resources("IncludeResource", "font", 1, - &prt_ps_font.ps_fontname[PRT_PS_FONT_ROMAN]); - prt_def_font("F0", (char *)p_encoding, (int)prt_line_height, - prt_ps_font.ps_fontname[PRT_PS_FONT_ROMAN]); - prt_dsc_resources("IncludeResource", "font", 1, - &prt_ps_font.ps_fontname[PRT_PS_FONT_BOLD]); - prt_def_font("F1", (char *)p_encoding, (int)prt_line_height, - prt_ps_font.ps_fontname[PRT_PS_FONT_BOLD]); - prt_dsc_resources("IncludeResource", "font", 1, - &prt_ps_font.ps_fontname[PRT_PS_FONT_OBLIQUE]); - prt_def_font("F2", (char *)p_encoding, (int)prt_line_height, - prt_ps_font.ps_fontname[PRT_PS_FONT_OBLIQUE]); - prt_dsc_resources("IncludeResource", "font", 1, - &prt_ps_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE]); - prt_def_font("F3", (char *)p_encoding, (int)prt_line_height, - prt_ps_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE]); +#ifdef FEAT_MBYTE + if (!prt_out_mbyte || prt_use_courier) + { + /* When using Courier for ASCII range when printing multi-byte, need to + * pick up ASCII encoding to use with it. */ + if (prt_use_courier) + p_encoding = prt_ascii_encoding; +#endif + prt_dsc_resources("IncludeResource", "font", + prt_ps_courier_font.ps_fontname[PRT_PS_FONT_ROMAN]); + prt_def_font("F0", (char *)p_encoding, (int)prt_line_height, + prt_ps_courier_font.ps_fontname[PRT_PS_FONT_ROMAN]); + prt_dsc_resources("IncludeResource", "font", + prt_ps_courier_font.ps_fontname[PRT_PS_FONT_BOLD]); + prt_def_font("F1", (char *)p_encoding, (int)prt_line_height, + prt_ps_courier_font.ps_fontname[PRT_PS_FONT_BOLD]); + prt_dsc_resources("IncludeResource", "font", + prt_ps_courier_font.ps_fontname[PRT_PS_FONT_OBLIQUE]); + prt_def_font("F2", (char *)p_encoding, (int)prt_line_height, + prt_ps_courier_font.ps_fontname[PRT_PS_FONT_OBLIQUE]); + prt_dsc_resources("IncludeResource", "font", + prt_ps_courier_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE]); + prt_def_font("F3", (char *)p_encoding, (int)prt_line_height, + prt_ps_courier_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE]); +#ifdef FEAT_MBYTE + } + if (prt_out_mbyte) + { + /* Define the CID fonts to be used in the job. Typically CJKV fonts do + * not have an italic form being a western style, so where no font is + * defined for these faces VIM falls back to an existing face. + * Note: if using Courier for the ASCII range then the printout will + * have bold/italic/bolditalic regardless of the setting of printmbfont. + */ + prt_dsc_resources("IncludeResource", "font", + prt_ps_mb_font.ps_fontname[PRT_PS_FONT_ROMAN]); + if (!prt_custom_cmap) + prt_dsc_resources("IncludeResource", "cmap", prt_cmap); + prt_def_cidfont("CF0", (int)prt_line_height, + prt_ps_mb_font.ps_fontname[PRT_PS_FONT_ROMAN]); + + if (prt_ps_mb_font.ps_fontname[PRT_PS_FONT_BOLD] != NULL) + { + prt_dsc_resources("IncludeResource", "font", + prt_ps_mb_font.ps_fontname[PRT_PS_FONT_BOLD]); + if (!prt_custom_cmap) + prt_dsc_resources("IncludeResource", "cmap", prt_cmap); + prt_def_cidfont("CF1", (int)prt_line_height, + prt_ps_mb_font.ps_fontname[PRT_PS_FONT_BOLD]); + } + else + /* Use ROMAN for BOLD */ + prt_dup_cidfont("CF0", "CF1"); + + if (prt_ps_mb_font.ps_fontname[PRT_PS_FONT_OBLIQUE] != NULL) + { + prt_dsc_resources("IncludeResource", "font", + prt_ps_mb_font.ps_fontname[PRT_PS_FONT_OBLIQUE]); + if (!prt_custom_cmap) + prt_dsc_resources("IncludeResource", "cmap", prt_cmap); + prt_def_cidfont("CF2", (int)prt_line_height, + prt_ps_mb_font.ps_fontname[PRT_PS_FONT_OBLIQUE]); + } + else + /* Use ROMAN for OBLIQUE */ + prt_dup_cidfont("CF0", "CF2"); + + if (prt_ps_mb_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE] != NULL) + { + prt_dsc_resources("IncludeResource", "font", + prt_ps_mb_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE]); + if (!prt_custom_cmap) + prt_dsc_resources("IncludeResource", "cmap", prt_cmap); + prt_def_cidfont("CF3", (int)prt_line_height, + prt_ps_mb_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE]); + } + else + /* Use BOLD for BOLDOBLIQUE */ + prt_dup_cidfont("CF1", "CF3"); + } +#endif /* Misc constant vars used for underlining and background rects */ prt_def_var("UO", PRT_PS_FONT_TO_USER(prt_line_height, - prt_ps_font.uline_offset), 2); + prt_ps_font->uline_offset), 2); prt_def_var("UW", PRT_PS_FONT_TO_USER(prt_line_height, - prt_ps_font.uline_width), 2); + prt_ps_font->uline_width), 2); prt_def_var("BO", prt_bgcol_offset, 2); prt_dsc_noarg("EndSetup"); @@ -5168,7 +6058,14 @@ mch_print_begin_page(str) prt_dsc_noarg("BeginPageSetup"); - prt_write_string("sv\n0 g\nF0 sf\n"); + prt_write_string("sv\n0 g\n"); +#ifdef FEAT_MBYTE + prt_in_ascii = !prt_out_mbyte; + if (prt_out_mbyte) + prt_write_string("CF0 sf\n"); + else +#endif + prt_write_string("F0 sf\n"); prt_fgcol = PRCOLOR_BLACK; prt_bgcol = PRCOLOR_WHITE; prt_font = PRT_PS_FONT_ROMAN; @@ -5213,6 +6110,9 @@ mch_print_start_line(margin, page_line) prt_attribute_change = TRUE; prt_need_moveto = TRUE; +#ifdef FEAT_MBYTE + prt_half_width = FALSE; +#endif } /*ARGSUSED*/ @@ -5224,6 +6124,68 @@ mch_print_text_out(p, len) int need_break; char_u ch; char_u ch_buff[8]; + float char_width; + float next_pos; +#ifdef FEAT_MBYTE + int in_ascii; + int half_width; +#endif + + char_width = prt_char_width; + +#ifdef FEAT_MBYTE + /* 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 + * in the ASCII range, and the origingal CID font for everything else. + * The problem is that GhostScript still (as of 8.13) does not support + * rearranged fonts even though they have been documented by Adobe for 7 + * years! If they ever do, a lot of this code will disappear. + */ + if (prt_use_courier) + { + in_ascii = (len == 1 && *p < 0x80); + if (prt_in_ascii) + { + if (!in_ascii) + { + /* No longer in ASCII range - need to switch font */ + prt_in_ascii = FALSE; + prt_need_font = TRUE; + prt_attribute_change = TRUE; + } + } + else if (in_ascii) + { + /* Now in ASCII range - need to switch font */ + prt_in_ascii = TRUE; + prt_need_font = TRUE; + prt_attribute_change = TRUE; + } + } + if (prt_out_mbyte) + { + half_width = ((*mb_ptr2cells)(p) == 1); + if (half_width) + char_width /= 2; + if (prt_half_width) + { + if (!half_width) + { + prt_half_width = FALSE; + prt_pos_x += prt_char_width/4; + prt_need_moveto = TRUE; + prt_attribute_change = TRUE; + } + } + else if (half_width) + { + prt_half_width = TRUE; + prt_pos_x += prt_char_width/4; + prt_need_moveto = TRUE; + prt_attribute_change = TRUE; + } + } +#endif /* Output any required changes to the graphics state, after flushing any * text buffered so far. @@ -5232,7 +6194,7 @@ mch_print_text_out(p, len) { prt_flush_buffer(); /* Reset count of number of chars that will be printed */ - prt_text_count = 0; + prt_text_run = 0; if (prt_need_moveto) { @@ -5244,10 +6206,15 @@ mch_print_text_out(p, len) } if (prt_need_font) { - prt_write_string("F"); - prt_write_int(prt_font); - prt_write_string("sf\n"); - prt_need_font = FALSE; +#ifdef FEAT_MBYTE + if (!prt_in_ascii) + prt_write_string("CF"); + else +#endif + prt_write_string("F"); + prt_write_int(prt_font); + prt_write_string("sf\n"); + prt_need_font = FALSE; } if (prt_need_fgcol) { @@ -5258,9 +6225,7 @@ mch_print_text_out(p, len) prt_write_real(r / 255.0, 3); if (r == g && g == b) - { prt_write_string("g\n"); - } else { prt_write_real(g / 255.0, 3); @@ -5295,46 +6260,64 @@ mch_print_text_out(p, len) if (p == NULL) p = (char_u *)""; } + + if (prt_out_mbyte) + { + /* Multi-byte character strings are represented more efficiently as hex + * strings when outputting clean 8 bit PS. + */ + do + { + ch = prt_hexchar[(*p) >> 4]; + ga_append(&prt_ps_buffer, ch); + ch = prt_hexchar[(*p) & 0xf]; + ga_append(&prt_ps_buffer, ch); + p++; + } + while (--len); + } + else #endif - /* Add next character to buffer of characters to output. - * Note: One printed character may require several PS characters to - * represent it, but we only count them as one printed character. - */ - ch = *p; - if (ch < 32 || ch == '(' || ch == ')' || ch == '\\') - { - /* Convert non-printing characters to either their escape or octal - * sequence, ensures PS sent over a serial line does not interfere with - * the comms protocol. - * Note: For EBCDIC we need to write out the escape sequences as ASCII - * codes! - * Note 2: Char codes < 32 are identical in EBCDIC and ASCII AFAIK! - */ - ga_append(&prt_ps_buffer, IF_EB('\\', 0134)); - switch (ch) - { - case BS: ga_append(&prt_ps_buffer, IF_EB('b', 0142)); break; - case TAB: ga_append(&prt_ps_buffer, IF_EB('t', 0164)); break; - case NL: ga_append(&prt_ps_buffer, IF_EB('n', 0156)); break; - case FF: ga_append(&prt_ps_buffer, IF_EB('f', 0146)); break; - case CAR: ga_append(&prt_ps_buffer, IF_EB('r', 0162)); break; - case '(': ga_append(&prt_ps_buffer, IF_EB('(', 0050)); break; - case ')': ga_append(&prt_ps_buffer, IF_EB(')', 0051)); break; - case '\\': ga_append(&prt_ps_buffer, IF_EB('\\', 0134)); break; - - default: - sprintf((char *)ch_buff, "%03o", (unsigned int)ch); + { + /* Add next character to buffer of characters to output. + * Note: One printed character may require several PS characters to + * represent it, but we only count them as one printed character. + */ + ch = *p; + if (ch < 32 || ch == '(' || ch == ')' || ch == '\\') + { + /* Convert non-printing characters to either their escape or octal + * sequence, ensures PS sent over a serial line does not interfere + * with the comms protocol. Note: For EBCDIC we need to write out + * the escape sequences as ASCII codes! + * Note 2: Char codes < 32 are identical in EBCDIC and ASCII AFAIK! + */ + ga_append(&prt_ps_buffer, IF_EB('\\', 0134)); + switch (ch) + { + case BS: ga_append(&prt_ps_buffer, IF_EB('b', 0142)); break; + case TAB: ga_append(&prt_ps_buffer, IF_EB('t', 0164)); break; + case NL: ga_append(&prt_ps_buffer, IF_EB('n', 0156)); break; + case FF: ga_append(&prt_ps_buffer, IF_EB('f', 0146)); break; + case CAR: ga_append(&prt_ps_buffer, IF_EB('r', 0162)); break; + case '(': ga_append(&prt_ps_buffer, IF_EB('(', 0050)); break; + case ')': ga_append(&prt_ps_buffer, IF_EB(')', 0051)); break; + case '\\': ga_append(&prt_ps_buffer, IF_EB('\\', 0134)); break; + + default: + sprintf((char *)ch_buff, "%03o", (unsigned int)ch); #ifdef EBCDIC - ebcdic2ascii(ch_buff, 3); + ebcdic2ascii(ch_buff, 3); #endif - ga_append(&prt_ps_buffer, ch_buff[0]); - ga_append(&prt_ps_buffer, ch_buff[1]); - ga_append(&prt_ps_buffer, ch_buff[2]); - break; - } + ga_append(&prt_ps_buffer, ch_buff[0]); + ga_append(&prt_ps_buffer, ch_buff[1]); + ga_append(&prt_ps_buffer, ch_buff[2]); + break; + } + } + else + ga_append(&prt_ps_buffer, ch); } - else - ga_append(&prt_ps_buffer, ch); #ifdef FEAT_MBYTE /* Need to free any translated characters */ @@ -5342,11 +6325,13 @@ mch_print_text_out(p, len) vim_free(p); #endif - prt_text_count++; - prt_pos_x += prt_char_width; + prt_text_run += char_width; + prt_pos_x += char_width; - /* The downside of fp - need a little tolerance in the right margin check */ - need_break = (prt_pos_x + prt_char_width > (prt_right_margin + 0.01)); + /* 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)); if (need_break) prt_flush_buffer(); diff --git a/src/ex_getln.c b/src/ex_getln.c index 140535efc..7d1e28250 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -80,6 +80,7 @@ static void correct_cmdspos __ARGS((int idx, int cells)); static void alloc_cmdbuff __ARGS((int len)); static int realloc_cmdbuff __ARGS((int len)); static void draw_cmdline __ARGS((int start, int len)); +static int cmdline_paste __ARGS((int regname, int literally)); #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) static void redrawcmd_preedit __ARGS((void)); #endif @@ -2536,6 +2537,102 @@ put_on_cmdline(str, len, redraw) return retval; } +/* + * paste a yank register into the command line. + * used by CTRL-R command in command-line mode + * insert_reg() can't be used here, because special characters from the + * register contents will be interpreted as commands. + * + * return FAIL for failure, OK otherwise + */ + static int +cmdline_paste(regname, literally) + int regname; + int literally; /* Insert text literally instead of "as typed" */ +{ + long i; + char_u *arg; + int allocated; + struct cmdline_info save_ccline; + + /* check for valid regname; also accept special characters for CTRL-R in + * the command line */ + if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W + && regname != Ctrl_A && !valid_yank_reg(regname, FALSE)) + return FAIL; + + /* A register containing CTRL-R can cause an endless loop. Allow using + * CTRL-C to break the loop. */ + line_breakcheck(); + if (got_int) + return FAIL; + +#ifdef FEAT_CLIPBOARD + regname = may_get_selection(regname); +#endif + + /* Need to save and restore ccline, because obtaining the "=" register may + * execute "normal :cmd" and overwrite it. */ + save_ccline = ccline; + ccline.cmdbuff = NULL; + ccline.cmdprompt = NULL; + i = get_spec_reg(regname, &arg, &allocated, TRUE); + ccline = save_ccline; + + if (i) + { + /* Got the value of a special register in "arg". */ + if (arg == NULL) + return FAIL; + cmdline_paste_str(arg, literally); + if (allocated) + vim_free(arg); + return OK; + } + + return cmdline_paste_reg(regname, literally); +} + +/* + * Put a string on the command line. + * When "literally" is TRUE, insert literally. + * When "literally" is FALSE, insert as typed, but don't leave the command + * line. + */ + void +cmdline_paste_str(s, literally) + char_u *s; + int literally; +{ + int c, cv; + + if (literally) + put_on_cmdline(s, -1, TRUE); + else + while (*s != NUL) + { + cv = *s; + if (cv == Ctrl_V && s[1]) + ++s; +#ifdef FEAT_MBYTE + if (has_mbyte) + { + c = mb_ptr2char(s); + s += mb_char2len(c); + } + else +#endif + c = *s++; + if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CAR || c == NL +#ifdef UNIX + || c == intr_char +#endif + || (c == Ctrl_BSL && *s == Ctrl_N)) + stuffcharReadbuff(Ctrl_V); + stuffcharReadbuff(c); + } +} + #ifdef FEAT_WILDMENU /* * Delete characters on the command line, from "from" to the current diff --git a/src/globals.h b/src/globals.h index 026a3fe79..83e6c4b96 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1102,6 +1102,30 @@ EXTERN option_table_T printer_opts[OPT_PRINT_NUM_OPTIONS] # define PRT_UNIT_MM 2 # define PRT_UNIT_POINT 3 # define PRT_UNIT_NAMES {"pc", "in", "mm", "pt"} + +# ifdef FEAT_MBYTE +# 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 +# +EXTERN option_table_T mbfont_opts[OPT_MBFONT_NUM_OPTIONS] +# ifdef DO_INIT + = +{ + {"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 +; +# endif #endif #ifdef FEAT_XCLIPBOARD diff --git a/src/if_mzsch.c b/src/if_mzsch.c index 377b5f755..57bc4de29 100644 --- a/src/if_mzsch.c +++ b/src/if_mzsch.c @@ -21,17 +21,6 @@ * 3. I don't use K&R-style functions. Anyway, MzScheme headers are ANSI. */ -/* TODO - * way to catch Vim errors (incl. verbose messages) - * libmzscheme.dll dynamic loading - * macros to pass modifiers (e.g. (browse edit)) - * opportunity to use shared mzscheme libraries on Unix - * event on-change-mode - * Scheme-driven coloring - * global exn-handler - * embed Read-Eval-Print-Loop - */ - #include "vim.h" #include "if_mzsch.h" @@ -44,7 +33,6 @@ typedef struct Scheme_Type tag; Scheme_Env *env; buf_T *buf; - Scheme_Object *text_objects; } vim_mz_buffer; #define INVALID_BUFFER_VALUE ((buf_T *)(-1)) @@ -2077,20 +2065,6 @@ win_T *get_valid_window(void *obj) return win; } -#if 0 - int -mzvim_bufferp(Scheme_Object *obj) -{ - return SCHEME_VIMBUFFERP(obj); -} - - int -mzvim_windowp(Scheme_Object *obj) -{ - return SCHEME_VIMWINDOWP(obj); -} -#endif - int mzthreads_allowed(void) { @@ -2215,14 +2189,6 @@ get_vim_curr_window(void) return (vim_mz_window *)curwin->mzscheme_ref; } -#if 0 - char * -mzscheme_version(void) -{ - return scheme_version(); -} -#endif - static void make_modules(Scheme_Env *env) { @@ -94,13 +94,10 @@ struct block_def static void shift_block __ARGS((oparg_T *oap, int amount)); static void block_insert __ARGS((oparg_T *oap, char_u *s, int b_insert, struct block_def*bdp)); #endif -static void get_yank_register __ARGS((int regname, int writing)); static int stuff_yank __ARGS((int, char_u *)); static void put_reedit_in_typebuf __ARGS((void)); static int put_in_typebuf __ARGS((char_u *s, int colon)); static void stuffescaped __ARGS((char_u *arg, int literally)); -static int get_spec_reg __ARGS((int regname, char_u **argp, int *allocated, int errmsg)); -static void cmdline_paste_str __ARGS((char_u *s, int literally)); #ifdef FEAT_MBYTE static void mb_adjust_opend __ARGS((oparg_T *oap)); #endif @@ -820,7 +817,7 @@ valid_yank_reg(regname, writing) * If regname is 0 and writing, use register 0 * If regname is 0 and reading, use previous register */ - static void + void get_yank_register(regname, writing) int regname; int writing; @@ -864,14 +861,12 @@ get_yank_register(regname, writing) y_previous = y_current; } -#ifdef FEAT_CLIPBOARD +#if defined(FEAT_CLIPBOARD) || defined(PROTO) /* * When "regname" is a clipboard register, obtain the selection. If it's not * available return zero, otherwise return "regname". */ -static int may_get_selection __ARGS((int regname)); - - static int + int may_get_selection(regname) int regname; { @@ -1347,7 +1342,7 @@ stuffescaped(arg, literally) /* * If "regname" is a special register, return a pointer to its value. */ - static int + int get_spec_reg(regname, argp, allocated, errmsg) int regname; char_u **argp; @@ -1426,47 +1421,20 @@ get_spec_reg(regname, argp, allocated, errmsg) } /* - * paste a yank register into the command line. - * used by CTRL-R command in command-line mode + * Paste a yank register into the command line. + * Only for non-special registers. + * Used by CTRL-R command in command-line mode * insert_reg() can't be used here, because special characters from the * register contents will be interpreted as commands. * * return FAIL for failure, OK otherwise */ int -cmdline_paste(regname, literally) +cmdline_paste_reg(regname, literally) int regname; int literally; /* Insert text literally instead of "as typed" */ { long i; - char_u *arg; - int allocated; - - /* check for valid regname; also accept special characters for CTRL-R in - * the command line */ - if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W - && regname != Ctrl_A && !valid_yank_reg(regname, FALSE)) - return FAIL; - - /* A register containing CTRL-R can cause an endless loop. Allow using - * CTRL-C to break the loop. */ - line_breakcheck(); - if (got_int) - return FAIL; - -#ifdef FEAT_CLIPBOARD - regname = may_get_selection(regname); -#endif - - if (get_spec_reg(regname, &arg, &allocated, TRUE)) - { - if (arg == NULL) - return FAIL; - cmdline_paste_str(arg, literally); - if (allocated) - vim_free(arg); - return OK; - } get_yank_register(regname, FALSE); if (y_current->y_array == NULL) @@ -1489,46 +1457,6 @@ cmdline_paste(regname, literally) return OK; } -/* - * Put a string on the command line. - * When "literally" is TRUE, insert literally. - * When "literally" is FALSE, insert as typed, but don't leave the command - * line. - */ - static void -cmdline_paste_str(s, literally) - char_u *s; - int literally; -{ - int c, cv; - - if (literally) - put_on_cmdline(s, -1, TRUE); - else - while (*s != NUL) - { - cv = *s; - if (cv == Ctrl_V && s[1]) - ++s; -#ifdef FEAT_MBYTE - if (has_mbyte) - { - c = mb_ptr2char(s); - s += mb_char2len(c); - } - else -#endif - c = *s++; - if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CAR || c == NL -#ifdef UNIX - || c == intr_char -#endif - || (c == Ctrl_BSL && *s == Ctrl_N)) - stuffcharReadbuff(Ctrl_V); - stuffcharReadbuff(c); - } -} - #if defined(FEAT_CLIPBOARD) || defined(PROTO) /* * Adjust the register name pointed to with "rp" for the clipboard being diff --git a/src/option.c b/src/option.c index 01609c29d..952a03e53 100644 --- a/src/option.c +++ b/src/option.c @@ -1678,6 +1678,24 @@ static struct vimoption {(char_u *)NULL, (char_u *)0L} #endif }, + {"printmbcharset", "pmbcs", P_STRING|P_VI_DEF, +#if defined(FEAT_POSTSCRIPT) && defined(FEAT_MBYTE) + (char_u *)&p_pmcs, PV_NONE, + {(char_u *)"", (char_u *)0L} +#else + (char_u *)NULL, PV_NONE, + {(char_u *)NULL, (char_u *)0L} +#endif + }, + {"printmbfont", "pmbfn", P_STRING|P_VI_DEF, +#if defined(FEAT_POSTSCRIPT) && defined(FEAT_MBYTE) + (char_u *)&p_pmfn, PV_NONE, + {(char_u *)"", (char_u *)0L} +#else + (char_u *)NULL, PV_NONE, + {(char_u *)NULL, (char_u *)0L} +#endif + }, {"printoptions", "popt", P_STRING|P_VI_DEF|P_COMMA|P_NODUP, #ifdef FEAT_PRINTER (char_u *)&p_popt, PV_NONE, @@ -5283,6 +5301,11 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf, #ifdef FEAT_PRINTER else if (varp == &p_popt) errmsg = parse_list_options(p_popt, printer_opts, OPT_PRINT_NUM_OPTIONS); + +# ifdef FEAT_MBYTE + else if (varp == &p_pmfn) + errmsg = parse_list_options(p_pmfn, mbfont_opts, OPT_MBFONT_NUM_OPTIONS); +# endif #endif #ifdef FEAT_LANGMAP diff --git a/src/option.h b/src/option.h index 0fa83a5eb..acb23de34 100644 --- a/src/option.h +++ b/src/option.h @@ -451,6 +451,10 @@ EXTERN char_u *p_pdev; /* 'printdevice' */ # ifdef FEAT_POSTSCRIPT EXTERN char_u *p_penc; /* 'printencoding' */ EXTERN char_u *p_pexpr; /* 'printexpr' */ +# ifdef FEAT_MBYTE +EXTERN char_u *p_pmfn; /* 'printmbfont' */ +EXTERN char_u *p_pmcs; /* 'printmbcharset' */ +# endif # endif EXTERN char_u *p_pfn; /* 'printfont' */ EXTERN char_u *p_popt; /* 'printoptions' */ diff --git a/src/os_mac.c b/src/os_mac.c index d38f12a61..d1eb03d9a 100644 --- a/src/os_mac.c +++ b/src/os_mac.c @@ -1301,27 +1301,27 @@ mch_copy_file_attribute(from, to) char_u *from; char_u *to; { - FSSpec frFSSpec; - FSSpec toFSSpec; - FInfo fndrInfo; - Str255 name; - ResType type; - ResType sink; - Handle resource; - short idxTypes; - short nbTypes; - short idxResources; - short nbResources; - short ID; - short frRFid; - short toRFid; - short attrs_orig; - short attrs_copy; - short temp; + FSSpec frFSSpec; + FSSpec toFSSpec; + FInfo fndrInfo; + Str255 name; + ResType type; + ResType sink; + Handle resource; + short idxTypes; + short nbTypes; + short idxResources; + short nbResources; + short ID; + short frRFid; + short toRFid; + short attrs_orig; + short attrs_copy; + short temp; /* TODO: Handle error */ - (void) GetFSSpecFromPath (from, &frFSSpec); - (void) GetFSSpecFromPath (to , &toFSSpec); + (void)GetFSSpecFromPath(from, &frFSSpec); + (void)GetFSSpecFromPath(to , &toFSSpec); /* Copy resource fork */ temp = 0; @@ -1332,51 +1332,51 @@ mch_copy_file_attribute(from, to) if (frRFid != -1) { FSpCreateResFile(&toFSSpec, 'TEXT', UNKNOWN_CREATOR, 0); - toRFid = FSpOpenResFile (&toFSSpec, fsRdWrPerm); + toRFid = FSpOpenResFile(&toFSSpec, fsRdWrPerm); - UseResFile (frRFid); + UseResFile(frRFid); nbTypes = Count1Types(); for (idxTypes = 1; idxTypes <= nbTypes; idxTypes++) { - Get1IndType (&type, idxTypes); - nbResources = Count1Resources(type); - - for (idxResources = 1; idxResources <= nbResources; idxResources++) - { - attrs_orig = 0; /* in case GetRes fails */ - attrs_copy = 0; /* in case GetRes fails */ - resource = Get1IndResource(type, idxResources); - GetResInfo (resource, &ID, &sink, name); - HLock (resource); - attrs_orig = GetResAttrs (resource); - DetachResource (resource); - - - UseResFile (toRFid); - AddResource (resource, type, ID, name); - attrs_copy = GetResAttrs (resource); - attrs_copy = (attrs_copy & 0x2) | (attrs_orig & 0xFD); - SetResAttrs (resource, attrs_copy); - WriteResource (resource); - UpdateResFile (toRFid); - - temp = GetResAttrs (resource); - - /*SetResAttrs (resource, 0);*/ - HUnlock(resource); - ReleaseResource (resource); - UseResFile (frRFid); + Get1IndType(&type, idxTypes); + nbResources = Count1Resources(type); + + for (idxResources = 1; idxResources <= nbResources; idxResources++) + { + attrs_orig = 0; /* in case GetRes fails */ + attrs_copy = 0; /* in case GetRes fails */ + resource = Get1IndResource(type, idxResources); + GetResInfo(resource, &ID, &sink, name); + HLock(resource); + attrs_orig = GetResAttrs(resource); + DetachResource(resource); + + + UseResFile(toRFid); + AddResource(resource, type, ID, name); + attrs_copy = GetResAttrs(resource); + attrs_copy = (attrs_copy & 0x2) | (attrs_orig & 0xFD); + SetResAttrs(resource, attrs_copy); + WriteResource(resource); + UpdateResFile(toRFid); + + temp = GetResAttrs(resource); + + /*SetResAttrs (resource, 0);*/ + HUnlock(resource); + ReleaseResource(resource); + UseResFile(frRFid); } } - CloseResFile (toRFid); - CloseResFile (frRFid); - } + CloseResFile(toRFid); + CloseResFile(frRFid); + } #endif /* Copy Finder Info */ - (void) FSpGetFInfo (&frFSSpec, &fndrInfo); - (void) FSpSetFInfo (&toFSSpec, &fndrInfo); + (void)FSpGetFInfo(&frFSSpec, &fndrInfo); + (void)FSpSetFInfo(&toFSSpec, &fndrInfo); return (temp == attrs_copy); } @@ -1386,13 +1386,13 @@ mch_has_resource_fork (file) char_u *file; { FSSpec fileFSSpec; - short fileRFid; + short fileRFid; /* TODO: Handle error */ - (void) GetFSSpecFromPath (file, &fileFSSpec); - fileRFid = FSpOpenResFile (&fileFSSpec, fsCurPerm); + (void)GetFSSpecFromPath(file, &fileFSSpec); + fileRFid = FSpOpenResFile(&fileFSSpec, fsCurPerm); if (fileRFid != -1) - CloseResFile (fileRFid); + CloseResFile(fileRFid); return (fileRFid != -1); } diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro index aa791ac9c..84be78ce2 100644 --- a/src/proto/ex_getln.pro +++ b/src/proto/ex_getln.pro @@ -9,6 +9,7 @@ colnr_T cmdline_getvcol_cursor __ARGS((void)); void putcmdline __ARGS((int c, int shift)); void unputcmdline __ARGS((void)); int put_on_cmdline __ARGS((char_u *str, int len, int redraw)); +void cmdline_paste_str __ARGS((char_u *s, int literally)); void redrawcmdline __ARGS((void)); void redrawcmd __ARGS((void)); void compute_cmdrow __ARGS((void)); diff --git a/src/proto/ops.pro b/src/proto/ops.pro index c64267309..be49f0f10 100644 --- a/src/proto/ops.pro +++ b/src/proto/ops.pro @@ -10,13 +10,16 @@ int get_expr_register __ARGS((void)); void set_expr_line __ARGS((char_u *new_line)); char_u *get_expr_line __ARGS((void)); int valid_yank_reg __ARGS((int regname, int writing)); +void get_yank_register __ARGS((int regname, int writing)); +int may_get_selection __ARGS((int regname)); void *get_register __ARGS((int name, int copy)); void put_register __ARGS((int name, void *reg)); int yank_register_mline __ARGS((int regname)); int do_record __ARGS((int c)); int do_execreg __ARGS((int regname, int colon, int addcr)); int insert_reg __ARGS((int regname, int literally)); -int cmdline_paste __ARGS((int regname, int literally)); +int get_spec_reg __ARGS((int regname, char_u **argp, int *allocated, int errmsg)); +int cmdline_paste_reg __ARGS((int regname, int literally)); void adjust_clip_reg __ARGS((int *rp)); int op_delete __ARGS((oparg_T *oap)); int op_replace __ARGS((oparg_T *oap, int c)); |