Mark Williams C v4.0.12
This commit is contained in:
parent
3815d3db57
commit
f6626f0e06
BIN
Mark Williams MWS v4/BIN/AS.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/AS.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/CC.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/CC.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/CC0.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/CC0.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/CC0L.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/CC0L.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/CC1.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/CC1.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/CC2.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/CC2.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/CC2L.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/CC2L.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/CC3.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/CC3.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/CMP.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/CMP.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/CPP.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/CPP.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/EGREP.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/EGREP.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/EXETOCOM.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/EXETOCOM.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/FIXOBJ.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/FIXOBJ.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/LINK.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/LINK.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/MAKE.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/MAKE.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/ME.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/ME.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/MWLIB.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/MWLIB.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/MWS.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/MWS.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/MWS1.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/MWS1.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/MWS2.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/MWS2.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/NM.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/NM.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/PR.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/PR.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/SIZE.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/SIZE.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/STRIP.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/STRIP.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/TAIL.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/TAIL.EXE
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/BIN/WC.EXE
Normal file
BIN
Mark Williams MWS v4/BIN/WC.EXE
Normal file
Binary file not shown.
527
Mark Williams MWS v4/BIN/ttt.c
Normal file
527
Mark Williams MWS v4/BIN/ttt.c
Normal file
@ -0,0 +1,527 @@
|
||||
/*
|
||||
This version builds with old compilers including:
|
||||
Aztec C 1.06 for 8080 & Z80 on CP/M.
|
||||
Microsoft C Compiler V1.04 for 8086 on DOS. (This is Lattice C)
|
||||
Microsoft C Compiler V2.03 for 8086 on DOS. (Still Lattice C)
|
||||
Microsoft C Compiler V3.00 for 8086 on DOS.
|
||||
QuickC 1.0
|
||||
Turbo C 2.0
|
||||
The syntax is old and reminds me of 7th grade summer vacation.
|
||||
Much of this code is awkward to satisfy the lowest common denominator of many compilers.
|
||||
unsigned long isn't supported in many older compilers, so long is used instead.
|
||||
Early DOS and CP/M require register variabes to be int, not char or other types.
|
||||
The perf improvement of using register-int instead of stack-char is worth it.
|
||||
*/
|
||||
|
||||
#define LINT_ARGS
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef DOSTIME
|
||||
#include <time.h>
|
||||
#include <dos.h>
|
||||
#endif
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
/* Function Pointers are the fastest implementation for almost every compiler */
|
||||
#define UseFunPointers 1
|
||||
#define UseWinner2 2
|
||||
#define UseLookForWinner 3
|
||||
#define WinMethod UseFunPointers
|
||||
|
||||
#define ABPrune true /* alpha beta pruning */
|
||||
#define WinLosePrune true /* stop early on win/lose */
|
||||
#define ScoreWin 6
|
||||
#define ScoreTie 5
|
||||
#define ScoreLose 4
|
||||
#define ScoreMax 9
|
||||
#define ScoreMin 2
|
||||
#define DefaultIterations 100
|
||||
|
||||
#define PieceX 1
|
||||
#define PieceO 2
|
||||
#define PieceBlank 0
|
||||
|
||||
typedef char ttype; /* 8-bit and 16-bit cpus do best with char aside from register in locals */
|
||||
|
||||
int g_Iterations = DefaultIterations;
|
||||
ttype g_board[ 9 ];
|
||||
|
||||
#if WinMethod == UseFunPointers
|
||||
|
||||
ttype pos0func()
|
||||
{
|
||||
/* using "register int" instead of "ttype" for x is faster on 8086 and Z80 */
|
||||
register int x = g_board[0];
|
||||
|
||||
if ( ( x == g_board[1] && x == g_board[2] ) ||
|
||||
( x == g_board[3] && x == g_board[6] ) ||
|
||||
( x == g_board[4] && x == g_board[8] ) )
|
||||
return x;
|
||||
return PieceBlank;
|
||||
}
|
||||
|
||||
ttype pos1func()
|
||||
{
|
||||
register int x = g_board[1];
|
||||
|
||||
if ( ( x == g_board[0] && x == g_board[2] ) ||
|
||||
( x == g_board[4] && x == g_board[7] ) )
|
||||
return x;
|
||||
return PieceBlank;
|
||||
}
|
||||
|
||||
ttype pos2func()
|
||||
{
|
||||
register int x = g_board[2];
|
||||
|
||||
if ( ( x == g_board[0] && x == g_board[1] ) ||
|
||||
( x == g_board[5] && x == g_board[8] ) ||
|
||||
( x == g_board[4] && x == g_board[6] ) )
|
||||
return x;
|
||||
return PieceBlank;
|
||||
}
|
||||
|
||||
ttype pos3func()
|
||||
{
|
||||
register int x = g_board[3];
|
||||
|
||||
if ( ( x == g_board[4] && x == g_board[5] ) ||
|
||||
( x == g_board[0] && x == g_board[6] ) )
|
||||
return x;
|
||||
return PieceBlank;
|
||||
}
|
||||
|
||||
ttype pos4func()
|
||||
{
|
||||
register int x = g_board[4];
|
||||
|
||||
if ( ( x == g_board[0] && x == g_board[8] ) ||
|
||||
( x == g_board[2] && x == g_board[6] ) ||
|
||||
( x == g_board[1] && x == g_board[7] ) ||
|
||||
( x == g_board[3] && x == g_board[5] ) )
|
||||
return x;
|
||||
return PieceBlank;
|
||||
}
|
||||
|
||||
ttype pos5func()
|
||||
{
|
||||
register int x = g_board[5];
|
||||
|
||||
if ( ( x == g_board[3] && x == g_board[4] ) ||
|
||||
( x == g_board[2] && x == g_board[8] ) )
|
||||
return x;
|
||||
return PieceBlank;
|
||||
}
|
||||
|
||||
ttype pos6func()
|
||||
{
|
||||
register int x = g_board[6];
|
||||
|
||||
if ( ( x == g_board[7] && x == g_board[8] ) ||
|
||||
( x == g_board[0] && x == g_board[3] ) ||
|
||||
( x == g_board[4] && x == g_board[2] ) )
|
||||
return x;
|
||||
return PieceBlank;
|
||||
}
|
||||
|
||||
ttype pos7func()
|
||||
{
|
||||
register int x = g_board[7];
|
||||
|
||||
if ( ( x == g_board[6] && x == g_board[8] ) ||
|
||||
( x == g_board[1] && x == g_board[4] ) )
|
||||
return x;
|
||||
return PieceBlank;
|
||||
}
|
||||
|
||||
ttype pos8func()
|
||||
{
|
||||
register int x = g_board[8];
|
||||
|
||||
if ( ( x == g_board[6] && x == g_board[7] ) ||
|
||||
( x == g_board[2] && x == g_board[5] ) ||
|
||||
( x == g_board[0] && x == g_board[4] ) )
|
||||
return x;
|
||||
return PieceBlank;
|
||||
}
|
||||
|
||||
typedef ttype pfunc_t();
|
||||
|
||||
pfunc_t * winner_functions[9] =
|
||||
{
|
||||
pos0func,
|
||||
pos1func,
|
||||
pos2func,
|
||||
pos3func,
|
||||
pos4func,
|
||||
pos5func,
|
||||
pos6func,
|
||||
pos7func,
|
||||
pos8func,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if WinMethod == UseWinner2
|
||||
|
||||
ttype winner2( move ) ttype move;
|
||||
{
|
||||
register int x; /* faster than ttype x on the stack */
|
||||
|
||||
switch( move ) /* msc v3 from 1985 generates a jump table! */
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
x = g_board[ 0 ];
|
||||
if ( ( ( x == g_board[1] ) && ( x == g_board[2] ) ) ||
|
||||
( ( x == g_board[3] ) && ( x == g_board[6] ) ) ||
|
||||
( ( x == g_board[4] ) && ( x == g_board[8] ) ) )
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
x = g_board[ 1 ];
|
||||
if ( ( ( x == g_board[0] ) && ( x == g_board[2] ) ) ||
|
||||
( ( x == g_board[4] ) && ( x == g_board[7] ) ) )
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
x = g_board[ 2 ];
|
||||
if ( ( ( x == g_board[0] ) && ( x == g_board[1] ) ) ||
|
||||
( ( x == g_board[5] ) && ( x == g_board[8] ) ) ||
|
||||
( ( x == g_board[4] ) && ( x == g_board[6] ) ) )
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
x = g_board[ 3 ];
|
||||
if ( ( ( x == g_board[4] ) && ( x == g_board[5] ) ) ||
|
||||
( ( x == g_board[0] ) && ( x == g_board[6] ) ) )
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
x = g_board[ 4 ];
|
||||
if ( ( ( x == g_board[0] ) && ( x == g_board[8] ) ) ||
|
||||
( ( x == g_board[2] ) && ( x == g_board[6] ) ) ||
|
||||
( ( x == g_board[1] ) && ( x == g_board[7] ) ) ||
|
||||
( ( x == g_board[3] ) && ( x == g_board[5] ) ) )
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
x = g_board[ 5 ];
|
||||
if ( ( ( x == g_board[3] ) && ( x == g_board[4] ) ) ||
|
||||
( ( x == g_board[2] ) && ( x == g_board[8] ) ) )
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
x = g_board[ 6 ];
|
||||
if ( ( ( x == g_board[7] ) && ( x == g_board[8] ) ) ||
|
||||
( ( x == g_board[0] ) && ( x == g_board[3] ) ) ||
|
||||
( ( x == g_board[4] ) && ( x == g_board[2] ) ) )
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
x = g_board[ 7 ];
|
||||
if ( ( ( x == g_board[6] ) && ( x == g_board[8] ) ) ||
|
||||
( ( x == g_board[1] ) && ( x == g_board[4] ) ) )
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
x = g_board[ 8 ];
|
||||
if ( ( ( x == g_board[6] ) && ( x == g_board[7] ) ) ||
|
||||
( ( x == g_board[2] ) && ( x == g_board[5] ) ) ||
|
||||
( ( x == g_board[0] ) && ( x == g_board[4] ) ) )
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return PieceBlank;
|
||||
} /*winner2*/
|
||||
|
||||
#endif
|
||||
|
||||
#if WinMethod == UseLookForWinner
|
||||
|
||||
ttype LookForWinner()
|
||||
{
|
||||
register int p = g_board[0]; /* faster as register int than ttype on 8086 and Z80 */
|
||||
if ( PieceBlank != p )
|
||||
{
|
||||
if ( p == g_board[1] && p == g_board[2] )
|
||||
return p;
|
||||
|
||||
if ( p == g_board[3] && p == g_board[6] )
|
||||
return p;
|
||||
}
|
||||
|
||||
p = g_board[3];
|
||||
if ( PieceBlank != p && p == g_board[4] && p == g_board[5] )
|
||||
return p;
|
||||
|
||||
p = g_board[6];
|
||||
if ( PieceBlank != p && p == g_board[7] && p == g_board[8] )
|
||||
return p;
|
||||
|
||||
p = g_board[1];
|
||||
if ( PieceBlank != p && p == g_board[4] && p == g_board[7] )
|
||||
return p;
|
||||
|
||||
p = g_board[2];
|
||||
if ( PieceBlank != p && p == g_board[5] && p == g_board[8] )
|
||||
return p;
|
||||
|
||||
p = g_board[4];
|
||||
if ( PieceBlank != p )
|
||||
{
|
||||
if ( ( p == g_board[0] ) && ( p == g_board[8] ) )
|
||||
return p;
|
||||
|
||||
if ( ( p == g_board[2] ) && ( p == g_board[6] ) )
|
||||
return p;
|
||||
}
|
||||
|
||||
return PieceBlank;
|
||||
} /*LookForWinner*/
|
||||
|
||||
#endif
|
||||
|
||||
int g_IMoves = 0;
|
||||
|
||||
ttype MinMax( alpha, beta, depth, move ) ttype alpha; ttype beta; ttype depth; ttype move;
|
||||
{
|
||||
ttype pieceMove, score; /* better perf with char than int. out of registers so use stack */
|
||||
register int p, value; /* better perf with these as an int on Z80, 8080, and 8086 */
|
||||
|
||||
g_IMoves++;
|
||||
|
||||
if ( depth >= 4 )
|
||||
{
|
||||
#if WinMethod == UseFunPointers
|
||||
p = ( * winner_functions[ move ] )();
|
||||
#endif
|
||||
#if WinMethod == UseWinner2
|
||||
p = winner2( move );
|
||||
#endif
|
||||
#if WinMethod == UseLookForWinner
|
||||
p = LookForWinner();
|
||||
#endif
|
||||
|
||||
if ( PieceBlank != p )
|
||||
{
|
||||
if ( PieceX == p )
|
||||
return ScoreWin;
|
||||
|
||||
return ScoreLose;
|
||||
}
|
||||
|
||||
if ( 8 == depth )
|
||||
return ScoreTie;
|
||||
}
|
||||
|
||||
if ( depth & 1 )
|
||||
{
|
||||
value = ScoreMin;
|
||||
pieceMove = PieceX;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = ScoreMax;
|
||||
pieceMove = PieceO;
|
||||
}
|
||||
|
||||
for ( p = 0; p < 9; p++ )
|
||||
{
|
||||
if ( PieceBlank == g_board[ p ] )
|
||||
{
|
||||
g_board[p] = pieceMove;
|
||||
score = MinMax( alpha, beta, depth + 1, p );
|
||||
g_board[p] = PieceBlank;
|
||||
|
||||
if ( depth & 1 )
|
||||
{
|
||||
#if WinLosePrune /* #if statements must be in first column for MS C 1.0 */
|
||||
if ( ScoreWin == score )
|
||||
return ScoreWin;
|
||||
#endif
|
||||
|
||||
if ( score > value )
|
||||
{
|
||||
value = score;
|
||||
|
||||
#if ABPrune
|
||||
if ( value >= beta )
|
||||
return value;
|
||||
if ( value > alpha )
|
||||
alpha = value;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if WinLosePrune
|
||||
if ( ScoreLose == score )
|
||||
return ScoreLose;
|
||||
#endif
|
||||
|
||||
if ( score < value )
|
||||
{
|
||||
value = score;
|
||||
|
||||
#if ABPrune
|
||||
if ( value <= alpha )
|
||||
return value;
|
||||
if ( value < beta )
|
||||
beta = value;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
} /*MinMax*/
|
||||
|
||||
long g_Moves = 0;
|
||||
|
||||
int FindSolution( position ) ttype position;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for ( i = 0; i < 9; i++ )
|
||||
g_board[ i ] = PieceBlank;
|
||||
|
||||
g_board[ position ] = PieceX;
|
||||
|
||||
for ( i = 0; i < g_Iterations; i++ )
|
||||
{
|
||||
g_IMoves = 0;
|
||||
MinMax( ScoreMin, ScoreMax, 0, position );
|
||||
g_Moves += g_IMoves; /* do the 4-byte long addition once per loop to save work */
|
||||
}
|
||||
|
||||
return 0;
|
||||
} /*FindSolution*/
|
||||
|
||||
#ifdef CPMTIME
|
||||
|
||||
struct CPMTimeValue
|
||||
{
|
||||
int h, m, s, l;
|
||||
};
|
||||
|
||||
void print_time_now()
|
||||
{
|
||||
/* This CP/M BDOS call of 105 is only implemented in NTVCM -- it's not a standard CP/M 2.2 call */
|
||||
|
||||
struct CPMTimeValue t;
|
||||
t.h = t.m = t.s = t.l = 0;
|
||||
|
||||
bdos( 105, &t );
|
||||
printf( "current time: %02d:%02d:%02d.%02d\n", t.h, t.m, t.s, t.l );
|
||||
} /*print_time_now*/
|
||||
|
||||
long get_ms()
|
||||
{
|
||||
/* This CP/M BDOS call of 105 is only implemented in NTVCM -- it's not a standard CP/M 2.2 call */
|
||||
|
||||
long h, m, s, l;
|
||||
struct CPMTimeValue t;
|
||||
t.h = t.m = t.s = t.l = 0;
|
||||
|
||||
bdos( 105, &t );
|
||||
h = t.h;
|
||||
m = t.m;
|
||||
s = t.s;
|
||||
l = t.l;
|
||||
|
||||
return h * 3600000 + m * 60000 + s * 1000 + l * 10;
|
||||
} /*get_ms*/
|
||||
|
||||
#else /* no elif with old compilers */
|
||||
|
||||
#ifdef DOSTIME
|
||||
|
||||
void print_time_now()
|
||||
{
|
||||
/* Make a DOS interrupt call to get the time */
|
||||
|
||||
union REGS wrIn, wrOut;
|
||||
|
||||
wrIn.h.ah = 0x2c;
|
||||
intdos( &wrIn, &wrOut );
|
||||
printf( "current time: %02d:%02d:%02d.%02d\n", wrOut.h.ch, wrOut.h.cl, wrOut.h.dh, wrOut.h.dl );
|
||||
fflush( stdout );
|
||||
} /*print_time_now*/
|
||||
|
||||
long get_ms()
|
||||
{
|
||||
/* this function takes about 3 milliseconds on the original IBM PC */
|
||||
|
||||
long h, m, s, l;
|
||||
union REGS wrIn, wrOut;
|
||||
|
||||
wrIn.h.ah = 0x2c;
|
||||
intdos( &wrIn, &wrOut );
|
||||
|
||||
h = wrOut.h.ch;
|
||||
m = wrOut.h.cl;
|
||||
s = wrOut.h.dh;
|
||||
l = wrOut.h.dl;
|
||||
|
||||
return h * 3600000 + m * 60000 + s * 1000 + l * 10;
|
||||
} /*get_ms*/
|
||||
|
||||
#else
|
||||
|
||||
/* must do this on actual CP/M machines */
|
||||
|
||||
int print_time_now() { return 0; }
|
||||
long get_ms() { return 0; }
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int main( argc, argv ) int argc; char * argv[];
|
||||
{
|
||||
long start_time, end_time;
|
||||
|
||||
if ( 2 == argc )
|
||||
sscanf( argv[ 1 ], "%d", &g_Iterations ); /* no atoi in MS C 1.0 */
|
||||
|
||||
start_time = get_ms();
|
||||
|
||||
FindSolution( 0 );
|
||||
FindSolution( 1 );
|
||||
FindSolution( 4 );
|
||||
|
||||
end_time = get_ms();
|
||||
|
||||
printf( "runtime in ms: %ld\n", end_time - start_time );
|
||||
printf( "move count: %ld\n", g_Moves ); /* 6493 * g_Iterations */
|
||||
printf( "iteration count: %d\n", g_Iterations );
|
||||
printf( "method: %s\n",
|
||||
( WinMethod == UseFunPointers ) ? "function pointers" :
|
||||
( WinMethod == UseWinner2 ) ? "winner2" :
|
||||
( WinMethod == UseLookForWinner ) ? "look for winner" :
|
||||
"invalid method" );
|
||||
return 0;
|
||||
} /*main*/
|
||||
|
21
Mark Williams MWS v4/INCLUDE/ACCESS.H
Normal file
21
Mark Williams MWS v4/INCLUDE/ACCESS.H
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modes for the access
|
||||
* system call.
|
||||
*/
|
||||
|
||||
#define AREAD 04 /* Test for read */
|
||||
#define AWRITE 02 /* Test for write */
|
||||
#define AEXEC 01 /* Test for execute */
|
||||
#define AAPPND AWRITE /* Test for append */
|
||||
|
||||
/* Dummy directory modes */
|
||||
#define ALIST AREAD /* List directory */
|
||||
#define ADEL AWRITE /* Delete directory entry */
|
||||
#define ASRCH AEXEC /* Search directory */
|
||||
#define ACREAT AAPPND /* Create directory entry */
|
24
Mark Williams MWS v4/INCLUDE/ASSERT.H
Normal file
24
Mark Williams MWS v4/INCLUDE/ASSERT.H
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* assert.h
|
||||
* Assertion verifier.
|
||||
*/
|
||||
|
||||
#ifndef ASSERT_H
|
||||
#define ASSERT_H
|
||||
|
||||
#if NDEBUG
|
||||
#define assert(p)
|
||||
#else
|
||||
#define assert(p) if(!(p)){printf("%s: %d: assert(%s) failed.\n",\
|
||||
__FILE__, __LINE__, #p);exit(1);}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* end of assert.h */
|
41
Mark Williams MWS v4/INCLUDE/CTYPE.H
Normal file
41
Mark Williams MWS v4/INCLUDE/CTYPE.H
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Character type classification routines.
|
||||
* This is implemented by table lookup.
|
||||
*/
|
||||
|
||||
#ifndef CTYPE_H
|
||||
#define CTYPE_H
|
||||
|
||||
extern char _ctype[];
|
||||
|
||||
/* Bits classifications */
|
||||
#define _U 01 /* Upper case alphabetic */
|
||||
#define _L 02 /* Lower case alphabetic */
|
||||
#define _A (_U|_L) /* Alphabetic */
|
||||
#define _D 010 /* Digit */
|
||||
#define _S 020 /* White space character */
|
||||
#define _P 040 /* Punctuation character */
|
||||
#define _C 0100 /* Control character */
|
||||
#define _X 0200 /* Printable but nothing else */
|
||||
|
||||
#define isalpha(c) ((_ctype+1)[(c)]&_A)
|
||||
#define isupper(c) ((_ctype+1)[(c)]&_U)
|
||||
#define islower(c) ((_ctype+1)[(c)]&_L)
|
||||
#define isdigit(c) ((_ctype+1)[(c)]&_D)
|
||||
#define isalnum(c) ((_ctype+1)[(c)]&(_A|_D))
|
||||
#define isspace(c) ((_ctype+1)[(c)]&_S)
|
||||
#define ispunct(c) ((_ctype+1)[(c)]&_P)
|
||||
#define isprint(c) ((_ctype+1)[(c)]&(_P|_X|_A|_D))
|
||||
#define iscntrl(c) ((_ctype+1)[(c)]&_C)
|
||||
#define isascii(c) (((c)&~0177)==0)
|
||||
#define _tolower(c) ((c)|('a'-'A'))
|
||||
#define _toupper(c) ((c)&~('a'-'A'))
|
||||
#define toascii(c) ((c)&0177)
|
||||
|
||||
#endif
|
186
Mark Williams MWS v4/INCLUDE/DOS.H
Normal file
186
Mark Williams MWS v4/INCLUDE/DOS.H
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Definitions for accessing MS-DOS and 8086 functions.
|
||||
*/
|
||||
|
||||
#ifndef DOS_H
|
||||
#define DOS_H
|
||||
|
||||
#define L2RECSZ 9 /* log base 2 of record size */
|
||||
#define RECSIZ (1<<L2RECSZ) /* Record size */
|
||||
#define TTYSIZ 128 /* # of bytes, CON: line buffer */
|
||||
#define BAD 0xFF /* Bad status, open, make */
|
||||
|
||||
#define SOK 0x00 /* All ok */
|
||||
#define SNOREC 0x01 /* Reading unwritten data */
|
||||
#define SOVER 0x02 /* Disc buffer overflows segment */
|
||||
#define SPART 0x03 /* Partial record read */
|
||||
|
||||
/*
|
||||
* DOS functions.
|
||||
*/
|
||||
#define EXIT 0x0000 /* Program terminate */
|
||||
#define CONIN 0x0100 /* Console input */
|
||||
#define CONOUT 0x0200 /* Console output */
|
||||
#define RDRIN 0x0300 /* Get byte from reader */
|
||||
#define AUXIN 0x0300 /* Alternative name */
|
||||
#define PUNOUT 0x0400 /* Put byte to punch */
|
||||
#define AUXOUT 0x0400 /* Alternative name */
|
||||
#define LSTOUT 0x0500 /* Put byte to printer */
|
||||
#define CONDIO 0x0600 /* Direct console I/O */
|
||||
#define DIRCON 0x0600 /* Old synonym */
|
||||
#define CONRAW 0x0700 /* Console input, no echo, no int */
|
||||
#define CON_E 0x0800 /* Console input, no echo */
|
||||
#define PUTSTR 0x0900 /* Put `$' delimited string */
|
||||
#define BUFCON 0x0A00 /* Buffered console read */
|
||||
#define CONSTAT 0x0B00 /* Console status */
|
||||
#define CLRIN 0x0C01 /* Console clear then input */
|
||||
#define CLRDIO 0x0C06 /* Console clear then direct I/O */
|
||||
#define CLRRAW 0x0C07 /* Console clear then raw input */
|
||||
#define CLR_E 0x0C08 /* Console clear then input no echo */
|
||||
#define CLRBUF 0x0C0A /* Console clear then buffered input*/
|
||||
#define RESDSK 0x0D00 /* Reset disc system */
|
||||
#define SELDSK 0x0E00 /* Select disc */
|
||||
#define OPENF 0x0F00 /* Open file */
|
||||
#define CLOSEF 0x1000 /* Close file */
|
||||
#define FFIRST 0x1100 /* Find first */
|
||||
#define FNEXT 0x1200 /* Find next */
|
||||
#define DELETEF 0x1300 /* Delete file */
|
||||
#define READS 0x1400 /* Read sequential */
|
||||
#define WRITES 0x1500 /* Write sequential */
|
||||
#define MAKEF 0x1600 /* Make file */
|
||||
#define CREATEF 0x1600 /* Create file (synonym) */
|
||||
#define RENAMEF 0x1700 /* Rename file */
|
||||
#define GETDISK 0x1900 /* Get current disk */
|
||||
#define SETDMAO 0x1A00 /* Set DMA offset */
|
||||
#define SETDTA 0x1A00 /* Set disk transfer address */
|
||||
#define GETALTI 0x1B00 /* Get allocation table info */
|
||||
#define READR 0x2100 /* Read random */
|
||||
#define WRITER 0x2200 /* Write random */
|
||||
#define SIZEF 0x2300 /* Compute file size */
|
||||
#define SETRREC 0x2400 /* Set random record */
|
||||
#define SETINT 0x2500 /* Set interrupt vector */
|
||||
#define PROGSEG 0x2600 /* Create program segment */
|
||||
#define READB 0x2700 /* Random block read */
|
||||
#define WRITEB 0x2800 /* Random block write */
|
||||
#define GETDATE 0x2A00 /* Get date */
|
||||
#define SETDATE 0x2B00 /* Set date */
|
||||
#define GETTIME 0x2C00 /* Get time */
|
||||
#define SETTIME 0x2D00 /* Set time */
|
||||
#define VERIFY 0x2E00 /* Disk write verification */
|
||||
#define GETDTA 0x2F00 /* Get address of disk transfer adr */
|
||||
#define GETVER 0x3000 /* Get DOS version number */
|
||||
#define TERMRES 0x3100 /* Terminate and remain resident */
|
||||
#define CTLBCHK 0x3300 /* Ctrl-break check */
|
||||
#define GETVEC 0x3500 /* Get interrupt vector */
|
||||
#define GETFREE 0x3600 /* Get free disk space */
|
||||
#define GETCDI 0x3800 /* Get country dependent info */
|
||||
#define MKDIR 0x3900 /* Create a sub-directory */
|
||||
#define RMDIR 0x3A00 /* Remove a sub-directory */
|
||||
#define CHDIR 0x3B00 /* Change the current directory */
|
||||
#define CREATH 0x3C00 /* Create a file */
|
||||
#define OPENH 0x3D00 /* Open a file */
|
||||
#define CLOSEH 0x3E00 /* Close a file */
|
||||
#define READH 0x3F00 /* Read from a file or device */
|
||||
#define WRITEH 0x4000 /* Write to a file or device */
|
||||
#define DELETE 0x4100 /* Delete a file */
|
||||
#define LSEEKH 0x4200 /* Move file read/write pointer */
|
||||
#define CHMOD 0x4300 /* Change file mode */
|
||||
#define IOCTLH 0x4400 /* I/O control for devices */
|
||||
#define DUPH 0x4500 /* Duplicate a file handle */
|
||||
#define FDUPH 0x4600 /* Force a duplicate of handle */
|
||||
#define GETCDIR 0x4700 /* Get current directory */
|
||||
#define ALLOC 0x4800 /* Allocate memory */
|
||||
#define FREE 0x4900 /* Free allocated memory */
|
||||
#define SETBLK 0x4A00 /* Modify allocated memory blocks */
|
||||
#define EXEC 0x4B00 /* Load or execute a program */
|
||||
#define NEXIT 0x4C00 /* Terminate a process */
|
||||
#define WAIT 0x4D00 /* Get return code of subprocess */
|
||||
#define NFFIRST 0x4E00 /* DOS 2.0 find first */
|
||||
#define NFNEXT 0x4F00 /* DOS 2.0 find next */
|
||||
#define GETVST 0x5400 /* Get verify state */
|
||||
#define RENAME 0x5600 /* Rename a file */
|
||||
#define GSDT 0x5700 /* Get/set a file's date and time */
|
||||
|
||||
#define ON 1 /* for verify */
|
||||
#define OFF 0 /* for verify */
|
||||
|
||||
/*
|
||||
* Function declarations for DOS functions.
|
||||
* Functions dos(), dosb(), dosc(), and dosd() have been replaced
|
||||
* by the more generalized function intcall(). The old functions
|
||||
* are retained in the library but will be retracted in a future release.
|
||||
* If you use an old DOS call, you must declare it.
|
||||
*/
|
||||
#define DOSINT 0x21 /* DOS interrupt */
|
||||
/*
|
||||
extern int dos();
|
||||
extern int dosb();
|
||||
extern long dosc();
|
||||
extern long dosd();
|
||||
*/
|
||||
|
||||
/*
|
||||
* Type definition for DOS file control block.
|
||||
* Assumes all elements get byte alignment.
|
||||
* FCBs are no longer necessary with DOS 2.0;
|
||||
* they are replaced by file handles.
|
||||
*/
|
||||
typedef struct fcb_t {
|
||||
unsigned char f_drive; /* drive code */
|
||||
char f_name[8], /* name */
|
||||
f_ext[3]; /* extension */
|
||||
unsigned short f_block; /* current block (=128 records) */
|
||||
unsigned short f_recsz; /* record size in bytes (=1) */
|
||||
unsigned long f_size; /* file size in bytes (system) */
|
||||
unsigned int f_date; /* modification date (system) */
|
||||
char f_sys[10]; /* for system use */
|
||||
unsigned char f_rec; /* current record in block */
|
||||
unsigned long f_seek; /* random record position */
|
||||
} fcb_t;
|
||||
|
||||
/*
|
||||
* The following masks test the state of the processor carry or zero flags.
|
||||
*/
|
||||
#define F_CF 0x0001 /* Carry flag mask */
|
||||
#define F_ZF 0x0040 /* Zero flag mask */
|
||||
|
||||
/*
|
||||
* A structure of this type is passed to intcall().
|
||||
*/
|
||||
#ifndef CSD
|
||||
struct reg {
|
||||
unsigned r_ax;
|
||||
unsigned r_bx;
|
||||
unsigned r_cx;
|
||||
unsigned r_dx;
|
||||
unsigned r_si;
|
||||
unsigned r_di;
|
||||
unsigned r_ds;
|
||||
unsigned r_es;
|
||||
unsigned r_flags;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These macros can be used to store or extract pointers
|
||||
* from a reg structure (defined above).
|
||||
* These are LARGE/SMALL model independent.
|
||||
*/
|
||||
#ifdef LARGE
|
||||
#define PTR(x) (x)
|
||||
#define ptoreg(t, off, seg, ptr) ((off)=(long)(ptr),(seg)=((long)ptr)>>16)
|
||||
#define regtop(off, seg, ptr) ((ptr)=(char *)((long)(off)+((long)(seg)<<16)))
|
||||
#else
|
||||
extern unsigned dsreg(), esreg(), csreg(), ssreg();
|
||||
#define PTR(x) (x), dsreg()
|
||||
#define ptoreg(t, off, seg, ptr) ((off)=(int)(ptr),(seg)=(t)())
|
||||
#define regtop(off, seg, ptr) ((ptr)=(char *)(off))
|
||||
#endif
|
||||
|
||||
#endif
|
52
Mark Williams MWS v4/INCLUDE/DOSFIND.H
Normal file
52
Mark Williams MWS v4/INCLUDE/DOSFIND.H
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MSDOS dosfind.h.
|
||||
*/
|
||||
|
||||
#ifndef DOSFIND_H
|
||||
#define DOSFIND_H
|
||||
|
||||
#define MAXDOSDIR 64 /* Max directory path length */
|
||||
|
||||
/*
|
||||
* MSDOS time and date.
|
||||
* See DOS Technical Reference Manual, pp. 4-6, 4-7.
|
||||
*/
|
||||
struct dostime {
|
||||
unsigned int dos_twosec:5; /* Seconds/2 0-29 */
|
||||
unsigned int dos_minute:6; /* Minute 0-59 */
|
||||
unsigned int dos_hour :5; /* Hour 0-23 */
|
||||
unsigned int dos_day :5; /* Day 1-31 */
|
||||
unsigned int dos_month :4; /* Month 1-12 */
|
||||
unsigned int dos_year :7; /* Year-1980 0-199 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure returned by DOS calls NFFIRST and NFNEXT.
|
||||
* See DOS Technical Reference Manual, pp. 5-46, 4-6.
|
||||
*/
|
||||
struct dosfind {
|
||||
char fnd_info[21]; /* Reserved for DOS */
|
||||
char fnd_attr; /* File attribute */
|
||||
struct dostime fnd_time; /* MSDOS time and date */
|
||||
long fnd_size; /* File size */
|
||||
char fnd_name[13]; /* Filename without dir */
|
||||
};
|
||||
|
||||
/*
|
||||
* MSDOS mode bits (attributes).
|
||||
* See DOS Technical Reference Manual, pp. 4-5, 4-6.
|
||||
*/
|
||||
#define S_RDONLY 0x0001 /* Readonly */
|
||||
#define S_HIDDEN 0x0002 /* Hidden */
|
||||
#define S_SYSTEM 0x0004 /* System */
|
||||
#define S_VOLUME 0x0008 /* Volume label */
|
||||
#define S_SUBDIR 0x0010 /* Subdirectory */
|
||||
#define S_ARCHIV 0x0020 /* Archive bit */
|
||||
|
||||
#endif
|
69
Mark Williams MWS v4/INCLUDE/LARGES.H
Normal file
69
Mark Williams MWS v4/INCLUDE/LARGES.H
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/* larges.h */
|
||||
/* Model-dependent definitions for i8086 assembler sources. */
|
||||
|
||||
#ifndef LARGES_H
|
||||
#define LARGES_H
|
||||
|
||||
#if LARGE
|
||||
#define LARGECODE 1
|
||||
#define LARGEDATA 1
|
||||
#endif
|
||||
|
||||
#if LARGECODE
|
||||
/* LARGE code: calls, jumps and returns are far, code pointer is 4 bytes. */
|
||||
#define Gcall xcall
|
||||
#define Gicall xicall
|
||||
#define Gijmp xijmp
|
||||
#define Gjmp xjmp
|
||||
#define Gptr .dword
|
||||
#define Gret xret
|
||||
#define CPL 4
|
||||
#else
|
||||
/* SMALL code: calls, jumps and returns are near, code pointer is 2 bytes. */
|
||||
#define Gcall call
|
||||
#define Gicall icall
|
||||
#define Gijmp ijmp
|
||||
#define Gjmp jmp
|
||||
#define Gptr .word
|
||||
#define Gret ret
|
||||
#define CPL 2
|
||||
#endif
|
||||
|
||||
#if LARGEDATA
|
||||
/* LARGE data: segment registers must be loaded to map data, escapes required. */
|
||||
/* Data pointer is 4 bytes. */
|
||||
#define Gdptr .dword
|
||||
#define Lds lds
|
||||
#define Les les
|
||||
#define Map(sreg, temp, val) mov temp, val; mov sreg, temp
|
||||
#define Pes es:
|
||||
#define Pss ss:
|
||||
#define DPL 4
|
||||
#else
|
||||
/* SMALL data: DS==ES==SS, no escapes required. */
|
||||
/* Data pointer is 2 bytes. */
|
||||
#define Gdptr .word
|
||||
#define Lds mov
|
||||
#define Les mov
|
||||
#define Map(sreg, temp, val)
|
||||
#define Pes
|
||||
#define Pss
|
||||
#define DPL 2
|
||||
#endif
|
||||
|
||||
/* Function entry and exit: preserve C register variables, initialize BP. */
|
||||
/* No automatics allocated. */
|
||||
#define Enter(x) .globl x; x: push si; push di; push bp; mov bp, sp
|
||||
#define Leave pop bp; pop di; pop si; Gret
|
||||
#define LEFTARG CPL+6
|
||||
|
||||
#define RASIZE CPL
|
||||
#define PTRSIZE DPL
|
||||
|
||||
#endif
|
89
Mark Williams MWS v4/INCLUDE/MATH.H
Normal file
89
Mark Williams MWS v4/INCLUDE/MATH.H
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Definitions for math library.
|
||||
*/
|
||||
#ifndef MATH_H
|
||||
#define MATH_H
|
||||
|
||||
#define HUGE_VAL 1.79769313486231e+308 /* Infinity */
|
||||
#define L2I 1023.0 /* log2(infinity) */
|
||||
#define L10P 16 /* log10(precision) */
|
||||
#define L2L2P 6 /* log2(log2(precision)) */
|
||||
|
||||
/*
|
||||
* Error return values.
|
||||
*/
|
||||
#define EBON 0 /* Succesful */
|
||||
#define EDOM 33 /* Domain error */
|
||||
#define ERANGE 34 /* Result too large */
|
||||
|
||||
/*
|
||||
* Constants.
|
||||
*/
|
||||
#define PI 0.31415926535897932e+01
|
||||
#define SQRT2 0.14142135623730950e+01
|
||||
#define LOG2B10 0.30102999566398119e+00
|
||||
#define LOG10BE 0.23025850929940456e+01
|
||||
#define LOG10B2 0.33219280948873623e+01
|
||||
#define LOGEB2 0.14426950408889634e+01
|
||||
|
||||
/*
|
||||
* Complex variables.
|
||||
*/
|
||||
typedef struct cpx {
|
||||
double z_r;
|
||||
double z_i;
|
||||
} CPX;
|
||||
|
||||
/*
|
||||
* Status from routines.
|
||||
*/
|
||||
extern int errno;
|
||||
|
||||
/*
|
||||
* Internal functions.
|
||||
*/
|
||||
double _pol();
|
||||
double _two();
|
||||
|
||||
/*
|
||||
* Math library functions.
|
||||
*/
|
||||
double acos();
|
||||
double asin();
|
||||
double atan();
|
||||
double atan2();
|
||||
double cabs();
|
||||
double ceil();
|
||||
double cos();
|
||||
double cosh();
|
||||
double exp();
|
||||
double fabs();
|
||||
double floor();
|
||||
double hypot();
|
||||
double j0();
|
||||
double j1();
|
||||
double jn();
|
||||
double log();
|
||||
double log10();
|
||||
double pow();
|
||||
double sin();
|
||||
double sinh();
|
||||
double sqrt();
|
||||
double tan();
|
||||
double tanh();
|
||||
|
||||
/*
|
||||
* C library floating point functions.
|
||||
*/
|
||||
double atof();
|
||||
double frexp();
|
||||
double ldexp();
|
||||
double modf();
|
||||
|
||||
#endif
|
29
Mark Williams MWS v4/INCLUDE/MTYPE.H
Normal file
29
Mark Williams MWS v4/INCLUDE/MTYPE.H
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Machine types.
|
||||
*/
|
||||
#ifndef MTYPE_H
|
||||
#define MTYPE_H
|
||||
|
||||
/*
|
||||
* Type definitions.
|
||||
*/
|
||||
#define M_PDP11 1 /* PDP-11 */
|
||||
#define M_VAX 2 /* VAX */
|
||||
#define M_360 3 /* IBM 360 */
|
||||
#define M_Z8001 4 /* Zilog 8001 (segmented) */
|
||||
#define M_Z8002 5 /* Zilog 8002 (unsegmented) */
|
||||
#define M_8086 6 /* Intel 8086 */
|
||||
#define M_8080 7 /* Intel 8080 */
|
||||
#define M_6800 8 /* Motorola 6800 */
|
||||
#define M_6809 9 /* Motorola 6809 */
|
||||
#define M_68000 10 /* Motorola 68000 */
|
||||
#define M_NS16000 11 /* National Semiconductor 16000 */
|
||||
#define M_LRG8086 12 /* Intel 8086 Large Model */
|
||||
|
||||
#endif
|
42
Mark Williams MWS v4/INCLUDE/PATH.H
Normal file
42
Mark Williams MWS v4/INCLUDE/PATH.H
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* path.h
|
||||
* For COHERENT, GEMDOS, MSDOS.
|
||||
*/
|
||||
|
||||
#include <access.h>
|
||||
|
||||
#if COHERENT
|
||||
#define PATHSEP '/' /* Path name component separator */
|
||||
#define PATHSEPSTRING "/" /* PATHSEP as a string */
|
||||
#define LISTSEP ':' /* Search list component separator */
|
||||
#define DEFPATH ":/bin:/usr/bin"
|
||||
#define DEFLIBPATH "/lib:/usr/lib"
|
||||
#define DEFSHELL "sh"
|
||||
#endif
|
||||
|
||||
#if GEMDOS
|
||||
#define PATHSEP '\\'
|
||||
#define PATHSEPSTRING "\\"
|
||||
#define LISTSEP ','
|
||||
#define DEFPATH ",\\bin,\\usr\\bin"
|
||||
#define DEFLIBPATH "\\lib,,\\usr\\lib"
|
||||
#define DEFSHELL "msh.prg"
|
||||
#endif
|
||||
|
||||
#if MSDOS
|
||||
#define PATHSEP '\\'
|
||||
#define PATHSEPSTRING "\\"
|
||||
#define LISTSEP ';'
|
||||
#define DEFPATH ";\\bin;\\usr\\bin"
|
||||
#define DEFLIBPATH "\\lib;\\usr\\lib"
|
||||
#define DEFSHELL "command.com"
|
||||
#endif
|
||||
|
||||
#define MAXPATH 128 /* Size of static pathname buffer */
|
||||
extern char *path(); /* (char *path, *file; int mode;) */
|
26
Mark Williams MWS v4/INCLUDE/SETJMP.H
Normal file
26
Mark Williams MWS v4/INCLUDE/SETJMP.H
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MSDOS setjmp.h.
|
||||
*/
|
||||
#ifndef SETJMP_H
|
||||
#define SETJMP_H
|
||||
|
||||
/*
|
||||
* This header defines the type used to
|
||||
* save state for setjmp() and longjmp().
|
||||
* Saves sp, bp and the return pc. The
|
||||
* return PC is 2 words long in large model.
|
||||
*/
|
||||
|
||||
#ifdef LARGE
|
||||
typedef int jmp_buf[4];
|
||||
#else
|
||||
typedef int jmp_buf[3];
|
||||
#endif
|
||||
|
||||
#endif
|
38
Mark Williams MWS v4/INCLUDE/STAT.H
Normal file
38
Mark Williams MWS v4/INCLUDE/STAT.H
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MSDOS stat.h.
|
||||
*/
|
||||
#ifndef STAT_H
|
||||
#define STAT_H
|
||||
|
||||
#include <dosfind.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
* Structure returned by stat.
|
||||
* The field names are compatible with COHERENT stat.h.
|
||||
* COHERENT stat.h fields which are meaningless under MSDOS are not included.
|
||||
* The st_dostime of the root is always 00:00 of 1/1/80.
|
||||
*/
|
||||
struct stat {
|
||||
unsigned short st_mode; /* Mode */
|
||||
long st_size; /* Size */
|
||||
struct dostime st_dostime; /* MSDOS time and date */
|
||||
time_t st_mtime; /* COHERENT modification time */
|
||||
};
|
||||
|
||||
/*
|
||||
* COHERENT-compatible mode bits.
|
||||
*/
|
||||
#define S_IFMT 0x0300 /* Type */
|
||||
#define S_IFDIR 0x0100 /* Directory */
|
||||
#define S_IFREG 0x0200 /* Regular */
|
||||
#define S_IREAD 0x0400 /* Read permission, always 1 */
|
||||
#define S_IWRITE 0x0800 /* Write permission */
|
||||
|
||||
#endif
|
83
Mark Williams MWS v4/INCLUDE/STDIO.H
Normal file
83
Mark Williams MWS v4/INCLUDE/STDIO.H
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Standard I/O library, msdos
|
||||
*/
|
||||
|
||||
#ifndef STDIO_H
|
||||
#define STDIO_H
|
||||
|
||||
typedef struct FILE {
|
||||
unsigned char *_cp, /* current character ptr */
|
||||
*_dp, /* ptr to start of data in buffer */
|
||||
*_bp; /* buffer pointer */
|
||||
int _cc; /* character count */
|
||||
int (*_gt)(), /* getc function */
|
||||
(*_pt)(); /* putc function */
|
||||
int _ff; /* flags; see below */
|
||||
char _fd; /* file descriptor (reqd by reopen) */
|
||||
int _uc; /* ungot char */
|
||||
} FILE;
|
||||
#endif
|
||||
|
||||
#define NULL ((char *)0)
|
||||
#define EOF (-1)
|
||||
#define BUFSIZ (1<<9)
|
||||
#define CTRLZ 26
|
||||
#define _NFILE 30
|
||||
|
||||
extern FILE _stdin, _stdout, _stderr, _stdaux, _stdprn, *_fp[_NFILE];
|
||||
|
||||
/* Flags in _ff */
|
||||
#define _FINUSE 0x01
|
||||
#define _FSTBUF 0x02 /* setbuf was called */
|
||||
#define _FUNGOT 0x04 /* ungotten char present */
|
||||
#define _FEOF 0x08
|
||||
#define _FERR 0x10
|
||||
#define _FASCII 0x20 /* Ascii mode (default) */
|
||||
#define _FWRITE 0x40 /* File is opened for writing */
|
||||
#define _FDONTC 0x80 /* Don't close */
|
||||
|
||||
#define _ep(fp) ((fp)->_bp+BUFSIZ)
|
||||
#define _isdev(fd) (_devinfo(fd)&0x80)
|
||||
#define _setbinary(fp) ((fp)->_ff &= ~_FASCII)
|
||||
|
||||
char *gets();
|
||||
char *fgets();
|
||||
FILE *fopen();
|
||||
FILE *freopen();
|
||||
FILE *fdopen();
|
||||
FILE *popen();
|
||||
FILE *_stropen();
|
||||
long ftell();
|
||||
void puts();
|
||||
void fputs();
|
||||
void setbuf();
|
||||
char *malloc();
|
||||
char *sbrk();
|
||||
|
||||
#define getchar() getc(stdin)
|
||||
#define getc(fp) ((*(fp)->_gt)(fp))
|
||||
#define putchar(c) putc(c, stdout)
|
||||
#define putc(c,fp) ((*(fp)->_pt)(c,fp))
|
||||
#define getw(fp) (fgetw(fp))
|
||||
#define putw(w,fp) (fputw(w,fp))
|
||||
#define feof(fp) ((fp)->_ff&(_FEOF|_FERR))
|
||||
#define ferror(fp) ((fp)->_ff&_FERR)
|
||||
#define clearerr(fp) ((fp)->_ff &= ~(_FERR|_FEOF))
|
||||
#define fileno(fp) ((fp)->_fd)
|
||||
#define wdleng() (16)
|
||||
|
||||
#define stdin (&_stdin)
|
||||
#define stdout (&_stdout)
|
||||
#define stderr (&_stderr)
|
||||
#define stdaux (&_stdaux)
|
||||
#define stdprn (&_stdprn)
|
||||
|
||||
/* The following definitions are for S-V style tmpnam() and tempnam(). */
|
||||
#define L_tmpnam 64
|
||||
#define P_tmpdir "\\tmp"
|
169
Mark Williams MWS v4/INCLUDE/TIME.H
Normal file
169
Mark Williams MWS v4/INCLUDE/TIME.H
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* time.h -- time and date services.
|
||||
*/
|
||||
|
||||
#ifndef TIME_H
|
||||
#define TIME_H
|
||||
|
||||
/*
|
||||
* Clock function for process timing.
|
||||
* This returns raw ticks, CLK_TCK per second,
|
||||
* for the process's personal interpretation.
|
||||
*/
|
||||
#if GEMDOS
|
||||
#define CLK_TCK 200 /* 200 hz timer */
|
||||
typedef unsigned long clock_t; /* 200 hz timer ticks */
|
||||
#endif
|
||||
#if MSDOS
|
||||
#define CLK_TCK 18.20648193359375 /* 1193180/65536 counts/sec */
|
||||
typedef unsigned long clock_t; /* Timer ticks */
|
||||
#endif
|
||||
clock_t clock(); /* (void) */
|
||||
|
||||
/*
|
||||
* Time difference as a double.
|
||||
*/
|
||||
double difftime(); /* (time_t time1, time_t time2) */
|
||||
|
||||
/*
|
||||
* Time function for calendar time.
|
||||
* Draft ANSI standard leaves time_t implementation-dependent:
|
||||
* ours is time_t is 32 bits of seconds,
|
||||
* beginning January 1, 1970, 0h00m00s GMT.
|
||||
*/
|
||||
typedef unsigned long time_t;
|
||||
time_t time(); /* (time_t *timer) */
|
||||
|
||||
/*
|
||||
* Time fields structure: struct "tm",
|
||||
* aliased to "tm_t" for neatness.
|
||||
* This structure is filled in by localtime() and gmtime().
|
||||
* Note that "tm_mon" is 0 through 11,
|
||||
* and "tm_year" is number of years since 1900.
|
||||
*/
|
||||
typedef struct tm {
|
||||
int tm_sec; /* Seconds (0-59) */
|
||||
int tm_min; /* Minutes (0-59) */
|
||||
int tm_hour; /* Hours (0-23); 0 = midnight */
|
||||
int tm_mday; /* Day of month (1..28,29,30,31) */
|
||||
int tm_mon; /* Month (0-11); 0 = January */
|
||||
int tm_year; /* Year AD since 1900 */
|
||||
int tm_wday; /* Day of week (0-6): 0 = Sunday */
|
||||
int tm_yday; /* Day of year (0-365,366) */
|
||||
int tm_isdst; /* Daylight savings time flag: */
|
||||
/* Non-standard, they make negative==NA */
|
||||
} tm_t;
|
||||
|
||||
/*
|
||||
* Calendar time conversion functions:
|
||||
*/
|
||||
char *asctime(); /* tm_t fields to ascii string */
|
||||
char *ctime(); /* time_t * to ascii string */
|
||||
tm_t *gmtime(); /* time_t * to standard time fields */
|
||||
tm_t *localtime(); /* time_t * to local time fields */
|
||||
|
||||
/*
|
||||
* Mark Williams extensions to the draft ANSI standard:
|
||||
*/
|
||||
/*
|
||||
* Timezone and daylight savings time implementation.
|
||||
* localtime() parses the TIMEZONE environmental parameter
|
||||
* or default values to set timezone, tzname[][], and daylight
|
||||
* savings time parameters.
|
||||
*/
|
||||
extern long timezone; /* Seconds subtracted from standard time */
|
||||
extern int dstadjust; /* Seconds added to local standard */
|
||||
extern char tzname[2][32]; /* Names of local standard and daylight zone */
|
||||
|
||||
/*
|
||||
* Calendar utilities:
|
||||
* Gregorian calendar counted from October 1582; Julian calendar
|
||||
* before that.
|
||||
* The month of Gregorian adjustment isn't right.
|
||||
*/
|
||||
int isleapyear(); /* (year) AD */
|
||||
int dayspermonth(); /* (month, year) [1..12], AD */
|
||||
|
||||
/*
|
||||
* Julian day structure consists of the days and seconds since
|
||||
* Greenwich mean noon of January 1st 4713 BC.
|
||||
* COHERENT time_t is a variation of Julian time:
|
||||
* it counts seconds from Julian day 2,440,587.5 (January 1, 1970).
|
||||
*/
|
||||
typedef struct { long j_d, j_s; } jday_t;
|
||||
#define COHEPOCH 2440587L /* Julian day 1969.12.31 12h00m00s */
|
||||
|
||||
jday_t time_to_jday(); /* COHERENT time into Julian date */
|
||||
time_t jday_to_time(); /* Julian date to coherent time */
|
||||
jday_t tm_to_jday(); /* tm_t structure into Julian date */
|
||||
tm_t *jday_to_tm(); /* Julian date into tm_t structure */
|
||||
|
||||
#if GEMDOS
|
||||
/*
|
||||
* Atari ST support.
|
||||
* TOS time & date: packed binary date and time
|
||||
* A "tetd_t" object is the object of xbios functions Gettime() and Settime().
|
||||
* The halves are the objects of gemdos Tgettime(), Tgetdate(), Tsettime(),
|
||||
* Tsetdate().
|
||||
* The file time and date stamps that Fdatime(), Fsfirst(),
|
||||
* and Fsnext() maintain are rtetd_t format:
|
||||
* they reverse the order of the time
|
||||
* and date fields from the utetd_t format used by Gettime() and Settime().
|
||||
*/
|
||||
typedef unsigned long tetd_t;
|
||||
typedef struct { unsigned g_date, g_time; } utetd_t;
|
||||
typedef struct { unsigned g_rtime, g_rdate; } rtetd_t;
|
||||
|
||||
tetd_t tm_to_tetd(); /* tm_t structure into TOS time and date */
|
||||
tm_t *tetd_to_tm(); /* TOS time and date into tm_t */
|
||||
#define tetd_to_jday(td) tm_to_jday(tetd_to_tm(td))
|
||||
#define jday_to_tetd(jd) tm_to_tetd(jday_to_tm(jd))
|
||||
#define tetd_to_time(td) jday_to_time(tetd_to_jday(td))
|
||||
#define time_to_tetd(t) jday_to_tetd(time_to_jday(t))
|
||||
|
||||
/*
|
||||
* The intelligent keyboard keeps time to the second
|
||||
* which neither xbios or gemdos support.
|
||||
* These two functions operate on tm_t objects.
|
||||
*/
|
||||
tm_t *Kgettime(); /* (void) */
|
||||
int Ksettime(); /* (tm_t *timep) */
|
||||
|
||||
#endif
|
||||
|
||||
#if MSDOS
|
||||
/* MSDOS support. */
|
||||
|
||||
/* Information returned by DOS calls GETDATE and GETTIME. */
|
||||
/* See DOS Technical Reference Manual, p. 5-30. */
|
||||
#define Year(r) (r.r_cx)
|
||||
#define Month(r) (r.r_dx >> 8)
|
||||
#define Day(r) (r.r_dx & 0xFF)
|
||||
#define Hour(r) (r.r_cx >> 8)
|
||||
#define Minute(r) (r.r_cx & 0xFF)
|
||||
#define Second(r) (r.r_dx >> 8)
|
||||
#define Hundredth(r) (r.r_dx & 0xFF)
|
||||
|
||||
/* COHERENT-compatible time buffer. */
|
||||
struct timeb {
|
||||
time_t time; /* Time since 1970. */
|
||||
unsigned short millitm; /* Milliseconds. */
|
||||
short timezone; /* Time zone -- obsolete. */
|
||||
short dstflag; /* DST applies -- obsolete. */
|
||||
};
|
||||
|
||||
tm_t *gettime(); /* (void) */
|
||||
int settime(); /* (tm_t *timep) */
|
||||
int stime(); /* (time_t *timep) */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* end of time.h */
|
4
Mark Williams MWS v4/LIB/CC
Normal file
4
Mark Williams MWS v4/LIB/CC
Normal file
@ -0,0 +1,4 @@
|
||||
-xcC:\bin\
|
||||
-xlC:\lib\
|
||||
-xtC:\tmp\
|
||||
-IC:\include\
|
BIN
Mark Williams MWS v4/LIB/CRTS0XL.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/CRTS0XL.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/CRTS0XS.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/CRTS0XS.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/FXL.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/FXL.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/FXL87.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/FXL87.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/FXS.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/FXS.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/FXS87.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/FXS87.OBJ
Normal file
Binary file not shown.
180
Mark Williams MWS v4/LIB/HELPFILE
Normal file
180
Mark Williams MWS v4/LIB/HELPFILE
Normal file
@ -0,0 +1,180 @@
|
||||
#shell_main
|
||||
The Mark Williams Shell (MWS) provides an integrated environment for
|
||||
editing, compiling, debugging and executing your programs. To select
|
||||
one of these functions, use the arrow keys to position the cursor bar
|
||||
over the desired choice, then press return.
|
||||
To leave the MWS, press the <esc> key. Short descriptions of
|
||||
each command follow.
|
||||
|
||||
|
||||
EDIT: Create a new file or edit an existing one. Edit invokes the
|
||||
MicroEMACS editor.
|
||||
|
||||
|
||||
COMPILE: Compile an existing C program. In the Compile menu, you
|
||||
may choose whatever compiler options you need, or simply execute a
|
||||
prior command line.
|
||||
|
||||
RUN: Use RUN to execute a compiled program.
|
||||
|
||||
|
||||
|
||||
DEBUG: Invoke the C Source Debugger (csd) to begin a debugging
|
||||
session. The entire dialogue in csd will reference your C source code.
|
||||
|
||||
|
||||
MAKE: Create a script for complex compilation sequences.
|
||||
Speeds compile time by eliminating unnecessary compilation.
|
||||
|
||||
|
||||
BUFFERS: Tailor the in-RAM compilation/accelerator to your needs.
|
||||
Allocate more memory, or add expanded memory, for even faster compilation.
|
||||
|
||||
|
||||
QUICK DOS: Accepts one DOS command and returns to MWS.
|
||||
|
||||
|
||||
|
||||
!DOS ESCAPE: Exit to DOS for unlimited DOS commands.
|
||||
In-RAM compilations and accelerator are still active. Type 'exit'
|
||||
to return to MWS.
|
||||
|
||||
NEW DIRECTORY: Changes the current working directory.
|
||||
#shell_main_edit
|
||||
Edit invokes the MicroEMACS editor.
|
||||
EXECUTE: Invokes the editor for the file named in the menu box.
|
||||
FILES: Lists files in current directory available for editing.
|
||||
Follow with the execute command to invoke the editor.
|
||||
NEW FILE: Lets you name a new file to edit.
|
||||
Follow with the Execute command to invoke the editor.
|
||||
#shell_main_edit_file
|
||||
Name a new file to edit. Follow with the Execute command to
|
||||
to invoke the editor.
|
||||
#shell_main_edit_files
|
||||
Select file(s) for editing. Then, use the Execute command to begin edit.
|
||||
#shell_main_compile
|
||||
EXECUTE: Invoke compiler and linker based on command line in command box.
|
||||
OPTIONS: Choose options for the compile command line.
|
||||
End list with END key.
|
||||
Backspace key deletes an option from the command line.
|
||||
FILES: List files in current directory with '.C' or '.OBJ' suffix.
|
||||
Use to add appropriate file(s) to command line. Follow with Execute
|
||||
command to compile.
|
||||
#shell_main_compile_files
|
||||
List files in current directory with '.C' or '.OBJ' suffix.
|
||||
Use to add appropriate file(s) to command line. Follow with Execute
|
||||
command to compile.
|
||||
#shell_main_compile_options
|
||||
Choose an option by moving the highlight bar to the option and pressing return.
|
||||
Press the <end> key once all desired options are selected.
|
||||
Delete an option by moving the highlight bar to the desired option
|
||||
and pressing backspace.
|
||||
For detailed information on each option, see the Lexicon entry for 'cc'
|
||||
or the introduction to the manual.
|
||||
#shell_main_run
|
||||
EXECUTE: Run a compiled program listed in the command box.
|
||||
ARGUMENTS: After file is selected, use Arguments to enter the desired
|
||||
run time arguments in the command box.
|
||||
|
||||
FILES: Lists '.EXE' files(s) in current directory. Choose one, then
|
||||
select Execute to run.
|
||||
#shell_main_run_arguments
|
||||
ARGUMENTS: After file is selected, use Arguments to enter the desired
|
||||
runtime arguments in the command box.
|
||||
#shell_main_quickDOS
|
||||
Accepts and executes one DOS command, then returns to MWS.
|
||||
#shell_main_directory
|
||||
Enter desired directory pathname, followed by return.
|
||||
#shell_main_debug
|
||||
Debug your programs with the csd C Source-Level Debugger.
|
||||
EXECUTE: Invokes the debugger for the file and options displayed in
|
||||
the command box.
|
||||
|
||||
OPTIONS: Choose options for command line. End list with <end> key.
|
||||
Backspace key deletes an option from the command line.
|
||||
|
||||
|
||||
ARGUMENTS: After selecting file to debug, use Arguments to
|
||||
enter command line parameters.
|
||||
|
||||
|
||||
FILES: Lists '.exe' files in current directory. Note: files must have
|
||||
been compiled using the '-vcsd' option for csd to debug your program.
|
||||
#shell_main_debug_options
|
||||
Choose an option by moving the highlight bar to the option and
|
||||
pressing backspace.
|
||||
For detailed information on each option, see the Commands Reference
|
||||
section in the csd C Source Debugger manual.
|
||||
#shell_main_debug_arguments
|
||||
Select file to debug, then use Arguments to enter the
|
||||
target program's command line parameters.
|
||||
#shell_main_debug_files
|
||||
Choose the .EXE file to debug.
|
||||
In order to use csd on a .EXE file,
|
||||
the program must have been compiled using the -VCSD option.
|
||||
#shell_main_make
|
||||
MAKE provides a systematic and efficient procedure for compiling
|
||||
a program comprised of several source files.
|
||||
EXECUTE: Invoke the makefile in the current directory based on
|
||||
the information in the command box.
|
||||
OPTIONS: Choose options for the make command. End list with <end> key.
|
||||
Backspace key deletes an option from command line.
|
||||
MACROS: Create macros used to eliminate repetitive typing or allow
|
||||
special option at run time.
|
||||
TARGETS: Enter name(s) of target file(s) to be made.
|
||||
#shell_main_make_options
|
||||
Choose an option by moving the highlight bar to the option and pressing
|
||||
return.
|
||||
Press the <end> key once all desired options are selected.
|
||||
|
||||
Delete an option by moving the highlight bar to the option and
|
||||
pressing backspace.
|
||||
For detailed information on each option, see the Lexicon entry for
|
||||
Make or the tutorial for Make in the manual.
|
||||
|
||||
#shell_main_make_macros
|
||||
Macros should be of the form 'a=b'. Macros can increase the flexibility
|
||||
of your makefiles.
|
||||
#shell_main_make_targets
|
||||
Enter name(s) of file(s) to be made.
|
||||
#shell_main_make_Alternate makefile
|
||||
Enter the name of the makefile if its name is not 'makefile'
|
||||
#shell_main_buffers
|
||||
Tailor the in-RAM compilation accelerator to your needs.
|
||||
Allocate memory or add expanded memory for faster compilation.
|
||||
|
||||
|
||||
LOAD/UNLOAD: Tell MWS to load or unload the accelerator.
|
||||
DISK DRIVES: Select disk drives to accelerate. The default is
|
||||
'*', or all drives accelerated.
|
||||
|
||||
BUFFER SIZE: Change the size of the buffer reserved for the accelerator.
|
||||
Default size is 128K.
|
||||
WRITE OPTIONS: Choose how data will be saved to disk: memory, timed save
|
||||
or disk. For details on write options, see the Let's C manual.
|
||||
SAVE DATA: Write to disk all data stored in the accelerator's buffer.
|
||||
CHANGE DISK: Write to disk all data in the buffer, then clear the buffer for
|
||||
a new disk.
|
||||
|
||||
EXPANDED MEMORY: Tell MWS to create buffers in the expanded memory rather
|
||||
than in main memory.
|
||||
#shell_main_buffers_load/unload
|
||||
Load or unload the accelerator.
|
||||
#shell_main_buffers_drive
|
||||
Select the disk drives you want to accelerate. The default is '*',
|
||||
or all drives accelerated.
|
||||
#shell_main_buffers_size
|
||||
Change the size of the buffer reserved for the accelerator.
|
||||
Default size is 128K.
|
||||
#shell_main_buffers_write
|
||||
Choose how data will be written to disk: Memory, Timed Save, or
|
||||
disk. For complete information on the write options, see
|
||||
the Let's C manual.
|
||||
#shell_main_buffers_save
|
||||
Write to disk all data stored in the accelerator's buffer.
|
||||
#shell_main_buffers_change
|
||||
Write to disk all data stored in the accelerator's buffer, then clear
|
||||
the buffer for a new disk.
|
||||
#shell_main_buffers_expanded
|
||||
Creates buffers in the expanded memory rather that in main memory.
|
||||
|
BIN
Mark Williams MWS v4/LIB/HELPINDX
Normal file
BIN
Mark Williams MWS v4/LIB/HELPINDX
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/I87RXL.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/I87RXL.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/I87RXS.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/I87RXS.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/LIBCXL.LIB
Normal file
BIN
Mark Williams MWS v4/LIB/LIBCXL.LIB
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/LIBCXL87.LIB
Normal file
BIN
Mark Williams MWS v4/LIB/LIBCXL87.LIB
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/LIBCXS.LIB
Normal file
BIN
Mark Williams MWS v4/LIB/LIBCXS.LIB
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/LIBCXS87.LIB
Normal file
BIN
Mark Williams MWS v4/LIB/LIBCXS87.LIB
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/LIBMXL.LIB
Normal file
BIN
Mark Williams MWS v4/LIB/LIBMXL.LIB
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/LIBMXL87.LIB
Normal file
BIN
Mark Williams MWS v4/LIB/LIBMXL87.LIB
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/LIBMXS.LIB
Normal file
BIN
Mark Williams MWS v4/LIB/LIBMXS.LIB
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/LIBMXS87.LIB
Normal file
BIN
Mark Williams MWS v4/LIB/LIBMXS87.LIB
Normal file
Binary file not shown.
12
Mark Williams MWS v4/LIB/MACTIONS
Normal file
12
Mark Williams MWS v4/LIB/MACTIONS
Normal file
@ -0,0 +1,12 @@
|
||||
#
|
||||
# Let's C Version 4.0.4.
|
||||
# Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
# All rights reserved. May not be copied or disclosed without permission.
|
||||
#
|
||||
|
||||
# Default actions.
|
||||
|
||||
.c.o .c.obj .s.o .s.obj .m.o .m.obj .asm.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
.o.exe .obj.exe:
|
||||
$(CC) $(LDFLAGS) -o $@ $<
|
14
Mark Williams MWS v4/LIB/MMACROS
Normal file
14
Mark Williams MWS v4/LIB/MMACROS
Normal file
@ -0,0 +1,14 @@
|
||||
#
|
||||
# Let's C Version 4.0.4.
|
||||
# Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
# All rights reserved. May not be copied or disclosed without permission.
|
||||
#
|
||||
|
||||
# Default macro definitions.
|
||||
|
||||
.SUFFIXES: .exe .o .obj .c .m .s .asm
|
||||
AS = as
|
||||
ASFLAGS = -gx
|
||||
CC = cc
|
||||
CFLAGS =
|
||||
LDFLAGS =
|
BIN
Mark Williams MWS v4/LIB/NAXL.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/NAXL.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/NAXS.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/NAXS.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/NSXL.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/NSXL.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/NSXS.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/NSXS.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/WXL.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/WXL.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LIB/WXS.OBJ
Normal file
BIN
Mark Williams MWS v4/LIB/WXS.OBJ
Normal file
Binary file not shown.
BIN
Mark Williams MWS v4/LetsC.pdf
Normal file
BIN
Mark Williams MWS v4/LetsC.pdf
Normal file
Binary file not shown.
107
Mark Williams MWS v4/SAMPLE/ANSI.C
Normal file
107
Mark Williams MWS v4/SAMPLE/ANSI.C
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* The routines in this file
|
||||
* provide support for ANSI style terminals
|
||||
* over a serial line. The serial I/O services are
|
||||
* provided by routines in "termio.c". It compiles
|
||||
* into nothing if not an ANSI device.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
#if ANSI
|
||||
|
||||
#define NROW 24 /* Screen size. */
|
||||
#define NCOL 80 /* Edit if you want to. */
|
||||
#define BEL 0x07 /* BEL character. */
|
||||
#define ESC 0x1B /* ESC character. */
|
||||
|
||||
extern int ttopen(); /* Forward references. */
|
||||
extern int ttgetc();
|
||||
extern int ttputc();
|
||||
extern int ttflush();
|
||||
extern int ttclose();
|
||||
extern int ansimove();
|
||||
extern int ansieeol();
|
||||
extern int ansieeop();
|
||||
extern int ansibeep();
|
||||
extern int ansiopen();
|
||||
|
||||
/*
|
||||
* Standard terminal interface
|
||||
* dispatch table. Most of the fields
|
||||
* point into "termio" code.
|
||||
*/
|
||||
TERM term = {
|
||||
NROW-1,
|
||||
NCOL,
|
||||
&ansiopen,
|
||||
&ttclose,
|
||||
&ttgetc,
|
||||
&ttputc,
|
||||
&ttflush,
|
||||
&ansimove,
|
||||
&ansieeol,
|
||||
&ansieeop,
|
||||
&ansibeep
|
||||
};
|
||||
|
||||
ansimove(row, col)
|
||||
{
|
||||
ttputc(ESC);
|
||||
ttputc('[');
|
||||
ansiparm(row+1);
|
||||
ttputc(';');
|
||||
ansiparm(col+1);
|
||||
ttputc('H');
|
||||
}
|
||||
|
||||
ansieeol()
|
||||
{
|
||||
ttputc(ESC);
|
||||
ttputc('[');
|
||||
ttputc('K');
|
||||
}
|
||||
|
||||
ansieeop()
|
||||
{
|
||||
ttputc(ESC);
|
||||
ttputc('[');
|
||||
ttputc('J');
|
||||
}
|
||||
|
||||
ansibeep()
|
||||
{
|
||||
ttputc(BEL);
|
||||
ttflush();
|
||||
}
|
||||
|
||||
ansiparm(n)
|
||||
register int n;
|
||||
{
|
||||
register int q;
|
||||
|
||||
q = n/10;
|
||||
if (q != 0)
|
||||
ansiparm(q);
|
||||
ttputc((n%10) + '0');
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ansiopen()
|
||||
{
|
||||
#if V7
|
||||
register char *cp;
|
||||
char *getenv();
|
||||
|
||||
if ((cp = getenv("TERM")) == NULL) {
|
||||
puts("Shell variable TERM not defined!");
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp(cp, "vt100") != 0) {
|
||||
puts("Terminal type not 'vt100'!");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
ttopen();
|
||||
}
|
66
Mark Williams MWS v4/SAMPLE/ATOD.C
Normal file
66
Mark Williams MWS v4/SAMPLE/ATOD.C
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define ERROR 0x10 /* largest input base */
|
||||
|
||||
/*
|
||||
* atod() converts the string 'num' to a double and returns its value.
|
||||
* If there is a non-digit in the string, or if there is an overflow,
|
||||
* then atod() exits with an appropriate error message.
|
||||
* atod() accepts leading zero for octal and leading 0x for hexidecimal;
|
||||
* in the latter case, 'a'-'f' and 'A'-'F' are accepted as digits.
|
||||
*/
|
||||
double
|
||||
atod(num)
|
||||
char *num;
|
||||
{
|
||||
register char *str;
|
||||
register int i;
|
||||
double res = 0,
|
||||
base = 10;
|
||||
|
||||
str = num;
|
||||
i = *str++;
|
||||
if (i == '0')
|
||||
if ((i = *str++) == 'x') {
|
||||
i = *str++;
|
||||
base = 0x10;
|
||||
} else
|
||||
base = 010;
|
||||
for (; i != '\0'; i = *str++) {
|
||||
i = todigit(i);
|
||||
if (i >= base)
|
||||
die("bad number '%s'", num);
|
||||
res = res * base + i;
|
||||
if (res+1 == res)
|
||||
die("number too big '%s'", num);
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* todigit() converts character 'ch' to an integer equivalent,
|
||||
* assuming that 'ch' is a digit or 'a'-'f' or 'A'-'F'.
|
||||
* If this is not true, then it returns ERROR.
|
||||
*/
|
||||
todigit(ch)
|
||||
register int ch;
|
||||
{
|
||||
if (!isascii(ch))
|
||||
return (ERROR);
|
||||
if (isdigit(ch))
|
||||
return (ch - '0' + 0);
|
||||
if (isupper(ch))
|
||||
ch = tolower(ch);
|
||||
if ('a' <= ch && ch <= 'f')
|
||||
return (ch - 'a' + 0xA);
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
|
138
Mark Williams MWS v4/SAMPLE/BANNER.C
Normal file
138
Mark Williams MWS v4/SAMPLE/BANNER.C
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Banner -- print in large type
|
||||
* td 80.09.24
|
||||
*/
|
||||
#include <stdio.h>
|
||||
char font[96][9]={
|
||||
0000,0000,0000,0000,0000,0000,0000,0000,0000, /* sp */
|
||||
0010,0010,0010,0010,0010,0000,0010,0000,0000, /* ! */
|
||||
0024,0024,0024,0000,0000,0000,0000,0000,0000, /* " */
|
||||
0024,0024,0076,0024,0076,0024,0024,0000,0000, /* # */
|
||||
0010,0036,0050,0034,0012,0074,0010,0000,0000, /* $ */
|
||||
0060,0062,0004,0010,0020,0046,0006,0000,0000, /* % */
|
||||
0010,0024,0024,0030,0052,0044,0032,0000,0000, /* & */
|
||||
0010,0010,0020,0000,0000,0000,0000,0000,0000, /* ' */
|
||||
0004,0010,0020,0020,0020,0010,0004,0000,0000, /* ( */
|
||||
0020,0010,0004,0004,0004,0010,0020,0000,0000, /* ) */
|
||||
0000,0010,0052,0034,0052,0010,0000,0000,0000, /* * */
|
||||
0000,0010,0010,0076,0010,0010,0000,0000,0000, /* + */
|
||||
0000,0000,0000,0000,0000,0030,0030,0010,0020, /* , */
|
||||
0000,0000,0000,0076,0000,0000,0000,0000,0000, /* - */
|
||||
0000,0000,0000,0000,0000,0030,0030,0000,0000, /* . */
|
||||
0001,0002,0004,0010,0020,0040,0100,0000,0000, /* / */
|
||||
0034,0042,0046,0052,0062,0042,0034,0000,0000, /* 0 */
|
||||
0010,0030,0010,0010,0010,0010,0034,0000,0000, /* 1 */
|
||||
0034,0042,0002,0004,0010,0020,0076,0000,0000, /* 2 */
|
||||
0076,0004,0010,0004,0002,0042,0034,0000,0000, /* 3 */
|
||||
0004,0014,0024,0044,0076,0004,0004,0000,0000, /* 4 */
|
||||
0076,0040,0074,0002,0002,0042,0034,0000,0000, /* 5 */
|
||||
0014,0020,0040,0074,0042,0042,0034,0000,0000, /* 6 */
|
||||
0076,0002,0004,0010,0020,0020,0020,0000,0000, /* 7 */
|
||||
0034,0042,0042,0034,0042,0042,0034,0000,0000, /* 8 */
|
||||
0034,0042,0042,0036,0002,0004,0030,0000,0000, /* 9 */
|
||||
0000,0030,0030,0000,0030,0030,0000,0000,0000, /* : */
|
||||
0000,0030,0030,0000,0030,0030,0010,0020,0000, /* ; */
|
||||
0002,0004,0010,0020,0010,0004,0002,0000,0000, /* < */
|
||||
0000,0000,0076,0000,0076,0000,0000,0000,0000, /* = */
|
||||
0040,0020,0010,0004,0010,0020,0040,0000,0000, /* > */
|
||||
0034,0042,0002,0004,0010,0000,0010,0000,0000, /* ? */
|
||||
0014,0022,0056,0052,0056,0040,0036,0000,0000, /* @ */
|
||||
0034,0042,0042,0076,0042,0042,0042,0000,0000, /* A */
|
||||
0074,0042,0042,0074,0042,0042,0074,0000,0000, /* B */
|
||||
0034,0042,0040,0040,0040,0042,0034,0000,0000, /* C */
|
||||
0070,0044,0042,0042,0042,0044,0070,0000,0000, /* D */
|
||||
0076,0040,0040,0074,0040,0040,0076,0000,0000, /* E */
|
||||
0076,0040,0040,0074,0040,0040,0040,0000,0000, /* F */
|
||||
0036,0040,0040,0046,0042,0042,0036,0000,0000, /* G */
|
||||
0042,0042,0042,0076,0042,0042,0042,0000,0000, /* H */
|
||||
0034,0010,0010,0010,0010,0010,0034,0000,0000, /* I */
|
||||
0034,0010,0010,0010,0010,0050,0020,0000,0000, /* J */
|
||||
0042,0044,0050,0060,0050,0044,0042,0000,0000, /* K */
|
||||
0040,0040,0040,0040,0040,0040,0076,0000,0000, /* L */
|
||||
0042,0066,0052,0052,0042,0042,0042,0000,0000, /* M */
|
||||
0042,0042,0062,0052,0046,0042,0042,0000,0000, /* N */
|
||||
0034,0042,0042,0042,0042,0042,0034,0000,0000, /* O */
|
||||
0074,0042,0042,0074,0040,0040,0040,0000,0000, /* P */
|
||||
0034,0042,0042,0042,0052,0044,0032,0000,0000, /* Q */
|
||||
0074,0042,0042,0074,0050,0044,0042,0000,0000, /* R */
|
||||
0034,0042,0040,0034,0002,0042,0034,0000,0000, /* S */
|
||||
0076,0010,0010,0010,0010,0010,0010,0000,0000, /* T */
|
||||
0042,0042,0042,0042,0042,0042,0034,0000,0000, /* U */
|
||||
0042,0042,0042,0024,0024,0010,0010,0000,0000, /* V */
|
||||
0042,0042,0042,0052,0052,0052,0024,0000,0000, /* W */
|
||||
0042,0042,0024,0010,0024,0042,0042,0000,0000, /* X */
|
||||
0042,0042,0024,0010,0010,0010,0010,0000,0000, /* Y */
|
||||
0076,0002,0004,0010,0020,0040,0076,0000,0000, /* Z */
|
||||
0034,0020,0020,0020,0020,0020,0034,0000,0000, /* [ */
|
||||
0100,0040,0020,0010,0004,0002,0001,0000,0000, /* \ */
|
||||
0034,0004,0004,0004,0004,0004,0034,0000,0000, /* ] */
|
||||
0010,0024,0042,0000,0000,0000,0000,0000,0000, /* ^ */
|
||||
0000,0000,0000,0000,0000,0000,0076,0000,0000, /* _ */
|
||||
0010,0010,0004,0000,0000,0000,0000,0000,0000, /* ` */
|
||||
0000,0000,0034,0002,0036,0042,0036,0000,0000, /* a */
|
||||
0040,0040,0074,0042,0042,0042,0074,0000,0000, /* b */
|
||||
0000,0000,0030,0044,0040,0044,0030,0000,0000, /* c */
|
||||
0002,0002,0036,0042,0042,0042,0036,0000,0000, /* d */
|
||||
0000,0000,0034,0042,0076,0040,0034,0000,0000, /* e */
|
||||
0014,0022,0070,0020,0020,0020,0020,0000,0000, /* f */
|
||||
0000,0000,0032,0046,0042,0046,0032,0002,0034, /* g */
|
||||
0040,0040,0074,0042,0042,0042,0042,0000,0000, /* h */
|
||||
0010,0000,0030,0010,0010,0010,0034,0000,0000, /* i */
|
||||
0004,0000,0004,0004,0004,0004,0004,0044,0030, /* j */
|
||||
0040,0040,0044,0050,0064,0042,0042,0000,0000, /* k */
|
||||
0030,0010,0010,0010,0010,0010,0034,0000,0000, /* l */
|
||||
0000,0000,0064,0052,0052,0052,0052,0000,0000, /* m */
|
||||
0000,0000,0074,0042,0042,0042,0042,0000,0000, /* n */
|
||||
0000,0000,0034,0042,0042,0042,0034,0000,0000, /* o */
|
||||
0000,0000,0054,0062,0042,0062,0054,0040,0040, /* p */
|
||||
0000,0000,0032,0046,0042,0046,0032,0002,0002, /* q */
|
||||
0000,0000,0054,0062,0040,0040,0040,0000,0000, /* r */
|
||||
0000,0000,0036,0040,0034,0002,0074,0000,0000, /* s */
|
||||
0020,0020,0070,0020,0020,0022,0014,0000,0000, /* t */
|
||||
0000,0000,0042,0042,0042,0046,0032,0000,0000, /* u */
|
||||
0000,0000,0042,0042,0042,0024,0010,0000,0000, /* v */
|
||||
0000,0000,0042,0042,0052,0052,0024,0000,0000, /* w */
|
||||
0000,0000,0042,0024,0010,0024,0042,0000,0000, /* x */
|
||||
0000,0000,0042,0042,0042,0046,0032,0002,0034, /* y */
|
||||
0000,0000,0076,0004,0010,0020,0076,0000,0000, /* z */
|
||||
0014,0020,0020,0040,0020,0020,0014,0000,0000, /* { */
|
||||
0010,0010,0010,0000,0010,0010,0010,0000,0000, /* | */
|
||||
0030,0004,0004,0002,0004,0004,0030,0000,0000, /* } */
|
||||
0020,0052,0004,0000,0000,0000,0000,0000,0000, /* ~ */
|
||||
0177,0177,0177,0177,0177,0177,0177,0177,0177 /* del */
|
||||
};
|
||||
char line[512];
|
||||
main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
register i;
|
||||
if(argc>1) for(i=1;i!=argc;i++){
|
||||
if(i!=1)
|
||||
putchar('\n');
|
||||
banner(argv[i]);
|
||||
}
|
||||
else while(gets(line)!=NULL){
|
||||
putchar('\n');
|
||||
banner(line);
|
||||
}
|
||||
}
|
||||
banner(line)
|
||||
char *line;
|
||||
{
|
||||
register i, j;
|
||||
register char *s;
|
||||
for(i=0;i!=9;i++){
|
||||
for(s=line;*s;s++) for(j=0200;j!=0;j>>=1)
|
||||
if(' '<=*s && *s<=0177 && font[*s-' '][i]&j)
|
||||
putchar('x');
|
||||
else
|
||||
putchar(' ');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
367
Mark Williams MWS v4/SAMPLE/BASIC.C
Normal file
367
Mark Williams MWS v4/SAMPLE/BASIC.C
Normal file
@ -0,0 +1,367 @@
|
||||
/*
|
||||
* The routines in this file move the cursor around on the screen.
|
||||
* They compute a new value for the cursor, then adjust ".".
|
||||
* The display code always updates the cursor location, so only moves
|
||||
* between lines, or functions that adjust the top line in the window
|
||||
* and invalidate the framing, are hard.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
/*
|
||||
* Move the cursor to the beginning of the current line.
|
||||
* Trivial.
|
||||
*/
|
||||
gotobol(f, n)
|
||||
{
|
||||
curwp->w_doto = 0;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor backwards by "n" characters. If "n" is less than
|
||||
* zero call "forwchar" to actually do the move. Otherwise compute
|
||||
* the new cursor location. Error if you try and move out of the buffer.
|
||||
* Set the flag if the line pointer for dot changes.
|
||||
*/
|
||||
backchar(f, n)
|
||||
register int n;
|
||||
{
|
||||
register LINE *lp;
|
||||
|
||||
if (n < 0)
|
||||
return (forwchar(f, -n));
|
||||
while (n--) {
|
||||
if (curwp->w_doto == 0) {
|
||||
if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
|
||||
return (FALSE);
|
||||
curwp->w_dotp = lp;
|
||||
curwp->w_doto = llength(lp);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
} else
|
||||
curwp->w_doto--;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor to the end of the current line. Trivial.
|
||||
* No errors.
|
||||
*/
|
||||
gotoeol(f, n)
|
||||
{
|
||||
curwp->w_doto = llength(curwp->w_dotp);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor forwards by "n" characters. If "n" is less than
|
||||
* zero call "backchar" to actually do the move. Otherwise compute
|
||||
* the new cursor location, and move ".". Error if you try and move
|
||||
* off the end of the buffer. Set the flag if the line pointer
|
||||
* for dot changes.
|
||||
*/
|
||||
forwchar(f, n)
|
||||
register int n;
|
||||
{
|
||||
if (n < 0)
|
||||
return (backchar(f, -n));
|
||||
while (n--) {
|
||||
if (curwp->w_doto == llength(curwp->w_dotp)) {
|
||||
if (curwp->w_dotp == curbp->b_linep)
|
||||
return (FALSE);
|
||||
curwp->w_dotp = lforw(curwp->w_dotp);
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
} else
|
||||
curwp->w_doto++;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Goto the beginning of the buffer.
|
||||
* Massive adjustment of dot. This is considered to be hard motion;
|
||||
* it really isn't if the original value of dot is the same as the
|
||||
* new value of dot.
|
||||
* Normally bound to "M-<".
|
||||
*/
|
||||
gotobob(f, n)
|
||||
{
|
||||
curwp->w_dotp = lforw(curbp->b_linep);
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to the end of the buffer.
|
||||
* Dot is always put at the end of the file (ZJ). The standard screen code does
|
||||
* most of the hard parts of update. Bound to "M->".
|
||||
*/
|
||||
gotoeob(f, n)
|
||||
{
|
||||
curwp->w_dotp = curbp->b_linep;
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move forward by full lines.
|
||||
* If the number of lines to move is less than zero, call the backward line
|
||||
* function to actually do it. The last command controls how the goal column
|
||||
* is set. Bound to "C-N". No errors are possible.
|
||||
*/
|
||||
forwline(f, n)
|
||||
{
|
||||
register LINE *dlp;
|
||||
|
||||
if (n < 0)
|
||||
return (backline(f, -n));
|
||||
if ((lastflag&CFCPCN) == 0) /* Reset goal if last */
|
||||
curgoal = curcol; /* not C-P or C-N */
|
||||
thisflag |= CFCPCN;
|
||||
dlp = curwp->w_dotp;
|
||||
while (n-- && dlp!=curbp->b_linep)
|
||||
dlp = lforw(dlp);
|
||||
curwp->w_dotp = dlp;
|
||||
curwp->w_doto = getgoal(dlp);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is like "forwline", but goes backwards.
|
||||
* The scheme is exactly the same. Check for arguments that are
|
||||
* less than zero and call your alternate. Figure out the new line and
|
||||
* call "movedot" to perform the motion. No errors are possible.
|
||||
* Bound to "C-P".
|
||||
*/
|
||||
backline(f, n)
|
||||
{
|
||||
register LINE *dlp;
|
||||
|
||||
if (n < 0)
|
||||
return (forwline(f, -n));
|
||||
if ((lastflag&CFCPCN) == 0) /* Reset goal if the */
|
||||
curgoal = curcol; /* last isn't C-P, C-N */
|
||||
thisflag |= CFCPCN;
|
||||
dlp = curwp->w_dotp;
|
||||
while (n-- && lback(dlp)!=curbp->b_linep)
|
||||
dlp = lback(dlp);
|
||||
curwp->w_dotp = dlp;
|
||||
curwp->w_doto = getgoal(dlp);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine, given a pointer to a LINE, and the current cursor goal
|
||||
* column, return the best choice for the offset. The offset is returned.
|
||||
* Used by "C-N" and "C-P".
|
||||
*/
|
||||
getgoal(dlp)
|
||||
register LINE *dlp;
|
||||
{
|
||||
register int c;
|
||||
register int col;
|
||||
register int newcol;
|
||||
register int dbo;
|
||||
|
||||
col = 0;
|
||||
dbo = 0;
|
||||
while (dbo != llength(dlp)) {
|
||||
c = lgetc(dlp, dbo);
|
||||
newcol = col;
|
||||
if (c == '\t')
|
||||
newcol |= 0x07;
|
||||
else if (c<0x20 || c==0x7F)
|
||||
++newcol;
|
||||
++newcol;
|
||||
if (newcol > curgoal)
|
||||
break;
|
||||
col = newcol;
|
||||
++dbo;
|
||||
}
|
||||
return (dbo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scroll forward by a specified number of lines, or by a full page if
|
||||
* no argument.
|
||||
* The "2" in the arithmetic on the window size is the overlap; this value is
|
||||
* the default overlap value in ITS EMACS. Because this zaps the top line in
|
||||
* the display window, we have to do a hard update.
|
||||
* Bound to "C-V".
|
||||
*/
|
||||
forwpage(f, n)
|
||||
register int n;
|
||||
{
|
||||
register LINE *lp;
|
||||
|
||||
if (f == FALSE) {
|
||||
n = curwp->w_ntrows - 2; /* Default scroll. */
|
||||
if (n <= 0) /* Forget the overlap */
|
||||
n = 1; /* if tiny window. */
|
||||
} else if (n < 0)
|
||||
return (backpage(f, -n));
|
||||
#if CVMVAS
|
||||
else /* Convert from pages */
|
||||
n *= curwp->w_ntrows; /* to lines. */
|
||||
#endif
|
||||
lp = curwp->w_linep;
|
||||
while (n-- && lp!=curbp->b_linep)
|
||||
lp = lforw(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_dotp = lp;
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This command is like "forwpage", but it goes backwards.
|
||||
* The "2", like above, is the overlap between the two windows. The
|
||||
* value is from the ITS EMACS manual. We do a hard update for exactly
|
||||
* the same reason.
|
||||
* Bound to "M-V".
|
||||
*/
|
||||
backpage(f, n)
|
||||
register int n;
|
||||
{
|
||||
register LINE *lp;
|
||||
|
||||
if (f == FALSE) {
|
||||
n = curwp->w_ntrows - 2; /* Default scroll. */
|
||||
if (n <= 0) /* Don't blow up if the */
|
||||
n = 1; /* window is tiny. */
|
||||
} else if (n < 0)
|
||||
return (forwpage(f, -n));
|
||||
#if CVMVAS
|
||||
else /* Convert from pages */
|
||||
n *= curwp->w_ntrows; /* to lines. */
|
||||
#endif
|
||||
lp = curwp->w_linep;
|
||||
while (n-- && lback(lp)!=curbp->b_linep)
|
||||
lp = lback(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_dotp = lp;
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the mark in the current window to the value of "." in the window.
|
||||
* No errors are possible.
|
||||
* Bound to "M-.".
|
||||
*/
|
||||
setmark(f, n)
|
||||
{
|
||||
curwp->w_markp = curwp->w_dotp;
|
||||
curwp->w_marko = curwp->w_doto;
|
||||
mlwrite("[Mark set]");
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap the values of "." and "mark" in the current window.
|
||||
* This is pretty easy, because all of the hard work gets done by the
|
||||
* standard routine that moves the mark about. The only possible error is
|
||||
* "no mark".
|
||||
* Bound to "C-X C-X".
|
||||
*/
|
||||
swapmark(f, n)
|
||||
{
|
||||
register LINE *odotp;
|
||||
register int odoto;
|
||||
|
||||
if (curwp->w_markp == NULL) {
|
||||
mlwrite("No mark in this window");
|
||||
return (FALSE);
|
||||
}
|
||||
odotp = curwp->w_dotp;
|
||||
odoto = curwp->w_doto;
|
||||
curwp->w_dotp = curwp->w_markp;
|
||||
curwp->w_doto = curwp->w_marko;
|
||||
curwp->w_markp = odotp;
|
||||
curwp->w_marko = odoto;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to a specific line in the buffer, mostly for
|
||||
* looking up errors in C programs, which give the
|
||||
* error a line number. If an argument is present, then
|
||||
* it is the line number, else prompt for a line number
|
||||
* to use.
|
||||
*/
|
||||
gotoline(f, n)
|
||||
register int n;
|
||||
{
|
||||
register LINE *clp;
|
||||
register int s;
|
||||
char buf[32];
|
||||
|
||||
if (f == FALSE) {
|
||||
if ((s=mlreply("Goto line: ", buf, sizeof(buf))) != TRUE)
|
||||
return (s);
|
||||
n = atoi(buf);
|
||||
}
|
||||
if (n <= 0) {
|
||||
mlwrite("Bad line");
|
||||
return (FALSE);
|
||||
}
|
||||
clp = lforw(curbp->b_linep); /* "clp" is first line */
|
||||
while (n != 1) {
|
||||
if (clp == curbp->b_linep) {
|
||||
mlwrite("Line too large");
|
||||
return (FALSE);
|
||||
}
|
||||
clp = lforw(clp);
|
||||
--n;
|
||||
}
|
||||
curwp->w_dotp = clp;
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to a specific line from the original file, mostly for
|
||||
* looking up errors in C programs, which give the
|
||||
* error a line number. If an argument is present, then
|
||||
* it is the line number, else prompt for a line number
|
||||
* to use.
|
||||
*/
|
||||
gotofline(f, n)
|
||||
register int n;
|
||||
{
|
||||
register LINE *clp;
|
||||
register int s;
|
||||
char buf[32];
|
||||
|
||||
if (f == FALSE) {
|
||||
if ((s=mlreply("Goto line: ", buf, sizeof(buf))) != TRUE)
|
||||
return (s);
|
||||
n = atoi(buf);
|
||||
}
|
||||
if (n <= 0) {
|
||||
mlwrite("Bad line");
|
||||
return (FALSE);
|
||||
}
|
||||
clp = lforw(curbp->b_linep); /* "clp" is first line */
|
||||
while (n != l_number(clp)) {
|
||||
if (clp == curbp->b_linep) {
|
||||
mlwrite("Line not in buffer");
|
||||
return (FALSE);
|
||||
}
|
||||
clp = lforw(clp);
|
||||
}
|
||||
curwp->w_dotp = clp;
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
153
Mark Williams MWS v4/SAMPLE/BIOS.H
Normal file
153
Mark Williams MWS v4/SAMPLE/BIOS.H
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* bios.h
|
||||
* IBM PC ROM BIOS information.
|
||||
* Cf. "I.B.M. PC Technical Reference", Appendix A, pp. 2-4.
|
||||
* Using this information guarantees that your program will NOT be portable.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Standard system pointer.
|
||||
*/
|
||||
struct seg {
|
||||
unsigned short offs;
|
||||
unsigned short segv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Item in keyboard buffer.
|
||||
*/
|
||||
struct creg {
|
||||
char scan_code;
|
||||
char ascii;
|
||||
};
|
||||
|
||||
/*
|
||||
* ROM BIOS data area starts at location 0.
|
||||
*/
|
||||
struct rom_data { /* emulated ROM BIOS data area */
|
||||
struct seg int_vect[0x100]; /* interrupt vectors */
|
||||
short rs232_base[4]; /* addresses of rs232 adapters */
|
||||
short printer_base[4]; /* addresses of printers */
|
||||
short equip_flag; /* installed hardware */
|
||||
char mfg_tst; /* initialization flag */
|
||||
short memory_size; /* memory size in Kbytes */
|
||||
short io_ram_size; /* memory in I/O channel */
|
||||
/*
|
||||
* Keyboard data areas.
|
||||
*/
|
||||
char kb_flag; /* shift flags */
|
||||
char kb_flag_1; /* second byte of kb status */
|
||||
char alt_input; /* alternate keypad */
|
||||
short buffer_head; /* pointer to head of kbd buff */
|
||||
short buffer_tail; /* pointer to tail of kbd buff */
|
||||
struct creg kb_buffer[16];
|
||||
/*
|
||||
* Diskette data areas.
|
||||
*/
|
||||
char seek_status; /* drive recalibration status */
|
||||
char motor_status; /* bit 3-0 drive 3-0 currently running */
|
||||
char motor_count; /* timeout counter for drive turn off */
|
||||
char diskette_status;
|
||||
char nec_status[7]; /* status bytes from NEC */
|
||||
/*
|
||||
* Video display area.
|
||||
*/
|
||||
char crt_mode;
|
||||
short crt_cols; /* number of cols on screen */
|
||||
short crt_len; /* length of CRT region in bytes */
|
||||
short crt_start; /* start of crt buffer (SEG ADDR) */
|
||||
short cursor_posn[8]; /* cursor position for 8 pages */
|
||||
short cursor_mode; /* current cursor mode setting */
|
||||
char active_page; /* current page being displayed */
|
||||
short addr_6845; /* base addr of active display card */
|
||||
char crt_mode_set; /* current setting of 3*8 register */
|
||||
char crt_palette; /* current palette setting color card */
|
||||
/*
|
||||
* Cassette data area.
|
||||
*/
|
||||
short edge_cnt;
|
||||
short crc_reg;
|
||||
char last_val;
|
||||
/*
|
||||
* Timer data area.
|
||||
*/
|
||||
short timer_low; /* low word of timer count */
|
||||
short timer_hi; /* hi word of timer count */
|
||||
char timer_ofl; /* timer has rolled over since last read */
|
||||
/*
|
||||
* System data area.
|
||||
*/
|
||||
char bios_break; /* bit 7 = 1 if break key depressed */
|
||||
short reset_flag; /* 0x1234 if kb reset underway */
|
||||
/*
|
||||
* Fixed disk data area.
|
||||
*/
|
||||
short fixed_disk_data[2];
|
||||
/*
|
||||
* Timeout counters.
|
||||
*/
|
||||
char prt_tim_out;
|
||||
char rs232_tim_out;
|
||||
};
|
||||
/*
|
||||
* Shift flag equates within kb_flag.
|
||||
*/
|
||||
#define INS_STATE 0x80
|
||||
#define CAPS_STATE 0x40
|
||||
#define NUM_STATE 0x20
|
||||
#define SCROLL_STATE 0x10
|
||||
#define ALT_SHIFT 0x08
|
||||
#define CTL_SHIFT 0x04
|
||||
#define LEFT_SHIFT 0x02
|
||||
#define RIGHT_SHIFT 0x01
|
||||
/*
|
||||
* Shift flag equates within kb_flag1.
|
||||
*/
|
||||
#define INS_SHIFT 0x80
|
||||
#define CAPS_SHIFT 0x40
|
||||
#define NUM_SHIFT 0x20
|
||||
#define SCROLL_SHIFT 0x10
|
||||
#define HOLD_STATE 0x08 /* hold state has been toggled */
|
||||
|
||||
/*
|
||||
* Diskette_status flags.
|
||||
*/
|
||||
#define TIME_OUT 0x80
|
||||
#define BAD_SEEK 0x40
|
||||
#define BAD_NEC 0x20 /* NEC Controller has failed */
|
||||
#define BAD_CRC 0x10 /* bad CRC on diskette read */
|
||||
#define DMA_BOUNDARY 0x09 /* DMA across DMA boundary */
|
||||
#define BAD_DMA 0x08 /* DMA Overrun */
|
||||
#define RECORD_NOT_FND 0x04 /* requested sector not found */
|
||||
#define WRITE_PROTECT 0x03 /* write protect violation */
|
||||
#define BAD_ADDR_MARK 0x02 /* address mark not found */
|
||||
#define BAD_COMMAND 0x01 /* bad command to diskette I/O */
|
||||
|
||||
/*
|
||||
* Timer equates.
|
||||
* Approximations of 1193180/65536 counts/sec.
|
||||
*/
|
||||
#define COUNTS_SEC 18
|
||||
#define COUNTS_MIN 1092
|
||||
#define COUNTS_HOUR 65543L
|
||||
#define COUNTS_DAY 0x1800B0L
|
||||
|
||||
/*
|
||||
* Port addresses.
|
||||
*/
|
||||
#define KB_DATA 0x60 /* keyboard scan code port */
|
||||
#define KB_CTL 0x61 /* control bits for kbd sense data */
|
||||
|
||||
#define TIMER 0x40 /* 8253/timer counter */
|
||||
#define TIM_CTL 0x43 /* 8253/timer control port */
|
||||
|
||||
#define DMA08 0x08 /* DMA status reg port */
|
||||
#define DMA 0x00 /* DMA channel 0 addr reg port */
|
||||
|
||||
/* end of bios.h */
|
109
Mark Williams MWS v4/SAMPLE/BIOSDATA.C
Normal file
109
Mark Williams MWS v4/SAMPLE/BIOSDATA.C
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* biosdata.c
|
||||
* Print snapshot of ROM BIOS data area.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <dos.h>
|
||||
#include "bios.h"
|
||||
|
||||
struct rom_data d;
|
||||
|
||||
main()
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* Copy ROM BIOS data. */
|
||||
_copy(PTR(&d), 0, 0, sizeof(d));
|
||||
|
||||
/* Interrupt vectors. */
|
||||
printf("Interrupt vectors:\n");
|
||||
for(i = 0; i<0x100; )
|
||||
{
|
||||
printf("%02x %04x:%04x",
|
||||
i, d.int_vect[i].offs, d.int_vect[i].segv);
|
||||
if(++i % 5)
|
||||
printf(" ");
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n\nRS-232 adapter addrs: %04x %04x %04x %04x\n",
|
||||
d.rs232_base[0], d.rs232_base[1],
|
||||
d.rs232_base[2], d.rs232_base[3]);
|
||||
printf("Printer addresses: %04x %04x %04x %04x\n",
|
||||
d.printer_base[0], d.printer_base[1],
|
||||
d.printer_base[2], d.printer_base[3]);
|
||||
|
||||
/* Machine flags. */
|
||||
printf("\nMachine flags:\n");
|
||||
printf("equip_flag\t%04x\n", d.equip_flag);
|
||||
printf("mfg_tst\t\t%02x\n", d.mfg_tst);
|
||||
printf("memory_size\t%04x\n", d.memory_size);
|
||||
printf("io_ram_size\t%04x\n", d.io_ram_size);
|
||||
|
||||
/* Keyboard data areas. */
|
||||
printf("\nKeyboard data areas:\n");
|
||||
printf("kb_flag\t\t%02x\n", d.kb_flag);
|
||||
printf("kb_flag_1\t%02x\n", d.kb_flag_1);
|
||||
printf("alt_input\t%02x\n", d.alt_input);
|
||||
printf("buffer_head\t%04x\n", d.buffer_head);
|
||||
printf("buffer_tail\t%04x\n", d.buffer_tail);
|
||||
printf("buffer scan codes ");
|
||||
for(i = 0; i < 16; i++)
|
||||
printf("%02x ", d.kb_buffer[i].scan_code);
|
||||
printf("\nbuffer ascii ");
|
||||
for(i = 0; i < 16; i++)
|
||||
printf("%02x ", d.kb_buffer[i].ascii);
|
||||
|
||||
/* Diskette data areas. */
|
||||
printf("\n\nDiskette data areas:\n");
|
||||
printf("seek_status\t%02x\n", d.seek_status);
|
||||
printf("motor_status\t%02x\n", d.motor_status);
|
||||
printf("motor_count\t%02x\n", d.motor_count);
|
||||
printf("diskette_status\t%02x\n", d.diskette_status);
|
||||
printf("NEC status bytes ");
|
||||
for(i = 0; i < 7; i++)
|
||||
printf("%02x ", d.nec_status[i]);
|
||||
|
||||
/* Video display area. */
|
||||
printf("\n\nVideo display area:\n");
|
||||
printf("crt_mode\t%02x\n", d.crt_mode);
|
||||
printf("crt_cols\t%04x\n", d.crt_cols);
|
||||
printf("crt_len\t\t%04x\n", d.crt_len);
|
||||
printf("crt_start\t%04x\n", d.crt_start);
|
||||
printf("cursor_posn\t%04x\n", d.cursor_posn);
|
||||
printf("cursor_mode\t%04x\n", d.cursor_mode);
|
||||
printf("active_page\t%02x\n", d.active_page);
|
||||
printf("addr_6845\t%04x\n", d.addr_6845);
|
||||
printf("crt_mode_set\t%02x\n", d.crt_mode_set);
|
||||
printf("crt_palette\t%02x\n", d.crt_palette);
|
||||
|
||||
/* Cassette data area. */
|
||||
printf("\nCassette data area:\n");
|
||||
printf("edge_cnt\t%04x\n", d.edge_cnt);
|
||||
printf("crc_reg\t\t%04x\n", d.crc_reg);
|
||||
printf("last_val\t%02x\n", d.last_val);
|
||||
|
||||
/* Timer data area. */
|
||||
printf("\nTimer data area:\n");
|
||||
printf("timer_low\t%04x\n", d.timer_low);
|
||||
printf("timer_hi\t%04x\n", d.timer_hi);
|
||||
printf("timer_ofl\t%02x\n", d.timer_ofl);
|
||||
|
||||
/* System data area. */
|
||||
printf("\nSystem data area:\n");
|
||||
printf("bios_break\t%02x\n", d.bios_break);
|
||||
printf("reset_flag\t%04x\n", d.reset_flag);
|
||||
|
||||
/* Timeout counters. */
|
||||
printf("\nTimeout counters:\n");
|
||||
printf("prt_tim_out\t%02x\n", d.prt_tim_out);
|
||||
printf("rs232_tim_out\t%02x\n", d.rs232_tim_out);
|
||||
}
|
||||
|
||||
/* end of biosdata.c */
|
358
Mark Williams MWS v4/SAMPLE/BUFFER.C
Normal file
358
Mark Williams MWS v4/SAMPLE/BUFFER.C
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Buffer management.
|
||||
* Some of the functions are internal,
|
||||
* and some are actually attached to user
|
||||
* keys. Like everyone else, they set hints
|
||||
* for the display system.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
/*
|
||||
* Attach a buffer to a window. The
|
||||
* values of dot and mark come from the buffer
|
||||
* if the use count is 0. Otherwise, they come
|
||||
* from some other window.
|
||||
*/
|
||||
usebuffer(f, n)
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register WINDOW *wp;
|
||||
register int s;
|
||||
char bufn[NBUFN];
|
||||
|
||||
if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
|
||||
return (s);
|
||||
#if GEM
|
||||
fixname(bufn);
|
||||
#endif
|
||||
if ((bp=bfind(bufn, TRUE, 0)) == NULL)
|
||||
return (FALSE);
|
||||
if (--curbp->b_nwnd == 0) { /* Last use. */
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
curbp->b_markp = curwp->w_markp;
|
||||
curbp->b_marko = curwp->w_marko;
|
||||
}
|
||||
curbp = bp; /* Switch. */
|
||||
curwp->w_bufp = bp;
|
||||
curwp->w_linep = bp->b_linep; /* For macros, ignored. */
|
||||
curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */
|
||||
if (bp->b_nwnd++ == 0) { /* First use. */
|
||||
curwp->w_dotp = bp->b_dotp;
|
||||
curwp->w_doto = bp->b_doto;
|
||||
curwp->w_markp = bp->b_markp;
|
||||
curwp->w_marko = bp->b_marko;
|
||||
return (TRUE);
|
||||
}
|
||||
wp = wheadp; /* Look for old. */
|
||||
while (wp != NULL) {
|
||||
if (wp!=curwp && wp->w_bufp==bp) {
|
||||
curwp->w_dotp = wp->w_dotp;
|
||||
curwp->w_doto = wp->w_doto;
|
||||
curwp->w_markp = wp->w_markp;
|
||||
curwp->w_marko = wp->w_marko;
|
||||
break;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispose of a buffer, by name.
|
||||
* Ask for the name. Look it up (don't get too
|
||||
* upset if it isn't there at all!). Get quite upset
|
||||
* if the buffer is being displayed. Clear the buffer (ask
|
||||
* if the buffer has been changed). Then free the header
|
||||
* line and the buffer header. Bound to "C-X K".
|
||||
*/
|
||||
killbuffer(f, n)
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register BUFFER *bp1;
|
||||
register BUFFER *bp2;
|
||||
register int s;
|
||||
char bufn[NBUFN];
|
||||
|
||||
if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
|
||||
return (s);
|
||||
#if GEM
|
||||
fixname(bufn);
|
||||
#endif
|
||||
if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */
|
||||
return (TRUE);
|
||||
if (bp->b_nwnd != 0) { /* Error if on screen. */
|
||||
mlwrite("Buffer is being displayed");
|
||||
return (FALSE);
|
||||
}
|
||||
if ((s=bclear(bp)) != TRUE) /* Blow text away. */
|
||||
return (s);
|
||||
free((char *) bp->b_linep); /* Release header line. */
|
||||
bp1 = NULL; /* Find the header. */
|
||||
bp2 = bheadp;
|
||||
while (bp2 != bp) {
|
||||
bp1 = bp2;
|
||||
bp2 = bp2->b_bufp;
|
||||
}
|
||||
bp2 = bp2->b_bufp; /* Next one in chain. */
|
||||
if (bp1 == NULL) /* Unlink it. */
|
||||
bheadp = bp2;
|
||||
else
|
||||
bp1->b_bufp = bp2;
|
||||
free((char *) bp); /* Release buffer block */
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* List all of the active buffers. First update the special buffer that
|
||||
* holds the list. Next make sure at least 1 window is displaying the
|
||||
* buffer list, splitting the screen if this is what it takes.
|
||||
* Lastly, repaint all of the windows that are displaying the list.
|
||||
* Bound to "C-X C-B".
|
||||
*/
|
||||
listbuffers(f, n)
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register BUFFER *bp;
|
||||
register int s;
|
||||
|
||||
if ((s=makelist()) != TRUE)
|
||||
return (s);
|
||||
if (blistp->b_nwnd == 0) { /* Not on screen yet. */
|
||||
if ((wp=wpopup()) == NULL)
|
||||
return (FALSE);
|
||||
bp = wp->w_bufp;
|
||||
if (--bp->b_nwnd == 0) {
|
||||
bp->b_dotp = wp->w_dotp;
|
||||
bp->b_doto = wp->w_doto;
|
||||
bp->b_markp = wp->w_markp;
|
||||
bp->b_marko = wp->w_marko;
|
||||
}
|
||||
wp->w_bufp = blistp;
|
||||
++blistp->b_nwnd;
|
||||
}
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_bufp == blistp) {
|
||||
wp->w_linep = lforw(blistp->b_linep);
|
||||
wp->w_dotp = lforw(blistp->b_linep);
|
||||
wp->w_doto = 0;
|
||||
wp->w_markp = NULL;
|
||||
wp->w_marko = 0;
|
||||
wp->w_flag |= WFMODE|WFHARD;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine rebuilds the text in the special secret buffer that holds
|
||||
* the buffer list. It is called by the list buffers command. Return TRUE
|
||||
* if everything works. Return FALSE if there is an error
|
||||
* (if there is no memory).
|
||||
*/
|
||||
makelist()
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register BUFFER *bp;
|
||||
register LINE *lp;
|
||||
register long nlines;
|
||||
register long nbytes;
|
||||
register int c;
|
||||
char b[6+1];
|
||||
char line[128];
|
||||
|
||||
blistp->b_flag &= ~BFCHG; /* Don't complain! */
|
||||
if ((c=bclear(blistp)) != TRUE) /* Blow old text away */
|
||||
return (c);
|
||||
strcpy(blistp->b_fname, "");
|
||||
if (addline("C Size Lines Buffer File") == FALSE
|
||||
|| addline("- ---- ----- ------ ----") == FALSE)
|
||||
return (FALSE);
|
||||
bp = bheadp; /* For all buffers */
|
||||
while (bp != NULL) {
|
||||
if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones. */
|
||||
bp = bp->b_bufp;
|
||||
continue;
|
||||
}
|
||||
cp1 = &line[0]; /* Start at left edge */
|
||||
if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */
|
||||
*cp1++ = '*';
|
||||
else
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = ' '; /* Gap. */
|
||||
nbytes = 0; /* Count bytes in buf. */
|
||||
nlines = 0; /* Count lines in buf. */
|
||||
lp = lforw(bp->b_linep);
|
||||
while (lp != bp->b_linep) {
|
||||
nlines++;
|
||||
nbytes += llength(lp)+1;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
ltoa(b, 6, nbytes); /* 6 digit buffer size. */
|
||||
cp2 = &b[0];
|
||||
while ((c = *cp2++) != 0)
|
||||
*cp1++ = c;
|
||||
*cp1++ = ' '; /* Gap. */
|
||||
ltoa(b, 6, nlines); /* 6 digit # of lines */
|
||||
cp2 = &b[0];
|
||||
while ((c = *cp2++) != 0)
|
||||
*cp1++ = c;
|
||||
*cp1++ = ' '; /* Gap. */
|
||||
cp2 = &bp->b_bname[0]; /* Buffer name */
|
||||
while ((c = *cp2++) != 0)
|
||||
*cp1++ = c;
|
||||
cp2 = &bp->b_fname[0]; /* File name */
|
||||
if (*cp2 != 0) {
|
||||
while (cp1 < &line[1+1+6+1+6+1+NBUFN+1])
|
||||
*cp1++ = ' ';
|
||||
while ((c = *cp2++) != 0) {
|
||||
if (cp1 < &line[128-1])
|
||||
*cp1++ = c;
|
||||
}
|
||||
}
|
||||
*cp1 = 0; /* Add to the buffer. */
|
||||
if (addline(line) == FALSE)
|
||||
return (FALSE);
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
return (TRUE); /* All done */
|
||||
}
|
||||
|
||||
ltoa(buf, width, num)
|
||||
register char buf[];
|
||||
register int width;
|
||||
register long num;
|
||||
{
|
||||
buf[width] = 0; /* End of string. */
|
||||
while (num >= 10) { /* Conditional digits. */
|
||||
buf[--width] = (num%10) + '0';
|
||||
num /= 10;
|
||||
}
|
||||
buf[--width] = num + '0'; /* Always 1 digit. */
|
||||
while (width != 0) /* Pad with blanks. */
|
||||
buf[--width] = ' ';
|
||||
}
|
||||
|
||||
/*
|
||||
* The argument "text" points to a string. Append this line to the buffer list
|
||||
* buffer. Handcraft the EOL on the end. Return TRUE if it worked and FALSE if
|
||||
* you ran out of room.
|
||||
*/
|
||||
addline(text)
|
||||
char *text;
|
||||
{
|
||||
register LINE *lp;
|
||||
register int i;
|
||||
register int ntext;
|
||||
|
||||
ntext = strlen(text);
|
||||
if ((lp=lalloc(ntext)) == NULL)
|
||||
return (FALSE);
|
||||
for (i=0; i<ntext; ++i)
|
||||
lputc(lp, i, text[i]);
|
||||
blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */
|
||||
lp->l_bp = blistp->b_linep->l_bp;
|
||||
blistp->b_linep->l_bp = lp;
|
||||
lp->l_fp = blistp->b_linep;
|
||||
if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */
|
||||
blistp->b_dotp = lp; /* move it to new line */
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look through the list of buffers. Return TRUE if there are any changed
|
||||
* buffers. Buffers that hold magic internal stuff are not considered;
|
||||
* who cares if the list of buffer names is hacked.
|
||||
* Return FALSE if no buffers have been changed.
|
||||
*/
|
||||
anycb()
|
||||
{
|
||||
register BUFFER *bp;
|
||||
|
||||
bp = bheadp;
|
||||
while (bp != NULL) {
|
||||
if ((bp->b_flag&(BFTEMP|BFNOWRT|BFERROR))==0
|
||||
&& (bp->b_flag&BFCHG)!=0)
|
||||
return (TRUE);
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a buffer, by name. Return a pointer to the BUFFER structure
|
||||
* associated with it. If the named buffer is found, but is a TEMP buffer
|
||||
* (like the buffer list) conplain. If the buffer is not found and the "cflag"
|
||||
* is TRUE, create it. The "bflag" is the settings for the flags in in buffer.
|
||||
*/
|
||||
BUFFER *bfind(bname, cflag, bflag)
|
||||
register char *bname;
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register LINE *lp;
|
||||
|
||||
bp = bheadp;
|
||||
while (bp != NULL) {
|
||||
if (strcmp(bname, bp->b_bname) == 0) {
|
||||
if ((bp->b_flag&BFTEMP) != 0) {
|
||||
mlwrite("Cannot select builtin buffer");
|
||||
return (NULL);
|
||||
}
|
||||
return (bp);
|
||||
}
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
if (cflag != FALSE) {
|
||||
if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
|
||||
return (NULL);
|
||||
if ((lp=lalloc(0)) == NULL) {
|
||||
free((char *) bp);
|
||||
return (NULL);
|
||||
}
|
||||
bp->b_bufp = bheadp;
|
||||
bheadp = bp;
|
||||
bp->b_dotp = lp;
|
||||
bp->b_doto = 0;
|
||||
bp->b_markp = NULL;
|
||||
bp->b_marko = 0;
|
||||
bp->b_flag = bflag;
|
||||
bp->b_nwnd = 0;
|
||||
bp->b_linep = lp;
|
||||
strcpy(bp->b_fname, "");
|
||||
strcpy(bp->b_bname, bname);
|
||||
lp->l_fp = lp;
|
||||
lp->l_bp = lp;
|
||||
}
|
||||
return (bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine blows away all of the text in a buffer. If the buffer is
|
||||
* marked as changed then we ask if it is ok to blow it away; this is
|
||||
* to save the user the grief of losing text. The window chain is nearly
|
||||
* always wrong if this gets called; the caller must arrange for the updates
|
||||
* that are required. Return TRUE if everything looks good.
|
||||
*/
|
||||
bclear(bp)
|
||||
register BUFFER *bp;
|
||||
{
|
||||
register LINE *lp;
|
||||
register int s;
|
||||
|
||||
if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */
|
||||
&& (bp->b_flag&BFCHG) != 0 /* Something changed */
|
||||
&& (s=mlyesno("Discard changes")) != TRUE)
|
||||
return (s);
|
||||
bp->b_flag &= ~BFCHG; /* Not changed */
|
||||
while ((lp=lforw(bp->b_linep)) != bp->b_linep)
|
||||
lfree(lp);
|
||||
bp->b_dotp = bp->b_linep; /* Fix "." */
|
||||
bp->b_doto = 0;
|
||||
bp->b_markp = NULL; /* Invalidate "mark" */
|
||||
bp->b_marko = 0;
|
||||
return (TRUE);
|
||||
}
|
98
Mark Williams MWS v4/SAMPLE/CRTS0XL.ASM
Normal file
98
Mark Williams MWS v4/SAMPLE/CRTS0XL.ASM
Normal file
@ -0,0 +1,98 @@
|
||||
;+
|
||||
; Let's C Version 4.0.C.
|
||||
; Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
; All rights reserved. May not be copied or disclosed without permission.
|
||||
;-
|
||||
|
||||
name crts0xl
|
||||
|
||||
;+
|
||||
; DOS LARGE model C runtime startoff.
|
||||
;-
|
||||
|
||||
;+
|
||||
; At compile time:
|
||||
; Declare the classes 'code', 'data', 'stack', 'memory' and 'debug'
|
||||
; in the right order so that LINK gets it right.
|
||||
; Set up a minimal stack of 2048 bytes.
|
||||
; Set up public label '_mbase_' in the memory segment
|
||||
; so C knows where the program ends.
|
||||
; At run time:
|
||||
; Save the program segment prefix base address in '_pspbase_'
|
||||
; so C knows where the program begins.
|
||||
; Free all memory past the end of the program for 'malloc_()'.
|
||||
; Initialize BP to NULL for 'longjmp_()'.
|
||||
; Call '_main_()'.
|
||||
; Provide low level C callable '_exit_()'.
|
||||
;-
|
||||
|
||||
extrn _main_:far
|
||||
extrn _pspbase_:word
|
||||
extrn __end_:word
|
||||
|
||||
code segment public 'code'
|
||||
code ends
|
||||
|
||||
data segment public 'data'
|
||||
data ends
|
||||
|
||||
stack segment stack 'stack'
|
||||
db 2048 dup (?)
|
||||
stack ends
|
||||
|
||||
memory segment memory 'memory'
|
||||
public _mbase_
|
||||
_mbase_ label word
|
||||
memory ends
|
||||
|
||||
debug segment byte public 'debug'
|
||||
debug ends
|
||||
|
||||
code segment public 'code'
|
||||
public _exit_
|
||||
|
||||
assume cs:code
|
||||
|
||||
crts0 proc far
|
||||
|
||||
mov ax, seg _pspbase_ ; Set DS to map the
|
||||
mov ds, ax ; _pspbase_ segment
|
||||
assume ds:seg _pspbase_ ; and tell the assembler.
|
||||
mov _pspbase_, es ; Initialize _pspbase.
|
||||
|
||||
mov ax, seg __end_ ; Set DS to map the
|
||||
mov ds, ax ; __end segment
|
||||
assume ds:seg __end_ ; and tell the assembler.
|
||||
mov bx, memory ; BX gets end of memory segment
|
||||
sub ax, ax ; and AX gets offset.
|
||||
mov __end_, ax ; Initialize __end offset
|
||||
mov __end_+2, bx ; and segment.
|
||||
|
||||
sub bp, bp ; Clear BP for longjmp.
|
||||
call _main_ ; Call _main which calls main.
|
||||
push ax ; Save return status,
|
||||
push ax ; push fake far return address
|
||||
push ax ; and fall through to _exit.
|
||||
|
||||
;+
|
||||
; void _exit(s) int s;
|
||||
;
|
||||
; Low level exit.
|
||||
; Return to caller with exit status in AL.
|
||||
; Since CSD catches end of execution at this label,
|
||||
; all program terminations should pass through _exit_.
|
||||
;-
|
||||
|
||||
_exit_ label far
|
||||
|
||||
cld ; For DOS.
|
||||
add sp, 4 ; Discard return address and
|
||||
pop ax ; get exit status in AL.
|
||||
mov ah, 4Ch ; Load return exit status function code
|
||||
int 21h ; and do it.
|
||||
|
||||
crts0 endp
|
||||
|
||||
code ends
|
||||
|
||||
end crts0
|
106
Mark Williams MWS v4/SAMPLE/CRTS0XS.ASM
Normal file
106
Mark Williams MWS v4/SAMPLE/CRTS0XS.ASM
Normal file
@ -0,0 +1,106 @@
|
||||
;+
|
||||
; Let's C Version 4.0.C.
|
||||
; Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
; All rights reserved. May not be copied or disclosed without permission.
|
||||
;-
|
||||
|
||||
name crts0xs
|
||||
|
||||
;+
|
||||
; DOS SMALL model C runtime startoff.
|
||||
;-
|
||||
|
||||
;+
|
||||
; At compile time:
|
||||
; Declare the classes 'CODE', 'DATA', 'CONST', 'STACK', 'MEMORY'
|
||||
; and 'DEBUG' in the right order so that LINK gets it right.
|
||||
; Set up a minimal stack of 2048 bytes.
|
||||
; Set up public label 'end_' in the MEMORY segment
|
||||
; so C knows where the program ends.
|
||||
; At run time:
|
||||
; Set up segment registers.
|
||||
; Save the program segment prefix base address in '_pspbase_'
|
||||
; so C knows where the program begins.
|
||||
; Initialize BP to NULL for 'longjmp_()'.
|
||||
; Call '_main_()'.
|
||||
; Provide low level C callable '_exit_()'.
|
||||
;-
|
||||
|
||||
extrn _main_:near
|
||||
|
||||
code segment public 'code'
|
||||
code ends
|
||||
|
||||
data segment public 'data'
|
||||
; The following declaration prevents LINK from putting data at address DS:0.
|
||||
dw 0
|
||||
extrn __end_:word
|
||||
extrn _pspbase_:word
|
||||
data ends
|
||||
|
||||
const segment public 'const'
|
||||
const ends
|
||||
|
||||
stack segment stack 'stack'
|
||||
db 2048 dup (?)
|
||||
stack ends
|
||||
|
||||
memory segment memory 'memory'
|
||||
public end_
|
||||
end_ label word
|
||||
memory ends
|
||||
|
||||
debug segment byte public 'debug'
|
||||
debug ends
|
||||
|
||||
cgroup group code
|
||||
dgroup group const, data, stack, memory
|
||||
|
||||
code segment public 'code'
|
||||
public _exit_
|
||||
|
||||
assume cs:cgroup
|
||||
|
||||
crts0 proc near
|
||||
|
||||
mov ax, dgroup ; Initialize SS and DS
|
||||
mov ss, ax ; with the
|
||||
mov ds, ax ; base of dgroup
|
||||
assume ds:dgroup ; and tell
|
||||
assume ss:dgroup ; the assembler.
|
||||
|
||||
mov _pspbase_, es ; Initialize _pspbase.
|
||||
mov es, ax ; Initialize ES
|
||||
assume es:dgroup ; and tell the assembler.
|
||||
lea ax, end_ ; Initialize
|
||||
mov __end_, ax ; __end_.
|
||||
mov sp, ax ; Initialize stack pointer.
|
||||
|
||||
sub bp, bp ; Clear BP for longjmp.
|
||||
call _main_ ; Call _main which calls main.
|
||||
push ax ; Save return status,
|
||||
push ax ; push fake return address
|
||||
; and fall through to _exit.
|
||||
|
||||
;+
|
||||
; void _exit(s) int s;
|
||||
;
|
||||
; Low level exit.
|
||||
; Return to caller with exit status in AL.
|
||||
; Since CSD catches end of execution at this label,
|
||||
; all program terminations should pass through _exit_.
|
||||
;-
|
||||
|
||||
_exit_ label near
|
||||
|
||||
cld ; For DOS.
|
||||
pop ax ; Discard return address and
|
||||
pop ax ; get exit status in AL.
|
||||
mov ah, 4Ch ; Load return exit status function code
|
||||
int 21h ; and do it.
|
||||
|
||||
crts0 endp
|
||||
|
||||
code ends
|
||||
|
||||
end crts0
|
722
Mark Williams MWS v4/SAMPLE/DISPLAY.C
Normal file
722
Mark Williams MWS v4/SAMPLE/DISPLAY.C
Normal file
@ -0,0 +1,722 @@
|
||||
/*
|
||||
* The functions in this file
|
||||
* handle redisplay. There are two halves,
|
||||
* the ones that update the virtual display
|
||||
* screen, and the ones that make the physical
|
||||
* display screen the same as the virtual
|
||||
* display screen. These functions use hints
|
||||
* that are left in the windows by the
|
||||
* commands.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
#define WFDEBUG 0 /* Window flag debug. */
|
||||
|
||||
typedef struct VIDEO {
|
||||
short v_flag; /* Flags */
|
||||
char v_text[]; /* Screen data. */
|
||||
} VIDEO;
|
||||
|
||||
#define VFCHG 0x0001 /* Changed. */
|
||||
|
||||
int sgarbf = TRUE; /* TRUE if screen is garbage */
|
||||
int mpresf = FALSE; /* TRUE if message in last line */
|
||||
int vtrow = 0; /* Row location of SW cursor */
|
||||
int vtcol = 0; /* Column location of SW cursor */
|
||||
int ttrow = HUGE; /* Row location of HW cursor */
|
||||
int ttcol = HUGE; /* Column location of HW cursor */
|
||||
|
||||
VIDEO **vscreen; /* Virtual screen. */
|
||||
VIDEO **pscreen; /* Physical screen. */
|
||||
|
||||
/*
|
||||
* Initialize the data structures used
|
||||
* by the display code. The edge vectors used
|
||||
* to access the screens are set up. The operating
|
||||
* system's terminal I/O channel is set up. All the
|
||||
* other things get initialized at compile time.
|
||||
* The original window has "WFCHG" set, so that it
|
||||
* will get completely redrawn on the first
|
||||
* call to "update".
|
||||
*/
|
||||
vtinit()
|
||||
{
|
||||
register int i;
|
||||
register VIDEO *vp;
|
||||
|
||||
(*term.t_open)();
|
||||
vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
|
||||
if (vscreen == NULL)
|
||||
abort();
|
||||
pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
|
||||
if (pscreen == NULL)
|
||||
abort();
|
||||
for (i=0; i<term.t_nrow; ++i) {
|
||||
vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
|
||||
if (vp == NULL)
|
||||
abort();
|
||||
vscreen[i] = vp;
|
||||
vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
|
||||
if (vp == NULL)
|
||||
abort();
|
||||
pscreen[i] = vp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the virtual terminal
|
||||
* system, in anticipation for a return to the
|
||||
* operating system. Move down to the last line and
|
||||
* clear it out (the next system prompt will be
|
||||
* written in the line). Shut down the channel
|
||||
* to the terminal.
|
||||
*/
|
||||
vttidy()
|
||||
{
|
||||
movecursor(term.t_nrow, 0);
|
||||
(*term.t_eeol)();
|
||||
(*term.t_close)();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the virtual cursor to
|
||||
* the specified row and column on the
|
||||
* virtual screen. There is no checking for
|
||||
* nonsense values; this might be a good
|
||||
* idea during the early stages.
|
||||
*/
|
||||
vtmove(row, col)
|
||||
{
|
||||
vtrow = row;
|
||||
vtcol = col;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a character to the
|
||||
* virtual screen. The virtual row and
|
||||
* column are updated. If the line is too
|
||||
* long put a "$" in the last column.
|
||||
* This routine only puts printing characters
|
||||
* into the virtual terminal buffers.
|
||||
* Only column overflow is checked.
|
||||
*/
|
||||
vtputc(c)
|
||||
register int c;
|
||||
{
|
||||
register VIDEO *vp;
|
||||
|
||||
vp = vscreen[vtrow];
|
||||
if (vtcol >= term.t_ncol)
|
||||
vp->v_text[term.t_ncol-1] = '$';
|
||||
else if (c == '\t') {
|
||||
do {
|
||||
vtputc(' ');
|
||||
} while ((vtcol&0x07) != 0);
|
||||
} else if (c<0x20 || c==0x7F) {
|
||||
vtputc('^');
|
||||
vtputc(c ^ 0x40);
|
||||
} else
|
||||
vp->v_text[vtcol++] = c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Erase from the end of the
|
||||
* software cursor to the end of the
|
||||
* line on which the software cursor is
|
||||
* located.
|
||||
*/
|
||||
vteeol()
|
||||
{
|
||||
register VIDEO *vp;
|
||||
|
||||
vp = vscreen[vtrow];
|
||||
while (vtcol < term.t_ncol)
|
||||
vp->v_text[vtcol++] = ' ';
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the display is
|
||||
* right. This is a three part process. First,
|
||||
* scan through all of the windows looking for dirty
|
||||
* ones. Check the framing, and refresh the screen.
|
||||
* Second, make sure that "currow" and "curcol" are
|
||||
* correct for the current window. Third, make the
|
||||
* virtual and physical screens the same.
|
||||
*/
|
||||
update()
|
||||
{
|
||||
register LINE *lp;
|
||||
register WINDOW *wp;
|
||||
register VIDEO *vp1;
|
||||
register VIDEO *vp2;
|
||||
register int i;
|
||||
register int j;
|
||||
register int c;
|
||||
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
/* Look at any window with update flags set on. */
|
||||
if (wp->w_flag != 0) {
|
||||
/* If not force reframe, check the framing. */
|
||||
if ((wp->w_flag&WFFORCE) == 0) {
|
||||
lp = wp->w_linep;
|
||||
for (i=0; i<wp->w_ntrows; ++i) {
|
||||
if (lp == wp->w_dotp)
|
||||
goto out;
|
||||
if (lp == wp->w_bufp->b_linep)
|
||||
break;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
}
|
||||
/* Not acceptable, better compute a new value */
|
||||
/* for the line at the top of the window. Then */
|
||||
/* set the "WFHARD" flag to force full redraw. */
|
||||
i = wp->w_force;
|
||||
if (i > 0) {
|
||||
--i;
|
||||
if (i >= wp->w_ntrows)
|
||||
i = wp->w_ntrows-1;
|
||||
} else if (i < 0) {
|
||||
i += wp->w_ntrows;
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
} else
|
||||
i = wp->w_ntrows/2;
|
||||
lp = wp->w_dotp;
|
||||
while (i!=0 && lback(lp)!=wp->w_bufp->b_linep) {
|
||||
--i;
|
||||
lp = lback(lp);
|
||||
}
|
||||
wp->w_linep = lp;
|
||||
wp->w_flag |= WFHARD; /* Force full. */
|
||||
out:
|
||||
/* Try to use reduced update. Mode line update */
|
||||
/* has its own special flag. The fast update is */
|
||||
/* used if the only thing to do is within the */
|
||||
/* line editing. */
|
||||
lp = wp->w_linep;
|
||||
i = wp->w_toprow;
|
||||
if ((wp->w_flag&~WFMODE) == WFEDIT) {
|
||||
while (lp != wp->w_dotp) {
|
||||
++i;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
vscreen[i]->v_flag |= VFCHG;
|
||||
vtmove(i, 0);
|
||||
for (j=0; j<llength(lp); ++j)
|
||||
vtputc(lgetc(lp, j));
|
||||
vteeol();
|
||||
} else if ((wp->w_flag&(WFEDIT|WFHARD)) != 0) {
|
||||
while (i < wp->w_toprow+wp->w_ntrows) {
|
||||
vscreen[i]->v_flag |= VFCHG;
|
||||
vtmove(i, 0);
|
||||
if (lp != wp->w_bufp->b_linep) {
|
||||
for (j=0; j<llength(lp); ++j)
|
||||
vtputc(lgetc(lp, j));
|
||||
lp = lforw(lp);
|
||||
}
|
||||
vteeol();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
#if !WFDEBUG
|
||||
if ((wp->w_flag&WFMODE) != 0)
|
||||
modeline(wp);
|
||||
wp->w_flag = 0;
|
||||
wp->w_force = 0;
|
||||
#endif
|
||||
}
|
||||
#if WFDEBUG
|
||||
modeline(wp);
|
||||
wp->w_flag = 0;
|
||||
wp->w_force = 0;
|
||||
#endif
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
/* Always recompute the row and column number of the hardware */
|
||||
/* cursor. This is the only update for simple moves. */
|
||||
lp = curwp->w_linep;
|
||||
currow = curwp->w_toprow;
|
||||
while (lp != curwp->w_dotp) {
|
||||
++currow;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
curcol = 0;
|
||||
i = 0;
|
||||
while (i < curwp->w_doto) {
|
||||
c = lgetc(lp, i++);
|
||||
if (c == '\t')
|
||||
curcol |= 0x07;
|
||||
else if (c<0x20 || c==0x7F)
|
||||
++curcol;
|
||||
++curcol;
|
||||
}
|
||||
if (curcol >= term.t_ncol) /* Long line. */
|
||||
curcol = term.t_ncol-1;
|
||||
/* Special hacking if the screen is garbage. Clear the hardware */
|
||||
/* screen, and update your copy to agree with it. Set all the */
|
||||
/* virtual screen change bits, to force a full update. */
|
||||
if (sgarbf != FALSE) {
|
||||
for (i=0; i<term.t_nrow; ++i) {
|
||||
vscreen[i]->v_flag |= VFCHG;
|
||||
vp1 = pscreen[i];
|
||||
for (j=0; j<term.t_ncol; ++j)
|
||||
vp1->v_text[j] = ' ';
|
||||
}
|
||||
movecursor(0, 0); /* Erase the screen. */
|
||||
(*term.t_eeop)();
|
||||
sgarbf = FALSE; /* Erase-page clears */
|
||||
mpresf = FALSE; /* the message area. */
|
||||
}
|
||||
/* Make sure that the physical and virtual displays agree. */
|
||||
/* Unlike before, the "updateline" code is only called with a */
|
||||
/* line that has been updated for sure. */
|
||||
for (i=0; i<term.t_nrow; ++i) {
|
||||
vp1 = vscreen[i];
|
||||
if ((vp1->v_flag&VFCHG) != 0) {
|
||||
vp1->v_flag &= ~VFCHG;
|
||||
vp2 = pscreen[i];
|
||||
updateline(i, &vp1->v_text[0], &vp2->v_text[0]);
|
||||
}
|
||||
}
|
||||
/* Finally, update the hardware cursor and flush out buffers. */
|
||||
movecursor(currow, curcol);
|
||||
(*term.t_flush)();
|
||||
}
|
||||
|
||||
/*
|
||||
* Update a single line. This
|
||||
* does not know how to use insert
|
||||
* or delete character sequences; we are
|
||||
* using VT52 functionality. Update the physical
|
||||
* row and column variables. It does try an
|
||||
* exploit erase to end of line. The RAINBOW version
|
||||
* of this routine uses fast video.
|
||||
*/
|
||||
updateline(row, vline, pline)
|
||||
char vline[];
|
||||
char pline[];
|
||||
{
|
||||
#if RAINBOW|IBM
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register int nch;
|
||||
|
||||
cp1 = &vline[0]; /* Use fast video. */
|
||||
cp2 = &pline[0];
|
||||
putline(row+1, 1, cp1);
|
||||
nch = term.t_ncol;
|
||||
do {
|
||||
*cp2 = *cp1;
|
||||
++cp2;
|
||||
++cp1;
|
||||
} while (--nch);
|
||||
#else
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register char *cp3;
|
||||
register char *cp4;
|
||||
register char *cp5;
|
||||
register int nbflag;
|
||||
|
||||
cp1 = &vline[0]; /* Compute left match. */
|
||||
cp2 = &pline[0];
|
||||
while (cp1!=&vline[term.t_ncol] && cp1[0]==cp2[0]) {
|
||||
++cp1;
|
||||
++cp2;
|
||||
}
|
||||
/* This can still happen, even though we only call this routine */
|
||||
/* on changed lines. A hard update is always done when a line */
|
||||
/* splits, a massive change is done, or a buffer is displayed */
|
||||
/* twice. This optimizes out most of the excess updating. A lot */
|
||||
/* of computes are used, but these tend to be hard operations */
|
||||
/* that do a lot of update, so I don't really care. */
|
||||
if (cp1 == &vline[term.t_ncol]) /* All equal. */
|
||||
return;
|
||||
nbflag = FALSE;
|
||||
cp3 = &vline[term.t_ncol]; /* Compute right match. */
|
||||
cp4 = &pline[term.t_ncol];
|
||||
while (cp3[-1] == cp4[-1]) {
|
||||
--cp3;
|
||||
--cp4;
|
||||
if (cp3[0] != ' ') /* Note if any nonblank */
|
||||
nbflag = TRUE; /* in right match. */
|
||||
}
|
||||
cp5 = cp3;
|
||||
if (nbflag == FALSE) { /* Erase to EOL ? */
|
||||
while (cp5!=cp1 && cp5[-1]==' ')
|
||||
--cp5;
|
||||
if (cp3-cp5 <= 3) /* Use only if erase is */
|
||||
cp5 = cp3; /* fewer characters. */
|
||||
}
|
||||
movecursor(row, (int)(cp1-&vline[0])); /* Go to start of line. */
|
||||
while (cp1 != cp5) { /* Ordinary. */
|
||||
(*term.t_putchar)(*cp1);
|
||||
++ttcol;
|
||||
*cp2++ = *cp1++;
|
||||
}
|
||||
if (cp5 != cp3) { /* Erase. */
|
||||
(*term.t_eeol)();
|
||||
while (cp1 != cp3)
|
||||
*cp2++ = *cp1++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Redisplay the mode line for
|
||||
* the window pointed to by the "wp".
|
||||
* This is the only routine that has any idea
|
||||
* of how the modeline is formatted. You can
|
||||
* change the modeline format by hacking at
|
||||
* this routine. Called by "update" any time
|
||||
* there is a dirty window.
|
||||
*/
|
||||
modeline(wp)
|
||||
register WINDOW *wp;
|
||||
{
|
||||
register char *cp;
|
||||
register int c;
|
||||
register int n;
|
||||
register BUFFER *bp;
|
||||
|
||||
n = wp->w_toprow+wp->w_ntrows; /* Location. */
|
||||
vscreen[n]->v_flag |= VFCHG; /* Redraw next time. */
|
||||
vtmove(n, 0); /* Seek to right line. */
|
||||
vtputc('-');
|
||||
bp = wp->w_bufp;
|
||||
if ((bp->b_flag&BFCHG) != 0) /* "*" if changed. */
|
||||
vtputc('*');
|
||||
else
|
||||
vtputc('-');
|
||||
n = 2;
|
||||
cp = PROMPT; /* Buffer name. */
|
||||
while ((c = *cp++) != 0) {
|
||||
vtputc(c);
|
||||
++n;
|
||||
}
|
||||
cp = &bp->b_bname[0];
|
||||
while ((c = *cp++) != 0) {
|
||||
vtputc(c);
|
||||
++n;
|
||||
}
|
||||
vtputc(' ');
|
||||
++n;
|
||||
if (bp->b_fname[0] != 0) { /* File name. */
|
||||
cp = "-- File: ";
|
||||
while ((c = *cp++) != 0) {
|
||||
vtputc(c);
|
||||
++n;
|
||||
}
|
||||
cp = &bp->b_fname[0];
|
||||
while ((c = *cp++) != 0) {
|
||||
vtputc(c);
|
||||
++n;
|
||||
}
|
||||
vtputc(' ');
|
||||
++n;
|
||||
}
|
||||
#if WFDEBUG
|
||||
vtputc('-');
|
||||
vtputc((wp->w_flag&WFMODE)!=0 ? 'M' : '-');
|
||||
vtputc((wp->w_flag&WFHARD)!=0 ? 'H' : '-');
|
||||
vtputc((wp->w_flag&WFEDIT)!=0 ? 'E' : '-');
|
||||
vtputc((wp->w_flag&WFMOVE)!=0 ? 'V' : '-');
|
||||
vtputc((wp->w_flag&WFFORCE)!=0 ? 'F' : '-');
|
||||
n += 6;
|
||||
#endif
|
||||
while (n < term.t_ncol) { /* Pad to full width. */
|
||||
vtputc('-');
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a command to the terminal
|
||||
* to move the hardware cursor to row "row"
|
||||
* and column "col". The row and column arguments
|
||||
* are origin 0. Optimize out random calls.
|
||||
* Update "ttrow" and "ttcol".
|
||||
*/
|
||||
movecursor(row, col)
|
||||
{
|
||||
if (row!=ttrow || col!=ttcol) {
|
||||
ttrow = row;
|
||||
ttcol = col;
|
||||
(*term.t_move)(row, col);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Erase the message line.
|
||||
* This is a special routine because
|
||||
* the message line is not considered to be
|
||||
* part of the virtual screen. It always works
|
||||
* immediately; the terminal buffer is flushed
|
||||
* via a call to the flusher.
|
||||
*/
|
||||
mlerase()
|
||||
{
|
||||
movecursor(term.t_nrow, 0);
|
||||
(*term.t_eeol)();
|
||||
(*term.t_flush)();
|
||||
mpresf = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask a yes or no question in
|
||||
* the message line. Return either TRUE,
|
||||
* FALSE, or ABORT. The ABORT status is returned
|
||||
* if the user bumps out of the question with
|
||||
* a ^G. Used any time a confirmation is
|
||||
* required.
|
||||
*/
|
||||
mlyesno(prompt)
|
||||
char *prompt;
|
||||
{
|
||||
register int s;
|
||||
char buf[64];
|
||||
|
||||
for (;;) {
|
||||
strcpy(buf, prompt);
|
||||
strcat(buf, " [y/n]? ");
|
||||
s = mlreply(buf, buf, sizeof(buf));
|
||||
if (s == ABORT)
|
||||
return (ABORT);
|
||||
if (s != FALSE) {
|
||||
if (buf[0]=='y' || buf[0]=='Y')
|
||||
return (TRUE);
|
||||
if (buf[0]=='n' || buf[0]=='N')
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a prompt into the message
|
||||
* line, then read back a response. Keep
|
||||
* track of the physical position of the cursor.
|
||||
* If we are in a keyboard macro throw the prompt
|
||||
* away, and return the remembered response. This
|
||||
* lets macros run at full speed. The reply is
|
||||
* always terminated by a carriage return. Handle
|
||||
* erase, kill, and abort keys.
|
||||
*/
|
||||
mlreply(prompt, buf, nbuf)
|
||||
char *prompt;
|
||||
char *buf;
|
||||
{
|
||||
register int cpos;
|
||||
register int i;
|
||||
register int c;
|
||||
|
||||
cpos = 0;
|
||||
if (kbdmop != NULL) {
|
||||
while ((c = *kbdmop++) != '\0')
|
||||
buf[cpos++] = c;
|
||||
buf[cpos] = 0;
|
||||
if (buf[0] == 0)
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
mlwrite(prompt);
|
||||
for (;;) {
|
||||
c = (*term.t_getchar)();
|
||||
switch (c) {
|
||||
case 0x0D: /* Return, end of line */
|
||||
buf[cpos++] = 0;
|
||||
if (kbdmip != NULL) {
|
||||
if (kbdmip+cpos > &kbdm[NKBDM-3]) {
|
||||
ctrlg(FALSE, 0);
|
||||
(*term.t_flush)();
|
||||
return (ABORT);
|
||||
}
|
||||
for (i=0; i<cpos; ++i)
|
||||
*kbdmip++ = buf[i];
|
||||
}
|
||||
(*term.t_putchar)('\r');
|
||||
ttcol = 0;
|
||||
(*term.t_flush)();
|
||||
if (buf[0] == 0)
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
|
||||
case 0x07: /* Bell, abort */
|
||||
(*term.t_putchar)('^');
|
||||
(*term.t_putchar)('G');
|
||||
ttcol += 2;
|
||||
ctrlg(FALSE, 0);
|
||||
(*term.t_flush)();
|
||||
return (ABORT);
|
||||
|
||||
case 0x7F: /* Rubout, erase */
|
||||
case 0x08: /* Backspace, erase */
|
||||
if (cpos != 0) {
|
||||
(*term.t_putchar)('\b');
|
||||
(*term.t_putchar)(' ');
|
||||
(*term.t_putchar)('\b');
|
||||
--ttcol;
|
||||
if (buf[--cpos] < 0x20) {
|
||||
(*term.t_putchar)('\b');
|
||||
(*term.t_putchar)(' ');
|
||||
(*term.t_putchar)('\b');
|
||||
--ttcol;
|
||||
}
|
||||
(*term.t_flush)();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x15: /* C-U, kill */
|
||||
while (cpos != 0) {
|
||||
(*term.t_putchar)('\b');
|
||||
(*term.t_putchar)(' ');
|
||||
(*term.t_putchar)('\b');
|
||||
--ttcol;
|
||||
if (buf[--cpos] < 0x20) {
|
||||
(*term.t_putchar)('\b');
|
||||
(*term.t_putchar)(' ');
|
||||
(*term.t_putchar)('\b');
|
||||
--ttcol;
|
||||
}
|
||||
}
|
||||
(*term.t_flush)();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (cpos < nbuf-1) {
|
||||
buf[cpos++] = c;
|
||||
if (c < ' ') {
|
||||
(*term.t_putchar)('^');
|
||||
++ttcol;
|
||||
c ^= 0x40;
|
||||
}
|
||||
(*term.t_putchar)(c);
|
||||
++ttcol;
|
||||
(*term.t_flush)();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a message into the message
|
||||
* line. Keep track of the physical cursor
|
||||
* position. A small class of printf like format
|
||||
* items is handled. Assumes the stack grows
|
||||
* down; this assumption is made by the "++"
|
||||
* in the argument scan loop. Set the "message
|
||||
* line" flag TRUE.
|
||||
*/
|
||||
mlwrite(fmt, arg)
|
||||
char *fmt;
|
||||
{
|
||||
register int c;
|
||||
register char *ap;
|
||||
|
||||
movecursor(term.t_nrow, 0);
|
||||
ap = (char *) &arg;
|
||||
while ((c = *fmt++) != 0) {
|
||||
if (c != '%') {
|
||||
(*term.t_putchar)(c);
|
||||
++ttcol;
|
||||
} else {
|
||||
c = *fmt++;
|
||||
switch (c) {
|
||||
case 'd':
|
||||
mlputi(*(int *)ap, 10);
|
||||
ap += sizeof(int);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
mlputi(*(int *)ap, 8);
|
||||
ap += sizeof(int);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
mlputi(*(int *)ap, 16);
|
||||
ap += sizeof(int);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
mlputli(*(long *)ap, 10);
|
||||
ap += sizeof(long);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
mlputs(*(char **)ap);
|
||||
ap += sizeof(char *);
|
||||
break;
|
||||
|
||||
default:
|
||||
(*term.t_putchar)(c);
|
||||
++ttcol;
|
||||
}
|
||||
}
|
||||
}
|
||||
(*term.t_eeol)();
|
||||
(*term.t_flush)();
|
||||
mpresf = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out a string.
|
||||
* Update the physical cursor position.
|
||||
* This assumes that the characters in the
|
||||
* string all have width "1"; if this is
|
||||
* not the case things will get screwed up
|
||||
* a little.
|
||||
*/
|
||||
mlputs(s)
|
||||
register char *s;
|
||||
{
|
||||
register int c;
|
||||
|
||||
while ((c = *s++) != 0) {
|
||||
(*term.t_putchar)(c);
|
||||
++ttcol;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out an integer, in
|
||||
* the specified radix. Update the physical
|
||||
* cursor position. This will not handle any
|
||||
* negative numbers; maybe it should.
|
||||
*/
|
||||
mlputi(i, r)
|
||||
{
|
||||
register int q;
|
||||
static char hexdigits[] = "0123456789ABCDEF";
|
||||
|
||||
if (i < 0) {
|
||||
i = -i;
|
||||
(*term.t_putchar)('-');
|
||||
}
|
||||
q = i/r;
|
||||
if (q != 0)
|
||||
mlputi(q, r);
|
||||
(*term.t_putchar)(hexdigits[i%r]);
|
||||
++ttcol;
|
||||
}
|
||||
|
||||
/*
|
||||
* do the same except as a long integer.
|
||||
*/
|
||||
mlputli(l, r)
|
||||
long l;
|
||||
{
|
||||
register long q;
|
||||
|
||||
if (l < 0) {
|
||||
l = -l;
|
||||
(*term.t_putchar)('-');
|
||||
}
|
||||
q = l/r;
|
||||
if (q != 0)
|
||||
mlputli(q, r);
|
||||
(*term.t_putchar)((int)(l%r)+'0');
|
||||
++ttcol;
|
||||
}
|
||||
|
||||
|
263
Mark Williams MWS v4/SAMPLE/ED.H
Normal file
263
Mark Williams MWS v4/SAMPLE/ED.H
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* This file is the general header file for
|
||||
* all parts of the MicroEMACS display editor. It contains
|
||||
* definitions used by everyone, and it contains the stuff
|
||||
* you have to edit to create a version of the editor for
|
||||
* a specific operating system and terminal.
|
||||
*/
|
||||
#ifdef COHERENT
|
||||
#define V7 1 /* V7 UN*X or Coherent */
|
||||
#define VMS 0 /* VAX/VMS */
|
||||
#define CPM 0 /* CP/M-86 */
|
||||
#define MSDOS 0 /* MS-DOS */
|
||||
#define GEM 0 /* GEMDOS */
|
||||
#define PROMPT " Coherent MicroEMACS -- "
|
||||
#endif
|
||||
|
||||
#ifdef GEMDOS
|
||||
#define V7 0 /* V7 UN*X or Coherent */
|
||||
#define VMS 0 /* VAX/VMS */
|
||||
#define CPM 0 /* CP/M-86 */
|
||||
#define MSDOS 0 /* MS-DOS */
|
||||
#define GEM 1 /* GEMDOS */
|
||||
#define UPPERNM 0 /* if 0 names in all lower case */
|
||||
#define PROMPT " ST MicroEMACS V1.6 -- "
|
||||
#endif
|
||||
|
||||
#ifdef MSDOS
|
||||
#define V7 0 /* V7 UN*X or Coherent */
|
||||
#define VMS 0 /* VAX/VMS */
|
||||
#define CPM 0 /* CP/M-86 */
|
||||
#define GEM 0 /* GEMDOS */
|
||||
#define PROMPT " DOS MicroEMACS V4.0.12 -- "
|
||||
#endif
|
||||
|
||||
#ifdef COHERENT
|
||||
#define ANSI 0
|
||||
#define VT52 0 /* VT52 terminal (Zenith). */
|
||||
#define VT100 0 /* Handle VT100 style keypad. */
|
||||
#define LK201 0 /* Handle LK201 style keypad. */
|
||||
#define RAINBOW 0 /* Use Rainbow fast video. */
|
||||
#define TERMCAP 1 /* Use TERMCAP */
|
||||
#endif
|
||||
|
||||
#ifdef GEMDOS
|
||||
#define ANSI 0
|
||||
#define VT52 1 /* VT52 terminal (Zenith). */
|
||||
#define VT100 0 /* Handle VT100 style keypad. */
|
||||
#define LK201 0 /* Handle LK201 style keypad. */
|
||||
#define RAINBOW 0 /* Use Rainbow fast video. */
|
||||
#define TERMCAP 0 /* Use TERMCAP */
|
||||
#endif
|
||||
|
||||
#ifdef MSDOS
|
||||
#ifndef IBM
|
||||
#define ANSI 1 /* Use ANSI.SYS */
|
||||
#else
|
||||
#define ANSI 0
|
||||
#endif
|
||||
#define VT52 0 /* VT52 terminal (Zenith). */
|
||||
#define VT100 0 /* Handle VT100 style keypad. */
|
||||
#define LK201 0 /* Handle LK201 style keypad. */
|
||||
#define RAINBOW 0 /* Use Rainbow fast video. */
|
||||
#define TERMCAP 0 /* Use TERMCAP */
|
||||
#endif
|
||||
|
||||
#ifndef PROMPT
|
||||
#define PROMPT " MicroEMACS -- "
|
||||
#endif
|
||||
|
||||
#define CVMVAS 1 /* C-V, M-V arg. in screens. */
|
||||
|
||||
#define NCFILES 5 /* Max # of files on command line */
|
||||
#define NFILEN 80 /* # of bytes, file name */
|
||||
#define NBUFN 16 /* # of bytes, buffer name */
|
||||
#define NLINE 256 /* # of bytes, line */
|
||||
#define NKBDM 256 /* # of strokes, keyboard macro */
|
||||
#define NPAT 80 /* # of bytes, pattern */
|
||||
#define HUGE 1000 /* Huge number */
|
||||
#define NSRCH 128 /* undoable search command len */
|
||||
#define ERRLINES 3 /* error window lines displayed */
|
||||
|
||||
#define AGRAVE 0x60 /* M- prefix, Grave (LK201) */
|
||||
#define METACH 0x1B /* M- prefix, Control-[, ESC */
|
||||
#define CTMECH 0x1C /* C-M- prefix, Control-\ */
|
||||
#define EXITCH 0x1D /* Exit level, Control-] */
|
||||
#define CTRLCH 0x1E /* C- prefix, Control-^ */
|
||||
#define HELPCH 0x1F /* Help key, Control-_ */
|
||||
|
||||
#define CTRL 0x0100 /* Control flag, or'ed in */
|
||||
#define META 0x0200 /* Meta flag, or'ed in */
|
||||
#define CTLX 0x0400 /* ^X flag, or'ed in */
|
||||
|
||||
#define FALSE 0 /* False, no, bad, etc. */
|
||||
#define TRUE 1 /* True, yes, good, etc. */
|
||||
#define ABORT 2 /* Death, ^G, abort, etc. */
|
||||
|
||||
#define FIOSUC 0 /* File I/O, success. */
|
||||
#define FIOFNF 1 /* File I/O, file not found. */
|
||||
#define FIOEOF 2 /* File I/O, end of file. */
|
||||
#define FIOERR 3 /* File I/O, error. */
|
||||
|
||||
#define CFCPCN 0x0001 /* Last command was C-P, C-N */
|
||||
#define CFKILL 0x0002 /* Last command was a kill */
|
||||
|
||||
/*
|
||||
* There is a window structure allocated for
|
||||
* every active display window. The windows are kept in a
|
||||
* big list, in top to bottom screen order, with the listhead at
|
||||
* "wheadp". Each window contains its own values of dot and mark.
|
||||
* The flag field contains some bits that are set by commands
|
||||
* to guide redisplay; although this is a bit of a compromise in
|
||||
* terms of decoupling, the full blown redisplay is just too
|
||||
* expensive to run for every input character.
|
||||
*/
|
||||
typedef struct WINDOW {
|
||||
struct WINDOW *w_wndp; /* Next window */
|
||||
struct BUFFER *w_bufp; /* Buffer displayed in window */
|
||||
struct LINE *w_linep; /* Top line in the window */
|
||||
struct LINE *w_dotp; /* Line containing "." */
|
||||
short w_doto; /* Byte offset for "." */
|
||||
struct LINE *w_markp; /* Line containing "mark" */
|
||||
short w_marko; /* Byte offset for "mark" */
|
||||
char w_toprow; /* Origin 0 top row of window */
|
||||
char w_ntrows; /* # of rows of text in window */
|
||||
char w_force; /* If NZ, forcing row. */
|
||||
char w_flag; /* Flags. */
|
||||
} WINDOW;
|
||||
|
||||
#define WFFORCE 0x01 /* Window needs forced reframe */
|
||||
#define WFMOVE 0x02 /* Movement from line to line */
|
||||
#define WFEDIT 0x04 /* Editing within a line */
|
||||
#define WFHARD 0x08 /* Better to a full display */
|
||||
#define WFMODE 0x10 /* Update mode line. */
|
||||
|
||||
/*
|
||||
* Text is kept in buffers. A buffer header, described
|
||||
* below, exists for every buffer in the system. The buffers are
|
||||
* kept in a big list, so that commands that search for a buffer by
|
||||
* name can find the buffer header. There is a safe store for the
|
||||
* dot and mark in the header, but this is only valid if the buffer
|
||||
* is not being displayed (that is, if "b_nwnd" is 0). The text for
|
||||
* the buffer is kept in a circularly linked list of lines, with
|
||||
* a pointer to the header line in "b_linep".
|
||||
*/
|
||||
typedef struct BUFFER {
|
||||
struct BUFFER *b_bufp; /* Link to next BUFFER */
|
||||
struct LINE *b_dotp; /* Link to "." LINE structure */
|
||||
short b_doto; /* Offset of "." in above LINE */
|
||||
struct LINE *b_markp; /* The same as the above two, */
|
||||
short b_marko; /* but for the "mark" */
|
||||
struct LINE *b_linep; /* Link to the header LINE */
|
||||
char b_nwnd; /* Count of windows on buffer */
|
||||
char b_flag; /* Flags */
|
||||
char b_fname[NFILEN]; /* File name */
|
||||
char b_bname[NBUFN]; /* Buffer name */
|
||||
} BUFFER;
|
||||
|
||||
#define BFTEMP 0x01 /* Internal temporary buffer */
|
||||
#define BFCHG 0x02 /* Changed since last write */
|
||||
#define BFERROR 0x04 /* Error file buffer */
|
||||
#define BFNOWRT 0x08 /* Don't write this buffer */
|
||||
#define BFBACKP 0x10 /* Rename file before write */
|
||||
#define BFWRITE 0x20 /* Written since read */
|
||||
#define BFTRUNC 0x40 /* File truncated */
|
||||
|
||||
/*
|
||||
* The starting position of a
|
||||
* region, and the size of the region in
|
||||
* characters, is kept in a region structure.
|
||||
* Used by the region commands.
|
||||
*/
|
||||
typedef struct {
|
||||
struct LINE *r_linep; /* Origin LINE address. */
|
||||
short r_offset; /* Origin LINE offset. */
|
||||
short r_size; /* Length in characters. */
|
||||
} REGION;
|
||||
|
||||
/*
|
||||
* All text is kept in circularly linked
|
||||
* lists of "LINE" structures. These begin at the
|
||||
* header line (which is the blank line beyond the
|
||||
* end of the buffer). This line is pointed to by
|
||||
* the "BUFFER". Each line contains a the number of
|
||||
* bytes in the line (the "used" size), the size
|
||||
* of the text array, and the text. The end of line
|
||||
* is not stored as a byte; it's implied. Future
|
||||
* additions will include update hints, and a
|
||||
* list of marks into the line.
|
||||
*/
|
||||
typedef struct LINE {
|
||||
struct LINE *l_fp; /* Link to the next line */
|
||||
struct LINE *l_bp; /* Link to the previous line */
|
||||
short l_size; /* Allocated size */
|
||||
short l_used; /* Used size */
|
||||
long l_lnumber; /* Line number in original file */
|
||||
char l_text[]; /* A bunch of characters. */
|
||||
} LINE;
|
||||
|
||||
#define lforw(lp) ((lp)->l_fp)
|
||||
#define lback(lp) ((lp)->l_bp)
|
||||
#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)
|
||||
#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
|
||||
#define llength(lp) ((lp)->l_used)
|
||||
#define l_number(lp) ((lp)->l_lnumber)
|
||||
/*
|
||||
* The editor communicates with the display
|
||||
* using a high level interface. A "TERM" structure
|
||||
* holds useful variables, and indirect pointers to
|
||||
* routines that do useful operations. The low level get
|
||||
* and put routines are here too. This lets a terminal,
|
||||
* in addition to having non standard commands, have
|
||||
* funny get and put character code too. The calls
|
||||
* might get changed to "termp->t_field" style in
|
||||
* the future, to make it possible to run more than
|
||||
* one terminal type.
|
||||
*/
|
||||
typedef struct {
|
||||
short t_nrow; /* Number of rows. */
|
||||
short t_ncol; /* Number of columns. */
|
||||
int (*t_open)(); /* Open terminal at the start. */
|
||||
int (*t_close)(); /* Close terminal at end. */
|
||||
int (*t_getchar)(); /* Get character from keyboard. */
|
||||
int (*t_putchar)(); /* Put character to display. */
|
||||
int (*t_flush)(); /* Flush output buffers. */
|
||||
int (*t_move)(); /* Move the cursor, origin 0. */
|
||||
int (*t_eeol)(); /* Erase to end of line. */
|
||||
int (*t_eeop)(); /* Erase to end of page. */
|
||||
int (*t_beep)(); /* Beep. */
|
||||
} TERM;
|
||||
|
||||
/* Command line switch flags */
|
||||
#define CF_ERROR (0x0001) /* Error edit switch specified */
|
||||
#define CF_BACKUP (0x0002) /* Rename file before write sw */
|
||||
#define CF_WARN (0x0004) /* Warn user before overwrite */
|
||||
#define CF_DEBUG (0x8000) /* Debugging flag */
|
||||
|
||||
extern int fillcol; /* Fill column */
|
||||
extern int currow; /* Cursor row */
|
||||
extern int curcol; /* Cursor column */
|
||||
extern int thisflag; /* Flags, this command */
|
||||
extern int lastflag; /* Flags, last command */
|
||||
extern int curgoal; /* Goal for C-P, C-N */
|
||||
extern int mpresf; /* Stuff in message line */
|
||||
extern int sgarbf; /* State of screen unknown */
|
||||
extern int runswitch; /* Switch flags */
|
||||
extern WINDOW *curwp; /* Current window */
|
||||
extern BUFFER *curbp; /* Current buffer */
|
||||
extern WINDOW *wheadp; /* Head of list of windows */
|
||||
extern BUFFER *bheadp; /* Head of list of buffers */
|
||||
extern BUFFER *blistp; /* Buffer for C-X C-B */
|
||||
extern BUFFER *errbp; /* Error file buffer */
|
||||
extern short kbdm[]; /* Holds kayboard macro data */
|
||||
extern short *kbdmip; /* Input pointer for above */
|
||||
extern short *kbdmop; /* Output pointer for above */
|
||||
extern char pat[]; /* Search pattern */
|
||||
extern TERM term; /* Terminal information. */
|
||||
extern char *ufiles[]; /* command-line specified files */
|
||||
extern int ffold; /* Fold in search flag. */
|
||||
extern char errfile[]; /* error file name */
|
||||
|
||||
extern BUFFER *bfind(); /* Lookup a buffer by name */
|
||||
extern WINDOW *wpopup(); /* Pop up window creation */
|
||||
extern LINE *lalloc(); /* Allocate a line */
|
205
Mark Williams MWS v4/SAMPLE/ERROR.C
Normal file
205
Mark Williams MWS v4/SAMPLE/ERROR.C
Normal file
@ -0,0 +1,205 @@
|
||||
#define ERRLINES 3 /* Number of lines in error window. */
|
||||
|
||||
/*
|
||||
* Micro-EMACS extension for MWC -- Search for next/previous error in
|
||||
* error buffer. This module must "know" the format of each type of
|
||||
* error message produced by the compiler that the error message is
|
||||
* generated by.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
/*
|
||||
* Find a window associated with the buffer list...
|
||||
*/
|
||||
|
||||
WINDOW *wfind(bp)
|
||||
BUFFER *bp;
|
||||
{
|
||||
register WINDOW *wp;
|
||||
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_bufp == bp)
|
||||
return wp;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search forward in the error buffer for an error message.
|
||||
*/
|
||||
|
||||
forwerr(dir)
|
||||
{
|
||||
register LINE *lp;
|
||||
register WINDOW *wp;
|
||||
register char *tp;
|
||||
register int c;
|
||||
register int error_line;
|
||||
char error_text[81];
|
||||
char *et;
|
||||
|
||||
if ((wp = wfind(errbp)) == NULL)
|
||||
return FALSE;
|
||||
|
||||
error_line = 0;
|
||||
lp = wp->w_dotp;
|
||||
if (wp->w_doto) {
|
||||
if (dir)
|
||||
lp = lp->l_bp;
|
||||
else
|
||||
lp = lp->l_fp;
|
||||
}
|
||||
while (lp != errbp->b_linep) {
|
||||
if((tp = &lp->l_text[0]) == NULL)
|
||||
goto next_line;
|
||||
while (((c = *tp++ - '0') >= 0) && (c <= 9)) {
|
||||
error_line *= 10;
|
||||
error_line += c;
|
||||
}
|
||||
et = error_text;
|
||||
while ((*et++ = *tp++) != 0) {
|
||||
if((et - error_text) > (term.t_ncol - 15))
|
||||
break;
|
||||
if((tp - lp->l_text) > (lp->l_used - 1))
|
||||
break;
|
||||
}
|
||||
*et = 0;
|
||||
mlwrite("[%d:%s]",error_line, error_text); /* Debug! */
|
||||
if (error_line != 0)
|
||||
break;
|
||||
next_line:
|
||||
if (dir)
|
||||
lp = lp->l_bp; /* Get the prev line... */
|
||||
else
|
||||
lp = lp->l_fp; /* Get the next line... */
|
||||
}
|
||||
|
||||
if (error_line == 0) {
|
||||
mlwrite("[No more errors.]");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wp->w_dotp = lp; /* set dot to this line */
|
||||
wp->w_doto = 1;
|
||||
wp->w_force = 1;
|
||||
wp->w_flag |= WFFORCE | WFMOVE;
|
||||
gotofline(TRUE, error_line);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure we have an error window...
|
||||
*/
|
||||
|
||||
errwind()
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register BUFFER *obp;
|
||||
register WINDOW *wp;
|
||||
register int r;
|
||||
|
||||
if ((runswitch & CF_ERROR) == 0) {
|
||||
mlwrite("[no error buffer]");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((bp = errbp) == NULL) {
|
||||
mlwrite( "[No error buffer]" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (bp->b_nwnd == 0) { /* If this buffer is not */
|
||||
if ((wp=wpopup()) == NULL) { /* in a window, display it */
|
||||
mlwrite("[Can't open window for error buffer]");
|
||||
return FALSE;
|
||||
}
|
||||
obp = wp->w_bufp; /* Get the old buffer ptr */
|
||||
if (--obp->b_nwnd == 0) {
|
||||
obp->b_dotp = wp->w_dotp;
|
||||
obp->b_doto = wp->w_doto;
|
||||
obp->b_markp = wp->w_markp;
|
||||
obp->b_marko = wp->w_marko;
|
||||
}
|
||||
wp->w_bufp = bp;
|
||||
++bp->b_nwnd;
|
||||
wp->w_linep = lback(bp->b_dotp);
|
||||
wp->w_dotp = bp->b_dotp;
|
||||
wp->w_doto = bp->b_doto;
|
||||
wp->w_markp = bp->b_markp;
|
||||
wp->w_marko = bp->b_marko;
|
||||
wp->w_flag |= WFMODE|WFHARD;
|
||||
if ((r = wp->w_ntrows - ERRLINES) > 0) {
|
||||
BUFFER *owp;
|
||||
|
||||
owp = curwp;
|
||||
curwp = wp;
|
||||
shrinkwind(0,r);
|
||||
curwp = owp;
|
||||
}
|
||||
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to find the next error line in the error file
|
||||
*/
|
||||
nexterr(f,n)
|
||||
{
|
||||
if (n < 0)
|
||||
return preverr(f, -n);
|
||||
|
||||
if (errwind() == FALSE)
|
||||
return FALSE;
|
||||
|
||||
return forwerr(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to find the previous error line in the error buffer.
|
||||
*/
|
||||
preverr(f,n)
|
||||
{
|
||||
if (n < 0)
|
||||
return nexterr(f, -n);
|
||||
|
||||
if (errwind() == FALSE)
|
||||
return FALSE;
|
||||
|
||||
return forwerr(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in the error file, giving it a buffer...
|
||||
*/
|
||||
readerr()
|
||||
{
|
||||
register BUFFER *bp;
|
||||
char bname[NBUFN];
|
||||
|
||||
makename(bname, "error-buffer"); /* New buffer name. */
|
||||
#if GEM
|
||||
fixname(bname);
|
||||
fixname(errfile);
|
||||
#endif
|
||||
if ((errbp = bp = bfind(bname, TRUE, 0)) == NULL) {
|
||||
mlwrite("Cannot create error buffer");
|
||||
return (FALSE);
|
||||
}
|
||||
if (--curbp->b_nwnd == 0) { /* Undisplay. */
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
curbp->b_markp = curwp->w_markp;
|
||||
curbp->b_marko = curwp->w_marko;
|
||||
}
|
||||
bp->b_flag |= BFNOWRT|BFERROR; /* Mark the buffer... */
|
||||
curbp = bp; /* Switch to it. */
|
||||
curwp->w_bufp = bp;
|
||||
curbp->b_nwnd++;
|
||||
return (readin(errfile)); /* Read it in. */
|
||||
}
|
99
Mark Williams MWS v4/SAMPLE/EXAMPLE.C
Normal file
99
Mark Williams MWS v4/SAMPLE/EXAMPLE.C
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* example.c
|
||||
* This program demonstrates the use of MS-DOS interrupt routines.
|
||||
* It works in either LARGE or SMALL model.
|
||||
* See also: int.c, intdis.m.
|
||||
* To compile: cc example.c int.c intdis.m -ns -na
|
||||
*/
|
||||
|
||||
#define INT_BREAK 0x1B /* Keyboard ctrl-break interrupt */
|
||||
#define INT_TICK 0x1C /* System timer tick interrupt */
|
||||
#define STACKSIZE 0x100 /* Small stack for locals */
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
int breakflag = FALSE;
|
||||
int timerflag = FALSE;
|
||||
|
||||
main()
|
||||
{
|
||||
int breaktrp(), timertrp();
|
||||
int breakid, timerid;
|
||||
|
||||
|
||||
/* Initialize the interrupts. */
|
||||
if ( (breakid=setint(INT_BREAK, breaktrp, STACKSIZE, 1)) == -1 )
|
||||
fatal("Cannot set Ctrl-Break interrupt.");
|
||||
else
|
||||
puts("Ctrl-Break interrupt set.");
|
||||
if ( (timerid=setint(INT_TICK, timertrp, STACKSIZE, 1)) == -1 )
|
||||
fatal("Cannot set timer tick interrupt.");
|
||||
else
|
||||
puts("Timer tick interrupt set.");
|
||||
|
||||
/* Wait for Ctrl-Break key. */
|
||||
puts("Type Ctrl-Break to exit.");
|
||||
for (;;) {
|
||||
if ( breakflag == TRUE )
|
||||
break;
|
||||
if ( timerflag == FALSE )
|
||||
continue;
|
||||
puts("Five seconds have passed.");
|
||||
timerflag = FALSE;
|
||||
}
|
||||
puts("Got the Ctrl-Break key.");
|
||||
|
||||
/* Reset the interrupts. */
|
||||
if ( clearint(breakid) != 0 )
|
||||
fatal("Cannot reset Ctrl-Break interrupt.");
|
||||
else
|
||||
puts("Ctrl-Break interrupt reset.");
|
||||
if ( clearint(timerid) != 0 )
|
||||
fatal("Cannot reset timer tick interrupt.");
|
||||
else
|
||||
puts("Timer tick interrupt reset.");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fatal error routine.
|
||||
*/
|
||||
fatal(s) register char *s;
|
||||
{
|
||||
puts(s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Service routine for the Ctrl-Break interrupt (0x1B).
|
||||
* Simply sets the breakflag to TRUE.
|
||||
*/
|
||||
breaktrp()
|
||||
{
|
||||
breakflag = TRUE;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Service routine for timer tick interrupt (0x1C).
|
||||
* This comes from the 8253-5 programmable interval timer at a rate of 18.2 Hz.
|
||||
* Every 91 (=18.2*5 ) interrupts (five seconds), set the timerflag to TRUE.
|
||||
*/
|
||||
timertrp()
|
||||
{
|
||||
static counter = 0;
|
||||
|
||||
if ( ++counter == 91 ) {
|
||||
timerflag = TRUE;
|
||||
counter = 0;
|
||||
}
|
||||
return(1); /* Link in case interrupt 0x1C did something already */
|
||||
}
|
29
Mark Williams MWS v4/SAMPLE/EXAMPLE1.C
Normal file
29
Mark Williams MWS v4/SAMPLE/EXAMPLE1.C
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/* This a simple C program that computes the results of three
|
||||
* different rates of inflation over a span of ten years.
|
||||
* Use this text file to learn how to use MicroEMACS commands
|
||||
* to make creating and editing text files fast, efficient, and
|
||||
* easy.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
main()
|
||||
{
|
||||
int i; /* count ten years */
|
||||
float w1, w2, w3; /* three inflated quantities */
|
||||
char *msg = " %2d\t%f %f\n"; /* printf string */
|
||||
i = 0;
|
||||
w1 = 1.0;
|
||||
w2 = 1.0;
|
||||
w3 = 1.0;
|
||||
for (i = 1; i<= 10; i++) {
|
||||
w1 *= 1.07; /* apply inflation */
|
||||
w2 *= 1.08;
|
||||
w3 *= 1.10;
|
||||
printf (msg, i, w1, w2, w3);
|
||||
}
|
||||
}
|
27
Mark Williams MWS v4/SAMPLE/EXAMPLE2.C
Normal file
27
Mark Williams MWS v4/SAMPLE/EXAMPLE2.C
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*Use this program to get better aquainted with the MicroEMACS
|
||||
*interactive screen editor. You can use this text to learn
|
||||
*some of the more advanced editing features of MicroEMACS.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
main()
|
||||
{
|
||||
FILE *fp;
|
||||
int ch;
|
||||
int filename[20];
|
||||
printf("Enter file name: ");
|
||||
gets(filename);
|
||||
|
||||
if ((fp =fopen(filename,"r")) !=NULL) {
|
||||
while ((ch = fgetc(fp)) != EOF)
|
||||
putc(ch, stdout);
|
||||
}
|
||||
else
|
||||
printf("Cannot open %s.\n", filename);
|
||||
fclose(fp);
|
||||
}
|
129
Mark Williams MWS v4/SAMPLE/EXAMPLE3.C
Normal file
129
Mark Williams MWS v4/SAMPLE/EXAMPLE3.C
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Factor prints out the prime factorization of numbers. If there are
|
||||
* any arguments, then it factors these. If there are no arguments,
|
||||
* then it reads stdin until either EOF or the number zero or a non-numeric
|
||||
* non-white-space character. Since factor does all of its calculations
|
||||
* in double format, the largest number which can be handled is quite
|
||||
* large.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define NUL '\0'
|
||||
#define ERROR 0x10 /* largest input base */
|
||||
#define MAXNUM 200 /* max number of chars in number */
|
||||
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
register char *argv[];
|
||||
{
|
||||
register char *chp;
|
||||
double n;
|
||||
double atod();
|
||||
char *getnum();
|
||||
|
||||
if (argc != 1)
|
||||
while ((chp=*++argv) != NULL && (n=atod(chp)) != 0)
|
||||
factor(n);
|
||||
else
|
||||
while ((chp=getnum()) != NULL && (n=atod(chp)) != 0)
|
||||
factor(n);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
die(str)
|
||||
char *str;
|
||||
{
|
||||
fprintf(stderr, "%r\n", &str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
die("usage: factor [number number ...]");
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
getnum()
|
||||
{
|
||||
register char *chp,
|
||||
ch;
|
||||
static char res[MAXNUM+1];
|
||||
|
||||
do {
|
||||
ch = getchar();
|
||||
} while (isascii(ch) && isspace(ch));
|
||||
if (!isascii(ch) || todigit(ch) == ERROR)
|
||||
return (NULL);
|
||||
for (chp=res; isascii(ch) && !isspace(ch); ch=getchar())
|
||||
if (chp < &res[MAXNUM])
|
||||
*chp++ = ch;
|
||||
if (chp >= &res[MAXNUM])
|
||||
die("Number too big");
|
||||
*chp++ = NUL;
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Todigit converts the char `ch' to an integer equivalent, assuming
|
||||
* that `ch' is a digit or `a'-`f' or `A'-`F'. If this is not true,
|
||||
* then it returns ERROR.
|
||||
*/
|
||||
todigit(ch)
|
||||
register int ch;
|
||||
{
|
||||
if (!isascii(ch))
|
||||
return (ERROR);
|
||||
if (isdigit(ch))
|
||||
return (ch - '0' + 0);
|
||||
if (isupper(ch))
|
||||
ch = tolower(ch);
|
||||
if ('a' <= ch && ch <= 'f')
|
||||
return (ch - 'a' + 0xa);
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Factor is the routine that actually factors the double `n'.
|
||||
* It writes the prime factors to standard output.
|
||||
*/
|
||||
factor(n)
|
||||
double n;
|
||||
{
|
||||
double temp,
|
||||
limit,
|
||||
try;
|
||||
|
||||
while (n > 1 && modf(n/2, &temp) == 0) {
|
||||
printf("2 ");
|
||||
n = temp;
|
||||
}
|
||||
limit = sqrt(n);
|
||||
for (try=3; try <= limit; try += 2) {
|
||||
if (modf(n/try, &temp) != 0)
|
||||
continue;
|
||||
do {
|
||||
printf("%.0f ", try);
|
||||
n = temp;
|
||||
} while (modf(n/try, &temp) == 0);
|
||||
limit = sqrt(n);
|
||||
}
|
||||
if (n > 1)
|
||||
printf("%.0f", n);
|
||||
putchar('\n');
|
||||
}
|
111
Mark Williams MWS v4/SAMPLE/FACTOR.C
Normal file
111
Mark Williams MWS v4/SAMPLE/FACTOR.C
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Factor prints out the prime factorization of numbers.
|
||||
* If there are arguments, it factors them.
|
||||
* If there are no arguments, it reads stdin until
|
||||
* either EOF or the number zero or a non-numeric
|
||||
* non-white-space character. Since factor does all of
|
||||
* its calculations in double format, the largest number
|
||||
* which can be handled is quite large.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define NUL '\0'
|
||||
#define ERROR 0x10 /* largest input base */
|
||||
#define MAXNUM 200 /* max number of chars in number */
|
||||
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
register char *argv[];
|
||||
{
|
||||
register char *chp;
|
||||
double n;
|
||||
double atod();
|
||||
char *getnum();
|
||||
|
||||
if (argc != 1)
|
||||
while ((chp=*++argv) != NULL &&
|
||||
(n=atod(chp)) != 0)
|
||||
factor(n);
|
||||
else
|
||||
while ((chp=getnum()) != NULL &&
|
||||
(n=atod(chp)) != 0)
|
||||
factor(n);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
die(str)
|
||||
char *str;
|
||||
{
|
||||
fprintf(stderr, "%r\n", &str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
die("Usage: factor [number number ...]");
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
getnum()
|
||||
{
|
||||
register char *chp,
|
||||
ch;
|
||||
static char res[MAXNUM+1];
|
||||
|
||||
do {
|
||||
ch = getchar();
|
||||
} while (isascii(ch) && isspace(ch));
|
||||
if (!isascii(ch) || todigit(ch) == ERROR)
|
||||
return (NULL);
|
||||
for (chp=res; isascii(ch) && !isspace(ch);
|
||||
ch=getchar())
|
||||
if (chp < &res[MAXNUM])
|
||||
*chp++ = ch;
|
||||
if (chp >= &res[MAXNUM])
|
||||
die("number too big");
|
||||
*chp++ = NUL;
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Factor is the routine that actually factors the double `n'.
|
||||
* It writes the prime factors to standard output.
|
||||
*/
|
||||
factor(n)
|
||||
double n;
|
||||
{
|
||||
double temp,
|
||||
limit,
|
||||
try;
|
||||
|
||||
while (n > 1 && modf(n/2, &temp) == 0) {
|
||||
printf("2 ");
|
||||
n = temp;
|
||||
}
|
||||
limit = sqrt(n);
|
||||
for (try=3; try <= limit; try += 2) {
|
||||
if (modf(n/try, &temp) != 0)
|
||||
continue;
|
||||
do {
|
||||
printf("%.0f ", try);
|
||||
n = temp;
|
||||
} while (modf(n/try, &temp) == 0);
|
||||
limit = sqrt(n);
|
||||
}
|
||||
if (n > 1)
|
||||
printf("%.0f", n);
|
||||
putchar('\n');
|
||||
}
|
353
Mark Williams MWS v4/SAMPLE/FDIR.C
Normal file
353
Mark Williams MWS v4/SAMPLE/FDIR.C
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* fdir.c
|
||||
* 5/8/87
|
||||
*
|
||||
* This program prints a formatted directory of its command line arguments.
|
||||
* Example command lines:
|
||||
* fdir
|
||||
* fdir -t
|
||||
* fdir *.c
|
||||
* fdir \test\*.c \source\*.*
|
||||
* It demonstrates some advanced features of MSDOS MWC86:
|
||||
* (1) The intcall() function, used to call MSDOS.
|
||||
* (2) The ptoreg() macro, used to pass a pointer to MSDOS
|
||||
* using code which is independent of LARGE or SMALL model.
|
||||
* (3) Bit fields, used to reference the dates of the files.
|
||||
* (4) The qsort() function, used to sort files and directories.
|
||||
* (5) The ctype macros.
|
||||
* (6) Dynamic memory allocation.
|
||||
* The -t option sorts files by time, -s sorts by size;
|
||||
* otherwise, files within each directory are sorted alphabetically.
|
||||
* Directories are listed before other files.
|
||||
* The output is in the following format for each file:
|
||||
* <attribute bits> <file length> <last modification date> <filename>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Header files.
|
||||
*/
|
||||
#include <stdio.h> /* Standard I/O definitions */
|
||||
#include <ctype.h> /* Character type macros */
|
||||
#include <dos.h> /* MSDOS definitions */
|
||||
|
||||
/*
|
||||
* Predefined limits.
|
||||
*/
|
||||
#define FNLEN 80 /* Maximum filename length */
|
||||
#define MAXFILES 512 /* Max number of files/directory */
|
||||
|
||||
/*
|
||||
* This macro returns the number of elements of its array argument.
|
||||
*/
|
||||
#define SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
/*
|
||||
* File attributes.
|
||||
* Defined on page C-4 of the IBM-PC DOS 2.0 manual.
|
||||
*/
|
||||
#define A_RONLY 0x01 /* Read only file */
|
||||
#define A_HIDDEN 0x02 /* Hidden file */
|
||||
#define A_SYSTEM 0x04 /* System file */
|
||||
#define A_DIRECTORY 0x10 /* Directory file */
|
||||
#define A_ARCHIVE 0x20 /* Archive bit */
|
||||
|
||||
/*
|
||||
* Attribute structure, associating a name with each mask.
|
||||
*/
|
||||
static struct atr {
|
||||
int a_mask;
|
||||
int a_name;
|
||||
} atr[] = {
|
||||
A_DIRECTORY, 'd', /* Directory file */
|
||||
A_RONLY, 'r', /* Read only file */
|
||||
A_HIDDEN, 'h', /* Hidden file */
|
||||
A_SYSTEM, 's', /* System file */
|
||||
A_ARCHIVE, 'a' /* Archive bit */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of MSDOS date/time bit fields.
|
||||
* Defined on page C-5 of the IBM-PC DOS 2.0 manual.
|
||||
*/
|
||||
struct date {
|
||||
unsigned d_sec : 5; /* Time, 2 second intervals */
|
||||
unsigned d_min : 6; /* Time, minutes */
|
||||
unsigned d_hour : 5; /* Time, hours */
|
||||
unsigned d_day : 5; /* Date, day of month */
|
||||
unsigned d_month : 4; /* Date, month of year */
|
||||
unsigned d_year : 7; /* Date, year since 1980 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure filled in by MSDOS for FINDFIRST and FINDNEXT calls.
|
||||
* Defined of page D-49 of the IBM-PC DOS 2.0 manual.
|
||||
*/
|
||||
#define FNDINFO 21
|
||||
#define FNDNAME 13
|
||||
struct find {
|
||||
char fnd_dosinfo[FNDINFO]; /* Reserved for dos */
|
||||
char fnd_attr; /* File attribute */
|
||||
struct date fnd_date; /* Date structure */
|
||||
long fnd_size; /* File size */
|
||||
char fnd_name[FNDNAME]; /* File name less path */
|
||||
};
|
||||
|
||||
/*
|
||||
* Routines which return values other than int.
|
||||
* All such routines should be declared before they are used.
|
||||
* Failure to do so could sacrifice portability between machines
|
||||
* or between LARGE and SMALL model.
|
||||
*/
|
||||
extern char *basename();
|
||||
extern char *date();
|
||||
extern void fatal();
|
||||
extern char *malloc();
|
||||
extern int qscmp();
|
||||
extern char *rindex();
|
||||
extern char *strcpy();
|
||||
extern char *strlower();
|
||||
|
||||
/*
|
||||
* Global data.
|
||||
*/
|
||||
int aflag = 0; /* Set if "-a" specified. */
|
||||
int howsort = 0;
|
||||
int filecount = 0; /* Total number of files */
|
||||
int dircount = 0; /* Total number of directories */
|
||||
long bytecount = 0L; /* Total length of files in bytes */
|
||||
char path[FNLEN]; /* Filename path */
|
||||
struct find *fnd[MAXFILES]; /* Pointers to file structures */
|
||||
|
||||
main(argc, argv)
|
||||
int argc; /* Number of command line arguments */
|
||||
char *argv[]; /* Array of pointers to arguments */
|
||||
{
|
||||
register int i;
|
||||
register int count; /* Number of files found */
|
||||
register char *file; /* Command line argument */
|
||||
register int status; /* Exit status */
|
||||
|
||||
status = 0;
|
||||
|
||||
/* "fdir -a" lists "." and "..", which are otherwise suppressed. */
|
||||
if (argc > 1 && *argv[1] == '-') { /* options */
|
||||
while ((i = toupper(*++argv[1])) != '\0')
|
||||
if (i == 'A')
|
||||
aflag = 1;
|
||||
else
|
||||
howsort = i;
|
||||
++argv;
|
||||
--argc;
|
||||
}
|
||||
|
||||
/* If no command line arguments, i.e. "fdir", fake argument "*.*". */
|
||||
if (argc == 1) {
|
||||
argc = 2;
|
||||
argv[1] = "*.*";
|
||||
}
|
||||
|
||||
while (--argc) { /* Loop for each argument */
|
||||
file = *++argv; /* Grab next argument */
|
||||
i = basename(file) - file; /* Find pathname length */
|
||||
if (i + FNDNAME > FNLEN)
|
||||
fatal("filename \"%s\" too long", file);
|
||||
strcpy(path, file); /* Copy file to path[] */
|
||||
path[i] = '\0'; /* NUL-terminate pathname */
|
||||
strlower(path); /* Convert pathname to lower case */
|
||||
count = dosfind(file); /* Find matching files */
|
||||
if (!count) { /* Issue error if no match */
|
||||
++status;
|
||||
fprintf(stderr, "fdir: cannot find \"%s\"\n", file);
|
||||
}
|
||||
qsort(fnd, count, sizeof(struct find *), qscmp); /* Sort */
|
||||
for (i=0; i < count; i++) /* Loop for each matching file */
|
||||
printinfo(fnd[i]); /* Print information */
|
||||
}
|
||||
|
||||
/* Print totals. */
|
||||
if (dircount != 0 || filecount != 0 || bytecount != 0L)
|
||||
printf("\n");
|
||||
if (dircount != 0)
|
||||
printf("Directories: %6d\n", dircount);
|
||||
if (filecount != 0)
|
||||
printf("Files: %6d\n", filecount);
|
||||
if (bytecount != 0L)
|
||||
printf("Total bytes: %6ld\n", bytecount);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a pointer to the beginning of the filename (past pathname, if any).
|
||||
*/
|
||||
char *basename(name) char *name;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if ((p = rindex(name, '\\')) != NULL || (p = rindex(name, ':')) != NULL)
|
||||
return(++p);
|
||||
return(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pointer to a date structure, return a pointer to an ASCII date.
|
||||
* The buffer for the return value is statically allocated.
|
||||
*/
|
||||
char *date(dp) register struct date *dp;
|
||||
{
|
||||
static char ad[21];
|
||||
static char *month[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
sprintf(ad, "%s %2d %02d:%02d:%02d %4d",
|
||||
month[dp->d_month - 1], dp->d_day,
|
||||
dp->d_hour, dp->d_min, dp->d_sec * 2,
|
||||
dp->d_year + 1980);
|
||||
return(ad);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand filename 'file' possibly containing wildcard characters.
|
||||
* Initialize global array fnd[] with pointers to matching filenames and
|
||||
* return the number of matches found.
|
||||
*/
|
||||
int dosfind(file) char *file;
|
||||
{
|
||||
register int count; /* Number of files found */
|
||||
struct find f; /* Filename return data from MSDOS */
|
||||
struct reg r; /* Register values for intcall() */
|
||||
|
||||
/*
|
||||
* Call MSDOS to set the disk transfer address (DTA) to &f.
|
||||
* Macro ptoreg() stores the segment:offset of f
|
||||
* in r.r_ds and r.r_dx in a model independent manner.
|
||||
*/
|
||||
r.r_ax = SETDTA; /* Function code to AX */
|
||||
ptoreg(dsreg, r.r_dx, r.r_ds, &f); /* Seg:off of f to DS:DX */
|
||||
intcall(&r, &r, DOSINT); /* Call MSDOS */
|
||||
|
||||
/* Call MSDOS to find the first matching filename. */
|
||||
r.r_ax = NFFIRST; /* Function code to AX*/
|
||||
r.r_cx = A_HIDDEN | A_SYSTEM | A_DIRECTORY | A_RONLY | A_ARCHIVE;
|
||||
/* Attributes to CX */
|
||||
ptoreg(dsreg, r.r_dx, r.r_ds, file); /* Seg:off of file to DS:DX */
|
||||
intcall(&r, &r, DOSINT); /* Call MSDOS */
|
||||
|
||||
/*
|
||||
* Loop for each matching filename.
|
||||
* Carry flag set indicates no more matching files.
|
||||
*/
|
||||
for (count = 0; (r.r_flags & F_CF) == 0; count++) {
|
||||
|
||||
/* Do not exceed maximum number of matching files. */
|
||||
if (count >= MAXFILES)
|
||||
fatal("too many matching files");
|
||||
|
||||
/* Dynamically allocate memory for a find structure. */
|
||||
if ((fnd[count] = (struct find *)malloc(sizeof(struct find))) == NULL)
|
||||
fatal("out of memory");
|
||||
|
||||
/* Copy the structure to the allocated space. */
|
||||
*fnd[count] = f; /* Structure assignment. */
|
||||
|
||||
/* Find the next matching filename. */
|
||||
r.r_ax = NFNEXT; /* Find next function */
|
||||
intcall(&r, &r, DOSINT); /* Call MSDOS */
|
||||
}
|
||||
return(count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fatal error.
|
||||
* The "%r" (recursive) format specifier is non-portable.
|
||||
*/
|
||||
void fatal(p) char *p;
|
||||
{
|
||||
fprintf(stderr, "fdir: %r\n", &p);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a line of information about a file.
|
||||
* Update running totals.
|
||||
*/
|
||||
printinfo(fndp) register struct fnd *fndp;
|
||||
{
|
||||
register int i, attr;
|
||||
|
||||
attr = fndp->fnd_attr;
|
||||
if (attr&A_DIRECTORY) {
|
||||
/* Suppress "." and ".." unless "-a" specified. */
|
||||
if (!aflag && (strcmp(fndp->fnd_name, ".") == 0
|
||||
|| strcmp(fndp->fnd_name, "..") == 0))
|
||||
return;
|
||||
++dircount;
|
||||
}
|
||||
else
|
||||
++filecount;
|
||||
bytecount += fndp->fnd_size;
|
||||
|
||||
/* Print attributes (name if bit is set, '-' if not). */
|
||||
for (i = 0; i < SIZE(atr); i++)
|
||||
putchar((atr[i].a_mask & attr) ? atr[i].a_name : '-');
|
||||
|
||||
/* Print size, date, name. */
|
||||
printf(" %10D %s %s%s\n",
|
||||
fndp->fnd_size, date(&(fndp->fnd_date)), path, strlower(fndp->fnd_name));
|
||||
|
||||
/* Free allocated structure. */
|
||||
free(fndp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare routine for qsort().
|
||||
* Called by qsort(), passed two pointers to find structure pointers.
|
||||
* Only the pointers to the find structures are actually sorted.
|
||||
*/
|
||||
int qscmp(fpp1, fpp2) struct find **fpp1, **fpp2;
|
||||
{
|
||||
register struct find *f1;
|
||||
register struct find *f2;
|
||||
register int i;
|
||||
|
||||
f1 = *fpp1;
|
||||
f2 = *fpp2;
|
||||
if (i = (f2->fnd_attr&A_DIRECTORY) - (f1->fnd_attr&A_DIRECTORY))
|
||||
return(i); /* Exactly one is directory */
|
||||
if (howsort == 'T') { /* take advantage of form of date */
|
||||
if (*(unsigned long *)&f1->fnd_date
|
||||
< *(unsigned long *)&f2->fnd_date)
|
||||
return(1);
|
||||
else
|
||||
return(-1);
|
||||
} else if (howsort == 'S') {
|
||||
if( f1->fnd_size < f2->fnd_size)
|
||||
return(1);
|
||||
else
|
||||
return(-1);
|
||||
} else
|
||||
return (strcmp(f1->fnd_name, f2->fnd_name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert string 'str' to lower case (in-place) and return a pointer to it.
|
||||
*/
|
||||
char *strlower(str) char *str;
|
||||
{
|
||||
register int c;
|
||||
register char *s;
|
||||
|
||||
s = str;
|
||||
while (c = *s)
|
||||
*s++ = tolower(c);
|
||||
return(str);
|
||||
}
|
||||
|
||||
/* end of fdir.c */
|
382
Mark Williams MWS v4/SAMPLE/FILE.C
Normal file
382
Mark Williams MWS v4/SAMPLE/FILE.C
Normal file
@ -0,0 +1,382 @@
|
||||
/*
|
||||
* The routines in this file
|
||||
* handle the reading and writing of
|
||||
* disk files. All of details about the
|
||||
* reading and writing of the disk are
|
||||
* in "fileio.c".
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
/*
|
||||
* Read a file into the current
|
||||
* buffer. This is really easy; all you do it
|
||||
* find the name of the file, and call the standard
|
||||
* "read a file into the current buffer" code.
|
||||
* Bound to "C-X C-R".
|
||||
*/
|
||||
fileread(f, n)
|
||||
{
|
||||
register int s;
|
||||
char fname[NFILEN];
|
||||
|
||||
if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE)
|
||||
return (s);
|
||||
#if GEM
|
||||
fixname(fname);
|
||||
#endif
|
||||
return (readin(fname));
|
||||
}
|
||||
|
||||
/*
|
||||
* Select a file for editing.
|
||||
* Look around to see if you can find the
|
||||
* fine in another buffer; if you can find it
|
||||
* just switch to the buffer. If you cannot find
|
||||
* the file, create a new buffer, read in the
|
||||
* text, and switch to the new buffer.
|
||||
* Bound to C-X C-V.
|
||||
*/
|
||||
filevisit(f, n)
|
||||
{
|
||||
char fname[NFILEN];
|
||||
int s;
|
||||
|
||||
if ((s=mlreply("Visit file: ", fname, NFILEN)) != TRUE)
|
||||
return (s);
|
||||
#if GEM
|
||||
fixname(fname);
|
||||
#endif
|
||||
return visitfile(fname);
|
||||
}
|
||||
|
||||
/* Real file visit routine... */
|
||||
visitfile(fname)
|
||||
char fname[];
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register WINDOW *wp;
|
||||
register LINE *lp;
|
||||
register int i;
|
||||
register int s;
|
||||
char bname[NBUFN];
|
||||
|
||||
for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
|
||||
if ((bp->b_flag&BFTEMP)==0 && strcmp(bp->b_fname, fname)==0) {
|
||||
if (--curbp->b_nwnd == 0) {
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
curbp->b_markp = curwp->w_markp;
|
||||
curbp->b_marko = curwp->w_marko;
|
||||
}
|
||||
curbp = bp;
|
||||
curwp->w_bufp = bp;
|
||||
if (bp->b_nwnd++ == 0) {
|
||||
curwp->w_dotp = bp->b_dotp;
|
||||
curwp->w_doto = bp->b_doto;
|
||||
curwp->w_markp = bp->b_markp;
|
||||
curwp->w_marko = bp->b_marko;
|
||||
} else {
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp!=curwp && wp->w_bufp==bp) {
|
||||
curwp->w_dotp = wp->w_dotp;
|
||||
curwp->w_doto = wp->w_doto;
|
||||
curwp->w_markp = wp->w_markp;
|
||||
curwp->w_marko = wp->w_marko;
|
||||
break;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
}
|
||||
lp = curwp->w_dotp;
|
||||
i = curwp->w_ntrows/2;
|
||||
while (i-- && lback(lp)!=curbp->b_linep)
|
||||
lp = lback(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_flag |= WFMODE|WFHARD;
|
||||
mlwrite("[Old buffer]");
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
makename(bname, fname); /* New buffer name. */
|
||||
while ((bp=bfind(bname, FALSE, 0)) != NULL) {
|
||||
s = mlreply("Buffer name: ", bname, NBUFN);
|
||||
#if GEM
|
||||
fixname(bname);
|
||||
#endif
|
||||
if (s == ABORT) /* ^G to just quit */
|
||||
return (s);
|
||||
if (s == FALSE) { /* CR to clobber it */
|
||||
makename(bname, fname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
|
||||
mlwrite("Cannot create buffer");
|
||||
return (FALSE);
|
||||
}
|
||||
if (--curbp->b_nwnd == 0) { /* Undisplay. */
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
curbp->b_markp = curwp->w_markp;
|
||||
curbp->b_marko = curwp->w_marko;
|
||||
}
|
||||
curbp = bp; /* Switch to it. */
|
||||
curwp->w_bufp = bp;
|
||||
curbp->b_nwnd++;
|
||||
return (readin(fname)); /* Read it in. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Read file "fname" into the current
|
||||
* buffer, blowing away any text found there. Called
|
||||
* by both the read and visit commands. Return the final
|
||||
* status of the read. Also called by the mainline,
|
||||
* to read in a file specified on the command line as
|
||||
* an argument.
|
||||
*/
|
||||
readin(fname)
|
||||
char fname[];
|
||||
{
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register int i;
|
||||
register WINDOW *wp;
|
||||
register BUFFER *bp;
|
||||
register int s;
|
||||
register int nbytes;
|
||||
register int nline;
|
||||
char line[NLINE];
|
||||
|
||||
mlwrite(" ");
|
||||
bp = curbp; /* Cheap. */
|
||||
if ((s=bclear(bp)) != TRUE) /* Might be old. */
|
||||
return (s);
|
||||
bp->b_flag &= ~(BFTEMP|BFCHG|BFTRUNC);
|
||||
strcpy(bp->b_fname, fname);
|
||||
if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
|
||||
goto out;
|
||||
if (s == FIOFNF) { /* File not found. */
|
||||
mlwrite("[New file: %s]", fname);
|
||||
goto out;
|
||||
}
|
||||
mlwrite("[Reading file %s]", fname);
|
||||
nline = 0;
|
||||
while ((s=ffgetline(line, NLINE)) == FIOSUC) {
|
||||
nbytes = strlen(line);
|
||||
if ((lp1=lalloc(nbytes)) == NULL) {
|
||||
mlwrite("File too large for available memory!");
|
||||
bp->b_flag |= BFTRUNC; /* Mark buffer truncated */
|
||||
s = FIOERR; /* Keep message on the */
|
||||
break; /* display. */
|
||||
}
|
||||
lp2 = lback(curbp->b_linep);
|
||||
lp2->l_fp = lp1;
|
||||
lp1->l_fp = curbp->b_linep;
|
||||
lp1->l_bp = lp2;
|
||||
curbp->b_linep->l_bp = lp1;
|
||||
lp1->l_lnumber = ++nline;
|
||||
for (i=0; i<nbytes; ++i)
|
||||
lputc(lp1, i, line[i]);
|
||||
}
|
||||
ffclose(); /* Ignore errors. */
|
||||
if (s == FIOEOF) { /* Don't zap message! */
|
||||
if (nline == 1)
|
||||
mlwrite("[Read 1 line]");
|
||||
else
|
||||
mlwrite("[Read %d lines]", nline);
|
||||
}
|
||||
out:
|
||||
for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
|
||||
if (wp->w_bufp == curbp) {
|
||||
wp->w_linep = lforw(curbp->b_linep);
|
||||
wp->w_dotp = lforw(curbp->b_linep);
|
||||
wp->w_doto = 0;
|
||||
wp->w_markp = NULL;
|
||||
wp->w_marko = 0;
|
||||
wp->w_flag |= WFMODE|WFHARD;
|
||||
}
|
||||
}
|
||||
if (s == FIOERR) /* False if error. */
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a file name, and from it
|
||||
* fabricate a buffer name. This routine knows
|
||||
* about the syntax of file names on the target system.
|
||||
* I suppose that this information could be put in
|
||||
* a better place than a line of code.
|
||||
*/
|
||||
makename(bname, fname)
|
||||
char bname[];
|
||||
char fname[];
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
|
||||
cp1 = &fname[0];
|
||||
while (*cp1 != 0)
|
||||
++cp1;
|
||||
#if VMS
|
||||
while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
|
||||
--cp1;
|
||||
#endif
|
||||
#if CPM
|
||||
while (cp1!=&fname[0] && cp1[-1]!=':')
|
||||
--cp1;
|
||||
#endif
|
||||
#if MSDOS || GEM
|
||||
while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\')
|
||||
--cp1;
|
||||
#endif
|
||||
#if V7
|
||||
while (cp1!=&fname[0] && cp1[-1]!='/')
|
||||
--cp1;
|
||||
#endif
|
||||
cp2 = &bname[0];
|
||||
while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
|
||||
*cp2++ = *cp1++;
|
||||
*cp2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask for a file name, and write the
|
||||
* contents of the current buffer to that file.
|
||||
* Update the remembered file name and clear the
|
||||
* buffer changed flag. This handling of file names
|
||||
* is different from the earlier versions, and
|
||||
* is more compatable with Gosling EMACS than
|
||||
* with ITS EMACS. Bound to "C-X C-W".
|
||||
*/
|
||||
filewrite(f, n)
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register int s;
|
||||
char fname[NFILEN];
|
||||
|
||||
if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE)
|
||||
return (s);
|
||||
#if GEM
|
||||
fixname(fname);
|
||||
#endif
|
||||
if ((s=writeout(fname)) == TRUE) {
|
||||
strcpy(curbp->b_fname, fname);
|
||||
curbp->b_flag &= ~BFCHG;
|
||||
wp = wheadp; /* Update mode lines. */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the contents of the current buffer in its associatd file. No nothing
|
||||
* if nothing has changed (this may be a bug, not a feature). Error if there is
|
||||
* no remembered file name for the buffer. Bound to "C-X C-S".
|
||||
* May get called by "C-Z".
|
||||
*/
|
||||
filesave(f, n)
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register int s;
|
||||
|
||||
if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */
|
||||
return (TRUE);
|
||||
if (curbp->b_fname[0] == 0) { /* Must have a name. */
|
||||
mlwrite("No file name");
|
||||
return (FALSE);
|
||||
}
|
||||
if ((curbp->b_flag & BFTRUNC) != 0) { /* If file was truncated... */
|
||||
if (mlyesno("File was truncated -- write it anyway") != TRUE)
|
||||
return (FALSE);
|
||||
}
|
||||
if ((s=writeout(curbp->b_fname)) == TRUE) {
|
||||
curbp->b_flag &= ~(BFCHG|BFTRUNC);
|
||||
wp = wheadp; /* Update mode lines. */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function performs the details of file
|
||||
* writing. Uses the file management routines in the
|
||||
* "fileio.c" package. The number of lines written is
|
||||
* displayed. Sadly, it looks inside a LINE; provide
|
||||
* a macro for this. Most of the grief is error
|
||||
* checking of some sort.
|
||||
*/
|
||||
writeout(fn)
|
||||
char *fn;
|
||||
{
|
||||
register int s;
|
||||
register LINE *lp;
|
||||
register int nline;
|
||||
|
||||
if ((s=ffwopen(fn)) != FIOSUC) /* Open writes message. */
|
||||
return (FALSE);
|
||||
lp = lforw(curbp->b_linep); /* First line. */
|
||||
nline = 0; /* Number of lines. */
|
||||
while (lp != curbp->b_linep) {
|
||||
if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
|
||||
break;
|
||||
++nline;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
if (s == FIOSUC) { /* No write error. */
|
||||
s = ffclose();
|
||||
if (s == FIOSUC) { /* No close error. */
|
||||
curbp->b_flag |= BFWRITE; /* Written... */
|
||||
if (nline == 1)
|
||||
mlwrite("[Wrote 1 line]");
|
||||
else
|
||||
mlwrite("[Wrote %d lines]", nline);
|
||||
}
|
||||
} else /* Ignore close error */
|
||||
ffclose(); /* if a write error. */
|
||||
if (s != FIOSUC) /* Some sort of error. */
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The command allows the user to modify the file name associated with
|
||||
* the current buffer. It is like the "f" command
|
||||
* in UNIX "ed". The operation is simple; just zap
|
||||
* the name in the BUFFER structure, and mark the windows
|
||||
* as needing an update. You can type a blank line at the
|
||||
* prompt if you wish.
|
||||
*/
|
||||
filename(f, n)
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register int s;
|
||||
char fname[NFILEN];
|
||||
|
||||
if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT)
|
||||
return (s);
|
||||
#if GEM
|
||||
fixname(fname);
|
||||
#endif
|
||||
if (s == FALSE)
|
||||
strcpy(curbp->b_fname, "");
|
||||
else
|
||||
strcpy(curbp->b_fname, fname);
|
||||
wp = wheadp; /* Update mode lines. */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
131
Mark Williams MWS v4/SAMPLE/FILEIO.C
Normal file
131
Mark Williams MWS v4/SAMPLE/FILEIO.C
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* The routines in this file
|
||||
* read and write ASCII files from the
|
||||
* disk. All of the knowledge about files
|
||||
* are here. A better message writing
|
||||
* scheme should be used.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
FILE *ffp; /* File pointer, all functions. */
|
||||
|
||||
/*
|
||||
* Open a file for reading.
|
||||
*/
|
||||
ffropen(fn)
|
||||
char *fn;
|
||||
{
|
||||
if ((ffp=fopen(fn, "r")) == NULL)
|
||||
return (FIOFNF);
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a file for writing.
|
||||
* Return TRUE if all is well, and
|
||||
* FALSE on error (cannot create).
|
||||
*/
|
||||
ffwopen(fn)
|
||||
char *fn;
|
||||
{
|
||||
#if VMS
|
||||
register int fd;
|
||||
|
||||
if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
|
||||
|| (ffp=fdopen(fd, "w")) == NULL) {
|
||||
#else
|
||||
if ((ffp=fopen(fn, "w")) == NULL) {
|
||||
#endif
|
||||
mlwrite("Cannot open file for writing");
|
||||
return (FIOERR);
|
||||
}
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a file.
|
||||
* Should look at the status in all systems.
|
||||
*/
|
||||
ffclose()
|
||||
{
|
||||
#if V7
|
||||
if (fclose(ffp) != FALSE) {
|
||||
mlwrite("Error closing file");
|
||||
return(FIOERR);
|
||||
}
|
||||
return(FIOSUC);
|
||||
#endif
|
||||
fclose(ffp);
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a line to the already
|
||||
* opened file. The "buf" points to the
|
||||
* buffer, and the "nbuf" is its length, less
|
||||
* the free newline. Return the status.
|
||||
* Check only at the newline.
|
||||
*/
|
||||
ffputline(buf, nbuf)
|
||||
register char buf[];
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; i<nbuf; ++i)
|
||||
putc(buf[i]&0xFF, ffp);
|
||||
putc('\n', ffp);
|
||||
if (ferror(ffp) != FALSE) {
|
||||
mlwrite("Write I/O error");
|
||||
return (FIOERR);
|
||||
}
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a line from a file,
|
||||
* and store the bytes in the supplied
|
||||
* buffer. The "nbuf" is the length of the
|
||||
* buffer. Complain about long lines and lines
|
||||
* at the end of the file that don't have a
|
||||
* newline present. Check for I/O errors
|
||||
* too. Return status.
|
||||
*/
|
||||
ffgetline(buf, nbuf)
|
||||
register char buf[];
|
||||
{
|
||||
register int c;
|
||||
register int i;
|
||||
|
||||
i = 0;
|
||||
while ((c=getc(ffp))!=EOF && c!='\n') {
|
||||
if (i >= nbuf-1) {
|
||||
mlwrite("File has long line");
|
||||
#if GEM
|
||||
buf[i] = 0;
|
||||
ungetc(c, ffp);
|
||||
return (FIOSUC); /* Make long lines load */
|
||||
#endif
|
||||
return (FIOERR);
|
||||
}
|
||||
buf[i++] = c;
|
||||
}
|
||||
if (c == EOF) {
|
||||
if (ferror(ffp) != FALSE) {
|
||||
mlwrite("File read error");
|
||||
return (FIOERR);
|
||||
}
|
||||
if (i != 0) {
|
||||
mlwrite("File has funny line at EOF");
|
||||
#if GEM
|
||||
buf[i]=0; /* Make funny line show up. */
|
||||
return (FIOSUC);
|
||||
#else
|
||||
return (FIOERR);
|
||||
#endif
|
||||
}
|
||||
return (FIOEOF);
|
||||
}
|
||||
buf[i] = 0;
|
||||
return (FIOSUC);
|
||||
}
|
4
Mark Williams MWS v4/SAMPLE/HELLO.C
Normal file
4
Mark Williams MWS v4/SAMPLE/HELLO.C
Normal file
@ -0,0 +1,4 @@
|
||||
main()
|
||||
{
|
||||
printf("hello world\n");
|
||||
}
|
84
Mark Williams MWS v4/SAMPLE/IBMBIOS.M
Normal file
84
Mark Williams MWS v4/SAMPLE/IBMBIOS.M
Normal file
@ -0,0 +1,84 @@
|
||||
//////////
|
||||
/ ibmbios.m
|
||||
/ IBM PC ROM BIOS support for MicroEMACS.
|
||||
/ The routines in this file use IBM PC ROM BIOS interrupts 0x10 and 0x16
|
||||
/ to control the screen and keyboard;
|
||||
/ they will not work on some IBM-compatible (non-IBM) systems.
|
||||
/ They make no assumptions about screen type.
|
||||
//////////
|
||||
|
||||
#if IBM
|
||||
|
||||
#include <larges.h>
|
||||
|
||||
RBVIDEO = 0x10 / IBM PC ROM BIOS video driver interrupt
|
||||
RBKEYB = 0x16 / IBM PC ROM BIOS keyboard interrupt
|
||||
|
||||
NROW = 24 / Screen size.
|
||||
NCOL = 80 / Edit if you want to; also in ibmpc.c.
|
||||
|
||||
//////////
|
||||
/ int ibmrbkey(i) int i;
|
||||
/ ROM bios keyboard service interrupt.
|
||||
//////////
|
||||
|
||||
i = LEFTARG
|
||||
|
||||
Enter(ibmrbkey_)
|
||||
mov ax, i(bp) / Parameter to AX
|
||||
int RBKEYB / perform the interrupt
|
||||
Leave / and return
|
||||
|
||||
//////////
|
||||
/ ibmmove(row, col)
|
||||
/ Move the cursor to row, col.
|
||||
//////////
|
||||
|
||||
row = LEFTARG
|
||||
col = row + 2
|
||||
|
||||
Enter(ibmmove_)
|
||||
movb dh, row(bp) / row to DH
|
||||
movb dl, col(bp) / col to DL
|
||||
0:
|
||||
movb ah, $2 / set cursor to AH
|
||||
movb bh, $0 / current page to BH
|
||||
1:
|
||||
int RBVIDEO
|
||||
Leave
|
||||
|
||||
//////////
|
||||
/ ibmeol()
|
||||
/ Erase to end of line.
|
||||
//////////
|
||||
|
||||
Enter(ibmeeol_)
|
||||
movb ah, $3 / get cursor to AH
|
||||
movb bh, $0 / current page to BH
|
||||
int RBVIDEO
|
||||
|
||||
mov ax, $0x0600 / init window to AH, erase to AL
|
||||
movb bh, $7 / normal video to BH
|
||||
mov cx, dx / upper x = current x, upper y = current y
|
||||
movb dl, $NCOL-1 / lower x = end of line
|
||||
jmp 1b
|
||||
|
||||
//////////
|
||||
/ ibmeeop()
|
||||
/ Erase to end of page.
|
||||
/////////
|
||||
|
||||
Enter(ibmeeop_)
|
||||
mov ax, $0x0600 / init window to AH, erase to AL
|
||||
movb bh, $7 / normal video to BH
|
||||
sub cx, cx / upper left
|
||||
movb dh, $NROW / lower right
|
||||
movb dl, $NCOL-1
|
||||
int RBVIDEO
|
||||
|
||||
sub dx, dx / home
|
||||
jmp 0b / set cursor
|
||||
|
||||
#endif
|
||||
|
||||
/ end of ibmbios.m
|
52
Mark Williams MWS v4/SAMPLE/IBMPC.C
Normal file
52
Mark Williams MWS v4/SAMPLE/IBMPC.C
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* The routines referenced in this file
|
||||
* are defined in the assembly language source "ibmbios.m".
|
||||
* Because they use IBM PC ROM BIOS interrupt 0x10 to control the screen,
|
||||
* they will not work on some IBM-compatible (non-IBM) systems.
|
||||
* They make no assumptions about screen type.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
#if IBM
|
||||
|
||||
#define NROW 24 /* Screen size. */
|
||||
#define NCOL 80 /* Edit if you want to; also in ibmbios.m. */
|
||||
#define BEL 0x07 /* BEL character. */
|
||||
|
||||
extern int ttopen(); /* Forward references. */
|
||||
extern int ttgetc();
|
||||
extern int ttputc();
|
||||
extern int ttflush();
|
||||
extern int ttclose();
|
||||
extern int ibmmove();
|
||||
extern int ibmeeol();
|
||||
extern int ibmeeop();
|
||||
extern int ibmbeep();
|
||||
|
||||
/*
|
||||
* Standard terminal interface dispatch table.
|
||||
* Most of the fields point into "termio" code.
|
||||
*/
|
||||
TERM term = {
|
||||
NROW-1,
|
||||
NCOL,
|
||||
&ttopen,
|
||||
&ttclose,
|
||||
&ttgetc,
|
||||
&ttputc,
|
||||
&ttflush,
|
||||
&ibmmove,
|
||||
&ibmeeol,
|
||||
&ibmeeop,
|
||||
&ibmbeep
|
||||
};
|
||||
|
||||
/* Beep the terminal. */
|
||||
ibmbeep()
|
||||
{
|
||||
ttputc(BEL);
|
||||
ttflush();
|
||||
}
|
||||
|
||||
#endif
|
253
Mark Williams MWS v4/SAMPLE/INT.C
Normal file
253
Mark Williams MWS v4/SAMPLE/INT.C
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Let's C Version 4.0.C.
|
||||
* Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
* All rights reserved. May not be copied or disclosed without permission.
|
||||
*/
|
||||
|
||||
/*
|
||||
* int.c
|
||||
* Let's C interface routines for MS-DOS hardware interrupt handling.
|
||||
* These work in either LARGE or SMALL model.
|
||||
* See also: intdis.m, example.c.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <dos.h>
|
||||
|
||||
#define SIZE(x) (sizeof(x)/sizeof(x[0])) /* Size in elements */
|
||||
#define END(x) (&x[SIZE(x)]) /* Address of end */
|
||||
|
||||
/*
|
||||
* The interrupts are set to jump to these assembly entry points first.
|
||||
*/
|
||||
extern intdis1();
|
||||
extern intdis2();
|
||||
extern intdis3();
|
||||
extern intdis4();
|
||||
extern intdis5();
|
||||
extern intdis6();
|
||||
extern intdis7();
|
||||
extern intdis8();
|
||||
extern intdis9();
|
||||
extern intdis10();
|
||||
extern intdis11();
|
||||
extern intdis12();
|
||||
extern intdis13();
|
||||
extern intdis14();
|
||||
extern intdis15();
|
||||
extern intdis16();
|
||||
|
||||
/*
|
||||
* Interrupt information.
|
||||
* Knowledge of this structure is hardcoded in intdis.m.
|
||||
*/
|
||||
struct INTINFO {
|
||||
int (*i_cfunc)(); /* C function to be called */
|
||||
int i_stacksize; /* Stack needed by C func */
|
||||
void (*i_intdis)(); /* Assembly dispatch routine */
|
||||
int i_intnum; /* 8086 int number (-1 if free) */
|
||||
unsigned i_oldoff; /* Old vector offset */
|
||||
unsigned i_oldseg; /* Old vector segment */
|
||||
char *i_stack; /* Pointer to start of stack */
|
||||
char *i_curstack; /* Current sp (grows down) */
|
||||
char *i_endstack; /* Pointer to end of stack */
|
||||
} intinfo[] = {
|
||||
{ NULL, 0, &intdis1, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis2, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis3, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis4, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis5, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis6, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis7, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis8, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis9, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis10, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis11, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis12, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis13, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis14, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis15, -1, 0, 0, NULL, NULL, NULL },
|
||||
{ NULL, 0, &intdis16, -1, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static char iovermsg[] = "Interrupt nesting capacity exceeded\r\n";
|
||||
|
||||
/*
|
||||
* Link a C function with an 8086 interrupt.
|
||||
* Up to 16 C functions can be linked to interrupts at once.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* intnum -- 8086 interrupt number.
|
||||
* func -- C function pointer for interrupt service routine.
|
||||
* stacksize -- Amount of stack (in bytes) that C function needs.
|
||||
* level -- Maximum number of levels that interrupt will be nested.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* The C function should return 1 if it wants the old interrupt
|
||||
* service routine to be called too. Otherwise, it should return 0.
|
||||
* This is useful for trapping an interrupt but not affecting its
|
||||
* old functionality.
|
||||
* This function returns a number from 0 to 15 on success. This
|
||||
* unique interrupt identifier is passed to clearint when
|
||||
* you want to dereference the C routine from the interrupt.
|
||||
* Returns -1 on failure (Bad intnum, all available ints in use, bad
|
||||
* level value, not enough memory for stack).
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* (1) If the interrupt service routine returns 0 and the interrupt
|
||||
* is a real hardware interrupt (e.g., interrupts 0x8 to 0xF on the
|
||||
* IBM-PC), the C service routine must output an EOI to the
|
||||
* interrupt controller.
|
||||
*
|
||||
* (2) All C service routines are called with interrupts disabled. You
|
||||
* may call cli() or sti() to clear or set the interrupt enable bit
|
||||
* respectively.
|
||||
*
|
||||
* (3) Most library functions cannot be called by an interrupt service
|
||||
* routine.
|
||||
*
|
||||
* (4) The use of floating point arithmetic within
|
||||
* an interrupt service routine is not recommended.
|
||||
*
|
||||
* (5) Caution should be exercised when interrupt routine(s)
|
||||
* and the main program access the same writeable data structures.
|
||||
*
|
||||
* (6) Interrupts can be linked. That is, setint may be called
|
||||
* several times with the same interrupt number. When that
|
||||
* interrupt occurs, if all C service routines for that interrupt
|
||||
* return 1, all such routines will be executed. When you link
|
||||
* interrupts, it is vital that setint/clearint calls are not crossed.
|
||||
* That is, between a setint and its corresponding clearint, no other
|
||||
* setints on that interrupt should have been performed which
|
||||
* weren't cleared.
|
||||
*
|
||||
* (7) No stack checking is performed. If stacksize is too small, the
|
||||
* system will crash. If level is too small (the interrupt
|
||||
* nests more than level levels), the system will print
|
||||
* an error message and hang with interrupts disabled.
|
||||
* The stack size (in bytes) needed by one function is equal to
|
||||
* 6 + sizeof parameters + sizeof automatics.
|
||||
* Allow at least 256 bytes excess stack for a safety margin.
|
||||
*
|
||||
* (8) It's OK to use this system after calling MS-DOS function 0x31
|
||||
* (terminate and remain resident). The routine termres, provided
|
||||
* here, does this.
|
||||
*/
|
||||
setint(intnum, func, stacksize, level)
|
||||
register int intnum;
|
||||
int (*func)();
|
||||
unsigned stacksize;
|
||||
int level;
|
||||
{
|
||||
register struct INTINFO *ip;
|
||||
register int i = 0;
|
||||
register unsigned totalstack = stacksize * level;
|
||||
struct reg r;
|
||||
char *malloc();
|
||||
|
||||
if (intnum < 0 || intnum >= 256 || level < 0)
|
||||
return(-1);
|
||||
|
||||
for (ip = intinfo; ip < END(intinfo); ++ip, ++i)
|
||||
if (ip->i_intnum == -1) { /* Free spot? */
|
||||
if ((ip->i_stack = malloc(totalstack)) == NULL)
|
||||
return(-1);
|
||||
r.r_ax = GETVEC | intnum;
|
||||
intcall(&r, &r, DOSINT); /* Get old vector */
|
||||
ip->i_oldseg = r.r_es; /* Save it */
|
||||
ip->i_oldoff = r.r_bx;
|
||||
ip->i_intnum = intnum;
|
||||
ip->i_cfunc = func;
|
||||
ip->i_stacksize = stacksize;
|
||||
ip->i_curstack = ip->i_endstack = ip->i_stack +
|
||||
totalstack;
|
||||
ptoreg(csreg, r.r_dx, r.r_ds, ip->i_intdis);
|
||||
r.r_ax = SETINT | intnum;
|
||||
intcall(&r, &r, DOSINT); /* Set new int */
|
||||
return(i);
|
||||
}
|
||||
return(-1); /* Table full */
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear an interrupt previously set by setint.
|
||||
* id -- unique identifier which setint returned.
|
||||
* Returns 0 on success.
|
||||
* Returns -1 on failure (id out of range, interrupt never set).
|
||||
*/
|
||||
clearint(id)
|
||||
register int id;
|
||||
{
|
||||
if (id < 0 || id >= SIZE(intinfo))
|
||||
return(-1);
|
||||
return(_clearint(&intinfo[id]));
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all interrupts.
|
||||
* You should not call this routine if you have linked several
|
||||
* interrupt service routines to the same interrupt with setint.
|
||||
*/
|
||||
doneint()
|
||||
{
|
||||
register struct INTINFO *ip;
|
||||
|
||||
for (ip = intinfo; ip < END(intinfo); ++ip)
|
||||
_clearint(ip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal routine to restore an interrupt to its old value.
|
||||
* Returns 0 if OK, -1 if interrupt is clear.
|
||||
*/
|
||||
static
|
||||
_clearint(ip)
|
||||
register struct INTINFO *ip;
|
||||
{
|
||||
struct reg r;
|
||||
|
||||
if (ip->i_intnum != -1) {
|
||||
r.r_ax = SETINT | ip->i_intnum;
|
||||
r.r_ds = ip->i_oldseg;
|
||||
r.r_dx = ip->i_oldoff;
|
||||
intcall(&r, &r, DOSINT);
|
||||
ip->i_intnum = -1;
|
||||
free(ip->i_stack);
|
||||
return(0);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal routine called by the assembly interrupt linkage
|
||||
* on interrupt nesting overflow. Called in interrupt context.
|
||||
* At this point, system may be foobared.
|
||||
*/
|
||||
isover()
|
||||
{
|
||||
write(1, iovermsg, sizeof(iovermsg) - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate process and remain resident.
|
||||
* This routine exits, but allocates all program and data memory
|
||||
* before doing so. You must call this routine if you want
|
||||
* to handle interrupts after normal program exit.
|
||||
* Basically figure out the total number of paragraphs that program,
|
||||
* data, stack, and malloc arena occupy and pass it to the MS-DOS
|
||||
* TERMRES function.
|
||||
* status -- Byte exit code.
|
||||
*/
|
||||
termres(status)
|
||||
int status;
|
||||
{
|
||||
struct reg r;
|
||||
extern int _pspbase;
|
||||
extern char *__end;
|
||||
|
||||
r.r_ax = TERMRES | (status & 0xFF);
|
||||
r.r_dx = dsreg() + ((int)__end >> 4) + 1 - _pspbase;
|
||||
intcall(&r, &r, DOSINT);
|
||||
}
|
208
Mark Williams MWS v4/SAMPLE/INTDIS.M
Normal file
208
Mark Williams MWS v4/SAMPLE/INTDIS.M
Normal file
@ -0,0 +1,208 @@
|
||||
/
|
||||
/ Lets C Version 4.0.C.
|
||||
/ Copyright (c) 1982-1987 by Mark Williams Company, Chicago.
|
||||
/ All rights reserved. May not be copied or disclosed without permission.
|
||||
/
|
||||
|
||||
/*
|
||||
* intdis.m
|
||||
* Assembly language interrupt dispatcher.
|
||||
* Works in either LARGE or SMALL model.
|
||||
* See also: int.c, example.c.
|
||||
*/
|
||||
|
||||
#if LARGE
|
||||
#define LARGECODE 1
|
||||
#define LARGEDATA 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following byte size parameters are used to determine the
|
||||
* actual offsets for the members of the structure INTINFO, which
|
||||
* is defined in int.c, independent of the data model LARGE or SMALL.
|
||||
*/
|
||||
#define INTSIZE 2
|
||||
|
||||
#if LARGEDATA
|
||||
#define PTRSIZE 4
|
||||
#else
|
||||
#define PTRSIZE 2
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following are used to get the correct 8086 mnemonics, independent
|
||||
* of the execution model LARGE or SMALL.
|
||||
*/
|
||||
#if LARGECODE
|
||||
#define Gicall xicall
|
||||
#define Gret xret
|
||||
#else
|
||||
#define Gicall icall
|
||||
#define Gret ret
|
||||
#endif
|
||||
|
||||
|
||||
.shri
|
||||
|
||||
.globl intdis1_ / Interrupt entry points
|
||||
.globl intdis2_
|
||||
.globl intdis3_
|
||||
.globl intdis4_
|
||||
.globl intdis5_
|
||||
.globl intdis6_
|
||||
.globl intdis7_
|
||||
.globl intdis8_
|
||||
.globl intdis9_
|
||||
.globl intdis10_
|
||||
.globl intdis11_
|
||||
.globl intdis12_
|
||||
.globl intdis13_
|
||||
.globl intdis14_
|
||||
.globl intdis15_
|
||||
.globl intdis16_
|
||||
|
||||
iisize = 5*PTRSIZE + 4*INTSIZE / sizeof(struct INTINFO)
|
||||
i_cfunc = 0 / Member offsets in intinfo
|
||||
i_stacksize = PTRSIZE
|
||||
i_oldoff = 2*PTRSIZE + 2*INTSIZE
|
||||
i_stack = 2*PTRSIZE + 4*INTSIZE
|
||||
i_curstack = 3*PTRSIZE + 4*INTSIZE
|
||||
i_endstack = 4*PTRSIZE + 4*INTSIZE
|
||||
|
||||
.globl intinfo_ / External references
|
||||
.globl isover_
|
||||
|
||||
.globl cli_ / External definitions
|
||||
.globl sti_
|
||||
|
||||
cli_:
|
||||
cli
|
||||
Gret
|
||||
sti_:
|
||||
sti
|
||||
Gret
|
||||
|
||||
intdis1_: / Entry points
|
||||
push bx
|
||||
mov bx, $0 * iisize
|
||||
jmp dispatch
|
||||
intdis2_:
|
||||
push bx
|
||||
mov bx, $1 * iisize
|
||||
jmp dispatch
|
||||
intdis3_:
|
||||
push bx
|
||||
mov bx, $2 * iisize
|
||||
jmp dispatch
|
||||
intdis4_:
|
||||
push bx
|
||||
mov bx, $3 * iisize
|
||||
jmp dispatch
|
||||
intdis5_:
|
||||
push bx
|
||||
mov bx, $4 * iisize
|
||||
jmp dispatch
|
||||
intdis6_:
|
||||
push bx
|
||||
mov bx, $5 * iisize
|
||||
jmp dispatch
|
||||
intdis7_:
|
||||
push bx
|
||||
mov bx, $6 * iisize
|
||||
jmp dispatch
|
||||
intdis8_:
|
||||
push bx
|
||||
mov bx, $7 * iisize
|
||||
jmp dispatch
|
||||
intdis9_:
|
||||
push bx
|
||||
mov bx, $8 * iisize
|
||||
jmp dispatch
|
||||
intdis10_:
|
||||
push bx
|
||||
mov bx, $9 * iisize
|
||||
jmp dispatch
|
||||
intdis11_:
|
||||
push bx
|
||||
mov bx, $10 * iisize
|
||||
jmp dispatch
|
||||
intdis12_:
|
||||
push bx
|
||||
mov bx, $11 * iisize
|
||||
jmp dispatch
|
||||
intdis13_:
|
||||
push bx
|
||||
mov bx, $12 * iisize
|
||||
jmp dispatch
|
||||
intdis14_:
|
||||
push bx
|
||||
mov bx, $13 * iisize
|
||||
jmp dispatch
|
||||
intdis15_:
|
||||
push bx
|
||||
mov bx, $14 * iisize
|
||||
jmp dispatch
|
||||
intdis16_:
|
||||
push bx
|
||||
mov bx, $15 * iisize
|
||||
dispatch:
|
||||
push ax / Save machine state
|
||||
push cx
|
||||
push dx
|
||||
push ds
|
||||
push es
|
||||
mov cx, ss
|
||||
mov dx, sp
|
||||
mov ax, $@intinfo_ / Segment of intinfo[]
|
||||
mov ds, ax / for data references
|
||||
mov es, ax
|
||||
|
||||
/*
|
||||
* The following is used to load the SS and SP registers to the
|
||||
* correct value for the interrupt processing routine. With
|
||||
* LARGEDATA model, we must get SS from the intinfo[]; otherwise,
|
||||
* simply set it the same as DS and ES.
|
||||
*/
|
||||
#if LARGEDATA
|
||||
mov ss, intinfo_+INTSIZE+i_curstack(bx)
|
||||
#else
|
||||
mov ss, ax
|
||||
#endif
|
||||
mov sp, intinfo_+i_curstack(bx)
|
||||
|
||||
mov ax, sp
|
||||
cmp ax, intinfo_+i_stack(bx) / Nesting overflow check
|
||||
je overflow
|
||||
sub ax, intinfo_+i_stacksize(bx) / Make room on stack
|
||||
mov intinfo_+i_curstack(bx), ax
|
||||
push dx
|
||||
push cx
|
||||
push bx
|
||||
Gicall intinfo_+i_cfunc(bx) / Call C routine
|
||||
pop bx / Pop intinfo offset
|
||||
pop cx / Pop old ss, sp
|
||||
pop dx
|
||||
test ax, ax / Call old interrupt?
|
||||
jz done / No
|
||||
pushf / Simulate int to old function
|
||||
mov ax, $@intinfo_ / Segment of intinfo[]
|
||||
mov ds, ax / for data reference
|
||||
xicall intinfo_+i_oldoff(bx) / Indirect intersegment call
|
||||
done:
|
||||
mov ax, $@intinfo_ / Segment of intinfo[]
|
||||
mov ds, ax / for data reference
|
||||
mov intinfo_+i_curstack(bx), sp / Deallocate stack
|
||||
mov ss, cx / Restore machine state
|
||||
mov sp, dx
|
||||
pop es
|
||||
pop ds
|
||||
pop dx
|
||||
pop cx
|
||||
pop ax
|
||||
pop bx
|
||||
iret
|
||||
overflow:
|
||||
mov sp, intinfo_+i_endstack(bx)
|
||||
call isover_ / Nesting overflow
|
||||
death:
|
||||
jmp death
|
467
Mark Williams MWS v4/SAMPLE/LINE.C
Normal file
467
Mark Williams MWS v4/SAMPLE/LINE.C
Normal file
@ -0,0 +1,467 @@
|
||||
/*
|
||||
* The functions in this file are a general set of line management utilities.
|
||||
* They are the only routines that touch the text. They also touch the buffer
|
||||
* and window structures, to make sure that the necessary updating gets done.
|
||||
* There are routines in this file that handle the kill buffer too.
|
||||
* It isn't here for any good reason.
|
||||
*
|
||||
* Note that this code only updates the dot and mark values in the window list.
|
||||
* Since all the code acts on the current window, the buffer that we are
|
||||
* editing must be being displayed, which means that "b_nwnd" is non zero,
|
||||
* which means that the dot and mark values in the buffer headers are nonsense.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
#define NBLOCK 16 /* Line block chunk size */
|
||||
#define KBLOCK 256 /* Kill buffer block size */
|
||||
|
||||
char *kbufp = NULL; /* Kill buffer data */
|
||||
int kused = 0; /* # of bytes used in KB */
|
||||
int ksize = 0; /* # of bytes allocated in KB */
|
||||
|
||||
/*
|
||||
* This routine allocates a block of memory large enough to hold a LINE
|
||||
* containing "used" characters. The block is always rounded up a bit.
|
||||
* Return a pointer to the new block, or NULL if there isn't any memory left.
|
||||
* Print a message in the message line if no space.
|
||||
*/
|
||||
LINE *
|
||||
lalloc(used)
|
||||
register int used;
|
||||
{
|
||||
register LINE *lp;
|
||||
register int size;
|
||||
|
||||
size = (used+NBLOCK-1) & ~(NBLOCK-1);
|
||||
if (size == 0) /* Assume that an empty */
|
||||
size = NBLOCK; /* line is for type-in. */
|
||||
if ((lp = (LINE *) malloc(sizeof(LINE)+size)) == NULL) {
|
||||
mlwrite("Cannot allocate %d bytes", size);
|
||||
return (NULL);
|
||||
}
|
||||
lp->l_size = size;
|
||||
lp->l_used = used;
|
||||
lp->l_lnumber = 0; /* This is a new line... */
|
||||
return (lp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete line "lp". Fix all of the links that might point at it (they are
|
||||
* moved to offset 0 of the next line. Unlink the line from whatever buffer it
|
||||
* might be in. Release the memory. The buffers are updated too; the magic
|
||||
* conditions described in the above comments don't hold here.
|
||||
*/
|
||||
lfree(lp)
|
||||
register LINE *lp;
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register WINDOW *wp;
|
||||
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep == lp)
|
||||
wp->w_linep = lp->l_fp;
|
||||
if (wp->w_dotp == lp) {
|
||||
wp->w_dotp = lp->l_fp;
|
||||
wp->w_doto = 0;
|
||||
}
|
||||
if (wp->w_markp == lp) {
|
||||
wp->w_markp = lp->l_fp;
|
||||
wp->w_marko = 0;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
bp = bheadp;
|
||||
while (bp != NULL) {
|
||||
if (bp->b_nwnd == 0) {
|
||||
if (bp->b_dotp == lp) {
|
||||
bp->b_dotp = lp->l_fp;
|
||||
bp->b_doto = 0;
|
||||
}
|
||||
if (bp->b_markp == lp) {
|
||||
bp->b_markp = lp->l_fp;
|
||||
bp->b_marko = 0;
|
||||
}
|
||||
}
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
lp->l_bp->l_fp = lp->l_fp;
|
||||
lp->l_fp->l_bp = lp->l_bp;
|
||||
free((char *) lp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine gets called when a character is changed in place in the
|
||||
* current buffer. It updates all of the required flags in the buffer and
|
||||
* window system. The flag used is passed as an argument; if the buffer is
|
||||
* being displayed in more than 1 window we change EDIT to HARD.
|
||||
* Set MODE if the mode line needs to be updated (the "*" has to be set).
|
||||
*/
|
||||
lchange(flag)
|
||||
register int flag;
|
||||
{
|
||||
register WINDOW *wp;
|
||||
|
||||
if (curbp->b_nwnd != 1) /* Ensure hard. */
|
||||
flag = WFHARD;
|
||||
if ((curbp->b_flag&BFCHG) == 0) { /* First change, so */
|
||||
flag |= WFMODE; /* update mode lines. */
|
||||
curbp->b_flag |= BFCHG;
|
||||
}
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= flag;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert "n" copies of the character "c" at the current location of dot.
|
||||
* In the easy case all that happens is the text is stored in the line.
|
||||
* In the hard case, the line has to be reallocated.
|
||||
* When the window list is updated, take special care; I screwed it up once.
|
||||
* You always update dot in the current window. You update mark, and a
|
||||
* dot in another window, if it is greater than the place where you did
|
||||
* the insert.
|
||||
* Return TRUE if all is well, and FALSE on errors.
|
||||
*/
|
||||
linsert(n, c)
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register LINE *lp3;
|
||||
register int doto;
|
||||
register int i;
|
||||
register WINDOW *wp;
|
||||
|
||||
lchange(WFEDIT);
|
||||
lp1 = curwp->w_dotp; /* Current line */
|
||||
if (lp1 == curbp->b_linep) { /* At the end: special */
|
||||
if (curwp->w_doto != 0) {
|
||||
mlwrite("bug: linsert");
|
||||
return (FALSE);
|
||||
}
|
||||
if ((lp2=lalloc(n)) == NULL) /* Allocate new line */
|
||||
return (FALSE);
|
||||
lp3 = lp1->l_bp; /* Previous line */
|
||||
lp3->l_fp = lp2; /* Link in */
|
||||
lp2->l_fp = lp1;
|
||||
lp1->l_bp = lp2;
|
||||
lp2->l_bp = lp3;
|
||||
for (i=0; i<n; ++i)
|
||||
lp2->l_text[i] = c;
|
||||
curwp->w_dotp = lp2;
|
||||
curwp->w_doto = n;
|
||||
return (TRUE);
|
||||
}
|
||||
doto = curwp->w_doto; /* Save for later. */
|
||||
if (lp1->l_used+n > lp1->l_size) { /* Hard: reallocate */
|
||||
if ((lp2=lalloc(lp1->l_used+n)) == NULL)
|
||||
return (FALSE);
|
||||
cp1 = &lp1->l_text[0];
|
||||
cp2 = &lp2->l_text[0];
|
||||
while (cp1 != &lp1->l_text[doto])
|
||||
*cp2++ = *cp1++;
|
||||
cp2 += n;
|
||||
while (cp1 != &lp1->l_text[lp1->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
lp1->l_bp->l_fp = lp2;
|
||||
lp2->l_fp = lp1->l_fp;
|
||||
lp1->l_fp->l_bp = lp2;
|
||||
lp2->l_bp = lp1->l_bp;
|
||||
free((char *) lp1);
|
||||
} else { /* Easy: in place */
|
||||
lp2 = lp1; /* Pretend new line */
|
||||
lp2->l_used += n;
|
||||
cp2 = &lp1->l_text[lp1->l_used];
|
||||
cp1 = cp2-n;
|
||||
while (cp1 != &lp1->l_text[doto])
|
||||
*--cp2 = *--cp1;
|
||||
}
|
||||
for (i=0; i<n; ++i) /* Add the characters */
|
||||
lp2->l_text[doto+i] = c;
|
||||
wp = wheadp; /* Update windows */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep == lp1)
|
||||
wp->w_linep = lp2;
|
||||
if (wp->w_dotp == lp1) {
|
||||
wp->w_dotp = lp2;
|
||||
if (wp==curwp || wp->w_doto>doto)
|
||||
wp->w_doto += n;
|
||||
}
|
||||
if (wp->w_markp == lp1) {
|
||||
wp->w_markp = lp2;
|
||||
if (wp->w_marko > doto)
|
||||
wp->w_marko += n;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a newline into the buffer at the current location of dot in the
|
||||
* current window. The funny ass-backwards way it does things is not a botch;
|
||||
* it just makes the last line in the file not a special case. Return TRUE if
|
||||
* everything works out and FALSE on error (memory allocation failure).
|
||||
* The update of dot and mark is a bit easier then in the above case, because
|
||||
* the split forces more updating.
|
||||
*/
|
||||
lnewline()
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register int doto;
|
||||
register WINDOW *wp;
|
||||
|
||||
lchange(WFHARD);
|
||||
lp1 = curwp->w_dotp; /* Get the address and */
|
||||
doto = curwp->w_doto; /* offset of "." */
|
||||
if ((lp2=lalloc(doto)) == NULL) /* New first half line */
|
||||
return (FALSE);
|
||||
cp1 = &lp1->l_text[0]; /* Shuffle text around */
|
||||
cp2 = &lp2->l_text[0];
|
||||
while (cp1 != &lp1->l_text[doto])
|
||||
*cp2++ = *cp1++;
|
||||
cp2 = &lp1->l_text[0];
|
||||
while (cp1 != &lp1->l_text[lp1->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
lp1->l_used -= doto;
|
||||
lp2->l_bp = lp1->l_bp;
|
||||
lp1->l_bp = lp2;
|
||||
lp2->l_bp->l_fp = lp2;
|
||||
lp2->l_fp = lp1;
|
||||
wp = wheadp; /* Windows */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep == lp1)
|
||||
wp->w_linep = lp2;
|
||||
if (wp->w_dotp == lp1) {
|
||||
if (wp->w_doto < doto)
|
||||
wp->w_dotp = lp2;
|
||||
else
|
||||
wp->w_doto -= doto;
|
||||
}
|
||||
if (wp->w_markp == lp1) {
|
||||
if (wp->w_marko < doto)
|
||||
wp->w_markp = lp2;
|
||||
else
|
||||
wp->w_marko -= doto;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function deletes "n" bytes, starting at dot. It understands how to deal
|
||||
* with end of lines, etc. It returns TRUE if all of the characters were
|
||||
* deleted, and FALSE if they were not (because dot ran into the end of
|
||||
* the buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
|
||||
*/
|
||||
ldelete(n, kflag)
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register LINE *dotp;
|
||||
register int doto;
|
||||
register int chunk;
|
||||
register WINDOW *wp;
|
||||
|
||||
while (n != 0) {
|
||||
dotp = curwp->w_dotp;
|
||||
doto = curwp->w_doto;
|
||||
if (dotp == curbp->b_linep) /* Hit end of buffer. */
|
||||
return (FALSE);
|
||||
chunk = dotp->l_used-doto; /* Size of chunk. */
|
||||
if (chunk > n)
|
||||
chunk = n;
|
||||
if (chunk == 0) { /* End of line, merge. */
|
||||
lchange(WFHARD);
|
||||
if (ldelnewline() == FALSE
|
||||
|| (kflag!=FALSE && kinsert('\n')==FALSE))
|
||||
return (FALSE);
|
||||
--n;
|
||||
continue;
|
||||
}
|
||||
lchange(WFEDIT);
|
||||
cp1 = &dotp->l_text[doto]; /* Scrunch text. */
|
||||
cp2 = cp1 + chunk;
|
||||
if (kflag != FALSE) { /* Kill? */
|
||||
while (cp1 != cp2) {
|
||||
if (kinsert(*cp1) == FALSE)
|
||||
return (FALSE);
|
||||
++cp1;
|
||||
}
|
||||
cp1 = &dotp->l_text[doto];
|
||||
}
|
||||
while (cp2 != &dotp->l_text[dotp->l_used])
|
||||
*cp1++ = *cp2++;
|
||||
dotp->l_used -= chunk;
|
||||
wp = wheadp; /* Fix windows */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_dotp==dotp && wp->w_doto>=doto) {
|
||||
wp->w_doto -= chunk;
|
||||
if (wp->w_doto < doto)
|
||||
wp->w_doto = doto;
|
||||
}
|
||||
if (wp->w_markp==dotp && wp->w_marko>=doto) {
|
||||
wp->w_marko -= chunk;
|
||||
if (wp->w_marko < doto)
|
||||
wp->w_marko = doto;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
n -= chunk;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a newline. Join the current line with the next line. If the next
|
||||
* line is the magic header line always return TRUE; merging the last line
|
||||
* with the header line can be thought of as always being a successful
|
||||
* operation, even if nothing is done, and this makes the kill buffer
|
||||
* work "right". Easy cases can be done by shuffling data around.
|
||||
* Hard cases require that lines be moved about in memory.
|
||||
* Return FALSE on error and TRUE if all looks ok. Called by "ldelete" only.
|
||||
*/
|
||||
ldelnewline()
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register LINE *lp3;
|
||||
register WINDOW *wp;
|
||||
|
||||
lp1 = curwp->w_dotp; /* This line... */
|
||||
lp2 = lp1->l_fp; /* The next line... */
|
||||
|
||||
if (lp2 == curbp->b_linep) { /* At the buffer end. */
|
||||
if (lp1->l_used == 0) /* Blank line. */
|
||||
lfree(lp1);
|
||||
return (TRUE);
|
||||
}
|
||||
/* Fix file-line numbers. */
|
||||
if ((lp1->l_used == 0) || (lp1->l_lnumber == 0))
|
||||
lp1->l_lnumber = lp2->l_lnumber;
|
||||
|
||||
if (lp2->l_used <= lp1->l_size-lp1->l_used) {
|
||||
cp1 = &lp1->l_text[lp1->l_used];
|
||||
cp2 = &lp2->l_text[0];
|
||||
while (cp2 != &lp2->l_text[lp2->l_used])
|
||||
*cp1++ = *cp2++;
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep == lp2)
|
||||
wp->w_linep = lp1;
|
||||
if (wp->w_dotp == lp2) {
|
||||
wp->w_dotp = lp1;
|
||||
wp->w_doto += lp1->l_used;
|
||||
}
|
||||
if (wp->w_markp == lp2) {
|
||||
wp->w_markp = lp1;
|
||||
wp->w_marko += lp1->l_used;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
lp1->l_used += lp2->l_used;
|
||||
lp1->l_fp = lp2->l_fp;
|
||||
lp2->l_fp->l_bp = lp1;
|
||||
free((char *) lp2);
|
||||
return (TRUE);
|
||||
}
|
||||
if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL)
|
||||
return (FALSE);
|
||||
cp1 = &lp1->l_text[0];
|
||||
cp2 = &lp3->l_text[0];
|
||||
while (cp1 != &lp1->l_text[lp1->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
cp1 = &lp2->l_text[0];
|
||||
while (cp1 != &lp2->l_text[lp2->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
lp1->l_bp->l_fp = lp3;
|
||||
lp3->l_fp = lp2->l_fp;
|
||||
lp2->l_fp->l_bp = lp3;
|
||||
lp3->l_bp = lp1->l_bp;
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep==lp1 || wp->w_linep==lp2)
|
||||
wp->w_linep = lp3;
|
||||
if (wp->w_dotp == lp1)
|
||||
wp->w_dotp = lp3;
|
||||
else if (wp->w_dotp == lp2) {
|
||||
wp->w_dotp = lp3;
|
||||
wp->w_doto += lp1->l_used;
|
||||
}
|
||||
if (wp->w_markp == lp1)
|
||||
wp->w_markp = lp3;
|
||||
else if (wp->w_markp == lp2) {
|
||||
wp->w_markp = lp3;
|
||||
wp->w_marko += lp1->l_used;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
free((char *) lp1);
|
||||
free((char *) lp2);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all of the text saved in the kill buffer. Called by commands when
|
||||
* a new kill context is being created. The kill buffer array is released,
|
||||
* just in case the buffer has grown to immense size. No errors.
|
||||
*/
|
||||
kdelete()
|
||||
{
|
||||
if (kbufp != NULL) {
|
||||
free((char *) kbufp);
|
||||
kbufp = NULL;
|
||||
kused = 0;
|
||||
ksize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a character to the kill buffer, enlarging the buffer if there
|
||||
* isn't any room. Always grow the buffer in chunks, on the assumption
|
||||
* that if you put something in the kill buffer you are going to put more
|
||||
* stuff there too later. Return TRUE if all is well, and FALSE on errors.
|
||||
*/
|
||||
kinsert(c)
|
||||
{
|
||||
register char *nbufp;
|
||||
register int i;
|
||||
|
||||
if (kused == ksize) {
|
||||
if ((nbufp=malloc(ksize+KBLOCK)) == NULL)
|
||||
return (FALSE);
|
||||
for (i=0; i<ksize; ++i)
|
||||
nbufp[i] = kbufp[i];
|
||||
if (kbufp != NULL)
|
||||
free((char *) kbufp);
|
||||
kbufp = nbufp;
|
||||
ksize += KBLOCK;
|
||||
}
|
||||
kbufp[kused++] = c;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function gets characters from the kill buffer. If the character index
|
||||
* "n" is off the end, it returns "-1". This lets the caller just scan along
|
||||
* until it gets a "-1" back.
|
||||
*/
|
||||
kremove(n)
|
||||
{
|
||||
if (n >= kused)
|
||||
return (-1);
|
||||
else
|
||||
return (kbufp[n] & 0xFF);
|
||||
}
|
863
Mark Williams MWS v4/SAMPLE/MAIN.C
Normal file
863
Mark Williams MWS v4/SAMPLE/MAIN.C
Normal file
@ -0,0 +1,863 @@
|
||||
/*
|
||||
* This program is in public domain; written by Dave G. Conroy.
|
||||
* This file contains the main driving routine, and some keyboard processing
|
||||
* code, for the MicroEMACS screen editor.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
#if VMS
|
||||
#include <ssdef.h>
|
||||
#define GOOD (SS$_NORMAL)
|
||||
#define BAD (SS$_ABORT)
|
||||
#endif
|
||||
|
||||
#ifndef GOOD
|
||||
#define GOOD 0
|
||||
#define BAD 1
|
||||
#endif
|
||||
|
||||
#define ERRLINES 3 /* Number of lines to display */
|
||||
|
||||
int currow; /* Working cursor row */
|
||||
int curcol; /* Working cursor column */
|
||||
int fillcol; /* Current fill column */
|
||||
int thisflag; /* Flags, this command */
|
||||
int lastflag; /* Flags, last command */
|
||||
int curgoal; /* Goal column */
|
||||
int ffold; /* Fold Flag */
|
||||
BUFFER *curbp; /* Current buffer */
|
||||
WINDOW *curwp; /* Current window */
|
||||
BUFFER *bheadp; /* BUFFER listhead */
|
||||
WINDOW *wheadp; /* WINDOW listhead */
|
||||
BUFFER *blistp; /* Buffer list BUFFER */
|
||||
BUFFER *errbp; /* Error file BUFFER */
|
||||
short kbdm[NKBDM] = CTLX|')'; /* Macro */
|
||||
short *kbdmip; /* Input for above */
|
||||
short *kbdmop; /* Output for above */
|
||||
char pat[NPAT]; /* Pattern */
|
||||
char errfile[NFILEN]; /* Error file name */
|
||||
|
||||
typedef struct {
|
||||
short k_code; /* Key code */
|
||||
int (*k_fp)(); /* Routine to handle it */
|
||||
} KEYTAB;
|
||||
|
||||
extern int ctrlg(); /* Abort out of things */
|
||||
extern int quit(); /* Quit */
|
||||
extern int ctlxlp(); /* Begin macro */
|
||||
extern int ctlxrp(); /* End macro */
|
||||
extern int ctlxe(); /* Execute macro */
|
||||
extern int fileread(); /* Get a file, read only */
|
||||
extern int filevisit(); /* Get a file, read write */
|
||||
extern int filewrite(); /* Write a file */
|
||||
extern int filesave(); /* Save current file */
|
||||
extern int filename(); /* Adjust file name */
|
||||
extern int getccol(); /* Get current column */
|
||||
extern int gotobol(); /* Move to start of line */
|
||||
extern int forwchar(); /* Move forward by characters */
|
||||
extern int gotoeol(); /* Move to end of line */
|
||||
extern int backchar(); /* Move backward by characters */
|
||||
extern int forwline(); /* Move forward by lines */
|
||||
extern int backline(); /* Move backward by lines */
|
||||
extern int forwpage(); /* Move forward by pages */
|
||||
extern int backpage(); /* Move backward by pages */
|
||||
extern int gotobob(); /* Move to start of buffer */
|
||||
extern int gotoeob(); /* Move to end of buffer */
|
||||
extern int setfillcol(); /* Set fill column. */
|
||||
extern int setmark(); /* Set mark */
|
||||
extern int swapmark(); /* Swap "." and mark */
|
||||
extern int forwsearch(); /* Search forward */
|
||||
extern int forwisearch(); /* forward incremental search */
|
||||
extern int backisearch(); /* backward incremental search */
|
||||
extern int queryrepl(); /* query/replace */
|
||||
extern int searchagain(); /* find next occurrance */
|
||||
extern int backsearch(); /* Search backwards */
|
||||
extern int showcpos(); /* Show the cursor position */
|
||||
extern int nextwind(); /* Move to the next window */
|
||||
extern int prevwind(); /* Move to the previous window */
|
||||
extern int onlywind(); /* Make current window only one */
|
||||
extern int splitwind(); /* Split current window */
|
||||
extern int mvdnwind(); /* Move window down */
|
||||
extern int mvupwind(); /* Move window up */
|
||||
extern int enlargewind(); /* Enlarge display window. */
|
||||
extern int shrinkwind(); /* Shrink window. */
|
||||
extern int listbuffers(); /* Display list of buffers */
|
||||
extern int usebuffer(); /* Switch a window to a buffer */
|
||||
extern int killbuffer(); /* Make a buffer go away. */
|
||||
extern int reposition(); /* Reposition window */
|
||||
extern int refresh(); /* Refresh the screen */
|
||||
extern int twiddle(); /* Twiddle characters */
|
||||
extern int tab(); /* Insert tab */
|
||||
extern int newline(); /* Insert CR-LF */
|
||||
extern int indent(); /* Insert CR-LF, then indent */
|
||||
extern int openline(); /* Open up a blank line */
|
||||
extern int deblank(); /* Delete blank lines */
|
||||
extern int quote(); /* Insert literal */
|
||||
extern int backword(); /* Backup by words */
|
||||
extern int forwword(); /* Advance by words */
|
||||
extern int forwdel(); /* Forward delete */
|
||||
extern int backdel(); /* Backward delete */
|
||||
extern int kill(); /* Kill forward */
|
||||
extern int yank(); /* Yank back from killbuffer. */
|
||||
extern int upperword(); /* Upper case word. */
|
||||
extern int lowerword(); /* Lower case word. */
|
||||
extern int upperregion(); /* Upper case region. */
|
||||
extern int lowerregion(); /* Lower case region. */
|
||||
extern int capword(); /* Initial capitalize word. */
|
||||
extern int delfword(); /* Delete forward word. */
|
||||
extern int delbword(); /* Delete backward word. */
|
||||
extern int killregion(); /* Kill region. */
|
||||
extern int copyregion(); /* Copy region to kill buffer. */
|
||||
extern int spawncli(); /* Run CLI in a subjob. */
|
||||
extern int spawn(); /* Run a command in a subjob. */
|
||||
extern int quickexit(); /* low keystroke style exit. */
|
||||
extern int gotoline(); /* goto line given as arg */
|
||||
extern int gotofline(); /* goto line in file. */
|
||||
extern int setfold(); /* set case-fold on search flag */
|
||||
extern int nexterr(); /* Seek the next error */
|
||||
extern int preverr(); /* Seek the previous error */
|
||||
|
||||
extern char *strcpy(); /* copy string */
|
||||
|
||||
/*
|
||||
* File-name list for command line...
|
||||
*/
|
||||
char *cfiles[NCFILES]; /* Command line specified files */
|
||||
int cfilecnt; /* File count... */
|
||||
|
||||
/*
|
||||
* Command line switch flags...
|
||||
*/
|
||||
int runswitch;
|
||||
|
||||
/*
|
||||
* Command table.
|
||||
* This table is *roughly* in ASCII
|
||||
* order, left to right across the characters
|
||||
* of the command. This expains the funny
|
||||
* location of the control-X commands.
|
||||
*/
|
||||
KEYTAB keytab[] = {
|
||||
CTRL|'@', &setmark,
|
||||
CTRL|'A', &gotobol,
|
||||
CTRL|'B', &backchar,
|
||||
CTRL|'C', &spawncli, /* Run CLI in subjob. */
|
||||
CTRL|'D', &forwdel,
|
||||
CTRL|'E', &gotoeol,
|
||||
CTRL|'F', &forwchar,
|
||||
CTRL|'G', &ctrlg,
|
||||
CTRL|'H', &backdel,
|
||||
CTRL|'I', &tab,
|
||||
CTRL|'J', &indent,
|
||||
CTRL|'K', &kill,
|
||||
CTRL|'L', &refresh,
|
||||
CTRL|'M', &newline,
|
||||
CTRL|'N', &forwline,
|
||||
CTRL|'O', &openline,
|
||||
CTRL|'P', &backline,
|
||||
CTRL|'Q', "e, /* Often unreachable */
|
||||
CTRL|'R', &backisearch,
|
||||
CTRL|'S', &forwisearch,
|
||||
CTRL|'T', &twiddle,
|
||||
CTRL|'V', &forwpage,
|
||||
CTRL|'W', &killregion,
|
||||
CTRL|'Y', &yank,
|
||||
CTRL|'Z', &quickexit, /* quick save and exit */
|
||||
CTLX|CTRL|'B', &listbuffers,
|
||||
CTLX|CTRL|'C', &quit, /* Hard quit. */
|
||||
CTLX|CTRL|'F', &filename,
|
||||
CTLX|CTRL|'L', &lowerregion,
|
||||
CTLX|CTRL|'O', &deblank,
|
||||
CTLX|CTRL|'N', &mvdnwind,
|
||||
CTLX|CTRL|'P', &mvupwind,
|
||||
CTLX|CTRL|'R', &fileread,
|
||||
CTLX|CTRL|'S', &filesave, /* Often unreachable */
|
||||
CTLX|CTRL|'U', &upperregion,
|
||||
CTLX|CTRL|'V', &filevisit,
|
||||
CTLX|CTRL|'W', &filewrite,
|
||||
CTLX|CTRL|'X', &swapmark,
|
||||
CTLX|CTRL|'Z', &shrinkwind,
|
||||
CTLX|'!', &spawn, /* Run 1 command. */
|
||||
CTLX|'<', &preverr, /* Seek previous error */
|
||||
CTLX|'=', &showcpos,
|
||||
CTLX|'>', &nexterr, /* Seek next error */
|
||||
CTLX|'(', &ctlxlp,
|
||||
CTLX|')', &ctlxrp,
|
||||
CTLX|'1', &onlywind,
|
||||
CTLX|'2', &splitwind,
|
||||
CTLX|'B', &usebuffer,
|
||||
CTLX|'E', &ctlxe,
|
||||
CTLX|'F', &setfillcol,
|
||||
CTLX|'G', &gotoline,
|
||||
CTLX|'K', &killbuffer,
|
||||
CTLX|'N', &nextwind,
|
||||
CTLX|'P', &prevwind,
|
||||
CTLX|'Z', &enlargewind,
|
||||
#ifdef VT52KEYS
|
||||
META|CTRL|'B', &backword,
|
||||
META|CTRL|'C', &capword,
|
||||
META|CTRL|'D', &delfword,
|
||||
#endif
|
||||
META|CTRL|'H', &delbword,
|
||||
META|CTRL|'R', &queryrepl,
|
||||
META|'!', &reposition,
|
||||
META|'.', &setmark,
|
||||
META|'>', &gotoeob,
|
||||
META|'<', &gotobob,
|
||||
META|'%', &queryrepl,
|
||||
META|'/', &searchagain,
|
||||
META|'@', &setfold,
|
||||
#ifdef VT52KEYS
|
||||
META|'A', &backline, /* VT52 arrow keys */
|
||||
META|'B', &forwline,
|
||||
META|'C', &backchar,
|
||||
META|'D', &forwchar,
|
||||
#else
|
||||
META|'B', &backword,
|
||||
META|'C', &capword,
|
||||
META|'D', &delfword,
|
||||
#endif
|
||||
META|'F', &forwword,
|
||||
META|'G', &gotofline,
|
||||
META|'L', &lowerword,
|
||||
META|'Q', "e,
|
||||
META|'R', &backsearch,
|
||||
META|'S', &forwsearch,
|
||||
META|'U', &upperword,
|
||||
META|'V', &backpage,
|
||||
META|'W', ©region,
|
||||
META|0x7F, &delbword,
|
||||
0x7F, &backdel
|
||||
};
|
||||
|
||||
#define NKEYTAB (sizeof(keytab)/sizeof(keytab[0]))
|
||||
|
||||
#if LK201
|
||||
/*
|
||||
* Mapping table for all of the funny
|
||||
* keys with the numeric parameters on the LK201.
|
||||
* Indexed by the code, which is between 0 (unused) and
|
||||
* 34 (F20). An entry of 0 means no mapping. The map
|
||||
* goes to command keys. If I had a "special" bit,
|
||||
* I could use the code in the escape sequence as a
|
||||
* key code, and return (for example) "do" as
|
||||
* SPECIAL + 29. Then the dispatch would be
|
||||
* done by the default keymap. This is probably a
|
||||
* better way to go.
|
||||
*/
|
||||
short lkmap[] = {
|
||||
0,
|
||||
CTRL|'S', /* 1 Find */
|
||||
CTRL|'Y', /* 2 Insert here */
|
||||
CTRL|'W', /* 3 Remove */
|
||||
CTRL|'@', /* 4 Select */
|
||||
META|'V', /* 5 Previous screen */
|
||||
CTRL|'V', /* 6 Next screen */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, /* 10 Compose */
|
||||
0,
|
||||
0, /* 12 Print screen */
|
||||
0,
|
||||
0, /* 14 F4 */
|
||||
0,
|
||||
0,
|
||||
0, /* 17 F6 */
|
||||
0, /* 18 F7 */
|
||||
0, /* 19 F8 */
|
||||
0, /* 20 F9 */
|
||||
0, /* 21 F10 */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, /* 26 F14 */
|
||||
0,
|
||||
0, /* 28 Help */
|
||||
CTLX|'E', /* 29 Do C-X E */
|
||||
0,
|
||||
CTLX|'P', /* 31 F17 C-X P */
|
||||
CTLX|'N', /* 32 F18 C-X N */
|
||||
CTLX|'Z', /* 33 F19 C-X Z */
|
||||
CTLX|CTRL|'Z' /* 34 F20 C-X C-Z */
|
||||
};
|
||||
#endif
|
||||
|
||||
main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
register int c;
|
||||
register int f;
|
||||
register int n;
|
||||
register int mflag;
|
||||
char bname[NBUFN];
|
||||
|
||||
#if MSDOS
|
||||
setkeys();
|
||||
#endif
|
||||
#if IBM
|
||||
vidnit();
|
||||
#endif
|
||||
runswitch = 0; /* Initialize the switches */
|
||||
ffold = TRUE; /* initialize the fold flg */
|
||||
argproc(argc, argv); /* Parse the arg list */
|
||||
strcpy(bname, "main"); /* Work out the name of */
|
||||
if (cfilecnt > 0) /* the default buffer. */
|
||||
makename(bname, cfiles[0]); /* Make a buffer name */
|
||||
edinit(bname); /* Buffers, windows. */
|
||||
vtinit(); /* Displays. */
|
||||
if (cfilecnt > 0) {
|
||||
update(); /* You have to update */
|
||||
readin(cfiles[0]); /* in case "[New file]" */
|
||||
}
|
||||
if (cfilecnt > 1) {
|
||||
n = (term.t_nrow - cfilecnt - 1) / cfilecnt;
|
||||
for (c = 1; c < cfilecnt ; c++) { /* For all other files... */
|
||||
splitwind(0,0); /* Split this window... */
|
||||
if ((f=curwp->w_ntrows-n) != 0)
|
||||
shrinkwind(0,f); /* Even out the windows */
|
||||
nextwind(0,0); /* Go on to the next one */
|
||||
visitfile(cfiles[c]); /* Read in that file */
|
||||
}
|
||||
}
|
||||
if ((runswitch & CF_ERROR) != 0) {
|
||||
splitwind(0,0); /* Split this window */
|
||||
f = curwp->w_ntrows - ERRLINES; /* Make error window small */
|
||||
if (f > 0)
|
||||
shrinkwind(0,f);
|
||||
readerr();
|
||||
nextwind();
|
||||
mlerase();
|
||||
update();
|
||||
nexterr(0,1);
|
||||
update();
|
||||
}
|
||||
|
||||
lastflag = 0; /* Fake last flags. */
|
||||
loop:
|
||||
update(); /* Fix up the screen */
|
||||
c = getkey();
|
||||
if (mpresf != FALSE) {
|
||||
mlerase();
|
||||
update();
|
||||
if (c == ' ') /* ITS EMACS does this */
|
||||
goto loop;
|
||||
}
|
||||
f = FALSE;
|
||||
n = 1;
|
||||
if (c == (CTRL|'U')) { /* ^U, start argument */
|
||||
f = TRUE;
|
||||
n = 4; /* with argument of 4 */
|
||||
mflag = 0; /* that can be discarded. */
|
||||
mlwrite("Arg: 4");
|
||||
while ((c=getkey()) >='0' && c<='9' || c==(CTRL|'U') || c=='-'){
|
||||
if (c == (CTRL|'U'))
|
||||
n = n*4;
|
||||
/*
|
||||
* If dash, and start of argument string, set arg.
|
||||
* to -1. Otherwise, insert it.
|
||||
*/
|
||||
else if (c == '-') {
|
||||
if (mflag)
|
||||
break;
|
||||
n = 0;
|
||||
mflag = -1;
|
||||
}
|
||||
/*
|
||||
* If first digit entered, replace previous argument
|
||||
* with digit and set sign. Otherwise, append to arg.
|
||||
*/
|
||||
else {
|
||||
if (!mflag) {
|
||||
n = 0;
|
||||
mflag = 1;
|
||||
}
|
||||
n = 10*n + c - '0';
|
||||
}
|
||||
mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1));
|
||||
}
|
||||
/*
|
||||
* Make arguments preceded by a minus sign negative and change
|
||||
* the special argument "^U -" to an effective "^U -1".
|
||||
*/
|
||||
if (mflag == -1) {
|
||||
if (n == 0)
|
||||
n++;
|
||||
n = -n;
|
||||
}
|
||||
}
|
||||
if (c == (CTRL|'X')) /* ^X is a prefix */
|
||||
c = CTLX | getctl();
|
||||
if (kbdmip != NULL) { /* Save macro strokes. */
|
||||
if (c!=(CTLX|')') && kbdmip>&kbdm[NKBDM-6]) {
|
||||
ctrlg(FALSE, 0);
|
||||
goto loop;
|
||||
}
|
||||
if (f != FALSE) {
|
||||
*kbdmip++ = (CTRL|'U');
|
||||
*kbdmip++ = n;
|
||||
}
|
||||
*kbdmip++ = c;
|
||||
}
|
||||
execute(c, f, n); /* Do it. */
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize all of the buffers
|
||||
* and windows. The buffer name is passed down as
|
||||
* an argument, because the main routine may have been
|
||||
* told to read in a file by default, and we want the
|
||||
* buffer name to be right.
|
||||
*/
|
||||
edinit(bname)
|
||||
char bname[];
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register WINDOW *wp;
|
||||
|
||||
bp = bfind(bname, TRUE, 0); /* First buffer */
|
||||
blistp = bfind("[List]", TRUE, BFTEMP); /* Buffer list buffer */
|
||||
wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */
|
||||
if (bp==NULL || wp==NULL || blistp==NULL)
|
||||
abort();
|
||||
curbp = bp; /* Make this current */
|
||||
wheadp = wp;
|
||||
curwp = wp;
|
||||
wp->w_wndp = NULL; /* Initialize window */
|
||||
wp->w_bufp = bp;
|
||||
bp->b_nwnd = 1; /* Displayed. */
|
||||
wp->w_linep = bp->b_linep;
|
||||
wp->w_dotp = bp->b_linep;
|
||||
wp->w_doto = 0;
|
||||
wp->w_markp = NULL;
|
||||
wp->w_marko = 0;
|
||||
wp->w_toprow = 0;
|
||||
wp->w_ntrows = term.t_nrow-1; /* "-1" for mode line. */
|
||||
wp->w_force = 0;
|
||||
wp->w_flag = WFMODE|WFHARD; /* Full. */
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the general command execution
|
||||
* routine. It handles the fake binding of all the
|
||||
* keys to "self-insert". It also clears out the "thisflag"
|
||||
* word, and arranges to move it to the "lastflag", so that
|
||||
* the next command can look at it. Return the status of
|
||||
* command.
|
||||
*/
|
||||
execute(c, f, n)
|
||||
{
|
||||
register KEYTAB *ktp;
|
||||
register int status;
|
||||
|
||||
ktp = &keytab[0]; /* Look in key table. */
|
||||
while (ktp < &keytab[NKEYTAB]) {
|
||||
if (ktp->k_code == c) {
|
||||
thisflag = 0;
|
||||
status = (*ktp->k_fp)(f, n);
|
||||
lastflag = thisflag;
|
||||
return (status);
|
||||
}
|
||||
++ktp;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a space was typed, fill column is defined, the argument is non-
|
||||
* negative, and we are now past fill column, perform word wrap.
|
||||
*/
|
||||
if (c == ' ' && fillcol > 0 && n>=0 && getccol(FALSE) > fillcol)
|
||||
wrapword();
|
||||
|
||||
if ((c>=0x20 && c<=0x7E) /* Self inserting. */
|
||||
|| (c>=0xA0 && c<=0xFE)) {
|
||||
if (n <= 0) { /* Fenceposts. */
|
||||
lastflag = 0;
|
||||
return (n<0 ? FALSE : TRUE);
|
||||
}
|
||||
thisflag = 0; /* For the future. */
|
||||
status = linsert(n, c);
|
||||
lastflag = thisflag;
|
||||
return (status);
|
||||
}
|
||||
lastflag = 0; /* Fake last flags. */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in a key.
|
||||
* Do the standard keyboard preprocessing.
|
||||
* Convert the keys to the internal character set. On
|
||||
* the LK201, which lacks a reasonable ESC key, make the
|
||||
* grave accent a meta key too; this is a fairly common
|
||||
* customization around Digital. Also read and decode
|
||||
* the arrow keys, and other special keys. This is
|
||||
* done in Rainbow mode; does this work on all
|
||||
* the terminals with LK201 keyboards?
|
||||
*/
|
||||
getkey()
|
||||
{
|
||||
register int c;
|
||||
#if LK201
|
||||
register int n;
|
||||
loop:
|
||||
c = (*term.t_getchar)();
|
||||
if (c == AGRAVE) { /* Alternate M- prefix. */
|
||||
c = getctl();
|
||||
return (META | c);
|
||||
}
|
||||
if (c == METACH) { /* M-, or special key. */
|
||||
c = (*term.t_getchar)();
|
||||
if (c == '[') { /* Arrows and extras. */
|
||||
c = (*term.t_getchar)();
|
||||
if (c == 'A')
|
||||
return (CTRL | 'P');
|
||||
if (c == 'B')
|
||||
return (CTRL | 'N');
|
||||
if (c == 'C')
|
||||
return (CTRL | 'F');
|
||||
if (c == 'D')
|
||||
return (CTRL | 'B');
|
||||
if (c>='0' && c<='9') {
|
||||
n = 0;
|
||||
do {
|
||||
n = 10*n + c - '0';
|
||||
c = (*term.t_getchar)();
|
||||
} while (c>='0' && c<='9');
|
||||
if (c=='~' && n<=34 && (c=lkmap[n])!=0)
|
||||
return (c);
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
if (c == 'O') {
|
||||
c = (*term.t_getchar)();
|
||||
if (c == 'P') /* PF1 => M-X (Future) */
|
||||
return (META | 'X');
|
||||
if (c == 'Q') /* PF2 => C-Q */
|
||||
return (CTRL | 'Q');
|
||||
if (c == 'R') /* PF3 => C-S */
|
||||
return (CTRL | 'S');
|
||||
if (c == 'S') /* PF4 => C-R */
|
||||
return (CTRL | 'R');
|
||||
goto loop;
|
||||
}
|
||||
if (c>='a' && c<='z') /* Force to upper */
|
||||
c -= 0x20;
|
||||
if (c>=0x00 && c<=0x1F) /* C0 control -> C- */
|
||||
c = CTRL | (c+'@');
|
||||
return (META | c);
|
||||
}
|
||||
#endif
|
||||
#if VT100
|
||||
loop:
|
||||
c = (*term.t_getchar)();
|
||||
if (c == METACH) { /* Apply M- prefix */
|
||||
c = (*term.t_getchar)();
|
||||
if (c == '[') { /* Arrow keys. */
|
||||
c = (*term.t_getchar)();
|
||||
if (c == 'A')
|
||||
return (CTRL | 'P');
|
||||
if (c == 'B')
|
||||
return (CTRL | 'N');
|
||||
if (c == 'C')
|
||||
return (CTRL | 'F');
|
||||
if (c == 'D')
|
||||
return (CTRL | 'B');
|
||||
goto loop;
|
||||
}
|
||||
if (c == 'O') {
|
||||
c = (*term.t_getchar)();
|
||||
if (c == 'P') /* PF1 => M-X (Future) */
|
||||
return (META | 'X');
|
||||
if (c == 'Q') /* PF2 => C-Q */
|
||||
return (CTRL | 'Q');
|
||||
if (c == 'R') /* PF3 => C-S */
|
||||
return (CTRL | 'S');
|
||||
if (c == 'S') /* PF4 => C-R */
|
||||
return (CTRL | 'R');
|
||||
goto loop;
|
||||
}
|
||||
if (c>='a' && c<='z') /* Force to upper */
|
||||
c -= 0x20;
|
||||
if (c>=0x00 && c<=0x1F) /* C0 control -> C- */
|
||||
c = CTRL | (c+'@');
|
||||
return (META | c);
|
||||
}
|
||||
#endif
|
||||
#if !LK201 && !VT100
|
||||
c = (*term.t_getchar)();
|
||||
if (c == METACH) { /* Apply M- prefix */
|
||||
c = getctl();
|
||||
return (META | c);
|
||||
}
|
||||
#endif
|
||||
if (c == CTRLCH) { /* Apply C- prefix */
|
||||
c = getctl();
|
||||
return (CTRL | c);
|
||||
}
|
||||
if (c == CTMECH) { /* Apply C-M- prefix */
|
||||
c = getctl();
|
||||
return (CTRL | META | c);
|
||||
}
|
||||
if (c>=0x00 && c<=0x1F) /* C0 control -> C- */
|
||||
c = CTRL | (c+'@');
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a key.
|
||||
* Apply control modifications
|
||||
* to the read key.
|
||||
*/
|
||||
getctl()
|
||||
{
|
||||
register int c;
|
||||
|
||||
c = (*term.t_getchar)();
|
||||
if (c>='a' && c<='z') /* Force to upper */
|
||||
c -= 0x20;
|
||||
if (c>=0x00 && c<=0x1F) /* C0 control -> C- */
|
||||
c = CTRL | (c+'@');
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fancy quit command, as implemented
|
||||
* by Norm. If the current buffer has changed
|
||||
* do a write current buffer and exit emacs,
|
||||
* otherwise simply exit.
|
||||
*/
|
||||
quickexit(f, n)
|
||||
{
|
||||
if ((curbp->b_flag&BFCHG) != 0 /* Changed. */
|
||||
&& (curbp->b_flag&(BFTEMP|BFERROR|BFNOWRT)) == 0)
|
||||
/* Real and not R/O... */
|
||||
filesave(f, n);
|
||||
quit(f, n); /* conditionally quit */
|
||||
}
|
||||
|
||||
/*
|
||||
* Quit command. If an argument, always
|
||||
* quit. Otherwise confirm if a buffer has been
|
||||
* changed and not written out. Normally bound
|
||||
* to "C-X C-C".
|
||||
*/
|
||||
quit(f, n)
|
||||
{
|
||||
register int s = FALSE;
|
||||
|
||||
if (f != FALSE /* Argument forces it. */
|
||||
|| anycb() == FALSE /* All buffers clean. */
|
||||
|| (s=mlyesno("Quit")) == TRUE) { /* User says it's OK. */
|
||||
vttidy();
|
||||
#if MSDOS
|
||||
resetkeys();
|
||||
#endif
|
||||
if (f != FALSE || s != FALSE)
|
||||
exit(BAD);
|
||||
else
|
||||
exit(GOOD);
|
||||
}
|
||||
#if MSDOS
|
||||
setkeys();
|
||||
#endif
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin a keyboard macro.
|
||||
* Error if not at the top level
|
||||
* in keyboard processing. Set up
|
||||
* variables and return.
|
||||
*/
|
||||
ctlxlp(f, n)
|
||||
{
|
||||
if (kbdmip!=NULL || kbdmop!=NULL) {
|
||||
mlwrite("Not now");
|
||||
return (FALSE);
|
||||
}
|
||||
mlwrite("[Start macro]");
|
||||
kbdmip = &kbdm[0];
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* End keyboard macro. Check for
|
||||
* the same limit conditions as the
|
||||
* above routine. Set up the variables
|
||||
* and return to the caller.
|
||||
*/
|
||||
ctlxrp(f, n)
|
||||
{
|
||||
if (kbdmip == NULL) {
|
||||
mlwrite("Not now");
|
||||
return (FALSE);
|
||||
}
|
||||
mlwrite("[End macro]");
|
||||
kbdmip = NULL;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute a macro.
|
||||
* The command argument is the
|
||||
* number of times to loop. Quit as
|
||||
* soon as a command gets an error.
|
||||
* Return TRUE if all ok, else
|
||||
* FALSE.
|
||||
*/
|
||||
ctlxe(f, n)
|
||||
{
|
||||
register int c;
|
||||
register int af;
|
||||
register int an;
|
||||
register int s;
|
||||
|
||||
if (kbdmip!=NULL || kbdmop!=NULL) {
|
||||
mlwrite("Not now");
|
||||
return (FALSE);
|
||||
}
|
||||
if (n <= 0)
|
||||
return (TRUE);
|
||||
do {
|
||||
kbdmop = &kbdm[0];
|
||||
do {
|
||||
af = FALSE;
|
||||
an = 1;
|
||||
if ((c = *kbdmop++) == (CTRL|'U')) {
|
||||
af = TRUE;
|
||||
an = *kbdmop++;
|
||||
c = *kbdmop++;
|
||||
}
|
||||
s = TRUE;
|
||||
} while (c!=(CTLX|')') && (s=execute(c, af, an))==TRUE);
|
||||
kbdmop = NULL;
|
||||
} while (s==TRUE && --n);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Abort.
|
||||
* Beep the beeper.
|
||||
* Kill off any keyboard macro,
|
||||
* etc., that is in progress.
|
||||
* Sometimes called as a routine,
|
||||
* to do general aborting of
|
||||
* stuff.
|
||||
*/
|
||||
ctrlg(f, n)
|
||||
{
|
||||
(*term.t_beep)();
|
||||
if (kbdmip != NULL) {
|
||||
kbdm[0] = (CTLX|')');
|
||||
kbdmip = NULL;
|
||||
}
|
||||
return (ABORT);
|
||||
}
|
||||
|
||||
|
||||
#if MSDOS
|
||||
setkeys() /* redefine cursor keys */
|
||||
/* so that they make */
|
||||
/* sense to microEMACS */
|
||||
/* as described in IBM */
|
||||
/* DOS tech. reference */
|
||||
/* manual */
|
||||
{
|
||||
#if !IBM
|
||||
static char *ctlseq[] = {
|
||||
"\033[0;72;16p", /* up = <ctrl-p> */
|
||||
"\033[0;77;6p", /* right = <ctrl-f> */
|
||||
"\033[0;75;2p", /* left = <ctrl-b> */
|
||||
"\033[0;80;14p", /* down = <ctrl-n> */
|
||||
"\033[0;81;22p", /* pg dn = <ctrl-v> */
|
||||
"\033[0;73;27;86p", /* pg up = <esc>V */
|
||||
"\033[0;71;27;60p", /* home = <esc>< */
|
||||
"\033[0;79;27;62p", /* end = <esc>> */
|
||||
"\033[0;83;127p", /* del = del */
|
||||
"\033[0;3;27;46p", /* <ctrl-@> = <exc>. */
|
||||
NULL
|
||||
};
|
||||
register char **ctlp;
|
||||
|
||||
for(ctlp = ctlseq; NULL != *ctlp; ctlp++)
|
||||
mlwrite(*ctlp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
resetkeys() /* redefine cursor keys */
|
||||
/* to default values */
|
||||
{
|
||||
#if !IBM
|
||||
static char *ctlseq[] = {
|
||||
"\033[0;72;0;72p",
|
||||
"\033[0;77;0;77p",
|
||||
"\033[0;75;0;75p",
|
||||
"\033[0;80;0;80p",
|
||||
"\033[0;81;0;81p",
|
||||
"\033[0;73;0;73p",
|
||||
"\033[0;71;0;71p",
|
||||
"\033[0;79;0;79p",
|
||||
"\033[0;83;0;83p",
|
||||
"\033[0;3;0;3p",
|
||||
NULL
|
||||
};
|
||||
register char **ctlp;
|
||||
|
||||
for(ctlp = ctlseq; NULL != *ctlp; ctlp++)
|
||||
mlwrite(*ctlp);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
argproc(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
char *ptr;
|
||||
|
||||
cfilecnt = 0;
|
||||
for (i = 1; i < argc; i++) {
|
||||
ptr = argv[i]; /* Get this argument... */
|
||||
if (*ptr == '-') { /* Is this a switch? */
|
||||
switch (ptr[1]) {
|
||||
case 'b':
|
||||
runswitch |= CF_BACKUP;
|
||||
break;
|
||||
case 'd':
|
||||
runswitch |= CF_DEBUG;
|
||||
break;
|
||||
case 'e':
|
||||
runswitch |= CF_ERROR;
|
||||
if (ptr[2] == 0) {
|
||||
if (++i == argc) {
|
||||
runswitch &= ~CF_ERROR;
|
||||
continue;
|
||||
}
|
||||
strcpy(errfile, argv[i]);
|
||||
} else {
|
||||
strcpy(errfile, &ptr[2]);
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
runswitch |= CF_WARN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Process this switch */
|
||||
} else { /* Otherwise... */
|
||||
if (cfilecnt >= NCFILES)
|
||||
continue;
|
||||
cfiles[cfilecnt++] = ptr; /* This is a file. */
|
||||
#if GEM
|
||||
fixname(cfiles[cfilecnt-1]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
64
Mark Williams MWS v4/SAMPLE/MAKEFILE
Normal file
64
Mark Williams MWS v4/SAMPLE/MAKEFILE
Normal file
@ -0,0 +1,64 @@
|
||||
# Makefile 10/13/87
|
||||
# Make command file to build MSDOS executable MicroEMACS me.exe.
|
||||
|
||||
# Source file directory.
|
||||
# This allows the object to be built in a different directory
|
||||
# than where source resides.
|
||||
SOURCE=\sample
|
||||
|
||||
# Memory Model: either "SMALL" or "LARGE", no spaces please.
|
||||
MEMMODEL=SMALL
|
||||
|
||||
# Unlinked objects.
|
||||
OBJ1=ansi.obj basic.obj buffer.obj display.obj error.obj file.obj fileio.obj
|
||||
OBJ2=ibmbios.obj ibmpc.obj line.obj main.obj putline.obj random.obj region.obj
|
||||
OBJ3=search.obj spawn.obj tcap.obj termio.obj vt52.obj window.obj word.obj
|
||||
|
||||
# Files "putline.m" and "ibmbios.m" use IBM PC ROM BIOS calls for screen and
|
||||
# keyboard control; they may not work on some IBM-compatible (non-IBM) systems.
|
||||
# Remove the definition of IBM below and recompile if necessary.
|
||||
# Note: the definition of IBM is required in addition to the definition
|
||||
# of TANDY to make a Tandy 2000 version, via the command "make tandy".
|
||||
CFLAGS=-VQUIET -DIBM -V$(MEMMODEL)
|
||||
LDFLAGS=-w -o me -V$(MEMMODEL)
|
||||
|
||||
# Primary targets.
|
||||
ibm: me.exe
|
||||
@
|
||||
|
||||
tandy: tandyspecific me.exe
|
||||
@
|
||||
|
||||
tandyspecific:
|
||||
$(CC) $(CFLAGS) -DTANDY -c $(SOURCE)\putline.m
|
||||
|
||||
# Uses "tempfile" to avoid MSDOS command line length restrictions.
|
||||
me.exe: $(OBJ1) $(OBJ2) $(OBJ3)
|
||||
echo $(OBJ1) >tempfile
|
||||
echo $(OBJ2) >>tempfile
|
||||
echo $(OBJ3) >>tempfile
|
||||
cc $(LDFLAGS) @tempfile
|
||||
del tempfile
|
||||
|
||||
# Secondary targets.
|
||||
ansi.obj: $(SOURCE)\ansi.c $(SOURCE)\ed.h
|
||||
basic.obj: $(SOURCE)\basic.c $(SOURCE)\ed.h
|
||||
buffer.obj: $(SOURCE)\buffer.c $(SOURCE)\ed.h
|
||||
display.obj: $(SOURCE)\display.c $(SOURCE)\ed.h
|
||||
error.obj: $(SOURCE)\error.c $(SOURCE)\ed.h
|
||||
file.obj: $(SOURCE)\file.c $(SOURCE)\ed.h
|
||||
fileio.obj: $(SOURCE)\fileio.c $(SOURCE)\ed.h
|
||||
ibmbios.obj: $(SOURCE)\ibmbios.m
|
||||
ibmpc.obj: $(SOURCE)\ibmpc.c $(SOURCE)\ed.h
|
||||
line.obj: $(SOURCE)\line.c $(SOURCE)\ed.h
|
||||
main.obj: $(SOURCE)\main.c $(SOURCE)\ed.h
|
||||
putline.obj: $(SOURCE)\putline.m
|
||||
random.obj: $(SOURCE)\random.c $(SOURCE)\ed.h
|
||||
region.obj: $(SOURCE)\region.c $(SOURCE)\ed.h
|
||||
search.obj: $(SOURCE)\search.c $(SOURCE)\ed.h
|
||||
spawn.obj: $(SOURCE)\spawn.c $(SOURCE)\ed.h
|
||||
tcap.obj: $(SOURCE)\tcap.c $(SOURCE)\ed.h
|
||||
termio.obj: $(SOURCE)\termio.c $(SOURCE)\ed.h
|
||||
vt52.obj: $(SOURCE)\vt52.c $(SOURCE)\ed.h
|
||||
window.obj: $(SOURCE)\window.c $(SOURCE)\ed.h
|
||||
word.obj: $(SOURCE)\word.c $(SOURCE)\ed.h
|
118
Mark Williams MWS v4/SAMPLE/PUTLINE.M
Normal file
118
Mark Williams MWS v4/SAMPLE/PUTLINE.M
Normal file
@ -0,0 +1,118 @@
|
||||
//////////
|
||||
/ putline.m
|
||||
/ IBM PC Fast Video Support for MicroEMACS.
|
||||
/ The routines in this file use IBM PC ROM BIOS Interrupt 0x10
|
||||
/ to control the screen. They may not work on some IBM-compatible
|
||||
/ (non-IBM) systems.
|
||||
//////////
|
||||
|
||||
#if IBM
|
||||
|
||||
#include <larges.h>
|
||||
|
||||
RBVIDEO = 0x10 / IBM PC ROM BIOS video driver interrupt
|
||||
|
||||
MONOSEG = 0xB000 / Segment of Screen for Monochrome Adapter
|
||||
COLSEG = 0xB800 / Segment of Screen for Yes Color Graphics Card
|
||||
|
||||
IBMATTRIB = 0x07 / Character Attribute for IBM PC
|
||||
TANDYATTRIB = 0x0A / Character Attribute for Tandy PC
|
||||
|
||||
SETVID = 0 / Function Number to Set the Video State
|
||||
COL8025 = 3 / Argument for 80x25 Color Character Mode
|
||||
SETPAGE = 5 / Function Number to Select Displayed Page
|
||||
PAGE0 = 0 / Argument to Select Page 0
|
||||
GETVID = 15 / Function Number to get Current Video State
|
||||
MONOSTATE = 7 / Return Value for Monochrome Adapter
|
||||
/ NB: COL8025 is Return Value from GETVID, too
|
||||
|
||||
//////////
|
||||
/ Local Data
|
||||
//////////
|
||||
|
||||
.shrd
|
||||
|
||||
Vidseg_: .word MONOSEG / Segment of Screen
|
||||
|
||||
.shri
|
||||
|
||||
//////////
|
||||
/ vidnit()
|
||||
/ Checks to see if there is a Color Graphics Card Installed, and
|
||||
/ sets the Local Variable Vidseg_ appropriately. Initializes the
|
||||
/ screen to 80x25 Character Mode, if necessary, and then selects
|
||||
/ displayed page 0.
|
||||
/ Conditionalized for TANDY, to locate base page for Video Segment.
|
||||
//////////
|
||||
|
||||
Enter( vidnit_ )
|
||||
#if TANDY
|
||||
mov dx, es
|
||||
sub ax, ax
|
||||
mov es, ax
|
||||
mov bx, es:0x474 / Location of Video Base Page
|
||||
mov Vidseg_, bx
|
||||
mov es, dx
|
||||
#else
|
||||
movb ah, $GETVID
|
||||
int RBVIDEO
|
||||
cmpb al, $MONOSTATE
|
||||
je 0f
|
||||
|
||||
Map( ds, cx, $@Vidseg_)
|
||||
mov Vidseg_, $COLSEG
|
||||
|
||||
cmpb al, $COL8025
|
||||
je 0f
|
||||
movb ah, $SETVID
|
||||
movb al, $COL8025
|
||||
int RBVIDEO
|
||||
|
||||
0: movb ah, $SETPAGE
|
||||
movb al, $PAGE0
|
||||
int RBVIDEO
|
||||
#endif
|
||||
Leave
|
||||
|
||||
//////////
|
||||
/ putline(row, col, buf) int row, col; char *buf;
|
||||
/ Display buffer at designated location, by direct screen update.
|
||||
//////////
|
||||
|
||||
row = LEFTARG
|
||||
col = row+2
|
||||
buf = col+2
|
||||
|
||||
Enter( putline_ )
|
||||
Map( ds, ax, $@Vidseg_)
|
||||
movb ah, row(bp)
|
||||
decb ah
|
||||
movb al, $10
|
||||
mulb ah
|
||||
add ax, Vidseg_
|
||||
mov es, ax
|
||||
#if TANDY
|
||||
movb ah, $TANDYATTRIB
|
||||
#else
|
||||
movb ah, $IBMATTRIB
|
||||
#endif
|
||||
|
||||
mov di, col(bp)
|
||||
dec di
|
||||
mov cx, $80
|
||||
sub cx, di
|
||||
jna 2f
|
||||
Lds si, buf(bp)
|
||||
|
||||
1: lodsb
|
||||
stos
|
||||
loop 1b
|
||||
|
||||
2: mov ax, ds
|
||||
mov es, ax
|
||||
Leave
|
||||
|
||||
#endif
|
||||
|
||||
/ end of putline.m
|
||||
|
470
Mark Williams MWS v4/SAMPLE/RANDOM.C
Normal file
470
Mark Williams MWS v4/SAMPLE/RANDOM.C
Normal file
@ -0,0 +1,470 @@
|
||||
/* @(microEMACS)random.c
|
||||
*
|
||||
* This file contains the command processing functions for a number of
|
||||
* random commands. There is no functional grouping here, for sure.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
int tabsize; /* Tab size (0: use real tabs) */
|
||||
|
||||
/*
|
||||
* Return current column. Stop at first non-blank given TRUE argument.
|
||||
*/
|
||||
getccol(bflg)
|
||||
int bflg;
|
||||
{
|
||||
register int c, i;
|
||||
register int col = 0;
|
||||
register WINDOW *lcurwp;
|
||||
|
||||
lcurwp = curwp;
|
||||
for (i=0; i<lcurwp->w_doto; ++i) {
|
||||
c = lgetc(lcurwp->w_dotp, i);
|
||||
if (c!=' ' && c!='\t' && bflg)
|
||||
break;
|
||||
if (c == '\t')
|
||||
col |= 0x07;
|
||||
else if (c<0x20 || c==0x7F)
|
||||
++col;
|
||||
++col;
|
||||
}
|
||||
return(col);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set fill column to n, if given, otherwise use the current cursor
|
||||
* column. Either way, tell user where the fill column really is.
|
||||
*/
|
||||
setfillcol(f, n)
|
||||
register int n;
|
||||
{
|
||||
if (n < 2)
|
||||
fillcol = getccol(FALSE);
|
||||
else
|
||||
fillcol = n - 1;
|
||||
mlwrite("[Wrap at column %d]", fillcol+1);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display the current position of the cursor,
|
||||
* in origin 1 X-Y coordinates, the character that is
|
||||
* under the cursor (in hex), and the fraction of the
|
||||
* text that is before the cursor. The displayed column
|
||||
* is not the current column, but the column that would
|
||||
* be used on an infinite width display. Normally this
|
||||
* is bound to "C-X =".
|
||||
*/
|
||||
showcpos(f, n)
|
||||
{
|
||||
register LINE *clp;
|
||||
register long nch = 0L;
|
||||
register long nbc;
|
||||
register int cbo = 0;
|
||||
register int linecnt = 1;
|
||||
register int cac;
|
||||
register int curline = 0;
|
||||
int ratio;
|
||||
int col;
|
||||
|
||||
clp = lforw(curbp->b_linep); /* Grovel the data. */
|
||||
|
||||
for (;;) {
|
||||
if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
|
||||
curline = linecnt;
|
||||
nbc = nch;
|
||||
if (cbo == llength(clp))
|
||||
cac = '\n';
|
||||
else
|
||||
cac = lgetc(clp, cbo);
|
||||
}
|
||||
if (cbo == llength(clp)) {
|
||||
if (clp == curbp->b_linep)
|
||||
break;
|
||||
clp = lforw(clp);
|
||||
++linecnt;
|
||||
cbo = 0;
|
||||
} else
|
||||
++cbo;
|
||||
++nch;
|
||||
}
|
||||
col = getccol(FALSE)+1; /* Get real column. */
|
||||
ratio = 0; /* Ratio before dot. */
|
||||
if (nch != 0)
|
||||
ratio = (100L*nbc) / nch;
|
||||
mlwrite("X=%d Y=%d CH=0x%x .=%D (%d%% of %D) line %d of %d",
|
||||
col, currow+1, cac, nbc, ratio, nch, curline, linecnt);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Twiddle the two characters on either side of
|
||||
* dot. If dot is at the end of the line twiddle the
|
||||
* two characters before it. Return with an error if dot
|
||||
* is at the beginning of line; it seems to be a bit
|
||||
* pointless to make this work. This fixes up a very
|
||||
* common typo with a single stroke. Normally bound
|
||||
* to "C-T". This always works within a line, so
|
||||
* "WFEDIT" is good enough.
|
||||
*/
|
||||
twiddle(f, n)
|
||||
{
|
||||
register WINDOW *lcurwp;
|
||||
register LINE *dotp;
|
||||
register int doto;
|
||||
register int cl;
|
||||
register int cr;
|
||||
|
||||
lcurwp = curwp;
|
||||
dotp = lcurwp->w_dotp;
|
||||
doto = lcurwp->w_doto;
|
||||
if (doto==llength(dotp) && --doto<0)
|
||||
return (FALSE);
|
||||
cr = lgetc(dotp, doto);
|
||||
if (--doto < 0)
|
||||
return (FALSE);
|
||||
cl = lgetc(dotp, doto);
|
||||
lputc(dotp, doto+0, cr);
|
||||
lputc(dotp, doto+1, cl);
|
||||
lchange(WFEDIT);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Quote the next character, and
|
||||
* insert it into the buffer. All the characters
|
||||
* are taken literally, with the exception of the newline,
|
||||
* which always has its line splitting meaning. The character
|
||||
* is always read, even if it is inserted 0 times, for
|
||||
* regularity. Bound to "M-Q" (for me) and "C-Q" (for Rich,
|
||||
* and only on terminals that don't need XON-XOFF).
|
||||
*/
|
||||
quote(f, n)
|
||||
register int n;
|
||||
{
|
||||
register int s;
|
||||
register int c;
|
||||
|
||||
c = (*term.t_getchar)();
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
if (n == 0)
|
||||
return (TRUE);
|
||||
if (c == '\n') {
|
||||
do {
|
||||
s = lnewline();
|
||||
} while (s==TRUE && --n);
|
||||
return (s);
|
||||
}
|
||||
return (linsert(n, c));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set tab size if given non-default argument (n <> 1). Otherwise, insert a
|
||||
* tab into file. If given argument, n, of zero, change to true tabs.
|
||||
* If n > 1, simulate tab stop every n-characters using spaces.
|
||||
* This has to be done in this slightly funny way because the
|
||||
* tab (in ASCII) has been turned into "C-I" (in 10
|
||||
* bit code) already. Bound to "C-I".
|
||||
*/
|
||||
tab(f, n)
|
||||
register int n;
|
||||
{
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
if (n == 0 || n > 1) {
|
||||
tabsize = n;
|
||||
return(TRUE);
|
||||
}
|
||||
if (! tabsize)
|
||||
return(linsert(1, '\t'));
|
||||
return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
|
||||
}
|
||||
|
||||
/*
|
||||
* Open up some blank space. The basic plan
|
||||
* is to insert a bunch of newlines, and then back
|
||||
* up over them. Everything is done by the subcommand
|
||||
* procerssors. They even handle the looping. Normally
|
||||
* this is bound to "C-O".
|
||||
*/
|
||||
openline(f, n)
|
||||
register int n;
|
||||
{
|
||||
register int i;
|
||||
register int s;
|
||||
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
if (n == 0)
|
||||
return (TRUE);
|
||||
i = n; /* Insert newlines. */
|
||||
do {
|
||||
s = lnewline();
|
||||
} while (s==TRUE && --i);
|
||||
if (s == TRUE) /* Then back up overtop */
|
||||
s = backchar(f, n); /* of them all. */
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a newline. Bound to "C-M".
|
||||
* If you are at the end of the line and the
|
||||
* next line is a blank line, just move into the
|
||||
* blank line. This makes "C-O" and "C-X C-O" work
|
||||
* nicely, and reduces the ammount of screen
|
||||
* update that has to be done. This would not be
|
||||
* as critical if screen update were a lot
|
||||
* more efficient.
|
||||
*/
|
||||
newline(f, n)
|
||||
register int n;
|
||||
{
|
||||
register LINE *lp;
|
||||
register int s;
|
||||
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
while (n--) {
|
||||
lp = curwp->w_dotp;
|
||||
if (llength(lp) == curwp->w_doto
|
||||
&& lp != curbp->b_linep
|
||||
&& llength(lforw(lp)) == 0) {
|
||||
if ((s=forwchar(FALSE, 1)) != TRUE)
|
||||
return (s);
|
||||
} else if ((s=lnewline()) != TRUE)
|
||||
return (s);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete blank lines around dot.
|
||||
* What this command does depends if dot is
|
||||
* sitting on a blank line. If dot is sitting on a
|
||||
* blank line, this command deletes all the blank lines
|
||||
* above and below the current line. If it is sitting
|
||||
* on a non blank line then it deletes all of the
|
||||
* blank lines after the line. Normally this command
|
||||
* is bound to "C-X C-O". Any argument is ignored.
|
||||
*/
|
||||
deblank(f, n)
|
||||
{
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register int nld;
|
||||
register WINDOW *lcurwp;
|
||||
|
||||
lcurwp = curwp;
|
||||
lp1 = lcurwp->w_dotp;
|
||||
while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
|
||||
lp1 = lp2;
|
||||
lp2 = lp1;
|
||||
nld = 0;
|
||||
while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
|
||||
++nld;
|
||||
if (nld == 0)
|
||||
return (TRUE);
|
||||
lcurwp->w_dotp = lforw(lp1);
|
||||
lcurwp->w_doto = 0;
|
||||
return (ldelete(nld));
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a newline, then enough
|
||||
* tabs and spaces to duplicate the indentation
|
||||
* of the previous line. Assumes tabs are every eight
|
||||
* characters. Quite simple. Figure out the indentation
|
||||
* of the current line. Insert a newline by calling
|
||||
* the standard routine. Insert the indentation by
|
||||
* inserting the right number of tabs and spaces.
|
||||
* Return TRUE if all ok. Return FALSE if one
|
||||
* of the subcomands failed. Normally bound
|
||||
* to "C-J".
|
||||
*/
|
||||
indent(f, n)
|
||||
{
|
||||
register int nicol;
|
||||
register int c;
|
||||
register int i;
|
||||
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
while (n--) {
|
||||
nicol = 0;
|
||||
for (i=0; i<llength(curwp->w_dotp); ++i) {
|
||||
c = lgetc(curwp->w_dotp, i);
|
||||
if (c!=' ' && c!='\t')
|
||||
break;
|
||||
if (c == '\t')
|
||||
nicol |= 0x07;
|
||||
++nicol;
|
||||
}
|
||||
if (lnewline() == FALSE
|
||||
|| ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
|
||||
|| ((i=nicol%8)!=0 && linsert(i, ' ')==FALSE))
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete forward. This is real
|
||||
* easy, because the basic delete routine does
|
||||
* all of the work. Watches for negative arguments,
|
||||
* and does the right thing. If any argument is
|
||||
* present, it kills rather than deletes, to prevent
|
||||
* loss of text if typed with a big argument.
|
||||
* Normally bound to "C-D".
|
||||
*/
|
||||
forwdel(f, n)
|
||||
{
|
||||
if (n < 0)
|
||||
return (backdel(f, -n));
|
||||
if (f != FALSE) { /* Really a kill. */
|
||||
if ((lastflag&CFKILL) == 0)
|
||||
kdelete();
|
||||
thisflag |= CFKILL;
|
||||
}
|
||||
return (ldelete(n, f));
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete backwards. This is quite easy too,
|
||||
* because it's all done with other functions. Just
|
||||
* move the cursor back, and delete forwards.
|
||||
* Like delete forward, this actually does a kill
|
||||
* if presented with an argument. Bound to both
|
||||
* "RUBOUT" and "C-H".
|
||||
*/
|
||||
backdel(f, n)
|
||||
{
|
||||
register int s;
|
||||
|
||||
if (n < 0)
|
||||
return (forwdel(f, -n));
|
||||
if (f != FALSE) { /* Really a kill. */
|
||||
if ((lastflag&CFKILL) == 0)
|
||||
kdelete();
|
||||
thisflag |= CFKILL;
|
||||
}
|
||||
if ((s=backchar(f, n)) == TRUE)
|
||||
s = ldelete(n, f);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Kill text. If called without an argument,
|
||||
* it kills from dot to the end of the line, unless it
|
||||
* is at the end of the line, when it kills the newline.
|
||||
* If called with an argument of 0, it kills from the
|
||||
* start of the line to dot. If called with a positive
|
||||
* argument, it kills from dot forward over that number
|
||||
* of newlines. If called with a negative argument it
|
||||
* kills backwards that number of newlines. Normally
|
||||
* bound to "C-K".
|
||||
*/
|
||||
kill(f, n)
|
||||
{
|
||||
register int chunk;
|
||||
register LINE *nextp;
|
||||
|
||||
if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */
|
||||
kdelete(); /* last wasn't a kill. */
|
||||
thisflag |= CFKILL;
|
||||
if (f == FALSE) {
|
||||
chunk = llength(curwp->w_dotp)-curwp->w_doto;
|
||||
if (chunk == 0)
|
||||
chunk = 1;
|
||||
} else if (n == 0) {
|
||||
chunk = curwp->w_doto;
|
||||
curwp->w_doto = 0;
|
||||
} else if (n > 0) {
|
||||
chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
|
||||
nextp = lforw(curwp->w_dotp);
|
||||
while (--n) {
|
||||
if (nextp == curbp->b_linep)
|
||||
return (FALSE);
|
||||
chunk += llength(nextp)+1;
|
||||
nextp = lforw(nextp);
|
||||
}
|
||||
} else {
|
||||
mlwrite("neg kill");
|
||||
return (FALSE);
|
||||
}
|
||||
return (ldelete(chunk, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Yank text back from the kill buffer. This
|
||||
* is really easy. All of the work is done by the
|
||||
* standard insert routines. All you do is run the loop,
|
||||
* and check for errors. Bound to "C-Y". The blank
|
||||
* lines are inserted with a call to "newline"
|
||||
* instead of a call to "lnewline" so that the magic
|
||||
* stuff that happens when you type a carriage
|
||||
* return also happens when a carriage return is
|
||||
* yanked back from the kill buffer.
|
||||
*/
|
||||
yank(f, n)
|
||||
{
|
||||
register int c;
|
||||
register int i;
|
||||
extern int kused;
|
||||
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
while (n--) {
|
||||
i = 0;
|
||||
while ((c=kremove(i)) >= 0) {
|
||||
if (c == '\n') {
|
||||
if (newline(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
} else {
|
||||
if (linsert(1, c) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
#if GEM
|
||||
/*
|
||||
* singlecase the characters in the given buffer. this is used for
|
||||
* buffer and file names on the ST, since everything becomes uppercase
|
||||
* (whether you like it or not) from the desktop and in file names.
|
||||
* this routine assumes ASCII.
|
||||
*/
|
||||
fixname(bp)
|
||||
register unsigned char *bp;
|
||||
{
|
||||
register unsigned c;
|
||||
|
||||
while (c = *bp)
|
||||
#if UPPERNM
|
||||
if (c >= 'a' && c <= 'z')
|
||||
*bp++ = c & ~0x20; /* Lower to upper case */
|
||||
#else
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
*bp++ = c | 0x20; /* Upper to lower case */
|
||||
#endif
|
||||
else
|
||||
++bp;
|
||||
}
|
||||
#endif
|
||||
|
||||
setfold(f,n)
|
||||
{
|
||||
if (f)
|
||||
ffold = n;
|
||||
else
|
||||
ffold = !ffold;
|
||||
if (ffold)
|
||||
mlwrite("[Case fold on search]");
|
||||
else
|
||||
mlwrite("[Match case on search]");
|
||||
return TRUE;
|
||||
}
|
199
Mark Williams MWS v4/SAMPLE/REGION.C
Normal file
199
Mark Williams MWS v4/SAMPLE/REGION.C
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* The routines in this file
|
||||
* deal with the region, that magic space
|
||||
* between "." and mark. Some functions are
|
||||
* commands. Some functions are just for
|
||||
* internal use.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
/*
|
||||
* Kill the region. Ask "getregion"
|
||||
* to figure out the bounds of the region.
|
||||
* Move "." to the start, and kill the characters.
|
||||
* Bound to "C-W".
|
||||
*/
|
||||
killregion(f, n)
|
||||
{
|
||||
register int s;
|
||||
REGION region;
|
||||
|
||||
if ((s=getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
if ((lastflag&CFKILL) == 0) /* This is a kill type */
|
||||
kdelete(); /* command, so do magic */
|
||||
thisflag |= CFKILL; /* kill buffer stuff. */
|
||||
curwp->w_dotp = region.r_linep;
|
||||
curwp->w_doto = region.r_offset;
|
||||
return (ldelete(region.r_size, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy all of the characters in the
|
||||
* region to the kill buffer. Don't move dot
|
||||
* at all. This is a bit like a kill region followed
|
||||
* by a yank. Bound to "M-W".
|
||||
*/
|
||||
copyregion(f, n)
|
||||
{
|
||||
register LINE *linep;
|
||||
register int loffs;
|
||||
register int s;
|
||||
REGION region;
|
||||
|
||||
if ((s=getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
if ((lastflag&CFKILL) == 0) /* Kill type command. */
|
||||
kdelete();
|
||||
thisflag |= CFKILL;
|
||||
linep = region.r_linep; /* Current line. */
|
||||
loffs = region.r_offset; /* Current offset. */
|
||||
while (region.r_size--) {
|
||||
if (loffs == llength(linep)) { /* End of line. */
|
||||
if ((s=kinsert('\n')) != TRUE)
|
||||
return (s);
|
||||
linep = lforw(linep);
|
||||
loffs = 0;
|
||||
} else { /* Middle of line. */
|
||||
if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
|
||||
return (s);
|
||||
++loffs;
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lower case region. Zap all of the upper
|
||||
* case characters in the region to lower case. Use
|
||||
* the region code to set the limits. Scan the buffer,
|
||||
* doing the changes. Call "lchange" to ensure that
|
||||
* redisplay is done in all buffers. Bound to
|
||||
* "C-X C-L".
|
||||
*/
|
||||
lowerregion(f, n)
|
||||
{
|
||||
register LINE *linep;
|
||||
register int loffs;
|
||||
register int c;
|
||||
register int s;
|
||||
REGION region;
|
||||
|
||||
if ((s=getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
lchange(WFHARD);
|
||||
linep = region.r_linep;
|
||||
loffs = region.r_offset;
|
||||
while (region.r_size--) {
|
||||
if (loffs == llength(linep)) {
|
||||
linep = lforw(linep);
|
||||
loffs = 0;
|
||||
} else {
|
||||
c = lgetc(linep, loffs);
|
||||
if (c>='A' && c<='Z')
|
||||
lputc(linep, loffs, c+'a'-'A');
|
||||
++loffs;
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Upper case region. Zap all of the lower
|
||||
* case characters in the region to upper case. Use
|
||||
* the region code to set the limits. Scan the buffer,
|
||||
* doing the changes. Call "lchange" to ensure that
|
||||
* redisplay is done in all buffers. Bound to
|
||||
* "C-X C-L".
|
||||
*/
|
||||
upperregion(f, n)
|
||||
{
|
||||
register LINE *linep;
|
||||
register int loffs;
|
||||
register int c;
|
||||
register int s;
|
||||
REGION region;
|
||||
|
||||
if ((s=getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
lchange(WFHARD);
|
||||
linep = region.r_linep;
|
||||
loffs = region.r_offset;
|
||||
while (region.r_size--) {
|
||||
if (loffs == llength(linep)) {
|
||||
linep = lforw(linep);
|
||||
loffs = 0;
|
||||
} else {
|
||||
c = lgetc(linep, loffs);
|
||||
if (c>='a' && c<='z')
|
||||
lputc(linep, loffs, c-'a'+'A');
|
||||
++loffs;
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine figures out the
|
||||
* bounds of the region in the current window, and
|
||||
* fills in the fields of the "REGION" structure pointed
|
||||
* to by "rp". Because the dot and mark are usually very
|
||||
* close together, we scan outward from dot looking for
|
||||
* mark. This should save time. Return a standard code.
|
||||
* Callers of this routine should be prepared to get
|
||||
* an "ABORT" status; we might make this have the
|
||||
* conform thing later.
|
||||
*/
|
||||
getregion(rp)
|
||||
register REGION *rp;
|
||||
{
|
||||
register LINE *flp;
|
||||
register LINE *blp;
|
||||
register int fsize;
|
||||
register int bsize;
|
||||
|
||||
if (curwp->w_markp == NULL) {
|
||||
mlwrite("No mark set in this window");
|
||||
return (FALSE);
|
||||
}
|
||||
if (curwp->w_dotp == curwp->w_markp) {
|
||||
rp->r_linep = curwp->w_dotp;
|
||||
if (curwp->w_doto < curwp->w_marko) {
|
||||
rp->r_offset = curwp->w_doto;
|
||||
rp->r_size = curwp->w_marko-curwp->w_doto;
|
||||
} else {
|
||||
rp->r_offset = curwp->w_marko;
|
||||
rp->r_size = curwp->w_doto-curwp->w_marko;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
blp = curwp->w_dotp;
|
||||
bsize = curwp->w_doto;
|
||||
flp = curwp->w_dotp;
|
||||
fsize = llength(flp)-curwp->w_doto+1;
|
||||
while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
|
||||
if (flp != curbp->b_linep) {
|
||||
flp = lforw(flp);
|
||||
if (flp == curwp->w_markp) {
|
||||
rp->r_linep = curwp->w_dotp;
|
||||
rp->r_offset = curwp->w_doto;
|
||||
rp->r_size = fsize+curwp->w_marko;
|
||||
return (TRUE);
|
||||
}
|
||||
fsize += llength(flp)+1;
|
||||
}
|
||||
if (lback(blp) != curbp->b_linep) {
|
||||
blp = lback(blp);
|
||||
bsize += llength(blp)+1;
|
||||
if (blp == curwp->w_markp) {
|
||||
rp->r_linep = blp;
|
||||
rp->r_offset = curwp->w_marko;
|
||||
rp->r_size = bsize - curwp->w_marko;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
mlwrite("Bug: lost mark");
|
||||
return (FALSE);
|
||||
}
|
799
Mark Williams MWS v4/SAMPLE/SEARCH.C
Normal file
799
Mark Williams MWS v4/SAMPLE/SEARCH.C
Normal file
@ -0,0 +1,799 @@
|
||||
|
||||
/*
|
||||
* The functions in this file implement the
|
||||
* search commands (both plain and incremental searches
|
||||
* are supported) and the query-replace command.
|
||||
*
|
||||
* The plain old search code is part of the original
|
||||
* MicroEMACS "distribution". The incremental search code,
|
||||
* and the query-replace code, is by Rich Ellison, with
|
||||
* some stylistic modifications.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ed.h"
|
||||
|
||||
/*
|
||||
* Should these macros be fixed up to
|
||||
* correctly handle the upper case and lower case
|
||||
* diacritical vowels in the multinational
|
||||
* character set?
|
||||
*/
|
||||
#define ISUPPER(x) (('A'<=(x) && (x)<='Z'))
|
||||
#define ISLOWER(x) (('a'<=(x) && (x)<='z'))
|
||||
#define TOUPPER(x) ((x)+'A'-'a')
|
||||
#define TOLOWER(x) ((x)-'A'+'a')
|
||||
#define CCHR(x) ((x)-'@')
|
||||
|
||||
#define SRCH_BEGIN (0) /* Search sub-codes. */
|
||||
#define SRCH_FORW (-1)
|
||||
#define SRCH_BACK (-2)
|
||||
#define SRCH_PREV (-3)
|
||||
#define SRCH_NEXT (-4)
|
||||
#define SRCH_NOPR (-5)
|
||||
#define SRCH_ACCM (-6)
|
||||
|
||||
typedef struct {
|
||||
int s_code;
|
||||
LINE *s_dotp;
|
||||
int s_doto;
|
||||
} SRCHCOM;
|
||||
|
||||
extern int ctrlg();
|
||||
|
||||
static SRCHCOM cmds[NSRCH];
|
||||
static int cip;
|
||||
|
||||
int srch_lastdir = SRCH_NOPR; /* Last search flags. */
|
||||
|
||||
/*
|
||||
* Search forward.
|
||||
* Get a search string from the user, and search for it,
|
||||
* starting at ".". If found, "." gets moved to just after the
|
||||
* matched characters, and display does all the hard stuff.
|
||||
* If not found, it just prints a message. This is
|
||||
* normally bound to "M-S".
|
||||
*/
|
||||
forwsearch(f, n)
|
||||
{
|
||||
register int s;
|
||||
|
||||
if ((s=readpattern("Search")) != TRUE)
|
||||
return (s);
|
||||
if (forwsrch() == FALSE) {
|
||||
mlwrite("Not found");
|
||||
return (FALSE);
|
||||
}
|
||||
srch_lastdir = SRCH_FORW;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reverse search.
|
||||
* Get a search string from the user, and search, starting at "."
|
||||
* and proceeding toward the front of the buffer. If found "." is left
|
||||
* pointing at the first character of the pattern [the last character that
|
||||
* was matched]. Bound to "M-R".
|
||||
*/
|
||||
backsearch(f, n)
|
||||
{
|
||||
register int s;
|
||||
|
||||
if ((s=readpattern("Reverse search")) != TRUE)
|
||||
return (s);
|
||||
if (backsrch() == FALSE) {
|
||||
mlwrite("Not found");
|
||||
return (FALSE);
|
||||
}
|
||||
srch_lastdir = SRCH_BACK;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search again, using the same search string
|
||||
* and direction as the last search command. The direction
|
||||
* has been saved in "srch_lastdir", so you know which way
|
||||
* to go. This is only bound to the "find" key on the
|
||||
* LK201; it should have a normal binding.
|
||||
*/
|
||||
searchagain(f, n)
|
||||
{
|
||||
if (srch_lastdir == SRCH_FORW) {
|
||||
if (forwsrch() == FALSE) {
|
||||
mlwrite("Not found");
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
if (srch_lastdir == SRCH_BACK) {
|
||||
if (backsrch() == FALSE) {
|
||||
mlwrite("Not found");
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
mlwrite("No last search");
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use incremental searching, initially in the forward direction.
|
||||
* isearch ignores any explicit arguments.
|
||||
*/
|
||||
forwisearch(f, n)
|
||||
{
|
||||
return (isearch(SRCH_FORW));
|
||||
}
|
||||
|
||||
/*
|
||||
* Use incremental searching, initially in the reverse direction.
|
||||
* isearch ignores any explicit arguments.
|
||||
*/
|
||||
backisearch(f, n)
|
||||
{
|
||||
return (isearch(SRCH_BACK));
|
||||
}
|
||||
|
||||
/*
|
||||
* Incremental Search.
|
||||
* dir is used as the initial direction to search.
|
||||
* ^N find next occurance (if first thing typed reuse old string).
|
||||
* ^P find prev occurance (if first thing typed reuse old string).
|
||||
* ^S switch direction to forward, find next
|
||||
* ^R switch direction to reverse, find prev
|
||||
* ^Q quote next character (allows searching for ^N etc.)
|
||||
* <ESC> exit from Isearch.
|
||||
* <DEL>
|
||||
* ^H undoes last character typed. (tricky job to do this correctly).
|
||||
* else accumulate into search string
|
||||
*/
|
||||
isearch(dir)
|
||||
{
|
||||
int c;
|
||||
int pptr;
|
||||
LINE *clp;
|
||||
int cbo;
|
||||
int success;
|
||||
|
||||
for (cip=0; cip<NSRCH; cip++)
|
||||
cmds[cip].s_code = SRCH_NOPR;
|
||||
cip = 0;
|
||||
pptr = -1;
|
||||
clp = curwp->w_dotp;
|
||||
cbo = curwp->w_doto;
|
||||
isrch_lpush();
|
||||
isrch_cpush(SRCH_BEGIN);
|
||||
success = TRUE;
|
||||
isrch_prompt(dir,TRUE,success);
|
||||
for (;;) {
|
||||
update();
|
||||
switch (c = ttgetc()) {
|
||||
|
||||
case CCHR('M'):
|
||||
case METACH:
|
||||
#if LK201
|
||||
case AGRAVE:
|
||||
#endif
|
||||
srch_lastdir = dir;
|
||||
mlwrite("[Done]");
|
||||
return (TRUE);
|
||||
|
||||
case CCHR('G'):
|
||||
curwp->w_dotp = clp;
|
||||
curwp->w_doto = cbo;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
srch_lastdir = dir;
|
||||
mlwrite("Aborting");
|
||||
return (FALSE);
|
||||
|
||||
case CCHR('S'):
|
||||
case CCHR('F'):
|
||||
if (dir == SRCH_BACK) {
|
||||
dir = SRCH_FORW;
|
||||
isrch_lpush();
|
||||
isrch_cpush(SRCH_FORW);
|
||||
success = TRUE;
|
||||
}
|
||||
/* drop through to find next */
|
||||
|
||||
case CCHR('N'):
|
||||
if ((success == FALSE)&&(dir == SRCH_FORW))
|
||||
break;
|
||||
isrch_lpush();
|
||||
forwchar(FALSE, 1);
|
||||
if (isrch_find(SRCH_NEXT) != FALSE) {
|
||||
isrch_cpush(SRCH_NEXT);
|
||||
pptr = strlen(pat);
|
||||
} else {
|
||||
backchar(FALSE, 1);
|
||||
(*term.t_beep)();
|
||||
success = FALSE;
|
||||
}
|
||||
isrch_prompt(dir,FALSE,success);
|
||||
break;
|
||||
|
||||
case CCHR('R'):
|
||||
case CCHR('B'):
|
||||
if (dir == SRCH_FORW) {
|
||||
dir = SRCH_BACK;
|
||||
isrch_lpush();
|
||||
isrch_cpush(SRCH_BACK);
|
||||
success = TRUE;
|
||||
}
|
||||
/* drop through to find prev */
|
||||
|
||||
case CCHR('P'):
|
||||
if ((success == FALSE)&&(dir == SRCH_BACK))
|
||||
break;
|
||||
isrch_lpush();
|
||||
backchar(FALSE, 1);
|
||||
if (isrch_find(SRCH_PREV) != FALSE) {
|
||||
isrch_cpush(SRCH_PREV);
|
||||
pptr = strlen(pat);
|
||||
} else {
|
||||
forwchar(FALSE, 1);
|
||||
(*term.t_beep)();
|
||||
success = FALSE;
|
||||
}
|
||||
isrch_prompt(dir,FALSE,success);
|
||||
break;
|
||||
|
||||
case CCHR('H'):
|
||||
case 0x7F:
|
||||
if (isrch_undo(&pptr,&dir) != TRUE) {
|
||||
return (ABORT);
|
||||
}
|
||||
if (isrch_peek() != SRCH_ACCM)
|
||||
success = TRUE;
|
||||
isrch_prompt(dir,FALSE,success);
|
||||
break;
|
||||
|
||||
case CCHR('^'):
|
||||
case CCHR('Q'):
|
||||
c = ttgetc();
|
||||
case CCHR('U'):
|
||||
case CCHR('X'):
|
||||
case CCHR('I'):
|
||||
case CCHR('J'):
|
||||
goto addchar;
|
||||
default:
|
||||
if (c < ' ') { /* uninterpreted ctrl */
|
||||
c += '@';
|
||||
c |= CTRL;
|
||||
success = execute(c, FALSE, 1);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (success);
|
||||
}
|
||||
addchar:
|
||||
if (pptr == -1)
|
||||
pptr=0;
|
||||
if (pptr == 0)
|
||||
success = TRUE;
|
||||
pat[pptr++] = c;
|
||||
if (pptr==NPAT) {
|
||||
mlwrite("Pattern too long");
|
||||
ctrlg(FALSE, 0);
|
||||
return (ABORT);
|
||||
}
|
||||
pat[pptr] = '\0';
|
||||
isrch_lpush();
|
||||
if (success != FALSE) {
|
||||
if (isrch_find(dir) != FALSE) {
|
||||
isrch_cpush(c);
|
||||
} else {
|
||||
success = FALSE;
|
||||
(*term.t_beep)();
|
||||
isrch_cpush(SRCH_ACCM);
|
||||
}
|
||||
} else {
|
||||
isrch_cpush(SRCH_ACCM);
|
||||
}
|
||||
isrch_prompt(dir, FALSE, success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isrch_cpush(cmd)
|
||||
register int cmd;
|
||||
{
|
||||
if (++cip >= NSRCH)
|
||||
cip = 0;
|
||||
cmds[cip].s_code = cmd;
|
||||
}
|
||||
|
||||
isrch_lpush()
|
||||
{
|
||||
register int ctp;
|
||||
|
||||
ctp = cip+1;
|
||||
if (ctp >= NSRCH)
|
||||
ctp = 0;
|
||||
cmds[ctp].s_code = SRCH_NOPR;
|
||||
cmds[ctp].s_doto = curwp->w_doto;
|
||||
cmds[ctp].s_dotp = curwp->w_dotp;
|
||||
}
|
||||
|
||||
isrch_pop()
|
||||
{
|
||||
if (cmds[cip].s_code != SRCH_NOPR) {
|
||||
curwp->w_doto = cmds[cip].s_doto;
|
||||
curwp->w_dotp = cmds[cip].s_dotp;
|
||||
curwp->w_flag |= WFMOVE; /* Was "=", wrong. */
|
||||
cmds[cip].s_code = SRCH_NOPR;
|
||||
}
|
||||
if (--cip <= 0) /* Is "=" right? */
|
||||
cip = NSRCH-1;
|
||||
}
|
||||
|
||||
int
|
||||
isrch_peek()
|
||||
{
|
||||
if (cip == 0)
|
||||
return (cmds[NSRCH-1].s_code);
|
||||
else
|
||||
return (cmds[cip-1].s_code);
|
||||
}
|
||||
|
||||
int
|
||||
isrch_undo(pptr,dir)
|
||||
register int *pptr;
|
||||
register int *dir;
|
||||
{
|
||||
switch (cmds[cip].s_code) {
|
||||
case SRCH_NOPR:
|
||||
case SRCH_BEGIN:
|
||||
case SRCH_NEXT:
|
||||
case SRCH_PREV:
|
||||
break;
|
||||
|
||||
case SRCH_FORW:
|
||||
if (*dir == SRCH_BACK) {
|
||||
mlwrite("ISEARCH error, to back when already back");
|
||||
return (FALSE);
|
||||
}
|
||||
*dir = SRCH_BACK;
|
||||
break;
|
||||
|
||||
case SRCH_BACK:
|
||||
if (*dir == SRCH_FORW) {
|
||||
mlwrite("ISEARCH error, to forw when already forw");
|
||||
return (FALSE);
|
||||
}
|
||||
*dir = SRCH_FORW;
|
||||
break;
|
||||
|
||||
case SRCH_ACCM:
|
||||
default:
|
||||
if (*pptr == 0) {
|
||||
mlwrite("ISEARCH error, delete without character");
|
||||
return (FALSE);
|
||||
}
|
||||
*pptr -= 1;
|
||||
if (*pptr < 0)
|
||||
*pptr = 0;
|
||||
pat[*pptr] = '\0';
|
||||
break;
|
||||
}
|
||||
isrch_pop();
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
isrch_find(dir)
|
||||
register int dir;
|
||||
{
|
||||
register int plen;
|
||||
|
||||
plen = strlen(pat);
|
||||
if (plen != 0) {
|
||||
if (dir==SRCH_FORW || dir==SRCH_NEXT) {
|
||||
backchar(FALSE, plen);
|
||||
if (forwsrch() == FALSE) {
|
||||
forwchar(FALSE, plen);
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
if (dir==SRCH_BACK || dir==SRCH_PREV) {
|
||||
forwchar(FALSE, plen);
|
||||
if (backsrch() == FALSE) {
|
||||
backchar(FALSE, plen);
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
mlwrite("bad call to isrch_find");
|
||||
ctrlg(FALSE, 0);
|
||||
return (FALSE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If called with "dir" not one of SRCH_FORW
|
||||
* or SRCH_BACK, this routine used to print an error
|
||||
* message. It also used to return TRUE or FALSE,
|
||||
* depending on if it liked the "dir". However, none
|
||||
* of the callers looked at the status, so I just
|
||||
* made the checking vanish.
|
||||
*/
|
||||
isrch_prompt(dir, flag, success)
|
||||
{
|
||||
if (dir == SRCH_FORW) {
|
||||
if (success != FALSE)
|
||||
isrch_dspl("i-search forward", flag);
|
||||
else
|
||||
isrch_dspl("failing i-search forward", flag);
|
||||
} else if (dir == SRCH_BACK) {
|
||||
if (success != FALSE)
|
||||
isrch_dspl("i-search backward", flag);
|
||||
else
|
||||
isrch_dspl("failing i-search backward", flag);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prompt writing routine for the incremental
|
||||
* search. The "prompt" is just a string. The "flag" determines
|
||||
* if a "[ ]" or ":" embelishment is used. The string is packed
|
||||
* into a big buffer and zapped out with a single call to
|
||||
* "mlwrite". The "26" in the "tpat" declaration is the length
|
||||
* of the longest prompt string. This actually isn't long
|
||||
* enough if the pattern is full of control characters
|
||||
* and other things that need an "^".
|
||||
*/
|
||||
isrch_dspl(prompt, flag)
|
||||
char *prompt;
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register int c;
|
||||
char tpat[NPAT+26+2+1+1];
|
||||
|
||||
cp1 = &tpat[0];
|
||||
cp2 = prompt;
|
||||
while ((c = *cp2++) != '\0')
|
||||
*cp1++ = c;
|
||||
if (flag != FALSE) {
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = '[';
|
||||
} else {
|
||||
*cp1++ = ':';
|
||||
*cp1++ = ' ';
|
||||
}
|
||||
cp2 = &pat[0];
|
||||
while ((c = *cp2++) != 0) {
|
||||
if (cp1 < &tpat[NPAT+20-4]) { /* "??]\0" */
|
||||
if (c<0x20 || c==0x7F) {
|
||||
*cp1++ = '^';
|
||||
c ^= 0x40;
|
||||
} else if (c == '%') /* Map "%" to */
|
||||
*cp1++ = c; /* "%%". */
|
||||
*cp1++ = c;
|
||||
}
|
||||
}
|
||||
if (flag != FALSE)
|
||||
*cp1++ = ']';
|
||||
*cp1= '\0';
|
||||
mlwrite(tpat);
|
||||
}
|
||||
|
||||
/*
|
||||
* Query Replace.
|
||||
* Replace strings selectively. Does a search and replace operation.
|
||||
* A space or a comma replaces the string, a period replaces and quits,
|
||||
* an n doesn't replace, a C-G quits.
|
||||
*/
|
||||
queryrepl(f, n)
|
||||
{
|
||||
register int s;
|
||||
char news[NPAT];
|
||||
LINE *clp;
|
||||
int cbo;
|
||||
register int flg;
|
||||
register int flgc;
|
||||
int rcnt;
|
||||
|
||||
if ((s=readpattern("Old string")) != TRUE)
|
||||
return (s);
|
||||
if ((s=mlreply("New string: ",news, NPAT)) == ABORT)
|
||||
return (s);
|
||||
if (s == FALSE) /* Null string. */
|
||||
news[0] = '\0';
|
||||
mlwrite("Query Replace: [%s] -> [%s]", pat, news);
|
||||
clp = curwp->w_dotp;
|
||||
cbo = curwp->w_doto;
|
||||
rcnt = 0;
|
||||
flg = TRUE;
|
||||
flgc = FALSE;
|
||||
while (flg==TRUE && forwsrch()==TRUE) {
|
||||
if (flgc != TRUE) {
|
||||
retry:
|
||||
update();
|
||||
switch (ttgetc()) {
|
||||
case ' ':
|
||||
case ',':
|
||||
replstring(news, f);
|
||||
rcnt++;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
replstring(news, f);
|
||||
rcnt++;
|
||||
flg = FALSE;
|
||||
break;
|
||||
|
||||
case '\007':
|
||||
flg = ABORT;
|
||||
ctrlg(FALSE, 0);
|
||||
break;
|
||||
|
||||
case '!':
|
||||
replstring(news, f);
|
||||
rcnt++;
|
||||
flgc = TRUE;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
break;
|
||||
|
||||
default:
|
||||
mlwrite("<SP>[,] replace, [.] rep-end, [n] dont, [!] repl rest <C-G> quit");
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
replstring(news, f);
|
||||
rcnt++;
|
||||
}
|
||||
}
|
||||
curwp->w_dotp = clp;
|
||||
curwp->w_doto = cbo;
|
||||
curwp->w_flag = WFHARD;
|
||||
update();
|
||||
if (rcnt == 0)
|
||||
mlwrite("[No replacements done]");
|
||||
else if (rcnt == 1)
|
||||
mlwrite("[1 replacement done]");
|
||||
else
|
||||
mlwrite("[%d replacements done]", rcnt);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
#define FLOWER 0 /* Found lower case. */
|
||||
#define FCAPTL 1 /* Found capital. */
|
||||
#define FUPPER 2 /* Found upper case. */
|
||||
|
||||
replstring(st, f)
|
||||
char st[];
|
||||
int f;
|
||||
{
|
||||
register char *tpt;
|
||||
register int plen;
|
||||
register int rtype;
|
||||
register int c;
|
||||
|
||||
plen = strlen(pat);
|
||||
backchar(TRUE, plen);
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto);
|
||||
rtype = FLOWER;
|
||||
if (ISUPPER(c) != FALSE) {
|
||||
rtype = FCAPTL;
|
||||
if (curwp->w_doto+1 != llength(curwp->w_dotp)) {
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto+1);
|
||||
if (ISUPPER(c) != FALSE)
|
||||
rtype = FUPPER;
|
||||
}
|
||||
}
|
||||
ldelete(plen, FALSE);
|
||||
tpt = &st[0];
|
||||
if (f != FALSE) {
|
||||
while (*tpt != '\0')
|
||||
linsert(1, *tpt++);
|
||||
} else {
|
||||
switch (rtype) {
|
||||
case FLOWER:
|
||||
while (*tpt != '\0') {
|
||||
linsert(1, *tpt++);
|
||||
}
|
||||
break;
|
||||
|
||||
case FCAPTL:
|
||||
if (*tpt != '\0') {
|
||||
if (ISLOWER(*tpt) != FALSE)
|
||||
linsert(1, TOUPPER(*tpt++));
|
||||
else
|
||||
linsert(1, *tpt++);
|
||||
}
|
||||
while (*tpt != '\0')
|
||||
linsert(1, *tpt++);
|
||||
break;
|
||||
|
||||
case FUPPER:
|
||||
while (*tpt != '\0') {
|
||||
if (ISLOWER(*tpt) != FALSE)
|
||||
linsert(1, TOUPPER(*tpt++));
|
||||
else
|
||||
linsert(1, *tpt++);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
curwp->w_flag |= WFHARD;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine does the real work of a
|
||||
* forward search. The pattern is sitting in the external
|
||||
* variable "pat". If found, dot is updated, the window system
|
||||
* is notified of the change, and TRUE is returned. If the
|
||||
* string isn't found, FALSE is returned.
|
||||
*/
|
||||
forwsrch()
|
||||
{
|
||||
register LINE *clp;
|
||||
register int cbo;
|
||||
register LINE *tlp;
|
||||
register int tbo;
|
||||
register char *pp;
|
||||
register int c;
|
||||
|
||||
clp = curwp->w_dotp;
|
||||
cbo = curwp->w_doto;
|
||||
while (clp != curbp->b_linep) {
|
||||
if (cbo == llength(clp)) {
|
||||
clp = lforw(clp);
|
||||
cbo = 0;
|
||||
c = '\n';
|
||||
} else
|
||||
c = lgetc(clp, cbo++);
|
||||
if (eq(c, pat[0]) != FALSE) {
|
||||
tlp = clp;
|
||||
tbo = cbo;
|
||||
pp = &pat[1];
|
||||
while (*pp != 0) {
|
||||
if (tlp == curbp->b_linep)
|
||||
goto fail;
|
||||
if (tbo == llength(tlp)) {
|
||||
tlp = lforw(tlp);
|
||||
tbo = 0;
|
||||
c = '\n';
|
||||
} else
|
||||
c = lgetc(tlp, tbo++);
|
||||
if (eq(c, *pp++) == FALSE)
|
||||
goto fail;
|
||||
}
|
||||
curwp->w_dotp = tlp;
|
||||
curwp->w_doto = tbo;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
fail: ;
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine does the real work of a
|
||||
* backward search. The pattern is sitting in the external
|
||||
* variable "pat". If found, dot is updated, the window system
|
||||
* is notified of the change, and TRUE is returned. If the
|
||||
* string isn't found, FALSE is returned.
|
||||
*/
|
||||
backsrch()
|
||||
{
|
||||
register LINE *clp;
|
||||
register int cbo;
|
||||
register LINE *tlp;
|
||||
register int tbo;
|
||||
register int c;
|
||||
register char *epp;
|
||||
register char *pp;
|
||||
|
||||
for (epp = &pat[0]; epp[1] != 0; ++epp)
|
||||
;
|
||||
clp = curwp->w_dotp;
|
||||
cbo = curwp->w_doto;
|
||||
for (;;) {
|
||||
if (cbo == 0) {
|
||||
clp = lback(clp);
|
||||
if (clp == curbp->b_linep)
|
||||
return (FALSE);
|
||||
cbo = llength(clp)+1;
|
||||
}
|
||||
if (--(cbo) == llength(clp))
|
||||
c = '\n';
|
||||
else
|
||||
c = lgetc(clp,cbo);
|
||||
if (eq(c, *epp) != FALSE) {
|
||||
tlp = clp;
|
||||
tbo = cbo;
|
||||
pp = epp;
|
||||
while (pp != &pat[0]) {
|
||||
if (tbo == 0) {
|
||||
tlp = lback(tlp);
|
||||
if (tlp == curbp->b_linep)
|
||||
goto fail;
|
||||
tbo = llength(tlp)+1;
|
||||
}
|
||||
if (--(tbo) == llength(tlp))
|
||||
c = '\n';
|
||||
else
|
||||
c = lgetc(tlp,tbo);
|
||||
if (eq(c, *--pp) == FALSE)
|
||||
goto fail;
|
||||
}
|
||||
curwp->w_dotp = tlp;
|
||||
curwp->w_doto = tbo;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
fail: ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two characters.
|
||||
* The "bc" comes from the buffer.
|
||||
* It has it's case folded out. The
|
||||
* "pc" is from the pattern.
|
||||
*/
|
||||
eq(bc, pc)
|
||||
register int bc;
|
||||
register int pc;
|
||||
{
|
||||
if (ffold){
|
||||
if (bc>='a' && bc<='z')
|
||||
bc -= 0x20;
|
||||
if (pc>='a' && pc<='z')
|
||||
pc -= 0x20;
|
||||
}
|
||||
if (bc == pc)
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a pattern.
|
||||
* Stash it in the external variable "pat". The "pat" is
|
||||
* not updated if the user types in an empty line. If the user typed
|
||||
* an empty line, and there is no old pattern, it is an error.
|
||||
* Display the old pattern, in the style of Jeff Lomicka. There is
|
||||
* some do-it-yourself control expansion.
|
||||
*/
|
||||
readpattern(prompt)
|
||||
char *prompt;
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register int c;
|
||||
register int s;
|
||||
char tpat[NPAT+20];
|
||||
|
||||
cp1 = &tpat[0]; /* Copy prompt */
|
||||
cp2 = prompt;
|
||||
while ((c = *cp2++) != '\0')
|
||||
*cp1++ = c;
|
||||
if (pat[0] != '\0') { /* Old pattern */
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = '[';
|
||||
cp2 = &pat[0];
|
||||
while ((c = *cp2++) != 0) {
|
||||
if (cp1 < &tpat[NPAT+20-6]) { /* "??]: \0" */
|
||||
if (c<0x20 || c==0x7F) {
|
||||
*cp1++ = '^';
|
||||
c ^= 0x40;
|
||||
} else if (c == '%') /* Map "%" to */
|
||||
*cp1++ = c; /* "%%". */
|
||||
*cp1++ = c;
|
||||
}
|
||||
}
|
||||
*cp1++ = ']';
|
||||
}
|
||||
*cp1++ = ':'; /* Finish prompt */
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = '\0';
|
||||
s = mlreply(tpat, tpat, NPAT); /* Read pattern */
|
||||
if (s == TRUE) /* Specified */
|
||||
strcpy(pat, tpat);
|
||||
else if (s==FALSE && pat[0]!=0) /* CR, but old one */
|
||||
s = TRUE;
|
||||
return (s);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user