diff options
| author | fffw | 2015-02-13 15:20:13 +0800 | 
|---|---|---|
| committer | fffw | 2015-02-13 15:20:13 +0800 | 
| commit | c00cfb38ee3aee8da409898fed17e80716095e89 (patch) | |
| tree | e6997d1ab53bfb8e1dfeafec7e239f8cfbc35838 | |
| parent | 85d3e528d5a1d1ef8b60dcafc901c633343b4a37 (diff) | |
| parent | 6a81309bde4a67b2d5d1cb57b2e89945ba63fde6 (diff) | |
| download | systray-issue-2143-lib.tar.bz2 | |
merge xcompileissue-2143-lib
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | lib/systray_darwin.c | 16 | ||||
| -rwxr-xr-x | systray.dll | bin | 0 -> 9728 bytes | |||
| -rw-r--r-- | systray.go | 71 | ||||
| -rw-r--r-- | systray.h | 4 | ||||
| -rw-r--r-- | systray.lib | bin | 0 -> 2450 bytes | |||
| -rwxr-xr-x | systray/systray.sdf | bin | 0 -> 11423744 bytes | |||
| -rwxr-xr-x | systray/systray.sln | 20 | ||||
| -rwxr-xr-x | systray/systray.suo | bin | 0 -> 9728 bytes | |||
| -rwxr-xr-x | systray/systray/ReadMe.txt | 48 | ||||
| -rwxr-xr-x | systray/systray/dllmain.cpp | 19 | ||||
| -rwxr-xr-x | systray/systray/stdafx.cpp | 8 | ||||
| -rwxr-xr-x | systray/systray/stdafx.h | 17 | ||||
| -rwxr-xr-x[-rw-r--r--] | systray/systray/systray.cpp (renamed from systray_windows.c) | 512 | ||||
| -rwxr-xr-x | systray/systray/systray.h | 10 | ||||
| -rwxr-xr-x | systray/systray/systray.vcxproj | 100 | ||||
| -rwxr-xr-x | systray/systray/systray.vcxproj.filters | 42 | ||||
| -rwxr-xr-x | systray/systray/systray.vcxproj.user | 3 | ||||
| -rwxr-xr-x | systray/systray/targetver.h | 8 | ||||
| -rw-r--r-- | systray_linux.c | 17 | ||||
| -rw-r--r-- | systray_nonwindows.go | 71 | ||||
| -rw-r--r-- | systray_windows.go | 151 | ||||
| -rw-r--r-- | systraydll_windows.go | 3 | 
24 files changed, 783 insertions, 343 deletions
| @@ -2,3 +2,5 @@ example/example  *~  *.swp  *.exe +Release +Debug @@ -28,8 +28,8 @@ Checked menu item not implemented on Linux yet.  ### Windows -Install [MinGW-W64](http://sourceforge.net/projects/mingw-w64) as it has up to date SDK headers we require. - +Use the Visual Studio solution to build systray.dll and then check that in to +Git. Make sure to target Windows XP.  ## Try diff --git a/lib/systray_darwin.c b/lib/systray_darwin.c index 50a37d8..fffc49e 100644 --- a/lib/systray_darwin.c +++ b/lib/systray_darwin.c @@ -4,27 +4,26 @@  @interface MenuItem : NSObject  {    @public -    NSString* menuId; +    NSNumber* menuId;      NSString* title;      NSString* tooltip;      short disabled;      short checked;  } --(id) initWithId: (const char*)theMenuId +-(id) initWithId: (int)theMenuId         withTitle: (const char*)theTitle       withTooltip: (const char*)theTooltip      withDisabled: (short)theDisabled       withChecked: (short)theChecked;       @end       @implementation MenuItem -     -(id) initWithId: (const char*)theMenuId +     -(id) initWithId: (int)theMenuId              withTitle: (const char*)theTitle            withTooltip: (const char*)theTooltip           withDisabled: (short)theDisabled            withChecked: (short)theChecked  { -  menuId = [[NSString alloc] initWithCString:theMenuId -                                    encoding:NSUTF8StringEncoding]; +  menuId = [NSNumber numberWithInt:theMenuId];    title = [[NSString alloc] initWithCString:theTitle                                     encoding:NSUTF8StringEncoding];    tooltip = [[NSString alloc] initWithCString:theTooltip @@ -80,8 +79,8 @@  - (IBAction)menuHandler:(id)sender  { -  NSString* menuId = [sender representedObject]; -  systray_menu_item_selected((char*)[menuId cStringUsingEncoding: NSUTF8StringEncoding]); +  NSNumber* menuId = [sender representedObject]; +  systray_menu_item_selected(menuId.intValue);  }  - (void) add_or_update_menu_item:(MenuItem*) item @@ -152,9 +151,8 @@ void setTooltip(char* ctooltip) {    runInMainThread(@selector(setTooltip:), (id)tooltip);  } -void add_or_update_menu_item(char* menuId, char* title, char* tooltip, short disabled, short checked) { +void add_or_update_menu_item(int menuId, char* title, char* tooltip, short disabled, short checked) {    MenuItem* item = [[MenuItem alloc] initWithId: menuId withTitle: title withTooltip: tooltip withDisabled: disabled withChecked: checked]; -  free(menuId);    free(title);    free(tooltip);    runInMainThread(@selector(add_or_update_menu_item:), (id)item); diff --git a/systray.dll b/systray.dllBinary files differ new file mode 100755 index 0000000..5fcbf1f --- /dev/null +++ b/systray.dll @@ -5,21 +5,12 @@ Methods can be called from any goroutine except Run(), which should be called at  */  package systray -/* -#cgo LDFLAGS: -L /Users/merlin/workspace/go/src/github.com/getlantern/systray -#cgo linux pkg-config: gtk+-3.0 appindicator3-0.1 -#cgo windows CFLAGS: -DWIN32 -DUNICODE -D_UNICODE -#cgo darwin 386 LDFLAGS: -framework Cocoa -lsystray_darwin_386 -#cgo darwin amd64 LDFLAGS: -framework Cocoa -lsystray_darwin_amd64 - -#include "systray.h" -*/ -import "C"  import ( -	"code.google.com/p/go-uuid/uuid"  	"runtime"  	"sync" -	"unsafe" +	"sync/atomic" + +	"github.com/getlantern/golog"  )  // MenuItem is used to keep track each menu item of systray @@ -29,7 +20,7 @@ type MenuItem struct {  	ClickedCh chan interface{}  	// id uniquely identify a menu item, not supposed to be modified -	id string +	id int32  	// title is the text shown on menu item  	title string  	// tooltip is the text shown when pointing to menu item @@ -41,10 +32,14 @@ type MenuItem struct {  }  var ( +	log = golog.LoggerFor("systray") +  	readyCh       = make(chan interface{})  	clickedCh     = make(chan interface{}) -	menuItems     = make(map[string]*MenuItem) +	menuItems     = make(map[int32]*MenuItem)  	menuItemsLock sync.RWMutex + +	currentId int32  )  // Run initializes GUI and starts the event loop, then invokes the onReady @@ -58,31 +53,12 @@ func Run(onReady func()) {  		onReady()  	}() -	C.nativeLoop() +	nativeLoop()  }  // Quit the systray and whole app  func Quit() { -	C.quit() -} - -// SetIcon sets the systray icon. -// iconBytes should be the content of .ico for windows and .ico/.jpg/.png -// for other platforms. -func SetIcon(iconBytes []byte) { -	cstr := (*C.char)(unsafe.Pointer(&iconBytes[0])) -	C.setIcon(cstr, (C.int)(len(iconBytes))) -} - -// SetTitle sets the systray title, only available on Mac. -func SetTitle(title string) { -	C.setTitle(C.CString(title)) -} - -// SetTitle sets the systray tooltip to display on mouse hover of the tray icon, -// only available on Mac. -func SetTooltip(tooltip string) { -	C.setTooltip(C.CString(tooltip)) +	quit()  }  // Add menu item with designated title and tooltip, returning a channel that @@ -93,7 +69,7 @@ func SetTooltip(tooltip string) {  //  // AddMenuItem can be safely invoked from different goroutines.  func AddMenuItem(title string, tooltip string) *MenuItem { -	id := uuid.New() +	id := atomic.AddInt32(¤tId, 1)  	item := &MenuItem{nil, id, title, tooltip, false, false}  	item.ClickedCh = make(chan interface{})  	item.update() @@ -143,31 +119,14 @@ func (item *MenuItem) update() {  	menuItemsLock.Lock()  	defer menuItemsLock.Unlock()  	menuItems[item.id] = item -	var disabled C.short = 0 -	if item.disabled { -		disabled = 1 -	} -	var checked C.short = 0 -	if item.checked { -		checked = 1 -	} -	C.add_or_update_menu_item( -		C.CString(item.id), -		C.CString(item.title), -		C.CString(item.tooltip), -		disabled, -		checked, -	) +	addOrUpdateMenuItem(item)  } -//export systray_ready -func systray_ready() { +func systrayReady() {  	readyCh <- nil  } -//export systray_menu_item_selected -func systray_menu_item_selected(cId *C.char) { -	id := C.GoString(cId) +func systrayMenuItemSelected(id int32) {  	menuItemsLock.RLock()  	item := menuItems[id]  	menuItemsLock.RUnlock() @@ -1,9 +1,9 @@  extern void systray_ready(); -extern void systray_menu_item_selected(char* menu_id); +extern void systray_menu_item_selected(int menu_id);  int nativeLoop(void);  void setIcon(const char* iconBytes, int length);  void setTitle(char* title);  void setTooltip(char* tooltip); -void add_or_update_menu_item(char* menuId, char* title, char* tooltip, short disabled, short checked); +void add_or_update_menu_item(int menuId, char* title, char* tooltip, short disabled, short checked);  void quit(); diff --git a/systray.lib b/systray.libBinary files differ new file mode 100644 index 0000000..d6b210f --- /dev/null +++ b/systray.lib diff --git a/systray/systray.sdf b/systray/systray.sdfBinary files differ new file mode 100755 index 0000000..431663e --- /dev/null +++ b/systray/systray.sdf diff --git a/systray/systray.sln b/systray/systray.sln new file mode 100755 index 0000000..30c2245 --- /dev/null +++ b/systray/systray.sln @@ -0,0 +1,20 @@ +
 +Microsoft Visual Studio Solution File, Format Version 11.00
 +# Visual C++ Express 2010
 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "systray", "systray\systray.vcxproj", "{7DD84108-D77F-4F51-AC68-5DD13AC1E489}"
 +EndProject
 +Global
 +	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 +		Debug|Win32 = Debug|Win32
 +		Release|Win32 = Release|Win32
 +	EndGlobalSection
 +	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 +		{7DD84108-D77F-4F51-AC68-5DD13AC1E489}.Debug|Win32.ActiveCfg = Debug|Win32
 +		{7DD84108-D77F-4F51-AC68-5DD13AC1E489}.Debug|Win32.Build.0 = Debug|Win32
 +		{7DD84108-D77F-4F51-AC68-5DD13AC1E489}.Release|Win32.ActiveCfg = Release|Win32
 +		{7DD84108-D77F-4F51-AC68-5DD13AC1E489}.Release|Win32.Build.0 = Release|Win32
 +	EndGlobalSection
 +	GlobalSection(SolutionProperties) = preSolution
 +		HideSolutionNode = FALSE
 +	EndGlobalSection
 +EndGlobal
 diff --git a/systray/systray.suo b/systray/systray.suoBinary files differ new file mode 100755 index 0000000..f2c9d40 --- /dev/null +++ b/systray/systray.suo diff --git a/systray/systray/ReadMe.txt b/systray/systray/ReadMe.txt new file mode 100755 index 0000000..7e906df --- /dev/null +++ b/systray/systray/ReadMe.txt @@ -0,0 +1,48 @@ +========================================================================
 +    DYNAMIC LINK LIBRARY : systray Project Overview
 +========================================================================
 +
 +AppWizard has created this systray DLL for you.
 +
 +This file contains a summary of what you will find in each of the files that
 +make up your systray application.
 +
 +
 +systray.vcxproj
 +    This is the main project file for VC++ projects generated using an Application Wizard.
 +    It contains information about the version of Visual C++ that generated the file, and
 +    information about the platforms, configurations, and project features selected with the
 +    Application Wizard.
 +
 +systray.vcxproj.filters
 +    This is the filters file for VC++ projects generated using an Application Wizard. 
 +    It contains information about the association between the files in your project 
 +    and the filters. This association is used in the IDE to show grouping of files with
 +    similar extensions under a specific node (for e.g. ".cpp" files are associated with the
 +    "Source Files" filter).
 +
 +systray.cpp
 +    This is the main DLL source file.
 +
 +	When created, this DLL does not export any symbols. As a result, it
 +	will not produce a .lib file when it is built. If you wish this project
 +	to be a project dependency of some other project, you will either need to
 +	add code to export some symbols from the DLL so that an export library
 +	will be produced, or you can set the Ignore Input Library property to Yes
 +	on the General propert page of the Linker folder in the project's Property
 +	Pages dialog box.
 +
 +/////////////////////////////////////////////////////////////////////////////
 +Other standard files:
 +
 +StdAfx.h, StdAfx.cpp
 +    These files are used to build a precompiled header (PCH) file
 +    named systray.pch and a precompiled types file named StdAfx.obj.
 +
 +/////////////////////////////////////////////////////////////////////////////
 +Other notes:
 +
 +AppWizard uses "TODO:" comments to indicate parts of the source code you
 +should add to or customize.
 +
 +/////////////////////////////////////////////////////////////////////////////
 diff --git a/systray/systray/dllmain.cpp b/systray/systray/dllmain.cpp new file mode 100755 index 0000000..8a4edd3 --- /dev/null +++ b/systray/systray/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : Defines the entry point for the DLL application.
 +#include "stdafx.h"
 +
 +BOOL APIENTRY DllMain( HMODULE hModule,
 +                       DWORD  ul_reason_for_call,
 +                       LPVOID lpReserved
 +					 )
 +{
 +	switch (ul_reason_for_call)
 +	{
 +	case DLL_PROCESS_ATTACH:
 +	case DLL_THREAD_ATTACH:
 +	case DLL_THREAD_DETACH:
 +	case DLL_PROCESS_DETACH:
 +		break;
 +	}
 +	return TRUE;
 +}
 +
 diff --git a/systray/systray/stdafx.cpp b/systray/systray/stdafx.cpp new file mode 100755 index 0000000..a71cba8 --- /dev/null +++ b/systray/systray/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes
 +// systray.pch will be the pre-compiled header
 +// stdafx.obj will contain the pre-compiled type information
 +
 +#include "stdafx.h"
 +
 +// TODO: reference any additional headers you need in STDAFX.H
 +// and not in this file
 diff --git a/systray/systray/stdafx.h b/systray/systray/stdafx.h new file mode 100755 index 0000000..7e739d9 --- /dev/null +++ b/systray/systray/stdafx.h @@ -0,0 +1,17 @@ +// stdafx.h : include file for standard system include files,
 +// or project specific include files that are used frequently, but
 +// are changed infrequently
 +//
 +
 +#pragma once
 +
 +#include "targetver.h"
 +
 +#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
 +// Windows Header Files:
 +#include <windows.h>
 +// Additional required headers
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <windows.h>
 +#include <shellapi.h>
 diff --git a/systray_windows.c b/systray/systray/systray.cpp index ebc0bdd..eb2ea29 100644..100755 --- a/systray_windows.c +++ b/systray/systray/systray.cpp @@ -1,268 +1,244 @@ -#include <stdio.h> -#include <stdlib.h> -#include <windows.h> -#include <shellapi.h> -#include "systray.h" - -// Message posted into message loop when Notification Icon is clicked -#define WM_SYSTRAY_MESSAGE (WM_USER + 1) - -static NOTIFYICONDATA nid; -static HWND hWnd; -static HMENU hTrayMenu; - -void reportWindowsError(const char* action) { -	LPTSTR pErrMsg = NULL; -	DWORD errCode = GetLastError(); -	DWORD result = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER| -			FORMAT_MESSAGE_FROM_SYSTEM| -			FORMAT_MESSAGE_ARGUMENT_ARRAY, -			NULL, -			errCode, -			LANG_NEUTRAL, -			pErrMsg, -			0, -			NULL); -	printf("Systray error %s: %d %s\n", action, errCode, pErrMsg); -} - -wchar_t* UTF8ToUnicode(const char* str) { -	wchar_t* result; -	int textLen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL ,0); -	result = (wchar_t *)calloc((textLen+1), sizeof(wchar_t)); -	int converted = MultiByteToWideChar(CP_UTF8, 0, str, -1, (LPWSTR)result, textLen); -	// Ensure result is alway zero terminated in case either syscall failed -	if (converted == 0) { -		reportWindowsError("convert UTF8 to UNICODE"); -		result[0] = L'\0'; -	} -	return result; -} - -void ShowMenu(HWND hWnd) { -	POINT p; -	if (0 == GetCursorPos(&p)) { -		reportWindowsError("get tray menu position"); -		return; -	}; -	SetForegroundWindow(hWnd); // Win32 bug work-around -	TrackPopupMenu(hTrayMenu, TPM_BOTTOMALIGN | TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL); - -} - -char* GetMenuItemId(int index) { -	MENUITEMINFO menuItemInfo; -	menuItemInfo.cbSize = sizeof(MENUITEMINFO); -	menuItemInfo.fMask = MIIM_DATA; -	if (0 == GetMenuItemInfo(hTrayMenu, index, TRUE, &menuItemInfo)) { -		reportWindowsError("get menu item id"); -		return NULL; -	} -	return (char*)menuItemInfo.dwItemData; -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { -	switch (message) { -		case WM_MENUCOMMAND: -			{ -				char * menuId = GetMenuItemId(wParam); -				if (menuId != NULL) { -					systray_menu_item_selected(menuId); -				} -			} -			break; -		case WM_DESTROY: -			Shell_NotifyIcon(NIM_DELETE, &nid); -			PostQuitMessage(0); -			break; -		case WM_SYSTRAY_MESSAGE: -			switch(lParam) { -				case WM_RBUTTONUP: -					ShowMenu(hWnd); -					break; -				case WM_LBUTTONUP: -					ShowMenu(hWnd); -					break; -				default: -					return DefWindowProc(hWnd, message, wParam, lParam); -			}; -			break; -		default: -			return DefWindowProc(hWnd, message, wParam, lParam); -	} -	return 0; -} - -void MyRegisterClass(HINSTANCE hInstance, TCHAR* szWindowClass) { -	WNDCLASSEX wcex; - -	wcex.cbSize = sizeof(WNDCLASSEX); -	wcex.style          = CS_HREDRAW | CS_VREDRAW; -	wcex.lpfnWndProc    = WndProc; -	wcex.cbClsExtra     = 0; -	wcex.cbWndExtra     = 0; -	wcex.hInstance      = hInstance; -	wcex.hIcon          = LoadIcon(NULL, IDI_APPLICATION); -	wcex.hCursor        = LoadCursor(NULL, IDC_ARROW); -	wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1); -	wcex.lpszMenuName   = 0; -	wcex.lpszClassName  = szWindowClass; -	wcex.hIconSm        = LoadIcon(NULL, IDI_APPLICATION); - -	RegisterClassEx(&wcex); -} - -HWND InitInstance(HINSTANCE hInstance, int nCmdShow, TCHAR* szWindowClass) { -	HWND hWnd = CreateWindow(szWindowClass, TEXT(""), WS_OVERLAPPEDWINDOW, -			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); -	if (!hWnd) { -		return 0; -	} - -	ShowWindow(hWnd, nCmdShow); -	UpdateWindow(hWnd); - -	return hWnd; -} - - -BOOL createMenu() { -	hTrayMenu = CreatePopupMenu(); -	MENUINFO menuInfo; -	menuInfo.cbSize = sizeof(MENUINFO); -	menuInfo.fMask = MIM_APPLYTOSUBMENUS | MIM_STYLE; -	menuInfo.dwStyle = MNS_NOTIFYBYPOS; -	return SetMenuInfo(hTrayMenu, &menuInfo); -} - -BOOL addNotifyIcon() { -	nid.cbSize = sizeof(NOTIFYICONDATA); -	nid.hWnd = hWnd; -	nid.uID = 100; -	nid.uCallbackMessage = WM_SYSTRAY_MESSAGE; -	nid.uFlags = NIF_MESSAGE; -	return Shell_NotifyIcon(NIM_ADD, &nid); -} - -int nativeLoop(void) { -	HINSTANCE hInstance = GetModuleHandle(NULL); -	TCHAR* szWindowClass = TEXT("SystrayClass"); -	MyRegisterClass(hInstance, szWindowClass); -	hWnd = InitInstance(hInstance, FALSE, szWindowClass); // Don't show window -	if (!hWnd) { -		return EXIT_FAILURE; -	} -	if (!createMenu() || !addNotifyIcon()) { -		return EXIT_FAILURE; -	} -	systray_ready(); - -	MSG msg; -	while (GetMessage(&msg, NULL, 0, 0)) { -		TranslateMessage(&msg); -		DispatchMessage(&msg); -	}    -	return EXIT_SUCCESS; -} - - -void setIcon(const char* iconBytes, int length) { -	HICON hIcon; -	// This is really hacky, but LoadImage won't let me load an image from memory. -	// So we have to write out a temporary file, load it from there, then delete the file. - -	// From http://msdn.microsoft.com/en-us/library/windows/desktop/aa363875.aspx -	TCHAR szTempFileName[MAX_PATH+1]; -	TCHAR lpTempPathBuffer[MAX_PATH+1]; -	int dwRetVal = GetTempPath(MAX_PATH+1, lpTempPathBuffer); -	if (dwRetVal > MAX_PATH+1 || (dwRetVal == 0)) { -		reportWindowsError("get temp icon path"); -		return; -	} - -	int uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("systray_"), 0, szTempFileName); -	if (uRetVal == 0) { -		reportWindowsError("get temp icon file name"); -		return; -	} - -	FILE* fIcon = _wfopen(szTempFileName, TEXT("wb")); -	if (fIcon == NULL) { -		reportWindowsError("open temp icon file to write"); -		return; -	} -	ssize_t bytesWritten = fwrite(iconBytes, 1, length, fIcon); -	fclose(fIcon); -	if (bytesWritten != length) { -		printf("error write temp icon file\n"); -	} else { - -		hIcon = LoadImage(NULL, szTempFileName, IMAGE_ICON, 64, 64, LR_LOADFROMFILE); -		if (hIcon == NULL) { -			reportWindowsError("load icon image"); -		} else { - -			nid.hIcon = hIcon; -			nid.uFlags = NIF_ICON; -			Shell_NotifyIcon(NIM_MODIFY, &nid); -		} -	} -	_wremove(szTempFileName); - -} - -// Don't support for Windows -void setTitle(char* ctitle) { -	free(ctitle); -} - -void setTooltip(char* ctooltip) { -	wchar_t* tooltip = UTF8ToUnicode(ctooltip); -	wcsncpy(nid.szTip, tooltip, 64); -	nid.uFlags = NIF_TIP; -	Shell_NotifyIcon(NIM_MODIFY, &nid); -	free(tooltip); -	free(ctooltip); -} - -void add_or_update_menu_item(char* menuId, char* ctitle, char* ctooltip, short disabled, short checked) { -	wchar_t* title = UTF8ToUnicode(ctitle); -	MENUITEMINFO menuItemInfo; -	menuItemInfo.cbSize = sizeof(MENUITEMINFO); -	menuItemInfo.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA | MIIM_STATE; -	menuItemInfo.fType = MFT_STRING; -	menuItemInfo.dwTypeData = title; -	menuItemInfo.cch = wcslen(title) + 1; -	menuItemInfo.dwItemData = (ULONG_PTR)menuId; -	menuItemInfo.fState = 0; -	if (disabled == 1) { -		menuItemInfo.fState |= MFS_DISABLED; -	} -	if (checked == 1) { -		menuItemInfo.fState |= MFS_CHECKED; -	} - -	int itemCount = GetMenuItemCount(hTrayMenu); -	int i; -	for (i = 0; i < itemCount; i++) { -		char * idString = GetMenuItemId(i); -		if (NULL == idString) { -			continue; -		} -		if (strcmp(menuId, idString) == 0) { -			free(idString); -			SetMenuItemInfo(hTrayMenu, i, TRUE, &menuItemInfo); -			break; -		} -	} -	if (i == itemCount) { -		InsertMenuItem(hTrayMenu, -1, TRUE, &menuItemInfo); -	} -	free(title); -	free(ctitle); -	free(ctooltip); -} - -void quit() { -	PostMessage(hWnd, WM_DESTROY, 0, 0); -} +// systray.cpp : Defines the exported functions for the DLL application.
 +//
 +
 +// dllmain.cpp : Defines the entry point for the DLL application.
 +#include "stdafx.h"
 +#include "systray.h"
 +
 +// Message posted into message loop when Notification Icon is clicked
 +#define WM_SYSTRAY_MESSAGE (WM_USER + 1)
 +
 +static NOTIFYICONDATA nid;
 +static HWND hWnd;
 +static HMENU hTrayMenu;
 +
 +void (*systray_menu_item_selected)(int menu_id);
 +
 +void reportWindowsError(const char* action) {
 +	LPTSTR pErrMsg = NULL;
 +	DWORD errCode = GetLastError();
 +	DWORD result = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
 +			FORMAT_MESSAGE_FROM_SYSTEM|
 +			FORMAT_MESSAGE_ARGUMENT_ARRAY,
 +			NULL,
 +			errCode,
 +			LANG_NEUTRAL,
 +			pErrMsg,
 +			0,
 +			NULL);
 +	printf("Systray error %s: %d %s\n", action, errCode, pErrMsg);
 +}
 +
 +wchar_t* UTF8ToUnicode(const char* str) {
 +	wchar_t* result;
 +	int textLen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL ,0);
 +	result = (wchar_t *)calloc((textLen+1), sizeof(wchar_t));
 +	int converted = MultiByteToWideChar(CP_UTF8, 0, str, -1, (LPWSTR)result, textLen);
 +	// Ensure result is alway zero terminated in case either syscall failed
 +	if (converted == 0) {
 +		reportWindowsError("convert UTF8 to UNICODE");
 +		result[0] = L'\0';
 +	}
 +	return result;
 +}
 +
 +void ShowMenu(HWND hWnd) {
 +	POINT p;
 +	if (0 == GetCursorPos(&p)) {
 +		reportWindowsError("get tray menu position");
 +		return;
 +	};
 +	SetForegroundWindow(hWnd); // Win32 bug work-around
 +	TrackPopupMenu(hTrayMenu, TPM_BOTTOMALIGN | TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);
 +
 +}
 +
 +int GetMenuItemId(int index) {
 +	MENUITEMINFO menuItemInfo;
 +	menuItemInfo.cbSize = sizeof(MENUITEMINFO);
 +	menuItemInfo.fMask = MIIM_DATA;
 +	if (0 == GetMenuItemInfo(hTrayMenu, index, TRUE, &menuItemInfo)) {
 +		reportWindowsError("get menu item id");
 +		return -1;
 +	}
 +	int *id = (int*)menuItemInfo.dwItemData;
 +	if (id == NULL) {
 +		return -1;
 +	}
 +	return *id;
 +}
 +
 +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
 +	switch (message) {
 +		case WM_MENUCOMMAND:
 +			{
 +				int menuId = GetMenuItemId(wParam);
 +				if (menuId != -1) {
 +					systray_menu_item_selected(menuId);
 +				}
 +			}
 +			break;
 +		case WM_DESTROY:
 +			Shell_NotifyIcon(NIM_DELETE, &nid);
 +			PostQuitMessage(0);
 +			break;
 +		case WM_SYSTRAY_MESSAGE:
 +			switch(lParam) {
 +				case WM_RBUTTONUP:
 +					ShowMenu(hWnd);
 +					break;
 +				case WM_LBUTTONUP:
 +					ShowMenu(hWnd);
 +					break;
 +				default:
 +					return DefWindowProc(hWnd, message, wParam, lParam);
 +			};
 +			break;
 +		default:
 +			return DefWindowProc(hWnd, message, wParam, lParam);
 +	}
 +	return 0;
 +}
 +
 +void MyRegisterClass(HINSTANCE hInstance, TCHAR* szWindowClass) {
 +	WNDCLASSEX wcex;
 +
 +	wcex.cbSize = sizeof(WNDCLASSEX);
 +	wcex.style          = CS_HREDRAW | CS_VREDRAW;
 +	wcex.lpfnWndProc    = WndProc;
 +	wcex.cbClsExtra     = 0;
 +	wcex.cbWndExtra     = 0;
 +	wcex.hInstance      = hInstance;
 +	wcex.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
 +	wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
 +	wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
 +	wcex.lpszMenuName   = 0;
 +	wcex.lpszClassName  = szWindowClass;
 +	wcex.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
 +
 +	RegisterClassEx(&wcex);
 +}
 +
 +HWND InitInstance(HINSTANCE hInstance, int nCmdShow, TCHAR* szWindowClass) {
 +	HWND hWnd = CreateWindow(szWindowClass, TEXT(""), WS_OVERLAPPEDWINDOW,
 +			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
 +	if (!hWnd) {
 +		return 0;
 +	}
 +
 +	ShowWindow(hWnd, nCmdShow);
 +	UpdateWindow(hWnd);
 +
 +	return hWnd;
 +}
 +
 +
 +BOOL createMenu() {
 +	hTrayMenu = CreatePopupMenu();
 +	MENUINFO menuInfo;
 +	menuInfo.cbSize = sizeof(MENUINFO);
 +	menuInfo.fMask = MIM_APPLYTOSUBMENUS | MIM_STYLE;
 +	menuInfo.dwStyle = MNS_NOTIFYBYPOS;
 +	return SetMenuInfo(hTrayMenu, &menuInfo);
 +}
 +
 +BOOL addNotifyIcon() {
 +	nid.cbSize = sizeof(NOTIFYICONDATA);
 +	nid.hWnd = hWnd;
 +	nid.uID = 100;
 +	nid.uCallbackMessage = WM_SYSTRAY_MESSAGE;
 +	nid.uFlags = NIF_MESSAGE;
 +	return Shell_NotifyIcon(NIM_ADD, &nid);
 +}
 +
 +int nativeLoop(void (*systray_ready)(), void (*_systray_menu_item_selected)(int menu_id)) {
 +	systray_menu_item_selected = _systray_menu_item_selected;
 +
 +	HINSTANCE hInstance = GetModuleHandle(NULL);
 +	TCHAR* szWindowClass = TEXT("SystrayClass");
 +	MyRegisterClass(hInstance, szWindowClass);
 +	hWnd = InitInstance(hInstance, FALSE, szWindowClass); // Don't show window
 +	if (!hWnd) {
 +		return EXIT_FAILURE;
 +	}
 +	if (!createMenu() || !addNotifyIcon()) {
 +		return EXIT_FAILURE;
 +	}
 +	systray_ready();
 +
 +	MSG msg;
 +	while (GetMessage(&msg, NULL, 0, 0)) {
 +		TranslateMessage(&msg);
 +		DispatchMessage(&msg);
 +	}   
 +	return EXIT_SUCCESS;
 +}
 +
 +
 +void setIcon(const char* ciconFile) {
 +	wchar_t* iconFile = UTF8ToUnicode(ciconFile); 
 +	HICON hIcon = (HICON) LoadImage(NULL, iconFile, IMAGE_ICON, 64, 64, LR_LOADFROMFILE);
 +	if (hIcon == NULL) {
 +		reportWindowsError("load icon image");
 +	} else {
 +		nid.hIcon = hIcon;
 +		nid.uFlags = NIF_ICON;
 +		Shell_NotifyIcon(NIM_MODIFY, &nid);
 +	}
 +}
 +
 +void setTooltip(char* ctooltip) {
 +	wchar_t* tooltip = UTF8ToUnicode(ctooltip);
 +	wcsncpy_s(nid.szTip, tooltip, 64);
 +	nid.uFlags = NIF_TIP;
 +	Shell_NotifyIcon(NIM_MODIFY, &nid);
 +	free(tooltip);
 +	free(ctooltip);
 +}
 +
 +void add_or_update_menu_item(int menuId, char* ctitle, char* ctooltip, short disabled, short checked) {
 +	wchar_t* title = UTF8ToUnicode(ctitle);
 +	int *id = (int *) malloc(sizeof(int));
 +	if (id == NULL) {
 +		printf("Unable to allocate space for id");
 +		return;
 +	}
 +	*id = menuId;
 +
 +	MENUITEMINFO menuItemInfo;
 +	menuItemInfo.cbSize = sizeof(MENUITEMINFO);
 +	menuItemInfo.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA | MIIM_STATE;
 +	menuItemInfo.fType = MFT_STRING;
 +	menuItemInfo.dwTypeData = title;
 +	menuItemInfo.cch = wcslen(title) + 1;
 +	menuItemInfo.dwItemData = (ULONG_PTR)id;
 +	menuItemInfo.fState = 0;
 +	if (disabled == 1) {
 +		menuItemInfo.fState |= MFS_DISABLED;
 +	}
 +	if (checked == 1) {
 +		menuItemInfo.fState |= MFS_CHECKED;
 +	}
 +
 +	int itemCount = GetMenuItemCount(hTrayMenu);
 +	int i;
 +	for (i = 0; i < itemCount; i++) {
 +		int id = GetMenuItemId(i);
 +		if (-1 == id) {
 +			continue;
 +		}
 +		if (menuId == id) {
 +			SetMenuItemInfo(hTrayMenu, i, TRUE, &menuItemInfo);
 +			break;
 +		}
 +	}
 +	if (i == itemCount) {
 +		InsertMenuItem(hTrayMenu, -1, TRUE, &menuItemInfo);
 +	}
 +
 +	free(ctooltip);
 +}
 +
 +void quit() {
 +	PostMessage(hWnd, WM_DESTROY, 0, 0);
 +}
\ No newline at end of file diff --git a/systray/systray/systray.h b/systray/systray/systray.h new file mode 100755 index 0000000..76d0f11 --- /dev/null +++ b/systray/systray/systray.h @@ -0,0 +1,10 @@ +#pragma once
 +
 +extern "C" {
 +	__declspec(dllexport) int nativeLoop(void (*systray_ready)(), void (*_systray_menu_item_selected)(int menu_id));
 +
 +	__declspec(dllexport) void setIcon(const char* iconFile);
 +	__declspec(dllexport) void setTooltip(char* tooltip);
 +	__declspec(dllexport) void add_or_update_menu_item(int menuId, char* title, char* tooltip, short disabled, short checked);
 +	__declspec(dllexport) void quit();
 +}
\ No newline at end of file diff --git a/systray/systray/systray.vcxproj b/systray/systray/systray.vcxproj new file mode 100755 index 0000000..704aceb --- /dev/null +++ b/systray/systray/systray.vcxproj @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="utf-8"?>
 +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 +  <ItemGroup Label="ProjectConfigurations">
 +    <ProjectConfiguration Include="Debug|Win32">
 +      <Configuration>Debug</Configuration>
 +      <Platform>Win32</Platform>
 +    </ProjectConfiguration>
 +    <ProjectConfiguration Include="Release|Win32">
 +      <Configuration>Release</Configuration>
 +      <Platform>Win32</Platform>
 +    </ProjectConfiguration>
 +  </ItemGroup>
 +  <PropertyGroup Label="Globals">
 +    <ProjectGuid>{7DD84108-D77F-4F51-AC68-5DD13AC1E489}</ProjectGuid>
 +    <Keyword>Win32Proj</Keyword>
 +    <RootNamespace>systray</RootNamespace>
 +  </PropertyGroup>
 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
 +    <ConfigurationType>DynamicLibrary</ConfigurationType>
 +    <UseDebugLibraries>true</UseDebugLibraries>
 +    <CharacterSet>Unicode</CharacterSet>
 +  </PropertyGroup>
 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
 +    <ConfigurationType>DynamicLibrary</ConfigurationType>
 +    <UseDebugLibraries>false</UseDebugLibraries>
 +    <WholeProgramOptimization>true</WholeProgramOptimization>
 +    <CharacterSet>Unicode</CharacterSet>
 +  </PropertyGroup>
 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
 +  <ImportGroup Label="ExtensionSettings">
 +  </ImportGroup>
 +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
 +  </ImportGroup>
 +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
 +  </ImportGroup>
 +  <PropertyGroup Label="UserMacros" />
 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
 +    <LinkIncremental>true</LinkIncremental>
 +  </PropertyGroup>
 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
 +    <LinkIncremental>false</LinkIncremental>
 +  </PropertyGroup>
 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
 +    <ClCompile>
 +      <PrecompiledHeader>Use</PrecompiledHeader>
 +      <WarningLevel>Level3</WarningLevel>
 +      <Optimization>Disabled</Optimization>
 +      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SYSTRAY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 +    </ClCompile>
 +    <Link>
 +      <SubSystem>Windows</SubSystem>
 +      <GenerateDebugInformation>true</GenerateDebugInformation>
 +    </Link>
 +  </ItemDefinitionGroup>
 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
 +    <ClCompile>
 +      <WarningLevel>Level3</WarningLevel>
 +      <PrecompiledHeader>Use</PrecompiledHeader>
 +      <Optimization>MaxSpeed</Optimization>
 +      <FunctionLevelLinking>true</FunctionLevelLinking>
 +      <IntrinsicFunctions>true</IntrinsicFunctions>
 +      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SYSTRAY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 +    </ClCompile>
 +    <Link>
 +      <SubSystem>Windows</SubSystem>
 +      <GenerateDebugInformation>true</GenerateDebugInformation>
 +      <EnableCOMDATFolding>true</EnableCOMDATFolding>
 +      <OptimizeReferences>true</OptimizeReferences>
 +    </Link>
 +  </ItemDefinitionGroup>
 +  <ItemGroup>
 +    <None Include="ReadMe.txt" />
 +  </ItemGroup>
 +  <ItemGroup>
 +    <ClInclude Include="stdafx.h" />
 +    <ClInclude Include="systray.h" />
 +    <ClInclude Include="targetver.h" />
 +  </ItemGroup>
 +  <ItemGroup>
 +    <ClCompile Include="dllmain.cpp">
 +      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
 +      </PrecompiledHeader>
 +      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
 +      </PrecompiledHeader>
 +    </ClCompile>
 +    <ClCompile Include="stdafx.cpp">
 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
 +    </ClCompile>
 +    <ClCompile Include="systray.cpp" />
 +  </ItemGroup>
 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
 +  <ImportGroup Label="ExtensionTargets">
 +  </ImportGroup>
 +</Project>
\ No newline at end of file diff --git a/systray/systray/systray.vcxproj.filters b/systray/systray/systray.vcxproj.filters new file mode 100755 index 0000000..594e345 --- /dev/null +++ b/systray/systray/systray.vcxproj.filters @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?>
 +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 +  <ItemGroup>
 +    <Filter Include="Source Files">
 +      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
 +      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
 +    </Filter>
 +    <Filter Include="Header Files">
 +      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
 +      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
 +    </Filter>
 +    <Filter Include="Resource Files">
 +      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
 +      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
 +    </Filter>
 +  </ItemGroup>
 +  <ItemGroup>
 +    <None Include="ReadMe.txt" />
 +  </ItemGroup>
 +  <ItemGroup>
 +    <ClInclude Include="stdafx.h">
 +      <Filter>Header Files</Filter>
 +    </ClInclude>
 +    <ClInclude Include="targetver.h">
 +      <Filter>Header Files</Filter>
 +    </ClInclude>
 +    <ClInclude Include="systray.h">
 +      <Filter>Header Files</Filter>
 +    </ClInclude>
 +  </ItemGroup>
 +  <ItemGroup>
 +    <ClCompile Include="stdafx.cpp">
 +      <Filter>Source Files</Filter>
 +    </ClCompile>
 +    <ClCompile Include="systray.cpp">
 +      <Filter>Source Files</Filter>
 +    </ClCompile>
 +    <ClCompile Include="dllmain.cpp">
 +      <Filter>Source Files</Filter>
 +    </ClCompile>
 +  </ItemGroup>
 +</Project>
\ No newline at end of file diff --git a/systray/systray/systray.vcxproj.user b/systray/systray/systray.vcxproj.user new file mode 100755 index 0000000..695b5c7 --- /dev/null +++ b/systray/systray/systray.vcxproj.user @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?>
 +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 +</Project>
\ No newline at end of file diff --git a/systray/systray/targetver.h b/systray/systray/targetver.h new file mode 100755 index 0000000..90e767b --- /dev/null +++ b/systray/systray/targetver.h @@ -0,0 +1,8 @@ +#pragma once
 +
 +// Including SDKDDKVer.h defines the highest available Windows platform.
 +
 +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
 +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
 +
 +#include <SDKDDKVer.h>
 diff --git a/systray_linux.c b/systray_linux.c index 1cbebbe..83b4690 100644 --- a/systray_linux.c +++ b/systray_linux.c @@ -13,11 +13,11 @@ static GArray *global_temp_icon_file_names = NULL;  typedef struct {  	GtkWidget *menu_item; -	char *menu_id; +	int menu_id;  } MenuItemNode;  typedef struct { -	char* menu_id; +	int menu_id;  	char* title;  	char* tooltip;  	short disabled; @@ -62,15 +62,18 @@ gboolean do_set_icon(gpointer data) {  	return FALSE;  } +void _systray_menu_item_selected(int *id) { +	systray_menu_item_selected(*id); +} +  // runs in main thread, should always return FALSE to prevent gtk to execute it again  gboolean do_add_or_update_menu_item(gpointer data) {  	MenuItemInfo *mii = (MenuItemInfo*)data;  	GList* it;  	for(it = global_menu_items; it != NULL; it = it->next) {  		MenuItemNode* item = (MenuItemNode*)(it->data); -		if(strcmp(item->menu_id, mii->menu_id) == 0){ +		if(item->menu_id == mii->menu_id){  			gtk_menu_item_set_label(GTK_MENU_ITEM(item->menu_item), mii->title); -			free(mii->menu_id);  			break;  		}  	} @@ -78,7 +81,9 @@ gboolean do_add_or_update_menu_item(gpointer data) {  	// menu id doesn't exist, add new item  	if(it == NULL) {  		GtkWidget *menu_item = gtk_menu_item_new_with_label(mii->title); -		g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(systray_menu_item_selected), mii->menu_id); +		int *id = malloc(sizeof(int)); +		*id = mii->menu_id; +		g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(_systray_menu_item_selected), id);  		gtk_menu_shell_append(GTK_MENU_SHELL(global_tray_menu), menu_item);  		MenuItemNode* new_item = malloc(sizeof(MenuItemNode)); @@ -134,7 +139,7 @@ void setTooltip(char* ctooltip) {  	free(ctooltip);  } -void add_or_update_menu_item(char* menu_id, char* title, char* tooltip, short disabled, short checked) { +void add_or_update_menu_item(int menu_id, char* title, char* tooltip, short disabled, short checked) {  	MenuItemInfo *mii = malloc(sizeof(MenuItemInfo));  	mii->menu_id = menu_id;  	mii->title = title; diff --git a/systray_nonwindows.go b/systray_nonwindows.go new file mode 100644 index 0000000..f570b42 --- /dev/null +++ b/systray_nonwindows.go @@ -0,0 +1,71 @@ +// +build !windows + +package systray + +/* +#cgo linux pkg-config: gtk+-3.0 appindicator3-0.1 +#cgo darwin CFLAGS: -DDARWIN -x objective-c -fobjc-arc +#cgo darwin LDFLAGS: -framework Cocoa + +#include "systray.h" +*/ +import "C" + +import ( +	"unsafe" +) + +func nativeLoop() { +	C.nativeLoop() +} + +func quit() { +	C.quit() +} + +// SetIcon sets the systray icon. +// iconBytes should be the content of .ico for windows and .ico/.jpg/.png +// for other platforms. +func SetIcon(iconBytes []byte) { +	cstr := (*C.char)(unsafe.Pointer(&iconBytes[0])) +	C.setIcon(cstr, (C.int)(len(iconBytes))) +} + +// SetTitle sets the systray title, only available on Mac. +func SetTitle(title string) { +	C.setTitle(C.CString(title)) +} + +// SetTitle sets the systray tooltip to display on mouse hover of the tray icon, +// only available on Mac and Windows. +func SetTooltip(tooltip string) { +	C.setTooltip(C.CString(tooltip)) +} + +func addOrUpdateMenuItem(item *MenuItem) { +	var disabled C.short = 0 +	if item.disabled { +		disabled = 1 +	} +	var checked C.short = 0 +	if item.checked { +		checked = 1 +	} +	C.add_or_update_menu_item( +		C.int(item.id), +		C.CString(item.title), +		C.CString(item.tooltip), +		disabled, +		checked, +	) +} + +//export systray_ready +func systray_ready() { +	systrayReady() +} + +//export systray_menu_item_selected +func systray_menu_item_selected(cId C.int) { +	systrayMenuItemSelected(int32(cId)) +} diff --git a/systray_windows.go b/systray_windows.go new file mode 100644 index 0000000..9ae9520 --- /dev/null +++ b/systray_windows.go @@ -0,0 +1,151 @@ +package systray + +import ( +	"fmt" +	"io/ioutil" +	"os" +	"path" +	"syscall" +	"unsafe" + +	"github.com/getlantern/tarfs" +) + +var ( +	iconFiles = make([]*os.File, 0) +	dllDir    = path.Join(os.Getenv("APPDATA"), "systray") +	dllFile   = path.Join(dllDir, "systray.dll") + +	mod                      = syscall.NewLazyDLL(dllFile) +	_nativeLoop              = mod.NewProc("nativeLoop") +	_quit                    = mod.NewProc("quit") +	_setIcon                 = mod.NewProc("setIcon") +	_setTitle                = mod.NewProc("setTitle") +	_setTooltip              = mod.NewProc("setTooltip") +	_add_or_update_menu_item = mod.NewProc("add_or_update_menu_item") +) + +func init() { +	// Write DLL to file +	fs, err := tarfs.New(systraydll, "") +	if err != nil { +		panic(fmt.Errorf("Unable to open systray.dll: %v", err)) +	} + +	b, err := fs.Get("systray.dll") +	if err != nil { +		panic(fmt.Errorf("Unable to read systray.dll: %v", err)) +	} + +	err = os.MkdirAll(dllDir, 755) +	if err != nil { +		panic(fmt.Errorf("Unable to create directory %v to hold systray.dll: %v", dllDir, err)) +	} + +	err = ioutil.WriteFile(dllFile, b, 0644) +	if err != nil { +		panic(fmt.Errorf("Unable to save systray.dll to %v: %v", dllFile, err)) +	} +} + +func nativeLoop() { +	_nativeLoop.Call( +		syscall.NewCallback(systray_ready), +		syscall.NewCallback(systray_menu_item_selected)) +} + +func quit() { +	_quit.Call() +	for _, f := range iconFiles { +		err := os.Remove(f.Name()) +		if err != nil { +			log.Debugf("Unable to delete temporary icon file %v: %v", f.Name(), err) +		} +	} +} + +// SetIcon sets the systray icon. +// iconBytes should be the content of .ico for windows and .ico/.jpg/.png +// for other platforms. +func SetIcon(iconBytes []byte) { +	f, err := ioutil.TempFile("", "systray_temp_icon") +	if err != nil { +		log.Errorf("Unable to create temp icon: %v", err) +		return +	} +	defer f.Close() +	_, err = f.Write(iconBytes) +	if err != nil { +		log.Errorf("Unable to write icon to temp file %v: %v", f.Name(), f) +		return +	} +	f.Close() +	name, err := strPtr(f.Name()) +	if err != nil { +		log.Errorf("Unable to convert name to string pointer: %v", err) +		return +	} +	_setIcon.Call(name) +} + +// SetTitle sets the systray title, only available on Mac. +func SetTitle(title string) { +	// do nothing +} + +// SetTooltip sets the systray tooltip to display on mouse hover of the tray icon, +// only available on Mac and Windows. +func SetTooltip(tooltip string) { +	t, err := strPtr(tooltip) +	if err != nil { +		log.Errorf("Unable to convert tooltip to string pointer: %v", err) +		return +	} +	_setTooltip.Call(t) +} + +func addOrUpdateMenuItem(item *MenuItem) { +	var disabled = 0 +	if item.disabled { +		disabled = 1 +	} +	var checked = 0 +	if item.checked { +		checked = 1 +	} +	title, err := strPtr(item.title) +	if err != nil { +		log.Errorf("Unable to convert title to string pointer: %v", err) +		return +	} +	tooltip, err := strPtr(item.tooltip) +	if err != nil { +		log.Errorf("Unable to convert tooltip to string pointer: %v", err) +		return +	} +	_add_or_update_menu_item.Call( +		uintptr(item.id), +		title, +		tooltip, +		uintptr(disabled), +		uintptr(checked), +	) +} + +func strPtr(s string) (uintptr, error) { +	bp, err := syscall.BytePtrFromString(s) +	if err != nil { +		return 0, err +	} +	return uintptr(unsafe.Pointer(bp)), nil +} + +func systray_ready() uintptr { +	systrayReady() +	return 0 +} + +func systray_menu_item_selected(id uintptr) uintptr { +	systrayMenuItemSelected(int32(id)) +	return 0 +} diff --git a/systraydll_windows.go b/systraydll_windows.go new file mode 100644 index 0000000..bf3161c --- /dev/null +++ b/systraydll_windows.go @@ -0,0 +1,3 @@ +package systray + +var systraydll = []byte("\x73\x79\x73\x74\x72\x61\x79\x2e\x64\x6c\x6c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x30\x30\x30\x30\x30\x30\x00\x30\x30\x30\x30\x30\x30\x30\x00\x30\x30\x30\x30\x30\x30\x30\x00\x30\x30\x30\x30\x30\x30\x32\x33\x30\x30\x30\x00\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x00\x30\x31\x31\x33\x31\x35\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x75\x73\x74\x61\x72\x00\x30\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x30\x30\x30\x30\x30\x30\x00\x30\x30\x30\x30\x30\x30\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4d\x5a\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x00\x00\x00\x0e\x1f\xba\x0e\x00\xb4\x09\xcd\x21\xb8\x01\x4c\xcd\x21\x54\x68\x69\x73\x20\x70\x72\x6f\x67\x72\x61\x6d\x20\x63\x61\x6e\x6e\x6f\x74\x20\x62\x65\x20\x72\x75\x6e\x20\x69\x6e\x20\x44\x4f\x53\x20\x6d\x6f\x64\x65\x2e\x0d\x0d\x0a\x24\x00\x00\x00\x00\x00\x00\x00\x74\x8f\x66\x67\x30\xee\x08\x34\x30\xee\x08\x34\x30\xee\x08\x34\x5f\x98\x94\x34\x32\xee\x08\x34\x5f\x98\x96\x34\x31\xee\x08\x34\x5f\x98\xa2\x34\x3b\xee\x08\x34\x5f\x98\xa3\x34\x32\xee\x08\x34\x39\x96\x9b\x34\x37\xee\x08\x34\x30\xee\x09\x34\x0c\xee\x08\x34\x5f\x98\xa7\x34\x33\xee\x08\x34\x5f\x98\x93\x34\x31\xee\x08\x34\x5f\x98\x95\x34\x31\xee\x08\x34\x52\x69\x63\x68\x30\xee\x08\x34\x00\x00\x00\x00\x00\x00\x00\x00\x50\x45\x00\x00\x4c\x01\x05\x00\xba\x85\xdd\x54\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x02\x21\x0b\x01\x0a\x00\x00\x10\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\xf0\x19\x00\x00\x00\x10\x00\x00\x00\x20\x00\x00\x00\x00\x00\x10\x00\x10\x00\x00\x00\x02\x00\x00\x05\x00\x01\x00\x00\x00\x00\x00\x05\x00\x01\x00\x00\x00\x00\x00\x00\x60\x00\x00\x00\x04\x00\x00\xb9\xfd\x00\x00\x02\x00\x40\x01\x00\x00\x10\x00\x00\x10\x00\x00\x00\x00\x10\x00\x00\x10\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x10\x29\x00\x00\xa1\x00\x00\x00\x4c\x23\x00\x00\x64\x00\x00\x00\x00\x40\x00\x00\xb4\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x50\x00\x00\xd4\x01\x00\x00\x20\x21\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x21\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2e\x74\x65\x78\x74\x00\x00\x00\xde\x0e\x00\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x60\x2e\x72\x64\x61\x74\x61\x00\x00\xb1\x09\x00\x00\x00\x20\x00\x00\x00\x0a\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x40\x2e\x64\x61\x74\x61\x00\x00\x00\x28\x07\x00\x00\x00\x30\x00\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\xc0\x2e\x72\x73\x72\x63\x00\x00\x00\xb4\x01\x00\x00\x00\x40\x00\x00\x00\x02\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x40\x2e\x72\x65\x6c\x6f\x63\x00\x00\x6e\x02\x00\x00\x00\x50\x00\x00\x00\x04\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb8\x01\x00\x00\x00\xc2\x0c\x00\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x56\x57\x6a\x00\x6a\x00\x6a\xff\x53\x6a\x00\x68\xe9\xfd\x00\x00\xff\x15\x08\x20\x00\x10\x8b\xf0\x8d\x46\x01\x6a\x02\x50\xff\x15\x78\x20\x00\x10\x83\xc4\x08\x56\x8b\xf8\x57\x6a\xff\x53\x6a\x00\x68\xe9\xfd\x00\x00\xff\x15\x08\x20\x00\x10\x85\xc0\x75\x39\xff\x15\x00\x20\x00\x10\x6a\x00\x6a\x00\x6a\x00\x6a\x00\x8b\xf0\x56\x6a\x00\x68\x00\x31\x00\x00\xff\x15\x04\x20\x00\x10\x6a\x00\x56\x68\x64\x21\x00\x10\x68\x48\x21\x00\x10\xff\x15\x74\x20\x00\x10\x83\xc4\x10\x33\xc9\x66\x89\x0f\x8b\xc7\x5f\x5e\xc3\xcc\xcc\xcc\x55\x8b\xec\x83\xec\x0c\x56\x8b\xf0\x8d\x45\xf8\x50\xff\x15\xf4\x20\x00\x10\x85\xc0\x75\x39\xff\x15\x00\x20\x00\x10\x6a\x00\x6a\x00\x6a\x00\x6a\x00\x8b\xf0\x56\x6a\x00\x68\x00\x31\x00\x00\xff\x15\x04\x20\x00\x10\x6a\x00\x56\x68\x7c\x21\x00\x10\x68\x48\x21\x00\x10\xff\x15\x74\x20\x00\x10\x83\xc4\x10\x5e\x8b\xe5\x5d\xc3\x56\xff\x15\xf0\x20\x00\x10\x8b\x4d\xfc\x8b\x55\xf8\xa1\x50\x33\x00\x10\x6a\x00\x56\x6a\x00\x51\x52\x6a\x20\x50\xff\x15\xec\x20\x00\x10\x5e\x8b\xe5\x5d\xc3\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x55\x8b\xec\x83\xec\x34\x8b\x15\x50\x33\x00\x10\x56\x8d\x45\xd0\x50\x6a\x01\x51\x52\xc7\x45\xd0\x30\x00\x00\x00\xc7\x45\xd4\x20\x00\x00\x00\xff\x15\xe8\x20\x00\x10\x85\xc0\x75\x3c\xff\x15\x00\x20\x00\x10\x6a\x00\x6a\x00\x6a\x00\x6a\x00\x8b\xf0\x56\x6a\x00\x68\x00\x31\x00\x00\xff\x15\x04\x20\x00\x10\x6a\x00\x56\x68\x94\x21\x00\x10\x68\x48\x21\x00\x10\xff\x15\x74\x20\x00\x10\x83\xc4\x10\x83\xc8\xff\x5e\x8b\xe5\x5d\xc3\x8b\x45\xf0\x85\xc0\x74\xf1\x8b\x00\x5e\x8b\xe5\x5d\xc3\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x55\x8b\xec\x83\xe4\xf8\x8b\x4d\x0c\x8b\xc1\x83\xe8\x02\x0f\x84\x81\x00\x00\x00\x2d\x24\x01\x00\x00\x74\x5b\x2d\xdb\x02\x00\x00\x74\x19\x8b\x45\x14\x8b\x55\x10\x50\x8b\x45\x08\x52\x51\x50\xff\x15\xe0\x20\x00\x10\x8b\xe5\x5d\xc2\x10\x00\x8b\x4d\x14\x8b\xc1\x2d\x02\x02\x00\x00\x74\x1f\x83\xe8\x03\x74\x1a\x8b\x55\x08\x51\x8b\x4d\x10\x51\x68\x01\x04\x00\x00\x52\xff\x15\xe0\x20\x00\x10\x8b\xe5\x5d\xc2\x10\x00\x8b\x45\x08\xe8\x92\xfe\xff\xff\x33\xc0\x8b\xe5\x5d\xc2\x10\x00\x8b\x4d\x10\xe8\x02\xff\xff\xff\x83\xf8\xff\x74\x27\x50\xff\x15\x4c\x33\x00\x10\x83\xc4\x04\x33\xc0\x8b\xe5\x5d\xc2\x10\x00\x68\x58\x33\x00\x10\x6a\x02\xff\x15\x9c\x20\x00\x10\x6a\x00\xff\x15\xe4\x20\x00\x10\x33\xc0\x8b\xe5\x5d\xc2\x10\x00\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x55\x8b\xec\x83\xec\x30\x56\x8b\x35\xdc\x20\x00\x10\x68\x00\x7f\x00\x00\x6a\x00\xc7\x45\xd0\x30\x00\x00\x00\xc7\x45\xd4\x03\x00\x00\x00\xc7\x45\xd8\x90\x11\x00\x10\xc7\x45\xdc\x00\x00\x00\x00\xc7\x45\xe0\x00\x00\x00\x00\x89\x45\xe4\xff\xd6\x68\x00\x7f\x00\x00\x6a\x00\x89\x45\xe8\xff\x15\xd8\x20\x00\x10\x68\x00\x7f\x00\x00\x6a\x00\x89\x45\xec\xc7\x45\xf0\x06\x00\x00\x00\xc7\x45\xf4\x00\x00\x00\x00\xc7\x45\xf8\xac\x21\x00\x10\xff\xd6\x8d\x4d\xd0\x51\x89\x45\xfc\xff\x15\xd4\x20\x00\x10\x5e\x8b\xe5\x5d\xc3\xcc\x55\x8b\xec\x8b\x45\x0c\x83\xec\x38\x56\x6a\x00\xa3\x4c\x33\x00\x10\xff\x15\x0c\x20\x00\x10\x8b\xf0\xe8\x62\xff\xff\xff\x6a\x00\x56\x6a\x00\x6a\x00\x6a\x00\x68\x00\x00\x00\x80\x6a\x00\x68\x00\x00\x00\x80\x68\x00\x00\xcf\x00\x68\xa8\x21\x00\x10\x68\xac\x21\x00\x10\x6a\x00\xff\x15\xd0\x20\x00\x10\x8b\xf0\x85\xf6\x74\x10\x6a\x00\x56\xff\x15\xcc\x20\x00\x10\x56\xff\x15\xc8\x20\x00\x10\x89\x35\x54\x33\x00\x10\x85\xf6\x0f\x84\xc7\x00\x00\x00\xff\x15\xc4\x20\x00\x10\x8d\x4d\xe4\x51\x50\xa3\x50\x33\x00\x10\xc7\x45\xe4\x1c\x00\x00\x00\xc7\x45\xe8\x10\x00\x00\x80\xc7\x45\xec\x00\x00\x00\x08\xff\x15\xc0\x20\x00\x10\x85\xc0\x0f\x84\x94\x00\x00\x00\x8b\x15\x54\x33\x00\x10\x68\x58\x33\x00\x10\x6a\x00\xc7\x05\x58\x33\x00\x10\xbc\x03\x00\x00\x89\x15\x5c\x33\x00\x10\xc7\x05\x60\x33\x00\x10\x64\x00\x00\x00\xc7\x05\x68\x33\x00\x10\x01\x04\x00\x00\xc7\x05\x64\x33\x00\x10\x01\x00\x00\x00\xff\x15\x9c\x20\x00\x10\x85\xc0\x74\x4f\xff\x55\x08\x8b\x35\xa4\x20\x00\x10\x6a\x00\x6a\x00\x6a\x00\x8d\x45\xc8\x50\xff\xd6\x85\xc0\x74\x2f\x53\x8b\x1d\xbc\x20\x00\x10\x57\x8b\x3d\xf8\x20\x00\x10\x8d\x49\x00\x8d\x4d\xc8\x51\xff\xd7\x8d\x55\xc8\x52\xff\xd3\x6a\x00\x6a\x00\x6a\x00\x8d\x45\xc8\x50\xff\xd6\x85\xc0\x75\xe4\x5f\x5b\x33\xc0\x5e\x8b\xe5\x5d\xc3\xb8\x01\x00\x00\x00\x5e\x8b\xe5\x5d\xc3\xcc\x55\x8b\xec\x53\x8b\x5d\x08\xe8\xf4\xfb\xff\xff\x6a\x10\x6a\x40\x6a\x40\x6a\x01\x50\x6a\x00\xff\x15\xb8\x20\x00\x10\x5b\x85\xc0\x75\x38\x56\xff\x15\x00\x20\x00\x10\x6a\x00\x6a\x00\x6a\x00\x6a\x00\x8b\xf0\x56\x6a\x00\x68\x00\x31\x00\x00\xff\x15\x04\x20\x00\x10\x6a\x00\x56\x68\xc8\x21\x00\x10\x68\x48\x21\x00\x10\xff\x15\x74\x20\x00\x10\x83\xc4\x10\x5e\x5d\xc3\x68\x58\x33\x00\x10\x6a\x01\xa3\x6c\x33\x00\x10\xc7\x05\x64\x33\x00\x10\x02\x00\x00\x00\xff\x15\x9c\x20\x00\x10\x5d\xc3\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x55\x8b\xec\x53\x8b\x5d\x08\x56\xe8\x73\xfb\xff\xff\x6a\x40\x8b\xf0\x56\x68\x80\x00\x00\x00\x68\x70\x33\x00\x10\xff\x15\x84\x20\x00\x10\x83\xc4\x10\x68\x58\x33\x00\x10\x6a\x01\xc7\x05\x64\x33\x00\x10\x04\x00\x00\x00\xff\x15\x9c\x20\x00\x10\x56\x8b\x35\x68\x20\x00\x10\xff\xd6\x53\xff\xd6\x83\xc4\x08\x5e\x5b\x5d\xc3\xcc\x55\x8b\xec\x83\xe4\xf8\x83\xec\x64\x53\x8b\x5d\x0c\x56\x57\xe8\x1c\xfb\xff\xff\x6a\x04\x8b\xf0\xff\x15\x80\x20\x00\x10\x33\xff\x83\xc4\x04\x3b\xc7\x75\x15\x68\xd8\x21\x00\x10\xff\x15\x74\x20\x00\x10\x83\xc4\x04\x5f\x5e\x5b\x8b\xe5\x5d\xc3\x8b\x4d\x08\x89\x08\x8b\xce\x89\x74\x24\x34\xc7\x44\x24\x10\x30\x00\x00\x00\xc7\x44\x24\x14\x61\x01\x00\x00\x89\x7c\x24\x18\x8d\x71\x02\x8b\xff\x66\x8b\x11\x83\xc1\x02\x66\x3b\xd7\x75\xf5\x2b\xce\xd1\xf9\x89\x44\x24\x30\x41\xb8\x01\x00\x00\x00\x89\x4c\x24\x38\x89\x7c\x24\x1c\x66\x39\x45\x14\x75\x08\xc7\x44\x24\x1c\x03\x00\x00\x00\x66\x39\x45\x18\x75\x05\x83\x4c\x24\x1c\x08\x8b\x15\x50\x33\x00\x10\x52\xff\x15\xb4\x20\x00\x10\x8b\xf0\x89\x74\x24\x0c\x3b\xfe\x0f\x8d\x9b\x00\x00\x00\x8b\x1d\x74\x20\x00\x10\xeb\x03\x8d\x49\x00\x8b\x0d\x50\x33\x00\x10\x8d\x44\x24\x40\x50\x6a\x01\x57\x51\xc7\x44\x24\x50\x30\x00\x00\x00\xc7\x44\x24\x54\x20\x00\x00\x00\xff\x15\xe8\x20\x00\x10\x85\xc0\x75\x36\xff\x15\x00\x20\x00\x10\x6a\x00\x6a\x00\x6a\x00\x6a\x00\x8b\xf0\x56\x6a\x00\x68\x00\x31\x00\x00\xff\x15\x04\x20\x00\x10\x6a\x00\x56\x68\x94\x21\x00\x10\x68\x48\x21\x00\x10\xff\xd3\x8b\x74\x24\x1c\x83\xc4\x10\xeb\x14\x8b\x44\x24\x60\x85\xc0\x74\x0c\x8b\x00\x83\xf8\xff\x74\x05\x39\x45\x08\x74\x07\x47\x3b\xfe\x7c\x88\xeb\x14\xa1\x50\x33\x00\x10\x8d\x54\x24\x10\x52\x6a\x01\x57\x50\xff\x15\xb0\x20\x00\x10\x3b\xfe\x75\x16\x8b\x15\x50\x33\x00\x10\x8d\x4c\x24\x10\x51\x6a\x01\x6a\xff\x52\xff\x15\xac\x20\x00\x10\x8b\x45\x10\x50\xff\x15\x68\x20\x00\x10\x83\xc4\x04\x5f\x5e\x5b\x8b\xe5\x5d\xc3\xcc\xcc\xcc\xcc\xa1\x54\x33\x00\x10\x6a\x00\x6a\x00\x6a\x02\x50\xff\x15\xa8\x20\x00\x10\xc3\x3b\x0d\x00\x30\x00\x10\x75\x02\xf3\xc3\xe9\x91\x03\x00\x00\x8b\xff\x56\x68\x80\x00\x00\x00\xff\x15\x88\x20\x00\x10\x59\x8b\xf0\x56\xff\x15\x44\x20\x00\x10\xa3\x20\x37\x00\x10\xa3\x1c\x37\x00\x10\x85\xf6\x75\x05\x33\xc0\x40\x5e\xc3\x83\x26\x00\xe8\x28\x05\x00\x00\x68\x03\x1c\x00\x10\xe8\x07\x05\x00\x00\xc7\x04\x24\x19\x1b\x00\x10\xe8\xfb\x04\x00\x00\x59\x33\xc0\x5e\xc3\x8b\xff\x55\x8b\xec\x51\x51\x53\x33\xc0\x56\x57\x39\x45\x0c\x75\x32\x39\x05\x10\x30\x00\x10\x7e\x23\x64\xa1\x18\x00\x00\x00\xff\x0d\x10\x30\x00\x10\x8b\x58\x04\x83\x65\xfc\x00\x8b\x35\x34\x20\x00\x10\xbf\x18\x37\x00\x10\xe9\xea\x00\x00\x00\x33\xc0\xe9\xc0\x01\x00\x00\x83\x7d\x0c\x01\x0f\x85\xb3\x01\x00\x00\x64\x8b\x0d\x18\x00\x00\x00\x8b\x59\x04\x8b\x35\x34\x20\x00\x10\x89\x45\x0c\x50\xbf\x18\x37\x00\x10\xeb\x11\x3b\xc3\x74\x17\x68\xe8\x03\x00\x00\xff\x15\x38\x20\x00\x10\x6a\x00\x53\x57\xff\xd6\x85\xc0\x75\xe7\xeb\x07\xc7\x45\x0c\x01\x00\x00\x00\xa1\x14\x37\x00\x10\x6a\x02\x5e\x85\xc0\x74\x09\x6a\x1f\xe8\x1b\x06\x00\x00\xeb\x39\x68\x10\x21\x00\x10\x68\x08\x21\x00\x10\xc7\x05\x14\x37\x00\x10\x01\x00\x00\x00\xe8\xfa\x05\x00\x00\x59\x59\x85\xc0\x0f\x85\x7a\xff\xff\xff\x68\x04\x21\x00\x10\x68\x00\x21\x00\x10\xe8\xdb\x05\x00\x00\x59\x89\x35\x14\x37\x00\x10\x33\xdb\x59\x39\x5d\x0c\x75\x08\x53\x57\xff\x15\x3c\x20\x00\x10\x39\x1d\x24\x37\x00\x10\x74\x1c\x68\x24\x37\x00\x10\xe8\xf6\x04\x00\x00\x59\x85\xc0\x74\x0d\xff\x75\x10\x56\xff\x75\x08\xff\x15\x24\x37\x00\x10\xff\x05\x10\x30\x00\x10\xe9\xe9\x00\x00\x00\x3b\xc3\x74\x17\x68\xe8\x03\x00\x00\xff\x15\x38\x20\x00\x10\x6a\x00\x53\x57\xff\xd6\x85\xc0\x75\xe7\xeb\x07\xc7\x45\xfc\x01\x00\x00\x00\xa1\x14\x37\x00\x10\x83\xf8\x02\x74\x0d\x6a\x1f\xe8\x6e\x05\x00\x00\x59\xe9\xb0\x00\x00\x00\xff\x35\x20\x37\x00\x10\x8b\x35\x40\x20\x00\x10\xff\xd6\x89\x45\x0c\x85\xc0\x0f\x84\x83\x00\x00\x00\xff\x35\x1c\x37\x00\x10\xff\xd6\x8b\xd8\x8b\x45\x0c\x89\x45\x10\x89\x5d\x08\x83\xeb\x04\x3b\x5d\x0c\x72\x4e\x83\x3b\x00\x74\xf3\xff\x15\x8c\x20\x00\x10\x39\x03\x74\xe9\xff\x33\xff\xd6\x89\x45\xf8\xff\x15\x8c\x20\x00\x10\x89\x03\xff\x55\xf8\xff\x35\x20\x37\x00\x10\xff\xd6\xff\x35\x1c\x37\x00\x10\x89\x45\xf8\xff\xd6\x8b\x4d\xf8\x39\x4d\x10\x75\x05\x39\x45\x08\x74\xb7\x89\x4d\x10\x89\x4d\x0c\x89\x45\x08\x8b\xd8\xeb\xaa\xff\x75\x0c\xff\x15\x68\x20\x00\x10\x59\xff\x15\x8c\x20\x00\x10\xa3\x1c\x37\x00\x10\xa3\x20\x37\x00\x10\x33\xc0\xa3\x14\x37\x00\x10\x39\x45\xfc\x75\x08\x50\x57\xff\x15\x3c\x20\x00\x10\x33\xc0\x40\x5f\x5e\x5b\xc9\xc2\x0c\x00\x6a\x10\x68\xe8\x22\x00\x10\xe8\xba\x04\x00\x00\x8b\xf9\x8b\xf2\x8b\x5d\x08\x33\xc0\x40\x89\x45\xe4\x33\xc9\x89\x4d\xfc\x89\x35\x08\x30\x00\x10\x89\x45\xfc\x3b\xf1\x75\x10\x39\x0d\x10\x30\x00\x10\x75\x08\x89\x4d\xe4\xe9\xb7\x00\x00\x00\x3b\xf0\x74\x05\x83\xfe\x02\x75\x2e\xa1\x3c\x21\x00\x10\x3b\xc1\x74\x08\x57\x56\x53\xff\xd0\x89\x45\xe4\x83\x7d\xe4\x00\x0f\x84\x93\x00\x00\x00\x57\x56\x53\xe8\x8f\xfd\xff\xff\x89\x45\xe4\x85\xc0\x0f\x84\x80\x00\x00\x00\x57\x56\x53\xe8\xac\xf6\xff\xff\x89\x45\xe4\x83\xfe\x01\x75\x24\x85\xc0\x75\x20\x57\x50\x53\xe8\x98\xf6\xff\xff\x57\x6a\x00\x53\xe8\x5f\xfd\xff\xff\xa1\x3c\x21\x00\x10\x85\xc0\x74\x06\x57\x6a\x00\x53\xff\xd0\x85\xf6\x74\x05\x83\xfe\x03\x75\x43\x57\x56\x53\xe8\x3f\xfd\xff\xff\x85\xc0\x75\x03\x21\x45\xe4\x83\x7d\xe4\x00\x74\x2e\xa1\x3c\x21\x00\x10\x85\xc0\x74\x25\x57\x56\x53\xff\xd0\x89\x45\xe4\xeb\x1b\x8b\x45\xec\x8b\x08\x8b\x09\x89\x4d\xe0\x50\x51\xe8\xcc\x03\x00\x00\x59\x59\xc3\x8b\x65\xe8\x83\x65\xe4\x00\x83\x65\xfc\x00\xc7\x45\xfc\xfe\xff\xff\xff\xe8\x09\x00\x00\x00\x8b\x45\xe4\xe8\x01\x04\x00\x00\xc3\xc7\x05\x08\x30\x00\x10\xff\xff\xff\xff\xc3\x8b\xff\x55\x8b\xec\x83\x7d\x0c\x01\x75\x05\xe8\x1e\x04\x00\x00\xff\x75\x08\x8b\x4d\x10\x8b\x55\x0c\xe8\xcc\xfe\xff\xff\x59\x5d\xc2\x0c\x00\x8b\xff\x55\x8b\xec\x81\xec\x28\x03\x00\x00\xa3\x20\x31\x00\x10\x89\x0d\x1c\x31\x00\x10\x89\x15\x18\x31\x00\x10\x89\x1d\x14\x31\x00\x10\x89\x35\x10\x31\x00\x10\x89\x3d\x0c\x31\x00\x10\x66\x8c\x15\x38\x31\x00\x10\x66\x8c\x0d\x2c\x31\x00\x10\x66\x8c\x1d\x08\x31\x00\x10\x66\x8c\x05\x04\x31\x00\x10\x66\x8c\x25\x00\x31\x00\x10\x66\x8c\x2d\xfc\x30\x00\x10\x9c\x8f\x05\x30\x31\x00\x10\x8b\x45\x00\xa3\x24\x31\x00\x10\x8b\x45\x04\xa3\x28\x31\x00\x10\x8d\x45\x08\xa3\x34\x31\x00\x10\x8b\x85\xe0\xfc\xff\xff\xc7\x05\x70\x30\x00\x10\x01\x00\x01\x00\xa1\x28\x31\x00\x10\xa3\x24\x30\x00\x10\xc7\x05\x18\x30\x00\x10\x09\x04\x00\xc0\xc7\x05\x1c\x30\x00\x10\x01\x00\x00\x00\xa1\x00\x30\x00\x10\x89\x85\xd8\xfc\xff\xff\xa1\x04\x30\x00\x10\x89\x85\xdc\xfc\xff\xff\xff\x15\x20\x20\x00\x10\xa3\x68\x30\x00\x10\x6a\x01\xe8\xda\x03\x00\x00\x59\x6a\x00\xff\x15\x24\x20\x00\x10\x68\x40\x21\x00\x10\xff\x15\x28\x20\x00\x10\x83\x3d\x68\x30\x00\x10\x00\x75\x08\x6a\x01\xe8\xb6\x03\x00\x00\x59\x68\x09\x04\x00\xc0\xff\x15\x2c\x20\x00\x10\x50\xff\x15\x30\x20\x00\x10\xc9\xc3\x68\x3c\x33\x00\x10\xe8\x9d\x03\x00\x00\x59\xc3\x6a\x14\x68\x10\x23\x00\x10\xe8\x6f\x02\x00\x00\xff\x35\x20\x37\x00\x10\x8b\x35\x40\x20\x00\x10\xff\xd6\x89\x45\xe4\x83\xf8\xff\x75\x0c\xff\x75\x08\xff\x15\x54\x20\x00\x10\x59\xeb\x64\x6a\x08\xe8\x78\x03\x00\x00\x59\x83\x65\xfc\x00\xff\x35\x20\x37\x00\x10\xff\xd6\x89\x45\xe4\xff\x35\x1c\x37\x00\x10\xff\xd6\x89\x45\xe0\x8d\x45\xe0\x50\x8d\x45\xe4\x50\xff\x75\x08\x8b\x35\x44\x20\x00\x10\xff\xd6\x50\xe8\x3e\x03\x00\x00\x83\xc4\x0c\x89\x45\xdc\xff\x75\xe4\xff\xd6\xa3\x20\x37\x00\x10\xff\x75\xe0\xff\xd6\xa3\x1c\x37\x00\x10\xc7\x45\xfc\xfe\xff\xff\xff\xe8\x09\x00\x00\x00\x8b\x45\xdc\xe8\x29\x02\x00\x00\xc3\x6a\x08\xe8\x02\x03\x00\x00\x59\xc3\x8b\xff\x55\x8b\xec\xff\x75\x08\xe8\x52\xff\xff\xff\xf7\xd8\x1b\xc0\xf7\xd8\x59\x48\x5d\xc3\x8b\xff\x56\xb8\xd8\x22\x00\x10\xbe\xd8\x22\x00\x10\x57\x8b\xf8\x3b\xc6\x73\x0f\x8b\x07\x85\xc0\x74\x02\xff\xd0\x83\xc7\x04\x3b\xfe\x72\xf1\x5f\x5e\xc3\x8b\xff\x56\xb8\xe0\x22\x00\x10\xbe\xe0\x22\x00\x10\x57\x8b\xf8\x3b\xc6\x73\x0f\x8b\x07\x85\xc0\x74\x02\xff\xd0\x83\xc7\x04\x3b\xfe\x72\xf1\x5f\x5e\xc3\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x8b\xff\x55\x8b\xec\x8b\x4d\x08\xb8\x4d\x5a\x00\x00\x66\x39\x01\x74\x04\x33\xc0\x5d\xc3\x8b\x41\x3c\x03\xc1\x81\x38\x50\x45\x00\x00\x75\xef\x33\xd2\xb9\x0b\x01\x00\x00\x66\x39\x48\x18\x0f\x94\xc2\x8b\xc2\x5d\xc3\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x8b\xff\x55\x8b\xec\x8b\x45\x08\x8b\x48\x3c\x03\xc8\x0f\xb7\x41\x14\x53\x56\x0f\xb7\x71\x06\x33\xd2\x57\x8d\x44\x08\x18\x85\xf6\x74\x1b\x8b\x7d\x0c\x8b\x48\x0c\x3b\xf9\x72\x09\x8b\x58\x08\x03\xd9\x3b\xfb\x72\x0a\x42\x83\xc0\x28\x3b\xd6\x72\xe8\x33\xc0\x5f\x5e\x5b\x5d\xc3\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x8b\xff\x55\x8b\xec\x6a\xfe\x68\x30\x23\x00\x10\x68\xf9\x1d\x00\x10\x64\xa1\x00\x00\x00\x00\x50\x83\xec\x08\x53\x56\x57\xa1\x00\x30\x00\x10\x31\x45\xf8\x33\xc5\x50\x8d\x45\xf0\x64\xa3\x00\x00\x00\x00\x89\x65\xe8\xc7\x45\xfc\x00\x00\x00\x00\x68\x00\x00\x00\x10\xe8\x2a\xff\xff\xff\x83\xc4\x04\x85\xc0\x74\x54\x8b\x45\x08\x2d\x00\x00\x00\x10\x50\x68\x00\x00\x00\x10\xe8\x50\xff\xff\xff\x83\xc4\x08\x85\xc0\x74\x3a\x8b\x40\x24\xc1\xe8\x1f\xf7\xd0\x83\xe0\x01\xc7\x45\xfc\xfe\xff\xff\xff\x8b\x4d\xf0\x64\x89\x0d\x00\x00\x00\x00\x59\x5f\x5e\x5b\x8b\xe5\x5d\xc3\x8b\x45\xec\x8b\x08\x33\xd2\x81\x39\x05\x00\x00\xc0\x0f\x94\xc2\x8b\xc2\xc3\x8b\x65\xe8\xc7\x45\xfc\xfe\xff\xff\xff\x33\xc0\x8b\x4d\xf0\x64\x89\x0d\x00\x00\x00\x00\x59\x5f\x5e\x5b\x8b\xe5\x5d\xc3\xff\x25\x90\x20\x00\x10\xff\x25\x94\x20\x00\x10\xff\x25\x7c\x20\x00\x10\xff\x25\x70\x20\x00\x10\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x68\xf9\x1d\x00\x10\x64\xff\x35\x00\x00\x00\x00\x8b\x44\x24\x10\x89\x6c\x24\x10\x8d\x6c\x24\x10\x2b\xe0\x53\x56\x57\xa1\x00\x30\x00\x10\x31\x45\xfc\x33\xc5\x50\x89\x65\xe8\xff\x75\xf8\x8b\x45\xfc\xc7\x45\xfc\xfe\xff\xff\xff\x89\x45\xf8\x8d\x45\xf0\x64\xa3\x00\x00\x00\x00\xc3\x8b\x4d\xf0\x64\x89\x0d\x00\x00\x00\x00\x59\x5f\x5f\x5e\x5b\x8b\xe5\x5d\x51\xc3\x8b\xff\x55\x8b\xec\xff\x75\x14\xff\x75\x10\xff\x75\x0c\xff\x75\x08\x68\x73\x16\x00\x10\x68\x00\x30\x00\x10\xe8\xbf\x00\x00\x00\x83\xc4\x18\x5d\xc3\x8b\xff\x55\x8b\xec\x83\xec\x10\xa1\x00\x30\x00\x10\x83\x65\xf8\x00\x83\x65\xfc\x00\x53\x57\xbf\x4e\xe6\x40\xbb\xbb\x00\x00\xff\xff\x3b\xc7\x74\x0d\x85\xc3\x74\x09\xf7\xd0\xa3\x04\x30\x00\x10\xeb\x65\x56\x8d\x45\xf8\x50\xff\x15\x48\x20\x00\x10\x8b\x75\xfc\x33\x75\xf8\xff\x15\x10\x20\x00\x10\x33\xf0\xff\x15\x14\x20\x00\x10\x33\xf0\xff\x15\x18\x20\x00\x10\x33\xf0\x8d\x45\xf0\x50\xff\x15\x1c\x20\x00\x10\x8b\x45\xf4\x33\x45\xf0\x33\xf0\x3b\xf7\x75\x07\xbe\x4f\xe6\x40\xbb\xeb\x10\x85\xf3\x75\x0c\x8b\xc6\x0d\x11\x47\x00\x00\xc1\xe0\x10\x0b\xf0\x89\x35\x00\x30\x00\x10\xf7\xd6\x89\x35\x04\x30\x00\x10\x5e\x5f\x5b\xc9\xc3\xcc\xff\x25\x6c\x20\x00\x10\xff\x25\x64\x20\x00\x10\xff\x25\x60\x20\x00\x10\xff\x25\x5c\x20\x00\x10\xff\x25\x58\x20\x00\x10\xff\x25\x50\x20\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb0\x24\x00\x00\xc0\x24\x00\x00\xd2\x24\x00\x00\xe8\x24\x00\x00\xda\x28\x00\x00\xc4\x28\x00\x00\xb4\x28\x00\x00\x9a\x28\x00\x00\x86\x28\x00\x00\x68\x28\x00\x00\x4c\x28\x00\x00\x38\x28\x00\x00\x24\x28\x00\x00\x06\x28\x00\x00\xfe\x27\x00\x00\xe8\x27\x00\x00\xd8\x27\x00\x00\xc8\x27\x00\x00\xf0\x28\x00\x00\x00\x00\x00\x00\xae\x27\x00\x00\xa4\x27\x00\x00\x9c\x27\x00\x00\x8e\x27\x00\x00\x84\x27\x00\x00\x60\x27\x00\x00\xc6\x26\x00\x00\x4a\x27\x00\x00\x38\x27\x00\x00\xb2\x26\x00\x00\xbc\x26\x00\x00\x2a\x27\x00\x00\xce\x26\x00\x00\xd8\x26\x00\x00\xf2\x26\x00\x00\x00\x27\x00\x00\x10\x27\x00\x00\x1c\x27\x00\x00\x00\x00\x00\x00\x92\x26\x00\x00\x00\x00\x00\x00\xf8\x25\x00\x00\x76\x26\x00\x00\x64\x26\x00\x00\x50\x26\x00\x00\x3c\x26\x00\x00\x2e\x26\x00\x00\x1a\x26\x00\x00\xea\x25\x00\x00\xd8\x25\x00\x00\xc8\x25\x00\x00\xba\x25\x00\x00\xa8\x25\x00\x00\x94\x25\x00\x00\x86\x25\x00\x00\x7a\x25\x00\x00\x68\x25\x00\x00\x56\x25\x00\x00\x42\x25\x00\x00\x30\x25\x00\x00\x1a\x25\x00\x00\x0a\x25\x00\x00\x06\x26\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x16\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xba\x85\xdd\x54\x00\x00\x00\x00\x02\x00\x00\x00\x85\x00\x00\x00\x40\x22\x00\x00\x40\x16\x00\x00\x00\x00\x00\x00\x18\x30\x00\x10\x70\x30\x00\x10\x53\x79\x73\x74\x72\x61\x79\x20\x65\x72\x72\x6f\x72\x20\x25\x73\x3a\x20\x25\x64\x20\x25\x73\x0a\x00\x00\x00\x00\x63\x6f\x6e\x76\x65\x72\x74\x20\x55\x54\x46\x38\x20\x74\x6f\x20\x55\x4e\x49\x43\x4f\x44\x45\x00\x67\x65\x74\x20\x74\x72\x61\x79\x20\x6d\x65\x6e\x75\x20\x70\x6f\x73\x69\x74\x69\x6f\x6e\x00\x00\x67\x65\x74\x20\x6d\x65\x6e\x75\x20\x69\x74\x65\x6d\x20\x69\x64\x00\x00\x00\x00\x00\x00\x00\x00\x53\x00\x79\x00\x73\x00\x74\x00\x72\x00\x61\x00\x79\x00\x43\x00\x6c\x00\x61\x00\x73\x00\x73\x00\x00\x00\x00\x00\x6c\x6f\x61\x64\x20\x69\x63\x6f\x6e\x20\x69\x6d\x61\x67\x65\x00\x55\x6e\x61\x62\x6c\x65\x20\x74\x6f\x20\x61\x6c\x6c\x6f\x63\x61\x74\x65\x20\x73\x70\x61\x63\x65\x20\x66\x6f\x72\x20\x69\x64\x00\x48\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x00\x10\xd0\x22\x00\x10\x01\x00\x00\x00\x52\x53\x44\x53\xde\x0d\xf5\x5e\x53\xf4\xb2\x48\xa1\x4b\x12\xb9\x0c\x85\xb7\x09\x16\x00\x00\x00\x43\x3a\x5c\x44\x6f\x63\x75\x6d\x65\x6e\x74\x73\x20\x61\x6e\x64\x20\x53\x65\x74\x74\x69\x6e\x67\x73\x5c\x41\x64\x6d\x69\x6e\x69\x73\x74\x72\x61\x74\x6f\x72\x5c\x67\x6f\x63\x6f\x64\x65\x5c\x73\x72\x63\x5c\x67\x69\x74\x68\x75\x62\x2e\x63\x6f\x6d\x5c\x67\x65\x74\x6c\x61\x6e\x74\x65\x72\x6e\x5c\x73\x79\x73\x74\x72\x61\x79\x5c\x73\x79\x73\x74\x72\x61\x79\x5c\x52\x65\x6c\x65\x61\x73\x65\x5c\x73\x79\x73\x74\x72\x61\x79\x2e\x70\x64\x62\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf9\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\x00\x00\x00\x00\xd0\xff\xff\xff\x00\x00\x00\x00\xfe\xff\xff\xff\x00\x00\x00\x00\xe5\x19\x00\x10\x00\x00\x00\x00\xb1\x19\x00\x10\xc5\x19\x00\x10\xfe\xff\xff\xff\x00\x00\x00\x00\xcc\xff\xff\xff\x00\x00\x00\x00\xfe\xff\xff\xff\x00\x00\x00\x00\xbd\x1b\x00\x10\x00\x00\x00\x00\xfe\xff\xff\xff\x00\x00\x00\x00\xd8\xff\xff\xff\x00\x00\x00\x00\xfe\xff\xff\xff\x4b\x1d\x00\x10\x5e\x1d\x00\x10\xb0\x23\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfc\x24\x00\x00\x00\x20\x00\x00\x54\x24\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x26\x00\x00\xa4\x20\x00\x00\x4c\x24\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa6\x26\x00\x00\x9c\x20\x00\x00\x00\x24\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe4\x26\x00\x00\x50\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb0\x24\x00\x00\xc0\x24\x00\x00\xd2\x24\x00\x00\xe8\x24\x00\x00\xda\x28\x00\x00\xc4\x28\x00\x00\xb4\x28\x00\x00\x9a\x28\x00\x00\x86\x28\x00\x00\x68\x28\x00\x00\x4c\x28\x00\x00\x38\x28\x00\x00\x24\x28\x00\x00\x06\x28\x00\x00\xfe\x27\x00\x00\xe8\x27\x00\x00\xd8\x27\x00\x00\xc8\x27\x00\x00\xf0\x28\x00\x00\x00\x00\x00\x00\xae\x27\x00\x00\xa4\x27\x00\x00\x9c\x27\x00\x00\x8e\x27\x00\x00\x84\x27\x00\x00\x60\x27\x00\x00\xc6\x26\x00\x00\x4a\x27\x00\x00\x38\x27\x00\x00\xb2\x26\x00\x00\xbc\x26\x00\x00\x2a\x27\x00\x00\xce\x26\x00\x00\xd8\x26\x00\x00\xf2\x26\x00\x00\x00\x27\x00\x00\x10\x27\x00\x00\x1c\x27\x00\x00\x00\x00\x00\x00\x92\x26\x00\x00\x00\x00\x00\x00\xf8\x25\x00\x00\x76\x26\x00\x00\x64\x26\x00\x00\x50\x26\x00\x00\x3c\x26\x00\x00\x2e\x26\x00\x00\x1a\x26\x00\x00\xea\x25\x00\x00\xd8\x25\x00\x00\xc8\x25\x00\x00\xba\x25\x00\x00\xa8\x25\x00\x00\x94\x25\x00\x00\x86\x25\x00\x00\x7a\x25\x00\x00\x68\x25\x00\x00\x56\x25\x00\x00\x42\x25\x00\x00\x30\x25\x00\x00\x1a\x25\x00\x00\x0a\x25\x00\x00\x06\x26\x00\x00\x00\x00\x00\x00\x02\x02\x47\x65\x74\x4c\x61\x73\x74\x45\x72\x72\x6f\x72\x00\x00\x5e\x01\x46\x6f\x72\x6d\x61\x74\x4d\x65\x73\x73\x61\x67\x65\x57\x00\x00\x67\x03\x4d\x75\x6c\x74\x69\x42\x79\x74\x65\x54\x6f\x57\x69\x64\x65\x43\x68\x61\x72\x00\x18\x02\x47\x65\x74\x4d\x6f\x64\x75\x6c\x65\x48\x61\x6e\x64\x6c\x65\x57\x00\x00\x4b\x45\x52\x4e\x45\x4c\x33\x32\x2e\x64\x6c\x6c\x00\x00\x20\x01\x47\x65\x74\x43\x75\x72\x73\x6f\x72\x50\x6f\x73\x00\x00\x93\x02\x53\x65\x74\x46\x6f\x72\x65\x67\x72\x6f\x75\x6e\x64\x57\x69\x6e\x64\x6f\x77\x00\xf6\x02\x54\x72\x61\x63\x6b\x50\x6f\x70\x75\x70\x4d\x65\x6e\x75\x00\x00\x54\x01\x47\x65\x74\x4d\x65\x6e\x75\x49\x74\x65\x6d\x49\x6e\x66\x6f\x57\x00\x00\x37\x02\x50\x6f\x73\x74\x51\x75\x69\x74\x4d\x65\x73\x73\x61\x67\x65\x00\x9c\x00\x44\x65\x66\x57\x69\x6e\x64\x6f\x77\x50\x72\x6f\x63\x57\x00\x00\xed\x01\x4c\x6f\x61\x64\x49\x63\x6f\x6e\x57\x00\xeb\x01\x4c\x6f\x61\x64\x43\x75\x72\x73\x6f\x72\x57\x00\x4d\x02\x52\x65\x67\x69\x73\x74\x65\x72\x43\x6c\x61\x73\x73\x45\x78\x57\x00\x00\x6e\x00\x43\x72\x65\x61\x74\x65\x57\x69\x6e\x64\x6f\x77\x45\x78\x57\x00\xdf\x02\x53\x68\x6f\x77\x57\x69\x6e\x64\x6f\x77\x00\x00\x11\x03\x55\x70\x64\x61\x74\x65\x57\x69\x6e\x64\x6f\x77\x00\x00\x6b\x00\x43\x72\x65\x61\x74\x65\x50\x6f\x70\x75\x70\x4d\x65\x6e\x75\x00\x9f\x02\x53\x65\x74\x4d\x65\x6e\x75\x49\x6e\x66\x6f\x00\x5d\x01\x47\x65\x74\x4d\x65\x73\x73\x61\x67\x65\x57\x00\xfc\x02\x54\x72\x61\x6e\x73\x6c\x61\x74\x65\x4d\x65\x73\x73\x61\x67\x65\x00\x00\xaf\x00\x44\x69\x73\x70\x61\x74\x63\x68\x4d\x65\x73\x73\x61\x67\x65\x57\x00\x00\xef\x01\x4c\x6f\x61\x64\x49\x6d\x61\x67\x65\x57\x00\x00\x51\x01\x47\x65\x74\x4d\x65\x6e\x75\x49\x74\x65\x6d\x43\x6f\x75\x6e\x74\x00\x00\xa2\x02\x53\x65\x74\x4d\x65\x6e\x75\x49\x74\x65\x6d\x49\x6e\x66\x6f\x57\x00\x00\xb9\x01\x49\x6e\x73\x65\x72\x74\x4d\x65\x6e\x75\x49\x74\x65\x6d\x57\x00\x36\x02\x50\x6f\x73\x74\x4d\x65\x73\x73\x61\x67\x65\x57\x00\x00\x55\x53\x45\x52\x33\x32\x2e\x64\x6c\x6c\x00\x00\x2e\x01\x53\x68\x65\x6c\x6c\x5f\x4e\x6f\x74\x69\x66\x79\x49\x63\x6f\x6e\x57\x00\x53\x48\x45\x4c\x4c\x33\x32\x2e\x64\x6c\x6c\x00\xd7\x05\x70\x72\x69\x6e\x74\x66\x00\x00\x6b\x05\x63\x61\x6c\x6c\x6f\x63\x00\x00\x8b\x05\x66\x72\x65\x65\x00\x00\xc4\x05\x6d\x61\x6c\x6c\x6f\x63\x00\x00\x3c\x06\x77\x63\x73\x6e\x63\x70\x79\x5f\x73\x00\x4d\x53\x56\x43\x52\x31\x30\x30\x2e\x64\x6c\x6c\x00\x00\x34\x03\x5f\x6d\x61\x6c\x6c\x6f\x63\x5f\x63\x72\x74\x00\x19\x02\x5f\x65\x6e\x63\x6f\x64\x65\x64\x5f\x6e\x75\x6c\x6c\x00\xb0\x02\x5f\x69\x6e\x69\x74\x74\x65\x72\x6d\x00\xb1\x02\x5f\x69\x6e\x69\x74\x74\x65\x72\x6d\x5f\x65\x00\xc5\x01\x5f\x61\x6d\x73\x67\x5f\x65\x78\x69\x74\x00\x00\x31\x01\x5f\x5f\x43\x70\x70\x58\x63\x70\x74\x46\x69\x6c\x74\x65\x72\x00\xfb\x01\x5f\x63\x72\x74\x5f\x64\x65\x62\x75\x67\x67\x65\x72\x5f\x68\x6f\x6f\x6b\x00\x00\x53\x01\x5f\x5f\x63\x6c\x65\x61\x6e\x5f\x74\x79\x70\x65\x5f\x69\x6e\x66\x6f\x5f\x6e\x61\x6d\x65\x73\x5f\x69\x6e\x74\x65\x72\x6e\x61\x6c\x00\x00\x8d\x04\x5f\x75\x6e\x6c\x6f\x63\x6b\x00\x5b\x01\x5f\x5f\x64\x6c\x6c\x6f\x6e\x65\x78\x69\x74\x00\x23\x03\x5f\x6c\x6f\x63\x6b\x00\xc9\x03\x5f\x6f\x6e\x65\x78\x69\x74\x00\x21\x02\x5f\x65\x78\x63\x65\x70\x74\x5f\x68\x61\x6e\x64\x6c\x65\x72\x34\x5f\x63\x6f\x6d\x6d\x6f\x6e\x00\xea\x00\x45\x6e\x63\x6f\x64\x65\x50\x6f\x69\x6e\x74\x65\x72\x00\xca\x00\x44\x65\x63\x6f\x64\x65\x50\x6f\x69\x6e\x74\x65\x72\x00\xec\x02\x49\x6e\x74\x65\x72\x6c\x6f\x63\x6b\x65\x64\x45\x78\x63\x68\x61\x6e\x67\x65\x00\xb2\x04\x53\x6c\x65\x65\x70\x00\xe9\x02\x49\x6e\x74\x65\x72\x6c\x6f\x63\x6b\x65\x64\x43\x6f\x6d\x70\x61\x72\x65\x45\x78\x63\x68\x61\x6e\x67\x65\x00\x00\xc0\x04\x54\x65\x72\x6d\x69\x6e\x61\x74\x65\x50\x72\x6f\x63\x65\x73\x73\x00\x00\xc0\x01\x47\x65\x74\x43\x75\x72\x72\x65\x6e\x74\x50\x72\x6f\x63\x65\x73\x73\x00\xd3\x04\x55\x6e\x68\x61\x6e\x64\x6c\x65\x64\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\x46\x69\x6c\x74\x65\x72\x00\x00\xa5\x04\x53\x65\x74\x55\x6e\x68\x61\x6e\x64\x6c\x65\x64\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\x46\x69\x6c\x74\x65\x72\x00\x00\x03\x49\x73\x44\x65\x62\x75\x67\x67\x65\x72\x50\x72\x65\x73\x65\x6e\x74\x00\xa7\x03\x51\x75\x65\x72\x79\x50\x65\x72\x66\x6f\x72\x6d\x61\x6e\x63\x65\x43\x6f\x75\x6e\x74\x65\x72\x00\x93\x02\x47\x65\x74\x54\x69\x63\x6b\x43\x6f\x75\x6e\x74\x00\x00\xc5\x01\x47\x65\x74\x43\x75\x72\x72\x65\x6e\x74\x54\x68\x72\x65\x61\x64\x49\x64\x00\x00\xc1\x01\x47\x65\x74\x43\x75\x72\x72\x65\x6e\x74\x50\x72\x6f\x63\x65\x73\x73\x49\x64\x00\x79\x02\x47\x65\x74\x53\x79\x73\x74\x65\x6d\x54\x69\x6d\x65\x41\x73\x46\x69\x6c\x65\x54\x69\x6d\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xba\x85\xdd\x54\x00\x00\x00\x00\x6a\x29\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x38\x29\x00\x00\x4c\x29\x00\x00\x60\x29\x00\x00\xe0\x14\x00\x00\xd0\x12\x00\x00\x60\x16\x00\x00\x10\x14\x00\x00\x90\x14\x00\x00\x76\x29\x00\x00\x8e\x29\x00\x00\x99\x29\x00\x00\x9e\x29\x00\x00\xa6\x29\x00\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x73\x79\x73\x74\x72\x61\x79\x2e\x64\x6c\x6c\x00\x61\x64\x64\x5f\x6f\x72\x5f\x75\x70\x64\x61\x74\x65\x5f\x6d\x65\x6e\x75\x5f\x69\x74\x65\x6d\x00\x6e\x61\x74\x69\x76\x65\x4c\x6f\x6f\x70\x00\x71\x75\x69\x74\x00\x73\x65\x74\x49\x63\x6f\x6e\x00\x73\x65\x74\x54\x6f\x6f\x6c\x74\x69\x70\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4e\xe6\x40\xbb\xb1\x19\xbf\x44\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x18\x00\x00\x00\x18\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x30\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x09\x04\x00\x00\x48\x00\x00\x00\x58\x40\x00\x00\x5a\x01\x00\x00\xe4\x04\x00\x00\x00\x00\x00\x00\x3c\x61\x73\x73\x65\x6d\x62\x6c\x79\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x75\x72\x6e\x3a\x73\x63\x68\x65\x6d\x61\x73\x2d\x6d\x69\x63\x72\x6f\x73\x6f\x66\x74\x2d\x63\x6f\x6d\x3a\x61\x73\x6d\x2e\x76\x31\x22\x20\x6d\x61\x6e\x69\x66\x65\x73\x74\x56\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x3e\x0d\x0a\x20\x20\x3c\x74\x72\x75\x73\x74\x49\x6e\x66\x6f\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x75\x72\x6e\x3a\x73\x63\x68\x65\x6d\x61\x73\x2d\x6d\x69\x63\x72\x6f\x73\x6f\x66\x74\x2d\x63\x6f\x6d\x3a\x61\x73\x6d\x2e\x76\x33\x22\x3e\x0d\x0a\x20\x20\x20\x20\x3c\x73\x65\x63\x75\x72\x69\x74\x79\x3e\x0d\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x65\x71\x75\x65\x73\x74\x65\x64\x50\x72\x69\x76\x69\x6c\x65\x67\x65\x73\x3e\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x72\x65\x71\x75\x65\x73\x74\x65\x64\x45\x78\x65\x63\x75\x74\x69\x6f\x6e\x4c\x65\x76\x65\x6c\x20\x6c\x65\x76\x65\x6c\x3d\x22\x61\x73\x49\x6e\x76\x6f\x6b\x65\x72\x22\x20\x75\x69\x41\x63\x63\x65\x73\x73\x3d\x22\x66\x61\x6c\x73\x65\x22\x3e\x3c\x2f\x72\x65\x71\x75\x65\x73\x74\x65\x64\x45\x78\x65\x63\x75\x74\x69\x6f\x6e\x4c\x65\x76\x65\x6c\x3e\x0d\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x72\x65\x71\x75\x65\x73\x74\x65\x64\x50\x72\x69\x76\x69\x6c\x65\x67\x65\x73\x3e\x0d\x0a\x20\x20\x20\x20\x3c\x2f\x73\x65\x63\x75\x72\x69\x74\x79\x3e\x0d\x0a\x20\x20\x3c\x2f\x74\x72\x75\x73\x74\x49\x6e\x66\x6f\x3e\x0d\x0a\x3c\x2f\x61\x73\x73\x65\x6d\x62\x6c\x79\x3e\x50\x41\x50\x41\x44\x44\x49\x4e\x47\x58\x58\x50\x41\x44\x44\x49\x4e\x47\x50\x41\x44\x44\x49\x4e\x47\x58\x58\x50\x41\x44\x44\x49\x4e\x47\x50\x41\x44\x44\x49\x4e\x47\x58\x58\x50\x41\x44\x44\x49\x4e\x47\x50\x41\x44\x44\x49\x4e\x47\x58\x58\x50\x41\x44\x44\x49\x4e\x47\x50\x41\x44\x44\x49\x4e\x47\x58\x58\x50\x41\x44\x00\x10\x00\x00\xb4\x01\x00\x00\x22\x30\x30\x30\x47\x30\x51\x30\x69\x30\x71\x30\x76\x30\x7c\x30\x9f\x30\xa9\x30\xc1\x30\xc9\x30\xce\x30\xd4\x30\xe3\x30\xee\x30\xfe\x30\x18\x31\x35\x31\x3f\x31\x57\x31\x5f\x31\x64\x31\x6a\x31\xc1\x31\xec\x31\x16\x32\x26\x32\x2e\x32\x36\x32\x59\x32\x75\x32\x98\x32\xb7\x32\xc6\x32\xdd\x32\xe3\x32\x09\x33\x0e\x33\x16\x33\x25\x33\x2c\x33\x32\x33\x40\x33\x4a\x33\x65\x33\x73\x33\x78\x33\x80\x33\x8a\x33\x90\x33\x9a\x33\xa4\x33\xae\x33\xbb\x33\xd2\x33\xd9\x33\x29\x34\x35\x34\x4d\x34\x55\x34\x5a\x34\x60\x34\x6b\x34\x72\x34\x78\x34\x82\x34\xa8\x34\xae\x34\xb6\x34\xbe\x34\xc8\x34\xcf\x34\xfa\x34\x08\x35\x0e\x35\x7c\x35\x83\x35\x97\x35\xa2\x35\xc1\x35\xcb\x35\xe3\x35\xeb\x35\xf0\x35\x1b\x36\x2a\x36\x34\x36\x44\x36\x4e\x36\x61\x36\x6e\x36\x75\x36\x8c\x36\x96\x36\x9b\x36\xa0\x36\xb6\x36\xc2\x36\xe3\x36\xf1\x36\xfe\x36\x03\x37\x29\x37\x32\x37\x43\x37\x5b\x37\x70\x37\x75\x37\x7b\x37\x93\x37\x98\x37\xa4\x37\xb4\x37\xba\x37\xc1\x37\xd8\x37\xde\x37\xf2\x37\x0a\x38\x22\x38\x28\x38\x3b\x38\x5b\x38\x6c\x38\x77\x38\x7f\x38\xa7\x38\xae\x38\xb3\x38\xb8\x38\xbf\x38\xcc\x38\xdd\x38\xfa\x38\x07\x39\x1f\x39\x72\x39\x9f\x39\xe7\x39\x1f\x3a\x25\x3a\x2b\x3a\x31\x3a\x37\x3a\x3d\x3a\x44\x3a\x4b\x3a\x52\x3a\x59\x3a\x60\x3a\x67\x3a\x6e\x3a\x76\x3a\x7e\x3a\x86\x3a\x92\x3a\x9b\x3a\xa0\x3a\xa6\x3a\xb0\x3a\xb9\x3a\xc4\x3a\xd0\x3a\xd5\x3a\xe5\x3a\xea\x3a\xf0\x3a\xf6\x3a\x0c\x3b\x13\x3b\x1a\x3b\x28\x3b\x33\x3b\x39\x3b\x4c\x3b\x61\x3b\x6c\x3b\x82\x3b\x9a\x3b\xa4\x3b\xe1\x3b\xe6\x3b\x07\x3c\x0c\x3c\xc8\x3c\xcd\x3c\xdf\x3c\xfd\x3c\x11\x3d\x17\x3d\x7e\x3d\x84\x3d\x8a\x3d\x90\x3d\xa1\x3d\xbe\x3d\x0b\x3e\x10\x3e\x27\x3e\x4a\x3e\x57\x3e\x63\x3e\x6b\x3e\x73\x3e\x7f\x3e\xa8\x3e\xb0\x3e\xbc\x3e\xc2\x3e\xc8\x3e\xce\x3e\xd4\x3e\xda\x3e\x00\x20\x00\x00\x20\x00\x00\x00\x0c\x31\x40\x31\x44\x31\x34\x32\x38\x32\x00\x33\x08\x33\x0c\x33\x28\x33\x44\x33\x48\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") | 
