home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Devil's Doorknob BBS Capture (1996-2003)
/
devilsdoorknobbbscapture1996-2003.iso
/
WWIV2.ZIP
/
COM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-31
|
24KB
|
1,172 lines
#include "vars.h"
#pragma hdrstop
#include <stdarg.h>
#include <math.h>
#define frequency 500
int check_comport(int pn)
{
unsigned char new_iir, old_iir;
old_iir = inportb(syscfg.com_base[pn]+2);
outportb(syscfg.com_base[pn]+2,0x81);
new_iir = inportb(syscfg.com_base[pn]+2);
outportb(syscfg.com_base[pn]+2,old_iir);
if (new_iir & 0x38) {
/* no com port */
return(0);
}
if (new_iir==0) {
/* unbuffered */
return(1);
}
outportb(syscfg.com_base[pn]+2,0xc1);
new_iir = inportb(syscfg.com_base[pn]+2);
outportb(syscfg.com_base[pn]+2,old_iir);
switch ((new_iir >> 6) & 0x03) {
case 0: /* no 16550 */
case 1: /* huh? */
return(1);
case 2: /* 16550 */
case 3: /* 16550A */
return(2);
}
return(1);
}
void savel(char *cl, char *atr, char *xl, char *cc)
{
int i, i1;
*cc = curatr;
strcpy(xl, endofline);
i = ((wherey() + topline) * 80) * 2;
for (i1 = 0; i1 < wherex(); i1++) {
cl[i1] = scrn[i + (i1 * 2)];
atr[i1] = scrn[i + (i1 * 2) + 1];
}
cl[wherex()] = 0;
atr[wherex()] = 0;
}
void restorel(char *cl, char *atr, char *xl, char *cc)
{
int i;
if (wherex())
nl();
for (i = 0; cl[i] != 0; i++) {
setc(atr[i]);
outchr(cl[i]);
}
setc(*cc);
strcpy(endofline, xl);
}
void ptime(void)
{
char xl[81], cl[81], atr[81], cc, s[81];
long l;
savel(cl, atr, xl, &cc);
ansic(0);
nl();
nl();
time(&l);
strcpy(s, ctime(&l));
s[strlen(s) - 1] = 0;
pl(s);
if (useron) {
outstr(get_string(29)); npr("%s\r\n", ctim(timer() - timeon));
outstr(get_string(921)); npr("%s\r\n", ctim(nsl()));
}
nl();
restorel(cl, atr, xl, &cc);
}
void reprint(void)
{
char xl[81], cl[81], atr[81], cc, ansistr_1[81];
int ansiptr_1;
ansiptr_1=ansiptr;
ansiptr=0;
ansistr[ansiptr_1]=0;
strcpy(ansistr_1,ansistr);
savel(cl, atr, xl, &cc);
nl();
restorel(cl, atr, xl, &cc);
strcpy(ansistr,ansistr_1);
ansiptr=ansiptr_1;
}
void print_help(int n)
{
char xl[81], cl[81], atr[81], cc, s[81];
int next;
savel(cl, atr, xl, &cc);
ansic(0);
outstr("\f");
sprintf(s,"%sHELP.MSG",languagedir);
next = 0;
if (helps[n].stored_as)
read_message1(&helps[n], 0, 0, &next, s);
restorel(cl, atr, xl, &cc);
}
void setbeep(int i)
{
int i1,i2;
if (i) {
i1 = 0x34DD / frequency;
i2 = inportb(0x61);
if (!(i2 & 0x03)) {
outportb(0x61, i2 | 0x03);
outportb(0x43, 0xB6);
}
outportb(0x42, i1 & 0x0F);
outportb(0x42, i1 >> 4);
} else
outportb(0x61, inportb(0x61) & 0xFC);
}
void far interrupt async_isr(void)
/* This function is called every time a char is received on the com port.
* The character is stored in the buffer[] array, and the head pointer is
* updated.
*/
{
buffer[head++] = inportb(base);
if (head == max_buf)
head = 0;
outportb(0x20, 0x20);
}
void outcomch(char ch)
/* This function outputs one character to the com port */
{
while (!(inportb(base + 5) & 0x20))
;
if (flow_control)
while (!(inportb(base + 6) & 0x10))
;
outportb(base, ch);
}
char peek1c(void)
{
if (head!=tail) {
return(buffer[tail]);
} else
return(0);
}
char get1c(void)
/* This function returns one character from the com port, or a zero if
* no character is waiting
*/
{
char c1;
if (head != tail) {
disable();
c1 = buffer[tail++];
if (tail == max_buf)
tail = 0;
enable();
return(c1);
} else
return(0);
}
int comhit(void)
/* This returns a value telling if there is a character waiting in the com
* buffer.
*/
{
return(head != tail);
}
void dump(void)
/* This function clears the com buffer */
{
disable();
head = tail = 0;
enable();
}
void set_baud(unsigned int rate)
/* This function sets the com speed to that passed */
{
float rl;
if ((rate > 49) && (rate < 57601)) {
rl = 115200.0 / ((float) rate);
rate = (int) rl;
outportb(base + 3, inportb(base + 3) | 0x80);
outportb(base, (rate & 0x00FF));
outportb(base + 1, ((rate >> 8) & 0x00FF));
outportb(base + 3, inportb(base + 3) & 0x7F);
}
}
void initport(int port_num)
/* This function initializes the com buffer, setting up the interrupt,
* and com parameters
*/
{
int temp;
base = syscfg.com_base[port_num];
async_irq = syscfg.com_ISR[port_num];
setvect(8 + async_irq, async_isr);
head = tail = 0;
outportb(base + 3, 0x03);
disable();
temp = inportb(base + 5);
temp = inportb(base);
temp = inportb(0x21);
temp = temp & ((1 << async_irq) ^ 0x00FF);
outportb(0x21, temp);
outportb(base + 1, 0x01);
temp=inportb(base + 4);
outportb(base + 4, temp | 0x0A);
outportb(base+2,0xc0);
enable();
dtr(1);
}
void closeport(void)
/* This function closes out the com port, removing the interrupt routine,
* etc.
*/
{
int temp;
if (base) {
disable();
temp = inportb(0x21);
temp = temp | ((1 << async_irq));
outportb(0x21, temp);
outportb(base + 2, 0);
outportb(base + 4, 3);
setvect(async_irq+8,getvect(8)); /* for desqview */
enable();
base=0;
}
}
void dtr(int i)
/* This function sets the DTR pin to the status given */
{
int i1;
i1 = inportb(base + 4) & 0x00FE;
outportb(base + 4, (i || no_hangup) ? (i1 + 1) : i1);
}
void rts(int i)
/* This function sets the RTS pin to the status given */
{
int i1;
i1 = inportb(base + 4) & 0x00FD;
outportb(base + 4, (i) ? (i1 + 2) : i1);
}
int cdet(void)
/* This returns the status of the carrier detect lead from the modem */
{
return((inportb(base + 6) & 0x80) ? 1 : 0);
}
void checkhangup(void)
/* This function checks to see if the user logged on to the com port has
* hung up. Obviously, if no user is logged on remotely, this does nothing.
* If carrier detect is detected to be low, it is checked 100 times
* sequentially to make sure it stays down, and is not just a quirk.
*/
{
int i, ok;
if (!hangup && using_modem && !cdet()) {
ok = 0;
for (i = 0; (i < 500) && !ok; i++)
if (cdet())
ok = 1;
if (!ok) {
hangup = hungup = 1;
if (useron && !in_extern)
{
++thisuser.ass_pts;
sysoplog(get_stringx(1,99));
}
}
}
}
void addto(char *s, int i)
{
char temp[20];
if (s[0])
strcat(s, ";");
else
strcpy(s, "\x1b[");
itoa(i, temp, 10);
strcat(s, temp);
}
void makeansi(unsigned char attr, char *s, int forceit)
/* Passed to this function is a one-byte attribute as defined for IBM type
* screens. Returned is a string which, when printed, will change the
* display to the color desired, from the current function.
*/
{
unsigned char catr;
char *temp = "04261537";
catr = curatr;
s[0] = 0;
if (attr != catr) {
if ((catr & 0x88) ^ (attr & 0x88)) {
addto(s, 0);
addto(s, 30 + temp[attr & 0x07] - '0');
addto(s, 40 + temp[(attr & 0x70) >> 4] - '0');
catr = attr & 0x77;
}
if ((catr & 0x07) != (attr & 0x07))
addto(s, 30 + temp[attr & 0x07] - '0');
if ((catr & 0x70) != (attr & 0x70))
addto(s, 40 + temp[(attr & 0x70) >> 4] - '0');
if ((catr & 0x08) ^ (attr & 0x08))
addto(s, 1);
if ((catr & 0x80) ^ (attr & 0x80)) {
if (checkcomp("Mac")) /*This is the code for Mac's underline*/
addto(s, 4); /*They don't have Blinking or Italics*/
else {
if (checkcomp("Ami")) /*Some Amiga terminals use 3 instead of*/
addto(s, 3); /*5 for italics. Using both won't hurt*/
addto(s, 5); /*anything, only italics will be generated*/
}
}
}
if (s[0])
strcat(s, "m");
if (!okansi() && !forceit)
s[0]=0;
}
void setfgc(int i)
/* This sets the foreground color to that passed. It is called only from
* execute_ansi
*/
{
curatr = (curatr & 0xf8) | i;
}
void setbgc(int i)
/* This sets the background color to that passed. It is called only from
* execute_ansi
*/
{
curatr = (curatr & 0x8f) | (i << 4);
}
void execute_ansi(void)
/* This function executes an ANSI string to change color, position the
* cursor, etc.
*/
{
int args[11], argptr, count, ptr, tempptr, ox, oy;
char cmd, temp[11], teol[81], *clrlst = "04261537";
if (ansistr[1] != '[') {
/* do nothing if invalid ANSI string. */
} else {
argptr = tempptr = 0;
ptr = 2;
for (count = 0; count < 10; count++)
args[count] = temp[count] = 0;
cmd = ansistr[ansiptr - 1];
ansistr[ansiptr - 1] = 0;
while ((ansistr[ptr]) && (argptr<10) && (tempptr<10)) {
if (ansistr[ptr] == ';') {
temp[tempptr] = 0;
tempptr = 0;
args[argptr++] = atoi(temp);
} else
temp[tempptr++] = ansistr[ptr];
++ptr;
}
if (tempptr && (argptr<10)) {
temp[tempptr] = 0;
args[argptr++] = atoi(temp);
}
if ((cmd >= 'A') && (cmd <= 'D') && !args[0])
args[0] = 1;
switch (cmd) {
case 'f':
case 'H':
movecsr(args[1] - 1, args[0] - 1);
break;
case 'A':
movecsr(wherex(), wherey() - args[0]);
break;
case 'B':
movecsr(wherex(), wherey() + args[0]);
break;
case 'C':
movecsr(wherex() + args[0], wherey());
break;
case 'D':
movecsr(wherex() - args[0], wherey());
break;
case 's':
oldx = wherex();
oldy = wherey();
break;
case 'u':
movecsr(oldx, oldy);
break;
case 'J':
if (args[0] == 2) {
if (x_only)
movecsr(0,0);
else
clrscrb();
}
break;
case 'k':
case 'K':
if (!x_only) {
ox = wherex();
oy = wherey();
_CX = 80 - ox;
_AH = 0x09;
_BH = 0x00;
_AL = 32;
_BL = curatr;
my_video_int();
movecsr(ox, oy);
}
break;
case 'm':
if (!argptr) {
argptr = 1;
args[0] = 0;
}
for (count = 0; count < argptr; count++)
switch (args[count]) {
case 0: curatr = 0x07; break;
case 1: curatr = curatr | 0x08; break;
case 4: break;
case 5: curatr = curatr | 0x80; break;
case 7:
ptr = curatr & 0x77;
curatr = (curatr & 0x88) | (ptr << 4) | (ptr >> 4);
break;
case 8: curatr = 0; break;
default:
if ((args[count] >= 30) && (args[count] <= 37))
setfgc(clrlst[args[count] - 30] - '0');
else if ((args[count] >= 40) && (args[count] <= 47))
setbgc(clrlst[args[count] - 40] - '0');
}
break;
}
}
ansiptr = 0;
}
void outchr(char c)
/* This function outputs one character to the screen, and if output to the
* com port is enabled, the character is output there too. ANSI graphics
* are also trapped here, and the ansi function is called to execute the
* ANSI codes
*/
{
int i, i1;
if (change_color) {
change_color = 0;
if ((c >= '0') && (c <= '7'))
ansic(c - '0');
return;
}
if (c == 3) {
change_color = 1;
return;
}
if ((c == 10) && endofline[0]) {
if (!in_extern)
outstr(endofline);
endofline[0] = 0;
}
if (global_handle) {
if (echo)
global_char(c);
}
if (chatcall && !x_only && !(syscfg.sysconfig & sysconfig_no_beep))
setbeep(1);
if (outcom && !x_only && (c != 9))
outcomch(echo ? c : 'X');
if (ansiptr) {
ansistr[ansiptr++] = c;
ansistr[ansiptr] = 0;
if ((((c < '0') || (c > '9')) && (c!='[') && (c!=';')) ||
(ansistr[1] != '[') || (ansiptr>75))
execute_ansi();
} else if (c == 27) {
ansistr[0] = 27;
ansiptr = 1;
ansistr[ansiptr]=0;
} else {
if (c == 9) {
i1 = wherex();
for (i = i1; i< (((i1 / 8) + 1) * 8); i++)
outchr(32);
} else if (echo || lecho) {
out1ch(c);
if (c == 10) {
++lines_listed;
if ((sysstatus_pause_on_page & thisuser.sysstatus) &&
(lines_listed >= screenlinest - 1)) {
if (!x_only)
pausescr();
lines_listed = 0;
}
}
} else
out1ch('X');
}
if (chatcall)
setbeep(0);
}
void outstr(char *s)
/* This function outputs a string of characters to the screen (and remotely
* if applicable). The com port is also checked first to see if a remote
* user has hung up
*/
{
int i=0;
checkhangup();
if (!hangup)
while (s[i])
outchr(s[i++]);
}
void nl(void)
/* This function performs a CR/LF sequence to move the cursor to the next
* line. If any end-of-line ANSI codes are set (such as changing back to
* the default color) are specified, those are executed first.
*/
{
if (endofline[0]) {
outstr(endofline);
endofline[0] = 0;
}
outstr("\r\n");
}
void nln(int n)
{
int i;
for (i=0; i<n; i++) {
nl();
}
}
void backspace(void)
/* This function executes a backspace, space, backspace sequence. */
{
int i;
i = echo;
echo = 1;
outstr("\b \b");
echo = i;
}
void setc(unsigned char ch)
/* This sets the current color (both locally and remotely) to that
* specified (in IBM format).
*/
{
char s[30];
makeansi(ch, s, 0);
outstr(s);
}
void pausescr(void)
/* This will pause output, displaying the [PAUSE] message, and wait for
* a key to be hit.
*/
{
int i,i1;
char *ss;
if (x_only)
return;
ss=str_pause;
i1=strlen(ss);
if (okansi()) {
i = curatr;
setc((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[3] :
thisuser.bwcolors[3]);
outstr(ss);
npr("\x1b[%dD",i1);
setc(i);
getkey();
for (i=0; i<i1; i++)
outchr(' ');
npr("\x1b[%dD",i1);
} else {
outstr(ss);
getkey();
for (i = 0; i<i1; i++)
backspace();
}
}
void npr(char *fmt, ...)
/* just like printf, only out to the com port */
{
va_list ap;
char s[512];
va_start(ap, fmt);
vsprintf(s, fmt, ap);
va_end(ap);
outstr(s);
}
void pl(char *s)
{
outstr(s);
nl();
}
void pln(int n)
{
char s[81];
sprintf(s,"%u",n);
pl(s);
}
int kbhitb(void)
{
union REGS r;
if (x_only)
return(0);
r.h.ah = 1;
int86(0x16, &r, &r);
return((r.x.flags & 64) == 0);
}
int empty(void)
{
if (x_only)
return(1);
if (kbhitb() || (incom && (head != tail)) ||
(charbufferpointer && charbuffer[charbufferpointer]) ||
(in_extern == 2))
return(0);
return(1);
}
void skey1(char *ch)
{
char c;
c = *ch;
if ((c == 127) && (!in_fsed))
c = 8;
if (okskey)
switch(c) {
case 1:
case 4:
case 6:
if (okmacro && !charbufferpointer) {
if (c == 1)
c = 2;
else if (c == 4)
c = 0;
else if (c == 6)
c = 1;
strcpy(charbuffer, &(thisuser.macros[c][0]));
c = charbuffer[0];
if (c)
charbufferpointer = 1;
}
break;
case 15:
if (helpl && !ihelp && !chatting && echo) {
ihelp = 1;
print_help(helpl);
ihelp = 0;
}
break;
case 20:
if (echo)
ptime();
break;
case 18:
if (echo)
reprint();
break;
}
*ch = c;
}
char getchd(void)
{
union REGS r;
r.h.ah = 0x07;
int86(save_dos, &r, &r);
return(r.h.al);
}
char getchd1(void)
{
union REGS r;
r.h.ah = 0x06;
r.h.dl = 0xFF;
int86(save_dos, &r, &r);
return((r.x.flags & 0x40) ? 255 : r.h.al);
}
char inkey(void)
/* This function checks both the local keyboard, and the remote terminal
* (if any) for input. If there is input, the key is returned. If there
* is no input, a zero is returned. Function keys hit are interpreted as
* such within the routine and not returned.
*/
{
char ch=0;
if (x_only)
return(0);
if (charbufferpointer) {
if (!charbuffer[charbufferpointer])
charbufferpointer = charbuffer[0] = 0;
else
return(charbuffer[charbufferpointer++]);
}
if (kbhitb() || (in_extern == 2)) {
ch = getchd1();
lastcon = 1;
if (!ch) {
if (in_extern)
in_extern = 2;
else {
ch = getchd1();
skey(ch);
ch = (((ch == 68) || (ch==103)) ? 2 : 0);
}
} else if (in_extern)
in_extern = 1;
timelastchar1=timer1();
} else if (incom && comhit()) {
ch = (get1c() & andwith);
lastcon = 0;
}
skey1(&ch);
return(ch);
}
void mpl(int i)
/* This will make a reverse-video prompt line i characters long, repositioning
* the cursor at the beginning of the input prompt area. Of course, if the
* user does not want ansi, this routine does nothing.
*/
{
int i1;
char s[81];
if (okansi()) {
ansic(3);
for (i1 = 0; i1 < i; i1++)
outchr(' ');
outstr("\x1b[");
itoa(i,s,10);
outstr(s);
outstr("D");
}
}
char upcase(char ch)
/* This converts a character to uppercase */
{
if ((ch > '`') && (ch < '{'))
ch = ch - 32;
return(ch);
}
unsigned char getkey(void)
/* This function returns one character from either the local keyboard or
* remote com port (if applicable). After 1.5 minutes of inactivity, a
* beep is sounded. After 3 minutes of inactivity, the user is hung up.
*/
{
unsigned char ch;
int beepyet;
long dd,tv,tv1;
beepyet = 0;
timelastchar1=timer1();
if (so())
tv=10920L;
else
tv=3276L;
tv1=tv/2;
lines_listed = 0;
do {
while (empty() && !hangup) {
giveup_timeslice();
dd = timer1();
if ((dd<timelastchar1) && ((dd+1000)>timelastchar1))
timelastchar1=dd;
if (labs(dd - timelastchar1) > 65536L)
timelastchar1 -= 1572480L;
if (((dd - timelastchar1) > tv1) && (!beepyet)) {
beepyet = 1;
outchr(7);
}
if (labs(dd - timelastchar1) > tv) {
nl();
outstr(get_string(924));
nl();
hangup = 1;
}
checkhangup();
}
ch = inkey();
} while (!ch && !in_extern && !hangup);
if (checkit && (ch > 127)) {
checkit = 0;
ch = ch & (andwith = 0x7F);
}
return(ch);
}
void input1(char *s, int maxlen, int lc, int crend)
/* This will input a line of data, maximum maxlen characters long, terminated
* by a C/R. if (lc) is non-zero, lowercase is allowed, otherwise all
* characters are converted to uppercase.
*/
{
int curpos=0, done=0, in_ansi=0;
unsigned char ch;
while (!done && !hangup) {
ch = getkey();
if (in_ansi) {
if ((in_ansi==1) && (ch!='['))
in_ansi=0;
else {
if (in_ansi==1)
in_ansi=2;
else if (((ch<'0') || (ch>'9')) && (ch!=';'))
in_ansi=3;
else
in_ansi=2;
}
}
if (!in_ansi) {
if (ch > 31) {
if (curpos < maxlen) {
if (!lc)
ch = upcase(ch);
s[curpos++] = ch;
outchr(ch);
}
} else
switch(ch) {
case 14:
case 13:
s[curpos] = 0;
done = echo = 1;
if (crend)
nl();
break;
case 23: /* Ctrl-W */
if (curpos) {
do {
curpos--;
backspace();
if (s[curpos]==26)
backspace();
} while ((curpos) && (s[curpos-1]!=32));
}
break;
case 26:
if (input_extern) {
s[curpos++] = 26;
outstr("^Z");
}
break;
case 8:
if (curpos) {
curpos--;
backspace();
if (s[curpos] == 26)
backspace();
}
break;
case 21:
case 24:
while (curpos) {
curpos--;
backspace();
if (s[curpos] == 26)
backspace();
}
break;
case 27:
in_ansi=1;
break;
}
}
if (in_ansi==3)
in_ansi=0;
}
if (hangup)
s[0] = 0;
}
void input(char *s, int len)
/* This will input an upper-case string */
{
input1(s, len, 0, 1);
}
void inputl(char *s, int len)
/* This will input an upper or lowercase string of characters */
{
input1(s, len, 1, 1);
}
static void print_yn(int i)
{
if (num_strings(i))
pl(getrandomstring(i));
else switch(i) {
case 2: pl(str_yes); break;
case 3: pl(str_no); break;
}
}
int yn(void)
/* The keyboard is checked for either a Y, N, or C/R to be hit. C/R is
* assumed to be the same as a N. Yes or No is output, and yn is set to
* zero if No was returned, and yn() is non-zero if Y was hit.
*/
{
char ch=0;
ansic(1);
while ((!hangup) &&
((ch = upcase(getkey())) != *str_yes) &&
(ch != *str_no) &&
(ch != 13))
;
if (ch==*str_yes)
print_yn(2);
else
print_yn(3);
return(ch == *str_yes);
}
int ny(void)
/* This is the same as yn(), except C/R is assumed to be "Y" */
{
char ch=0;
ansic(1);
while ((!hangup) &&
((ch = upcase(getkey())) != *str_yes) &&
(ch != *str_no) &&
(ch != 13))
;
if (ch==*str_no)
print_yn(3);
else
print_yn(2);
return((ch == *str_yes) || (ch==13));
}
char ynq(void)
{
char ch=0;
ansic(1);
while ((!hangup) &&
((ch = upcase(getkey())) != *str_yes) &&
(ch != *str_no) &&
(ch != *str_quit) &&
(ch != 13))
;
if (ch==*str_yes) {
ch='Y';
print_yn(2);
} else if (ch==*str_quit) {
ch='Q';
pl(str_quit);
} else {
ch='N';
print_yn(3);
}
return(ch);
}
void ansic(int n)
{
char c;
c = ((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[n] :
thisuser.bwcolors[n]);
if (c == curatr)
return;
setc(c);
makeansi((thisuser.sysstatus & sysstatus_color) ? thisuser.colors[0] :
thisuser.bwcolors[0],endofline, 0);
}
char onek(char *s)
{
char ch;
while (!strchr(s, ch = upcase(getkey())) && !hangup)
;
if (hangup)
ch = s[0];
outchr(ch);
nl();
return(ch);
}
void prt(int i, char *s)
{
ansic(i);
outstr(s);
ansic(0);
}
void reset_colors(void)
{
outstr("\x1b[0m");
}
void goxy(int x, int y)
{
if (okansi())
npr("\x1b[%d;%dH",y,x);
}