/*s
 * The window procedure for the hidden message window.
 * It handles callback messages and notifications from servers.
 * In order to process these messages, it is necessary to run a
 * message loop. Code which may run before the main message loop
 * is started (in the GUI) is careful to pump messages when it needs
 * to. Features which require message delivery during normal use will
 * not work in the console version - this basically means those
 * features which allow Vim to act as a server, rather than a client.
 */
    static LRESULT CALLBACK
Messaging_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    int err;

    if (msg == WM_COPYDATA)
    {
	/* This is a message from another Vim. The dwData member of the
	 * COPYDATASTRUCT determines the type of message:
	 *   COPYDATA_ENCODING:
	 *	The encoding that the client uses. Following messages will
	 *	use this encoding, convert if needed.
	 *   COPYDATA_KEYS:
	 *	A key sequence. We are a server, and a client wants these keys
	 *	adding to the input queue.
	 *   COPYDATA_REPLY:
	 *	A reply. We are a client, and a server has sent this message
	 *	in response to a request.  (server2client())
	 *   COPYDATA_EXPR:
	 *	An expression. We are a server, and a client wants us to
	 *	evaluate this expression.
	 *   COPYDATA_RESULT:
	 *	A reply. We are a client, and a server has sent this message
	 *	in response to a COPYDATA_EXPR.
	 *   COPYDATA_ERROR_RESULT:
	 *	A reply. We are a client, and a server has sent this message
	 *	in response to a COPYDATA_EXPR that failed to evaluate.
	 */
	COPYDATASTRUCT	*data = (COPYDATASTRUCT*)lParam;
	HWND		sender = (HWND)wParam;
	COPYDATASTRUCT	reply;
	char_u		*res;
	int		retval;
	char_u		*str;
	char_u		*tofree;

	switch (data->dwData)
	{
	case COPYDATA_ENCODING:
	    /* Remember the encoding that the client uses. */
	    vim_free(client_enc);
            // TODO:
	    //client_enc = enc_canonize((char_u *)data->lpData);
	    client_enc = vim_strsave(data->lpData);
	    return 1;

	case COPYDATA_KEYS:
            /* not supported */
	    return 1;

	case COPYDATA_EXPR:
	    str = serverConvert(client_enc, (char_u *)data->lpData, &tofree);

            if (usereval == NULL)
            {
                err = -1;
                res = NULL;
            }
            else
            {
                res = NULL;
                err = usereval((char *)str, (char **)&res);
            }

	    vim_free(tofree);

            if (!err)
		reply.dwData = COPYDATA_RESULT;
            else
		reply.dwData = COPYDATA_ERROR_RESULT;
	    reply.lpData = (res == NULL) ? (char_u *)"" : res;
	    reply.cbData = (res == NULL) ? 1 : (DWORD)STRLEN(res) + 1;

	    serverSendEnc(sender);
	    retval = (int)SendMessage(sender, WM_COPYDATA, (WPARAM)message_window,
							    (LPARAM)(&reply));
	    vim_free(res);
	    return retval;

	case COPYDATA_REPLY:
	case COPYDATA_RESULT:
	case COPYDATA_ERROR_RESULT:
	    if (data->lpData != NULL)
	    {
		str = serverConvert(client_enc, (char_u *)data->lpData,
								     &tofree);
		if (tofree == NULL)
		    str = vim_strsave(str);
		if (save_reply(sender, str,
			   (data->dwData == COPYDATA_REPLY ?  0 :
			   (data->dwData == COPYDATA_RESULT ? 1 :
							      2))) == FAIL)
		    vim_free(str);
	    }
	    return 1;
	}

	return 0;
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}
Exemple #2
0
/*
 * ":delmarks[!] [marks]"
 */
void ex_delmarks(exarg_T *eap)
{
  char_u      *p;
  int from, to;
  int i;
  int lower;
  int digit;
  int n;

  if (*eap->arg == NUL && eap->forceit)
    /* clear all marks */
    clrallmarks(curbuf);
  else if (eap->forceit)
    EMSG(_(e_invarg));
  else if (*eap->arg == NUL)
    EMSG(_(e_argreq));
  else {
    /* clear specified marks only */
    for (p = eap->arg; *p != NUL; ++p) {
      lower = ASCII_ISLOWER(*p);
      digit = VIM_ISDIGIT(*p);
      if (lower || digit || ASCII_ISUPPER(*p)) {
        if (p[1] == '-') {
          /* clear range of marks */
          from = *p;
          to = p[2];
          if (!(lower ? ASCII_ISLOWER(p[2])
                : (digit ? VIM_ISDIGIT(p[2])
                   : ASCII_ISUPPER(p[2])))
              || to < from) {
            EMSG2(_(e_invarg2), p);
            return;
          }
          p += 2;
        } else
          /* clear one lower case mark */
          from = to = *p;

        for (i = from; i <= to; ++i) {
          if (lower)
            curbuf->b_namedm[i - 'a'].lnum = 0;
          else {
            if (digit)
              n = i - '0' + NMARKS;
            else
              n = i - 'A';
            namedfm[n].fmark.mark.lnum = 0;
            vim_free(namedfm[n].fname);
            namedfm[n].fname = NULL;
          }
        }
      } else
        switch (*p) {
        case '"': curbuf->b_last_cursor.lnum = 0; break;
        case '^': curbuf->b_last_insert.lnum = 0; break;
        case '.': curbuf->b_last_change.lnum = 0; break;
        case '[': curbuf->b_op_start.lnum    = 0; break;
        case ']': curbuf->b_op_end.lnum      = 0; break;
        case '<': curbuf->b_visual.vi_start.lnum = 0; break;
        case '>': curbuf->b_visual.vi_end.lnum   = 0; break;
        case ' ': break;
        default:  EMSG2(_(e_invarg2), p);
          return;
        }
    }
  }
}
Exemple #3
0
/*
 * External interface
 */
    static void
DoPy3Command(exarg_T *eap, const char *cmd)
{
#if defined(MACOS) && !defined(MACOS_X_UNIX)
    GrafPtr		oldPort;
#endif
#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
    char		*saved_locale;
#endif
    PyObject		*cmdstr;
    PyObject		*cmdbytes;

#if defined(MACOS) && !defined(MACOS_X_UNIX)
    GetPort(&oldPort);
    /* Check if the Python library is available */
    if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress)
	goto theend;
#endif
    if (Python3_Init())
	goto theend;

    RangeStart = eap->line1;
    RangeEnd = eap->line2;
    Python_Release_Vim();	    /* leave vim */

#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
    /* Python only works properly when the LC_NUMERIC locale is "C". */
    saved_locale = setlocale(LC_NUMERIC, NULL);
    if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0)
	saved_locale = NULL;
    else
    {
	/* Need to make a copy, value may change when setting new locale. */
	saved_locale = (char *)vim_strsave((char_u *)saved_locale);
	(void)setlocale(LC_NUMERIC, "C");
    }
#endif

    pygilstate = PyGILState_Ensure();

    /* PyRun_SimpleString expects a UTF-8 string. Wrong encoding may cause
     * SyntaxError (unicode error). */
    cmdstr = PyUnicode_Decode(cmd, strlen(cmd),
					(char *)ENC_OPT, CODEC_ERROR_HANDLER);
    cmdbytes = PyUnicode_AsEncodedString(cmdstr, "utf-8", CODEC_ERROR_HANDLER);
    Py_XDECREF(cmdstr);
    PyRun_SimpleString(PyBytes_AsString(cmdbytes));
    Py_XDECREF(cmdbytes);

    PyGILState_Release(pygilstate);

#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
    if (saved_locale != NULL)
    {
	(void)setlocale(LC_NUMERIC, saved_locale);
	vim_free(saved_locale);
    }
#endif

    Python_Lock_Vim();		    /* enter vim */
    PythonIO_Flush();
#if defined(MACOS) && !defined(MACOS_X_UNIX)
    SetPort(oldPort);
#endif

theend:
    return;	    /* keeps lint happy */
}
Exemple #4
0
/*
 * get a new block
 *
 *   negative: TRUE if negative block number desired (data block)
 */
    bhdr_T *
mf_new(memfile_T *mfp, int negative, int page_count)
{
    bhdr_T	*hp;	/* new bhdr_T */
    bhdr_T	*freep;	/* first block in free list */
    char_u	*p;

    /*
     * If we reached the maximum size for the used memory blocks, release one
     * If a bhdr_T is returned, use it and adjust the page_count if necessary.
     */
    hp = mf_release(mfp, page_count);

/*
 * Decide on the number to use:
 * If there is a free block, use its number.
 * Otherwise use mf_block_min for a negative number, mf_block_max for
 * a positive number.
 */
    freep = mfp->mf_free_first;
    if (!negative && freep != NULL && freep->bh_page_count >= page_count)
    {
	/*
	 * If the block in the free list has more pages, take only the number
	 * of pages needed and allocate a new bhdr_T with data
	 *
	 * If the number of pages matches and mf_release() did not return a
	 * bhdr_T, use the bhdr_T from the free list and allocate the data
	 *
	 * If the number of pages matches and mf_release() returned a bhdr_T,
	 * just use the number and free the bhdr_T from the free list
	 */
	if (freep->bh_page_count > page_count)
	{
	    if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
		return NULL;
	    hp->bh_bnum = freep->bh_bnum;
	    freep->bh_bnum += page_count;
	    freep->bh_page_count -= page_count;
	}
	else if (hp == NULL)	    /* need to allocate memory for this block */
	{
	    if ((p = (char_u *)alloc(mfp->mf_page_size * page_count)) == NULL)
		return NULL;
	    hp = mf_rem_free(mfp);
	    hp->bh_data = p;
	}
	else		    /* use the number, remove entry from free list */
	{
	    freep = mf_rem_free(mfp);
	    hp->bh_bnum = freep->bh_bnum;
	    vim_free(freep);
	}
    }
    else	/* get a new number */
    {
	if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
	    return NULL;
	if (negative)
	{
	    hp->bh_bnum = mfp->mf_blocknr_min--;
	    mfp->mf_neg_count++;
	}
	else
	{
	    hp->bh_bnum = mfp->mf_blocknr_max;
	    mfp->mf_blocknr_max += page_count;
	}
    }
    hp->bh_flags = BH_LOCKED | BH_DIRTY;	/* new block is always dirty */
    mfp->mf_dirty = TRUE;
    hp->bh_page_count = page_count;
    mf_ins_used(mfp, hp);
    mf_ins_hash(mfp, hp);

    /*
     * Init the data to all zero, to avoid reading uninitialized data.
     * This also avoids that the passwd file ends up in the swap file!
     */
    (void)vim_memset((char *)(hp->bh_data), 0,
				      (size_t)mfp->mf_page_size * page_count);

    return hp;
}
Exemple #5
0
/*
 * External interface
 */
    static void
DoPythonCommand(exarg_T *eap, const char *cmd, typval_T *rettv)
{
#ifndef PY_CAN_RECURSE
    static int		recursive = 0;
#endif
#if defined(MACOS) && !defined(MACOS_X_UNIX)
    GrafPtr		oldPort;
#endif
#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
    char		*saved_locale;
#endif

#ifndef PY_CAN_RECURSE
    if (recursive)
    {
	EMSG(_("E659: Cannot invoke Python recursively"));
	return;
    }
    ++recursive;
#endif

#if defined(MACOS) && !defined(MACOS_X_UNIX)
    GetPort(&oldPort);
    /* Check if the Python library is available */
    if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress)
	goto theend;
