aboutsummaryrefslogtreecommitdiffstats
path: root/src/window.c
diff options
context:
space:
mode:
authorGerd Moellmann2000-07-04 18:58:02 +0000
committerGerd Moellmann2000-07-04 18:58:02 +0000
commit6749220013111f1e6deba841c451830d5148ff8a (patch)
treef995dd3158da516a6a16a339878d7d892e389ba2 /src/window.c
parent75816372d2c8a375c0986d692e03739b4d3db4fe (diff)
downloademacs-6749220013111f1e6deba841c451830d5148ff8a.tar.gz
emacs-6749220013111f1e6deba841c451830d5148ff8a.zip
(Vwindow_list): New variable.
(make_window, delete_window): Set Vwindow_list to nil. (check_window_containing): New function. (window_from_coordinates): Rewritten. (add_window_to_list, window_list, candidate_window_p) (decode_next_window_args, next_window): New functions. (Fnext_window, Fprevious_window): Rewritten in terms of next_window. (Fwindow_list): New function. (Fother_window): Cleaned up. (foreach_window): Add a longer "variable argument list". Let callback function return 0 to indicate that cycling over windows should stop. (foreach_window_1): Likewise. (freeze_window_start): Return int. (init_window): New function. (syms_of_window): Staticpro Vwindow_list and defsubr Swindow_list.
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c641
1 files changed, 352 insertions, 289 deletions
diff --git a/src/window.c b/src/window.c
index 1289d18679b..81662b5204b 100644
--- a/src/window.c
+++ b/src/window.c
@@ -62,11 +62,19 @@ static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
62static int window_min_size_1 P_ ((struct window *, int)); 62static int window_min_size_1 P_ ((struct window *, int));
63static int window_min_size P_ ((struct window *, int, int, int *)); 63static int window_min_size P_ ((struct window *, int, int, int *));
64static void size_window P_ ((Lisp_Object, int, int, int)); 64static void size_window P_ ((Lisp_Object, int, int, int));
65static void foreach_window_1 P_ ((struct window *, void (*fn) (), int, int, 65static int foreach_window_1 P_ ((struct window *, int (*fn) (), int, int,
66 int, int)); 66 int, int, int, int, int, int, int));
67static void freeze_window_start P_ ((struct window *, int)); 67static int freeze_window_start P_ ((struct window *, int));
68static int window_fixed_size_p P_ ((struct window *, int, int)); 68static int window_fixed_size_p P_ ((struct window *, int, int));
69static void enlarge_window P_ ((Lisp_Object, int, int)); 69static void enlarge_window P_ ((Lisp_Object, int, int));
70static Lisp_Object window_list P_ ((void));
71static int add_window_to_list P_ ((struct window *));
72static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
73static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
74 Lisp_Object, int));
75static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
76 Lisp_Object *));
77
70 78
71 79
72/* This is the window in which the terminal's cursor should 80/* This is the window in which the terminal's cursor should
@@ -79,6 +87,12 @@ static void enlarge_window P_ ((Lisp_Object, int, int));
79 87
80Lisp_Object selected_window; 88Lisp_Object selected_window;
81 89
90/* A list of all windows for use by next_window and Fwindow_list.
91 Functions creating or deleting windows should invalidate this cache
92 by setting it to nil. */
93
94Lisp_Object Vwindow_list;
95
82/* The mini-buffer window of the selected frame. 96/* The mini-buffer window of the selected frame.
83 Note that you cannot test for mini-bufferness of an arbitrary window 97 Note that you cannot test for mini-bufferness of an arbitrary window
84 by comparing against this; but you can test for mini-bufferness of 98 by comparing against this; but you can test for mini-bufferness of
@@ -238,6 +252,8 @@ make_window ()
238 XSETWINDOW (val, p); 252 XSETWINDOW (val, p);
239 XSETFASTINT (p->last_point, 0); 253 XSETFASTINT (p->last_point, 0);
240 p->frozen_window_start_p = 0; 254 p->frozen_window_start_p = 0;
255
256 Vwindow_list = Qnil;
241 return val; 257 return val;
242} 258}
243 259
@@ -586,50 +602,73 @@ If they are on the border between WINDOW and its right sibling,\n\
586 } 602 }
587} 603}
588 604
605
606/* Callback for foreach_window, used in window_from_coordinates.
607 Check if window W contains coordinates *X/*Y. If it does, return W
608 in *WINDOW, as Lisp_Object, and return in *PART the part of the
609 window under coordinates *X/*Y. Return zero from this function to
610 stop iterating over windows. */
611
612static int
613check_window_containing (w, window, x, y, part)
614 struct window *w;
615 Lisp_Object *window;
616 int *x, *y, *part;
617{
618 int found;
619
620 found = coordinates_in_window (w, x, y);
621 if (found)
622 {
623 *part = found - 1;
624 XSETWINDOW (*window, w);
625 }
626
627 return !found;
628}
629
630
589/* Find the window containing frame-relative pixel position X/Y and 631/* Find the window containing frame-relative pixel position X/Y and
590 return it as a Lisp_Object. If X, Y is on the window's modeline, 632 return it as a Lisp_Object. If X, Y is on the window's modeline,
591 set *PART to 1; if it is on the separating line between the window 633 set *PART to 1; if it is on the separating line between the window
592 and its right sibling, set it to 2; otherwise set it to 0. If 634 and its right sibling, set it to 2; otherwise set it to 0. If
593 there is no window under X, Y return nil and leave *PART 635 there is no window under X, Y return nil and leave *PART
594 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows. */ 636 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
637
638 This function was previously implemented with a loop cycling over
639 windows with Fnext_window, and starting with the frame's selected
640 window. It turned out that this doesn't work with an
641 implementation of next_window using Vwindow_list, because
642 FRAME_SELECTED_WINDOW (F) is not always contained in the window
643 tree of F when this function is called asynchronously from
644 note_mouse_highlight. The original loop didn't terminate in this
645 case. */
595 646
596Lisp_Object 647Lisp_Object
597window_from_coordinates (frame, x, y, part, tool_bar_p) 648window_from_coordinates (f, x, y, part, tool_bar_p)
598 FRAME_PTR frame; 649 struct frame *f;
599 int x, y; 650 int x, y;
600 int *part; 651 int *part;
601 int tool_bar_p; 652 int tool_bar_p;
602{ 653{
603 register Lisp_Object tem, first; 654 Lisp_Object window;
604 int found;
605
606 tem = first = FRAME_SELECTED_WINDOW (frame);
607
608 do
609 {
610 found = coordinates_in_window (XWINDOW (tem), &x, &y);
611
612 if (found)
613 {
614 *part = found - 1;
615 return tem;
616 }
617
618 tem = Fnext_window (tem, Qt, Qlambda);
619 }
620 while (!EQ (tem, first));
621 655
622 /* See if it's in the tool bar window, if a tool bar exists. */ 656 window = Qnil;
623 if (tool_bar_p 657 foreach_window (f, check_window_containing, &window, &x, &y, part);
624 && WINDOWP (frame->tool_bar_window) 658
625 && XFASTINT (XWINDOW (frame->tool_bar_window)->height) 659 /* If not found above, see if it's in the tool bar window, if a tool
626 && coordinates_in_window (XWINDOW (frame->tool_bar_window), &x, &y)) 660 bar exists. */
661 if (NILP (window)
662 && tool_bar_p
663 && WINDOWP (f->tool_bar_window)
664 && XINT (XWINDOW (f->tool_bar_window)->height) > 0
665 && coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y))
627 { 666 {
628 *part = 0; 667 *part = 0;
629 return frame->tool_bar_window; 668 window = f->tool_bar_window;
630 } 669 }
631 670
632 return Qnil; 671 return window;
633} 672}
634 673
635DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0, 674DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
@@ -1021,6 +1060,7 @@ delete_window (window)
1021 par = XWINDOW (parent); 1060 par = XWINDOW (parent);
1022 1061
1023 windows_or_buffers_changed++; 1062 windows_or_buffers_changed++;
1063 Vwindow_list = Qnil;
1024 frame = XFRAME (WINDOW_FRAME (p)); 1064 frame = XFRAME (WINDOW_FRAME (p));
1025 FRAME_WINDOW_SIZES_CHANGED (frame) = 1; 1065 FRAME_WINDOW_SIZES_CHANGED (frame) = 1;
1026 1066
@@ -1133,9 +1173,217 @@ delete_window (window)
1133 adjust_glyphs (frame); 1173 adjust_glyphs (frame);
1134 UNBLOCK_INPUT; 1174 UNBLOCK_INPUT;
1135} 1175}
1176
1177
1136 1178
1179/***********************************************************************
1180 Window List
1181 ***********************************************************************/
1182
1183/* Add window W to Vwindow_list. This is a callback function for
1184 foreach_window, used from window_list. */
1185
1186static int
1187add_window_to_list (w)
1188 struct window *w;
1189{
1190 Lisp_Object window;
1191 XSETWINDOW (window, w);
1192 Vwindow_list = Fcons (window, Vwindow_list);
1193 return 1;
1194}
1195
1196
1197/* Return a list of all windows, for use by next_window. If
1198 Vwindow_list is a list, return that list. Otherwise, build a new
1199 list, cache it in Vwindow_list, and return that. */
1200
1201static Lisp_Object
1202window_list ()
1203{
1204 if (!CONSP (Vwindow_list))
1205 {
1206 Lisp_Object tail;
1207 Vwindow_list = Qnil;
1208 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1209 foreach_window (XFRAME (XCAR (tail)), add_window_to_list);
1210 }
1211
1212 return Vwindow_list;
1213}
1214
1215
1216/* Value is non-zero if WINODW satisfies the constraints given by
1217 MINIBUF and ALL_FRAMES.
1218
1219 MINIBUF t means WINDOW may be a minibuffer window.
1220 MINIBUF `lambda' means it may not be a minibuffer window.
1221 MINIBUF being a window means WINDOW must be equal to MINIBUF.
1222
1223 ALL_FRAMES t means WINDOW may be on any frame.
1224 ALL_FRAMES nil means WINDOW must not be on a minibuffer-only frame.
1225 ALL_FRAMES `visible' means WINDOW must be on a visible frame.
1226 ALL_FRAMES 0 means WINDOW must be on a visible or iconified frame.
1227 ALL_FRAMES being a frame means WINDOW must be on that frame.
1228 ALL_FRAMES being a window means WINDOW must be on a frame using
1229 the same minibuffer as ALL_FRAMES. */
1230
1231static int
1232candidate_window_p (window, minibuf, all_frames)
1233 Lisp_Object window, minibuf, all_frames;
1234{
1235 struct window *w = XWINDOW (window);
1236 struct frame *f = XFRAME (w->frame);
1237 int candidate_p = 1;
1238
1239 if (!BUFFERP (w->buffer))
1240 candidate_p = 0;
1241 else if (MINI_WINDOW_P (w)
1242 && (EQ (minibuf, Qlambda)
1243 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1244 {
1245 /* If MINIBUF is `lambda' don't consider any mini-windows.
1246 If it is a window, consider only that one. */
1247 candidate_p = 0;
1248 }
1249 else if (NILP (all_frames))
1250 candidate_p = !FRAME_MINIBUF_ONLY_P (f);
1251 else if (EQ (all_frames, Qvisible))
1252 {
1253 FRAME_SAMPLE_VISIBILITY (f);
1254 candidate_p = FRAME_VISIBLE_P (f);
1255 }
1256 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1257 {
1258 FRAME_SAMPLE_VISIBILITY (f);
1259 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1260 }
1261 else if (FRAMEP (all_frames))
1262 candidate_p = EQ (all_frames, w->frame);
1263 else if (WINDOWP (all_frames))
1264 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1265 || EQ (XWINDOW (all_frames)->frame, w->frame)
1266 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1267
1268 return candidate_p;
1269}
1270
1271
1272/* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1273 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1274 ALL_FRAMES. */
1275
1276static void
1277decode_next_window_args (window, minibuf, all_frames)
1278 Lisp_Object *window, *minibuf, *all_frames;
1279{
1280 if (NILP (*window))
1281 *window = selected_window;
1282 else
1283 CHECK_LIVE_WINDOW (*window, 0);
1284
1285 /* MINIBUF nil may or may not include minibuffers. Decide if it
1286 does. */
1287 if (NILP (*minibuf))
1288 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1289 else if (!EQ (*minibuf, Qt))
1290 *minibuf = Qlambda;
1291
1292 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1293 => count none of them, or a specific minibuffer window (the
1294 active one) to count. */
1295
1296 /* ALL_FRAMES nil doesn't specify which frames to include. */
1297 if (NILP (*all_frames))
1298 *all_frames = (!EQ (*minibuf, Qlambda)
1299 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1300 : Qnil);
1301 else if (EQ (*all_frames, Qvisible))
1302 ;
1303 else if (XFASTINT (*all_frames) == 0)
1304 ;
1305 else if (FRAMEP (*all_frames))
1306 ;
1307 else if (!EQ (*all_frames, Qt))
1308 *all_frames = Qnil;
1309
1310 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1311 search just current frame, `visible' meaning search just visible
1312 frames, 0 meaning search visible and iconified frames, or a
1313 window, meaning search the frame that window belongs to, or a
1314 frame, meaning consider windows on that frame, only. */
1315}
1316
1317
1318/* Return the next or previous window of WINDOW in canonical ordering
1319 of windows. NEXT_P non-zero means return the next window. See the
1320 documentation string of next-window for the meaning of MINIBUF and
1321 ALL_FRAMES. */
1322
1323static Lisp_Object
1324next_window (window, minibuf, all_frames, next_p)
1325 Lisp_Object window, minibuf, all_frames;
1326 int next_p;
1327{
1328 decode_next_window_args (&window, &minibuf, &all_frames);
1329
1330 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1331 return the first window on the frame. */
1332 if (FRAMEP (all_frames)
1333 && !EQ (all_frames, XWINDOW (window)->frame))
1334 return Fframe_first_window (all_frames);
1335
1336 if (!next_p)
1337 {
1338 Lisp_Object list;
1339
1340 /* Find WINDOW in the list of all windows. */
1341 list = Fmemq (window, window_list ());
1342
1343 /* Scan forward from WINDOW to the end of the window list. */
1344 if (CONSP (list))
1345 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1346 if (candidate_window_p (XCAR (list), minibuf, all_frames))
1347 break;
1348
1349 /* Scan from the start of the window list up to WINDOW. */
1350 if (!CONSP (list))
1351 for (list = Vwindow_list;
1352 CONSP (list) && !EQ (XCAR (list), window);
1353 list = XCDR (list))
1354 if (candidate_window_p (XCAR (list), minibuf, all_frames))
1355 break;
1356
1357 if (CONSP (list))
1358 window = XCAR (list);
1359 }
1360 else
1361 {
1362 Lisp_Object candidate, list;
1363
1364 /* Scan through the list of windows for candidates. If there are
1365 candidate windows in front of WINDOW, the last one of these
1366 is the one we want. If there are candidates following WINDOW
1367 in the list, again the last one of these is the one we want. */
1368 candidate = Qnil;
1369 for (list = window_list (); CONSP (list); list = XCDR (list))
1370 {
1371 if (EQ (XCAR (list), window))
1372 {
1373 if (WINDOWP (candidate))
1374 break;
1375 }
1376 else if (candidate_window_p (XCAR (list), minibuf, all_frames))
1377 candidate = XCAR (list);
1378 }
1379
1380 if (WINDOWP (candidate))
1381 window = candidate;
1382 }
1383
1384 return window;
1385}
1137 1386
1138extern Lisp_Object next_frame (), prev_frame ();
1139 1387
1140/* This comment supplies the doc string for `next-window', 1388/* This comment supplies the doc string for `next-window',
1141 for make-docfile to see. We cannot put this in the real DEFUN 1389 for make-docfile to see. We cannot put this in the real DEFUN
@@ -1172,114 +1420,12 @@ windows, eventually ending up back at the window you started with.\n\
1172DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0, 1420DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1173 0) 1421 0)
1174 (window, minibuf, all_frames) 1422 (window, minibuf, all_frames)
1175 register Lisp_Object window, minibuf, all_frames; 1423 Lisp_Object window, minibuf, all_frames;
1176{ 1424{
1177 register Lisp_Object tem; 1425 return next_window (window, minibuf, all_frames, 1);
1178 Lisp_Object start_window;
1179
1180 if (NILP (window))
1181 window = selected_window;
1182 else
1183 CHECK_LIVE_WINDOW (window, 0);
1184
1185 start_window = window;
1186
1187 /* minibuf == nil may or may not include minibuffers.
1188 Decide if it does. */
1189 if (NILP (minibuf))
1190 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1191 else if (! EQ (minibuf, Qt))
1192 minibuf = Qlambda;
1193 /* Now minibuf can be t => count all minibuffer windows,
1194 lambda => count none of them,
1195 or a specific minibuffer window (the active one) to count. */
1196
1197 /* all_frames == nil doesn't specify which frames to include. */
1198 if (NILP (all_frames))
1199 all_frames = (! EQ (minibuf, Qlambda)
1200 ? (FRAME_MINIBUF_WINDOW
1201 (XFRAME
1202 (WINDOW_FRAME
1203 (XWINDOW (window)))))
1204 : Qnil);
1205 else if (EQ (all_frames, Qvisible))
1206 ;
1207 else if (XFASTINT (all_frames) == 0)
1208 ;
1209 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1210 /* If all_frames is a frame and window arg isn't on that frame, just
1211 return the first window on the frame. */
1212 return Fframe_first_window (all_frames);
1213 else if (! EQ (all_frames, Qt))
1214 all_frames = Qnil;
1215 /* Now all_frames is t meaning search all frames,
1216 nil meaning search just current frame,
1217 visible meaning search just visible frames,
1218 0 meaning search visible and iconified frames,
1219 or a window, meaning search the frame that window belongs to. */
1220
1221 /* Do this loop at least once, to get the next window, and perhaps
1222 again, if we hit the minibuffer and that is not acceptable. */
1223 do
1224 {
1225 /* Find a window that actually has a next one. This loop
1226 climbs up the tree. */
1227 while (tem = XWINDOW (window)->next, NILP (tem))
1228 if (tem = XWINDOW (window)->parent, !NILP (tem))
1229 window = tem;
1230 else
1231 {
1232 /* We've reached the end of this frame.
1233 Which other frames are acceptable? */
1234 tem = WINDOW_FRAME (XWINDOW (window));
1235 if (! NILP (all_frames))
1236 {
1237 Lisp_Object tem1;
1238
1239 tem1 = tem;
1240 tem = next_frame (tem, all_frames);
1241 /* In the case where the minibuffer is active,
1242 and we include its frame as well as the selected one,
1243 next_frame may get stuck in that frame.
1244 If that happens, go back to the selected frame
1245 so we can complete the cycle. */
1246 if (EQ (tem, tem1))
1247 tem = selected_frame;
1248 }
1249 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1250
1251 break;
1252 }
1253
1254 window = tem;
1255
1256 /* If we're in a combination window, find its first child and
1257 recurse on that. Otherwise, we've found the window we want. */
1258 while (1)
1259 {
1260 if (!NILP (XWINDOW (window)->hchild))
1261 window = XWINDOW (window)->hchild;
1262 else if (!NILP (XWINDOW (window)->vchild))
1263 window = XWINDOW (window)->vchild;
1264 else break;
1265 }
1266
1267 QUIT;
1268 }
1269 /* Which windows are acceptable?
1270 Exit the loop and accept this window if
1271 this isn't a minibuffer window,
1272 or we're accepting all minibuffer windows,
1273 or this is the active minibuffer and we are accepting that one, or
1274 we've come all the way around and we're back at the original window. */
1275 while (MINI_WINDOW_P (XWINDOW (window))
1276 && ! EQ (minibuf, Qt)
1277 && ! EQ (minibuf, window)
1278 && ! EQ (window, start_window));
1279
1280 return window;
1281} 1426}
1282 1427
1428
1283/* This comment supplies the doc string for `previous-window', 1429/* This comment supplies the doc string for `previous-window',
1284 for make-docfile to see. We cannot put this in the real DEFUN 1430 for make-docfile to see. We cannot put this in the real DEFUN
1285 due to limits in the Unix cpp. 1431 due to limits in the Unix cpp.
@@ -1316,128 +1462,12 @@ windows, eventually ending up back at the window you started with.\n\
1316DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0, 1462DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1317 0) 1463 0)
1318 (window, minibuf, all_frames) 1464 (window, minibuf, all_frames)
1319 register Lisp_Object window, minibuf, all_frames; 1465 Lisp_Object window, minibuf, all_frames;
1320{ 1466{
1321 register Lisp_Object tem; 1467 return next_window (window, minibuf, all_frames, 0);
1322 Lisp_Object start_window;
1323
1324 if (NILP (window))
1325 window = selected_window;
1326 else
1327 CHECK_LIVE_WINDOW (window, 0);
1328
1329 start_window = window;
1330
1331 /* minibuf == nil may or may not include minibuffers.
1332 Decide if it does. */
1333 if (NILP (minibuf))
1334 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1335 else if (! EQ (minibuf, Qt))
1336 minibuf = Qlambda;
1337 /* Now minibuf can be t => count all minibuffer windows,
1338 lambda => count none of them,
1339 or a specific minibuffer window (the active one) to count. */
1340
1341 /* all_frames == nil doesn't specify which frames to include.
1342 Decide which frames it includes. */
1343 if (NILP (all_frames))
1344 all_frames = (! EQ (minibuf, Qlambda)
1345 ? (FRAME_MINIBUF_WINDOW
1346 (XFRAME
1347 (WINDOW_FRAME
1348 (XWINDOW (window)))))
1349 : Qnil);
1350 else if (EQ (all_frames, Qvisible))
1351 ;
1352 else if (XFASTINT (all_frames) == 0)
1353 ;
1354 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1355 /* If all_frames is a frame and window arg isn't on that frame, just
1356 return the first window on the frame. */
1357 return Fframe_first_window (all_frames);
1358 else if (! EQ (all_frames, Qt))
1359 all_frames = Qnil;
1360 /* Now all_frames is t meaning search all frames,
1361 nil meaning search just current frame,
1362 visible meaning search just visible frames,
1363 0 meaning search visible and iconified frames,
1364 or a window, meaning search the frame that window belongs to. */
1365
1366 /* Do this loop at least once, to get the previous window, and perhaps
1367 again, if we hit the minibuffer and that is not acceptable. */
1368 do
1369 {
1370 /* Find a window that actually has a previous one. This loop
1371 climbs up the tree. */
1372 while (tem = XWINDOW (window)->prev, NILP (tem))
1373 if (tem = XWINDOW (window)->parent, !NILP (tem))
1374 window = tem;
1375 else
1376 {
1377 /* We have found the top window on the frame.
1378 Which frames are acceptable? */
1379 tem = WINDOW_FRAME (XWINDOW (window));
1380 if (! NILP (all_frames))
1381 /* It's actually important that we use prev_frame here,
1382 rather than next_frame. All the windows acceptable
1383 according to the given parameters should form a ring;
1384 Fnext_window and Fprevious_window should go back and
1385 forth around the ring. If we use next_frame here,
1386 then Fnext_window and Fprevious_window take different
1387 paths through the set of acceptable windows.
1388 window_loop assumes that these `ring' requirement are
1389 met. */
1390 {
1391 Lisp_Object tem1;
1392
1393 tem1 = tem;
1394 tem = prev_frame (tem, all_frames);
1395 /* In the case where the minibuffer is active,
1396 and we include its frame as well as the selected one,
1397 next_frame may get stuck in that frame.
1398 If that happens, go back to the selected frame
1399 so we can complete the cycle. */
1400 if (EQ (tem, tem1))
1401 tem = selected_frame;
1402 }
1403 /* If this frame has a minibuffer, find that window first,
1404 because it is conceptually the last window in that frame. */
1405 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1406 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1407 else
1408 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1409
1410 break;
1411 }
1412
1413 window = tem;
1414 /* If we're in a combination window, find its last child and
1415 recurse on that. Otherwise, we've found the window we want. */
1416 while (1)
1417 {
1418 if (!NILP (XWINDOW (window)->hchild))
1419 window = XWINDOW (window)->hchild;
1420 else if (!NILP (XWINDOW (window)->vchild))
1421 window = XWINDOW (window)->vchild;
1422 else break;
1423 while (tem = XWINDOW (window)->next, !NILP (tem))
1424 window = tem;
1425 }
1426 }
1427 /* Which windows are acceptable?
1428 Exit the loop and accept this window if
1429 this isn't a minibuffer window,
1430 or we're accepting all minibuffer windows,
1431 or this is the active minibuffer and we are accepting that one, or
1432 we've come all the way around and we're back at the original window. */
1433 while (MINI_WINDOW_P (XWINDOW (window))
1434 && ! EQ (minibuf, Qt)
1435 && ! EQ (minibuf, window)
1436 && ! EQ (window, start_window));
1437
1438 return window;
1439} 1468}
1440 1469
1470
1441DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p", 1471DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1442 "Select the ARG'th different window on this frame.\n\ 1472 "Select the ARG'th different window on this frame.\n\
1443All windows on current frame are arranged in a cyclic order.\n\ 1473All windows on current frame are arranged in a cyclic order.\n\
@@ -1445,28 +1475,43 @@ This command selects the window ARG steps away in that order.\n\
1445A negative ARG moves in the opposite order. If the optional second\n\ 1475A negative ARG moves in the opposite order. If the optional second\n\
1446argument ALL_FRAMES is non-nil, cycle through all frames.") 1476argument ALL_FRAMES is non-nil, cycle through all frames.")
1447 (arg, all_frames) 1477 (arg, all_frames)
1448 register Lisp_Object arg, all_frames; 1478 Lisp_Object arg, all_frames;
1449{ 1479{
1450 register int i; 1480 Lisp_Object window;
1451 register Lisp_Object w; 1481 int i;
1452 1482
1453 CHECK_NUMBER (arg, 0); 1483 CHECK_NUMBER (arg, 0);
1454 w = selected_window; 1484 window = selected_window;
1455 i = XINT (arg); 1485
1456 1486 for (i = XINT (arg); i > 0; --i)
1457 while (i > 0) 1487 window = Fnext_window (window, Qnil, all_frames);
1458 { 1488 for (; i < 0; ++i)
1459 w = Fnext_window (w, Qnil, all_frames); 1489 window = Fprevious_window (window, Qnil, all_frames);
1460 i--; 1490
1461 } 1491 Fselect_window (window);
1462 while (i < 0)
1463 {
1464 w = Fprevious_window (w, Qnil, all_frames);
1465 i++;
1466 }
1467 Fselect_window (w);
1468 return Qnil; 1492 return Qnil;
1469} 1493}
1494
1495
1496DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1497 "Return a list windows in canonical ordering.\n\
1498Arguments are like for `next-window'.")
1499 (window, minibuf, all_frames)
1500 Lisp_Object minibuf, all_frames;
1501{
1502 Lisp_Object tail, list;
1503
1504 decode_next_window_args (&window, &minibuf, &all_frames);
1505 list = Qnil;
1506
1507 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1508 if (candidate_window_p (XCAR (tail), minibuf, all_frames))
1509 list = Fcons (XCAR (tail), list);
1510
1511 return list;
1512}
1513
1514
1470 1515
1471/* Look at all windows, performing an operation specified by TYPE 1516/* Look at all windows, performing an operation specified by TYPE
1472 with argument OBJ. 1517 with argument OBJ.
@@ -5030,39 +5075,47 @@ non-negative multiple of the canonical character height of WINDOW.")
5030 5075
5031/* Call FN for all leaf windows on frame F. FN is called with the 5076/* Call FN for all leaf windows on frame F. FN is called with the
5032 first argument being a pointer to the leaf window, and with 5077 first argument being a pointer to the leaf window, and with
5033 additional arguments A1..A4. */ 5078 additional arguments A1..A9. Stops when FN returns 0. */
5034 5079
5035void 5080void
5036foreach_window (f, fn, a1, a2, a3, a4) 5081foreach_window (f, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
5037 struct frame *f; 5082 struct frame *f;
5038 void (* fn) (); 5083 int (* fn) ();
5039 int a1, a2, a3, a4; 5084 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
5040{ 5085{
5041 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, a1, a2, a3, a4); 5086 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)),
5087 fn, a1, a2, a3, a4, a5, a6, a7, a8, a9);
5042} 5088}
5043 5089
5044 5090
5045/* Helper function for foreach_window. Call FN for all leaf windows 5091/* Helper function for foreach_window. Call FN for all leaf windows
5046 reachable from W. FN is called with the first argument being a 5092 reachable from W. FN is called with the first argument being a
5047 pointer to the leaf window, and with additional arguments A1..A4. */ 5093 pointer to the leaf window, and with additional arguments A1..A9.
5094 Stop when FN returns 0. Value is 0 if stopped by FN. */
5048 5095
5049static void 5096static int
5050foreach_window_1 (w, fn, a1, a2, a3, a4) 5097foreach_window_1 (w, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
5051 struct window *w; 5098 struct window *w;
5052 void (* fn) (); 5099 int (* fn) ();
5053 int a1, a2, a3, a4; 5100 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
5054{ 5101{
5055 while (w) 5102 int cont;
5103
5104 for (cont = 1; w && cont;)
5056 { 5105 {
5057 if (!NILP (w->hchild)) 5106 if (!NILP (w->hchild))
5058 foreach_window_1 (XWINDOW (w->hchild), fn, a1, a2, a3, a4); 5107 cont = foreach_window_1 (XWINDOW (w->hchild),
5108 fn, a1, a2, a3, a4, a5, a6, a7, a8, a9);
5059 else if (!NILP (w->vchild)) 5109 else if (!NILP (w->vchild))
5060 foreach_window_1 (XWINDOW (w->vchild), fn, a1, a2, a3, a4); 5110 cont = foreach_window_1 (XWINDOW (w->vchild),
5061 else 5111 fn, a1, a2, a3, a4, a5, a6, a7, a8, a9);
5062 fn (w, a1, a2, a3, a4); 5112 else if (fn (w, a1, a2, a3, a4, a5, a6, a7, a8, a9) == 0)
5113 cont = 0;
5063 5114
5064 w = NILP (w->next) ? 0 : XWINDOW (w->next); 5115 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5065 } 5116 }
5117
5118 return cont;
5066} 5119}
5067 5120
5068 5121
@@ -5070,7 +5123,7 @@ foreach_window_1 (w, fn, a1, a2, a3, a4)
5070 mini-window or the selected window. FREEZE_P non-zero means freeze 5123 mini-window or the selected window. FREEZE_P non-zero means freeze
5071 the window start. */ 5124 the window start. */
5072 5125
5073static void 5126static int
5074freeze_window_start (w, freeze_p) 5127freeze_window_start (w, freeze_p)
5075 struct window *w; 5128 struct window *w;
5076 int freeze_p; 5129 int freeze_p;
@@ -5083,6 +5136,7 @@ freeze_window_start (w, freeze_p)
5083 freeze_p = 0; 5136 freeze_p = 0;
5084 5137
5085 w->frozen_window_start_p = freeze_p; 5138 w->frozen_window_start_p = freeze_p;
5139 return 1;
5086} 5140}
5087 5141
5088 5142
@@ -5234,6 +5288,12 @@ init_window_once ()
5234} 5288}
5235 5289
5236void 5290void
5291init_window ()
5292{
5293 Vwindow_list = Qnil;
5294}
5295
5296void
5237syms_of_window () 5297syms_of_window ()
5238{ 5298{
5239 Qleft_bitmap_area = intern ("left-bitmap-area"); 5299 Qleft_bitmap_area = intern ("left-bitmap-area");
@@ -5260,6 +5320,8 @@ syms_of_window ()
5260 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook"); 5320 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
5261 staticpro (&Qtemp_buffer_show_hook); 5321 staticpro (&Qtemp_buffer_show_hook);
5262 5322
5323 staticpro (&Vwindow_list);
5324
5263 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function, 5325 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
5264 "Non-nil means call as function to display a help buffer.\n\ 5326 "Non-nil means call as function to display a help buffer.\n\
5265The function is called with one argument, the buffer to be displayed.\n\ 5327The function is called with one argument, the buffer to be displayed.\n\
@@ -5467,6 +5529,7 @@ The selected frame is the one whose configuration has changed.");
5467 defsubr (&Swindow_vscroll); 5529 defsubr (&Swindow_vscroll);
5468 defsubr (&Sset_window_vscroll); 5530 defsubr (&Sset_window_vscroll);
5469 defsubr (&Scompare_window_configurations); 5531 defsubr (&Scompare_window_configurations);
5532 defsubr (&Swindow_list);
5470} 5533}
5471 5534
5472void 5535void