allbery@ncoast.UUCP (06/15/87)
: #!/bin/sh # shar+ created from directory /usr2/davidsen/emacs38i # 13:42 on Thu Jun 11, 1987 by davidsen echo 'x - window.c (text)' sed << 'E!O!F' 's/^X//' > window.c X/* X * Window management. Some of the functions are internal, and some are X * attached to keys that the user actually types. X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if MEGAMAX & ST520 Xoverlay "window" X#endif X X/* X * Reposition dot in the current window to line "n". If the argument is X * positive, it is that line. If it is negative it is that line from the X * bottom. If it is 0 the window is centered (this is what the standard X * redisplay code does). With no argument it defaults to 0. Bound to M-!. X */ Xreposition(f, n) X { X if (f == FALSE) /* default to 0 to center screen */ X n = 0; X curwp->w_force = n; X curwp->w_flag |= WFFORCE; X return (TRUE); X } X X/* X * Refresh the screen. With no argument, it just does the refresh. With an X * argument it recenters "." in the current window. Bound to "C-L". X */ Xrefresh(f, n) X { X if (f == FALSE) X sgarbf = TRUE; X else X { X curwp->w_force = 0; /* Center dot. */ X curwp->w_flag |= WFFORCE; X } X X return (TRUE); X } X X/* X * The command make the next window (next => down the screen) the current X * window. There are no real errors, although the command does nothing if X * there is only 1 window on the screen. Bound to "C-X C-N". X * X * with an argument this command finds the <n>th window from the top X * X */ Xnextwind(f, n) X Xint f, n; /* default flag and numeric argument */ X X{ X register WINDOW *wp; X register int nwindows; /* total number of windows */ X X if (f) { X X /* first count the # of windows */ X wp = wheadp; X nwindows = 1; X while (wp->w_wndp != NULL) { X nwindows++; X wp = wp->w_wndp; X } X X /* if the argument is negative, it is the nth window X from the bottom of the screen */ X if (n < 0) X n = nwindows + n + 1; X X /* if an argument, give them that window from the top */ X if (n > 0 && n <= nwindows) { X wp = wheadp; X while (--n) X wp = wp->w_wndp; X } else { X mlwrite("Window number out of range"); X return(FALSE); X } X } else X if ((wp = curwp->w_wndp) == NULL) X wp = wheadp; X curwp = wp; X curbp = wp->w_bufp; X upmode(); X return (TRUE); X} X X/* X * This command makes the previous window (previous => up the screen) the X * current window. There arn't any errors, although the command does not do a X * lot if there is 1 window. X */ Xprevwind(f, n) X{ X register WINDOW *wp1; X register WINDOW *wp2; X X /* if we have an argument, we mean the nth window from the bottom */ X if (f) X return(nextwind(f, -n)); X X wp1 = wheadp; X wp2 = curwp; X X if (wp1 == wp2) X wp2 = NULL; X X while (wp1->w_wndp != wp2) X wp1 = wp1->w_wndp; X X curwp = wp1; X curbp = wp1->w_bufp; X upmode(); X return (TRUE); X} X X/* X * This command moves the current window down by "arg" lines. Recompute the X * top line in the window. The move up and move down code is almost completely X * the same; most of the work has to do with reframing the window, and picking X * a new dot. We share the code by having "move down" just be an interface to X * "move up". Magic. Bound to "C-X C-N". X */ Xmvdnwind(f, n) X Xint n; X X{ X return (mvupwind(f, -n)); X} X X/* X * Move the current window up by "arg" lines. Recompute the new top line of X * the window. Look to see if "." is still on the screen. If it is, you win. X * If it isn't, then move "." to center it in the new framing of the window X * (this command does not really move "."; it moves the frame). Bound to X * "C-X C-P". X */ Xmvupwind(f, n) X int n; X { X register LINE *lp; X register int i; X X lp = curwp->w_linep; X X if (n < 0) X { X while (n++ && lp!=curbp->b_linep) X lp = lforw(lp); X } X else X { X while (n-- && lback(lp)!=curbp->b_linep) X lp = lback(lp); X } X X curwp->w_linep = lp; X curwp->w_flag |= WFHARD; /* Mode line is OK. */ X X for (i = 0; i < curwp->w_ntrows; ++i) X { X if (lp == curwp->w_dotp) X return (TRUE); X if (lp == curbp->b_linep) X break; X lp = lforw(lp); X } X X lp = curwp->w_linep; X i = curwp->w_ntrows/2; X X while (i-- && lp != curbp->b_linep) X lp = lforw(lp); X X curwp->w_dotp = lp; X curwp->w_doto = 0; X return (TRUE); X } X X/* X * This command makes the current window the only window on the screen. Bound X * to "C-X 1". Try to set the framing so that "." does not have to move on the X * display. Some care has to be taken to keep the values of dot and mark in X * the buffer structures right if the distruction of a window makes a buffer X * become undisplayed. X */ Xonlywind(f, n) X{ X register WINDOW *wp; X register LINE *lp; X register int i; X X while (wheadp != curwp) { X wp = wheadp; X wheadp = wp->w_wndp; X if (--wp->w_bufp->b_nwnd == 0) { X wp->w_bufp->b_dotp = wp->w_dotp; X wp->w_bufp->b_doto = wp->w_doto; X wp->w_bufp->b_markp = wp->w_markp; X wp->w_bufp->b_marko = wp->w_marko; X } X free((char *) wp); X } X while (curwp->w_wndp != NULL) { X wp = curwp->w_wndp; X curwp->w_wndp = wp->w_wndp; X if (--wp->w_bufp->b_nwnd == 0) { X wp->w_bufp->b_dotp = wp->w_dotp; X wp->w_bufp->b_doto = wp->w_doto; X wp->w_bufp->b_markp = wp->w_markp; X wp->w_bufp->b_marko = wp->w_marko; X } X free((char *) wp); X } X lp = curwp->w_linep; X i = curwp->w_toprow; X while (i!=0 && lback(lp)!=curbp->b_linep) { X --i; X lp = lback(lp); X } X curwp->w_toprow = 0; X curwp->w_ntrows = term.t_nrow-1; X curwp->w_linep = lp; X curwp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* X * Delete the current window, placing its space in the window above, X * or, if it is the top window, the window below. Bound to C-X 0. X */ X Xdelwind(f,n) X Xint f, n; /* arguments are ignored for this command */ X X{ X register WINDOW *wp; /* window to recieve deleted space */ X register WINDOW *lwp; /* ptr window before curwp */ X register int target; /* target line to search for */ X X /* if there is only one window, don't delete it */ X if (wheadp->w_wndp == NULL) { X mlwrite("Can not delete this window"); X return(FALSE); X } X X /* find window before curwp in linked list */ X wp = wheadp; X lwp = NULL; X while (wp != NULL) { X if (wp == curwp) X break; X lwp = wp; X wp = wp->w_wndp; X } X X /* find recieving window and give up our space */ X wp = wheadp; X if (curwp->w_toprow == 0) { X /* find the next window down */ X target = curwp->w_ntrows + 1; X while (wp != NULL) { X if (wp->w_toprow == target) X break; X wp = wp->w_wndp; X } X if (wp == NULL) X return(FALSE); X wp->w_toprow = 0; X wp->w_ntrows += target; X } else { X /* find the next window up */ X target = curwp->w_toprow - 1; X while (wp != NULL) { X if ((wp->w_toprow + wp->w_ntrows) == target) X break; X wp = wp->w_wndp; X } X if (wp == NULL) X return(FALSE); X wp->w_ntrows += 1 + curwp->w_ntrows; X } X X /* get rid of the current window */ X if (--curwp->w_bufp->b_nwnd == 0) { X curwp->w_bufp->b_dotp = curwp->w_dotp; X curwp->w_bufp->b_doto = curwp->w_doto; X curwp->w_bufp->b_markp = curwp->w_markp; X curwp->w_bufp->b_marko = curwp->w_marko; X } X if (lwp == NULL) X wheadp = curwp->w_wndp; X else X lwp->w_wndp = curwp->w_wndp; X free((char *)curwp); X curwp = wp; X wp->w_flag |= WFHARD; X curbp = wp->w_bufp; X upmode(); X return(TRUE); X} X X/* X XSplit the current window. A window smaller than 3 lines cannot be Xsplit. An argument of 1 forces the cursor into the upper window, an Xargument of two forces the cursor to the lower window. The only other Xerror that is possible is a "malloc" failure allocating the structure Xfor the new window. Bound to "C-X 2". X X */ Xsplitwind(f, n) X Xint f, n; /* default flag and numeric argument */ X X{ X register WINDOW *wp; X register LINE *lp; X register int ntru; X register int ntrl; X register int ntrd; X register WINDOW *wp1; X register WINDOW *wp2; X char *malloc(); X X if (curwp->w_ntrows < 3) { X mlwrite("Cannot split a %d line window", curwp->w_ntrows); X return (FALSE); X } X if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) { X mlwrite("Cannot allocate WINDOW block"); X return (FALSE); X } X ++curbp->b_nwnd; /* Displayed twice. */ X wp->w_bufp = curbp; X wp->w_dotp = curwp->w_dotp; X wp->w_doto = curwp->w_doto; X wp->w_markp = curwp->w_markp; X wp->w_marko = curwp->w_marko; X wp->w_flag = 0; X wp->w_force = 0; X#if COLOR X /* set the colors of the new window */ X wp->w_fcolor = gfcolor; X wp->w_bcolor = gbcolor; X#endif X ntru = (curwp->w_ntrows-1) / 2; /* Upper size */ X ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */ X lp = curwp->w_linep; X ntrd = 0; X while (lp != curwp->w_dotp) { X ++ntrd; X lp = lforw(lp); X } X lp = curwp->w_linep; X if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) { X /* Old is upper window. */ X if (ntrd == ntru) /* Hit mode line. */ X lp = lforw(lp); X curwp->w_ntrows = ntru; X wp->w_wndp = curwp->w_wndp; X curwp->w_wndp = wp; X wp->w_toprow = curwp->w_toprow+ntru+1; X wp->w_ntrows = ntrl; X } else { /* Old is lower window */ X wp1 = NULL; X wp2 = wheadp; X while (wp2 != curwp) { X wp1 = wp2; X wp2 = wp2->w_wndp; X } X if (wp1 == NULL) X wheadp = wp; X else X wp1->w_wndp = wp; X wp->w_wndp = curwp; X wp->w_toprow = curwp->w_toprow; X wp->w_ntrows = ntru; X ++ntru; /* Mode line. */ X curwp->w_toprow += ntru; X curwp->w_ntrows = ntrl; X while (ntru--) X lp = lforw(lp); X } X curwp->w_linep = lp; /* Adjust the top lines */ X wp->w_linep = lp; /* if necessary. */ X curwp->w_flag |= WFMODE|WFHARD; X wp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* X * Enlarge the current window. Find the window that loses space. Make sure it X * is big enough. If so, hack the window descriptions, and ask redisplay to do X * all the hard work. You don't just set "force reframe" because dot would X * move. Bound to "C-X Z". X */ Xenlargewind(f, n) X{ X register WINDOW *adjwp; X register LINE *lp; X register int i; X X if (n < 0) X return (shrinkwind(f, -n)); X if (wheadp->w_wndp == NULL) { X mlwrite("Only one window"); X return (FALSE); X } X if ((adjwp=curwp->w_wndp) == NULL) { X adjwp = wheadp; X while (adjwp->w_wndp != curwp) X adjwp = adjwp->w_wndp; X } X if (adjwp->w_ntrows <= n) { X mlwrite("Impossible change"); X return (FALSE); X } X if (curwp->w_wndp == adjwp) { /* Shrink below. */ X lp = adjwp->w_linep; X for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i) X lp = lforw(lp); X adjwp->w_linep = lp; X adjwp->w_toprow += n; X } else { /* Shrink above. */ X lp = curwp->w_linep; X for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i) X lp = lback(lp); X curwp->w_linep = lp; X curwp->w_toprow -= n; X } X curwp->w_ntrows += n; X adjwp->w_ntrows -= n; X curwp->w_flag |= WFMODE|WFHARD; X adjwp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* X * Shrink the current window. Find the window that gains space. Hack at the X * window descriptions. Ask the redisplay to do all the hard work. Bound to X * "C-X C-Z". X */ Xshrinkwind(f, n) X{ X register WINDOW *adjwp; X register LINE *lp; X register int i; X X if (n < 0) X return (enlargewind(f, -n)); X if (wheadp->w_wndp == NULL) { X mlwrite("Only one window"); X return (FALSE); X } X if ((adjwp=curwp->w_wndp) == NULL) { X adjwp = wheadp; X while (adjwp->w_wndp != curwp) X adjwp = adjwp->w_wndp; X } X if (curwp->w_ntrows <= n) { X mlwrite("Impossible change"); X return (FALSE); X } X if (curwp->w_wndp == adjwp) { /* Grow below. */ X lp = adjwp->w_linep; X for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i) X lp = lback(lp); X adjwp->w_linep = lp; X adjwp->w_toprow -= n; X } else { /* Grow above. */ X lp = curwp->w_linep; X for (i=0; i<n && lp!=curbp->b_linep; ++i) X lp = lforw(lp); X curwp->w_linep = lp; X curwp->w_toprow += n; X } X curwp->w_ntrows -= n; X adjwp->w_ntrows += n; X curwp->w_flag |= WFMODE|WFHARD; X adjwp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* Resize the current window to the requested size */ X Xresize(f, n) X Xint f, n; /* default flag and numeric argument */ X X{ X int clines; /* current # of lines in window */ X X /* must have a non-default argument, else ignore call */ X if (f == FALSE) X return(TRUE); X X /* find out what to do */ X clines = curwp->w_ntrows; X X /* already the right size? */ X if (clines == n) X return(TRUE); X X return(enlargewind(TRUE, n - clines)); X} X X/* X * Pick a window for a pop-up. Split the screen if there is only one window. X * Pick the uppermost window that isn't the current window. An LRU algorithm X * might be better. Return a pointer, or NULL on error. X */ XWINDOW * Xwpopup() X{ X register WINDOW *wp; X X if (wheadp->w_wndp == NULL /* Only 1 window */ X && splitwind(FALSE, 0) == FALSE) /* and it won't split */ X return (NULL); X wp = wheadp; /* Find window to use */ X while (wp!=NULL && wp==curwp) X wp = wp->w_wndp; X return (wp); X} X Xscrnextup(f, n) /* scroll the next window up (back) a page */ X X{ X nextwind(FALSE, 1); X backpage(f, n); X prevwind(FALSE, 1); X} X Xscrnextdw(f, n) /* scroll the next window down (forward) a page */ X X{ X nextwind(FALSE, 1); X forwpage(f, n); X prevwind(FALSE, 1); X} X Xsavewnd(f, n) /* save ptr to current window */ X X{ X swindow = curwp; X return(TRUE); X} X Xrestwnd(f, n) /* restore the saved screen */ X X{ X register WINDOW *wp; X X /* find the window */ X wp = wheadp; X while (wp != NULL) { X if (wp == swindow) { X curwp = wp; X curbp = wp->w_bufp; X upmode(); X return (TRUE); X } X wp = wp->w_wndp; X } X X mlwrite("[No such window exists]"); X return(FALSE); X} X Xnewsize(f, n) /* resize the screen, re-writing the screen */ X Xint f; /* default flag */ Xint n; /* numeric argument */ X X{ X WINDOW *wp; /* current window being examined */ X WINDOW *nextwp; /* next window to scan */ X WINDOW *lastwp; /* last window scanned */ X int lastline; /* screen line of last line of current window */ X X /* if the command defaults, assume the largest */ X if (f == FALSE) X n = term.t_mrow + 1; X X /* make sure it's in range */ X if (n < 3 || n > term.t_mrow + 1) { X mlwrite("%%Screen size out of range"); X return(FALSE); X } X X if (term.t_nrow == n - 1) X return(TRUE); X else if (term.t_nrow < n - 1) { X X /* go to the last window */ X wp = wheadp; X while (wp->w_wndp != NULL) X wp = wp->w_wndp; X X /* and enlarge it as needed */ X wp->w_ntrows = n - wp->w_toprow - 2; X wp->w_flag |= WFHARD|WFMODE; X X } else { X X /* rebuild the window structure */ X nextwp = wheadp; X wp = NULL; X lastwp = NULL; X while (nextwp != NULL) { X wp = nextwp; X nextwp = wp->w_wndp; X X /* get rid of it if it is too low */ X if (wp->w_toprow > n - 2) { X X /* save the point/mark if needed */ X if (--wp->w_bufp->b_nwnd == 0) { X wp->w_bufp->b_dotp = wp->w_dotp; X wp->w_bufp->b_doto = wp->w_doto; X wp->w_bufp->b_markp = wp->w_markp; X wp->w_bufp->b_marko = wp->w_marko; X } X X /* update curwp and lastwp if needed */ X if (wp == curwp) X curwp = wheadp; X curbp = curwp->w_bufp; X if (lastwp != NULL) X lastwp->w_wndp = NULL; X X /* free the structure */ X free((char *)wp); X wp = NULL; X X } else { X /* need to change this window size? */ X lastline = wp->w_toprow + wp->w_ntrows - 1; X if (lastline >= n - 2) { X wp->w_ntrows = n - wp->w_toprow - 2; X wp->w_flag |= WFHARD|WFMODE; X } X } X X lastwp = wp; X } X } X X /* screen is garbage */ X term.t_nrow = n - 1; X sgarbf = TRUE; X return(TRUE); X} X Xnewwidth(f, n) /* resize the screen, re-writing the screen */ X Xint f; /* default flag */ Xint n; /* numeric argument */ X X{ X /* if the command defaults, assume the largest */ X if (f == FALSE) X n = term.t_mcol; X X /* make sure it's in range */ X if (n < 10 || n > term.t_mcol) { X mlwrite("%%Screen width out of range"); X return(FALSE); X } X X /* otherwise, just re-width it (no big deal) */ X term.t_ncol = n; X term.t_margin = n / 10; X term.t_scrsiz = n - (term.t_margin * 2); X curwp->w_flag |= WFHARD | WFMOVE | WFMODE; X sgarbf = TRUE; X return(TRUE); X} E!O!F newsize=`wc -c < window.c` if [ $newsize -ne 18032 ] then echo "File window.c was $newsize bytes, 18032 expected" fi echo 'x - word.c (text)' sed << 'E!O!F' 's/^X//' > word.c X/* X * The routines in this file implement commands that work word or a X * paragraph at a time. There are all sorts of word mode commands. If I X * do any sentence mode commands, they are likely to be put in this file. X */ X X#if MEGAMAX & ST520 Xoverlay "word" X#endif X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X/* Word wrap on n-spaces. Back-over whatever precedes the point on the current X * line and stop on the first word-break or the beginning of the line. If we X * reach the beginning of the line, jump back to the end of the word and start X * a new line. Otherwise, break the line at the word-break, eat it, and jump X * back to the end of the word. X * Returns TRUE on success, FALSE on errors. X */ Xwrapword(f, n) X Xint f; /* default flag */ Xint n; /* numeric argument */ X X{ X register int cnt; /* size of word wrapped to next line */ X register int c; /* charector temporary */ X X /* backup from the <NL> 1 char */ X if (!backchar(0, 1)) X return(FALSE); X X /* back up until we aren't in a word, X make sure there is a break in the line */ X cnt = 0; X while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ') X && (c != '\t')) { X cnt++; X if (!backchar(0, 1)) X return(FALSE); X /* if we make it to the beginning, start a new line */ X if (curwp->w_doto == 0) { X gotoeol(FALSE, 0); X return(lnewline()); X } X } X X /* delete the forward white space */ X if (!forwdel(0, 1)) X return(FALSE); X X /* put in a end of line */ X if (!lnewline()) X return(FALSE); X X /* and past the first word */ X while (cnt-- > 0) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X } X return(TRUE); X} X X/* X * Move the cursor backward by "n" words. All of the details of motion are X * performed by the "backchar" and "forwchar" routines. Error if you try to X * move beyond the buffers. X */ Xbackword(f, n) X{ X if (n < 0) X return (forwword(f, -n)); X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (forwchar(FALSE, 1)); X} X X/* X * Move the cursor forward by the specified number of words. All of the motion X * is done by "forwchar". Error if you try and move beyond the buffer's end. X */ Xforwword(f, n) X{ X if (n < 0) X return (backword(f, -n)); X while (n--) { X#if NFWORD X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#endif X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#if NFWORD == 0 X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#endif X } X return(TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move, X * convert any characters to upper case. Error if you try and move beyond the X * end of the buffer. Bound to "M-U". X */ Xupperword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert characters to lower case. Error if you try and move over the end of X * the buffer. Bound to "M-L". X */ Xlowerword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert the first character of the word to upper case, and subsequent X * characters to lower case. Error if you try and move past the end of the X * buffer. Bound to "M-C". X */ Xcapword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X if (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X } X return (TRUE); X} X X/* X * Kill forward by "n" words. Remember the location of dot. Move forward by X * the right number of words. Put dot back where it was and issue the kill X * command for the right number of characters. Bound to "M-D". X */ Xdelfword(f, n) X{ X register LINE *dotp; X register int doto; X long size; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ X kdelete(); /* last wasn't a kill. */ X thisflag |= CFKILL; X dotp = curwp->w_dotp; X doto = curwp->w_doto; X size = 0; X while (n--) { X#if NFWORD X if (curwp->w_doto == llength(curwp->w_dotp)) { X if (forwchar(FALSE,1) == FALSE) X return(FALSE); X ++size; X } X X if (inword()) { X while (inword() != FALSE) { X if (forwchar(FALSE,1) == FALSE) X return(FALSE); X ++size; X } X X while ((iswhite()) && X (curwp->w_doto != llength(curwp->w_dotp))) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X } X else { X while ((inword() == FALSE) && X (curwp->w_doto != llength(curwp->w_dotp))) { X if (forwchar(FALSE,1) == FALSE) X return(FALSE); X ++size; X } X } X#else X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X#endif X } X curwp->w_dotp = dotp; X curwp->w_doto = doto; X return (ldelete(size, TRUE)); X} X X/* X * Kill backwards by "n" words. Move backwards by the desired number of words, X * counting the characters. When dot is finally moved to its resting place, X * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace". X */ Xdelbword(f, n) X{ X long size; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ X kdelete(); /* last wasn't a kill. */ X thisflag |= CFKILL; X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X size = 0; X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X while (inword() != FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X return (ldelete(size, TRUE)); X} X X/* X * Return TRUE if the character at dot is a character that is considered to be X * part of a word. The word character list is hard coded. Should be setable. X */ Xinword() X{ X register int c; X X if (curwp->w_doto == llength(curwp->w_dotp)) X return (FALSE); X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') X return (TRUE); X if (c>='A' && c<='Z') X return (TRUE); X if (c>='0' && c<='9') X return (TRUE); X if (c=='$' || c=='_') /* For identifiers */ X return (TRUE); X return (FALSE); X} X X/* X * return TRUE if the current character is whitespace, X * else return FALSE. X */ X Xiswhite() X{ X register int c; X X if (curwp->w_doto == llength(curwp->w_dotp)) X return (FALSE); X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c == ' ' || c == '\t') return (TRUE); X return (FALSE); X} X X#if WORDPRO Xfillpara(f, n) /* Fill the current paragraph according to the current X fill column */ X Xint f, n; /* deFault flag and Numeric argument */ X X{ X register int c; /* current char durring scan */ X register int wordlen; /* length of current word */ X register int clength; /* position on line during fill */ X register int i; /* index during word copy */ X register int newlength; /* tentative new line length */ X register int eopflag; /* Are we at the End-Of-Paragraph? */ X register int firstflag; /* first word? (needs no space) */ X register LINE *eopline; /* pointer to line just past EOP */ X register int dotflag; /* was the last char a period? */ X char wbuf[NSTRING]; /* buffer for current word */ X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (fillcol == 0) { /* no fill column set */ X mlwrite("No fill column set"); X return(FALSE); X } X X /* record the pointer to the line just past the EOP */ X gotoeop(FALSE, 1); X eopline = lforw(curwp->w_dotp); X X /* and back top the beginning of the paragraph */ X gotobop(FALSE, 1); X X /* initialize various info */ X clength = curwp->w_doto; X if (clength && curwp->w_dotp->l_text[0] == TAB) X clength = 8; X wordlen = 0; X dotflag = FALSE; X X /* scan through lines, filling words */ X firstflag = TRUE; X eopflag = FALSE; X while (!eopflag) { X /* get the next character in the paragraph */ X if (curwp->w_doto == llength(curwp->w_dotp)) { X c = ' '; X if (lforw(curwp->w_dotp) == eopline) X eopflag = TRUE; X } else X c = lgetc(curwp->w_dotp, curwp->w_doto); X X /* and then delete it */ X ldelete(1L, FALSE); X X /* if not a separator, just add it in */ X if (c != ' ' && c != '\t') { X dotflag = (c == '.'); /* was it a dot */ X if (wordlen < NSTRING - 1) X wbuf[wordlen++] = c; X } else if (wordlen) { X /* at a word break with a word waiting */ X /* calculate tantitive new length with word added */ X newlength = clength + 1 + wordlen; X if (newlength <= fillcol) { X /* add word to current line */ X if (!firstflag) { X linsert(1, ' '); /* the space */ X ++clength; X } X firstflag = FALSE; X } else { X /* start a new line */ X lnewline(); X clength = 0; X } X X /* and add the word in in either case */ X for (i=0; i<wordlen; i++) { X linsert(1, wbuf[i]); X ++clength; X } X if (dotflag) { X linsert(1, ' '); X ++clength; X } X wordlen = 0; X } X } X /* and add a last newline for the end of our new paragraph */ X lnewline(); X return(TRUE); X} X Xkillpara(f, n) /* delete n paragraphs starting with the current one */ X Xint f; /* default flag */ Xint n; /* # of paras to delete */ X X{ X register int status; /* returned status of functions */ X X while (n--) { /* for each paragraph to delete */ X X /* mark out the end and beginning of the para to delete */ X gotoeop(FALSE, 1); X X /* set the mark here */ X curwp->w_markp = curwp->w_dotp; X curwp->w_marko = curwp->w_doto; X X /* go to the beginning of the paragraph */ X gotobop(FALSE, 1); X curwp->w_doto = 0; /* force us to the beginning of line */ X X /* and delete it */ X if ((status = killregion(FALSE, 1)) != TRUE) X return(status); X X /* and clean up the 2 extra lines */ X ldelete(2L, TRUE); X } X return(TRUE); X} X X X/* wordcount: count the # of words in the marked region, X along with average word sizes, # of chars, etc, X and report on them. */ X Xwordcount(f, n) X Xint f, n; /* ignored numeric arguments */ X X{ X register LINE *lp; /* current line to scan */ X register int offset; /* current char to scan */ X long size; /* size of region left to count */ X register int ch; /* current character to scan */ X register int wordflag; /* are we in a word now? */ X register int lastword; /* were we just in a word? */ X long nwords; /* total # of words */ X long nchars; /* total number of chars */ X int nlines; /* total number of lines in region */ X int avgch; /* average number of chars/word */ X int status; /* status return code */ X REGION region; /* region to look at */ X X /* make sure we have a region to count */ X if ((status = getregion(®ion)) != TRUE) X return(status); X lp = region.r_linep; X offset = region.r_offset; X size = region.r_size; X X /* count up things */ X lastword = FALSE; X nchars = 0L; X nwords = 0L; X nlines = 0; X while (size--) { X X /* get the current character */ X if (offset == llength(lp)) { /* end of line */ X ch = '\n'; X lp = lforw(lp); X offset = 0; X ++nlines; X } else { X ch = lgetc(lp, offset); X ++offset; X } X X /* and tabulate it */ X wordflag = ((ch >= 'a' && ch <= 'z') || X (ch >= 'A' && ch <= 'Z') || X (ch >= '0' && ch <= '9') || X (ch == '$' || ch == '_')); X if (wordflag == TRUE && lastword == FALSE) X ++nwords; X lastword = wordflag; X ++nchars; X } X X /* and report on the info */ X if (nwords > 0L) X avgch = (int)((100L * nchars) / nwords); X else X avgch = 0; X X mlwrite("Words %D Chars %D Lines %d Avg chars/word %f", X nwords, nchars, nlines + 1, avgch); X return(TRUE); X} X#endif E!O!F newsize=`wc -c < word.c` if [ $newsize -ne 16421 ] then echo "File word.c was $newsize bytes, 16421 expected" fi echo 'x - word.old (text)' sed << 'E!O!F' 's/^X//' > word.old X/* X * The routines in this file implement commands that work word or a X * paragraph at a time. There are all sorts of word mode commands. If I X * do any sentence mode commands, they are likely to be put in this file. X */ X X#if MEGAMAX & ST520 Xoverlay "word" X#endif X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X/* Word wrap on n-spaces. Back-over whatever precedes the point on the current X * line and stop on the first word-break or the beginning of the line. If we X * reach the beginning of the line, jump back to the end of the word and start X * a new line. Otherwise, break the line at the word-break, eat it, and jump X * back to the end of the word. X * Returns TRUE on success, FALSE on errors. X */ Xwrapword(f, n) X Xint f; /* default flag */ Xint n; /* numeric argument */ X X{ X register int cnt; /* size of word wrapped to next line */ X register int c; /* charector temporary */ X X /* backup from the <NL> 1 char */ X if (!backchar(0, 1)) X return(FALSE); X X /* back up until we aren't in a word, X make sure there is a break in the line */ X cnt = 0; X while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ') X && (c != '\t')) { X cnt++; X if (!backchar(0, 1)) X return(FALSE); X /* if we make it to the beginning, start a new line */ X if (curwp->w_doto == 0) { X gotoeol(FALSE, 0); X return(lnewline()); X } X } X X /* delete the forward white space */ X if (!forwdel(0, 1)) X return(FALSE); X X /* put in a end of line */ X if (!lnewline()) X return(FALSE); X X /* and past the first word */ X while (cnt-- > 0) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X } X return(TRUE); X} X X/* X * Move the cursor backward by "n" words. All of the details of motion are X * performed by the "backchar" and "forwchar" routines. Error if you try to X * move beyond the buffers. X */ Xbackword(f, n) X{ X if (n < 0) X return (forwword(f, -n)); X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (forwchar(FALSE, 1)); X} X X/* X * Move the cursor forward by the specified number of words. All of the motion X * is done by "forwchar". Error if you try and move beyond the buffer's end. X */ Xforwword(f, n) X{ X if (n < 0) X return (backword(f, -n)); X while (n--) { X#if NFWORD X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#endif X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#if NFWORD == 0 X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#endif X } X return(TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move, X * convert any characters to upper case. Error if you try and move beyond the X * end of the buffer. Bound to "M-U". X */ Xupperword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert characters to lower case. Error if you try and move over the end of X * the buffer. Bound to "M-L". X */ Xlowerword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert the first character of the word to upper case, and subsequent X * characters to lower case. Error if you try and move past the end of the X * buffer. Bound to "M-C". X */ Xcapword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X if (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X } X return (TRUE); X} X X/* X * Kill forward by "n" words. Remember the location of dot. Move forward by X * the right number of words. Put dot back where it was and issue the kill X * command for the right number of characters. Bound to "M-D". X */ Xdelfword(f, n) X{ X register LINE *dotp; X register int doto; X long size; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ X kdelete(); /* last wasn't a kill. */ X thisflag |= CFKILL; X dotp = curwp->w_dotp; X doto = curwp->w_doto; X size = 0; X while (n--) { X#if NFWORD X if (curwp->w_doto == llength(curwp->w_dotp)) { X if (forwchar(FALSE,1) == FALSE) X return(FALSE); X ++size; X } X X while (inword() != FALSE) { X if (forwchar(FALSE,1) == FALSE) X return(FALSE); X ++size; X } X X while ((inword() == FALSE) && X (curwp->w_doto != llength(curwp->w_dotp))) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X#else X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X#endif X } X curwp->w_dotp = dotp; X curwp->w_doto = doto; X return (ldelete(size, TRUE)); X} X X/* X * Kill backwards by "n" words. Move backwards by the desired number of words, X * counting the characters. When dot is finally moved to its resting place, X * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace". X */ Xdelbword(f, n) X{ X long size; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ X kdelete(); /* last wasn't a kill. */ X thisflag |= CFKILL; X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X size = 0; X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X while (inword() != FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X return (ldelete(size, TRUE)); X} X X/* X * Return TRUE if the character at dot is a character that is considered to be X * part of a word. The word character list is hard coded. Should be setable. X */ Xinword() X{ X register int c; X X if (curwp->w_doto == llength(curwp->w_dotp)) X return (FALSE); X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') X return (TRUE); X if (c>='A' && c<='Z') X return (TRUE); X if (c>='0' && c<='9') X return (TRUE); X if (c=='$' || c=='_') /* For identifiers */ X return (TRUE); X return (FALSE); X} X X#if WORDPRO Xfillpara(f, n) /* Fill the current paragraph according to the current X fill column */ X Xint f, n; /* deFault flag and Numeric argument */ X X{ X register int c; /* current char durring scan */ X register int wordlen; /* length of current word */ X register int clength; /* position on line during fill */ X register int i; /* index during word copy */ X register int newlength; /* tentative new line length */ X register int eopflag; /* Are we at the End-Of-Paragraph? */ X register int firstflag; /* first word? (needs no space) */ X register LINE *eopline; /* pointer to line just past EOP */ X register int dotflag; /* was the last char a period? */ X char wbuf[NSTRING]; /* buffer for current word */ X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (fillcol == 0) { /* no fill column set */ X mlwrite("No fill column set"); X return(FALSE); X } X X /* record the pointer to the line just past the EOP */ X gotoeop(FALSE, 1); X eopline = lforw(curwp->w_dotp); X X /* and back top the beginning of the paragraph */ X gotobop(FALSE, 1); X X /* initialize various info */ X clength = curwp->w_doto; X if (clength && curwp->w_dotp->l_text[0] == TAB) X clength = 8; X wordlen = 0; X dotflag = FALSE; X X /* scan through lines, filling words */ X firstflag = TRUE; X eopflag = FALSE; X while (!eopflag) { X /* get the next character in the paragraph */ X if (curwp->w_doto == llength(curwp->w_dotp)) { X c = ' '; X if (lforw(curwp->w_dotp) == eopline) X eopflag = TRUE; X } else X c = lgetc(curwp->w_dotp, curwp->w_doto); X X /* and then delete it */ X ldelete(1L, FALSE); X X /* if not a separator, just add it in */ X if (c != ' ' && c != '\t') { X dotflag = (c == '.'); /* was it a dot */ X if (wordlen < NSTRING - 1) X wbuf[wordlen++] = c; X } else if (wordlen) { X /* at a word break with a word waiting */ X /* calculate tantitive new length with word added */ X newlength = clength + 1 + wordlen; X if (newlength <= fillcol) { X /* add word to current line */ X if (!firstflag) { X linsert(1, ' '); /* the space */ X ++clength; X } X firstflag = FALSE; X } else { X /* start a new line */ X lnewline(); X clength = 0; X } X X /* and add the word in in either case */ X for (i=0; i<wordlen; i++) { X linsert(1, wbuf[i]); X ++clength; X } X if (dotflag) { X linsert(1, ' '); X ++clength; X } X wordlen = 0; X } X } X /* and add a last newline for the end of our new paragraph */ X lnewline(); X return(TRUE); X} X Xkillpara(f, n) /* delete n paragraphs starting with the current one */ X Xint f; /* default flag */ Xint n; /* # of paras to delete */ X X{ X register int status; /* returned status of functions */ X X while (n--) { /* for each paragraph to delete */ X X /* mark out the end and beginning of the para to delete */ X gotoeop(FALSE, 1); X X /* set the mark here */ X curwp->w_markp = curwp->w_dotp; X curwp->w_marko = curwp->w_doto; X X /* go to the beginning of the paragraph */ X gotobop(FALSE, 1); X curwp->w_doto = 0; /* force us to the beginning of line */ X X /* and delete it */ X if ((status = killregion(FALSE, 1)) != TRUE) X return(status); X X /* and clean up the 2 extra lines */ X ldelete(2L, TRUE); X } X return(TRUE); X} X X X/* wordcount: count the # of words in the marked region, X along with average word sizes, # of chars, etc, X and report on them. */ X Xwordcount(f, n) X Xint f, n; /* ignored numeric arguments */ X X{ X register LINE *lp; /* current line to scan */ X register int offset; /* current char to scan */ X long size; /* size of region left to count */ X register int ch; /* current character to scan */ X register int wordflag; /* are we in a word now? */ X register int lastword; /* were we just in a word? */ X long nwords; /* total # of words */ X long nchars; /* total number of chars */ X int nlines; /* total number of lines in region */ X int avgch; /* average number of chars/word */ X int status; /* status return code */ X REGION region; /* region to look at */ X X /* make sure we have a region to count */ X if ((status = getregion(®ion)) != TRUE) X return(status); X lp = region.r_linep; X offset = region.r_offset; X size = region.r_size; X X /* count up things */ X lastword = FALSE; X nchars = 0L; X nwords = 0L; X nlines = 0; X while (size--) { X X /* get the current character */ X if (offset == llength(lp)) { /* end of line */ X ch = '\n'; X lp = lforw(lp); X offset = 0; X ++nlines; X } else { X ch = lgetc(lp, offset); X ++offset; X } X X /* and tabulate it */ X wordflag = ((ch >= 'a' && ch <= 'z') || X (ch >= 'A' && ch <= 'Z') || X (ch >= '0' && ch <= '9') || X (ch == '$' || ch == '_')); X if (wordflag == TRUE && lastword == FALSE) X ++nwords; X lastword = wordflag; X ++nchars; X } X X /* and report on the info */ X if (nwords > 0L) X avgch = (int)((100L * nchars) / nwords); X else X avgch = 0; X X mlwrite("Words %D Chars %D Lines %d Avg chars/word %f", X nwords, nchars, nlines + 1, avgch); X return(TRUE); X} X#endif E!O!F newsize=`wc -c < word.old` if [ $newsize -ne 15895 ] then echo "File word.old was $newsize bytes, 15895 expected" fi echo 'x - z309.c (text)' sed << 'E!O!F' 's/^X//' > z309.c X/* X * The routines in this file provide support for the Zenith Z-100 PC X * family. It goes directly to the graphics RAM to do screen output. X * It compiles into nothing if not a Zenith driver. X */ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if Z309 X X/* set NROW to 25 for 25-line interlaced mode */ X#define NROW 50 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define NPAUSE 200 /* # times thru update to pause */ X#define BEL 0x07 /* BEL character. */ X#define ESC 0x1B /* ESC character. */ X#define SPACE 32 /* space character */ X X#define SCADC 0xb8000000L /* CGA address of screen RAM */ X#define SCADM 0xb0000000L /* MONO address of screen RAM */ X X#define CDMONO 0 /* monochrome text card */ X#define CDCGA50 1 /* 50-line color graphics card */ X#define CDCGI25 2 /* 25-line interlaced CGA text */ X#define CDCGA25 3 /* 25-line color graphics card */ X#define CDSENSE 9 /* detect the card type */ X Xint dtype = CDCGA50; /* current display type */ Xlong scadd; /* address of screen ram */ Xint *scptr[NROW]; /* pointer to screen lines */ Xint sline[NCOL]; /* screen line image */ Xextern union REGS rg; /* cpu register for use of DOS calls */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int z309move(); Xextern int z309eeol(); Xextern int z309eeop(); Xextern int z309beep(); Xextern int z309open(); Xextern int z309rev(); Xextern int z309cres(); Xextern int z309close(); Xextern int z309putc(); Xextern int z309kopen(); Xextern int z309kclose(); X X#if COLOR Xextern int z309fcol(); Xextern int z309bcol(); X Xint cfcolor = -1; /* current forground color */ Xint cbcolor = -1; /* current background color */ Xint ctrans[] = /* ansi to z309 color translation table */ X {0, 4, 2, 6, 1, 5, 3, 7}; X#endif X X/* X * Standard terminal interface dispatch table. Most of the fields point into X * "termio" code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X z309open, X z309close, X z309kopen, X z309kclose, X ttgetc, X z309putc, X ttflush, X z309move, X z309eeol, X z309eeop, X z309beep, X z309rev, X z309cres X#if COLOR X , z309fcol, X z309bcol X#endif X}; X Xextern union REGS rg; X X#if COLOR Xz309fcol(color) /* set the current output color */ X Xint color; /* color to set */ X X{ X cfcolor = ctrans[color]; X} X Xz309bcol(color) /* set the current background color */ X Xint color; /* color to set */ X X{ X cbcolor = ctrans[color]; X} X#endif Xz309move(row, col) X{ X rg.h.ah = 2; /* set cursor position function code */ X rg.h.dl = col; X rg.h.dh = row; X rg.h.bh = 0; /* set screen page number */ X int86(0x10, &rg, &rg); X} X Xz309eeol() /* erase to the end of the line */ X X{ X int attr; /* attribute byte mask to place in RAM */ X int *lnptr; /* pointer to the destination line */ X int i; X int ccol; /* current column cursor lives */ X int crow; /* row */ X X /* find the current cursor position */ X rg.h.ah = 3; /* read cursor position function code */ X rg.h.bh = 0; /* current video page */ X int86(0x10, &rg, &rg); X ccol = rg.h.dl; /* record current column */ X crow = rg.h.dh; /* and row */ X X /* build the attribute byte and setup the screen pointer */ X#if COLOR X if (dtype != CDMONO) X attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8; X else X attr = 0x0700; X#else X attr = 0x0700; X#endif X lnptr = &sline[0]; X for (i=0; i < term.t_ncol; i++) X *lnptr++ = SPACE | attr; X X#if 0 /* Heath/Zenith builds flicker-less CGAs */ X if (flickcode) { X /* wait for vertical retrace to be off */ X while ((inp(0x3da) & 8)) X ; X X /* and to be back on */ X while ((inp(0x3da) & 8) == 0) X ; X } X#endif X X /* and send the string out */ X movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2); X X} X Xz309putc(ch) /* put a character at the current position in the X current colors */ X Xint ch; X X{ X rg.h.ah = 14; /* write char to screen with current attrs */ X rg.h.al = ch; X#if COLOR X if (dtype != CDMONO) X rg.h.bl = cfcolor; X else X rg.h.bl = 0x07; X#else X rg.h.bl = 0x07; X#endif X int86(0x10, &rg, &rg); X} X Xz309eeop() X{ X int attr; /* attribute to fill screen with */ X X rg.h.ah = 6; /* scroll page up function code */ X rg.h.al = 0; /* # lines to scroll (clear it) */ X rg.x.cx = 0; /* upper left corner of scroll */ X/*HERE*/ rg.x.dx = 0x184f; /* lower right corner of scroll */ X#if COLOR X if (dtype != CDMONO) X attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15); X else X attr = 0; X#else X attr = 0; X#endif X rg.h.bh = attr; X int86(0x10, &rg, &rg); X} X Xz309rev(state) /* change reverse video state */ X Xint state; /* TRUE = reverse, FALSE = normal */ X X{ X /* This never gets used under the z309-PC driver */ X} X Xz309cres(res) /* change screen resolution */ X Xchar *res; /* resolution to change to */ X X{ X if (strcmp(res, "CGA50") == 0) { X scinit(CDCGA50); X return(TRUE); X } else if (strcmp(res, "MONO") == 0) { X scinit(CDMONO); X return(TRUE); X } else X return(FALSE); X} X Xz309beep() X{ X#if MWC86 X putcnb(BEL); X#else X bdos(6, BEL, 0); X#endif X} X Xz309open() X{ X scinit(CDSENSE); X revexist = TRUE; X ttopen(); X} X Xz309close() X X{ X rg.h.ah = 101; X rg.h.al = 1; /* 25-line interlace mode */ X int86(0x10, &rg, &rg); X#if COLOR X z309fcol(7); X z309bcol(0); X#endif X ttclose(); X} X Xz309kopen() /* open the keyboard */ X X{ X} X Xz309kclose() /* close the keyboard */ X X{ X} X Xscinit(type) /* initialize the screen head pointers */ X Xint type; /* type of adapter to init for */ X X{ X union { X long laddr; /* long form of address */ X int *paddr; /* pointer form of address */ X } addr; X int i; X X /* if asked...find out what display is connected */ X int86(0x11, &rg, &rg); X dtype = CDCGA50; X scadd = SCADC; X strcpy(sres, "CGA50"); X if ((((rg.x.ax >> 4) & 11) == 3) || type == CDMONO) { X strcpy(sres, "MONO"); X dtype = CDMONO; X scadd = SCADM; X } X else { X rg.h.ah = 101; X/* set al = 1 for 25-line interlace mode */ X rg.h.al = 2; /* 50-line interlace mode */ X int86(0x10, &rg, &rg); X } X X /* initialize the screen pointer array */ X for (i = 0; i < NROW; i++) { X addr.laddr = scadd + (long)(NCOL * i * 2); X scptr[i] = addr.paddr; X } X} X Xscwrite(row, outstr, forg, bacg) /* write a line out*/ X Xint row; /* row of screen to place outstr on */ Xchar *outstr; /* string to write out (must be term.t_ncol long) */ Xint forg; /* forground color of string to write */ Xint bacg; /* background color */ X X{ X int attr; /* attribute byte mask to place in RAM */ X int *lnptr; /* pointer to the destination line */ X int i; X X /* build the attribute byte and setup the screen pointer */ X#if COLOR X if (dtype != CDMONO) X attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8; X else X attr = (((bacg & 15) << 4) | (forg & 15)) << 8; X#else X attr = (((bacg & 15) << 4) | (forg & 15)) << 8; X#endif X lnptr = &sline[0]; X for (i=0; i<term.t_ncol; i++) X *lnptr++ = (outstr[i] & 255) | attr; X X#if 0 /* Heath/Zenith builds flicker-less CGAs */ X if (flickcode) { X /* wait for vertical retrace to be off */ X while ((inp(0x3da) & 8)) X ; X X /* and to be back on */ X while ((inp(0x3da) & 8) == 0) X ; X } X#endif X X /* and send the string out */ X movmem(&sline[0], scptr[row],term.t_ncol*2); X} X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument [unused] */ X X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X#else Xz309hello() X{ X} X#endif E!O!F newsize=`wc -c < z309.c` if [ $newsize -ne 7806 ] then echo "File z309.c was $newsize bytes, 7806 expected" fi bill davidsen (wedu@ge-crd.arpa) {chinet | philabs | sesimo}!steinmetz!crdos1!davidsen "Stupidity, like virtue, is its own reward" -me