#include "ded.h" #include "range.h" char BAD_RANGE[] = "range must be letter, ., ^, $ or *"; char EMP_RANGE[] = "!! no such range !!"; /************************************************************************ * * * copyright Richard Bornat 1981 * * * ************************************************************************/ /* make sure that each line has only one mark */ val_range(a) char a; { register int c; register int bra,era; /* erase any range which includes the beginning or the end of * the new range or is included within it */ a -= 'a'; bra = b_range[a]; era=e_range[a]; for (c = 0; c < NLETTS; c++) if (c != a && e_range[c]>=bra && era>=b_range[c]) b_range[c] = e_range[c] = -1; } shift_range(str, moving) char *str; int moving; { int begin, end, destination; int after; int size; char c1,c2; char afterc; str = get_range(str, &c1, &begin, &end); str = get_pos(str, &c2, &destination, &afterc); /* destination is the line which text must appear BEFORE * in the file. */ if (afterc=='-') after = false; else { after = true; destination++; } /* default */ if (*str!=0) fdiag("!! only two arguments allowed !!"); else if (begin>end) fdiag("!! invalid source range (%d to %d)", begin+1, end+1); else if ( beginend) /* begin stays the same (next line of source moves down one) * end moves down one * destination stays same (first line of destination moves down) */ end--; else /* (destination is before begin) * begin moves up one (next line of source moves down) * destination moves up one * end stays the same */ { destination++; begin++; } } else { copyline(begin, destination); if (destination>end) /* begin moves up one, to next line of source * end stays the same * destination moves up one */ { begin++; destination++; } else /* (destination is before begin) * destination moves up one * begin moves up two (destination has pushed it) * end moves up one */ { destination++; begin += 2; end++; } } /* make sure ranges don't do anything silly */ if (moving) { if (alpha(c1)) val_range(c1); else if (alpha(c2)) val_range(c2); } /* if the line was moved after, display start of range! */ topl = enclose_range(destination-size-1, destination, after); adj_maxl(); refreshscreen(); disp_range(destination-size-1, destination, after, true); } /* alter a range which has this line as first or last member */ clip_range(fline) register int fline; { register int i; for (i=0; i='a' && rc<='z') { rc -= 'a'; if (b_range[rc] == -1 || e_range[rc]>maxl || b_range[rc]>e_range[rc]) *a_first = *a_second= -1; else { *a_first = b_range[rc]; *a_second = e_range[rc]; } } else if (rc=='.') *a_first = *a_second = topl+in_c.row; else if (rc=='^') *a_first = *a_second = 0; else if (rc=='$') *a_first = *a_second = maxl; else if (rc=='*') { *a_first=0; *a_second = maxl; } else *a_first = *a_second = -2; } /* show ranges on the screen */ show_range() { savescreen(); refreshscreen(); } /* display size of range */ tell_range(c) register char c; { int first, second; tran_range(c, &first, &second); tdiag(first==-1 ? EMP_RANGE : first==-2 ? BAD_RANGE : first==second? "line %d" : "lines %d to %d", first+1, second+1); } /* read a single range character argument */ char one_letter(str) char *str; { register char c = lcase(*str); if (c==0 || c<'a' || c>'z' || str[1] != 0) tdiag("!! single letter required !!"); return(c); } /* show a range on the screen */ disp_range(begin, end, before, saveit) int begin, end; int before, saveit; { int newtop; newtop = enclose_range(begin, end, before); set_topl(newtop, saveit); i_mode((before ? begin-topl: end-topl), MARGIN); } int enclose_range(begin, end, before) int begin, end, before; { register int size, res; if ((size = end-begin+1) <= NINROWS) res = (begintopl+LASTINROW-2 ? begin-(NINROWS-size)/2 : topl); else if (before) res = (begintopl+NINROWS/2 ? begin-NINROWS/2 : topl); else res = (endtopl+LASTINROW-2 ? end-NINROWS/2 : topl); return(res<0 ? 0 : res+LASTINROW>=maxl ? maxl-(LASTINROW) : res); }