home *** CD-ROM | disk | FTP | other *** search
- /* edit.c -- Editing buffers
- Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- This file is part of Jade.
-
- Jade 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 2, or (at your option)
- any later version.
-
- Jade 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 Jade; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "jade.h"
- #include "jade_protos.h"
-
- #include <string.h>
- #include <ctype.h>
-
- _PR bool clearlinelist(TX *);
- _PR void killlinelist(TX *);
- _PR LINE *resizelinelist(TX *, long, long);
- _PR bool insertgap(TX *, long, const POS *);
- _PR bool insertstr(TX *, const u_char *, POS *);
- _PR bool insertstrn(TX *, const u_char *, long, POS *);
- _PR bool insertstring(TX *, const u_char *, long, POS *);
- _PR bool rectinsertstring(TX *, const u_char *, POS *);
- _PR bool deletechars(TX *, const POS *, long);
- _PR bool deletelines(TX *, long, long);
- _PR bool deletesection(TX *, POS *, POS *);
- _PR bool rectdeletesection(TX *, POS *, POS *);
- _PR bool splitline(TX *, POS *);
- static bool joinlines(TX *, POS *);
- _PR bool padpos(TX *, POS *);
- _PR bool padcursor(VW *);
- _PR void orderpos(POS *, POS *);
- _PR void orderrect(POS *, POS *, POS *, POS *);
- _PR bool checksect(TX *, POS *, POS *);
- _PR void checkpos(TX *, POS *);
- _PR bool checkline(TX *, POS *);
- _PR long sectionlength(TX *, POS *, POS *);
- _PR void copysection(TX *, POS *, POS *, u_char *);
- _PR long rectsectionlength(TX *, POS *, POS *);
- _PR void rectcopysection(TX *, POS *, POS *, u_char *);
- _PR bool colcopysect(TX *, long *, u_char *, long);
- _PR bool posinblock(VW *, long, long);
- _PR bool cursinblock(VW *);
- _PR bool pageinblock(VW *);
- _PR short lineinblock(VW *, long);
- _PR void orderblock(VW *);
- _PR void setblockrefresh(VW *);
- _PR bool readonly(TX *);
-
- #define ALLOCLL(n) mymalloc(sizeof(LINE) * (n))
- #define FREELL(l) myfree(l)
-
- /*
- * This copies a line list (or part of one).
- * d = destination
- * s = source
- * n = number of LINE's to copy.
- */
- #define MOVLL(d,s,n) memcpy((d), (s), (n) * sizeof(LINE))
- /*
- * void
- * MOVLL(LINE *dst, LINE *src, long number)
- * {
- * memcpy(dst, src, number * sizeof(LINE));
- * }
- */
-
- /*
- * Makes file empty (null string in first line)
- */
- bool
- clearlinelist(TX *tx)
- {
- if(tx->tx_Lines)
- killlinelist(tx);
- tx->tx_Lines = ALLOCLL(1);
- if(tx->tx_Lines)
- {
- tx->tx_Lines[0].ln_Line = mystrdupn("", 0);
- if(tx->tx_Lines[0].ln_Line)
- tx->tx_Lines[0].ln_Strlen = 1;
- else
- tx->tx_Lines[0].ln_Strlen = 0;
- tx->tx_NumLines = 1;
- return(TRUE);
- }
- return(FALSE);
- }
-
- /*
- * deallocates all lines and their list
- */
- void
- killlinelist(TX *tx)
- {
- if(tx->tx_Lines)
- {
- LINE *line;
- long i;
- for(i = 0, line = tx->tx_Lines; i < tx->tx_NumLines; i++, line++)
- {
- if(line->ln_Strlen)
- mystrfree(line->ln_Line);
- }
- FREELL(tx->tx_Lines);
- tx->tx_Lines = NULL;
- tx->tx_NumLines = 0;
- }
- }
-
- /*
- * deallocates some lines (but not the list)
- */
- static void
- killsomelines(TX *tx, long start, long number)
- {
- LINE *line = tx->tx_Lines + start;
- long i;
- for(i = 0; i < number; i++, line++)
- {
- if(line->ln_Strlen)
- {
- mystrfree(line->ln_Line);
- line->ln_Strlen = 0;
- line->ln_Line = NULL;
- }
- }
- }
-
- /*
- * Creates blank entries or removes existing lines starting from line 'where'
- * 'change' is the number of lines to insert, negative numbers mean delete
- * that number of lines starting at the cursor line.
- * If lines are deleted the actual text is also deleted.
- * NOTE: You can't have a line list of zero lines.
- */
- LINE *
- resizelinelist(TX *tx, long change, long where)
- {
- LINE *newlines;
- long newsize = tx->tx_NumLines + change;
- if((newsize > 0) && (newlines = ALLOCLL(newsize)))
- {
- if(tx->tx_Lines)
- {
- if(change > 0)
- {
- MOVLL(newlines, tx->tx_Lines, where);
- MOVLL(newlines + where + change, tx->tx_Lines + where, tx->tx_NumLines - where);
- }
- else
- {
- MOVLL(newlines, tx->tx_Lines, where);
- MOVLL(newlines + where, tx->tx_Lines + where - change, tx->tx_NumLines - where + change);
- killsomelines(tx, where, -change);
- }
- FREELL(tx->tx_Lines);
- }
- if(change > 0)
- bzero(newlines + where, change * sizeof(LINE));
- tx->tx_Lines = newlines;
- tx->tx_NumLines = newsize;
- return(newlines);
- }
- return(FALSE);
- }
-
- #if 0
- /*
- * Pastes a line into the current view at line num.
- * a LINE should have been made if it is wanted.
- * text is not copied, it should have been mymalloc()'ed (or savestring()'ed)
- */
- bool
- stuffline(TX *tx, u_char *text, long lineNum)
- {
- LINE *line = tx->tx_Lines + lineNum;
- if(line->ln_Strlen)
- mystrfree(line->ln_Line);
- line->ln_Strlen = strlen(text) + 1;
- line->ln_Line = text;
- return(TRUE);
- }
- #endif
-
- /*
- * Inserts some `space' at pos. The gap will be filled with random garbage.
- * pos is *not* altered.
- */
- bool
- insertgap(TX *tx, long len, const POS *pos)
- {
- LINE *line = tx->tx_Lines + pos->pos_Line;
- u_char *newline = mystralloc(len + line->ln_Strlen);
- if(newline)
- {
- if(line->ln_Strlen)
- {
- memcpy(newline, line->ln_Line, pos->pos_Col);
- strcpy(newline + pos->pos_Col + len, line->ln_Line + pos->pos_Col);
- mystrfree(line->ln_Line);
- }
- else
- newline[len] = 0;
- line->ln_Line = newline;
- line->ln_Strlen += len;
- keepposaddx(tx, len, pos->pos_Col, pos->pos_Line);
- return(TRUE);
- }
- return(FALSE);
- }
-
- /*
- * Inserts a string into the current line at the cursor pos
- *
- * IMPORTANT: For any of the next functions which insert text the pos
- * argument must not be one which will be fiddled with by the keeppos*()
- * functions (specifically a direct pointer to vw_CursorPos).
- */
- bool
- insertstr(TX *tx, const u_char *text, POS *pos)
- {
- return(insertstrn(tx, text, strlen(text), pos));
- }
-
- bool
- insertstrn(TX *tx, const u_char *text, long textLen, POS *pos)
- {
- LINE *line = tx->tx_Lines + pos->pos_Line;
- if(insertgap(tx, textLen, pos))
- {
- memcpy(line->ln_Line + pos->pos_Col, text, textLen);
- pos->pos_Col += textLen;
- return(TRUE);
- }
- return(FALSE);
- }
-
- /*
- * Inserts a null teminated string, this routine acts on any '\n' or '\t'
- * characters that it finds.
- * I expect that this routine will be incredibly slow.
- */
- bool
- insertstring(TX *tx, const u_char *text, long tabSize, POS *pos)
- {
- #define INSERT_BUF_LEN 128
- u_char *buff = mystralloc(INSERT_BUF_LEN);
- if(buff)
- {
- const u_char *str = text;
- POS orig = *pos;
- while(*str)
- {
- u_char c;
- long i = 0;
- long startx = pos->pos_Col;
- while((c = *str++) && (c != '\n') && (i < INSERT_BUF_LEN))
- {
- if(c == '\t')
- {
- int numspc = tabSize - ((i + startx) % tabSize);
- memset(buff + i, ' ', numspc);
- i += numspc;
- }
- else
- buff[i++] = c;
- }
- buff[i] = 0;
- if(c == '\n')
- {
- if(pos->pos_Col)
- {
- if(!insertstrn(tx, buff, i, pos))
- goto abort;
- if(!splitline(tx, pos))
- goto abort;
- pos->pos_Col = 0;
- }
- else
- {
- u_char *copy;
- if(!resizelinelist(tx, +1, pos->pos_Line))
- goto abort;
- if(!(copy = mystrdupn(buff, i)))
- goto abort;
- tx->tx_Lines[pos->pos_Line].ln_Strlen = i + 1;
- tx->tx_Lines[pos->pos_Line].ln_Line = copy;
- keepposaddy(tx, +1, pos->pos_Line);
- }
- pos->pos_Line++;
- startx = 0;
- }
- else
- {
- str--;
- if(!insertstrn(tx, buff, i, pos))
- {
- abort:
- settitle(NoMemMsg);
- mystrfree(buff);
- return(FALSE);
- }
- }
- }
- flaginsertion(tx, &orig, pos);
- mystrfree(buff);
- return(TRUE);
- }
- settitle(NoMemMsg);
- return(FALSE);
- }
-
- /*
- */
- bool
- rectinsertstring(TX *tx, const u_char *text, POS *pos)
- {
- long col = pos->pos_Col;
- LINE *line = tx->tx_Lines + pos->pos_Line;
- long llen = 0;
- POS orig;
- while(*text && (pos->pos_Line < tx->tx_NumLines))
- {
- const u_char *tmp = text;
- while(*tmp && (*tmp != '\n'))
- tmp++;
- llen = tmp - text;
- if(!padpos(tx, pos))
- goto nomem;
- orig = *pos;
- if(!insertstrn(tx, text, llen, pos))
- goto nomem;
- flaginsertion(tx, &orig, pos);
- pos->pos_Line++;
- pos->pos_Col = col;
- line++;
- if(*(text = tmp))
- text++;
- }
- if(*text && pos->pos_Line == tx->tx_NumLines)
- {
- /*
- * Now start expanding off the bottom of the file.
- */
- orig = *pos;
- while(*text)
- {
- const u_char *tmp = text;
- u_char *new;
- while(*tmp && (*tmp != '\n'))
- tmp++;
- llen = tmp - text;
- if(!resizelinelist(tx, +1, pos->pos_Line))
- goto nomem;
- if(!(new = mystralloc(col + llen + 1)))
- goto nomem;
- memset(new, ' ', col);
- memcpy(new + col, text, llen);
- new[col + llen] = 0;
- tx->tx_Lines[pos->pos_Line].ln_Strlen = col + llen + 1;
- tx->tx_Lines[pos->pos_Line].ln_Line = new;
- keepposaddy(tx, +1, pos->pos_Line);
- pos->pos_Line++;
- /*
- * Possible need for keepposaddx() here, my theory is
- * that since i've just created a new line nothing
- * will point to it???
- */
- line++;
- if(*(text = tmp))
- text++;
- }
- if(llen > 0)
- pos->pos_Col += llen;
- pos->pos_Line--;
- flaginsertion(tx, &orig, pos);
- }
- return(TRUE);
- nomem:
- settitle(NoMemMsg);
- return(FALSE);
- }
-
- /*
- * Deletes some text (this line only)
- */
- bool
- deletechars(TX *tx, const POS *pos, long size)
- {
- LINE *line = tx->tx_Lines + pos->pos_Line;
- if(line->ln_Strlen)
- {
- u_char *newline;
- if(size >= line->ln_Strlen)
- size = line->ln_Strlen - 1;
- newline = mystralloc(line->ln_Strlen - size);
- if(newline)
- {
- strncpy(newline, line->ln_Line, pos->pos_Col);
- strcpy(newline + pos->pos_Col, line->ln_Line + pos->pos_Col + size);
- mystrfree(line->ln_Line);
- line->ln_Strlen -= size;
- line->ln_Line = newline;
- keeppossubx(tx, size, pos->pos_Col, pos->pos_Line);
- return(TRUE);
- }
- return(FALSE);
- }
- return(TRUE);
- }
-
- /*
- * deletes some lines
- */
- bool
- deletelines(TX *tx, long linenum, long size)
- {
- bool rc = FALSE;
- if(resizelinelist(tx, -size, linenum))
- rc = TRUE;
- keeppossuby(tx, size, linenum);
- return(rc);
- }
-
- /*
- * Deletes from startPos to endPos
- */
- bool
- deletesection(TX *tx, POS *startPos, POS *endPos)
- {
- if(endPos->pos_Line == startPos->pos_Line)
- {
- deletechars(tx, startPos, endPos->pos_Col - startPos->pos_Col);
- flagdeletion(tx, startPos, endPos);
- }
- else
- {
- long middle;
- bool joinflag = FALSE;
- POS orig = *startPos, oend = *endPos;
- if(startPos->pos_Col)
- {
- long start = tx->tx_Lines[startPos->pos_Line].ln_Strlen - startPos->pos_Col - 1;
- if(start)
- deletechars(tx, startPos, start);
- startPos->pos_Col = 0;
- startPos->pos_Line++;
- joinflag = TRUE;
- }
- middle = endPos->pos_Line - startPos->pos_Line;
- if(middle != 0)
- {
- deletelines(tx, startPos->pos_Line, middle);
- endPos->pos_Line -= middle;
- }
- if(endPos->pos_Col)
- deletechars(tx, startPos, endPos->pos_Col);
- if(joinflag && startPos->pos_Line)
- {
- startPos->pos_Line--;
- startPos->pos_Col = tx->tx_Lines[startPos->pos_Line].ln_Strlen - 1;
- joinlines(tx, startPos);
- }
- flagdeletion(tx, &orig, &oend);
- }
- return(TRUE);
- }
-
- bool
- rectdeletesection(TX *tx, POS *startPos, POS *endPos)
- {
- LINE *line = tx->tx_Lines + startPos->pos_Line;
- while(startPos->pos_Line <= endPos->pos_Line)
- {
- if(line->ln_Strlen > startPos->pos_Col)
- {
- long dlen;
- POS tmp;
- if(line->ln_Strlen > endPos->pos_Col)
- dlen = (endPos->pos_Col - startPos->pos_Col) + 1;
- else
- dlen = line->ln_Strlen - 1 - startPos->pos_Col;
- if(!deletechars(tx, startPos, dlen))
- {
- settitle(NoMemMsg);
- return(FALSE);
- }
- tmp.pos_Line = startPos->pos_Line;
- tmp.pos_Col = startPos->pos_Col + dlen;
- flagdeletion(tx, startPos, &tmp);
- }
- startPos->pos_Line++;
- line++;
- }
- return(TRUE);
- }
-
- /*
- * splits the line into two
- */
- bool
- splitline(TX *tx, POS *pos)
- {
- if(resizelinelist(tx, +1, pos->pos_Line + 1))
- {
- LINE *line = tx->tx_Lines + pos->pos_Line;
- u_char *newline1 = mystrdupn(line->ln_Line, pos->pos_Col);
- if(newline1)
- {
- long nl2len = line->ln_Strlen - pos->pos_Col;
- u_char *newline2 = mystrdupn(line->ln_Line + pos->pos_Col,
- nl2len - 1);
- if(newline2)
- {
- if(line[0].ln_Line)
- mystrfree(line[0].ln_Line);
- line[0].ln_Strlen = pos->pos_Col + 1;
- line[0].ln_Line = newline1;
- if(line[1].ln_Line)
- mystrfree(line[1].ln_Line);
- line[1].ln_Strlen = nl2len;
- line[1].ln_Line = newline2;
- keeppossplity(tx, pos->pos_Col, pos->pos_Line);
- return(TRUE);
- }
- mystrfree(newline1);
- }
- }
- settitle(NoMemMsg);
- return(FALSE);
- }
-
- /*
- * joins the current line to the line below it.
- */
- static bool
- joinlines(TX *tx, POS *pos)
- {
- if((pos->pos_Line + 1) < tx->tx_NumLines)
- {
- LINE *line1 = tx->tx_Lines + pos->pos_Line;
- LINE *line2 = line1 + 1;
- int newlen = line1->ln_Strlen + line2->ln_Strlen - 1;
- u_char *newstr = mystralloc(newlen);
- if(newstr)
- {
- stpcpy(stpcpy(newstr, line1->ln_Line), line2->ln_Line);
- resizelinelist(tx, -1, pos->pos_Line);
- line1 = tx->tx_Lines + pos->pos_Line;
- if(line1->ln_Line)
- mystrfree(line1->ln_Line);
- line1->ln_Strlen = newlen;
- line1->ln_Line = newstr;
- keepposjoiny(tx, pos->pos_Col, pos->pos_Line);
- return(TRUE);
- }
- settitle(NoMemMsg);
- }
- return(FALSE);
- }
-
- /*
- * Inserts spaces from end of line to pos
- */
- bool
- padpos(TX *tx, POS *pos)
- {
- if(pos->pos_Line < tx->tx_NumLines)
- {
- LINE *line = tx->tx_Lines + pos->pos_Line;
- if(line->ln_Strlen < (pos->pos_Col + 1))
- {
- u_char *newline = mystralloc(pos->pos_Col + 1);
- if(newline)
- {
- long i;
- strcpy(newline, line->ln_Line);
- for(i = line->ln_Strlen - 1; i < pos->pos_Col; i++)
- newline[i] = ' ';
- newline[i] = 0;
- if(line->ln_Line)
- mystrfree(line->ln_Line);
- line->ln_Strlen = pos->pos_Col + 1;
- line->ln_Line = newline;
- return(TRUE);
- }
- settitle(NoMemMsg);
- pos->pos_Col = line->ln_Strlen - 1;
- return(FALSE);
- }
- return(TRUE);
- }
- return(FALSE);
- }
-
- bool
- padcursor(VW *vw)
- {
- return(padpos(vw->vw_Tx, &vw->vw_CursorPos));
- }
-
- /*
- * if end is before start then swap the two
- */
- void
- orderpos(POS *start, POS *end)
- {
- if(((start->pos_Line == end->pos_Line) && (start->pos_Col > end->pos_Col))
- || (start->pos_Line > end->pos_Line))
- {
- POS temp;
- temp = *start;
- *start = *end;
- *end = temp;
- }
- }
-
- /*
- * makes sure that the corners of a rectangle are how I want them
- */
- void
- orderrect(POS *dstart, POS *dend, POS *sstart, POS *send)
- {
- if(sstart->pos_Col < send->pos_Col)
- {
- dstart->pos_Col = sstart->pos_Col;
- dend->pos_Col = send->pos_Col;
- }
- else
- {
- dstart->pos_Col = send->pos_Col;
- dend->pos_Col = sstart->pos_Col;
- }
- if(sstart->pos_Line < send->pos_Line)
- {
- dstart->pos_Line = sstart->pos_Line;
- dend->pos_Line = send->pos_Line;
- }
- else
- {
- dstart->pos_Line = send->pos_Line;
- dend->pos_Line = sstart->pos_Line;
- }
- }
-
- bool
- checksect(TX *tx, POS *start, POS *end)
- {
- orderpos(start, end);
- if((start->pos_Line >= tx->tx_NumLines) || (end->pos_Line >= tx->tx_NumLines))
- return(FALSE);
- if(start->pos_Col >= tx->tx_Lines[start->pos_Line].ln_Strlen)
- start->pos_Col = tx->tx_Lines[start->pos_Line].ln_Strlen - 1;
- if(end->pos_Col >= tx->tx_Lines[end->pos_Line].ln_Strlen)
- end->pos_Col = tx->tx_Lines[end->pos_Line].ln_Strlen - 1;
- return(TRUE);
- }
-
- void
- checkpos(TX *tx, POS *pos)
- {
- if(pos->pos_Line >= tx->tx_NumLines)
- pos->pos_Line = tx->tx_NumLines - 1;
- if(pos->pos_Col >= tx->tx_Lines[pos->pos_Line].ln_Strlen)
- pos->pos_Col = tx->tx_Lines[pos->pos_Line].ln_Strlen - 1;
- }
-
- bool
- checkline(TX *tx, POS *pos)
- {
- if((pos->pos_Line >= tx->tx_NumLines) || (pos->pos_Col < 0))
- return(FALSE);
- return(TRUE);
- }
-
- /*
- * Returns the number of bytes needed to store a section, doesn't include
- * a zero terminator but does include all newline chars.
- */
- long
- sectionlength(TX *tx, POS *startPos, POS *endPos)
- {
- long linenum = startPos->pos_Line;
- LINE *line = tx->tx_Lines + linenum;
- long length;
- if(startPos->pos_Line == endPos->pos_Line)
- length = endPos->pos_Col - startPos->pos_Col;
- else
- {
- length = line->ln_Strlen - startPos->pos_Col;
- linenum++;
- line++;
- while(linenum < endPos->pos_Line)
- {
- length += line->ln_Strlen;
- linenum++;
- line++;
- }
- length += endPos->pos_Col;
- }
- return(length);
- }
-
- /*
- * Copies a section to a buffer.
- * end of copy does NOT have a zero appended to it.
- */
- void
- copysection(TX *tx, POS *startPos, POS *endPos, u_char *buff)
- {
- long linenum = startPos->pos_Line;
- LINE *line = tx->tx_Lines + linenum;
- long copylen;
- if(startPos->pos_Line == endPos->pos_Line)
- {
- copylen = endPos->pos_Col - startPos->pos_Col;
- memcpy(buff, line->ln_Line + startPos->pos_Col, copylen);
- buff[copylen] = 0;
- }
- else
- {
- copylen = line->ln_Strlen - startPos->pos_Col - 1;
- memcpy(buff, line->ln_Line + startPos->pos_Col, copylen);
- buff[copylen] = '\n';
- buff += copylen + 1;
- linenum++;
- line++;
- while(linenum < endPos->pos_Line)
- {
- copylen = line->ln_Strlen - 1;
- memcpy(buff, line->ln_Line, copylen);
- buff[copylen] = '\n';
- buff += copylen + 1;
- linenum++;
- line++;
- }
- memcpy(buff, line->ln_Line, endPos->pos_Col);
- }
- }
-
- /*
- * Returns the size of the rectangle (start, end). zero terminator
- * isn't included.
- */
- long
- rectsectionlength(TX *tx, POS *startPos, POS *endPos)
- {
- return(((endPos->pos_Line - startPos->pos_Line) + 1) * ((endPos->pos_Col - startPos->pos_Col) + 2));
- }
-
- /*
- * Copies a rectangle to a string, newlines are inserted between lines (and
- * after the last line) but \0 terminator is NOT.
- */
- void
- rectcopysection(TX *tx, POS *startPos, POS *endPos, u_char *buff)
- {
- long linenum = startPos->pos_Line;
- LINE *line = tx->tx_Lines + linenum;
- long width = (endPos->pos_Col - startPos->pos_Col) + 1;
- while(linenum <= endPos->pos_Line)
- {
- long copylen = (line->ln_Strlen - 1) - startPos->pos_Col;
- if(copylen <= 0)
- copylen = 0;
- else
- {
- if(copylen > width)
- copylen = width;
- memcpy(buff, line->ln_Line + startPos->pos_Col, copylen);
- }
- if(copylen < width)
- memset(buff + copylen, ' ', width - copylen);
- buff[width] = '\n';
- buff += width + 1;
- linenum++;
- line++;
- }
- }
-
- /*
- * Copies the end of each line from column codePos[0] between the cP[1] and
- * cP[2] lines (exclusively).
- */
- bool
- colcopysect(TX *tx, long *codePos, u_char *buf, long bufLen)
- {
- LINE *line;
- codePos[1]++;
- line = tx->tx_Lines + codePos[1];
- while(codePos[1] < codePos[2])
- {
- int clen = line->ln_Strlen - codePos[0];
- if((clen > 0) && (clen < bufLen))
- {
- memcpy(buf, line->ln_Line + codePos[0], clen - 1);
- buf[clen - 1] = '\n';
- buf += clen;
- bufLen -= clen;
- }
- line++;
- codePos[1]++;
- }
- *buf = 0;
- return(TRUE);
- }
-
- /*
- * returns TRUE if the specified position is inside a block
- */
- bool
- posinblock(VW *vw, long col, long line)
- {
- if((vw->vw_BlockStatus)
- || (line < vw->vw_BlockS.pos_Line)
- || (line > vw->vw_BlockE.pos_Line))
- return(FALSE);
- if(vw->vw_Flags & VWFF_RECTBLOCKS)
- {
- if(vw->vw_BlockS.pos_Col < vw->vw_BlockE.pos_Col)
- {
- if((col < vw->vw_BlockS.pos_Col) || (col > vw->vw_BlockE.pos_Col))
- return(FALSE);
- }
- else
- {
- if((col < vw->vw_BlockE.pos_Col) || (col > vw->vw_BlockS.pos_Col))
- return(FALSE);
- }
- }
- else
- {
- if(((line == vw->vw_BlockS.pos_Line) && (col < vw->vw_BlockS.pos_Col))
- || ((line == vw->vw_BlockE.pos_Line) && (col >= vw->vw_BlockE.pos_Col)))
- return(FALSE);
- }
- return(TRUE);
- }
-
- bool
- cursinblock(VW *vw)
- {
- return(posinblock(vw, vw->vw_CursorPos.pos_Col, vw->vw_CursorPos.pos_Line));
- }
-
-
- bool
- pageinblock(VW *vw)
- {
- if((vw->vw_BlockStatus)
- || ((vw->vw_BlockE.pos_Line + 1) < vw->vw_StartLine)
- || (vw->vw_BlockS.pos_Line > vw->vw_StartLine + vw->vw_MaxY))
- return(FALSE);
- return(TRUE);
- }
-
- /*
- * these returns,
- *
- * 0 line not in block
- * 1 whole line in block
- * 2 start of line in block
- * 3 end of line in block
- * 4 middle of line in block
- *
- * note:
- * this isn't very intelligent (but it works :-).
- *
- * now handles rectangular blocks (VWFF_RECTBLOCKS)
- */
- short
- lineinblock(VW *vw, long line)
- {
- bool startin = FALSE;
- bool endin = FALSE;
-
- if((vw->vw_BlockStatus)
- || (line < vw->vw_BlockS.pos_Line)
- || (line > vw->vw_BlockE.pos_Line))
- return(0);
- if(vw->vw_Flags & VWFF_RECTBLOCKS)
- {
- /*
- * ???
- */
- /*
- * if(vw->vw_BlockS.pos_Col != 0)
- * startin = TRUE;
- * if(vw->vw_BlockE.pos_Col <= vw->vw_Tx->tx_Lines[line].ln_Strlen)
- * endin = TRUE;
- */
- startin = endin = 4;
- }
- else
- {
- if(line == vw->vw_BlockE.pos_Line)
- startin = TRUE;
- if(line == vw->vw_BlockS.pos_Line)
- endin = TRUE;
- }
- if(startin)
- {
- if(endin)
- return(4);
- return(2);
- }
- if(endin)
- return(3);
- return(1);
- }
-
- /*
- * makes sure that the marked block is valid
- */
- void
- orderblock(VW *vw)
- {
- if(!vw->vw_BlockStatus)
- {
- if(vw->vw_BlockS.pos_Line > vw->vw_BlockE.pos_Line)
- {
- POS temp = vw->vw_BlockE;
- vw->vw_BlockE = vw->vw_BlockS;
- vw->vw_BlockS = temp;
- }
- else if(vw->vw_BlockS.pos_Line == vw->vw_BlockE.pos_Line)
- {
- if(vw->vw_BlockS.pos_Col > vw->vw_BlockE.pos_Col)
- {
- POS temp = vw->vw_BlockE;
- vw->vw_BlockE = vw->vw_BlockS;
- vw->vw_BlockS = temp;
- }
- }
- }
- }
-
- /*
- * Set up the refresh flags to refresh the block in the most efficient manner.
- */
- void
- setblockrefresh(VW *vw)
- {
- long endline = vw->vw_StartLine + vw->vw_MaxY;
- if((vw->vw_BlockS.pos_Line > endline)
- || (vw->vw_BlockE.pos_Line < vw->vw_StartLine))
- return;
- if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
- /*
- * If the all-powerful bit is already set I have no way of telling
- * myself to refresh two blocked areas, stupid huh? Anyway I just
- * blast in the whole window instead.
- */
- vw->vw_Flags |= VWFF_FORCE_REFRESH;
- else
- vw->vw_Flags |= VWFF_REFRESH_BLOCK;
- }
-
- bool
- readonly(TX *tx)
- {
- if(tx->tx_Flags & TXFF_RDONLY)
- {
- cmd_signal(sym_buffer_read_only, LIST_1(tx));
- return(TRUE);
- }
- else
- return(FALSE);
- }
-