[net.micro.pc] Fixes to Microemacs 3.6

toma@tekgvs.UUCP (Thomas Almy) (06/17/86)

I recently got Microemacs 3.6 running using Microsoft C, following the
guidelines recently given by Oliver Sharp at Yale.

The following are the modifications I made to Microemacs V3.6.  The
major concern was increasing the display speed by writing directly to
display memory.  The modifications are designed for CGA or CGA
equivalent display controllers. (See note at end for EGA 80x43 mode!).
The result is spectacular!

Several other modifications apply even if the change to direct display
output are not performed, so read in any case!

*****STEP 1 -- Modification to display.c for direct video.

This modification is in the spirit of "RAINBOW".  I am not showing the
modifications as conditional compilations -- I leave that to you (YES I
did it on my copy!).

First -- delete all references to and definitions of pscreen.  These are
not needed by the new routines since they never take the time to compare
the physical and virtual screens.  RAINBOW didn't need this either.

Second -- updateline should be called with the reference to pscreen (vp2)
deleted.  Then use this definition of updateline:

updateline(row, vline, flags)
    int  row;
    char vline[];   /* what we want it to end up as */
    short *flags;   /* and how we want it that way  */
{
    char *cp1;
    int req,gmode;

    req = *flags & VFREQ;
    gmode = (req ? 2 : 0x17 );  /* white on blue, inverse is green on black */
        if (req)
            *flags |= VFREV;
        else
            *flags &= ~VFREV;

    cp1 = &vline[0];                    /* Use fast video. */

    putline(row+1,1,cp1,gmode);

    *flags &= ~VFCHG;
}


Then add the following definition for putline:

putline(row, col, buf, mode)
    int row,col,mode;
    char *buf;
    {
    register int n;
    char *display;

    n = strlen(buf); 
    if (col + n - 1 > term.t_ncol) 
        n = term.t_ncol - col + 1;
    display = (char *)(0xb8000000L + 2*((col-1)+(row-1)*term.t_ncol));
    while (n--) {
        *display++ = *buf++;
        *display++ = mode;
        }
    }

The above is only for Microsoft C compiler, medium or large memory model.
It probably would have to be changed for other compilers, and definately
needed to be changed for the small model.


*******STEP 2 -- Improvement of inline editing in display.c and line.c

The speedup for within line editing does not work if the same file is in
two or more windows.  In this case the performance is excruciatingly
slow without a PC AT.  This fix makes things work alot faster, even without
the direct display writing of step 1.


The following change is made to update() in display.c so that only the line 
containing the cursor will be updated:

            if ((wp->w_flag & ~WFMODE) == WFEDIT)
                {
                j = wp->w_ntrows + i;        /* added line */
                while ((lp != curwp->w_dotp) &&   /* wp becomes curwp */
                       (j > i))			/* added line */
                    {
                    ++i;
                    lp = lforw(lp);
                    }
                if (j>i)                   /* added line */
                    {
                    vscreen[i]->v_flag |= VFCHG;
                    vtmove(i, 0);

                    for (j = 0; j < llength(lp); ++j)
                        vtputc(lgetc(lp, j));

                    vteeol();
                    }
                }

The following change is made to the first statement of lchange(flag) 
in line.c so that we don't signal hard updates if more than one window 
and just single line edit.

        if ((!(flag&WFEDIT)) &&                 /* added term */
            (curbp->b_nwnd != 1))               /* Ensure hard.         */
                flag = WFHARD;

******STEP 3:  Fix for erroneous buffer sizes in buffer.c

Problem in that the buffer list shows buffer sizes only if they fit in an
int.  Fix is in makelist() -- change declaration of nbytes to "long", 
change itoa() so declaration of num is "long".

******STEP 4:  Fix keyboard lookahead (add file kbhit.asm)

The Microsoft C compiled version has a brain damaged set of bios/bdos
calls which cannot return the zero flag, just the sign flag.  The use of
"kbhit" causes emacs to be exited with the printer on if ^P has been
used an odd number of times in an editing session.  I linked in this
version of kbhit.  (Note that failure of these routines in termio.c are
the primary cause of the dreaded stack overflow message!).

KBHIT_TEXT	segment 'CODE'
	assume  cs:KBHIT_TEXT
	public _kbhit
_kbhit	PROC FAR
	mov	ah,1
	int	22		; bios call for keyboard status
	jz	nokey
	mov	ax,1
	ret
