misc2.c
资源名称:vim53src.zip [点击查看]
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:47k
源码类别:
编辑器/阅读器
开发平台:
DOS
- /* 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.
- */
- /*
- * misc2.c: Various functions.
- */
- #include "vim.h"
- #ifdef HAVE_FCNTL_H
- # include <fcntl.h> /* for chdir() */
- #endif
- /*
- * coladvance(col)
- *
- * Try to advance the Cursor to the specified column.
- *
- * return OK if desired column is reached, FAIL if not
- */
- int
- coladvance(wcol)
- colnr_t wcol;
- {
- int idx;
- char_u *ptr;
- colnr_t col;
- ptr = ml_get_curline();
- /* try to advance to the specified column */
- idx = -1;
- col = 0;
- while (col <= wcol && *ptr)
- {
- ++idx;
- /* Count a tab for what it's worth (if list mode not on) */
- col += lbr_chartabsize(ptr, col);
- ++ptr;
- }
- /*
- * In Insert mode it is allowed to be one char beyond the end of the line.
- * Also in Visual mode, when 'selection' is not "old".
- */
- if (((State & INSERT) || (VIsual_active && *p_sel != 'o')) && col <= wcol)
- ++idx;
- if (idx < 0)
- curwin->w_cursor.col = 0;
- else
- curwin->w_cursor.col = idx;
- #ifdef MULTI_BYTE
- /* prevent cursor from moving on the trail byte */
- if (is_dbcs)
- AdjustCursorForMultiByteCharacter();
- #endif
- if (col <= wcol)
- return FAIL; /* Couldn't reach column */
- else
- return OK; /* Reached column */
- }
- /*
- * inc(p)
- *
- * Increment the line pointer 'p' crossing line boundaries as necessary.
- * Return 1 when crossing a line, -1 when at end of file, 0 otherwise.
- */
- int
- inc_cursor()
- {
- return inc(&curwin->w_cursor);
- }
- int
- inc(lp)
- FPOS *lp;
- {
- char_u *p = ml_get_pos(lp);
- if (*p != NUL) /* still within line, move to next char (may be NUL) */
- {
- #ifdef MULTI_BYTE
- if (is_dbcs && IsLeadByte(p[0]) && p[1] != NUL)
- {
- lp->col += 2;
- return ((p[2] != NUL) ? 0 : 1);
- }
- #endif
- lp->col++;
- return ((p[1] != NUL) ? 0 : 1);
- }
- if (lp->lnum != curbuf->b_ml.ml_line_count) /* there is a next line */
- {
- lp->col = 0;
- lp->lnum++;
- return 1;
- }
- return -1;
- }
- /*
- * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines
- */
- int
- incl(lp)
- FPOS *lp;
- {
- int r;
- if ((r = inc(lp)) == 1 && lp->col)
- r = inc(lp);
- return r;
- }
- /*
- * dec(p)
- *
- * Decrement the line pointer 'p' crossing line boundaries as necessary.
- * Return 1 when crossing a line, -1 when at start of file, 0 otherwise.
- */
- int
- dec_cursor()
- {
- #ifdef MULTI_BYTE
- return (is_dbcs ? han_dec(&curwin->w_cursor) : dec(&curwin->w_cursor));
- #else
- return dec(&curwin->w_cursor);
- #endif
- }
- int
- dec(lp)
- FPOS *lp;
- {
- if (lp->col > 0)
- { /* still within line */
- lp->col--;
- return 0;
- }
- if (lp->lnum > 1)
- { /* there is a prior line */
- lp->lnum--;
- lp->col = STRLEN(ml_get(lp->lnum));
- return 1;
- }
- return -1; /* at start of file */
- }
- /*
- * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines
- */
- int
- decl(lp)
- FPOS *lp;
- {
- int r;
- if ((r = dec(lp)) == 1 && lp->col)
- r = dec(lp);
- return r;
- }
- /*
- * Make sure curwin->w_cursor.lnum is valid.
- */
- void
- check_cursor_lnum()
- {
- if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
- curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- if (curwin->w_cursor.lnum <= 0)
- curwin->w_cursor.lnum = 1;
- }
- /*
- * Make sure curwin->w_cursor.col is valid.
- */
- void
- check_cursor_col()
- {
- colnr_t len;
- len = STRLEN(ml_get_curline());
- if (len == 0)
- curwin->w_cursor.col = 0;
- else if (curwin->w_cursor.col >= len)
- {
- if (State & INSERT || restart_edit)
- curwin->w_cursor.col = len;
- else
- curwin->w_cursor.col = len - 1;
- }
- }
- /*
- * make sure curwin->w_cursor in on a valid character
- */
- void
- adjust_cursor()
- {
- check_cursor_lnum();
- check_cursor_col();
- }
- /*
- * Make sure curwin->w_cursor is not on the NUL at the end of the line.
- * Allow it when in Visual mode and 'selection' is not "old".
- */
- void
- adjust_cursor_col()
- {
- if ((!VIsual_active || *p_sel == 'o')
- && curwin->w_cursor.col && gchar_cursor() == NUL)
- --curwin->w_cursor.col;
- }
- /*
- * When curwin->w_leftcol has changed, adjust the cursor position.
- * Return TRUE if the cursor was moved.
- */
- int
- leftcol_changed()
- {
- long lastcol;
- colnr_t s, e;
- int retval = FALSE;
- changed_cline_bef_curs();
- lastcol = curwin->w_leftcol + Columns - (curwin->w_p_nu ? 8 : 0) - 1;
- validate_virtcol();
- /*
- * If the cursor is right or left of the screen, move it to last or first
- * character.
- */
- if (curwin->w_virtcol > (colnr_t)lastcol)
- {
- retval = TRUE;
- coladvance((colnr_t)lastcol);
- }
- else if (curwin->w_virtcol < curwin->w_leftcol)
- {
- retval = TRUE;
- (void)coladvance(curwin->w_leftcol);
- }
- /*
- * If the start of the character under the cursor is not on the screen,
- * advance the cursor one more char. If this fails (last char of the
- * line) adjust the scrolling.
- */
- getvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
- if (e > (colnr_t)lastcol)
- {
- retval = TRUE;
- coladvance(s - 1);
- }
- else if (s < curwin->w_leftcol)
- {
- retval = TRUE;
- if (coladvance(e + 1) == FAIL) /* there isn't another character */
- {
- curwin->w_leftcol = s; /* adjust w_leftcol instead */
- changed_cline_bef_curs();
- }
- }
- redraw_later(NOT_VALID);
- return retval;
- }
- /**********************************************************************
- * Various routines dealing with allocation and deallocation of memory.
- */
- #if defined(MEM_PROFILE) || defined(PROTO)
- # define MEM_SIZES 8200
- static long_u mem_allocs[MEM_SIZES];
- static long_u mem_frees[MEM_SIZES];
- static long_u mem_allocated;
- static long_u mem_freed;
- static long_u mem_peak;
- static long_u num_alloc;
- static long_u num_freed;
- static void mem_pre_alloc_s __ARGS((size_t *sizep));
- static void mem_pre_alloc_l __ARGS((long_u *sizep));
- static void mem_post_alloc __ARGS((void **pp, size_t size));
- static void mem_pre_free __ARGS((void **pp));
- static void
- mem_pre_alloc_s(sizep)
- size_t *sizep;
- {
- *sizep += sizeof(size_t);
- }
- static void
- mem_pre_alloc_l(sizep)
- long_u *sizep;
- {
- *sizep += sizeof(size_t);
- }
- static void
- mem_post_alloc(pp, size)
- void **pp;
- size_t size;
- {
- if (*pp == NULL)
- return;
- size -= sizeof(size_t);
- *(long_u *)*pp = size;
- if (size <= MEM_SIZES-1)
- mem_allocs[size-1]++;
- else
- mem_allocs[MEM_SIZES-1]++;
- mem_allocated += size;
- if (mem_allocated - mem_freed > mem_peak)
- mem_peak = mem_allocated - mem_freed;
- num_alloc++;
- *pp = (void *)((char *)*pp + sizeof(size_t));
- }
- static void
- mem_pre_free(pp)
- void **pp;
- {
- long_u size;
- *pp = (void *)((char *)*pp - sizeof(size_t));
- size = *(size_t *)*pp;
- if (size <= MEM_SIZES-1)
- mem_frees[size-1]++;
- else
- mem_frees[MEM_SIZES-1]++;
- mem_freed += size;
- num_freed++;
- }
- /*
- * called on exit via atexit()
- */
- void
- vim_mem_profile_dump()
- {
- int i, j;
- printf("rn");
- j = 0;
- for (i = 0; i < MEM_SIZES - 1; i++)
- {
- if (mem_allocs[i] || mem_frees[i])
- {
- if (mem_frees[i] > mem_allocs[i])
- printf("rnERROR: ");
- printf("[%4d / %4lu-%-4lu] ", i + 1, mem_allocs[i], mem_frees[i]);
- j++;
- if (j > 3)
- {
- j = 0;
- printf("rn");
- }
- }
- }
- i = MEM_SIZES - 1;
- if (mem_allocs[i])
- {
- printf("rn");
- if (mem_frees[i] > mem_allocs[i])
- printf("ERROR: ");
- printf("[>%d / %4lu-%-4lu]", i, mem_allocs[i], mem_frees[i]);
- }
- printf("rnn[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lurn",
- mem_allocated, mem_freed, mem_allocated - mem_freed, mem_peak);
- printf("[calls] total re/malloc()'s %lu, total free()'s %lurnn",
- num_alloc, num_freed);
- }
- #endif /* MEM_PROFILE */
- /*
- * Some memory is reserved for error messages and for being able to
- * call mf_release_all(), which needs some memory for mf_trans_add().
- */
- #define KEEP_ROOM 8192L
- static void vim_strup __ARGS((char_u *p));
- /*
- * Note: if unsinged is 16 bits we can only allocate up to 64K with alloc().
- * Use lalloc for larger blocks.
- */
- char_u *
- alloc(size)
- unsigned size;
- {
- return (lalloc((long_u)size, TRUE));
- }
- /*
- * Allocate memory and set all bytes to zero.
- */
- char_u *
- alloc_clear(size)
- unsigned size;
- {
- char_u *p;
- p = (lalloc((long_u)size, TRUE));
- if (p != NULL)
- (void)vim_memset(p, 0, (size_t)size);
- return p;
- }
- /*
- * alloc() with check for maximum line length
- */
- char_u *
- alloc_check(size)
- unsigned size;
- {
- #if !defined(UNIX) && !defined(__EMX__)
- if (sizeof(int) == 2 && size > 0x7fff)
- {
- EMSG("Line is becoming too long");
- return NULL;
- }
- #endif
- return (lalloc((long_u)size, TRUE));
- }
- /*
- * Allocate memory like lalloc() and set all bytes to zero.
- */
- char_u *
- lalloc_clear(size, message)
- long_u size;
- int message;
- {
- char_u *p;
- p = (lalloc(size, message));
- if (p != NULL)
- (void)vim_memset(p, 0, (size_t)size);
- return p;
- }
- char_u *
- lalloc(size, message)
- long_u size;
- int message;
- {
- char_u *p; /* pointer to new storage space */
- static int releasing = FALSE; /* don't do mf_release_all() recursive */
- int try_again;
- if (size <= 0)
- {
- EMSGN("Internal error: lalloc(%ld, )", size);
- return NULL;
- }
- #ifdef MEM_PROFILE
- mem_pre_alloc_l(&size);
- #endif
- #if defined(MSDOS) && !defined(DJGPP)
- if (size >= 0xfff0) /* in MSDOS we can't deal with >64K blocks */
- p = NULL;
- else
- #endif
- /*
- * If out of memory, try to release some memfile blocks.
- * If some blocks are released call malloc again.
- */
- for (;;)
- {
- if ((p = (char_u *)malloc((size_t)size)) != NULL)
- {
- if (mch_avail_mem(TRUE) < KEEP_ROOM && !releasing)
- { /* System is low... no go! */
- vim_free((char *)p);
- p = NULL;
- }
- }
- /*
- * Remember that mf_release_all() is being called to avoid an endless loop,
- * because mf_release_all() may call alloc() recursively.
- */
- if (p != NULL || releasing)
- break;
- releasing = TRUE;
- try_again = mf_release_all();
- releasing = FALSE;
- if (!try_again)
- break;
- }
- if (message && p == NULL)
- do_outofmem_msg();
- #ifdef MEM_PROFILE
- mem_post_alloc((void **)&p, (size_t)size);
- #endif
- return (p);
- }
- #if defined(MEM_PROFILE) || defined(PROTO)
- /*
- * realloc(), with memory profiling.
- */
- void *
- vim_realloc(ptr, size)
- void *ptr;
- size_t size;
- {
- void *p;
- mem_pre_free(&ptr);
- mem_pre_alloc_s(&size);
- p = realloc(ptr, size);
- mem_post_alloc(&p, size);
- return p;
- }
- #endif
- /*
- * Avoid repeating the error message many times (they take 1 second each).
- * Did_outofmem_msg is reset when a character is read.
- */
- void
- do_outofmem_msg()
- {
- if (!did_outofmem_msg)
- {
- emsg(e_outofmem);
- did_outofmem_msg = TRUE;
- }
- }
- /*
- * copy a string into newly allocated memory
- */
- char_u *
- vim_strsave(string)
- char_u *string;
- {
- char_u *p;
- unsigned len;
- len = STRLEN(string) + 1;
- p = alloc(len);
- if (p != NULL)
- mch_memmove(p, string, (size_t)len);
- return p;
- }
- char_u *
- vim_strnsave(string, len)
- char_u *string;
- int len;
- {
- char_u *p;
- p = alloc((unsigned)(len + 1));
- if (p != NULL)
- {
- STRNCPY(p, string, len);
- p[len] = NUL;
- }
- return p;
- }
- /*
- * like vim_strnsave(), but remove backslashes from the string.
- */
- char_u *
- vim_strnsave_esc(string, len)
- char_u *string;
- int len;
- {
- char_u *p1, *p2;
- p1 = alloc((unsigned) (len + 1));
- if (p1 != NULL)
- {
- STRNCPY(p1, string, len);
- p1[len] = NUL;
- for (p2 = p1; *p2; ++p2)
- if (*p2 == '\' && *(p2 + 1) != NUL)
- STRCPY(p2, p2 + 1);
- }
- return p1;
- }
- /*
- * Same as vim_strsave(), but any characters found in esc_chars are preceded
- * by a backslash.
- */
- char_u *
- vim_strsave_escaped(string, esc_chars)
- char_u *string;
- char_u *esc_chars;
- {
- char_u *p;
- char_u *p2;
- char_u *escaped_string;
- unsigned length;
- /*
- * First count the number of backslashes required.
- * Then allocate the memory and insert them.
- */
- length = 1; /* count the trailing '/' and NUL */
- for (p = string; *p; p++)
- {
- if (vim_strchr(esc_chars, *p) != NULL)
- ++length; /* count a backslash */
- ++length; /* count an ordinary char */
- }
- escaped_string = alloc(length);
- if (escaped_string != NULL)
- {
- p2 = escaped_string;
- for (p = string; *p; p++)
- {
- if (vim_strchr(esc_chars, *p) != NULL)
- *p2++ = '\';
- *p2++ = *p;
- }
- *p2 = NUL;
- }
- return escaped_string;
- }
- /*
- * like vim_strsave(), but make all characters uppercase.
- */
- char_u *
- vim_strsave_up(string)
- char_u *string;
- {
- char_u *p1;
- p1 = vim_strsave(string);
- vim_strup(p1);
- return p1;
- }
- /*
- * like vim_strnsave(), but make all characters uppercase.
- */
- char_u *
- vim_strnsave_up(string, len)
- char_u *string;
- int len;
- {
- char_u *p1;
- p1 = vim_strnsave(string, len);
- vim_strup(p1);
- return p1;
- }
- static void
- vim_strup(p)
- char_u *p;
- {
- char_u *p2;
- int c;
- if (p != NULL)
- {
- p2 = p;
- while ((c = *p2) != NUL)
- *p2++ = TO_UPPER(c);
- }
- }
- /*
- * copy a number of spaces
- */
- void
- copy_spaces(ptr, count)
- char_u *ptr;
- size_t count;
- {
- size_t i = count;
- char_u *p = ptr;
- while (i--)
- *p++ = ' ';
- }
- /*
- * delete spaces at the end of a string
- */
- void
- del_trailing_spaces(ptr)
- char_u *ptr;
- {
- char_u *q;
- q = ptr + STRLEN(ptr);
- while (--q > ptr && vim_iswhite(q[0]) && q[-1] != '\' &&
- q[-1] != Ctrl('V'))
- *q = NUL;
- }
- /*
- * vim_strncpy()
- *
- * This is here because strncpy() does not guarantee successful results when
- * the to and from strings overlap. It is only currently called from nextwild()
- * which copies part of the command line to another part of the command line.
- * This produced garbage when expanding files etc in the middle of the command
- * line (on my terminal, anyway) -- webb.
- */
- void
- vim_strncpy(to, from, len)
- char_u *to;
- char_u *from;
- int len;
- {
- int i;
- if (to <= from)
- {
- while (len-- && *from)
- *to++ = *from++;
- if (len >= 0)
- *to = *from; /* Copy NUL */
- }
- else
- {
- for (i = 0; i < len; i++)
- {
- to++;
- if (*from++ == NUL)
- {
- i++;
- break;
- }
- }
- for (; i > 0; i--)
- *--to = *--from;
- }
- }
- /*
- * Isolate one part of a string option where parts are separated with commas.
- * The part is copied into buf[maxlen].
- * "*option" is advanced to the next part.
- * The length is returned.
- */
- int
- copy_option_part(option, buf, maxlen, sep_chars)
- char_u **option;
- char_u *buf;
- int maxlen;
- char *sep_chars;
- {
- int len = 0;
- char_u *p = *option;
- /* skip '.' at start of option part, for 'suffixes' */
- if (*p == '.')
- buf[len++] = *p++;
- while (*p && vim_strchr((char_u *)sep_chars, *p) == NULL)
- {
- /*
- * Skip backslash before a separator character and space.
- */
- if (p[0] == '\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL)
- ++p;
- if (len < maxlen - 1)
- buf[len++] = *p;
- ++p;
- }
- buf[len] = NUL;
- p = skip_to_option_part(p); /* p points to next file name */
- *option = p;
- return len;
- }
- /*
- * replacement for free() that ignores NULL pointers
- */
- void
- vim_free(x)
- void *x;
- {
- if (x != NULL)
- {
- #ifdef MEM_PROFILE
- mem_pre_free(&x);
- #endif
- free(x);
- }
- }
- #ifndef HAVE_MEMSET
- void *
- vim_memset(ptr, c, size)
- void *ptr;
- int c;
- size_t size;
- {
- char *p = ptr;
- while (size-- > 0)
- *p++ = c;
- return ptr;
- }
- #endif
- #ifdef VIM_MEMCMP
- /*
- * Return zero when "b1" and "b2" are the same for "len" bytes.
- * Return non-zero otherwise.
- */
- int
- vim_memcmp(b1, b2, len)
- void *b1;
- void *b2;
- size_t len;
- {
- char_u *p1 = (char_u *)b1, *p2 = (char_u *)b2;
- for ( ; len > 0; --len)
- {
- if (*p1 != *p2)
- return 1;
- ++p1;
- ++p2;
- }
- return 0;
- }
- #endif
- #ifdef VIM_MEMMOVE
- /*
- * Version of memmove that handles overlapping source and destination.
- * For systems that don't have a function that is guaranteed to do that (SYSV).
- */
- void
- mch_memmove(dst_arg, src_arg, len)
- void *src_arg, *dst_arg;
- size_t len;
- {
- /*
- * A void doesn't have a size, we use char pointers.
- */
- char *dst = dst_arg, *src = src_arg;
- /* overlap, copy backwards */
- if (dst > src && dst < src + len)
- {
- src +=len;
- dst +=len;
- while (len-- > 0)
- *--dst = *--src;
- }
- else /* copy forwards */
- while (len-- > 0)
- *dst++ = *src++;
- }
- #endif
- #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO)
- /*
- * Compare two strings, ignoring case.
- * return 0 for match, 1 for difference
- */
- int
- vim_stricmp(s1, s2)
- char *s1;
- char *s2;
- {
- for (;;)
- {
- if (TO_LOWER(*s1) != TO_LOWER(*s2))
- return 1; /* this character different */
- if (*s1 == NUL)
- break; /* strings match until NUL */
- ++s1;
- ++s2;
- }
- return 0; /* strings match */
- }
- #endif
- #if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP)) || defined(PROTO)
- /*
- * Compare two strings, for length "len", ignoring case.
- * return 0 for match, 1 for difference
- */
- int
- vim_strnicmp(s1, s2, len)
- char *s1;
- char *s2;
- size_t len;
- {
- while (len)
- {
- if (TO_LOWER(*s1) != TO_LOWER(*s2))
- return 1; /* this character different */
- if (*s1 == NUL)
- break; /* strings match until NUL */
- ++s1;
- ++s2;
- --len;
- }
- return 0; /* strings match */
- }
- #endif
- /*
- * Version of strchr() and strrchr() that handle unsigned char strings
- * with characters above 128 correctly. Also it doesn't return a pointer to
- * the NUL at the end of the string.
- */
- char_u *
- vim_strchr(string, n)
- char_u *string;
- int n;
- {
- char_u *p;
- int c;
- p = string;
- while ((c = *p) != NUL)
- {
- if (c == n)
- return p;
- ++p;
- }
- return NULL;
- }
- char_u *
- vim_strrchr(string, n)
- char_u *string;
- int n;
- {
- char_u *retval = NULL;
- while (*string)
- {
- if (*string == n)
- retval = string;
- ++string;
- }
- return retval;
- }
- /*
- * Vim's version of strpbrk(), in case it's missing.
- * Don't generate a prototype for this, causes problems when it's not used.
- */
- #ifndef PROTO
- # ifndef HAVE_STRPBRK
- # ifdef vim_strpbrk
- # undef vim_strpbrk
- # endif
- char_u *
- vim_strpbrk(s, charset)
- char_u *s;
- char_u *charset;
- {
- while (*s)
- {
- if (vim_strchr(charset, *s) != NULL)
- return s;
- ++s;
- }
- return NULL;
- }
- # endif
- #endif
- /*
- * Vim has its own isspace() function, because on some machines isspace()
- * can't handle characters above 128.
- */
- int
- vim_isspace(x)
- int x;
- {
- return ((x >= 9 && x <= 13) || x == ' ');
- }
- /************************************************************************
- * Functions for hanlding growing arrays.
- */
- /*
- * Clear an allocated growing array.
- */
- void
- ga_clear(gap)
- struct growarray *gap;
- {
- vim_free(gap->ga_data);
- ga_init(gap);
- }
- /*
- * Clear a growing array that contains a list of strings.
- */
- void
- ga_clear_strings(gap)
- struct growarray *gap;
- {
- int i;
- for (i = 0; i < gap->ga_len; ++i)
- vim_free(((char_u **)(gap->ga_data))[i]);
- ga_clear(gap);
- }
- /*
- * Initialize a growing array. Don't forget to set ga_itemsize and
- * ga_growsize! Or use ga_init2().
- */
- void
- ga_init(gap)
- struct growarray *gap;
- {
- gap->ga_data = NULL;
- gap->ga_room = 0;
- gap->ga_len = 0;
- }
- void
- ga_init2(gap, itemsize, growsize)
- struct growarray *gap;
- int itemsize;
- int growsize;
- {
- ga_init(gap);
- gap->ga_itemsize = itemsize;
- gap->ga_growsize = growsize;
- }
- /*
- * Make room in growing array "ga" for at least "n" items.
- * Return FAIL for failure, OK otherwise.
- */
- int
- ga_grow(ga, n)
- struct growarray *ga;
- int n;
- {
- size_t len;
- char_u *pp;
- if (ga->ga_room < n)
- {
- if (n < ga->ga_growsize)
- n = ga->ga_growsize;
- len = ga->ga_itemsize * (ga->ga_len + n);
- pp = alloc_clear((unsigned)len);
- if (pp == NULL)
- return FAIL;
- ga->ga_room = n;
- if (ga->ga_data != NULL)
- {
- mch_memmove(pp, ga->ga_data,
- (size_t)(ga->ga_itemsize * ga->ga_len));
- vim_free(ga->ga_data);
- }
- ga->ga_data = pp;
- }
- return OK;
- }
- /************************************************************************
- * functions that use lookup tables for various things, generally to do with
- * special key codes.
- */
- /*
- * Some useful tables.
- */
- static struct modmasktable
- {
- int mod_mask; /* Bit-mask for particular key modifier */
- char_u name; /* Single letter name of modifier */
- } mod_mask_table[] =
- {
- {MOD_MASK_ALT, (char_u)'M'},
- {MOD_MASK_CTRL, (char_u)'C'},
- {MOD_MASK_SHIFT, (char_u)'S'},
- {MOD_MASK_2CLICK, (char_u)'2'},
- {MOD_MASK_3CLICK, (char_u)'3'},
- {MOD_MASK_4CLICK, (char_u)'4'},
- #ifdef macintosh
- {MOD_MASK_CMD, (char_u)'D'},
- #endif
- {0x0, NUL}
- };
- /*
- * Shifted key terminal codes and their unshifted equivalent.
- * Don't add mouse codes here, they are handled seperately!
- */
- static char_u shifted_keys_table[] =
- {
- /* shifted unshifted */
- '&', '9', '@', '1', /* begin */
- '&', '0', '@', '2', /* cancel */
- '*', '1', '@', '4', /* command */
- '*', '2', '@', '5', /* copy */
- '*', '3', '@', '6', /* create */
- '*', '4', 'k', 'D', /* delete char */
- '*', '5', 'k', 'L', /* delete line */
- '*', '7', '@', '7', /* end */
- '*', '9', '@', '9', /* exit */
- '*', '0', '@', '0', /* find */
- '#', '1', '%', '1', /* help */
- '#', '2', 'k', 'h', /* home */
- '#', '3', 'k', 'I', /* insert */
- '#', '4', 'k', 'l', /* left arrow */
- '%', 'a', '%', '3', /* message */
- '%', 'b', '%', '4', /* move */
- '%', 'c', '%', '5', /* next */
- '%', 'd', '%', '7', /* options */
- '%', 'e', '%', '8', /* previous */
- '%', 'f', '%', '9', /* print */
- '%', 'g', '%', '0', /* redo */
- '%', 'h', '&', '3', /* replace */
- '%', 'i', 'k', 'r', /* right arrow */
- '%', 'j', '&', '5', /* resume */
- '!', '1', '&', '6', /* save */
- '!', '2', '&', '7', /* suspend */
- '!', '3', '&', '8', /* undo */
- KS_EXTRA, (int)KE_S_UP, 'k', 'u', /* up arrow */
- KS_EXTRA, (int)KE_S_DOWN, 'k', 'd', /* down arrow */
- KS_EXTRA, (int)KE_S_F1, 'k', '1', /* F1 */
- KS_EXTRA, (int)KE_S_F2, 'k', '2',
- KS_EXTRA, (int)KE_S_F3, 'k', '3',
- KS_EXTRA, (int)KE_S_F4, 'k', '4',
- KS_EXTRA, (int)KE_S_F5, 'k', '5',
- KS_EXTRA, (int)KE_S_F6, 'k', '6',
- KS_EXTRA, (int)KE_S_F7, 'k', '7',
- KS_EXTRA, (int)KE_S_F8, 'k', '8',
- KS_EXTRA, (int)KE_S_F9, 'k', '9',
- KS_EXTRA, (int)KE_S_F10, 'k', ';', /* F10 */
- KS_EXTRA, (int)KE_S_F11, 'F', '1',
- KS_EXTRA, (int)KE_S_F12, 'F', '2',
- KS_EXTRA, (int)KE_S_F13, 'F', '3',
- KS_EXTRA, (int)KE_S_F14, 'F', '4',
- KS_EXTRA, (int)KE_S_F15, 'F', '5',
- KS_EXTRA, (int)KE_S_F16, 'F', '6',
- KS_EXTRA, (int)KE_S_F17, 'F', '7',
- KS_EXTRA, (int)KE_S_F18, 'F', '8',
- KS_EXTRA, (int)KE_S_F19, 'F', '9',
- KS_EXTRA, (int)KE_S_F20, 'F', 'A',
- KS_EXTRA, (int)KE_S_F21, 'F', 'B',
- KS_EXTRA, (int)KE_S_F22, 'F', 'C',
- KS_EXTRA, (int)KE_S_F23, 'F', 'D',
- KS_EXTRA, (int)KE_S_F24, 'F', 'E',
- KS_EXTRA, (int)KE_S_F25, 'F', 'F',
- KS_EXTRA, (int)KE_S_F26, 'F', 'G',
- KS_EXTRA, (int)KE_S_F27, 'F', 'H',
- KS_EXTRA, (int)KE_S_F28, 'F', 'I',
- KS_EXTRA, (int)KE_S_F29, 'F', 'J',
- KS_EXTRA, (int)KE_S_F30, 'F', 'K',
- KS_EXTRA, (int)KE_S_F31, 'F', 'L',
- KS_EXTRA, (int)KE_S_F32, 'F', 'M',
- KS_EXTRA, (int)KE_S_F33, 'F', 'N',
- KS_EXTRA, (int)KE_S_F34, 'F', 'O',
- KS_EXTRA, (int)KE_S_F35, 'F', 'P',
- KS_EXTRA, (int)KE_S_TAB, KS_EXTRA, (int)KE_TAB, /* TAB pseudo code*/
- NUL
- };
- static struct key_name_entry
- {
- int key; /* Special key code or ascii value */
- char_u *name; /* Name of key */
- } key_names_table[] =
- {
- {' ', (char_u *)"Space"},
- {TAB, (char_u *)"Tab"},
- {K_TAB, (char_u *)"Tab"},
- {NL, (char_u *)"NL"},
- {NL, (char_u *)"NewLine"}, /* Alternative name */
- {NL, (char_u *)"LineFeed"}, /* Alternative name */
- {NL, (char_u *)"LF"}, /* Alternative name */
- {CR, (char_u *)"CR"},
- {CR, (char_u *)"Return"}, /* Alternative name */
- {K_BS, (char_u *)"BS"},
- {K_BS, (char_u *)"BackSpace"}, /* Alternative name */
- {ESC, (char_u *)"Esc"},
- {'|', (char_u *)"Bar"},
- {'\', (char_u *)"Bslash"},
- {K_DEL, (char_u *)"Del"},
- {K_DEL, (char_u *)"Delete"}, /* Alternative name */
- {K_UP, (char_u *)"Up"},
- {K_DOWN, (char_u *)"Down"},
- {K_LEFT, (char_u *)"Left"},
- {K_RIGHT, (char_u *)"Right"},
- {K_F1, (char_u *)"F1"},
- {K_F2, (char_u *)"F2"},
- {K_F3, (char_u *)"F3"},
- {K_F4, (char_u *)"F4"},
- {K_F5, (char_u *)"F5"},
- {K_F6, (char_u *)"F6"},
- {K_F7, (char_u *)"F7"},
- {K_F8, (char_u *)"F8"},
- {K_F9, (char_u *)"F9"},
- {K_F10, (char_u *)"F10"},
- {K_F11, (char_u *)"F11"},
- {K_F12, (char_u *)"F12"},
- {K_F13, (char_u *)"F13"},
- {K_F14, (char_u *)"F14"},
- {K_F15, (char_u *)"F15"},
- {K_F16, (char_u *)"F16"},
- {K_F17, (char_u *)"F17"},
- {K_F18, (char_u *)"F18"},
- {K_F19, (char_u *)"F19"},
- {K_F20, (char_u *)"F20"},
- {K_F21, (char_u *)"F21"},
- {K_F22, (char_u *)"F22"},
- {K_F23, (char_u *)"F23"},
- {K_F24, (char_u *)"F24"},
- {K_F25, (char_u *)"F25"},
- {K_F26, (char_u *)"F26"},
- {K_F27, (char_u *)"F27"},
- {K_F28, (char_u *)"F28"},
- {K_F29, (char_u *)"F29"},
- {K_F30, (char_u *)"F30"},
- {K_F31, (char_u *)"F31"},
- {K_F32, (char_u *)"F32"},
- {K_F33, (char_u *)"F33"},
- {K_F34, (char_u *)"F34"},
- {K_F35, (char_u *)"F35"},
- {K_XF1, (char_u *)"F1"},
- {K_XF2, (char_u *)"F2"},
- {K_XF3, (char_u *)"F3"},
- {K_XF4, (char_u *)"F4"},
- {K_HELP, (char_u *)"Help"},
- {K_UNDO, (char_u *)"Undo"},
- {K_INS, (char_u *)"Insert"},
- {K_INS, (char_u *)"Ins"}, /* Alternative name */
- {K_HOME, (char_u *)"Home"},
- {K_END, (char_u *)"End"},
- {K_PAGEUP, (char_u *)"PageUp"},
- {K_PAGEDOWN, (char_u *)"PageDown"},
- {K_KHOME, (char_u *)"kHome"},
- {K_KEND, (char_u *)"kEnd"},
- {K_KPAGEUP, (char_u *)"kPageUp"},
- {K_KPAGEDOWN, (char_u *)"kPageDown"},
- {K_KPLUS, (char_u *)"kPlus"},
- {K_KMINUS, (char_u *)"kMinus"},
- {K_KDIVIDE, (char_u *)"kDivide"},
- {K_KMULTIPLY, (char_u *)"kMultiply"},
- {K_KENTER, (char_u *)"kEnter"},
- {'<', (char_u *)"lt"},
- {K_MOUSE, (char_u *)"Mouse"},
- {K_LEFTMOUSE, (char_u *)"LeftMouse"},
- {K_LEFTDRAG, (char_u *)"LeftDrag"},
- {K_LEFTRELEASE, (char_u *)"LeftRelease"},
- {K_MIDDLEMOUSE, (char_u *)"MiddleMouse"},
- {K_MIDDLEDRAG, (char_u *)"MiddleDrag"},
- {K_MIDDLERELEASE, (char_u *)"MiddleRelease"},
- {K_RIGHTMOUSE, (char_u *)"RightMouse"},
- {K_RIGHTDRAG, (char_u *)"RightDrag"},
- {K_RIGHTRELEASE, (char_u *)"RightRelease"},
- {K_ZERO, (char_u *)"Nul"},
- {0, NULL}
- };
- #define KEY_NAMES_TABLE_LEN (sizeof(key_names_table) / sizeof(struct key_name_entry))
- #ifdef USE_MOUSE
- static struct mousetable
- {
- int pseudo_code; /* Code for pseudo mouse event */
- int button; /* Which mouse button is it? */
- int is_click; /* Is it a mouse button click event? */
- int is_drag; /* Is it a mouse drag event? */
- } mouse_table[] =
- {
- {(int)KE_LEFTMOUSE, MOUSE_LEFT, TRUE, FALSE},
- {(int)KE_LEFTDRAG, MOUSE_LEFT, FALSE, TRUE},
- {(int)KE_LEFTRELEASE, MOUSE_LEFT, FALSE, FALSE},
- {(int)KE_MIDDLEMOUSE, MOUSE_MIDDLE, TRUE, FALSE},
- {(int)KE_MIDDLEDRAG, MOUSE_MIDDLE, FALSE, TRUE},
- {(int)KE_MIDDLERELEASE, MOUSE_MIDDLE, FALSE, FALSE},
- {(int)KE_RIGHTMOUSE, MOUSE_RIGHT, TRUE, FALSE},
- {(int)KE_RIGHTDRAG, MOUSE_RIGHT, FALSE, TRUE},
- {(int)KE_RIGHTRELEASE, MOUSE_RIGHT, FALSE, FALSE},
- /* DRAG without CLICK */
- {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, TRUE},
- /* RELEASE without CLICK */
- {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, FALSE},
- {0, 0, 0, 0},
- };
- #endif /* USE_MOUSE */
- /*
- * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given
- * modifier name ('S' for Shift, 'C' for Ctrl etc).
- */
- int
- name_to_mod_mask(c)
- int c;
- {
- int i;
- for (i = 0; mod_mask_table[i].mod_mask; i++)
- if (TO_LOWER(c) == TO_LOWER(mod_mask_table[i].name))
- return mod_mask_table[i].mod_mask;
- return 0x0;
- }
- /*
- * Decide whether the given key code (K_*) is a shifted special
- * key (by looking at mod_mask). If it is, then return the appropriate shifted
- * key code, otherwise just return the character as is.
- */
- int
- check_shifted_spec_key(c)
- int c;
- {
- return simplify_key(c, &mod_mask);
- }
- /*
- * Check if if there is a special key code for "key" that includes the
- * modifiers specified.
- */
- int
- simplify_key(key, modifiers)
- int key;
- int *modifiers;
- {
- int i;
- int key0;
- int key1;
- if (*modifiers & MOD_MASK_SHIFT)
- {
- if (key == TAB) /* TAB is a special case */
- {
- *modifiers &= ~MOD_MASK_SHIFT;
- return K_S_TAB;
- }
- key0 = KEY2TERMCAP0(key);
- key1 = KEY2TERMCAP1(key);
- for (i = 0; shifted_keys_table[i] != NUL; i += 4)
- if (key0 == shifted_keys_table[i + 2] &&
- key1 == shifted_keys_table[i + 3])
- {
- *modifiers &= ~MOD_MASK_SHIFT;
- return TERMCAP2KEY(shifted_keys_table[i],
- shifted_keys_table[i + 1]);
- }
- }
- return key;
- }
- /*
- * Return a string which contains the name of the given key when the given
- * modifiers are down.
- */
- char_u *
- get_special_key_name(c, modifiers)
- int c;
- int modifiers;
- {
- static char_u string[MAX_KEY_NAME_LEN + 1];
- int i, idx;
- int table_idx;
- char_u *s;
- string[0] = '<';
- idx = 1;
- /*
- * Translate shifted special keys into unshifted keys and set modifier.
- */
- if (IS_SPECIAL(c))
- {
- for (i = 0; shifted_keys_table[i]; i += 4)
- if ( KEY2TERMCAP0(c) == shifted_keys_table[i]
- && KEY2TERMCAP1(c) == shifted_keys_table[i + 1])
- {
- modifiers |= MOD_MASK_SHIFT;
- c = TERMCAP2KEY(shifted_keys_table[i + 2],
- shifted_keys_table[i + 3]);
- break;
- }
- }
- /* try to find the key in the special key table */
- table_idx = find_special_key_in_table(c);
- /*
- * When not a known special key, and not a printable character, try to
- * extract modifiers.
- */
- if (table_idx < 0 && (!vim_isprintc(c) || (c & 0x7f) == ' ') && (c & 0x80))
- {
- c &= 0x7f;
- modifiers |= MOD_MASK_ALT;
- /* try again, to find the un-alted key in the special key table */
- table_idx = find_special_key_in_table(c);
- }
- if (table_idx < 0 && !vim_isprintc(c) && c < ' ')
- {
- c += '@';
- modifiers |= MOD_MASK_CTRL;
- }
- /* translate the modifier into a string */
- for (i = 0; mod_mask_table[i].mod_mask; i++)
- if (modifiers & mod_mask_table[i].mod_mask)
- {
- string[idx++] = mod_mask_table[i].name;
- string[idx++] = (char_u)'-';
- }
- if (table_idx < 0) /* unknown special key, output t_xx */
- {
- if (IS_SPECIAL(c))
- {
- string[idx++] = 't';
- string[idx++] = '_';
- string[idx++] = KEY2TERMCAP0(c);
- string[idx++] = KEY2TERMCAP1(c);
- }
- /* Not a special key, only modifiers, output directly */
- else
- {
- if (vim_isprintc(c))
- string[idx++] = c;
- else
- {
- s = transchar(c);
- while (*s)
- string[idx++] = *s++;
- }
- }
- }
- else /* use name of special key */
- {
- STRCPY(string + idx, key_names_table[table_idx].name);
- idx = STRLEN(string);
- }
- string[idx++] = '>';
- string[idx] = NUL;
- return string;
- }
- /*
- * Try translating a <> name at (*srcp)[] to dst[].
- * Return the number of characters added to dst[], zero for no match.
- * If there is a match, srcp is advanced to after the <> name.
- * dst[] must be big enough to hold the result (up to six characters)!
- */
- int
- trans_special(srcp, dst, keycode)
- char_u **srcp;
- char_u *dst;
- int keycode; /* prefer key code, e.g. K_DEL instead of DEL */
- {
- int modifiers;
- int key;
- int dlen = 0;
- key = find_special_key(srcp, &modifiers, keycode);
- if (key == 0)
- return 0;
- /* Put the appropriate modifier in a string */
- if (modifiers != 0)
- {
- dst[dlen++] = K_SPECIAL;
- dst[dlen++] = KS_MODIFIER;
- dst[dlen++] = modifiers;
- }
- if (IS_SPECIAL(key))
- {
- dst[dlen++] = K_SPECIAL;
- dst[dlen++] = KEY2TERMCAP0(key);
- dst[dlen++] = KEY2TERMCAP1(key);
- }
- else
- dst[dlen++] = key;
- return dlen;
- }
- /*
- * Try translating a <> name at (*srcp)[], return the key and modifiers.
- * srcp is advanced to after the <> name.
- * returns 0 if there is no match.
- */
- int
- find_special_key(srcp, modp, keycode)
- char_u **srcp;
- int *modp;
- int keycode; /* prefer key code, e.g. K_DEL instead of DEL */
- {
- char_u *last_dash;
- char_u *end_of_name;
- char_u *src;
- char_u *bp;
- int modifiers;
- int bit;
- int key;
- src = *srcp;
- if (src[0] != '<')
- return 0;
- /* Find end of modifier list */
- last_dash = src;
- for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++)
- {
- if (*bp == '-')
- {
- last_dash = bp;
- if (bp[1] != NUL && bp[2] == '>')
- ++bp; /* anything accepted, like <C-?> */
- }
- if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
- bp += 3; /* skip t_xx, xx may be '-' or '>' */
- }
- if (*bp == '>') /* found matching '>' */
- {
- end_of_name = bp + 1;
- /* Which modifiers are given? */
- modifiers = 0x0;
- for (bp = src + 1; bp < last_dash; bp++)
- {
- if (*bp != '-')
- {
- bit = name_to_mod_mask(*bp);
- if (bit == 0x0)
- break; /* Illegal modifier name */
- modifiers |= bit;
- }
- }
- /*
- * Legal modifier name.
- */
- if (bp >= last_dash)
- {
- /*
- * Modifier with single letter, or special key name.
- */
- if (modifiers != 0 && last_dash[2] == '>')
- key = last_dash[1];
- else
- key = get_special_key_code(last_dash + 1);
- /*
- * get_special_key_code() may return NUL for invalid
- * special key name.
- */
- if (key != NUL)
- {
- /*
- * Only use a modifier when there is no special key code that
- * includes the modifier.
- */
- key = simplify_key(key, &modifiers);
- if (!keycode)
- {
- /* don't want keycode, use single byte code */
- if (key == K_BS)
- key = BS;
- else if (key == K_DEL)
- key = DEL;
- }
- /*
- * Normal Key with modifier: Try to make a single byte code.
- */
- if (!IS_SPECIAL(key))
- {
- if ((modifiers & MOD_MASK_SHIFT) && isalpha(key))
- {
- key = TO_UPPER(key);
- modifiers &= ~MOD_MASK_SHIFT;
- }
- if ((modifiers & MOD_MASK_CTRL)
- && ((key >= '?' && key <= '_') || isalpha(key)))
- {
- if (key == '?')
- key = DEL;
- else
- key &= 0x1f;
- modifiers &= ~MOD_MASK_CTRL;
- }
- if ((modifiers & MOD_MASK_ALT) && key < 0x80)
- {
- key |= 0x80;
- modifiers &= ~MOD_MASK_ALT;
- }
- }
- *modp = modifiers;
- *srcp = end_of_name;
- return key;
- }
- }
- }
- return 0;
- }
- /*
- * Try to find key "c" in the special key table.
- * Return the index when found, -1 when not found.
- */
- int
- find_special_key_in_table(c)
- int c;
- {
- int i;
- for (i = 0; key_names_table[i].name != NULL; i++)
- if (c == key_names_table[i].key)
- break;
- if (key_names_table[i].name == NULL)
- i = -1;
- return i;
- }
- /*
- * Find the special key with the given name (the given string does not have to
- * end with NUL, the name is assumed to end before the first non-idchar).
- * If the name starts with "t_" the next two characters are interpreted as a
- * termcap name.
- * Return the key code, or 0 if not found.
- */
- int
- get_special_key_code(name)
- char_u *name;
- {
- char_u *table_name;
- char_u string[3];
- int i, j;
- /*
- * If it's <t_xx> we get the code for xx from the termcap
- */
- if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL)
- {
- string[0] = name[2];
- string[1] = name[3];
- string[2] = NUL;
- if (add_termcap_entry(string, FALSE) == OK)
- return TERMCAP2KEY(name[2], name[3]);
- }
- else
- for (i = 0; key_names_table[i].name != NULL; i++)
- {
- table_name = key_names_table[i].name;
- for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++)
- if (TO_LOWER(table_name[j]) != TO_LOWER(name[j]))
- break;
- if (!vim_isIDc(name[j]) && table_name[j] == NUL)
- return key_names_table[i].key;
- }
- return 0;
- }
- char_u *
- get_key_name(i)
- int i;
- {
- if (i >= KEY_NAMES_TABLE_LEN)
- return NULL;
- return key_names_table[i].name;
- }
- #ifdef USE_MOUSE
- /*
- * Look up the given mouse code to return the relevant information in the other
- * arguments. Return which button is down or was released.
- */
- int
- get_mouse_button(code, is_click, is_drag)
- int code;
- int *is_click;
- int *is_drag;
- {
- int i;
- for (i = 0; mouse_table[i].pseudo_code; i++)
- if (code == mouse_table[i].pseudo_code)
- {
- *is_click = mouse_table[i].is_click;
- *is_drag = mouse_table[i].is_drag;
- return mouse_table[i].button;
- }
- return 0; /* Shouldn't get here */
- }
- /*
- * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on
- * the given information about which mouse button is down, and whether the
- * mouse was clicked, dragged or released.
- */
- int
- get_pseudo_mouse_code(button, is_click, is_drag)
- int button; /* eg MOUSE_LEFT */
- int is_click;
- int is_drag;
- {
- int i;
- for (i = 0; mouse_table[i].pseudo_code; i++)
- if (button == mouse_table[i].button
- && is_click == mouse_table[i].is_click
- && is_drag == mouse_table[i].is_drag)
- {
- return mouse_table[i].pseudo_code;
- }
- return (int)KE_IGNORE; /* not recongnized, ignore it */
- }
- #endif /* USE_MOUSE */
- /*
- * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
- */
- int
- get_fileformat(buf)
- BUF *buf;
- {
- int c = *buf->b_p_ff;
- if (buf->b_p_bin || c == 'u')
- return EOL_UNIX;
- if (c == 'm')
- return EOL_MAC;
- return EOL_DOS;
- }
- /*
- * Set the current end-of-line type to EOL_DOS, EOL_UNIX or EOL_MAC.
- * Sets both 'textmode' and 'fileformat'.
- */
- void
- set_fileformat(t)
- int t;
- {
- switch (t)
- {
- case EOL_DOS:
- set_string_option_direct((char_u *)"ff", -1, (char_u *)FF_DOS, TRUE);
- curbuf->b_p_tx = TRUE;
- break;
- case EOL_UNIX:
- set_string_option_direct((char_u *)"ff", -1, (char_u *)FF_UNIX, TRUE);
- curbuf->b_p_tx = FALSE;
- break;
- case EOL_MAC:
- set_string_option_direct((char_u *)"ff", -1, (char_u *)FF_MAC, TRUE);
- curbuf->b_p_tx = FALSE;
- break;
- }
- check_status(curbuf);
- }
- /*
- * Return the default fileformat from 'fileformats'.
- */
- int
- default_fileformat()
- {
- switch (*p_ffs)
- {
- case 'm': return EOL_MAC;
- case 'd': return EOL_DOS;
- }
- return EOL_UNIX;
- }
- /*
- * Call shell. Calls mch_call_shell, with 'shellxquote' added.
- */
- int
- call_shell(cmd, opt)
- char_u *cmd;
- int opt;
- {
- char_u *ncmd;
- #ifdef USE_GUI_WIN32
- /* Don't hide the pointer while executing a shell command. */
- gui_mch_mousehide(FALSE);
- #endif
- if (cmd == NULL || *p_sxq == NUL)
- call_shell_retval = mch_call_shell(cmd, opt);
- else
- {
- ncmd = alloc((unsigned)(STRLEN(cmd) + STRLEN(p_sxq) * 2 + 1));
- if (ncmd != NULL)
- {
- STRCPY(ncmd, p_sxq);
- STRCAT(ncmd, cmd);
- STRCAT(ncmd, p_sxq);
- call_shell_retval = mch_call_shell(ncmd, opt);
- vim_free(ncmd);
- }
- else
- call_shell_retval = -1;
- }
- return call_shell_retval;
- }
- /*
- * VISUAL and OP_PENDING State are never set, they are equal to NORMAL State
- * with a condition. This function returns the real State.
- */
- int
- get_real_state()
- {
- if ((State & NORMAL))
- {
- if (VIsual_active)
- return VISUAL;
- else if (finish_op)
- return OP_PENDING;
- }
- return State;
- }
- /*
- * Change to a file's directory.
- */
- int
- vim_chdirfile(fname)
- char_u *fname;
- {
- char_u temp_string[MAXPATHL];
- char_u *p;
- char_u *t;
- STRCPY(temp_string, fname);
- p = get_past_head(temp_string);
- t = gettail(temp_string);
- while (t > p && vim_ispathsep(t[-1]))
- --t;
- *t = NUL; /* chop off end of string */
- return mch_chdir((char *)temp_string);
- }
- #ifdef CURSOR_SHAPE
- /*
- * Handling of cursor shapes in various modes.
- */
- struct cursor_entry cursor_table[SHAPE_COUNT] =
- {
- /* The values will be filled in from the guicursor' default when the GUI
- * starts. */
- {0, 0, 700L, 400L, 250L, 0, "n"},
- {0, 0, 700L, 400L, 250L, 0, "v"},
- {0, 0, 700L, 400L, 250L, 0, "i"},
- {0, 0, 700L, 400L, 250L, 0, "r"},
- {0, 0, 700L, 400L, 250L, 0, "c"},
- {0, 0, 700L, 400L, 250L, 0, "ci"},
- {0, 0, 700L, 400L, 250L, 0, "cr"},
- {0, 0, 100L, 100L, 100L, 0, "sm"},
- {0, 0, 700L, 400L, 250L, 0, "o"},
- {0, 0, 700L, 400L, 250L, 0, "ve"}
- };
- /*
- * Parse the 'guicursor' option.
- * Returns error message for an illegal option, NULL otherwise.
- */
- char_u *
- parse_guicursor()
- {
- char_u *modep;
- char_u *colonp;
- char_u *commap;
- char_u *p, *endp;
- int idx = 0; /* init for GCC */
- int all_idx;
- int len;
- int i;
- long n;
- int found_ve = FALSE; /* found "ve" flag */
- /*
- * Repeat for all comma separated parts.
- */
- modep = p_guicursor;
- while (*modep)
- {
- colonp = vim_strchr(modep, ':');
- if (colonp == NULL)
- return (char_u *)"Missing colon";
- commap = vim_strchr(modep, ',');
- /*
- * Repeat for all mode's before the colon.
- * For the 'a' mode, we loop to handle all the modes.
- */
- all_idx = -1;
- while (modep < colonp || all_idx >= 0)
- {
- if (all_idx < 0)
- {
- /* Find the mode. */
- if (modep[1] == '-' || modep[1] == ':')
- len = 1;
- else
- len = 2;
- if (len == 1 && TO_LOWER(modep[0]) == 'a')
- all_idx = SHAPE_COUNT - 1;
- else
- {
- for (idx = 0; idx < SHAPE_COUNT; ++idx)
- if (STRNICMP(modep, cursor_table[idx].name, len) == 0)
- break;
- if (idx == SHAPE_COUNT)
- return (char_u *)"Illegal mode";
- if (len == 2 && modep[0] == 'v' && modep[1] == 'e')
- found_ve = TRUE;
- }
- modep += len + 1;
- }
- if (all_idx >= 0)
- idx = all_idx--;
- else
- {
- /* Set the defaults, for the missing parts */
- cursor_table[idx].shape = SHAPE_BLOCK;
- cursor_table[idx].blinkwait = 700L;
- cursor_table[idx].blinkon = 400L;
- cursor_table[idx].blinkoff = 250L;
- }
- /* Parse the part after the colon */
- for (p = colonp + 1; *p && *p != ','; )
- {
- /*
- * First handle the ones with a number argument.
- */
- i = *p;
- len = 0;
- if (STRNICMP(p, "ver", 3) == 0)
- len = 3;
- else if (STRNICMP(p, "hor", 3) == 0)
- len = 3;
- else if (STRNICMP(p, "blinkwait", 9) == 0)
- len = 9;
- else if (STRNICMP(p, "blinkon", 7) == 0)
- len = 7;
- else if (STRNICMP(p, "blinkoff", 8) == 0)
- len = 8;
- if (len)
- {
- p += len;
- if (!isdigit(*p))
- return (char_u *)"digit expected";
- n = getdigits(&p);
- if (len == 3) /* "ver" or "hor" */
- {
- if (n == 0)
- return (char_u *)"Illegal percentage";
- if (TO_LOWER(i) == 'v')
- cursor_table[idx].shape = SHAPE_VER;
- else
- cursor_table[idx].shape = SHAPE_HOR;
- cursor_table[idx].percentage = n;
- }
- else if (len == 9)
- cursor_table[idx].blinkwait = n;
- else if (len == 7)
- cursor_table[idx].blinkon = n;
- else
- cursor_table[idx].blinkoff = n;
- }
- else if (STRNICMP(p, "block", 5) == 0)
- {
- cursor_table[idx].shape = SHAPE_BLOCK;
- p += 5;
- }
- else /* must be a highlight group name then */
- {
- endp = vim_strchr(p, '-');
- if (commap == NULL) /* last part */
- {
- if (endp == NULL)
- endp = p + STRLEN(p); /* find end of part */
- }
- else if (endp > commap || endp == NULL)
- endp = commap;
- cursor_table[idx].id = syn_check_group(p, (int)(endp - p));
- p = endp;
- }
- if (*p == '-')
- ++p;
- }
- }
- modep = p;
- if (*modep == ',')
- ++modep;
- }
- /* If the 's' flag is not given, use the 'v' cursor for 's' */
- if (!found_ve)
- {
- cursor_table[SHAPE_VE].shape = cursor_table[SHAPE_V].shape;
- cursor_table[SHAPE_VE].percentage = cursor_table[SHAPE_V].percentage;
- cursor_table[SHAPE_VE].blinkwait = cursor_table[SHAPE_V].blinkwait;
- cursor_table[SHAPE_VE].blinkon = cursor_table[SHAPE_V].blinkon;
- cursor_table[SHAPE_VE].blinkoff = cursor_table[SHAPE_V].blinkoff;
- cursor_table[SHAPE_VE].id = cursor_table[SHAPE_V].id;
- }
- return NULL;
- }
- /*
- * Return the index into cursor_table[] for the current mode.
- */
- int
- get_cursor_idx()
- {
- if (State == SHOWMATCH)
- return SHAPE_SM;
- if (State == INSERT)
- return SHAPE_I;
- if (State == REPLACE)
- return SHAPE_R;
- if (State == CMDLINE)
- {
- if (cmdline_at_end())
- return SHAPE_C;
- if (cmdline_overstrike())
- return SHAPE_CR;
- return SHAPE_CI;
- }
- if (finish_op)
- return SHAPE_O;
- if (VIsual_active)
- {
- if (*p_sel == 'e')
- return SHAPE_VE;
- else
- return SHAPE_V;
- }
- return SHAPE_N;
- }
- #endif /* CURSOR_SHAPE */