347 lines
15 KiB
C
347 lines
15 KiB
C
|
/* EX_CHAT.C - Example of a multi-window full-screen chat program written */
|
||
|
/* with OpenDoors. See manual for instructions on how to compile */
|
||
|
/* a program using OpenDoors. */
|
||
|
/* */
|
||
|
/* This program shows how to do the following: */
|
||
|
/* */
|
||
|
/* - Replace the standard OpenDoors chat mode with your own */
|
||
|
/* chat mode implementation. See instructions below. */
|
||
|
/* - How to scroll a portion of the screen, leaving the rest */
|
||
|
/* of the screen unaltered. */
|
||
|
/* - How to determine whether input came from the local or */
|
||
|
/* remote keyboard. */
|
||
|
/* - How to display a popup window with a message in it when */
|
||
|
/* the sysop shells to DOS. (DOS version only.) */
|
||
|
/* - How to save and restore the entire contents of the */
|
||
|
/* screen. */
|
||
|
/* */
|
||
|
/* Conditional compilation directives allow this program to */
|
||
|
/* be compiled as a stand-alone chat door, or as a */
|
||
|
/* replacement chat mode to be integrated into any OpenDoors */
|
||
|
/* program. If STANDALONE is #defined, ex_chat.c will be */
|
||
|
/* compiled as a split-screen chat door that can be run like */
|
||
|
/* any door program. If STANDALONE is not #defined, the chat */
|
||
|
/* mode function will be compiled as a replacement chat mode */
|
||
|
/* for the chat mode built into OpenDoors. In this case, the */
|
||
|
/* demo mainline function simply displays a prompt, and will */
|
||
|
/* exit the door as soon as you press the [ENTER] key. While */
|
||
|
/* the program is running, if you invoke chat mode (press */
|
||
|
/* [ALT]-[C]), the current screen will be saved and the */
|
||
|
/* split-screen chat mode will be activated. When you press */
|
||
|
/* [ESC] the split-screen chat mode will end, and the */
|
||
|
/* original screen will be restored. To integrate this chat */
|
||
|
/* mode into your own program, you should simply set */
|
||
|
/* od_control.od_cbefore_chat to point to the */
|
||
|
/* fullscreen_chat function, as shown, and remove the mainline */
|
||
|
/* (main()/WinMain()) function from this file. The compile this */
|
||
|
/* file into your program after removing the #define STANDALONE */
|
||
|
/* line. */
|
||
|
|
||
|
/* Include required header files. */
|
||
|
#include "OpenDoor.h"
|
||
|
#include <string.h>
|
||
|
|
||
|
|
||
|
/* The following #define forces this code to compile as a stand-alone door */
|
||
|
/* program. If you wish to use this code to replace the standard OpenDoors */
|
||
|
/* chat mode in your own program, remove this #define. */
|
||
|
#define STANDALONE
|
||
|
|
||
|
|
||
|
/* Full-screen chat function prototypes. */
|
||
|
void fullscreen_chat(void);
|
||
|
void chat_new_line(void);
|
||
|
void display_shell_window(void);
|
||
|
void remove_shell_window(void);
|
||
|
|
||
|
|
||
|
|
||
|
/* The main() or WinMain() function: program execution begins here. */
|
||
|
#ifdef ODPLAT_WIN32
|
||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||
|
LPSTR lpszCmdLine, int nCmdShow)
|
||
|
#else
|
||
|
int main(int argc, char *argv[])
|
||
|
#endif
|
||
|
{
|
||
|
/* Handle standard command-line options and perform other needed setup. */
|
||
|
#ifdef ODPLAT_WIN32
|
||
|
od_control.od_cmd_show = nCmdShow;
|
||
|
od_parse_cmd_line(lpszCmdLine);
|
||
|
#else
|
||
|
od_parse_cmd_line(argc, argv);
|
||
|
#endif
|
||
|
|
||
|
#ifdef STANDALONE /* If compiled as a stand-alone chat program */
|
||
|
od_init(); /* Initialize OpenDoors */
|
||
|
|
||
|
fullscreen_chat(); /* Invoke full-screen chat function */
|
||
|
|
||
|
#else /* If compiled as replacement for OpenDoors chat mode */
|
||
|
/* Setup OpenDoors to use our custom chat mode instead */
|
||
|
od_control.od_cbefore_chat=fullscreen_chat;
|
||
|
|
||
|
od_printf("Press [Enter] to exit door, or invoke chat mode.\n\r");
|
||
|
od_get_answer("\n\r");
|
||
|
#endif
|
||
|
|
||
|
od_exit(0, FALSE); /* Exit program. */
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* FULL-SCREEN CHAT CUSTOMIZATION OPTIONS */
|
||
|
|
||
|
char window_colour[2]={0x0b,0x0c}; /* Text colour used for each person */
|
||
|
char bar_colour=0x70; /* Colour of window seperation bar */
|
||
|
char top_line[2]={13,1}; /* Specifies location of each window on screen */
|
||
|
char bottom_line[2]={23,11}; /* Line number of bottom of each window */
|
||
|
char bar_line=12; /* Line number of window seperation bar */
|
||
|
char scroll_distance=2; /* Distance to scroll window when required */
|
||
|
char shell_window_title=0x1a; /* Colour of title of DOS shell notice window */
|
||
|
char shell_window_boarder=0x1f; /* Colour of DOS shell window boarder */
|
||
|
char shell_window_text=0x1b; /* Colour of text in DOS shell window */
|
||
|
|
||
|
|
||
|
|
||
|
int cursor_window; /* FULL-SCREEN CHAT INTERNAL VARIABLES */
|
||
|
char current_word[2][81];
|
||
|
int word_length[2];
|
||
|
int cursor_col[2];
|
||
|
int cursor_line[2];
|
||
|
unsigned char key;
|
||
|
int old_chat_key;
|
||
|
void *shell_window;
|
||
|
char *before_shell_text;
|
||
|
char *after_shell_text;
|
||
|
#ifndef STANDALONE /* If compiled as replacement for OpenDoors chat mode */
|
||
|
char screen_buffer[4004];
|
||
|
#endif
|
||
|
|
||
|
/* FULL-SCREEN CHAT FUNCTION */
|
||
|
void fullscreen_chat(void)
|
||
|
{
|
||
|
cursor_window=0; /* Reset working variables */
|
||
|
word_length[0]=word_length[1]=0;
|
||
|
cursor_col[0]=cursor_col[1]=1;
|
||
|
cursor_line[0]=top_line[0];
|
||
|
cursor_line[1]=top_line[1];
|
||
|
|
||
|
|
||
|
/* If ANSI or AVATAR graphics mode is not available */
|
||
|
if(!od_control.user_ansi && !od_control.user_avatar)
|
||
|
{ /* Then use OpenDoor's line chat mode instead */
|
||
|
#ifdef STANDALONE /* If compiled as a stand-alone chat program */
|
||
|
od_chat();
|
||
|
#endif
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
od_control.od_cbefore_shell=display_shell_window; /* Set shell settings */
|
||
|
od_control.od_cafter_shell=remove_shell_window;
|
||
|
before_shell_text=od_control.od_before_shell;
|
||
|
after_shell_text=od_control.od_after_shell;
|
||
|
od_control.od_before_shell=NULL;
|
||
|
od_control.od_after_shell=NULL;
|
||
|
od_control.od_chat_active=TRUE;
|
||
|
|
||
|
#ifdef STANDALONE /* If compiled as a stand-alone chat program */
|
||
|
old_chat_key=od_control.key_chat; /* Prevent internal chat mode from */
|
||
|
od_control.key_chat=0; /* being invoked */
|
||
|
|
||
|
#else /* If compiled as replacement for OpenDoors chat mode */
|
||
|
od_save_screen(screen_buffer); /* Save current screen contents. */
|
||
|
#endif
|
||
|
|
||
|
/* DRAW THE CHAT SCREEN */
|
||
|
od_set_attrib(window_colour[0]);
|
||
|
od_clr_scr(); /* Clear the screen */
|
||
|
|
||
|
od_set_cursor(bar_line,1); /* Draw window separation bar */
|
||
|
od_set_attrib(bar_colour);
|
||
|
od_clr_line();
|
||
|
od_set_cursor(bar_line,67);
|
||
|
od_printf("Ctrl-A: Clear");
|
||
|
od_set_cursor(bar_line,1);
|
||
|
od_printf(" Top : %-.28s Bottom : %-.28s ",
|
||
|
od_control.sysop_name, od_control.user_name);
|
||
|
|
||
|
od_set_cursor(top_line[0],1); /* Locate cursor where typing will begin */
|
||
|
od_set_attrib(window_colour[0]); /* Set appropriate text colour */
|
||
|
|
||
|
/* MAIN CHAT LOOP */
|
||
|
for(;;) /* (Repeats for each character typed) */
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
key=(char)od_get_key(FALSE); /* Get next keystroke from keyboard */
|
||
|
|
||
|
/* CHECK FOR SYSOP ABORT */
|
||
|
if((key==27 && od_control.od_last_input==1) /* If sysop pressed ESC */
|
||
|
|| !od_control.od_chat_active)
|
||
|
{
|
||
|
od_set_attrib(0x07); /* Reset display colour */
|
||
|
od_clr_scr(); /* Clear the screen */
|
||
|
|
||
|
od_control.od_cbefore_shell=NULL; /* Restore DOS shell settings */
|
||
|
od_control.od_cafter_shell=NULL;
|
||
|
od_control.od_before_shell=before_shell_text;
|
||
|
od_control.od_after_shell=after_shell_text;
|
||
|
#ifdef STANDALONE /* If compiled as a stand-alone chat program */
|
||
|
od_control.key_chat=old_chat_key;/* Re-enable internal chat mode */
|
||
|
|
||
|
#else /* If compiled as replacement for OpenDoors chat mode */
|
||
|
od_control.od_chat_active=FALSE; /* Turn off chat mode */
|
||
|
od_restore_screen(screen_buffer); /* Restore orignal screen */
|
||
|
#endif
|
||
|
return; /* Exit full-screen chat */
|
||
|
|
||
|
}
|
||
|
} while(key==0);
|
||
|
|
||
|
/* CHECK FOR NEW TYPIST */
|
||
|
if(od_control.od_last_input!=cursor_window)/* If new person typing now */
|
||
|
{ /* Switch cursor to appropriate window */
|
||
|
cursor_window=od_control.od_last_input; /* Set current typist */
|
||
|
|
||
|
/* Move cursor to new window */
|
||
|
od_set_cursor(cursor_line[cursor_window],cursor_col[cursor_window]);
|
||
|
|
||
|
od_set_attrib(window_colour[cursor_window]); /* Change text colour */
|
||
|
}
|
||
|
|
||
|
|
||
|
if(key==13 || key==10) /* IF USER PRESSED [ENTER] / [RETURN] */
|
||
|
{
|
||
|
word_length[cursor_window]=0; /* Enter constitutes end of word */
|
||
|
|
||
|
chat_new_line(); /* Move to next line */
|
||
|
}
|
||
|
|
||
|
|
||
|
else if(key==8) /* IF USER PRESS [BACKSPACE] */
|
||
|
{
|
||
|
if(cursor_col[cursor_window] > 1) /* If not at left of screen */
|
||
|
{
|
||
|
--cursor_col[cursor_window]; /* Move cursor back on character */
|
||
|
if(word_length[cursor_window] > 0) --word_length[cursor_window];
|
||
|
od_printf("\b \b"); /* Erase last character from screen */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
else if(key==32) /* IF USER PRESSED [SPACE] */
|
||
|
{
|
||
|
word_length[cursor_window]=0; /* [Space] constitutes end of word */
|
||
|
|
||
|
if(cursor_col[cursor_window]==79) /* If at end of line */
|
||
|
chat_new_line(); /* Move cursor to next line */
|
||
|
else /* If not at end of line */
|
||
|
{
|
||
|
++cursor_col[cursor_window]; /* Increment cursor position */
|
||
|
od_putch(32); /* Display a space */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
else if(key==1) /* IF USER PRESSED CLEAR WINDOW KEY */
|
||
|
{ /* Clear user's window */
|
||
|
od_scroll(1,top_line[cursor_window],79,bottom_line[cursor_window],
|
||
|
bottom_line[cursor_window]-top_line[cursor_window]+1,0);
|
||
|
|
||
|
word_length[cursor_window]=0; /* We are no longer composing a word */
|
||
|
|
||
|
cursor_col[cursor_window]=1; /* Reset cursor position */
|
||
|
cursor_line[cursor_window]=top_line[cursor_window];
|
||
|
od_set_cursor(cursor_line[cursor_window],cursor_col[cursor_window]);
|
||
|
}
|
||
|
|
||
|
|
||
|
else if(key>32) /* IF USER TYPED A PRINTABLE CHARACTER */
|
||
|
{ /* PERFORM WORD WRAP IF NECESSARY */
|
||
|
if(cursor_col[cursor_window]==79) /* If cursor is at end of line */
|
||
|
{
|
||
|
/* If there is a word to wrap */
|
||
|
if(word_length[cursor_window]>0 && word_length[cursor_window]<78)
|
||
|
{
|
||
|
/* Move cursor to beginning of word */
|
||
|
od_set_cursor(cursor_line[cursor_window],
|
||
|
cursor_col[cursor_window]-word_length[cursor_window]);
|
||
|
|
||
|
od_clr_line(); /* Erase word from current line */
|
||
|
|
||
|
chat_new_line(); /* Move cursor to next line */
|
||
|
|
||
|
/* Redisplay word */
|
||
|
od_disp(current_word[cursor_window],word_length[cursor_window],
|
||
|
TRUE);
|
||
|
cursor_col[cursor_window]+=word_length[cursor_window];
|
||
|
}
|
||
|
|
||
|
else /* If there is no word to "wrap" */
|
||
|
{
|
||
|
chat_new_line(); /* Move cursor to next line */
|
||
|
word_length[cursor_window]=0; /* Start a new word */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* ADD CHARACTER TO CURRENT WORD */
|
||
|
/* If there is room for more character in word */
|
||
|
if(strlen(current_word[cursor_window])<79) /* Add new character */
|
||
|
current_word[cursor_window][word_length[cursor_window]++]=key;
|
||
|
|
||
|
/* DISPLAY NEWLY TYPED CHARACTER */
|
||
|
++cursor_col[cursor_window];
|
||
|
od_putch(key);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* FUNCTION USED BY FULL-SCREEN CHAT TO START A NEW INPUT LINE */
|
||
|
void chat_new_line(void)
|
||
|
{ /* If cursor is at bottom of window */
|
||
|
if(cursor_line[cursor_window]==bottom_line[cursor_window])
|
||
|
{ /* Scroll window up one line on screen */
|
||
|
od_scroll(1,top_line[cursor_window],79, bottom_line[cursor_window],
|
||
|
scroll_distance, 0);
|
||
|
cursor_line[cursor_window]-=(scroll_distance - 1);
|
||
|
}
|
||
|
|
||
|
else /* If cursor is not at bottom of window */
|
||
|
{
|
||
|
++cursor_line[cursor_window]; /* Move cursor down one line */
|
||
|
}
|
||
|
|
||
|
/* Move cursor's position on screen */
|
||
|
od_set_cursor(cursor_line[cursor_window],cursor_col[cursor_window]=1);
|
||
|
|
||
|
od_set_attrib(window_colour[cursor_window]); /* Change text colour */
|
||
|
}
|
||
|
|
||
|
|
||
|
void display_shell_window(void)
|
||
|
{
|
||
|
if((shell_window=od_window_create(17,9,63,15,"DOS Shell",
|
||
|
shell_window_boarder, shell_window_title,
|
||
|
shell_window_text, 0))==NULL) return;
|
||
|
|
||
|
od_set_attrib(shell_window_text);
|
||
|
od_set_cursor(11,26);
|
||
|
od_printf("The Sysop has shelled to DOS");
|
||
|
od_set_cursor(13,21);
|
||
|
od_printf("He/She will return in a few moments...");
|
||
|
}
|
||
|
|
||
|
|
||
|
void remove_shell_window(void)
|
||
|
{
|
||
|
od_window_remove(shell_window);
|
||
|
od_set_cursor(cursor_line[cursor_window],cursor_col[cursor_window]);
|
||
|
od_set_attrib(window_colour[cursor_window]);
|
||
|
}
|