#endif
    if (Python_Init())
	goto theend;

    if (rettv == NULL)
    {
	RangeStart = eap->line1;
	RangeEnd = eap->line2;
    }
    else
    {
	RangeStart = (PyInt) curwin->w_cursor.lnum;
	RangeEnd = RangeStart;
    }
    Python_Release_Vim();	    /* leave vim */

#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
    /* Python only works properly when the LC_NUMERIC locale is "C". */
    saved_locale = setlocale(LC_NUMERIC, NULL);
    if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0)
	saved_locale = NULL;
    else
    {
	/* Need to make a copy, value may change when setting new locale. */
	saved_locale = (char *)vim_strsave((char_u *)saved_locale);
	(void)setlocale(LC_NUMERIC, "C");
    }
#endif

    Python_RestoreThread();	    /* enter python */

    if (rettv == NULL)
	PyRun_SimpleString((char *)(cmd));
    else
    {
	PyObject	*r;

	r = PyRun_String((char *)(cmd), Py_eval_input, globals, globals);
	if (r == NULL)
	{
	    if (PyErr_Occurred() && !msg_silent)
		PyErr_PrintEx(0);
	    EMSG(_("E858: Eval did not return a valid python object"));
	}
	else
	{
	    if (ConvertFromPyObject(r, rettv) == -1)
		EMSG(_("E859: Failed to convert returned python object to vim value"));
	    Py_DECREF(r);
	}
	PyErr_Clear();
    }

    Python_SaveThread();	    /* leave python */

#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
    if (saved_locale != NULL)
    {
	(void)setlocale(LC_NUMERIC, saved_locale);
	vim_free(saved_locale);
    }
#endif

    Python_Lock_Vim();		    /* enter vim */
    PythonIO_Flush();
#if defined(MACOS) && !defined(MACOS_X_UNIX)
    SetPort(oldPort);
#endif

theend:
#ifndef PY_CAN_RECURSE
    --recursive;
#endif
    return;
}
Exemple #6
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;
}
Exemple #7
0
    void
blob_free(blob_T *b)
{
    ga_clear(&b->bv_ga);
    vim_free(b);
}
Exemple #8
0
/*
 * Free everything that we allocated.
 * Can be used to detect memory leaks, e.g., with ccmalloc.
 * NOTE: This is tricky!  Things are freed that functions depend on.  Don't be
 * surprised if Vim crashes...
 * Some things can't be freed, esp. things local to a library function.
 */
void free_all_mem(void)
{
  buf_T       *buf, *nextbuf;
  static int entered = FALSE;

  /* When we cause a crash here it is caught and Vim tries to exit cleanly.
   * Don't try freeing everything again. */
  if (entered)
    return;
  entered = TRUE;

  block_autocmds();         /* don't want to trigger autocommands here */

  /* Close all tabs and windows.  Reset 'equalalways' to avoid redraws. */
  p_ea = FALSE;
  if (first_tabpage->tp_next != NULL)
    do_cmdline_cmd((char_u *)"tabonly!");
  if (firstwin != lastwin)
    do_cmdline_cmd((char_u *)"only!");

  /* Free all spell info. */
  spell_free_all();

  /* Clear user commands (before deleting buffers). */
  ex_comclear(NULL);

  /* Clear menus. */
  do_cmdline_cmd((char_u *)"aunmenu *");
  do_cmdline_cmd((char_u *)"menutranslate clear");

  /* Clear mappings, abbreviations, breakpoints. */
  do_cmdline_cmd((char_u *)"lmapclear");
  do_cmdline_cmd((char_u *)"xmapclear");
  do_cmdline_cmd((char_u *)"mapclear");
  do_cmdline_cmd((char_u *)"mapclear!");
  do_cmdline_cmd((char_u *)"abclear");
  do_cmdline_cmd((char_u *)"breakdel *");
  do_cmdline_cmd((char_u *)"profdel *");
  do_cmdline_cmd((char_u *)"set keymap=");

  free_titles();
  free_findfile();

  /* Obviously named calls. */
  free_all_autocmds();
  clear_termcodes();
  free_all_options();
  free_all_marks();
  alist_clear(&global_alist);
  free_homedir();
  free_users();
  free_search_patterns();
  free_old_sub();
  free_last_insert();
  free_prev_shellcmd();
  free_regexp_stuff();
  free_tag_stuff();
  free_cd_dir();
  free_signs();
  set_expr_line(NULL);
  diff_clear(curtab);
  clear_sb_text();            /* free any scrollback text */

  /* Free some global vars. */
  vim_free(last_cmdline);
  vim_free(new_last_cmdline);
  set_keep_msg(NULL, 0);

  /* Clear cmdline history. */
  p_hi = 0;
  init_history();

  {
    win_T       *win;
    tabpage_T   *tab;

    qf_free_all(NULL);
    /* Free all location lists */
    FOR_ALL_TAB_WINDOWS(tab, win)
    qf_free_all(win);
  }

  /* Close all script inputs. */
  close_all_scripts();

  /* Destroy all windows.  Must come before freeing buffers. */
  win_free_all();

  /* Free all buffers.  Reset 'autochdir' to avoid accessing things that
   * were freed already. */
  p_acd = FALSE;
  for (buf = firstbuf; buf != NULL; ) {
    nextbuf = buf->b_next;
    close_buffer(NULL, buf, DOBUF_WIPE, FALSE);
    if (buf_valid(buf))
      buf = nextbuf;            /* didn't work, try next one */
    else
      buf = firstbuf;
  }

  free_cmdline_buf();

  /* Clear registers. */
  clear_registers();
  ResetRedobuff();
  ResetRedobuff();


  /* highlight info */
  free_highlight();

  reset_last_sourcing();

  free_tabpage(first_tabpage);
  first_tabpage = NULL;

# ifdef UNIX
  /* Machine-specific free. */
  mch_free_mem();
# endif

  /* message history */
  for (;; )
    if (delete_first_msg() == FAIL)
      break;

  eval_clear();

  free_termoptions();

  /* screenlines (can't display anything now!) */
  free_screenlines();

  clear_hl_tables();

  vim_free(NameBuff);
}
Exemple #9
0
/// Redraw the popup menu, using "pum_first" and "pum_selected".
void pum_redraw(void)
{
  int row = pum_row;
  int col;
  int attr_norm = highlight_attr[HLF_PNI];
  int attr_select = highlight_attr[HLF_PSI];
  int attr_scroll = highlight_attr[HLF_PSB];
  int attr_thumb = highlight_attr[HLF_PST];
  int attr;
  int i;
  int idx;
  char_u *s;
  char_u *p = NULL;
  int totwidth, width, w;
  int thumb_pos = 0;
  int thumb_heigth = 1;
  int round;
  int n;

  // Never display more than we have
  if (pum_first > pum_size - pum_height) {
    pum_first = pum_size - pum_height;
  }

  if (pum_scrollbar) {
    thumb_heigth = pum_height * pum_height / pum_size;
    if (thumb_heigth == 0) {
      thumb_heigth = 1;
    }
    thumb_pos = (pum_first * (pum_height - thumb_heigth)
                 + (pum_size - pum_height) / 2)
                / (pum_size - pum_height);
  }

  for (i = 0; i < pum_height; ++i) {
    idx = i + pum_first;
    attr = (idx == pum_selected) ? attr_select : attr_norm;

    // prepend a space if there is room
    if (curwin->w_p_rl) {
      if (pum_col < W_WINCOL(curwin) + W_WIDTH(curwin) - 1) {
        screen_putchar(' ', row, pum_col + 1, attr);
      }
    } else if (pum_col > 0) {
      screen_putchar(' ', row, pum_col - 1, attr);
    }

    // Display each entry, use two spaces for a Tab.
    // Do this 3 times: For the main text, kind and extra info
    col = pum_col;
    totwidth = 0;

    for (round = 1; round <= 3; ++round) {
      width = 0;
      s = NULL;

      switch (round) {
        case 1:
          p = pum_array[idx].pum_text;
          break;

        case 2:
          p = pum_array[idx].pum_kind;
          break;

        case 3:
          p = pum_array[idx].pum_extra;
          break;
      }

      if (p != NULL) {
        for (;; mb_ptr_adv(p)) {
          if (s == NULL) {
            s = p;
          }
          w = ptr2cells(p);

          if ((*p == NUL) || (*p == TAB) || (totwidth + w > pum_width)) {
            // Display the text that fits or comes before a Tab.
            // First convert it to printable characters.
            char_u *st;
            int saved = *p;

            *p = NUL;
            st = transstr(s);
            *p = saved;

            if (curwin->w_p_rl) {
              if (st != NULL) {
                char_u  *rt = reverse_text(st);

                if (rt != NULL) {
                  char_u *rt_start = rt;
                  int size;

                  size = vim_strsize(rt);

                  if (size > pum_width) {
                    do {
                      size -= has_mbyte ? (*mb_ptr2cells)(rt) : 1;
                      mb_ptr_adv(rt);
                    } while (size > pum_width);

                    if (size < pum_width) {
                      // Most left character requires 2-cells but only 1 cell
                      // is available on screen.  Put a '<' on the left of the 
                      // pum item
                      *(--rt) = '<';
                      size++;
                    }
                  }
                  screen_puts_len(rt, (int)STRLEN(rt), row, col - size + 1,
                                  attr);
                  vim_free(rt_start);
                }
                vim_free(st);
              }
              col -= width;
            } else {
              if (st != NULL) {
                screen_puts_len(st, (int)STRLEN(st), row, col, attr);
                vim_free(st);
              }
              col += width;
            }

            if (*p != TAB) {
              break;
            }

            // Display two spaces for a Tab.
            if (curwin->w_p_rl) {
              screen_puts_len((char_u *)"  ", 2, row, col - 1, attr);
              col -= 2;
            } else   {
              screen_puts_len((char_u *)"  ", 2, row, col, attr);
              col += 2;
            }
            totwidth += 2;
            // start text at next char
            s = NULL;
            width = 0;
          } else {
            width += w;
          }
        }
      }

      if (round > 1) {
        n = pum_kind_width + 1;
      } else {
        n = 1;
      }

      // Stop when there is nothing more to display.
      if ((round == 3)
          || ((round == 2)
              && (pum_array[idx].pum_extra == NULL))
          || ((round == 1)
              && (pum_array[idx].pum_kind == NULL)
              && (pum_array[idx].pum_extra == NULL))
          || (pum_base_width + n >= pum_width)) {
        break;
      }

      if (curwin->w_p_rl) {
        screen_fill(row, row + 1, pum_col - pum_base_width - n + 1,
                    col + 1, ' ', ' ', attr);
        col = pum_col - pum_base_width - n + 1;
      } else   {
        screen_fill(row, row + 1, col, pum_col + pum_base_width + n,
                    ' ', ' ', attr);
        col = pum_col + pum_base_width + n;
      }
      totwidth = pum_base_width + n;
    }

    if (curwin->w_p_rl) {
      screen_fill(row, row + 1, pum_col - pum_width + 1, col + 1, ' ', ' ',
                  attr);
    } else {
      screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ', attr);
    }

    if (pum_scrollbar > 0) {
      if (curwin->w_p_rl) {
        screen_putchar(' ', row, pum_col - pum_width,
                       i >= thumb_pos && i < thumb_pos + thumb_heigth
                       ? attr_thumb : attr_scroll);
      } else {
        screen_putchar(' ', row, pum_col + pum_width,
                       i >= thumb_pos && i < thumb_pos + thumb_heigth
                       ? attr_thumb : attr_scroll);
      }
    }
    row++;
  }
}
Exemple #10
0
/*
 * Free the crypt state.
 */
    void
