1 /* Copyright (c) 1993-2002
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Copyright (c) 1987 Oliver Laumann
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, write to the
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 ****************************************************************
24 #include <sys/types.h>
34 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
36 * WARNING: these routines use the global variables "fore" and
37 * "flayer" to make things easier.
39 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
42 static int is_letter
__P((int));
43 static void nextword
__P((int *, int *, int, int));
44 static int linestart
__P((int));
45 static int lineend
__P((int));
46 static int rem
__P((int, int , int , int , int , char *, int));
47 static int eq
__P((int, int ));
48 static int MarkScrollDownDisplay
__P((int));
49 static int MarkScrollUpDisplay
__P((int));
51 static void MarkProcess
__P((char **, int *));
52 static void MarkAbort
__P((void));
53 static void MarkRedisplayLine
__P((int, int, int, int));
54 static int MarkRewrite
__P((int, int, int, struct mchar
*, int));
56 extern struct layer
*flayer
;
57 extern struct display
*display
, *displays
;
58 extern struct win
*fore
;
59 extern struct mline mline_blank
, mline_null
;
60 extern struct mchar mchar_so
;
66 struct LayFuncs MarkLf
=
80 unsigned char mark_key_tab
[256]; /* this array must be initialised first! */
82 static struct markdata
*markdata
;
86 * VI like is_letter: 0 - whitespace
90 static int is_letter(c
)
93 if ((c
>= 'a' && c
<= 'z') ||
94 (c
>= 'A' && c
<= 'Z') ||
95 (c
>= '0' && c
<= '9') ||
96 c
== '_' || c
== '.' ||
97 c
== '@' || c
== ':' ||
98 c
== '%' || c
== '!' ||
100 /* thus we can catch email-addresses as a word :-) */
112 register unsigned char *i
;
114 for (x
= markdata
->left_mar
, i
= WIN(y
)->image
+ x
; x
< fore
->w_width
- 1; x
++)
117 if (x
== fore
->w_width
- 1)
118 x
= markdata
->left_mar
;
127 register unsigned char *i
;
129 for (x
= markdata
->right_mar
, i
= WIN(y
)->image
+ x
; x
>= 0; x
--)
133 x
= markdata
->left_mar
;
138 * nextchar sets *xp to the num-th occurrence of the target in the line.
140 * Returns -1 if the target doesn't appear num times, 0 otherwise.
143 nextchar(int *xp
, int *yp
, int direction
, char target
, int num
)
145 int width
; /* width of the current window. */
146 int x
; /* x coordinate of the current cursor position. */
147 int step
; /* amount to increment x (+1 or -1) */
148 int adjust
; /* Final adjustment of cursor position. */
149 char *displayed_line
; /* Line in which search takes place. */
155 width
= fore
->w_width
;
156 displayed_line
= WIN(*yp
) -> image
;
159 case 't': adjust
= -1; /* fall through */
160 case 'f': step
= 1; /* fall through */
162 case 'T': adjust
= 1; /* fall through */
163 case 'F': step
= -1; /* fall through */
171 debug1("ml->image = %s\n", displayed_line
);
172 debug2("num = %d, width = %d\n",num
, width
);
173 debug2("x = %d targe = %c\n", x
, target
);
175 for ( ;x
>=0 && x
<= width
; x
+= step
) {
176 if (displayed_line
[x
] == target
) {
187 * nextword calculates the cursor position of the num'th word.
188 * If the cursor is on a word, it counts as the first.
189 * NW_BACK: search backward
190 * NW_ENDOFWORD: find the end of the word
191 * NW_MUSTMOVE: move at least one char
192 * NW_BIG: match WORDs not words
195 #define NW_BACK (1<<0)
196 #define NW_ENDOFWORD (1<<1)
197 #define NW_MUSTMOVE (1<<2)
198 #define NW_BIG (1<<3)
203 nextword(xp
, yp
, flags
, num
)
204 int *xp
, *yp
, flags
, num
;
206 int xx
= fore
->w_width
, yy
= fore
->w_histheight
+ fore
->w_height
;
207 register int sx
, oq
, q
, x
, y
;
212 sx
= (flags
& NW_BACK
) ? -1 : 1;
213 if ((flags
& NW_ENDOFWORD
) && (flags
& NW_MUSTMOVE
))
216 for (oq
= -1; ; x
+= sx
, oq
= q
)
218 if (x
>= xx
|| x
< 0)
220 else if (flags
& NW_BIG
)
221 q
= ml
->image
[x
] == ' ';
223 q
= is_letter(ml
->image
[x
]);
224 if (oq
>= 0 && oq
!= q
)
226 if (oq
== 0 || !(flags
& NW_ENDOFWORD
))
231 if ((!(flags
& NW_ENDOFWORD
) && q
) ||
232 ((flags
& NW_ENDOFWORD
) && oq
))
257 * y1, y2 are WIN coordinates
259 * redisplay: 0 - just copy
260 * 1 - redisplay + copy
261 * 2 - count + copy, don't redisplay
265 rem(x1
, y1
, x2
, y2
, redisplay
, pt
, yend
)
266 int x1
, y1
, x2
, y2
, redisplay
, yend
;
269 int i
, j
, from
, to
, ry
, c
;
278 markdata
->second
= 0;
279 if (y2
< y1
|| ((y2
== y1
) && (x2
< x1
)))
288 ry
= y1
- markdata
->hist_offset
;
291 if (redisplay
!= 2 && pt
== 0 && ry
<0)
296 for (; i
<= y2
; i
++, ry
++)
298 if (redisplay
!= 2 && pt
== 0 && ry
> yend
)
301 from
= (i
== y1
) ? x1
: 0;
302 if (from
< markdata
->left_mar
)
303 from
= markdata
->left_mar
;
304 for (to
= fore
->w_width
, im
= ml
->image
+ to
; to
>= 0; to
--)
307 if (i
== y2
&& x2
< to
)
309 if (to
> markdata
->right_mar
)
310 to
= markdata
->right_mar
;
311 if (redisplay
== 1 && from
<= to
&& ry
>=0 && ry
<= yend
)
312 MarkRedisplayLine(ry
, from
, to
, 0);
313 if (redisplay
!= 2 && pt
== 0) /* don't count/copy */
317 if (dw_right(ml
, j
, fore
->w_encoding
))
327 c
= (unsigned char)*im
++;
329 cf
= (unsigned char)*fo
++;
331 if (fore
->w_encoding
== UTF8
)
336 c
= ToUtf8_comb(pt
, c
);
346 c
= c
<< 8 | (unsigned char)*im
++;
353 c
= EncodeChar(pt
, c
| cf
<< 16, fore
->w_encoding
, &font
);
365 if (pastefont
&& font
!= ASCII
)
369 strcpy(pt
, "\033(B");
375 if (i
!= y2
&& (to
!= fore
->w_width
- 1 || ml
->image
[to
+ 1] == ' '))
378 * this code defines, what glues lines together
380 switch (markdata
->nonl
)
382 case 0: /* lines separated by newlines */
393 case 1: /* nothing to separate lines */
395 case 2: /* lines separated by blanks */
400 case 3: /* seperate by comma, for csh junkies */
411 /* Check if two chars are identical. All digits are treated
412 * as same. Used for GetHistory()
421 if (a
== 0 || b
== 0)
423 if (a
<= '9' && a
>= '0' && b
<= '9' && b
>= '0')
429 /**********************************************************************/
432 GetHistory() /* return value 1 if copybuffer changed */
434 int i
= 0, q
= 0, xx
, yy
, x
, y
;
435 unsigned char *linep
;
438 ASSERT(display
&& fore
);
440 if (x
>= fore
->w_width
)
441 x
= fore
->w_width
- 1;
442 y
= fore
->w_y
+ fore
->w_histheight
;
443 debug2("cursor is at x=%d, y=%d\n", x
, y
);
445 for (xx
= x
- 1, linep
= ml
->image
+ xx
; xx
>= 0; xx
--)
446 if ((q
= *linep
--) != ' ' )
448 debug3("%c at (%d,%d)\n", q
, xx
, y
);
449 for (yy
= y
- 1; yy
>= 0; yy
--)
453 if (xx
< 0 || eq(linep
[xx
], q
))
454 { /* line is matching... */
455 for (i
= fore
->w_width
- 1, linep
+= i
; i
>= x
; i
--)
464 if (D_user
->u_plop
.buf
)
465 UserFreeCopyBuffer(D_user
);
466 if ((D_user
->u_plop
.buf
= (char *)malloc((unsigned) (i
- x
+ 2))) == NULL
)
468 LMsg(0, "Not enough memory... Sorry.");
471 bcopy((char *)linep
- i
+ x
+ 1, D_user
->u_plop
.buf
, i
- x
+ 1);
472 D_user
->u_plop
.len
= i
- x
+ 1;
474 D_user
->u_plop
.enc
= fore
->w_encoding
;
479 /**********************************************************************/
487 ASSERT(fore
&& display
&& D_user
);
489 debug2("MarkRoutine called: fore nr %d, display %s\n",
490 fore
->w_number
, D_usertty
);
492 if (InitOverlayPage(sizeof(*markdata
), &MarkLf
, 1))
494 flayer
->l_encoding
= fore
->w_encoding
;
495 markdata
= (struct markdata
*)flayer
->l_data
;
496 markdata
->md_user
= D_user
; /* XXX: Correct? */
497 markdata
->md_window
= fore
;
498 markdata
->second
= 0;
499 markdata
->rep_cnt
= 0;
500 markdata
->append_mode
= 0;
501 markdata
->write_buffer
= 0;
503 markdata
->left_mar
= 0;
504 markdata
->right_mar
= fore
->w_width
- 1;
505 markdata
->hist_offset
= fore
->w_histheight
;
508 if (x
>= fore
->w_width
)
509 x
= fore
->w_width
- 1;
511 LGotoPos(flayer
, x
, W2D(y
));
512 LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)",
513 x
+ 1, W2D(y
+ 1), fore
->w_histheight
, fore
->w_width
, fore
->w_height
);
514 markdata
->cx
= markdata
->x1
= x
;
515 markdata
->cy
= markdata
->y1
= y
;
517 flayer
->l_y
= W2D(y
);
521 MarkProcess(inbufp
,inlenp
)
527 int cx
, cy
, x2
, y2
, j
, yend
;
528 int newcopylen
= 0, od
;
531 struct acluser
*md_user
;
534 char *extrap = 0, extrabuf[100];
537 markdata
= (struct markdata
*)flayer
->l_data
;
538 fore
= markdata
->md_window
;
539 md_user
= markdata
->md_user
;
546 LGotoPos(flayer
, markdata
->cx
, W2D(markdata
->cy
));
551 while (in_mark
&& (inlen
/* || extrap */))
563 od
= mark_key_tab
[(int)(unsigned char)*pt
++];
566 rep_cnt
= markdata
->rep_cnt
;
567 if (od
>= '0' && od
<= '9' && !markdata
->f_cmd
.flag
)
569 if (rep_cnt
< 1001 && (od
!= '0' || rep_cnt
!= 0))
571 markdata
->rep_cnt
= 10 * rep_cnt
+ od
- '0';
574 * Now what is that 1001 here? Well, we have a screen with
575 * 25 * 80 = 2000 characters. Movement is at most across the full
576 * screen. This we do with word by word movement, as character by
577 * character movement never steps over line boundaries. The most words
578 * we can place on the screen are 1000 single letter words. Thus 1001
579 * is sufficient. Users with bigger screens never write in single letter
580 * words, as they should be more advanced. jw.
581 * Oh, wrong. We still give even the experienced user a factor of ten.
588 if (markdata
-> f_cmd
.flag
) {
589 debug2("searching for %c:%d\n",od
,rep_cnt
);
590 markdata
->f_cmd
.flag
= 0;
591 markdata
->rep_cnt
= 0;
594 markdata
->f_cmd
.target
= od
;
595 rep_cnt
= (rep_cnt
) ? rep_cnt
: 1;
596 nextchar(&cx
, &cy
, markdata
->f_cmd
.direction
, od
, rep_cnt
);
604 case 'f': /* fall through */
605 case 'F': /* fall through */
606 case 't': /* fall through */
607 case 'T': /* fall through */
609 * Set f_cmd to do a search on the next key stroke.
610 * If we break, rep_cnt will be reset, so we
611 * continue instead. It might be cleaner to
612 * store the rep_count in f_cmd and
613 * break here so later followon code will be
616 markdata
->f_cmd
.flag
= 1;
617 markdata
->f_cmd
.direction
= od
;
618 debug("entering char search\n");
623 nextchar(&cx
, &cy
, markdata
->f_cmd
.direction
, markdata
->f_cmd
.target
, rep_cnt
);
630 switch (markdata
->f_cmd
.direction
) {
631 case 't': search_dir
= 'T'; break;
632 case 'T': search_dir
= 't'; break;
633 case 'f': search_dir
= 'F'; break;
634 case 'F': search_dir
= 'f'; break;
636 nextchar(&cx
, &cy
, search_dir
, markdata
->f_cmd
.target
, rep_cnt
);
644 if (!markdata
->second
)
646 markdata
->cx
= markdata
->x1
;
647 markdata
->cy
= markdata
->y1
;
650 revto(markdata
->cx
, markdata
->cy
);
652 case '\014': /* CTRL-L Redisplay */
654 LGotoPos(flayer
, cx
, W2D(cy
));
656 case 0202: /* M-C-b */
657 case '\010': /* CTRL-H Backspace */
661 revto(cx
- rep_cnt
, cy
);
663 case 0216: /* M-C-p */
664 case '\016': /* CTRL-N */
668 revto(cx
, cy
+ rep_cnt
);
674 if (j
> fore
->w_histheight
+ fore
->w_height
- 1)
675 j
= fore
->w_histheight
+ fore
->w_height
- 1;
676 revto(linestart(j
), j
);
684 revto(linestart(cy
), cy
);
687 revto(linestart(cy
), cy
);
690 revto(markdata
->left_mar
, cy
+ 1);
692 case 0220: /* M-C-p */
693 case '\020': /* CTRL-P */
697 revto(cx
, cy
- rep_cnt
);
699 case 0206: /* M-C-f */
703 revto(cx
+ rep_cnt
, cy
);
705 case '\001': /* CTRL-A from tcsh/emacs */
707 revto(markdata
->left_mar
, cy
);
709 case '\004': /* CTRL-D down half screen */
711 rep_cnt
= (fore
->w_height
+ 1) >> 1;
712 revto_line(cx
, cy
+ rep_cnt
, W2D(cy
));
715 revto(lineend(cy
), cy
);
717 case '\022': /* CTRL-R emacs style backwards search */
721 case '\023': /* CTRL-S emacs style search */
725 case '\025': /* CTRL-U up half screen */
727 rep_cnt
= (fore
->w_height
+ 1) >> 1;
728 revto_line(cx
, cy
- rep_cnt
, W2D(cy
));
730 case '\007': /* CTRL-G show cursorpos */
731 if (markdata
->left_mar
== 0 && markdata
->right_mar
== fore
->w_width
- 1)
732 LMsg(0, "Column %d Line %d(+%d)", cx
+1, W2D(cy
)+1,
733 markdata
->hist_offset
);
735 LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx
+1,
736 markdata
->left_mar
+1, markdata
->right_mar
+1, W2D(cy
)+1, markdata
->hist_offset
);
738 case '\002': /* CTRL-B back one page */
741 rep_cnt
*= fore
->w_height
;
742 revto(cx
, cy
- rep_cnt
);
744 case '\006': /* CTRL-F forward one page */
747 rep_cnt
*= fore
->w_height
;
748 revto(cx
, cy
+ rep_cnt
);
750 case '\005': /* CTRL-E scroll up */
753 rep_cnt
= MarkScrollUpDisplay(rep_cnt
);
757 LGotoPos(flayer
, cx
, W2D(cy
));
759 case '\031': /* CTRL-Y scroll down */
762 rep_cnt
= MarkScrollDownDisplay(rep_cnt
);
763 if (cy
> D2W(fore
->w_height
-1))
764 revto(cx
, D2W(fore
->w_height
-1));
766 LGotoPos(flayer
, cx
, W2D(cy
));
769 /* it may be usefull to have a key that does nothing */
773 /* rep_cnt is a percentage for the history buffer */
778 revto_line(markdata
->left_mar
, (rep_cnt
* (fore
->w_histheight
+ fore
->w_height
)) / 100, (fore
->w_height
- 1) / 2);
786 /* rep_cnt is here the WIN line number */
788 rep_cnt
= fore
->w_histheight
+ fore
->w_height
;
789 revto_line(markdata
->left_mar
, --rep_cnt
, (fore
->w_height
- 1) / 2);
792 revto(markdata
->left_mar
, D2W(0));
795 revto(markdata
->left_mar
, D2W((fore
->w_height
- 1) / 2));
798 revto(markdata
->left_mar
, D2W(fore
->w_height
- 1));
801 revto(--rep_cnt
, cy
);
806 nextword(&cx
, &cy
, NW_MUSTMOVE
, rep_cnt
);
813 nextword(&cx
, &cy
, NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'E' ? NW_BIG
: 0), rep_cnt
);
820 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'B' ? NW_BIG
: 0), rep_cnt
);
824 markdata
->append_mode
= 1 - markdata
->append_mode
;
825 debug1("append mode %d--\n", markdata
->append_mode
);
826 LMsg(0, (markdata
->append_mode
) ? ":set append" : ":set noappend");
830 /* this sets start column to column 9 for VI :set nu users */
831 if (markdata
->left_mar
== 8)
838 /* set start column (c) and end column (C) */
839 if (markdata
->second
)
841 rem(markdata
->x1
, markdata
->y1
, cx
, cy
, 1, (char *)0, fore
->w_height
-1); /* Hack */
842 markdata
->second
= 1; /* rem turns off second */
849 markdata
->left_mar
= rep_cnt
;
850 if (markdata
->left_mar
> markdata
->right_mar
)
851 markdata
->left_mar
= markdata
->right_mar
;
855 markdata
->right_mar
= rep_cnt
;
856 if (markdata
->left_mar
> markdata
->right_mar
)
857 markdata
->right_mar
= markdata
->left_mar
;
859 if (markdata
->second
)
861 markdata
->cx
= markdata
->x1
; markdata
->cy
= markdata
->y1
;
864 if (od
== 'v' || od
== 'V')
865 LMsg(0, (markdata
->left_mar
!= 8) ? ":set nonu" : ":set nu");
868 /* how do you join lines in VI ? */
869 markdata
->nonl
= (markdata
->nonl
+ 1) % 4;
870 switch (markdata
->nonl
)
874 LMsg(0, "Multiple lines (CR/LF)");
876 LMsg(0, "Multiple lines (LF)");
879 LMsg(0, "Lines joined");
882 LMsg(0, "Lines joined with blanks");
885 LMsg(0, "Lines joined with comma");
901 markdata
->isdir
= -markdata
->isdir
;
903 markdata
->isdir
= -markdata
->isdir
;
907 if (markdata
->second
== 0)
909 revto(linestart(cy
), cy
);
911 cx
= markdata
->x1
= markdata
->cx
;
912 cy
= markdata
->y1
= markdata
->cy
;
915 revto(cx
, cy
+ rep_cnt
);
916 revto(lineend(markdata
->cy
), markdata
->cy
);
925 if (!markdata
->second
)
927 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
, 1);
930 cx
= markdata
->x1
= markdata
->cx
;
931 cy
= markdata
->y1
= markdata
->cy
;
933 nextword(&cx
, &cy
, NW_ENDOFWORD
, rep_cnt
);
941 markdata
->append_mode
= 1;
945 markdata
->write_buffer
= 1;
949 if (!markdata
->second
)
955 LMsg(0, "First mark set - Column %d Line %d", cx
+1, W2D(cy
)+1);
960 int append_mode
= markdata
->append_mode
;
961 int write_buffer
= markdata
->write_buffer
;
965 newcopylen
= rem(markdata
->x1
, markdata
->y1
, x2
, y2
, 2, (char *)0, 0); /* count */
966 if (md_user
->u_plop
.buf
&& !append_mode
)
967 UserFreeCopyBuffer(md_user
);
968 yend
= fore
->w_height
- 1;
969 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
971 markdata
->second
= 0;
972 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
976 /* the +3 below is for : cr + lf + \0 */
977 if (md_user
->u_plop
.buf
)
978 md_user
->u_plop
.buf
= realloc(md_user
->u_plop
.buf
,
979 (unsigned) (md_user
->u_plop
.len
+ newcopylen
+ 3));
982 md_user
->u_plop
.len
= 0;
983 md_user
->u_plop
.buf
= malloc((unsigned) (newcopylen
+ 3));
985 if (!md_user
->u_plop
.buf
)
989 LMsg(0, "Not enough memory... Sorry.");
990 md_user
->u_plop
.len
= 0;
991 md_user
->u_plop
.buf
= 0;
996 switch (markdata
->nonl
)
999 * this code defines, what glues lines together
1004 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\r';
1005 md_user
->u_plop
.len
++;
1007 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\n';
1008 md_user
->u_plop
.len
++;
1013 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ' ';
1014 md_user
->u_plop
.len
++;
1017 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ',';
1018 md_user
->u_plop
.len
++;
1022 md_user
->u_plop
.len
+= rem(markdata
->x1
, markdata
->y1
, x2
, y2
,
1023 markdata
->hist_offset
== fore
->w_histheight
,
1024 md_user
->u_plop
.buf
+ md_user
->u_plop
.len
, yend
);
1026 md_user
->u_plop
.enc
= fore
->w_encoding
;
1029 if (markdata
->hist_offset
!= fore
->w_histheight
)
1031 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1035 LMsg(0, "Appended %d characters to buffer",
1038 LMsg(0, "Copied %d characters into buffer", md_user
->u_plop
.len
);
1040 WriteFile(md_user
, (char *)0, DUMP_EXCHANGE
);
1046 LMsg(0, "Copy mode aborted");
1050 if (in_mark
) /* markdata may be freed */
1051 markdata
->rep_cnt
= 0;
1055 flayer
->l_x
= markdata
->cx
;
1056 flayer
->l_y
= W2D(markdata
->cy
);
1065 revto_line(tx
, ty
, -1);
1068 /* tx, ty: WINDOW, line: DISPLAY */
1069 void revto_line(tx
, ty
, line
)
1073 int x
, y
, t
, revst
, reven
, qq
, ff
, tt
, st
, en
, ce
= 0;
1074 int ystart
= 0, yend
= fore
->w_height
-1;
1082 else if (tx
> fore
->w_width
- 1)
1083 tx
= fore
->w_width
-1;
1086 else if (ty
> fore
->w_histheight
+ fore
->w_height
- 1)
1087 ty
= fore
->w_histheight
+ fore
->w_height
- 1;
1089 fx
= markdata
->cx
; fy
= markdata
->cy
;
1092 /* don't just move inside of a kanji, the user wants to see something */
1094 if (ty
== fy
&& fx
+ 1 == tx
&& dw_right(ml
, tx
, fore
->w_encoding
) && tx
< D_width
- 1)
1096 if (ty
== fy
&& fx
- 1 == tx
&& dw_right(ml
, fx
, fore
->w_encoding
) && tx
)
1100 markdata
->cx
= tx
; markdata
->cy
= ty
;
1103 * if we go to a position that is currently offscreen
1104 * then scroll the screen
1107 if (line
>= 0 && line
< fore
->w_height
)
1109 else if (ty
< markdata
->hist_offset
)
1110 i
= ty
- markdata
->hist_offset
;
1111 else if (ty
> markdata
->hist_offset
+ (fore
->w_height
- 1))
1112 i
= ty
- markdata
->hist_offset
- (fore
->w_height
- 1);
1114 yend
-= MarkScrollUpDisplay(i
);
1116 ystart
+= MarkScrollDownDisplay(-i
);
1118 if (markdata
->second
== 0)
1120 LGotoPos(flayer
, tx
, W2D(ty
));
1124 qq
= markdata
->x1
+ markdata
->y1
* fore
->w_width
;
1125 ff
= fx
+ fy
* fore
->w_width
; /* "from" offset in WIN coords */
1126 tt
= tx
+ ty
* fore
->w_width
; /* "to" offset in WIN coords*/
1147 revst
= qq
; reven
= tt
;
1151 revst
= tt
; reven
= qq
;
1153 ry
= y
- markdata
->hist_offset
;
1158 st
= y
* fore
->w_width
;
1162 for (t
= st
; t
<= en
; t
++, x
++)
1164 if (x
>= fore
->w_width
)
1172 if (t
== st
|| x
== 0)
1174 wi
= ml
->image
+ fore
->w_width
;
1175 for (ce
= fore
->w_width
; ce
>= 0; ce
--, wi
--)
1179 if (x
<= ce
&& x
>= markdata
->left_mar
&& x
<= markdata
->right_mar
)
1182 if (dw_right(ml
, x
, fore
->w_encoding
))
1190 if (t
>= revst
&& t
<= reven
)
1195 mc
.font
= ml
->font
[x
];
1197 mc
.image
= ml
->image
[x
];
1200 copy_mline2mchar(&mc
, ml
, x
);
1202 if (dw_left(ml
, x
, fore
->w_encoding
))
1204 mc
.mbcs
= ml
->image
[x
+ 1];
1205 LPutChar(flayer
, &mc
, x
, W2D(y
));
1209 LPutChar(flayer
, &mc
, x
, W2D(y
));
1211 if (dw_left(ml
, x
, fore
->w_encoding
))
1216 LGotoPos(flayer
, tx
, W2D(ty
));
1224 debug("MarkAbort\n");
1225 markdata
= (struct markdata
*)flayer
->l_data
;
1226 fore
= markdata
->md_window
;
1227 yend
= fore
->w_height
- 1;
1228 redisp
= markdata
->second
;
1229 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
1231 markdata
->second
= 0;
1232 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
1234 if (markdata
->hist_offset
!= fore
->w_histheight
)
1236 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1240 rem(markdata
->x1
, markdata
->y1
, markdata
->cx
, markdata
->cy
, redisp
, (char *)0, yend
);
1247 MarkRedisplayLine(y
, xs
, xe
, isblank
)
1248 int y
; /* NOTE: y is in DISPLAY coords system! */
1253 int sta
, sto
, cp
; /* NOTE: these 3 are in WINDOW coords system */
1256 struct mchar mchar_marked
;
1258 if (y
< 0) /* No special full page handling */
1261 markdata
= (struct markdata
*)flayer
->l_data
;
1262 fore
= markdata
->md_window
;
1264 mchar_marked
= mchar_so
;
1269 if (markdata
->second
== 0)
1271 if (dw_right(ml
, xs
, fore
->w_encoding
) && xs
> 0)
1273 if (dw_left(ml
, xe
, fore
->w_encoding
) && xe
< fore
->w_width
- 1)
1275 if (xs
== 0 && y
> 0 && wy
> 0 && WIN(wy
- 1)->image
[flayer
->l_width
] == 0)
1276 LCDisplayLineWrap(flayer
, ml
, y
, xs
, xe
, isblank
);
1278 LCDisplayLine(flayer
, ml
, y
, xs
, xe
, isblank
);
1282 sta
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1283 sto
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1286 i
=sta
; sta
=sto
; sto
=i
;
1288 cp
= wy
* fore
->w_width
+ xs
;
1290 rm
= markdata
->right_mar
;
1291 for (x
= fore
->w_width
, wi
= ml
->image
+ fore
->w_width
; x
>= 0; x
--, wi
--)
1297 for (x
= xs
; x
<= xe
; x
++, cp
++)
1298 if (cp
>= sta
&& x
>= markdata
->left_mar
)
1301 if (dw_right(ml
, x
, fore
->w_encoding
))
1305 LCDisplayLine(flayer
, ml
, y
, xs
, x
- 1, isblank
);
1306 for (; x
<= xe
; x
++, cp
++)
1308 if (cp
> sto
|| x
> rm
)
1312 mchar_marked
.font
= ml
->font
[x
];
1314 mchar_marked
.image
= ml
->image
[x
];
1316 mchar_marked
.mbcs
= 0;
1317 if (dw_left(ml
, x
, fore
->w_encoding
))
1319 mchar_marked
.mbcs
= ml
->image
[x
+ 1];
1323 LPutChar(flayer
, &mchar_marked
, x
, y
);
1325 if (dw_left(ml
, x
, fore
->w_encoding
))
1330 LCDisplayLine(flayer
, ml
, y
, x
, xe
, isblank
);
1335 * This ugly routine is to speed up GotoPos()
1338 MarkRewrite(ry
, xs
, xe
, rend
, doit
)
1339 int ry
, xs
, xe
, doit
;
1342 int dx
, x
, y
, st
, en
, t
, rm
;
1345 struct mchar mchar_marked
;
1347 mchar_marked
= mchar_so
;
1349 debug3("MarkRewrite %d, %d-%d\n", ry
, xs
, xe
);
1350 markdata
= (struct markdata
*)flayer
->l_data
;
1351 fore
= markdata
->md_window
;
1355 if (fore
->w_encoding
&& fore
->w_encoding
!= UTF8
&& D_encoding
== UTF8
&& ContainsSpecialDeffont(ml
, xs
, xe
, fore
->w_encoding
))
1367 if (markdata
->second
== 0)
1371 st
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1372 en
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1375 t
= st
; st
= en
; en
= t
;
1378 t
= y
* fore
->w_width
+ xs
;
1379 for (rm
= fore
->w_width
, i
= ml
->image
+ fore
->w_width
; rm
>= 0; rm
--)
1382 if (rm
> markdata
->right_mar
)
1383 rm
= markdata
->right_mar
;
1387 if (t
>= st
&& t
<= en
&& x
>= markdata
->left_mar
&& x
<= rm
)
1391 mchar_marked
.font
= ml
->font
[x
];
1393 rend
->image
= mchar_marked
.image
;
1394 if (!cmp_mchar(rend
, &mchar_marked
))
1399 rend
->image
= ml
->image
[x
];
1400 if (!cmp_mchar_mline(rend
, ml
, x
))
1410 * scroll the screen contents up/down.
1412 static int MarkScrollUpDisplay(n
)
1417 debug1("MarkScrollUpDisplay(%d)\n", n
);
1420 if (n
> fore
->w_histheight
- markdata
->hist_offset
)
1421 n
= fore
->w_histheight
- markdata
->hist_offset
;
1422 markdata
->hist_offset
+= n
;
1423 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1424 LScrollV(flayer
, i
, 0, flayer
->l_height
- 1, 0);
1426 MarkRedisplayLine(flayer
->l_height
- i
- 1, 0, flayer
->l_width
- 1, 1);
1431 MarkScrollDownDisplay(n
)
1436 debug1("MarkScrollDownDisplay(%d)\n", n
);
1439 if (n
> markdata
->hist_offset
)
1440 n
= markdata
->hist_offset
;
1441 markdata
->hist_offset
-= n
;
1442 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1443 LScrollV(flayer
, -i
, 0, fore
->w_height
- 1, 0);
1445 MarkRedisplayLine(i
, 0, flayer
->l_width
- 1, 1);
1452 if (flayer
&& flayer
->l_layfn
== &MarkLf
)
1458 MakePaster(pa
, buf
, len
, bufiscopy
)
1465 pa
->pa_pasteptr
= buf
;
1466 pa
->pa_pastelen
= len
;
1468 pa
->pa_pastebuf
= buf
;
1469 pa
->pa_pastelayer
= flayer
;
1470 DoProcess(Layer2Window(flayer
), &pa
->pa_pasteptr
, &pa
->pa_pastelen
, pa
);
1477 if (pa
->pa_pastebuf
)
1478 free(pa
->pa_pastebuf
);
1479 pa
->pa_pastebuf
= 0;
1480 pa
->pa_pasteptr
= 0;
1481 pa
->pa_pastelen
= 0;
1482 pa
->pa_pastelayer
= 0;
1483 evdeq(&pa
->pa_slowev
);
1486 #endif /* COPY_PASTE */