home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
GETSCRN.EXE
/
SOURCE
/
MAIN.C
< prev
next >
Wrap
Text File
|
1990-06-24
|
17KB
|
551 lines
/*
MAIN.c
Copyright (c) 1990 by: Arthur Kevin McGrath
Contract Engineers
P. O. Box 128
Barboursville, VA 22923
703/832-7025
ALL RIGHTS ARE RESERVED. You may not copy this program in any way
except to make back-up copies FOR YOUR OWN USE. If you copy this
program for any reason without WRITTEN PERMISSION from the above
named copyright owner (except to make back-up copies FOR YOUR OWN USE),
you are breaking the Copyright Laws of the United States. You will go
to jail for one year and pay a $50,000 fine.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define INCL_BASE
#define INCL_VIO
#include <os2.h>
#include "capture.h"
/*
This program will capture the screen from a FULL SCREEN OS/2
session and store it in a file. To do this, it needs to know:
1. when to install itself.
(The program will install itself when the user types
CAPTURE )
2. when to capture the screen
(This shall happen when the user hits the
<ALT><Print Screen> key combination.)
3. the name of a file to use for the contents of the screen.
(The user shall enter this information each time a screen
is captured.)
4. when to de-install itself
Internally, this program will:
1. install itself as a keyboard monitor
2. wait for the ALT-PrintScreen key combination
3. find the location of the physical screen buffer
4. if and only if we are in a text mode transfer
every other byte in that buffer to a file
Optionally, I might want to consider providing a "PRINTABLE
CHARACTER ONLY" option for this thing.
*/
/* GLOBAL VARIABLES !!!!!!!!!!!!!!!!!! */
unsigned char printable_only;
char get_file_popup_title[ 80 ];
char drive_prompt[ 80 ];
char directory_prompt[ 80 ];
char file_prompt[ 80 ];
char ok_prompt[ 80 ];
char pause_prompt[ 80 ];
UCHAR yes, no;
char ansi_sequence[] = { "\033[46;1;34m" };
char default_drive_name;
char default_path_name[ LONGEST_PATH_NAME + 1 ];
char default_file_name[ LONGEST_FILE_NAME + 1 ];
int capturing = FALSE;
char program_name[ LONGEST_FILE_NAME + LONGEST_PATH_NAME + 1 ];
/* !!!!!!!!!!!!!!!! End of GLOBAL VARIABLES */
/* CENTER_THE_LINE() compares the length of the string you want to
display with the width of the pop up window that will be displaying
that line. It returns the offset from the left margin where that
string will have to start in order to be centered on this line.
It requires the following parameters:
It returns the folowing values:
OFFSET this is the number of columns you must add to the
left margin to make this string appear centered in
the pop up window. This number is an UNSIGNED
INTEGER (USHORT in OS/2 terminology).
If this function returns the number 0xFFFF,
then either:
1. the string you are trying to display
is larger than the line you are trying
to display it on, or
2. the right margin that you passed this
function was SMALLER than the left margin. */
USHORT center_the_line( USHORT left, USHORT right, USHORT string_length )
{
USHORT line_length;
/* Protect this function from OBVIOUSLY bad values. */
if( left > right )
{
return( 0xFFFF );
}
line_length = right - left;
/* Protect this function from OBVIOUSLY bad values. */
if( string_length > line_length )
{
return( 0xFFFF );
}
return( (line_length - string_length) / 2 );
}
/* GET_STRING() will:
1. display any default data.
2. position the cursor.
3. input a string from the keyboard.
4. return either the default string or the input string
to the calling function.
5. echo the data it returns to the screen.
It needs the following parameters to do this:
DEFAULT_DATA a string to display for the user
STRING holds the data returned to the user
SIZE how long is STRING?
ROW positioning information
COLUMN positioning information
WIDTH how wide is the space on the screen
that will display the data?
KEYBOARD the handle of the logical keyboard
It returns the following error codes:
NOTHING ( VOID ) */
void get_string( char *default_data, char *string,
USHORT size,
USHORT row,
USHORT column,
USHORT width,
HKBD keyboard )
{
USHORT error, string_length;
UCHAR attribute = NORMAL_TEXT_COLOR;
KBDINFO current;
STRINGINBUF data_length;
char *this_one;
struct screen_text blank;
/* Initialize... */
blank.attribute = NORMAL_TEXT_COLOR;
blank.letter = ' ';
/* Copy DEFAULT_DATA to STRING. */
thread_copy( string, default_data );
/* Make sure we cannot overflow our spot on the screen. */
string_length = MIN( ( USHORT )thread_strlen( default_data ), width );
/* Display the default data. */
error = VioWrtCharStrAtt( default_data,
string_length,
row, column,
&attribute,
DEFAULT_SCREEN_HANDLE );
/* Position the cursor for data entry. */
error = VioSetCurPos( row, column, DEFAULT_SCREEN_HANDLE );
/* Get the data. */
data_length.cb = MIN( size, ( USHORT )255 );
error = KbdStringIn( string, &data_length, IO_WAIT, keyboard );
/* Did the operator enter nothing more than the
TURN AROUND character. If so, copy DEFAULT_DATA
into STRING. */
error = KbdGetStatus( ¤t, keyboard );
/* Once we have a string we are happy with, make that string
the new default. That way, if the user comes back to this
point again, he/she will see the last thing he/she entered. */
if( ( ( USHORT )string[0] == current.chTurnAround )
||
( string[0] == '\r' )
||
( string[0] == '\n' ) )
{
thread_copy( string, default_data );
}
else
{
/* Did we get a delete key? */
if( string[0] == '\xFF' )
{
string[0] = '\0';
default_data[0] = '\0';
}
else
{
/* Make sure the string ends in a NULL character. */
string[ data_length.cchIn ] = '\0';
/* Strip off any trailing blanks. */
for( this_one = &string[ data_length.cchIn - 1 ];
( ( *this_one < '\"' ) || ( *this_one == '\\' ) ) && ( this_one >= string );
this_one-- )
{
*this_one = '\0';
}
/* Strip off any leading blanks or back slashes. */
for( this_one = string;
( (*this_one < '\"') || (*this_one == '\\' ) ) && *this_one; )
{
this_one++;
}
thread_copy( string, this_one );
/* Make this data entry the new default. */
thread_copy( default_data, string );
}
}
/* Echo the data the user entered. We do this so that
the color of the displayed data will match the rest
of our screen. */
string_length = ( USHORT )thread_strlen( default_data );
/* Do we have any old data to erase before we go back
to our calling function??? */
if( string_length < width )
{
/* Write some blank spaces. */
error = VioWrtNCell( ( BYTE *)&blank,
width,
row,
column,
DEFAULT_SCREEN_HANDLE );
}
error = VioWrtCharStrAtt( default_data,
string_length,
row, column,
&attribute,
DEFAULT_SCREEN_HANDLE );
return;
}
/* VALIDATE_DRIVE() will tell us if a given drive letter is listed
on the logical drive map for this computer.
It needs the following parameters to do this:
DRIVE_NUMBER the NUMBER of the drive we are checking
(A = 1, B = 2, C = 3, ..., Z = 26)
DRIVE_MAP the map returned by the DosQCurDisk()
system call
It returns the following values:
TRUE the drive is on the list. It is VALID.
FALSE there is no such drive on this machine. */
void command_line_options( void )
{
puts( "Valid parameters are:\n" );
puts( "\t/A\tcapture all ASCII characters whether or not they are printable\n" );
puts( "\t/X\tcapture only printable ASCII characters. Replace the\n" );
puts( "\t\tnon-printable ASCII characters with dots.\n\n" );
puts( "The following choices affect the name of the file used\n" );
puts( "to hold the text captured from the screen.\n" );
puts( "\t/D\tthe letter of the drive to hold the file.\n" );
puts( "\t/P\tthe PATH to the file (OMIT the leading \\\n" );
puts( "\t/F\tthe file name (OMIT any drive or path names)\n" );
puts( "\n\n" );
puts( "You may use either upper or lower case.\n" );
puts( "You may use these options in any order on the command line\n" );
puts( "\n\n" );
return;
}
main(int argc, char *argv[], char *envp[] )
{
unsigned char capture_flag;
USHORT error;
int x, i;
char *marker, bad_module[ LONGEST_FILE_NAME + LONGEST_PATH_NAME ];
char *comspec;
BYTE *thread_stack;
TID id;
SEL selector;
RESULTCODES result;
/* Initialize some global variables. */
strcpy( program_name, argv[0] );
default_drive_name = '\0';
default_path_name[0] = default_file_name[0] = '\0';
strcpy( default_file_name, "screen.dat" );
/* Initialize the various prompts. */
strcpy( get_file_popup_title, "CAPTURE FILE NAME AND PATH" );
strcpy( drive_prompt, "Drive letter:" );
strcpy( directory_prompt, "Directory path: (Do NOT enter the TRAILING \\ ):" );
strcpy( file_prompt, "File name:" );
strcpy( ok_prompt, "Are the above entries correct? (Y or N):" );
strcpy( pause_prompt, "Hit any key to continue..." );
yes = 'Y';
no = 'N';
/* Command line parameters:
/A capture ALL ASCII characters, both
printable and non printable , from
the screen. (This is the DEFAULT
condition.)
/X capture ONLY PRONTABLE ASCII characters
from the screen. Replace non printable
characters with dots.
/D drive name.
/P path name.
/F file name.
/? list the valid command line options. */
/* Invent a default capture flag. */
capture_flag = ALL_ASCII_CHARACTERS;
/* Parse the command line. */
for( x = 1; x < argc; x++ )
{
switch( argv[x][0] )
{
case '-':
case '/':
switch( argv[x][1] )
{
case 'a':
case 'A':
capture_flag = ALL_ASCII_CHARACTERS;
break;
case 'd':
case 'D':
x++;
if( x < argc )
{
default_drive_name = ( char )toupper( argv[x][0] );
}
break;
case 'f':
case 'F':
x++;
if( x < argc )
{
strcpy( default_file_name, argv[x] );
}
break;
case 'p':
case 'P':
/* Copy the next command line parameter to internal storeage. */
x++;
if( x < argc )
{
strcpy( default_path_name, argv[x] );
/* Strip opff any TRAILING \ */
i = strlen( default_path_name );
i--;
if( default_path_name[i] == '\\' )
{
default_path_name[i] = '\0';
}
/* Strip off any LEADING \ */
for( marker = default_path_name;
*marker == '\\'; marker++ );
if( marker != default_path_name )
{
strcpy( default_path_name, marker );
}
}
break;
case 'x':
case 'X':
capture_flag = PRINTABLE_ASCII_ONLY;
break;
case '?':
command_line_options();
DosExit( EXIT_PROCESS, NO_ERROR );
break;
default:
printf( "\n\"%s\" is not a valid parameter\n",
argv[x] );
command_line_options();
}
break;
default:
printf( "\n\"%s\" is not a valid parameter\n",
argv[1] );
command_line_options();
}
}
/* Allocate the stack space needed for our STACK KILLER thread. */
DosAllocSeg( STACK_KILLER_STACK,
&selector,
NOSHARE_NODISCARD );
thread_stack = ( BYTE *)MAKEP( selector, 0 );
/* Mark the stack we are about to use so that we can
monitor stack useage. */
mark_stack( (char *)thread_stack,
STACK_KILLER_STACK );
/* Start the thread that will free the stack of threads
that have exited. */
DosCreateThread( free_the_stack,
&id,
( BYTE *)&thread_stack[ STACK_KILLER_STACK - 1 ] );
/* Get the name of our command processor. */
DosScanEnv( "COMSPEC", &comspec );
/* Generate a new command line. */
DosExecPgm( bad_module,
sizeof( bad_module ),
EXEC_ASYNC,
( PSZ )NULL, // Pass NO arguments.
( PSZ )NULL, // Pass PARENT's environment to child.
&result,
comspec );
/* Start our keyboard monitor. */
error = monitor_the_keyboard();
/* Let the operator know that this program is ending. */
pop_up( FAREWELL, comspec, error );
DosExit( EXIT_PROCESS, NO_ERROR );
return( NO_ERROR );
}