1 /*
2  *  fbcmd.cc
3  *
4  *  Copyright (C) 1998  Jiann-Ching Liu
5  */
6 
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include "qe_config.h"
14 #include "filebuffer.h"
15 #include "colors.h"
16 #include "messages.h"
17 
18 static int  saved_flag = 0;
19 
cmd_insert_toggle(void)20 int filebuffer::cmd_insert_toggle(void) {
21     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
22     input_mode = insert_mode;
23     input_mode = (input_mode + 1) % 2;
24     insert_mode = input_mode;
25     display_status();
26     return 0;
27 }
28 
cmd_insert_mode(void)29 int filebuffer::cmd_insert_mode(void) {
30     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
31     input_mode = insert_mode;
32     input_mode = FB_INSERT_MODE;
33     display_status();
34     return 0;
35 }
36 
cmd_toggle_historykey(void)37 int filebuffer::cmd_toggle_historykey(void) {
38     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
39 
40     history_key = (history_key + 1) % 4;
41     return 0;
42 }
43 
cmd_toggle_searchcase(void)44 int filebuffer::cmd_toggle_searchcase(void) {
45     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
46 
47     search_case = (search_case + 1) % 2;
48     return 0;
49 }
50 
cmd_toggle_dirsort(void)51 int filebuffer::cmd_toggle_dirsort(void) {
52     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
53 
54     dir_sort = (dir_sort + 1) % 3;
55     return 0;
56 }
57 
cmd_replace_mode(void)58 int filebuffer::cmd_replace_mode(void) {
59     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
60 
61     input_mode = FB_REPLACE_MODE;
62     display_status();
63     return 0;
64 }
65 
cmd_toggle_blankcompress(void)66 int filebuffer::cmd_toggle_blankcompress(void) {
67     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
68 
69     blank_compress = (blank_compress + 1) % 2;
70     return 0;
71 }
72 
73 
cmd_command_toggle(void)74 int filebuffer::cmd_command_toggle(void) {
75     return (mode == FB_DATAAREA_MODE) ? cmd_cursor_cmd() : cmd_cursor_data();
76 }
77 
cmd_cursor_data(void)78 int filebuffer::cmd_cursor_data(void) {
79     if (mode != FB_DATAAREA_MODE) load_workbuffer();
80     mode = FB_DATAAREA_MODE;
81     return 0;
82 }
83 
cmd_cursor_cmd(void)84 int filebuffer::cmd_cursor_cmd(void) {
85     if (mode != FB_COMMAND_MODE) write_workbuffer(QE_IF_NECESSARY);
86     mode = FB_COMMAND_MODE;
87     return 0;
88 }
89 
cmd_split(void)90 int filebuffer::cmd_split(void) {
91     if (read_only) {
92         display_messages(MSG_READ_ONLY_FILE);
93         return 0;
94     }
95 
96 //  if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
97 
98     cmd_cursor_data();
99 
100     if (buffer_x > workbuflen-1) {
101         buffer_x = workbufidx = workbuflen - 1;
102         linebuffer  *nl = new linebuffer("");
103         nl->next                = current->next;
104         nl->previous            = current;
105         current->next->previous = nl;
106         current->next           = nl;
107         total_line++;
108         cmd_endline();
109     } else {
110         // wprintw(win, "[split]");
111         workbuffer[workbuflen] = '\0';
112         linebuffer *nl = new linebuffer(&workbuffer[workbufidx]);
113         nl->next                = current->next;
114         nl->previous            = current;
115         current->next->previous = nl;
116         current->next           = nl;
117         total_line++;
118         workbuffer[workbufidx] = '\0';
119         workbuflen = (buffer_x = workbufidx) + 1;
120     }
121     write_workbuffer(QE_FORCE);
122     fix_all_mark_position(FIX_MARK_INSERT_LINE);
123     refresh_clientarea(0);
124     load_workbuffer();
125     return 0;
126 }
127 
cmd_join(void)128 int filebuffer::cmd_join(void) {
129     if (read_only) {
130         display_messages(MSG_READ_ONLY_FILE);
131         return 0;
132     }
133 
134 //  if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
135 
136     if (current->next != tail) {
137         fix_all_mark_position(FIX_MARK_JOIN_LINE);
138 
139         linebuffer  *ptr= current->next;
140 
141         workbuffer[workbuflen] = '\0';
142         strncat(workbuffer, ptr->getString(), MAX_BUFFER_LEN - workbuflen - 2);
143         workbuflen = strlen(workbuffer);
144         current->next = ptr->next;
145         ptr->next->previous = current;
146         total_line--;
147         ptr->~linebuffer();
148         dirty_line = 1;
149         write_workbuffer(QE_FORCE);
150         refresh_clientarea(0);
151     }
152     return 0;
153 }
154 
cmd_new(void)155 int filebuffer::cmd_new(void) {
156     return cmd_edit("");
157 }
158 
cmd_edit(void)159 int filebuffer::cmd_edit(void) {
160     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
161 
162     if (current_buffer == current_buffer->next_buffer) return 0;
163 
164 
165     write_workbuffer(QE_IF_NECESSARY);
166     current_buffer = current_buffer->next_buffer;
167     if (keep_in_menu == MENU_KEEP_IN_MENU) {
168         keep_in_menu = MENU_NOT_IN_MENU;
169         current_buffer->keep_in_menu = MENU_BACK_TO_MENU;
170     }
171     return RTNVAL_NEXT_BUFFER;
172 }
173 
cmd_edit(const char * args,const int ro)174 int filebuffer::cmd_edit(const char *args, const int  ro) {
175     if (current_buffer->filename.getLength() == 0 ||
176                      strcmp(current_buffer->filename.getString(), args) != 0) {
177         int  found = 0;
178 
179         write_workbuffer(QE_IF_NECESSARY);
180 
181         filebuffer *f = current_buffer;
182         while ((f = f->next_buffer) != current_buffer) {
183             if (f->filename.getLength() != 0 &&
184                                  strcmp(f->filename.getString(), args) == 0) {
185                 found = 1;
186                 break;
187             }
188         }
189         if (! found) f = new filebuffer(args);
190         f->read_only = ro;
191         current_buffer = f;
192 
193         return RTNVAL_NEXT_BUFFER;
194     }
195     return 0;
196 }
197 
cmd_save_all_quit(void)198 int filebuffer::cmd_save_all_quit(void) {
199     quit_confirm = 0;
200 
201     if (dirty_flag || dirty_line) cmd_save();
202     cmd_quit();
203 
204     return RTNVAL_SAVE_ALL_AND_QUIT;
205 }
206 
cmd_quit_all(void)207 int filebuffer::cmd_quit_all(void) {
208     quit_confirm = 0;
209     cmd_quit();
210     return RTNVAL_QUIT_ALL_BUFFER;
211 }
212 
cmd_quit(void)213 int filebuffer::cmd_quit(void) {
214 
215     write_workbuffer(QE_IF_NECESSARY);
216 
217     if (quit_confirm) {
218         if (dirty_flag || dirty_line) {
219             int   k;
220 
221             display_messages(MSG_REALLY_QUIT);
222 
223             while (1) {
224                 k = wgetch(win);
225                 if (k == 'y' || k == 'Y') break;
226                 if (k == 'n' || k == 'N') {
227                     display_messages();
228                     return 0;
229                 }
230             }
231         }
232     }
233 
234     return RTNVAL_QUIT_BUFFER;
235 }
236 
cmd_file(void)237 int filebuffer::cmd_file(void) {
238     write_workbuffer(QE_IF_NECESSARY);
239     saved_flag = 0;
240     cmd_save();
241     if (saved_flag && dirty_flag == 0) return cmd_quit();
242     return 0;
243 }
244 
cmd_save(void)245 int filebuffer::cmd_save(void) {
246     if (filename.getLength() != 0) {
247         FILE         *fd;
248         linebuffer   *ptr = head;
249         struct stat  stbuf;
250         int          mode_changed = 0;
251 
252         write_workbuffer(QE_IF_NECESSARY);
253 
254         if (access(filename.getString(), F_OK) == 0 &&
255                           access(filename.getString(), W_OK) != 0) {
256             int  k;
257             display_messages(MSG_WRITE_FORCE);
258             while (1) {
259                 k = wgetch(win);
260                 if (k == 'y' || k == 'Y') break;
261                 if (k == 'n' || k == 'N') {
262                     display_messages();
263                     return 0;
264                 }
265             }
266             stat(filename.getString(), &stbuf);
267             chmod(filename.getString(), stbuf.st_mode | 0222);
268             mode_changed = 1;
269         }
270 
271         if ((fd = fopen(filename.getString(), "w+")) != NULL) {
272             int   i, j, k, m, len;
273             char  buffer[MAX_BUFFER_LEN+1];
274 
275             while ((ptr = ptr->next) != tail) {
276                 if (blank_compress) {
277                     len = ptr->getLength();
278                     m   = 0;
279 
280                     for (i = TAB_SPACE; i < len; i += TAB_SPACE) {
281                         for (j = i - 1; j >= i - TAB_SPACE; j--)
282                             if ((*ptr)[j] != ' ')
283                                 break;
284 
285                         for (k = i - TAB_SPACE; k <= j; k++)
286                             buffer[m++] = (*ptr)[k];
287 
288                         if (j == i-2) {
289                             buffer[m++] = ' ';
290                         } else if (j < i-2) {
291                             buffer[m++] = '\t';
292                         }
293                     }
294                     for (i = i - TAB_SPACE; i <= len; i++)
295                         buffer[m++] = (*ptr)[i];
296 
297                     for (m--; m >= 0; m--) {
298                         if (buffer[m] != ' ' && buffer[m] != '\t'
299                                              && buffer[m] != '\0')
300                             break;
301                         buffer[m] = '\0';
302                     }
303 
304                     fprintf(fd, "%s\n", buffer);
305                 } else {
306                     fprintf(fd, "%s\n", ptr->getString());
307                 }
308             }
309             fclose(fd);
310             dirty_flag = 0;
311             display_filename();
312             // setattr(win, ATTRIBUTE_status_line);
313             // mvwprintw(win, screen_y-2, 0, "%-30s ", filename);
314             display_messages(MSG_FILE_SAVED);
315             saved_flag = 1;
316         } else {
317             display_messages(MSG_ERROR_OPEN_FILE);
318         }
319 
320         if (mode_changed) chmod(filename.getString(), stbuf.st_mode);
321     } else {
322         display_messages(MSG_MESSING_FILE_NAME);
323     }
324     // mode = FB_COMMAND_MODE;
325 
326     return 0;
327 }
328 
cmd_undo(void)329 int filebuffer::cmd_undo(void) {
330     load_workbuffer();
331     dirty_line = 0;
332     refresh_bufferline();
333 
334     return 0;
335 }
336 
cmd_first_nonblank(void)337 int filebuffer::cmd_first_nonblank(void) {
338     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
339 
340     cmd_cursor_data();
341 
342     for (workbufidx = 0; workbufidx < workbuflen; workbufidx++)
343         if (workbuffer[workbufidx] != ' ')
344             break;
345 
346     buffer_x = workbufidx;
347 
348     moveto(buffer_y, buffer_x);
349 
350 //  if (workbufidx < screen_x - 1) {
351 //      cursor_x = workbufidx;
352 //      if (left_col_no != 0) {
353 //          left_col_no = 0;
354 //          refresh_clientarea();
355 //          refresh_bufferline();
356 //      }
357 //  } else {
358 //      if ((unsigned int) workbufidx >= left_col_no &&
359 //          (unsigned int) workbufidx < left_col_no + screen_x -1) {
360 //          cursor_x = workbufidx - left_col_no;
361 //      } else {
362 //          cursor_x = screen_x - 1;
363 //          left_col_no = workbufidx - cursor_x;
364 //          refresh_clientarea();
365 //          refresh_bufferline();
366 //      }
367 //  }
368     return 0;
369 }
370 
cmd_insertline(void)371 int filebuffer::cmd_insertline(void) {
372     if (read_only) {
373         display_messages(MSG_READ_ONLY_FILE);
374         return 0;
375     }
376 
377     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
378 
379     write_workbuffer(QE_FORCE);
380 
381     linebuffer *newline     = new linebuffer("");
382     newline->next           = current->next;
383     newline->previous       = current;
384     newline->next->previous = newline;
385     current->next           = newline;
386     current                 = newline;
387 
388     buffer_x = 0;
389     buffer_y++;
390 
391     cursor_x = 0;
392 
393     if (cursor_y == screen_y-4) {
394         top_line_no++;
395         topline = topline->next;
396     } else {
397         cursor_y++;
398     }
399 
400     total_line++;
401     fix_all_mark_position(FIX_MARK_INSERT_LINE);
402     refresh_clientarea(0);
403     load_workbuffer();
404 
405     return 0;
406 }
407 
cmd_beep(void)408 int filebuffer::cmd_beep(void) {
409     beep();
410     return 0;
411 }
412 
cmd_cmdquote(const char * quote)413 int filebuffer::cmd_cmdquote(const char *quote) {
414     cmd_execute(quote);
415     return 0;
416 }
417