nokey:	mov	ax,0
	ret
_kbhit	endP
KBHIT_TEXT	ends
	end


******STEP 5:  Fix for WRAP mode not wrapping on white space in word.c

Problem is that words ending in periods or other punctuation which are
wrapped will cause the punctuation to vanish!  Fix is to have wordwrap()
call nonblank() instead of inword(), where the definition of nonblank()
is:

nonblank()
{
	register char c;
	
        if (curwp->w_doto == llength(curwp->w_dotp))
                return (FALSE);
        c = lgetc(curwp->w_dotp, curwp->w_doto);
	if (c == ' ') return (FALSE);
	if (c == '\t') return (FALSE); /* a tab is white space too */
	return (TRUE);
}

******STEP 6: Fix for terminal initialization on spawning in spawn.c

Problem is that terminal de-initialization code should be executed just
before spawning a task (^X-C command), and initialization code just after.
I discovered this problem after I modified the system to use 80x43 mode
on an EGA display (using NANSI.SYS to change modes).

	(*term.t_close)();			/* added line */
        spawnlp(P_WAIT,"command",NULL);         /* Run CLI.             */
	(*term.t_open)();			/* added line */

This change should be made for at all spawning calls.


******STEP 7: Fix for "delete-blank-lines" in random.c

Problem is that this command puts text into kill buffer (yet does not
clear the buffer first).  An examination of the code shows that this
command should not use the kill buffer; its call of ldelete is missing
an argument!

In deblank, change "ldelete(nld)" to "ldelete(nld,FALSE)".

******STEP 8: Fix for "delete-word" in word.c


Problem is that this command puts text into the kill buffer yet
does not clear the buffer first.  An examination of the code
shows that this command intends to use the kill buffer, but is
improperly coded.  Since other versions of EMACS do not use the
kill buffer for this command, the fix is to change delfword and
delbword so that they call ldelete with a second argument
"FALSE" instead of "TRUE", and change the source file
documentation accordingly.  If it is desired to have the command
put the text into the kill buffer (much more useful, in my
opinion) then the following code must be added before the call
of ldelete:

        if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
                kdelete();                      /* last wasn't a kill.  */
        thisflag |= CFKILL;




******Personal preference modifications

The problem is that if more than one file is specified, my
preference is for the first two files to appear in windows.  To
do this I add a variable sfile which gets set TRUE if two or
more files, and then just before the outermost execution loop I
added:

if (sfile) {
	splitwind();		/* split window into two */
	nextwind();		/* go to bottom window */
	nextbuffer();		/* put next buffer in window */
	nextwind();		/* goes back to top window */
	}

I modified the handling of tabs so that the tab character is always
inserted but on display tabs are expanded to the set tab size. 
This follows the operation of other emaxen (?) that I use.  This change
required many minor changes to display.c (look for places where the
constant 7 and the character '\t' appear.  

I also modified display.c so that characters with the parity
bit set will display with a leading tilde.


I added EGA support by having ANSI.C send the command "ESC[=43h" to
NANSI.SYS in the open routine, and "ESC[=3h" in the close routine.  I
also changed the number of lines to 43.  Works like a charm with the
direct video mods!


By the way, if the editor is compiled with the small model, and 2k of
stack space (which I found to be adequate), then it works much faster,
and still has a capacity of about 30k in buffers.

Tom Almy

lawrence@duncan.UUCP (06/22/86)

	Thanks for the fix notice.  I sneaked them in just before I sent
3.7 off to mod.sources.

step1: 3.7 has an IBM-PC specific screen driver similar to the mods made
	here
step2:	update changed so much, I will look into making an equivilant change
	with the new code
step3:  3.7 fixes this problem...I also changed the name of itoa() to ltoa()
	to reflect the fact a long was being changed to an ascii (the same
	problem also existed in the showcpos() command and has been fixed
	as well).
step4:	agreed. 3.7 also has this problem fixed, but in a different way
	using C code. (check typahead() in termio.c)
step5:	3.7 also has this fixed. I used some very similar code to this.
step6:	also done already
step7:	I hadn't caught this one. It is fixed now.
step8:	this one has already been fixed

					Daniel Lawrence
				ihnp4!pur-ee!pur-phy!duncan!lawrence
		or		ihnp4!itivax!duncan!lawrence