1 /*
2  *  filebuffer.cc
3  *
4  *  Copyright (C) 1998, 1999  Jiann-Ching Liu
5  */
6 
7 
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "qe_config.h"
13 #include "keydefine.h"
14 #include "filebuffer.h"
15 #include "history.h"
16 #include "misc.h"
17 #include "colors.h"
18 #include "messages.h"
19 #include "menu.h"
20 
21 #if AUTO_TERM_SIZE_DETECT
22 #    include <term.h>
23 #endif
24 
25 
26 // const int  markstacksize = 5;
27 mark        filebuffer::markstack[markstacksize];
28 int         filebuffer::marksp = -1;
29 mark        filebuffer::current_mark;
30 filebuffer* filebuffer::current_buffer = NULL;
31 short       filebuffer::enable_ctrl_k  = 0;
32 short       filebuffer::enable_ctrl_x  = 0;
33 short       filebuffer::enable_ctrl_q  = 0;
34 short       filebuffer::quit_confirm   = 1;
35 short       filebuffer::history_key    = HISTORY_KEY_NONE;
36 short       filebuffer::insert_mode    = 0;
37 short       filebuffer::blank_compress = 0;
38 short       filebuffer::search_case    = 0;
39 short       filebuffer::big5msg_flag   = 0;
40 short       filebuffer::dir_sort       = DIR_SORT_BY_NAME;
41 char        filebuffer::current_dir[PATH_MAX] = "";
42 int         filebuffer::screen_lines   = 0;
43 int         filebuffer::screen_columns = 0;
44 keydefine*  filebuffer::kdf = NULL;
45 menu        filebuffer::menubar;
46 cmdHistory  filebuffer::history;
47 
48 // linebuffer* filebuffer::cmdhistory = NULL;
49 // int         filebuffer::history_no = 0;
50 
51 
52 #ifdef USE_ANSICOLOR
53 int         filebuffer::ansi_color = -1;
54 #endif
55 
56 
filebuffer(void)57 filebuffer::filebuffer(void) : filename() {
58     init_window();
59 }
60 
filebuffer(const char * fname)61 filebuffer::filebuffer(const char *fname) : filename(fname) {
62     init_window();
63     // load_file();
64 }
65 
load_file(void)66 void filebuffer::load_file(void) {
67     FILE          *fd;
68     unsigned int  j, len, tmplen;
69     char          tmpbuf[MAX_BUFFER_LEN+1];
70     char          linebuf[MAX_BUFFER_LEN+1];
71 
72     if (loadingOK) return;
73 
74 
75     if (filename.getLength() != 0) {
76 
77         if (access(filename.getString(), F_OK) == 0) {
78             if (access(filename.getString(), R_OK) == 0) {
79                 if ((fd = fopen(filename.getString(), "r")) != NULL) {
80                     linebuffer  *tmpptr, *ptr = current;
81 
82                     total_line = 0;
83 
84                     while (fgets(tmpbuf, MAX_BUFFER_LEN, fd) != NULL) {
85                         if (total_line % 100 == 0) {
86                             display_messages("Loading %d ...", total_line);
87                         }
88                         tmplen = strlen(tmpbuf);
89                         for (unsigned int i = j = len = 0;
90                                (i < tmplen) && (j < MAX_BUFFER_LEN); i++) {
91                             switch(tmpbuf[i]) {
92                             case '\r':
93                             case '\n':
94                                 linebuf[j++] = '\0';
95                                 break;
96                             case '\t':
97                                 for (int k = j % TAB_SPACE; k < TAB_SPACE;
98                                                                       k++, j++)
99                                     linebuf[j] = ' ';
100                                 break;
101                             case ' ' :
102                                 linebuf[j++] = ' ';
103                                 break;
104 //                          case 127 :
105 //                              linebuf[j++] = '^';
106 //                              linebuf[j++] = '?';
107 //                              len = j;
108 //                              break;
109                             case '\b':
110                             case '\f':
111                                 break;
112                             default  :
113                                 linebuf[j++] = tmpbuf[i];
114                                 len = j;
115                                 break;
116                             }
117                         }
118                         linebuf[len] = '\0';
119 
120                         tmpptr = new linebuffer(linebuf);
121                         ptr->next        = tmpptr;
122                         tmpptr->previous = ptr;
123                         ptr              = tmpptr;
124                         total_line++;
125                     }
126                     ptr->next         = tail;
127                     tail->previous    = ptr;
128 
129                     if (ptr == current) { // empty input file
130                         head->next        = current;
131                         current->previous = head;
132                         total_line        = 1;
133                     } else {
134                         head->next        = current->next;
135                         ptr               = current;
136                         current           = current->next;
137                         current->previous = head;
138                         delete ptr;
139                     }
140                     fclose(fd);
141 
142                     if (access(filename.getString(), W_OK) == 0) {
143                         display_messages("Loading file: %s .... ok.",
144                                                basename(filename.getString()));
145                     } else {
146                         display_messages("Reading file: %s .... ok.",
147                                                basename(filename.getString()));
148                     }
149                 } else {
150                     display_messages(MSG_NEW_FILE);
151                 }
152             } else {
153                 display_messages(MSG_READ_ERROR);
154             }
155         } else { // new file
156             display_messages(MSG_NEW_FILE);
157         }
158 
159         refresh_clientarea(0);
160         display_status();
161     }
162     loadingOK = 1;
163 }
164 
165 
init_window(void)166 void filebuffer::init_window(void) {
167 #ifdef USE_ANSICOLOR
168     if (ansi_color == -1) ansi_color = has_colors() ? 0 : 1;
169 #endif
170 
171     if (current_dir[0] == '\0') getcwd(current_dir, PATH_MAX);
172 
173     if (current_buffer == NULL) {
174         current_buffer  = this;
175         next_buffer     = this;
176         previous_buffer = this;
177 
178         qeString::setHandler(filebuffer::out_of_memory);
179 
180         init_menu();
181     } else {
182         next_buffer                  = current_buffer->next_buffer;
183         previous_buffer              = current_buffer;
184         current_buffer->next_buffer  = this;
185         next_buffer->previous_buffer = this;
186     }
187 
188     head    = new linebuffer("=== Top of file ===");
189     tail    = new linebuffer("=== Bottom of file ===");
190     current = new linebuffer("");
191     head->previous     = NULL;
192     head->next         = current;
193     current->previous  = head;
194     current->next      = tail;
195     tail->previous     = current;
196     tail->next         = NULL;
197     buffer_type        = NORMAL_TEXT_BUFFER;
198 
199     screen_x  = screen_columns;
200     screen_y  = screen_lines;
201 
202     read_only    = 0;
203     loadingOK    = 0;
204     win          = NULL;
205     keep_in_menu = MENU_NOT_IN_MENU;
206 
207     sprintf(outputformat, "%%-%ds", screen_x);
208 
209     general_init();
210 }
211 
general_init(void)212 void filebuffer::general_init(void) {
213     cursor_x = 0;
214     cursor_y = 1;
215     buffer_x = 0;
216     buffer_y = 0;
217 
218     // keycommand = NULL;
219 
220     topline            = head;
221     total_line         =  1;
222     top_line_no        = -1;
223     left_col_no        =  0;
224 
225     dirty_flag         = 0;
226     dirty_line         = 0;
227     quiet_flag         = 0;
228     message_dirty_flag = 0;
229 
230     mode               = FB_DATAAREA_MODE;
231 //    input_mode         = FB_REPLACE_MODE;
232     input_mode         = insert_mode;
233     cmdline[(cmdline_idx = 0)] = '\0';
234 }
235 
~filebuffer(void)236 filebuffer::~filebuffer(void) {
237 //  FILE  *fd;
238 //
239 //  fd = fopen("log.txt", "a+");
240 //  fprintf(fd, "quit: %s\n", filename);
241 //  fclose(fd);
242 
243     // if (filename != NULL) qeFree(filename);
244     filename.~qeString();
245     if (win != NULL) delwin(win);
246 
247     for (linebuffer *ptr = head; ptr != NULL; ptr = current) {
248         current = ptr->next;
249         ptr->~linebuffer();
250         delete ptr;   // version 0.0.23
251     }
252 
253     // filename = NULL;
254     win = NULL;
255 }
256 
out_of_memory(void)257 void filebuffer::out_of_memory(void) {
258     if (current_buffer != NULL) {
259         current_buffer->read_only = 1;
260         current_buffer->display_messages(MSG_OUT_OF_MEMORY);
261     }
262 }
263 
init_curses(void)264 void filebuffer::init_curses(void) {
265 
266 #if AUTO_TERM_SIZE_DETECT
267     if (screen_columns == 0) {
268         char   entrybuf[1024];
269         char   *term = getenv("TERM");
270         if (term != NULL && tgetent(entrybuf, term) != -1) {   // read in entry
271             screen_columns = tgetnum("co");
272             screen_lines   = tgetnum("li");
273         } else {
274             screen_columns = 80;
275             screen_lines   = 24;
276 //          screen_columns = COLUMNS;
277 //          screen_lines   = LINES;
278         }
279     }
280 #else
281     screen_columns = 80;
282     screen_lines   = 24;
283 #endif
284 
285     initscr();             // initialize the curses library
286     keypad(stdscr, TRUE);  // enable keyboard mapping
287     nonl();                // tell curses not to do NL->CR/NL on output
288     cbreak();              // take input chars one at a time, no wait for \n
289     nocrmode();            // Control input mode: ^S, ^Q, ^C, ^Y go to kernel
290     noecho();              // don't echo input
291     color_setup();
292     raw();                 // Raw input mode no processing by the kernel.
293     intrflush(stdscr, FALSE);
294     nodelay(stdscr, FALSE);
295     refresh();
296 }
297 
end_curses(void)298 void filebuffer::end_curses(void) {
299     endwin();
300 }
301 
302 
init_keydefine(const char * fname)303 void filebuffer::init_keydefine(const char *fname) {
304     kdf = new keydefine(fname);
305 }
306 
init_keydefine(void)307 void filebuffer::init_keydefine(void) {
308     kdf = new keydefine();
309 }
310 
311 // char* filebuffer::qeStrdup(const char *s) {
312 //     char  *ptr;
313 //     int   len = strlen(s) + 1;
314 //
315 //     if ((ptr = new char[len]) != NULL) {
316 //         memcpy(ptr, s, len);
317 //     }
318 //     return ptr;
319 // }
320 
active(void)321 filebuffer* filebuffer::active(void) {
322     int         finish = 0;
323     static int  quit_all = 0;
324     filebuffer  *fb;
325 
326     if (win == NULL) win = newwin(screen_y, screen_x, 0, 0);
327     wclear(win);
328     keypad(win, TRUE);
329     nodelay(win, FALSE);
330 
331     paint();
332     load_file();
333     load_workbuffer();
334 
335     switch (quit_all) {
336     case 1:
337         finish = cmd_quit_all();
338         break;
339     case 2:
340         finish = cmd_save_all_quit();
341         break;
342     default:
343         if (keep_in_menu == MENU_BACK_TO_MENU) finish = cmd_menu();
344         break;
345     }
346 
347     while (finish == 0)
348         finish = (mode == FB_COMMAND_MODE) ? cmdarea() : clientarea();
349 
350     if (win != NULL) delwin(win);
351     win = NULL;
352 
353     quit_all = 0;
354 
355     switch (finish) {
356     case RTNVAL_SHELL_ESCAPE:
357         end_curses();
358         system(getenv("SHELL"));
359         init_curses();
360         break;
361     case RTNVAL_QUIT_BUFFER:
362         unmark_all_mark();
363         if ((current_buffer = this->previous_buffer) == this) {
364             current_buffer = NULL;
365             display_messages(MSG_QUIT);
366         } else {
367             this->next_buffer->previous_buffer = current_buffer;
368             current_buffer->next_buffer        = this->next_buffer;
369         }
370         this->~filebuffer();
371 
372         break;
373     case RTNVAL_SAVE_ALL_AND_QUIT:
374         quit_all = 1;
375     case RTNVAL_QUIT_ALL_BUFFER:
376         quit_all++;
377     case RTNVAL_QUIT_CURRENT_BUFFER:
378         current_buffer->unmark_all_mark();
379         fb = current_buffer;
380         current_buffer = current_buffer->next_buffer;
381         if (fb == current_buffer) {
382             current_buffer = NULL;
383         } else {
384             current_buffer->previous_buffer = fb->previous_buffer;
385             fb->previous_buffer->next_buffer = current_buffer;
386         }
387 
388         fb->~filebuffer();
389         break;
390     }
391 
392     return current_buffer;
393 }
394 
load_workbuffer(void)395 void filebuffer::load_workbuffer(void) {
396     strncpy(workbuffer, current->getString(), MAX_BUFFER_LEN);
397     workbuflen = strlen(workbuffer);
398     for (int i = strlen(workbuffer); i < MAX_BUFFER_LEN; i++)
399         workbuffer[i] = ' ';
400     workbufidx = buffer_x;
401 }
402 
write_workbuffer(const int force)403 void filebuffer::write_workbuffer(const int  force) {
404     if (force || dirty_line) {
405         dirty_buffer(1);
406         workbuffer[workbuflen] = '\0';
407         // current->assign(workbuffer);
408         *current = workbuffer;
409         for (int i = workbuflen; i < MAX_BUFFER_LEN; i++)
410             workbuffer[i] = ' ';
411         // workbuffer[workbuflen] = ' ';
412     }
413     dirty_line = 0;
414 }
415 
dirty_buffer(const int force)416 int filebuffer::dirty_buffer(const int force) {
417     if (! dirty_flag && (force || dirty_line)) {
418         dirty_flag = 1;
419         display_filename();
420         return 1;
421     }
422     return 0;
423 }
424 
cmd_kbinput(void)425 int filebuffer::cmd_kbinput(void) {
426     int  key;
427 
428     if (mode == FB_DATAAREA_MODE) {
429         // setattr(win, ATTRIBUTE_normal_text);
430         ca_attrset();
431         wmove(win, cursor_y, cursor_x);
432 //      load_workbuffer(QE_IF_NECESSARY);
433 //      if (newline_flag) {
434 //          load_workbuffer();
435 //          newline_flag = 0;
436 //      }
437 
438         if (((key = getfirstkey()) >= ' ') && (key < 256)) {
439             ca_attrset();
440             wmove(win, cursor_y, cursor_x);
441             if (read_only) {
442                 display_messages(MSG_READ_ONLY_FILE);
443             } else {
444                 if (workbufidx >= MAX_BUFFER_LEN-2) return 0;
445 
446                 if (input_mode == FB_REPLACE_MODE) {
447                     mvwaddch(win, cursor_y, cursor_x, key);
448                     workbuffer[workbufidx++] = key;
449                     workbuflen = maximum(workbuflen, workbufidx);
450                 } else {
451                     mvwinsch(win, cursor_y, cursor_x, key);
452                     for (int i = minimum(workbuflen, MAX_BUFFER_LEN-2);
453                                                           i > workbufidx; i--)
454                         workbuffer[i] = workbuffer[i-1];
455                     workbuffer[workbufidx++] = key;
456                     workbuflen=workbuflen>=workbufidx?workbuflen+1:workbufidx;
457                     workbuflen = minimum(workbuflen, MAX_BUFFER_LEN-2);
458                 }
459                 dirty_line = 1;
460                 buffer_x = workbufidx;
461                 if (cursor_x < screen_x-1) {
462                     cursor_x++;
463                 } else {
464                     left_col_no++;
465                     refresh_clientarea(1);
466                 }
467                 display_status();
468             }
469         } else {
470             if (buffer_type == DIRECTORY_BUFFER) {
471                 if (key == KEY_ENTER || key == KEY_RETURN
472                                      || key == KEY_LINEFEED) {
473                     // load_file();
474                 }
475             }
476             // if ((key = getnextkey()) != 0) return key;
477             return do_function_key(key);
478             // return getnextkey();
479         }
480     } else { /////////////// Command Line ////////////////////////
481         setattr(win, ATTRIBUTE_command_line);
482         wmove(win, screen_y-3, cmdline_idx < screen_x - 1 ? cmdline_idx :
483                                screen_x -1);
484 
485         int  cmdlen = strlen(cmdline);
486 
487         if (((key = getfirstkey()) >= ' ') && (key < 256)) {
488             setattr(win, ATTRIBUTE_command_line);
489             wmove(win, screen_y-3, cmdline_idx < screen_x - 1 ? cmdline_idx :
490                                screen_x -1);
491             if (cmdline_idx < MAX_BUFFER_LEN - 2) {
492                 if (input_mode == FB_REPLACE_MODE) {
493                     cmdline[cmdline_idx++] = key;
494                     cmdlen = maximum(cmdlen, cmdline_idx);
495                     cmdline[cmdlen] = '\0';
496                     if (cmdline_idx < screen_x-1) {
497                         waddch(win, key);
498                     } else {
499                         refresh_cmdarea();
500                     }
501                 } else {
502                     winsch(win, key);
503                     for (int i = cmdlen; i > cmdline_idx; i--)
504                         cmdline[i] = cmdline[i-1];
505                     cmdline[cmdline_idx++] = key;
506                     cmdlen = minimum(cmdlen + 1, MAX_BUFFER_LEN -2);
507                     cmdline[cmdlen] = '\0';
508 
509                     // mvwinsch(win, cursor_y, cursor_x, key);
510                     // for (int i = workbuflen; i > workbufidx; i--)
511                     //     workbuffer[i] = workbuffer[i-1];
512                     // workbuffer[workbufidx++] = key;
513                     // workbuflen=workbuflen>=workbufidx?workbuflen+1:workbufidx;
514                     // workbuflen = minimum(workbuflen, MAX_BUFFER_LEN);
515                 }
516             } else {
517                 beep();
518             }
519         } else {
520             switch (key) {
521 //          case KEY_DOWN:
522 //              display_messages(MSG_CMD_HISTORY);
523 //              history.push(cmdline);
524 //              if (history.active(cmdline, win, screen_y, screen_x, 10, 40)) {
525 //                  refresh_cmdarea();
526 //                  cmdline_idx = 0;
527 //              }
528 //              history.pop();
529 //              display_messages();
530 //              break;
531             case KEY_RETURN:
532             case KEY_ENTER:
533             case KEY_LINEFEED:
534                 if (cmdlen > 0) {
535                     history.push(cmdline);
536                     return cmd_execute();
537                 }
538                 break;
539             default:
540                 // if ((key = getnextkey()) != 0) return key;
541                 // return getnextkey();
542                 if (((key == KEY_UP)   && (history_key & HISTORY_KEY_UP  )) ||
543                     ((key == KEY_DOWN) && (history_key & HISTORY_KEY_DOWN))) {
544                     return cmd_history();
545                 } else {
546                     return do_function_key(key);
547                 }
548                 // waddch(win, key);
549                 // wprintw(win, "(%d)", key);
550                 break;
551             }
552         }
553     }
554     return 0;
555 }
556 
cmd_history(void)557 int filebuffer::cmd_history(void) {
558     write_workbuffer(QE_IF_NECESSARY);
559     cmd_cursor_cmd();
560 
561     display_messages(MSG_CMD_HISTORY);
562     history.push(cmdline);
563 
564     if (history.active(cmdline, win, screen_y, screen_x, 10, 40)) {
565         refresh_cmdarea();
566         cmdline_idx = 0;
567     }
568 
569     history.pop();
570 
571     display_messages();
572     return 0;
573 }
574 
do_function_key(const int key)575 int filebuffer::do_function_key(const int key) {
576     return getnextkey();
577 }
578 
clientarea(void)579 int filebuffer::clientarea(void) {
580     // int      modified = 0;
581     // keycmdlist  *keycommand;
582     int rtlval = 0;
583 
584     // newline_flag = 1;
585 
586     while (mode == FB_DATAAREA_MODE) {
587         if ((rtlval = cmd_kbinput()) != 0) return rtlval;
588     }
589     return rtlval;
590 }
591 
display_status(void)592 void filebuffer::display_status(void) {
593     setattr(win, ATTRIBUTE_status_line);
594     mvwprintw(win, screen_y-2, screen_x-26, "%6d/%-6d %3d  %7s",
595               buffer_y + 1, total_line,
596               mode == FB_DATAAREA_MODE ? buffer_x + 1 : cmdline_idx + 1,
597               (big5msg_flag == 1) ?
598               (input_mode == FB_INSERT_MODE  ? "<I>���J" : "<R>���N") :
599               (input_mode == FB_INSERT_MODE  ? " Insert" : "Replace"));
600 
601 }
602 
paint(void)603 void filebuffer::paint(void) {
604     for (int i = 0; i < screen_y-3; i++) {
605         setattr(win, ATTRIBUTE_normal_text);
606         mvprint(i, 0, "");
607     }
608     setattr(win, ATTRIBUTE_command_line);
609     mvprint(screen_y-3, 0, "");
610     setattr(win, ATTRIBUTE_status_line);
611     mvprint(screen_y-2, 0, "");
612     setattr(win, ATTRIBUTE_message_line);
613     mvprint(screen_y-1, 0, "");
614 
615     display_filename();
616     display_status();
617     refresh_clientarea(0);
618     display_messages();
619     wmove(win, 0, 0);
620     setattr(win, ATTRIBUTE_normal_text);
621     touchwin(win);
622     wrefresh(win);
623 }
624 
625 
display_filename(void)626 void filebuffer::display_filename(void) {
627 
628     if (filename.getLength() == 0 || current_buffer != this) return;
629 
630     char dispbuff[MAX_BUFFER_LEN];
631     int  len = filename.getLength();
632     int  idx = 0;
633 
634 //  dispbuff[0] = '\0';
635 //
636 //  if (read_only) {
637 //      strcpy(dispbuff, "%% ");
638 //  } else if (dirty_flag) {
639 //      strcpy(dispbuff, "** ");
640 //  } else {
641 //      strcpy(dispbuff, "-- ");
642 //  }
643 //  idx = strlen(dispbuff);
644 
645     if (len > screen_x - 35) {
646         dispbuff[idx] = filename[0] == '[' ? '[' : '.';
647 //      sprintf(&dispbuff[idx+1], ".. %s", &filename[len + 35 - screen_x]);
648         sprintf(&dispbuff[idx+1], ".. %s",
649                                     filename.getString(len + 35 - screen_x));
650     } else {
651         strcpy(&dispbuff[idx], filename.getString());
652     }
653 
654     setattr(win, dirty_flag ? ATTRIBUTE_modified_file_line : ATTRIBUTE_status_line);
655     mvwprintw(win, screen_y-2, 0, "%s", dispbuff);
656 }
657 
658 
659 
refresh_bufferline(void)660 void filebuffer::refresh_bufferline(void) {
661     int           mlnos = -2, mlnoe = -2;
662     unsigned int  bml = MAX_BUFFER_LEN + 1;
663     unsigned int  bmr = MAX_BUFFER_LEN + 1;
664     int           bmfix = 0;
665 
666     if (quiet_flag || current_buffer != this) return;
667 
668     if (current_mark != UNKNOW_MARK && current_mark.fb == this) {
669         mlnos = minimum(current_mark.fn, current_mark.ln);
670         mlnoe = maximum(current_mark.fn, current_mark.ln);
671 
672         if (current_mark == BLOCK_MARK) {
673             bml = minimum(current_mark.fc, current_mark.lc);
674             bmr = maximum(current_mark.fc, current_mark.lc);
675         }
676     }
677 
678     if (buffer_y >= mlnos && buffer_y <= mlnoe) {
679         if (current_mark == BLOCK_MARK) {
680             if (bmr >= left_col_no && bml <= left_col_no + screen_x)
681                 bmfix = 1;
682             setattr(win, ATTRIBUTE_normal_text);
683         } else {
684             setattr(win, ATTRIBUTE_mark_text);
685         }
686     } else {
687         setattr(win, ATTRIBUTE_normal_text);
688     }
689 
690     mvprint(cursor_y, 0,
691      ((unsigned int)workbuflen > left_col_no) ?  &workbuffer[left_col_no] : "");
692 
693     if (bmfix) {
694         setattr(win, ATTRIBUTE_mark_text);
695         int   leftmax = maximum(bml, left_col_no);
696 /*
697         mvprint(cursor_y, (bml > left_col_no ? bml - left_col_no : 0),
698                    minimum(minimum(bmr+1, screen_x + left_col_no) -
699                            maximum(bml, left_col_no),
700                            (unsigned int) screen_x),
701                    ((unsigned int) workbuflen > bml) ?  &workbuffer[bml] : "");
702 */
703         mvprint(cursor_y, leftmax - left_col_no,
704             minimum(minimum(bmr+1, screen_x+left_col_no) - leftmax,
705                           (unsigned int) screen_x),
706             (workbuflen > leftmax) ? &workbuffer[leftmax] : "");
707     }
708     setattr(win, ATTRIBUTE_normal_text);
709 }
710 
refresh_clientarea(const int bufflag)711 void filebuffer::refresh_clientarea(const int bufflag) {
712     int           i, mlnos = -2, mlnoe = -2, lno = top_line_no;
713     int           blockmark_need_fix = 0;
714     unsigned int  bml = MAX_BUFFER_LEN + 1;
715     unsigned int  bmr = MAX_BUFFER_LEN + 1;
716     linebuffer    *ptr = topline;
717 
718     if (quiet_flag || current_buffer != this) return;
719 
720     if (current_mark != UNKNOW_MARK && current_mark.fb == this) {
721         mlnos = minimum(current_mark.fn, current_mark.ln);
722         mlnoe = maximum(current_mark.fn, current_mark.ln);
723 
724         if (current_mark == BLOCK_MARK) {
725             bml = minimum(current_mark.fc, current_mark.lc);
726             bmr = maximum(current_mark.fc, current_mark.lc);
727         }
728     }
729 
730     setattr(win, ATTRIBUTE_normal_text);
731 
732     for (i = 0; i < screen_y-3 && ptr != NULL; i++, ptr = ptr->next, lno++) {
733         if (lno >= mlnos && lno <= mlnoe) {
734             if (current_mark == BLOCK_MARK) {
735                 if (bmr >= left_col_no && bml <= left_col_no + screen_x)
736                     blockmark_need_fix = 1;
737                 setattr(win, ATTRIBUTE_normal_text);
738             } else {
739                 setattr(win, ATTRIBUTE_mark_text);
740             }
741         } else {
742             setattr(win, ATTRIBUTE_normal_text);
743         }
744 
745         if (ptr == head || ptr == tail) {
746             mvprint(i, 0, ptr->getString());
747         } else {
748             mvprint(i, 0, (ptr->getLength() > left_col_no) ?
749                            ptr->getString(left_col_no) : "");
750 //                         &((*ptr)[left_col_no]) : "");
751         }
752 
753         if (blockmark_need_fix) {
754             blockmark_need_fix = 0;
755             setattr(win, ATTRIBUTE_mark_text);
756             unsigned int   leftmax = maximum(bml, left_col_no);
757             mvprint(i, leftmax - left_col_no,
758                   minimum(minimum(bmr+1, screen_x+left_col_no) - leftmax,
759                           (unsigned int) screen_x),
760                   (ptr->getLength() > leftmax ? ptr->getString(leftmax) : ""));
761 //                (ptr->getLength() > leftmax ? &((*ptr)[leftmax]) : ""));
762         }
763     }
764     setattr(win, ATTRIBUTE_normal_text);
765 
766     for (; i < screen_y-3; i++) mvprint(i, 0, "");
767 
768     if (bufflag) refresh_bufferline();
769 }
770 
mvprint(const int y,const int x,const char * str)771 void filebuffer::mvprint(const int y, const int x, const char *str) {
772     char buffer[MAX_BUFFER_LEN+1];
773 
774     if (current_buffer != this) return;
775 
776     sprintf(buffer, outputformat, str);
777     mvwaddnstr(win, y, x, buffer, screen_x);
778 }
779 
mvprint(const int y,const int x,const int len,const char * str)780 void filebuffer::mvprint(const int y, const int x, const int len,
781                                                    const char *str) {
782     char buffer[MAX_BUFFER_LEN+1];
783     char fmt[20];
784 
785     if (current_buffer != this) return;
786     sprintf(fmt, "%%-%ds", len);
787     sprintf(buffer, fmt, str);
788     mvwaddnstr(win, y, x, buffer, len);
789 }
790 
display_messages(const char * fmt,...)791 void filebuffer::display_messages(const char *fmt, ...) {
792     // char     msg[MAX_BUFFER_LEN+1];
793     char     buffer[MAX_BUFFER_LEN+1];
794     va_list  ap;
795     // attr_t   attr = wattr_get(win);
796 
797     if (current_buffer != this) return;
798 
799     message_dirty_flag = 1;
800 
801     va_start(ap, fmt);
802 #ifndef HAS_VSNPRINTF
803     vsprintf(buffer, fmt, ap);
804 #else
805     vsnprintf(buffer, 80, fmt, ap);
806 #endif
807     va_end(ap);
808     // sprintf(msg, outputformat, buffer);
809     setattr(win, ATTRIBUTE_message_line);
810     mvwprintw(win, screen_y-1, 0, outputformat, "");
811     mvwaddnstr(win, screen_y-1, 0, buffer, screen_x);
812     // setattr(win, attr);
813     touchwin(win);
814     wrefresh(win);
815 }
816 
display_messages(const int msgno)817 void filebuffer::display_messages(const int msgno) {
818     display_messages(big5msg_flag ? chinese_message[msgno]
819                                   : english_message[msgno]);
820 }
821 
display_messages(void)822 void filebuffer::display_messages(void) {
823     static char *buffer =
824     "  qe v" QE_VERSION
825     " (c) written by  Jiann-Ching Liu.                          ";
826 
827     if (current_buffer != this) return;
828 
829     message_dirty_flag = 0;
830 
831     // attr_t   attr = wattr_get(win);
832 
833     setattr(win, ATTRIBUTE_copyright_line);
834     mvwaddnstr(win, screen_y-1, 0, buffer, screen_x);
835     // setattr(win, attr);
836 
837     touchwin(win);
838     wrefresh(win);
839 }
840 
is_big5(void)841 int filebuffer::is_big5(void) {
842     return big5msg_flag == 0 ? 0 : 1;
843 }
844 
845 
cmd_lang_big5(void)846 int filebuffer::cmd_lang_big5(void) {
847     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
848 
849     big5msg_flag = 1;
850     display_status();
851     return 0;
852 }
853 
cmd_lang_english(void)854 int filebuffer::cmd_lang_english(void) {
855     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
856 
857     big5msg_flag = 0;
858     display_status();
859     return 0;
860 }
861 
862 #ifdef USE_ANSICOLOR
863 
setattr(WINDOW * w,int color)864 void filebuffer::setattr(WINDOW *w, int color) {
865     if (ansi_color) {
866         switch(color) {
867         case ATTRIBUTE_normal_text:
868             printf("%c[37m%c[44m", 27, 27);
869             break;
870         case ATTRIBUTE_mark_text:
871             printf("%c[37m%c[41m", 27, 27);
872             break;
873         case ATTRIBUTE_command_line:
874             printf("%c[33m%c[42m", 27, 27);
875             break;
876         case ATTRIBUTE_status_line:
877             printf("%c[37m%c[40m", 27, 27);
878             break;
879         case ATTRIBUTE_message_line:
880             printf("%c[32m%c[40m", 27, 27);
881             break;
882         case ATTRIBUTE_modified_file_line:
883             printf("%c[32m%c[40m", 27, 27);
884             break;
885         case ATTRIBUTE_copyright_line:
886             printf("%c[33m%c[40m", 27, 27);
887             break;
888         }
889     } else {
890         wattrset(w, attributes[color]);
891     }
892 }
893 
894 #endif
895 
896 
897 /***************************************************************************/
898 //
899 // resume last file buffer status
900 // Macro  : [resume]
901 // Status : Still in develop
902 //
903 
904 
cmd_resume(void)905 int filebuffer::cmd_resume(void) {
906     FILE *fd;
907     char  init_str[8000];
908     int   idx;
909     char  fname[MAX_BUFFER_LEN+1];
910     char  arg1[MAX_BUFFER_LEN+1];
911     char  arg2[MAX_BUFFER_LEN+1];
912 
913     char   filename[500];
914     sprintf(filename, "/root/%s", DEFAULT_USER_STATUS);   //
915     if ((fd = fopen(filename, "r")) != NULL) {
916        while (fgets(init_str,MAX_BUFFER_LEN, fd) != NULL) {
917           for (idx = strlen(init_str)-1; idx >= 0; idx--) {
918             if (init_str[idx] == '\r' || init_str[idx] == '\n' ||
919                 init_str[idx] == ' '  || init_str[idx] == '\t') {
920                 init_str[idx] = '\0';                     // make string close here
921             } else break;
922        }
923     sscanf(init_str, "%s %s %s", fname, arg1, arg2);      // %s %s %s   -- filename linenumber column
924        for (int finish = 0; !finish; ) {
925          if (access(fname,F_OK) == 0)
926             {
927                 cmd_edit(fname);                          // load file in to buffer
928                 cmd_goto_currline(atoi(arg1),atoi(arg2)); // goto specified line and column
929               finish = 1;
930             }
931        }
932      } // end of while
933     }
934     fclose(fd);
935     return 0;
936 }
937