home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / GETSCRN.EXE / SOURCE / MAIN.C < prev    next >
Text File  |  1990-06-24  |  17KB  |  551 lines

  1. /*
  2.  
  3.  
  4.  
  5.                                 MAIN.c
  6.  
  7.  
  8.         Copyright (c) 1990 by:  Arthur Kevin McGrath
  9.                                 Contract Engineers
  10.                                 P. O. Box 128
  11.                                 Barboursville, VA  22923
  12.  
  13.                                 703/832-7025
  14.  
  15.  
  16.   ALL RIGHTS ARE RESERVED.  You may not copy this program in any way
  17.   except to make back-up copies FOR YOUR OWN USE.  If you copy this
  18.   program for any reason without WRITTEN PERMISSION from the above
  19.   named copyright owner (except to make back-up copies FOR YOUR OWN USE),
  20.   you are breaking the Copyright Laws of the United States.  You will go
  21.   to jail for one year and pay a $50,000 fine.
  22.  
  23.  
  24.  
  25.  
  26. */
  27.  
  28.  
  29.  
  30. #include        <stdio.h>
  31. #include        <string.h>
  32. #include        <stdlib.h>
  33. #include        <ctype.h>
  34.  
  35.  
  36. #define INCL_BASE
  37. #define INCL_VIO
  38. #include <os2.h>
  39.  
  40. #include "capture.h"
  41.  
  42.  
  43.  
  44. /*
  45.     This program will capture the screen from a FULL SCREEN OS/2
  46.     session and store it in a file.     To do this, it needs to know:
  47.  
  48.         1.  when to install itself.
  49.             (The program will install itself when the user types
  50.                     CAPTURE      )
  51.         2.  when to capture the screen
  52.             (This shall happen when the user hits the
  53.                     <ALT><Print Screen> key combination.)
  54.         3.  the name of a file to use for the contents of the screen.
  55.             (The user shall enter this information each time a screen
  56.                     is captured.)
  57.         4.  when to de-install itself
  58.  
  59.     Internally, this program will:
  60.  
  61.         1.  install itself as a keyboard monitor
  62.         2.  wait for the ALT-PrintScreen key combination
  63.         3.  find the location of the physical screen buffer
  64.         4.  if and only if we are in a text mode transfer
  65.                 every other byte in that buffer to a file
  66.  
  67.     Optionally, I might want to consider providing a "PRINTABLE
  68.     CHARACTER ONLY" option for this thing.
  69.                                                                 */
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76. /*  GLOBAL VARIABLES    !!!!!!!!!!!!!!!!!!  */
  77.  
  78. unsigned char   printable_only;
  79. char    get_file_popup_title[ 80 ];
  80. char    drive_prompt[ 80 ];
  81. char    directory_prompt[ 80 ];
  82. char    file_prompt[ 80 ];
  83. char    ok_prompt[ 80 ];
  84. char    pause_prompt[ 80 ];
  85.  
  86. UCHAR   yes, no;
  87. char    ansi_sequence[] = { "\033[46;1;34m" };
  88.  
  89. char    default_drive_name;
  90. char    default_path_name[ LONGEST_PATH_NAME + 1 ];
  91. char    default_file_name[ LONGEST_FILE_NAME + 1 ];
  92.  
  93. int     capturing = FALSE;
  94.  
  95. char    program_name[ LONGEST_FILE_NAME + LONGEST_PATH_NAME + 1 ];
  96.  
  97. /*  !!!!!!!!!!!!!!!!    End of GLOBAL VARIABLES */
  98.  
  99.  
  100.  
  101.  
  102.  
  103. /*  CENTER_THE_LINE() compares the length of the string you want to
  104.     display with the width of the pop up window that will be displaying
  105.     that line.  It returns the offset from the left margin where that
  106.     string will have to start in order to be centered on this line.
  107.  
  108.     It requires the following parameters:
  109.  
  110.     It returns the folowing values:
  111.         OFFSET      this is the number of columns you must add to the
  112.                     left margin to make this string appear centered in
  113.                     the pop up window.  This number is an UNSIGNED
  114.                     INTEGER (USHORT in OS/2 terminology).
  115.                     If this function returns the number 0xFFFF,
  116.                     then either:
  117.                         1.  the string you are trying to display
  118.                             is larger than the line you are trying
  119.                             to display it on, or
  120.                         2.  the right margin that you passed this
  121.                             function was SMALLER than the left margin.  */
  122. USHORT  center_the_line( USHORT left, USHORT right, USHORT string_length )
  123. {
  124.     USHORT  line_length;
  125.  
  126.     /*  Protect this function from OBVIOUSLY bad values.    */
  127.     if( left > right )
  128.     {
  129.         return( 0xFFFF );
  130.  
  131.     }
  132.  
  133.     line_length = right - left;
  134.  
  135.     /*  Protect this function from OBVIOUSLY bad values.    */
  136.     if( string_length > line_length )
  137.     {
  138.         return( 0xFFFF );
  139.  
  140.     }
  141.  
  142.     return(  (line_length - string_length) / 2  );
  143.  
  144. }
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151. /*  GET_STRING() will:
  152.             1.  display any default data.
  153.             2.  position the cursor.
  154.             3.  input a string from the keyboard.
  155.             4.  return either the default string or the input string
  156.                 to the calling function.
  157.             5.  echo the data it returns to the screen.
  158.  
  159.     It needs the following parameters to do this:
  160.             DEFAULT_DATA    a string to display for the user
  161.             STRING          holds the data returned to the user
  162.             SIZE            how long is STRING?
  163.             ROW             positioning information
  164.             COLUMN          positioning information
  165.             WIDTH           how wide is the space on the screen
  166.                                 that will display the data?
  167.             KEYBOARD        the handle of the logical keyboard
  168.  
  169.     It returns the following error codes:
  170.             NOTHING     ( VOID )                */
  171. void    get_string( char *default_data, char *string,
  172.                     USHORT size,
  173.                     USHORT row,
  174.                     USHORT column,
  175.                     USHORT width,
  176.                     HKBD keyboard       )
  177. {
  178.     USHORT      error, string_length;
  179.     UCHAR       attribute = NORMAL_TEXT_COLOR;
  180.     KBDINFO     current;
  181.     STRINGINBUF data_length;
  182.     char        *this_one;
  183.     struct screen_text  blank;
  184.  
  185.     /*  Initialize...       */
  186.     blank.attribute = NORMAL_TEXT_COLOR;
  187.     blank.letter = ' ';
  188.  
  189.  
  190.     /*  Copy DEFAULT_DATA to STRING.    */
  191.     thread_copy( string, default_data );
  192.  
  193.     /*  Make sure we cannot overflow our spot on the screen.    */
  194.     string_length = MIN(   ( USHORT )thread_strlen( default_data ), width );
  195.  
  196.     /*  Display the default data.   */
  197.     error = VioWrtCharStrAtt( default_data,
  198.                     string_length,
  199.                     row, column,
  200.                     &attribute,
  201.                     DEFAULT_SCREEN_HANDLE );
  202.  
  203.  
  204.     /*  Position the cursor for data entry. */
  205.     error = VioSetCurPos( row, column, DEFAULT_SCREEN_HANDLE );
  206.  
  207.  
  208.     /*  Get the data. */
  209.     data_length.cb = MIN( size, ( USHORT )255 );
  210.     error = KbdStringIn( string, &data_length, IO_WAIT, keyboard );
  211.  
  212.     /*  Did the operator enter nothing more than the
  213.         TURN AROUND character.  If so, copy DEFAULT_DATA
  214.         into STRING.    */
  215.     error = KbdGetStatus( ¤t, keyboard );
  216.  
  217.     /*  Once we have a string we are happy with, make that string
  218.         the new default.  That way, if the user comes back to this
  219.         point again, he/she will see the last thing he/she entered. */
  220.     if( (   ( USHORT )string[0] == current.chTurnAround )
  221.                         ||
  222.             ( string[0] == '\r' )
  223.                         ||
  224.             ( string[0] == '\n' )          )
  225.     {
  226.         thread_copy( string, default_data );
  227.  
  228.     }
  229.     else
  230.     {
  231.         /*  Did we get a delete key?    */
  232.         if( string[0] == '\xFF' )
  233.         {
  234.             string[0] = '\0';
  235.             default_data[0] = '\0';
  236.  
  237.         }
  238.         else
  239.         {
  240.             /*  Make sure the string ends in a NULL character.   */
  241.             string[ data_length.cchIn ] = '\0';
  242.  
  243.             /*  Strip off any trailing blanks.   */
  244.             for(        this_one = &string[ data_length.cchIn - 1 ];
  245.                 (    ( *this_one < '\"' ) || ( *this_one == '\\' )     )    &&    ( this_one >= string );
  246.                 this_one--      )
  247.             {
  248.                 *this_one = '\0';
  249.  
  250.             }
  251.  
  252.             /*  Strip off any leading blanks or back slashes.   */
  253.             for( this_one = string;
  254.                 ( (*this_one < '\"') || (*this_one == '\\' )   )    &&    *this_one;       )
  255.             {
  256.                 this_one++;
  257.  
  258.             }
  259.  
  260.             thread_copy( string, this_one );
  261.  
  262.             /*  Make this data entry the new default.   */
  263.             thread_copy( default_data, string );
  264.  
  265.  
  266.         }
  267.  
  268.     }
  269.  
  270.     /*  Echo the data the user entered.  We do this so that
  271.         the color of the displayed data will match the rest
  272.         of our screen.  */
  273.     string_length = ( USHORT )thread_strlen( default_data );
  274.  
  275.     /*  Do we have any old data to erase before we go back
  276.         to our calling function???  */
  277.     if( string_length < width )
  278.     {
  279.         /*  Write some blank spaces.    */
  280.         error = VioWrtNCell( ( BYTE *)&blank,
  281.                             width,
  282.                             row,
  283.                             column,
  284.                             DEFAULT_SCREEN_HANDLE   );
  285.  
  286.     }
  287.  
  288.     error = VioWrtCharStrAtt( default_data,
  289.                     string_length,
  290.                     row, column,
  291.                     &attribute,
  292.                     DEFAULT_SCREEN_HANDLE );
  293.  
  294.  
  295.  
  296.     return;
  297.  
  298. }
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312. /*  VALIDATE_DRIVE() will tell us if a given drive letter is listed
  313.     on the logical drive map for this computer.
  314.  
  315.     It needs the following parameters to do this:
  316.             DRIVE_NUMBER    the NUMBER of the drive we are checking
  317.                             (A = 1, B = 2, C = 3, ..., Z = 26)
  318.             DRIVE_MAP       the map returned by the DosQCurDisk()
  319.                             system call
  320.  
  321.     It returns the following values:
  322.             TRUE            the drive is on the list.  It is VALID.
  323.             FALSE           there is no such drive on this machine. */
  324.  
  325.  
  326.  
  327.  
  328.  
  329. void    command_line_options( void )
  330. {
  331.     puts( "Valid parameters are:\n" );
  332.     puts( "\t/A\tcapture all ASCII characters whether or not they are printable\n" );
  333.     puts( "\t/X\tcapture only printable ASCII characters.  Replace the\n" );
  334.     puts( "\t\tnon-printable ASCII characters with dots.\n\n" );
  335.  
  336.     puts( "The following choices affect the name of the file used\n" );
  337.     puts( "to hold the text captured from the screen.\n" );
  338.  
  339.     puts( "\t/D\tthe letter of the drive to hold the file.\n" );
  340.     puts( "\t/P\tthe PATH to the file (OMIT the leading \\\n" );
  341.     puts( "\t/F\tthe file name (OMIT any drive or path names)\n" );
  342.     puts( "\n\n" );
  343.  
  344.     puts( "You may use either upper or lower case.\n" );
  345.     puts( "You may use these options in any order on the command line\n" );
  346.     puts( "\n\n" );
  347.  
  348.  
  349.  
  350.     return;
  351.  
  352. }
  353.  
  354.  
  355.  
  356. main(int argc, char *argv[], char *envp[] )
  357. {
  358.  
  359.     unsigned char   capture_flag;
  360.     USHORT          error;
  361.     int             x, i;
  362.     char            *marker, bad_module[ LONGEST_FILE_NAME + LONGEST_PATH_NAME ];
  363.     char            *comspec;
  364.     BYTE            *thread_stack;
  365.     TID             id;
  366.     SEL             selector;
  367.     RESULTCODES     result;
  368.  
  369.  
  370.     /*  Initialize some global variables.   */
  371.     strcpy( program_name, argv[0] );
  372.  
  373.     default_drive_name = '\0';
  374.     default_path_name[0] = default_file_name[0] = '\0';
  375.     strcpy( default_file_name, "screen.dat" );
  376.  
  377.     /*  Initialize the various prompts. */
  378.     strcpy( get_file_popup_title, "CAPTURE FILE NAME AND PATH" );
  379.     strcpy( drive_prompt, "Drive letter:" );
  380.     strcpy( directory_prompt, "Directory path: (Do NOT enter the TRAILING \\ ):" );
  381.     strcpy( file_prompt, "File name:" );
  382.     strcpy( ok_prompt, "Are the above entries correct? (Y or N):" );
  383.     strcpy( pause_prompt, "Hit any key to continue..." );
  384.     yes = 'Y';
  385.     no = 'N';
  386.  
  387.  
  388.  
  389.     /*  Command line parameters:
  390.             /A      capture ALL ASCII characters, both
  391.                     printable and non printable , from
  392.                     the screen.  (This is the DEFAULT
  393.                     condition.)
  394.             /X      capture ONLY PRONTABLE ASCII characters
  395.                     from the screen.  Replace non printable
  396.                     characters with dots.
  397.  
  398.             /D      drive name.
  399.             /P      path name.
  400.             /F      file name.
  401.  
  402.             /?      list the valid command line options.                    */
  403.  
  404.  
  405.     /*  Invent a default capture flag. */
  406.     capture_flag = ALL_ASCII_CHARACTERS;
  407.  
  408.     /*  Parse the command line. */
  409.     for( x = 1;  x < argc;  x++ )
  410.     {
  411.         switch( argv[x][0] )
  412.         {
  413.             case '-':
  414.             case '/':
  415.                 switch( argv[x][1] )
  416.                 {
  417.                     case 'a':
  418.                     case 'A':
  419.                         capture_flag = ALL_ASCII_CHARACTERS;
  420.                         break;
  421.  
  422.  
  423.                     case 'd':
  424.                     case 'D':
  425.                         x++;
  426.  
  427.                         if( x < argc )
  428.                         {
  429.                             default_drive_name = ( char )toupper( argv[x][0] );
  430.  
  431.                         }
  432.  
  433.                         break;
  434.  
  435.                     case 'f':
  436.                     case 'F':
  437.                         x++;
  438.  
  439.                         if( x < argc )
  440.                         {
  441.                             strcpy( default_file_name, argv[x] );
  442.  
  443.                         }
  444.                         break;
  445.  
  446.                     case 'p':
  447.                     case 'P':
  448.                         /* Copy the next command line parameter to internal storeage.   */
  449.                         x++;
  450.  
  451.                         if( x < argc )
  452.                         {
  453.                             strcpy( default_path_name, argv[x] );
  454.  
  455.                             /*  Strip opff any TRAILING \   */
  456.                             i = strlen( default_path_name );
  457.                             i--;
  458.  
  459.                             if( default_path_name[i] == '\\' )
  460.                             {
  461.                                 default_path_name[i] = '\0';
  462.  
  463.                             }
  464.  
  465.                             /*  Strip off any LEADING \ */
  466.                             for( marker = default_path_name;
  467.                                  *marker == '\\'; marker++ );
  468.  
  469.                             if( marker != default_path_name )
  470.                             {
  471.                                 strcpy( default_path_name, marker );
  472.  
  473.                             }
  474.  
  475.                         }
  476.  
  477.                         break;
  478.  
  479.                     case 'x':
  480.                     case 'X':
  481.                         capture_flag = PRINTABLE_ASCII_ONLY;
  482.                         break;
  483.  
  484.                     case '?':
  485.                         command_line_options();
  486.                         DosExit( EXIT_PROCESS, NO_ERROR );
  487.                         break;
  488.  
  489.  
  490.  
  491.                     default:
  492.                             printf( "\n\"%s\" is not a valid parameter\n",
  493.                                                   argv[x] );
  494.                             command_line_options();
  495.  
  496.  
  497.                 }
  498.  
  499.                 break;
  500.  
  501.             default:
  502.                 printf( "\n\"%s\" is not a valid parameter\n",
  503.                             argv[1] );
  504.                 command_line_options();
  505.  
  506.         }
  507.  
  508.     }
  509.  
  510.     /*  Allocate the stack space needed for our STACK KILLER thread.    */
  511.     DosAllocSeg( STACK_KILLER_STACK,
  512.                 &selector,
  513.                 NOSHARE_NODISCARD   );
  514.     thread_stack = ( BYTE *)MAKEP( selector, 0 );
  515.  
  516.     /*  Mark the stack we are about to use so that we can
  517.         monitor stack useage.       */
  518.     mark_stack( (char *)thread_stack,
  519.                 STACK_KILLER_STACK              );
  520.  
  521.  
  522.     /*  Start the thread that will free the stack of threads
  523.         that have exited.   */
  524.     DosCreateThread( free_the_stack,
  525.                     &id,
  526.                     ( BYTE *)&thread_stack[ STACK_KILLER_STACK - 1 ]   );
  527.  
  528.     /*  Get the name of our command processor.  */
  529.     DosScanEnv( "COMSPEC", &comspec );
  530.  
  531.     /*  Generate a new command line.    */
  532.     DosExecPgm( bad_module,
  533.                 sizeof( bad_module ),
  534.                 EXEC_ASYNC,
  535.                 ( PSZ )NULL,    //  Pass NO arguments.
  536.                 ( PSZ )NULL,    //  Pass PARENT's environment to child.
  537.                 &result,
  538.                 comspec     );
  539.  
  540.     /*  Start our keyboard monitor. */
  541.     error = monitor_the_keyboard();
  542.  
  543.     /*  Let the operator know that this program is ending.  */
  544.     pop_up( FAREWELL, comspec, error );
  545.  
  546.     DosExit( EXIT_PROCESS, NO_ERROR );
  547.  
  548.     return( NO_ERROR );
  549.  
  550. }
  551.