Hi,

2013/10/11 Fri 10:13:34 UTC+9 Ken Takata wrote:
> Your patch still have some coding style errors and I fixed them.
> Please check the attached patch.
> 
> Additionally, there are still some issues I think:
> 
> 1. Copyright information is missing in the timers.c.
> 2. MCH_MONOTONIC_TIME is defined in os_macosx.m and os_unix.c, but it should 
> be
>    defined in header files because the definition is used in timers.c.
> 3. Do we still need to support MSVC6? (Note that 7.4.044 is a fix for VC6.)
>    If it is needed, we can't use "long long". We should define a 64-bit type.
>    Similar (but not the same) thing is written in the todo.txt:
> 
> > On 64 bit MS-Windows "long" is only 32 bits, but we sometimes need to store 
> > a
> > 64 bits value.  Change all number options to use nropt_T and define it to 
> > the
> > right type.

I have updated the patch:

* Couldn't compile with MSVC.
* Add has("timers").
* Update documents.
* Fix a warning.
* etc.

Regards,
Ken Takata

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
diff --git a/Filelist b/Filelist
--- a/Filelist
+++ b/Filelist
@@ -69,6 +69,7 @@
 		src/term.c \
 		src/term.h \
 		src/termlib.c \
+		src/timers.c \
 		src/ui.c \
 		src/undo.c \
 		src/version.c \
