/* BEGIN DOCUMENTATION Name: TCMEDFUNC.C Created: 08/02/83 DTS Last Update: 05/15/84 Title: Text collection management editing functions. Index: Abstract: Implements keypad functions of TCM system. All functions have same basic format. Usage: coutptr = func(cinptr); Parameters: cinptr - pointer to current character in fixed line buffer. coutptr - pointer to new current character after function applied. Note: Many routines use and change global editing parameters defined in TCMPUBLIC.H. Environment: DECUS C, RSX11M V4.0 See Also: TCM.C, TCMTABLES.C, TCMEDIT.C, TCM.DOC Description: Example(s): Uses: Internal: Update History: END DOCUMENTATION */ #include #include #include #include "tcmerr.h" #include "tcmdefs.h" #include "tcmpublic.h" /* externals not in tcmpublic */ extern padlin(); extern nxtchr(); extern lstchr(); /* forward references */ extern charpointer csdown(); extern charpointer bottom(); extern charpointer inewln(); /*** Null editing function to ignore undefined key press ***/ charpointer nulfun(chr) charpointer chr; { return(chr); } /* end nulfun */ /*** Null editing function to ignore user special key press ***/ charpointer invfun(chr) charpointer chr; { tcmerr(TS_UKY); /* Undefined Key (for user) */ return(chr); } /* end invfun */ /*** Exit editing function forward ***/ charpointer xitfwd(chr) charpointer chr; { ret.cd = TS_XFR; eddone = true; return(chr); } /* end xitfwd */ /*** Exit editing function backwards ***/ charpointer xitbkd(chr) charpointer chr; { ret.cd = TS_XBK; eddone = true; return(chr); } /* end xitbkd */ /*** Cancel editing function to ignore entry ***/ charpointer canfun(chr) charpointer chr; { ret.cd = TS_ABO; eddone = true; return(chr); } /* end canfun */ /*** Invalid key press (ENTER) ***/ charpointer entfun(chr) charpointer chr; { tcmerr(TS_ENT); return(chr); } /* end entfun */ /*** Toggle insert/replace mode ***/ charpointer instgl(chr) register charpointer chr; { iff rdonly then { tcmerr(TS_IKY); return(chr); } insert = !insert; iff lin[vtlin].fircol == nochg then lin[vtlin].fircol = changed; /* Mark status line as changed */ return(chr); } /* end instgl */ /*** Carriage return function ***/ charpointer retfun(chr) register charpointer chr; { iff rdonly then { bufcol = 1; return(csdown(line)); } iff (bufline == curwin->botline) or insert then { iff !insert then chr = &line[lin[0].len - 1]; /* Point to end of text */ chr = inewln(chr); iff ret.cd != TS_SUC then return(chr); /* Exit if error */ } savlin(curwin); bufline++; bufcol = 1; iff curline < bot then curwin->edline = lin[++curline].start; else { scrlup(); curwin->topline++; curwin->edline = lin[curline].start + lin[curline].len; /* Next line in buffer */ } return(getlin(curwin->edline)); } /* end retfun */ /*** Move cursor up ***/ charpointer csup(chr) register charpointer chr; { iff bufline > 1 then { savlin(curwin); iff curline > top then chr = lin[--curline].start; else { curwin->topline--; inslin(); chr = fndlast(curwin->edline,curwin->bufstart); } bufline--; chr = getlin(curwin->edline = chr); } else tcmerr(TS_BPS); return(chr); } /* end csup */ /*** Move cursor down ***/ charpointer csdown(chr) register charpointer chr; { iff bufline < curwin->botline then { savlin(curwin); curwin->edline = lin[curline].start + lin[curline].len; /* Assumes contiguous buffer */ iff curline < bot then curline++; else { scrlup(); curwin->topline++; } bufline++; chr = getlin(curwin->edline); } else tcmerr(TS_APE); return(chr); } /* end csdown */ /*** Move cursor left ***/ charpointer csleft(chr) register charpointer chr; { iff bufcol > 1 then { bufcol--; chr = lstchr(chr); } /* Backup on this line (chr--) */ else iff bufline == 1 then tcmerr(TS_BPS); /* Error: backup past start */ else { savlin(curwin); iff curline > top then /* Move cursor up line */ { curline--; chr = lin[curline].start; } else { chr = fndlast(curwin->edline,curwin->bufstart); /* backup line */ inslin(); /* Insert line on screen */ curwin->topline--; } bufcol = virlen(chr)+1; /* Cursor at end of previous line */ bufline--; curwin->edline = chr; chr = getlin(chr); } return(chr); } /* end csleft */ /*** Move cursor right ***/ charpointer csright(chr) register charpointer chr; { iff bufcol < curwin->width then { bufcol++; chr = nxtchr(chr); /* Advance to next character */ } else { iff bufline < curwin->botline then /* Error if at end */ bufcol = 1; chr = csdown(chr); /* Advance to start of next line */ } return(chr); } /* end csright */ /*** Cursor to top of window ***/ charpointer topscr(chr) register charpointer chr; { savlin(curwin); curwin->edline = lin[top].start; bufline -= (curline - top); curline = top; return(getlin(curwin->edline)); } /* end topscr */ /*** Cursor to bottom of window ***/ charpointer botscr(chr) register charpointer chr; { register int oldcol; oldcol = bufcol; iff curwin->topline + curwin->height - 1 > curwin->botline then chr = bottom(chr); while ((curwin->topline + curwin->height - 1 > curwin->botline) and (ret.cd == TS_SUC)) chr = inewln(chr); /* Extend buffer */ bufline = curwin->topline + curwin->height - 1; savlin(curwin); iff bufline > curwin->botline then { curline = bot - (bufline - curwin->botline); bufline = curwin->botline; } else curline = bot; bufcol = oldcol; curwin->edline = lin[curline].start; return(getlin(curwin->edline)); } /* end botscr */ /*** Cursor to start of line ***/ charpointer beglin(chr) register charpointer chr; { bufcol = 1; return(line); } /* end beglin */ /*** Cursor to right side of window ***/ charpointer endlin(chr) register charpointer chr; { bufcol = curwin->width; line[lin[0].len] = eos; return(virchr(line,bufcol)); } /* end endlin */ /*** Backup Cursor one line ***/ charpointer backln(chr) register charpointer chr; { iff bufcol > 1 then { bufcol = 1; return(line); } else return(csup(chr)); } /* end backln */ /*** Scroll screen down page (backup cursor) ***/ charpointer pgbac(chr) register charpointer chr; { register int i; iff curline > top then chr = topscr(chr); else iff bufline <= 1 then tcmerr(TS_BPS); for (i = 0; (i < curwin->scroll) and (bufline > 1); i++) chr = csup(chr); return(chr); } /* end pgbac */ /*** Scroll screen up page (advance cursor) ***/ charpointer pgfor(chr) register charpointer chr; { register int i; iff curline < bot then chr = botscr(chr); else iff bufline >= curwin->botline then tcmerr(TS_APE); for (i = 0; (i < curwin->scroll) and (bufline < curwin->botline); i++) chr = csdown(chr); return(chr); } /* end pgfor */ /*** Go to top of text ***/ charpointer toptxt(chr) register charpointer chr; { register int oldtop; oldtop = curwin->topline; savlin(curwin); curwin->edline = curwin->bufstart; curwin->topline = curwin->column = bufline = 1; curline = top; bufcol = 1; iff oldtop != 1 then setout(curwin); return(getlin(curwin->edline)); } /* end toptxt */ /*** Go to bottom (end) of text ***/ charpointer bottom(chr) register charpointer chr; { register int i,oldtop; oldtop = curwin->topline; savlin(curwin); /* curwin->edline = fndlin(curwin->edline,curwin->bufend,(curwin->botline - curline) + 1); */ curwin->edline = fndlin(curwin->bufstart,curwin->bufend,curwin->botline); curwin->topline = ifx (i = curwin->botline - curwin->height) > 0 thenx (i+1) elsex 1; bufline = curwin->botline; curline = ifx i < 0 thenx bot + i elsex bot; /* Bottom of window unless .height > .botline */ bufcol = curwin->column = virlen(curwin->edline) + 1; iff oldtop != curwin->topline then setout(curwin); return(getlin(curwin->edline)); } /* end bottom */ /*** Delete character to left of cursor ***/ charpointer deleft(chr) register charpointer chr; { register charpointer str,linend; iff rdonly then { tcmerr(TS_IKY); return(chr); } iff bufcol > 1 then { str = &line[lin[0].len]; *str = eos; bufcol--; /* Move cursor left */ iff chr-- < str then /* Within line */ /* iff insert or (chr+2 == str) then * Close this line */ { movedn(chr+1,chr,(str-chr)+1); subchr(); rfline(bufcol,chr-line,lin[0].len+2); } } else iff bufline == 1 then tcmerr(TS_BPS); /* Error: backup past start */ else { /* Delete end of line character & join lines */ savlin(curwin); iff ((curline == top) and (bot > top)) /* or * scroll down to close * ((curwin->botline <= curwin->topline + curwin->height) and (curwin->topline > 1)) */ then { inslin(); /* scroll top of screen down */ curwin->topline--; curline++; } chr = fndlast(curwin->edline,curwin->bufstart); bufcol = virlen(chr)+2; /* Cursor at end of previous line */ /* Assumes contiguous buffer */ *(curwin->edline-1) = ' '; /* Join current line with previous */ iff virlen(chr) > curwin->width then { for(str = linend = virchr(chr,curwin->width+1); str >= curwin->edline; ) iff *(--str) == ' ' then break; iff str < curwin->edline then { movedn(str+1,str,linend-str); /* Close over added space */ str = linend; bufcol--; } *str = eos; /* Break line at last space or break word */ lin[curline].start = ++str; lin[curline].len = strlen(str) + 1; lin[curline].fircol = newlin; } else { iff (bufcol <= 2) and (curline > top) then /* Test added for hard scroll */ dellin(curline-1); else dellin(curline); /* Delete line on screen (scroll others up) */ sublin(); /* Adjust max counters */ } bufline--; iff curline > top then curline--; curwin->edline = chr; chr = getlin(chr); } return(chr); } /* end deleft */ /*** FMS Stype Delete character left ***/ charpointer dechlf(chr) register charpointer chr; { iff insert or ((chr-line)+1 >= lin[0].len) then /* or end of line */ chr = deleft(chr); else chr = csleft(chr); /* * Replace mode: change char to space * { *chr = ' '; rfline(bufcol,chr-line,chr-line); } */ return(chr); } /* end dechlf */ /*** Delete character right ***/ charpointer dechrt(chr) register charpointer chr; { register int oldcol; iff rdonly then { tcmerr(TS_IKY); return(chr); } oldcol = bufcol; iff (chr-line)+1 >= lin[0].len then /* IF End of line */ { padlin(chr); /* Pad with spaces (see tcmedit) */ iff (*(chr-1) == ' ') and (bufline < curwin->botline) then *(chr-1) = '\r'; /* Mark end of line */ bufcol = 1; chr = csdown(line); iff ret.cd == TS_SUC then { chr = deleft(chr); /* THEN Join with next line */ iff (ret.cd == TS_SUC) and (lin[0].len < curwin->width+1) then chr = deleft(chr); /* Delete added space */ iff *(chr-1) == '\r' then *(chr-1) = ' '; while (oldcol < bufcol) chr = csleft(chr); } else { chr = virchr(line,oldcol); bufcol = oldcol; } } else { chr = csright(chr); /* ELSE Cursor Right */ iff ret.cd == TS_SUC then chr = deleft(chr); /* Delete character left */ else bufcol = oldcol; } return(chr); } /* end dechrt */ /*** Insert line break at current cursor position ***/ /*** Note: Assumes contiguous text buffer (see TCMBUF) ***/ charpointer inewln(chr) register charpointer chr; { register int newlen,nxtlin; register char *lasthalf; iff rdonly then { tcmerr(TS_IKY); return(chr); } iff ! addchr() then /* Add one to current line length */ return(chr); iff ! addlin() then /* Add line to buffer length */ { subchr(); return(chr); /* Buffer full */ } newlen = chr - line; line[lin[0].len - 2] = 'x'; /* Overwrite end of old line */ iff newlen < lin[0].len - 1 then moveup(chr,chr+1,lin[0].len - newlen); /* Make room for line break */ else newlen = lin[0].len - 2; savlin(curwin); *chr = eos; /* Mark end of new line (redundant?) */ lasthalf = curwin->edline + newlen; *lasthalf++ = eos; /* Mark end of new current line */ inslin(); /* Roll lines down on screen */ iff curline < bot then /* Update next line to current */ { nxtlin = curline + 1; lin[nxtlin].start = lasthalf; lin[nxtlin].len = strlen(lasthalf) + 1; lin[nxtlin].fircol = newlin; } return(getlin(curwin->edline)); } /* end inewln */