image
 
image
ConsoleInfo.java


/*::.
==================================================================================================================================
=================================================¦ Copyright © 2014 Allen Baker ¦=================================================
                                                 +------------------------------+
File:       ConsoleInfo.java
Originator: Allen Baker (2014.07.04 20:44)
LayoutRev:  5
================================================================================================================================== */
package cosmicabyss.com.lib;

import java.io.*;
import java.util.*;
import java.net.*;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;



/*::
======================================================================================================================== *//**
Instances of this class represent a Windows console window. This class leverages the Java Native Access (JNA) libraries
which are located at: https://github.com/twall/jna.<P>

Salient characteristics of ConsoleInfos are:
   <BLOCKQUOTE>
      => It accesses a native Windows library to get the Windows-specific console screen properties.
   </BLOCKQUOTE>

<P>
   <DL>
      <DT>
         <B>
            Example usage:
         </B>
         <DD>
            <BLOCKQUOTE>
               <PRE id="unindent">
                  =========================================================================================
                  Get a the properties of the current console window directly from the OS.
                  -----------------------------------------------------------------------------------------
                  Kernel32.ConsoleWindowScreenBufferInfo  theInfo = info();

                  System.out.printf("size .x=%d .y=%d\n", theInfo.wSizeX, theInfo.wSizeY);
                  System.out.printf("cursor .x=%d .y=%d\n", theInfo.wCursorPositionX, theInfo.wCursorPositionY);
                  System.out.printf("window .left=%d .top=%d .right=%d .bottom=%d\n", theInfo.wWindowLeft, theInfo.wWindowTop, theInfo.wWindowRight, theInfo.wWindowBottom);
                  System.out.printf("max-window-size .x=%d .y=%d\n", theInfo.wMaximumWindowSizeX, theInfo.wMaximumWindowSizeY);

                  System.out.println("WIDTH IS " + width());
               </PRE>
            </BLOCKQUOTE>
         </DD>
      </DT>
      <DT>
         <B>
            View Source:
         </B>
         <DD>
            <A href="ConsoleInfo.java.html">
               ConsoleInfo.java
            </A>
         </DD>
      </DT>
      <DT>
         <B>
            Author:
         </B>
         <DD>
            <A href="mailto:sourcecode.v01@cosmicabyss.com">
               Allen Baker
            </A>
         </DD>
      </DT>
   </DL>
*//*
======================================================================================================================== */
public class ConsoleInfo
   {



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Constants  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*.
   ==========================================================================================
   CLASS_NAME:
      The name of this class
   DFLT_LINE_LEN:
      The default line length for word wrapping
   ------------------------------------------------------------------------------------------ */
   private static final XString  CLASS_NAME    = new XString(ConsoleInfo.class.getName());
   private static final int      DFLT_LINE_LEN = ConsoleMessage.defaultLineLength();



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Types  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */
   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Enums  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */
   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Structs  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */
   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Classes  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */
   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Interfaces  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */



   public interface Kernel32 extends StdCallLibrary
      {
      Kernel32 INSTANCE = (Kernel32)
      Native.loadLibrary("kernel32", Kernel32.class);

      int  STD_INPUT_HANDLE  = -10;
      int  STD_OUTPUT_HANDLE = -11;
      int  STD_ERROR_HANDLE  = -12;

      int GetStdHandle(int nStdHandle);

      public static class ConsoleWindowScreenBufferInfo extends Structure
         {
         public short wSizeX;  // effective console width
         public short wSizeY;
         public short wCursorPositionX;
         public short wCursorPositionY;
         public short wAttributes;
         public short wWindowLeft;
         public short wWindowTop;
         public short wWindowRight;
         public short wWindowBottom;
         public short wMaximumWindowSizeX;
         public short wMaximumWindowSizeY;
         }

      boolean GetConsoleScreenBufferInfo(int hConsoleOutput, ConsoleWindowScreenBufferInfo lpConsoleScreenBufferInfo);
      }



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Variables  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*.
   ==========================================================================================
   cOut:
      Formatted and time-stamped console output.
   ------------------------------------------------------------------------------------------ */
   private static ConsoleStream  cOut = ConsoleStream.getSingleton();



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Functions  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */
   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Constructors  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */



   /*:                                    :METHOD:000:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a ConsoleInfo class object.

   <P><B>Implementation: </B><A HREF="ConsoleInfo.java.html#000">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleInfo() throws Exception
      {
      initializeInstanceConstantsAndVariables();
      }



   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Initialization  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */



   static
      {
      /*.
      ==========================================================================================
      Make sure all the class constants and variables are initialized the first time the JVM
      loads this class code and before anything else in this class is accessed
      ------------------------------------------------------------------------------------------ */
      initializeClassConstantsAndVariables();
      }



   /*:                                    :METHOD:001:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method initializes all the class constants and variables

   <P><B>Implementation: </B><A HREF="ConsoleInfo.java.html#001">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private static void initializeClassConstantsAndVariables()
      {
      }



   /*:                                    :METHOD:002:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method initializes all the instance constants and variables. The intent of this method is to
   encapsulate all the common instance initializations in one place that can be called from all the
   constructors.

   <P><B>Implementation: </B><A HREF="ConsoleInfo.java.html#002">View source</A>

   @return
      True if the initialization succeeded, flase otherwise.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   private boolean initializeInstanceConstantsAndVariables() throws Exception
      {
      boolean  successCode = true;

      if (successCode)
         {
         }
      return successCode;
      }



   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Methods  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */



   /*:                                    :METHOD:003:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method sets the ConsoleStream for this object.

   <P><B>Implementation: </B><A HREF="ConsoleInfo.java.html#003">View source</A>

   @return
      A reference to this object

   @param
      pConsole is a ConsoleStream through which this objects sends its output.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleInfo setOut(ConsoleStream pConsole)
      {
      cOut = pConsole;
      return this;
      }



   /*:                                    :METHOD:004:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This boilerplate method is used for testing an instantiated object of this class and may include any
   code the developer chooses.

   <P><B>Implementation: </B><A HREF="ConsoleInfo.java.html#004">View source</A>

   @return
      A reference to this object
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleInfo test() throws Exception
      {
      cOut.titledPrintf
         (
         "\"HELLO WORLD!\"",
         "%s  %s  %s",
         "I'm an object of the", CLASS_NAME, "class, and I approved this message."
         );

      Kernel32.ConsoleWindowScreenBufferInfo  theInfo = info();

      System.out.printf("size .x=%d .y=%d\n", theInfo.wSizeX, theInfo.wSizeY);
      System.out.printf("cursor .x=%d .y=%d\n", theInfo.wCursorPositionX, theInfo.wCursorPositionY);
      System.out.printf("window .left=%d .top=%d .right=%d .bottom=%d\n", theInfo.wWindowLeft, theInfo.wWindowTop, theInfo.wWindowRight, theInfo.wWindowBottom);
      System.out.printf("max-window-size .x=%d .y=%d\n", theInfo.wMaximumWindowSizeX, theInfo.wMaximumWindowSizeY);

      System.out.println("WIDTH IS " + width());

      return this;
      }



   /*:                                    :METHOD:005:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns the ConsoleWindowScreenBufferInfo for the current console window.

   <P><B>Implementation: </B><A HREF="ConsoleInfo.java.html#005">View source</A>

   @return
      This method returns the ConsoleWindowScreenBufferInfo for the current console window.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static Kernel32.ConsoleWindowScreenBufferInfo info()
      {
      Kernel32                                lib     = Kernel32.INSTANCE;
      int                                     h       = lib.GetStdHandle(Kernel32.STD_OUTPUT_HANDLE);
      Kernel32.ConsoleWindowScreenBufferInfo  theInfo = new Kernel32.ConsoleWindowScreenBufferInfo();

      lib.GetConsoleScreenBufferInfo(h, theInfo);

      return theInfo;
      }



   /*:                                    :METHOD:006:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns the width in characters for the current console window.

   NOTICE! Hard-learned info to follow - I chased my tail for quite a while on it:
      The Kernel32 call through GetConsoleScreenBufferInfo() apparently returns 0 for the screen width
      whenever stdout is redirected or piped from the commandline. For example, this line which is
      paraphrased from the batch file MirrorInternalDrive.bat and redirects stdout to logfile.txt:
         <BLOCKQUOTE>
            <PRE id="unindent">
               call mirror I:\  J:\  >>  logfile.txt
            </PRE>
         </BLOCKQUOTE>
      Invokes DirectoryPruner.class. DirectoryPruner.class uses this method to find the
      Console window width. Without the redirection, it works fine; with the redirection, this method -
      width() - returns 0. Therefor, I inserted code into width() to return 200 instead of
      theInfo.wMaximumWindowSizeX if theInfo.wMaximumWindowSizeX is 0.

         200 is a total guess at the minimum likely cmd window width.

   <P><B>Implementation: </B><A HREF="ConsoleInfo.java.html#006">View source</A>

   @return
      This method returns the width in characters for the current console window or 200 if the system
      call retuns 0 for a screen window width..
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static int width()
      {
      int result = 0;
      Kernel32.ConsoleWindowScreenBufferInfo  theInfo = info();
      result = (theInfo.wMaximumWindowSizeX == 0)? 200 : theInfo.wMaximumWindowSizeX;
      return result;
      }



   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Main  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */



   /*:                                    :METHOD:007:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method allows this class file to be unit tested as a standalone application. It's the method
   that's called when the class is invoked from the command line by using the java application launcher
   - "java". Main() is not a required method, but the practice of putting one in each class and
   wrapping class test code within it allows easy unit testing of the class; and main does not need to
   be removed when testing is complete.

   <P>
      <DL>
         <DT>
            <B>
               Command line usage:
            </B>
            <DD>
               Java cosmicabyss.com.lib.ConsoleInfo
            </DD>
         </DT>
      </DL>

   <P><B>Implementation: </B><A HREF="ConsoleInfo.java.html#007">View source</A>

   @param
      pArgs contains the command line arguments with which this class was invoked as an application.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static void main(String[] pArgs) throws Exception
      {
      /*.
      ==========================================================================================
      Greetings !
      ------------------------------------------------------------------------------------------ */
      cOut.banner(CLASS_NAME);
      /*.
      ==========================================================================================
      Create an object and send its output to the ConsoleStream
      ------------------------------------------------------------------------------------------ */
      ConsoleInfo  obj = new ConsoleInfo();
      /*.
      ==========================================================================================
      Test code
      ------------------------------------------------------------------------------------------ */
      obj.test();
      }



   }  // End of Class ConsoleInfo



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Notes  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */
   /*:                                    :METHOD:008:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method => -> -- c c c c c c c

   <P><B>Implementation: </B><A HREF="ConsoleInfo.java.html#008">View source</A>

   @return
      This method returns

   @exception
      Xx is thrown when
   @exception
      Yy is thrown when

   @param
      PX (optional)(input/output)(output) is the
   @param
      PY (optional)(input/output)(output) is the
   *//*
   ---------------------------------------------------------------------------------------------------- */
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Section Level 0 Banner  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */
   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Section Level 1 Banner  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */
   /*:.
   ==============================================================================================================
   :::::::::::::::::::::::::::::::::::::::::[  Section Level 2 Banner  ]:::::::::::::::::::::::::::::::::::::::::
   ============================================================================================================== */
   /*:.
   ==============================================================================================================
   -----------------------------------------[  Section Level 3 Banner  ]-----------------------------------------
   ============================================================================================================== */
   /*:.
   ==============================================================================================================
                                            [  Section Level 4 Banner  ]
   ============================================================================================================== */