os/graphics/windowing/windowserver/debuglog/DEBLOGWN.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// code for the Windows-dependent derived class 
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "../SERVER/w32cmd.h"
sl@0
    19
#include <emulator.h>
sl@0
    20
sl@0
    21
#include "_windows.h"
sl@0
    22
sl@0
    23
#include "DEBLOGWN.H"
sl@0
    24
sl@0
    25
sl@0
    26
// static container for sharing data between Symbian & Windows threads
sl@0
    27
struct TSharedMemory
sl@0
    28
	{
sl@0
    29
	RSemaphore		iStartSemaphore;
sl@0
    30
	struct HWND__*	iHwnd;
sl@0
    31
	};
sl@0
    32
sl@0
    33
static struct TSharedMemory GSharedMemory;
sl@0
    34
sl@0
    35
sl@0
    36
enum TWindowsUserMessage
sl@0
    37
	{
sl@0
    38
	EAppendText16,
sl@0
    39
	EAppendText8,
sl@0
    40
	};
sl@0
    41
sl@0
    42
// Constants
sl@0
    43
const int KMaxLogLines = 1000;
sl@0
    44
const int KAverageLogLineLength = 60;
sl@0
    45
const int KWinTimerId = 1;
sl@0
    46
sl@0
    47
sl@0
    48
EXPORT_C CDebugLogBase *CreateDebugLog(TBool aIsFirst, TDesC &aParams)
sl@0
    49
	{
sl@0
    50
	CDebugLogWin *device=new(ELeave) CDebugLogWin();
sl@0
    51
	CDebugLog *log=NULL;
sl@0
    52
	TRAPD(err,log=new(ELeave) CDebugLog(device));
sl@0
    53
	if (err!=KErrNone)
sl@0
    54
		{
sl@0
    55
		delete device;
sl@0
    56
		User::Leave(err);
sl@0
    57
		}
sl@0
    58
	TRAP(err,log->ConstructL(aIsFirst, aParams));
sl@0
    59
	if (err!=KErrNone)
sl@0
    60
		{
sl@0
    61
		delete log;
sl@0
    62
		User::Leave(err);
sl@0
    63
		}
sl@0
    64
	return(log);
sl@0
    65
	}
sl@0
    66
sl@0
    67
CDebugLogWin::CDebugLogWin() :iThreadCreated(EFalse)
sl@0
    68
	{}
sl@0
    69
sl@0
    70
CDebugLogWin::~CDebugLogWin()
sl@0
    71
	{
sl@0
    72
	if (iThreadCreated)
sl@0
    73
		{
sl@0
    74
		if (GSharedMemory.iHwnd)
sl@0
    75
			{
sl@0
    76
			PostMessage(GSharedMemory.iHwnd, WM_CLOSE, 0, 0);
sl@0
    77
			}
sl@0
    78
		iThread.Close();
sl@0
    79
		iThreadCreated = 0;
sl@0
    80
		GSharedMemory.iStartSemaphore.Close();
sl@0
    81
		}
sl@0
    82
	}
sl@0
    83
sl@0
    84
void CDebugLogWin::ConstructL(TBool , TDesC &)
sl@0
    85
	{
sl@0
    86
	_LIT(KLog,"DebugLog");
sl@0
    87
	GSharedMemory.iStartSemaphore.CreateLocal(0);
sl@0
    88
	User::LeaveIfError(iThread.Create(KLog,logWinMain,KDefaultStackSize,KHeapSize,KHeapSize,(TAny *)123));
sl@0
    89
	iThreadCreated=ETrue;
sl@0
    90
	iThread.Resume();
sl@0
    91
	GSharedMemory.iStartSemaphore.Wait();
sl@0
    92
	}
sl@0
    93
sl@0
    94
void CDebugLogWin::WriteToLogL(const TDesC &aDes, const TDesC &aDes2)
sl@0
    95
	{
sl@0
    96
	TBuf<LogTBufSize*2+1> bufPlusZero;
sl@0
    97
	bufPlusZero.Copy(iTextBuf);
sl@0
    98
	bufPlusZero.Append(aDes);
sl@0
    99
	bufPlusZero.ZeroTerminate();
sl@0
   100
	TInt32 bufferAddr = (TInt32)(bufPlusZero.Ptr());
sl@0
   101
	// synchronously transfer string to debug window
sl@0
   102
	Emulator::Escape();
sl@0
   103
	SendMessage(GSharedMemory.iHwnd, WM_USER + EAppendText16, 0, bufferAddr);
sl@0
   104
	Emulator::Reenter();
sl@0
   105
	iTextBuf.Copy(aDes2);
sl@0
   106
	}
sl@0
   107
sl@0
   108
