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
=
87 unsigned char mark_key_tab
[256]; /* this array must be initialised first! */
89 static struct markdata
*markdata
;
93 * VI like is_letter: 0 - whitespace
97 static int is_letter(c
)
100 if ((c
>= 'a' && c
<= 'z') ||
101 (c
>= 'A' && c
<= 'Z') ||
102 (c
>= '0' && c
<= '9') ||
103 c
== '_' || c
== '.' ||
104 c
== '@' || c
== ':' ||
105 c
== '%' || c
== '!' ||
106 c
== '-' || c
== '+')
107 /* thus we can catch email-addresses as a word :-) */
119 register unsigned char *i
;
121 for (x
= markdata
->left_mar
, i
= WIN(y
)->image
+ x
; x
< fore
->w_width
- 1; x
++)
124 if (x
== fore
->w_width
- 1)
125 x
= markdata
->left_mar
;
134 register unsigned char *i
;
136 for (x
= markdata
->right_mar
, i
= WIN(y
)->image
+ x
; x
>= 0; x
--)
140 x
= markdata
->left_mar
;
145 * nextchar sets *xp to the num-th occurrence of the target in the line.
147 * Returns -1 if the target doesn't appear num times, 0 otherwise.
150 nextchar(int *xp
, int *yp
, int direction
, char target
, int num
)
152 int width
; /* width of the current window. */
153 int x
; /* x coordinate of the current cursor position. */
154 int step
; /* amount to increment x (+1 or -1) */
155 int adjust
; /* Final adjustment of cursor position. */
156 char *displayed_line
; /* Line in which search takes place. */
162 width
= fore
->w_width
;
163 displayed_line
= (char *)WIN(*yp
) -> image
;
167 adjust
= -1; /* fall through */
172 adjust
= 1; /* fall through */
182 debug1("ml->image = %s\n", displayed_line
);
183 debug2("num = %d, width = %d\n",num
, width
);
184 debug2("x = %d target = %c\n", x
, target
);
186 for ( ;x
>=0 && x
<= width
; x
+= step
) {
187 if (displayed_line
[x
] == target
) {
198 * nextword calculates the cursor position of the num'th word.
199 * If the cursor is on a word, it counts as the first.
200 * NW_BACK: search backward
201 * NW_ENDOFWORD: find the end of the word
202 * NW_MUSTMOVE: move at least one char
203 * NW_BIG: match WORDs not words
206 #define NW_BACK (1<<0)
207 #define NW_ENDOFWORD (1<<1)
208 #define NW_MUSTMOVE (1<<2)
209 #define NW_BIG (1<<3)
214 nextword(xp
, yp
, flags
, num
)
215 int *xp
, *yp
, flags
, num
;
217 int xx
= fore
->w_width
, yy
= fore
->w_histheight
+ fore
->w_height
;
218 register int sx
, oq
, q
, x
, y
;
223 sx
= (flags
& NW_BACK
) ? -1 : 1;
224 if ((flags
& NW_ENDOFWORD
) && (flags
& NW_MUSTMOVE
))
227 for (oq
= -1; ; x
+= sx
, oq
= q
)
229 if (x
>= xx
|| x
< 0)
231 else if (flags
& NW_BIG
)
232 q
= ml
->image
[x
] == ' ';
234 q
= is_letter(ml
->image
[x
]);
235 if (oq
>= 0 && oq
!= q
)
237 if (oq
== 0 || !(flags
& NW_ENDOFWORD
))
242 if ((!(flags
& NW_ENDOFWORD
) && q
) ||
243 ((flags
& NW_ENDOFWORD
) && oq
))
268 * y1, y2 are WIN coordinates
270 * redisplay: 0 - just copy
271 * 1 - redisplay + copy
272 * 2 - count + copy, don't redisplay
276 rem(x1
, y1
, x2
, y2
, redisplay
, pt
, yend
)
277 int x1
, y1
, x2
, y2
, redisplay
, yend
;
280 int i
, j
, from
, to
, ry
, c
;
289 markdata
->second
= 0;
290 if (y2
< y1
|| ((y2
== y1
) && (x2
< x1
)))
299 ry
= y1
- markdata
->hist_offset
;
302 if (redisplay
!= 2 && pt
== 0 && ry
<0)
307 for (; i
<= y2
; i
++, ry
++)
309 if (redisplay
!= 2 && pt
== 0 && ry
> yend
)
312 from
= (i
== y1
) ? x1
: 0;
313 if (from
< markdata
->left_mar
)
314 from
= markdata
->left_mar
;
315 for (to
= fore
->w_width
, im
= ml
->image
+ to
; to
>= 0; to
--)
318 if (i
== y2
&& x2
< to
)
320 if (to
> markdata
->right_mar
)
321 to
= markdata
->right_mar
;
322 if (redisplay
== 1 && from
<= to
&& ry
>=0 && ry
<= yend
)
323 MarkRedisplayLine(ry
, from
, to
, 0);
324 if (redisplay
!= 2 && pt
== 0) /* don't count/copy */
328 if (dw_right(ml
, j
, fore
->w_encoding
))
338 c
= (unsigned char)*im
++;
340 cf
= (unsigned char)*fo
++;
342 if (fore
->w_encoding
== UTF8
)
347 c
= ToUtf8_comb(pt
, c
);
357 c
= c
<< 8 | (unsigned char)*im
++;
364 c
= EncodeChar(pt
, c
| cf
<< 16, fore
->w_encoding
, &font
);
376 if (pastefont
&& font
!= ASCII
)
380 strcpy(pt
, "\033(B");
386 if (i
!= y2
&& (to
!= fore
->w_width
- 1 || ml
->image
[to
+ 1] == ' '))
389 * this code defines, what glues lines together
391 switch (markdata
->nonl
)
393 case 0: /* lines separated by newlines */
404 case 1: /* nothing to separate lines */
406 case 2: /* lines separated by blanks */
411 case 3: /* seperate by comma, for csh junkies */
422 /* Check if two chars are identical. All digits are treated
423 * as same. Used for GetHistory()
432 if (a
== 0 || b
== 0)
434 if (a
<= '9' && a
>= '0' && b
<= '9' && b
>= '0')
440 /**********************************************************************/
443 GetHistory() /* return value 1 if copybuffer changed */
445 int i
= 0, q
= 0, xx
, yy
, x
, y
;
446 unsigned char *linep
;
449 ASSERT(display
&& fore
);
451 if (x
>= fore
->w_width
)
452 x
= fore
->w_width
- 1;
453 y
= fore
->w_y
+ fore
->w_histheight
;
454 debug2("cursor is at x=%d, y=%d\n", x
, y
);
456 for (xx
= x
- 1, linep
= ml
->image
+ xx
; xx
>= 0; xx
--)
457 if ((q
= *linep
--) != ' ' )
459 debug3("%c at (%d,%d)\n", q
, xx
, y
);
460 for (yy
= y
- 1; yy
>= 0; yy
--)
464 if (xx
< 0 || eq(linep
[xx
], q
))
465 { /* line is matching... */
466 for (i
= fore
->w_width
- 1, linep
+= i
; i
>= x
; i
--)
475 if (D_user
->u_plop
.buf
)
476 UserFreeCopyBuffer(D_user
);
477 if ((D_user
->u_plop
.buf
= (char *)malloc((unsigned) (i
- x
+ 2))) == NULL
)
479 LMsg(0, "Not enough memory... Sorry.");
482 bcopy((char *)linep
- i
+ x
+ 1, D_user
->u_plop
.buf
, i
- x
+ 1);
483 D_user
->u_plop
.len
= i
- x
+ 1;
485 D_user
->u_plop
.enc
= fore
->w_encoding
;
490 /**********************************************************************/
498 ASSERT(fore
&& display
&& D_user
);
500 debug2("MarkRoutine called: fore nr %d, display %s\n",
501 fore
->w_number
, D_usertty
);
503 if (InitOverlayPage(sizeof(*markdata
), &MarkLf
, 1))
505 flayer
->l_encoding
= fore
->w_encoding
;
507 markdata
= (struct markdata
*)flayer
->l_data
;
508 markdata
->md_user
= D_user
; /* XXX: Correct? */
509 markdata
->md_window
= fore
;
510 markdata
->second
= 0;
511 markdata
->rep_cnt
= 0;
512 markdata
->append_mode
= 0;
513 markdata
->write_buffer
= 0;
515 markdata
->left_mar
= 0;
516 markdata
->right_mar
= fore
->w_width
- 1;
517 markdata
->hist_offset
= fore
->w_histheight
;
520 if (x
>= fore
->w_width
)
521 x
= fore
->w_width
- 1;
523 LGotoPos(flayer
, x
, W2D(y
));
524 LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)",
525 x
+ 1, W2D(y
+ 1), fore
->w_histheight
, fore
->w_width
, fore
->w_height
);
526 markdata
->cx
= markdata
->x1
= x
;
527 markdata
->cy
= markdata
->y1
= y
;
529 flayer
->l_y
= W2D(y
);
533 MarkProcess(inbufp
,inlenp
)
539 int cx
, cy
, x2
, y2
, j
, yend
;
540 int newcopylen
= 0, od
;
543 struct acluser
*md_user
;
546 char *extrap = 0, extrabuf[100];
549 markdata
= (struct markdata
*)flayer
->l_data
;
550 fore
= markdata
->md_window
;
551 md_user
= markdata
->md_user
;
558 LGotoPos(flayer
, markdata
->cx
, W2D(markdata
->cy
));
563 while (in_mark
&& (inlen
/* || extrap */))
565 unsigned char ch
= (unsigned char )*pt
++;
567 if (flayer
->l_mouseevent
.start
)
569 int r
= LayProcessMouse(flayer
, ch
);
571 LayProcessMouseSwitch(flayer
, 0);
580 od
= mark_key_tab
[(int)ch
];
581 rep_cnt
= markdata
->rep_cnt
;
582 if (od
>= '0' && od
<= '9' && !markdata
->f_cmd
.flag
)
584 if (rep_cnt
< 1001 && (od
!= '0' || rep_cnt
!= 0))
586 markdata
->rep_cnt
= 10 * rep_cnt
+ od
- '0';
589 * Now what is that 1001 here? Well, we have a screen with
590 * 25 * 80 = 2000 characters. Movement is at most across the full
591 * screen. This we do with word by word movement, as character by
592 * character movement never steps over line boundaries. The most words
593 * we can place on the screen are 1000 single letter words. Thus 1001
594 * is sufficient. Users with bigger screens never write in single letter
595 * words, as they should be more advanced. jw.
596 * Oh, wrong. We still give even the experienced user a factor of ten.
603 if (markdata
-> f_cmd
.flag
) {
604 debug2("searching for %c:%d\n",od
,rep_cnt
);
605 markdata
->f_cmd
.flag
= 0;
606 markdata
->rep_cnt
= 0;
609 markdata
->f_cmd
.target
= od
;
610 rep_cnt
= (rep_cnt
) ? rep_cnt
: 1;
611 nextchar(&cx
, &cy
, markdata
->f_cmd
.direction
, od
, rep_cnt
);
620 case 'f': /* fall through */
621 case 'F': /* fall through */
622 case 't': /* fall through */
623 case 'T': /* fall through */
625 * Set f_cmd to do a search on the next key stroke.
626 * If we break, rep_cnt will be reset, so we
627 * continue instead. It might be cleaner to
628 * store the rep_count in f_cmd and
629 * break here so later followon code will be
632 markdata
->f_cmd
.flag
= 1;
633 markdata
->f_cmd
.direction
= od
;
634 debug("entering char search\n");
638 if (!markdata
->f_cmd
.target
)
643 od
== ';' ? markdata
->f_cmd
.direction
: (markdata
->f_cmd
.direction
^ 0x20),
644 markdata
->f_cmd
.target
, rep_cnt
);
649 if (!markdata
->second
)
651 markdata
->cx
= markdata
->x1
;
652 markdata
->cy
= markdata
->y1
;
655 revto(markdata
->cx
, markdata
->cy
);
657 case '\014': /* CTRL-L Redisplay */
659 LGotoPos(flayer
, cx
, W2D(cy
));
661 case 0202: /* M-C-b */
662 case '\010': /* CTRL-H Backspace */
666 revto(cx
- rep_cnt
, cy
);
668 case 0216: /* M-C-p */
669 case '\016': /* CTRL-N */
673 revto(cx
, cy
+ rep_cnt
);
679 if (j
> fore
->w_histheight
+ fore
->w_height
- 1)
680 j
= fore
->w_histheight
+ fore
->w_height
- 1;
681 revto(linestart(j
), j
);
689 revto(linestart(cy
), cy
);
692 revto(linestart(cy
), cy
);
695 revto(markdata
->left_mar
, cy
+ 1);
697 case 0220: /* M-C-p */
698 case '\020': /* CTRL-P */
702 revto(cx
, cy
- rep_cnt
);
704 case 0206: /* M-C-f */
708 revto(cx
+ rep_cnt
, cy
);
710 case '\001': /* CTRL-A from tcsh/emacs */
712 revto(markdata
->left_mar
, cy
);
714 case '\004': /* CTRL-D down half screen */
716 rep_cnt
= (fore
->w_height
+ 1) >> 1;
717 revto_line(cx
, cy
+ rep_cnt
, W2D(cy
));
720 revto(lineend(cy
), cy
);
722 case '\022': /* CTRL-R emacs style backwards search */
726 case '\023': /* CTRL-S emacs style search */
730 case '\025': /* CTRL-U up half screen */
732 rep_cnt
= (fore
->w_height
+ 1) >> 1;
733 revto_line(cx
, cy
- rep_cnt
, W2D(cy
));
735 case '\007': /* CTRL-G show cursorpos */
736 if (markdata
->left_mar
== 0 && markdata
->right_mar
== fore
->w_width
- 1)
737 LMsg(0, "Column %d Line %d(+%d)", cx
+1, W2D(cy
)+1,
738 markdata
->hist_offset
);
740 LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx
+1,
741 markdata
->left_mar
+1, markdata
->right_mar
+1, W2D(cy
)+1, markdata
->hist_offset
);
743 case '\002': /* CTRL-B back one page */
746 rep_cnt
*= fore
->w_height
;
747 revto(cx
, cy
- rep_cnt
);
749 case '\006': /* CTRL-F forward one page */
752 rep_cnt
*= fore
->w_height
;
753 revto(cx
, cy
+ rep_cnt
);
755 case '\005': /* CTRL-E scroll up */
758 rep_cnt
= MarkScrollUpDisplay(rep_cnt
);
762 LGotoPos(flayer
, cx
, W2D(cy
));
764 case '\031': /* CTRL-Y scroll down */
767 rep_cnt
= MarkScrollDownDisplay(rep_cnt
);
768 if (cy
> D2W(fore
->w_height
-1))
769 revto(cx
, D2W(fore
->w_height
-1));
771 LGotoPos(flayer
, cx
, W2D(cy
));
774 /* it may be usefull to have a key that does nothing */
778 /* rep_cnt is a percentage for the history buffer */
783 revto_line(markdata
->left_mar
, (rep_cnt
* (fore
->w_histheight
+ fore
->w_height
)) / 100, (fore
->w_height
- 1) / 2);
791 /* rep_cnt is here the WIN line number */
793 rep_cnt
= fore
->w_histheight
+ fore
->w_height
;
794 revto_line(markdata
->left_mar
, --rep_cnt
, (fore
->w_height
- 1) / 2);
797 revto(markdata
->left_mar
, D2W(0));
800 revto(markdata
->left_mar
, D2W((fore
->w_height
- 1) / 2));
803 revto(markdata
->left_mar
, D2W(fore
->w_height
- 1));
806 revto(--rep_cnt
, cy
);
811 nextword(&cx
, &cy
, NW_MUSTMOVE
, rep_cnt
);
818 nextword(&cx
, &cy
, NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'E' ? NW_BIG
: 0), rep_cnt
);
825 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
|NW_MUSTMOVE
| (od
== 'B' ? NW_BIG
: 0), rep_cnt
);
829 markdata
->append_mode
= 1 - markdata
->append_mode
;
830 debug1("append mode %d--\n", markdata
->append_mode
);
831 LMsg(0, (markdata
->append_mode
) ? ":set append" : ":set noappend");
835 /* this sets start column to column 9 for VI :set nu users */
836 if (markdata
->left_mar
== 8)
843 /* set start column (c) and end column (C) */
844 if (markdata
->second
)
846 rem(markdata
->x1
, markdata
->y1
, cx
, cy
, 1, (char *)0, fore
->w_height
-1); /* Hack */
847 markdata
->second
= 1; /* rem turns off second */
854 markdata
->left_mar
= rep_cnt
;
855 if (markdata
->left_mar
> markdata
->right_mar
)
856 markdata
->left_mar
= markdata
->right_mar
;
860 markdata
->right_mar
= rep_cnt
;
861 if (markdata
->left_mar
> markdata
->right_mar
)
862 markdata
->right_mar
= markdata
->left_mar
;
864 if (markdata
->second
)
866 markdata
->cx
= markdata
->x1
; markdata
->cy
= markdata
->y1
;
869 if (od
== 'v' || od
== 'V')
870 LMsg(0, (markdata
->left_mar
!= 8) ? ":set nonu" : ":set nu");
873 /* how do you join lines in VI ? */
874 markdata
->nonl
= (markdata
->nonl
+ 1) % 4;
875 switch (markdata
->nonl
)
879 LMsg(0, "Multiple lines (CR/LF)");
881 LMsg(0, "Multiple lines (LF)");
884 LMsg(0, "Lines joined");
887 LMsg(0, "Lines joined with blanks");
890 LMsg(0, "Lines joined with comma");
906 markdata
->isdir
= -markdata
->isdir
;
908 markdata
->isdir
= -markdata
->isdir
;
912 if (markdata
->second
== 0)
914 revto(linestart(cy
), cy
);
916 cx
= markdata
->x1
= markdata
->cx
;
917 cy
= markdata
->y1
= markdata
->cy
;
920 revto(cx
, cy
+ rep_cnt
);
921 revto(lineend(markdata
->cy
), markdata
->cy
);
930 if (!markdata
->second
)
932 nextword(&cx
, &cy
, NW_BACK
|NW_ENDOFWORD
, 1);
935 cx
= markdata
->x1
= markdata
->cx
;
936 cy
= markdata
->y1
= markdata
->cy
;
938 nextword(&cx
, &cy
, NW_ENDOFWORD
, rep_cnt
);
946 markdata
->append_mode
= 1;
950 markdata
->write_buffer
= 1;
954 if (!markdata
->second
)
960 LMsg(0, "First mark set - Column %d Line %d", cx
+1, W2D(cy
)+1);
965 int append_mode
= markdata
->append_mode
;
966 int write_buffer
= markdata
->write_buffer
;
970 newcopylen
= rem(markdata
->x1
, markdata
->y1
, x2
, y2
, 2, (char *)0, 0); /* count */
971 if (md_user
->u_plop
.buf
&& !append_mode
)
972 UserFreeCopyBuffer(md_user
);
973 yend
= fore
->w_height
- 1;
974 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
976 markdata
->second
= 0;
977 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
981 /* the +3 below is for : cr + lf + \0 */
982 if (md_user
->u_plop
.buf
)
983 md_user
->u_plop
.buf
= realloc(md_user
->u_plop
.buf
,
984 (unsigned) (md_user
->u_plop
.len
+ newcopylen
+ 3));
987 md_user
->u_plop
.len
= 0;
988 md_user
->u_plop
.buf
= malloc((unsigned) (newcopylen
+ 3));
990 if (!md_user
->u_plop
.buf
)
994 LMsg(0, "Not enough memory... Sorry.");
995 md_user
->u_plop
.len
= 0;
996 md_user
->u_plop
.buf
= 0;
1001 switch (markdata
->nonl
)
1004 * this code defines, what glues lines together
1009 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\r';
1010 md_user
->u_plop
.len
++;
1012 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\n';
1013 md_user
->u_plop
.len
++;
1018 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ' ';
1019 md_user
->u_plop
.len
++;
1022 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ',';
1023 md_user
->u_plop
.len
++;
1027 md_user
->u_plop
.len
+= rem(markdata
->x1
, markdata
->y1
, x2
, y2
,
1028 markdata
->hist_offset
== fore
->w_histheight
,
1029 md_user
->u_plop
.buf
+ md_user
->u_plop
.len
, yend
);
1031 md_user
->u_plop
.enc
= fore
->w_encoding
;
1034 if (markdata
->hist_offset
!= fore
->w_histheight
)
1036 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1039 WindowChanged(fore
, 'P');
1041 LMsg(0, "Appended %d characters to buffer",
1044 LMsg(0, "Copied %d characters into buffer", md_user
->u_plop
.len
);
1046 WriteFile(md_user
, (char *)0, DUMP_EXCHANGE
);
1052 if (flayer
->l_mouseevent
.start
)
1054 int button
= flayer
->l_mouseevent
.buffer
[0];
1060 else if (button
== '`')
1065 else if (button
== ' ')
1068 cx
= flayer
->l_mouseevent
.buffer
[1];
1069 cy
= D2W(flayer
->l_mouseevent
.buffer
[2]);
1075 LayProcessMouseSwitch(flayer
, 0);
1080 LayProcessMouseSwitch(flayer
, 1);
1085 LMsg(0, "Copy mode aborted");
1089 if (in_mark
) /* markdata may be freed */
1090 markdata
->rep_cnt
= 0;
1094 flayer
->l_x
= markdata
->cx
;
1095 flayer
->l_y
= W2D(markdata
->cy
);
1104 revto_line(tx
, ty
, -1);
1107 /* tx, ty: WINDOW, line: DISPLAY */
1108 void revto_line(tx
, ty
, line
)
1112 int x
, y
, t
, revst
, reven
, qq
, ff
, tt
, st
, en
, ce
= 0;
1113 int ystart
= 0, yend
= fore
->w_height
-1;
1121 else if (tx
> fore
->w_width
- 1)
1122 tx
= fore
->w_width
-1;
1125 else if (ty
> fore
->w_histheight
+ fore
->w_height
- 1)
1126 ty
= fore
->w_histheight
+ fore
->w_height
- 1;
1128 fx
= markdata
->cx
; fy
= markdata
->cy
;
1131 /* don't just move inside of a kanji, the user wants to see something */
1133 if (ty
== fy
&& fx
+ 1 == tx
&& dw_right(ml
, tx
, fore
->w_encoding
) && tx
< D_width
- 1)
1135 if (ty
== fy
&& fx
- 1 == tx
&& dw_right(ml
, fx
, fore
->w_encoding
) && tx
)
1139 markdata
->cx
= tx
; markdata
->cy
= ty
;
1142 * if we go to a position that is currently offscreen
1143 * then scroll the screen
1146 if (line
>= 0 && line
< fore
->w_height
)
1148 else if (ty
< markdata
->hist_offset
)
1149 i
= ty
- markdata
->hist_offset
;
1150 else if (ty
> markdata
->hist_offset
+ (fore
->w_height
- 1))
1151 i
= ty
- markdata
->hist_offset
- (fore
->w_height
- 1);
1153 yend
-= MarkScrollUpDisplay(i
);
1155 ystart
+= MarkScrollDownDisplay(-i
);
1157 if (markdata
->second
== 0)
1160 flayer
->l_y
= W2D(ty
);
1161 LGotoPos(flayer
, tx
, W2D(ty
));
1165 qq
= markdata
->x1
+ markdata
->y1
* fore
->w_width
;
1166 ff
= fx
+ fy
* fore
->w_width
; /* "from" offset in WIN coords */
1167 tt
= tx
+ ty
* fore
->w_width
; /* "to" offset in WIN coords*/
1188 revst
= qq
; reven
= tt
;
1192 revst
= tt
; reven
= qq
;
1194 ry
= y
- markdata
->hist_offset
;
1199 st
= y
* fore
->w_width
;
1203 for (t
= st
; t
<= en
; t
++, x
++)
1205 if (x
>= fore
->w_width
)
1213 if (t
== st
|| x
== 0)
1215 wi
= ml
->image
+ fore
->w_width
;
1216 for (ce
= fore
->w_width
; ce
>= 0; ce
--, wi
--)
1220 if (x
<= ce
&& x
>= markdata
->left_mar
&& x
<= markdata
->right_mar
)
1223 if (dw_right(ml
, x
, fore
->w_encoding
))
1231 if (t
>= revst
&& t
<= reven
)
1236 mc
.font
= ml
->font
[x
];
1238 mc
.image
= ml
->image
[x
];
1241 copy_mline2mchar(&mc
, ml
, x
);
1243 if (dw_left(ml
, x
, fore
->w_encoding
))
1245 mc
.mbcs
= ml
->image
[x
+ 1];
1246 LPutChar(flayer
, &mc
, x
, W2D(y
));
1250 LPutChar(flayer
, &mc
, x
, W2D(y
));
1252 if (dw_left(ml
, x
, fore
->w_encoding
))
1258 flayer
->l_y
= W2D(ty
);
1259 LGotoPos(flayer
, tx
, W2D(ty
));
1267 debug("MarkAbort\n");
1268 markdata
= (struct markdata
*)flayer
->l_data
;
1269 fore
= markdata
->md_window
;
1270 yend
= fore
->w_height
- 1;
1271 redisp
= markdata
->second
;
1272 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
)
1274 markdata
->second
= 0;
1275 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
1277 if (markdata
->hist_offset
!= fore
->w_histheight
)
1279 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1283 rem(markdata
->x1
, markdata
->y1
, markdata
->cx
, markdata
->cy
, redisp
, (char *)0, yend
);
1286 WindowChanged(fore
, 'P');
1291 MarkRedisplayLine(y
, xs
, xe
, isblank
)
1292 int y
; /* NOTE: y is in DISPLAY coords system! */
1297 int sta
, sto
, cp
; /* NOTE: these 3 are in WINDOW coords system */
1300 struct mchar mchar_marked
;
1302 if (y
< 0) /* No special full page handling */
1305 markdata
= (struct markdata
*)flayer
->l_data
;
1306 fore
= markdata
->md_window
;
1308 mchar_marked
= mchar_so
;
1313 if (markdata
->second
== 0)
1315 if (dw_right(ml
, xs
, fore
->w_encoding
) && xs
> 0)
1317 if (dw_left(ml
, xe
, fore
->w_encoding
) && xe
< fore
->w_width
- 1)
1319 if (xs
== 0 && y
> 0 && wy
> 0 && WIN(wy
- 1)->image
[flayer
->l_width
] == 0)
1320 LCDisplayLineWrap(flayer
, ml
, y
, xs
, xe
, isblank
);
1322 LCDisplayLine(flayer
, ml
, y
, xs
, xe
, isblank
);
1326 sta
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1327 sto
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1330 i
=sta
; sta
=sto
; sto
=i
;
1332 cp
= wy
* fore
->w_width
+ xs
;
1334 rm
= markdata
->right_mar
;
1335 for (x
= fore
->w_width
, wi
= ml
->image
+ fore
->w_width
; x
>= 0; x
--, wi
--)
1341 for (x
= xs
; x
<= xe
; x
++, cp
++)
1342 if (cp
>= sta
&& x
>= markdata
->left_mar
)
1345 if (dw_right(ml
, x
, fore
->w_encoding
))
1349 LCDisplayLine(flayer
, ml
, y
, xs
, x
- 1, isblank
);
1350 for (; x
<= xe
; x
++, cp
++)
1352 if (cp
> sto
|| x
> rm
)
1356 mchar_marked
.font
= ml
->font
[x
];
1358 mchar_marked
.image
= ml
->image
[x
];
1360 mchar_marked
.mbcs
= 0;
1361 if (dw_left(ml
, x
, fore
->w_encoding
))
1363 mchar_marked
.mbcs
= ml
->image
[x
+ 1];
1367 LPutChar(flayer
, &mchar_marked
, x
, y
);
1369 if (dw_left(ml
, x
, fore
->w_encoding
))
1374 LCDisplayLine(flayer
, ml
, y
, x
, xe
, isblank
);
1379 * This ugly routine is to speed up GotoPos()
1382 MarkRewrite(ry
, xs
, xe
, rend
, doit
)
1383 int ry
, xs
, xe
, doit
;
1386 int dx
, x
, y
, st
, en
, t
, rm
;
1389 struct mchar mchar_marked
;
1391 mchar_marked
= mchar_so
;
1393 debug3("MarkRewrite %d, %d-%d\n", ry
, xs
, xe
);
1394 markdata
= (struct markdata
*)flayer
->l_data
;
1395 fore
= markdata
->md_window
;
1399 if (fore
->w_encoding
&& fore
->w_encoding
!= UTF8
&& D_encoding
== UTF8
&& ContainsSpecialDeffont(ml
, xs
, xe
, fore
->w_encoding
))
1411 if (markdata
->second
== 0)
1415 st
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1416 en
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1419 t
= st
; st
= en
; en
= t
;
1422 t
= y
* fore
->w_width
+ xs
;
1423 for (rm
= fore
->w_width
, i
= ml
->image
+ fore
->w_width
; rm
>= 0; rm
--)
1426 if (rm
> markdata
->right_mar
)
1427 rm
= markdata
->right_mar
;
1431 if (t
>= st
&& t
<= en
&& x
>= markdata
->left_mar
&& x
<= rm
)
1435 mchar_marked
.font
= ml
->font
[x
];
1437 rend
->image
= mchar_marked
.image
;
1438 if (!cmp_mchar(rend
, &mchar_marked
))
1443 rend
->image
= ml
->image
[x
];
1444 if (!cmp_mchar_mline(rend
, ml
, x
))
1454 * scroll the screen contents up/down.
1456 static int MarkScrollUpDisplay(n
)
1461 debug1("MarkScrollUpDisplay(%d)\n", n
);
1464 if (n
> fore
->w_histheight
- markdata
->hist_offset
)
1465 n
= fore
->w_histheight
- markdata
->hist_offset
;
1466 markdata
->hist_offset
+= n
;
1467 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1468 LScrollV(flayer
, i
, 0, flayer
->l_height
- 1, 0);
1470 MarkRedisplayLine(flayer
->l_height
- i
- 1, 0, flayer
->l_width
- 1, 1);
1475 MarkScrollDownDisplay(n
)
1480 debug1("MarkScrollDownDisplay(%d)\n", n
);
1483 if (n
> markdata
->hist_offset
)
1484 n
= markdata
->hist_offset
;
1485 markdata
->hist_offset
-= n
;
1486 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1487 LScrollV(flayer
, -i
, 0, fore
->w_height
- 1, 0);
1489 MarkRedisplayLine(i
, 0, flayer
->l_width
- 1, 1);
1494 MakePaster(pa
, buf
, len
, bufiscopy
)
1501 pa
->pa_pasteptr
= buf
;
1502 pa
->pa_pastelen
= len
;
1504 pa
->pa_pastebuf
= buf
;
1505 pa
->pa_pastelayer
= flayer
;
1506 DoProcess(Layer2Window(flayer
), &pa
->pa_pasteptr
, &pa
->pa_pastelen
, pa
);
1513 if (pa
->pa_pastebuf
)
1514 free(pa
->pa_pastebuf
);
1515 pa
->pa_pastebuf
= 0;
1516 pa
->pa_pasteptr
= 0;
1517 pa
->pa_pastelen
= 0;
1518 pa
->pa_pastelayer
= 0;
1519 evdeq(&pa
->pa_slowev
);
1522 #endif /* COPY_PASTE */