@@ -94,6 +95,7 @@
 		src/testdir/python_after/*.py \
 		src/testdir/python_before/*.py \
 		src/proto.h \
+		src/proto/timers.pro \
 		src/proto/blowfish.pro \
 		src/proto/buffer.pro \
 		src/proto/charset.pro \
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*	For Vim version 7.4.  Last change: 2013 Aug 24
+*eval.txt*	For Vim version 7.4.  Last change: 2013 Sep 10
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -1715,6 +1715,7 @@
 byteidx( {expr}, {nr})		Number	byte index of {nr}'th char in {expr}
 call( {func}, {arglist} [, {dict}])
 				any	call {func} with arguments {arglist}
+canceltimeout( {nr})		Number	cancel the timeout or interval
 ceil( {expr})			Float	round {expr} up
 changenr()			Number	current change number
 char2nr( {expr}[, {utf8}])	Number	ASCII/UTF8 value of first char in {expr}
@@ -1926,6 +1927,8 @@
 serverlist()			String	get a list of available servers
 setbufvar( {expr}, {varname}, {val})	set {varname} in buffer {expr} to {val}
 setcmdpos( {pos})		Number	set cursor position in command-line
+setinterval( {nr}, {string})	Number	evaluate the expression {string} every
+					{nr} milliseconds
 setline( {lnum}, {line})	Number	set line {lnum} to {line}
 setloclist( {nr}, {list}[, {action}])
 				Number	modify location list using {list}
@@ -1936,6 +1939,8 @@
 settabvar( {nr}, {varname}, {val})	set {varname} in tab page {nr} to {val}
 settabwinvar( {tabnr}, {winnr}, {varname}, {val})    set {varname} in window
 					{winnr} in tab page {tabnr} to {val}
+settimeout( {nr}, {string})	Number	evaluate the expression {string} after
+					{nr} milliseconds
 setwinvar( {nr}, {varname}, {val})	set {varname} in window {nr} to {val}
 sha256( {string})		String	SHA256 checksum of {string}
 shellescape( {string} [, {special}])
@@ -2281,6 +2286,15 @@
 		{dict} is for functions with the "dict" attribute.  It will be
 		used to set the local variable "self". |Dictionary-function|
 
+canceltimeout({nr})					*canceltimeout()*
+		Cancel the timeout or interval with id, {nr}, preventing it
+		from every firing.
+		Also see |settimeout()| and |setinterval()|.
+		{only available when compiled with the |+timers| feature}
+		Examples: >
+			let timeout_id = settimeout(5000, 'echo(2)')
+			echo canceltimeout(timeout_id)
+
 ceil({expr})							*ceil()*
 		Return the smallest integral value greater than or equal to
 		{expr} as a |Float| (round up).
@@ -5187,6 +5201,23 @@
 		Returns 0 when successful, 1 when not editing the command
 		line.
 
+setinterval({nr}, {string})				*setinterval()* *E881*
+		Immediately returns an interval id and evaluate the expression,
+		{string}, every {nr} milliseconds. Intervals do not pile up.
+		The timer's resolution defaults to 100ms and can be changed by
+		setting |ticktime|.  Intervals can be canceled by calling
+		|canceltimeout({interval_id})|.
+		NOTE: Vim is single-threaded and all expressions are run
+		within the main thread.  Therefore, expressions should return
+		control flow within a short amount of time.
+		Also see |settimeout()| and |canceltimeout()|.
+		{only available when compiled with the |+timers| feature}
+		Examples: >
+			:call setinterval(1000, "call echo(2)")
+<		2
+		2
+		2
+
 setline({lnum}, {text})					*setline()*
 		Set line {lnum} of the current buffer to {text}.  To insert
 		lines use |append()|.
@@ -5356,6 +5387,21 @@
 			:call settabwinvar(3, 2, "myvar", "foobar")
 <		This function is not available in the |sandbox|.
 
+settimeout({nr}, {string})				*settimeout()*
+		Immediately returns an interval id and evaluate the expression,
+		{string}, once after {nr} milliseconds. The timer's
+		resolution defaults to 100ms and can be changed by setting
+		|ticktime|.  Timeouts can be canceled by calling
+		|canceltimeout({interval_id})|.
+		NOTE: Vim is single-threaded and all expressions are run
+		within the main thread.  Therefore, expressions should return
+		control flow within a short amount of time.
+		Also see |setinterval()| and |canceltimeout()|.
+		{only available when compiled with the |+timers| feature}
+		Examples: >
+			:call settimeout(1000, "call echo(2)")
+<		2
+
 setwinvar({nr}, {varname}, {val})			*setwinvar()*
 		Like |settabwinvar()| for the current tab page.
 		Examples: >
@@ -6479,6 +6525,7 @@
 textobjects		Compiled with support for |text-objects|.
 tgetent			Compiled with tgetent support, able to use a termcap
 			or terminfo file.
+timers			Compiled with support for timer funtions.
 title			Compiled with window title support |'title'|.
 toolbar			Compiled with support for |gui-toolbar|.
 unix			Unix version of Vim.
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1544,6 +1544,7 @@
 |:tearoff|	:te[aroff]	tear-off a menu
 |:tfirst|	:tf[irst]	jump to first matching tag
 |:throw|	:th[row]	throw an exception
+|:timers|	:ti[mers]	show all pending timers
 |:tjump|	:tj[ump]	like ":tselect", but jump directly when there
 				is only one match
 |:tlast|	:tl[ast]	jump to last matching tag
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -7253,6 +7253,17 @@
 	uses another default.
 	Backticks cannot be used in this option for security reasons.
 
+						*'ticktime'* *'tt'*
+'ticktime' 'tt'		number	(default 100)
+			global
+			{not in Vi}
+	This is the resolution for all timers set with |setinterval()| and
+	|settimeout()|.  Decreasing this number will make the timers
+	more accurate but will also make Vim less efficient.  To globally
+	disable all timers for debugging, set |ticktime| to -1.
+	Also see |setinterval()|, |settimeout()|, and |canceltimeout()|.
+	{only available when compiled with the |+timers| feature}
+
 			     *'tildeop'* *'top'* *'notildeop'* *'notop'*
 'tildeop' 'top'		boolean	(default off)
 			global
diff --git a/runtime/doc/tags b/runtime/doc/tags
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -1014,6 +1014,7 @@
 'tf'	options.txt	/*'tf'*
 'tgst'	options.txt	/*'tgst'*
 'thesaurus'	options.txt	/*'thesaurus'*
+'ticktime'	options.txt	/*'ticktime'*
 'tildeop'	options.txt	/*'tildeop'*
 'timeout'	options.txt	/*'timeout'*
 'timeoutlen'	options.txt	/*'timeoutlen'*
@@ -1032,6 +1033,7 @@
 'ts'	options.txt	/*'ts'*
 'tsl'	options.txt	/*'tsl'*
 'tsr'	options.txt	/*'tsr'*
+'tt'	options.txt	/*'tt'*
 'ttimeout'	options.txt	/*'ttimeout'*
 'ttimeoutlen'	options.txt	/*'ttimeoutlen'*
 'ttm'	options.txt	/*'ttm'*
@@ -4296,6 +4298,7 @@
 E879	syntax.txt	/*E879*
 E88	windows.txt	/*E88*
 E880	if_pyth.txt	/*E880*
+E881	eval.txt	/*E881*
 E89	message.txt	/*E89*
 E90	message.txt	/*E90*
 E91	options.txt	/*E91*
@@ -4987,6 +4990,7 @@
 c_digraph	cmdline.txt	/*c_digraph*
 c_wildchar	cmdline.txt	/*c_wildchar*
 call()	eval.txt	/*call()*
+canceltimeout()	eval.txt	/*canceltimeout()*
 carriage-return	intro.txt	/*carriage-return*
 case	change.txt	/*case*
 catch-all	eval.txt	/*catch-all*
@@ -7653,6 +7657,7 @@
 set-spc-auto	spell.txt	/*set-spc-auto*
 setbufvar()	eval.txt	/*setbufvar()*
 setcmdpos()	eval.txt	/*setcmdpos()*
+setinterval()	eval.txt	/*setinterval()*
 setline()	eval.txt	/*setline()*
 setloclist()	eval.txt	/*setloclist()*
 setmatches()	eval.txt	/*setmatches()*
@@ -7661,6 +7666,7 @@
 setreg()	eval.txt	/*setreg()*
 settabvar()	eval.txt	/*settabvar()*
 settabwinvar()	eval.txt	/*settabwinvar()*
+settimeout()	eval.txt	/*settimeout()*
 setting-guifont	gui.txt	/*setting-guifont*
 setting-guitablabel	tabpage.txt	/*setting-guitablabel*
 setting-tabline	tabpage.txt	/*setting-tabline*
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -412,6 +412,7 @@
 N  *+termresponse*	support for |t_RV| and |v:termresponse|
 N  *+textobjects*	|text-objects| selection
    *+tgetent*		non-Unix only: able to use external termcap
+   *+timers*		timer functions
 N  *+title*		Setting the window 'title' and 'icon'
 N  *+toolbar*		|gui-toolbar|
 N  *+user_commands*	User-defined commands. |user-commands|
diff --git a/src/Make_bc3.mak b/src/Make_bc3.mak
--- a/src/Make_bc3.mak
+++ b/src/Make_bc3.mak
@@ -91,6 +91,7 @@
 	syntax.obj \
 	tag.obj \
 	term.obj \
+	timers.obj \
 	ui.obj \
 	undo.obj \
 	window.obj
diff --git a/src/Make_bc5.mak b/src/Make_bc5.mak
--- a/src/Make_bc5.mak
+++ b/src/Make_bc5.mak
@@ -617,6 +617,7 @@
 	$(OBJDIR)\syntax.obj \
 	$(OBJDIR)\tag.obj \
 	$(OBJDIR)\term.obj \
+	$(OBJDIR)\timers.obj \
 	$(OBJDIR)\ui.obj \
 	$(OBJDIR)\undo.obj \
 	$(OBJDIR)\version.obj \
diff --git a/src/Make_cyg.mak b/src/Make_cyg.mak
--- a/src/Make_cyg.mak
+++ b/src/Make_cyg.mak
@@ -568,6 +568,7 @@
 	$(OUTDIR)/syntax.o \
 	$(OUTDIR)/tag.o \
 	$(OUTDIR)/term.o \
+	$(OUTDIR)/timers.o \
 	$(OUTDIR)/ui.o \
 	$(OUTDIR)/undo.o \
 	$(OUTDIR)/version.o \
diff --git a/src/Make_dice.mak b/src/Make_dice.mak
--- a/src/Make_dice.mak
+++ b/src/Make_dice.mak
@@ -67,6 +67,7 @@
 	syntax.c \
 	tag.c \
 	term.c \
+	timers.c \
 	ui.c \
 	undo.c \
 	window.c \
@@ -113,6 +114,7 @@
 	o/syntax.o \
 	o/tag.o \
 	o/term.o \
+	o/timers.o \
 	o/ui.o \
 	o/undo.o \
 	o/window.o \
@@ -226,6 +228,8 @@
 
 o/termlib.o:	termlib.c $(SYMS)
 
+o/timers.o:	timers.c  $(SYMS)
+
 o/ui.o: ui.c	$(SYMS)
 
 o/undo.o: undo.c	$(SYMS)
diff --git a/src/Make_djg.mak b/src/Make_djg.mak
--- a/src/Make_djg.mak
+++ b/src/Make_djg.mak
@@ -60,6 +60,7 @@
 	obj/syntax.o \
 	obj/tag.o \
 	obj/term.o \
+	obj/timers.o \
 	obj/ui.o \
 	obj/undo.o \
 	obj/window.o \
diff --git a/src/Make_ivc.mak b/src/Make_ivc.mak
--- a/src/Make_ivc.mak
+++ b/src/Make_ivc.mak
@@ -253,6 +253,7 @@
 	"$(INTDIR)/syntax.obj" \
 	"$(INTDIR)/tag.obj" \
 	"$(INTDIR)/term.obj" \
+	"$(INTDIR)/timers.obj" \
 	"$(INTDIR)/ui.obj" \
 	"$(INTDIR)/undo.obj" \
 	"$(INTDIR)/version.obj" \
@@ -649,6 +650,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\timers.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\ui.c
 # End Source File
 # Begin Source File
diff --git a/src/Make_manx.mak b/src/Make_manx.mak
--- a/src/Make_manx.mak
+++ b/src/Make_manx.mak
@@ -75,6 +75,7 @@
 	syntax.c \
 	tag.c \
 	term.c \
+	timers.c \
 	ui.c \
 	undo.c \
 	window.c \
@@ -123,6 +124,7 @@
 	obj/syntax.o \
 	obj/tag.o \
 	obj/term.o \
+	obj/timers.o \
 	obj/ui.o \
 	obj/undo.o \
 	obj/window.o \
@@ -170,6 +172,7 @@
 	proto/tag.pro \
 	proto/term.pro \
 	proto/termlib.pro \
+	proto/timers.pro \
 	proto/ui.pro \
 	proto/undo.pro \
 	proto/window.pro
@@ -348,6 +351,9 @@
 obj/termlib.o:	termlib.c
 	$(CCSYM) $@ termlib.c
 
+obj/timers.o:	timers.c
+	$(CCSYM) $@ timers.c
+
 obj/ui.o:	ui.c
 	$(CCSYM) $@ ui.c
 
diff --git a/src/Make_ming.mak b/src/Make_ming.mak
--- a/src/Make_ming.mak
+++ b/src/Make_ming.mak
@@ -546,6 +546,7 @@
 	$(OUTDIR)/syntax.o \
 	$(OUTDIR)/tag.o \
 	$(OUTDIR)/term.o \
+	$(OUTDIR)/timers.o \
 	$(OUTDIR)/ui.o \
 	$(OUTDIR)/undo.o \
 	$(OUTDIR)/version.o \
diff --git a/src/Make_morph.mak b/src/Make_morph.mak
--- a/src/Make_morph.mak
+++ b/src/Make_morph.mak
@@ -65,6 +65,7 @@
 	syntax.c						\
 	tag.c							\
 	term.c							\
+	timers.c						\
 	ui.c							\
 	undo.c							\
 	version.c						\
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -569,6 +569,7 @@
 	$(OUTDIR)\syntax.obj \
 	$(OUTDIR)\tag.obj \
 	$(OUTDIR)\term.obj \
+	$(OUTDIR)\timers.obj \
 	$(OUTDIR)\ui.obj \
 	$(OUTDIR)\undo.obj \
 	$(OUTDIR)\window.obj \
@@ -1192,6 +1193,8 @@
 
 $(OUTDIR)/term.obj:	$(OUTDIR) term.c  $(INCL)
 
+$(OUTDIR)/timers.obj:	$(OUTDIR) timers.c  $(INCL)
+
 $(OUTDIR)/ui.obj:	$(OUTDIR) ui.c  $(INCL)
 
 $(OUTDIR)/undo.obj:	$(OUTDIR) undo.c  $(INCL)
diff --git a/src/Make_os2.mak b/src/Make_os2.mak
--- a/src/Make_os2.mak
+++ b/src/Make_os2.mak
@@ -79,6 +79,7 @@
 	syntax.o \
 	tag.o \
 	term.o \
+	timers.o \
 	ui.o \
 	undo.o \
 	window.o \
diff --git a/src/Make_sas.mak b/src/Make_sas.mak
--- a/src/Make_sas.mak
+++ b/src/Make_sas.mak
@@ -177,6 +177,7 @@
 	syntax.o \
 	tag.o \
 	term.o \
+	timers.o \
 	ui.o \
 	undo.o \
 	window.o \
@@ -225,6 +226,7 @@
 	proto/tag.pro \
 	proto/term.pro \
 	proto/termlib.pro \
+	proto/timers.pro \
 	proto/ui.pro \
 	proto/undo.pro \
 	proto/window.pro
@@ -368,6 +370,8 @@
 proto/term.pro:		term.c
 termlib.o:		termlib.c
 proto/termlib.pro:	termlib.c
+timers.o:		timers.c
+proto/timers.pro:	timers.c
 ui.o:			ui.c
 proto/ui.pro:		ui.c
 undo.o:			undo.c
diff --git a/src/Make_vms.mms b/src/Make_vms.mms
--- a/src/Make_vms.mms
+++ b/src/Make_vms.mms
@@ -308,7 +308,7 @@
 	ex_docmd.c ex_eval.c ex_getln.c if_xcmdsrv.c fileio.c fold.c getchar.c \
 	hardcopy.c hashtab.c main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \
 	misc2.c move.c normal.c ops.c option.c popupmnu.c quickfix.c regexp.c search.c sha256.c\
-	spell.c syntax.c tag.c term.c termlib.c ui.c undo.c version.c screen.c \
+	spell.c syntax.c tag.c term.c termlib.c timers.c ui.c undo.c version.c screen.c \
 	window.c os_unix.c os_vms.c pathdef.c \
 	$(GUI_SRC) $(PERL_SRC) $(PYTHON_SRC) $(TCL_SRC) $(SNIFF_SRC) \
 	$(RUBY_SRC) $(HANGULIN_SRC) $(MZSCH_SRC)
@@ -319,7 +319,7 @@
 	menu.obj memfile.obj memline.obj message.obj misc1.obj misc2.obj \
 	move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj quickfix.obj \
 	regexp.obj search.obj sha256.obj spell.obj syntax.obj tag.obj term.obj termlib.obj \
-	ui.obj undo.obj screen.obj version.obj window.obj os_unix.obj \
+	timers.obj ui.obj undo.obj screen.obj version.obj window.obj os_unix.obj \
 	os_vms.obj pathdef.obj if_mzsch.obj\
 	$(GUI_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(TCL_OBJ) $(SNIFF_OBJ) \
 	$(RUBY_OBJ) $(HANGULIN_OBJ) $(MZSCH_OBJ)
diff --git a/src/Makefile b/src/Makefile
--- a/src/Makefile
+++ b/src/Makefile
@@ -1468,6 +1468,7 @@
 	syntax.c \
 	tag.c \
 	term.c \
+	timers.c \
 	ui.c \
 	undo.c \
 	version.c \
@@ -1557,6 +1558,7 @@
 	$(SNIFF_OBJ) \
 	objects/tag.o \
 	objects/term.o \
+	objects/timers.o \
 	objects/ui.o \
 	objects/undo.o \
 	objects/version.o \
@@ -1630,6 +1632,7 @@
 	tag.pro \
 	term.pro \
 	termlib.pro \
+	timers.pro \
 	ui.pro \
 	undo.pro \
 	version.pro \
@@ -2723,6 +2726,9 @@
 objects/term.o: term.c
 	$(CCC) -o $@ term.c
 
+objects/timers.o: timers.c
+	$(CCC) -o $@ timers.c
+
 objects/ui.o: ui.c
 	$(CCC) -o $@ ui.c
 
@@ -3004,6 +3010,9 @@
  ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
  gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
  arabic.h
+objects/timers.o: timers.c vim.h auto/config.h feature.h os_unix.h os_mac.h ascii.h \
+  keymap.h term.h macros.h option.h structs.h regexp.h gui.h ex_cmds.h \
+  proto.h proto/timers.pro globals.h farsi.h arabic.h auto/osdef.h
 objects/ui.o: ui.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h ascii.h \
  keymap.h term.h macros.h option.h structs.h regexp.h gui.h gui_beval.h \
  proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h arabic.h
diff --git a/src/auto/configure b/src/auto/configure
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -11090,6 +11090,57 @@
 
 fi
 
+
+for ac_func in clock_gettime
+do :
+  ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
+if test "x$ac_cv_func_clock_gettime" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CLOCK_GETTIME 1
+_ACEOF
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
+if ${ac_cv_lib_rt_clock_gettime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rt_clock_gettime=yes
+else
+  ac_cv_lib_rt_clock_gettime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+     LIBS="$LIBS -lrt"
+fi
+fi
+done
+
 for ac_func in bcmp fchdir fchown fsync getcwd getpseudotty \
 	getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \
 	memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
diff --git a/src/configure.in b/src/configure.in
--- a/src/configure.in
+++ b/src/configure.in
@@ -3263,6 +3263,13 @@
   AC_DEFINE(BAD_GETCWD)
 fi
 
+AC_CHECK_FUNCS(clock_gettime, [], [
+  AC_CHECK_LIB(rt, clock_gettime, [
+     LIBS="$LIBS -lrt"
+   ])
+])
+
+
 dnl Check for functions in one big call, to reduce the size of configure.
 dnl Can only be used for functions that do not require any include.
 AC_CHECK_FUNCS(bcmp fchdir fchown fsync getcwd getpseudotty \
diff --git a/src/eval.c b/src/eval.c
--- a/src/eval.c
+++ b/src/eval.c
@@ -674,6 +674,11 @@
 static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setmatches __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setpos __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_TIMERS
+static void f_canceltimeout __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_setinterval __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_settimeout __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_settabvar __ARGS((typval_T *argvars, typval_T *rettv));
@@ -7862,6 +7867,9 @@
     {"byte2line",	1, 1, f_byte2line},
     {"byteidx",		2, 2, f_byteidx},
     {"call",		2, 3, f_call},
+#ifdef FEAT_TIMERS
+    {"canceltimeout",	1, 1, f_canceltimeout},
+#endif
 #ifdef FEAT_FLOAT
     {"ceil",		1, 1, f_ceil},
 #endif
@@ -8060,6 +8068,9 @@
     {"serverlist",	0, 0, f_serverlist},
     {"setbufvar",	3, 3, f_setbufvar},
     {"setcmdpos",	1, 1, f_setcmdpos},
+#ifdef FEAT_TIMERS
+    {"setinterval",	2, 2, f_setinterval},
+#endif
     {"setline",		2, 2, f_setline},
     {"setloclist",	2, 3, f_setloclist},
     {"setmatches",	1, 1, f_setmatches},
@@ -8068,6 +8079,9 @@
     {"setreg",		2, 3, f_setreg},
     {"settabvar",	3, 3, f_settabvar},
     {"settabwinvar",	4, 4, f_settabwinvar},
+#ifdef FEAT_TIMERS
+    {"settimeout",	2, 2, f_settimeout},
+#endif
     {"setwinvar",	3, 3, f_setwinvar},
 #ifdef FEAT_CRYPT
     {"sha256",		1, 1, f_sha256},
@@ -12486,9 +12500,15 @@
 #ifdef FEAT_TEXTOBJ
 	"textobjects",
 #endif
+#ifdef FEAT_TIMERS
+	"timers",
+#endif
 #ifdef HAVE_TGETENT
 	"tgetent",
 #endif
+#ifdef FEAT_TIMERS
+	"timers",
+#endif
 #ifdef FEAT_TITLE
 	"title",
 #endif
@@ -16599,6 +16619,119 @@
 #endif
 }
 
+#ifdef FEAT_TIMERS
+static int timeout_id = 0;
+
+    static void
+set_timeout(argvars, rettv, interval)
+    typval_T	*argvars;
+    typval_T	*rettv;
+    int		interval;
+{
+    timeout_T *to;
+    long i = get_tv_number(&argvars[0]);
+    char_u *cmd = get_tv_string(&argvars[1]);
+
+    rettv->v_type = VAR_NUMBER;
+
+    if (i < 0)
+    {
+	rettv->vval.v_number = -1;
+	EMSG2(_(e_invarg2), "Interval cannot be negative.");
+	return;
+    }
+
+    to = malloc(sizeof(timeout_T));
+    to->id = timeout_id++;
+    to->tm = get_monotonic_time() + i;
+    if (sourcing_name)
+    {
+	to->sourcing_name = (char_u*)strdup((char *)sourcing_name);
+	to->sourcing_lnum = sourcing_lnum;
+    }
+    else
+    {
+	to->sourcing_name = (char_u*)strdup((char*)cmd);
+	to->sourcing_lnum = 0;
+    }
+
+    rettv->vval.v_number = to->id;
+    to->cmd = (char_u*)strdup((char*)cmd);
+    to->interval = interval ? i : -1;
+    to->next = NULL;
+
+    insert_timeout(to);
+}
+
+/*
+ * "setinterval()" function
+ */
+    static void
+f_setinterval(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    set_timeout(argvars, rettv, TRUE);
+}
+
+/*
+ * "settimeout()" function
+ */
+    static void
+f_settimeout(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    set_timeout(argvars, rettv, FALSE);
+}
+
+/*
+ * "canceltimeout()" function
+ */
+    static void
+f_canceltimeout(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    timeout_T *tmp = timeouts;
+    timeout_T *prev = NULL;
+    timeout_T *next;
+    long id = get_tv_number(&argvars[0]);
+
+    if (id < 0)
+    {
+	rettv->vval.v_number = -1;
+	EMSG2(_(e_invarg2), "Timeout id cannot be negative.");
+	return;
+    }
+
+    while (tmp != NULL)
+    {
+	next = tmp->next;
+	if (tmp->id == id)
+	{
+	    if (prev)
+		prev->next = next;
+	    else
+		timeouts = next;
+	    free(tmp->cmd);
+	    free(tmp);
+	    rettv->vval.v_number = 0;
+	    rettv->v_type = VAR_NUMBER;
+	    return;
+	}
+	else
+	{
+	    prev = tmp;
+	}
+	tmp = next;
+    }
+    rettv->vval.v_number = 1;
+    rettv->v_type = VAR_NUMBER;
+    EMSG2(_(e_invarg2), "Timeout id not found.");
+}
+#endif
+
 /*
  * "setpos()" function
  */
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -979,6 +979,8 @@
 			RANGE|NOTADR|BANG|TRLBAR|ZEROR),
 EX(CMD_throw,		"throw",	ex_throw,
 			EXTRA|NEEDARG|SBOXOK|CMDWIN),