void CDebugLogWin::WriteToLog8L(const TDesC8 &aDes, const TDesC8 &aDes2)
sl@0
   109
	{
sl@0
   110
	TBuf8<LogTBufSize*2+1> bufPlusZero;
sl@0
   111
	bufPlusZero.Copy(iTextBuf);
sl@0
   112
	bufPlusZero.Append(aDes);
sl@0
   113
	bufPlusZero.ZeroTerminate();
sl@0
   114
	TInt32 bufferAddr = (TInt32)(bufPlusZero.Ptr());
sl@0
   115
	// synchronously transfer string to debug window
sl@0
   116
	Emulator::Escape();
sl@0
   117
	SendMessage(GSharedMemory.iHwnd, WM_USER + EAppendText8, 0, bufferAddr);
sl@0
   118
	Emulator::Reenter();
sl@0
   119
	iTextBuf.Copy(aDes2);
sl@0
   120
	}
sl@0
   121
sl@0
   122
TInt32 __stdcall WndProc(struct HWND__ *aHwnd, TUint aMessage,
sl@0
   123
						TUint wParam, TInt32 lParam)
sl@0
   124
	{
sl@0
   125
	static HWND hWndListBox;
sl@0
   126
	static HFONT hfont;
sl@0
   127
	static TBool timerSet = EFalse;
sl@0
   128
sl@0
   129
	switch (aMessage)
sl@0
   130
		{
sl@0
   131
	case WM_CREATE:
sl@0
   132
			{ // Disable Close menu option
sl@0
   133
			HMENU menu = GetSystemMenu(aHwnd, FALSE);
sl@0
   134
			EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
sl@0
   135
sl@0
   136
			// create fixed pitch font for debug log
sl@0
   137
			LOGFONT lf;
sl@0
   138
			if (GetObject(hfont, sizeof(lf), &lf))
sl@0
   139
				{
sl@0
   140
				lf.lfPitchAndFamily = FIXED_PITCH;
sl@0
   141
				lstrcpy(lf.lfFaceName, L"courier");
sl@0
   142
				hfont = CreateFontIndirect(&lf);
sl@0
   143
				}
sl@0
   144
			else
sl@0
   145
				{
sl@0
   146
				hfont = CreateFont(16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
sl@0
   147
						OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, L"courier");
sl@0
   148
				}
sl@0
   149
sl@0
   150
			HINSTANCE hinstance = ((LPCREATESTRUCT) lParam) -> hInstance;
sl@0
   151
			SendMessage(aHwnd, WM_SETFONT, (WPARAM) (hfont), 0);
sl@0
   152
			RECT clientRect;
sl@0
   153
			GetClientRect(aHwnd, &clientRect);
sl@0
   154
sl@0
   155
			hWndListBox = CreateWindowEx(WS_EX_CLIENTEDGE,
sl@0
   156
										L"listbox",
sl@0
   157
										NULL,
sl@0
   158
										WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER | LBS_NOINTEGRALHEIGHT,
sl@0
   159
										0, 0,
sl@0
   160
										clientRect.right, clientRect.bottom,
sl@0
   161
										aHwnd, (HMENU) 1, hinstance, NULL);
sl@0
   162
			SendMessage(hWndListBox, WM_SETFONT, (WPARAM) (hfont), 0);
sl@0
   163
sl@0
   164
			// preallocate string memory
sl@0
   165
			SendMessage(hWndListBox, LB_INITSTORAGE, KMaxLogLines + 20, KAverageLogLineLength);
sl@0
   166
			}
sl@0
   167
		return 0;
sl@0
   168
sl@0
   169
	case WM_USER+EAppendText16:
sl@0
   170
			{ // send wide char string to ListBox
sl@0
   171
			int numRows = SendMessageW(hWndListBox, LB_ADDSTRING, 0, lParam);
sl@0
   172
			// if too many lines set a timer to delete some lines
sl@0
   173
			if (!timerSet && (numRows > KMaxLogLines) )
sl@0
   174
				{ // set a timer for 2s
sl@0
   175
				SetTimer(aHwnd, KWinTimerId, 2000, NULL);
sl@0
   176
				timerSet = ETrue;
sl@0
   177
				}
sl@0
   178
sl@0
   179
			// scroll ListBox so that newest line is visible
sl@0
   180
			SendMessage(hWndListBox, LB_SETTOPINDEX, numRows, 0);
sl@0
   181
			}
sl@0
   182
		return KErrNone;
sl@0
   183
sl@0
   184
	case WM_USER+EAppendText8:
sl@0
   185
			{ // send narrow character string to ListBox
sl@0
   186
			int numRows = SendMessageA(hWndListBox, LB_ADDSTRING, 0, lParam);
sl@0
   187
			// if too many lines set a timer to delete some lines
sl@0
   188
			if (!timerSet && (numRows > KMaxLogLines) )
sl@0
   189
				{ // set a timer for 2s
sl@0
   190
				SetTimer(aHwnd, KWinTimerId, 2000, NULL);
sl@0
   191
				timerSet = ETrue;
sl@0
   192
				}
sl@0
   193
		
sl@0
   194
			// scroll ListBox so that newest line is visible
sl@0
   195
			SendMessage(hWndListBox, LB_SETTOPINDEX, numRows, 0);
sl@0
   196
			}
sl@0
   197
		return KErrNone;
sl@0
   198
sl@0
   199
	case WM_TIMER:
sl@0
   200
			{ // too many rows in listbox, release some memory
sl@0
   201
			TInt numRows;	
sl@0
   202
			do
sl@0
   203
				{
sl@0
   204
				numRows = SendMessage(hWndListBox, LB_DELETESTRING, 0, 0);
sl@0
   205
				}
sl@0
   206
				while (numRows > KMaxLogLines);
sl@0
   207
			KillTimer(aHwnd, KWinTimerId);
sl@0
   208
			timerSet = EFalse;
sl@0
   209
sl@0
   210
			// ensure newest line is visible (delete moves focus to line 0)
sl@0
   211
			SendMessage(hWndListBox, LB_SETTOPINDEX, numRows-1, 0);
sl@0
   212
			}
sl@0
   213
		break;
sl@0
   214
sl@0
   215
	case WM_SIZE:
sl@0
   216
		// forward to the ListBox, and make it repaint
sl@0
   217
		if ( (wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED) )
sl@0
   218
			{
sl@0
   219
			int width = LOWORD(lParam);
sl@0
   220
			int height = HIWORD(lParam);
sl@0
   221
			MoveWindow(hWndListBox, 0, 0, width, height, TRUE);
sl@0
   222
			}
sl@0
   223
		return 0;
sl@0
   224
sl@0
   225
	case WM_DESTROY:
sl@0
   226
		PostQuitMessage(0);
sl@0
   227
		DeleteObject(hfont);
sl@0
   228
		return 0;
sl@0
   229
sl@0
   230
	case WM_SYSCOMMAND:
sl@0
   231
		if (wParam == SC_CLOSE)
sl@0
   232
			{ // do not allow window to be closed with ALT-F4 (this would close the emulator)
sl@0
   233
			return 1;
sl@0
   234
			}
sl@0
   235
		break;
sl@0
   236
		}
sl@0
   237
sl@0
   238
	return DefWindowProc(aHwnd, aMessage, wParam, lParam);
sl@0
   239
	}
