1449 lines
33 KiB
C
1449 lines
33 KiB
C
/* Copyright (c) 2008, 2009
|
|
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
|
|
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
|
|
* Micah Cowan (micah@cowan.name)
|
|
* Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
|
|
* Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
|
|
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
|
|
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
|
|
* Copyright (c) 1987 Oliver Laumann
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program (see the file COPYING); if not, see
|
|
* https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
|
*
|
|
****************************************************************
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <ctype.h>
|
|
|
|
#include "config.h"
|
|
#include "screen.h"
|
|
#include "mark.h"
|
|
#include "extern.h"
|
|
|
|
#ifdef COPY_PASTE
|
|
|
|
/*
|
|
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
*
|
|
* WARNING: these routines use the global variables "fore" and
|
|
* "flayer" to make things easier.
|
|
*
|
|
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
*/
|
|
|
|
static int is_letter __P((char));
|
|
static void nextword __P((int *, int *, int, int));
|
|
static int linestart __P((int));
|
|
static int lineend __P((int));
|
|
static int rem __P((int, int, int, int, int, char *, int));
|
|
static int eq __P((int, int));
|
|
static int MarkScrollDownDisplay __P((int));
|
|
static int MarkScrollUpDisplay __P((int));
|
|
|
|
static void MarkProcess __P((char **, int *));
|
|
static void MarkAbort __P((void));
|
|
static void MarkRedisplayLine __P((int, int, int, int));
|
|
static int MarkRewrite __P((int, int, int, struct mchar *, int));
|
|
|
|
extern struct layer *flayer;
|
|
extern struct display *display, *displays;
|
|
extern struct win *fore;
|
|
extern struct mline mline_blank, mline_null;
|
|
extern struct mchar mchar_so;
|
|
|
|
#ifdef FONT
|
|
int pastefont = 1;
|
|
#endif
|
|
|
|
struct LayFuncs MarkLf = {
|
|
MarkProcess,
|
|
MarkAbort,
|
|
MarkRedisplayLine,
|
|
DefClearLine,
|
|
MarkRewrite,
|
|
DefResize,
|
|
DefRestore,
|
|
0
|
|
};
|
|
|
|
int join_with_cr = 0;
|
|
int compacthist = 0;
|
|
|
|
unsigned char mark_key_tab[256]; /* this array must be initialised first! */
|
|
|
|
static struct markdata *markdata;
|
|
|
|
/*
|
|
* VI like is_letter: 0 - whitespace
|
|
* 1 - letter
|
|
* 2 - other
|
|
*/
|
|
static int
|
|
is_letter(char c)
|
|
{
|
|
if ((c >= 'a' && c <= 'z') ||
|
|
(c >= 'A' && c <= 'Z') ||
|
|
(c >= '0' && c <= '9') ||
|
|
c == '_' || c == '.' ||
|
|
c == '@' || c == ':' ||
|
|
c == '%' || c == '!' ||
|
|
c == '-' || c == '+')
|
|
/* thus we can catch email-addresses as a word :-) */
|
|
return 1;
|
|
else if (c != ' ')
|
|
return 2;
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
linestart(int y)
|
|
{
|
|
register int x;
|
|
register unsigned char *i;
|
|
|
|
for (x = markdata->left_mar, i = WIN(y)->image + x; x < fore->w_width - 1; x++)
|
|
if (*i++ != ' ')
|
|
break;
|
|
if (x == fore->w_width - 1)
|
|
x = markdata->left_mar;
|
|
return x;
|
|
}
|
|
|
|
static int
|
|
lineend(int y)
|
|
{
|
|
register int x;
|
|
register unsigned char *i;
|
|
|
|
for (x = markdata->right_mar, i = WIN(y)->image + x; x >= 0; x--)
|
|
if (*i-- != ' ')
|
|
break;
|
|
if (x < 0)
|
|
x = markdata->left_mar;
|
|
return x;
|
|
}
|
|
|
|
/*
|
|
* nextchar sets *xp to the num-th occurrence of the target in the line.
|
|
*
|
|
* Returns -1 if the target doesn't appear num times, 0 otherwise.
|
|
*/
|
|
static int
|
|
nextchar(int *xp, int *yp, int direction, char target, int num)
|
|
{
|
|
int width; /* width of the current window. */
|
|
int x; /* x coordinate of the current cursor position. */
|
|
int step; /* amount to increment x (+1 or -1) */
|
|
int adjust; /* Final adjustment of cursor position. */
|
|
char *displayed_line; /* Line in which search takes place. */
|
|
|
|
debug("nextchar\n");
|
|
|
|
x = *xp;
|
|
step = 1;
|
|
adjust = 0;
|
|
width = fore->w_width;
|
|
displayed_line = (char *)WIN(*yp)->image;
|
|
|
|
switch (direction) {
|
|
case 't':
|
|
adjust = -1; /* fall through */
|
|
case 'f':
|
|
step = 1;
|
|
break;
|
|
case 'T':
|
|
adjust = 1; /* fall through */
|
|
case 'F':
|
|
step = -1;
|
|
break;
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
|
|
x += step;
|
|
|
|
debug1("ml->image = %s\n", displayed_line);
|
|
debug2("num = %d, width = %d\n", num, width);
|
|
debug2("x = %d target = %c\n", x, target);
|
|
|
|
for (; x >= 0 && x <= width; x += step) {
|
|
if (displayed_line[x] == target) {
|
|
if (--num == 0) {
|
|
*xp = x + adjust;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* nextword calculates the cursor position of the num'th word.
|
|
* If the cursor is on a word, it counts as the first.
|
|
* NW_BACK: search backward
|
|
* NW_ENDOFWORD: find the end of the word
|
|
* NW_MUSTMOVE: move at least one char
|
|
* NW_BIG: match WORDs not words
|
|
*/
|
|
|
|
#define NW_BACK (1<<0)
|
|
#define NW_ENDOFWORD (1<<1)
|
|
#define NW_MUSTMOVE (1<<2)
|
|
#define NW_BIG (1<<3)
|
|
|
|
static void
|
|
nextword(int *xp, int *yp, int flags, int num)
|
|
{
|
|
int xx = fore->w_width, yy = fore->w_histheight + fore->w_height;
|
|
register int sx, oq, q, x, y;
|
|
struct mline *ml;
|
|
|
|
x = *xp;
|
|
y = *yp;
|
|
sx = (flags & NW_BACK) ? -1 : 1;
|
|
if ((flags & NW_ENDOFWORD) && (flags & NW_MUSTMOVE))
|
|
x += sx;
|
|
ml = WIN(y);
|
|
for (oq = -1;; x += sx, oq = q) {
|
|
if (x >= xx || x < 0)
|
|
q = 0;
|
|
else if (flags & NW_BIG)
|
|
q = ml->image[x] == ' ';
|
|
else
|
|
q = is_letter(ml->image[x]);
|
|
|
|
if (oq >= 0 && oq != q) {
|
|
if (oq == 0 || !(flags & NW_ENDOFWORD))
|
|
*xp = x;
|
|
else
|
|
*xp = x - sx;
|
|
*yp = y;
|
|
|
|
if ((!(flags & NW_ENDOFWORD) && q) || ((flags & NW_ENDOFWORD) && oq)) {
|
|
if (--num <= 0)
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (x == xx) {
|
|
x = -1;
|
|
if (++y >= yy)
|
|
return;
|
|
ml = WIN(y);
|
|
} else if (x < 0) {
|
|
x = xx;
|
|
if (--y < 0)
|
|
return;
|
|
ml = WIN(y);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* y1, y2 are WIN coordinates
|
|
*
|
|
* redisplay: 0 - just copy
|
|
* 1 - redisplay + copy
|
|
* 2 - count + copy, don't redisplay
|
|
*/
|
|
|
|
static int
|
|
rem(int x1, int y1, int x2, int y2, int redisplay, char *pt, int yend)
|
|
{
|
|
int i, j, from, to, ry, c;
|
|
int l = 0;
|
|
unsigned char *im;
|
|
struct mline *ml;
|
|
#ifdef FONT
|
|
int cf, cfx, font;
|
|
unsigned char *fo, *fox;
|
|
#endif
|
|
|
|
markdata->second = 0;
|
|
if (y2 < y1 || ((y2 == y1) && (x2 < x1))) {
|
|
i = y2;
|
|
y2 = y1;
|
|
y1 = i;
|
|
i = x2;
|
|
x2 = x1;
|
|
x1 = i;
|
|
}
|
|
ry = y1 - markdata->hist_offset;
|
|
|
|
i = y1;
|
|
if (redisplay != 2 && pt == 0 && ry < 0) {
|
|
i -= ry;
|
|
ry = 0;
|
|
}
|
|
for (; i <= y2; i++, ry++) {
|
|
if (redisplay != 2 && pt == 0 && ry > yend)
|
|
break;
|
|
ml = WIN(i);
|
|
from = (i == y1) ? x1 : 0;
|
|
|
|
if (from < markdata->left_mar)
|
|
from = markdata->left_mar;
|
|
for (to = fore->w_width, im = ml->image + to; to >= 0; to--)
|
|
if (*im-- != ' ')
|
|
break;
|
|
if (i == y2 && x2 < to)
|
|
to = x2;
|
|
if (to > markdata->right_mar)
|
|
to = markdata->right_mar;
|
|
if (redisplay == 1 && from <= to && ry >= 0 && ry <= yend)
|
|
MarkRedisplayLine(ry, from, to, 0);
|
|
if (redisplay != 2 && pt == 0) /* don't count/copy */
|
|
continue;
|
|
j = from;
|
|
#ifdef DW_CHARS
|
|
if (dw_right(ml, j, fore->w_encoding))
|
|
j--;
|
|
#endif
|
|
im = ml->image + j;
|
|
#ifdef FONT
|
|
fo = ml->font + j;
|
|
fox = ml->fontx + j;
|
|
font = ASCII;
|
|
#endif
|
|
for (; j <= to; j++) {
|
|
c = (unsigned char)*im++;
|
|
#ifdef FONT
|
|
cf = (unsigned char)*fo++;
|
|
cfx = (unsigned char)*fox++;
|
|
# ifdef UTF8
|
|
if (fore->w_encoding == UTF8) {
|
|
c |= cf << 8 | cfx << 16;
|
|
if (c == UCS_HIDDEN)
|
|
continue;
|
|
c = ToUtf8_comb(pt, c);
|
|
l += c;
|
|
if (pt)
|
|
pt += c;
|
|
continue;
|
|
}
|
|
# endif
|
|
# ifdef DW_CHARS
|
|
if (is_dw_font(cf)) {
|
|
c = c << 8 | (unsigned char)*im++;
|
|
fo++;
|
|
j++;
|
|
}
|
|
# endif
|
|
if (pastefont) {
|
|
c = EncodeChar(pt, c | cf << 16, fore->w_encoding, &font);
|
|
l += c;
|
|
if (pt)
|
|
pt += c;
|
|
continue;
|
|
}
|
|
#endif /* FONT */
|
|
if (pt)
|
|
*pt++ = c;
|
|
l++;
|
|
}
|
|
#ifdef FONT
|
|
if (pastefont && font != ASCII) {
|
|
if (pt) {
|
|
strcpy(pt, "\033(B");
|
|
pt += 3;
|
|
}
|
|
l += 3;
|
|
}
|
|
#endif
|
|
if (i != y2 && (to != fore->w_width - 1 || ml->image[to + 1] == ' ')) {
|
|
/*
|
|
* this code defines, what glues lines together
|
|
*/
|
|
switch (markdata->nonl) {
|
|
case 0: /* lines separated by newlines */
|
|
if (pt)
|
|
*pt++ = '\r';
|
|
l++;
|
|
if (join_with_cr) {
|
|
if (pt)
|
|
*pt++ = '\n';
|
|
l++;
|
|
}
|
|
break;
|
|
case 1: /* nothing to separate lines */
|
|
break;
|
|
case 2: /* lines separated by blanks */
|
|
if (pt)
|
|
*pt++ = ' ';
|
|
l++;
|
|
break;
|
|
case 3: /* seperate by comma, for csh junkies */
|
|
if (pt)
|
|
*pt++ = ',';
|
|
l++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
/* Check if two chars are identical. All digits are treated
|
|
* as same. Used for GetHistory()
|
|
*/
|
|
|
|
static int
|
|
eq(int a, int b)
|
|
{
|
|
if (a == b)
|
|
return 1;
|
|
if (a == 0 || b == 0)
|
|
return 1;
|
|
if (a <= '9' && a >= '0' && b <= '9' && b >= '0')
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
|
|
int
|
|
GetHistory() /* return value 1 if copybuffer changed */
|
|
{
|
|
int i = 0, q = 0, xx, yy, x, y;
|
|
unsigned char *linep;
|
|
struct mline *ml;
|
|
|
|
ASSERT(display && fore);
|
|
x = fore->w_x;
|
|
if (x >= fore->w_width)
|
|
x = fore->w_width - 1;
|
|
y = fore->w_y + fore->w_histheight;
|
|
debug2("cursor is at x=%d, y=%d\n", x, y);
|
|
ml = WIN(y);
|
|
for (xx = x - 1, linep = ml->image + xx; xx >= 0; xx--)
|
|
if ((q = *linep--) != ' ')
|
|
break;
|
|
debug3("%c at (%d,%d)\n", q, xx, y);
|
|
for (yy = y - 1; yy >= 0; yy--) {
|
|
ml = WIN(yy);
|
|
linep = ml->image;
|
|
if (xx < 0 || eq(linep[xx], q)) { /* line is matching... */
|
|
for (i = fore->w_width - 1, linep += i; i >= x; i--)
|
|
if (*linep-- != ' ')
|
|
break;
|
|
if (i >= x)
|
|
break;
|
|
}
|
|
}
|
|
if (yy < 0)
|
|
return 0;
|
|
if (D_user->u_plop.buf)
|
|
UserFreeCopyBuffer(D_user);
|
|
if ((D_user->u_plop.buf = (char *)malloc((unsigned)(i - x + 2))) ==
|
|
NULL) {
|
|
LMsg(0, "Not enough memory... Sorry.");
|
|
return 0;
|
|
}
|
|
bcopy((char *)linep - i + x + 1, D_user->u_plop.buf, i - x + 1);
|
|
D_user->u_plop.len = i - x + 1;
|
|
#ifdef ENCODINGS
|
|
D_user->u_plop.enc = fore->w_encoding;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
|
|
|
|
void
|
|
MarkRoutine()
|
|
{
|
|
int x, y;
|
|
|
|
ASSERT(fore && display && D_user);
|
|
|
|
debug2("MarkRoutine called: fore nr %d, display %s\n", fore->w_number, D_usertty);
|
|
|
|
if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1))
|
|
return;
|
|
flayer->l_encoding = fore->w_encoding;
|
|
flayer->l_mode = 1;
|
|
markdata = (struct markdata *)flayer->l_data;
|
|
markdata->md_user = D_user; /* XXX: Correct? */
|
|
markdata->md_window = fore;
|
|
markdata->second = 0;
|
|
markdata->rep_cnt = 0;
|
|
markdata->append_mode = 0;
|
|
markdata->write_buffer = 0;
|
|
markdata->nonl = 0;
|
|
markdata->left_mar = 0;
|
|
markdata->right_mar = fore->w_width - 1;
|
|
markdata->hist_offset = fore->w_histheight;
|
|
x = fore->w_x;
|
|
y = D2W(fore->w_y);
|
|
if (x >= fore->w_width)
|
|
x = fore->w_width - 1;
|
|
|
|
LGotoPos(flayer, x, W2D(y));
|
|
LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)", x + 1, W2D(y + 1), fore->w_histheight, fore->w_width, fore->w_height);
|
|
markdata->cx = markdata->x1 = x;
|
|
markdata->cy = markdata->y1 = y;
|
|
flayer->l_x = x;
|
|
flayer->l_y = W2D(y);
|
|
}
|
|
|
|
static void
|
|
MarkProcess(char **inbufp, int *inlenp)
|
|
{
|
|
char *inbuf, *pt;
|
|
int inlen;
|
|
int cx, cy, x2, y2, j, yend;
|
|
int newcopylen = 0, od;
|
|
int in_mark;
|
|
int rep_cnt;
|
|
struct acluser *md_user;
|
|
|
|
/*
|
|
char *extrap = 0, extrabuf[100];
|
|
*/
|
|
|
|
markdata = (struct markdata *)flayer->l_data;
|
|
fore = markdata->md_window;
|
|
md_user = markdata->md_user;
|
|
if (inbufp == 0) {
|
|
MarkAbort();
|
|
return;
|
|
}
|
|
|
|
LGotoPos(flayer, markdata->cx, W2D(markdata->cy));
|
|
inbuf = *inbufp;
|
|
inlen = *inlenp;
|
|
pt = inbuf;
|
|
in_mark = 1;
|
|
while (in_mark && (inlen /* || extrap */)) {
|
|
unsigned char ch = (unsigned char)*pt++;
|
|
inlen--;
|
|
if (flayer->l_mouseevent.start) {
|
|
int r = LayProcessMouse(flayer, ch);
|
|
if (r == -1)
|
|
LayProcessMouseSwitch(flayer, 0);
|
|
else {
|
|
if (r)
|
|
ch = 0222;
|
|
else
|
|
continue;
|
|
}
|
|
}
|
|
od = mark_key_tab[(int)ch];
|
|
rep_cnt = markdata->rep_cnt;
|
|
if (od >= '0' && od <= '9' && !markdata->f_cmd.flag) {
|
|
if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) {
|
|
markdata->rep_cnt = 10 * rep_cnt + od - '0';
|
|
continue;
|
|
/*
|
|
* Now what is that 1001 here? Well, we have a screen with
|
|
* 25 * 80 = 2000 characters. Movement is at most across the full
|
|
* screen. This we do with word by word movement, as character by
|
|
* character movement never steps over line boundaries. The most words
|
|
* we can place on the screen are 1000 single letter words. Thus 1001
|
|
* is sufficient. Users with bigger screens never write in single letter
|
|
* words, as they should be more advanced. jw.
|
|
* Oh, wrong. We still give even the experienced user a factor of ten.
|
|
*/
|
|
}
|
|
}
|
|
cx = markdata->cx;
|
|
cy = markdata->cy;
|
|
|
|
if (markdata->f_cmd.flag) {
|
|
debug2("searching for %c:%d\n", od, rep_cnt);
|
|
markdata->f_cmd.flag = 0;
|
|
markdata->rep_cnt = 0;
|
|
|
|
if (isgraph(od)) {
|
|
markdata->f_cmd.target = od;
|
|
rep_cnt = (rep_cnt) ? rep_cnt : 1;
|
|
nextchar(&cx, &cy, markdata->f_cmd.direction, od, rep_cnt);
|
|
revto(cx, cy);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
processchar:
|
|
switch (od) {
|
|
case 'f': /* fall through */
|
|
case 'F': /* fall through */
|
|
case 't': /* fall through */
|
|
case 'T': /* fall through */
|
|
/*
|
|
* Set f_cmd to do a search on the next key stroke.
|
|
* If we break, rep_cnt will be reset, so we
|
|
* continue instead. It might be cleaner to
|
|
* store the rep_count in f_cmd and
|
|
* break here so later followon code will be
|
|
* hit.
|
|
*/
|
|
markdata->f_cmd.flag = 1;
|
|
markdata->f_cmd.direction = od;
|
|
debug("entering char search\n");
|
|
continue;
|
|
case ';':
|
|
case ',':
|
|
if (!markdata->f_cmd.target)
|
|
break;
|
|
if (!rep_cnt)
|
|
rep_cnt = 1;
|
|
nextchar(&cx,
|
|
&cy,
|
|
od == ';' ? markdata->f_cmd.direction : (markdata->f_cmd.direction ^ 0x20),
|
|
markdata->f_cmd.target,
|
|
rep_cnt);
|
|
revto(cx, cy);
|
|
break;
|
|
case 'o':
|
|
case 'x':
|
|
if (!markdata->second)
|
|
break;
|
|
markdata->cx = markdata->x1;
|
|
markdata->cy = markdata->y1;
|
|
markdata->x1 = cx;
|
|
markdata->y1 = cy;
|
|
revto(markdata->cx, markdata->cy);
|
|
break;
|
|
case '\014': /* CTRL-L Redisplay */
|
|
Redisplay(0);
|
|
LGotoPos(flayer, cx, W2D(cy));
|
|
break;
|
|
case 0202: /* M-C-b */
|
|
case '\010': /* CTRL-H Backspace */
|
|
case 'h':
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
revto(cx - rep_cnt, cy);
|
|
break;
|
|
case 0216: /* M-C-p */
|
|
case '\016': /* CTRL-N */
|
|
case 'j':
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
revto(cx, cy + rep_cnt);
|
|
break;
|
|
case '+':
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
j = cy + rep_cnt;
|
|
if (j > fore->w_histheight + fore->w_height - 1)
|
|
j = fore->w_histheight + fore->w_height - 1;
|
|
revto(linestart(j), j);
|
|
break;
|
|
case '-':
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
cy -= rep_cnt;
|
|
if (cy < 0)
|
|
cy = 0;
|
|
revto(linestart(cy), cy);
|
|
break;
|
|
case '^':
|
|
revto(linestart(cy), cy);
|
|
break;
|
|
case '\n':
|
|
revto(markdata->left_mar, cy + 1);
|
|
break;
|
|
case 0220: /* M-C-p */
|
|
case '\020': /* CTRL-P */
|
|
case 'k':
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
revto(cx, cy - rep_cnt);
|
|
break;
|
|
case 0206: /* M-C-f */
|
|
case 'l':
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
revto(cx + rep_cnt, cy);
|
|
break;
|
|
case '\001': /* CTRL-A from tcsh/emacs */
|
|
case '0':
|
|
revto(markdata->left_mar, cy);
|
|
break;
|
|
case '\004': /* CTRL-D down half screen */
|
|
if (rep_cnt == 0)
|
|
rep_cnt = (fore->w_height + 1) >> 1;
|
|
revto_line(cx, cy + rep_cnt, W2D(cy));
|
|
break;
|
|
case '$':
|
|
revto(lineend(cy), cy);
|
|
break;
|
|
case '\022': /* CTRL-R emacs style backwards search */
|
|
ISearch(-1);
|
|
in_mark = 0;
|
|
break;
|
|
case '\023': /* CTRL-S emacs style search */
|
|
ISearch(1);
|
|
in_mark = 0;
|
|
break;
|
|
case '\025': /* CTRL-U up half screen */
|
|
if (rep_cnt == 0)
|
|
rep_cnt = (fore->w_height + 1) >> 1;
|
|
revto_line(cx, cy - rep_cnt, W2D(cy));
|
|
break;
|
|
case '\007': /* CTRL-G show cursorpos */
|
|
if (markdata->left_mar == 0 && markdata->right_mar == fore->w_width - 1)
|
|
LMsg(0, "Column %d Line %d(+%d)", cx + 1, W2D(cy) + 1, markdata->hist_offset);
|
|
else
|
|
LMsg(0, "Column %d(%d..%d) Line %d(+%d)",
|
|
cx + 1, markdata->left_mar + 1,
|
|
markdata->right_mar + 1, W2D(cy) + 1,
|
|
markdata->hist_offset);
|
|
break;
|
|
case '\002': /* CTRL-B back one page */
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
rep_cnt *= fore->w_height;
|
|
revto(cx, cy - rep_cnt);
|
|
break;
|
|
case '\006': /* CTRL-F forward one page */
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
rep_cnt *= fore->w_height;
|
|
revto(cx, cy + rep_cnt);
|
|
break;
|
|
case '\005': /* CTRL-E scroll up */
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
rep_cnt = MarkScrollUpDisplay(rep_cnt);
|
|
if (cy < D2W(0))
|
|
revto(cx, D2W(0));
|
|
else
|
|
LGotoPos(flayer, cx, W2D(cy));
|
|
break;
|
|
case '\031': /* CTRL-Y scroll down */
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
rep_cnt = MarkScrollDownDisplay(rep_cnt);
|
|
if (cy > D2W(fore->w_height - 1))
|
|
revto(cx, D2W(fore->w_height - 1));
|
|
else
|
|
LGotoPos(flayer, cx, W2D(cy));
|
|
break;
|
|
case '@':
|
|
/* it may be useful to have a key that does nothing */
|
|
break;
|
|
case '%':
|
|
/* rep_cnt is a percentage for the history buffer */
|
|
if (rep_cnt < 0)
|
|
rep_cnt = 0;
|
|
if (rep_cnt > 100)
|
|
rep_cnt = 100;
|
|
|
|
revto_line(markdata->left_mar,
|
|
fore->w_histheight - fore->w_scrollback_height +
|
|
(int)(rep_cnt * (fore->w_scrollback_height +
|
|
fore->w_height) / 100.0), (fore->w_height - 1) / 2);
|
|
break;
|
|
case 0201:
|
|
case 'g':
|
|
rep_cnt = 1;
|
|
/* FALLTHROUGH */
|
|
case 0205:
|
|
case 'G':
|
|
/* rep_cnt is here the WIN line number */
|
|
if (rep_cnt == 0)
|
|
rep_cnt = fore->w_histheight + fore->w_height;
|
|
revto_line(markdata->left_mar, --rep_cnt, (fore->w_height - 1) / 2);
|
|
break;
|
|
case 'H':
|
|
revto(markdata->left_mar, D2W(0));
|
|
break;
|
|
case 'M':
|
|
revto(markdata->left_mar, D2W((fore->w_height - 1) / 2));
|
|
break;
|
|
case 'L':
|
|
revto(markdata->left_mar, D2W(fore->w_height - 1));
|
|
break;
|
|
case '|':
|
|
revto(--rep_cnt, cy);
|
|
break;
|
|
case 'w':
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
nextword(&cx, &cy, NW_MUSTMOVE, rep_cnt);
|
|
revto(cx, cy);
|
|
break;
|
|
case 'e':
|
|
case 'E':
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
nextword(&cx, &cy, NW_ENDOFWORD|NW_MUSTMOVE | (od == 'E' ? NW_BIG : 0), rep_cnt);
|
|
revto(cx, cy);
|
|
break;
|
|
case 'b':
|
|
case 'B':
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE | (od == 'B' ? NW_BIG : 0), rep_cnt);
|
|
revto(cx, cy);
|
|
break;
|
|
case 'a':
|
|
markdata->append_mode = 1 - markdata->append_mode;
|
|
debug1("append mode %d--\n", markdata->append_mode);
|
|
LMsg(0, (markdata->append_mode) ? ":set append" : ":set noappend");
|
|
break;
|
|
case 'v':
|
|
case 'V':
|
|
/* this sets start column to column 9 for VI :set nu users */
|
|
if (markdata->left_mar == 8)
|
|
rep_cnt = 1;
|
|
else
|
|
rep_cnt = 9;
|
|
/* FALLTHROUGH */
|
|
case 'c':
|
|
case 'C':
|
|
/* set start column (c) and end column (C) */
|
|
if (markdata->second) {
|
|
rem(markdata->x1, markdata->y1, cx, cy, 1, (char *)0, fore->w_height - 1); /* Hack */
|
|
markdata->second = 1; /* rem turns off second */
|
|
}
|
|
rep_cnt--;
|
|
if (rep_cnt < 0)
|
|
rep_cnt = cx;
|
|
if (od != 'C') {
|
|
markdata->left_mar = rep_cnt;
|
|
if (markdata->left_mar > markdata->right_mar)
|
|
markdata->left_mar = markdata->right_mar;
|
|
} else {
|
|
markdata->right_mar = rep_cnt;
|
|
if (markdata->left_mar > markdata->right_mar)
|
|
markdata->right_mar = markdata->left_mar;
|
|
}
|
|
if (markdata->second) {
|
|
markdata->cx = markdata->x1;
|
|
markdata->cy = markdata->y1;
|
|
revto(cx, cy);
|
|
}
|
|
if (od == 'v' || od == 'V')
|
|
LMsg(0, (markdata->left_mar != 8) ? ":set nonu" : ":set nu");
|
|
break;
|
|
case 'J':
|
|
/* how do you join lines in VI ? */
|
|
markdata->nonl = (markdata->nonl + 1) % 4;
|
|
switch (markdata->nonl) {
|
|
case 0:
|
|
if (join_with_cr)
|
|
LMsg(0, "Multiple lines (CR/LF)");
|
|
else
|
|
LMsg(0, "Multiple lines (LF)");
|
|
break;
|
|
case 1:
|
|
LMsg(0, "Lines joined");
|
|
break;
|
|
case 2:
|
|
LMsg(0, "Lines joined with blanks");
|
|
break;
|
|
case 3:
|
|
LMsg(0, "Lines joined with comma");
|
|
break;
|
|
}
|
|
break;
|
|
case '/':
|
|
Search(1);
|
|
in_mark = 0;
|
|
break;
|
|
case '?':
|
|
Search(-1);
|
|
in_mark = 0;
|
|
break;
|
|
case 'n':
|
|
Search(0);
|
|
break;
|
|
case 'N':
|
|
markdata->isdir = -markdata->isdir;
|
|
Search(0);
|
|
markdata->isdir = -markdata->isdir;
|
|
break;
|
|
case 'y':
|
|
case 'Y':
|
|
if (markdata->second == 0) {
|
|
revto(linestart(cy), cy);
|
|
markdata->second++;
|
|
cx = markdata->x1 = markdata->cx;
|
|
cy = markdata->y1 = markdata->cy;
|
|
}
|
|
if (--rep_cnt > 0)
|
|
revto(cx, cy + rep_cnt);
|
|
revto(lineend(markdata->cy), markdata->cy);
|
|
if (od == 'y')
|
|
break;
|
|
/* FALLTHROUGH */
|
|
case 'W':
|
|
if (od == 'W') {
|
|
if (rep_cnt == 0)
|
|
rep_cnt = 1;
|
|
if (!markdata->second) {
|
|
nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD, 1);
|
|
revto(cx, cy);
|
|
markdata->second++;
|
|
cx = markdata->x1 = markdata->cx;
|
|
cy = markdata->y1 = markdata->cy;
|
|
}
|
|
nextword(&cx, &cy, NW_ENDOFWORD, rep_cnt);
|
|
revto(cx, cy);
|
|
}
|
|
cx = markdata->cx;
|
|
cy = markdata->cy;
|
|
/* FALLTHROUGH */
|
|
case 'A':
|
|
if (od == 'A')
|
|
markdata->append_mode = 1;
|
|
/* FALLTHROUGH */
|
|
case '>':
|
|
if (od == '>')
|
|
markdata->write_buffer = 1;
|
|
/* FALLTHROUGH */
|
|
case ' ':
|
|
case '\r':
|
|
if (!markdata->second) {
|
|
markdata->second++;
|
|
markdata->x1 = cx;
|
|
markdata->y1 = cy;
|
|
revto(cx, cy);
|
|
LMsg(0, "First mark set - Column %d Line %d", cx + 1, W2D(cy) + 1);
|
|
break;
|
|
} else {
|
|
int append_mode = markdata->append_mode;
|
|
int write_buffer = markdata->write_buffer;
|
|
|
|
x2 = cx;
|
|
y2 = cy;
|
|
newcopylen = rem(markdata->x1, markdata->y1, x2, y2, 2, (char *)0, 0); /* count */
|
|
if (md_user->u_plop.buf && !append_mode)
|
|
UserFreeCopyBuffer(md_user);
|
|
yend = fore->w_height - 1;
|
|
if (fore->w_histheight - markdata->hist_offset < fore->w_height) {
|
|
markdata->second = 0;
|
|
yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset);
|
|
}
|
|
if (newcopylen > 0) {
|
|
/* the +3 below is for : cr + lf + \0 */
|
|
if (md_user->u_plop.buf)
|
|
md_user->u_plop.buf = realloc(md_user->u_plop.buf, (unsigned)(md_user->u_plop.len + newcopylen + 3));
|
|
else {
|
|
md_user->u_plop.len = 0;
|
|
md_user->u_plop.buf = malloc((unsigned)(newcopylen + 3));
|
|
}
|
|
if (!md_user->u_plop.buf) {
|
|
MarkAbort();
|
|
in_mark = 0;
|
|
LMsg(0, "Not enough memory... Sorry.");
|
|
md_user->u_plop.len = 0;
|
|
md_user->u_plop.buf = 0;
|
|
break;
|
|
}
|
|
if (append_mode) {
|
|
switch (markdata->nonl) {
|
|
/*
|
|
* this code defines, what glues lines together
|
|
*/
|
|
case 0:
|
|
if (join_with_cr) {
|
|
md_user->u_plop.buf[md_user->u_plop.len] = '\r';
|
|
md_user->u_plop.len++;
|
|
}
|
|
md_user->u_plop.buf[md_user->u_plop.len] = '\n';
|
|
md_user->u_plop.len++;
|
|
break;
|
|
case 1:
|
|
break;
|
|
case 2:
|
|
md_user->u_plop.buf[md_user->u_plop.len] = ' ';
|
|
md_user->u_plop.len++;
|
|
break;
|
|
case 3:
|
|
md_user->u_plop.buf[md_user->u_plop.len] = ',';
|
|
md_user->u_plop.len++;
|
|
break;
|
|
}
|
|
}
|
|
md_user->u_plop.len += rem(markdata->x1,
|
|
markdata->y1,
|
|
x2,
|
|
y2,
|
|
markdata->hist_offset == fore->w_histheight,
|
|
md_user->u_plop.buf + md_user->u_plop.len,
|
|
yend);
|
|
#ifdef ENCODINGS
|
|
md_user->u_plop.enc = fore->w_encoding;
|
|
#endif
|
|
}
|
|
if (markdata->hist_offset != fore->w_histheight) {
|
|
LAY_CALL_UP(LRefreshAll(flayer, 0));
|
|
}
|
|
ExitOverlayPage();
|
|
WindowChanged(fore, 'P');
|
|
|
|
if (append_mode)
|
|
LMsg(0, "Appended %d characters to buffer", newcopylen);
|
|
else
|
|
LMsg(0, "Copied %d characters into buffer", md_user->u_plop.len);
|
|
|
|
if (write_buffer)
|
|
WriteFile(md_user, (char *)0, DUMP_EXCHANGE);
|
|
in_mark = 0;
|
|
break;
|
|
}
|
|
|
|
case 0222:
|
|
if (flayer->l_mouseevent.start) {
|
|
int button = flayer->l_mouseevent.buffer[0];
|
|
if (button == 'a') {
|
|
/* Scroll down */
|
|
od = 'j';
|
|
} else if (button == '`') {
|
|
/* Scroll up */
|
|
od = 'k';
|
|
} else if (button == ' ') {
|
|
/* Left click */
|
|
cx = flayer->l_mouseevent.buffer[1];
|
|
cy = D2W(flayer->l_mouseevent.buffer[2]);
|
|
revto(cx, cy);
|
|
od = ' ';
|
|
} else
|
|
od = 0;
|
|
LayProcessMouseSwitch(flayer, 0);
|
|
if (od)
|
|
goto processchar;
|
|
} else
|
|
LayProcessMouseSwitch(flayer, 1);
|
|
break;
|
|
|
|
default:
|
|
MarkAbort();
|
|
LMsg(0, "Copy mode aborted");
|
|
in_mark = 0;
|
|
break;
|
|
}
|
|
if (in_mark) /* markdata may be freed */
|
|
markdata->rep_cnt = 0;
|
|
}
|
|
if (in_mark) {
|
|
flayer->l_x = markdata->cx;
|
|
flayer->l_y = W2D(markdata->cy);
|
|
}
|
|
*inbufp = pt;
|
|
*inlenp = inlen;
|
|
}
|
|
|
|
void
|
|
revto(int tx, int ty)
|
|
{
|
|
revto_line(tx, ty, -1);
|
|
}
|
|
|
|
/* tx, ty: WINDOW, line: DISPLAY */
|
|
void
|
|
revto_line(int tx, int ty, int line)
|
|
{
|
|
int fx, fy;
|
|
int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0;
|
|
int ystart = 0, yend = fore->w_height - 1;
|
|
int i, ry;
|
|
unsigned char *wi;
|
|
struct mline *ml;
|
|
struct mchar mc;
|
|
|
|
if (tx < 0)
|
|
tx = 0;
|
|
else if (tx > fore->w_width - 1)
|
|
tx = fore->w_width - 1;
|
|
if (ty < fore->w_histheight - fore->w_scrollback_height)
|
|
ty = fore->w_histheight - fore->w_scrollback_height;
|
|
else if (ty > fore->w_histheight + fore->w_height - 1)
|
|
ty = fore->w_histheight + fore->w_height - 1;
|
|
|
|
fx = markdata->cx;
|
|
fy = markdata->cy;
|
|
|
|
#ifdef DW_CHARS
|
|
/* don't just move inside of a kanji, the user wants to see something */
|
|
ml = WIN(ty);
|
|
if (ty == fy && fx + 1 == tx && dw_right(ml, tx, fore->w_encoding) && tx < D_width - 1)
|
|
tx++;
|
|
if (ty == fy && fx - 1 == tx && dw_right(ml, fx, fore->w_encoding) && tx)
|
|
tx--;
|
|
#endif
|
|
|
|
markdata->cx = tx;
|
|
markdata->cy = ty;
|
|
|
|
/*
|
|
* if we go to a position that is currently offscreen
|
|
* then scroll the screen
|
|
*/
|
|
i = 0;
|
|
|
|
if (line >= 0 && line < fore->w_height)
|
|
i = W2D(ty) - line;
|
|
else if (ty < markdata->hist_offset)
|
|
i = ty - markdata->hist_offset;
|
|
else if (ty > markdata->hist_offset + (fore->w_height - 1))
|
|
i = ty - markdata->hist_offset - (fore->w_height - 1);
|
|
|
|
if (i > 0)
|
|
yend -= MarkScrollUpDisplay(i);
|
|
else if (i < 0)
|
|
ystart += MarkScrollDownDisplay(-i);
|
|
|
|
if (markdata->second == 0) {
|
|
flayer->l_x = tx;
|
|
flayer->l_y = W2D(ty);
|
|
LGotoPos(flayer, tx, W2D(ty));
|
|
return;
|
|
}
|
|
|
|
qq = markdata->x1 + markdata->y1 * fore->w_width;
|
|
ff = fx + fy * fore->w_width; /* "from" offset in WIN coords */
|
|
tt = tx + ty * fore->w_width; /* "to" offset in WIN coords*/
|
|
|
|
if (ff > tt) {
|
|
st = tt;
|
|
en = ff;
|
|
x = tx;
|
|
y = ty;
|
|
} else {
|
|
st = ff;
|
|
en = tt;
|
|
x = fx;
|
|
y = fy;
|
|
}
|
|
|
|
if (st > qq) {
|
|
st++;
|
|
x++;
|
|
}
|
|
|
|
if (en < qq)
|
|
en--;
|
|
|
|
if (tt > qq) {
|
|
revst = qq;
|
|
reven = tt;
|
|
} else {
|
|
revst = tt;
|
|
reven = qq;
|
|
}
|
|
ry = y - markdata->hist_offset;
|
|
|
|
if (ry < ystart) {
|
|
y += (ystart - ry);
|
|
x = 0;
|
|
st = y * fore->w_width;
|
|
ry = ystart;
|
|
}
|
|
ml = WIN(y);
|
|
|
|
for (t = st; t <= en; t++, x++) {
|
|
if (x >= fore->w_width) {
|
|
x = 0;
|
|
y++, ry++;
|
|
ml = WIN(y);
|
|
}
|
|
if (ry > yend)
|
|
break;
|
|
if (t == st || x == 0) {
|
|
wi = ml->image + fore->w_width;
|
|
for (ce = fore->w_width; ce >= 0; ce--, wi--)
|
|
if (*wi != ' ')
|
|
break;
|
|
}
|
|
|
|
if (x <= ce && x >= markdata->left_mar && x <= markdata->right_mar) {
|
|
#ifdef DW_CHARS
|
|
if (dw_right(ml, x, fore->w_encoding)) {
|
|
if (t == revst)
|
|
revst--;
|
|
t--;
|
|
x--;
|
|
}
|
|
#endif
|
|
if (t >= revst && t <= reven) {
|
|
mc = mchar_so;
|
|
#ifdef FONT
|
|
if (pastefont) {
|
|
mc.font = ml->font[x];
|
|
mc.fontx = ml->fontx[x];
|
|
}
|
|
#endif
|
|
mc.image = ml->image[x];
|
|
} else
|
|
copy_mline2mchar(&mc, ml, x);
|
|
#ifdef DW_CHARS
|
|
if (dw_left(ml, x, fore->w_encoding)) {
|
|
mc.mbcs = ml->image[x + 1];
|
|
LPutChar(flayer, &mc, x, W2D(y));
|
|
t++;
|
|
}
|
|
#endif
|
|
LPutChar(flayer, &mc, x, W2D(y));
|
|
#ifdef DW_CHARS
|
|
if (dw_left(ml, x, fore->w_encoding))
|
|
x++;
|
|
#endif
|
|
}
|
|
}
|
|
flayer->l_x = tx;
|
|
flayer->l_y = W2D(ty);
|
|
LGotoPos(flayer, tx, W2D(ty));
|
|
}
|
|
|
|
static void
|
|
MarkAbort()
|
|
{
|
|
int yend, redisp;
|
|
|
|
debug("MarkAbort\n");
|
|
markdata = (struct markdata *)flayer->l_data;
|
|
fore = markdata->md_window;
|
|
yend = fore->w_height - 1;
|
|
redisp = markdata->second;
|
|
if (fore->w_histheight - markdata->hist_offset < fore->w_height) {
|
|
markdata->second = 0;
|
|
yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset);
|
|
}
|
|
if (markdata->hist_offset != fore->w_histheight) {
|
|
LAY_CALL_UP(LRefreshAll(flayer, 0));
|
|
} else {
|
|
rem(markdata->x1, markdata->y1, markdata->cx, markdata->cy, redisp, (char *)0, yend);
|
|
}
|
|
ExitOverlayPage();
|
|
WindowChanged(fore, 'P');
|
|
}
|
|
|
|
static void
|
|
MarkRedisplayLine(int y, int xs, int xe, int isblank) /* NOTE: y is in DISPLAY coords system! */
|
|
{
|
|
int wy, x, i, rm;
|
|
int sta, sto, cp; /* NOTE: these 3 are in WINDOW coords system */
|
|
unsigned char *wi;
|
|
struct mline *ml;
|
|
struct mchar mchar_marked;
|
|
|
|
if (y < 0) /* No special full page handling */
|
|
return;
|
|
|
|
markdata = (struct markdata *)flayer->l_data;
|
|
fore = markdata->md_window;
|
|
|
|
mchar_marked = mchar_so;
|
|
|
|
wy = D2W(y);
|
|
ml = WIN(wy);
|
|
|
|
if (markdata->second == 0) {
|
|
if (dw_right(ml, xs, fore->w_encoding) && xs > 0)
|
|
xs--;
|
|
if (dw_left(ml, xe, fore->w_encoding) && xe < fore->w_width - 1)
|
|
xe++;
|
|
if (xs == 0 && y > 0 && wy > 0 && WIN(wy - 1)->image[flayer->l_width] == 0)
|
|
LCDisplayLineWrap(flayer, ml, y, xs, xe, isblank);
|
|
else
|
|
LCDisplayLine(flayer, ml, y, xs, xe, isblank);
|
|
return;
|
|
}
|
|
|
|
sta = markdata->y1 * fore->w_width + markdata->x1;
|
|
sto = markdata->cy * fore->w_width + markdata->cx;
|
|
if (sta > sto) {
|
|
i = sta;
|
|
sta = sto;
|
|
sto = i;
|
|
}
|
|
cp = wy * fore->w_width + xs;
|
|
|
|
rm = markdata->right_mar;
|
|
for (x = fore->w_width, wi = ml->image + fore->w_width; x >= 0; x--, wi--)
|
|
if (*wi != ' ')
|
|
break;
|
|
if (x < rm)
|
|
rm = x;
|
|
|
|
for (x = xs; x <= xe; x++, cp++)
|
|
if (cp >= sta && x >= markdata->left_mar)
|
|
break;
|
|
#ifdef DW_CHARS
|
|
if (dw_right(ml, x, fore->w_encoding))
|
|
x--;
|
|
#endif
|
|
if (x > xs)
|
|
LCDisplayLine(flayer, ml, y, xs, x - 1, isblank);
|
|
for (; x <= xe; x++, cp++) {
|
|
if (cp > sto || x > rm)
|
|
break;
|
|
#ifdef FONT
|
|
if (pastefont) {
|
|
mchar_marked.font = ml->font[x];
|
|
mchar_marked.fontx = ml->fontx[x];
|
|
}
|
|
#endif
|
|
mchar_marked.image = ml->image[x];
|
|
#ifdef DW_CHARS
|
|
mchar_marked.mbcs = 0;
|
|
if (dw_left(ml, x, fore->w_encoding)) {
|
|
mchar_marked.mbcs = ml->image[x + 1];
|
|
cp++;
|
|
}
|
|
#endif
|
|
LPutChar(flayer, &mchar_marked, x, y);
|
|
#ifdef DW_CHARS
|
|
if (dw_left(ml, x, fore->w_encoding))
|
|
x++;
|
|
#endif
|
|
}
|
|
if (x <= xe)
|
|
LCDisplayLine(flayer, ml, y, x, xe, isblank);
|
|
}
|
|
|
|
/*
|
|
* This ugly routine is to speed up GotoPos()
|
|
*/
|
|
static int
|
|
MarkRewrite(int ry, int xs, int xe, struct mchar *rend, int doit)
|
|
{
|
|
int dx, x, y, st, en, t, rm;
|
|
unsigned char *i;
|
|
struct mline *ml;
|
|
struct mchar mchar_marked;
|
|
|
|
mchar_marked = mchar_so;
|
|
|
|
debug3("MarkRewrite %d, %d-%d\n", ry, xs, xe);
|
|
markdata = (struct markdata *)flayer->l_data;
|
|
fore = markdata->md_window;
|
|
y = D2W(ry);
|
|
ml = WIN(y);
|
|
#ifdef UTF8
|
|
if (fore->w_encoding && fore->w_encoding != UTF8 && D_encoding == UTF8 && ContainsSpecialDeffont(ml, xs, xe, fore->w_encoding))
|
|
return EXPENSIVE;
|
|
#endif
|
|
dx = xe - xs + 1;
|
|
if (doit) {
|
|
i = ml->image + xs;
|
|
while (dx--)
|
|
PUTCHAR(*i++);
|
|
return 0;
|
|
}
|
|
|
|
if (markdata->second == 0)
|
|
st = en = -1;
|
|
else {
|
|
st = markdata->y1 * fore->w_width + markdata->x1;
|
|
en = markdata->cy * fore->w_width + markdata->cx;
|
|
if (st > en) {
|
|
t = st;
|
|
st = en;
|
|
en = t;
|
|
}
|
|
}
|
|
t = y * fore->w_width + xs;
|
|
for (rm = fore->w_width, i = ml->image + fore->w_width; rm >= 0; rm--)
|
|
if (*i-- != ' ')
|
|
break;
|
|
if (rm > markdata->right_mar)
|
|
rm = markdata->right_mar;
|
|
x = xs;
|
|
while (dx--) {
|
|
if (t >= st && t <= en && x >= markdata->left_mar && x <= rm) {
|
|
#ifdef FONT
|
|
if (pastefont) {
|
|
mchar_marked.font = ml->font[x];
|
|
mchar_marked.fontx = ml->fontx[x];
|
|
}
|
|
#endif
|
|
rend->image = mchar_marked.image;
|
|
if (!cmp_mchar(rend, &mchar_marked))
|
|
return EXPENSIVE;
|
|
} else {
|
|
rend->image = ml->image[x];
|
|
if (!cmp_mchar_mline(rend, ml, x))
|
|
return EXPENSIVE;
|
|
}
|
|
x++;
|
|
}
|
|
return xe - xs + 1;
|
|
}
|
|
|
|
/*
|
|
* scroll the screen contents up/down.
|
|
*/
|
|
static int
|
|
MarkScrollUpDisplay(int n)
|
|
{
|
|
int i;
|
|
|
|
debug1("MarkScrollUpDisplay(%d)\n", n);
|
|
if (n <= 0)
|
|
return 0;
|
|
if (n > fore->w_histheight - markdata->hist_offset)
|
|
n = fore->w_histheight - markdata->hist_offset;
|
|
|
|
markdata->hist_offset += n;
|
|
i = (n < flayer->l_height) ? n : (flayer->l_height);
|
|
LScrollV(flayer, i, 0, flayer->l_height - 1, 0);
|
|
while (i-- > 0)
|
|
MarkRedisplayLine(flayer->l_height - i - 1, 0, flayer->l_width - 1, 1);
|
|
return n;
|
|
}
|
|
|
|
static int
|
|
MarkScrollDownDisplay(int n)
|
|
{
|
|
int i;
|
|
|
|
debug1("MarkScrollDownDisplay(%d)\n", n);
|
|
if (n <= 0)
|
|
return 0;
|
|
if (n > markdata->hist_offset)
|
|
n = markdata->hist_offset;
|
|
markdata->hist_offset -= n;
|
|
i = (n < flayer->l_height) ? n : (flayer->l_height);
|
|
LScrollV(flayer, -i, 0, fore->w_height - 1, 0);
|
|
while (i-- > 0)
|
|
MarkRedisplayLine(i, 0, flayer->l_width - 1, 1);
|
|
return n;
|
|
}
|
|
|
|
void
|
|
MakePaster(struct paster *pa, char *buf, int len, int bufiscopy)
|
|
{
|
|
FreePaster(pa);
|
|
pa->pa_pasteptr = buf;
|
|
pa->pa_pastelen = len;
|
|
if (bufiscopy)
|
|
pa->pa_pastebuf = buf;
|
|
pa->pa_pastelayer = flayer;
|
|
DoProcess(Layer2Window(flayer), &pa->pa_pasteptr, &pa->pa_pastelen, pa);
|
|
}
|
|
|
|
void
|
|
FreePaster(struct paster *pa)
|
|
{
|
|
if (pa->pa_pastebuf)
|
|
free(pa->pa_pastebuf);
|
|
pa->pa_pastebuf = 0;
|
|
pa->pa_pasteptr = 0;
|
|
pa->pa_pastelen = 0;
|
|
pa->pa_pastelayer = 0;
|
|
evdeq(&pa->pa_slowev);
|
|
}
|
|
|
|
#endif /* COPY_PASTE */
|
|
|