crypt_free_state(cryptstate_T *state)
{
    vim_free(state->method_state);
    vim_free(state);
}
Exemple #11
0
/*
 * Get the text and position to be evaluated for "beval".
 * If "getword" is true the returned text is not the whole line but the
 * relevant word in allocated memory.
 * Returns OK or FAIL.
 */
    int
get_beval_info(
    BalloonEval	*beval,
    int		getword,
    win_T	**winp,
    linenr_T	*lnump,
    char_u	**textp,
    int		*colp)
{
    win_T	*wp;
    int		row, col;
    char_u	*lbuf;
    linenr_T	lnum;

    *textp = NULL;
# ifdef FEAT_BEVAL_TERM
#  ifdef FEAT_GUI
    if (!gui.in_use)
#  endif
    {
	row = mouse_row;
	col = mouse_col;
    }
# endif
# ifdef FEAT_GUI
    if (gui.in_use)
    {
	row = Y_2_ROW(beval->y);
	col = X_2_COL(beval->x);
    }
#endif
    wp = mouse_find_win(&row, &col);
    if (wp != NULL && row >= 0 && row < wp->w_height && col < wp->w_width)
    {
	/* Found a window and the cursor is in the text.  Now find the line
	 * number. */
	if (!mouse_comp_pos(wp, &row, &col, &lnum))
	{
	    /* Not past end of the file. */
	    lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE);
	    if (col <= win_linetabsize(wp, lbuf, (colnr_T)MAXCOL))
	    {
		/* Not past end of line. */
		if (getword)
		{
		    /* For Netbeans we get the relevant part of the line
		     * instead of the whole line. */
		    int		len;
		    pos_T	*spos = NULL, *epos = NULL;

		    if (VIsual_active)
		    {
			if (LT_POS(VIsual, curwin->w_cursor))
			{
			    spos = &VIsual;
			    epos = &curwin->w_cursor;
			}
			else
			{
			    spos = &curwin->w_cursor;
			    epos = &VIsual;
			}
		    }

		    col = vcol2col(wp, lnum, col);

		    if (VIsual_active
			    && wp->w_buffer == curwin->w_buffer
			    && (lnum == spos->lnum
				? col >= (int)spos->col
				: lnum > spos->lnum)
			    && (lnum == epos->lnum
				? col <= (int)epos->col
				: lnum < epos->lnum))
		    {
			/* Visual mode and pointing to the line with the
			 * Visual selection: return selected text, with a
			 * maximum of one line. */
			if (spos->lnum != epos->lnum || spos->col == epos->col)
			    return FAIL;

			lbuf = ml_get_buf(curwin->w_buffer, VIsual.lnum, FALSE);
			len = epos->col - spos->col;
			if (*p_sel != 'e')
			    len += MB_PTR2LEN(lbuf + epos->col);
			lbuf = vim_strnsave(lbuf + spos->col, len);
			lnum = spos->lnum;
			col = spos->col;
		    }
		    else
		    {
			/* Find the word under the cursor. */
			++emsg_off;
			len = find_ident_at_pos(wp, lnum, (colnr_T)col, &lbuf,
					FIND_IDENT + FIND_STRING + FIND_EVAL);
			--emsg_off;
			if (len == 0)
			    return FAIL;
			lbuf = vim_strnsave(lbuf, len);
		    }
		}

		*winp = wp;
		*lnump = lnum;
		*textp = lbuf;
		*colp = col;
#ifdef FEAT_VARTABS
		vim_free(beval->vts);
		beval->vts = tabstop_copy(wp->w_buffer->b_p_vts_array);
		if (wp->w_buffer->b_p_vts_array != NULL && beval->vts == NULL)
		    return FAIL;
#endif
		beval->ts = wp->w_buffer->b_p_ts;
		return OK;
	    }
	}
    }

    return FAIL;
}
Exemple #12
0
    void
gui_mch_draw_string(
    int		row,
    int		col,
    char_u	*text,
    int		len,
    int		flags)
{
#ifndef MSWIN16_FASTTEXT
    static int	*padding = NULL;
    static int	pad_size = 0;
    int		i;
#endif
    HPEN	hpen, old_pen;
    int		y;

#ifndef MSWIN16_FASTTEXT
    /*
     * Italic and bold text seems to have an extra row of pixels at the bottom
     * (below where the bottom of the character should be).  If we draw the
     * characters with a solid background, the top row of pixels in the
     * character below will be overwritten.  We can fix this by filling in the
     * background ourselves, to the correct character proportions, and then
     * writing the character in transparent mode.  Still have a problem when
     * the character is "_", which gets written on to the character below.
     * New fix: set gui.char_ascent to -1.  This shifts all characters up one
     * pixel in their slots, which fixes the problem with the bottom row of
     * pixels.	We still need this code because otherwise the top row of pixels
     * becomes a problem. - webb.
     */
    HBRUSH	hbr;
    RECT	rc;

    if (!(flags & DRAW_TRANSP))
    {
	/*
	 * Clear background first.
	 * Note: FillRect() excludes right and bottom of rectangle.
	 */
	rc.left = FILL_X(col);
	rc.top = FILL_Y(row);
#ifdef FEAT_MBYTE
	if (has_mbyte)
	{
	    /* Compute the length in display cells. */
	    rc.right = FILL_X(col + mb_string2cells(text, len));
	}
	else
#endif
	    rc.right = FILL_X(col + len);
	rc.bottom = FILL_Y(row + 1);
	hbr = CreateSolidBrush(gui.currBgColor);
	FillRect(s_hdc, &rc, hbr);
	DeleteBrush(hbr);

	SetBkMode(s_hdc, TRANSPARENT);

	/*
	 * When drawing block cursor, prevent inverted character spilling
	 * over character cell (can happen with bold/italic)
	 */
	if (flags & DRAW_CURSOR)
	{
	    pcliprect = &rc;
	    foptions = ETO_CLIPPED;
	}
    }
#else
    /*
     * Alternative: write the characters in opaque mode, since we have blocked
     * bold or italic fonts.
     */
    /* The OPAQUE mode and backcolour have already been set */
#endif
    /* The forecolor and font have already been set */

#ifndef MSWIN16_FASTTEXT

    if (pad_size != Columns || padding == NULL || padding[0] != gui.char_width)
    {
	vim_free(padding);
	pad_size = Columns;

	padding = (int *)alloc(pad_size * sizeof(int));
	if (padding != NULL)
	    for (i = 0; i < pad_size; i++)
		padding[i] = gui.char_width;
    }
#endif

    /*
     * We have to provide the padding argument because italic and bold versions
     * of fixed-width fonts are often one pixel or so wider than their normal
     * versions.
     * No check for DRAW_BOLD, Windows will have done it already.
     */
#ifndef MSWIN16_FASTTEXT
    ExtTextOut(s_hdc, TEXT_X(col), TEXT_Y(row), 0, NULL,
						     (char *)text, len, padding);
#else
    TextOut(s_hdc, TEXT_X(col), TEXT_Y(row), (char *)text, len);
#endif

    if (flags & DRAW_UNDERL)
    {
	hpen = CreatePen(PS_SOLID, 1, gui.currFgColor);
	old_pen = SelectObject(s_hdc, hpen);
	/* When p_linespace is 0, overwrite the bottom row of pixels.
	 * Otherwise put the line just below the character. */
	y = FILL_Y(row + 1) - 1;
#ifndef MSWIN16_FASTTEXT
	if (p_linespace > 1)
	    y -= p_linespace - 1;
#endif
	MoveToEx(s_hdc, FILL_X(col), y, NULL);
	/* Note: LineTo() excludes the last pixel in the line. */
	LineTo(s_hdc, FILL_X(col + len), y);
	DeleteObject(SelectObject(s_hdc, old_pen));
    }
}
Exemple #13
0
    int