+EX(CMD_timers,		"timers",	ex_timers,
+			SBOXOK|CMDWIN),
 EX(CMD_tjump,		"tjump",	ex_tag,
 			BANG|TRLBAR|WORD1),
 EX(CMD_tlast,		"tlast",	ex_tag,
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -470,6 +470,12 @@
 # define ex_nbstart		ex_ni
 #endif
 
+#ifdef FEAT_TIMERS
+static void	ex_timers __ARGS((exarg_T *eap));
+#else
+# define ex_timers		ex_ni
+#endif
+
 #ifndef FEAT_EVAL
 # define ex_debug		ex_ni
 # define ex_breakadd		ex_ni
@@ -11508,3 +11514,54 @@
     ml_clearmarked();	   /* clear rest of the marks */
 }
 #endif
+
+#ifdef FEAT_TIMERS
+
+	static void
+ex_timers(eap)
+	exarg_T *eap;
+{
+    int			msg_save = msg_scroll;
+    timeout_T		*tm;
+    char		num_str[20];
+    unsigned long long	now = get_monotonic_time();
+
+    msg_start();
+    MSG_PUTS_TITLE(_("\n--- Timers ---\n"));
+    msg_puts((char_u *)"ID        Next (ms)     Interval (ms)   Source                             Command\n");
+    for (tm = timeouts; tm != NULL; tm = tm->next)
+    {
+	sprintf(num_str, "%i", tm->id);
+	msg_puts((char_u *)num_str);
+	msg_col = 10;
+
+	sprintf(num_str, "%llu", tm->tm - now);
+	msg_puts((char_u *)num_str);
+	msg_col = 24;
+
+	if (tm->interval != -1)
+	{
+	    sprintf(num_str, "%i", tm->interval);
+	    msg_puts((char_u *)num_str);
+	}
+	msg_col = 40;
+
+	msg_puts_long_attr(tm->sourcing_name, 30);
+	if (tm->sourcing_lnum)
+	{
+	    sprintf(num_str, ":%li", tm->sourcing_lnum);
+	    msg_puts_long_attr((char_u *)num_str, 5);
+	}
+
+	msg_col = 75;
+	MSG_PUTS_TITLE(tm->cmd);
+	msg_putchar('\n');
+
+	msg_col = 0;
+    }
+
+    msg_clr_eos();
+    msg_end();
+    msg_scroll = msg_save;
+}
+#endif
diff --git a/src/feature.h b/src/feature.h
--- a/src/feature.h
+++ b/src/feature.h
@@ -467,6 +467,14 @@
 #endif
 
 /*
+ * +timers		settimeout and setinterval functions.
+ */
+#if defined(FEAT_NORMAL) && (defined(MSWIN) || defined(MACOS_X) || \
+	(defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)))
+# define FEAT_TIMERS
+#endif
+
+/*
  * +diff		Displaying diffs in a nice way.
  *			Requires +windows and +autocmd.
  */
