1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/windowing/windowserver/debuglog/DEBLOGWN.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,287 @@
1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// code for the Windows-dependent derived class
1.18 +//
1.19 +//
1.20 +
1.21 +#include "../SERVER/w32cmd.h"
1.22 +#include <emulator.h>
1.23 +
1.24 +#include "_windows.h"
1.25 +
1.26 +#include "DEBLOGWN.H"
1.27 +
1.28 +
1.29 +// static container for sharing data between Symbian & Windows threads
1.30 +struct TSharedMemory
1.31 + {
1.32 + RSemaphore iStartSemaphore;
1.33 + struct HWND__* iHwnd;
1.34 + };
1.35 +
1.36 +static struct TSharedMemory GSharedMemory;
1.37 +
1.38 +
1.39 +enum TWindowsUserMessage
1.40 + {
1.41 + EAppendText16,
1.42 + EAppendText8,
1.43 + };
1.44 +
1.45 +// Constants
1.46 +const int KMaxLogLines = 1000;
1.47 +const int KAverageLogLineLength = 60;
1.48 +const int KWinTimerId = 1;
1.49 +
1.50 +
1.51 +EXPORT_C CDebugLogBase *CreateDebugLog(TBool aIsFirst, TDesC &aParams)
1.52 + {
1.53 + CDebugLogWin *device=new(ELeave) CDebugLogWin();
1.54 + CDebugLog *log=NULL;
1.55 + TRAPD(err,log=new(ELeave) CDebugLog(device));
1.56 + if (err!=KErrNone)
1.57 + {
1.58 + delete device;
1.59 + User::Leave(err);
1.60 + }
1.61 + TRAP(err,log->ConstructL(aIsFirst, aParams));
1.62 + if (err!=KErrNone)
1.63 + {
1.64 + delete log;
1.65 + User::Leave(err);
1.66 + }
1.67 + return(log);
1.68 + }
1.69 +
1.70 +CDebugLogWin::CDebugLogWin() :iThreadCreated(EFalse)
1.71 + {}
1.72 +
1.73 +CDebugLogWin::~CDebugLogWin()
1.74 + {
1.75 + if (iThreadCreated)
1.76 + {
1.77 + if (GSharedMemory.iHwnd)
1.78 + {
1.79 + PostMessage(GSharedMemory.iHwnd, WM_CLOSE, 0, 0);
1.80 + }
1.81 + iThread.Close();
1.82 + iThreadCreated = 0;
1.83 + GSharedMemory.iStartSemaphore.Close();
1.84 + }
1.85 + }
1.86 +
1.87 +void CDebugLogWin::ConstructL(TBool , TDesC &)
1.88 + {
1.89 + _LIT(KLog,"DebugLog");
1.90 + GSharedMemory.iStartSemaphore.CreateLocal(0);
1.91 + User::LeaveIfError(iThread.Create(KLog,logWinMain,KDefaultStackSize,KHeapSize,KHeapSize,(TAny *)123));
1.92 + iThreadCreated=ETrue;
1.93 + iThread.Resume();
1.94 + GSharedMemory.iStartSemaphore.Wait();
1.95 + }
1.96 +
1.97 +void CDebugLogWin::WriteToLogL(const TDesC &aDes, const TDesC &aDes2)
1.98 + {
1.99 + TBuf<LogTBufSize*2+1> bufPlusZero;
1.100 + bufPlusZero.Copy(iTextBuf);
1.101 + bufPlusZero.Append(aDes);
1.102 + bufPlusZero.ZeroTerminate();
1.103 + TInt32 bufferAddr = (TInt32)(bufPlusZero.Ptr());
1.104 + // synchronously transfer string to debug window
1.105 + Emulator::Escape();
1.106 + SendMessage(GSharedMemory.iHwnd, WM_USER + EAppendText16, 0, bufferAddr);
1.107 + Emulator::Reenter();
1.108 + iTextBuf.Copy(aDes2);
1.109 + }
1.110 +
1.111 +void CDebugLogWin::WriteToLog8L(const TDesC8 &aDes, const TDesC8 &aDes2)
1.112 + {
1.113 + TBuf8<LogTBufSize*2+1> bufPlusZero;
1.114 + bufPlusZero.Copy(iTextBuf);
1.115 + bufPlusZero.Append(aDes);
1.116 + bufPlusZero.ZeroTerminate();
1.117 + TInt32 bufferAddr = (TInt32)(bufPlusZero.Ptr());
1.118 + // synchronously transfer string to debug window
1.119 + Emulator::Escape();
1.120 + SendMessage(GSharedMemory.iHwnd, WM_USER + EAppendText8, 0, bufferAddr);
1.121 + Emulator::Reenter();
1.122 + iTextBuf.Copy(aDes2);
1.123 + }
1.124 +
1.125 +TInt32 __stdcall WndProc(struct HWND__ *aHwnd, TUint aMessage,
1.126 + TUint wParam, TInt32 lParam)
1.127 + {
1.128 + static HWND hWndListBox;
1.129 + static HFONT hfont;
1.130 + static TBool timerSet = EFalse;
1.131 +
1.132 + switch (aMessage)
1.133 + {
1.134 + case WM_CREATE:
1.135 + { // Disable Close menu option
1.136 + HMENU menu = GetSystemMenu(aHwnd, FALSE);
1.137 + EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
1.138 +
1.139 + // create fixed pitch font for debug log
1.140 + LOGFONT lf;
1.141 + if (GetObject(hfont, sizeof(lf), &lf))
1.142 + {
1.143 + lf.lfPitchAndFamily = FIXED_PITCH;
1.144 + lstrcpy(lf.lfFaceName, L"courier");
1.145 + hfont = CreateFontIndirect(&lf);
1.146 + }
1.147 + else
1.148 + {
1.149 + hfont = CreateFont(16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
1.150 + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, L"courier");
1.151 + }
1.152 +
1.153 + HINSTANCE hinstance = ((LPCREATESTRUCT) lParam) -> hInstance;
1.154 + SendMessage(aHwnd, WM_SETFONT, (WPARAM) (hfont), 0);
1.155 + RECT clientRect;
1.156 + GetClientRect(aHwnd, &clientRect);
1.157 +
1.158 + hWndListBox = CreateWindowEx(WS_EX_CLIENTEDGE,
1.159 + L"listbox",
1.160 + NULL,
1.161 + WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER | LBS_NOINTEGRALHEIGHT,
1.162 + 0, 0,
1.163 + clientRect.right, clientRect.bottom,
1.164 + aHwnd, (HMENU) 1, hinstance, NULL);
1.165 + SendMessage(hWndListBox, WM_SETFONT, (WPARAM) (hfont), 0);
1.166 +
1.167 + // preallocate string memory
1.168 + SendMessage(hWndListBox, LB_INITSTORAGE, KMaxLogLines + 20, KAverageLogLineLength);
1.169 + }
1.170 + return 0;
1.171 +
1.172 + case WM_USER+EAppendText16:
1.173 + { // send wide char string to ListBox
1.174 + int numRows = SendMessageW(hWndListBox, LB_ADDSTRING, 0, lParam);
1.175 + // if too many lines set a timer to delete some lines
1.176 + if (!timerSet && (numRows > KMaxLogLines) )
1.177 + { // set a timer for 2s
1.178 + SetTimer(aHwnd, KWinTimerId, 2000, NULL);
1.179 + timerSet = ETrue;
1.180 + }
1.181 +
1.182 + // scroll ListBox so that newest line is visible
1.183 + SendMessage(hWndListBox, LB_SETTOPINDEX, numRows, 0);
1.184 + }
1.185 + return KErrNone;
1.186 +
1.187 + case WM_USER+EAppendText8:
1.188 + { // send narrow character string to ListBox
1.189 + int numRows = SendMessageA(hWndListBox, LB_ADDSTRING, 0, lParam);
1.190 + // if too many lines set a timer to delete some lines
1.191 + if (!timerSet && (numRows > KMaxLogLines) )
1.192 + { // set a timer for 2s
1.193 + SetTimer(aHwnd, KWinTimerId, 2000, NULL);
1.194 + timerSet = ETrue;
1.195 + }
1.196 +
1.197 + // scroll ListBox so that newest line is visible
1.198 + SendMessage(hWndListBox, LB_SETTOPINDEX, numRows, 0);
1.199 + }
1.200 + return KErrNone;
1.201 +
1.202 + case WM_TIMER:
1.203 + { // too many rows in listbox, release some memory
1.204 + TInt numRows;
1.205 + do
1.206 + {
1.207 + numRows = SendMessage(hWndListBox, LB_DELETESTRING, 0, 0);
1.208 + }
1.209 + while (numRows > KMaxLogLines);
1.210 + KillTimer(aHwnd, KWinTimerId);
1.211 + timerSet = EFalse;
1.212 +
1.213 + // ensure newest line is visible (delete moves focus to line 0)
1.214 + SendMessage(hWndListBox, LB_SETTOPINDEX, numRows-1, 0);
1.215 + }
1.216 + break;
1.217 +
1.218 + case WM_SIZE:
1.219 + // forward to the ListBox, and make it repaint
1.220 + if ( (wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED) )
1.221 + {
1.222 + int width = LOWORD(lParam);
1.223 + int height = HIWORD(lParam);
1.224 + MoveWindow(hWndListBox, 0, 0, width, height, TRUE);
1.225 + }
1.226 + return 0;
1.227 +
1.228 + case WM_DESTROY:
1.229 + PostQuitMessage(0);
1.230 + DeleteObject(hfont);
1.231 + return 0;
1.232 +
1.233 + case WM_SYSCOMMAND:
1.234 + if (wParam == SC_CLOSE)
1.235 + { // do not allow window to be closed with ALT-F4 (this would close the emulator)
1.236 + return 1;
1.237 + }
1.238 + break;
1.239 + }
1.240 +
1.241 + return DefWindowProc(aHwnd, aMessage, wParam, lParam);
1.242 + }
1.243 +
1.244 +TInt logWinMain(TAny *)
1.245 + {
1.246 + MSG msg;
1.247 + WNDCLASS wndclass;
1.248 + const TText *szAppName=_S("Window Server Log");
1.249 +
1.250 + wndclass.style=CS_HREDRAW|CS_VREDRAW;
1.251 + wndclass.lpfnWndProc=WndProc;
1.252 + wndclass.cbClsExtra=0;
1.253 + wndclass.cbWndExtra=0;
1.254 + wndclass.hInstance=NULL;
1.255 + wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
1.256 + wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);
1.257 + wndclass.hbrBackground=(HBRUSH)GetSysColorBrush(COLOR_BTNFACE);
1.258 + wndclass.lpszMenuName=NULL;
1.259 + wndclass.lpszClassName=(LPCTSTR)szAppName;
1.260 +
1.261 + RegisterClass(&wndclass);
1.262 +
1.263 + GSharedMemory.iHwnd = CreateWindow((LPCTSTR)szAppName,
1.264 + (LPCTSTR)szAppName,
1.265 + WS_OVERLAPPEDWINDOW,
1.266 + CW_USEDEFAULT,
1.267 + CW_USEDEFAULT,
1.268 + CW_USEDEFAULT,
1.269 + CW_USEDEFAULT,
1.270 + NULL,
1.271 + NULL,
1.272 + NULL,
1.273 + NULL);
1.274 +
1.275 + ShowWindow(GSharedMemory.iHwnd, SW_SHOWMINNOACTIVE);
1.276 +
1.277 + GSharedMemory.iStartSemaphore.Signal(); // allows logging to start now that the window, etc. has been set up
1.278 +
1.279 + // Must remove thread from Symbian scheduler before calling blocking Windows APIs (e.g. GetMessage)
1.280 + Emulator::Escape();
1.281 + while (GetMessage(&msg, NULL, 0, 0))
1.282 + {
1.283 + TranslateMessage(&msg);
1.284 + DispatchMessage(&msg);
1.285 + }
1.286 + // return to Symbian Scheduler
1.287 + Emulator::Reenter();
1.288 + GSharedMemory.iHwnd = NULL;
1.289 + return msg.wParam;
1.290 + }