/* 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. */ /* * message.c: functions for displaying messages on the command line */ #define MESSAGE_FILE /* don't include prototype for smsg() */ #include "vim.h" static int other_sourcing_name __ARGS((void));static char_u *get_emsg_source __ARGS((void));static char_u *get_emsg_lnum __ARGS((void));static void add_msg_hist __ARGS((char_u *s, int len, int attr));static void hit_return_msg __ARGS((void));static void msg_home_replace_attr __ARGS((char_u *fname, int attr));#ifdef FEAT_MBYTEstatic char_u *screen_puts_mbyte __ARGS((char_u *s, int l, int attr));#endifstatic void msg_puts_attr_len __ARGS((char_u *str, int maxlen, int attr));static void msg_puts_display __ARGS((char_u *str, int maxlen, int attr, int recurse));static void msg_scroll_up __ARGS((void));static void inc_msg_scrolled __ARGS((void));static void store_sb_text __ARGS((char_u **sb_str, char_u *s, int attr, int *sb_col, int finish));static void t_puts __ARGS((int *t_col, char_u *t_s, char_u *s, int attr));static void msg_puts_printf __ARGS((char_u *str, int maxlen));static int do_more_prompt __ARGS((int typed_char));static void msg_screen_putchar __ARGS((int c, int attr));static int msg_check_screen __ARGS((void));static void redir_write __ARGS((char_u *s, int maxlen));static void verbose_write __ARGS((char_u *s, int maxlen));#ifdef FEAT_CON_DIALOGstatic char_u *msg_show_console_dialog __ARGS((char_u *message, char_u *buttons, int dfltbutton));static int confirm_msg_used = FALSE; /* displaying confirm_msg */static char_u *confirm_msg = NULL; /* ":confirm" message */static char_u *confirm_msg_tail; /* tail of confirm_msg */#endif struct msg_hist{ struct msg_hist *next; char_u *msg; int attr;}; static struct msg_hist *first_msg_hist = NULL;static struct msg_hist *last_msg_hist = NULL;static int msg_hist_len = 0; /* * When writing messages to the screen, there are many different situations. * A number of variables is used to remember the current state: * msg_didany TRUE when messages were written since the last time the * user reacted to a prompt. * Reset: After hitting a key for the hit-return prompt, * hitting <CR> for the command line or input(). * Set: When any message is written to the screen. * msg_didout TRUE when something was written to the current line. * Reset: When advancing to the next line, when the current * text can be overwritten. * Set: When any message is written to the screen. * msg_nowait No extra delay for the last drawn message. * Used in normal_cmd() before the mode message is drawn. * emsg_on_display There was an error message recently. Indicates that there * should be a delay before redrawing. * msg_scroll The next message should not overwrite the current one. * msg_scrolled How many lines the screen has been scrolled (because of * messages). Used in update_screen() to scroll the screen * back. Incremented each time the screen scrolls a line. * msg_scrolled_ign TRUE when msg_scrolled is non-zero and msg_puts_attr() * writes something without scrolling should not make * need_wait_return to be set. This is a hack to make ":ts" * work without an extra prompt. * lines_left Number of lines available for messages before the * more-prompt is to be given. * need_wait_return TRUE when the hit-return prompt is needed. * Reset: After giving the hit-return prompt, when the user * has answered some other prompt. * Set: When the ruler or typeahead display is overwritten, * scrolling the screen for some message. * keep_msg Message to be displayed after redrawing the screen, in * main_loop(). * This is an allocated string or NULL when not used. */ /* * msg(s) - displays the string 's' on the status line * When terminal not initialized (yet) mch_errmsg(..) is used. * return TRUE if wait_return not called */ intmsg(s) char_u *s;{ return msg_attr_keep(s, 0, FALSE);} #if defined(FEAT_EVAL) || defined(FEAT_X11) || defined(USE_XSMP) \ || defined(PROTO)/* * Like msg() but keep it silent when 'verbosefile' is set. */ intverb_msg(s) char_u *s;{ int n; verbose_enter(); n = msg_attr_keep(s, 0, FALSE); verbose_leave(); return n;}#endif intmsg_attr(s, attr) char_u *s; int attr;{ return msg_attr_keep(s, attr, FALSE);} intmsg_attr_keep(s, attr, keep) char_u *s; int attr; int keep; /* TRUE: set keep_msg if it doesn't scroll */{ static int entered = 0; int retval; char_u *buf = NULL; #ifdef FEAT_EVAL if (attr == 0) set_vim_var_string(VV_STATUSMSG, s, -1);#endif /* * It is possible that displaying a messages causes a problem (e.g., * when redrawing the window), which causes another message, etc.. To * break this loop, limit the recursiveness to 3 levels. */ if (entered >= 3) return TRUE; ++entered; /* Add message to history (unless it's a repeated kept message or a * truncated message) */ if (s != keep_msg || (*s != '<' && last_msg_hist != NULL && last_msg_hist->msg != NULL && STRCMP(s, last_msg_hist->msg))) add_msg_hist(s, -1, attr); /* When displaying keep_msg, don't let msg_start() free it, caller must do * that. */ if (s == keep_msg) keep_msg = NULL; /* Truncate the message if needed. */ msg_start(); buf = msg_strtrunc(s, FALSE); if (buf != NULL) s = buf; msg_outtrans_attr(s, attr); msg_clr_eos(); retval = msg_end(); if (keep && retval && vim_strsize(s) < (int)(Rows - cmdline_row - 1) * Columns + sc_col) set_keep_msg(s, 0); vim_free(buf); --entered; return retval;} /* * Truncate a string such that it can be printed without causing a scroll. * Returns an allocated string or NULL when no truncating is done. */ char_u *msg_strtrunc(s, force) char_u *s; int force; /* always truncate */{ char_u *buf = NULL; int len; int room; /* May truncate message to avoid a hit-return prompt */ if ((!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL) && !exmode_active && msg_silent == 0) || force) { len = vim_strsize(s); if (msg_scrolled != 0) /* Use all the columns. */ room = (int)(Rows - msg_row) * Columns - 1; else /* Use up to 'showcmd' column. */ room = (int)(Rows - msg_row - 1) * Columns + sc_col - 1; if (len > room && room > 0) {#ifdef FEAT_MBYTE if (enc_utf8) /* may have up to 18 bytes per cell (6 per char, up to two * composing chars) */ buf = alloc((room + 2) * 18); else if (enc_dbcs == DBCS_JPNU) /* may have up to 2 bytes per cell for euc-jp */ buf = alloc((room + 2) * 2); else#endif buf = alloc(room + 2); if (buf != NULL) trunc_string(s, buf, room); } } return buf;} /* * Truncate a string "s" to "buf" with cell width "room". * "s" and "buf" may be equal. */ voidtrunc_string(s, buf, room) char_u *s; char_u *buf; int room;{ int half; int len; int e; int i; int n; room -= 3; half = room / 2; len = 0; /* First part: Start of the string. */ for (e = 0; len < half; ++e) { if (s[e] == NUL) { /* text fits without truncating! */ buf[e] = NUL; return; } n = ptr2cells(s + e); if (len + n >= half) break; len += n; buf[e] = s[e];#ifdef FEAT_MBYTE if (has_mbyte) for (n = (*mb_ptr2len)(s + e); --n > 0; ) { ++e; buf[e] = s[e]; }#endif } /* Last part: End of the string. */ i = e;#ifdef FEAT_MBYTE if (enc_dbcs != 0) { /* For DBCS going backwards in a string is slow, but * computing the cell width isn't too slow: go forward * until the rest fits. */ n = vim_strsize(s + i); while (len + n > room) { n -= ptr2cells(s + i); i += (*mb_ptr2len)(s + i); } } else if (enc_utf8) { /* For UTF-8 we can go backwards easily. */ half = i = (int)STRLEN(s); for (;;) { do half = half - (*mb_head_off)(s, s + half - 1) - 1; while (utf_iscomposing(utf_ptr2char(s + half)) && half > 0); n = ptr2cells(s + half); if (len + n > room) break; len += n; i = half; } } else#endif { for (i = (int)STRLEN(s); len + (n = ptr2cells(s + i - 1)) <= room; --i) len += n; } /* Set the middle and copy the last part. */ mch_memmove(buf + e, "...", (size_t)3); mch_memmove(buf + e + 3, s + i, STRLEN(s + i) + 1);} /* * Automatic prototype generation does not understand this function. * Note: Caller of smgs() and smsg_attr() must check the resulting string is * shorter than IOSIZE!!! */#ifndef PROTO# ifndef HAVE_STDARG_H int#ifdef __BORLANDC___RTLENTRYF#endifsmsg __ARGS((char_u *, long, long, long, long, long, long, long, long, long, long));int#ifdef __BORLANDC___RTLENTRYF#endifsmsg_attr __ARGS((int, char_u *, long, long, long, long, long, long, long, long, long, long)); int vim_snprintf __ARGS((char *, size_t, char *, long, long, long, long, long, long, long, long, long, long)); /* * smsg(str, arg, ...) is like using sprintf(buf, str, arg, ...) and then * calling msg(buf). * The buffer used is IObuff, the message is truncated at IOSIZE. */ /* VARARGS */ int#ifdef __BORLANDC___RTLENTRYF#endifsmsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) char_u *s; long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;{ return smsg_attr(0, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);} /* VARARGS */ int#ifdef __BORLANDC___RTLENTRYF#endifsmsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) int attr; char_u *s; long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;{ vim_snprintf((char *)IObuff, IOSIZE, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); return msg_attr(IObuff, attr);} # else /* HAVE_STDARG_H */ int vim_snprintf(char *str, size_t str_m, char *fmt, ...); int#ifdef __BORLANDC___RTLENTRYF#endifsmsg(char_u *s, ...){ va_list arglist; va_start(arglist, s); vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist, NULL); va_end(arglist); return msg(IObuff);} int#ifdef __BORLANDC___RTLENTRYF#endifsmsg_attr(int attr, char_u *s, ...){ va_list arglist; va_start(arglist, s); vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist, NULL); va_end(arglist); return msg_attr(IObuff, attr);} # endif /* HAVE_STDARG_H */#endif /* * Remember the last sourcing name/lnum used in an error message, so that it * isn't printed each time when it didn't change. */static int last_sourcing_lnum = 0;static char_u *last_sourcing_name = NULL; /* * Reset the last used sourcing name/lnum. Makes sure it is displayed again * for the next error message; */ voidreset_last_sourcing(){ vim_free(last_sourcing_name); last_sourcing_name = NULL; last_sourcing_lnum = 0;} /* * Return TRUE if "sourcing_name" differs from "last_sourcing_name". */ static intother_sourcing_name(){ if (sourcing_name != NULL) { if (last_sourcing_name != NULL) return STRCMP(sourcing_name, last_sourcing_name) != 0; return TRUE; } return FALSE;} /* * Get the message about the source, as used for an error message. * Returns an allocated string with room for one more character. * Returns NULL when no message is to be given. */ static char_u *get_emsg_source(){ char_u *Buf, *p; if (sourcing_name != NULL && other_sourcing_name()) { p = (char_u *)_("Error detected while processing %s:"); Buf = alloc((unsigned)(STRLEN(sourcing_name) + STRLEN(p))); if (Buf != NULL) sprintf((char *)Buf, (char *)p, sourcing_name); return Buf; } return NULL;} /* * Get the message about the source lnum, as used for an error message. * Returns an allocated string with room for one more character. * Returns NULL when no message is to be given. */ static char_u *get_emsg_lnum(){ char_u *Buf, *p; /* lnum is 0 when executing a command from the command line * argument, we don't want a line number then */ if (sourcing_name != NULL && (other_sourcing_name() || sourcing_lnum != last_sourcing_lnum) && sourcing_lnum != 0) { p = (char_u *)_("line %4ld:"); Buf = alloc((unsigned)(STRLEN(p) + 20)); if (Buf != NULL) sprintf((char *)Buf, (char *)p, (long)sourcing_lnum); return Buf; } return NULL;} /* * Display name and line number for the source of an error. * Remember the file name and line number, so that for the next error the info * is only displayed if it changed. */ voidmsg_source(attr) int attr;{Lines 1–500 of 4595. Load more
/* 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. */ /* * message.c: functions for displaying messages on the command line */ #define MESSAGE_FILE /* don't include prototype for smsg() */ #include "vim.h" static int other_sourcing_name __ARGS((void)); static char_u *get_emsg_source __ARGS((void)); static char_u *get_emsg_lnum __ARGS((void)); static void add_msg_hist __ARGS((char_u *s, int len, int attr)); static void hit_return_msg __ARGS((void)); static void msg_home_replace_attr __ARGS((char_u *fname, int attr)); #ifdef FEAT_MBYTE static char_u *screen_puts_mbyte __ARGS((char_u *s, int l, int attr)); #endif static void msg_puts_attr_len __ARGS((char_u *str, int maxlen, int attr)); static void msg_puts_display __ARGS((char_u *str, int maxlen, int attr, int recurse)); static void msg_scroll_up __ARGS((void)); static void inc_msg_scrolled __ARGS((void)); static void store_sb_text __ARGS((char_u **sb_str, char_u *s, int attr, int *sb_col, int finish)); static void t_puts __ARGS((int *t_col, char_u *t_s, char_u *s, int attr)); static void msg_puts_printf __ARGS((char_u *str, int maxlen)); static int do_more_prompt __ARGS((int typed_char)); static void msg_screen_putchar __ARGS((int c, int attr)); static int msg_check_screen __ARGS((void)); static void redir_write __ARGS((char_u *s, int maxlen)); static void verbose_write __ARGS((char_u *s, int maxlen)); #ifdef FEAT_CON_DIALOG static char_u *msg_show_console_dialog __ARGS((char_u *message, char_u *buttons, int dfltbutton)); static int confirm_msg_used = FALSE; /* displaying confirm_msg */ static char_u *confirm_msg = NULL; /* ":confirm" message */ static char_u *confirm_msg_tail; /* tail of confirm_msg */ #endif struct msg_hist { struct msg_hist *next; char_u *msg; int attr; }; static struct msg_hist *first_msg_hist = NULL; static struct msg_hist *last_msg_hist = NULL; static int msg_hist_len = 0; /* * When writing messages to the screen, there are many different situations. * A number of variables is used to remember the current state: * msg_didany TRUE when messages were written since the last time the * user reacted to a prompt. * Reset: After hitting a key for the hit-return prompt, * hitting <CR> for the command line or input(). * Set: When any message is written to the screen. * msg_didout TRUE when something was written to the current line. * Reset: When advancing to the next line, when the current * text can be overwritten. * Set: When any message is written to the screen. * msg_nowait No extra delay for the last drawn message. * Used in normal_cmd() before the mode message is drawn. * emsg_on_display There was an error message recently. Indicates that there * should be a delay before redrawing. * msg_scroll The next message should not overwrite the current one. * msg_scrolled How many lines the screen has been scrolled (because of * messages). Used in update_screen() to scroll the screen * back. Incremented each time the screen scrolls a line. * msg_scrolled_ign TRUE when msg_scrolled is non-zero and msg_puts_attr() * writes something without scrolling should not make * need_wait_return to be set. This is a hack to make ":ts" * work without an extra prompt. * lines_left Number of lines available for messages before the * more-prompt is to be given. * need_wait_return TRUE when the hit-return prompt is needed. * Reset: After giving the hit-return prompt, when the user * has answered some other prompt. * Set: When the ruler or typeahead display is overwritten, * scrolling the screen for some message. * keep_msg Message to be displayed after redrawing the screen, in * main_loop(). * This is an allocated string or NULL when not used. */ /* * msg(s) - displays the string 's' on the status line * When terminal not initialized (yet) mch_errmsg(..) is used. * return TRUE if wait_return not called */ int msg(s) char_u *s; { return msg_attr_keep(s, 0, FALSE); } #if defined(FEAT_EVAL) || defined(FEAT_X11) || defined(USE_XSMP) \ || defined(PROTO) /* * Like msg() but keep it silent when 'verbosefile' is set. */ int verb_msg(s) char_u *s; { int n; verbose_enter(); n = msg_attr_keep(s, 0, FALSE); verbose_leave(); return n; } #endif int msg_attr(s, attr) char_u *s; int attr; { return msg_attr_keep(s, attr, FALSE); } int msg_attr_keep(s, attr, keep) char_u *s; int attr; int keep; /* TRUE: set keep_msg if it doesn't scroll */ { static int entered = 0; int retval; char_u *buf = NULL; #ifdef FEAT_EVAL if (attr == 0) set_vim_var_string(VV_STATUSMSG, s, -1); #endif /* * It is possible that displaying a messages causes a problem (e.g., * when redrawing the window), which causes another message, etc.. To * break this loop, limit the recursiveness to 3 levels. */ if (entered >= 3) return TRUE; ++entered; /* Add message to history (unless it's a repeated kept message or a * truncated message) */ if (s != keep_msg || (*s != '<' && last_msg_hist != NULL && last_msg_hist->msg != NULL && STRCMP(s, last_msg_hist->msg))) add_msg_hist(s, -1, attr); /* When displaying keep_msg, don't let msg_start() free it, caller must do * that. */ if (s == keep_msg) keep_msg = NULL; /* Truncate the message if needed. */ msg_start(); buf = msg_strtrunc(s, FALSE); if (buf != NULL) s = buf; msg_outtrans_attr(s, attr); msg_clr_eos(); retval = msg_end(); if (keep && retval && vim_strsize(s) < (int)(Rows - cmdline_row - 1) * Columns + sc_col) set_keep_msg(s, 0); vim_free(buf); --entered; return retval; } /* * Truncate a string such that it can be printed without causing a scroll. * Returns an allocated string or NULL when no truncating is done. */ char_u * msg_strtrunc(s, force) char_u *s; int force; /* always truncate */ { char_u *buf = NULL; int len; int room; /* May truncate message to avoid a hit-return prompt */ if ((!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL) && !exmode_active && msg_silent == 0) || force) { len = vim_strsize(s); if (msg_scrolled != 0) /* Use all the columns. */ room = (int)(Rows - msg_row) * Columns - 1; else /* Use up to 'showcmd' column. */ room = (int)(Rows - msg_row - 1) * Columns + sc_col - 1; if (len > room && room > 0) { #ifdef FEAT_MBYTE if (enc_utf8) /* may have up to 18 bytes per cell (6 per char, up to two * composing chars) */ buf = alloc((room + 2) * 18); else if (enc_dbcs == DBCS_JPNU) /* may have up to 2 bytes per cell for euc-jp */ buf = alloc((room + 2) * 2); else #endif buf = alloc(room + 2); if (buf != NULL) trunc_string(s, buf, room); } } return buf; } /* * Truncate a string "s" to "buf" with cell width "room". * "s" and "buf" may be equal. */ void trunc_string(s, buf, room) char_u *s; char_u *buf; int room; { int half; int len; int e; int i; int n; room -= 3; half = room / 2; len = 0; /* First part: Start of the string. */ for (e = 0; len < half; ++e) { if (s[e] == NUL) { /* text fits without truncating! */ buf[e] = NUL; return; } n = ptr2cells(s + e); if (len + n >= half) break; len += n; buf[e] = s[e]; #ifdef FEAT_MBYTE if (has_mbyte) for (n = (*mb_ptr2len)(s + e); --n > 0; ) { ++e; buf[e] = s[e]; } #endif } /* Last part: End of the string. */ i = e; #ifdef FEAT_MBYTE if (enc_dbcs != 0) { /* For DBCS going backwards in a string is slow, but * computing the cell width isn't too slow: go forward * until the rest fits. */ n = vim_strsize(s + i); while (len + n > room) { n -= ptr2cells(s + i); i += (*mb_ptr2len)(s + i); } } else if (enc_utf8) { /* For UTF-8 we can go backwards easily. */ half = i = (int)STRLEN(s); for (;;) { do half = half - (*mb_head_off)(s, s + half - 1) - 1; while (utf_iscomposing(utf_ptr2char(s + half)) && half > 0); n = ptr2cells(s + half); if (len + n > room) break; len += n; i = half; } } else #endif { for (i = (int)STRLEN(s); len + (n = ptr2cells(s + i - 1)) <= room; --i) len += n; } /* Set the middle and copy the last part. */ mch_memmove(buf + e, "...", (size_t)3); mch_memmove(buf + e + 3, s + i, STRLEN(s + i) + 1); } /* * Automatic prototype generation does not understand this function. * Note: Caller of smgs() and smsg_attr() must check the resulting string is * shorter than IOSIZE!!! */ #ifndef PROTO # ifndef HAVE_STDARG_H int #ifdef __BORLANDC__ _RTLENTRYF #endif smsg __ARGS((char_u *, long, long, long, long, long, long, long, long, long, long)); int #ifdef __BORLANDC__ _RTLENTRYF #endif smsg_attr __ARGS((int, char_u *, long, long, long, long, long, long, long, long, long, long)); int vim_snprintf __ARGS((char *, size_t, char *, long, long, long, long, long, long, long, long, long, long)); /* * smsg(str, arg, ...) is like using sprintf(buf, str, arg, ...) and then * calling msg(buf). * The buffer used is IObuff, the message is truncated at IOSIZE. */ /* VARARGS */ int #ifdef __BORLANDC__ _RTLENTRYF #endif smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) char_u *s; long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10; { return smsg_attr(0, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } /* VARARGS */ int #ifdef __BORLANDC__ _RTLENTRYF #endif smsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) int attr; char_u *s; long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10; { vim_snprintf((char *)IObuff, IOSIZE, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); return msg_attr(IObuff, attr); } # else /* HAVE_STDARG_H */ int vim_snprintf(char *str, size_t str_m, char *fmt, ...); int #ifdef __BORLANDC__ _RTLENTRYF #endif smsg(char_u *s, ...) { va_list arglist; va_start(arglist, s); vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist, NULL); va_end(arglist); return msg(IObuff); } int #ifdef __BORLANDC__ _RTLENTRYF #endif smsg_attr(int attr, char_u *s, ...) { va_list arglist; va_start(arglist, s); vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist, NULL); va_end(arglist); return msg_attr(IObuff, attr); } # endif /* HAVE_STDARG_H */ #endif /* * Remember the last sourcing name/lnum used in an error message, so that it * isn't printed each time when it didn't change. */ static int last_sourcing_lnum = 0; static char_u *last_sourcing_name = NULL; /* * Reset the last used sourcing name/lnum. Makes sure it is displayed again * for the next error message; */ void reset_last_sourcing() { vim_free(last_sourcing_name); last_sourcing_name = NULL; last_sourcing_lnum = 0; } /* * Return TRUE if "sourcing_name" differs from "last_sourcing_name". */ static int other_sourcing_name() { if (sourcing_name != NULL) { if (last_sourcing_name != NULL) return STRCMP(sourcing_name, last_sourcing_name) != 0; return TRUE; } return FALSE; } /* * Get the message about the source, as used for an error message. * Returns an allocated string with room for one more character. * Returns NULL when no message is to be given. */ static char_u * get_emsg_source() { char_u *Buf, *p; if (sourcing_name != NULL && other_sourcing_name()) { p = (char_u *)_("Error detected while processing %s:"); Buf = alloc((unsigned)(STRLEN(sourcing_name) + STRLEN(p))); if (Buf != NULL) sprintf((char *)Buf, (char *)p, sourcing_name); return Buf; } return NULL; } /* * Get the message about the source lnum, as used for an error message. * Returns an allocated string with room for one more character. * Returns NULL when no message is to be given. */ static char_u * get_emsg_lnum() { char_u *Buf, *p; /* lnum is 0 when executing a command from the command line * argument, we don't want a line number then */ if (sourcing_name != NULL && (other_sourcing_name() || sourcing_lnum != last_sourcing_lnum) && sourcing_lnum != 0) { p = (char_u *)_("line %4ld:"); Buf = alloc((unsigned)(STRLEN(p) + 20)); if (Buf != NULL) sprintf((char *)Buf, (char *)p, (long)sourcing_lnum); return Buf; } return NULL; } /* * Display name and line number for the source of an error. * Remember the file name and line number, so that for the next error the info * is only displayed if it changed. */ void msg_source(attr) int attr; {