diff --git a/src/globals.h b/src/globals.h
--- a/src/globals.h
+++ b/src/globals.h
@@ -1626,3 +1626,10 @@
 #ifdef FEAT_ARABIC
 # include "arabic.h"
 #endif
+
+#ifdef FEAT_TIMERS
+/*
+ * For keeping track of timeouts.
+ */
+EXTERN timeout_T *timeouts INIT(= NULL);
+#endif
diff --git a/src/gui.c b/src/gui.c
--- a/src/gui.c
+++ b/src/gui.c
@@ -2862,7 +2862,9 @@
 gui_wait_for_chars(wtime)
     long    wtime;
 {
-    int	    retval;
+    int 	retval;
+    long	i = 0;
+    long	time_to_wait;
 
 #ifdef FEAT_MENU
     /*
@@ -2887,7 +2889,19 @@
 	/* Blink when waiting for a character.	Probably only does something
 	 * for showmatch() */
 	gui_mch_start_blink();
-	retval = gui_mch_wait_for_chars(wtime);
+	while (i < wtime)
+	{
+#ifdef FEAT_TIMERS
+	    time_to_wait = call_timeouts(wtime - i);
+	    i += time_to_wait;
+	    retval = gui_mch_wait_for_chars(time_to_wait);
+#else
+	    retval = gui_mch_wait_for_chars(wtime);
+	    i += wtime;
+#endif
+	    if (retval == OK)
+		break;
+	}
 	gui_mch_stop_blink();
 	return retval;
     }
