diff options
| author | Gerd Moellmann | 2000-07-04 18:58:02 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2000-07-04 18:58:02 +0000 |
| commit | 6749220013111f1e6deba841c451830d5148ff8a (patch) | |
| tree | f995dd3158da516a6a16a339878d7d892e389ba2 /src/window.c | |
| parent | 75816372d2c8a375c0986d692e03739b4d3db4fe (diff) | |
| download | emacs-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.c | 641 |
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)); | |||
| 62 | static int window_min_size_1 P_ ((struct window *, int)); | 62 | static int window_min_size_1 P_ ((struct window *, int)); |
| 63 | static int window_min_size P_ ((struct window *, int, int, int *)); | 63 | static int window_min_size P_ ((struct window *, int, int, int *)); |
| 64 | static void size_window P_ ((Lisp_Object, int, int, int)); | 64 | static void size_window P_ ((Lisp_Object, int, int, int)); |
| 65 | static void foreach_window_1 P_ ((struct window *, void (*fn) (), int, int, | 65 | static int foreach_window_1 P_ ((struct window *, int (*fn) (), int, int, |
| 66 | int, int)); | 66 | int, int, int, int, int, int, int)); |
| 67 | static void freeze_window_start P_ ((struct window *, int)); | 67 | static int freeze_window_start P_ ((struct window *, int)); |
| 68 | static int window_fixed_size_p P_ ((struct window *, int, int)); | 68 | static int window_fixed_size_p P_ ((struct window *, int, int)); |
| 69 | static void enlarge_window P_ ((Lisp_Object, int, int)); | 69 | static void enlarge_window P_ ((Lisp_Object, int, int)); |
| 70 | static Lisp_Object window_list P_ ((void)); | ||
| 71 | static int add_window_to_list P_ ((struct window *)); | ||
| 72 | static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); | ||
| 73 | static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object, | ||
| 74 | Lisp_Object, int)); | ||
| 75 | static 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 | ||
| 80 | Lisp_Object selected_window; | 88 | Lisp_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 | |||
| 94 | Lisp_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 | |||
| 612 | static int | ||
| 613 | check_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 | ||
| 596 | Lisp_Object | 647 | Lisp_Object |
| 597 | window_from_coordinates (frame, x, y, part, tool_bar_p) | 648 | window_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 | ||
| 635 | DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0, | 674 | DEFUN ("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 | |||
| 1186 | static int | ||
| 1187 | add_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 | |||
| 1201 | static Lisp_Object | ||
| 1202 | window_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 | |||
| 1231 | static int | ||
| 1232 | candidate_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 | |||
| 1276 | static void | ||
| 1277 | decode_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 | |||
| 1323 | static Lisp_Object | ||
| 1324 | next_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 | ||
| 1138 | extern 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\ | |||
| 1172 | DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0, | 1420 | DEFUN ("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\ | |||
| 1316 | DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0, | 1462 | DEFUN ("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 | |||
| 1441 | DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p", | 1471 | DEFUN ("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\ |
| 1443 | All windows on current frame are arranged in a cyclic order.\n\ | 1473 | All 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\ | |||
| 1445 | A negative ARG moves in the opposite order. If the optional second\n\ | 1475 | A negative ARG moves in the opposite order. If the optional second\n\ |
| 1446 | argument ALL_FRAMES is non-nil, cycle through all frames.") | 1476 | argument 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 | |||
| 1496 | DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0, | ||
| 1497 | "Return a list windows in canonical ordering.\n\ | ||
| 1498 | Arguments 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 | ||
| 5035 | void | 5080 | void |
| 5036 | foreach_window (f, fn, a1, a2, a3, a4) | 5081 | foreach_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 | ||
| 5049 | static void | 5096 | static int |
| 5050 | foreach_window_1 (w, fn, a1, a2, a3, a4) | 5097 | foreach_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 | ||
| 5073 | static void | 5126 | static int |
| 5074 | freeze_window_start (w, freeze_p) | 5127 | freeze_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 | ||
| 5236 | void | 5290 | void |
| 5291 | init_window () | ||
| 5292 | { | ||
| 5293 | Vwindow_list = Qnil; | ||
| 5294 | } | ||
| 5295 | |||
| 5296 | void | ||
| 5237 | syms_of_window () | 5297 | syms_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\ |
| 5265 | The function is called with one argument, the buffer to be displayed.\n\ | 5327 | The 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 | ||
| 5472 | void | 5535 | void |