diff -r 000000000000 -r 5d03bc08d59c windowing/windowserver/debuglog/DEBLOGWN.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/windowing/windowserver/debuglog/DEBLOGWN.CPP Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,287 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// code for the Windows-dependent derived class +// +// + +#include "../SERVER/w32cmd.h" +#include + +#include "_windows.h" + +#include "DEBLOGWN.H" + + +// static container for sharing data between Symbian & Windows threads +struct TSharedMemory + { + RSemaphore iStartSemaphore; + struct HWND__* iHwnd; + }; + +static struct TSharedMemory GSharedMemory; + + +enum TWindowsUserMessage + { + EAppendText16, + EAppendText8, + }; + +// Constants +const int KMaxLogLines = 1000; +const int KAverageLogLineLength = 60; +const int KWinTimerId = 1; + + +EXPORT_C CDebugLogBase *CreateDebugLog(TBool aIsFirst, TDesC &aParams) + { + CDebugLogWin *device=new(ELeave) CDebugLogWin(); + CDebugLog *log=NULL; + TRAPD(err,log=new(ELeave) CDebugLog(device)); + if (err!=KErrNone) + { + delete device; + User::Leave(err); + } + TRAP(err,log->ConstructL(aIsFirst, aParams)); + if (err!=KErrNone) + { + delete log; + User::Leave(err); + } + return(log); + } + +CDebugLogWin::CDebugLogWin() :iThreadCreated(EFalse) + {} + +CDebugLogWin::~CDebugLogWin() + { + if (iThreadCreated) + { + if (GSharedMemory.iHwnd) + { + PostMessage(GSharedMemory.iHwnd, WM_CLOSE, 0, 0); + } + iThread.Close(); + iThreadCreated = 0; + GSharedMemory.iStartSemaphore.Close(); + } + } + +void CDebugLogWin::ConstructL(TBool , TDesC &) + { + _LIT(KLog,"DebugLog"); + GSharedMemory.iStartSemaphore.CreateLocal(0); + User::LeaveIfError(iThread.Create(KLog,logWinMain,KDefaultStackSize,KHeapSize,KHeapSize,(TAny *)123)); + iThreadCreated=ETrue; + iThread.Resume(); + GSharedMemory.iStartSemaphore.Wait(); + } + +void CDebugLogWin::WriteToLogL(const TDesC &aDes, const TDesC &aDes2) + { + TBuf bufPlusZero; + bufPlusZero.Copy(iTextBuf); + bufPlusZero.Append(aDes); + bufPlusZero.ZeroTerminate(); + TInt32 bufferAddr = (TInt32)(bufPlusZero.Ptr()); + // synchronously transfer string to debug window + Emulator::Escape(); + SendMessage(GSharedMemory.iHwnd, WM_USER + EAppendText16, 0, bufferAddr); + Emulator::Reenter(); + iTextBuf.Copy(aDes2); + } + +void CDebugLogWin::WriteToLog8L(const TDesC8 &aDes, const TDesC8 &aDes2) + { + TBuf8 bufPlusZero; + bufPlusZero.Copy(iTextBuf); + bufPlusZero.Append(aDes); + bufPlusZero.ZeroTerminate(); + TInt32 bufferAddr = (TInt32)(bufPlusZero.Ptr()); + // synchronously transfer string to debug window + Emulator::Escape(); + SendMessage(GSharedMemory.iHwnd, WM_USER + EAppendText8, 0, bufferAddr); + Emulator::Reenter(); + iTextBuf.Copy(aDes2); + } + +TInt32 __stdcall WndProc(struct HWND__ *aHwnd, TUint aMessage, + TUint wParam, TInt32 lParam) + { + static HWND hWndListBox; + static HFONT hfont; + static TBool timerSet = EFalse; + + switch (aMessage) + { + case WM_CREATE: + { // Disable Close menu option + HMENU menu = GetSystemMenu(aHwnd, FALSE); + EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); + + // create fixed pitch font for debug log + LOGFONT lf; + if (GetObject(hfont, sizeof(lf), &lf)) + { + lf.lfPitchAndFamily = FIXED_PITCH; + lstrcpy(lf.lfFaceName, L"courier"); + hfont = CreateFontIndirect(&lf); + } + else + { + hfont = CreateFont(16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, L"courier"); + } + + HINSTANCE hinstance = ((LPCREATESTRUCT) lParam) -> hInstance; + SendMessage(aHwnd, WM_SETFONT, (WPARAM) (hfont), 0); + RECT clientRect; + GetClientRect(aHwnd, &clientRect); + + hWndListBox = CreateWindowEx(WS_EX_CLIENTEDGE, + L"listbox", + NULL, + WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER | LBS_NOINTEGRALHEIGHT, + 0, 0, + clientRect.right, clientRect.bottom, + aHwnd, (HMENU) 1, hinstance, NULL); + SendMessage(hWndListBox, WM_SETFONT, (WPARAM) (hfont), 0); + + // preallocate string memory + SendMessage(hWndListBox, LB_INITSTORAGE, KMaxLogLines + 20, KAverageLogLineLength); + } + return 0; + + case WM_USER+EAppendText16: + { // send wide char string to ListBox + int numRows = SendMessageW(hWndListBox, LB_ADDSTRING, 0, lParam); + // if too many lines set a timer to delete some lines + if (!timerSet && (numRows > KMaxLogLines) ) + { // set a timer for 2s + SetTimer(aHwnd, KWinTimerId, 2000, NULL); + timerSet = ETrue; + } + + // scroll ListBox so that newest line is visible + SendMessage(hWndListBox, LB_SETTOPINDEX, numRows, 0); + } + return KErrNone; + + case WM_USER+EAppendText8: + { // send narrow character string to ListBox + int numRows = SendMessageA(hWndListBox, LB_ADDSTRING, 0, lParam); + // if too many lines set a timer to delete some lines + if (!timerSet && (numRows > KMaxLogLines) ) + { // set a timer for 2s + SetTimer(aHwnd, KWinTimerId, 2000, NULL); + timerSet = ETrue; + } + + // scroll ListBox so that newest line is visible + SendMessage(hWndListBox, LB_SETTOPINDEX, numRows, 0); + } + return KErrNone; + + case WM_TIMER: + { // too many rows in listbox, release some memory + TInt numRows; + do + { + numRows = SendMessage(hWndListBox, LB_DELETESTRING, 0, 0); + } + while (numRows > KMaxLogLines); + KillTimer(aHwnd, KWinTimerId); + timerSet = EFalse; + + // ensure newest line is visible (delete moves focus to line 0) + SendMessage(hWndListBox, LB_SETTOPINDEX, numRows-1, 0); + } + break; + + case WM_SIZE: + // forward to the ListBox, and make it repaint + if ( (wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED) ) + { + int width = LOWORD(lParam); + int height = HIWORD(lParam); + MoveWindow(hWndListBox, 0, 0, width, height, TRUE); + } + return 0; + + case WM_DESTROY: + PostQuitMessage(0); + DeleteObject(hfont); + return 0; + + case WM_SYSCOMMAND: + if (wParam == SC_CLOSE) + { // do not allow window to be closed with ALT-F4 (this would close the emulator) + return 1; + } + break; + } + + return DefWindowProc(aHwnd, aMessage, wParam, lParam); + } + +TInt logWinMain(TAny *) + { + MSG msg; + WNDCLASS wndclass; + const TText *szAppName=_S("Window Server Log"); + + wndclass.style=CS_HREDRAW|CS_VREDRAW; + wndclass.lpfnWndProc=WndProc; + wndclass.cbClsExtra=0; + wndclass.cbWndExtra=0; + wndclass.hInstance=NULL; + wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION); + wndclass.hCursor=LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground=(HBRUSH)GetSysColorBrush(COLOR_BTNFACE); + wndclass.lpszMenuName=NULL; + wndclass.lpszClassName=(LPCTSTR)szAppName; + + RegisterClass(&wndclass); + + GSharedMemory.iHwnd = CreateWindow((LPCTSTR)szAppName, + (LPCTSTR)szAppName, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + NULL, + NULL); + + ShowWindow(GSharedMemory.iHwnd, SW_SHOWMINNOACTIVE); + + GSharedMemory.iStartSemaphore.Signal(); // allows logging to start now that the window, etc. has been set up + + // Must remove thread from Symbian scheduler before calling blocking Windows APIs (e.g. GetMessage) + Emulator::Escape(); + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + // return to Symbian Scheduler + Emulator::Reenter(); + GSharedMemory.iHwnd = NULL; + return msg.wParam; + }