/* * Initialise vim to use the font with the given name. Return FAIL if the font * could not be loaded, OK otherwise. */ int gui_mch_init_font(char_u *font_name, int fontset) { vimjs_init_font((char*)font_name); gui.char_width = vimjs_get_char_width(); gui.char_height = vimjs_get_char_height(); gui.char_ascent = gui.char_height; char_u buf[100]; gui.norm_font = vim_strsave(font_name); vim_strncpy(buf, "bold ", 99); // should report 1 less to vim_strncpy vim_strcat(buf, font_name, 100); gui.bold_font = vim_strsave(buf); vim_strncpy(buf, "italic ", 99); // should report 1 less to vim_strncpy vim_strcat(buf, font_name, 100); gui.ital_font = vim_strsave(buf); vim_strncpy(buf, "bold italic ", 99); // should report 1 less to vim_strncpy vim_strcat(buf, font_name, 100); gui.boldital_font = vim_strsave(buf); int w,h; w = vimjs_get_window_width(); h = vimjs_get_window_height(); gui_resize_shell(w, h); return OK; }
/* * For an xtended filemark: set the fnum from the fname. * This is used for marks obtained from the .viminfo file. It's postponed * until the mark is used to avoid a long startup delay. */ static void fname2fnum(xfmark_T *fm) { char_u *p; if (fm->fname != NULL) { /* * First expand "~/" in the file name to the home directory. * Don't expand the whole name, it may contain other '~' chars. */ if (fm->fname[0] == '~' && (fm->fname[1] == '/' #ifdef BACKSLASH_IN_FILENAME || fm->fname[1] == '\\' #endif )) { int len; expand_env((char_u *)"~/", NameBuff, MAXPATHL); len = (int)STRLEN(NameBuff); vim_strncpy(NameBuff + len, fm->fname + 2, MAXPATHL - len - 1); } else vim_strncpy(NameBuff, fm->fname, MAXPATHL - 1); /* Try to shorten the file name. */ mch_dirname(IObuff, IOSIZE); p = shorten_fname(NameBuff, IObuff); /* buflist_new() will call fmarks_check_names() */ (void)buflist_new(NameBuff, p, (linenr_T)1, 0); } }
int OpenPTY(char **ttyn) { int f; /* used for opening a new pty-pair: */ static char TtyName[32]; /* a dumb looking loop replaced by mycrofts code: */ if ((f = open("/dev/ptc", O_RDWR | O_NOCTTY | O_EXTRA)) < 0) return -1; vim_strncpy((char_u *)TtyName, (char_u *)ttyname(f), sizeof(TtyName) - 1); if (geteuid() != ROOT_UID && mch_access(TtyName, R_OK | W_OK)) { close(f); return -1; } initmaster(f); # ifdef _IBMR2 if (aixhack >= 0) close(aixhack); if ((aixhack = open(TtyName, O_RDWR | O_NOCTTY | O_EXTRA, 0)) < 0) { close(f); return -1; } # endif *ttyn = TtyName; return f; }
int OpenPTY(char **ttyn) { int f; char *m; char *(ptsname(int)); int unlockpt(int); int grantpt(int); RETSIGTYPE (*sigcld) SIGPROTOARG; /* used for opening a new pty-pair: */ static char TtyName[32]; if ((f = open("/dev/ptmx", O_RDWR | O_NOCTTY | O_EXTRA, 0)) == -1) return -1; /* * SIGCHLD set to SIG_DFL for grantpt() because it fork()s and * exec()s pt_chmod */ sigcld = signal(SIGCHLD, SIG_DFL); if ((m = ptsname(f)) == NULL || grantpt(f) || unlockpt(f)) { signal(SIGCHLD, sigcld); close(f); return -1; } signal(SIGCHLD, sigcld); vim_strncpy((char_u *)TtyName, (char_u *)m, sizeof(TtyName) - 1); initmaster(f); *ttyn = TtyName; return f; }
/* * Find item "key[len]" in Dictionary "d". * If "len" is negative use strlen(key). * Returns NULL when not found. */ dictitem_T * dict_find(dict_T *d, char_u *key, int len) { #define AKEYLEN 200 char_u buf[AKEYLEN]; char_u *akey; char_u *tofree = NULL; hashitem_T *hi; if (d == NULL) return NULL; if (len < 0) akey = key; else if (len >= AKEYLEN) { tofree = akey = vim_strnsave(key, len); if (akey == NULL) return NULL; } else { /* Avoid a malloc/free by using buf[]. */ vim_strncpy(buf, key, len); akey = buf; } hi = hash_find(&d->dv_hashtab, akey); vim_free(tofree); if (HASHITEM_EMPTY(hi)) return NULL; return HI2DI(hi); }
int os_dirname(char_u *buf, size_t len) { assert(buf && len); int errno; if ((errno = uv_cwd((char *)buf, &len)) != 0) { vim_strncpy(buf, (char_u *)uv_strerror(errno), len - 1); return FAIL; } return OK; }
int OpenPTY(char **ttyn) { char *m, *s; int f; /* used for opening a new pty-pair: */ static char PtyName[32]; static char TtyName[32]; if ((f = getpseudotty(&s, &m)) < 0) return -1; #ifdef _SEQUENT_ fvhangup(s); #endif vim_strncpy((char_u *)PtyName, (char_u *)m, sizeof(PtyName) - 1); vim_strncpy((char_u *)TtyName, (char_u *)s, sizeof(TtyName) - 1); initmaster(f); *ttyn = TtyName; return f; }
void clip_mch_set_selection(VimClipboard *cbd) { int type; long_u len; char_u *text_clip, vim_clip[2], *str = NULL; PhClipHeader clip_header[2]; /* Prevent recursion from clip_get_selection() */ if (cbd->owned == TRUE) return; cbd->owned = TRUE; clip_get_selection(cbd); cbd->owned = FALSE; type = clip_convert_selection(&str, &len, cbd); if (type >= 0) { text_clip = lalloc(len + 1, TRUE); /* Normal text */ if (text_clip && vim_clip) { memset(clip_header, 0, sizeof(clip_header)); STRNCPY(clip_header[0].type, CLIP_TYPE_VIM, 8); clip_header[0].length = sizeof(vim_clip); clip_header[0].data = vim_clip; STRNCPY(clip_header[1].type, CLIP_TYPE_TEXT, 8); clip_header[1].length = len + 1; clip_header[1].data = text_clip; switch(type) { default: /* fallthrough to MLINE */ case MLINE: *vim_clip = 'L'; break; case MCHAR: *vim_clip = 'C'; break; case MBLOCK: *vim_clip = 'B'; break; } vim_strncpy(text_clip, str, len); vim_clip[ 1 ] = NUL; PhClipboardCopy(PhInputGroup(NULL), 2, clip_header); } vim_free(text_clip); } vim_free(str); }
// Insert user name for "uid" in s[len]. // Return OK if a name found. // If the name is not found, write the uid into s[len] and return FAIL. int os_get_uname(uid_t uid, char *s, size_t len) { #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID) struct passwd *pw; if ((pw = getpwuid(uid)) != NULL && pw->pw_name != NULL && *(pw->pw_name) != NUL) { vim_strncpy((char_u *)s, (char_u *)pw->pw_name, len - 1); return OK; } #endif snprintf(s, len, "%d", (int)uid); return FAIL; // a number is not a name }
/* * Return TRUE if "name" can be found in $PATH and executed, FALSE if not or an * error occurs. */ static int is_executable_in_path(const char_u *name) { const char *path = getenv("PATH"); /* PATH environment variable does not exist or is empty. */ if (path == NULL || *path == NUL) { return FALSE; } int buf_len = STRLEN(name) + STRLEN(path) + 2; char_u *buf = alloc((unsigned)(buf_len)); if (buf == NULL) { return FALSE; } /* * Walk through all entries in $PATH to check if "name" exists there and * is an executable file. */ for (;; ) { const char *e = strchr(path, ':'); if (e == NULL) { e = path + STRLEN(path); } /* Glue together the given directory from $PATH with name and save into * buf. */ vim_strncpy(buf, (char_u *) path, e - path); append_path((char *) buf, (const char *) name, buf_len); if (is_executable(buf)) { /* Found our executable. Free buf and return. */ vim_free(buf); return OK; } if (*e != ':') { /* End of $PATH without finding any executable called name. */ vim_free(buf); return FALSE; } path = e + 1; } /* We should never get to this point. */ assert(false); return FALSE; }
/* * Split a string into parts to display in the balloon. * Aimed at output from gdb. Attempts to split at white space, preserve quoted * strings and make a struct look good. * Resulting array is stored in "array" and returns the size of the array. */ int split_message(char_u *mesg, pumitem_T **array) { garray_T ga; char_u *p; balpart_T *item; int quoted = FALSE; int height; int line; int item_idx; int indent = 0; int max_cells = 0; int max_height = Rows / 2 - 2; int long_item_count = 0; int split_long_items = FALSE; ga_init2(&ga, sizeof(balpart_T), 20); p = mesg; while (*p != NUL) { if (ga_grow(&ga, 1) == FAIL) goto failed; item = ((balpart_T *)ga.ga_data) + ga.ga_len; item->start = p; item->indent = indent; item->cells = indent * 2; ++ga.ga_len; while (*p != NUL) { if (*p == '"') quoted = !quoted; else if (*p == '\\' && p[1] != NUL) ++p; else if (!quoted) { if ((*p == ',' && p[1] == ' ') || *p == '{' || *p == '}') { /* Looks like a good point to break. */ if (*p == '{') ++indent; else if (*p == '}' && indent > 0) --indent; ++item->cells; p = skipwhite(p + 1); break; } } item->cells += ptr2cells(p); p += MB_PTR2LEN(p); } item->bytelen = p - item->start; if (item->cells > max_cells) max_cells = item->cells; long_item_count += (item->cells - 1) / BALLOON_MIN_WIDTH; } height = 2 + ga.ga_len; /* If there are long items and the height is below the limit: split lines */ if (long_item_count > 0 && height + long_item_count <= max_height) { split_long_items = TRUE; height += long_item_count; } /* Limit to half the window height, it has to fit above or below the mouse * position. */ if (height > max_height) height = max_height; *array = (pumitem_T *)alloc_clear((unsigned)sizeof(pumitem_T) * height); if (*array == NULL) goto failed; /* Add an empty line above and below, looks better. */ (*array)->pum_text = vim_strsave((char_u *)""); (*array + height - 1)->pum_text = vim_strsave((char_u *)""); for (line = 1, item_idx = 0; line < height - 1; ++item_idx) { int skip; int thislen; int copylen; int ind; int cells; item = ((balpart_T *)ga.ga_data) + item_idx; for (skip = 0; skip < item->bytelen; skip += thislen) { if (split_long_items && item->cells >= BALLOON_MIN_WIDTH) { cells = item->indent * 2; for (p = item->start + skip; p < item->start + item->bytelen; p += MB_PTR2LEN(p)) if ((cells += ptr2cells(p)) > BALLOON_MIN_WIDTH) break; thislen = p - (item->start + skip); } else thislen = item->bytelen; /* put indent at the start */ p = alloc(thislen + item->indent * 2 + 1); for (ind = 0; ind < item->indent * 2; ++ind) p[ind] = ' '; /* exclude spaces at the end of the string */ for (copylen = thislen; copylen > 0; --copylen) if (item->start[skip + copylen - 1] != ' ') break; vim_strncpy(p + ind, item->start + skip, copylen); (*array)[line].pum_text = p; item->indent = 0; /* wrapped line has no indent */ ++line; } } ga_clear(&ga); return height; failed: ga_clear(&ga); return 0; }
static void do_intro_line(int row, char_u *mesg, int add_version, int attr) { char_u vers[20]; int col; char_u *p; int l; int clen; #ifdef MODIFIED_BY # define MODBY_LEN 150 char_u modby[MODBY_LEN]; if (*mesg == ' ') { vim_strncpy(modby, (char_u *)_("Modified by "), MODBY_LEN - 1); l = STRLEN(modby); vim_strncpy(modby + l, (char_u *)MODIFIED_BY, MODBY_LEN - l - 1); mesg = modby; } #endif // ifdef MODIFIED_BY // Center the message horizontally. col = vim_strsize(mesg); if (add_version) { STRCPY(vers, mediumVersion); if (highest_patch()) { // Check for 9.9x or 9.9xx, alpha/beta version if (isalpha((int)vers[3])) { int len = (isalpha((int)vers[4])) ? 5 : 4; sprintf((char *)vers + len, ".%d%s", highest_patch(), mediumVersion + len); } else { sprintf((char *)vers + 3, ".%d", highest_patch()); } } col += (int)STRLEN(vers); } col = (Columns - col) / 2; if (col < 0) { col = 0; } // Split up in parts to highlight <> items differently. for (p = mesg; *p != NUL; p += l) { clen = 0; for (l = 0; p[l] != NUL && (l == 0 || (p[l] != '<' && p[l - 1] != '>')); ++l) { if (has_mbyte) { clen += ptr2cells(p + l); l += (*mb_ptr2len)(p + l) - 1; } else { clen += byte2cells(p[l]); } } screen_puts_len(p, l, row, col, *p == '<' ? hl_attr(HLF_8) : attr); col += clen; } // Add the version number to the version line. if (add_version) { screen_puts(vers, row, col, 0); } }
/* * Initialization routine for vim_findfile(). * * Returns the newly allocated search context or NULL if an error occurred. * * Don't forget to clean up by calling vim_findfile_cleanup() if you are done * with the search context. * * Find the file 'filename' in the directory 'path'. * The parameter 'path' may contain wildcards. If so only search 'level' * directories deep. The parameter 'level' is the absolute maximum and is * not related to restricts given to the '**' wildcard. If 'level' is 100 * and you use '**200' vim_findfile() will stop after 100 levels. * * 'filename' cannot contain wildcards! It is used as-is, no backslashes to * escape special characters. * * If 'stopdirs' is not NULL and nothing is found downward, the search is * restarted on the next higher directory level. This is repeated until the * start-directory of a search is contained in 'stopdirs'. 'stopdirs' has the * format ";*<dirname>*\(;<dirname>\)*;\=$". * * If the 'path' is relative, the starting dir for the search is either VIM's * current dir or if the path starts with "./" the current files dir. * If the 'path' is absolute, the starting dir is that part of the path before * the first wildcard. * * Upward search is only done on the starting dir. * * If 'free_visited' is TRUE the list of already visited files/directories is * cleared. Set this to FALSE if you just want to search from another * directory, but want to be sure that no directory from a previous search is * searched again. This is useful if you search for a file at different places. * The list of visited files/dirs can also be cleared with the function * vim_findfile_free_visited(). * * Set the parameter 'find_what' to FINDFILE_DIR if you want to search for * directories only, FINDFILE_FILE for files only, FINDFILE_BOTH for both. * * A search context returned by a previous call to vim_findfile_init() can be * passed in the parameter "search_ctx_arg". This context is reused and * reinitialized with the new parameters. The list of already visited * directories from this context is only deleted if the parameter * "free_visited" is true. Be aware that the passed "search_ctx_arg" is freed * if the reinitialization fails. * * If you don't have a search context from a previous call "search_ctx_arg" * must be NULL. * * This function silently ignores a few errors, vim_findfile() will have * limited functionality then. */ void * vim_findfile_init ( char_u *path, char_u *filename, char_u *stopdirs, int level, int free_visited, int find_what, void *search_ctx_arg, int tagfile, /* expanding names of tags files */ char_u *rel_fname /* file name to use for "." */ ) { char_u *wc_part; ff_stack_T *sptr; ff_search_ctx_T *search_ctx; /* If a search context is given by the caller, reuse it, else allocate a * new one. */ if (search_ctx_arg != NULL) search_ctx = search_ctx_arg; else { search_ctx = (ff_search_ctx_T*)alloc((unsigned)sizeof(ff_search_ctx_T)); if (search_ctx == NULL) goto error_return; vim_memset(search_ctx, 0, sizeof(ff_search_ctx_T)); } search_ctx->ffsc_find_what = find_what; search_ctx->ffsc_tagfile = tagfile; /* clear the search context, but NOT the visited lists */ ff_clear(search_ctx); /* clear visited list if wanted */ if (free_visited == TRUE) vim_findfile_free_visited(search_ctx); else { /* Reuse old visited lists. Get the visited list for the given * filename. If no list for the current filename exists, creates a new * one. */ search_ctx->ffsc_visited_list = ff_get_visited_list(filename, &search_ctx->ffsc_visited_lists_list); if (search_ctx->ffsc_visited_list == NULL) goto error_return; search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename, &search_ctx->ffsc_dir_visited_lists_list); if (search_ctx->ffsc_dir_visited_list == NULL) goto error_return; } if (ff_expand_buffer == NULL) { ff_expand_buffer = (char_u*)alloc(MAXPATHL); if (ff_expand_buffer == NULL) goto error_return; } /* Store information on starting dir now if path is relative. * If path is absolute, we do that later. */ if (path[0] == '.' && (vim_ispathsep(path[1]) || path[1] == NUL) && (!tagfile || vim_strchr(p_cpo, CPO_DOTTAG) == NULL) && rel_fname != NULL) { int len = (int)(gettail(rel_fname) - rel_fname); if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL) { /* Make the start dir an absolute path name. */ vim_strncpy(ff_expand_buffer, rel_fname, len); search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer, FALSE); } else search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len); if (search_ctx->ffsc_start_dir == NULL) goto error_return; if (*++path != NUL) ++path; } else if (*path == NUL || !vim_isAbsName(path)) { #ifdef BACKSLASH_IN_FILENAME /* "c:dir" needs "c:" to be expanded, otherwise use current dir */ if (*path != NUL && path[1] == ':') { char_u drive[3]; drive[0] = path[0]; drive[1] = ':'; drive[2] = NUL; if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL) goto error_return; path += 2; } else #endif if (mch_dirname(ff_expand_buffer, MAXPATHL) == FAIL) goto error_return; search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer); if (search_ctx->ffsc_start_dir == NULL) goto error_return; #ifdef BACKSLASH_IN_FILENAME /* A path that starts with "/dir" is relative to the drive, not to the * directory (but not for "//machine/dir"). Only use the drive name. */ if ((*path == '/' || *path == '\\') && path[1] != path[0] && search_ctx->ffsc_start_dir[1] == ':') search_ctx->ffsc_start_dir[2] = NUL; #endif } /* * If stopdirs are given, split them into an array of pointers. * If this fails (mem allocation), there is no upward search at all or a * stop directory is not recognized -> continue silently. * If stopdirs just contains a ";" or is empty, * search_ctx->ffsc_stopdirs_v will only contain a NULL pointer. This * is handled as unlimited upward search. See function * ff_path_in_stoplist() for details. */ if (stopdirs != NULL) { char_u *walker = stopdirs; int dircount; while (*walker == ';') walker++; dircount = 1; search_ctx->ffsc_stopdirs_v = (char_u **)alloc((unsigned)sizeof(char_u *)); if (search_ctx->ffsc_stopdirs_v != NULL) { do { char_u *helper; void *ptr; helper = walker; ptr = vim_realloc(search_ctx->ffsc_stopdirs_v, (dircount + 1) * sizeof(char_u *)); if (ptr) search_ctx->ffsc_stopdirs_v = ptr; else /* ignore, keep what we have and continue */ break; walker = vim_strchr(walker, ';'); if (walker) { search_ctx->ffsc_stopdirs_v[dircount-1] = vim_strnsave(helper, (int)(walker - helper)); walker++; } else /* this might be "", which means ascent till top * of directory tree. */ search_ctx->ffsc_stopdirs_v[dircount-1] = vim_strsave(helper); dircount++; } while (walker != NULL); search_ctx->ffsc_stopdirs_v[dircount-1] = NULL; } } search_ctx->ffsc_level = level; /* split into: * -fix path * -wildcard_stuff (might be NULL) */ wc_part = vim_strchr(path, '*'); if (wc_part != NULL) { int llevel; int len; char *errpt; /* save the fix part of the path */ search_ctx->ffsc_fix_path = vim_strnsave(path, (int)(wc_part - path)); /* * copy wc_path and add restricts to the '**' wildcard. * The octet after a '**' is used as a (binary) counter. * So '**3' is transposed to '**^C' ('^C' is ASCII value 3) * or '**76' is transposed to '**N'( 'N' is ASCII value 76). * For EBCDIC you get different character values. * If no restrict is given after '**' the default is used. * Due to this technique the path looks awful if you print it as a * string. */ len = 0; while (*wc_part != NUL) { if (len + 5 >= MAXPATHL) { EMSG(_(e_pathtoolong)); break; } if (STRNCMP(wc_part, "**", 2) == 0) { ff_expand_buffer[len++] = *wc_part++; ff_expand_buffer[len++] = *wc_part++; llevel = strtol((char *)wc_part, &errpt, 10); if ((char_u *)errpt != wc_part && llevel > 0 && llevel < 255) ff_expand_buffer[len++] = llevel; else if ((char_u *)errpt != wc_part && llevel == 0) /* restrict is 0 -> remove already added '**' */ len -= 2; else ff_expand_buffer[len++] = FF_MAX_STAR_STAR_EXPAND; wc_part = (char_u *)errpt; if (*wc_part != NUL && !vim_ispathsep(*wc_part)) { EMSG2(_( "E343: Invalid path: '**[number]' must be at the end of the path or be followed by '%s'."), PATHSEPSTR); goto error_return; } } else ff_expand_buffer[len++] = *wc_part++; } ff_expand_buffer[len] = NUL; search_ctx->ffsc_wc_path = vim_strsave(ff_expand_buffer); if (search_ctx->ffsc_wc_path == NULL) goto error_return; } else search_ctx->ffsc_fix_path = vim_strsave(path); if (search_ctx->ffsc_start_dir == NULL) { /* store the fix part as startdir. * This is needed if the parameter path is fully qualified. */ search_ctx->ffsc_start_dir = vim_strsave(search_ctx->ffsc_fix_path); if (search_ctx->ffsc_start_dir == NULL) goto error_return; search_ctx->ffsc_fix_path[0] = NUL; } /* create an absolute path */ if (STRLEN(search_ctx->ffsc_start_dir) + STRLEN(search_ctx->ffsc_fix_path) + 3 >= MAXPATHL) { EMSG(_(e_pathtoolong)); goto error_return; } STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir); add_pathsep(ff_expand_buffer); { int eb_len = (int)STRLEN(ff_expand_buffer); char_u *buf = alloc(eb_len + (int)STRLEN(search_ctx->ffsc_fix_path) + 1); STRCPY(buf, ff_expand_buffer); STRCPY(buf + eb_len, search_ctx->ffsc_fix_path); if (mch_isdir(buf)) { STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path); add_pathsep(ff_expand_buffer); } else { char_u *p = gettail(search_ctx->ffsc_fix_path); char_u *wc_path = NULL; char_u *temp = NULL; int len = 0; if (p > search_ctx->ffsc_fix_path) { len = (int)(p - search_ctx->ffsc_fix_path) - 1; STRNCAT(ff_expand_buffer, search_ctx->ffsc_fix_path, len); add_pathsep(ff_expand_buffer); } else len = (int)STRLEN(search_ctx->ffsc_fix_path); if (search_ctx->ffsc_wc_path != NULL) { wc_path = vim_strsave(search_ctx->ffsc_wc_path); temp = alloc((int)(STRLEN(search_ctx->ffsc_wc_path) + STRLEN(search_ctx->ffsc_fix_path + len) + 1)); } if (temp == NULL || wc_path == NULL) { vim_free(buf); vim_free(temp); vim_free(wc_path); goto error_return; } STRCPY(temp, search_ctx->ffsc_fix_path + len); STRCAT(temp, search_ctx->ffsc_wc_path); vim_free(search_ctx->ffsc_wc_path); vim_free(wc_path); search_ctx->ffsc_wc_path = temp; } vim_free(buf); } sptr = ff_create_stack_element(ff_expand_buffer, search_ctx->ffsc_wc_path, level, 0); if (sptr == NULL) goto error_return; ff_push(search_ctx, sptr); search_ctx->ffsc_file_to_search = vim_strsave(filename); if (search_ctx->ffsc_file_to_search == NULL) goto error_return; return search_ctx; error_return: /* * We clear the search context now! * Even when the caller gave us a (perhaps valid) context we free it here, * as we might have already destroyed it. */ vim_findfile_cleanup(search_ctx); return NULL; }
/* * maintains the list of already visited files and dirs * returns FAIL if the given file/dir is already in the list * returns OK if it is newly added * * TODO: What to do on memory allocation problems? * -> return TRUE - Better the file is found several times instead of * never. */ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *wc_path) { ff_visited_T *vp; #ifdef UNIX struct stat st; int url = FALSE; #endif /* For an URL we only compare the name, otherwise we compare the * device/inode (unix) or the full path name (not Unix). */ if (path_with_url(fname)) { vim_strncpy(ff_expand_buffer, fname, MAXPATHL - 1); #ifdef UNIX url = TRUE; #endif } else { ff_expand_buffer[0] = NUL; #ifdef UNIX if (mch_stat((char *)fname, &st) < 0) #else if (vim_FullName(fname, ff_expand_buffer, MAXPATHL, TRUE) == FAIL) #endif return FAIL; } /* check against list of already visited files */ for (vp = *visited_list; vp != NULL; vp = vp->ffv_next) { if ( #ifdef UNIX !url ? (vp->ffv_dev_valid && vp->ffv_dev == st.st_dev && vp->ffv_ino == st.st_ino) : #endif fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0 ) { /* are the wildcard parts equal */ if (ff_wc_equal(vp->ffv_wc_path, wc_path) == TRUE) /* already visited */ return FAIL; } } /* * New file/dir. Add it to the list of visited files/dirs. */ vp = (ff_visited_T *)alloc((unsigned)(sizeof(ff_visited_T) + STRLEN(ff_expand_buffer))); if (vp != NULL) { #ifdef UNIX if (!url) { vp->ffv_dev_valid = TRUE; vp->ffv_ino = st.st_ino; vp->ffv_dev = st.st_dev; vp->ffv_fname[0] = NUL; } else { vp->ffv_dev_valid = FALSE; #endif STRCPY(vp->ffv_fname, ff_expand_buffer); #ifdef UNIX } #endif if (wc_path != NULL) vp->ffv_wc_path = vim_strsave(wc_path); else vp->ffv_wc_path = NULL; vp->ffv_next = *visited_list; *visited_list = vp; } return OK; }
/* * Get absolute file name into "buf[len]". * * return FAIL for failure, OK for success */ int mch_FullName( char_u *fname, char_u *buf, int len, int force /* also expand when already absolute path */ ) { int l; char_u olddir[MAXPATHL]; char_u *p; int retval = OK; /* expand it if forced or not an absolute path */ if (force || !mch_isFullName(fname)) { /* * If the file name has a path, change to that directory for a moment, * and then do the getwd() (and get back to where we were). * This will get the correct path name with "../" things. */ if ((p = vim_strrchr(fname, '/')) != NULL) { /* Only change directory when we are sure we can return to where * we are now. After doing "su" chdir(".") might not work. */ if ((mch_dirname(olddir, MAXPATHL) == FAIL || mch_chdir((char *)olddir) != 0)) { p = NULL; /* can't get current dir: don't chdir */ retval = FAIL; } else { /* The directory is copied into buf[], to be able to remove * the file name without changing it (could be a string in * read-only memory) */ if (p - fname >= len) retval = FAIL; else { vim_strncpy(buf, fname, p - fname); if (mch_chdir((char *)buf)) retval = FAIL; else fname = p + 1; *buf = NUL; } } } if (mch_dirname(buf, len) == FAIL) { retval = FAIL; *buf = NUL; } if (p != NULL) { l = mch_chdir((char *)olddir); if (l != 0) EMSG(_(e_prev_dir)); } l = STRLEN(buf); if (l >= len - 1) retval = FAIL; /* no space for trailing "/" */ else if (l > 0 && buf[l - 1] != '/' && *fname != NUL && STRCMP(fname, ".") != 0) STRCAT(buf, "/"); } /* Catch file names which are too long. */ if (retval == FAIL || (int)(STRLEN(buf) + STRLEN(fname)) >= len) return FAIL; /* Do not append ".", "/dir/." is equal to "/dir". */ if (STRCMP(fname, ".") != 0) STRCAT(buf, fname); return OK; }