@@ -2898,18 +2912,29 @@
     gui_mch_start_blink();
 
     retval = FAIL;
+
+    while (i < p_ut) {
+#ifdef FEAT_TIMERS
+	time_to_wait = call_timeouts(p_ut - i);
+	i += time_to_wait;
+	retval = gui_mch_wait_for_chars(time_to_wait);
+#else
+	retval = gui_mch_wait_for_chars(p_ut);
+	i += p_ut;
+#endif
+	if (retval == OK)
+	    break;
+    }
+
+#ifdef FEAT_AUTOCMD
     /*
      * We may want to trigger the CursorHold event.  First wait for
      * 'updatetime' and if nothing is typed within that time put the
      * K_CURSORHOLD key in the input buffer.
      */
-    if (gui_mch_wait_for_chars(p_ut) == OK)
-	retval = OK;
-#ifdef FEAT_AUTOCMD
-    else if (trigger_cursorhold())
+    if (retval == FAIL && trigger_cursorhold())
     {
 	char_u	buf[3];
-
 	/* Put K_CURSORHOLD in the input buffer. */
 	buf[0] = CSI;
 	buf[1] = KS_EXTRA;
@@ -2920,13 +2945,6 @@
     }
 #endif
 
-    if (retval == FAIL)
-    {
-	/* Blocking wait. */
-	before_blocking();
-	retval = gui_mch_wait_for_chars(-1L);
-    }
-
     gui_mch_stop_blink();
     return retval;
 }
