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