Mercurial > vim
comparison src/buffer.c @ 5586:505cf1943dc2 v7.4.140
updated for version 7.4.140
Problem: Crash when wiping out buffer triggers autocommand that wipes out
only other buffer.
Solution: Do not delete the last buffer, make it empty. (Hirohito Higashi)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Fri, 10 Jan 2014 16:43:14 +0100 |
parents | d0595545e98a |
children | 06e5f65c34d8 |
comparison
equal
deleted
inserted
replaced
5585:8ce54730f806 | 5586:505cf1943dc2 |
---|---|
992 #endif /* FEAT_LISTCMDS */ | 992 #endif /* FEAT_LISTCMDS */ |
993 | 993 |
994 #if defined(FEAT_LISTCMDS) || defined(FEAT_PYTHON) \ | 994 #if defined(FEAT_LISTCMDS) || defined(FEAT_PYTHON) \ |
995 || defined(FEAT_PYTHON3) || defined(PROTO) | 995 || defined(FEAT_PYTHON3) || defined(PROTO) |
996 | 996 |
997 static int empty_curbuf __ARGS((int close_others, int forceit, int action)); | |
998 | |
999 /* | |
1000 * Make the current buffer empty. | |
1001 * Used when it is wiped out and it's the last buffer. | |
1002 */ | |
1003 static int | |
1004 empty_curbuf(close_others, forceit, action) | |
1005 int close_others; | |
1006 int forceit; | |
1007 int action; | |
1008 { | |
1009 int retval; | |
1010 buf_T *buf = curbuf; | |
1011 | |
1012 if (action == DOBUF_UNLOAD) | |
1013 { | |
1014 EMSG(_("E90: Cannot unload last buffer")); | |
1015 return FAIL; | |
1016 } | |
1017 | |
1018 if (close_others) | |
1019 { | |
1020 /* Close any other windows on this buffer, then make it empty. */ | |
1021 #ifdef FEAT_WINDOWS | |
1022 close_windows(buf, TRUE); | |
1023 #endif | |
1024 } | |
1025 | |
1026 setpcmark(); | |
1027 retval = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, | |
1028 forceit ? ECMD_FORCEIT : 0, curwin); | |
1029 | |
1030 /* | |
1031 * do_ecmd() may create a new buffer, then we have to delete | |
1032 * the old one. But do_ecmd() may have done that already, check | |
1033 * if the buffer still exists. | |
1034 */ | |
1035 if (buf != curbuf && buf_valid(buf) && buf->b_nwindows == 0) | |
1036 close_buffer(NULL, buf, action, FALSE); | |
1037 if (!close_others) | |
1038 need_fileinfo = FALSE; | |
1039 return retval; | |
1040 } | |
997 /* | 1041 /* |
998 * Implementation of the commands for the buffer list. | 1042 * Implementation of the commands for the buffer list. |
999 * | 1043 * |
1000 * action == DOBUF_GOTO go to specified buffer | 1044 * action == DOBUF_GOTO go to specified buffer |
1001 * action == DOBUF_SPLIT split window and go to specified buffer | 1045 * action == DOBUF_SPLIT split window and go to specified buffer |
1112 * delete buffer buf from memory and/or the list | 1156 * delete buffer buf from memory and/or the list |
1113 */ | 1157 */ |
1114 if (unload) | 1158 if (unload) |
1115 { | 1159 { |
1116 int forward; | 1160 int forward; |
1117 int retval; | |
1118 | 1161 |
1119 /* When unloading or deleting a buffer that's already unloaded and | 1162 /* When unloading or deleting a buffer that's already unloaded and |
1120 * unlisted: fail silently. */ | 1163 * unlisted: fail silently. */ |
1121 if (action != DOBUF_WIPE && buf->b_ml.ml_mfp == NULL && !buf->b_p_bl) | 1164 if (action != DOBUF_WIPE && buf->b_ml.ml_mfp == NULL && !buf->b_p_bl) |
1122 return FAIL; | 1165 return FAIL; |
1153 */ | 1196 */ |
1154 for (bp = firstbuf; bp != NULL; bp = bp->b_next) | 1197 for (bp = firstbuf; bp != NULL; bp = bp->b_next) |
1155 if (bp->b_p_bl && bp != buf) | 1198 if (bp->b_p_bl && bp != buf) |
1156 break; | 1199 break; |
1157 if (bp == NULL && buf == curbuf) | 1200 if (bp == NULL && buf == curbuf) |
1158 { | 1201 return empty_curbuf(TRUE, forceit, action); |
1159 if (action == DOBUF_UNLOAD) | |
1160 { | |
1161 EMSG(_("E90: Cannot unload last buffer")); | |
1162 return FAIL; | |
1163 } | |
1164 | |
1165 /* Close any other windows on this buffer, then make it empty. */ | |
1166 #ifdef FEAT_WINDOWS | |
1167 close_windows(buf, TRUE); | |
1168 #endif | |
1169 setpcmark(); | |
1170 retval = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, | |
1171 forceit ? ECMD_FORCEIT : 0, curwin); | |
1172 | |
1173 /* | |
1174 * do_ecmd() may create a new buffer, then we have to delete | |
1175 * the old one. But do_ecmd() may have done that already, check | |
1176 * if the buffer still exists. | |
1177 */ | |
1178 if (buf != curbuf && buf_valid(buf) && buf->b_nwindows == 0) | |
1179 close_buffer(NULL, buf, action, FALSE); | |
1180 return retval; | |
1181 } | |
1182 | 1202 |
1183 #ifdef FEAT_WINDOWS | 1203 #ifdef FEAT_WINDOWS |
1184 /* | 1204 /* |
1185 * If the deleted buffer is the current one, close the current window | 1205 * If the deleted buffer is the current one, close the current window |
1186 * (unless it's the only window). Repeat this so long as we end up in | 1206 * (unless it's the only window). Repeat this so long as we end up in |
1210 return OK; | 1230 return OK; |
1211 } | 1231 } |
1212 | 1232 |
1213 /* | 1233 /* |
1214 * Deleting the current buffer: Need to find another buffer to go to. | 1234 * Deleting the current buffer: Need to find another buffer to go to. |
1215 * There must be another, otherwise it would have been handled above. | 1235 * There should be another, otherwise it would have been handled |
1236 * above. However, autocommands may have deleted all buffers. | |
1216 * First use au_new_curbuf, if it is valid. | 1237 * First use au_new_curbuf, if it is valid. |
1217 * Then prefer the buffer we most recently visited. | 1238 * Then prefer the buffer we most recently visited. |
1218 * Else try to find one that is loaded, after the current buffer, | 1239 * Else try to find one that is loaded, after the current buffer, |
1219 * then before the current buffer. | 1240 * then before the current buffer. |
1220 * Finally use any buffer. | 1241 * Finally use any buffer. |
1309 else | 1330 else |
1310 buf = curbuf->b_prev; | 1331 buf = curbuf->b_prev; |
1311 } | 1332 } |
1312 } | 1333 } |
1313 | 1334 |
1335 if (buf == NULL) | |
1336 { | |
1337 /* Autocommands must have wiped out all other buffers. Only option | |
1338 * now is to make the current buffer empty. */ | |
1339 return empty_curbuf(FALSE, forceit, action); | |
1340 } | |
1341 | |
1314 /* | 1342 /* |
1315 * make buf current buffer | 1343 * make buf current buffer |
1316 */ | 1344 */ |
1317 if (action == DOBUF_SPLIT) /* split window first */ | 1345 if (action == DOBUF_SPLIT) /* split window first */ |
1318 { | 1346 { |