gui_mch_dialog(
    int		 type,
    char_u	*title,
    char_u	*message,
    char_u	*buttons,
    int		 dfltbutton,
    char_u	*textfield,
    int		ex_cmd)
{
    FARPROC	dp;
    LPWORD	p, pnumitems;
    int		numButtons;
    int		*buttonWidths, *buttonPositions;
    int		buttonYpos;
    int		nchar, i;
    DWORD	lStyle;
    int		dlgwidth = 0;
    int		dlgheight;
    int		editboxheight;
    int		horizWidth;
    int		msgheight;
    char_u	*pstart;
    char_u	*pend;
    char_u	*tbuffer;
    RECT	rect;
    HWND	hwnd;
    HDC		hdc;
    HFONT	oldFont;
    TEXTMETRIC	fontInfo;
    int		fontHeight;
    int		textWidth, minButtonWidth, messageWidth;
    int		maxDialogWidth;
    int		vertical;
    int		dlgPaddingX;
    int		dlgPaddingY;
    HGLOBAL	hglbDlgTemp;

#ifndef NO_CONSOLE
    /* Don't output anything in silent mode ("ex -s") */
    if (silent_mode)
	return dfltbutton;   /* return default option */
#endif

    /* If there is no window yet, open it. */
    if (s_hwnd == NULL && gui_mch_init() == FAIL)
	return dfltbutton;

    if ((type < 0) || (type > VIM_LAST_TYPE))
	type = 0;

    /* allocate some memory for dialog template */
    /* TODO should compute this really*/

    hglbDlgTemp = GlobalAlloc(GHND,  DLG_ALLOC_SIZE);
    if (hglbDlgTemp == NULL)
	return -1;

    p = (LPWORD) GlobalLock(hglbDlgTemp);

    if (p == NULL)
	return -1;

    /*
     * make a copy of 'buttons' to fiddle with it.  compiler grizzles because
     * vim_strsave() doesn't take a const arg (why not?), so cast away the
     * const.
     */
    tbuffer = vim_strsave(buttons);
    if (tbuffer == NULL)
	return -1;

    --dfltbutton;   /* Change from one-based to zero-based */

    /* Count buttons */
    numButtons = 1;
    for (i = 0; tbuffer[i] != '\0'; i++)
    {
	if (tbuffer[i] == DLG_BUTTON_SEP)
	    numButtons++;
    }
    if (dfltbutton >= numButtons)
	dfltbutton = 0;

    /* Allocate array to hold the width of each button */
    buttonWidths = (int *) lalloc(numButtons * sizeof(int), TRUE);
    if (buttonWidths == NULL)
	return -1;

    /* Allocate array to hold the X position of each button */
    buttonPositions = (int *) lalloc(numButtons * sizeof(int), TRUE);
    if (buttonPositions == NULL)
	return -1;

    /*
     * Calculate how big the dialog must be.
     */
    hwnd = GetDesktopWindow();
    hdc = GetWindowDC(hwnd);
    oldFont = SelectFont(hdc, GetStockObject(SYSTEM_FONT));
    dlgPaddingX = DLG_OLD_STYLE_PADDING_X;
    dlgPaddingY = DLG_OLD_STYLE_PADDING_Y;

    GetTextMetrics(hdc, &fontInfo);
    fontHeight = fontInfo.tmHeight;

    /* Minimum width for horizontal button */
    minButtonWidth = GetTextWidth(hdc, "Cancel", 6);

    /* Maximum width of a dialog, if possible */
    GetWindowRect(s_hwnd, &rect);
    maxDialogWidth = rect.right - rect.left
		     - GetSystemMetrics(SM_CXFRAME) * 2;
    if (maxDialogWidth < DLG_MIN_MAX_WIDTH)
	maxDialogWidth = DLG_MIN_MAX_WIDTH;

    /* Set dlgwidth to width of message */
    pstart = message;
    messageWidth = 0;
    msgheight = 0;
    do
    {
	pend = vim_strchr(pstart, DLG_BUTTON_SEP);
	if (pend == NULL)
	    pend = pstart + STRLEN(pstart);	/* Last line of message. */
	msgheight += fontHeight;
	textWidth = GetTextWidth(hdc, pstart, pend - pstart);
	if (textWidth > messageWidth)
	    messageWidth = textWidth;
	pstart = pend + 1;
    } while (*pend != NUL);
    dlgwidth = messageWidth;

    /* Add width of icon to dlgwidth, and some space */
    dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX;

    if (msgheight < DLG_ICON_HEIGHT)
	msgheight = DLG_ICON_HEIGHT;

    /*
     * Check button names.  A long one will make the dialog wider.
     */
	 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
    if (!vertical)
    {
	// Place buttons horizontally if they fit.
	horizWidth = dlgPaddingX;
	pstart = tbuffer;
	i = 0;
	do
	{
	    pend = vim_strchr(pstart, DLG_BUTTON_SEP);
	    if (pend == NULL)
		pend = pstart + STRLEN(pstart);	// Last button name.
	    textWidth = GetTextWidth(hdc, pstart, pend - pstart);
	    if (textWidth < minButtonWidth)
		textWidth = minButtonWidth;
	    textWidth += dlgPaddingX;	    /* Padding within button */
	    buttonWidths[i] = textWidth;
	    buttonPositions[i++] = horizWidth;
	    horizWidth += textWidth + dlgPaddingX; /* Pad between buttons */
	    pstart = pend + 1;
	} while (*pend != NUL);

	if (horizWidth > maxDialogWidth)
	    vertical = TRUE;	// Too wide to fit on the screen.
	else if (horizWidth > dlgwidth)
	    dlgwidth = horizWidth;
    }

    if (vertical)
    {
	// Stack buttons vertically.
	pstart = tbuffer;
	do
	{
	    pend = vim_strchr(pstart, DLG_BUTTON_SEP);
	    if (pend == NULL)
		pend = pstart + STRLEN(pstart);	// Last button name.
	    textWidth = GetTextWidth(hdc, pstart, pend - pstart);
	    textWidth += dlgPaddingX;		/* Padding within button */
	    textWidth += DLG_VERT_PADDING_X * 2; /* Padding around button */
	    if (textWidth > dlgwidth)
		dlgwidth = textWidth;
	    pstart = pend + 1;
	} while (*pend != NUL);
    }

    if (dlgwidth < DLG_MIN_WIDTH)
	dlgwidth = DLG_MIN_WIDTH;	/* Don't allow a really thin dialog!*/

    /* start to fill in the dlgtemplate information.  addressing by WORDs */
    lStyle = DS_MODALFRAME | WS_CAPTION | WS_VISIBLE ;

    add_long(lStyle);
    pnumitems = p;	/*save where the number of items must be stored*/
    add_byte(0);	// NumberOfItems(will change later)
    add_word(10);	// x
    add_word(10);	// y
    add_word(PixelToDialogX(dlgwidth));

    // Dialog height.
    if (vertical)
	dlgheight = msgheight + 2 * dlgPaddingY +
			      DLG_VERT_PADDING_Y + 2 * fontHeight * numButtons;
    else
	dlgheight = msgheight + 3 * dlgPaddingY + 2 * fontHeight;

    // Dialog needs to be taller if contains an edit box.
    editboxheight = fontHeight + dlgPaddingY + 4 * DLG_VERT_PADDING_Y;
    if (textfield != NULL)
	dlgheight += editboxheight;

    add_word(PixelToDialogY(dlgheight));

    add_byte(0);	//menu
    add_byte(0);	//class

    /* copy the title of the dialog */
    add_string(title ? title : ("Vim"VIM_VERSION_MEDIUM));

    buttonYpos = msgheight + 2 * dlgPaddingY;

    if (textfield != NULL)
	buttonYpos += editboxheight;

    pstart = tbuffer; //dflt_text
    horizWidth = (dlgwidth - horizWidth) / 2;	/* Now it's X offset */
    for (i = 0; i < numButtons; i++)
    {
	/* get end of this button. */
	for (	pend = pstart;
		*pend && (*pend != DLG_BUTTON_SEP);
		pend++)
	    ;

	if (*pend)
	    *pend = '\0';

	/*
	 * NOTE:
	 * setting the BS_DEFPUSHBUTTON style doesn't work because Windows sets
	 * the focus to the first tab-able button and in so doing makes that
	 * the default!! Grrr.  Workaround: Make the default button the only
	 * one with WS_TABSTOP style. Means user can't tab between buttons, but
	 * he/she can use arrow keys.
	 *
	 * NOTE (Thore): Setting BS_DEFPUSHBUTTON works fine when it's the
	 * first one, so I changed the correct button to be this style. This
	 * is necessary because when an edit box is added, we need a button to
	 * be default.  The edit box will be the default control, and when the
	 * user presses enter from the edit box we want the default button to
	 * be pressed.
	 */
	if (vertical)
	{
	    p = add_dialog_element(p,
		    ((i == dfltbutton || dfltbutton < 0) && textfield != NULL
			    ?  BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
		    PixelToDialogX(DLG_VERT_PADDING_X),
		    PixelToDialogY(buttonYpos /* TBK */
				   + 2 * fontHeight * i),
		    PixelToDialogX(dlgwidth - 2 * DLG_VERT_PADDING_X),
		    (WORD)(PixelToDialogY(2 * fontHeight) - 1),
		    (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
	}
	else
	{
	    p = add_dialog_element(p,
		    ((i == dfltbutton || dfltbutton < 0) && textfield != NULL
			     ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
		    PixelToDialogX(horizWidth + buttonPositions[i]),
		    PixelToDialogY(buttonYpos), /* TBK */
		    PixelToDialogX(buttonWidths[i]),
		    (WORD)(PixelToDialogY(2 * fontHeight) - 1),
		    (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
	}

	pstart = pend + 1;	/*next button*/

    }
    *pnumitems += numButtons;

    /* Vim icon */
    p = add_dialog_element(p, SS_ICON,
	    PixelToDialogX(dlgPaddingX),
	    PixelToDialogY(dlgPaddingY),
	    PixelToDialogX(DLG_ICON_WIDTH),
	    PixelToDialogY(DLG_ICON_HEIGHT),
	    DLG_NONBUTTON_CONTROL + 0, (BYTE)0x82,
	    &dlg_icons[type]);


    /* Dialog message */
    p = add_dialog_element(p, SS_LEFT,
	    PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH),
	    PixelToDialogY(dlgPaddingY),
	    (WORD)(PixelToDialogX(messageWidth) + 1),
	    PixelToDialogY(msgheight),
	    DLG_NONBUTTON_CONTROL + 1, (BYTE)0x82, message);

    /* Edit box */
    if (textfield != NULL)
    {
	p = add_dialog_element(p, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP | WS_BORDER,
		PixelToDialogX(2 * dlgPaddingX),
		PixelToDialogY(2 * dlgPaddingY + msgheight),
		PixelToDialogX(dlgwidth - 4 * dlgPaddingX),
		PixelToDialogY(fontHeight + dlgPaddingY),
		DLG_NONBUTTON_CONTROL + 2, (BYTE)0x81, textfield);
	*pnumitems += 1;
    }

    *pnumitems += 2;

    SelectFont(hdc, oldFont);
    ReleaseDC(hwnd, hdc);
    dp = MakeProcInstance((FARPROC)dialog_callback, s_hinst);


    /* Let the dialog_callback() function know which button to make default
     * If we have an edit box, make that the default. We also need to tell
     * dialog_callback() if this dialog contains an edit box or not. We do
     * this by setting s_textfield if it does.
     */
    if (textfield != NULL)
    {
	dialog_default_button = DLG_NONBUTTON_CONTROL + 2;
	s_textfield = textfield;
    }
    else
    {
	dialog_default_button = IDCANCEL + 1 + dfltbutton;
	s_textfield = NULL;
    }

    /*show the dialog box modally and get a return value*/
    nchar = DialogBoxIndirect(
	    s_hinst,
	    (HGLOBAL) hglbDlgTemp,
	    s_hwnd,
	    (DLGPROC)dp);

    FreeProcInstance( dp );
    GlobalUnlock(hglbDlgTemp);
    GlobalFree(hglbDlgTemp);
    vim_free(tbuffer);
    vim_free(buttonWidths);
    vim_free(buttonPositions);


    return nchar;
}
Exemple #14
0
// Set the indent of the current line.
// Leaves the cursor on the first non-blank in the line.
// Caller must take care of undo.
// "flags":
//  SIN_CHANGED:    call changed_bytes() if the line was changed.
//  SIN_INSERT: insert the indent in front of the line.
//  SIN_UNDO:   save line for undo before changing it.
//  @param size measured in spaces
// Returns true if the line was changed.
int set_indent(int size, int flags)
{
  char_u *p;
  char_u *newline;
  char_u *oldline;
  char_u *s;
  int todo;
  int ind_len;  // Measured in characters.
  int line_len;
  int doit = false;
  int ind_done = 0;  // Measured in spaces.
  int tab_pad;
  int retval = false;

  // Number of initial whitespace chars when 'et' and 'pi' are both set.
  int orig_char_len = -1;

  // First check if there is anything to do and compute the number of
  // characters needed for the indent.
  todo = size;
  ind_len = 0;
  p = oldline = ml_get_curline();

  // Calculate the buffer size for the new indent, and check to see if it
  // isn't already set.
  // If 'expandtab' isn't set: use TABs; if both 'expandtab' and
  // 'preserveindent' are set count the number of characters at the
  // beginning of the line to be copied.
  if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi)) {
    // If 'preserveindent' is set then reuse as much as possible of
    // the existing indent structure for the new indent.
    if (!(flags & SIN_INSERT) && curbuf->b_p_pi) {
      ind_done = 0;

      // Count as many characters as we can use.
      while (todo > 0 && vim_iswhite(*p)) {
        if (*p == TAB) {
          tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);

          // Stop if this tab will overshoot the target.
          if (todo < tab_pad) {
            break;
          }
          todo -= tab_pad;
          ind_len++;
          ind_done += tab_pad;
        } else {
          todo--;
          ind_len++;
          ind_done++;
        }
        p++;
      }

      // Set initial number of whitespace chars to copy if we are
      // preserving indent but expandtab is set.
      if (curbuf->b_p_et) {
        orig_char_len = ind_len;
      }

      // Fill to next tabstop with a tab, if possible.
      tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);

      if ((todo >= tab_pad) && (orig_char_len == -1)) {
        doit = true;
        todo -= tab_pad;
        ind_len++;

        // ind_done += tab_pad;
      }
    }

    // Count tabs required for indent.
    while (todo >= (int)curbuf->b_p_ts) {
      if (*p != TAB) {
        doit = true;
      } else {
        p++;
      }
      todo -= (int)curbuf->b_p_ts;
      ind_len++;

      // ind_done += (int)curbuf->b_p_ts;
    }
  }

  // Count spaces required for indent.
  while (todo > 0) {
    if (*p != ' ') {
      doit = true;
    } else {
      p++;
    }
    todo--;
    ind_len++;

    // ind_done++;
  }

  // Return if the indent is OK already.
  if (!doit && !vim_iswhite(*p) && !(flags & SIN_INSERT)) {
    return false;
  }

  // Allocate memory for the new line.
  if (flags & SIN_INSERT) {
    p = oldline;
  } else {
    p = skipwhite(p);
  }
  line_len = (int)STRLEN(p) + 1;

  // If 'preserveindent' and 'expandtab' are both set keep the original
  // characters and allocate accordingly.  We will fill the rest with spaces
  // after the if (!curbuf->b_p_et) below.
  if (orig_char_len != -1) {
    newline = alloc(orig_char_len + size - ind_done + line_len);
    todo = size - ind_done;

    // Set total length of indent in characters, which may have been
    // undercounted until now.
    ind_len = orig_char_len + todo;
    p = oldline;
    s = newline;

    while (orig_char_len > 0) {
      *s++ = *p++;
      orig_char_len--;
    }

    // Skip over any additional white space (useful when newindent is less
    // than old).
    while (vim_iswhite(*p)) {
      p++;
    }
  } else {
    todo = size;
    newline = alloc(ind_len + line_len);
    s = newline;
  }

  // Put the characters in the new line.
  // if 'expandtab' isn't set: use TABs
  if (!curbuf->b_p_et) {
    // If 'preserveindent' is set then reuse as much as possible of
    // the existing indent structure for the new indent.
    if (!(flags & SIN_INSERT) && curbuf->b_p_pi) {
      p = oldline;
      ind_done = 0;

      while (todo > 0 && vim_iswhite(*p)) {
        if (*p == TAB) {
          tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);

          // Stop if this tab will overshoot the target.
          if (todo < tab_pad) {
            break;
          }
          todo -= tab_pad;
          ind_done += tab_pad;
        } else {
          todo--;
          ind_done++;
        }
        *s++ = *p++;
      }

      // Fill to next tabstop with a tab, if possible.
      tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);

      if (todo >= tab_pad) {
        *s++ = TAB;
        todo -= tab_pad;
      }
      p = skipwhite(p);
    }

    while (todo >= (int)curbuf->b_p_ts) {
      *s++ = TAB;
      todo -= (int)curbuf->b_p_ts;
    }
  }

  while (todo > 0) {
    *s++ = ' ';
    todo--;
  }
  memmove(s, p, (size_t)line_len);

  // Replace the line (unless undo fails).
  if (!(flags & SIN_UNDO) || (u_savesub(curwin->w_cursor.lnum) == OK)) {
    ml_replace(curwin->w_cursor.lnum, newline, false);

    if (flags & SIN_CHANGED) {
      changed_bytes(curwin->w_cursor.lnum, 0);
    }

    // Correct saved cursor position if it is in this line.
    if (saved_cursor.lnum == curwin->w_cursor.lnum) {
      if (saved_cursor.col >= (colnr_T)(p - oldline)) {
        // Cursor was after the indent, adjust for the number of
        // bytes added/removed.
        saved_cursor.col += ind_len - (colnr_T)(p - oldline);

      } else if (saved_cursor.col >= (colnr_T)(s - newline)) {
        // Cursor was in the indent, and is now after it, put it back
        // at the start of the indent (replacing spaces with TAB).
        saved_cursor.col = (colnr_T)(s - newline);
      }
    }
    retval = true;
  } else {
    vim_free(newline);
  }
  curwin->w_cursor.col = ind_len;
  return retval;
}
Exemple #15
0
    static int