sl@0
   240
sl@0
   241
TInt logWinMain(TAny *)
sl@0
   242
	{
sl@0
   243
	MSG msg;
sl@0
   244
	WNDCLASS wndclass;
sl@0
   245
	const TText *szAppName=_S("Window Server Log");
sl@0
   246
sl@0
   247
	wndclass.style=CS_HREDRAW|CS_VREDRAW;
sl@0
   248
	wndclass.lpfnWndProc=WndProc;
sl@0
   249
	wndclass.cbClsExtra=0;
sl@0
   250
	wndclass.cbWndExtra=0;
sl@0
   251
	wndclass.hInstance=NULL;
sl@0
   252
	wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
sl@0
   253
	wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);
sl@0
   254
	wndclass.hbrBackground=(HBRUSH)GetSysColorBrush(COLOR_BTNFACE);
sl@0
   255
	wndclass.lpszMenuName=NULL;
sl@0
   256
	wndclass.lpszClassName=(LPCTSTR)szAppName;
sl@0
   257
sl@0
   258
	RegisterClass(&wndclass);
sl@0
   259
sl@0
   260
	GSharedMemory.iHwnd = CreateWindow((LPCTSTR)szAppName,
sl@0
   261
					(LPCTSTR)szAppName,
sl@0
   262
					WS_OVERLAPPEDWINDOW,
sl@0
   263
					CW_USEDEFAULT,
sl@0
   264
					CW_USEDEFAULT,
sl@0
   265
					CW_USEDEFAULT,
sl@0
   266
					CW_USEDEFAULT,
sl@0
   267
					NULL,
sl@0
   268
					NULL,
sl@0
   269
					NULL,
sl@0
   270
					NULL);
sl@0
   271
sl@0
   272
	ShowWindow(GSharedMemory.iHwnd, SW_SHOWMINNOACTIVE);
sl@0
   273
sl@0
   274
	GSharedMemory.iStartSemaphore.Signal(); // allows logging to start now that the window, etc. has been set up
sl@0
   275
sl@0
   276
	// Must remove thread from Symbian scheduler before calling blocking Windows APIs (e.g. GetMessage)
sl@0
   277
	Emulator::Escape();
sl@0
   278
	while (GetMessage(&msg, NULL, 0, 0))
sl@0
   279
		{
sl@0
   280
		TranslateMessage(&msg);
sl@0
   281
		DispatchMessage(&msg);
sl@0
   282
		}
sl@0
   283
	// return to Symbian Scheduler
sl@0
   284
	Emulator::Reenter();
sl@0
   285
	GSharedMemory.iHwnd = NULL;
sl@0
   286
	return msg.wParam;
sl@0
   287
	}