1"
2" Filename: cream-lib-win-tab-buf.vim
3"
4" Cream -- An easy-to-use configuration of the famous Vim text editor
5" [ http://cream.sourceforge.net ] Copyright (C) 2001-2011 Steve Hall
6"
7" License:
8" This program is free software; you can redistribute it and/or modify
9" it under the terms of the GNU General Public License as published by
10" the Free Software Foundation; either version 3 of the License, or
11" (at your option) any later version.
12" [ http://www.gnu.org/licenses/gpl.html ]
13"
14" This program is distributed in the hope that it will be useful, but
15" WITHOUT ANY WARRANTY; without even the implied warranty of
16" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17" General Public License for more details.
18"
19" You should have received a copy of the GNU General Public License
20" along with this program; if not, write to the Free Software
21" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22" 02111-1307, USA.
23"
24" Description:
25" Window and buffer related functions
26"
27" We refer to windows in the following fashion:
28"
29"     +---+---+---+--------------+
30"     |   |   |   |    :    :    |
31"     |   |   |   |    :    :    |
32"     |   |   |   |   Primary    |
33"     | Specials  |    :    :    |
34"     |   |   |   |    :    :    |
35"     |   |   |   +--------------+
36"     |   |   |   |              |
37"     |   |   |   |     Help     |
38"     |   |   |   |              |
39"     +---+---+---+--------------+
40"
41" Note that Help is also considered a Special.
42"
43
44" Cream_nextwindow() {{{1
45function! Cream_nextwindow()
46" go to next valid window or tab (if multiple) or buffer (if not)
47
48	" multiple windows: change windows
49	if NumberOfWindows() > 1
50		execute "wincmd w"
51		" if unnamed, unmodified buffer, go to next if others exist
52		if  Cream_buffer_isnewunmod() == 1
53		\&& Cream_NumberOfBuffers("neither") > 0
54			call Cream_TryAnotherBuffer()
55		endif
56	" single window: change tabs or buffers
57	else
58		" try tabs first
59		if tabpagenr('$') > 1
60			tabnext
61			" if current is unnamed, unmodified buffer, go to next (Once!
62			" If more than 1 exist, the user created one this session.)
63			if bufname("%") == "" && &modified == 0
64				tabnext
65			endif
66		else
67			bnext
68			" if current is unnamed, unmodified buffer, go to next (Once!
69			" If more than 1 exist, the user created one this session.)
70			if bufname("%") == "" && &modified == 0
71				bnext
72			endif
73		endif
74
75	endif
76
77endfunction
78
79" Cream_prevwindow() {{{1
80function! Cream_prevwindow()
81" go to next valid window or tab (if multiple) or buffer (if not)
82
83	" multiple windows: change windows
84	if NumberOfWindows() > 1
85		execute "wincmd W"
86		" if unnamed, unmodified buffer, go to next if others exist
87		if  Cream_buffer_isnewunmod() == 1
88		\&& Cream_NumberOfBuffers("neither") > 0
89			call Cream_TryAnotherBuffer()
90		endif
91	" single window: change buffers
92	else
93		" try tabs first
94		if tabpagenr('$') > 1
95			tabprevious
96			" if current is unnamed, unmodified buffer, go to next (Once!
97			" If more than 1 exist, the user created one this session.)
98			if bufname("%") == "" && &modified == 0
99				tabprevious
100			endif
101		else
102			bprevious
103			" if current is unnamed, unmodified buffer, go to next (Once!
104			" If more than 1 exist, the user created one this session.)
105			if bufname("%") == "" && &modified == 0
106				bprevious
107			endif
108		endif
109
110	endif
111
112endfunction
113
114" Cream_buffer_edit() {{{1
115function! Cream_buffer_edit(bufnum)
116" test current window is not special (calendar, help) before edit
117" a buffer in it. If it is, we try to switch to a "valid" window
118" first.
119" Arguments: buffer number to be edited
120
121	" ignore specials
122	call Cream_TryAnotherWindow()
123
124	if exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1
125		" go to each tab, test if matches a:bufnum (assumes only one
126		" buffer per tab)
127		let tabcnt = tabpagenr("$")
128		let i = 1
129		while i <= tabcnt
130			" quit if current
131			if bufnr("%") == a:bufnum
132				break
133			endif
134			tabnext
135			let i = i + 1
136		endwhile
137	else
138		execute "buffer " . a:bufnum
139	endif
140
141endfunction
142
143" Cream_TryAnotherWindow() {{{1
144function! Cream_TryAnotherWindow(...)
145" try to go to another window if current is special
146" optional agument "nonewmod" avoids unnamed modified too
147
148	let trys = 0
149	let attempts = Cream_NumberOfWindows("neither")
150	while trys <= attempts
151		let trys = trys + 1
152		if  Cream_buffer_isspecial() == 1
153		\|| Cream_buffer_isnewunmod() == 1
154		\|| a:0 > 0 && a:1 == "nonewmod" && Cream_buffer_isnewmod() == 1
155			call Cream_nextwindow()
156			continue
157		else
158			" found a non-special buffer
159			break
160		endif
161	endwhile
162
163endfunction
164
165" Cream_TryAnotherBuffer() {{{1
166function! Cream_TryAnotherBuffer()
167" go to another buffer (in same window) if current is special or new
168
169	let trys = 0
170	let attempts = Cream_buffer_isspecial("specialct") + Cream_NumberOfBuffers("new")
171	while trys <= attempts
172		let trys = trys + 1
173		if  Cream_buffer_isspecial() == 1
174		\|| Cream_buffer_isnewunmod() == 1
175			bnext
176			continue
177		else
178			" found a non-special buffer
179			break
180		endif
181	endwhile
182
183endfunction
184
185" Cream_buffer_isspecial() {{{1
186function! Cream_buffer_isspecial(...)
187" returns 1 if "special" buffer, 0 if not argument is buffer number
188" aguments:
189"   empty == "%"
190"   number = [bufnr]
191"   "specialct" = number of special buffers
192
193	" verify
194	call Cream_buffer_nr()
195
196	" use current if no buffer number passed
197	if     a:0 == 0
198		let mybufnr = b:cream_nr
199	elseif a:1 == "specialct"
200		return 6
201	elseif a:1 == "tempbufname"
202		return "_cream_temp_buffer_"
203	else
204		let mybufnr = a:1
205	endif
206
207	" true "special"
208	if  bufname(mybufnr) == "_opsplorer"
209	\|| bufname(mybufnr) == "__Calendar"
210	\|| bufname(mybufnr) == "__Tag_List__"
211	\|| bufname(mybufnr) == "-- EasyHtml --"
212	" TODO: Only for old file explorer.	Removed since it has to poll
213	" file/directory just to test (slow over long connection).
214	"\|| isdirectory(bufname(mybufnr))
215		return 1
216	endif
217
218	" help
219	if Cream_buffer_ishelp(mybufnr) == 1
220		return 1
221	endif
222
223	return 0
224
225endfunction
226
227" Cream_buffer_isnewunmod() {{{1
228function! Cream_buffer_isnewunmod(...)
229" returns 1 if new, unmodified buffer, 0 if not
230" argument is buffer number
231
232	" use current if no buffer number passed
233	if a:0 == 0
234		let mybufnr = bufnr("%")
235	else
236		let mybufnr = a:1
237	endif
238
239	if  bufname(mybufnr) == ""
240	\&& getbufvar(mybufnr, "&modified") == 0
241	\&& bufexists(mybufnr) == 1
242		return 1
243	" no earthly idea why this is here
244	elseif bufexists(mybufnr) == 0
245		return -1
246	endif
247
248	return 0
249
250endfunction
251
252" Cream_buffer_isnewmod() {{{1
253function! Cream_buffer_isnewmod(...)
254" returns 1 if new, unmodified buffer, 0 if not
255" argument is buffer number
256
257	" use current if no buffer number passed
258	if a:0 == 0
259		let mybufnr = bufnr("%")
260	else
261		let mybufnr = a:1
262	endif
263
264	if  bufname(mybufnr) == ""
265	\&& getbufvar(mybufnr, "&modified") == 1
266	\&& bufexists(mybufnr) == 1
267		return 1
268	elseif bufexists(mybufnr) == 0
269		return -1
270	endif
271
272	return 0
273
274endfunction
275
276" Cream_buffer_ishelp() {{{1
277function! Cream_buffer_ishelp(...)
278" returns 1 if "help" buffer, 0 if not argument is buffer number
279" aguments:
280"   empty == "%"
281"   number = [bufnr]
282
283	" verify
284	call Cream_buffer_nr()
285
286	" use current if no buffer number passed
287	if     a:0 == 0
288		let mybufnr = b:cream_nr
289	else
290		let mybufnr = a:1
291	endif
292
293	if     bufexists(mybufnr) == 0
294		return -1
295	elseif getbufvar(mybufnr, "&buftype") == "help"
296		return 1
297	endif
298
299	return 0
300
301endfunction
302
303" NumberOfBuffers() {{{1
304function! NumberOfBuffers()
305" return number of existing buffers
306" *** This should be part of genutils--it's not Cream-specific ***
307
308	let i = 0
309	let j = 0
310	while i < bufnr('$')
311		let i = i + 1
312		if bufexists(bufnr("%"))
313			let j = j + 1
314		endif
315	endwhile
316	return j
317
318endfunction
319
320" Cream_NumberOfWindows() {{{1
321function! Cream_NumberOfWindows(filter)
322" return the number of Cream windows (buffers currently open/shown)
323" filtered per argument
324" (see also NumberOfWindows() )
325
326	let i = 1
327	let j = 0
328
329	if     a:filter == "special"
330		while winbufnr(i) != -1
331			if  Cream_buffer_isspecial(winbufnr(i)) == 1
332				let j = j + 1
333			endif
334			let i = i + 1
335		endwhile
336	elseif a:filter == "nospecial"
337		while winbufnr(i) != -1
338			if  Cream_buffer_isspecial(winbufnr(i)) == 0
339				let j = j + 1
340			endif
341			let i = i + 1
342		endwhile
343	elseif a:filter == "new"
344		while winbufnr(i) != -1
345			if  Cream_buffer_isnewunmod(winbufnr(i)) == 1
346				let j = j + 1
347			endif
348			let i = i + 1
349		endwhile
350	elseif a:filter == "nonew"
351		while winbufnr(i) != -1
352			if  Cream_buffer_isnewunmod(winbufnr(i)) == 0
353				let j = j + 1
354			endif
355			let i = i + 1
356		endwhile
357	elseif a:filter == "newmod"
358		while i < bufnr('$')
359			let i = i + 1
360			if  Cream_buffer_isnewmod(winbufnr(i)) == 1
361				let j = j + 1
362			endif
363		endwhile
364	elseif a:filter == "newunmod"
365		while i < bufnr('$')
366			let i = i + 1
367			if  Cream_buffer_isnewunmod(winbufnr(i)) == 1
368				let j = j + 1
369			endif
370		endwhile
371	elseif a:filter == "neither"
372		while winbufnr(i) != -1
373			" only count if isn't special
374			if  Cream_buffer_isspecial(winbufnr(i)) == 0
375			\&& Cream_buffer_isnewunmod(winbufnr(i)) == 0
376				let j = j + 1
377			endif
378			let i = i + 1
379		endwhile
380	elseif a:filter == "all"
381		while winbufnr(i) != -1
382			let j = j + 1
383			let i = i + 1
384		endwhile
385	else
386		" bad argument
387		let j = 0
388	endif
389
390	return j
391
392endfunction
393
394" Cream_NumberOfBuffers() {{{1
395function! Cream_NumberOfBuffers(filter)
396" return number of buffers filtered per argument
397
398	let i = 0
399	let j = 0
400
401	if     a:filter == "special"
402		while i < bufnr('$')
403			let i = i + 1
404			if  Cream_buffer_isspecial(i) == 1
405				let j = j + 1
406			endif
407		endwhile
408	elseif a:filter == "nospecial"
409		while i < bufnr('$')
410			let i = i + 1
411			if Cream_buffer_isspecial(i) == 0
412				let j = j + 1
413			endif
414		endwhile
415	elseif a:filter == "new"
416		while i < bufnr('$')
417			let i = i + 1
418			if  Cream_buffer_isnewunmod(i) == 1
419				let j = j + 1
420			endif
421		endwhile
422	elseif a:filter == "nonew"
423		while winbufnr(i) != -1
424			if  Cream_buffer_isnewunmod(i) == 0
425				let j = j + 1
426			endif
427			let i = i + 1
428		endwhile
429	elseif a:filter == "newmod"
430		while i < bufnr('$')
431			let i = i + 1
432			if  Cream_buffer_isnewmod(i) == 1
433				let j = j + 1
434			endif
435		endwhile
436	elseif a:filter == "newunmod"
437		while i < bufnr('$')
438			let i = i + 1
439			if  Cream_buffer_isnewunmod(i) == 1
440				let j = j + 1
441			endif
442		endwhile
443	elseif a:filter == "neither"
444		while i < bufnr('$')
445			let i = i + 1
446			if  Cream_buffer_isspecial(i) == 0
447			\&& Cream_buffer_isnewunmod(i) == 0
448				let j = j + 1
449			endif
450		endwhile
451	elseif a:filter == "all"
452		while i < bufnr('$')
453			let i = i + 1
454			if  bufnr(i) != -1
455				let j = j + 1
456			endif
457		endwhile
458	else
459		" bad argument
460		let j = 0
461	endif
462
463	return j
464
465endfunction
466
467" Cream_bwipeout() {{{1
468function! Cream_bwipeout(...)
469" handle special window/buffer conditions when closing current buffer
470" *** File save verification must occur before here!! ***
471" * Optional argument is buffer number to be removed
472" * Window management here is laissez-faire. (Wrap functions
473"   elsewhere.)
474" * Buffer managment simply tries to not end in special or new
475
476	if a:0 == 0
477		let mybufnr = bufnr("%")
478	else
479		if bufexists(a:1) == 0
480			call confirm(
481				\ "Error: Buffer number passed to Cream_bwipeout() \n" .
482				\ "       doesn't exist. No action taken.\n" .
483				\ "\n", "&Ok", 1, "Info")
484			return
485		endif
486		let mybufnr = a:1
487	endif
488
489
490	" no special buffers
491
492	"......................................................................
493	" current is single new--alone
494	if  Cream_NumberOfBuffers("all") == 1
495	\&& Cream_buffer_isnewunmod() == 1
496		" do nothing
497		return
498	endif
499
500	"......................................................................
501	" no special buffers, just normal(s) (and possibly new ones)
502	if Cream_NumberOfBuffers("special") == 0
503		" simple close--Vim handles merging of existing windows
504		execute "bwipeout! " . mybufnr
505		call Cream_TryAnotherWindow()
506		" setup remaining
507		call Cream_window_setup()
508		return
509	endif
510
511	" special buffer current (by definition, multiple windows)
512
513	"......................................................................
514	" current buffer is special
515	if Cream_buffer_isspecial() == 1
516		if bufname(mybufnr) == "__Calendar"
517			" unset calendar environment
518			if exists("g:CREAM_CALENDAR")
519				unlet g:CREAM_CALENDAR
520			endif
521		endif
522
523		" other special buffer conditions here...
524
525		" go to next named window/buffer
526		call Cream_nextwindow()
527		" close special window/buffer w/out save
528		execute "bwipeout! " . mybufnr
529		" only try if we have at least one non-new/special (otherwise,
530		" we could bounce into one of the specials we're trying to
531		" manage!)
532		if Cream_NumberOfWindows("neither") > 0
533			call Cream_TryAnotherWindow()
534		endif
535		" setup remaining
536		call Cream_window_setup()
537		return
538
539	endif
540
541	" special buffer(s), none current
542
543	"......................................................................
544	" current is single new--adjacent to special(s)
545	if  Cream_buffer_isnewunmod() == 1
546	\&& Cream_NumberOfWindows("special") > 0
547	\&& Cream_NumberOfBuffers("neither") == 0
548		" do nothing
549		return
550	endif
551
552	"......................................................................
553	" current is single *not* new--adjacent to special(s)
554	" (start new file in current window)
555	" * Remember: we've already handled current buffer == special  above
556	if  Cream_buffer_isnewunmod() == 0
557	\&& Cream_NumberOfWindows("special") > 0
558	\&& Cream_NumberOfBuffers("neither") == 1
559		if Cream_NumberOfBuffers("new") == 0
560			" start a new buffer in same window (":enew")
561			call Cream_file_new()
562		else
563			" move to new buffer
564			let i = 0
565			while i < bufnr('$')
566				if  Cream_buffer_isnewunmod(i) == 1
567					execute "buffer " . i
568					break
569				endif
570				let i = i + 1
571			endwhile
572		endif
573		" then close old buffer
574		execute "bwipeout! " . mybufnr
575		"call Cream_TryAnotherWindow()
576		" setup remaining
577		call Cream_window_setup()
578		return
579	endif
580
581	"......................................................................
582	" multiple buffers, all windowed
583	if Cream_NumberOfBuffers("all") <= Cream_NumberOfWindows("all")
584		" let Vim manage windows
585		execute "bwipeout! " . mybufnr
586		call Cream_TryAnotherWindow()
587		" setup remaining
588		call Cream_window_setup()
589		return
590	endif
591
592	"......................................................................
593	" multiple buffers, some un-windowed
594	if Cream_NumberOfBuffers("all") > Cream_NumberOfWindows("all")
595		" place next unshown buffer in same window
596		" iterate through buffers, check each if windowed
597		let i = 1
598		while i <= bufnr('$')
599			" if buffer exists, isn't special, and isn't the
600			" current buffer(!)
601			if  bufexists(i) != 0
602			\&& Cream_buffer_isspecial(i) == 0
603			\&& Cream_buffer_isnewunmod(i) == 0
604			\&& bufnr(i) != bufnr("%")
605			" is hidden
606			"\&& bufwinnr(i) == -1
607				" edit it here
608				execute "buffer " . i
609				" then close old buffer
610				execute "bwipeout! " . mybufnr
611				" stop
612				break
613			endif
614			let i = i + 1
615		endwhile
616		call Cream_TryAnotherWindow()
617		" setup remaining
618		call Cream_window_setup()
619		return
620	endif
621
622"*** DEBUG:
623call confirm(
624	\ "Whoops! Unexpectedly dropped through Cream_bwipeout()!\n" .
625	\ "(Window and buffer management didn't happen.)\n" .
626	\ "\n", "&Ok", 1, "Info")
627"***
628
629endfunction
630
631" Cream_buffers_delete_untitled() {{{1
632function! Cream_buffers_delete_untitled()
633" wipeout all unnamed, unmodified (Untitled) buffers
634
635	" get out of any special (including Untitled)
636	call Cream_TryAnotherBuffer()
637
638	" remember
639	let mybufnr = bufnr("%")
640	let i = 0
641	while i < bufnr('$')
642		let i = i + 1
643		if Cream_buffer_isnewunmod(i) == 1
644			" ignore current buffer
645			if i != mybufnr
646				" delete
647				execute "bwipeout! " . i
648			endif
649		endif
650	endwhile
651	" recall if wasn't deleted
652	if exists("mybufnr")
653		execute "buffer " . mybufnr
654	endif
655endfunction
656
657" Cream_buffers_delete_special() {{{1
658function! Cream_buffers_delete_special()
659" wipeout special buffers
660
661	"" not in a special
662	"call Cream_TryAnotherBuffer()
663
664	" remember
665	let mybufnr = bufnr("%")
666	let i = 0
667	while i < bufnr('$')
668		let i = i + 1
669		if Cream_buffer_isspecial(i) == 1
670			" forget current if untitled
671			if mybufnr == i
672				unlet mybufnr
673			endif
674			" delete
675			execute "bwipeout! " . i
676		endif
677	endwhile
678	" recall if wasn't deleted
679	if exists("mybufnr")
680		execute "buffer " . mybufnr
681	endif
682endfunction
683
684
685" Cream_window_setup() {{{1
686function! Cream_window_setup()
687" general window management, called whenever something opened or closed
688
689	" turn on equal settings, must be on to specify others(?!)
690	let myequalalways = &equalalways
691	set equalalways
692
693	" get current window (could be special)
694	let mybuf = bufnr("%")
695
696	" manage tabs from here, too.
697	if exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1
698		call Cream_tabpages_refresh()
699	endif
700
701	" go to a non-special window (temp, won't be changed below)
702	call Cream_TryAnotherWindow()
703	"" get current (temp) non-special window
704	"let buftemp = bufnr("%")
705
706	" arrange special windows
707	call Cream_window_setup_special()
708
709	" restore cursor to original buffer's window
710	call MoveCursorToWindow(bufwinnr(mybuf))
711
712	" restore equal split preference
713	let &equalalways = myequalalways
714
715endfunction
716
717" Cream_window_setup_special() {{{1
718function! Cream_window_setup_special()
719" set all "special" windows to pre-defined locations around a single
720" primary (working) window.
721" * Special windows are vertical, to the left (see order below)
722" * Help window is horizontal below primary window
723" * Primary window(s) remain untouched
724"
725" Strategy: Close everything but non-new/specials, then re-open them.
726
727	call Cream_window_hide_specials()
728
729	" parse through each buffer placing specials as found
730	let bufnr = -1
731
732	" help (do first so is below all normal windows if horizontal tile)
733	let i = 1
734	while i <= bufnr('$')
735		if getbufvar(i, "&buftype") == "help"
736			let bufnr = i
737			" re-open in correct position/size
738			execute "botright sbuffer " . bufnr
739			if exists("g:cream_help_size")
740				execute "resize " . g:cream_help_size
741			else
742				execute "resize " . 20
743			endif
744		endif
745		let i = i + 1
746	endwhile
747
748	" easyhtml
749	let bufnr = FindBufferForName("-- EasyHtml --")
750	if bufnr != -1
751		" re-open in correct position/size
752		execute "topleft vertical sbuffer " . bufnr
753		let mybuf1 = bufnr
754		setlocal nowrap
755		setlocal nonumber
756	endif
757	" taglist
758	let bufnr = FindBufferForName("__Tag_List__")
759	if bufnr != -1
760		"" always split from the same window (our temp)
761		"execute "call MoveCursorToWindow(bufwinnr(" . buftemp . "))"
762		" re-open in correct position/size
763		execute "topleft vertical sbuffer " . bufnr
764		let mybuf2 = bufnr
765		setlocal nowrap
766		setlocal nonumber
767	endif
768	" calendar
769	let bufnr = FindBufferForName("__Calendar")
770	if bufnr != -1
771		" re-open in correct position/size
772		execute "topleft vertical sbuffer " . bufnr
773		let mybuf3 = bufnr
774		setlocal nowrap
775		setlocal nonumber
776	endif
777	" explorer -- this is going to be obsolete, let's pass
778	"
779	" opsplorer
780	let bufnr = FindBufferForName("_opsplorer")
781	if bufnr != -1
782		" re-open in correct position/size
783		execute "topleft vertical sbuffer " . bufnr
784		let mybuf4 = bufnr
785		setlocal nowrap
786		setlocal nonumber
787	endif
788
789	" resize (after all have been opened)
790	if exists("mybuf4")
791		call MoveCursorToWindow(bufwinnr(mybuf4))
792		topleft vertical resize 25
793	endif
794	if exists("mybuf3")
795		call MoveCursorToWindow(bufwinnr(mybuf3))
796		topleft vertical resize 22
797	endif
798	if exists("mybuf2")
799		call MoveCursorToWindow(bufwinnr(mybuf2))
800		topleft vertical resize 30
801	endif
802	if exists("mybuf1")
803		call MoveCursorToWindow(bufwinnr(mybuf1))
804		topleft vertical resize 25
805	endif
806
807endfunction
808
809" Cream_window_hide() {{{1
810function! Cream_window_hide(bufnr)
811" hide all windows matching bufnr
812" argument: second (optional) is 1 if special, 0 if normal
813" * cursor drop controled by Vim, wrapper should manage
814" * buffer name is actually accepted, too, but a bad idea
815
816	" turn off equal settings so special widths are retained
817	let myequalalways = &equalalways
818	set equalalways
819
820	" no buffer by this number exists, but isn't help
821	if bufexists(a:bufnr) == 0
822	\&& Cream_buffer_ishelp(a:bufnr) != 1
823		return
824	endif
825	" no window associated
826	if bufwinnr(a:bufnr) == -1
827		return
828	endif
829
830	" go to it's window
831	call MoveCursorToWindow(bufwinnr(a:bufnr))
832
833""*** DEBUG:
834"let n = confirm(
835"    \ "DEBUG:\n" .
836"    \ "  a:bufnr           = \"" . a:bufnr . "\"\n" .
837"    \ "  bufwinnr(a:bufnr) = \"" . bufwinnr(a:bufnr) . "\"\n" .
838"    \ "  bufnr(\"%\")      = \"" . bufnr("%") . "\"\n" .
839"    \ "  bufname(\"%\")    = \"" . bufname("%") . "\"\n" .
840"    \ "\n", "&Ok\n&Cancel", 1, "Info")
841"if n != 1
842"    return
843"endif
844""***
845
846	" hide if currently open
847	hide
848
849""*** DEBUG:
850"let n = confirm(
851"    \ "DEBUG: (post hide)\n" .
852"    \ "  a:bufnr           = \"" . a:bufnr . "\"\n" .
853"    \ "  bufwinnr(a:bufnr) = \"" . bufwinnr(a:bufnr) . "\"\n" .
854"    \ "  bufnr(\"%\")      = \"" . bufnr("%") . "\"\n" .
855"    \ "  bufname(\"%\")    = \"" . bufname("%") . "\"\n" .
856"    \ "\n", "&Ok\n&Cancel", 1, "Info")
857"if n != 1
858"    return
859"endif
860""***
861
862	" restore equal split preference
863	let &equalalways = myequalalways
864
865endfunction
866
867" Cream_window_hide_specials() {{{1
868function! Cream_window_hide_specials()
869" hide all special windows
870
871	let myct = bufnr("$")
872	let i = 1
873	while i <= myct
874		if Cream_buffer_isspecial(i) == 1
875			" hide
876			call Cream_window_hide(i)
877		endif
878		let i = i + 1
879	endwhile
880
881endfunction
882
883" Cream_window_setup_tile() {{{1
884function! Cream_window_setup_tile(layout)
885" set up non-special buffer windows in tile mode in the (current)
886" primary pane
887" * Argument is orientation: "vertical" or "horizontal"
888" * Assumes the current pane is alone!
889" * Assumes specials set elsewhere
890" * Sorts according to buffer number
891
892	" only do it if more than one non-special (solves div by 0
893	" problem, too)
894	let bufct = Cream_NumberOfBuffers("neither")
895	if bufct <= 1
896		return
897	endif
898
899	" get out of specials
900	call Cream_TryAnotherWindow()
901	" remember current buffer
902	let mybufnr = bufnr("%")
903	"*** TEST: if we leave them open, Vim will account for them in spacing decisions.
904	" hide specials
905	call Cream_window_hide_specials()
906	"***
907	" do not start with new unmod as current
908	call Cream_TryAnotherBuffer()
909
910	" make lowest non-special exposed buffer current *and only*
911	let i = 1
912	while i <= bufnr("$")
913		" non-special, non-new, must exist in a window in case
914		" other non-specials are hidden
915		if  bufexists(i) > 0
916		\&& Cream_buffer_isspecial(i) == 0
917		\&& Cream_buffer_isnewunmod(i) == 0
918		"*** don't understand why it has to be shown, we're changing
919		"    it to an :only window anyway. ***
920		"\&& bufwinnr(i) != -1
921			execute "buffer " . i
922			let startbufnr = i
923			break
924		endif
925		let i = i + 1
926	endwhile
927	" couldn't find non-special buffer in a window
928	if !exists("startbufnr")
929		" equal to current
930		let startbufnr = 0
931	endif
932
933	" make a single window
934	only
935
936	" capture environment
937	let mysplitright = &splitright
938	let mysplitbelow = &splitbelow
939	" turn on equal settings
940	let myequalalways = &equalalways
941	set equalalways
942
943	" split
944	if     a:layout ==? "vertical"
945		" split right
946		set splitright
947		set nosplitbelow
948		" split primary window into equal portions
949		" width equals primary win divided by no. of non-special bufs
950		let mywidth = winwidth(0) / bufct
951	elseif a:layout ==? "horizontal"
952		" split below
953		set nosplitright
954		set splitbelow
955		" split primary window into equal portions
956		" height equals primary win divided by no. of non-special bufs
957		let mywidth = winheight(0) / bufct
958	endif
959
960	" split off buffers, highest first
961	let i = bufnr("$")
962	while i > 0
963		" non-special, non-new only
964		if  bufexists(i) > 0
965		\&& Cream_buffer_isspecial(i) == 0
966		\&& Cream_buffer_isnewunmod(i) == 0
967		\&& i != startbufnr
968			if a:layout ==? "vertical"
969				execute "topleft vertical sbuffer " . i
970				execute mywidth . "wincmd \|"
971			elseif a:layout ==? "horizontal"
972				execute "botright sbuffer " . i
973				execute mywidth . "wincmd _"
974			endif
975			" move back to original window
976			call MoveCursorToWindow(bufwinnr(startbufnr))
977		endif
978		let i = i - 1
979	endwhile
980
981	" restore equal split preference
982	let &equalalways = myequalalways
983	" restore environment
984	let &splitright = mysplitright
985	let &splitbelow = mysplitbelow
986
987	" arrange windows
988	call Cream_window_setup()
989
990	" go to the original window (could be special)
991	call MoveCursorToWindow(bufwinnr(mybufnr))
992
993endfunction
994
995" Cream_window_setup_maximize() {{{1
996function! Cream_window_setup_maximize()
997" ":only" ruins specials setup... handle.
998
999	" don't maximize specials
1000	if Cream_buffer_isspecial(bufnr("%"))
1001		call confirm(
1002			\ "Can't maximize a special window.\n" .
1003			\ "\n", "&Ok", 1, "Info")
1004		return
1005	endif
1006
1007	" already maximized if only one non-special exists
1008	if Cream_NumberOfWindows("neither") == 1
1009		call confirm(
1010			\ "Can't maximize any further.\n" .
1011			\ "\n", "&Ok", 1, "Info")
1012		return
1013	endif
1014
1015	" make only
1016	only
1017
1018	" arrange specials
1019	call Cream_window_setup()
1020
1021endfunction
1022
1023" Cream_window_setup_minimize() {{{1
1024function! Cream_window_setup_minimize()
1025" ":hide" can ruin specials setup... handle.
1026
1027	" don't minimize specials
1028	if Cream_buffer_isspecial(bufnr("%"))
1029		call confirm(
1030			\ "Can't minimize a special window.\n" .
1031			\ "\n", "&Ok", 1, "Info")
1032		return
1033	endif
1034
1035	" already minimized if only one non-special exists
1036	if Cream_NumberOfWindows("nospecial") == 1
1037		call confirm(
1038			\ "Can't minimize the last window.\n" .
1039			\ "\n", "&Ok", 1, "Info")
1040		return
1041	endif
1042
1043	" :hide
1044	hide
1045
1046	" arrange specials
1047	call Cream_window_setup()
1048
1049endfunction
1050
1051"}}}1
1052" Window width/heights {{{1
1053function! Cream_window_equal()
1054	wincmd =
1055endfunction
1056function! Cream_window_height_max()
1057	wincmd _
1058endfunction
1059function! Cream_window_height_min()
1060	"wincmd 1_
1061	"execute 'normal z1<CR>'
1062	resize 1
1063endfunction
1064function! Cream_window_width_max()
1065	wincmd |
1066endfunction
1067function! Cream_window_width_min()
1068	wincmd 1|
1069endfunction
1070" }}}1
1071" Window splits {{{1
1072function! Cream_window_new_ver()
1073	vnew
1074endfunction
1075function! Cream_window_new_hor()
1076	new
1077endfunction
1078
1079function! Cream_window_split_exist_ver()
1080	wincmd v
1081endfunction
1082function! Cream_window_split_exist_hor()
1083	wincmd s
1084endfunction
1085
1086" 1}}}
1087" Tab pages
1088" Cream_tabpages_init() {{{1
1089function! Cream_tabpages_init()
1090" Initialize tab state.
1091
1092	" uninitialized (no tabs exist to manage)
1093	if !exists("g:CREAM_TABPAGES")
1094		let g:CREAM_TABPAGES = 0
1095	" convert multiple tabs to one
1096	elseif g:CREAM_TABPAGES == 0
1097		set guioptions-=e
1098		set showtabline=0
1099	" multiple could exist, convert to tabs
1100	elseif g:CREAM_TABPAGES == 1
1101		" set 1: avoid default titles on startup
1102		call Cream_tabpages_labels()
1103		set guioptions+=e
1104		set sessionoptions+=tabpages
1105		set showtabline=2
1106		" set 2: refresh tab line
1107		call Cream_tabpages_labels()
1108
1109		if Cream_NumberOfBuffers("neither") > 0
1110			"""" get out of specials before refreshing
1111			"""call Cream_TryAnotherWindow()
1112			" don't tab untitled or special
1113			call Cream_buffers_delete_untitled()
1114			" TODO: manage these in the current tab, don't delete
1115			call Cream_buffers_delete_special()
1116		endif
1117
1118	endif
1119
1120endfunction
1121
1122" Cream_tabpages_toggle() {{{1
1123function! Cream_tabpages_toggle()
1124" Turn the tab bar on and off.
1125	if exists("g:CREAM_TABPAGES")
1126		if g:CREAM_TABPAGES == 0
1127			let g:CREAM_TABPAGES = 1
1128			call Cream_tabpages_init()
1129		elseif g:CREAM_TABPAGES == 1
1130			let g:CREAM_TABPAGES = 0
1131			call Cream_tabpages_init()
1132		endif
1133	endif
1134	call Cream_menu_settings_preferences()
1135endfunction
1136
1137" Cream_tabpages_labels() {{{1
1138function! Cream_tabpages_labels()
1139	set guitablabel=%{Cream_statusline_filename()}%{Cream_tabpages_filestate()}
1140endfunction
1141
1142" Cream_tabpages_filestate() {{{1
1143function! Cream_tabpages_filestate()
1144" Return tab label file modified state.
1145" Note: Unlike similar function for statusline, this function ignores
1146"       everything but modified state.
1147	if &modified != 0
1148		return '*'
1149	else
1150		return ''
1151	endif
1152endfunction
1153
1154" Cream_tabpages_refresh() {{{1
1155function! Cream_tabpages_refresh()
1156" ensure one buffer per tab and refresh titles
1157
1158	" remember current buffer
1159	let mybuf = bufnr("%")
1160
1161	" start fresh
1162	"" get out of any specials
1163	"call Cream_TryAnotherBuffer()
1164	" kill off non-memorable buffers now hidden
1165	call Cream_buffers_delete_untitled()
1166	" make sure we haven't deleted it already
1167	if !bufexists(mybuf)
1168		return
1169	endif
1170
1171	" close all tabs but one (silence if we only have one)
1172	silent! tabonly!
1173	" make first tab the first buffer
1174	bfirst
1175	" open a new tab for each non-special buffer
1176	let i = bufnr("%")
1177	while i < bufnr('$')
1178		let i = i + 1
1179		if  Cream_buffer_isspecial(i) != 1
1180		\&& Cream_buffer_isnewunmod(i) != 1
1181		\&& bufexists(i)
1182			" Broken, cannot ":tabedit bufnr"
1183			"execute "tabedit " . bufname(i)
1184			" TODO: The next two lines create a bunch of
1185			" hidden untitled buffers which we hack-fix following.
1186			tabedit
1187			execute "buffer " . i
1188		endif
1189	endwhile
1190	" kill off non-memorable buffers now hidden
1191	call Cream_buffers_delete_untitled()
1192
1193	" restore current buffer
1194	call Cream_tab_goto(mybuf)
1195
1196	" TODO: need window/tab/highlighting refresh?
1197	redraw!
1198
1199endfunction
1200
1201" Cream_tab_goto(bufnr) {{{1
1202function! Cream_tab_goto(bufnr)
1203" Make tab active that contains {buffer}.
1204
1205	" skip if not turned on
1206	if !exists("g:CREAM_TABPAGES") || g:CREAM_TABPAGES == 0
1207		return
1208	endif
1209
1210	let i = 1
1211	while i <= tabpagenr('$')
1212		" we match, stop
1213		if bufnr("%") == a:bufnr
1214			break
1215		endif
1216		tabnext
1217		let i = i + 1
1218	endwhile
1219
1220endfunction
1221
1222"""function! Cream_tabnr(bufnr)
1223"""" Return the tab number containing {bufnr}.
1224"""
1225"""    " TODO: cleanup: Is there anyway to do this without paging all the
1226"""    " tabs twice?!
1227"""
1228"""    " remember this buffer(tab)
1229"""    let mybufnr = bufnr("%")
1230"""    " go to bufnr
1231"""    call Cream_tab_goto(a:bufnr)
1232"""    " remember bufnr
1233"""    let bufnr = bufnr("%")
1234"""    " restore original tab
1235"""    call Cream_tab_goto(mybufnr)
1236"""    return bufnr
1237"""
1238"""endfunction
1239
1240" Cream_tabs_focusgained() {{{1
1241function! Cream_tabs_focusgained()
1242" fix when buffer externally added to session
1243
1244	if !exists("g:CREAM_FOCUS_BUFNR")
1245		return
1246	endif
1247
1248	" quit if no new buffer (old and new the same)
1249	if g:CREAM_FOCUS_BUFNR == bufnr("%")
1250		return
1251	endif
1252	" one buffer per tab
1253	call Cream_window_setup()
1254	" put this new tab after the previous current tab
1255	execute "tabmove " . tabpagenr()
1256
1257endfunction
1258
1259" Cream_tabs_focuslost() {{{1
1260function! Cream_tabs_focuslost()
1261" remember current buffer when focus lost
1262	let g:CREAM_FOCUS_BUFNR = bufnr("%")
1263endfunction
1264
1265" Cream_tab_move_left() {{{1
1266function! Cream_tab_move_left()
1267" Move the current tab one tab to the left in a circular fashion
1268" i.e. if the tab is already at the leftmost position, move it all
1269" the way over to the right again.
1270	if tabpagenr() == 1
1271		execute "tabmove " . tabpagenr("$")
1272	else
1273		execute "tabmove " . (tabpagenr()-2)
1274	endif
1275
1276	" Re-sync the tabs with the file buffers
1277	call Cream_window_setup()
1278endfunction
1279
1280" Cream_tab_move_right() {{{1
1281function! Cream_tab_move_right()
1282" Move the current tab one tab to the right in a circular fashion
1283" i.e. if the tab is already at the rightmost position, move it
1284" all the way over to the left again.
1285	if tabpagenr() == tabpagenr("$")
1286		tabmove 0
1287	else
1288		execute "tabmove " . tabpagenr()
1289	endif
1290
1291	" Re-sync the tabs with the file buffers
1292	call Cream_window_setup()
1293endfunction
1294
1295" Cream_tab_move_first() {{{1
1296function! Cream_tab_move_first()
1297" Make the current tab first (move it to the far left)
1298	" nothing if already there
1299	if tabpagenr() == 1
1300		return
1301	endif
1302	tabmove 0
1303
1304	" Re-sync the tabs with the file buffers
1305	call Cream_window_setup()
1306endfunction
1307
1308" Cream_tab_move_last() {{{1
1309function! Cream_tab_move_last()
1310" Make the current tab last (move it to the far right)
1311	" nothing if already there
1312	if tabpagenr() == tabpagenr("$")
1313		return
1314	endif
1315	tabmove
1316
1317	" Re-sync the tabs with the file buffers
1318	call Cream_window_setup()
1319endfunction
1320
1321
1322" 1}}}
1323" vim:foldmethod=marker
1324