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>
35 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
37 * WARNING: these routines use the global variables "fore" and
38 * "flayer" to make things easier.
40 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
43 static int is_letter
__P((int));
44 static void nextword
__P((int *, int *, int, int));
45 static int linestart
__P((int));
46 static int lineend
__P((int));
47 static int rem
__P((int, int , int , int , int , char *, int));
48 static int eq
__P((int, int ));
49 static int MarkScrollDownDisplay
__P((int));
50 static int MarkScrollUpDisplay
__P((int));
52 static void MarkProcess
__P((char **, int *));
53 static void MarkAbort
__P((void));
54 static void MarkRedisplayLine
__P((int, int, int, int));
55 static int MarkRewrite
__P((int, int, int, struct mchar
*, int));
57 extern struct layer
*flayer
;
58 extern struct display
*display
, *displays
;
59 extern struct win
*fore
;
60 extern struct mline mline_blank
, mline_null
;
61 extern struct mchar mchar_so
;
67 struct LayFuncs MarkLf
=
81 unsigned char mark_key_tab
[256]; /* this array must be initialised first! */
83 static struct markdata
*markdata
;
87 * VI like is_letter: 0 - whitespace
91 static int is_letter(c
)
94 if ((c
>= 'a' && c
<= 'z') ||
95 (c
>= 'A' && c
<= 'Z') ||
96 (c
>= '0' && c
<= '9') ||
97 c
== '_' || c
== '.' ||
98 c
== '@' || c
== ':' ||
99 c
== '%' || c
== '!' ||
100 c
== '-' || c
== '+')
101 /* thus we can catch email-addresses as a word :-) */
113 register unsigned char *i
;
115 for (x
= markdata
->left_mar
, i
= WIN(y
)->image
+ x
; x
< fore
->w_width
- 1; x
++)
118 if (x
== fore
->w_width
- 1)
119 x
= markdata
->left_mar
;
128 register unsigned char *i
;
130 for (x
= markdata
->right_mar
, i
= WIN(y
)->image
+ x
; x
>= 0; x
--)
134 x
= markdata
->left_mar
;
139 * nextchar sets *xp to the num-th occurrence of the target in the line.
141 * Returns -1 if the target doesn't appear num times, 0 otherwise.
144 nextchar(int *xp
, int *yp
, int direction
, char target
, int num
)
146 int width
; /* width of the current window. */
147 int x
; /* x coordinate of the current cursor position. */
148 int step
; /* amount to increment x (+1 or -1) */
149 int adjust
; /* Final adjustment of cursor position. */
150 char *displayed_line
; /* Line in which search takes place. */
156 width
= fore
->w_width
;
157 displayed_line
= (char *)WIN(*yp
) -> image
;
160 case 't': adjust
= -1; /* fall through */
161 case 'f': step
= 1; /* fall through */
163 case 'T': adjust
= 1; /* fall through */
164 case 'F': step
= -1; /* fall through */
172 debug1("ml->image = %s\n", displayed_line
);
173 debug2("num = %d, width = %d\n",num
, width
);
174 debug2("x = %d target = %c\n", x
, target
);
176 for ( ;x
>=0 && x
<= width
; x
+= step
) {
177 if (displayed_line
[x
] == target
) {
188 * nextword calculates the cursor position of the num'th word.
189 * If the cursor is on a word, it counts as the first.
190 * NW_BACK: search backward
191 * NW_ENDOFWORD: find the end of the word
192 * NW_MUSTMOVE: move at least one char
193 * NW_BIG: match WORDs not words
196 #define NW_BACK (1<<0)
197 #define NW_ENDOFWORD (1<<1)
198 #define NW_MUSTMOVE (1<<2)
199 #define NW_BIG (1<<3)
204 nextword(xp
, yp
, flags
, num
)
205 int *xp
, *yp
, flags
, num
;
207 int xx
= fore
->w_width
, yy
= fore
->w_histheight
+ fore
->w_height
;
208 register int sx
, oq
, q
, x
, y
;
213 sx
= (flags
& NW_BACK
) ? -1 : 1;
214 if ((flags
& NW_ENDOFWORD
) && (flags
& NW_MUSTMOVE
))
217 for (oq
= -1; ; x
+= sx
, oq
= q
)
219 if (x
>= xx
|| x
< 0)
221 else if (flags
& NW_BIG
)
222 q
= ml
->image
[x
] == ' ';
224 q
= is_letter(ml
->image
[x
]);
225 if (oq
>= 0 && oq
!= q
)
227 if (oq
== 0 || !(flags
& NW_ENDOFWORD
))
232 if ((!(flags
& NW_ENDOFWORD
) && q
) ||
233 ((flags
& NW_ENDOFWORD
) && oq
))
258 * y1, y2 are WIN coordinates
260 * redisplay: 0 - just copy
261 * 1 - redisplay + copy
262 * 2 - count + copy, don't redisplay
266 rem(x1
, y1
, x2
, y2
, redisplay
, pt
, yend
)
267 int x1
, y1
, x2
, y2
, redisplay
, yend
;
270 int i
, j
, from
, to
, ry
, c
;
279 markdata
->second
= 0;
280 if (y2
< y1
|| ((y2
== y1
) && (x2
< x1
)))
289 ry
= y1
- markdata
->hist_offset
;
292 if (redisplay
!= 2 && pt
== 0 && ry
<0)
297 for (; i
<= y2
; i
++, ry
++)
299 if (redisplay
!= 2 && pt
== 0 && ry
> yend
)
302 from
= (i
== y1
) ? x1
: 0;
303 if (from
< markdata
->left_mar
)
304 from
= markdata
->left_mar
;
305 for (to
= fore
->w_width
, im
= ml
->image
+ to
; to
>= 0; to
--)
308 if (i
== y2
&& x2
< to
)
310 if (to
> markdata
->right_mar
)
311 to
= markdata
->right_mar
;
312 if (redisplay
== 1 && from
<= to
&& ry
>=0 && ry
<= yend
)
313 MarkRedisplayLine(ry
, from
, to
, 0);
314 if (redisplay
!= 2 && pt
== 0) /* don't count/copy */
318 if (dw_right(ml
, j
, fore
->w_encoding
))
328 c
= (unsigned char)*im
++;
330 cf
= (unsigned char)*fo
++;
332 if (fore
->w_encoding
== UTF8
)
337 c
= ToUtf8_comb(pt
, c
);
347 c
= c
<< 8 | (unsigned char)*im
++;
354 c
= EncodeChar(pt
, c
| cf
<< 16, fore
->w_encoding
, &font
);
366 if (pastefont
&& font
!= ASCII
)
370 strcpy(pt
, "\033(B");
376 if (i
!= y2
&& (to
!= fore
->w_width
- 1 || ml
->image
[to
+ 1] == ' '))
379 * this code defines, what glues lines together
381 switch (markdata
->nonl
)
383 case 0: /* lines separated by newlines */
394 case 1: /* nothing to separate lines */
396 case 2: /* lines separated by blanks */
401 case 3: /* seperate by comma, for csh junkies */
412 /* Check if two chars are identical. All digits are treated
413 * as same. Used for GetHistory()
422 if (a
== 0 || b
== 0)
424 if (a
<= '9' && a
>= '0' && b
<= '9' && b
>= '0')
430 /**********************************************************************/
433 GetHistory() /* return value 1 if copybuffer changed */
435 int i
= 0, q
= 0, xx
, yy
, x
, y
;
436 unsigned char *linep
;
439 ASSERT(display
&& fore
);
441 if (x
>= fore
->w_width
)
442 x
= fore
->w_width
- 1;
443 y
= fore
->w_y
+ fore
->w_histheight
;
444 debug2("cursor is at x=%d, y=%d\n", x
, y
);
446 for (xx
= x
- 1, linep
= ml
->image
+ xx
; xx
>= 0; xx
--)
447 if ((q
= *linep
--) != ' ' )
449 debug3("%c at (%d,%d)\n", q
, xx
, y
);
450 for (yy
= y
- 1; yy
>= 0; yy
--)
454 if (xx
< 0 || eq(linep
[xx
], q
))
455 { /* line is matching... */
456 for (i
= fore
->w_width
- 1, linep
+= i
; i
>= x
; i
--)
465 if (D_user
->u_plop
.buf
)
466 UserFreeCopyBuffer(D_user
);
467 if ((D_user
->u_plop
.buf
= (char *)malloc((unsigned) (i
- x
+ 2))) == NULL
)
469 LMsg(0, "Not enough memory... Sorry.");
472 bcopy((char *)linep
- i
+ x
+ 1, D_user
->u_plop
.buf
, i
- x
+ 1);
473 D_user
->u_plop
.len
= i
- x
+ 1;
475 D_user
->u_plop
.enc
= fore
->w_encoding
;
480 /**********************************************************************/
488 ASSERT(fore
&& display
&& D_user
);
490 debug2("MarkRoutine called: fore nr %d, display %s\n",
491 fore
->w_number
, D_usertty
);
493 if (InitOverlayPage(sizeof(*markdata
), &MarkLf
, 1))
495 flayer
->l_encoding
= fore
->w_encoding
;
496 markdata
= (struct markdata
*)flayer
->l_data
;
497 markdata
->md_user
= D_user
; /* XXX: Correct? */
498 markdata
->md_window
= fore
;
499 markdata
->second
= 0;
500 markdata
->rep_cnt
= 0;
501 markdata
->append_mode
= 0;
502 markdata
->write_buffer
= 0;
504 markdata
->left_mar
= 0;
505 markdata
->right_mar
= fore
->w_width
- 1;
506 markdata
->hist_offset
= fore
->w_histheight
;
509 if (x
>= fore
->w_width
)
510 x
= fore
->w_width
- 1;
512 LGotoPos(flayer
, x
, W2D(y
));
513 LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)",
514 x
+ 1, W2D(y
+ 1), fore
->w_histheight
, fore
->w_width
, fore
->w_height
);
515 markdata
->cx
= markdata
->x1
= x
;
516 markdata
->cy
= markdata
->y1
= y
;
518 flayer
->l_y
= W2D(y
);
522 MarkProcess(inbufp
,inlenp
)
528 int cx
, cy
, x2
, y2
, j
, yend
;
529 int newcopylen
= 0, od
;
532 struct acluser
*md_user
;
535 char *extrap = 0, extrabuf[100];
538 markdata
= (struct markdata
*)flayer
->l_data
;
539 fore
= markdata
->md_window
;
540 md_user
= markdata
->md_user
;
547 LGotoPos(flayer
, markdata
->cx
, W2D(markdata
->cy
));
552 while (in_mark
&& (inlen
/* || extrap */))
564 od
= mark_key_tab
[(int)(unsigned char)*pt
++];
567 rep_cnt
= markdata
->rep_cnt
;
568 if (od
>= '0' && od
<= '9' && !markdata
->f_cmd
.flag
)
570 if (rep_cnt
< 1001 && (od
!= '0' || rep_cnt
!= 0))
572 markdata
->rep_cnt
= 10 * rep_cnt
+ od
- '0';
575 * Now what is that 1001 here? Well, we have a screen with
576 * 25 * 80 = 2000 characters. Movement is at most across the full
577 * screen. This we do with word by word movement, as character by
578 * character movement never steps over line boundaries. The most words
579 * we can place on the screen are 1000 single letter words. Thus 1001
580 * is sufficient. Users with bigger screens never write in single letter
581 * words, as they should be more advanced. jw.
582 * Oh, wrong. We still give even the experienced user a factor of ten.
589 if (markdata
-> f_cmd
.flag
) {
590 debug2("searching for %c:%d\n",od
,rep_cnt
);
591 markdata
->f_cmd
.flag
= 0;
592 markdata
->rep_cnt
= 0;
595 markdata
->f_cmd
.target
= od
;
596 rep_cnt
= (rep_cnt
) ? rep_cnt
: 1;
597 nextchar(&cx
, &cy
, markdata
->f_cmd
.direction
, od
, rep_cnt
);
605 case 'f': /* fall through */
606 case 'F': /* fall through */
607 case 't': /* fall through */
608 case 'T': /* fall through */
610 * Set f_cmd to do a search on the next key stroke.
611 * If we break, rep_cnt will be reset, so we
612 * continue instead. It might be cleaner to
613 * store the rep_count in f_cmd and
614 * break here so later followon code will be
617 markdata
->f_cmd
.flag
= 1;
618 markdata
->f_cmd
.direction
= od
;
619 debug("entering char search\n");
622 if (!markdata
->f_cmd
.target
)
626 nextchar(&cx
, &cy
, markdata
->f_cmd
.direction
, markdata
->f_cmd
.target
, rep_cnt
);
631 if (!markdata
->f_cmd
.target
)
635 switch (markdata
->f_cmd
.direction
) {
636 case 't': search_dir
= 'T'; break;
637 case 'T': search_dir
= 't'; break;
638 case 'f': search_dir
= 'F'; break;
639 case 'F': search_dir
= 'f'; break;
641 nextchar(&cx
, &cy
, search_dir
, markdata
->f_cmd
.target
, rep_cnt
);
648 if (!markdata
->second
)
650 markdata
->cx
= markdata
->x1
;
651 markdata
->cy
= markdata
->y1
;
654 revto(markdata
->cx
, markdata
->cy
);
656 case '\014': /* CTRL-L Redisplay */
658 LGotoPos(flayer
, cx
, W2D(cy
));
660 case 0202: /* M-C-b */
661 case '\010': /* CTRL-H Backspace */
665 revto(cx
- rep_cnt
, cy
);
667 case 0216: /* M-C-p */
668 case '\016': /* CTRL-N */
672 revto(cx
, cy
+ rep_cnt
);
678 if (j
> fore
->w_histheight
+ fore
->w_height
- 1)
679 j
= fore
->w_histheight
+ fore
->w_height
- 1;
680 revto(linestart(j
), j
);
688 revto(linestart(cy
), cy
);
691 revto(linestart(cy
), cy
);
694 revto(markdata
->left_mar
, cy
+ 1);
696 case 0220: /* M-C-p */
697 case '\020': /* CTRL-P */
701 revto(cx
, cy
- rep_cnt
);
703 case 0206: /* M-C-f */
707 revto(cx
+ rep_cnt
, cy
);
709 case '\001': /* CTRL-A from tcsh/emacs */
711 revto(markdata
->left_mar
, cy
);
713 case '\004': /* CTRL-D down half screen */
715 rep_cnt
= (fore
->w_height
+ 1) >> 1;
716 revto_line(cx
, cy
+ rep_cnt
, W2D(cy
));
719 revto(lineend(cy
), cy
);
721 case '\022': /* CTRL-R emacs style backwards search */
725 case '\023': /* CTRL-S emacs style search */
729 case '\025': /* CTRL-U up half screen */
731 rep_cnt
= (fore
->w_height
+ 1) >> 1;
732 revto_line(cx
, cy
- rep_cnt
, W2D(cy
));
734 case '\007': /* CTRL-G show cursorpos */
735 if (markdata
->left_mar
== 0 && markdata
->right_mar
== fore
->w_width
- 1)
736 LMsg(0, "Column %d Line %d(+%d)", cx
+1, W2D(cy
)+1,
737 markdata
->hist_offset
);
739 LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx
+1,
740 markdata
->left_mar
+1, markdata
->right_mar
+1, W2D(cy
)+1, markdata
->hist_offset
);
742 case '\002': /* CTRL-B back one page */
745 rep_cnt
*= fore
->w_height
;
746 revto(cx
, cy
- rep_cnt
);
748 case '\006': /* CTRL-F forward one page */
751 rep_cnt
*= fore
->w_height
;
752 revto(cx
, cy
+ rep_cnt
);
754 case '\005': /* CTRL-E scroll up */
757 rep_cnt
= MarkScrollUpDisplay(rep_cnt
);
761 LGotoPos(flayer
, cx
, W2D(cy
));
763 case '\031': /* CTRL-Y scroll down */
766 rep_cnt
= MarkScrollDownDisplay(rep_cnt
);
767 if (cy
> D2W(fore
->w_height
-1))
768 revto(cx
, D2W(fore
->w_height
-1));
770 LGotoPos(flayer
, cx
, W2D(cy
));
773 /* it may be usefull to have a key that does nothing */
777 /* rep_cnt is a percentage for the history buffer */
782 revto_line(markdata
->left_mar
, (rep_cnt
* (fore
->w_histheight
+ fore
->w_height
)) / 100, (fore
->w_height
- 1) / 2);
790 /* rep_cnt is here the WIN line number */
792 rep_cnt
= fore
->w_histheight
+ fore
->w_height
;
793 revto_line(markdata
->left_mar
, --rep_cnt
, (fore
->w_height
- 1) / 2);
796 revto(markdata
->left_mar
, D2W(0));
799 revto(markdata
->left_mar
, D2W((fore
->w_height
- 1) / 2));
802 revto(markdata
->left_mar
, D2W(fore
->w_height
- 1));
805 revto(--rep_cnt
, cy
);
810 nextword(&cx
, &cy
, NW_MUSTMOVE
, rep_cnt
);
817 nextword(&cx
, &cy
, NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'E' ? NW_BIG
: 0), rep_cnt
);
824 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'B' ? NW_BIG
: 0), rep_cnt
);
828 markdata
->append_mode
= 1 - markdata
->append_mode
;
829 debug1("append mode %d--\n", markdata
->append_mode
);
830 LMsg(0, (markdata
->append_mode
) ? ":set append" : ":set noappend");
834 /* this sets start column to column 9 for VI :set nu users */
835 if (markdata
->left_mar
== 8)
842 /* set start column (c) and end column (C) */
843 if (markdata
->second
)
845 rem(markdata
->x1
, markdata
->y1
, cx
, cy
, 1, (char *)0, fore
->w_height
-1); /* Hack */
846 markdata
->second
= 1; /* rem turns off second */
853 markdata
->left_mar
= rep_cnt
;
854 if (markdata
->left_mar
> markdata
->right_mar
)
855 markdata
->left_mar
= markdata
->right_mar
;
859 markdata
->right_mar
= rep_cnt
;
860 if (markdata
->left_mar
> markdata
->right_mar
)
861 markdata
->right_mar
= markdata
->left_mar
;
863 if (markdata
->second
)
865 markdata
->cx
= markdata
->x1
; markdata
->cy
= markdata
->y1
;
868 if (od
== 'v' || od
== 'V')
869 LMsg(0, (markdata
->left_mar
!= 8) ? ":set nonu" : ":set nu");
872 /* how do you join lines in VI ? */
873 markdata
->nonl
= (markdata
->nonl
+ 1) % 4;
874 switch (markdata
->nonl
)
878 LMsg(0, "Multiple lines (CR/LF)");
880 LMsg(0, "Multiple lines (LF)");
883 LMsg(0, "Lines joined");
886 LMsg(0, "Lines joined with blanks");
889 LMsg(0, "Lines joined with comma");
905 markdata
->isdir
= -markdata
->isdir
;
907 markdata
->isdir
= -markdata
->isdir
;
911 if (markdata
->second
== 0)
913 revto(linestart(cy
), cy
);
915 cx
= markdata
->x1
= markdata
->cx
;
916 cy
= markdata
->y1
= markdata
->cy
;
919 revto(cx
, cy
+ rep_cnt
);
920 revto(lineend(markdata
->cy
), markdata
->cy
);
929 if (!markdata
->second
)
931 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
, 1);
934 cx
= markdata
->x1
= markdata
->cx
;
935 cy
= markdata
->y1
= markdata
->cy
;
937 nextword(&cx
, &cy
, NW_ENDOFWORD
, rep_cnt
);
945 markdata
->append_mode
= 1;
949 markdata
->write_buffer
= 1;
953 if (!markdata
->second
)
959 LMsg(0, "First mark set - Column %d Line %d", cx
+1, W2D(cy
)+1);
964 int append_mode
= markdata
->append_mode
;
965 int write_buffer
= markdata
->write_buffer
;
969 newcopylen
= rem(markdata
->x1
, markdata
->y1
, x2
, y2
, 2, (char *)0, 0); /* count */
970 if (md_user
->u_plop
.buf
&& !append_mode
)
971 UserFreeCopyBuffer(md_user
);
972 yend
= fore
->w_height
- 1;
973 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
975 markdata
->second
= 0;
976 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
980 /* the +3 below is for : cr + lf + \0 */
981 if (md_user
->u_plop
.buf
)
982 md_user
->u_plop
.buf
= realloc(md_user
->u_plop
.buf
,
983 (unsigned) (md_user
->u_plop
.len
+ newcopylen
+ 3));
986 md_user
->u_plop
.len
= 0;
987 md_user
->u_plop
.buf
= malloc((unsigned) (newcopylen
+ 3));
989 if (!md_user
->u_plop
.buf
)
993 LMsg(0, "Not enough memory... Sorry.");
994 md_user
->u_plop
.len
= 0;
995 md_user
->u_plop
.buf
= 0;
1000 switch (markdata
->nonl
)
1003 * this code defines, what glues lines together
1008 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\r';
1009 md_user
->u_plop
.len
++;
1011 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\n';
1012 md_user
->u_plop
.len
++;
1017 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ' ';
1018 md_user
->u_plop
.len
++;
1021 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ',';
1022 md_user
->u_plop
.len
++;
1026 md_user
->u_plop
.len
+= rem(markdata
->x1
, markdata
->y1
, x2
, y2
,
1027 markdata
->hist_offset
== fore
->w_histheight
,
1028 md_user
->u_plop
.buf
+ md_user
->u_plop
.len
, yend
);
1030 md_user
->u_plop
.enc
= fore
->w_encoding
;
1033 if (markdata
->hist_offset
!= fore
->w_histheight
)
1035 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1039 LMsg(0, "Appended %d characters to buffer",
1042 LMsg(0, "Copied %d characters into buffer", md_user
->u_plop
.len
);
1044 WriteFile(md_user
, (char *)0, DUMP_EXCHANGE
);
1050 LMsg(0, "Copy mode aborted");
1054 if (in_mark
) /* markdata may be freed */
1055 markdata
->rep_cnt
= 0;
1059 flayer
->l_x
= markdata
->cx
;
1060 flayer
->l_y
= W2D(markdata
->cy
);
1069 revto_line(tx
, ty
, -1);
1072 /* tx, ty: WINDOW, line: DISPLAY */
1073 void revto_line(tx
, ty
, line
)
1077 int x
, y
, t
, revst
, reven
, qq
, ff
, tt
, st
, en
, ce
= 0;
1078 int ystart
= 0, yend
= fore
->w_height
-1;
1086 else if (tx
> fore
->w_width
- 1)
1087 tx
= fore
->w_width
-1;
1090 else if (ty
> fore
->w_histheight
+ fore
->w_height
- 1)
1091 ty
= fore
->w_histheight
+ fore
->w_height
- 1;
1093 fx
= markdata
->cx
; fy
= markdata
->cy
;
1096 /* don't just move inside of a kanji, the user wants to see something */
1098 if (ty
== fy
&& fx
+ 1 == tx
&& dw_right(ml
, tx
, fore
->w_encoding
) && tx
< D_width
- 1)
1100 if (ty
== fy
&& fx
- 1 == tx
&& dw_right(ml
, fx
, fore
->w_encoding
) && tx
)
1104 markdata
->cx
= tx
; markdata
->cy
= ty
;
1107 * if we go to a position that is currently offscreen
1108 * then scroll the screen
1111 if (line
>= 0 && line
< fore
->w_height
)
1113 else if (ty
< markdata
->hist_offset
)
1114 i
= ty
- markdata
->hist_offset
;
1115 else if (ty
> markdata
->hist_offset
+ (fore
->w_height
- 1))
1116 i
= ty
- markdata
->hist_offset
- (fore
->w_height
- 1);
1118 yend
-= MarkScrollUpDisplay(i
);
1120 ystart
+= MarkScrollDownDisplay(-i
);
1122 if (markdata
->second
== 0)
1124 LGotoPos(flayer
, tx
, W2D(ty
));
1128 qq
= markdata
->x1
+ markdata
->y1
* fore
->w_width
;
1129 ff
= fx
+ fy
* fore
->w_width
; /* "from" offset in WIN coords */
1130 tt
= tx
+ ty
* fore
->w_width
; /* "to" offset in WIN coords*/
1151 revst
= qq
; reven
= tt
;
1155 revst
= tt
; reven
= qq
;
1157 ry
= y
- markdata
->hist_offset
;
1162 st
= y
* fore
->w_width
;
1166 for (t
= st
; t
<= en
; t
++, x
++)
1168 if (x
>= fore
->w_width
)
1176 if (t
== st
|| x
== 0)
1178 wi
= ml
->image
+ fore
->w_width
;
1179 for (ce
= fore
->w_width
; ce
>= 0; ce
--, wi
--)
1183 if (x
<= ce
&& x
>= markdata
->left_mar
&& x
<= markdata
->right_mar
)
1186 if (dw_right(ml
, x
, fore
->w_encoding
))
1194 if (t
>= revst
&& t
<= reven
)
1199 mc
.font
= ml
->font
[x
];
1201 mc
.image
= ml
->image
[x
];
1204 copy_mline2mchar(&mc
, ml
, x
);
1206 if (dw_left(ml
, x
, fore
->w_encoding
))
1208 mc
.mbcs
= ml
->image
[x
+ 1];
1209 LPutChar(flayer
, &mc
, x
, W2D(y
));
1213 LPutChar(flayer
, &mc
, x
, W2D(y
));
1215 if (dw_left(ml
, x
, fore
->w_encoding
))
1220 LGotoPos(flayer
, tx
, W2D(ty
));
1228 debug("MarkAbort\n");
1229 markdata
= (struct markdata
*)flayer
->l_data
;
1230 fore
= markdata
->md_window
;
1231 yend
= fore
->w_height
- 1;
1232 redisp
= markdata
->second
;
1233 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
1235 markdata
->second
= 0;
1236 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
1238 if (markdata
->hist_offset
!= fore
->w_histheight
)
1240 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1244 rem(markdata
->x1
, markdata
->y1
, markdata
->cx
, markdata
->cy
, redisp
, (char *)0, yend
);
1251 MarkRedisplayLine(y
, xs
, xe
, isblank
)
1252 int y
; /* NOTE: y is in DISPLAY coords system! */
1257 int sta
, sto
, cp
; /* NOTE: these 3 are in WINDOW coords system */
1260 struct mchar mchar_marked
;
1262 if (y
< 0) /* No special full page handling */
1265 markdata
= (struct markdata
*)flayer
->l_data
;
1266 fore
= markdata
->md_window
;
1268 mchar_marked
= mchar_so
;
1273 if (markdata
->second
== 0)
1275 if (dw_right(ml
, xs
, fore
->w_encoding
) && xs
> 0)
1277 if (dw_left(ml
, xe
, fore
->w_encoding
) && xe
< fore
->w_width
- 1)
1279 if (xs
== 0 && y
> 0 && wy
> 0 && WIN(wy
- 1)->image
[flayer
->l_width
] == 0)
1280 LCDisplayLineWrap(flayer
, ml
, y
, xs
, xe
, isblank
);
1282 LCDisplayLine(flayer
, ml
, y
, xs
, xe
, isblank
);
1286 sta
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1287 sto
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1290 i
=sta
; sta
=sto
; sto
=i
;
1292 cp
= wy
* fore
->w_width
+ xs
;
1294 rm
= markdata
->right_mar
;
1295 for (x
= fore
->w_width
, wi
= ml
->image
+ fore
->w_width
; x
>= 0; x
--, wi
--)
1301 for (x
= xs
; x
<= xe
; x
++, cp
++)
1302 if (cp
>= sta
&& x
>= markdata
->left_mar
)
1305 if (dw_right(ml
, x
, fore
->w_encoding
))
1309 LCDisplayLine(flayer
, ml
, y
, xs
, x
- 1, isblank
);
1310 for (; x
<= xe
; x
++, cp
++)
1312 if (cp
> sto
|| x
> rm
)
1316 mchar_marked
.font
= ml
->font
[x
];
1318 mchar_marked
.image
= ml
->image
[x
];
1320 mchar_marked
.mbcs
= 0;
1321 if (dw_left(ml
, x
, fore
->w_encoding
))
1323 mchar_marked
.mbcs
= ml
->image
[x
+ 1];
1327 LPutChar(flayer
, &mchar_marked
, x
, y
);
1329 if (dw_left(ml
, x
, fore
->w_encoding
))
1334 LCDisplayLine(flayer
, ml
, y
, x
, xe
, isblank
);
1339 * This ugly routine is to speed up GotoPos()
1342 MarkRewrite(ry
, xs
, xe
, rend
, doit
)
1343 int ry
, xs
, xe
, doit
;
1346 int dx
, x
, y
, st
, en
, t
, rm
;
1349 struct mchar mchar_marked
;
1351 mchar_marked
= mchar_so
;
1353 debug3("MarkRewrite %d, %d-%d\n", ry
, xs
, xe
);
1354 markdata
= (struct markdata
*)flayer
->l_data
;
1355 fore
= markdata
->md_window
;
1359 if (fore
->w_encoding
&& fore
->w_encoding
!= UTF8
&& D_encoding
== UTF8
&& ContainsSpecialDeffont(ml
, xs
, xe
, fore
->w_encoding
))
1371 if (markdata
->second
== 0)
1375 st
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1376 en
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1379 t
= st
; st
= en
; en
= t
;
1382 t
= y
* fore
->w_width
+ xs
;
1383 for (rm
= fore
->w_width
, i
= ml
->image
+ fore
->w_width
; rm
>= 0; rm
--)
1386 if (rm
> markdata
->right_mar
)
1387 rm
= markdata
->right_mar
;
1391 if (t
>= st
&& t
<= en
&& x
>= markdata
->left_mar
&& x
<= rm
)
1395 mchar_marked
.font
= ml
->font
[x
];
1397 rend
->image
= mchar_marked
.image
;
1398 if (!cmp_mchar(rend
, &mchar_marked
))
1403 rend
->image
= ml
->image
[x
];
1404 if (!cmp_mchar_mline(rend
, ml
, x
))
1414 * scroll the screen contents up/down.
1416 static int MarkScrollUpDisplay(n
)
1421 debug1("MarkScrollUpDisplay(%d)\n", n
);
1424 if (n
> fore
->w_histheight
- markdata
->hist_offset
)
1425 n
= fore
->w_histheight
- markdata
->hist_offset
;
1426 markdata
->hist_offset
+= n
;
1427 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1428 LScrollV(flayer
, i
, 0, flayer
->l_height
- 1, 0);
1430 MarkRedisplayLine(flayer
->l_height
- i
- 1, 0, flayer
->l_width
- 1, 1);
1435 MarkScrollDownDisplay(n
)
1440 debug1("MarkScrollDownDisplay(%d)\n", n
);
1443 if (n
> markdata
->hist_offset
)
1444 n
= markdata
->hist_offset
;
1445 markdata
->hist_offset
-= n
;
1446 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1447 LScrollV(flayer
, -i
, 0, fore
->w_height
- 1, 0);
1449 MarkRedisplayLine(i
, 0, flayer
->l_width
- 1, 1);
1456 if (flayer
&& flayer
->l_layfn
== &MarkLf
)
1462 MakePaster(pa
, buf
, len
, bufiscopy
)
1469 pa
->pa_pasteptr
= buf
;
1470 pa
->pa_pastelen
= len
;
1472 pa
->pa_pastebuf
= buf
;
1473 pa
->pa_pastelayer
= flayer
;
1474 DoProcess(Layer2Window(flayer
), &pa
->pa_pasteptr
, &pa
->pa_pastelen
, pa
);
1481 if (pa
->pa_pastebuf
)
1482 free(pa
->pa_pastebuf
);
1483 pa
->pa_pastebuf
= 0;
1484 pa
->pa_pasteptr
= 0;
1485 pa
->pa_pastelen
= 0;
1486 pa
->pa_pastelayer
= 0;
1487 evdeq(&pa
->pa_slowev
);
1490 #endif /* COPY_PASTE */