|
|
1.1 root 1: /* Window creation, deletion and examination for GNU Emacs.
2: Does not include redisplay.
3: Copyright (C) 1985 Richard M. Stallman.
4:
5: This file is part of GNU Emacs.
6:
7: GNU Emacs is distributed in the hope that it will be useful,
8: but WITHOUT ANY WARRANTY. No author or distributor
9: accepts responsibility to anyone for the consequences of using it
10: or for whether it serves any particular purpose or works at all,
11: unless he says so in writing. Refer to the GNU Emacs General Public
12: License for full details.
13:
14: Everyone is granted permission to copy, modify and redistribute
15: GNU Emacs, but only under the conditions described in the
16: GNU Emacs General Public License. A copy of this license is
17: supposed to have been given to you along with GNU Emacs so you
18: can know your rights and responsibilities. It should be in a
19: file named COPYING. Among other things, the copyright notice
20: and this notice must be preserved on all copies. */
21:
22:
23: #include "config.h"
24: #include "lisp.h"
25: #include "buffer.h"
26: #include "window.h"
27: #include "commands.h"
28: #include "indent.h"
29: #include "termchar.h"
30:
31: Lisp_Object Qwindowp;
32:
33: Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
34: Lisp_Object Fshow_buffer (), Fsplit_window (), Frecenter ();
35:
36: /* This is the window which displays the minibuffer.
37: It is always the same window. */
38:
39: Lisp_Object minibuf_window;
40:
41: /* This is the window in which the terminal's cursor should
42: be left when nothing is being done with it. This must
43: always be a leaf window, and its buffer is selected by
44: the top level editing loop at the end of each command. */
45:
46: Lisp_Object selected_window;
47:
48: /* If a window gets smaller than either of these, it is removed. */
49:
50: int window_min_height;
51: int window_min_width;
52:
53: /* Nonzero implies pop_to_buffer should create windows. */
54:
55: int pop_up_windows;
56:
57: /* display-buffer always splits the largest window
58: if that window is more than this high */
59:
60: int split_height_threshold;
61:
62: /* Number of lines of continuity in scrolling by screenfuls. */
63:
64: int next_screen_context_lines;
65:
66: /* Incremented for each window created. */
67:
68: static int sequence_number;
69:
70: DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
71: "Returns t if OBJ is a window.")
72: (obj)
73: Lisp_Object obj;
74: {
75: return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
76: }
77:
78: Lisp_Object
79: make_window ()
80: {
81: Lisp_Object val;
82: register struct window *p;
83:
84: val = Fmake_vector (
85: make_number ((sizeof (struct window) - sizeof (struct Lisp_Vector))
86: / sizeof (Lisp_Object)),
87: Qnil);
88: XSETTYPE (val, Lisp_Window);
89: p = XWINDOW (val);
90: XFASTINT (p->left) = XFASTINT (p->top)
91: = XFASTINT (p->height) = XFASTINT (p->width)
92: = XFASTINT (p->hscroll) = 0;
93: XFASTINT (p->last_point_x) = XFASTINT (p->last_point_y) = 0;
94: p->start = Fmake_marker ();
95: p->pointm = Fmake_marker ();
96: XFASTINT (p->sequence_number) = ++sequence_number;
97: XFASTINT (p->use_time) = 0;
98: return val;
99: }
100:
101: DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
102: "Return the window that the cursor appears in and commands apply to.")
103: ()
104: {
105: return selected_window;
106: }
107:
108: DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
109: Spos_visible_in_window_p, 0, 2, 0,
110: "Return t if position POS is currently on the screen in WINDOW.\n\
111: Returns nil if that position is scrolled vertically out of view.\n\
112: POS defaults to point; WINDOW, to the selected window.")
113: (pos, window)
114: Lisp_Object pos, window;
115: {
116: register struct window *w;
117: register int top;
118: register int height;
119: register int posint;
120: register struct buffer_text *text;
121: struct position posval;
122:
123: if (NULL (pos))
124: posint = point;
125: else
126: {
127: CHECK_NUMBER_COERCE_MARKER (pos, 0);
128: posint = XINT (pos);
129: }
130:
131: if (NULL (window))
132: window = selected_window;
133: else
134: CHECK_WINDOW (window, 1);
135: w = XWINDOW (window);
136: top = marker_position (w->start);
137:
138: if (posint < top)
139: return Qnil;
140:
141: height = XFASTINT (w->height) - !EQ (window, minibuf_window);
142:
143: bf_cur->text = bf_text;
144: text = &XBUFFER (w->buffer)->text;
145: if (XFASTINT (w->last_modified) >= text->modified)
146: {
147: /* If screen is up to date,
148: use the info recorded about how much text fit on it. */
149: if (posint < text->size1 + text->size2 + 1 - XFASTINT (w->window_end_pos)
150: || (XFASTINT (w->window_end_vpos) < height))
151: return Qt;
152: return Qnil;
153: }
154: else
155: {
156: if (posint > text->size1 + text->size2 + 1)
157: return Qnil;
158: /* If that info is not correct, calculate afresh */
159: posval = *compute_motion (top, 0, 0,
160: posint, height, 0,
161: XFASTINT (w->width) - 1
162: - (XFASTINT (w->width) + XFASTINT (w->left) != XFASTINT (XWINDOW (minibuf_window)->width)),
163:
164: XINT (w->hscroll), 0);
165: return posval.vpos < height ? Qt : Qnil;
166: }
167: }
168:
169: struct window *
170: decode_window (window)
171: Lisp_Object window;
172: {
173: if (NULL (window))
174: return XWINDOW (selected_window);
175:
176: CHECK_WINDOW (window, 0);
177: return XWINDOW (window);
178: }
179:
180: DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
181: "Return the buffer that WINDOW is displaying.")
182: (window)
183: Lisp_Object window;
184: {
185: return decode_window (window)->buffer;
186: }
187:
188: DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
189: "Return the number of lines in WINDOW (including its mode line).")
190: (window)
191: Lisp_Object window;
192: {
193: return decode_window (window)->height;
194: }
195:
196: DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
197: "Return the number of columns in WINDOW.")
198: (window)
199: Lisp_Object window;
200: {
201: return decode_window (window)->width;
202: }
203:
204: DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
205: "Return the number of columns by which WINDOW is scrolled from left margin.")
206: (window)
207: Lisp_Object window;
208: {
209: return decode_window (window)->hscroll;
210: }
211:
212: DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
213: "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
214: NCOL should be zero or positive.")
215: (window, ncol)
216: Lisp_Object window, ncol;
217: {
218: CHECK_NUMBER (ncol, 1);
219: if (XINT (ncol) < 0) XFASTINT (ncol) = 0;
220: if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
221: args_out_of_range (ncol, Qnil);
222:
223: clip_changed = 1; /* Prevent redisplay shortcuts */
224: decode_window (window)->hscroll = ncol;
225: return ncol;
226: }
227:
228: DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
229: "Return a list of the edge coordinates of WINDOW.\n\
230: \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of screen.")
231: (window)
232: Lisp_Object window;
233: {
234: register struct window *w = decode_window (window);
235:
236: return Fcons (w->left, Fcons (w->top,
237: Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)),
238: Fcons (make_number (XFASTINT (w->top)
239: + XFASTINT (w->height)),
240: Qnil))));
241: }
242:
243: DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
244: "Return current value of point in WINDOW.")
245: (window)
246: Lisp_Object window;
247: {
248: return Fmarker_position (decode_window (window)->pointm);
249: }
250:
251: DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
252: "Return position at which display currently starts in WINDOW.")
253: (window)
254: Lisp_Object window;
255: {
256: return Fmarker_position (decode_window (window)->start);
257: }
258:
259: DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
260: "Make point value in WINDOW be at position POS in WINDOW's buffer.")
261: (window, pos)
262: Lisp_Object window, pos;
263: {
264: struct window *w = decode_window (window);
265: CHECK_NUMBER_COERCE_MARKER (pos, 1);
266: Fset_marker (w->pointm, pos, w->buffer);
267: return pos;
268: }
269:
270: DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
271: "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
272: Optional third arg NOFORCE non-nil inhibits next redisplay\n\
273: from overriding motion of point in order to display at this exact start.")
274: (window, pos, noforce)
275: Lisp_Object window, pos, noforce;
276: {
277: struct window *w = decode_window (window);
278: CHECK_NUMBER_COERCE_MARKER (pos, 1);
279: Fset_marker (w->start, pos, w->buffer);
280: if (NULL (noforce))
281: w->force_start = Qt;
282: w->redo_mode_line = Qt;
283: XFASTINT (w->last_modified) = 0;
284: return pos;
285: }
286:
287: DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
288: "Remove WINDOW from the display. Default is selected window.")
289: (window)
290: Lisp_Object window;
291: {
292: int osize;
293: Lisp_Object tem, parent;
294: register struct window *p;
295:
296: if (NULL (window))
297: window = selected_window;
298: else
299: CHECK_WINDOW (window, 0);
300:
301: p = XWINDOW (window);
302: parent = p->parent;
303: if (NULL (parent))
304: error ("Attempt to delete minibuffer or sole ordinary window");
305:
306: windows_or_buffers_changed++;
307:
308: if (EQ (window, selected_window))
309: Fselect_window (Fnext_window (window, Qnil));
310:
311: tem = p->buffer;
312: /* tem is null for dummy parent windows
313: (which have inferiors but not any contents themselves) */
314: if (!NULL (tem))
315: {
316: unshow_buffer (p);
317: unchain_marker (p->pointm);
318: unchain_marker (p->start);
319: }
320:
321: tem = p->next;
322: if (!NULL (tem))
323: XWINDOW (tem)->prev = p->prev;
324:
325: tem = p->prev;
326: if (!NULL (tem))
327: XWINDOW (tem)->next = p->next;
328:
329: if (EQ (window, XWINDOW (parent)->hchild))
330: XWINDOW (parent)->hchild = p->next;
331: if (EQ (window, XWINDOW (parent)->vchild))
332: XWINDOW (parent)->vchild = p->next;
333:
334: /* Stretch the siblings to use all the available space */
335: if (!NULL (XWINDOW (parent)->vchild))
336: {
337: /* It's a vertical combination */
338: osize = XFASTINT (XWINDOW (parent)->height);
339: XFASTINT (XWINDOW (parent)->height)
340: -= XFASTINT (p->height);
341: set_window_height (parent, osize, 1);
342: }
343: if (!NULL (XWINDOW (parent)->hchild))
344: {
345: /* It's a horizontal combination */
346: osize = XFASTINT (XWINDOW (parent)->width);
347: XFASTINT (XWINDOW (parent)->width)
348: -= XFASTINT (p->width);
349: set_window_width (parent, osize, 1);
350: }
351:
352: /* If parent now has only one child,
353: put the child into the parent's place. */
354:
355: tem = XWINDOW (parent)->hchild;
356: if (NULL (tem))
357: tem = XWINDOW (parent)->vchild;
358: if (NULL (XWINDOW (tem)->next))
359: replace_window (parent, tem);
360: return Qnil;
361: }
362:
363: /* Put replacement into the window structure in place of old. */
364:
365: replace_window (old, replacement)
366: Lisp_Object old, replacement;
367: {
368: Lisp_Object tem;
369: register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
370:
371: p->left = o->left;
372: p->top = o->top;
373: p->width = o->width;
374: p->height = o->height;
375:
376: p->next = tem = o->next;
377: if (!NULL (tem))
378: XWINDOW (tem)->prev = replacement;
379:
380: p->prev = tem = o->prev;
381: if (!NULL (tem))
382: XWINDOW (tem)->next = replacement;
383:
384: p->parent = tem = o->parent;
385: if (!NULL (tem))
386: {
387: if (EQ (XWINDOW (tem)->vchild, old))
388: XWINDOW (tem)->vchild = replacement;
389: if (EQ (XWINDOW (tem)->hchild, old))
390: XWINDOW (tem)->hchild = replacement;
391: }
392:
393: /*** Here, if replacement is a vertical combination
394: and so is its new parent, we should make replacement's
395: children be children of that parent instead. ***/
396: }
397:
398: DEFUN ("next-window", Fnext_window, Snext_window, 0, 2, 0,
399: "Return next window after WINDOW in canonical ordering of windows.")
400: (window, yesmini)
401: Lisp_Object window, yesmini;
402: {
403: Lisp_Object tem;
404: if (NULL (window))
405: window = selected_window;
406: else
407: CHECK_WINDOW (window, 0);
408: do
409: {
410: while (tem = XWINDOW (window)->next, NULL (tem))
411: if (tem = XWINDOW (window)->parent, !NULL (tem))
412: window = tem;
413: else /* window must be minibuf_window now */
414: {
415: tem = XWINDOW (window)->prev;
416: break;
417: }
418: window = tem;
419: while (1)
420: {
421: if (!NULL (XWINDOW (window)->hchild))
422: window = XWINDOW (window)->hchild;
423: else if (!NULL (XWINDOW (window)->vchild))
424: window = XWINDOW (window)->vchild;
425: else break;
426: }
427: }
428: while (EQ (window, minibuf_window) && NULL (yesmini) && !MinibufDepth);
429: return window;
430: }
431:
432: DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 1, 0,
433: "Return previous window before WINDOW in canonical ordering of windows.")
434: (window)
435: Lisp_Object window;
436: {
437: Lisp_Object tem;
438: if (NULL (window))
439: window = selected_window;
440: else
441: CHECK_WINDOW (window, 0);
442: do /* at least once, and until not the minibuffer */
443: {
444: while (tem = XWINDOW (window)->prev, NULL (tem))
445: if (tem = XWINDOW (window)->parent, !NULL (tem))
446: window = tem;
447: else /* window must be the root window now */
448: {
449: tem = minibuf_window;
450: break;
451: }
452: window = tem;
453: while (1)
454: {
455: if (!NULL (XWINDOW (window)->hchild))
456: window = XWINDOW (window)->hchild;
457: else if (!NULL (XWINDOW (window)->vchild))
458: window = XWINDOW (window)->vchild;
459: else break;
460: while (tem = XWINDOW (window)->next, !NULL (tem))
461: window = tem;
462: }
463: }
464: while (EQ (window, minibuf_window) && !MinibufDepth);
465: return window;
466: }
467:
468: DEFUN ("other-window", Fother_window, Sother_window, 1, 1, "p",
469: "Select the ARG'th different window.")
470: (n)
471: Lisp_Object n;
472: {
473: int i;
474: Lisp_Object w;
475:
476: CHECK_NUMBER (n, 0);
477: w = selected_window;
478: i = XINT (n);
479:
480: while (i > 0)
481: {
482: w = Fnext_window (w, Qnil);
483: i--;
484: }
485: while (i < 0)
486: {
487: w = Fprevious_window (w);
488: i++;
489: }
490: Fselect_window (w);
491: return Qnil;
492: }
493:
494: Lisp_Object
495: window_loop (type, obj)
496: int type;
497: Lisp_Object obj;
498: {
499: Lisp_Object w, w1, ret_w, tem;
500: register struct window *p, *q;
501:
502: w = minibuf_window;
503: ret_w = Qnil;
504: while (1)
505: {
506: p = XWINDOW (w);
507: w1 = Fnext_window (w, Qt);
508: if (!EQ (w, minibuf_window))
509: switch (type)
510: {
511: case 1:
512: if (XBUFFER (p->buffer) == XBUFFER (obj))
513: return w;
514: break;
515:
516: case 2:
517: /* t as arg means consider only full-width windows */
518: if (!NULL (obj) && XFASTINT (p->width) != screen_width)
519: break;
520: if (NULL (ret_w) ||
521: XFASTINT (XWINDOW (ret_w)->use_time) > XFASTINT (p->use_time))
522: ret_w = w;
523: break;
524:
525: case 3:
526: if (p != XWINDOW (obj))
527: Fdelete_window (w);
528: break;
529:
530: case 4:
531: if (EQ (p->buffer, obj))
532: {
533: if (NULL (p->parent))
534: {
535: tem = Fother_buffer (obj);
536: if (NULL (tem))
537: tem = Fget_buffer_create (build_string ("*scratch*"));
538: Fshow_buffer (w, tem);
539: Fset_buffer (p->buffer);
540: }
541: else
542: Fdelete_window (w);
543: }
544: break;
545:
546: case 5:
547: q = XWINDOW (ret_w);
548: if (NULL (ret_w) ||
549: (XFASTINT (p->height) * XFASTINT (p->width))
550: >
551: (XFASTINT (q->height) * XFASTINT (q->width)))
552: ret_w = w;
553: break;
554:
555: case 6:
556: if (EQ (p->buffer, obj))
557: {
558: tem = Fother_buffer (obj);
559: if (NULL (tem))
560: tem = Fget_buffer_create (build_string ("*scratch*"));
561: Fshow_buffer (w, tem);
562: Fset_buffer (p->buffer);
563: }
564: break;
565: }
566: w = w1;
567: if (EQ (w, minibuf_window))
568: return ret_w;
569: }
570: }
571:
572: DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 0, 0,
573: "Return the window least recently selected or used for display.")
574: ()
575: {
576: Lisp_Object w;
577: /* First try for a window that is full-width */
578: w = window_loop (2, Qt);
579: if (!NULL (w) && !EQ (w, selected_window))
580: return w;
581: /* If none of them, try the rest */
582: return window_loop (2, Qnil);
583: }
584:
585: DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 0, 0,
586: "Return the largest window in area.")
587: ()
588: {
589: return window_loop (5, Qnil);
590: }
591:
592: DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 1, 0,
593: "Return a window currently displaying BUFFER, or nil if none.")
594: (buffer)
595: Lisp_Object buffer;
596: {
597: buffer = Fget_buffer (buffer);
598: if (XTYPE (buffer) == Lisp_Buffer)
599: return window_loop (1, buffer);
600: else return Qnil;
601: }
602:
603: DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
604: 0, 1, "",
605: "Make WINDOW (or the selected window) fill the screen.")
606: (w)
607: Lisp_Object w;
608: {
609: window_loop (3, !NULL (w) ? w : selected_window);
610: return Qnil;
611: }
612:
613: DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
614: 1, 1, "bDelete windows on (buffer): ",
615: "Delete all windows showing BUFFER.")
616: (buffer)
617: Lisp_Object buffer;
618: {
619: if (!NULL (buffer))
620: {
621: buffer = Fget_buffer (buffer);
622: CHECK_BUFFER (buffer, 0);
623: window_loop (4, buffer);
624: }
625: return Qnil;
626: }
627:
628: DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
629: Sreplace_buffer_in_windows,
630: 1, 1, "bReplace buffer in windows: ",
631: "Replace BUFFER with some other buffer in all windows showing it.")
632: (buffer)
633: Lisp_Object buffer;
634: {
635: if (!NULL (buffer))
636: {
637: buffer = Fget_buffer (buffer);
638: CHECK_BUFFER (buffer, 0);
639: window_loop (6, buffer);
640: }
641: return Qnil;
642: }
643:
644: /* Set the height of WINDOW and all its inferiors. */
645: /* Normally the window is deleted if it gets too small.
646: nodelete nonzero means do not do this.
647: (The caller should check later and do so if appropriate) */
648:
649: set_window_height (window, height, nodelete)
650: Lisp_Object window;
651: int height;
652: int nodelete;
653: {
654: register struct window *w = XWINDOW (window);
655: register struct window *c;
656: int oheight = XFASTINT (w->height);
657: int top, pos, lastbot, opos, lastobot;
658: Lisp_Object child;
659:
660: if (window_min_height < 2)
661: window_min_height = 2;
662:
663: if (!nodelete &&
664: height < (EQ(window, minibuf_window) ? 1 : window_min_height))
665: {
666: Fdelete_window (window);
667: return;
668: }
669:
670: XFASTINT (w->last_modified) = 0;
671: windows_or_buffers_changed++;
672: XFASTINT (w->height) = height;
673: if (!NULL (w->hchild))
674: {
675: for (child = w->hchild; !NULL (child); child = XWINDOW (child)->next)
676: {
677: XWINDOW (child)->top = w->top;
678: set_window_height (child, height, nodelete);
679: }
680: }
681: else if (!NULL (w->vchild))
682: {
683: lastbot = top = XFASTINT (w->top);
684: lastobot = 0;
685: for (child = w->vchild; !NULL (child); child = c->next)
686: {
687: c = XWINDOW (child);
688:
689: opos = lastobot + XFASTINT (c->height);
690:
691: XFASTINT (c->top) = lastbot;
692:
693: pos = (((opos * height) << 1) + oheight) / (oheight << 1);
694:
695: /* Avoid confusion: inhibit deletion of child if becomes too small */
696: set_window_height (child, pos + top - lastbot, 1);
697:
698: /* Now advance child to next window,
699: and set lastbot if child was not just deleted. */
700: lastbot = pos + top, lastobot = opos;
701: }
702: /* Now delete any children that became too small. */
703: if (!nodelete)
704: for (child = w->vchild; !NULL (child); child = XWINDOW (child)->next)
705: {
706: set_window_height (child, XINT (XWINDOW (child)->height), 0);
707: }
708: }
709: }
710:
711: /* Recursively set width of WINDOW and its inferiors. */
712:
713: set_window_width (window, width, nodelete)
714: Lisp_Object window;
715: int width;
716: int nodelete;
717: {
718: register struct window *w = XWINDOW (window);
719: register struct window *c;
720: int owidth = XFASTINT (w->width);
721: int left, pos, lastright, opos, lastoright;
722: Lisp_Object child;
723:
724: if (!nodelete && width < window_min_width)
725: {
726: Fdelete_window (window);
727: return;
728: }
729:
730: XFASTINT (w->last_modified) = 0;
731: XFASTINT (w->width) = width;
732: if (!NULL (w->vchild))
733: {
734: for (child = w->vchild; !NULL (child); child = XWINDOW (child)->next)
735: {
736: XWINDOW (child)->left = w->left;
737: set_window_width (child, width, nodelete);
738: }
739: }
740: else if (!NULL (w->hchild))
741: {
742: lastright = left = XFASTINT (w->left);
743: lastoright = 0;
744: for (child = w->hchild; !NULL (child); child = c->next)
745: {
746: c = XWINDOW (child);
747:
748: opos = lastoright + XFASTINT (c->width);
749:
750: XFASTINT (c->left) = lastright;
751:
752: pos = (((opos * width) << 1) + owidth) / (owidth << 1);
753:
754: /* Inhibit deletion for becoming too small */
755: set_window_width (child, pos + left - lastright, 1);
756:
757: /* Now advance child to next window,
758: and set lastright if child was not just deleted. */
759: lastright = pos + left, lastoright = opos;
760: }
761: /* Delete children that became too small */
762: if (!nodelete)
763: for (child = w->hchild; !NULL (child); child = XWINDOW (child)->next)
764: {
765: set_window_width (child, XINT (XWINDOW (child)->width), 0);
766: }
767: }
768: }
769:
770: static int window_select_count;
771:
772: DEFUN ("show-buffer", Fshow_buffer, Sshow_buffer, 2, 2, 0,
773: "Make WINDOW display BUFFER as its contents.\n\
774: BUFFER can be a buffer or buffer name.")
775: (window, buffer)
776: Lisp_Object window, buffer;
777: {
778: Lisp_Object tem;
779: struct window *w = decode_window (window);
780:
781: buffer = Fget_buffer (buffer);
782: CHECK_BUFFER (buffer, 1);
783:
784: if (NULL (XBUFFER (buffer)->name))
785: error ("Attempt to display deleted buffer");
786:
787: tem = w->buffer;
788: if (!NULL (tem))
789: unshow_buffer (w);
790:
791: w->buffer = buffer;
792: Fset_marker (w->pointm,
793: make_number (XBUFFER (buffer) == bf_cur
794: ? point : XBUFFER (buffer)->text.pointloc),
795: buffer);
796: Fset_marker (w->start, make_number (XBUFFER (buffer)->last_window_start),
797: buffer);
798: XFASTINT (w->last_modified) = 0;
799: windows_or_buffers_changed++;
800: if (EQ (window, selected_window))
801: Fset_buffer (buffer);
802:
803: return Qnil;
804: }
805:
806: /* Record info on buffer window w is displaying
807: when it is about to cease to display that buffer. */
808:
809: unshow_buffer (w)
810: struct window *w;
811: {
812: Lisp_Object buf;
813: buf = w->buffer;
814:
815: if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
816: abort ();
817:
818: if (w != XWINDOW (selected_window)
819: && EQ (buf, XWINDOW (selected_window)->buffer))
820: return;
821:
822: if (XBUFFER (buf) == bf_cur)
823: {
824: if (w != XWINDOW (selected_window))
825: point = marker_position (w->pointm);
826: }
827: else
828: XBUFFER (buf)->text.pointloc =
829: marker_position (w->pointm);
830: XBUFFER (buf)->last_window_start =
831: marker_position (w->start);
832: }
833:
834: DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
835: "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
836: The main editor command loop selects the buffer of the selected window\n\
837: before each command.")
838: (window)
839: Lisp_Object window;
840: {
841: register struct window *w = XWINDOW (window);
842: register struct window *ow = XWINDOW (selected_window);
843:
844: CHECK_WINDOW (window, 0);
845:
846: if (NULL (w->buffer))
847: error ("Trying to select window with no buffer");
848:
849: XFASTINT (w->use_time) = ++window_select_count;
850: if (EQ (window, selected_window))
851: return window;
852:
853: if (bf_cur == XBUFFER (ow->buffer))
854: Fset_marker (ow->pointm, make_number (point), ow->buffer);
855:
856: selected_window = window;
857:
858: record_buffer (w->buffer);
859: Fset_buffer (w->buffer);
860: if (bf_cur == XBUFFER (ow->buffer))
861: {
862: /* If the new and old windows show the same buffer,
863: Fset_buffer did nothing. So we must switch to
864: the new buffer's value of point. */
865: SetPoint (marker_position (w->pointm));
866: if (point < FirstCharacter)
867: point = FirstCharacter;
868: if (point > NumCharacters + 1)
869: point = NumCharacters + 1;
870: }
871:
872: windows_or_buffers_changed++;
873:
874: return window;
875: }
876:
877: DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2, 0,
878: "Make BUFFER appear in some window but don't select it.\n\
879: BUFFER can be a buffer or a buffer name.\n\
880: If BUFFER is shown already in some window, just uses that one,\n\
881: unless the window is the selected window and NOTTHISWINDOW is non-nil.\n\
882: Returns the window displaying BUFFER.")
883: (buffer, notthiswindow)
884: Lisp_Object buffer, notthiswindow;
885: {
886: Lisp_Object window;
887: buffer = Fget_buffer (buffer);
888: CHECK_BUFFER (buffer, 0);
889:
890: if (NULL (notthiswindow)
891: && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
892: return selected_window;
893:
894: window = Fget_buffer_window (buffer);
895: if (!NULL (window)
896: && (NULL (notthiswindow) || !EQ (window, selected_window)))
897: return window;
898:
899: if (pop_up_windows)
900: {
901: /* Don't try to create a window if would get an error */
902: if (window_min_height < 2)
903: window_min_height = 2;
904: if (split_height_threshold < window_min_height << 1)
905: split_height_threshold = window_min_height << 1;
906:
907: window = Fget_largest_window ();
908: if (window_height (window) >= split_height_threshold
909: &&
910: XFASTINT (XWINDOW (window)->width) != screen_width)
911: window = Fsplit_window (window, Qnil, Qnil);
912: else
913: {
914: window = Fget_lru_window ();
915: if ((EQ (window, selected_window)
916: || (EQ (selected_window, minibuf_window)
917: && EQ (window, XWINDOW (minibuf_window)->prev)))
918: && window_height (window) >= window_min_height << 1)
919: window = Fsplit_window (window, Qnil, Qnil);
920: }
921: }
922: else
923: window = Fget_lru_window ();
924:
925: Fshow_buffer (window, buffer);
926: return window;
927: }
928:
929: temp_output_buffer_show (buf)
930: Lisp_Object buf;
931: {
932: struct buffer *old = bf_cur;
933: Lisp_Object window;
934:
935: Fset_buffer (buf);
936: XBUFFER (buf)->save_modified = bf_modified;
937: SetPoint (1);
938: bf_head_clip = 1;
939: bf_tail_clip = 0;
940: clip_changed = 1;
941: SetBfp (old);
942:
943: window = Fdisplay_buffer (buf, Qnil);
944: XFASTINT (XWINDOW (window)->hscroll) = 0;
945: Fset_marker (XWINDOW (window)->start, make_number (1), buf);
946: Fset_marker (XWINDOW (window)->pointm, make_number (1), buf);
947: }
948:
949: make_dummy_parent (window)
950: Lisp_Object window;
951: {
952: Lisp_Object old, new;
953: register struct window *o, *p;
954: old = window;
955: XSETTYPE (old, Lisp_Vector);
956: new = Fcopy_sequence (old);
957: XSETTYPE (new, Lisp_Window);
958:
959: o = XWINDOW (old);
960: p = XWINDOW (new);
961: XFASTINT (p->sequence_number) = ++sequence_number;
962:
963: /* Put new into window structure in place of window */
964: replace_window (window, new);
965:
966: o->next = Qnil;
967: o->prev = Qnil;
968: o->vchild = Qnil;
969: o->hchild = Qnil;
970: o->parent = new;
971:
972: p->start = Qnil;
973: p->pointm = Qnil;
974: p->buffer = Qnil;
975: }
976:
977: DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
978: "Split WINDOW, putting SIZE lines in the first of the pair.\n\
979: WINDOW defaults to selected one and SIZE to half its size.\n\
980: If optional third arg HOR-FLAG is non-nil, split side by side\n\
981: and put SIZE columns in the first of the pair.")
982: (window, chsize, horflag)
983: Lisp_Object window, chsize, horflag;
984: {
985: Lisp_Object new;
986: register struct window *o, *p;
987: int size;
988:
989: if (NULL (window))
990: window = selected_window;
991: else
992: CHECK_WINDOW (window, 0);
993:
994: o = XWINDOW (window);
995:
996: if (NULL (chsize))
997: {
998: if (!NULL (horflag))
999: size = XFASTINT (o->width) >> 1;
1000: else
1001: size = XFASTINT (o->height) >> 1;
1002: }
1003: else
1004: {
1005: CHECK_NUMBER (chsize, 1);
1006: size = XINT (chsize);
1007: }
1008:
1009: if (EQ (window, minibuf_window))
1010: error ("Attempt to split minibuffer window");
1011:
1012: if (NULL (horflag))
1013: {
1014: if (window_min_height < 2)
1015: window_min_height = 2;
1016:
1017: if (size < window_min_height ||
1018: size + window_min_height > XFASTINT (o->height))
1019: args_out_of_range_3 (window, chsize, horflag);
1020: if (NULL (o->parent) ||
1021: NULL (XWINDOW (o->parent)->vchild))
1022: {
1023: make_dummy_parent (window);
1024: new = o->parent;
1025: XWINDOW (new)->vchild = window;
1026: }
1027: }
1028: else
1029: {
1030: if (size < window_min_width ||
1031: size + window_min_width > XFASTINT (o->width))
1032: args_out_of_range_3 (window, chsize, horflag);
1033: if (NULL (o->parent) ||
1034: NULL (XWINDOW (o->parent)->hchild))
1035: {
1036: make_dummy_parent (window);
1037: new = o->parent;
1038: XWINDOW (new)->hchild = window;
1039: }
1040: }
1041:
1042: /* Now we know that window's parent is a vertical combination
1043: if we are dividing vertically, or a horizontal combination
1044: if we are making side-by-side windows */
1045:
1046: windows_or_buffers_changed++;
1047: new = make_window ();
1048: p = XWINDOW (new);
1049:
1050: p->next = o->next;
1051: if (!NULL (p->next))
1052: XWINDOW (p->next)->prev = new;
1053: p->prev = window;
1054: o->next = new;
1055: p->parent = o->parent;
1056:
1057: Fshow_buffer (new, o->buffer);
1058:
1059: /* Apportion the available screen space among the two new windows */
1060:
1061: if (!NULL (horflag))
1062: {
1063: p->height = o->height;
1064: p->top = o->top;
1065: XFASTINT (p->width) = XFASTINT (o->width) - size;
1066: XFASTINT (o->width) = size;
1067: XFASTINT (p->left) = XFASTINT (o->left) + size;
1068: }
1069: else
1070: {
1071: p->left = o->left;
1072: p->width = o->width;
1073: XFASTINT (p->height) = XFASTINT (o->height) - size;
1074: XFASTINT (o->height) = size;
1075: XFASTINT (p->top) = XFASTINT (o->top) + size;
1076: }
1077:
1078: return new;
1079: }
1080:
1081: DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
1082: "Make current window ARG lines bigger.\n\
1083: From program, optional second arg non-nil means grow sideways ARG columns.")
1084: (n, side)
1085: Lisp_Object n, side;
1086: {
1087: CHECK_NUMBER (n, 0);
1088: change_window_height (XINT (n), !NULL (side));
1089: return Qnil;
1090: }
1091:
1092: DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
1093: "Make current window ARG lines smaller.\n\
1094: From program, optional second arg non-nil means shrink sideways ARG columns.")
1095: (n, side)
1096: Lisp_Object n, side;
1097: {
1098: CHECK_NUMBER (n, 0);
1099: change_window_height (-XINT (n), !NULL (side));
1100: return Qnil;
1101: }
1102:
1103: int
1104: window_height (window)
1105: Lisp_Object window;
1106: {
1107: register struct window *p = XWINDOW (window);
1108: return XFASTINT (p->height);
1109: }
1110:
1111: int
1112: window_width (window)
1113: Lisp_Object window;
1114: {
1115: register struct window *p = XWINDOW (window);
1116: return XFASTINT (p->width);
1117: }
1118:
1119: #define MINSIZE(window) \
1120: (widthflag ? window_min_width \
1121: : (EQ (window, minibuf_window) ? 1 : window_min_height))
1122:
1123: #define CURBEG(w) \
1124: *(widthflag ? (int *) &w->left : (int *) &w->top)
1125:
1126: #define CURSIZE(w) \
1127: *(widthflag ? (int *) &w->width : (int *) &w->height)
1128:
1129: /* Unlike set_window_height, this function
1130: also changes the heights of the siblings so as to
1131: keep everything consistent. */
1132:
1133: change_window_height (delta, widthflag)
1134: int delta, widthflag;
1135: {
1136: Lisp_Object window, parent, tem;
1137: register struct window *p;
1138: int *sizep;
1139: int (*sizefun) () = widthflag ? window_width : window_height;
1140: int (*setsizefun) () = widthflag ? set_window_width : set_window_height;
1141: int opht, maxdelta;
1142:
1143: window = selected_window;
1144: while (1)
1145: {
1146: p = XWINDOW (window);
1147: parent = p->parent;
1148: if (NULL (parent))
1149: {
1150: if (widthflag)
1151: error ("No other window to side of this one");
1152: break;
1153: }
1154: if (widthflag ? !NULL (XWINDOW (parent)->hchild)
1155: : !NULL (XWINDOW (parent)->vchild))
1156: break;
1157: window = parent;
1158: }
1159:
1160: sizep = &CURSIZE (p);
1161:
1162: if (*sizep + delta < MINSIZE (window))
1163: {
1164: Fdelete_window (window);
1165: return;
1166: }
1167:
1168: maxdelta = (!NULL (parent) ? (*sizefun) (parent) - *sizep
1169: : (tem = (!NULL (p->next) ? p->next : p->prev),
1170: (*sizefun) (tem) - MINSIZE (tem)));
1171:
1172: if (delta > maxdelta)
1173: /* This case traps trying to make the minibuffer
1174: the full screen, or make the only window aside from the
1175: minibuffer the full screen. */
1176: delta = maxdelta;
1177:
1178: if (!NULL (p->next) &&
1179: (*sizefun) (p->next) - delta >= MINSIZE (p->next))
1180: {
1181: (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
1182: (*setsizefun) (window, *sizep + delta, 0);
1183: CURBEG (XWINDOW (p->next)) += delta;
1184: /* This does not change size of p->next,
1185: but it propagates the new top edge to its children */
1186: (*setsizefun) (p->next, (*sizefun) (p->next), 0);
1187: }
1188: else if (!NULL (p->prev) &&
1189: (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
1190: {
1191: (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
1192: CURBEG (p) -= delta;
1193: (*setsizefun) (window, *sizep + delta, 0);
1194: }
1195: else
1196: {
1197: opht = (*sizefun) (parent);
1198:
1199: delta = (int) ((float) (delta * opht)
1200: / (float) (opht - *sizep - delta));
1201: /* Add delta lines or columns to this window, and to the parent,
1202: keeping things consistent while not affecting siblings. */
1203: CURSIZE (XWINDOW (parent)) = opht + delta;
1204: (*setsizefun) (window, *sizep + delta, 0);
1205: /* Squeeze out delta lines or columns from our parent,
1206: shriking this window and siblings proportionately.
1207: This brings parent back to correct size.
1208: Delta was calculated so this makes this window the desired size,
1209: taking it all out of the siblings. */
1210: (*setsizefun) (parent, opht, 0);
1211: }
1212:
1213: XFASTINT (p->last_modified) = 0;
1214: }
1215:
1216: static
1217: window_scroll (window, n)
1218: Lisp_Object window;
1219: int n;
1220: {
1221: register struct window *w = XWINDOW (window);
1222: register int opoint = point;
1223: register int ht, pos;
1224: int lose;
1225: Lisp_Object tem;
1226:
1227: ht = XFASTINT (w->height) - !EQ (window, minibuf_window);
1228:
1229: XFASTINT (tem) = point;
1230: tem = Fpos_visible_in_window_p (tem, window);
1231:
1232: if (NULL (tem))
1233: {
1234: Fvertical_motion (make_number (- ht / 2));
1235: XFASTINT (tem) = point;
1236: Fset_marker (w->start, tem, w->buffer);
1237: w->force_start = Qt;
1238: }
1239:
1240: SetPoint (marker_position (w->start));
1241: lose = n < 0 && point == FirstCharacter;
1242: Fvertical_motion (make_number (n));
1243: pos = point;
1244: SetPoint (opoint);
1245:
1246: if (lose)
1247: Fsignal (Qbeginning_of_buffer, Qnil);
1248:
1249: if (pos < NumCharacters + 1)
1250: {
1251: Fset_marker (w->start, make_number (pos), w->buffer);
1252: w->redo_mode_line = Qt;
1253: XFASTINT (w->last_modified) = 0;
1254: if (pos > opoint)
1255: SetPoint (pos);
1256: if (n < 0)
1257: {
1258: SetPoint (pos);
1259: tem = Fvertical_motion (make_number (ht));
1260: if (point > opoint || XFASTINT (tem) < ht)
1261: SetPoint (opoint);
1262: else
1263: Fvertical_motion (make_number (-1));
1264: }
1265: }
1266: else
1267: Fsignal (Qend_of_buffer, Qnil);
1268: }
1269:
1270: scroll_command (n, direction)
1271: Lisp_Object n;
1272: int direction;
1273: {
1274: register int defalt
1275: = direction * (window_height (selected_window) - 1
1276: - next_screen_context_lines);
1277:
1278: if (NULL (n))
1279: window_scroll (selected_window, defalt);
1280: else if (EQ (n, Qminus))
1281: window_scroll (selected_window, - defalt);
1282: else
1283: {
1284: n = Fprefix_numeric_value (n);
1285: window_scroll (selected_window, XINT (n) * direction);
1286: }
1287: }
1288:
1289: DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
1290: "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
1291: When calling from a program, supply a number as argument or nil.")
1292: (n)
1293: Lisp_Object n;
1294: {
1295: scroll_command (n, 1);
1296: return Qnil;
1297: }
1298:
1299: DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
1300: "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
1301: When calling from a program, supply a number as argument or nil.")
1302: (n)
1303: Lisp_Object n;
1304: {
1305: scroll_command (n, -1);
1306: return Qnil;
1307: }
1308:
1309: DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 1, 1, "P",
1310: "Scroll selected window display ARG columns left.\n\
1311: Default for ARG is window width minus 2.")
1312: (arg)
1313: Lisp_Object arg;
1314: {
1315: if (NULL (arg))
1316: XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2;
1317: else
1318: arg = Fprefix_numeric_value (arg);
1319:
1320: return Fset_window_hscroll (selected_window,
1321: make_number (XINT (XWINDOW (selected_window)->hscroll)
1322: + XINT (arg)));
1323: }
1324:
1325: DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 1, 1, "P",
1326: "Scroll selected window display ARG columns right.\n\
1327: Default for ARG is window width minus 2.")
1328: (arg)
1329: Lisp_Object arg;
1330: {
1331: if (NULL (arg))
1332: XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2;
1333: else
1334: arg = Fprefix_numeric_value (arg);
1335:
1336: return Fset_window_hscroll (selected_window,
1337: make_number (XINT (XWINDOW (selected_window)->hscroll)
1338: - XINT (arg)));
1339: }
1340:
1341: DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
1342: "Scroll text of next window upward ARG lines; or near full screen if no ARG.\n\
1343: The next window is the one below the current one; or the one at the top\n\
1344: if the current one is at the bottom.\n\
1345: When calling from a program, supply a number as argument or nil.")
1346: (n)
1347: Lisp_Object n;
1348: {
1349: Lisp_Object window;
1350: struct buffer *old = bf_cur;
1351: register int ht;
1352: register int opoint = point;
1353:
1354: window = Fnext_window (selected_window, Qnil);
1355: ht = window_height (window) - 1;
1356:
1357: if (EQ (window, selected_window))
1358: error ("There is no other window");
1359:
1360: Fset_buffer (XWINDOW (window)->buffer);
1361: SetPoint (marker_position (XWINDOW (window)->pointm));
1362:
1363: if (NULL (n))
1364: window_scroll (window, ht - next_screen_context_lines);
1365: else if (EQ (n, Qminus))
1366: window_scroll (window, next_screen_context_lines - ht);
1367: else
1368: {
1369: if (XTYPE (n) == Lisp_Cons)
1370: n = Fcar (n);
1371: CHECK_NUMBER (n, 0);
1372: window_scroll (window, XINT (n));
1373: }
1374:
1375: Fset_marker (XWINDOW (window)->pointm, make_number (point), Qnil);
1376: SetBfp (old);
1377: SetPoint (opoint);
1378: return Qnil;
1379: }
1380:
1381: DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
1382: "Center point in window and redisplay screen. With ARG, put point on line ARG.\n\
1383: The desired position of point is always relative to the current window.\n\
1384: If there is no ARG (i.e., it is nil) then the entire screen is redisplayed.")
1385: (n)
1386: Lisp_Object n;
1387: {
1388: int ht = window_height (selected_window)
1389: - !EQ (selected_window, minibuf_window);
1390: struct window *w = XWINDOW (selected_window);
1391: register int opoint = point;
1392:
1393: if (NULL (n))
1394: {
1395: extern int screen_garbaged;
1396: screen_garbaged++;
1397: XFASTINT (n) = ht / 2;
1398: }
1399: else
1400: {
1401: n = Fprefix_numeric_value (n);
1402: CHECK_NUMBER (n, 0);
1403: }
1404:
1405: if (XINT (n) < 0)
1406: XSETINT (n, XINT (n) + ht);
1407:
1408: XSETINT (n, - XINT (n));
1409:
1410: Fvertical_motion (n);
1411: Fset_marker (w->start, make_number (point), w->buffer);
1412:
1413: SetPoint (opoint);
1414: w->force_start = Qt;
1415:
1416: return Qnil;
1417: }
1418:
1419: DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
1420: 1, 1, "P",
1421: "Position point relative to window.\n\
1422: With no argument, position at text at center of window.\n\
1423: An argument specifies screen line; zero means top of window,\n\
1424: negative means relative to bottom of window.")
1425: (arg)
1426: Lisp_Object arg;
1427: {
1428: register struct window *w = XWINDOW (selected_window);
1429: int height = XFASTINT (w->height);
1430: register int start;
1431:
1432: if (!EQ (selected_window, minibuf_window)) height--;
1433:
1434: if (NULL (arg))
1435: XFASTINT (arg) = height / 2;
1436: else
1437: {
1438: arg = Fprefix_numeric_value (arg);
1439: if (XINT (arg) < 0)
1440: XSETINT (arg, XINT (arg) + height);
1441: }
1442:
1443: start = marker_position (w->start);
1444: if (start < FirstCharacter || start > NumCharacters + 1)
1445: {
1446: Fvertical_motion (make_number (- height / 2));
1447: Fset_marker (w->start, make_number (point), w->buffer);
1448: w->force_start = Qt;
1449: start = point;
1450: }
1451: else
1452: SetPoint (start);
1453:
1454: return Fvertical_motion (arg);
1455: }
1456:
1457: struct saved_window
1458: {
1459: Lisp_Object window;
1460: Lisp_Object buffer, start, pointm, mark;
1461: Lisp_Object left, top, width, height, hscroll;
1462: Lisp_Object parent, prev;
1463: };
1464:
1465: struct save_window_data
1466: {
1467: long size;
1468: struct Lisp_Vector *unused;
1469: Lisp_Object nsaved;
1470: Lisp_Object current_window;
1471: Lisp_Object current_buffer;
1472: struct saved_window info[1];
1473: };
1474:
1475: Lisp_Object
1476: save_window_restore (arg)
1477: Lisp_Object arg;
1478: {
1479: register struct window *w;
1480: register struct save_window_data *data = (struct save_window_data *) XINTPTR (arg);
1481: register struct saved_window *p = data->info;
1482: Lisp_Object tem;
1483: register int k;
1484:
1485: windows_or_buffers_changed++;
1486: for (k = 0; k < XFASTINT (data->nsaved); k++, p++)
1487: {
1488: w = XWINDOW (p->window);
1489: w->next = Qnil;
1490:
1491: if (!NULL (p->parent))
1492: w->parent = data->info[XFASTINT (p->parent)].window;
1493: else
1494: w->parent = Qnil;
1495:
1496: if (!NULL (p->prev))
1497: {
1498: w->prev = data->info[XFASTINT (p->prev)].window;
1499: XWINDOW (w->prev)->next = p->window;
1500: }
1501: else
1502: {
1503: w->prev = Qnil;
1504: if (!NULL (w->parent))
1505: {
1506: if (EQ (p->width, XWINDOW (w->parent)->width))
1507: {
1508: XWINDOW (w->parent)->vchild = p->window;
1509: XWINDOW (w->parent)->hchild = Qnil;
1510: }
1511: else
1512: {
1513: XWINDOW (w->parent)->hchild = p->window;
1514: XWINDOW (w->parent)->vchild = Qnil;
1515: }
1516: }
1517: }
1518: w->left = p->left;
1519: w->top = p->top;
1520: w->width = p->width;
1521: w->height = p->height;
1522: w->hscroll = p->hscroll;
1523: XFASTINT (w->last_modified) = 0;
1524:
1525: /* Reinstall the saved buffer and pointers into it. */
1526: if (NULL (p->buffer))
1527: w->buffer = p->buffer;
1528: else
1529: {
1530: if (!NULL (XBUFFER (p->buffer)->name))
1531: /* If saved buffer is alive, install it. */
1532: {
1533: w->buffer = p->buffer;
1534: Fset_marker (w->start, Fmarker_position (p->start), w->buffer);
1535: Fset_marker (w->pointm, Fmarker_position (p->pointm), w->buffer);
1536: }
1537: else if (NULL (XBUFFER (w->buffer)->name))
1538: /* Else if window's old buffer is dead too, get a live one. */
1539: {
1540: w->buffer = Fcdr (Fcar (Vbuffer_alist));
1541: /* Set window markers at start of buffer.
1542: Rely on Fset_marker to put them within the restriction. */
1543: Fset_marker (w->start, make_number (0), w->buffer);
1544: Fset_marker (w->pointm, make_number (0), w->buffer);
1545: }
1546: unchain_marker (p->start);
1547: unchain_marker (p->pointm);
1548:
1549: tem = p->mark;
1550: if (NULL (tem))
1551: XBUFFER (w->buffer)->mark = Qnil;
1552: else
1553: {
1554: if (NULL (XBUFFER (w->buffer)->mark))
1555: XBUFFER (w->buffer)->mark = Fmake_marker ();
1556:
1557: Fset_marker (XBUFFER (w->buffer)->mark,
1558: Fmarker_position (p->mark), w->buffer);
1559: unchain_marker (p->mark);
1560: }
1561: }
1562: }
1563:
1564: Fselect_window (data->current_window);
1565: Fset_buffer (data->current_buffer);
1566:
1567: free (data);
1568: return Qnil;
1569: }
1570:
1571: count_windows (window)
1572: struct window *window;
1573: {
1574: int count = 1;
1575: if (!NULL (window->next))
1576: count += count_windows (XWINDOW (window->next));
1577: if (!NULL (window->vchild))
1578: count += count_windows (XWINDOW (window->vchild));
1579: if (!NULL (window->hchild))
1580: count += count_windows (XWINDOW (window->hchild));
1581: return count;
1582: }
1583:
1584: #define SAVE_DATA_SIZE(n_windows) \
1585: ((n_windows - 1) * sizeof (struct saved_window) \
1586: + sizeof (struct save_window_data))
1587:
1588: Lisp_Object
1589: save_window_save ()
1590: {
1591: Lisp_Object root;
1592: int n_windows;
1593: struct save_window_data *data;
1594: Lisp_Object tem;
1595: int size;
1596:
1597: root = XWINDOW (minibuf_window)->prev;
1598: n_windows = count_windows (XWINDOW (root));
1599:
1600: size = SAVE_DATA_SIZE (n_windows);
1601: data = (struct save_window_data *) xmalloc (size);
1602:
1603: data->size = (size - sizeof (long) - sizeof (struct Lisp_Vector *))
1604: / sizeof (Lisp_Object);
1605: XFASTINT (data->nsaved) = n_windows;
1606: data->current_window = selected_window;
1607: XSET (data->current_buffer, Lisp_Buffer, bf_cur);
1608:
1609: save_window_save_1 (root, data, 0);
1610:
1611: XSET (tem, Lisp_Temp_Vector, data);
1612: return tem;
1613: }
1614:
1615: save_window_save_1 (window, data, i)
1616: Lisp_Object window;
1617: struct save_window_data *data;
1618: int i;
1619: {
1620: struct saved_window *p;
1621: struct window *w;
1622: Lisp_Object tem;
1623:
1624: for (;!NULL (window); window = w->next)
1625: {
1626: p = &data->info[i];
1627: w = XWINDOW (window);
1628:
1629: XFASTINT (w->temslot) = i++;
1630: p->window = window;
1631: p->buffer = w->buffer;
1632: p->left = w->left;
1633: p->top = w->top;
1634: p->width = w->width;
1635: p->height = w->height;
1636: p->hscroll = w->hscroll;
1637: if (!NULL (w->buffer))
1638: {
1639: if (EQ (window, selected_window)
1640: && XBUFFER (w->buffer) == bf_cur)
1641: p->pointm = Fpoint_marker ();
1642: else
1643: p->pointm = Fcopy_marker (w->pointm);
1644:
1645: p->start = Fcopy_marker (w->start);
1646:
1647: tem = XBUFFER (w->buffer)->mark;
1648: if (!NULL (tem))
1649: p->mark = Fcopy_marker (tem);
1650: else
1651: p->mark = Qnil;
1652: }
1653: else
1654: {
1655: p->pointm = Qnil;
1656: p->start = Qnil;
1657: p->mark = Qnil;
1658: }
1659:
1660: if (NULL (w->parent))
1661: p->parent = Qnil;
1662: else
1663: p->parent = XWINDOW (w->parent)->temslot;
1664:
1665: if (NULL (w->prev))
1666: p->prev = Qnil;
1667: else
1668: p->prev = XWINDOW (w->prev)->temslot;
1669:
1670: if (!NULL (w->vchild))
1671: i = save_window_save_1 (w->vchild, data, i);
1672: if (!NULL (w->hchild))
1673: i = save_window_save_1 (w->hchild, data, i);
1674: }
1675:
1676: return i;
1677: }
1678:
1679: DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
1680: 0, UNEVALLED, 0,
1681: "Execute body, preserving window sizes and contents.\n\
1682: Restores which buffer appears in which window, where display starts,\n\
1683: as well as the current buffer.\n\
1684: Does not restore the value of point in that buffer.")
1685: (args)
1686: Lisp_Object args;
1687: {
1688: Lisp_Object tem, val;
1689: struct gcpro gcpro1;
1690: int count = specpdl_ptr - specpdl;
1691:
1692: tem = save_window_save ();
1693:
1694: GCPRO1 (*XOBJFWD (tem));
1695: gcpro1.nvars
1696: = SAVE_DATA_SIZE (XFASTINT (((struct save_window_data *) XINTPTR (tem))
1697: ->nsaved))
1698: / 4;
1699:
1700: record_unwind_protect (save_window_restore, tem);
1701: val = Fprogn (args);
1702: UNGCPRO;
1703: unbind_to (count);
1704: return val;
1705: }
1706:
1707: init_window_once ()
1708: {
1709: extern Lisp_Object get_minibuffer ();
1710: Lisp_Object root_window;
1711:
1712: root_window = make_window ();
1713: minibuf_window = make_window ();
1714:
1715: XWINDOW (root_window)->next = minibuf_window;
1716: XWINDOW (minibuf_window)->prev = root_window;
1717:
1718: /* These values 9 and 10 are arbitrary,
1719: just so that there is "something there."
1720: Correct values are put in in init_xdisp */
1721:
1722: XFASTINT (XWINDOW (root_window)->width) = 10;
1723: XFASTINT (XWINDOW (minibuf_window)->width) = 10;
1724:
1725: XFASTINT (XWINDOW (root_window)->height) = 9;
1726: XFASTINT (XWINDOW (minibuf_window)->top) = 9;
1727: XFASTINT (XWINDOW (minibuf_window)->height) = 1;
1728:
1729: Fshow_buffer (root_window, Fcurrent_buffer ());
1730: Fshow_buffer (minibuf_window, get_minibuffer (0));
1731:
1732: selected_window = root_window;
1733: }
1734:
1735: syms_of_window ()
1736: {
1737: Qwindowp = intern ("windowp");
1738: staticpro (&Qwindowp);
1739:
1740: /* Make sure all windows get marked */
1741: staticpro (&minibuf_window);
1742:
1743: DefBoolVar ("pop-up-windows", &pop_up_windows,
1744: "*Non-nil means display-buffer should make new windows.");
1745: pop_up_windows = 1;
1746:
1747: DefIntVar ("next-screen-context-lines", &next_screen_context_lines,
1748: "*Number of lines of continuity when scrolling by screenfuls.");
1749: next_screen_context_lines = 2;
1750:
1751: DefIntVar ("split-height-threshold", &split_height_threshold,
1752: "*display-buffer would prefer to split the largest window if this large.\n\
1753: If there is only one window, it is split regardless of this value.");
1754: split_height_threshold = 500;
1755:
1756: DefIntVar ("window-min-height", &window_min_height,
1757: "*Delete any window less than this tall (including its mode line).");
1758: window_min_height = 4;
1759:
1760: DefIntVar ("window-min-width", &window_min_width,
1761: "*Delete any window less than this wide.");
1762: window_min_width = 10;
1763:
1764: defsubr (&Sselected_window);
1765: defsubr (&Swindowp);
1766: defsubr (&Spos_visible_in_window_p);
1767: defsubr (&Swindow_buffer);
1768: defsubr (&Swindow_height);
1769: defsubr (&Swindow_width);
1770: defsubr (&Swindow_hscroll);
1771: defsubr (&Sset_window_hscroll);
1772: defsubr (&Swindow_edges);
1773: defsubr (&Swindow_point);
1774: defalias (&Swindow_point, "window-dot");
1775: defsubr (&Swindow_start);
1776: defsubr (&Sset_window_point);
1777: defalias (&Sset_window_point, "set-window-dot");
1778: defsubr (&Sset_window_start);
1779: defsubr (&Snext_window);
1780: defsubr (&Sprevious_window);
1781: defsubr (&Sother_window);
1782: defsubr (&Sget_lru_window);
1783: defsubr (&Sget_largest_window);
1784: defsubr (&Sget_buffer_window);
1785: defsubr (&Sdelete_other_windows);
1786: defsubr (&Sdelete_windows_on);
1787: defsubr (&Sreplace_buffer_in_windows);
1788: defsubr (&Sdelete_window);
1789: defsubr (&Sshow_buffer);
1790: defsubr (&Sselect_window);
1791: defsubr (&Sdisplay_buffer);
1792: defsubr (&Ssplit_window);
1793: defsubr (&Senlarge_window);
1794: defsubr (&Sshrink_window);
1795: defsubr (&Sscroll_up);
1796: defsubr (&Sscroll_down);
1797: defsubr (&Sscroll_left);
1798: defsubr (&Sscroll_right);
1799: defsubr (&Sscroll_other_window);
1800: defsubr (&Srecenter);
1801: defsubr (&Smove_to_window_line);
1802: defsubr (&Ssave_window_excursion);
1803: }
1804:
1805: keys_of_window ()
1806: {
1807: defkey (CtlXmap, '1', "delete-other-windows");
1808: defkey (CtlXmap, '2', "split-window");
1809: defkey (CtlXmap, '0', "delete-window");
1810: defkey (CtlXmap, 'o', "other-window");
1811: defkey (CtlXmap, '^', "enlarge-window");
1812: defkey (CtlXmap, '<', "scroll-left");
1813: defkey (CtlXmap, '>', "scroll-right");
1814:
1815: defkey (GlobalMap, Ctl ('V'), "scroll-up");
1816: defkey (ESCmap, Ctl ('V'), "scroll-other-window");
1817: defkey (ESCmap, 'v', "scroll-down");
1818:
1819: defkey (GlobalMap, Ctl('L'), "recenter");
1820: defkey (ESCmap, 'r', "move-to-window-line");
1821: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.