summaryrefslogtreecommitdiff
path: root/plugins/MirandaG15/src/LCDFramework/ConStream.cpp
blob: 4c09b830ac09eaf8f6248e54acce228fcf6711cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//
// ConStream.cpp: implementation of the ConStream class.
//
// Mark Nelson, October 17, 1998
//
// The ConStream class creates a C++ ostream object that can be 
// used in Win32 C++ programs to write to a console window, often
// for debugging purposes. This code is demonstrated in the 
// ConStreamDemo MFC program, and is fully explained in the 
// accompanying Dr. Dobb's Journal article. For more details,
// see the article online at http://www.dogma.net/markn
//

//
// Implementation of this class requires that you link in the IO.H
// and FCNTL.H header files from the standard C library. You should
// be able to substitute <cio> and <cfcnt> for these two includes.
// stdafx.h is here because the code is being used in an MFC application
// 

#include "stdafx.h"
#include <io.h>
#include <fcntl.h>

#include "ConStream.h"

//
// The ConStream constructor initializes the object to point to the 
// NUL device. It does this by calling two consecutive constructors.
// First, the member variable m_Nul is initialized with a FILE object
// created by opening device "nul", the bit bucket. Second, the base
// class constructor is called with a reference to m_Nul, which is
// an ofstream object. This sets up ConStream so that it will direct
// its output to the given file.
//
ConStream::ConStream() : m_Nul( m_fNul = fopen( "nul", "w" ) ), m_fConsole(nullptr),
#ifdef _UNICODE
                         basic_ostream<wchar_t>( &m_Nul ) 
#else
                         basic_ostream<char>( &m_Nul ) 
#endif
{
    m_FileBuf = nullptr;
    m_hConsole = INVALID_HANDLE_VALUE;
}

//
// The ConStream destructor always has to close the m_fNul FILE object
// which was created in the constructor. Even if the Open() method has
// been called and the bit bucket isn't being used, the FILE object is
// still using memory and a system file handle.
//
// If the ConStream object has been opened with a call to member function
// Open(), we have to call the Win32 API function FreeConsole() to close
// the console window. If the console window was open, we also call the
// C fclose() function on the m_fConsole member.
//
ConStream::~ConStream()
{
    delete m_FileBuf;
    if ( m_hConsole != INVALID_HANDLE_VALUE ) {
        FreeConsole();
        fclose( m_fConsole );
    }
    fclose( m_fNul );
}

//
// Opening the stream means doing these things:
//   1) Opening a Win32 console using the Win32 API
//   2) Getting an O/S handle to the console
//   3) Converting the O/S handle to a C stdio file handle
//   4) Converting the C stdio file handler to a C FILE object
//   5) Attaching the C FILE object to a C++ filebuf
//   6) Attaching the filebuf object to this
//   7) Disabling buffering so we see our output in real time.
//
void ConStream::Open()
{
    if ( m_hConsole == INVALID_HANDLE_VALUE ) {
		AllocConsole();
		m_hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
		int handle = _open_osfhandle((INT_PTR)m_hConsole, _O_TEXT );
		m_fConsole = _fdopen( handle, "w" );
#ifdef _UNICODE
		m_FileBuf = new basic_filebuf<wchar_t>( m_fConsole );
#else
		m_FileBuf = new basic_filebuf<char>( m_fConsole );
#endif
		init( m_FileBuf );
		setf(ios::unitbuf);
	}
};

//
// Closing the ConStream is considerably simpler. We just use the
// init() call to attach this to the NUL file stream, then close
// the console descriptors.
//
void ConStream::Close()
{
    if ( m_hConsole != INVALID_HANDLE_VALUE ) {
        init( &m_Nul );
        FreeConsole();
        fclose( m_fConsole );
        m_hConsole = INVALID_HANDLE_VALUE;
    }
};