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 * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
33 #include <sys/types.h>
48 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
50 * WARNING: these routines use the global variables "fore" and
51 * "flayer" to make things easier.
53 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
56 static int is_letter(int);
57 static void nextword(int *, int *, int, int);
58 static int linestart(int);
59 static int lineend(int);
60 static int rem(int, int, int, int, int, char *, int);
61 static bool eq(int, int);
62 static int MarkScrollDownDisplay(int);
63 static int MarkScrollUpDisplay(int);
65 static void MarkProcess(char **, size_t *);
66 static void MarkAbort(void);
67 static void MarkRedisplayLine(int, int, int, int);
69 bool compacthist
= false;
70 bool join_with_cr
= false;
71 bool pastefont
= true;
73 const struct LayFuncs MarkLf
= {
83 unsigned char mark_key_tab
[256]; /* this array must be initialised first! */
85 static struct markdata
*markdata
;
88 * VI like is_letter: 0 - whitespace
92 static int is_letter(int c
)
95 c
== '_' || c
== '.' || c
== '@' || c
== ':' || c
== '%' || c
== '!' || c
== '-' || c
== '+')
96 /* thus we can catch email-addresses as a word :-) */
103 static int linestart(int y
)
108 for (x
= markdata
->left_mar
, i
= WIN(y
)->image
+ x
; x
< fore
->w_width
- 1; x
++)
111 if (x
== fore
->w_width
- 1)
112 x
= markdata
->left_mar
;
116 static int lineend(int y
)
121 for (x
= markdata
->right_mar
, i
= WIN(y
)->image
+ x
; x
>= 0; x
--)
125 x
= markdata
->left_mar
;
130 * nextchar sets *xp to the num-th occurrence of the target in the line.
132 * Returns -1 if the target doesn't appear num times, 0 otherwise.
134 static int nextchar(int *xp
, int *yp
, int direction
, char target
, int num
)
136 int width
; /* width of the current window. */
137 int x
; /* x coordinate of the current cursor position. */
138 int step
; /* amount to increment x (+1 or -1) */
139 int adjust
; /* Final adjustment of cursor position. */
140 char *displayed_line
; /* Line in which search takes place. */
145 width
= fore
->w_width
;
146 displayed_line
= (char *)WIN(*yp
)->image
;
150 adjust
= -1; /* fall through */
155 adjust
= 1; /* fall through */
163 for (; x
>= 0 && x
<= width
; x
+= step
) {
164 if (displayed_line
[x
] == target
) {
175 * nextword calculates the cursor position of the num'th word.
176 * If the cursor is on a word, it counts as the first.
177 * NW_BACK: search backward
178 * NW_ENDOFWORD: find the end of the word
179 * NW_MUSTMOVE: move at least one char
180 * NW_BIG: match WORDs not words
183 #define NW_BACK (1<<0)
184 #define NW_ENDOFWORD (1<<1)
185 #define NW_MUSTMOVE (1<<2)
186 #define NW_BIG (1<<3)
188 static void nextword(int *xp
, int *yp
, int flags
, int num
)
190 int xx
= fore
->w_width
, yy
= fore
->w_histheight
+ fore
->w_height
;
196 sx
= (flags
& NW_BACK
) ? -1 : 1;
197 if ((flags
& NW_ENDOFWORD
) && (flags
& NW_MUSTMOVE
))
200 for (oq
= -1;; x
+= sx
, oq
= q
) {
201 if (x
>= xx
|| x
< 0)
203 else if (flags
& NW_BIG
)
204 q
= ml
->image
[x
] == ' ';
206 q
= is_letter(ml
->image
[x
]);
207 if (oq
>= 0 && oq
!= q
) {
208 if (oq
== 0 || !(flags
& NW_ENDOFWORD
))
213 if ((!(flags
& NW_ENDOFWORD
) && q
) || ((flags
& NW_ENDOFWORD
) && oq
)) {
233 * y1, y2 are WIN coordinates
235 * redisplay: 0 - just copy
236 * 1 - redisplay + copy
237 * 2 - count + copy, don't redisplay
240 static int rem(int x1
, int y1
, int x2
, int y2
, int redisplay
, char *pt
, int yend
)
242 int i
, j
, from
, to
, ry
;
249 markdata
->second
= 0;
250 if (y2
< y1
|| ((y2
== y1
) && (x2
< x1
))) {
258 ry
= y1
- markdata
->hist_offset
;
261 if (redisplay
!= 2 && pt
== NULL
&& ry
< 0) {
265 for (; i
<= y2
; i
++, ry
++) {
266 if (redisplay
!= 2 && pt
== NULL
&& ry
> yend
)
269 from
= (i
== y1
) ? x1
: 0;
270 if (from
< markdata
->left_mar
)
271 from
= markdata
->left_mar
;
272 for (to
= fore
->w_width
, im
= ml
->image
+ to
; to
>= 0; to
--)
275 if (i
== y2
&& x2
< to
)
277 if (to
> markdata
->right_mar
)
278 to
= markdata
->right_mar
;
279 if (redisplay
== 1 && from
<= to
&& ry
>= 0 && ry
<= yend
)
280 MarkRedisplayLine(ry
, from
, to
, 0);
281 if (redisplay
!= 2 && pt
== NULL
) /* don't count/copy */
284 if (dw_right(ml
, j
, fore
->w_encoding
))
289 for (; j
<= to
; j
++) {
292 if (fore
->w_encoding
== UTF8
) {
296 c
= ToUtf8_comb(pt
, c
);
302 if (is_dw_font(cf
)) {
308 c
= EncodeChar(pt
, c
| cf
<< 16, fore
->w_encoding
, &font
);
318 if (pastefont
&& font
!= ASCII
) {
320 strncpy(pt
, "\033(B", 4);
325 if (i
!= y2
&& (to
!= fore
->w_width
- 1 || ml
->image
[to
+ 1] == ' ')) {
327 * this code defines, what glues lines together
329 switch (markdata
->nonl
) {
330 case 0: /* lines separated by newlines */
340 case 1: /* nothing to separate lines */
342 case 2: /* lines separated by blanks */
347 case 3: /* seperate by comma, for csh junkies */
358 /* Check if two chars are identical. All digits are treated
359 * as same. Used for GetHistory()
362 static bool eq(int a
, int b
)
366 if (a
== 0 || b
== 0)
368 if (isdigit(a
) && isdigit(b
))
373 /**********************************************************************/
376 { /* return value 1 if copybuffer changed */
377 int i
= 0, q
= 0, xx
, yy
, x
, y
;
382 if (x
>= fore
->w_width
)
383 x
= fore
->w_width
- 1;
384 y
= fore
->w_y
+ fore
->w_histheight
;
386 for (xx
= x
- 1, linep
= ml
->image
+ xx
; xx
>= 0; xx
--)
387 if ((q
= *linep
--) != ' ')
389 for (yy
= y
- 1; yy
>= 0; yy
--) {
392 if (xx
< 0 || eq(linep
[xx
], q
)) { /* line is matching... */
393 for (i
= fore
->w_width
- 1, linep
+= i
; i
>= x
; i
--)
402 if (D_user
->u_plop
.buf
)
403 UserFreeCopyBuffer(D_user
);
404 if ((D_user
->u_plop
.buf
= malloc((unsigned)(i
- x
+ 2))) == NULL
) {
405 LMsg(0, "Not enough memory... Sorry.");
408 memmove(D_user
->u_plop
.buf
, (char *)linep
- i
+ x
+ 1, i
- x
+ 1);
409 D_user
->u_plop
.len
= i
- x
+ 1;
410 D_user
->u_plop
.enc
= fore
->w_encoding
;
414 /**********************************************************************/
416 void MarkRoutine(void)
420 if (InitOverlayPage(sizeof(struct markdata
), &MarkLf
, 1))
422 flayer
->l_encoding
= fore
->w_encoding
;
424 markdata
= (struct markdata
*)flayer
->l_data
;
425 markdata
->md_user
= D_user
; /* XXX: Correct? */
426 markdata
->md_window
= fore
;
427 markdata
->second
= 0;
428 markdata
->rep_cnt
= 0;
429 markdata
->append_mode
= 0;
430 markdata
->write_buffer
= 0;
432 markdata
->left_mar
= 0;
433 markdata
->right_mar
= fore
->w_width
- 1;
434 markdata
->hist_offset
= fore
->w_histheight
;
437 if (x
>= fore
->w_width
)
438 x
= fore
->w_width
- 1;
440 LGotoPos(flayer
, x
, W2D(y
));
441 LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)",
442 x
+ 1, W2D(y
+ 1), fore
->w_histheight
, fore
->w_width
, fore
->w_height
);
443 markdata
->cx
= markdata
->x1
= x
;
444 markdata
->cy
= markdata
->y1
= y
;
446 flayer
->l_y
= W2D(y
);
449 static void MarkProcess(char **inbufp
, size_t *inlenp
)
453 int cx
, cy
, x2
, y2
, j
, yend
;
454 int newcopylen
= 0, od
;
457 struct acluser
*md_user
;
460 char *extrap = 0, extrabuf[100];
463 markdata
= (struct markdata
*)flayer
->l_data
;
464 fore
= markdata
->md_window
;
465 md_user
= markdata
->md_user
;
466 if (inbufp
== NULL
) {
471 LGotoPos(flayer
, markdata
->cx
, W2D(markdata
->cy
));
476 while (in_mark
&& (inlen
/* || extrap */ )) {
477 unsigned char ch
= (unsigned char)*pt
++;
479 if (flayer
->l_mouseevent
.start
) {
480 int r
= LayProcessMouse(flayer
, ch
);
482 LayProcessMouseSwitch(flayer
, 0);
490 od
= mark_key_tab
[(int)ch
];
491 rep_cnt
= markdata
->rep_cnt
;
492 if (isdigit(od
) && !markdata
->f_cmd
.flag
) {
493 if (rep_cnt
< 1001 && (od
!= '0' || rep_cnt
!= 0)) {
494 markdata
->rep_cnt
= 10 * rep_cnt
+ od
- '0';
497 * Now what is that 1001 here? Well, we have a screen with
498 * 25 * 80 = 2000 characters. Movement is at most across the full
499 * screen. This we do with word by word movement, as character by
500 * character movement never steps over line boundaries. The most words
501 * we can place on the screen are 1000 single letter words. Thus 1001
502 * is sufficient. Users with bigger screens never write in single letter
503 * words, as they should be more advanced. jw.
504 * Oh, wrong. We still give even the experienced user a factor of ten.
511 if (markdata
->f_cmd
.flag
) {
512 markdata
->f_cmd
.flag
= 0;
513 markdata
->rep_cnt
= 0;
516 markdata
->f_cmd
.target
= od
;
517 rep_cnt
= (rep_cnt
) ? rep_cnt
: 1;
518 nextchar(&cx
, &cy
, markdata
->f_cmd
.direction
, od
, rep_cnt
);
526 case 'f': /* fall through */
527 case 'F': /* fall through */
528 case 't': /* fall through */
529 case 'T': /* fall through */
531 * Set f_cmd to do a search on the next key stroke.
532 * If we break, rep_cnt will be reset, so we
533 * continue instead. It might be cleaner to
534 * store the rep_count in f_cmd and
535 * break here so later followon code will be
538 markdata
->f_cmd
.flag
= 1;
539 markdata
->f_cmd
.direction
= od
;
543 if (!markdata
->f_cmd
.target
)
548 od
== ';' ? markdata
->f_cmd
.direction
: (markdata
->f_cmd
.direction
^ 0x20),
549 markdata
->f_cmd
.target
, rep_cnt
);
554 if (!markdata
->second
)
556 markdata
->cx
= markdata
->x1
;
557 markdata
->cy
= markdata
->y1
;
560 revto(markdata
->cx
, markdata
->cy
);
562 case '\014': /* CTRL-L Redisplay */
564 LGotoPos(flayer
, cx
, W2D(cy
));
566 case 0202: /* M-C-b */
567 case '\010': /* CTRL-H Backspace */
571 revto(cx
- rep_cnt
, cy
);
573 case 0216: /* M-C-p */
574 case '\016': /* CTRL-N */
578 revto(cx
, cy
+ rep_cnt
);
584 if (j
> fore
->w_histheight
+ fore
->w_height
- 1)
585 j
= fore
->w_histheight
+ fore
->w_height
- 1;
586 revto(linestart(j
), j
);
594 revto(linestart(cy
), cy
);
597 revto(linestart(cy
), cy
);
600 revto(markdata
->left_mar
, cy
+ 1);
602 case 0220: /* M-C-p */
603 case '\020': /* CTRL-P */
607 revto(cx
, cy
- rep_cnt
);
609 case 0206: /* M-C-f */
613 revto(cx
+ rep_cnt
, cy
);
615 case '\001': /* CTRL-A from tcsh/emacs */
617 revto(markdata
->left_mar
, cy
);
619 case '\004': /* CTRL-D down half screen */
621 rep_cnt
= (fore
->w_height
+ 1) >> 1;
622 revto_line(cx
, cy
+ rep_cnt
, W2D(cy
));
625 revto(lineend(cy
), cy
);
627 case '\022': /* CTRL-R emacs style backwards search */
631 case '\023': /* CTRL-S emacs style search */
635 case '\025': /* CTRL-U up half screen */
637 rep_cnt
= (fore
->w_height
+ 1) >> 1;
638 revto_line(cx
, cy
- rep_cnt
, W2D(cy
));
640 case '\007': /* CTRL-G show cursorpos */
641 if (markdata
->left_mar
== 0 && markdata
->right_mar
== fore
->w_width
- 1)
642 LMsg(0, "Column %d Line %d(+%d)", cx
+ 1, W2D(cy
) + 1, markdata
->hist_offset
);
644 LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx
+ 1,
645 markdata
->left_mar
+ 1, markdata
->right_mar
+ 1, W2D(cy
) + 1,
646 markdata
->hist_offset
);
648 case '\002': /* CTRL-B back one page */
651 rep_cnt
*= fore
->w_height
;
652 revto(cx
, cy
- rep_cnt
);
654 case '\006': /* CTRL-F forward one page */
657 rep_cnt
*= fore
->w_height
;
658 revto(cx
, cy
+ rep_cnt
);
660 case '\005': /* CTRL-E scroll up */
663 MarkScrollUpDisplay(rep_cnt
);
667 LGotoPos(flayer
, cx
, W2D(cy
));
669 case '\031': /* CTRL-Y scroll down */
672 MarkScrollDownDisplay(rep_cnt
);
673 if (cy
> D2W(fore
->w_height
- 1))
674 revto(cx
, D2W(fore
->w_height
- 1));
676 LGotoPos(flayer
, cx
, W2D(cy
));
679 /* it may be useful to have a key that does nothing */
682 /* rep_cnt is a percentage for the history buffer */
687 revto_line(markdata
->left_mar
,
688 fore
->w_histheight
- fore
->w_scrollback_height
+
689 (int)(rep_cnt
* (fore
->w_scrollback_height
+ fore
->w_height
) / 100.0),
690 (fore
->w_height
- 1) / 2);
698 /* rep_cnt is here the WIN line number */
700 rep_cnt
= fore
->w_histheight
+ fore
->w_height
;
701 revto_line(markdata
->left_mar
, --rep_cnt
, (fore
->w_height
- 1) / 2);
704 revto(markdata
->left_mar
, D2W(0));
707 revto(markdata
->left_mar
, D2W((fore
->w_height
- 1) / 2));
710 revto(markdata
->left_mar
, D2W(fore
->w_height
- 1));
713 revto(--rep_cnt
, cy
);
718 nextword(&cx
, &cy
, NW_MUSTMOVE
, rep_cnt
);
725 nextword(&cx
, &cy
, NW_ENDOFWORD
| NW_MUSTMOVE
| (od
== 'E' ? NW_BIG
: 0), rep_cnt
);
732 nextword(&cx
, &cy
, NW_BACK
| NW_ENDOFWORD
| NW_MUSTMOVE
| (od
== 'B' ? NW_BIG
: 0), rep_cnt
);
736 markdata
->append_mode
= 1 - markdata
->append_mode
;
737 LMsg(0, (markdata
->append_mode
) ? ":set append" : ":set noappend");
741 /* this sets start column to column 9 for VI :set nu users */
742 if (markdata
->left_mar
== 8)
749 /* set start column (c) and end column (C) */
750 if (markdata
->second
) {
751 rem(markdata
->x1
, markdata
->y1
, cx
, cy
, 1, NULL
, fore
->w_height
- 1); /* Hack */
752 markdata
->second
= 1; /* rem turns off second */
758 markdata
->left_mar
= rep_cnt
;
759 if (markdata
->left_mar
> markdata
->right_mar
)
760 markdata
->left_mar
= markdata
->right_mar
;
762 markdata
->right_mar
= rep_cnt
;
763 if (markdata
->left_mar
> markdata
->right_mar
)
764 markdata
->right_mar
= markdata
->left_mar
;
766 if (markdata
->second
) {
767 markdata
->cx
= markdata
->x1
;
768 markdata
->cy
= markdata
->y1
;
771 if (od
== 'v' || od
== 'V')
772 LMsg(0, (markdata
->left_mar
!= 8) ? ":set nonu" : ":set nu");
775 /* how do you join lines in VI ? */
776 markdata
->nonl
= (markdata
->nonl
+ 1) % 4;
777 switch (markdata
->nonl
) {
780 LMsg(0, "Multiple lines (CR/LF)");
782 LMsg(0, "Multiple lines (LF)");
785 LMsg(0, "Lines joined");
788 LMsg(0, "Lines joined with blanks");
791 LMsg(0, "Lines joined with comma");
807 markdata
->isdir
= -markdata
->isdir
;
809 markdata
->isdir
= -markdata
->isdir
;
813 if (markdata
->second
== 0) {
814 revto(linestart(cy
), cy
);
816 cx
= markdata
->x1
= markdata
->cx
;
817 cy
= markdata
->y1
= markdata
->cy
;
820 revto(cx
, cy
+ rep_cnt
);
821 revto(lineend(markdata
->cy
), markdata
->cy
);
829 if (!markdata
->second
) {
830 nextword(&cx
, &cy
, NW_BACK
| NW_ENDOFWORD
, 1);
833 cx
= markdata
->x1
= markdata
->cx
;
834 cy
= markdata
->y1
= markdata
->cy
;
836 nextword(&cx
, &cy
, NW_ENDOFWORD
, rep_cnt
);
844 markdata
->append_mode
= 1;
848 markdata
->write_buffer
= 1;
852 if (!markdata
->second
) {
857 LMsg(0, "First mark set - Column %d Line %d", cx
+ 1, W2D(cy
) + 1);
860 int append_mode
= markdata
->append_mode
;
861 int write_buffer
= markdata
->write_buffer
;
865 newcopylen
= rem(markdata
->x1
, markdata
->y1
, x2
, y2
, 2, NULL
, 0); /* count */
866 if (md_user
->u_plop
.buf
&& !append_mode
)
867 UserFreeCopyBuffer(md_user
);
868 yend
= fore
->w_height
- 1;
869 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
) {
870 markdata
->second
= 0;
871 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
873 if (newcopylen
> 0) {
874 /* the +3 below is for : cr + lf + \0 */
875 if (md_user
->u_plop
.buf
)
876 md_user
->u_plop
.buf
= realloc(md_user
->u_plop
.buf
,
877 (unsigned)(md_user
->u_plop
.len
+
880 md_user
->u_plop
.len
= 0;
881 md_user
->u_plop
.buf
= malloc((unsigned)(newcopylen
+ 3));
883 if (!md_user
->u_plop
.buf
) {
886 LMsg(0, "Not enough memory... Sorry.");
887 md_user
->u_plop
.len
= 0;
888 md_user
->u_plop
.buf
= NULL
;
892 switch (markdata
->nonl
) {
894 * this code defines, what glues lines together
898 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\r';
899 md_user
->u_plop
.len
++;
901 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = '\n';
902 md_user
->u_plop
.len
++;
907 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ' ';
908 md_user
->u_plop
.len
++;
911 md_user
->u_plop
.buf
[md_user
->u_plop
.len
] = ',';
912 md_user
->u_plop
.len
++;
916 md_user
->u_plop
.len
+= rem(markdata
->x1
, markdata
->y1
, x2
, y2
,
917 markdata
->hist_offset
== fore
->w_histheight
,
918 md_user
->u_plop
.buf
+ md_user
->u_plop
.len
, yend
);
919 md_user
->u_plop
.enc
= fore
->w_encoding
;
921 if (markdata
->hist_offset
!= fore
->w_histheight
) {
922 LAY_CALL_UP(LRefreshAll(flayer
, 0));
925 WindowChanged(fore
, WINESC_COPY_MODE
);
927 LMsg(0, "Appended %d characters to buffer", newcopylen
);
929 LMsg(0, "Copied %zu characters into buffer", md_user
->u_plop
.len
);
931 WriteFile(md_user
, NULL
, DUMP_EXCHANGE
);
937 if (flayer
->l_mouseevent
.start
) {
938 int button
= flayer
->l_mouseevent
.buffer
[0];
942 } else if (button
== '`') {
945 } else if (button
== ' ') {
947 cx
= flayer
->l_mouseevent
.buffer
[1];
948 cy
= D2W(flayer
->l_mouseevent
.buffer
[2]);
953 LayProcessMouseSwitch(flayer
, 0);
957 LayProcessMouseSwitch(flayer
, 1);
962 LMsg(0, "Copy mode aborted");
966 if (in_mark
) /* markdata may be freed */
967 markdata
->rep_cnt
= 0;
970 flayer
->l_x
= markdata
->cx
;
971 flayer
->l_y
= W2D(markdata
->cy
);
977 void revto(int tx
, int ty
)
979 revto_line(tx
, ty
, -1);
982 /* tx, ty: WINDOW, line: DISPLAY */
983 void revto_line(int tx
, int ty
, int line
)
986 int x
, y
, t
, revst
, reven
, qq
, ff
, tt
, st
, en
, ce
= 0;
987 int ystart
= 0, yend
= fore
->w_height
- 1;
995 else if (tx
> fore
->w_width
- 1)
996 tx
= fore
->w_width
- 1;
997 if (ty
< fore
->w_histheight
- fore
->w_scrollback_height
)
998 ty
= fore
->w_histheight
- fore
->w_scrollback_height
;
999 else if (ty
> fore
->w_histheight
+ fore
->w_height
- 1)
1000 ty
= fore
->w_histheight
+ fore
->w_height
- 1;
1005 /* don't just move inside of a kanji, the user wants to see something */
1007 if (ty
== fy
&& fx
+ 1 == tx
&& dw_right(ml
, tx
, fore
->w_encoding
) && tx
< D_width
- 1)
1009 if (ty
== fy
&& fx
- 1 == tx
&& dw_right(ml
, fx
, fore
->w_encoding
) && tx
)
1016 * if we go to a position that is currently offscreen
1017 * then scroll the screen
1020 if (line
>= 0 && line
< fore
->w_height
)
1022 else if (ty
< markdata
->hist_offset
)
1023 i
= ty
- markdata
->hist_offset
;
1024 else if (ty
> markdata
->hist_offset
+ (fore
->w_height
- 1))
1025 i
= ty
- markdata
->hist_offset
- (fore
->w_height
- 1);
1027 yend
-= MarkScrollUpDisplay(i
);
1029 ystart
+= MarkScrollDownDisplay(-i
);
1031 if (markdata
->second
== 0) {
1033 flayer
->l_y
= W2D(ty
);
1034 LGotoPos(flayer
, tx
, W2D(ty
));
1038 qq
= markdata
->x1
+ markdata
->y1
* fore
->w_width
;
1039 ff
= fx
+ fy
* fore
->w_width
; /* "from" offset in WIN coords */
1040 tt
= tx
+ ty
* fore
->w_width
; /* "to" offset in WIN coords */
1066 ry
= y
- markdata
->hist_offset
;
1070 st
= y
* fore
->w_width
;
1074 for (t
= st
; t
<= en
; t
++, x
++) {
1075 if (x
>= fore
->w_width
) {
1082 if (t
== st
|| x
== 0) {
1083 wi
= ml
->image
+ fore
->w_width
;
1084 for (ce
= fore
->w_width
; ce
>= 0; ce
--, wi
--)
1088 if (x
<= ce
&& x
>= markdata
->left_mar
&& x
<= markdata
->right_mar
) {
1089 if (dw_right(ml
, x
, fore
->w_encoding
)) {
1095 if (t
>= revst
&& t
<= reven
) {
1098 mc
.font
= ml
->font
[x
];
1100 mc
.image
= ml
->image
[x
];
1102 copy_mline2mchar(&mc
, ml
, x
);
1103 if (dw_left(ml
, x
, fore
->w_encoding
)) {
1104 mc
.mbcs
= ml
->image
[x
+ 1];
1105 LPutChar(flayer
, &mc
, x
, W2D(y
));
1108 LPutChar(flayer
, &mc
, x
, W2D(y
));
1109 if (dw_left(ml
, x
, fore
->w_encoding
))
1114 flayer
->l_y
= W2D(ty
);
1115 LGotoPos(flayer
, tx
, W2D(ty
));
1118 static void MarkAbort(void)
1122 markdata
= (struct markdata
*)flayer
->l_data
;
1123 fore
= markdata
->md_window
;
1124 yend
= fore
->w_height
- 1;
1125 redisp
= markdata
->second
;
1126 if (fore
->w_histheight
- markdata
->hist_offset
< fore
->w_height
) {
1127 markdata
->second
= 0;
1128 yend
-= MarkScrollUpDisplay(fore
->w_histheight
- markdata
->hist_offset
);
1130 if (markdata
->hist_offset
!= fore
->w_histheight
) {
1131 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1133 rem(markdata
->x1
, markdata
->y1
, markdata
->cx
, markdata
->cy
, redisp
, NULL
, yend
);
1136 WindowChanged(fore
, WINESC_COPY_MODE
);
1139 static void MarkRedisplayLine(int y
, int xs
, int xe
, int isblank
)
1140 /* NOTE: y is in DISPLAY coords system! */
1143 int sta
, sto
, cp
; /* NOTE: these 3 are in WINDOW coords system */
1146 struct mchar mchar_marked
;
1148 if (y
< 0) /* No special full page handling */
1151 markdata
= (struct markdata
*)flayer
->l_data
;
1152 fore
= markdata
->md_window
;
1154 mchar_marked
= mchar_so
;
1159 if (markdata
->second
== 0) {
1160 if (dw_right(ml
, xs
, fore
->w_encoding
) && xs
> 0)
1162 if (dw_left(ml
, xe
, fore
->w_encoding
) && xe
< fore
->w_width
- 1)
1164 if (xs
== 0 && y
> 0 && wy
> 0 && WIN(wy
- 1)->image
[flayer
->l_width
] == 0)
1165 LCDisplayLineWrap(flayer
, ml
, y
, xs
, xe
, isblank
);
1167 LCDisplayLine(flayer
, ml
, y
, xs
, xe
, isblank
);
1171 sta
= markdata
->y1
* fore
->w_width
+ markdata
->x1
;
1172 sto
= markdata
->cy
* fore
->w_width
+ markdata
->cx
;
1178 cp
= wy
* fore
->w_width
+ xs
;
1180 rm
= markdata
->right_mar
;
1181 for (x
= fore
->w_width
, wi
= ml
->image
+ fore
->w_width
; x
>= 0; x
--, wi
--)
1187 for (x
= xs
; x
<= xe
; x
++, cp
++)
1188 if (cp
>= sta
&& x
>= markdata
->left_mar
)
1190 if (dw_right(ml
, x
, fore
->w_encoding
))
1193 LCDisplayLine(flayer
, ml
, y
, xs
, x
- 1, isblank
);
1194 for (; x
<= xe
; x
++, cp
++) {
1195 if (cp
> sto
|| x
> rm
)
1198 mchar_marked
.font
= ml
->font
[x
];
1200 mchar_marked
.image
= ml
->image
[x
];
1201 mchar_marked
.mbcs
= 0;
1202 if (dw_left(ml
, x
, fore
->w_encoding
)) {
1203 mchar_marked
.mbcs
= ml
->image
[x
+ 1];
1206 LPutChar(flayer
, &mchar_marked
, x
, y
);
1207 if (dw_left(ml
, x
, fore
->w_encoding
))
1211 LCDisplayLine(flayer
, ml
, y
, x
, xe
, isblank
);
1215 * scroll the screen contents up/down.
1217 static int MarkScrollUpDisplay(int n
)
1223 if (n
> fore
->w_histheight
- markdata
->hist_offset
)
1224 n
= fore
->w_histheight
- markdata
->hist_offset
;
1225 markdata
->hist_offset
+= n
;
1226 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1227 LScrollV(flayer
, i
, 0, flayer
->l_height
- 1, 0);
1229 MarkRedisplayLine(flayer
->l_height
- i
- 1, 0, flayer
->l_width
- 1, 1);
1233 static int MarkScrollDownDisplay(int n
)
1239 if (n
> markdata
->hist_offset
)
1240 n
= markdata
->hist_offset
;
1241 markdata
->hist_offset
-= n
;
1242 i
= (n
< flayer
->l_height
) ? n
: (flayer
->l_height
);
1243 LScrollV(flayer
, -i
, 0, fore
->w_height
- 1, 0);
1245 MarkRedisplayLine(i
, 0, flayer
->l_width
- 1, 1);
1249 void MakePaster(struct paster
*pa
, char *buf
, size_t len
, int bufiscopy
)
1252 pa
->pa_pasteptr
= buf
;
1253 pa
->pa_pastelen
= len
;
1255 pa
->pa_pastebuf
= buf
;
1256 pa
->pa_pastelayer
= flayer
;
1257 DoProcess(Layer2Window(flayer
), &pa
->pa_pasteptr
, &pa
->pa_pastelen
, pa
);
1260 void FreePaster(struct paster
*pa
)
1262 if (pa
->pa_pastebuf
)
1263 free(pa
->pa_pastebuf
);
1264 pa
->pa_pastebuf
= NULL
;
1265 pa
->pa_pasteptr
= NULL
;
1266 pa
->pa_pastelen
= 0;
1267 pa
->pa_pastelayer
= NULL
;
1268 evdeq(&pa
->pa_slowev
);