json_decode_string(js_read_T *reader, typval_T *res)
{
    garray_T    ga;
    int		len;
    char_u	*p;
    int		c;
    varnumber_T	nr;

    if (res != NULL)
	ga_init2(&ga, 1, 200);

    p = reader->js_buf + reader->js_used + 1; /* skip over " */
    while (*p != '"')
    {
	/* The JSON is always expected to be utf-8, thus use utf functions
	 * here. The string is converted below if needed. */
	if (*p == NUL || p[1] == NUL
#ifdef FEAT_MBYTE
		|| utf_ptr2len(p) < utf_byte2len(*p)
#endif
		)
	{
	    /* Not enough bytes to make a character or end of the string. Get
	     * more if possible. */
	    if (reader->js_fill == NULL)
		break;
	    len = (int)(reader->js_end - p);
	    reader->js_used = (int)(p - reader->js_buf);
	    if (!reader->js_fill(reader))
		break; /* didn't get more */
	    p = reader->js_buf + reader->js_used;
	    reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
	    continue;
	}

	if (*p == '\\')
	{
	    c = -1;
	    switch (p[1])
	    {
		case '\\': c = '\\'; break;
		case '"': c = '"'; break;
		case 'b': c = BS; break;
		case 't': c = TAB; break;
		case 'n': c = NL; break;
		case 'f': c = FF; break;
		case 'r': c = CAR; break;
		case 'u':
		    if (reader->js_fill != NULL
				     && (int)(reader->js_end - p) < NUMBUFLEN)
		    {
			reader->js_used = (int)(p - reader->js_buf);
			if (reader->js_fill(reader))
			{
			    p = reader->js_buf + reader->js_used;
			    reader->js_end = reader->js_buf
						     + STRLEN(reader->js_buf);
			}
		    }
		    nr = 0;
		    len = 0;
		    vim_str2nr(p + 2, NULL, &len,
				     STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4);
		    p += len + 2;
		    if (0xd800 <= nr && nr <= 0xdfff
			    && (int)(reader->js_end - p) >= 6
			    && *p == '\\' && *(p+1) == 'u')
		    {
			varnumber_T	nr2 = 0;

			/* decode surrogate pair: \ud812\u3456 */
			len = 0;
			vim_str2nr(p + 2, NULL, &len,
				     STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4);
			if (0xdc00 <= nr2 && nr2 <= 0xdfff)
			{
			    p += len + 2;
			    nr = (((nr - 0xd800) << 10) |
				((nr2 - 0xdc00) & 0x3ff)) + 0x10000;
			}
		    }
		    if (res != NULL)
		    {
#ifdef FEAT_MBYTE
			char_u	buf[NUMBUFLEN];
			buf[utf_char2bytes((int)nr, buf)] = NUL;
			ga_concat(&ga, buf);
#else
			ga_append(&ga, (int)nr);
#endif
		    }
		    break;
		default:
		    /* not a special char, skip over \ */
		    ++p;
		    continue;
	    }
	    if (c > 0)
	    {
		p += 2;
		if (res != NULL)
		    ga_append(&ga, c);
	    }
	}
	else
	{
#ifdef FEAT_MBYTE
	    len = utf_ptr2len(p);
#else
	    len = 1;
#endif
	    if (res != NULL)
	    {
		if (ga_grow(&ga, len) == FAIL)
		{
		    ga_clear(&ga);
		    return FAIL;
		}
		mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len);
		ga.ga_len += len;
	    }
	    p += len;
	}
    }

    reader->js_used = (int)(p - reader->js_buf);
    if (*p == '"')
    {
	++reader->js_used;
	if (res != NULL)
	{
	    ga_append(&ga, NUL);
	    res->v_type = VAR_STRING;
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
	    if (!enc_utf8)
	    {
		vimconv_T   conv;

		/* Convert the utf-8 string to 'encoding'. */
		conv.vc_type = CONV_NONE;
		convert_setup(&conv, (char_u*)"utf-8", p_enc);
		if (conv.vc_type != CONV_NONE)
		{
		    res->vval.v_string =
				      string_convert(&conv, ga.ga_data, NULL);
		    vim_free(ga.ga_data);
		}
		convert_setup(&conv, NULL, NULL);
	    }
	    else
#endif
		res->vval.v_string = ga.ga_data;
	}
	return OK;
    }
    if (res != NULL)
    {
	res->v_type = VAR_SPECIAL;
	res->vval.v_number = VVAL_NONE;
	ga_clear(&ga);
    }
    return MAYBE;
}
/*ARGSUSED*/
    void
workshop_toolbar_button(
	char	*label,
	char	*verb,
	char	*senseVerb,
	char	*filepos,
	char	*help,
	char	*sense,
	char	*file,
	char	*left)
{
    char	cbuf[BUFSIZ + MAXPATHLEN];
    char	namebuf[BUFSIZ];
    static int	tbid = 1;
    char_u	*p;
    int		len;

#ifdef WSDEBUG_TRACE
    if (WSDLEVEL(WS_TRACE_VERBOSE))
	wsdebug("workshop_toolbar_button(\"%s\", %s, %s,\n"
		"\t%s, \"%s\", %s,\n\t\"%s\",\n\t<%s>)\n",
		label   && *label   ? label   : "<None>",
		verb    && *verb    ? verb    : "<None>",
		senseVerb && *senseVerb    ? senseVerb    : "<None>",
		filepos && *filepos ? filepos : "<None>",
		help    && *help    ? help    : "<None>",
		sense   && *sense   ? sense   : "<None>",
		file    && *file    ? file    : "<None>",
		left    && *left    ? left    : "<None>");
    else if (WSDLEVEL(WS_TRACE))
	wstrace("workshop_toolbar_button(\"%s\", %s)\n",
		label   && *label   ? label   : "<None>",
		verb    && *verb    ? verb    : "<None>");
#endif
#ifdef WSDEBUG_SENSE
    if (ws_debug)
	wsdebug("button: %-21.20s%-21.20s(%s)\n", label, verb,
		*sense == '1' ? "Sensitive" : "Insensitive");
#endif

    if (left && *left && atoi(left) > 0)
    {
	/* Add a separator (but pass the width passed after the ':') */
	sprintf(cbuf, "amenu 1.%d ToolBar.-sep%d:%s- <nul>",
		tbpri - 5, tbid++, left);

	coloncmd(cbuf, True);
    }

    p = vim_strsave_escaped((char_u *)label, (char_u *)"\\. ");
    vim_snprintf(namebuf, sizeof(namebuf), "ToolBar.%s", p);
    vim_free(p);
    STRCPY(cbuf, "amenu <silent> ");
    if (file != NULL && *file != NUL)
    {
	p = vim_strsave_escaped((char_u *)file, (char_u *)" ");
	len = STRLEN(cbuf);
	vim_snprintf(cbuf + len, sizeof(cbuf) - len, "icon=%s ", p);
	vim_free(p);
    }
    len = STRLEN(cbuf);
    vim_snprintf(cbuf + len, sizeof(cbuf) - len,"1.%d %s :wsverb %s<CR>",
							tbpri, namebuf, verb);

    /* Define the menu item */
    coloncmd(cbuf, True);

    if (*sense == '0')
    {
	/* If menu isn't sensitive at startup... */
	vim_snprintf(cbuf, sizeof(cbuf), "amenu disable %s", namebuf);
	coloncmd(cbuf, True);
    }

    if (help && *help)
    {
	/* Do the tooltip */
	vim_snprintf(cbuf, sizeof(cbuf), "tmenu %s %s", namebuf, help);
	coloncmd(cbuf, True);
    }

    addMenu(namebuf, NULL, verb);
    tbpri += 10;
}
Exemple #17
0
    static void
