00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <errno.h>
00027 #include <stdlib.h>
00028 #include "buffer.h"
00029 #include "buffer_util.h"
00030 #include "buffer_internal.h"
00031 #include "buffer_action.h"
00032 #include "buffer_action_edit.h"
00033 #include "debug.h"
00034 #include "util.h"
00035
00036 #pragma GCC visibility push(default)
00037
00038
00039
00040
00041
00042
00043
00044
00045 int bless_buffer_undo(bless_buffer_t *buf)
00046 {
00047 if (buf == NULL)
00048 return_error(EINVAL);
00049
00050
00051 int can_undo;
00052 int err = bless_buffer_can_undo(buf, &can_undo);
00053 if (err)
00054 return_error(err);
00055
00056 if (!can_undo)
00057 return_error(EINVAL);
00058
00059
00060 struct list_node *last = list_tail(buf->undo_list)->prev;
00061
00062 struct buffer_action_entry *entry =
00063 list_entry(last, struct buffer_action_entry, ln);
00064
00065 err = buffer_action_undo(entry->action);
00066 if (err)
00067 return_error(err);
00068
00069
00070 err = list_delete_chain(last, last);
00071 if (err) {
00072
00073 buffer_action_do(entry->action);
00074 return_error(err);
00075 }
00076
00077 --buf->undo_list_size;
00078
00079
00080 err = list_insert_before(list_tail(buf->redo_list), &entry->ln);
00081 if (err) {
00082
00083 list_insert_before(list_tail(buf->undo_list), &entry->ln);
00084 ++buf->undo_list_size;
00085 buffer_action_do(entry->action);
00086 return_error(err);
00087 }
00088
00089 ++buf->redo_list_size;
00090
00091
00092 if (buf->event_func != NULL) {
00093 struct bless_buffer_event_info event_info;
00094
00095
00096 err = buffer_action_to_event(entry->action, &event_info);
00097 if (err)
00098 return_error(err);
00099
00100 event_info.event_type = BLESS_BUFFER_EVENT_UNDO;
00101 (*buf->event_func)(buf, &event_info, buf->event_user_data);
00102 }
00103
00104 return 0;
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 int bless_buffer_redo(bless_buffer_t *buf)
00116 {
00117 if (buf == NULL)
00118 return_error(EINVAL);
00119
00120
00121 int can_redo;
00122 int err = bless_buffer_can_redo(buf, &can_redo);
00123 if (err)
00124 return_error(err);
00125
00126 if (!can_redo)
00127 return_error(EINVAL);
00128
00129
00130 struct list_node *last = list_tail(buf->redo_list)->prev;
00131
00132 struct buffer_action_entry *entry =
00133 list_entry(last, struct buffer_action_entry, ln);
00134
00135 err = buffer_action_do(entry->action);
00136 if (err)
00137 return_error(err);
00138
00139
00140 err = list_delete_chain(last, last);
00141 if (err) {
00142
00143 buffer_action_undo(entry->action);
00144 return_error(err);
00145 }
00146
00147 --buf->redo_list_size;
00148
00149
00150
00151
00152
00153
00154
00155 err = list_insert_before(list_tail(buf->undo_list), &entry->ln);
00156 if (err) {
00157
00158 list_insert_before(list_tail(buf->redo_list), &entry->ln);
00159 ++buf->redo_list_size;
00160 buffer_action_undo(entry->action);
00161 return_error(err);
00162 }
00163
00164 ++buf->undo_list_size;
00165
00166
00167 if (buf->event_func != NULL) {
00168 struct bless_buffer_event_info event_info;
00169
00170
00171 err = buffer_action_to_event(entry->action, &event_info);
00172 if (err)
00173 return_error(err);
00174
00175 event_info.event_type = BLESS_BUFFER_EVENT_REDO;
00176 (*buf->event_func)(buf, &event_info, buf->event_user_data);
00177 }
00178
00179 return 0;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 int bless_buffer_begin_multi_action(bless_buffer_t *buf)
00196 {
00197 if (buf == NULL || buf->multi_action_mode == 1)
00198 return_error(EINVAL);
00199
00200
00201
00202
00203
00204 int err = undo_list_enforce_limit(buf, 1);
00205 if (err)
00206 return_error(err);
00207
00208
00209
00210
00211
00212 if (buf->undo_list_size >= buf->options->undo_limit) {
00213 buf->multi_action_mode = 1;
00214 return 0;
00215 }
00216
00217
00218 err = buffer_action_multi_new(&buf->multi_action);
00219 if (err)
00220 return_error(err);
00221
00222 err = undo_list_append(buf, buf->multi_action);
00223 if (err) {
00224 buffer_action_free(buf->multi_action);
00225 return_error(err);
00226 }
00227
00228 action_list_clear(buf->redo_list);
00229 buf->redo_list_size = 0;
00230
00231
00232 buf->multi_action_mode = 1;
00233
00234 return 0;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 int bless_buffer_end_multi_action(bless_buffer_t *buf)
00250 {
00251 if (buf == NULL || buf->multi_action_mode == 0)
00252 return_error(EINVAL);
00253
00254 int err = 0;
00255 struct bless_buffer_event_info event_info;
00256
00257
00258 if (buf->multi_action != NULL) {
00259
00260 err = buffer_action_to_event(buf->multi_action, &event_info);
00261 if (err)
00262 return_error(err);
00263 }
00264 else {
00265
00266 event_info.action_type = BLESS_BUFFER_ACTION_MULTI;
00267 event_info.range_start = -1;
00268 event_info.range_length = -1;
00269 event_info.save_fd = -1;
00270 }
00271
00272
00273 if (buf->event_func != NULL) {
00274 event_info.event_type = BLESS_BUFFER_EVENT_EDIT;
00275 (*buf->event_func)(buf, &event_info, buf->event_user_data);
00276 }
00277
00278
00279 buf->multi_action_mode = 0;
00280 buf->multi_action = NULL;
00281
00282 return 0;
00283 }
00284
00285 #pragma GCC visibility pop