This is ublock.c in view mode; [Download] [Up]
/* Highlighted block functions
Copyright (C) 1992 Joseph H. Allen
This file is part of JOE (Joe's Own Editor)
JOE 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 1, or (at your option) any later version.
JOE 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
JOE; see the file COPYING. If not, write to the Free Software Foundation,
675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "b.h"
#include "bw.h"
#include "scrn.h"
#include "w.h"
#include "pw.h"
#include "qw.h"
#include "uedit.h"
#include "zstr.h"
#include "vs.h"
#include "ublock.h"
/* Global options */
int square=0; /* Set for rectangle mode */
int lightoff=0; /* Set if highlighting should turn off
after block operations */
extern int marking;
/* Global variables */
P *markb=0; /* Beginning and end of block */
P *markk=0;
/* Push markb & markk */
typedef struct marksav MARKSAV;
struct marksav
{
LINK(MARKSAV) link;
P *markb, *markk;
} markstack={{&markstack,&markstack}};
MARKSAV markfree={{&markfree,&markfree}};
int nstack=0;
int upsh(bw)
BW *bw;
{
MARKSAV *m=alitem(&markfree,sizeof(MARKSAV));
m->markb=0; m->markk=0;
if(markk) pdupown(markk,&m->markk);
if(markb) pdupown(markb,&m->markb);
enqueb(MARKSAV,link,&markstack,m);
++nstack;
return 0;
}
int upop(bw)
BW *bw;
{
MARKSAV *m=markstack.link.prev;
if(m!=&markstack)
{
--nstack;
prm(markk);
prm(markb);
markk=m->markk; if(markk) markk->owner= &markk;
markb=m->markb; if(markb) markb->owner= &markb;
demote(MARKSAV,link,&markfree,m);
if(lightoff) unmark(bw);
updall();
return 0;
}
else return -1;
}
/* Return true if markb/markk are valid */
int markv(r)
{
if(markb && markk && markb->b==markk->b && markk->byte>markb->byte &&
(!square || markk->xcol>markb->xcol)) return 1;
else if(r && markb && markk && markb->b==markk->b &&
markk->byte<markb->byte && (!square || markk->xcol<markb->xcol))
{
P *t=markb;
markb=markk;
markk=t;
markb->owner= &markb;
markk->owner= &markk;
return 1;
}
else return 0;
}
/* Rectangle-mode subroutines */
/* B *pextrect(P *org,long height,long left,long right);
* Copy a rectangle into a new buffer
*
* org points to top-left corner of rectangle.
* height is number of lines in rectangle.
* right is rightmost column of rectangle + 1
*/
B *pextrect(org,height,right)
P *org;
long height,right;
{
P *p=pdup(org); /* Left part of text to extract */
P *q=pdup(p); /* After right part of text to extract */
B *tmp=bmk(NULL); /* Buffer to extract to */
P *z=pdup(tmp->eof); /* Buffer pointer */
while(height--)
{
pcol(p,org->xcol);
pset(q,p);
pcolwse(q,right);
peof(z); binsb(z,bcpy(p,q));
peof(z); binsc(z,'\n');
pnextl(p);
}
prm(p); prm(q); prm(z);
return tmp;
}
/* void pdelrect(P *org,long height,long right);
* Delete a rectangle.
*/
void pdelrect(org,height,right)
P *org;
long height,right;
{
P *p=pdup(org);
P *q=pdup(p);
while(height--)
{
pcol(p,org->xcol);
pset(q,p);
pcol(q,right);
bdel(p,q);
pnextl(p);
}
prm(p); prm(q);
}
/* void pclrrect(P *org,long height,long right,int usetabs);
* Blank-out a rectangle.
*/
void pclrrect(org,height,right,usetabs)
P *org;
long height,right;
{
P *p=pdup(org);
P *q=pdup(p);
while(height--)
{
long pos;
pcol(p,org->xcol);
pset(q,p);
pcoli(q,right);
pos=q->col;
bdel(p,q);
pfill(p,pos,usetabs);
pnextl(p);
}
prm(p); prm(q);
}
/* int ptabrect(P *org,long height,long right)
* Check if there are any TABs in a rectange
*/
int ptabrect(org,height,right)
P *org;
long height,right;
{
P *p=pdup(org);
while(height--)
{
int c;
pcol(p,org->xcol);
while(c=pgetc(p), c!=MAXINT && c!='\n')
if(c=='\t')
{
prm(p); return 1;
}
else if(piscol(p)>right) break;
if(c!='\n') pnextl(p);
}
prm(p); return 0;
}
/* Insert rectangle */
void pinsrect(cur,tmp,width,usetabs)
P *cur;
B *tmp;
long width;
{
P *p=pdup(cur); /* We insert at & move this pointer */
P *q=pdup(tmp->bof); /* These are for scanning through 'tmp' */
P *r=pdup(q);
if(width)
while(pset(r,q), peol(q), (q->line!=tmp->eof->line || piscol(q)))
{
pcol(p,cur->xcol);
if(piscol(p)<cur->xcol) pfill(p,cur->xcol,usetabs);
binsb(p,bcpy(r,q)); pfwrd(p,q->byte-r->byte);
if(piscol(p)<cur->xcol+width) pfill(p,cur->xcol+width,usetabs);
if(piseol(p)) pbackws(p);
if(!pnextl(p)) binsc(p,'\n'), pgetc(p);
if(pgetc(q)==MAXINT) break;
}
prm(p); prm(q); prm(r);
}
/* Block functions */
/* Set beginning */
int umarkb(bw)
BW *bw;
{
pdupown(bw->cursor,&markb);
markb->xcol=bw->cursor->xcol;
updall();
return 0;
}
int udrop(bw)
BW *bw;
{
prm(markk);
if(marking && markb)
prm(markb);
else
umarkb(bw);
return 0;
}
/* Set end */
int umarkk(bw)
BW *bw;
{
pdupown(bw->cursor,&markk);
markk->xcol=bw->cursor->xcol;
updall();
return 0;
}
/* Unset marks */
int unmark(bw)
BW *bw;
{
prm(markb);
prm(markk);
updall();
return 0;
}
/* Mark line */
int umarkl(bw)
BW *bw;
{
pbol(bw->cursor);
umarkb(bw);
pnextl(bw->cursor);
umarkk(bw);
utomarkb(bw);
pcol(bw->cursor,bw->cursor->xcol);
return 0;
}
int utomarkb(bw)
BW *bw;
{
if(markb && markb->b==bw->b) { pset(bw->cursor,markb); return 0; }
else return -1;
}
int utomarkk(bw)
BW *bw;
{
if(markk && markk->b==bw->b) { pset(bw->cursor,markk); return 0; }
else return -1;
}
int uswap(bw)
BW *bw;
{
if(markb && markb->b==bw->b)
{
P *q=pdup(markb);
umarkb(bw);
pset(bw->cursor,q); prm(q);
return 0;
}
else return -1;
}
int utomarkbk(bw)
BW *bw;
{
if(markb && markb->b==bw->b && bw->cursor->byte!=markb->byte)
{ pset(bw->cursor,markb); return 0; }
else if(markk && markk->b==bw->b && bw->cursor->byte!=markk->byte)
{ pset(bw->cursor,markk); return 0; }
else return -1;
}
/* Delete block */
int ublkdel(bw)
BW *bw;
{
if(markv(1))
{
if(square)
if(bw->o.overtype)
{
long ocol=markk->xcol;
pclrrect(markb,markk->line-markb->line+1,markk->xcol,
ptabrect(markb,markk->line-markb->line+1,markk->xcol));
pcol(markk,ocol); markk->xcol=ocol;
}
else
pdelrect(markb,markk->line-markb->line+1,markk->xcol);
else
bdel(markb,markk);
if(lightoff) unmark(bw);
}
else { msgnw(bw,"No block"); return -1; }
return 0;
}
/* Move highlighted block */
int ublkmove(bw)
BW *bw;
{
if(markv(1))
{
if(markb->b->rdonly) { msgnw(bw,"Read only"); return -1; }
if(square)
{
long height=markk->line-markb->line+1;
long width=markk->xcol-markb->xcol;
int usetabs=ptabrect(markb,height,markk->xcol);
long ocol=piscol(bw->cursor);
B *tmp=pextrect(markb,height,markk->xcol);
ublkdel(bw);
if(bw->o.overtype)
{
/* If cursor was in block, blkdel moves it to left edge of block, so fix it
* back to its original place here */
pcol(bw->cursor,ocol);
pfill(bw->cursor,ocol,0);
pdelrect(bw->cursor,height,piscol(bw->cursor)+width);
}
else if(bw->cursor->xcol>=markk->xcol &&
bw->cursor->line>=markb->line &&
bw->cursor->line<=markk->line)
/* If cursor was to right of block, xcol was not properly updated */
bw->cursor->xcol-=width;
pinsrect(bw->cursor,tmp,width,usetabs);
brm(tmp);
if(lightoff) unmark(bw);
else
{
umarkb(bw);
umarkk(bw);
pline(markk,markk->line+height-1);
pcol(markk,markb->xcol+width); markk->xcol=markb->xcol+width;
}
return 0;
}
else if(bw->cursor->b!=markk->b ||
bw->cursor->byte>markk->byte ||
bw->cursor->byte<markb->byte)
{
long size=markk->byte-markb->byte;
binsb(bw->cursor,bcpy(markb,markk));
bdel(markb,markk);
if(lightoff) unmark(bw);
else
{
umarkb(bw);
umarkk(bw);
pfwrd(markk,size);
}
updall();
return 0;
}
}
msgnw(bw,"No block");
return -1;
}
/* Duplicate highlighted block */
int ublkcpy(bw)
BW *bw;
{
if(markv(1))
if(square)
{
long height=markk->line-markb->line+1;
long width=markk->xcol-markb->xcol;
int usetabs=ptabrect(markb,height,markk->xcol);
B *tmp=pextrect(markb,height,markk->xcol);
if(bw->o.overtype) pdelrect(bw->cursor,height,piscol(bw->cursor)+width);
pinsrect(bw->cursor,tmp,width,usetabs);
brm(tmp);
if(lightoff) unmark(bw);
else
{
umarkb(bw);
umarkk(bw);
pline(markk,markk->line+height-1);
pcol(markk,markb->xcol+width); markk->xcol=markb->xcol+width;
}
return 0;
}
else
{
long size=markk->byte-markb->byte;
binsb(bw->cursor,bcpy(markb,markk));
if(lightoff) unmark(bw);
else
{
umarkb(bw);
umarkk(bw);
pfwrd(markk,size);
}
updall();
return 0;
}
else { msgnw(bw,"No block"); return -1; }
}
/* Write highlighted block to a file */
/* This is called by ublksave in ufile.c */
int dowrite(bw,s,object,notify)
BW *bw;
char *s;
void *object;
int *notify;
{
if(notify) *notify=1;
if(markv(1))
if(square)
{
int fl;
int ret=0;
B *tmp=pextrect(markb,markk->line-markb->line+1,markk->xcol);
if(fl=bsave(tmp->bof,s,tmp->eof->byte)) msgnw(bw,msgs[5+fl]), ret= -1;
brm(tmp);
if(lightoff) unmark(bw);
vsrm(s);
return ret;
}
else
{
int fl;
int ret=0;
if(fl=bsave(markb,s,markk->byte-markb->byte)) msgnw(bw,msgs[5+fl]), ret= -1;
if(lightoff) unmark(bw);
vsrm(s);
return ret;
}
else
{
vsrm(s);
msgnw(bw,"No block");
return -1;
}
}
/* Set highlighted block on a program block */
void setindent(bw)
BW *bw;
{
P *p, *q;
long indent;
if(pisblank(bw->cursor)) return;
p=pdup(bw->cursor);
q=pdup(p);
indent=pisindent(p);
do
if(!pprevl(p)) goto done;
else pbol(p);
while(pisindent(p)>=indent && !pisblank(p));
pnextl(p);
done:
pbol(p);
p->xcol=piscol(p);
if(markb) prm(markb);
markb=p; p->owner= &markb;
do
if(!pnextl(q)) break;
while(pisindent(q)>=indent && !pisblank(q));
if(markk) prm(markk);
q->xcol=piscol(q);
markk=q; q->owner= &markk;
updall();
}
/* Indent more */
int urindent(bw)
BW *bw;
{
if(square)
{
if(markb && markk && markb->b==markk->b &&
markb->byte<=markk->byte && markb->xcol<=markk->xcol)
{
P *p=pdup(markb);
do
{
pcol(p,markb->xcol);
pfill(p,markb->xcol+bw->o.istep,bw->o.indentc=='\t'?1:0);
} while(pnextl(p) && p->line<=markk->line);
prm(p);
}
}
else
{
if(!markb || !markk || markb->b!=markk->b ||
bw->cursor->byte<markb->byte || bw->cursor->byte>markk->byte ||
markb->byte==markk->byte)
setindent(bw);
else
{
P *p=pdup(markb);
while(p->byte<markk->byte)
{
pbol(p);
if(!piseol(p)) while(piscol(p)<bw->o.istep) binsc(p,bw->o.indentc), pgetc(p);
pnextl(p);
}
prm(p);
}
}
return 0;
}
/* Indent less */
int ulindent(bw)
BW *bw;
{
if(square)
{
if(markb && markk && markb->b==markk->b &&
markb->byte<=markk->byte && markb->xcol<=markk->xcol)
{
P *p=pdup(markb);
P *q=pdup(p);
do
{
pcol(p,markb->xcol);
while(piscol(p)<markb->xcol+bw->o.istep)
{
int c=pgetc(p);
if(c!=' ' && c!='\t' && c!=bw->o.indentc)
{
prm(p);
prm(q);
return -1;
}
}
} while(pnextl(p) && p->line<=markk->line);
pset(p,markb);
do
{
pcol(p,markb->xcol);
pset(q,p);
pcol(q,markb->xcol+bw->o.istep);
bdel(p,q);
} while(pnextl(p) && p->line<=markk->line);
prm(p); prm(q);
}
}
else
{
if(!markb || !markk || markb->b!=markk->b ||
bw->cursor->byte<markb->byte || bw->cursor->byte>markk->byte ||
markb->byte==markk->byte)
setindent(bw);
else
{
P *p=pdup(markb);
P *q=pdup(p);
pbol(p);
while(p->byte<markk->byte)
{
if(!piseol(p)) while(piscol(p)<bw->o.istep)
{
int c=pgetc(p);
if(c!=' ' && c!='\t' && c!=bw->o.indentc)
{
prm(p);
prm(q);
return -1;
}
}
pnextl(p);
}
pset(p,markb);
pbol(p);
while(p->byte<markk->byte)
{
if(!piseol(p))
{
pset(q,p);
while(piscol(q)<bw->o.istep) pgetc(q);
bdel(p,q);
}
pnextl(p);
}
prm(p); prm(q);
}
}
return 0;
}
/* Insert a file */
int doinsf(bw,s,object,notify)
BW *bw;
char *s;
void *object;
int *notify;
{
if(notify) *notify=1;
if(square)
if(markv(1))
{
B *tmp;
long width=markk->xcol-markb->xcol;
long height;
int usetabs=ptabrect(markb,markk->line-markb->line+1,markk->xcol);
tmp=bload(s);
if(error)
{
msgnw(bw,msgs[error+5]);
brm(tmp);
return -1;
}
if(piscol(tmp->eof)) height=tmp->eof->line+1;
else height=tmp->eof->line;
if(bw->o.overtype)
{
pclrrect(markb,Lmax(markk->line-markb->line+1,height),markk->xcol,usetabs);
pdelrect(markb,height,width+markb->xcol);
}
pinsrect(markb,tmp,width,usetabs);
pdupown(markb,&markk);
markk->xcol=markb->xcol;
if(height)
{
pline(markk,markk->line+height-1);
pcol(markk,markb->xcol+width); markk->xcol=markb->xcol+width;
}
brm(tmp);
updall();
return 0;
}
else { msgnw(bw,"No block"); return -1; }
else
{
int ret=0;
B *tmp=bload(s);
if(error) msgnw(bw,msgs[error+5]), brm(tmp), ret= -1;
else binsb(bw->cursor,tmp);
vsrm(s);
bw->cursor->xcol=piscol(bw->cursor);
return ret;
}
}
/* Filter highlighted block through a UNIX command */
static int filtflg=0;
static int dofilt(bw,s,object,notify)
BW *bw;
char *s;
void *object;
int *notify;
{
int fr[2];
int fw[2];
if(notify) *notify=1;
if(markb && markk && !square &&
markb->b==bw->b && markk->b==bw->b && markb->byte==markk->byte) goto ok;
if(!markv(1))
{
msgnw(bw,"No block");
return -1;
}
ok:
pipe(fr);
pipe(fw);
npartial(bw->parent->t->t);
ttclsn();
if(!fork())
{
signrm();
close(0);
close(1);
dup(fw[0]);
dup(fr[1]);
close(fw[0]);
close(fr[1]);
close(fw[1]);
close(fr[0]);
execl("/bin/sh","/bin/sh","-c",s,NULL);
_exit(0);
}
close(fr[1]);
close(fw[0]);
if(fork())
{
long szz;
close(fw[1]);
if(square)
{
B *tmp;
long width=markk->xcol-markb->xcol;
long height;
int usetabs=ptabrect(markb,markk->line-markb->line+1,markk->xcol);
tmp=bread(fr[0],MAXLONG);
if(piscol(tmp->eof)) height=tmp->eof->line+1;
else height=tmp->eof->line;
if(bw->o.overtype)
{
pclrrect(markb,markk->line-markb->line+1,markk->xcol,usetabs);
pdelrect(markb,Lmax(height,markk->line-markb->line+1),width+markb->xcol);
}
else pdelrect(markb,markk->line-markb->line+1,markk->xcol);
pinsrect(markb,tmp,width,usetabs);
pdupown(markb,&markk);
markk->xcol=markb->xcol;
if(height)
{
pline(markk,markk->line+height-1);
pcol(markk,markb->xcol+width); markk->xcol=markb->xcol+width;
}
if(lightoff) unmark(bw);
brm(tmp);
updall();
}
else
{
bdel(markb,markk);
szz=markk->b->eof->byte;
binsb(markk,bread(fr[0],MAXLONG));
pfwrd(markk,markk->b->eof->byte-szz);
if(lightoff) unmark(bw);
}
close(fr[0]);
wait(0);
wait(0);
}
else
{
if(square)
{
B *tmp=pextrect(markb,markk->line-markb->line+1,markk->xcol);
bsavefd(tmp->bof,fw[1],tmp->eof->byte);
}
else bsavefd(markb,fw[1],markk->byte-markb->byte);
close(fw[1]);
_exit(0);
}
vsrm(s);
ttopnn();
if(filtflg) umarkb(bw), umarkk(bw);
bw->cursor->xcol=piscol(bw->cursor);
return 0;
}
static B *filthist=0;
void markall(bw)
BW *bw;
{
pdupown(bw->cursor->b->bof,&markb); markb->xcol=0;
pdupown(bw->cursor->b->eof,&markk); markk->xcol=piscol(markk);
updall();
}
int checkmark(bw)
BW *bw;
{
if(!markv(1))
if(square) return 2;
else
{
markall(bw), filtflg=1;
return 1;
}
else
{
filtflg=0;
return 0;
}
}
int ufilt(bw)
BW *bw;
{
#ifdef __MSDOS__
msgnw(bw,"Sorry, no sub-processes in DOS (yet)");
return -1;
#else
switch(checkmark(bw))
{
case 0:
if(wmkpw(bw,
"Command to filter block through (^C to abort): ",
&filthist,dofilt,NULL,NULL,utypebw,NULL,NULL)) return 0;
else return -1;
case 1:
if(wmkpw(bw,
"Command to filter file through (^C to abort): ",
&filthist,dofilt,NULL,NULL,utypebw,NULL,NULL)) return 0;
else return -1;
case 2:
msgnw(bw,"No block");
return -1;
}
#endif
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.