write_string(garray_T *gap, char_u *str)
{
    char_u	*res = str;
    char_u	numbuf[NUMBUFLEN];

    if (res == NULL)
	ga_concat(gap, (char_u *)"null");
    else
    {
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
	vimconv_T   conv;
	char_u	    *converted = NULL;

	if (!enc_utf8)
	{
	    /* Convert the text from 'encoding' to utf-8, the JSON string is
	     * always utf-8. */
	    conv.vc_type = CONV_NONE;
	    convert_setup(&conv, p_enc, (char_u*)"utf-8");
	    if (conv.vc_type != CONV_NONE)
		converted = res = string_convert(&conv, res, NULL);
	    convert_setup(&conv, NULL, NULL);
	}
#endif
	ga_append(gap, '"');
	while (*res != NUL)
	{
	    int c;
#ifdef FEAT_MBYTE
	    /* always use utf-8 encoding, ignore 'encoding' */
	    c = utf_ptr2char(res);
#else
	    c = *res;
#endif

	    switch (c)
	    {
		case 0x08:
		    ga_append(gap, '\\'); ga_append(gap, 'b'); break;
		case 0x09:
		    ga_append(gap, '\\'); ga_append(gap, 't'); break;
		case 0x0a:
		    ga_append(gap, '\\'); ga_append(gap, 'n'); break;
		case 0x0c:
		    ga_append(gap, '\\'); ga_append(gap, 'f'); break;
		case 0x0d:
		    ga_append(gap, '\\'); ga_append(gap, 'r'); break;
		case 0x22: /* " */
		case 0x5c: /* \ */
		    ga_append(gap, '\\');
		    ga_append(gap, c);
		    break;
		default:
		    if (c >= 0x20)
		    {
#ifdef FEAT_MBYTE
			numbuf[utf_char2bytes(c, numbuf)] = NUL;
#else
			numbuf[0] = c;
			numbuf[1] = NUL;
#endif
			ga_concat(gap, numbuf);
		    }
		    else
		    {
			vim_snprintf((char *)numbuf, NUMBUFLEN,
							 "\\u%04lx", (long)c);
			ga_concat(gap, numbuf);
		    }
	    }
#ifdef FEAT_MBYTE
	    res += utf_ptr2len(res);
#else
	    ++res;
#endif
	}
	ga_append(gap, '"');
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
	vim_free(converted);
#endif
    }
}
Exemple #18
0
/*
 * Common code, invoked when the mouse is resting for a moment.
 */
    void
general_beval_cb(BalloonEval *beval, int state UNUSED)
{
#ifdef FEAT_EVAL
    win_T	*wp;
    int		col;
    int		use_sandbox;
    linenr_T	lnum;
    char_u	*text;
    static char_u  *result = NULL;
    long	winnr = 0;
    char_u	*bexpr;
    buf_T	*save_curbuf;
    size_t	len;
# ifdef FEAT_WINDOWS
    win_T	*cw;
# endif
#endif
    static int	recursive = FALSE;

    /* Don't do anything when 'ballooneval' is off, messages scrolled the
     * windows up or we have no beval area. */
    if (!p_beval || balloonEval == NULL || msg_scrolled > 0)
	return;

    /* Don't do this recursively.  Happens when the expression evaluation
     * takes a long time and invokes something that checks for CTRL-C typed. */
    if (recursive)
	return;
    recursive = TRUE;

#ifdef FEAT_EVAL
    if (get_beval_info(balloonEval, TRUE, &wp, &lnum, &text, &col) == OK)
    {
	bexpr = (*wp->w_buffer->b_p_bexpr == NUL) ? p_bexpr
						    : wp->w_buffer->b_p_bexpr;
	if (*bexpr != NUL)
	{
# ifdef FEAT_WINDOWS
	    /* Convert window pointer to number. */
	    for (cw = firstwin; cw != wp; cw = cw->w_next)
		++winnr;
# endif

	    set_vim_var_nr(VV_BEVAL_BUFNR, (long)wp->w_buffer->b_fnum);
	    set_vim_var_nr(VV_BEVAL_WINNR, winnr);
	    set_vim_var_nr(VV_BEVAL_LNUM, (long)lnum);
	    set_vim_var_nr(VV_BEVAL_COL, (long)(col + 1));
	    set_vim_var_string(VV_BEVAL_TEXT, text, -1);
	    vim_free(text);

	    /*
	     * Temporarily change the curbuf, so that we can determine whether
	     * the buffer-local balloonexpr option was set insecurely.
	     */
	    save_curbuf = curbuf;
	    curbuf = wp->w_buffer;
	    use_sandbox = was_set_insecurely((char_u *)"balloonexpr",
				 *curbuf->b_p_bexpr == NUL ? 0 : OPT_LOCAL);
	    curbuf = save_curbuf;
	    if (use_sandbox)
		++sandbox;
	    ++textlock;

	    vim_free(result);
	    result = eval_to_string(bexpr, NULL, TRUE);

	    /* Remove one trailing newline, it is added when the result was a
	     * list and it's hardly every useful.  If the user really wants a
	     * trailing newline he can add two and one remains. */
	    if (result != NULL)
	    {
		len = STRLEN(result);
		if (len > 0 && result[len - 1] == NL)
		    result[len - 1] = NUL;
	    }

	    if (use_sandbox)
		--sandbox;
	    --textlock;

	    set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
	    if (result != NULL && result[0] != NUL)
	    {
		gui_mch_post_balloon(beval, result);
		recursive = FALSE;
		return;
	    }
	}
    }
#endif
#ifdef FEAT_NETBEANS_INTG
    if (bevalServers & BEVAL_NETBEANS)
	netbeans_beval_cb(beval, state);
#endif
#ifdef FEAT_SUN_WORKSHOP
    if (bevalServers & BEVAL_WORKSHOP)
	workshop_beval_cb(beval, state);
#endif

    recursive = FALSE;
}
Exemple #19
0
/*
 * Either execute a command by calling the shell or start a new shell
 */
    int
mch_call_shell(
    char_u *cmd,
    int options)	    /* SHELL_, see vim.h */
{
    int		x;
    int		tmode = cur_tmode;

    out_flush();


#ifdef MCH_WRITE_DUMP
    if (fdDump)
    {
	fprintf(fdDump, "mch_call_shell(\"%s\", %d)\n", cmd, options);
	fflush(fdDump);
    }
#endif

    /*
     * Catch all deadly signals while running the external command, because a
     * CTRL-C, Ctrl-Break or illegal instruction  might otherwise kill us.
     */
    signal(SIGINT, SIG_IGN);
    signal(SIGILL, SIG_IGN);
    signal(SIGFPE, SIG_IGN);
    signal(SIGSEGV, SIG_IGN);
    signal(SIGTERM, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

    if (options & SHELL_COOKED)
	settmode(TMODE_COOK);	/* set to normal mode */

    if (cmd == NULL)
    {
	x = mch_system(p_sh, options);
    }
    else
    {
	/* we use "command" or "cmd" to start the shell; slow but easy */
	char_u *newcmd;

	newcmd = lalloc(
		STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10, TRUE);
	if (newcmd != NULL)
	{
	    if (STRNICMP(cmd, "start ", 6) == 0)
	    {
		sprintf((char *)newcmd, "%s\0", cmd+6);
		if (WinExec((LPCSTR)newcmd, SW_SHOWNORMAL) > 31)
		    x = 0;
		else
		    x = -1;
	    }
	    else
	    {
		sprintf((char *)newcmd, "%s%s %s %s",
			"",
			p_sh,
			p_shcf,
			cmd);
		x = mch_system((char *)newcmd, options);
	    }
	    vim_free(newcmd);
	}
    }

    if (tmode == TMODE_RAW)
	settmode(TMODE_RAW);	/* set to raw mode */

    if (x && !(options & SHELL_SILENT) && !emsg_silent)
    {
	smsg(_("shell returned %d"), x);
	msg_putchar('\n');
    }
#ifdef FEAT_TITLE
    resettitle();
#endif

    signal(SIGINT, SIG_DFL);
    signal(SIGILL, SIG_DFL);
    signal(SIGFPE, SIG_DFL);
    signal(SIGSEGV, SIG_DFL);
    signal(SIGTERM, SIG_DFL);
    signal(SIGABRT, SIG_DFL);


    return x;
}
Exemple #20
0
/*
 * Free a list item.  Also clears the value.  Does not notify watchers.
 */
    void
listitem_free(listitem_T *item)
{
    clear_tv(&item->li_tv);
    vim_free(item);
}
Exemple #21
0
/*
 * Test mf_hash_*() functions.
 */
    static void
test_mf_hash(void)
{
    mf_hashtab_T   ht;
    mf_hashitem_T  *item;
    blocknr_T      key;
    long_u	   i;
    long_u	   num_buckets;

    mf_hash_init(&ht);

    /* insert some items and check invariants */
    for (i = 0; i < TEST_COUNT; i++)
    {
	assert(ht.mht_count == i);

	/* check that number of buckets is a power of 2 */
	num_buckets = ht.mht_mask + 1;
	assert(num_buckets > 0 && (num_buckets & (num_buckets - 1)) == 0);

	/* check load factor */
	assert(ht.mht_count <= (num_buckets << MHT_LOG_LOAD_FACTOR));

	if (i < (MHT_INIT_SIZE << MHT_LOG_LOAD_FACTOR))
	{
	    /* first expansion shouldn't have occurred yet */
	    assert(num_buckets == MHT_INIT_SIZE);
	    assert(ht.mht_buckets == ht.mht_small_buckets);
	}
	else
	{
	    assert(num_buckets > MHT_INIT_SIZE);
	    assert(ht.mht_buckets != ht.mht_small_buckets);
	}

	key = index_to_key(i);
	assert(mf_hash_find(&ht, key) == NULL);

	/* allocate and add new item */
	item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);
	assert(item != NULL);
	item->mhi_key = key;
	mf_hash_add_item(&ht, item);

	assert(mf_hash_find(&ht, key) == item);

	if (ht.mht_mask + 1 != num_buckets)
	{
	    /* hash table was expanded */
	    assert(ht.mht_mask + 1 == num_buckets * MHT_GROWTH_FACTOR);
	    assert(i + 1 == (num_buckets << MHT_LOG_LOAD_FACTOR));
	}
    }

    /* check presence of inserted items */
    for (i = 0; i < TEST_COUNT; i++)
    {
	key = index_to_key(i);
	item = mf_hash_find(&ht, key);
	assert(item != NULL);
	assert(item->mhi_key == key);
    }

    /* delete some items */
    for (i = 0; i < TEST_COUNT; i++)
    {
	if (i % 100 < 70)
	{
	    key = index_to_key(i);
	    item = mf_hash_find(&ht, key);
	    assert(item != NULL);
	    assert(item->mhi_key == key);

	    mf_hash_rem_item(&ht, item);
	    assert(mf_hash_find(&ht, key) == NULL);

	    mf_hash_add_item(&ht, item);
	    assert(mf_hash_find(&ht, key) == item);

	    mf_hash_rem_item(&ht, item);
	    assert(mf_hash_find(&ht, key) == NULL);

	    vim_free(item);
	}
    }

    /* check again */
    for (i = 0; i < TEST_COUNT; i++)
    {
	key = index_to_key(i);
	item = mf_hash_find(&ht, key);

	if (i % 100 < 70)
	{
	    assert(item == NULL);
	}
	else
	{
	    assert(item != NULL);
	    assert(item->mhi_key == key);
	}
    }

    /* free hash table and all remaining items */
    mf_hash_free_all(&ht);
}
Exemple #22
0
/*
 * Find a file in a search context.
 * The search context was created with vim_findfile_init() above.
 * Return a pointer to an allocated file name or NULL if nothing found.
 * To get all matching files call this function until you get NULL.
 *
 * If the passed search_context is NULL, NULL is returned.
 *
 * The search algorithm is depth first. To change this replace the
 * stack with a list (don't forget to leave partly searched directories on the
 * top of the list).
 */
