1 /*
2  *  fbcmdmark.cc
3  *
4  *  Copyright (C) 1998	Jiann-Ching Liu
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "qe_config.h"
11 #include "filebuffer.h"
12 #include "colors.h"
13 #include "mark.h"
14 #include "messages.h"
15 
16 
17 static int  copyok = 0;
18 
ca_attrset(void)19 void filebuffer::ca_attrset(void) {
20     if (current_mark != UNKNOW_MARK && current_mark.fb == this) {
21 	int u = minimum(current_mark.fn, current_mark.ln);
22 	int d = maximum(current_mark.fn, current_mark.ln);
23 	if (buffer_y >= u && buffer_y <= d) {
24 	    if (current_mark == BLOCK_MARK) {
25 		int bml = minimum(current_mark.fc, current_mark.lc);
26 		int bmr = maximum(current_mark.fc, current_mark.lc);
27 		setattr(win, (buffer_x >= bml && buffer_x <= bmr) ?
28 			       ATTRIBUTE_mark_text : ATTRIBUTE_normal_text);
29 	    } else {
30 		setattr(win, ATTRIBUTE_mark_text);
31 	    }
32 	} else {
33 	    setattr(win, ATTRIBUTE_normal_text);
34 	}
35     } else {
36 	setattr(win, ATTRIBUTE_normal_text);
37     }
38 }
39 
substrncpy_with_blankfill(char * buffer,const char * str,const int n,const int len)40 static void substrncpy_with_blankfill(char *buffer, const char *str,
41 		 const int n, const int len) {
42 
43     int l = minimum(len, MAX_BUFFER_LEN-1);
44     strncpy(buffer, (strlen(str) < (unsigned int) n) ? " " : &str[n], l);
45     for (int i = strlen(buffer); i < l; i++)
46 	buffer[i] = ' ';
47     buffer[l] = '\0';
48 }
49 
cmd_clear_marks(void)50 int filebuffer::cmd_clear_marks(void) {
51     marksp = -1;
52     return 0;
53 }
54 
cmd_pushmark(void)55 int filebuffer::cmd_pushmark(void) {
56     int  need_redraw = (current_mark.fb == this);
57 
58     if (push_mark()) {
59 	if (need_redraw) refresh_clientarea(1);
60     } else {
61 	display_messages(MSG_TOO_MANY_MARK_SAVE);
62     }
63     return 0;
64 }
65 
cmd_popmark(void)66 int filebuffer::cmd_popmark(void) {
67     int  need_redraw = (current_mark.fb == this);
68 
69     if (pop_mark()) {
70 	if (need_redraw || current_mark.fb == this) refresh_clientarea(1);
71     } else {
72 	display_messages(MSG_NO_MARK_SAVED);
73     }
74     return 0;
75 }
76 
cmd_markline(void)77 int filebuffer::cmd_markline(void) {
78     if (current_mark == UNKNOW_MARK) {
79 	/* mark line */
80 	current_mark.fb    = this;
81 	current_mark.first = current;
82 	current_mark.last  = current;
83 	current_mark.fn    = buffer_y;
84 	current_mark.ln    = buffer_y;
85 	current_mark.settype(LINE_MARK);
86 	refresh_clientarea(1);
87     } else if (current_mark.fb != this) {
88 	display_messages(MSG_CONFLICT_EXIST_MARK);
89     } else if (current_mark == LINE_MARK) {
90 	current_mark.last  = current;
91 	current_mark.ln    = buffer_y;
92 	refresh_clientarea(1);
93     } else {
94 	display_messages(MSG_CONFLICT_EXIST_MARK);
95     }
96     return 0;
97 }
98 
cmd_markblock(void)99 int filebuffer::cmd_markblock(void) {
100     if (current_mark == UNKNOW_MARK) {
101 	current_mark.fb    = this;
102 	current_mark.first = current;
103 	current_mark.fn    = buffer_y;
104 	current_mark.fc    = buffer_x;
105 	current_mark.last  = current;
106 	current_mark.ln    = buffer_y;
107 	current_mark.lc    = buffer_x;
108 	current_mark.settype(BLOCK_MARK);
109 	refresh_clientarea(1);
110     } else if (current_mark.fb != this) {
111 	display_messages(MSG_CONFLICT_EXIST_MARK);
112     } else if (current_mark == BLOCK_MARK) {
113        current_mark.last  = current;
114 	current_mark.ln    = buffer_y;
115 	current_mark.lc    = buffer_x;
116 	refresh_clientarea(1);
117     } else {
118 	display_messages(MSG_CONFLICT_EXIST_MARK);
119     }
120     return 0;
121 }
122 
cmd_markchar(void)123 int filebuffer::cmd_markchar(void) {
124     return 0;
125 }
126 
cmd_unmark(void)127 int filebuffer::cmd_unmark(void) {
128     current_mark.settype(UNKNOW_MARK);
129     if (current_mark.fb == this) refresh_clientarea(1);
130     current_mark.fb = NULL;
131     return 0;
132 }
133 
cmd_copymark(void)134 int filebuffer::cmd_copymark(void) {
135     copyok = 0;
136 
137     if (current_mark == UNKNOW_MARK) {
138 	display_messages(MSG_NO_MARKED_AREA);
139 	return 0;
140     }
141 
142     if (read_only) {
143 	display_messages(MSG_READ_ONLY_FILE);
144 	return 0;
145     }
146 
147 
148     write_workbuffer(QE_IF_NECESSARY);
149     int  u = minimum(current_mark.fn, current_mark.ln);
150     int  d = maximum(current_mark.fn, current_mark.ln);
151 
152     if (current_mark == LINE_MARK) {
153 	if (buffer_y < u || buffer_y >= d || current_mark.fb != this) {
154 	    linebuffer *ptr;
155 	    linebuffer *q = new linebuffer("");
156 	    linebuffer *f = q;
157 
158 	    ptr = (current_mark.fn < current_mark.ln) ? current_mark.first :
159 							current_mark.last;
160 
161 	    for (int i = u; i <= d; i++, ptr = ptr->next) {
162 		q->next 	  = new linebuffer(*ptr);
163 		q->next->previous = q;
164 		q		  = q->next;
165 	    }
166 	    q->next		    = current->next;
167 	    q->next->previous	    = q;
168 	    current->next	    = f->next;
169 	    current->next->previous = current;
170 	    delete f;
171 	    total_line = total_line + d - u + 1;
172 	    current_mark.renumber();
173 	    // newline_flag = 1;
174 	    dirty_buffer(1);
175 	    refresh_clientarea(0);
176 	    copyok = 1;
177 	} else {
178 	    display_messages(MSG_S_T_CONFLICT);
179 	}
180     } else if (current_mark == BLOCK_MARK) {
181 	int  from = minimum(current_mark.fc, current_mark.lc);
182 	int  to   = maximum(current_mark.fc, current_mark.lc);
183 
184 	if (current_mark.fb == this &&
185 	   (buffer_y <= d) && (buffer_y + (d - u + 1) > u) &&
186 	   ! (buffer_y == u && (buffer_x > to || buffer_x <= from))) {
187 	    display_messages(MSG_S_T_CONFLICT);
188 	} else {
189 	    char	  wkbf[MAX_BUFFER_LEN+MAX_BUFFER_LEN+1];
190 	    linebuffer	  *p, *q = current;
191 	    int 	  mklen = to - from + 1;
192 
193 	    p = (current_mark.fn < current_mark.ln) ? current_mark.first :
194 						      current_mark.last;
195 
196 	    for (int i = u; i <= d; i++, p = p->next) {
197 		if (q == tail) {
198 		    q = new linebuffer("");
199 		    q->previous = tail->previous;
200 		    tail->previous->next = q;
201 		    tail->previous = q;
202 		    q->next = tail;
203 		    total_line++;
204 		}
205 
206 		substrncpy_with_blankfill(wkbf, q->getString(), 0, buffer_x);
207 		substrncpy_with_blankfill(&wkbf[buffer_x], p->getString(),
208 								 from, mklen);
209 		if (q->getLength() > (unsigned int) buffer_x)
210 		    strcpy(&wkbf[buffer_x + mklen], &((*q)[buffer_x]));
211 		wkbf[MAX_BUFFER_LEN] = '\0';
212 		// q->assign(wkbf);
213 		*q = wkbf;
214 		q = q->next;
215 	    }
216 
217 	    if (buffer_y == u && buffer_x < from) {
218 		current_mark.fc += mklen;
219 		current_mark.lc += mklen;
220 	    }
221 	    dirty_buffer(1);
222 	    refresh_clientarea(0);
223 	    copyok = 1;
224 	}
225     }
226     load_workbuffer();
227     return 0;
228 }
229 
230 
cmd_overlayblock(void)231 int filebuffer::cmd_overlayblock(void) {
232     if (read_only) {
233 	display_messages(MSG_READ_ONLY_FILE);
234 	return 0;
235     }
236 
237     if (current_mark == BLOCK_MARK) {
238 	int  u = minimum(current_mark.fn, current_mark.ln);
239 	int  d = maximum(current_mark.fn, current_mark.ln);
240 	int  from = minimum(current_mark.fc, current_mark.lc);
241 	int  to   = maximum(current_mark.fc, current_mark.lc);
242 	int  mklen = to - from + 1;
243 
244 	write_workbuffer(QE_IF_NECESSARY);
245 
246 	if (current_mark.fb == this &&
247 	   (buffer_y <= d) && (buffer_y + (d - u + 1) > u) &&
248 	   ! (buffer_x > to || buffer_x + mklen <= from)) {
249 	    display_messages(MSG_S_T_CONFLICT);
250 	} else {
251 	    char	  wkbf[MAX_BUFFER_LEN+MAX_BUFFER_LEN+1];
252 	    linebuffer	  *p, *q = current;
253 
254 	    p = (current_mark.fn < current_mark.ln) ? current_mark.first :
255 						      current_mark.last;
256 
257 	    for (int i = u; i <= d; i++, p = p->next) {
258 		if (q == tail) {
259 		    q = new linebuffer("");
260 		    q->previous = tail->previous;
261 		    tail->previous->next = q;
262 		    tail->previous = q;
263 		    q->next = tail;
264 		    total_line++;
265 		}
266 
267 		substrncpy_with_blankfill(wkbf, q->getString(), 0, buffer_x);
268 		substrncpy_with_blankfill(&wkbf[buffer_x], p->getString(),
269 								  from, mklen);
270 		if (q->getLength() > (unsigned int) buffer_x + mklen)
271 		    strcpy(&wkbf[buffer_x + mklen], &((*q)[buffer_x + mklen]));
272 		wkbf[MAX_BUFFER_LEN] = '\0';
273 		// q->assign(wkbf);
274 		*q = wkbf;
275 		q = q->next;
276 	    }
277 
278 	    if (buffer_y == u && buffer_x < from) {
279 		current_mark.fc += mklen;
280 		current_mark.lc += mklen;
281 	    }
282 	    dirty_buffer(1);
283 	    refresh_clientarea(0);
284 	}
285 
286 	load_workbuffer();
287     } else {
288 	display_messages(MSG_BLOCK_MARK_REQ);
289     }
290     return 0;
291 }
292 
cmd_movemark(void)293 int filebuffer::cmd_movemark(void) {
294     if (current_mark == UNKNOW_MARK) {
295 	display_messages(MSG_NO_MARKED_AREA);
296 	return 0;
297     }
298 
299     if (read_only) {
300 	display_messages(MSG_READ_ONLY_FILE);
301 	return 0;
302     }
303 
304     cmd_copymark();
305     if (copyok) cmd_deletemark();
306     return 0;
307 }
308 
cmd_deletemark(void)309 int filebuffer::cmd_deletemark(void) {
310     // wprintw(win, "[delete mark]");
311     if (current_mark == UNKNOW_MARK) {
312 	display_messages(MSG_NO_MARKED_AREA);
313 	return 0;
314     }
315 
316     if (current_mark.fb->read_only) {
317 	display_messages(MSG_READ_ONLY_FILE);
318 	return 0;
319     }
320 
321     filebuffer *ptr = current_mark.fb;
322     int        u    = minimum(current_mark.fn, current_mark.ln);
323     int        d    = maximum(current_mark.fn, current_mark.ln);
324     linebuffer *lbf = (current_mark.fn < current_mark.ln) ?
325 					current_mark.first : current_mark.last;
326 
327     current_mark.fb->write_workbuffer(QE_IF_NECESSARY);
328 
329     if (current_mark == LINE_MARK) {
330 	int yy = ptr->buffer_y;
331 
332 	if (ptr->buffer_y >= u && ptr->buffer_y <= d) {
333 	    if ((yy = u - 1) < 0) yy = 0;
334 	} else if (ptr->buffer_y > d) {
335 	    yy = yy - (d - u + 1);
336 	}
337 
338 	quiet_flag = 1;
339 	ptr->moveto(u, ptr->buffer_x);
340 	for (int i = u; i <= d; i++) ptr->cmd_deleteline();
341 	ptr->moveto(yy, ptr->buffer_x);
342 	quiet_flag = 0;
343 
344     } else if (current_mark == BLOCK_MARK) {
345 	int  from  = minimum(current_mark.fc, current_mark.lc);
346 	int  to    = maximum(current_mark.fc, current_mark.lc);
347 	int  mklen = to - from + 1;
348 
349 	for (int i = u; i <= d; i++, lbf = lbf->next) {
350 	    int  len = lbf->getLength();
351 
352 	    if (from <= len) {
353 		if (to >= len) {
354 		    (*lbf)[from] = '\0';
355 		} else {
356 		    for (int j = to+1; j <= len; j++)
357 			(*lbf)[j - mklen] = (*lbf)[j];
358 		}
359 		lbf->setLength();
360 	    }
361 	}
362     }
363 
364     current_mark.fb->dirty_buffer(1);
365     current_mark.settype();
366 
367     if (current_mark.fb == this) {
368 	// newline_flag = 1;
369 	load_workbuffer();
370 	refresh_clientarea(0);
371     }
372 
373     return 0;
374 }
375 
cmd_fillmark(void)376 int filebuffer::cmd_fillmark(void) {
377     char  tmpbuf[MAX_BUFFER_LEN+1];
378     int   i, magic;
379 
380 
381     if (current_mark != UNKNOW_MARK && current_mark.fb->read_only) {
382 	display_messages(MSG_READ_ONLY_FILE);
383 	return 0;
384     }
385 
386     if (current_mark == BLOCK_MARK) {
387 	display_messages(MSG_TYPE_A_CHARACTER);
388 	if ((magic = getfirstkey()) >= ' ' && magic <= 126) {
389 	    int  from = minimum(current_mark.fc, current_mark.lc);
390 	    int  to   = maximum(current_mark.fc, current_mark.lc);
391 
392 	    int  lf = minimum(current_mark.fn, current_mark.ln);
393 	    int  lt = maximum(current_mark.fn, current_mark.ln);
394 
395 	    current_mark.fb->write_workbuffer(QE_IF_NECESSARY);
396 
397 	    linebuffer *lb = (current_mark.fn < current_mark.ln) ?
398 			      current_mark.first : current_mark.last;
399 
400 /*
401 	    if (current_mark.fb == this)
402 		if (buffer_y >= lf && buffer_y <= lt)
403 		    write_workbuffer();
404 */
405 
406 	    for (int j = lf; j <= lt; j++, lb = lb->next) {
407 		strncpy(tmpbuf, lb->getString(), MAX_BUFFER_LEN);
408 		int  len = strlen(tmpbuf);
409 
410 		for (i = len; i < from; i++)
411 		    tmpbuf[i] = ' ';
412 		for (i = from; i <= to; i++)
413 		    tmpbuf[i] = magic;
414 		tmpbuf[maximum(i, len)] = '\0';
415 		// lb->assign(tmpbuf);
416 		*lb = tmpbuf;
417 	    }
418 	    // current_mark.fb->newline_flag = 1;
419 	    current_mark.fb->dirty_buffer(1);
420 	    if (current_mark.fb == this) {
421 		if (buffer_y >= lf && buffer_y <= lt)
422 		    load_workbuffer();
423 		//  newline_flag = 1;
424 		refresh_clientarea(0);
425 		// refresh_bufferline();
426 	    }
427 	    display_messages("mark filled: %c", magic);
428 	    // display_messages("%d %d", lf, lt);
429 	} else {
430 	    display_messages("canceled");
431 	}
432     } else if (current_mark == UNKNOW_MARK) {
433 	display_messages(MSG_NO_MARKED_AREA);
434     } else {
435 	display_messages(MSG_BLOCK_MARK_REQ);
436     }
437     return 0;
438 }
439 
cmd_beginmark(void)440 int filebuffer::cmd_beginmark(void) {
441     if (current_mark != UNKNOW_MARK) {
442 	filebuffer *ptr = current_mark.fb;
443 	linebuffer *ltr;
444 	int	   line;
445 	int	   need_redraw = 0;
446 
447 	write_workbuffer(QE_IF_NECESSARY);
448 
449 	if (current_mark.fn < current_mark.ln) {
450 	    line = current_mark.fn;
451 	    ltr  = current_mark.first;
452 	} else {
453 	    line = current_mark.ln;
454 	    ltr  = current_mark.last;
455 	}
456 
457 	ptr->buffer_y = line;
458 	ptr->current  = ltr;
459 
460 	if (line < ptr->top_line_no ||
461 	    line > ptr->top_line_no + ptr->screen_y - 4) {
462 	    ptr->top_line_no = line - 1;
463 	    ptr->cursor_y    = 1;
464 	    ptr->topline     = ltr->previous;
465 	    need_redraw      = 1;
466 	} else {
467 	    ptr->cursor_y = ptr->buffer_y - ptr->top_line_no;
468 	}
469 
470 	if (current_mark == BLOCK_MARK) {
471 	    int raw = minimum(current_mark.fc, current_mark.lc);
472 	    if (raw < (int) ptr->left_col_no ||
473 		raw > (int) ptr->left_col_no + ptr->screen_x) {
474 		if (raw < ptr->screen_x) {
475 		    ptr->left_col_no = 0;
476 		} else {
477 		    ptr->left_col_no = raw - ptr->screen_x + 1;
478 		}
479 		need_redraw	 = 1;
480 	    }
481 	    ptr->buffer_x = raw;
482 	    ptr->cursor_x = ptr->buffer_x - ptr->left_col_no;
483 	}
484 
485 	ptr->load_workbuffer();
486 
487 	if (ptr != this) {
488 	    current_buffer = ptr;
489 	    return 1;
490 	} else if (need_redraw) {
491 	    refresh_clientarea(0);
492 	    // refresh_bufferline();
493 	}
494     } else {
495 	display_messages(MSG_NO_MARKED_AREA);
496     }
497     return 0;
498 }
499 
cmd_endmark(void)500 int filebuffer::cmd_endmark(void) {
501     if (current_mark != UNKNOW_MARK) {
502 	filebuffer *ptr = current_mark.fb;
503 	linebuffer *ltr;
504 	int	   line;
505 	int	   need_redraw = 0;
506 
507 	write_workbuffer(QE_IF_NECESSARY);
508 
509 	if (current_mark.fn > current_mark.ln) {
510 	    line = current_mark.fn;
511 	    ltr  = current_mark.first;
512 	} else {
513 	    line = current_mark.ln;
514 	    ltr  = current_mark.last;
515 	}
516 
517 	ptr->buffer_y = line;
518 	ptr->current  = ltr;
519 
520 	if (line < ptr->top_line_no ||
521 	    line > ptr->top_line_no + ptr->screen_y - 4) {
522 	    ptr->top_line_no = line;
523 	    ptr->topline     = ltr;
524 	    ptr->cursor_y    = 0;
525 	    for (ptr->cursor_y = 0; ptr->cursor_y < ptr->screen_y - 5 &&
526 				    ptr->top_line_no != -1; ptr->cursor_y++) {
527 		ptr->top_line_no--;
528 		ptr->topline = ptr->topline->previous;
529 	    }
530 	    need_redraw      = 1;
531 	} else {
532 	    ptr->cursor_y = ptr->buffer_y - ptr->top_line_no;
533 	}
534 
535 	if (current_mark == BLOCK_MARK) {
536 	    int raw = maximum(current_mark.fc, current_mark.lc);
537 	    if (raw < (int) ptr->left_col_no ||
538 		raw > (int) ptr->left_col_no + ptr->screen_x) {
539 		if (raw < ptr->screen_x) {
540 		    ptr->left_col_no = 0;
541 		} else {
542 		    ptr->left_col_no = raw - ptr->screen_x + 1;
543 		}
544 		need_redraw	 = 1;
545 	    }
546 	    ptr->buffer_x = raw;
547 	    ptr->cursor_x = ptr->buffer_x - ptr->left_col_no;
548 	}
549 
550 	ptr->load_workbuffer();
551 
552 	if (ptr != this) {
553 	    current_buffer = ptr;
554 	    return 1;
555 	} else if (need_redraw) {
556 	    refresh_clientarea(0);
557 	}
558     } else {
559 	display_messages(MSG_NO_MARKED_AREA);
560     }
561     return 0;
562 }
563 
cmd_shiftleft(void)564 int filebuffer::cmd_shiftleft(void) {
565     char  tmpbuf[MAX_BUFFER_LEN+1];
566     int   i;
567 
568     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
569 
570     if (current_mark == BLOCK_MARK || current_mark == LINE_MARK) {
571 	if (current_mark.fb->read_only) {
572 	    display_messages(MSG_READ_ONLY_FILE);
573 	    return 0;
574 	}
575 
576 	int  from = minimum(current_mark.fc, current_mark.lc);
577 	int  lf = minimum(current_mark.fn, current_mark.ln);
578 	int  lt = maximum(current_mark.fn, current_mark.ln);
579 
580 	if (current_mark == LINE_MARK) from = 0;
581 
582 	linebuffer *lb = (current_mark.fn < current_mark.ln) ?
583 			  current_mark.first : current_mark.last;
584 
585 	if (current_mark.fb == this)
586 	    if (buffer_y >= lf && buffer_y <= lt)
587 		write_workbuffer(QE_IF_NECESSARY);
588 
589 	for (int j = lf; j <= lt; j++, lb = lb->next) {
590 	    strncpy(tmpbuf, lb->getString(), MAX_BUFFER_LEN-1);
591 	    int  len = strlen(tmpbuf);
592 
593 	    for (i = from; i < len; i++)
594 		tmpbuf[i] = tmpbuf[i+1];
595 	    tmpbuf[maximum(from, len)] = '\0';
596 	    // lb->assign(tmpbuf);
597 	    *lb = tmpbuf;
598 	}
599 	// current_mark.fb->newline_flag = 1;
600 	current_mark.fb->dirty_buffer(1);
601 	if (current_mark.fb->buffer_y >= lf && current_mark.fb->buffer_y <= lt)
602 	    current_mark.fb->load_workbuffer();
603 
604 	if (current_mark.fb == this) {
605 	    refresh_clientarea(0);
606 	    if (buffer_y < lf || buffer_y > lt) refresh_bufferline();
607 	}
608     } else if (current_mark == UNKNOW_MARK) {
609 	display_messages(MSG_NO_MARKED_AREA);
610     } else {
611 	display_messages(MSG_BLOCK_MARK_REQ);
612     }
613     return 0;
614 }
615 
cmd_shiftright(void)616 int filebuffer::cmd_shiftright(void) {
617     char  tmpbuf[MAX_BUFFER_LEN+1];
618     int   i;
619 
620     if (keep_in_menu == MENU_IN_MENU) keep_in_menu = MENU_KEEP_IN_MENU;
621 
622     if (current_mark == BLOCK_MARK || current_mark == LINE_MARK) {
623 	if (current_mark.fb->read_only) {
624 	    display_messages(MSG_READ_ONLY_FILE);
625 	    return 0;
626 	}
627 
628 	int  from = minimum(current_mark.fc, current_mark.lc);
629 	int  lf = minimum(current_mark.fn, current_mark.ln);
630 	int  lt = maximum(current_mark.fn, current_mark.ln);
631 
632 	if (current_mark == LINE_MARK) from = 0;
633 
634 	linebuffer *lb = (current_mark.fn < current_mark.ln) ?
635 			  current_mark.first : current_mark.last;
636 
637 	if (current_mark.fb == this)
638 	    if (buffer_y >= lf && buffer_y <= lt)
639 		write_workbuffer(QE_IF_NECESSARY);
640 
641 	for (int j = lf; j <= lt; j++, lb = lb->next) {
642 	    strncpy(tmpbuf, lb->getString(), MAX_BUFFER_LEN-3);
643 	    tmpbuf[MAX_BUFFER_LEN-3] = '\0';
644 	    int  len = strlen(tmpbuf);
645 
646 	    for (i = len; i < from; i++)
647 		tmpbuf[i] = ' ';
648 
649 	    tmpbuf[len = (maximum(from, len))] = '\0';
650 
651 	    for (i = len; i > from; i--)
652 		tmpbuf[i] = tmpbuf[i-1];
653 	    tmpbuf[from] = ' ';
654 	    // lb->assign(tmpbuf);
655 	    *lb = tmpbuf;
656 	}
657 	current_mark.fb->dirty_buffer(1);
658 	if (current_mark.fb->buffer_y >= lf && current_mark.fb->buffer_y <= lt)
659 	    current_mark.fb->load_workbuffer();
660 
661 	if (current_mark.fb == this) {
662 	    refresh_clientarea(0);
663 	    if (buffer_y < lf || buffer_y > lt) refresh_bufferline();
664 	}
665     } else if (current_mark == UNKNOW_MARK) {
666 	display_messages(MSG_NO_MARKED_AREA);
667     } else {
668 	display_messages(MSG_BLOCK_MARK_REQ);
669     }
670     return 0;
671 }
672 
unmark_all_mark(void)673 void filebuffer::unmark_all_mark(void) {
674     if (current_mark.fb == this) current_mark.settype(UNKNOW_MARK);
675 
676     for (int i = 0; i <= marksp; i++)
677 	if (markstack[i].fb == this) markstack[i].settype(UNKNOW_MARK);
678 }
679 
fix_all_mark_position(const int tp)680 void filebuffer::fix_all_mark_position(const int tp) {
681     fix_mark_position(current_mark, tp);
682 
683     for (int i = 0; i <= marksp; i++)
684 	fix_mark_position(markstack[i], tp);
685 }
686 
fix_mark_position(mark & mk,const int tp)687 void filebuffer::fix_mark_position(mark &mk, const int tp) {
688     if (mk != UNKNOW_MARK && mk.fb == this) {
689 	int	    *un,  *dn;
690 	linebuffer  **ul, **dl;
691 
692 	if (mk.fn < mk.ln) {
693 	    un = &mk.fn;
694 	    ul = &mk.first;
695 	    dn = &mk.ln;
696 	    dl = &mk.last;
697 	} else {
698 	    dn = &mk.fn;
699 	    dl = &mk.first;
700 	    un = &mk.ln;
701 	    ul = &mk.last;
702 	}
703 
704 	switch (tp) {
705 	case FIX_MARK_INSERT_LINE:
706 	    // mk.renumber();
707 	    if (buffer_y <= *un) (*un)++;
708 	    if (buffer_y <= *dn) (*dn)++;
709 	    break;
710 	case FIX_MARK_DELETE_LINE:
711 	    if (buffer_y < *un) {
712 		(*un)--;
713 		(*dn)--;
714 	    } else if (buffer_y <= *dn) {
715 		if (buffer_y == *un && buffer_y == *dn) {
716 		    mk.settype(UNKNOW_MARK);
717 		} else if (buffer_y == *un) {
718 		    *ul = (*ul)->next;
719 		} else if (buffer_y == *dn) {
720 		    *dl = (*dl)->previous;
721 		}
722 		(*dn)--;
723 	    }
724 	    break;
725 	case FIX_MARK_JOIN_LINE:
726 	    break;
727 	}
728     }
729 }
730 
push_mark(void)731 int filebuffer::push_mark(void) {
732     if (marksp >= markstacksize - 1) return 0;
733 
734     markstack[++marksp] = current_mark;
735     current_mark.settype(UNKNOW_MARK);
736     return 1;
737 }
738 
pop_mark(void)739 int filebuffer::pop_mark(void) {
740     if (marksp < 0) return 0;
741 
742     current_mark = markstack[marksp--];
743     return 1;
744 }
745