diff --git a/src/main.aap b/src/main.aap
--- a/src/main.aap
+++ b/src/main.aap
@@ -334,6 +334,7 @@
         syntax.c
         tag.c
         term.c
+        timers.c
         ui.c
         undo.c
         window.c
diff --git a/src/option.c b/src/option.c
--- a/src/option.c
+++ b/src/option.c
@@ -2590,6 +2590,13 @@
 			    (char_u *)NULL, PV_NONE,
 #endif
 			    {(char_u *)"", (char_u *)0L} SCRIPTID_INIT},
+    {"ticktime",  "tt",   P_NUM|P_VI_DEF,
+#ifdef FEAT_TIMERS
+			    (char_u *)&p_tt, PV_NONE,
+#else
+			    (char_u *)NULL, PV_NONE,
+#endif
+			    {(char_u *)20L, (char_u *)0L} SCRIPTID_INIT},
     {"tildeop",	    "top",  P_BOOL|P_VI_DEF|P_VIM,
 			    (char_u *)&p_to, PV_NONE,
 			    {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
diff --git a/src/option.h b/src/option.h
--- a/src/option.h
+++ b/src/option.h
@@ -795,6 +795,9 @@
 #ifdef FEAT_INS_EXPAND
 EXTERN char_u	*p_tsr;		/* 'thesaurus' */
 #endif
+#ifdef FEAT_TIMERS
+EXTERN long	p_tt;		/* 'ticktime' */
+#endif
 EXTERN int	p_ttimeout;	/* 'ttimeout' */
 EXTERN long	p_ttm;		/* 'ttimeoutlen' */
 EXTERN int	p_tbi;		/* 'ttybuiltin' */
diff --git a/src/os_macosx.m b/src/os_macosx.m
--- a/src/os_macosx.m
+++ b/src/os_macosx.m
@@ -23,6 +23,22 @@
 #include "vim.h"
 #import <Cocoa/Cocoa.h>
 
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+
+
+#define MCH_MONOTONIC_TIME
+	unsigned long long
+mch_monotonic_time(void)
+{
+    mach_timebase_info_data_t info;
+
+    if (mach_timebase_info(&info) != KERN_SUCCESS)
+	abort();
+
+    return (mach_absolute_time() * info.numer / info.denom) / 1000000;
+}
+
 
 /*
  * Clipboard support for the console.
diff --git a/src/os_unix.c b/src/os_unix.c
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -892,6 +892,17 @@
 }
 #endif
 
+#if !defined(MACOS_X_UNIX)
+# define MCH_MONOTONIC_TIME
+	unsigned long long
+mch_monotonic_time(void)
+{
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+}
+#endif
+
 #ifdef SET_SIG_ALARM
 /*
  * signal function for alarm().
@@ -5057,9 +5068,13 @@
 #ifdef FEAT_NETBEANS_INTG
     int		nb_fd = netbeans_filedesc();
 #endif
-#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
+#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME) \
+						    || defined(FEAT_TIMERS)
     static int	busy = FALSE;
 
+# ifdef FEAT_TIMERS
+    unsigned long long now;
+# endif
     /* May retry getting characters after an event was handled. */
 # define MAY_LOOP
 
@@ -5072,18 +5087,24 @@
     if (msec > 0 && (
 #  ifdef FEAT_XCLIPBOARD
 	    xterm_Shell != (Widget)0
-#   if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
+#   if defined(USE_XSMP) || defined(FEAT_MZSCHEME) || defined(FEAT_TIMERS)
 	    ||
 #   endif
 #  endif
 #  ifdef USE_XSMP
 	    xsmp_icefd != -1
-#   ifdef FEAT_MZSCHEME
+#   if defined(FEAT_MZSCHEME) || defined(FEAT_TIMERS)
 	    ||
 #   endif
 #  endif
 #  ifdef FEAT_MZSCHEME
 	(mzthreads_allowed() && p_mzq > 0)
+#   ifdef FEAT_TIMERS
+	    ||
+#   endif
+#  endif
+#  ifdef FEAT_TIMERS
+	TRUE
 #  endif
 	    ))
 	gettimeofday(&start_tv, NULL);
@@ -5130,6 +5151,9 @@
 	    mzquantum_used = TRUE;
 	}
 # endif
+# ifdef FEAT_TIMERS
+	towait = call_timeouts(msec);
+# endif
 	fds[0].fd = fd;
 	fds[0].events = POLLIN;
 	nfd = 1;
@@ -5257,6 +5281,9 @@
 	    mzquantum_used = TRUE;
 	}
 # endif