char_u *vim_findfile(void *search_ctx_arg)
{
  char_u      *file_path;
  char_u      *rest_of_wildcards;
  char_u      *path_end = NULL;
  ff_stack_T  *stackp;
  int len;
  int i;
  char_u      *p;
  char_u      *suf;
  ff_search_ctx_T *search_ctx;

  if (search_ctx_arg == NULL)
    return NULL;

  search_ctx = (ff_search_ctx_T *)search_ctx_arg;

  /*
   * filepath is used as buffer for various actions and as the storage to
   * return a found filename.
   */
  if ((file_path = alloc((int)MAXPATHL)) == NULL)
    return NULL;

  /* store the end of the start dir -- needed for upward search */
  if (search_ctx->ffsc_start_dir != NULL)
    path_end = &search_ctx->ffsc_start_dir[
      STRLEN(search_ctx->ffsc_start_dir)];

  /* upward search loop */
  for (;; ) {
    /* downward search loop */
    for (;; ) {
      /* check if user user wants to stop the search*/
      ui_breakcheck();
      if (got_int)
        break;

      /* get directory to work on from stack */
      stackp = ff_pop(search_ctx);
      if (stackp == NULL)
        break;

      /*
       * TODO: decide if we leave this test in
       *
       * GOOD: don't search a directory(-tree) twice.
       * BAD:  - check linked list for every new directory entered.
       *       - check for double files also done below
       *
       * Here we check if we already searched this directory.
       * We already searched a directory if:
       * 1) The directory is the same.
       * 2) We would use the same wildcard string.
       *
       * Good if you have links on same directory via several ways
       *  or you have selfreferences in directories (e.g. SuSE Linux 6.3:
       *  /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
       *
       * This check is only needed for directories we work on for the
       * first time (hence stackp->ff_filearray == NULL)
       */
      if (stackp->ffs_filearray == NULL
          && ff_check_visited(&search_ctx->ffsc_dir_visited_list
              ->ffvl_visited_list,
              stackp->ffs_fix_path
              , stackp->ffs_wc_path
              ) == FAIL) {
#ifdef FF_VERBOSE
        if (p_verbose >= 5) {
          verbose_enter_scroll();
          smsg((char_u *)"Already Searched: %s (%s)",
              stackp->ffs_fix_path, stackp->ffs_wc_path);
          /* don't overwrite this either */
          msg_puts((char_u *)"\n");
          verbose_leave_scroll();
        }
#endif
        ff_free_stack_element(stackp);
        continue;
      }
#ifdef FF_VERBOSE
      else if (p_verbose >= 5) {
        verbose_enter_scroll();
        smsg((char_u *)"Searching: %s (%s)",
            stackp->ffs_fix_path, stackp->ffs_wc_path);
        /* don't overwrite this either */
        msg_puts((char_u *)"\n");
        verbose_leave_scroll();
      }
#endif

      /* check depth */
      if (stackp->ffs_level <= 0) {
        ff_free_stack_element(stackp);
        continue;
      }

      file_path[0] = NUL;

      /*
       * If no filearray till now expand wildcards
       * The function expand_wildcards() can handle an array of paths
       * and all possible expands are returned in one array. We use this
       * to handle the expansion of '**' into an empty string.
       */
      if (stackp->ffs_filearray == NULL) {
        char_u *dirptrs[2];

        /* we use filepath to build the path expand_wildcards() should
         * expand.
         */
        dirptrs[0] = file_path;
        dirptrs[1] = NULL;

        /* if we have a start dir copy it in */
        if (!vim_isAbsName(stackp->ffs_fix_path)
            && search_ctx->ffsc_start_dir) {
          STRCPY(file_path, search_ctx->ffsc_start_dir);
          add_pathsep(file_path);
        }

        /* append the fix part of the search path */
        STRCAT(file_path, stackp->ffs_fix_path);
        add_pathsep(file_path);

        rest_of_wildcards = stackp->ffs_wc_path;
        if (*rest_of_wildcards != NUL) {
          len = (int)STRLEN(file_path);
          if (STRNCMP(rest_of_wildcards, "**", 2) == 0) {
            /* pointer to the restrict byte
             * The restrict byte is not a character!
             */
            p = rest_of_wildcards + 2;

            if (*p > 0) {
              (*p)--;
              file_path[len++] = '*';
            }

            if (*p == 0) {
              /* remove '**<numb> from wildcards */
              STRMOVE(rest_of_wildcards, rest_of_wildcards + 3);
            } else
              rest_of_wildcards += 3;

            if (stackp->ffs_star_star_empty == 0) {
              /* if not done before, expand '**' to empty */
              stackp->ffs_star_star_empty = 1;
              dirptrs[1] = stackp->ffs_fix_path;
            }
          }

          /*
           * Here we copy until the next path separator or the end of
           * the path. If we stop at a path separator, there is
           * still something else left. This is handled below by
           * pushing every directory returned from expand_wildcards()
           * on the stack again for further search.
           */
          while (*rest_of_wildcards
                 && !vim_ispathsep(*rest_of_wildcards))
            file_path[len++] = *rest_of_wildcards++;

          file_path[len] = NUL;
          if (vim_ispathsep(*rest_of_wildcards))
            rest_of_wildcards++;
        }

        /*
         * Expand wildcards like "*" and "$VAR".
         * If the path is a URL don't try this.
         */
        if (path_with_url(dirptrs[0])) {
          stackp->ffs_filearray = (char_u **)
                                  alloc((unsigned)sizeof(char *));
          if (stackp->ffs_filearray != NULL
              && (stackp->ffs_filearray[0]
                    = vim_strsave(dirptrs[0])) != NULL)
            stackp->ffs_filearray_size = 1;
          else
            stackp->ffs_filearray_size = 0;
        } else
          /* Add EW_NOTWILD because the expanded path may contain
           * wildcard characters that are to be taken literally.
           * This is a bit of a hack. */
          expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs,
              &stackp->ffs_filearray_size,
              &stackp->ffs_filearray,
              EW_DIR|EW_ADDSLASH|EW_SILENT|EW_NOTWILD);

        stackp->ffs_filearray_cur = 0;
        stackp->ffs_stage = 0;
      } else
        rest_of_wildcards = &stackp->ffs_wc_path[
          STRLEN(stackp->ffs_wc_path)];

      if (stackp->ffs_stage == 0) {
        /* this is the first time we work on this directory */
        if (*rest_of_wildcards == NUL) {
          /*
           * We don't have further wildcards to expand, so we have to
           * check for the final file now.
           */
          for (i = stackp->ffs_filearray_cur;
               i < stackp->ffs_filearray_size; ++i) {
            if (!path_with_url(stackp->ffs_filearray[i])
                && !mch_isdir(stackp->ffs_filearray[i]))
              continue;                 /* not a directory */

            /* prepare the filename to be checked for existence
             * below */
            STRCPY(file_path, stackp->ffs_filearray[i]);
            add_pathsep(file_path);
            STRCAT(file_path, search_ctx->ffsc_file_to_search);

            /*
             * Try without extra suffix and then with suffixes
             * from 'suffixesadd'.
             */
            len = (int)STRLEN(file_path);
            if (search_ctx->ffsc_tagfile)
              suf = (char_u *)"";
            else
              suf = curbuf->b_p_sua;
            for (;; ) {
              /* if file exists and we didn't already find it */
              if ((path_with_url(file_path)
                   || (os_file_exists(file_path)
                       && (search_ctx->ffsc_find_what
                           == FINDFILE_BOTH
                           || ((search_ctx->ffsc_find_what
                                == FINDFILE_DIR)
                               == mch_isdir(file_path)))))
#ifndef FF_VERBOSE
                  && (ff_check_visited(
                          &search_ctx->ffsc_visited_list->ffvl_visited_list,
                          file_path
                          , (char_u *)""
                          ) == OK)
#endif
                  ) {
#ifdef FF_VERBOSE
                if (ff_check_visited(
                        &search_ctx->ffsc_visited_list->ffvl_visited_list,
                        file_path
                        , (char_u *)""
                        ) == FAIL) {
                  if (p_verbose >= 5) {
                    verbose_enter_scroll();
                    smsg((char_u *)"Already: %s",
                        file_path);
                    /* don't overwrite this either */
                    msg_puts((char_u *)"\n");
                    verbose_leave_scroll();
                  }
                  continue;
                }
#endif

                /* push dir to examine rest of subdirs later */
                stackp->ffs_filearray_cur = i + 1;
                ff_push(search_ctx, stackp);

                if (!path_with_url(file_path))
                  simplify_filename(file_path);
                if (mch_dirname(ff_expand_buffer, MAXPATHL)
                    == OK) {
                  p = shorten_fname(file_path,
                      ff_expand_buffer);
                  if (p != NULL)
                    STRMOVE(file_path, p);
                }
#ifdef FF_VERBOSE
                if (p_verbose >= 5) {
                  verbose_enter_scroll();
                  smsg((char_u *)"HIT: %s", file_path);
                  /* don't overwrite this either */
                  msg_puts((char_u *)"\n");
                  verbose_leave_scroll();
                }
#endif
                return file_path;
              }

              /* Not found or found already, try next suffix. */
              if (*suf == NUL)
                break;
              copy_option_part(&suf, file_path + len,
                  MAXPATHL - len, ",");
            }
          }
        } else   {
          /*
           * still wildcards left, push the directories for further
           * search
           */
          for (i = stackp->ffs_filearray_cur;
               i < stackp->ffs_filearray_size; ++i) {
            if (!mch_isdir(stackp->ffs_filearray[i]))
              continue;                 /* not a directory */

            ff_push(search_ctx,
                ff_create_stack_element(
                    stackp->ffs_filearray[i],
                    rest_of_wildcards,
                    stackp->ffs_level - 1, 0));
          }
        }
        stackp->ffs_filearray_cur = 0;
        stackp->ffs_stage = 1;
      }

      /*
       * if wildcards contains '**' we have to descent till we reach the
       * leaves of the directory tree.
       */
      if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0) {
        for (i = stackp->ffs_filearray_cur;
             i < stackp->ffs_filearray_size; ++i) {
          if (fnamecmp(stackp->ffs_filearray[i],
                  stackp->ffs_fix_path) == 0)
            continue;             /* don't repush same directory */
          if (!mch_isdir(stackp->ffs_filearray[i]))
            continue;               /* not a directory */
          ff_push(search_ctx,
              ff_create_stack_element(stackp->ffs_filearray[i],
                  stackp->ffs_wc_path, stackp->ffs_level - 1, 1));
        }
      }

      /* we are done with the current directory */
      ff_free_stack_element(stackp);

    }

    /* If we reached this, we didn't find anything downwards.
     * Let's check if we should do an upward search.
     */
    if (search_ctx->ffsc_start_dir
        && search_ctx->ffsc_stopdirs_v != NULL && !got_int) {
      ff_stack_T  *sptr;

      /* is the last starting directory in the stop list? */
      if (ff_path_in_stoplist(search_ctx->ffsc_start_dir,
              (int)(path_end - search_ctx->ffsc_start_dir),
              search_ctx->ffsc_stopdirs_v) == TRUE)
        break;

      /* cut of last dir */
      while (path_end > search_ctx->ffsc_start_dir
             && vim_ispathsep(*path_end))
        path_end--;
      while (path_end > search_ctx->ffsc_start_dir
             && !vim_ispathsep(path_end[-1]))
        path_end--;
      *path_end = 0;
      path_end--;

      if (*search_ctx->ffsc_start_dir == 0)
        break;

      STRCPY(file_path, search_ctx->ffsc_start_dir);
      add_pathsep(file_path);
      STRCAT(file_path, search_ctx->ffsc_fix_path);

      /* create a new stack entry */
      sptr = ff_create_stack_element(file_path,
          search_ctx->ffsc_wc_path, search_ctx->ffsc_level, 0);
      if (sptr == NULL)
        break;
      ff_push(search_ctx, sptr);
    } else
      break;
  }

  vim_free(file_path);
  return NULL;
}
Exemple #23
0
/*
 * Handle marks in the viminfo file:
 * fp_out != NULL: copy marks for buffers not in buffer list
 * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only
 * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles
 */
