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 target = %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");
621 if (!markdata
->f_cmd
.target
)
625 nextchar(&cx
, &cy
, markdata
->f_cmd
.direction
, markdata
->f_cmd
.target
, rep_cnt
);
630 if (!markdata
->f_cmd
.target
)
634 switch (markdata
->f_cmd
.direction
) {
635 case 't': search_dir
= 'T'; break;
636 case 'T': search_dir
= 't'; break;
637 case 'f': search_dir
= 'F'; break;
638 case 'F': search_dir
= 'f'; break;
640 nextchar(&cx
, &cy
, search_dir
, markdata
->f_cmd
.target
, rep_cnt
);
647 if (!markdata
->second
)
649 markdata
->cx
= markdata
->x1
;
650 markdata
->cy
= markdata
->y1
;
653 revto(markdata
->cx
, markdata
->cy
);
655 case '\014': /* CTRL-L Redisplay */
657 LGotoPos(flayer
, cx
, W2D(cy
));
659 case 0202: /* M-C-b */
660 case '\010': /* CTRL-H Backspace */
664 revto(cx
- rep_cnt
, cy
);
666 case 0216: /* M-C-p */
667 case '\016': /* CTRL-N */
671 revto(cx
, cy
+ rep_cnt
);
677 if (j
> fore
->w_histheight
+ fore
->w_height
- 1)
678 j
= fore
->w_histheight
+ fore
->w_height
- 1;
679 revto(linestart(j
), j
);
687 revto(linestart(cy
), cy
);
690 revto(linestart(cy
), cy
);
693 revto(markdata
->left_mar
, cy
+ 1);
695 case 0220: /* M-C-p */
696 case '\020': /* CTRL-P */
700 revto(cx
, cy
- rep_cnt
);
702 case 0206: /* M-C-f */
706 revto(cx
+ rep_cnt
, cy
);
708 case '\001': /* CTRL-A from tcsh/emacs */
710 revto(markdata
->left_mar
, cy
);
712 case '\004': /* CTRL-D down half screen */
714 rep_cnt
= (fore
->w_height
+ 1) >> 1;
715 revto_line(cx
, cy
+ rep_cnt
, W2D(cy
));
718 revto(lineend(cy
), cy
);
720 case '\022': /* CTRL-R emacs style backwards search */
724 case '\023': /* CTRL-S emacs style search */
728 case '\025': /* CTRL-U up half screen */
730 rep_cnt
= (fore
->w_height
+ 1) >> 1;
731 revto_line(cx
, cy
- rep_cnt
, W2D(cy
));
733 case '\007': /* CTRL-G show cursorpos */
734 if (markdata
->left_mar
== 0 && markdata
->right_mar
== fore
->w_width
- 1)
735 LMsg(0, "Column %d Line %d(+%d)", cx
+1, W2D(cy
)+1,
736 markdata
->hist_offset
);
738 LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx
+1,
739 markdata
->left_mar
+1, markdata
->right_mar
+1, W2D(cy
)+1, markdata
->hist_offset
);
741 case '\002': /* CTRL-B back one page */
744 rep_cnt
*= fore
->w_height
;
745 revto(cx
, cy
- rep_cnt
);
747 case '\006': /* CTRL-F forward one page */
750 rep_cnt
*= fore
->w_height
;
751 revto(cx
, cy
+ rep_cnt
);
753 case '\005': /* CTRL-E scroll up */
756 rep_cnt
= MarkScrollUpDisplay(rep_cnt
);
760 LGotoPos(flayer
, cx
, W2D(cy
));
762 case '\031': /* CTRL-Y scroll down */
765 rep_cnt
= MarkScrollDownDisplay(rep_cnt
);
766 if (cy
> D2W(fore
->w_height
-1))
767 revto(cx
, D2W(fore
->w_height
-1));
769 LGotoPos(flayer
, cx
, W2D(cy
));
772 /* it may be usefull to have a key that does nothing */
776 /* rep_cnt is a percentage for the history buffer */
781 revto_line(markdata
->left_mar
, (rep_cnt
* (fore
->w_histheight
+ fore
->w_height
)) / 100, (fore
->w_height
- 1) / 2);
789 /* rep_cnt is here the WIN line number */
791 rep_cnt
= fore
->w_histheight
+ fore
->w_height
;
792 revto_line(markdata
->left_mar
, --rep_cnt
, (fore
->w_height
- 1) / 2);
795 revto(markdata
->left_mar
, D2W(0));
798 revto(markdata
->left_mar
, D2W((fore
->w_height
- 1) / 2));
801 revto(markdata
->left_mar
, D2W(fore
->w_height
- 1));
804 revto(--rep_cnt
, cy
);
809 nextword(&cx
, &cy
, NW_MUSTMOVE
, rep_cnt
);
816 nextword(&cx
, &cy
, NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'E' ? NW_BIG
: 0), rep_cnt
);
823 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'B' ? NW_BIG
: 0), rep_cnt
);
827 markdata
->append_mode
= 1 - markdata
->append_mode
;
828 debug1("append mode %d--\n", markdata
->append_mode
);
829 LMsg(0, (markdata
->append_mode
) ? ":set append" : ":set noappend");
833 /* this sets start column to column 9 for VI :set nu users */
834 if (markdata
->left_mar
== 8)
841 /* set start column (c) and end column (C) */
842 if (markdata
->second
)
844 rem(markdata
->x1
, markdata
->y1
, cx
, cy
, 1, (char *)0, fore
->w_height
-1); /* Hack */
845 markdata
->second
= 1; /* rem turns off second */
852 markdata
->left_mar
= rep_cnt
;
853 if (markdata
->left_mar
> markdata
->right_mar
)
854 markdata
->left_mar
= markdata
->right_mar
;
858 markdata
->right_mar
= rep_cnt
;
859 if (markdata
->left_mar
> markdata
->right_mar
)
860 markdata
->right_mar
= markdata
->left_mar
;
862 if (markdata
->second
)
864 markdata
->cx
= markdata
->x1
; markdata
->cy
= markdata
->y1
;
867 if (od
== 'v' || od
== 'V')
868 LMsg(0, (markdata
->left_mar
!= 8) ? ":set nonu" : ":set nu");
871 /* how do you join lines in VI ? */
872 markdata
->nonl
= (markdata
->nonl
+ 1) % 4;
873 switch (markdata
->nonl
)
877 LMsg(0, "Multiple lines (CR/LF)");
879 LMsg(0, "Multiple lines (LF)");
882 LMsg(0, "Lines joined");
885 LMsg(0, "Lines joined with blanks");
888 LMsg(0, "Lines joined with comma");
904 markdata
->isdir
= -markdata
->isdir
;
906 markdata
->isdir
= -markdata
->isdir
;
910 if (markdata
->second
== 0)
912 revto(linestart(cy
), cy
);
914 cx
= markdata
->x1
= markdata
->cx
;
915 cy
= markdata
->y1
= markdata
->cy
;
918 revto(cx
, cy
+ rep_cnt
);
919 revto(lineend(markdata
->cy
), markdata
->cy
);
928 if (!markdata
->second
)
930 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
, 1);
933 cx
= markdata
->x1
= markdata
->cx
;
934 cy
= markdata
->y1
= markdata
->cy
;
936 nextword(&cx
, &cy
, NW_ENDOFWORD
, rep_cnt
);
944 markdata
->append_mode
= 1;
948 markdata
->write_buffer
= 1;
952 if (!markdata
->second
)
958 LMsg(0, "First mark set - Column %d Line %d", cx
+1, W2D(cy
)+1);
963 int append_mode
= markdata
->append_mode
;
964 int write_buffer
= markdata
->write_buffer
;
968 newcopylen
= rem(markdata
->x1
, markdata
->y1
, x2
, y2
, 2, (char *)0, 0); /* count */
969 if (md_user
->u_plop
.buf
&& !append_mode
)
970 UserFreeCopyBuffer(md_user
);
971 yend
= fore
->w_height
- 1;
972 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
974 markdata
->second
= 0;
975 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
979 /* the +3 below is for : cr + lf + \0 */
980 if (md_user
->u_plop
.buf
)
981 md_user
->u_plop
.buf
= realloc(md_user
->u_plop
.buf
,
982 (unsigned) (md_user
->u_plop
.len
+ newcopylen
+ 3));
985 md_user
->u_plop
.len
= 0;
986 md_user
->u_plop
.buf
= malloc((unsigned) (newcopylen
+ 3));
988 if (!md_user
->u_plop
.buf
)
992 LMsg(0, "Not enough memory... Sorry.");
993 md_user
->u_plop
.len
= 0;
994 md_user
->u_plop
.buf
= 0;
999 switch (markdata
->nonl
)
1002 * this code defines, what glues lines together
1007 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\r';
1008 md_user
->u_plop
.len
++;
1010 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\n';
1011 md_user
->u_plop
.len
++;
1016 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ' ';
1017 md_user
->u_plop
.len
++;
1020 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ',';
1021 md_user
->u_plop
.len
++;
1025 md_user
->u_plop
.len
+= rem(markdata
->x1
, markdata
->y1
, x2
, y2
,
1026 markdata
->hist_offset
== fore
->w_histheight
,
1027 md_user
->u_plop
.buf
+ md_user
->u_plop
.len
, yend
);
1029 md_user
->u_plop
.enc
= fore
->w_encoding
;
1032 if (markdata
->hist_offset
!= fore
->w_histheight
)
1034 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1038 LMsg(0, "Appended %d characters to buffer",
1041 LMsg(0, "Copied %d characters into buffer", md_user
->u_plop
.len
);
1043 WriteFile(md_user
, (char *)0, DUMP_EXCHANGE
);
1049 LMsg(0, "Copy mode aborted");
1053 if (in_mark
) /* markdata may be freed */
1054 markdata
->rep_cnt
= 0;
1058 flayer
->l_x
= markdata
->cx
;
1059 flayer
->l_y
= W2D(markdata
->cy
);
1068 revto_line(tx
, ty
, -1);
1071 /* tx, ty: WINDOW, line: DISPLAY */
1072 void revto_line(tx
, ty
, line
)
1076 int x
, y
, t
, revst
, reven
, qq
, ff
, tt
, st
, en
, ce
= 0;
1077 int ystart
= 0, yend
= fore
->w_height
-1;
1085 else if (tx
> fore
->w_width
- 1)
1086 tx
= fore
->w_width
-1;
1089 else if (ty
> fore
->w_histheight
+ fore
->w_height
- 1)
1090 ty
= fore
->w_histheight
+ fore
->w_height
- 1;
1092 fx
= markdata
->cx
; fy
= markdata
->cy
;
1095 /* don't just move inside of a kanji, the user wants to see something */
1097 if (ty
== fy
&& fx
+ 1 == tx
&& dw_right(ml
, tx
, fore
->w_encoding
) && tx
< D_width
- 1)
1099 if (ty
== fy
&& fx
- 1 == tx
&& dw_right(ml
, fx
, fore
->w_encoding
) && tx
)
1103 markdata
->cx
= tx
; markdata
->cy
= ty
;
1106 * if we go to a position that is currently offscreen
1107 * then scroll the screen
1110 if (line
>= 0 && line
< fore
->w_height
)
1112 else if (ty
< markdata
->hist_offset
)
1113 i
= ty
- markdata
->hist_offset
;
1114 else if (ty
> markdata
->hist_offset
+ (fore
->w_height
- 1))
1115 i
= ty
- markdata
->hist_offset
- (fore
->w_height
- 1);
1117 yend
-= MarkScrollUpDisplay(i
);
1119 ystart
+= MarkScrollDownDisplay(-i
);
1121 if (markdata
->second
== 0)
1123 LGotoPos(flayer
, tx
, W2D(ty
));
1127 qq
= markdata
->x1
+ markdata
->y1
* fore
->w_width
;
1128 ff
= fx
+ fy
* fore
->w_width
; /* "from" offset in WIN coords */
1129 tt
= tx
+ ty
* fore
->w_width
; /* "to" offset in WIN coords*/
1150 revst
= qq
; reven
= tt
;
1154 revst
= tt
; reven
= qq
;
1156 ry
= y
- markdata
->hist_offset
;
1161 st
= y
* fore
->w_width
;
1165 for (t
= st
; t
<= en
; t
++, x
++)
1167 if (x
>= fore
->w_width
)
1175 if (t
== st
|| x
== 0)
1177 wi
= ml
->image
+ fore
->w_width
;
1178 for (ce
= fore
->w_width
; ce
>= 0; ce
--, wi
--)
1182 if (x
<= ce
&& x
>= markdata
->left_mar
&& x
<= markdata
->right_mar
)
1185 if (dw_right(ml
, x
, fore
->w_encoding
))
1193 if (t
>= revst
&& t
<= reven
)
1198 mc
.font
= ml
->font
[x
];
1200 mc
.image
= ml
->image
[x
];
1203 copy_mline2mchar(&mc
, ml
, x
);
1205 if (dw_left(ml
, x
, fore
->w_encoding
))
1207 mc
.mbcs
= ml
->image
[x
+ 1];
1208 LPutChar(flayer
, &mc
, x
, W2D(y
));
1212 LPutChar(flayer
, &mc
, x
, W2D(y
));
1214 if (dw_left(ml
, x
, fore
->w_encoding
))
1219 LGotoPos(flayer
, tx
, W2D(ty
));
1227 debug("MarkAbort\n");
1228 markdata
= (struct markdata
*)flayer
->l_data
;
1229 fore
= markdata
->md_window
;
1230 yend
= fore
->w_height
- 1;
1231 redisp
= markdata
->second
;
1232 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
1234 markdata
->second
= 0;
1235 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
1237 if (markdata
->hist_offset
!= fore
->w_histheight
)
1239 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1243 rem(markdata
->x1
, markdata
->y1
, markdata
->cx
, markdata
->cy
, redisp
, (char *)0, yend
);
1250 MarkRedisplayLine(y
, xs
, xe
, isblank
)
1251 int y
; /* NOTE: y is in DISPLAY coords system! */
1256 int sta
, sto
, cp
; /* NOTE: these 3 are in WINDOW coords system */
1259 struct mchar mchar_marked
;
1261 if (y
< 0) /* No special full page handling */
1264 markdata
= (struct markdata
*)flayer
->l_data
;
1265 fore
= markdata
->md_window
;
1267 mchar_marked
= mchar_so
;
1272 if (markdata
->second
== 0)
1274 if (dw_right(ml
, xs
, fore
->w_encoding
) && xs
> 0)
1276 if (dw_left(ml
, xe
, fore
->w_encoding
) && xe
< fore
->w_width
- 1)
1278 if (xs
== 0 && y
> 0 && wy
> 0 && WIN(wy
- 1)->image
[flayer
->l_width
] == 0)
1279 LCDisplayLineWrap(flayer
, ml
, y
, xs
, xe
, isblank
);
1281 LCDisplayLine(flayer
, ml
, y
, xs
, xe
, isblank
);
1285 sta
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1286 sto
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1289 i
=sta
; sta
=sto
; sto
=i
;
1291 cp
= wy
* fore
->w_width
+ xs
;
1293 rm
= markdata
->right_mar
;
1294 for (x
= fore
->w_width
, wi
= ml
->image
+ fore
->w_width
; x
>= 0; x
--, wi
--)
1300 for (x
= xs
; x
<= xe
; x
++, cp
++)
1301 if (cp
>= sta
&& x
>= markdata
->left_mar
)
1304 if (dw_right(ml
, x
, fore
->w_encoding
))
1308 LCDisplayLine(flayer
, ml
, y
, xs
, x
- 1, isblank
);
1309 for (; x
<= xe
; x
++, cp
++)
1311 if (cp
> sto
|| x
> rm
)
1315 mchar_marked
.font
= ml
->font
[x
];
1317 mchar_marked
.image
= ml
->image
[x
];
1319 mchar_marked
.mbcs
= 0;
1320 if (dw_left(ml
, x
, fore
->w_encoding
))
1322 mchar_marked
.mbcs
= ml
->image
[x
+ 1];
1326 LPutChar(flayer
, &mchar_marked
, x
, y
);
1328 if (dw_left(ml
, x
, fore
->w_encoding
))
1333 LCDisplayLine(flayer
, ml
, y
, x
, xe
, isblank
);
1338 * This ugly routine is to speed up GotoPos()
1341 MarkRewrite(ry
, xs
, xe
, rend
, doit
)
1342 int ry
, xs
, xe
, doit
;
1345 int dx
, x
, y
, st
, en
, t
, rm
;
1348 struct mchar mchar_marked
;
1350 mchar_marked
= mchar_so
;
1352 debug3("MarkRewrite %d, %d-%d\n", ry
, xs
, xe
);
1353 markdata
= (struct markdata
*)flayer
->l_data
;
1354 fore
= markdata
->md_window
;
1358 if (fore
->w_encoding
&& fore
->w_encoding
!= UTF8
&& D_encoding
== UTF8
&& ContainsSpecialDeffont(ml
, xs
, xe
, fore
->w_encoding
))
1370 if (markdata
->second
== 0)
1374 st
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1375 en
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1378 t
= st
; st
= en
; en
= t
;
1381 t
= y
* fore
->w_width
+ xs
;
1382 for (rm
= fore
->w_width
, i
= ml
->image
+ fore
->w_width
; rm
>= 0; rm
--)
1385 if (rm
> markdata
->right_mar
)
1386 rm
= markdata
->right_mar
;
1390 if (t
>= st
&& t
<= en
&& x
>= markdata
->left_mar
&& x
<= rm
)
1394 mchar_marked
.font
= ml
->font
[x
];
1396 rend
->image
= mchar_marked
.image
;
1397 if (!cmp_mchar(rend
, &mchar_marked
))
1402 rend
->image
= ml
->image
[x
];
1403 if (!cmp_mchar_mline(rend
, ml
, x
))
1413 * scroll the screen contents up/down.
1415 static int MarkScrollUpDisplay(n
)
1420 debug1("MarkScrollUpDisplay(%d)\n", n
);
1423 if (n
> fore
->w_histheight
- markdata
->hist_offset
)
1424 n
= fore
->w_histheight
- markdata
->hist_offset
;
1425 markdata
->hist_offset
+= n
;
1426 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1427 LScrollV(flayer
, i
, 0, flayer
->l_height
- 1, 0);
1429 MarkRedisplayLine(flayer
->l_height
- i
- 1, 0, flayer
->l_width
- 1, 1);
1434 MarkScrollDownDisplay(n
)
1439 debug1("MarkScrollDownDisplay(%d)\n", n
);
1442 if (n
> markdata
->hist_offset
)
1443 n
= markdata
->hist_offset
;
1444 markdata
->hist_offset
-= n
;
1445 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1446 LScrollV(flayer
, -i
, 0, fore
->w_height
- 1, 0);
1448 MarkRedisplayLine(i
, 0, flayer
->l_width
- 1, 1);
1455 if (flayer
&& flayer
->l_layfn
== &MarkLf
)
1461 MakePaster(pa
, buf
, len
, bufiscopy
)
1468 pa
->pa_pasteptr
= buf
;
1469 pa
->pa_pastelen
= len
;
1471 pa
->pa_pastebuf
= buf
;
1472 pa
->pa_pastelayer
= flayer
;
1473 DoProcess(Layer2Window(flayer
), &pa
->pa_pasteptr
, &pa
->pa_pastelen
, pa
);
1480 if (pa
->pa_pastebuf
)
1481 free(pa
->pa_pastebuf
);
1482 pa
->pa_pastebuf
= 0;
1483 pa
->pa_pasteptr
= 0;
1484 pa
->pa_pastelen
= 0;
1485 pa
->pa_pastelayer
= 0;
1486 evdeq(&pa
->pa_slowev
);
1489 #endif /* COPY_PASTE */