--- /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 <emulator.h>
+
+#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<LogTBufSize*2+1> 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<LogTBufSize*2+1> 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;
+ }