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
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)
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.
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 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h>
40 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
42 * WARNING: these routines use the global variables "fore" and
43 * "flayer" to make things easier.
45 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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));
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));
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
;
72 struct LayFuncs MarkLf
=
86 unsigned char mark_key_tab
[256]; /* this array must be initialised first! */
88 static struct markdata
*markdata
;
92 * VI like is_letter: 0 - whitespace
96 static int is_letter(c
)
99 if ((c
>= 'a' && c
<= 'z') ||
100 (c
>= 'A' && c
<= 'Z') ||
101 (c
>= '0' && c
<= '9') ||
102 c
== '_' || c
== '.' ||
103 c
== '@' || c
== ':' ||
104 c
== '%' || c
== '!' ||
105 c
== '-' || c
== '+')
106 /* thus we can catch email-addresses as a word :-) */
118 register unsigned char *i
;
120 for (x
= markdata
->left_mar
, i
= WIN(y
)->image
+ x
; x
< fore
->w_width
- 1; x
++)
123 if (x
== fore
->w_width
- 1)
124 x
= markdata
->left_mar
;
133 register unsigned char *i
;
135 for (x
= markdata
->right_mar
, i
= WIN(y
)->image
+ x
; x
>= 0; x
--)
139 x
= markdata
->left_mar
;
144 * nextchar sets *xp to the num-th occurrence of the target in the line.
146 * Returns -1 if the target doesn't appear num times, 0 otherwise.
149 nextchar(int *xp
, int *yp
, int direction
, char target
, int num
)
151 int width
; /* width of the current window. */
152 int x
; /* x coordinate of the current cursor position. */
153 int step
; /* amount to increment x (+1 or -1) */
154 int adjust
; /* Final adjustment of cursor position. */
155 char *displayed_line
; /* Line in which search takes place. */
161 width
= fore
->w_width
;
162 displayed_line
= (char *)WIN(*yp
) -> image
;
165 case 't': adjust
= -1; /* fall through */
166 case 'f': step
= 1; /* fall through */
168 case 'T': adjust
= 1; /* fall through */
169 case 'F': step
= -1; /* fall through */
177 debug1("ml->image = %s\n", displayed_line
);
178 debug2("num = %d, width = %d\n",num
, width
);
179 debug2("x = %d target = %c\n", x
, target
);
181 for ( ;x
>=0 && x
<= width
; x
+= step
) {
182 if (displayed_line
[x
] == target
) {
193 * nextword calculates the cursor position of the num'th word.
194 * If the cursor is on a word, it counts as the first.
195 * NW_BACK: search backward
196 * NW_ENDOFWORD: find the end of the word
197 * NW_MUSTMOVE: move at least one char
198 * NW_BIG: match WORDs not words
201 #define NW_BACK (1<<0)
202 #define NW_ENDOFWORD (1<<1)
203 #define NW_MUSTMOVE (1<<2)
204 #define NW_BIG (1<<3)
209 nextword(xp
, yp
, flags
, num
)
210 int *xp
, *yp
, flags
, num
;
212 int xx
= fore
->w_width
, yy
= fore
->w_histheight
+ fore
->w_height
;
213 register int sx
, oq
, q
, x
, y
;
218 sx
= (flags
& NW_BACK
) ? -1 : 1;
219 if ((flags
& NW_ENDOFWORD
) && (flags
& NW_MUSTMOVE
))
222 for (oq
= -1; ; x
+= sx
, oq
= q
)
224 if (x
>= xx
|| x
< 0)
226 else if (flags
& NW_BIG
)
227 q
= ml
->image
[x
] == ' ';
229 q
= is_letter(ml
->image
[x
]);
230 if (oq
>= 0 && oq
!= q
)
232 if (oq
== 0 || !(flags
& NW_ENDOFWORD
))
237 if ((!(flags
& NW_ENDOFWORD
) && q
) ||
238 ((flags
& NW_ENDOFWORD
) && oq
))
263 * y1, y2 are WIN coordinates
265 * redisplay: 0 - just copy
266 * 1 - redisplay + copy
267 * 2 - count + copy, don't redisplay
271 rem(x1
, y1
, x2
, y2
, redisplay
, pt
, yend
)
272 int x1
, y1
, x2
, y2
, redisplay
, yend
;
275 int i
, j
, from
, to
, ry
, c
;
284 markdata
->second
= 0;
285 if (y2
< y1
|| ((y2
== y1
) && (x2
< x1
)))
294 ry
= y1
- markdata
->hist_offset
;
297 if (redisplay
!= 2 && pt
== 0 && ry
<0)
302 for (; i
<= y2
; i
++, ry
++)
304 if (redisplay
!= 2 && pt
== 0 && ry
> yend
)
307 from
= (i
== y1
) ? x1
: 0;
308 if (from
< markdata
->left_mar
)
309 from
= markdata
->left_mar
;
310 for (to
= fore
->w_width
, im
= ml
->image
+ to
; to
>= 0; to
--)
313 if (i
== y2
&& x2
< to
)
315 if (to
> markdata
->right_mar
)
316 to
= markdata
->right_mar
;
317 if (redisplay
== 1 && from
<= to
&& ry
>=0 && ry
<= yend
)
318 MarkRedisplayLine(ry
, from
, to
, 0);
319 if (redisplay
!= 2 && pt
== 0) /* don't count/copy */
323 if (dw_right(ml
, j
, fore
->w_encoding
))
333 c
= (unsigned char)*im
++;
335 cf
= (unsigned char)*fo
++;
337 if (fore
->w_encoding
== UTF8
)
342 c
= ToUtf8_comb(pt
, c
);
352 c
= c
<< 8 | (unsigned char)*im
++;
359 c
= EncodeChar(pt
, c
| cf
<< 16, fore
->w_encoding
, &font
);
371 if (pastefont
&& font
!= ASCII
)
375 strcpy(pt
, "\033(B");
381 if (i
!= y2
&& (to
!= fore
->w_width
- 1 || ml
->image
[to
+ 1] == ' '))
384 * this code defines, what glues lines together
386 switch (markdata
->nonl
)
388 case 0: /* lines separated by newlines */
399 case 1: /* nothing to separate lines */
401 case 2: /* lines separated by blanks */
406 case 3: /* seperate by comma, for csh junkies */
417 /* Check if two chars are identical. All digits are treated
418 * as same. Used for GetHistory()
427 if (a
== 0 || b
== 0)
429 if (a
<= '9' && a
>= '0' && b
<= '9' && b
>= '0')
435 /**********************************************************************/
438 GetHistory() /* return value 1 if copybuffer changed */
440 int i
= 0, q
= 0, xx
, yy
, x
, y
;
441 unsigned char *linep
;
444 ASSERT(display
&& fore
);
446 if (x
>= fore
->w_width
)
447 x
= fore
->w_width
- 1;
448 y
= fore
->w_y
+ fore
->w_histheight
;
449 debug2("cursor is at x=%d, y=%d\n", x
, y
);
451 for (xx
= x
- 1, linep
= ml
->image
+ xx
; xx
>= 0; xx
--)
452 if ((q
= *linep
--) != ' ' )
454 debug3("%c at (%d,%d)\n", q
, xx
, y
);
455 for (yy
= y
- 1; yy
>= 0; yy
--)
459 if (xx
< 0 || eq(linep
[xx
], q
))
460 { /* line is matching... */
461 for (i
= fore
->w_width
- 1, linep
+= i
; i
>= x
; i
--)
470 if (D_user
->u_plop
.buf
)
471 UserFreeCopyBuffer(D_user
);
472 if ((D_user
->u_plop
.buf
= (char *)malloc((unsigned) (i
- x
+ 2))) == NULL
)
474 LMsg(0, "Not enough memory... Sorry.");
477 bcopy((char *)linep
- i
+ x
+ 1, D_user
->u_plop
.buf
, i
- x
+ 1);
478 D_user
->u_plop
.len
= i
- x
+ 1;
480 D_user
->u_plop
.enc
= fore
->w_encoding
;
485 /**********************************************************************/
493 ASSERT(fore
&& display
&& D_user
);
495 debug2("MarkRoutine called: fore nr %d, display %s\n",
496 fore
->w_number
, D_usertty
);
498 if (InitOverlayPage(sizeof(*markdata
), &MarkLf
, 1))
500 flayer
->l_encoding
= fore
->w_encoding
;
501 markdata
= (struct markdata
*)flayer
->l_data
;
502 markdata
->md_user
= D_user
; /* XXX: Correct? */
503 markdata
->md_window
= fore
;
504 markdata
->second
= 0;
505 markdata
->rep_cnt
= 0;
506 markdata
->append_mode
= 0;
507 markdata
->write_buffer
= 0;
509 markdata
->left_mar
= 0;
510 markdata
->right_mar
= fore
->w_width
- 1;
511 markdata
->hist_offset
= fore
->w_histheight
;
514 if (x
>= fore
->w_width
)
515 x
= fore
->w_width
- 1;
517 LGotoPos(flayer
, x
, W2D(y
));
518 LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)",
519 x
+ 1, W2D(y
+ 1), fore
->w_histheight
, fore
->w_width
, fore
->w_height
);
520 markdata
->cx
= markdata
->x1
= x
;
521 markdata
->cy
= markdata
->y1
= y
;
523 flayer
->l_y
= W2D(y
);
527 MarkProcess(inbufp
,inlenp
)
533 int cx
, cy
, x2
, y2
, j
, yend
;
534 int newcopylen
= 0, od
;
537 struct acluser
*md_user
;
540 char *extrap = 0, extrabuf[100];
543 markdata
= (struct markdata
*)flayer
->l_data
;
544 fore
= markdata
->md_window
;
545 md_user
= markdata
->md_user
;
552 LGotoPos(flayer
, markdata
->cx
, W2D(markdata
->cy
));
557 while (in_mark
&& (inlen
/* || extrap */))
569 od
= mark_key_tab
[(int)(unsigned char)*pt
++];
572 rep_cnt
= markdata
->rep_cnt
;
573 if (od
>= '0' && od
<= '9' && !markdata
->f_cmd
.flag
)
575 if (rep_cnt
< 1001 && (od
!= '0' || rep_cnt
!= 0))
577 markdata
->rep_cnt
= 10 * rep_cnt
+ od
- '0';
580 * Now what is that 1001 here? Well, we have a screen with
581 * 25 * 80 = 2000 characters. Movement is at most across the full
582 * screen. This we do with word by word movement, as character by
583 * character movement never steps over line boundaries. The most words
584 * we can place on the screen are 1000 single letter words. Thus 1001
585 * is sufficient. Users with bigger screens never write in single letter
586 * words, as they should be more advanced. jw.
587 * Oh, wrong. We still give even the experienced user a factor of ten.
594 if (markdata
-> f_cmd
.flag
) {
595 debug2("searching for %c:%d\n",od
,rep_cnt
);
596 markdata
->f_cmd
.flag
= 0;
597 markdata
->rep_cnt
= 0;
600 markdata
->f_cmd
.target
= od
;
601 rep_cnt
= (rep_cnt
) ? rep_cnt
: 1;
602 nextchar(&cx
, &cy
, markdata
->f_cmd
.direction
, od
, rep_cnt
);
610 case 'f': /* fall through */
611 case 'F': /* fall through */
612 case 't': /* fall through */
613 case 'T': /* fall through */
615 * Set f_cmd to do a search on the next key stroke.
616 * If we break, rep_cnt will be reset, so we
617 * continue instead. It might be cleaner to
618 * store the rep_count in f_cmd and
619 * break here so later followon code will be
622 markdata
->f_cmd
.flag
= 1;
623 markdata
->f_cmd
.direction
= od
;
624 debug("entering char search\n");
627 if (!markdata
->f_cmd
.target
)
631 nextchar(&cx
, &cy
, markdata
->f_cmd
.direction
, markdata
->f_cmd
.target
, rep_cnt
);
636 if (!markdata
->f_cmd
.target
)
640 switch (markdata
->f_cmd
.direction
) {
641 case 't': search_dir
= 'T'; break;
642 case 'T': search_dir
= 't'; break;
643 case 'f': search_dir
= 'F'; break;
644 case 'F': search_dir
= 'f'; break;
646 nextchar(&cx
, &cy
, search_dir
, markdata
->f_cmd
.target
, rep_cnt
);
653 if (!markdata
->second
)
655 markdata
->cx
= markdata
->x1
;
656 markdata
->cy
= markdata
->y1
;
659 revto(markdata
->cx
, markdata
->cy
);
661 case '\014': /* CTRL-L Redisplay */
663 LGotoPos(flayer
, cx
, W2D(cy
));
665 case 0202: /* M-C-b */
666 case '\010': /* CTRL-H Backspace */
670 revto(cx
- rep_cnt
, cy
);
672 case 0216: /* M-C-p */
673 case '\016': /* CTRL-N */
677 revto(cx
, cy
+ rep_cnt
);
683 if (j
> fore
->w_histheight
+ fore
->w_height
- 1)
684 j
= fore
->w_histheight
+ fore
->w_height
- 1;
685 revto(linestart(j
), j
);
693 revto(linestart(cy
), cy
);
696 revto(linestart(cy
), cy
);
699 revto(markdata
->left_mar
, cy
+ 1);
701 case 0220: /* M-C-p */
702 case '\020': /* CTRL-P */
706 revto(cx
, cy
- rep_cnt
);
708 case 0206: /* M-C-f */
712 revto(cx
+ rep_cnt
, cy
);
714 case '\001': /* CTRL-A from tcsh/emacs */
716 revto(markdata
->left_mar
, cy
);
718 case '\004': /* CTRL-D down half screen */
720 rep_cnt
= (fore
->w_height
+ 1) >> 1;
721 revto_line(cx
, cy
+ rep_cnt
, W2D(cy
));
724 revto(lineend(cy
), cy
);
726 case '\022': /* CTRL-R emacs style backwards search */
730 case '\023': /* CTRL-S emacs style search */
734 case '\025': /* CTRL-U up half screen */
736 rep_cnt
= (fore
->w_height
+ 1) >> 1;
737 revto_line(cx
, cy
- rep_cnt
, W2D(cy
));
739 case '\007': /* CTRL-G show cursorpos */
740 if (markdata
->left_mar
== 0 && markdata
->right_mar
== fore
->w_width
- 1)
741 LMsg(0, "Column %d Line %d(+%d)", cx
+1, W2D(cy
)+1,
742 markdata
->hist_offset
);
744 LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx
+1,
745 markdata
->left_mar
+1, markdata
->right_mar
+1, W2D(cy
)+1, markdata
->hist_offset
);
747 case '\002': /* CTRL-B back one page */
750 rep_cnt
*= fore
->w_height
;
751 revto(cx
, cy
- rep_cnt
);
753 case '\006': /* CTRL-F forward one page */
756 rep_cnt
*= fore
->w_height
;
757 revto(cx
, cy
+ rep_cnt
);
759 case '\005': /* CTRL-E scroll up */
762 rep_cnt
= MarkScrollUpDisplay(rep_cnt
);
766 LGotoPos(flayer
, cx
, W2D(cy
));
768 case '\031': /* CTRL-Y scroll down */
771 rep_cnt
= MarkScrollDownDisplay(rep_cnt
);
772 if (cy
> D2W(fore
->w_height
-1))
773 revto(cx
, D2W(fore
->w_height
-1));
775 LGotoPos(flayer
, cx
, W2D(cy
));
778 /* it may be usefull to have a key that does nothing */
782 /* rep_cnt is a percentage for the history buffer */
787 revto_line(markdata
->left_mar
, (rep_cnt
* (fore
->w_histheight
+ fore
->w_height
)) / 100, (fore
->w_height
- 1) / 2);
795 /* rep_cnt is here the WIN line number */
797 rep_cnt
= fore
->w_histheight
+ fore
->w_height
;
798 revto_line(markdata
->left_mar
, --rep_cnt
, (fore
->w_height
- 1) / 2);
801 revto(markdata
->left_mar
, D2W(0));
804 revto(markdata
->left_mar
, D2W((fore
->w_height
- 1) / 2));
807 revto(markdata
->left_mar
, D2W(fore
->w_height
- 1));
810 revto(--rep_cnt
, cy
);
815 nextword(&cx
, &cy
, NW_MUSTMOVE
, rep_cnt
);
822 nextword(&cx
, &cy
, NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'E' ? NW_BIG
: 0), rep_cnt
);
829 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'B' ? NW_BIG
: 0), rep_cnt
);
833 markdata
->append_mode
= 1 - markdata
->append_mode
;
834 debug1("append mode %d--\n", markdata
->append_mode
);
835 LMsg(0, (markdata
->append_mode
) ? ":set append" : ":set noappend");
839 /* this sets start column to column 9 for VI :set nu users */
840 if (markdata
->left_mar
== 8)
847 /* set start column (c) and end column (C) */
848 if (markdata
->second
)
850 rem(markdata
->x1
, markdata
->y1
, cx
, cy
, 1, (char *)0, fore
->w_height
-1); /* Hack */
851 markdata
->second
= 1; /* rem turns off second */
858 markdata
->left_mar
= rep_cnt
;
859 if (markdata
->left_mar
> markdata
->right_mar
)
860 markdata
->left_mar
= markdata
->right_mar
;
864 markdata
->right_mar
= rep_cnt
;
865 if (markdata
->left_mar
> markdata
->right_mar
)
866 markdata
->right_mar
= markdata
->left_mar
;
868 if (markdata
->second
)
870 markdata
->cx
= markdata
->x1
; markdata
->cy
= markdata
->y1
;
873 if (od
== 'v' || od
== 'V')
874 LMsg(0, (markdata
->left_mar
!= 8) ? ":set nonu" : ":set nu");
877 /* how do you join lines in VI ? */
878 markdata
->nonl
= (markdata
->nonl
+ 1) % 4;
879 switch (markdata
->nonl
)
883 LMsg(0, "Multiple lines (CR/LF)");
885 LMsg(0, "Multiple lines (LF)");
888 LMsg(0, "Lines joined");
891 LMsg(0, "Lines joined with blanks");
894 LMsg(0, "Lines joined with comma");
910 markdata
->isdir
= -markdata
->isdir
;
912 markdata
->isdir
= -markdata
->isdir
;
916 if (markdata
->second
== 0)
918 revto(linestart(cy
), cy
);
920 cx
= markdata
->x1
= markdata
->cx
;
921 cy
= markdata
->y1
= markdata
->cy
;
924 revto(cx
, cy
+ rep_cnt
);
925 revto(lineend(markdata
->cy
), markdata
->cy
);
934 if (!markdata
->second
)
936 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
, 1);
939 cx
= markdata
->x1
= markdata
->cx
;
940 cy
= markdata
->y1
= markdata
->cy
;
942 nextword(&cx
, &cy
, NW_ENDOFWORD
, rep_cnt
);
950 markdata
->append_mode
= 1;
954 markdata
->write_buffer
= 1;
958 if (!markdata
->second
)
964 LMsg(0, "First mark set - Column %d Line %d", cx
+1, W2D(cy
)+1);
969 int append_mode
= markdata
->append_mode
;
970 int write_buffer
= markdata
->write_buffer
;
974 newcopylen
= rem(markdata
->x1
, markdata
->y1
, x2
, y2
, 2, (char *)0, 0); /* count */
975 if (md_user
->u_plop
.buf
&& !append_mode
)
976 UserFreeCopyBuffer(md_user
);
977 yend
= fore
->w_height
- 1;
978 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
980 markdata
->second
= 0;
981 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
985 /* the +3 below is for : cr + lf + \0 */
986 if (md_user
->u_plop
.buf
)
987 md_user
->u_plop
.buf
= realloc(md_user
->u_plop
.buf
,
988 (unsigned) (md_user
->u_plop
.len
+ newcopylen
+ 3));
991 md_user
->u_plop
.len
= 0;
992 md_user
->u_plop
.buf
= malloc((unsigned) (newcopylen
+ 3));
994 if (!md_user
->u_plop
.buf
)
998 LMsg(0, "Not enough memory... Sorry.");
999 md_user
->u_plop
.len
= 0;
1000 md_user
->u_plop
.buf
= 0;
1005 switch (markdata
->nonl
)
1008 * this code defines, what glues lines together
1013 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\r';
1014 md_user
->u_plop
.len
++;
1016 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\n';
1017 md_user
->u_plop
.len
++;
1022 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ' ';
1023 md_user
->u_plop
.len
++;
1026 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ',';
1027 md_user
->u_plop
.len
++;
1031 md_user
->u_plop
.len
+= rem(markdata
->x1
, markdata
->y1
, x2
, y2
,
1032 markdata
->hist_offset
== fore
->w_histheight
,
1033 md_user
->u_plop
.buf
+ md_user
->u_plop
.len
, yend
);
1035 md_user
->u_plop
.enc
= fore
->w_encoding
;
1038 if (markdata
->hist_offset
!= fore
->w_histheight
)
1040 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1044 LMsg(0, "Appended %d characters to buffer",
1047 LMsg(0, "Copied %d characters into buffer", md_user
->u_plop
.len
);
1049 WriteFile(md_user
, (char *)0, DUMP_EXCHANGE
);
1055 LMsg(0, "Copy mode aborted");
1059 if (in_mark
) /* markdata may be freed */
1060 markdata
->rep_cnt
= 0;
1064 flayer
->l_x
= markdata
->cx
;
1065 flayer
->l_y
= W2D(markdata
->cy
);
1074 revto_line(tx
, ty
, -1);
1077 /* tx, ty: WINDOW, line: DISPLAY */
1078 void revto_line(tx
, ty
, line
)
1082 int x
, y
, t
, revst
, reven
, qq
, ff
, tt
, st
, en
, ce
= 0;
1083 int ystart
= 0, yend
= fore
->w_height
-1;
1091 else if (tx
> fore
->w_width
- 1)
1092 tx
= fore
->w_width
-1;
1095 else if (ty
> fore
->w_histheight
+ fore
->w_height
- 1)
1096 ty
= fore
->w_histheight
+ fore
->w_height
- 1;
1098 fx
= markdata
->cx
; fy
= markdata
->cy
;
1101 /* don't just move inside of a kanji, the user wants to see something */
1103 if (ty
== fy
&& fx
+ 1 == tx
&& dw_right(ml
, tx
, fore
->w_encoding
) && tx
< D_width
- 1)
1105 if (ty
== fy
&& fx
- 1 == tx
&& dw_right(ml
, fx
, fore
->w_encoding
) && tx
)
1109 markdata
->cx
= tx
; markdata
->cy
= ty
;
1112 * if we go to a position that is currently offscreen
1113 * then scroll the screen
1116 if (line
>= 0 && line
< fore
->w_height
)
1118 else if (ty
< markdata
->hist_offset
)
1119 i
= ty
- markdata
->hist_offset
;
1120 else if (ty
> markdata
->hist_offset
+ (fore
->w_height
- 1))
1121 i
= ty
- markdata
->hist_offset
- (fore
->w_height
- 1);
1123 yend
-= MarkScrollUpDisplay(i
);
1125 ystart
+= MarkScrollDownDisplay(-i
);
1127 if (markdata
->second
== 0)
1129 LGotoPos(flayer
, tx
, W2D(ty
));
1133 qq
= markdata
->x1
+ markdata
->y1
* fore
->w_width
;
1134 ff
= fx
+ fy
* fore
->w_width
; /* "from" offset in WIN coords */
1135 tt
= tx
+ ty
* fore
->w_width
; /* "to" offset in WIN coords*/
1156 revst
= qq
; reven
= tt
;
1160 revst
= tt
; reven
= qq
;
1162 ry
= y
- markdata
->hist_offset
;
1167 st
= y
* fore
->w_width
;
1171 for (t
= st
; t
<= en
; t
++, x
++)
1173 if (x
>= fore
->w_width
)
1181 if (t
== st
|| x
== 0)
1183 wi
= ml
->image
+ fore
->w_width
;
1184 for (ce
= fore
->w_width
; ce
>= 0; ce
--, wi
--)
1188 if (x
<= ce
&& x
>= markdata
->left_mar
&& x
<= markdata
->right_mar
)
1191 if (dw_right(ml
, x
, fore
->w_encoding
))
1199 if (t
>= revst
&& t
<= reven
)
1204 mc
.font
= ml
->font
[x
];
1206 mc
.image
= ml
->image
[x
];
1209 copy_mline2mchar(&mc
, ml
, x
);
1211 if (dw_left(ml
, x
, fore
->w_encoding
))
1213 mc
.mbcs
= ml
->image
[x
+ 1];
1214 LPutChar(flayer
, &mc
, x
, W2D(y
));
1218 LPutChar(flayer
, &mc
, x
, W2D(y
));
1220 if (dw_left(ml
, x
, fore
->w_encoding
))
1225 LGotoPos(flayer
, tx
, W2D(ty
));
1233 debug("MarkAbort\n");
1234 markdata
= (struct markdata
*)flayer
->l_data
;
1235 fore
= markdata
->md_window
;
1236 yend
= fore
->w_height
- 1;
1237 redisp
= markdata
->second
;
1238 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
1240 markdata
->second
= 0;
1241 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
1243 if (markdata
->hist_offset
!= fore
->w_histheight
)
1245 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1249 rem(markdata
->x1
, markdata
->y1
, markdata
->cx
, markdata
->cy
, redisp
, (char *)0, yend
);
1256 MarkRedisplayLine(y
, xs
, xe
, isblank
)
1257 int y
; /* NOTE: y is in DISPLAY coords system! */
1262 int sta
, sto
, cp
; /* NOTE: these 3 are in WINDOW coords system */
1265 struct mchar mchar_marked
;
1267 if (y
< 0) /* No special full page handling */
1270 markdata
= (struct markdata
*)flayer
->l_data
;
1271 fore
= markdata
->md_window
;
1273 mchar_marked
= mchar_so
;
1278 if (markdata
->second
== 0)
1280 if (dw_right(ml
, xs
, fore
->w_encoding
) && xs
> 0)
1282 if (dw_left(ml
, xe
, fore
->w_encoding
) && xe
< fore
->w_width
- 1)
1284 if (xs
== 0 && y
> 0 && wy
> 0 && WIN(wy
- 1)->image
[flayer
->l_width
] == 0)
1285 LCDisplayLineWrap(flayer
, ml
, y
, xs
, xe
, isblank
);
1287 LCDisplayLine(flayer
, ml
, y
, xs
, xe
, isblank
);
1291 sta
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1292 sto
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1295 i
=sta
; sta
=sto
; sto
=i
;
1297 cp
= wy
* fore
->w_width
+ xs
;
1299 rm
= markdata
->right_mar
;
1300 for (x
= fore
->w_width
, wi
= ml
->image
+ fore
->w_width
; x
>= 0; x
--, wi
--)
1306 for (x
= xs
; x
<= xe
; x
++, cp
++)
1307 if (cp
>= sta
&& x
>= markdata
->left_mar
)
1310 if (dw_right(ml
, x
, fore
->w_encoding
))
1314 LCDisplayLine(flayer
, ml
, y
, xs
, x
- 1, isblank
);
1315 for (; x
<= xe
; x
++, cp
++)
1317 if (cp
> sto
|| x
> rm
)
1321 mchar_marked
.font
= ml
->font
[x
];
1323 mchar_marked
.image
= ml
->image
[x
];
1325 mchar_marked
.mbcs
= 0;
1326 if (dw_left(ml
, x
, fore
->w_encoding
))
1328 mchar_marked
.mbcs
= ml
->image
[x
+ 1];
1332 LPutChar(flayer
, &mchar_marked
, x
, y
);
1334 if (dw_left(ml
, x
, fore
->w_encoding
))
1339 LCDisplayLine(flayer
, ml
, y
, x
, xe
, isblank
);
1344 * This ugly routine is to speed up GotoPos()
1347 MarkRewrite(ry
, xs
, xe
, rend
, doit
)
1348 int ry
, xs
, xe
, doit
;
1351 int dx
, x
, y
, st
, en
, t
, rm
;
1354 struct mchar mchar_marked
;
1356 mchar_marked
= mchar_so
;
1358 debug3("MarkRewrite %d, %d-%d\n", ry
, xs
, xe
);
1359 markdata
= (struct markdata
*)flayer
->l_data
;
1360 fore
= markdata
->md_window
;
1364 if (fore
->w_encoding
&& fore
->w_encoding
!= UTF8
&& D_encoding
== UTF8
&& ContainsSpecialDeffont(ml
, xs
, xe
, fore
->w_encoding
))
1376 if (markdata
->second
== 0)
1380 st
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1381 en
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1384 t
= st
; st
= en
; en
= t
;
1387 t
= y
* fore
->w_width
+ xs
;
1388 for (rm
= fore
->w_width
, i
= ml
->image
+ fore
->w_width
; rm
>= 0; rm
--)
1391 if (rm
> markdata
->right_mar
)
1392 rm
= markdata
->right_mar
;
1396 if (t
>= st
&& t
<= en
&& x
>= markdata
->left_mar
&& x
<= rm
)
1400 mchar_marked
.font
= ml
->font
[x
];
1402 rend
->image
= mchar_marked
.image
;
1403 if (!cmp_mchar(rend
, &mchar_marked
))
1408 rend
->image
= ml
->image
[x
];
1409 if (!cmp_mchar_mline(rend
, ml
, x
))
1419 * scroll the screen contents up/down.
1421 static int MarkScrollUpDisplay(n
)
1426 debug1("MarkScrollUpDisplay(%d)\n", n
);
1429 if (n
> fore
->w_histheight
- markdata
->hist_offset
)
1430 n
= fore
->w_histheight
- markdata
->hist_offset
;
1431 markdata
->hist_offset
+= n
;
1432 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1433 LScrollV(flayer
, i
, 0, flayer
->l_height
- 1, 0);
1435 MarkRedisplayLine(flayer
->l_height
- i
- 1, 0, flayer
->l_width
- 1, 1);
1440 MarkScrollDownDisplay(n
)
1445 debug1("MarkScrollDownDisplay(%d)\n", n
);
1448 if (n
> markdata
->hist_offset
)
1449 n
= markdata
->hist_offset
;
1450 markdata
->hist_offset
-= n
;
1451 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1452 LScrollV(flayer
, -i
, 0, fore
->w_height
- 1, 0);
1454 MarkRedisplayLine(i
, 0, flayer
->l_width
- 1, 1);
1461 if (flayer
&& flayer
->l_layfn
== &MarkLf
)
1467 MakePaster(pa
, buf
, len
, bufiscopy
)
1474 pa
->pa_pasteptr
= buf
;
1475 pa
->pa_pastelen
= len
;
1477 pa
->pa_pastebuf
= buf
;
1478 pa
->pa_pastelayer
= flayer
;
1479 DoProcess(Layer2Window(flayer
), &pa
->pa_pasteptr
, &pa
->pa_pastelen
, pa
);
1486 if (pa
->pa_pastebuf
)
1487 free(pa
->pa_pastebuf
);
1488 pa
->pa_pastebuf
= 0;
1489 pa
->pa_pasteptr
= 0;
1490 pa
->pa_pastelen
= 0;
1491 pa
->pa_pastelayer
= 0;
1492 evdeq(&pa
->pa_slowev
);
1495 #endif /* COPY_PASTE */