1 /* Copyright (c) 2008, 2009
2  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4  *      Micah Cowan (micah@cowan.name)
5  *      Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6  * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9  * Copyright (c) 1987 Oliver Laumann
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 3, or (at your option)
14  * any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program (see the file COPYING); if not, see
23  * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
25  *
26  ****************************************************************
27  */
28 
29 #include <sys/types.h>
30 #include <ctype.h>
31 
32 #include "config.h"
33 #include "screen.h"
34 #include "mark.h"
35 #include "extern.h"
36 
37 #ifdef COPY_PASTE
38 
39 /*
40  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
41  *
42  * WARNING: these routines use the global variables "fore" and
43  * "flayer" to make things easier.
44  *
45  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
46  */
47 
48 static int  is_letter __P((int));
49 static void nextword __P((int *, int *, int, int));
50 static int  linestart __P((int));
51 static int  lineend __P((int));
52 static int  rem __P((int, int , int , int , int , char *, int));
53 static int  eq __P((int, int ));
54 static int  MarkScrollDownDisplay __P((int));
55 static int  MarkScrollUpDisplay __P((int));
56 
57 static void MarkProcess __P((char **, int *));
58 static void MarkAbort __P((void));
59 static void MarkRedisplayLine __P((int, int, int, int));
60 static int  MarkRewrite __P((int, int, int, struct mchar *, int));
61 
62 extern struct layer *flayer;
63 extern struct display *display, *displays;
64 extern struct win *fore;
65 extern struct mline mline_blank, mline_null;
66 extern struct mchar mchar_so;
67 
68 #ifdef FONT
69 int pastefont = 1;
70 #endif
71 
72 struct LayFuncs MarkLf =
73 {
74   MarkProcess,
75   MarkAbort,
76   MarkRedisplayLine,
77   DefClearLine,
78   MarkRewrite,
79   DefResize,
80   DefRestore,
81   0
82 };
83 
84 int join_with_cr =  0;
85 int compacthist = 0;
86 
87 unsigned char mark_key_tab[256]; /* this array must be initialised first! */
88 
89 static struct markdata *markdata;
90 
91 
92 /*
93  * VI like is_letter: 0 - whitespace
94  *                    1 - letter
95  *		      2 - other
96  */
is_letter(c)97 static int is_letter(c)
98 char c;
99 {
100   if ((c >= 'a' && c <= 'z') ||
101       (c >= 'A' && c <= 'Z') ||
102       (c >= '0' && c <= '9') ||
103       c == '_' || c == '.' ||
104       c == '@' || c == ':' ||
105       c == '%' || c == '!' ||
106       c == '-' || c == '+')
107     /* thus we can catch email-addresses as a word :-) */
108     return 1;
109   else if (c != ' ')
110     return 2;
111   return 0;
112 }
113 
114 static int
linestart(y)115 linestart(y)
116 int y;
117 {
118   register int x;
119   register unsigned char *i;
120 
121   for (x = markdata->left_mar, i = WIN(y)->image + x; x < fore->w_width - 1; x++)
122     if (*i++ != ' ')
123       break;
124   if (x == fore->w_width - 1)
125     x = markdata->left_mar;
126   return x;
127 }
128 
129 static int
lineend(y)130 lineend(y)
131 int y;
132 {
133   register int x;
134   register unsigned char *i;
135 
136   for (x = markdata->right_mar, i = WIN(y)->image + x; x >= 0; x--)
137     if (*i-- != ' ')
138       break;
139   if (x < 0)
140     x = markdata->left_mar;
141   return x;
142 }
143 
144 /*
145  * nextchar sets *xp to the num-th occurrence of the target in the line.
146  *
147  * Returns -1 if the target doesn't appear num times, 0 otherwise.
148  */
149 static int
nextchar(int * xp,int * yp,int direction,char target,int num)150 nextchar(int *xp, int *yp, int direction, char target, int num)
151 {
152   int width;  /* width of the current window. */
153   int x;      /* x coordinate of the current cursor position. */
154   int step;   /* amount to increment x (+1 or -1) */
155   int adjust; /* Final adjustment of cursor position. */
156   char *displayed_line; /* Line in which search takes place. */
157 
158   debug("nextchar\n");
159 
160   x = *xp;
161   step = 1;
162   adjust = 0;
163   width = fore->w_width;
164   displayed_line = (char *)WIN(*yp) -> image;
165 
166   switch(direction) {
167     case 't':
168       adjust = -1; /* fall through */
169     case 'f':
170       step = 1;
171       break;
172     case 'T':
173       adjust = 1; /* fall through */
174     case 'F':
175       step = -1;
176       break;
177     default:
178       ASSERT(0);
179   }
180 
181   x += step;
182 
183   debug1("ml->image = %s\n", displayed_line);
184   debug2("num = %d, width = %d\n",num, width);
185   debug2("x = %d target = %c\n", x, target );
186 
187   for ( ;x>=0 && x <= width; x += step) {
188     if (displayed_line[x] == target) {
189       if (--num == 0) {
190         *xp = x + adjust;
191         return 0;
192       }
193     }
194   }
195   return -1;
196 }
197 
198 /*
199  *  nextword calculates the cursor position of the num'th word.
200  *  If the cursor is on a word, it counts as the first.
201  *  NW_BACK:		search backward
202  *  NW_ENDOFWORD:	find the end of the word
203  *  NW_MUSTMOVE:	move at least one char
204  *  NW_BIG:             match WORDs not words
205  */
206 
207 #define NW_BACK		(1<<0)
208 #define NW_ENDOFWORD	(1<<1)
209 #define NW_MUSTMOVE	(1<<2)
210 #define NW_BIG		(1<<3)
211 
212 
213 
214 static void
nextword(xp,yp,flags,num)215 nextword(xp, yp, flags, num)
216 int *xp, *yp, flags, num;
217 {
218   int xx = fore->w_width, yy = fore->w_histheight + fore->w_height;
219   register int sx, oq, q, x, y;
220   struct mline *ml;
221 
222   x = *xp;
223   y = *yp;
224   sx = (flags & NW_BACK) ? -1 : 1;
225   if ((flags & NW_ENDOFWORD) && (flags & NW_MUSTMOVE))
226     x += sx;
227   ml = WIN(y);
228   for (oq = -1; ; x += sx, oq = q)
229     {
230       if (x >= xx || x < 0)
231 	q = 0;
232       else if (flags & NW_BIG)
233         q = ml->image[x] == ' ';
234       else
235         q = is_letter(ml->image[x]);
236       if (oq >= 0 && oq != q)
237 	{
238 	  if (oq == 0 || !(flags & NW_ENDOFWORD))
239 	    *xp = x;
240 	  else
241 	    *xp = x-sx;
242 	  *yp = y;
243 	  if ((!(flags & NW_ENDOFWORD) && q) ||
244 	      ((flags & NW_ENDOFWORD) && oq))
245 	    {
246 	      if (--num <= 0)
247 	        return;
248 	    }
249 	}
250       if (x == xx)
251 	{
252 	  x = -1;
253 	  if (++y >= yy)
254 	    return;
255 	  ml = WIN(y);
256 	}
257       else if (x < 0)
258 	{
259 	  x = xx;
260 	  if (--y < 0)
261 	    return;
262 	  ml = WIN(y);
263 	}
264     }
265 }
266 
267 
268 /*
269  * y1, y2 are WIN coordinates
270  *
271  * redisplay:	0  -  just copy
272  * 		1  -  redisplay + copy
273  *		2  -  count + copy, don't redisplay
274  */
275 
276 static int
rem(x1,y1,x2,y2,redisplay,pt,yend)277 rem(x1, y1, x2, y2, redisplay, pt, yend)
278 int x1, y1, x2, y2, redisplay, yend;
279 char *pt;
280 {
281   int i, j, from, to, ry, c;
282   int l = 0;
283   unsigned char *im;
284   struct mline *ml;
285 #ifdef FONT
286   int cf, cfx, font;
287   unsigned char *fo, *fox;
288 #endif
289 
290   markdata->second = 0;
291   if (y2 < y1 || ((y2 == y1) && (x2 < x1)))
292     {
293       i = y2;
294       y2 = y1;
295       y1 = i;
296       i = x2;
297       x2 = x1;
298       x1 = i;
299     }
300   ry = y1 - markdata->hist_offset;
301 
302   i = y1;
303   if (redisplay != 2 && pt == 0 && ry <0)
304     {
305       i -= ry;
306       ry = 0;
307     }
308   for (; i <= y2; i++, ry++)
309     {
310       if (redisplay != 2 && pt == 0 && ry > yend)
311 	break;
312       ml = WIN(i);
313       from = (i == y1) ? x1 : 0;
314       if (from < markdata->left_mar)
315 	from = markdata->left_mar;
316       for (to = fore->w_width, im = ml->image + to; to >= 0; to--)
317         if (*im-- != ' ')
318 	  break;
319       if (i == y2 && x2 < to)
320 	to = x2;
321       if (to > markdata->right_mar)
322 	to = markdata->right_mar;
323       if (redisplay == 1 && from <= to && ry >=0 && ry <= yend)
324 	MarkRedisplayLine(ry, from, to, 0);
325       if (redisplay != 2 && pt == 0)	/* don't count/copy */
326 	continue;
327       j = from;
328 #ifdef DW_CHARS
329       if (dw_right(ml, j, fore->w_encoding))
330 	j--;
331 #endif
332       im = ml->image + j;
333 #ifdef FONT
334       fo = ml->font + j;
335       fox = ml->fontx + j;
336       font = ASCII;
337 #endif
338       for (; j <= to; j++)
339 	{
340 	  c = (unsigned char)*im++;
341 #ifdef FONT
342 	  cf = (unsigned char)*fo++;
343 	  cfx = (unsigned char)*fox++;
344 # ifdef UTF8
345 	  if (fore->w_encoding == UTF8)
346 	    {
347 	      c |= cf << 8 | cfx << 16;
348 	      if (c == UCS_HIDDEN)
349 		continue;
350 	      c = ToUtf8_comb(pt, c);
351 	      l += c;
352 	      if (pt)
353 	        pt += c;
354 	      continue;
355 	    }
356 # endif
357 # ifdef DW_CHARS
358 	  if (is_dw_font(cf))
359 	    {
360 	      c = c << 8 | (unsigned char)*im++;
361 	      fo++;
362 	      j++;
363 	    }
364 # endif
365 	  if (pastefont)
366 	    {
367 	      c = EncodeChar(pt, c | cf << 16, fore->w_encoding, &font);
368 	      l += c;
369 	      if (pt)
370 		pt += c;
371 	      continue;
372 	    }
373 #endif /* FONT */
374 	  if (pt)
375 	    *pt++ = c;
376 	  l++;
377 	}
378 #ifdef FONT
379       if (pastefont && font != ASCII)
380 	{
381 	  if (pt)
382 	    {
383 	      strcpy(pt, "\033(B");
384 	      pt += 3;
385 	    }
386 	  l += 3;
387 	}
388 #endif
389       if (i != y2 && (to != fore->w_width - 1 || ml->image[to + 1] == ' '))
390 	{
391 	  /*
392 	   * this code defines, what glues lines together
393 	   */
394 	  switch (markdata->nonl)
395 	    {
396 	    case 0:		/* lines separated by newlines */
397 	      if (pt)
398 		*pt++ = '\r';
399 	      l++;
400 	      if (join_with_cr)
401 		{
402 		  if (pt)
403 		    *pt++ = '\n';
404 		  l++;
405 		}
406 	      break;
407 	    case 1:		/* nothing to separate lines */
408 	      break;
409 	    case 2:		/* lines separated by blanks */
410 	      if (pt)
411 		*pt++ = ' ';
412 	      l++;
413 	      break;
414 	    case 3:		/* seperate by comma, for csh junkies */
415 	      if (pt)
416 	        *pt++ = ',';
417 	      l++;
418 	      break;
419 	    }
420 	}
421     }
422   return l;
423 }
424 
425 /* Check if two chars are identical. All digits are treated
426  * as same. Used for GetHistory()
427  */
428 
429 static int
eq(a,b)430 eq(a, b)
431 int a, b;
432 {
433   if (a == b)
434     return 1;
435   if (a == 0 || b == 0)
436     return 1;
437   if (a <= '9' && a >= '0' && b <= '9' && b >= '0')
438     return 1;
439   return 0;
440 }
441 
442 
443 /**********************************************************************/
444 
445 int
GetHistory()446 GetHistory()	/* return value 1 if copybuffer changed */
447 {
448   int i = 0, q = 0, xx, yy, x, y;
449   unsigned char *linep;
450   struct mline *ml;
451 
452   ASSERT(display && fore);
453   x = fore->w_x;
454   if (x >= fore->w_width)
455     x = fore->w_width - 1;
456   y = fore->w_y + fore->w_histheight;
457   debug2("cursor is at x=%d, y=%d\n", x, y);
458   ml = WIN(y);
459   for (xx = x - 1, linep = ml->image + xx; xx >= 0; xx--)
460     if ((q = *linep--) != ' ' )
461       break;
462   debug3("%c at (%d,%d)\n", q, xx, y);
463   for (yy = y - 1; yy >= 0; yy--)
464     {
465       ml = WIN(yy);
466       linep = ml->image;
467       if (xx < 0 || eq(linep[xx], q))
468 	{		/* line is matching... */
469 	  for (i = fore->w_width - 1, linep += i; i >= x; i--)
470 	    if (*linep-- != ' ')
471 	      break;
472 	  if (i >= x)
473 	    break;
474 	}
475     }
476   if (yy < 0)
477     return 0;
478   if (D_user->u_plop.buf)
479     UserFreeCopyBuffer(D_user);
480   if ((D_user->u_plop.buf = (char *)malloc((unsigned) (i - x + 2))) == NULL)
481     {
482       LMsg(0, "Not enough memory... Sorry.");
483       return 0;
484     }
485   bcopy((char *)linep - i + x + 1, D_user->u_plop.buf, i - x + 1);
486   D_user->u_plop.len = i - x + 1;
487 #ifdef ENCODINGS
488   D_user->u_plop.enc = fore->w_encoding;
489 #endif
490   return 1;
491 }
492 
493 /**********************************************************************/
494 
495 
496 void
MarkRoutine()497 MarkRoutine()
498 {
499   int x, y;
500 
501   ASSERT(fore && display && D_user);
502 
503   debug2("MarkRoutine called: fore nr %d, display %s\n",
504          fore->w_number, D_usertty);
505 
506   if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1))
507     return;
508   flayer->l_encoding = fore->w_encoding;
509   flayer->l_mode = 1;
510   markdata = (struct markdata *)flayer->l_data;
511   markdata->md_user = D_user;	/* XXX: Correct? */
512   markdata->md_window = fore;
513   markdata->second = 0;
514   markdata->rep_cnt = 0;
515   markdata->append_mode = 0;
516   markdata->write_buffer = 0;
517   markdata->nonl = 0;
518   markdata->left_mar  = 0;
519   markdata->right_mar = fore->w_width - 1;
520   markdata->hist_offset = fore->w_histheight;
521   x = fore->w_x;
522   y = D2W(fore->w_y);
523   if (x >= fore->w_width)
524     x = fore->w_width - 1;
525 
526   LGotoPos(flayer, x, W2D(y));
527   LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)",
528       x + 1, W2D(y + 1), fore->w_histheight, fore->w_width, fore->w_height);
529   markdata->cx = markdata->x1 = x;
530   markdata->cy = markdata->y1 = y;
531   flayer->l_x = x;
532   flayer->l_y = W2D(y);
533 }
534 
535 static void
MarkProcess(inbufp,inlenp)536 MarkProcess(inbufp,inlenp)
537 char **inbufp;
538 int *inlenp;
539 {
540   char *inbuf, *pt;
541   int inlen;
542   int cx, cy, x2, y2, j, yend;
543   int newcopylen = 0, od;
544   int in_mark;
545   int rep_cnt;
546   struct acluser *md_user;
547 
548 /*
549   char *extrap = 0, extrabuf[100];
550 */
551 
552   markdata = (struct markdata *)flayer->l_data;
553   fore = markdata->md_window;
554   md_user = markdata->md_user;
555   if (inbufp == 0)
556     {
557       MarkAbort();
558       return;
559     }
560 
561   LGotoPos(flayer, markdata->cx, W2D(markdata->cy));
562   inbuf= *inbufp;
563   inlen= *inlenp;
564   pt = inbuf;
565   in_mark = 1;
566   while (in_mark && (inlen /* || extrap */))
567     {
568       unsigned char ch = (unsigned char )*pt++;
569       inlen--;
570       if (flayer->l_mouseevent.start)
571 	{
572 	  int r = LayProcessMouse(flayer, ch);
573 	  if (r == -1)
574 	    LayProcessMouseSwitch(flayer, 0);
575 	  else
576 	    {
577 	      if (r)
578 		ch = 0222;
579 	      else
580 		continue;
581 	    }
582 	}
583       od = mark_key_tab[(int)ch];
584       rep_cnt = markdata->rep_cnt;
585       if (od >= '0' && od <= '9' && !markdata->f_cmd.flag)
586         {
587 	  if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0))
588 	    {
589 	      markdata->rep_cnt = 10 * rep_cnt + od - '0';
590 	      continue;
591  	      /*
592 	       * Now what is that 1001 here? Well, we have a screen with
593 	       * 25 * 80 = 2000 characters. Movement is at most across the full
594 	       * screen. This we do with word by word movement, as character by
595 	       * character movement never steps over line boundaries. The most words
596 	       * we can place on the screen are 1000 single letter words. Thus 1001
597 	       * is sufficient. Users with bigger screens never write in single letter
598 	       * words, as they should be more advanced. jw.
599 	       * Oh, wrong. We still give even the experienced user a factor of ten.
600 	       */
601 	    }
602 	}
603       cx = markdata->cx;
604       cy = markdata->cy;
605 
606       if (markdata -> f_cmd.flag) {
607         debug2("searching for %c:%d\n",od,rep_cnt);
608         markdata->f_cmd.flag = 0;
609         markdata->rep_cnt = 0;
610 
611 	if (isgraph (od)) {
612 	  markdata->f_cmd.target = od;
613 	  rep_cnt = (rep_cnt) ? rep_cnt : 1;
614 	  nextchar(&cx, &cy, markdata->f_cmd.direction, od, rep_cnt );
615 	  revto(cx, cy);
616 	  continue;
617 	}
618       }
619 
620 processchar:
621       switch (od)
622         {
623 	case 'f': /* fall through */
624 	case 'F': /* fall through */
625 	case 't': /* fall through */
626 	case 'T': /* fall through */
627 	  /*
628 	   * Set f_cmd to do a search on the next key stroke.
629 	   * If we break, rep_cnt will be reset, so we
630 	   * continue instead. It might be cleaner to
631 	   * store the rep_count in f_cmd and
632 	   * break here so later followon code will be
633 	   * hit.
634 	   */
635 	  markdata->f_cmd.flag = 1;
636 	  markdata->f_cmd.direction = od;
637 	  debug("entering char search\n");
638 	  continue;
639 	case ';':
640 	case ',':
641 	  if (!markdata->f_cmd.target)
642 	    break;
643 	  if (!rep_cnt)
644 	    rep_cnt = 1;
645 	  nextchar(&cx, &cy,
646 	      od == ';' ? markdata->f_cmd.direction : (markdata->f_cmd.direction ^ 0x20),
647 	      markdata->f_cmd.target, rep_cnt );
648 	  revto(cx, cy);
649 	  break;
650 	case 'o':
651 	case 'x':
652 	  if (!markdata->second)
653 	    break;
654 	  markdata->cx = markdata->x1;
655 	  markdata->cy = markdata->y1;
656 	  markdata->x1 = cx;
657 	  markdata->y1 = cy;
658 	  revto(markdata->cx, markdata->cy);
659 	  break;
660 	case '\014':	/* CTRL-L Redisplay */
661 	  Redisplay(0);
662 	  LGotoPos(flayer, cx, W2D(cy));
663 	  break;
664 	case 0202:	/* M-C-b */
665 	case '\010':	/* CTRL-H Backspace */
666 	case 'h':
667 	  if (rep_cnt == 0)
668 	    rep_cnt = 1;
669 	  revto(cx - rep_cnt, cy);
670 	  break;
671 	case 0216:	/* M-C-p */
672 	case '\016':	/* CTRL-N */
673 	case 'j':
674 	  if (rep_cnt == 0)
675 	    rep_cnt = 1;
676 	  revto(cx, cy + rep_cnt);
677 	  break;
678 	case '+':
679 	  if (rep_cnt == 0)
680 	    rep_cnt = 1;
681 	  j = cy + rep_cnt;
682 	  if (j > fore->w_histheight + fore->w_height - 1)
683 	    j = fore->w_histheight + fore->w_height - 1;
684 	  revto(linestart(j), j);
685 	  break;
686 	case '-':
687 	  if (rep_cnt == 0)
688 	    rep_cnt = 1;
689 	  cy -= rep_cnt;
690 	  if (cy < 0)
691 	    cy = 0;
692 	  revto(linestart(cy), cy);
693 	  break;
694 	case '^':
695 	  revto(linestart(cy), cy);
696 	  break;
697 	case '\n':
698 	  revto(markdata->left_mar, cy + 1);
699 	  break;
700 	case 0220:	/* M-C-p */
701 	case '\020':	/* CTRL-P */
702 	case 'k':
703 	  if (rep_cnt == 0)
704 	    rep_cnt = 1;
705 	  revto(cx, cy - rep_cnt);
706 	  break;
707 	case 0206:	/* M-C-f */
708 	case 'l':
709 	  if (rep_cnt == 0)
710 	    rep_cnt = 1;
711 	  revto(cx + rep_cnt, cy);
712 	  break;
713 	case '\001':	/* CTRL-A from tcsh/emacs */
714 	case '0':
715 	  revto(markdata->left_mar, cy);
716 	  break;
717 	case '\004':    /* CTRL-D down half screen */
718 	  if (rep_cnt == 0)
719 	    rep_cnt = (fore->w_height + 1) >> 1;
720 	  revto_line(cx, cy + rep_cnt, W2D(cy));
721 	  break;
722 	case '$':
723 	  revto(lineend(cy), cy);
724 	  break;
725         case '\022':	/* CTRL-R emacs style backwards search */
726 	  ISearch(-1);
727 	  in_mark = 0;
728 	  break;
729         case '\023':	/* CTRL-S emacs style search */
730 	  ISearch(1);
731 	  in_mark = 0;
732 	  break;
733 	case '\025':	/* CTRL-U up half screen */
734 	  if (rep_cnt == 0)
735 	    rep_cnt = (fore->w_height + 1) >> 1;
736 	  revto_line(cx, cy - rep_cnt, W2D(cy));
737 	  break;
738 	case '\007':	/* CTRL-G show cursorpos */
739 	  if (markdata->left_mar == 0 && markdata->right_mar == fore->w_width - 1)
740 	    LMsg(0, "Column %d Line %d(+%d)", cx+1, W2D(cy)+1,
741 		markdata->hist_offset);
742 	  else
743 	    LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx+1,
744 		markdata->left_mar+1, markdata->right_mar+1, W2D(cy)+1, markdata->hist_offset);
745 	  break;
746 	case '\002':	/* CTRL-B  back one page */
747 	  if (rep_cnt == 0)
748 	    rep_cnt = 1;
749 	  rep_cnt *= fore->w_height;
750 	  revto(cx, cy - rep_cnt);
751 	  break;
752 	case '\006':	/* CTRL-F  forward one page */
753 	  if (rep_cnt == 0)
754 	    rep_cnt = 1;
755 	  rep_cnt *= fore->w_height;
756 	  revto(cx, cy + rep_cnt);
757 	  break;
758 	case '\005':	/* CTRL-E  scroll up */
759 	  if (rep_cnt == 0)
760 	    rep_cnt = 1;
761 	  rep_cnt = MarkScrollUpDisplay(rep_cnt);
762 	  if (cy < D2W(0))
763             revto(cx, D2W(0));
764 	  else
765             LGotoPos(flayer, cx, W2D(cy));
766 	  break;
767 	case '\031': /* CTRL-Y  scroll down */
768 	  if (rep_cnt == 0)
769 	    rep_cnt = 1;
770 	  rep_cnt = MarkScrollDownDisplay(rep_cnt);
771 	  if (cy > D2W(fore->w_height-1))
772             revto(cx, D2W(fore->w_height-1));
773 	  else
774             LGotoPos(flayer, cx, W2D(cy));
775 	  break;
776 	case '@':
777 	  /* it may be useful to have a key that does nothing */
778 	  break;
779 	case '%':
780 	  /* rep_cnt is a percentage for the history buffer */
781 	  if (rep_cnt < 0)
782 	    rep_cnt = 0;
783 	  if (rep_cnt > 100)
784 	    rep_cnt = 100;
785 	  revto_line(markdata->left_mar,
786 		     fore->w_histheight - fore->w_scrollback_height +
787 		     (int)(rep_cnt * (fore->w_scrollback_height + fore->w_height) / 100.0),
788 		     (fore->w_height - 1) / 2);
789 	  break;
790 	case 0201:
791 	case 'g':
792 	  rep_cnt = 1;
793 	  /* FALLTHROUGH */
794 	case 0205:
795 	case 'G':
796 	  /* rep_cnt is here the WIN line number */
797 	  if (rep_cnt == 0)
798 	    rep_cnt = fore->w_histheight + fore->w_height;
799 	  revto_line(markdata->left_mar, --rep_cnt, (fore->w_height - 1) / 2);
800 	  break;
801 	case 'H':
802 	  revto(markdata->left_mar, D2W(0));
803 	  break;
804 	case 'M':
805 	  revto(markdata->left_mar, D2W((fore->w_height - 1) / 2));
806 	  break;
807 	case 'L':
808 	  revto(markdata->left_mar, D2W(fore->w_height - 1));
809 	  break;
810 	case '|':
811 	  revto(--rep_cnt, cy);
812 	  break;
813 	case 'w':
814 	  if (rep_cnt == 0)
815 	    rep_cnt = 1;
816 	  nextword(&cx, &cy, NW_MUSTMOVE, rep_cnt);
817 	  revto(cx, cy);
818 	  break;
819 	case 'e':
820 	case 'E':
821 	  if (rep_cnt == 0)
822 	    rep_cnt = 1;
823 	  nextword(&cx, &cy, NW_ENDOFWORD|NW_MUSTMOVE | (od == 'E' ? NW_BIG : 0), rep_cnt);
824 	  revto(cx, cy);
825 	  break;
826 	case 'b':
827 	case 'B':
828 	  if (rep_cnt == 0)
829 	    rep_cnt = 1;
830 	  nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE | (od == 'B' ? NW_BIG : 0), rep_cnt);
831 	  revto(cx, cy);
832 	  break;
833 	case 'a':
834 	  markdata->append_mode = 1 - markdata->append_mode;
835 	  debug1("append mode %d--\n", markdata->append_mode);
836 	  LMsg(0, (markdata->append_mode) ? ":set append" : ":set noappend");
837 	  break;
838 	case 'v':
839 	case 'V':
840 	  /* this sets start column to column 9 for VI :set nu users */
841 	  if (markdata->left_mar == 8)
842 	    rep_cnt = 1;
843 	  else
844 	    rep_cnt = 9;
845 	  /* FALLTHROUGH */
846 	case 'c':
847 	case 'C':
848 	  /* set start column (c) and end column (C) */
849 	  if (markdata->second)
850 	    {
851 	      rem(markdata->x1, markdata->y1, cx, cy, 1, (char *)0, fore->w_height-1); /* Hack */
852 	      markdata->second = 1;	/* rem turns off second */
853 	    }
854 	  rep_cnt--;
855 	  if (rep_cnt < 0)
856 	    rep_cnt = cx;
857 	  if (od != 'C')
858 	    {
859 	      markdata->left_mar = rep_cnt;
860 	      if (markdata->left_mar > markdata->right_mar)
861 		markdata->left_mar = markdata->right_mar;
862 	    }
863 	  else
864 	    {
865 	      markdata->right_mar = rep_cnt;
866 	      if (markdata->left_mar > markdata->right_mar)
867 		markdata->right_mar = markdata->left_mar;
868 	    }
869 	  if (markdata->second)
870 	    {
871 	      markdata->cx = markdata->x1; markdata->cy = markdata->y1;
872 	      revto(cx, cy);
873 	    }
874 	  if (od == 'v' || od == 'V')
875 	    LMsg(0, (markdata->left_mar != 8) ? ":set nonu" : ":set nu");
876 	  break;
877 	case 'J':
878 	  /* how do you join lines in VI ? */
879 	  markdata->nonl = (markdata->nonl + 1) % 4;
880 	  switch (markdata->nonl)
881 	    {
882 	    case 0:
883 	      if (join_with_cr)
884 		LMsg(0, "Multiple lines (CR/LF)");
885 	      else
886 		LMsg(0, "Multiple lines (LF)");
887 	      break;
888 	    case 1:
889 	      LMsg(0, "Lines joined");
890 	      break;
891 	    case 2:
892 	      LMsg(0, "Lines joined with blanks");
893 	      break;
894 	    case 3:
895 	      LMsg(0, "Lines joined with comma");
896 	      break;
897 	    }
898 	  break;
899 	case '/':
900 	  Search(1);
901 	  in_mark = 0;
902 	  break;
903 	case '?':
904 	  Search(-1);
905 	  in_mark = 0;
906 	  break;
907 	case 'n':
908 	  Search(0);
909 	  break;
910 	case 'N':
911 	  markdata->isdir = -markdata->isdir;
912 	  Search(0);
913 	  markdata->isdir = -markdata->isdir;
914 	  break;
915 	case 'y':
916 	case 'Y':
917 	  if (markdata->second == 0)
918 	    {
919 	      revto(linestart(cy), cy);
920 	      markdata->second++;
921 	      cx = markdata->x1 = markdata->cx;
922 	      cy = markdata->y1 = markdata->cy;
923 	    }
924 	  if (--rep_cnt > 0)
925 	    revto(cx, cy + rep_cnt);
926 	  revto(lineend(markdata->cy), markdata->cy);
927 	  if (od == 'y')
928 	    break;
929 	  /* FALLTHROUGH */
930 	case 'W':
931 	  if (od == 'W')
932 	    {
933 	      if (rep_cnt == 0)
934 		rep_cnt = 1;
935 	      if (!markdata->second)
936 		{
937 		  nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD, 1);
938 		  revto(cx, cy);
939 		  markdata->second++;
940 		  cx = markdata->x1 = markdata->cx;
941 		  cy = markdata->y1 = markdata->cy;
942 		}
943 	      nextword(&cx, &cy, NW_ENDOFWORD, rep_cnt);
944 	      revto(cx, cy);
945 	    }
946 	  cx = markdata->cx;
947 	  cy = markdata->cy;
948 	  /* FALLTHROUGH */
949 	case 'A':
950 	  if (od == 'A')
951 	    markdata->append_mode = 1;
952 	  /* FALLTHROUGH */
953 	case '>':
954 	  if (od == '>')
955 	    markdata->write_buffer = 1;
956 	  /* FALLTHROUGH */
957 	case ' ':
958 	case '\r':
959 	  if (!markdata->second)
960 	    {
961 	      markdata->second++;
962 	      markdata->x1 = cx;
963 	      markdata->y1 = cy;
964 	      revto(cx, cy);
965 	      LMsg(0, "First mark set - Column %d Line %d", cx+1, W2D(cy)+1);
966 	      break;
967 	    }
968 	  else
969 	    {
970 	      int append_mode = markdata->append_mode;
971 	      int write_buffer = markdata->write_buffer;
972 
973 	      x2 = cx;
974 	      y2 = cy;
975 	      newcopylen = rem(markdata->x1, markdata->y1, x2, y2, 2, (char *)0, 0); /* count */
976 	      if (md_user->u_plop.buf && !append_mode)
977 		UserFreeCopyBuffer(md_user);
978 	      yend = fore->w_height - 1;
979 	      if (fore->w_histheight - markdata->hist_offset < fore->w_height)
980 		{
981 		  markdata->second = 0;
982 		  yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset);
983 		}
984 	      if (newcopylen > 0)
985 		{
986 		  /* the +3 below is for : cr + lf + \0 */
987 		  if (md_user->u_plop.buf)
988 		    md_user->u_plop.buf = realloc(md_user->u_plop.buf,
989 			(unsigned) (md_user->u_plop.len + newcopylen + 3));
990 		  else
991 		    {
992 		      md_user->u_plop.len = 0;
993 		      md_user->u_plop.buf = malloc((unsigned) (newcopylen + 3));
994 		    }
995 		  if (!md_user->u_plop.buf)
996 		    {
997 		      MarkAbort();
998 		      in_mark = 0;
999 		      LMsg(0, "Not enough memory... Sorry.");
1000 		      md_user->u_plop.len = 0;
1001 		      md_user->u_plop.buf = 0;
1002 		      break;
1003 		    }
1004 		  if (append_mode)
1005 		    {
1006 		      switch (markdata->nonl)
1007 			{
1008 			/*
1009 			 * this code defines, what glues lines together
1010 			 */
1011 			case 0:
1012 			  if (join_with_cr)
1013 			    {
1014 			      md_user->u_plop.buf[md_user->u_plop.len] = '\r';
1015 			      md_user->u_plop.len++;
1016 			    }
1017 			  md_user->u_plop.buf[md_user->u_plop.len] = '\n';
1018 			  md_user->u_plop.len++;
1019 			  break;
1020 			case 1:
1021 			  break;
1022 			case 2:
1023 			  md_user->u_plop.buf[md_user->u_plop.len] = ' ';
1024 			  md_user->u_plop.len++;
1025 			  break;
1026 			case 3:
1027 			  md_user->u_plop.buf[md_user->u_plop.len] = ',';
1028 			  md_user->u_plop.len++;
1029 			  break;
1030 			}
1031 		    }
1032 		  md_user->u_plop.len += rem(markdata->x1, markdata->y1, x2, y2,
1033 		    markdata->hist_offset == fore->w_histheight,
1034 		    md_user->u_plop.buf + md_user->u_plop.len, yend);
1035 #ifdef ENCODINGS
1036 		  md_user->u_plop.enc = fore->w_encoding;
1037 #endif
1038 		}
1039 	      if (markdata->hist_offset != fore->w_histheight)
1040 		{
1041 		  LAY_CALL_UP(LRefreshAll(flayer, 0));
1042 		}
1043 	      ExitOverlayPage();
1044 	      WindowChanged(fore, 'P');
1045 	      if (append_mode)
1046 		LMsg(0, "Appended %d characters to buffer",
1047 		    newcopylen);
1048 	      else
1049 		LMsg(0, "Copied %d characters into buffer", md_user->u_plop.len);
1050 	      if (write_buffer)
1051 		WriteFile(md_user, (char *)0, DUMP_EXCHANGE);
1052 	      in_mark = 0;
1053 	      break;
1054 	    }
1055 
1056 	case 0222:
1057 	  if (flayer->l_mouseevent.start)
1058 	    {
1059 	      int button = flayer->l_mouseevent.buffer[0];
1060 	      if (button == 'a')
1061 		{
1062 		  /* Scroll down */
1063 		  od = 'j';
1064 		}
1065 	      else if (button == '`')
1066 		{
1067 		  /* Scroll up */
1068 		  od = 'k';
1069 		}
1070 	      else if (button == ' ')
1071 		{
1072 		  /* Left click */
1073 		  cx = flayer->l_mouseevent.buffer[1];
1074 		  cy = D2W(flayer->l_mouseevent.buffer[2]);
1075 		  revto(cx, cy);
1076 		  od = ' ';
1077 		}
1078 	      else
1079 		od = 0;
1080 	      LayProcessMouseSwitch(flayer, 0);
1081 	      if (od)
1082 		goto processchar;
1083 	    }
1084 	  else
1085 	    LayProcessMouseSwitch(flayer, 1);
1086 	  break;
1087 
1088 	default:
1089 	  MarkAbort();
1090 	  LMsg(0, "Copy mode aborted");
1091 	  in_mark = 0;
1092 	  break;
1093 	}
1094       if (in_mark)	/* markdata may be freed */
1095         markdata->rep_cnt = 0;
1096     }
1097   if (in_mark)
1098     {
1099       flayer->l_x = markdata->cx;
1100       flayer->l_y = W2D(markdata->cy);
1101     }
1102   *inbufp = pt;
1103   *inlenp = inlen;
1104 }
1105 
revto(tx,ty)1106 void revto(tx, ty)
1107 int tx, ty;
1108 {
1109   revto_line(tx, ty, -1);
1110 }
1111 
1112 /* tx, ty: WINDOW,  line: DISPLAY */
revto_line(tx,ty,line)1113 void revto_line(tx, ty, line)
1114 int tx, ty, line;
1115 {
1116   int fx, fy;
1117   int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0;
1118   int ystart = 0, yend = fore->w_height-1;
1119   int i, ry;
1120   unsigned char *wi;
1121   struct mline *ml;
1122   struct mchar mc;
1123 
1124   if (tx < 0)
1125     tx = 0;
1126   else if (tx > fore->w_width - 1)
1127     tx = fore->w_width -1;
1128   if (ty < fore->w_histheight - fore->w_scrollback_height)
1129     ty = fore->w_histheight - fore->w_scrollback_height;
1130   else if (ty > fore->w_histheight + fore->w_height - 1)
1131     ty = fore->w_histheight + fore->w_height - 1;
1132 
1133   fx = markdata->cx; fy = markdata->cy;
1134 
1135 #ifdef DW_CHARS
1136   /* don't just move inside of a kanji, the user wants to see something */
1137   ml = WIN(ty);
1138   if (ty == fy && fx + 1 == tx && dw_right(ml, tx, fore->w_encoding) && tx < D_width - 1)
1139     tx++;
1140   if (ty == fy && fx - 1 == tx && dw_right(ml, fx, fore->w_encoding) && tx)
1141     tx--;
1142 #endif
1143 
1144   markdata->cx = tx; markdata->cy = ty;
1145 
1146   /*
1147    * if we go to a position that is currently offscreen
1148    * then scroll the screen
1149    */
1150   i = 0;
1151   if (line >= 0 && line < fore->w_height)
1152     i = W2D(ty) - line;
1153   else if (ty < markdata->hist_offset)
1154     i = ty - markdata->hist_offset;
1155   else if (ty > markdata->hist_offset + (fore->w_height - 1))
1156     i = ty - markdata->hist_offset - (fore->w_height - 1);
1157   if (i > 0)
1158     yend -= MarkScrollUpDisplay(i);
1159   else if (i < 0)
1160     ystart += MarkScrollDownDisplay(-i);
1161 
1162   if (markdata->second == 0)
1163     {
1164       flayer->l_x = tx;
1165       flayer->l_y = W2D(ty);
1166       LGotoPos(flayer, tx, W2D(ty));
1167       return;
1168     }
1169 
1170   qq = markdata->x1 + markdata->y1 * fore->w_width;
1171   ff = fx + fy * fore->w_width; /* "from" offset in WIN coords */
1172   tt = tx + ty * fore->w_width; /* "to" offset  in WIN coords*/
1173 
1174   if (ff > tt)
1175     {
1176       st = tt; en = ff;
1177       x = tx; y = ty;
1178     }
1179   else
1180     {
1181       st = ff; en = tt;
1182       x = fx; y = fy;
1183     }
1184   if (st > qq)
1185     {
1186       st++;
1187       x++;
1188     }
1189   if (en < qq)
1190     en--;
1191   if (tt > qq)
1192     {
1193       revst = qq; reven = tt;
1194     }
1195   else
1196     {
1197       revst = tt; reven = qq;
1198     }
1199   ry = y - markdata->hist_offset;
1200   if (ry < ystart)
1201     {
1202       y += (ystart - ry);
1203       x = 0;
1204       st = y * fore->w_width;
1205       ry = ystart;
1206     }
1207   ml = WIN(y);
1208   for (t = st; t <= en; t++, x++)
1209     {
1210       if (x >= fore->w_width)
1211 	{
1212 	  x = 0;
1213 	  y++, ry++;
1214 	  ml = WIN(y);
1215 	}
1216       if (ry > yend)
1217 	break;
1218       if (t == st || x == 0)
1219 	{
1220 	  wi = ml->image + fore->w_width;
1221 	  for (ce = fore->w_width; ce >= 0; ce--, wi--)
1222 	    if (*wi != ' ')
1223 	      break;
1224 	}
1225       if (x <= ce && x >= markdata->left_mar && x <= markdata->right_mar)
1226 	{
1227 #ifdef DW_CHARS
1228 	  if (dw_right(ml, x, fore->w_encoding))
1229 	      {
1230 		if (t == revst)
1231 		  revst--;
1232 	        t--;
1233 		x--;
1234 	      }
1235 #endif
1236 	  if (t >= revst && t <= reven)
1237 	    {
1238 	      mc = mchar_so;
1239 #ifdef FONT
1240 	      if (pastefont)
1241 		{
1242 		  mc.font = ml->font[x];
1243 		  mc.fontx = ml->fontx[x];
1244 		}
1245 #endif
1246 	      mc.image = ml->image[x];
1247 	    }
1248 	  else
1249 	    copy_mline2mchar(&mc, ml, x);
1250 #ifdef DW_CHARS
1251 	  if (dw_left(ml, x, fore->w_encoding))
1252 	    {
1253 	      mc.mbcs = ml->image[x + 1];
1254 	      LPutChar(flayer, &mc, x, W2D(y));
1255 	      t++;
1256 	    }
1257 #endif
1258 	  LPutChar(flayer, &mc, x, W2D(y));
1259 #ifdef DW_CHARS
1260 	  if (dw_left(ml, x, fore->w_encoding))
1261 	    x++;
1262 #endif
1263 	}
1264     }
1265   flayer->l_x = tx;
1266   flayer->l_y = W2D(ty);
1267   LGotoPos(flayer, tx, W2D(ty));
1268 }
1269 
1270 static void
MarkAbort()1271 MarkAbort()
1272 {
1273   int yend, redisp;
1274 
1275   debug("MarkAbort\n");
1276   markdata = (struct markdata *)flayer->l_data;
1277   fore = markdata->md_window;
1278   yend = fore->w_height - 1;
1279   redisp = markdata->second;
1280   if (fore->w_histheight - markdata->hist_offset < fore->w_height)
1281     {
1282       markdata->second = 0;
1283       yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset);
1284     }
1285   if (markdata->hist_offset != fore->w_histheight)
1286     {
1287       LAY_CALL_UP(LRefreshAll(flayer, 0));
1288     }
1289   else
1290     {
1291       rem(markdata->x1, markdata->y1, markdata->cx, markdata->cy, redisp, (char *)0, yend);
1292     }
1293   ExitOverlayPage();
1294   WindowChanged(fore, 'P');
1295 }
1296 
1297 
1298 static void
MarkRedisplayLine(y,xs,xe,isblank)1299 MarkRedisplayLine(y, xs, xe, isblank)
1300 int y;	/* NOTE: y is in DISPLAY coords system! */
1301 int xs, xe;
1302 int isblank;
1303 {
1304   int wy, x, i, rm;
1305   int sta, sto, cp;	/* NOTE: these 3 are in WINDOW coords system */
1306   unsigned char *wi;
1307   struct mline *ml;
1308   struct mchar mchar_marked;
1309 
1310   if (y < 0)	/* No special full page handling */
1311     return;
1312 
1313   markdata = (struct markdata *)flayer->l_data;
1314   fore = markdata->md_window;
1315 
1316   mchar_marked = mchar_so;
1317 
1318   wy = D2W(y);
1319   ml = WIN(wy);
1320 
1321   if (markdata->second == 0)
1322     {
1323       if (dw_right(ml, xs, fore->w_encoding) && xs > 0)
1324 	xs--;
1325       if (dw_left(ml, xe, fore->w_encoding) && xe < fore->w_width - 1)
1326 	xe++;
1327       if (xs == 0 && y > 0 && wy > 0 && WIN(wy - 1)->image[flayer->l_width] == 0)
1328         LCDisplayLineWrap(flayer, ml, y, xs, xe, isblank);
1329       else
1330         LCDisplayLine(flayer, ml, y, xs, xe, isblank);
1331       return;
1332     }
1333 
1334   sta = markdata->y1 * fore->w_width + markdata->x1;
1335   sto = markdata->cy * fore->w_width + markdata->cx;
1336   if (sta > sto)
1337     {
1338       i=sta; sta=sto; sto=i;
1339     }
1340   cp = wy * fore->w_width + xs;
1341 
1342   rm = markdata->right_mar;
1343   for (x = fore->w_width, wi = ml->image + fore->w_width; x >= 0; x--, wi--)
1344     if (*wi != ' ')
1345       break;
1346   if (x < rm)
1347     rm = x;
1348 
1349   for (x = xs; x <= xe; x++, cp++)
1350     if (cp >= sta && x >= markdata->left_mar)
1351       break;
1352 #ifdef DW_CHARS
1353   if (dw_right(ml, x, fore->w_encoding))
1354     x--;
1355 #endif
1356   if (x > xs)
1357     LCDisplayLine(flayer, ml, y, xs, x - 1, isblank);
1358   for (; x <= xe; x++, cp++)
1359     {
1360       if (cp > sto || x > rm)
1361 	break;
1362 #ifdef FONT
1363       if (pastefont)
1364 	{
1365 	  mchar_marked.font = ml->font[x];
1366 	  mchar_marked.fontx = ml->fontx[x];
1367 	}
1368 #endif
1369       mchar_marked.image = ml->image[x];
1370 #ifdef DW_CHARS
1371       mchar_marked.mbcs = 0;
1372       if (dw_left(ml, x, fore->w_encoding))
1373 	{
1374 	  mchar_marked.mbcs = ml->image[x + 1];
1375 	  cp++;
1376 	}
1377 #endif
1378       LPutChar(flayer, &mchar_marked, x, y);
1379 #ifdef DW_CHARS
1380       if (dw_left(ml, x, fore->w_encoding))
1381 	x++;
1382 #endif
1383     }
1384   if (x <= xe)
1385     LCDisplayLine(flayer, ml, y, x, xe, isblank);
1386 }
1387 
1388 
1389 /*
1390  * This ugly routine is to speed up GotoPos()
1391  */
1392 static int
MarkRewrite(ry,xs,xe,rend,doit)1393 MarkRewrite(ry, xs, xe, rend, doit)
1394 int ry, xs, xe, doit;
1395 struct mchar *rend;
1396 {
1397   int dx, x, y, st, en, t, rm;
1398   unsigned char *i;
1399   struct mline *ml;
1400   struct mchar mchar_marked;
1401 
1402   mchar_marked = mchar_so;
1403 
1404   debug3("MarkRewrite %d, %d-%d\n", ry, xs, xe);
1405   markdata = (struct markdata *)flayer->l_data;
1406   fore = markdata->md_window;
1407   y = D2W(ry);
1408   ml = WIN(y);
1409 #ifdef UTF8
1410   if (fore->w_encoding && fore->w_encoding != UTF8 && D_encoding == UTF8 && ContainsSpecialDeffont(ml, xs, xe, fore->w_encoding))
1411     return EXPENSIVE;
1412 #endif
1413   dx = xe - xs + 1;
1414   if (doit)
1415     {
1416       i = ml->image + xs;
1417       while (dx--)
1418         PUTCHAR(*i++);
1419       return 0;
1420     }
1421 
1422   if (markdata->second == 0)
1423     st = en = -1;
1424   else
1425     {
1426       st = markdata->y1 * fore->w_width + markdata->x1;
1427       en = markdata->cy * fore->w_width + markdata->cx;
1428       if (st > en)
1429         {
1430           t = st; st = en; en = t;
1431         }
1432     }
1433   t = y * fore->w_width + xs;
1434   for (rm = fore->w_width, i = ml->image + fore->w_width; rm >= 0; rm--)
1435     if (*i-- != ' ')
1436       break;
1437   if (rm > markdata->right_mar)
1438     rm = markdata->right_mar;
1439   x = xs;
1440   while (dx--)
1441     {
1442       if (t >= st && t <= en && x >= markdata->left_mar && x <= rm)
1443         {
1444 #ifdef FONT
1445 	  if (pastefont)
1446 	    {
1447 	      mchar_marked.font = ml->font[x];
1448 	      mchar_marked.fontx = ml->fontx[x];
1449 	    }
1450 #endif
1451 	  rend->image = mchar_marked.image;
1452 	  if (!cmp_mchar(rend, &mchar_marked))
1453 	    return EXPENSIVE;
1454         }
1455       else
1456         {
1457 	  rend->image = ml->image[x];
1458 	  if (!cmp_mchar_mline(rend, ml, x))
1459 	    return EXPENSIVE;
1460         }
1461       x++;
1462     }
1463   return xe - xs + 1;
1464 }
1465 
1466 
1467 /*
1468  * scroll the screen contents up/down.
1469  */
MarkScrollUpDisplay(n)1470 static int MarkScrollUpDisplay(n)
1471 int n;
1472 {
1473   int i;
1474 
1475   debug1("MarkScrollUpDisplay(%d)\n", n);
1476   if (n <= 0)
1477     return 0;
1478   if (n > fore->w_histheight - markdata->hist_offset)
1479     n = fore->w_histheight - markdata->hist_offset;
1480   markdata->hist_offset += n;
1481   i = (n < flayer->l_height) ? n : (flayer->l_height);
1482   LScrollV(flayer, i, 0, flayer->l_height - 1, 0);
1483   while (i-- > 0)
1484     MarkRedisplayLine(flayer->l_height - i - 1, 0, flayer->l_width - 1, 1);
1485   return n;
1486 }
1487 
1488 static int
MarkScrollDownDisplay(n)1489 MarkScrollDownDisplay(n)
1490 int n;
1491 {
1492   int i;
1493 
1494   debug1("MarkScrollDownDisplay(%d)\n", n);
1495   if (n <= 0)
1496     return 0;
1497   if (n > markdata->hist_offset)
1498     n = markdata->hist_offset;
1499   markdata->hist_offset -= n;
1500   i = (n < flayer->l_height) ? n : (flayer->l_height);
1501   LScrollV(flayer, -i, 0, fore->w_height - 1, 0);
1502   while (i-- > 0)
1503     MarkRedisplayLine(i, 0, flayer->l_width - 1, 1);
1504   return n;
1505 }
1506 
1507 void
MakePaster(pa,buf,len,bufiscopy)1508 MakePaster(pa, buf, len, bufiscopy)
1509 struct paster *pa;
1510 char *buf;
1511 int len;
1512 int bufiscopy;
1513 {
1514   FreePaster(pa);
1515   pa->pa_pasteptr = buf;
1516   pa->pa_pastelen = len;
1517   if (bufiscopy)
1518     pa->pa_pastebuf = buf;
1519   pa->pa_pastelayer = flayer;
1520   DoProcess(Layer2Window(flayer), &pa->pa_pasteptr, &pa->pa_pastelen, pa);
1521 }
1522 
1523 void
FreePaster(pa)1524 FreePaster(pa)
1525 struct paster *pa;
1526 {
1527   if (pa->pa_pastebuf)
1528     free(pa->pa_pastebuf);
1529   pa->pa_pastebuf = 0;
1530   pa->pa_pasteptr = 0;
1531   pa->pa_pastelen = 0;
1532   pa->pa_pastelayer = 0;
1533   evdeq(&pa->pa_slowev);
1534 }
1535 
1536 #endif /* COPY_PASTE */
1537 
1538