void copy_viminfo_marks(vir_T *virp, FILE *fp_out, int count, int eof, int flags)
{
  char_u      *line = virp->vir_line;
  buf_T       *buf;
  int num_marked_files;
  int load_marks;
  int copy_marks_out;
  char_u      *str;
  int i;
  char_u      *p;
  char_u      *name_buf;
  pos_T pos;
  list_T      *list = NULL;

  if ((name_buf = alloc(LSIZE)) == NULL)
    return;
  *name_buf = NUL;

  if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT))) {
    list = list_alloc();
    if (list != NULL)
      set_vim_var_list(VV_OLDFILES, list);
  }

  num_marked_files = get_viminfo_parameter('\'');
  while (!eof && (count < num_marked_files || fp_out == NULL)) {
    if (line[0] != '>') {
      if (line[0] != '\n' && line[0] != '\r' && line[0] != '#') {
        if (viminfo_error("E576: ", _("Missing '>'"), line))
          break;                /* too many errors, return now */
      }
      eof = vim_fgets(line, LSIZE, virp->vir_fd);
      continue;                 /* Skip this dud line */
    }

    /*
     * Handle long line and translate escaped characters.
     * Find file name, set str to start.
     * Ignore leading and trailing white space.
     */
    str = skipwhite(line + 1);
    str = viminfo_readstring(virp, (int)(str - virp->vir_line), FALSE);
    if (str == NULL)
      continue;
    p = str + STRLEN(str);
    while (p != str && (*p == NUL || vim_isspace(*p)))
      p--;
    if (*p)
      p++;
    *p = NUL;

    if (list != NULL)
      list_append_string(list, str, -1);

    /*
     * If fp_out == NULL, load marks for current buffer.
     * If fp_out != NULL, copy marks for buffers not in buflist.
     */
    load_marks = copy_marks_out = FALSE;
    if (fp_out == NULL) {
      if ((flags & VIF_WANT_MARKS) && curbuf->b_ffname != NULL) {
        if (*name_buf == NUL)               /* only need to do this once */
          home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE);
        if (fnamecmp(str, name_buf) == 0)
          load_marks = TRUE;
      }
    } else   { /* fp_out != NULL */
             /* This is slow if there are many buffers!! */
      for (buf = firstbuf; buf != NULL; buf = buf->b_next)
        if (buf->b_ffname != NULL) {
          home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE);
          if (fnamecmp(str, name_buf) == 0)
            break;
        }

      /*
       * copy marks if the buffer has not been loaded
       */
      if (buf == NULL || !buf->b_marks_read) {
        copy_marks_out = TRUE;
        fputs("\n> ", fp_out);
        viminfo_writestring(fp_out, str);
        count++;
      }
    }
    vim_free(str);

    pos.coladd = 0;
    while (!(eof = viminfo_readline(virp)) && line[0] == TAB) {
      if (load_marks) {
        if (line[1] != NUL) {
          unsigned u;

          sscanf((char *)line + 2, "%ld %u", &pos.lnum, &u);
          pos.col = u;
          switch (line[1]) {
          case '"': curbuf->b_last_cursor = pos; break;
          case '^': curbuf->b_last_insert = pos; break;
          case '.': curbuf->b_last_change = pos; break;
          case '+':
            /* changelist positions are stored oldest
             * first */
            if (curbuf->b_changelistlen == JUMPLISTSIZE)
              /* list is full, remove oldest entry */
              mch_memmove(curbuf->b_changelist,
                  curbuf->b_changelist + 1,
                  sizeof(pos_T) * (JUMPLISTSIZE - 1));
            else
              ++curbuf->b_changelistlen;
            curbuf->b_changelist[
              curbuf->b_changelistlen - 1] = pos;
            break;
          default:  if ((i = line[1] - 'a') >= 0 && i < NMARKS)
              curbuf->b_namedm[i] = pos;
          }
        }
      } else if (copy_marks_out)
        fputs((char *)line, fp_out);
    }
    if (load_marks) {
      win_T       *wp;

      FOR_ALL_WINDOWS(wp)
      {
        if (wp->w_buffer == curbuf)
          wp->w_changelistidx = curbuf->b_changelistlen;
      }
      break;
    }
  }
  vim_free(name_buf);
}
Exemple #24
0
/*
 * Open an existing or new memory block file.
 *
 *  fname:	name of file to use (NULL means no file at all)
 *		Note: fname must have been allocated, it is not copied!
 *			If opening the file fails, fname is freed.
 *  flags:	flags for open() call
 *
 *  If fname != NULL and file cannot be opened, fail.
 *
 * return value: identifier for this memory block file.
 */
    memfile_T *
mf_open(char_u *fname, int flags)
{
    memfile_T		*mfp;
    off_T		size;
#if defined(STATFS) && defined(UNIX) && !defined(__QNX__) && !defined(__minix)
# define USE_FSTATFS
    struct STATFS	stf;
#endif

    if ((mfp = (memfile_T *)alloc((unsigned)sizeof(memfile_T))) == NULL)
	return NULL;

    if (fname == NULL)	    /* no file for this memfile, use memory only */
    {
	mfp->mf_fname = NULL;
	mfp->mf_ffname = NULL;
	mfp->mf_fd = -1;
    }
    else
    {
	mf_do_open(mfp, fname, flags);	/* try to open the file */

	/* if the file cannot be opened, return here */
	if (mfp->mf_fd < 0)
	{
	    vim_free(mfp);
	    return NULL;
	}
    }

    mfp->mf_free_first = NULL;		/* free list is empty */
    mfp->mf_used_first = NULL;		/* used list is empty */
    mfp->mf_used_last = NULL;
    mfp->mf_dirty = FALSE;
    mfp->mf_used_count = 0;
    mf_hash_init(&mfp->mf_hash);
    mf_hash_init(&mfp->mf_trans);
    mfp->mf_page_size = MEMFILE_PAGE_SIZE;
#ifdef FEAT_CRYPT
    mfp->mf_old_key = NULL;
#endif

#ifdef USE_FSTATFS
    /*
     * Try to set the page size equal to the block size of the device.
     * Speeds up I/O a lot.
     * When recovering, the actual block size will be retrieved from block 0
     * in ml_recover().  The size used here may be wrong, therefore
     * mf_blocknr_max must be rounded up.
     */
    if (mfp->mf_fd >= 0
	    && fstatfs(mfp->mf_fd, &stf, sizeof(struct statfs), 0) == 0
	    && stf.F_BSIZE >= MIN_SWAP_PAGE_SIZE
	    && stf.F_BSIZE <= MAX_SWAP_PAGE_SIZE)
	mfp->mf_page_size = stf.F_BSIZE;
#endif

    if (mfp->mf_fd < 0 || (flags & (O_TRUNC|O_EXCL))
		  || (size = vim_lseek(mfp->mf_fd, (off_T)0L, SEEK_END)) <= 0)
	mfp->mf_blocknr_max = 0;	/* no file or empty file */
    else
	mfp->mf_blocknr_max = (blocknr_T)((size + mfp->mf_page_size - 1)
							 / mfp->mf_page_size);
    mfp->mf_blocknr_min = -1;
    mfp->mf_neg_count = 0;
    mfp->mf_infile_count = mfp->mf_blocknr_max;

    /*
     * Compute maximum number of pages ('maxmem' is in Kbyte):
     *	'mammem' * 1Kbyte / page-size-in-bytes.
     * Avoid overflow by first reducing page size as much as possible.
     */
    {
	int	    shift = 10;
	unsigned    page_size = mfp->mf_page_size;

	while (shift > 0 && (page_size & 1) == 0)
	{
	    page_size = page_size >> 1;
	    --shift;
	}
	mfp->mf_used_count_max = (p_mm << shift) / page_size;
	if (mfp->mf_used_count_max < 10)
	    mfp->mf_used_count_max = 10;
    }

    return mfp;
}
Exemple #25
0
/*
 * Set named mark "c" to position "pos".
 * When "c" is upper case use file "fnum".
 * Returns OK on success, FAIL if bad name given.
 */
int setmark_pos(int c, pos_T *pos, int fnum)
{
  int i;

  /* Check for a special key (may cause islower() to crash). */
  if (c < 0)
    return FAIL;

  if (c == '\'' || c == '`') {
    if (pos == &curwin->w_cursor) {
      setpcmark();
      /* keep it even when the cursor doesn't move */
      curwin->w_prev_pcmark = curwin->w_pcmark;
    } else
      curwin->w_pcmark = *pos;
    return OK;
  }

  if (c == '"') {
    curbuf->b_last_cursor = *pos;
    return OK;
  }

  /* Allow setting '[ and '] for an autocommand that simulates reading a
   * file. */
  if (c == '[') {
    curbuf->b_op_start = *pos;
    return OK;
  }
  if (c == ']') {
    curbuf->b_op_end = *pos;
    return OK;
  }

  if (c == '<' || c == '>') {
    if (c == '<')
      curbuf->b_visual.vi_start = *pos;
    else
      curbuf->b_visual.vi_end = *pos;
    if (curbuf->b_visual.vi_mode == NUL)
      /* Visual_mode has not yet been set, use a sane default. */
      curbuf->b_visual.vi_mode = 'v';
    return OK;
  }

  if (c > 'z')              /* some islower() and isupper() cannot handle
                                characters above 127 */
    return FAIL;
  if (islower(c)) {
    i = c - 'a';
    curbuf->b_namedm[i] = *pos;
    return OK;
  }
  if (isupper(c)) {
    i = c - 'A';
    namedfm[i].fmark.mark = *pos;
    namedfm[i].fmark.fnum = fnum;
    vim_free(namedfm[i].fname);
    namedfm[i].fname = NULL;
    return OK;
  }
  return FAIL;
}
Exemple #26
0
/// Free the array of a hash table.  Does not free the items it contains!
/// If "ht" is not freed then you should call hash_init() next!
///
/// @param ht
void hash_clear(hashtab_T *ht)
{
  if (ht->ht_array != ht->ht_smallarray) {
    vim_free(ht->ht_array);
  }
}
Exemple #27
0
/*
 * External interface
 */
    static void
DoPythonCommand(exarg_T *eap, const char *cmd)
{
#ifndef PY_CAN_RECURSE
    static int		recursive = 0;
#endif
#if defined(MACOS) && !defined(MACOS_X_UNIX)
    GrafPtr		oldPort;
#endif
#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
    char		*saved_locale;
#endif

#ifndef PY_CAN_RECURSE
    if (recursive)
    {
	EMSG(_("E659: Cannot invoke Python recursively"));
	return;
    }
    ++recursive;
#endif

#if defined(MACOS) && !defined(MACOS_X_UNIX)
    GetPort(&oldPort);
    /* Check if the Python library is available */
    if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress)
	goto theend;
#endif
    if (Python_Init())
	goto theend;

    RangeStart = eap->line1;
    RangeEnd = eap->line2;
    Python_Release_Vim();	    /* leave vim */

#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
    /* Python only works properly when the LC_NUMERIC locale is "C". */
    saved_locale = setlocale(LC_NUMERIC, NULL);
    if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0)
	saved_locale = NULL;
    else
    {
	/* Need to make a copy, value may change when setting new locale. */
	saved_locale = (char *)vim_strsave((char_u *)saved_locale);
	(void)setlocale(LC_NUMERIC, "C");
    }
#endif

    Python_RestoreThread();	    /* enter python */

    PyRun_SimpleString((char *)(cmd));

    Python_SaveThread();	    /* leave python */

#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
    if (saved_locale != NULL)
    {
	(void)setlocale(LC_NUMERIC, saved_locale);
	vim_free(saved_locale);
    }
#endif

    Python_Lock_Vim();		    /* enter vim */
    PythonIO_Flush();
#if defined(MACOS) && !defined(MACOS_X_UNIX)
    SetPort(oldPort);
#endif

theend:
#ifndef PY_CAN_RECURSE
    --recursive;
#endif
    return;	    /* keeps lint happy */
}