+# ifdef FEAT_TIMERS
+	towait = call_timeouts(msec);
+# endif
 # ifdef __EMX__
 	/* don't check for incoming chars if not in raw mode, because select()
 	 * always returns TRUE then (in some version of emx.dll) */
@@ -5369,6 +5396,10 @@
 	    /* loop if MzThreads must be scheduled and timeout occurred */
 	    finished = FALSE;
 # endif
+# ifdef FEAT_TIMERS
+	if (ret == 0 && msec > p_tt)
+	    finished = FALSE;
+# endif
 
 # ifdef FEAT_SNIFF
 	if (ret < 0 )
diff --git a/src/os_win32.c b/src/os_win32.c
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -29,6 +29,7 @@
 #include <sys/types.h>
 #include <signal.h>
 #include <limits.h>
+#include <math.h>
 
 /* cproto fails on missing include files */
 #ifndef PROTO
@@ -624,6 +625,52 @@
     }
 }
 
+	unsigned long long
+mch_monotonic_time(void)
+{
+    static ULONGLONG (*GetTickCount64) (void) = NULL;
+    static ULONGLONG (CALLBACK *_GetTickCount64)(void);
+    static int has_getickcount64 = -1;
+    ULONGLONG result;
+    OSVERSIONINFO ovi;
+
+    ovi.dwOSVersionInfoSize = sizeof(ovi);
+    GetVersionEx(&ovi);
+
+    if (has_getickcount64 == -1)
+    {
+	/* GetTickCount64() was added to Windows Vista */
+	if (ovi.dwMajorVersion >= 6)
+	{
+	    HINSTANCE hKernel32 = GetModuleHandleW(L"KERNEL32");
+	    *(FARPROC*)&_GetTickCount64 = GetProcAddress(hKernel32,
+							    "GetTickCount64");
+	    has_getickcount64 = (_GetTickCount64 != NULL);
+	}
+	else
+	    has_getickcount64 = 0;
+    }
+
+    if (has_getickcount64)
+    {
+	result = _GetTickCount64();
+    }
+    else
+    {
+	static DWORD last_ticks = 0;
+	static DWORD n_overflow = 0;
+	DWORD ticks;
+
+	ticks = GetTickCount();
+	if (ticks < last_ticks)
+	    n_overflow++;
+	last_ticks = ticks;
+
+	result = (unsigned long long)ldexp(n_overflow, 32);
+	result += ticks;
+    }
+    return result;
+}
 /*
  * Return TRUE when running on Windows 95 (or 98 or ME).
  * Only to be used after mch_init().
diff --git a/src/os_win32.h b/src/os_win32.h
--- a/src/os_win32.h
+++ b/src/os_win32.h
@@ -56,6 +56,7 @@
 #define HAVE_ST_MODE		/* have stat.st_mode */
 
 #define FEAT_SHORTCUT		/* resolve shortcuts */
+#define MCH_MONOTONIC_TIME	/* for timers */
 
 #if (!defined(__BORLANDC__) || __BORLANDC__ >= 0x550) \
 	&& (!defined(_MSC_VER) || _MSC_VER > 1020)
diff --git a/src/proto.h b/src/proto.h
--- a/src/proto.h
+++ b/src/proto.h
@@ -289,6 +289,10 @@
 void clip_mch_set_selection(VimClipboard *cbd);
 #endif
 
+#ifdef FEAT_TIMERS
+# include "timers.pro"
+#endif
+
 #ifdef __BORLANDC__
 # define _PROTO_H
 #endif
diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro
--- a/src/proto/os_unix.pro
+++ b/src/proto/os_unix.pro
@@ -6,6 +6,7 @@
 long_u mch_total_mem __ARGS((int special));
 void mch_delay __ARGS((long msec, int ignoreinput));
 int mch_stackcheck __ARGS((char *p));
+unsigned long long mch_monotonic_time __ARGS((void));
 void mch_startjmp __ARGS((void));
 void mch_endjmp __ARGS((void));
 void mch_didjmp __ARGS((void));
diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro
--- a/src/proto/os_win32.pro
+++ b/src/proto/os_win32.pro
@@ -55,4 +55,5 @@
 void used_file_arg __ARGS((char *name, int literal, int full_path, int diff_mode));
 void set_alist_count __ARGS((void));
 void fix_arg_enc __ARGS((void));
+unsigned long long mch_monotonic_time __ARGS((void));
 /* vim: set ft=c : */
diff --git a/src/proto/timers.pro b/src/proto/timers.pro
new file mode 100644
--- /dev/null
+++ b/src/proto/timers.pro
@@ -0,0 +1,5 @@
+/* timers.c */
+unsigned long long get_monotonic_time __ARGS((void));
+void insert_timeout __ARGS((timeout_T *to));
+long call_timeouts __ARGS((long max_wait));
+/* vim: set ft=c : */
diff --git a/src/structs.h b/src/structs.h
--- a/src/structs.h
+++ b/src/structs.h
@@ -2540,3 +2540,19 @@
   UINT32_T state[8];
   char_u   buffer[64];
 } context_sha256_T;
+
+#ifdef FEAT_TIMERS
+/*
+ * Used for +timers settimeout/interval.
+ */
+typedef struct timeout_S timeout_T;
+struct timeout_S {
+    int id;			/* timeout/interval id */
+    int interval;		/* interval period if interval, otherwise -1 */
+    unsigned long long tm;	/* time to fire (epoch milliseconds) */
+    char_u *cmd;		/* vim command to run */
+    char_u *sourcing_name;
+    linenr_T sourcing_lnum;
+    timeout_T *next;		/* pointer to next timeout in linked list */
+};
+#endif
diff --git a/src/timers.c b/src/timers.c
new file mode 100644
--- /dev/null
+++ b/src/timers.c
@@ -0,0 +1,152 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved	by Bram Moolenaar
+ *
+ * Do ":help uganda"  in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+#ifdef FEAT_TIMERS
+
+/*
+ * Avoid recursive calls to call_timeouts
+ */
+static int calling_timeouts = FALSE;
+
+/*
+ * Return monotonic time, if available. Fall back to gettimeofday otherwise.
+ */
+	unsigned long long
+get_monotonic_time(void)
+{
+    unsigned long long tm;
+# ifdef MCH_MONOTONIC_TIME
+    tm = mch_monotonic_time();
+# else
+    struct timeval now;
+    gettimeofday(&now, NULL);
+    tm = now.tv_sec * 1000 + now.tv_usec / 1000;
+# endif
+    return tm;
+}
+
+
+/*
+ * Insert a new timeout into the timeout linked list.
+ * This is called by set_timeout() in eval.c
+ */
+	void
+insert_timeout(to)
+    timeout_T *to;  /* timeout to insert */
+{
+    timeout_T *cur = timeouts;
+    timeout_T *prev = NULL;
+
+    if (timeouts == NULL)
+    {
+	timeouts = to;
+	return;
+    }
+
+    while (cur != NULL)
+    {
+	if (cur->tm > to->tm)
+	{
+	    if (prev)
+	    {
+		prev->next = to;
+	    }
+	    else
+	    {
+		timeouts = to;
+	    }
+	    to->next = cur;
+	    return;
+	}
+	prev = cur;
+	cur = cur->next;
+    }
+    prev->next = to;
+    to->next = NULL;
+}
+
+/*
+ * Execute timeouts that are due.
+ * Return the amount of time before call_timeouts() should be run again.
+ */
+	long
+call_timeouts(max_to_wait)
+    long max_to_wait;
+{
+    unsigned long long now = get_monotonic_time();
+    unsigned long long towait = p_tt;
+    timeout_T *tmp;
+    int retval;
+
+    if (calling_timeouts)
+    {
+	return max_to_wait;
+    }
+
+    calling_timeouts = TRUE;
+
+    while (timeouts != NULL && timeouts->tm < now)
+    {
+	retval = do_cmdline_cmd(timeouts->cmd);
+	tmp = timeouts;
+	timeouts = timeouts->next;
+	if (tmp->interval == -1 || retval == FAIL || did_throw || did_emsg)
+	{
+	    if (got_int)
+	    {
+		if (tmp->sourcing_lnum)
+		{
+		    EMSG(_("E881: An interval was canceled because of an interrupt"));
+		    EMSG3(_("%s:%s"), tmp->sourcing_name, tmp->sourcing_lnum);
+		}
+		else
+		{
+		    EMSG(_("E881: An interval was canceled because of an interrupt"));
+		    EMSG2(_("%s"), tmp->sourcing_name);
+		}
+	    }
+	    free(tmp->cmd);
+	    free(tmp->sourcing_name);
+	    free(tmp);
+	}
+	else
+	{
+	    tmp->tm = now + tmp->interval;
+	    insert_timeout(tmp);
+	}
+    }
+
+    calling_timeouts = FALSE;
+
+    /* if there is not a timer, change towait so that it will get called */
+    if (timeouts != NULL && max_to_wait != 0)
+    {
+	now = get_monotonic_time();
+	if (now > timeouts->tm)
+	    return p_tt;
+
+	towait = timeouts->tm - now;
+
+	/* don't wake up every 1 ms ... limit to p_tt */
+	if (towait < p_tt)
+	    towait = p_tt;
+
+	/* don't overshoot the wait time */
+	if (max_to_wait > 0 && towait > max_to_wait)
+	    towait = max_to_wait;
+
+        return (long)towait;
+    }
+
+    return max_to_wait;
+}
+
+#endif
diff --git a/src/version.c b/src/version.c
--- a/src/version.c
+++ b/src/version.c
@@ -617,6 +617,11 @@
 #else
 	"-textobjects",
 #endif
+#ifdef FEAT_TIMERS
+	"+timers",
+#else
+	"-timers",
+#endif
 #ifdef FEAT_TITLE
 	"+title",
 #else

Reply via email to