text:
#include "SDL_config.h"

/* Pocket PC GAPI SDL video driver implementation;
Implemented by Dmitry Yakimov - support@activekitten.com
Inspired by http://arisme.free.fr/ports/SDL.php
*/

// TODO: copy surface on window when lost focus
// TODO: test buttons rotation
// TODO: test on be300 and HPC ( check WinDib fullscreen keys catching )
// TODO: test on smartphones
// TODO: windib on SH3 PPC2000 landscape test
// TODO: optimize 8bpp landscape mode

// there is some problems in runnings apps from a device landscape mode
// due to WinCE bugs. Some works and some - does not.
// TODO: finish Axim Dell X30 and user landscape mode, device landscape mode
// TODO: finish Axim Dell X30 user portrait, device landscape stylus conversion
// TODO: fix running GAPI apps from landscape mode -
//       wince goes to portrait mode, but does not update video memory

#include "SDL.h"
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
#include "../wincommon/SDL_syswm_c.h"
#include "../wincommon/SDL_sysmouse_c.h"
#include "../windib/SDL_dibevents_c.h"

#include "SDL_gapivideo.h"

#define GAPIVID_DRIVER_NAME "gapi"

#if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG)
#define REPORT_VIDEO_INFO 1
#else
#define REPORT_VIDEO_INFO 0
#endif

// for testing with GapiEmu
#define USE_GAPI_EMU 0
#define EMULATE_AXIM_X30 0
#define WITHOUT_GAPI 0

#if USE_GAPI_EMU && !REPORT_VIDEO_INFO
#pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.")
#endif

// defined and used in SDL_sysevents.c
extern HINSTANCE aygshell;
extern void SDL_UnregisterApp();
extern int DIB_AddMode(_THIS, int bpp, int w, int h);

/* Initialization/Query functions */
static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat);
static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
static void GAPI_VideoQuit(_THIS);

/* Hardware surface functions */
static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface);
static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface);
static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface);
static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface);

/* Windows message handling functions, will not be processed */
static void GAPI_RealizePalette(_THIS);
static void GAPI_PaletteChanged(_THIS, HWND window);
static void GAPI_WinPAINT(_THIS, HDC hdc);

/* etc. */
static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects);

static HMODULE g_hGapiLib = 0;
#define LINK(type,name,import) \
	if( g_hGapiLib ) \
		name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) );

static char g_bRawBufferAvailable = 0;

/* GAPI driver bootstrap functions */

/* hi res definitions */
typedef struct _RawFrameBufferInfo
{
   WORD wFormat;
   WORD wBPP;
   VOID *pFramePointer;
   int  cxStride;
   int  cyStride;
   int  cxPixels;
   int  cyPixels;
} RawFrameBufferInfo;

static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0};

#define GETRAWFRAMEBUFFER   0x00020001

#define FORMAT_565 1
#define FORMAT_555 2
#define FORMAT_OTHER 3

/* Dell Axim x30 hangs when we use GAPI from landscape,
   so lets avoid using GxOpenDisplay there via GETGXINFO trick
   It seems that GAPI subsystem use the same ExtEscape code.
*/
#define GETGXINFO 0x00020000

typedef struct GXDeviceInfo
{
long Version; //00 (should filled with 100 before calling ExtEscape)
void * pvFrameBuffer; //04
unsigned long cbStride; //08
unsigned long cxWidth; //0c
unsigned long cyHeight; //10
unsigned long cBPP; //14
unsigned long ffFormat; //18
char Unused[0x84-7*4];
} GXDeviceInfo;

static int GAPI_Available(void)
{
	// try to use VGA display, even on emulator
	HDC hdc = GetDC(NULL);
	int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo);
	ReleaseDC(NULL, hdc);
	g_bRawBufferAvailable = result > 0;

#if WITHOUT_GAPI
	return g_bRawBufferAvailable;
#endif

#if USE_GAPI_EMU
	g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll"));
	if( !g_hGapiLib )
	{
		SDL_SetError("Gapi Emu not found!");
	}
	return g_hGapiLib != 0;
#endif

	// try to find gx.dll
	g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll"));
	if( !g_hGapiLib )
	{
		g_hGapiLib = LoadLibrary(_T("gx.dll"));
		if( !g_hGapiLib ) return g_bRawBufferAvailable;
	}

	return(1);
}

static int cmpmodes(const void *va, const void *vb)
{
    SDL_Rect *a = *(SDL_Rect **)va;
    SDL_Rect *b = *(SDL_Rect **)vb;
    if ( a->w == b->w )
        return b->h - a->h;
    else
        return b->w - a->w;
}

static int GAPI_AddMode(_THIS, int bpp, int w, int h)
{
	SDL_Rect *mode;
	int i, index;
	int next_mode;

	/* Check to see if we already have this mode */
	if ( bpp < 8 ) {  /* Not supported */
		return(0);
	}
	index = ((bpp+7)/8)-1;
	for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) {
		mode = gapi->SDL_modelist[index][i];
		if ( (mode->w == w) && (mode->h == h) ) {
			return(0);
		}
	}

	/* Set up the new video mode rectangle */
	mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
	if ( mode == NULL ) {
		SDL_OutOfMemory();
		return(-1);
	}
	mode->x = 0;
	mode->y = 0;
	mode->w = w;
	mode->h = h;

	/* Allocate the new list of modes, and fill in the new mode */
	next_mode = gapi->SDL_nummodes[index];
	gapi->SDL_modelist[index] = (SDL_Rect **)
	       SDL_realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
	if ( gapi->SDL_modelist[index] == NULL ) {
		SDL_OutOfMemory();
		gapi->SDL_nummodes[index] = 0;
		SDL_free(mode);
		return(-1);
	}
	gapi->SDL_modelist[index][next_mode] = mode;
	gapi->SDL_modelist[index][next_mode+1] = NULL;
	gapi->SDL_nummodes[index]++;

	return(0);
}

static void GAPI_DeleteDevice(SDL_VideoDevice *device)
{
	if( g_hGapiLib )
	{
		FreeLibrary(g_hGapiLib);
		g_hGapiLib = 0;
	}
	SDL_free(device->hidden);
	SDL_free(device);
}

static SDL_VideoDevice *GAPI_CreateDevice(int devindex)
{
	SDL_VideoDevice *device;

	if( !g_hGapiLib && !g_bRawBufferAvailable)
	{
		if( !GAPI_Available() )
		{
			SDL_SetError("GAPI dll is not found and VGA mode is not available!");
			return 0;
		}
	}

	/* Initialize all variables that we clean on shutdown */
	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
	if ( device ) {
		SDL_memset(device, 0, (sizeof *device));
		device->hidden = (struct SDL_PrivateVideoData *)
				SDL_malloc((sizeof *device->hidden));
	}
	if ( (device == NULL) || (device->hidden == NULL) ) {
		SDL_OutOfMemory();
		if ( device ) {
			SDL_free(device);
		}
		return(0);
	}
	SDL_memset(device->hidden, 0, (sizeof *device->hidden));

	/* Set the function pointers */
	device->VideoInit = GAPI_VideoInit;
	device->ListModes = GAPI_ListModes;
	device->SetVideoMode = GAPI_SetVideoMode;
	device->UpdateMouse = WIN_UpdateMouse;
	device->CreateYUVOverlay = NULL;
	device->SetColors = GAPI_SetColors;
	device->UpdateRects = GAPI_UpdateRects;
	device->VideoQuit = GAPI_VideoQuit;
	device->AllocHWSurface = GAPI_AllocHWSurface;
	device->CheckHWBlit = NULL;
	device->FillHWRect = NULL;
	device->SetHWColorKey = NULL;
	device->SetHWAlpha = NULL;
	device->LockHWSurface = GAPI_LockHWSurface;
	device->UnlockHWSurface = GAPI_UnlockHWSurface;
	device->FlipHWSurface = NULL;
	device->FreeHWSurface = GAPI_FreeHWSurface;
	device->SetCaption = WIN_SetWMCaption;
	device->SetIcon = WIN_SetWMIcon;
	device->IconifyWindow = WIN_IconifyWindow;
	device->GrabInput = WIN_GrabInput;
	device->GetWMInfo = WIN_GetWMInfo;
	device->FreeWMCursor = WIN_FreeWMCursor;
	device->CreateWMCursor = WIN_CreateWMCursor;
	device->ShowWMCursor = WIN_ShowWMCursor;
	device->WarpWMCursor = WIN_WarpWMCursor;
    device->CheckMouseMode = WIN_CheckMouseMode;
	device->InitOSKeymap = DIB_InitOSKeymap;
	device->PumpEvents = DIB_PumpEvents;

	/* Set up the windows message handling functions */
	WIN_RealizePalette = GAPI_RealizePalette;
	WIN_PaletteChanged = GAPI_PaletteChanged;
	WIN_WinPAINT = GAPI_WinPAINT;
	HandleMessage = DIB_HandleMessage;

	device->free = GAPI_DeleteDevice;

	/* Load gapi library */
#define gx device->hidden->gxFunc

    LINK( GXOpenDisplay, gx.GXOpenDisplay,         "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" )
    LINK( GXCloseDisplay, gx.GXCloseDisplay,        "?GXCloseDisplay@@YAHXZ" )
    LINK( GXBeginDraw, gx.GXBeginDraw,           "?GXBeginDraw@@YAPAXXZ" )
    LINK( GXEndDraw, gx.GXEndDraw,             "?GXEndDraw@@YAHXZ" )
    LINK( GXOpenInput, gx.GXOpenInput,           "?GXOpenInput@@YAHXZ" )
    LINK( GXCloseInput, gx.GXCloseInput,          "?GXCloseInput@@YAHXZ" )
    LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" )
    LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys,      "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" )
    LINK( GXSuspend, gx.GXSuspend,             "?GXSuspend@@YAHXZ" )
    LINK( GXResume, gx.GXResume,              "?GXResume@@YAHXZ" )
    LINK( GXSetViewport, gx.GXSetViewport,         "?GXSetViewport@@YAHKKKK@Z" )
    LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" )

	/* wrong gapi.dll */
	if( !gx.GXOpenDisplay )
	{
		if( g_hGapiLib )
		{
			FreeLibrary(g_hGapiLib);
			g_hGapiLib = 0;
		}
	}

	if( !gx.GXOpenDisplay && !g_bRawBufferAvailable)
	{
		SDL_SetError("Error: damaged or unknown gapi.dll!\n");
		GAPI_DeleteDevice(device);
		return 0;
	}

	return device;
}

VideoBootStrap GAPI_bootstrap = {
	GAPIVID_DRIVER_NAME, "WinCE GAPI video driver",
	GAPI_Available, GAPI_CreateDevice
};

static void FillStructs(_THIS, BOOL useVga)
{
#ifdef _ARM_
	WCHAR oemstr[100];
#endif
	/* fill a device properties */

	if( !useVga )
	{
		this->hidden->gxProperties = this->hidden->gxFunc.GXGetDisplayProperties();
		this->hidden->needUpdate = 1;
		this->hidden->hiresFix = 0;
		this->hidden->useVga = 0;
		this->hidden->useGXOpenDisplay = 1;

#ifdef _ARM_
		/* check some devices and extract addition info */
		SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 );

		// buggy iPaq38xx
		if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (this->hidden->gxProperties.cbxPitch > 0))
		{
			this->hidden->videoMem = (PIXEL*)0xac0755a0;
			this->hidden->gxProperties.cbxPitch = -640;
			this->hidden->gxProperties.cbyPitch = 2;
			this->hidden->needUpdate = 0;
		}
#if (EMULATE_AXIM_X30 == 0)
		// buggy Dell Axim X30
		if( _tcsncmp(oemstr, L"Dell Axim X30", 13) == 0 )
#endif
		{
			GXDeviceInfo gxInfo = {0};
			HDC hdc = GetDC(NULL);
			int result;

			gxInfo.Version = 100;
			result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *)&gxInfo);
			if( result > 0 )
			{
				this->hidden->useGXOpenDisplay = 0;
				this->hidden->videoMem = gxInfo.pvFrameBuffer;
				this->hidden->needUpdate = 0;
				this->hidden->gxProperties.cbxPitch = 2;
				this->hidden->gxProperties.cbyPitch = 480;
				this->hidden->gxProperties.cxWidth = gxInfo.cxWidth;
				this->hidden->gxProperties.cyHeight = gxInfo.cyHeight;
				this->hidden->gxProperties.ffFormat = gxInfo.ffFormat;
			}
		}
#endif
	} else
	{
	    this->hidden->needUpdate = 0;
		this->hidden->hiresFix = 0;
		this->hidden->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP;
		this->hidden->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride;
		this->hidden->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride;
		this->hidden->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels;
		this->hidden->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels;
		this->hidden->videoMem = g_RawFrameBufferInfo.pFramePointer;
		this->hidden->useVga = 1;

		switch( g_RawFrameBufferInfo.wFormat )
		{
		case FORMAT_565:
			this->hidden->gxProperties.ffFormat = kfDirect565;
			break;
		case FORMAT_555:
			this->hidden->gxProperties.ffFormat = kfDirect555;
			break;
		default:
			/* unknown pixel format, try define by BPP! */
			switch( g_RawFrameBufferInfo.wBPP )
			{
			case 4:
			case 8:
				this->hidden->gxProperties.ffFormat = kfDirect;
			case 16:
				this->hidden->gxProperties.ffFormat = kfDirect565;
			default:
				this->hidden->gxProperties.ffFormat = kfDirect;
				break;
			}
		}
	}

	if( this->hidden->gxProperties.cBPP != 16 )
	{
		this->hidden->gapiOrientation = SDL_ORIENTATION_UP;
	} else
	if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch > 0 ))
	{
		this->hidden->gapiOrientation = SDL_ORIENTATION_UP;
	} else
	if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch < 0 ))
	{
		this->hidden->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660
	} else
	if( (this->hidden->gxProperties.cbxPitch < 0) && (this->hidden->gxProperties.cbyPitch > 0 ))
	{
		this->hidden->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800
	}
}

static void GAPI_CreatePalette(int ncolors, SDL_Color *colors)
{
  // Setup a custom color palette
   BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ];
   int i;
   LOGPALETTE*   pLogical = (LOGPALETTE*)buffer;
   PALETTEENTRY* entries  = pLogical->palPalEntry;
   HPALETTE hPalette;
   HDC hdc;

   for (i = 0; i < ncolors; ++i)
   {
      // Find intensity by replicating the bit patterns over a byte
      entries[i].peRed   = colors[i].r;
      entries[i].peGreen = colors[i].g;
      entries[i].peBlue  = colors[i].b;
      entries[i].peFlags = 0;
   }

   // Create the GDI palette object
   pLogical->palVersion    = 0x0300;
   pLogical->palNumEntries = ncolors;

   hPalette = CreatePalette( pLogical );
   ASSERT(hPalette);

   // Realize the palette
   hdc = GetDC(0);

   SelectPalette( hdc, hPalette, FALSE );
   RealizePalette( hdc );

   ReleaseDC( 0, hdc );
   DeleteObject( hPalette );
}

int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat)
{
	int i,bpp;

	/* Create the window */
	if ( DIB_CreateWindow(this) < 0 ) {
		return(-1);
	}

	if( g_hGapiLib )
	{
		FillStructs(this, 0);

		// SDL does not supports 2/4bpp mode, so use 16 bpp
		bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;

		/* set up normal and landscape mode */
		GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);
		GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);
	}

	/* add hi-res mode */
	if( g_bRawBufferAvailable &&
		!((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels)))
	{
		FillStructs(this, 1);

		// SDL does not supports 2/4bpp mode, so use 16 bpp
		bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;

		/* set up normal and landscape mode */
		GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);
		GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);
	}

	/* Determine the current screen size */
	this->info.current_w = gapi->gxProperties.cxWidth;
	this->info.current_h = gapi->gxProperties.cyHeight;

	/* Sort the mode lists */
	for ( i=0; i<NUM_MODELISTS; ++i ) {
		if ( gapi->SDL_nummodes[i] > 0 ) {
			SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes);
		}
	}

	vformat->BitsPerPixel = this->hidden->gxProperties.cBPP < 8 ? 16 : (unsigned char)this->hidden->gxProperties.cBPP;

	// Get color mask
	if (this->hidden->gxProperties.ffFormat & kfDirect565) {
		vformat->BitsPerPixel = 16;
		vformat->Rmask = 0x0000f800;
		vformat->Gmask = 0x000007e0;
		vformat->Bmask = 0x0000001f;
		this->hidden->videoMode = GAPI_DIRECT_565;
	}
	else
	if (this->hidden->gxProperties.ffFormat & kfDirect555) {
		vformat->BitsPerPixel = 16;
		vformat->Rmask = 0x00007c00;
		vformat->Gmask = 0x000003e0;
		vformat->Bmask = 0x0000001f;
		this->hidden->videoMode = GAPI_DIRECT_555;
	}
	else
	if ((this->hidden->gxProperties.ffFormat & kfDirect) && (this->hidden->gxProperties.cBPP < 8)) {
		// We'll perform the conversion
		vformat->BitsPerPixel = 16;
		vformat->Rmask = 0x0000f800; // 16 bit 565
		vformat->Gmask = 0x000007e0;
		vformat->Bmask = 0x0000001f;
		if (this->hidden->gxProperties.ffFormat & kfDirectInverted)
			this->hidden->invert = (1 << this->hidden->gxProperties.cBPP) - 1;
		this->hidden->colorscale = this->hidden->gxProperties.cBPP < 8 ? 8 - this->hidden->gxProperties.cBPP : 0;
		this->hidden->videoMode = GAPI_MONO;
	}
	else
	if (this->hidden->gxProperties.ffFormat & kfPalette) {
		this->hidden->videoMode = GAPI_PALETTE;
	}

	/* We're done! */
	return(0);
}

SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
{
	return(this->hidden->SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
//  	 return (SDL_Rect **) -1;
}

SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current,
				int width, int height, int bpp, Uint32 flags)
{
	SDL_Surface *video;
	Uint32 Rmask, Gmask, Bmask;
	DWORD style;
	SDL_Rect allScreen;

	if( bpp < 4 )
	{
		SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!");
		return 0;
	}

	/* Recalculate bitmasks if necessary */
	if (bpp == current->format->BitsPerPixel) {
		video = current;
	}
	else {
		switch(bpp) {
			case 8:
				Rmask = 0;
				Gmask = 0;
				Bmask = 0;
				break;
			case 15:
			case 16:
				/* Default is 565 unless the display is specifically 555 */
				if (this->hidden->gxProperties.ffFormat & kfDirect555) {
					Rmask = 0x00007c00;
					Gmask = 0x000003e0;
					Bmask = 0x0000001f;
				}
				else {
					Rmask = 0x0000f800;
					Gmask = 0x000007e0;
					Bmask = 0x0000001f;
				}
				break;
			case 24:
			case 32:
				Rmask = 0x00ff0000;
				Gmask = 0x0000ff00;
				Bmask = 0x000000ff;
				break;
			default:
				SDL_SetError("Unsupported Bits Per Pixel format requested");
				return NULL;
		}
		video = SDL_CreateRGBSurface(SDL_SWSURFACE,
					0, 0, bpp, Rmask, Gmask, Bmask, 0);
		if ( video == NULL ) {
			SDL_OutOfMemory();
			return(NULL);
		}
	}

	gapi->userOrientation = SDL_ORIENTATION_UP;
	video->flags = SDL_FULLSCREEN;	/* Clear flags, GAPI supports fullscreen only */

	/* GAPI or VGA? */
	if( g_hGapiLib )
	{
		FillStructs(this, 0);
		if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight))
			&& (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth)))
			FillStructs(this, 1); // gapi is found but we use VGA resolution
	} else
		FillStructs(this, 1);

	if ( !this->hidden->needUpdate && !this->hidden->videoMem) {
		SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug");
		return(NULL);
	}

	/* detect user landscape mode */
	if( (width > height) && (GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN)))
		gapi->userOrientation = SDL_ORIENTATION_RIGHT;

	/* shall we apply hires fix? for example when we do not use hires resource */
	gapi->hiresFix = 0;
	if( gapi->userOrientation == SDL_ORIENTATION_RIGHT )
	{
		if( (width > GetSystemMetrics(SM_CYSCREEN)) || (height > GetSystemMetrics(SM_CXSCREEN)))
			gapi->hiresFix = 1;
	} else
		if( (width > GetSystemMetrics(SM_CXSCREEN)) || (height > GetSystemMetrics(SM_CYSCREEN)))
			if( !((width == GetSystemMetrics(SM_CYSCREEN)) && (height == GetSystemMetrics(SM_CXSCREEN)))) // user portrait, device landscape
				gapi->hiresFix = 1;

	switch( gapi->userOrientation )
	{
	case SDL_ORIENTATION_UP:
		gapi->startOffset = 0;
		gapi->dstLineStep = gapi->gxProperties.cbyPitch;
		gapi->dstPixelStep = gapi->gxProperties.cbxPitch;
		break;
	case SDL_ORIENTATION_RIGHT:
		switch( gapi->gapiOrientation )
		{
		case SDL_ORIENTATION_UP:
		case SDL_ORIENTATION_RIGHT:
		case SDL_ORIENTATION_LEFT:
			if( (this->hidden->videoMode == GAPI_MONO) )
				gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode
			else
				gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1);

			gapi->dstLineStep = gapi->gxProperties.cbxPitch;
			gapi->dstPixelStep = -gapi->gxProperties.cbyPitch;
			break;
		}
	}

	video->w = this->hidden->w = width;
	video->h = this->hidden->h = height;
	video->pitch = SDL_CalculatePitch(video);

	/* Small fix for WinCE/Win32 - when activating window
	   SDL_VideoSurface is equal to zero, so activating code
	   is not called properly for fullscreen windows because
	   macros WINDIB_FULLSCREEN uses SDL_VideoSurface
	*/
	SDL_VideoSurface = video;

	/* GAPI is always fullscreen, title bar is useless */
	style = 0;

	if (!SDL_windowid)
		SetWindowLong(SDL_Window, GWL_STYLE, style);

	/* Allocate bitmap */
	if(gapiBuffer)
	{
		SDL_free(gapiBuffer);
		gapiBuffer = NULL;
	}
	gapiBuffer = SDL_malloc(video->h * video->pitch);
	video->pixels = gapiBuffer;

	if ( ! this->hidden->buffer ) {
		SDL_SetError("Couldn't allocate buffer for requested mode");
		return(NULL);
	}

	SDL_memset(gapiBuffer, 255, video->h * video->pitch);
	MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE);
	ShowWindow(SDL_Window, SW_SHOW);
	SetForegroundWindow(SDL_Window);

	/* JC 14 Mar 2006
		Flush the message loop or this can cause big problems later
		Especially if the user decides to use dialog boxes or assert()!
	*/
	WIN_FlushMessageQueue();

	/* Open GAPI display */
	if( !gapi->useVga && this->hidden->useGXOpenDisplay )
		if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) )
		{
			SDL_SetError("Couldn't initialize GAPI");
			return(NULL);
		}

#if REPORT_VIDEO_INFO
	printf("Video properties:\n");
	printf("display bpp: %d\n", gapi->gxProperties.cBPP);
	printf("display width: %d\n", gapi->gxProperties.cxWidth);
	printf("display height: %d\n", gapi->gxProperties.cyHeight);
	printf("x pitch: %d\n", gapi->gxProperties.cbxPitch);
	printf("y pitch: %d\n", gapi->gxProperties.cbyPitch);
	printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat);

	if( !gapi->useVga && this->hidden->useGXOpenDisplay && gapi->needUpdate)
	{
		gapi->videoMem = gapi->gxFunc.GXBeginDraw();
		gapi->gxFunc.GXEndDraw();
	}

	printf("video memory: 0x%x\n", gapi->videoMem);
	printf("need update: %d\n", gapi->needUpdate);
	printf("hi-res fix: %d\n", gapi->hiresFix);
	printf("VGA is available on the device: %d\n", g_bRawBufferAvailable);
	printf("use raw framebuffer: %d\n", gapi->useVga);
	printf("video surface bpp: %d\n", video->format->BitsPerPixel);
	printf("video surface width: %d\n", video->w);
	printf("video surface height: %d\n", video->h);
#endif

	/* Blank screen */
	allScreen.x = allScreen.y = 0;
	allScreen.w = video->w - 1;
	allScreen.h = video->h - 1;
	GAPI_UpdateRects(this, 1, &allScreen);

	/* We're done */
	return(video);
}

/* We don't actually allow hardware surfaces other than the main one */
static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface)
{
	return(-1);
}
static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface)
{
	return;
}

/* We need to wait for vertical retrace on page flipped displays */
static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface)
{
	return(0);
}

static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface)
{
	return;
}

static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines)
{
	if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */
	{
		SDL_memcpy(destPointer, srcPointer, width);
		return 1;
	} else
	{
		// TODO: read 4 pixels, write DWORD
		int step = gapi->dstPixelStep;
		while(width--)
		{
			*destPointer = *srcPointer++;
			destPointer += step;
		}
	}
	return 1;
}

/* Video memory is very slow so lets optimize as much as possible */
static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines)
{
	PIXEL *line1, *line2;
	int step = gapi->dstPixelStep / 2;

	if( step == 1 ) /* optimized blitting on most devices */
	{
		SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL));
		return 1;
	}
	else
	{
		if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) &&
			(gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up
		{
			// to prevent data misalignment copy only one line
			if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT))
				|| ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT))
				|| (lines == 1) )
			{
				while(width--)
				{
					*destPointer = *srcPointer++;
					destPointer += step;
				}
				return 1;
			}

			/* read two lines at the same time, write DWORD */
			line1 = srcPointer;
			line2 = srcPointer + SDL_VideoSurface->pitch / 2;

			if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
				while(width--) // iPaq 3800
				{
					*(DWORD*)destPointer =(*line2++ << 16) | *line1++;
					destPointer += step;
				}
			else
			{
				destPointer += gapi->gxProperties.cbyPitch / 2;

				while(width--) // iPaq 3660
				{
					*(DWORD*)destPointer =(*line1++ << 16) | *line2++;
					destPointer += step;
				}
			}
			return 2;
		} else
		{
			// iPaq 3800 and user orientation landscape
			if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
			{
				int w1;

				// to prevent data misalignment copy only one pixel
				if( (((unsigned)destPointer & 3) == 0) && (width > 0))
				{
					*destPointer-- = *srcPointer++;
					width--;
				}

				destPointer--;

				w1 = width / 2;

				while(w1--)
				{
					DWORD p = *(DWORD*)srcPointer;
					*((DWORD*)destPointer) = (p << 16) | (p >> 16);
					destPointer -= 2;
					srcPointer += 2;
				}

				if( width & 1 ) // copy the last pixel
				{
					destPointer++;
					*destPointer = *srcPointer;
				}

				return 1;
			}

			// modern iPaqs and user orientation landscape
			// read two pixels, write DWORD

			line1 = srcPointer;
			line2 = srcPointer + SDL_VideoSurface->pitch / 2;

			if( (((unsigned)destPointer & 3) != 0) || (lines == 1) )
			{
				while(width--)
				{
					*destPointer = *srcPointer++;
					destPointer += step;
				}
				return 1;
			}

			while(width--)
			{
				*(DWORD*)destPointer =(*line2++ << 16) | *line1++;
				destPointer -= gapi->gxProperties.cbyPitch / 2;
			}
			return 2;
		}
	}
}

// Color component masks for 565
#define REDMASK (31<<11)
#define GREENMASK (63<<5)
#define BLUEMASK (31)

static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble)
{
	PIXEL *line1, *line2;
	int step = gapi->dstPixelStep;

	if( gapi->userOrientation == SDL_ORIENTATION_UP )
	{
		if( yNibble ) // copy bottom half of a line
		{
			while(width--)
			{
				PIXEL c1 = *srcPointer++;
				c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
				*destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
				destPointer += step;
			}
			return 1;
		}

		// either 1 pixel picture or tail, anyway this is the last line
		if( lines == 1 )
		{
			while(width--)
			{
				PIXEL c1 = *srcPointer++;
				c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
				*destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
				destPointer += step;
			}
			return 1;
		}

		line1 = srcPointer;
		line2 = srcPointer + SDL_VideoSurface->pitch / 2;

		while(width--)
		{
			PIXEL c1 = *line1++;
			PIXEL c2 = *line2++;
			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
			c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
			*destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4));
			destPointer += step;
		}
		return 2;
	} else
	{
		int w1;
		w1 = width / 2;

		if( xNibble )
		{
			// copy one pixel
			PIXEL c1 = *srcPointer++;
			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
			*destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
			destPointer++;
		}

		while(w1--)
		{
			PIXEL c1 = *srcPointer;
			PIXEL c2 = *(srcPointer + 1);
			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
			c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
			*destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4));
			srcPointer += 2;
		}

		// copy tail
		if( (width & 1) && !xNibble )
		{
			PIXEL c1 = *srcPointer;
			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
			*destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
		}

		return 1;
	}
}

static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects)
{
	int i, height;
	int linesProcessed;
	int xNibble, yNibble;

	for (i=0; i<numrects; i++)
	{
		unsigned char *destPointer;
		unsigned char *srcPointer;

		if( gapi->userOrientation == SDL_ORIENTATION_UP )
			destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep;
		else
			destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep;

		srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2;
		yNibble = rects[i].y & 1; // TODO: only for 4 bpp
		xNibble = rects[i].x & 1;
		height = rects[i].h;
		while (height > 0)
		{
			switch(gapi->gxProperties.cBPP)
			{
			case 2: // TODO
			case 4:
					linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble);
					yNibble = 0;
			}
			height -= linesProcessed;
			if( gapi->userOrientation == SDL_ORIENTATION_UP )
				destPointer--; // always fill 1 byte
			else destPointer += gapi->dstLineStep;
			srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
		}
	}
}

static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects)
{
	int i, height;
	int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8;
	int linesProcessed;
	for (i=0; i<numrects; i++) {
		unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep;
		unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel;
		height = rects[i].h;

//		fprintf(stderr, "Starting rect %dx%d, dst=0x%x, w = %d, h = %d\n", rects[i].w, rects[i].h,destPointer,rects[i].w,rects[i].h);
//		fflush(stderr);
		linesProcessed = height;

		while (height > 0) {
			switch(bytesPerPixel)
			{
			case 1:
				linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height);
				break;
			case 2:
#pragma warning(disable: 4133)
				linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height);
				break;
			}
			height -= linesProcessed;
			destPointer += gapi->dstLineStep * linesProcessed;
			srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
		}
//		fprintf(stderr, "End of rect\n");
//		fflush(stderr);
	}
}

static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
{
	// we do not want to corrupt video memory
	if( gapi->suspended ) return;

	if( gapi->needUpdate )
		gapi->videoMem = gapi->gxFunc.GXBeginDraw();

	if( gapi->gxProperties.cBPP < 8 )
		GAPI_UpdateRectsMono(this, numrects, rects);
	else
		GAPI_UpdateRectsColor(this, numrects, rects);

	if( gapi->needUpdate )
		gapi->gxFunc.GXEndDraw();
}

/* Note:  If we are terminated, this could be called in the middle of
   another SDL video routine -- notably UpdateRects.
*/
void GAPI_VideoQuit(_THIS)
{
	int i, j;
	/* Destroy the window and everything associated with it */
	if ( SDL_Window )
	{
	    if ((g_hGapiLib != 0) && this && this->hidden && this->hidden->gxFunc.GXCloseDisplay && !this->hidden->useVga)
			this->hidden->gxFunc.GXCloseDisplay();

		if (this->screen->pixels != NULL)
		{
			SDL_free(this->screen->pixels);
			this->screen->pixels = NULL;
		}
		if ( screen_icn ) {
			DestroyIcon(screen_icn);
			screen_icn = NULL;
		}

		DIB_DestroyWindow(this);
		SDL_UnregisterApp();

		SDL_Window = NULL;
#if defined(_WIN32_WCE)

// Unload wince aygshell library to prevent leak
		if( aygshell )
		{
			FreeLibrary(aygshell);
			aygshell = NULL;
		}
#endif

	/* Free video mode lists */
	for ( i=0; i<NUM_MODELISTS; ++i ) {
		if ( gapi->SDL_modelist[i] != NULL ) {
			for ( j=0; gapi->SDL_modelist[i][j]; ++j )
				SDL_free(gapi->SDL_modelist[i][j]);
			SDL_free(gapi->SDL_modelist[i]);
			gapi->SDL_modelist[i] = NULL;
		}
	}

	}

}

static void GAPI_RealizePalette(_THIS)
{
	OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n"));
}

static void GAPI_PaletteChanged(_THIS, HWND window)
{
	OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
}

static void GAPI_WinPAINT(_THIS, HDC hdc)
{
	// draw current offscreen buffer on hdc

	int bpp = 16; // we always use either 8 or 16 bpp internally
	HGDIOBJ prevObject;
	unsigned short *bitmapData;
	HBITMAP hb;
	HDC srcDC;

    // Create a DIB
    BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0};
    BITMAPINFO*       pBMI    = (BITMAPINFO*)buffer;
    BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader;
    DWORD*            pColors = (DWORD*)&pBMI->bmiColors;

	// CreateDIBSection does not support 332 pixel format on wce
	if( gapi->gxProperties.cBPP == 8 ) return;

    // DIB Header
    pHeader->biSize            = sizeof(BITMAPINFOHEADER);
    pHeader->biWidth           = this->hidden->w;
    pHeader->biHeight          = -this->hidden->h;
    pHeader->biPlanes          = 1;
    pHeader->biBitCount        = bpp;
    pHeader->biCompression     = BI_RGB;
    pHeader->biSizeImage       = (this->hidden->w * this->hidden->h * bpp) / 8;

    // Color masks
	if( bpp == 16 )
	{
		pColors[0] = REDMASK;
		pColors[1] = GREENMASK;
		pColors[2] = BLUEMASK;
		pHeader->biCompression = BI_BITFIELDS;
	}
    // Create the DIB
    hb =  CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 );

	// copy data
	// FIXME: prevent misalignment, but I've never seen non aligned width of screen
	memcpy(bitmapData, this->hidden->buffer, pHeader->biSizeImage);
	srcDC = CreateCompatibleDC(hdc);
	prevObject = SelectObject(srcDC, hb);

	BitBlt(hdc, 0, 0, this->hidden->w, this->hidden->h, srcDC, 0, 0, SRCCOPY);

	SelectObject(srcDC, prevObject);
	DeleteObject(hb);
	DeleteDC(srcDC);
}

int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
{
	GAPI_CreatePalette(ncolors, colors);
	return 1;
}


text:
using System;

namespace TomP2P.Core.Connection
{
    /// <summary>
    /// Stores port information.
    /// </summary>
    public class Ports
    {
        // the maximal port number, 2^16
        public const int MaxPort = 65535;
        // IANA recommends to use ports higher or equal than 49152
        public const int MinDynPort = 49152;
        // the default port of TomP2P
        public const int DefaultPort = 7700;

        private const int Range = MaxPort - MinDynPort;
        private static readonly Random Random = new Random();

        // provide this information if you know your mapping beforehand
        // i.e., manual port-forwarding
        /// <summary>
        /// The external TCP port, how other peers see us.
        /// </summary>
        public int TcpPort { get; private set; }
        /// <summary>
        /// The external UDP port, how other peers see us.
        /// </summary>
        public int UdpPort { get; private set; }
        private readonly bool _randomPorts;

        /// <summary>
        /// Creates random ports for TCP and UDP. The random ports start from port 49152.
        /// </summary>
        public Ports()
            : this(-1, -1)
        { }

        /// <summary>
        /// Creates a Ports class that stores port information.
        /// </summary>
        /// <param name="tcpPort">The external TCP port, how other peers will see us. If the provided port is negative, a random port will be used.</param>
        /// <param name="udpPort">The external UDP port, how other peers will see us. If the provided port is negative, a random port will be used.</param>
        public Ports(int tcpPort, int udpPort)
        {
            _randomPorts = tcpPort < 0 && udpPort < 0;
            TcpPort = tcpPort < 0 ? (Random.Next(Range) + MinDynPort) : tcpPort;
            UdpPort = udpPort < 0 ? (Random.Next(Range) + MinDynPort) : udpPort;
        }

        /// <summary>
        /// True, if the user specified both ports in advance. This tells us that the
        /// user knows about the ports and did a manual port-forwarding.
        /// </summary>
        public bool IsManualPort
        {
            get { return !_randomPorts; }
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
require 'rails'

module Kube
  module Rails
    class Engine < ::Rails::Engine
      initializer 'kube-rails.setup',
                  after: 'less-rails.after.load_config_initializers',
                  group: :all do |app|
        app.config.less.paths << File.join(config.root, 'vendor')
      end
    end
  end
end


text:
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["PaneGroup"] = factory();
	else
		root["relm"] = root["relm"] || {}, root["relm"]["PaneGroup"] = factory();
})(this, function() {
return webpackJsonprelm__name_([9],{

/***/ 320:
/***/ function(module, exports, __webpack_require__) {

"use strict";
/* harmony export */ exports["default"] = PaneGroup;var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _templateObject = _taggedTemplateLiteral(["\n  .paneGroup {\n    position: absolute;\n    top: 0;\n    right: 0;\n    bottom: 0;\n    left: 0;\n    display: flex;\n  }\n"], ["\n  .paneGroup {\n    position: absolute;\n    top: 0;\n    right: 0;\n    bottom: 0;\n    left: 0;\n    display: flex;\n  }\n"]);

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function PaneGroup(h, _ref) {
  var styles = _ref.styles;
  var props = _ref.props;
  var children = _ref.children;

  return h(
    "div",
    _extends({}, props, { className: [styles.paneGroup, props.className] }),
    children
  );
}

PaneGroup.styles = function (css) {
  return css(_templateObject);
};

/***/ }

},[320])
});
;


text:
namespace WinUX.Xaml.Controls
{
    using System;

    using Windows.Foundation;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;

    using WinUX.Maths;

    /// <summary>
    /// Defines a panel that supports wrapping content in a view.
    /// </summary>
    public sealed partial class WrapPanel : Panel
    {
        private bool ignorePropertyChange;

        /// <summary>
        /// Measures the child elements of the panel.
        /// </summary>
        /// <param name="constraint">
        /// The size available for child elements.
        /// </param>
        /// <returns>
        /// Returns the size required by the panel.
        /// </returns>
        protected override Size MeasureOverride(Size constraint)
        {
            var o = this.Orientation;
            var lineSize = new OrientedSize(o);
            var totalSize = new OrientedSize(o);
            var maximumSize = new OrientedSize(o, constraint.Width, constraint.Height);

            // Determine the constraints for individual items
            double itemWidth = this.ItemWidth;
            double itemHeight = this.ItemHeight;
            bool hasFixedWidth = !double.IsNaN(itemWidth);
            bool hasFixedHeight = !double.IsNaN(itemHeight);
            var itemSize = new Size(
                hasFixedWidth ? itemWidth : constraint.Width,
                hasFixedHeight ? itemHeight : constraint.Height);

            // Measure each of the children
            foreach (var element in this.Children)
            {
                // Determine the size of the element
                element.Measure(itemSize);
                var elementSize = new OrientedSize(
                    o,
                    hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                    hasFixedHeight ? itemHeight : element.DesiredSize.Height);

                // If this element falls of the edge of the line
                if (MathHelper.IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    // Update the total size with the direct and indirect growth for the current line
                    totalSize.Direct = Math.Max(lineSize.Direct, totalSize.Direct);
                    totalSize.Indirect += lineSize.Indirect;

                    // Move the element to a new line
                    lineSize = elementSize;

                    // If the current element is larger than the maximum size, place it on a line by itself
                    if (MathHelper.IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        // Update the total size for the line occupied by this single element
                        totalSize.Direct = Math.Max(elementSize.Direct, totalSize.Direct);
                        totalSize.Indirect += elementSize.Indirect;

                        // Move to a new line
                        lineSize = new OrientedSize(o);
                    }
                }
                else
                {
                    // Otherwise just add the element to the end of the line
                    lineSize.Direct += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }

            // Update the total size with the elements on the last line
            totalSize.Direct = Math.Max(lineSize.Direct, totalSize.Direct);
            totalSize.Indirect += lineSize.Indirect;

            // Return the total size required as an un-oriented quantity
            return new Size(totalSize.Width, totalSize.Height);
        }

        /// <summary>
        /// Arranges the child elements of the panel.
        /// </summary>
        /// <param name="finalSize">
        /// The final size.
        /// </param>
        /// <returns>
        /// Returns the size required by the panel.
        /// </returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            var o = this.Orientation;
            var lineSize = new OrientedSize(o);
            var maximumSize = new OrientedSize(o, finalSize.Width, finalSize.Height);

            // Determine the constraints for individual items
            double itemWidth = this.ItemWidth;
            double itemHeight = this.ItemHeight;
            bool hasFixedWidth = !itemWidth.IsNaN();
            bool hasFixedHeight = !itemHeight.IsNaN();
            double indirectOffset = 0;
            var directDelta = (o == Orientation.Horizontal)
                                  ? (hasFixedWidth ? (double?)itemWidth : null)
                                  : (hasFixedHeight ? (double?)itemHeight : null);

            var children = this.Children;
            int count = children.Count;
            int lineStart = 0;
            for (var lineEnd = 0; lineEnd < count; lineEnd++)
            {
                var element = children[lineEnd];

                // Get the size of the element
                var elementSize = new OrientedSize(
                    o,
                    hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                    hasFixedHeight ? itemHeight : element.DesiredSize.Height);

                // If this element falls of the edge of the line
                if (MathHelper.IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    // Then we just completed a line and we should arrange it
                    this.ArrangeLine(lineStart, lineEnd, directDelta, indirectOffset, lineSize.Indirect);

                    // Move the current element to a new line
                    indirectOffset += lineSize.Indirect;
                    lineSize = elementSize;

                    // If the current element is larger than the maximum size
                    if (MathHelper.IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        // Arrange the element as a single line
                        this.ArrangeLine(lineEnd, ++lineEnd, directDelta, indirectOffset, elementSize.Indirect);

                        // Move to a new line
                        indirectOffset += lineSize.Indirect;
                        lineSize = new OrientedSize(o);
                    }

                    // Advance the start index to a new line after arranging
                    lineStart = lineEnd;
                }
                else
                {
                    // Otherwise just add the element to the end of the line
                    lineSize.Direct += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }

            // Arrange any elements on the last line
            if (lineStart < count)
            {
                this.ArrangeLine(lineStart, count, directDelta, indirectOffset, lineSize.Indirect);
            }

            return finalSize;
        }

        private void ArrangeLine(
            int lineStart,
            int lineEnd,
            double? directDelta,
            double indirectOffset,
            double indirectGrowth)
        {
            double directOffset = 0.0;

            var o = this.Orientation;
            bool isHorizontal = o == Orientation.Horizontal;

            var children = this.Children;
            for (var index = lineStart; index < lineEnd; index++)
            {
                // Get the size of the element
                var element = children[index];
                var elementSize = new OrientedSize(o, element.DesiredSize.Width, element.DesiredSize.Height);

                // Determine if we should use the element's desired size or the fixed item width or height
                double directGrowth = directDelta ?? elementSize.Direct;

                // Arrange the element
                var bounds = isHorizontal
                                 ? new Rect(directOffset, indirectOffset, directGrowth, indirectGrowth)
                                 : new Rect(indirectOffset, directOffset, indirectGrowth, directGrowth);

                element.Arrange(bounds);

                directOffset += directGrowth;
            }
        }

        private void OnOrientationChanged(DependencyPropertyChangedEventArgs e)
        {
            var value = (Orientation)e.NewValue;

            if (this.ignorePropertyChange)
            {
                this.ignorePropertyChange = false;
                return;
            }

            if ((value != Orientation.Horizontal) && (value != Orientation.Vertical))
            {
                this.ignorePropertyChange = true;
                this.SetValue(WrapPanel.OrientationProperty, (Orientation)e.OldValue);

                return;
            }

            this.InvalidateMeasure();
        }

        private void OnItemSizeChanged(DependencyPropertyChangedEventArgs e)
        {
            double value = (double)e.NewValue;

            if (this.ignorePropertyChange)
            {
                this.ignorePropertyChange = false;
                return;
            }

            if (!double.IsNaN(value) && ((value <= 0.0) || double.IsPositiveInfinity(value)))
            {
                this.ignorePropertyChange = true;
                this.SetValue(e.Property, (double)e.OldValue);

                return;
            }

            this.InvalidateMeasure();
        }
    }
}


text:
import vim

SCOPE_ALL = 1

# for all vim-orgmode buffers
SCOPE_GLOBAL = 2

# just for the current buffer - has priority before the global settings
SCOPE_BUFFER = 4

VARIABLE_LEADER = {SCOPE_GLOBAL: u'g', SCOPE_BUFFER: u'b'}

u""" Evaluate and store settings """

def get(setting, default=None, scope=SCOPE_ALL):
	u""" Evaluate setting in scope of the current buffer,
	globally and also from the contents of the current buffer

	WARNING: Only string values are converted to unicode. If a different value
	is received, e.g. a list or dict, no conversion is done.

	:setting: name of the variable to evaluate
	:default: default value in case the variable is empty

	:returns: variable value
	"""
	# TODO first read setting from org file which take precedence over vim
	# variable settings
	if scope & SCOPE_ALL | SCOPE_BUFFER and int(vim.eval((u'exists("b:%s")' % setting).encode(u'utf-8'))):
		res = vim.eval((u"b:%s" % setting).encode(u'utf-8'))
		if type(res) in (unicode, str):
			return res.decode(u'utf-8')
		return res

	elif scope & SCOPE_ALL | SCOPE_GLOBAL and int(vim.eval((u'exists("g:%s")' % setting).encode(u'utf-8'))):
		res = vim.eval((u"g:%s" % setting).encode(u'utf-8'))
		if type(res) in (unicode, str):
			return res.decode(u'utf-8')
		return res
	return default

def set(setting, value, scope=SCOPE_GLOBAL, overwrite=False):
	u""" Store setting in the definied scope

	WARNING: For the return value, only string are converted to unicode. If a
	different value is received by vim.eval, e.g. a list or dict, no conversion
	is done.

	:setting: name of the setting
	:value: the actual value, repr is called on the value to create a string representation
	:scope: the scope o the setting/variable
	:overwrite: overwrite existing settings (probably user definied settings)

	:returns: the new value in case of overwrite==False the current value
	"""
	if not overwrite and int(vim.eval((u'exists("%s:%s")' % (VARIABLE_LEADER[scope], setting)).encode(u'utf-8'))):
		res = vim.eval((u'%s:%s' % (VARIABLE_LEADER[scope], setting)).encode(u'utf-8'))
		if type(res) in (unicode, str):
			return res.decode(u'utf-8')
		return res
	v = repr(value)
	if type(value) == unicode:
		# strip leading u of unicode string representations
		v = v[1:]

	vim.command((u'let %s:%s = %s' % (VARIABLE_LEADER[scope], setting, v)).encode(u'utf-8'))
	return value

def unset(setting, scope=SCOPE_GLOBAL):
	u""" Unset setting int the definied scope
	:setting: name of the setting
	:scope: the scope o the setting/variable

	:returns: last value of setting
	"""
	value = get(setting, scope=scope)
	vim.command((u'unlet! %s:%s' % (VARIABLE_LEADER[scope], setting)).encode(u'utf-8'))
	return value

# vim: set noexpandtab:


text:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href='https://casda.csiro.au/casda_vo_tools/votable.xsl' type='text/xsl'?>
<VOTABLE version="1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ivoa.net/xml/VOTable/v1.3" xmlns:stc="http://www.ivoa.net/xml/STC/v1.30" >
<RESOURCE name="CASDA SIAPv2 Result" type='results'>
<INFO name="QUERY_STATUS" value="OK">Successful query</INFO>
<INFO name="Instrument" value="ASKAP">Instrument from which data originated </INFO>
<INFO name="Server" value="https://casda.csiro.au/casda_vo_tools//tap">URL of the CASDA VO endpoint used </INFO>
<INFO name="Service Short Name" value="CASDA TAP">Short name for the TAP service </INFO>
<INFO name="Service Title" value="CSIRO ASKAP Science Data Archive TAP service">TAP service title </INFO>
<INFO name="Identifier" value="ivo://casda.csiro.au/casda/TAP">Unique resource registry identifier</INFO>
<INFO name="Service Publisher" value="The CASDA team">Publisher for the TAP service</INFO>
<INFO name="Further Information" value="http://www.atnf.csiro.au/projects/askap/index.html">Link to further information on the data and usage of the service</INFO>
<INFO name="Contact Person" value="CASDA Support <atnf-datasup@csiro.au>">Who to contact about this service </INFO>
<INFO name="Copyright" value="Creative Commons Attribution 4.0 International Licence">CASDA's Data license</INFO>
<INFO name="SIAP  query" value="POS=CIRCLE 333.9092 -45.8418 0.5">SIAP Query submitted by the user</INFO>
<INFO name="Execution Time" value="100ms">Time taken to execute query</INFO>
<INFO name="Datetime Requested" value="2019-06-21 00:49:11 UTC">Date and time that the request was received</INFO>
<INFO name="Table Name" value="ivoa.obscore">Name of the table queried</INFO>
<INFO name="Table Description" value="null">Description of the table queried</INFO>
<INFO name="Table Long Description" value=" ">Long description of the table queried</INFO>

<FIELD name="dataproduct_type" ID="dataproduct_type" datatype="char" arraysize="255" ucd="meta.id" utype="obscore:Obs.dataProductType" >
 <DESCRIPTION>Logical data product type from the IVOA controlled list. Catalogues will be null but described in the dataproduct_subtype field.</DESCRIPTION>
</FIELD>
<FIELD name="calib_level" ID="calib_level" datatype="int" ucd="meta.code;obs.calib" utype="obscore:Obs.calibLevel" >
 <DESCRIPTION>Calibration level {0, 1, 2, 3}</DESCRIPTION>
</FIELD>
<FIELD name="obs_collection" ID="obs_collection" datatype="char" arraysize="255" ucd="meta.id" utype="obscore:DataID.Collection" >
 <DESCRIPTION>Name of the data collection</DESCRIPTION>
</FIELD>
<FIELD name="obs_id" ID="obs_id" datatype="char" arraysize="255" ucd="meta.id" utype="obscore:DataID.observationID" >
 <DESCRIPTION>Observation ID</DESCRIPTION>
</FIELD>
<FIELD name="obs_publisher_did" ID="obs_publisher_did" datatype="char" arraysize="255" ucd="meta.ref.url;meta.curation" utype="obscore:Curation.PublisherDID" >
 <DESCRIPTION>Dataset identifier given by the publisher</DESCRIPTION>
</FIELD>
<FIELD name="access_url" ID="access_url" datatype="char" arraysize="2000" ucd="meta.ref.url" utype="obscore:Access.Reference" >
 <DESCRIPTION>URL used to access (download) dataset</DESCRIPTION>
</FIELD>
<FIELD name="access_format" ID="access_format" datatype="char" arraysize="255" ucd="meta.code.mime" utype="obscore:Access.Format" >
 <DESCRIPTION>File content format</DESCRIPTION>
</FIELD>
<FIELD name="access_estsize" ID="access_estsize" datatype="long" unit="kbyte" ucd="phys.size;meta.file" utype="obscore:Access.Size" >
 <DESCRIPTION>Estimated size of dataset in kilobytes</DESCRIPTION>
</FIELD>
<FIELD name="target_name" ID="target_name" datatype="char" arraysize="255" ucd="meta.id;src" utype="obscore:Target.Name" >
 <DESCRIPTION>Astronomical object observed, if any</DESCRIPTION>
</FIELD>
<FIELD name="s_ra" ID="s_ra" datatype="double" unit="deg" ucd="pos.eq.ra" utype="obscore:Char.SpatialAxis.Coverage.Location.Coord.Position2D.Value2.C1" >
 <DESCRIPTION>Central right ascension, ICRS</DESCRIPTION>
</FIELD>
<FIELD name="s_dec" ID="s_dec" datatype="double" unit="deg" ucd="pos.eq.dec" utype="obscore:Char.SpatialAxis.Coverage.Location.Coord.Position2D.Value2.C2" >
 <DESCRIPTION>Central declination, ICRS</DESCRIPTION>
</FIELD>
<FIELD name="s_fov" ID="s_fov" datatype="double" unit="deg" ucd="phys.angSize;instr.fov" utype="obscore:Char.SpatialAxis.Coverage.Bounds.Extent.diameter" >
 <DESCRIPTION>Diameter (bounds) of the covered region</DESCRIPTION>
</FIELD>
<FIELD name="s_region" ID="s_region" datatype="char" arraysize="200" ucd="phys.angArea;obs" utype="obscore:Char.SpatialAxis.Coverage.Support.Area" >
 <DESCRIPTION>Region covered as specified in STC or ADQL</DESCRIPTION>
</FIELD>
<FIELD name="s_resolution" ID="s_resolution" datatype="double" unit="arcsec" ucd="pos.angResolution" utype="obscore:Char.SpatialAxis.Resolution.refval" >
 <DESCRIPTION>Spatial resolution of data as FWHM</DESCRIPTION>
</FIELD>
<FIELD name="t_min" ID="t_min" datatype="double" unit="d" ucd="time.start;obs.exposure" utype="obscore:Char.TimeAxis.Coverage.Bounds.Limits.Interval.StartTime" >
 <DESCRIPTION>Start time in MJD</DESCRIPTION>
</FIELD>
<FIELD name="t_max" ID="t_max" datatype="double" unit="d" ucd="time.end;obs.exposure" utype="obscore:Char.TimeAxis.Coverage.Bounds.Limits.Interval.StopTime" >
 <DESCRIPTION>Stop time in MJD</DESCRIPTION>
</FIELD>
<FIELD name="t_exptime" ID="t_exptime" datatype="double" unit="s" ucd="time.duration;obs.exposure" utype="obscore:Char.TimeAxis.Coverage.Support.Extent" >
 <DESCRIPTION>Total exposure time</DESCRIPTION>
</FIELD>
<FIELD name="t_resolution" ID="t_resolution" datatype="double" unit="s" ucd="time.resolution" utype="obscore:Char.TimeAxis.Resolution.refval" >
 <DESCRIPTION>Temporal resolution FWHM</DESCRIPTION>
</FIELD>
<FIELD name="em_min" ID="em_min" datatype="double" unit="m" ucd="em.wl;stat.min" utype="obscore:Char.SpectralAxis.Coverage.Bounds.Limits.Interval.LoLim" >
 <DESCRIPTION>Start in spectral coordinates</DESCRIPTION>
</FIELD>
<FIELD name="em_max" ID="em_max" datatype="double" unit="m" ucd="em.wl;stat.max" utype="obscore:Char.SpectralAxis.Coverage.Bounds.Limits.Interval.HiLim" >
 <DESCRIPTION>Stop in spectral coordinates</DESCRIPTION>
</FIELD>
<FIELD name="em_res_power" ID="em_res_power" datatype="double" ucd="spect.resolution" utype="obscore:Char.SpectralAxis.Resolution.ResolPower.refVal" >
 <DESCRIPTION>Spectral resolving power</DESCRIPTION>
</FIELD>
<FIELD name="o_ucd" ID="o_ucd" datatype="char" arraysize="255" ucd="meta.ucd" utype="obscore:Char.ObservableAxis.ucd" >
 <DESCRIPTION>UCD of observable (e.g. phot. plux. density)</DESCRIPTION>
</FIELD>
<FIELD name="pol_states" ID="pol_states" datatype="char" arraysize="255" ucd="meta.code;phys.polarization" utype="obscore:Char.PolarizationAxis.stateList" >
 <DESCRIPTION>List of polarization states or NULL if not applicable</DESCRIPTION>
</FIELD>
<FIELD name="facility_name" ID="facility_name" datatype="char" arraysize="255" ucd="meta.id;instr.tel" utype="obscore:Provenance.ObsConfig.facility.name" >
 <DESCRIPTION>Name of the facility used for this observation</DESCRIPTION>
</FIELD>
<FIELD name="instrument_name" ID="instrument_name" datatype="char" arraysize="255" ucd="meta.id;instr" utype="obscore:Provenance.ObsConfig.instrument.name" >
 <DESCRIPTION>Name of the instrument used for this observation</DESCRIPTION>
</FIELD>
<FIELD name="dataproduct_subtype" ID="dataproduct_subtype" datatype="char" arraysize="255" ucd="meta.id" utype="obscore:Obs.dataProductSubtype" >
 <DESCRIPTION>Further description of the type of data product, including where the dataproduct_type is null.</DESCRIPTION>
</FIELD>
<FIELD name="em_ucd" ID="em_ucd" datatype="char" arraysize="255" ucd="meta.ucd" utype="obscore:Char.SpectralAxis.ucd" >
 <DESCRIPTION>Nature of the spectral axis</DESCRIPTION>
</FIELD>
<FIELD name="em_unit" ID="em_unit" datatype="char" arraysize="255" ucd="meta.unit" utype="obscore:Char.SpectralAxis.unit" >
 <DESCRIPTION>Units along the spectral axis</DESCRIPTION>
</FIELD>
<FIELD name="em_resolution" ID="em_resolution" datatype="double" unit="m" ucd="spect.resolution;stat.mean" utype="obscore:Char.SpectralAxis.Resolution.refval.value" >
 <DESCRIPTION>Value of Resolution along the spectral axis</DESCRIPTION>
</FIELD>
<FIELD name="s_resolution_min" ID="s_resolution_min" datatype="double" unit="arcsec" ucd="pos.angResolution;stat.min" utype="obscore:Char.SpatialAxis.Resolution.Bounds.Limits.Interval.LoLim" >
 <DESCRIPTION>Resolution min value on spatial axis (FHWM of PSF)</DESCRIPTION>
</FIELD>
<FIELD name="s_resolution_max" ID="s_resolution_max" datatype="double" unit="arcsec" ucd="pos.angResolution;stat.max" utype="obscore:Char.SpatialAxis.Resolution.Bounds.Limits.Interval.HiLim" >
 <DESCRIPTION>Resolution max value on spatial axis</DESCRIPTION>
</FIELD>
<FIELD name="s_ucd" ID="s_ucd" datatype="char" arraysize="255" ucd="meta.ucd" utype="obscore:Char.SpatialAxis.ucd" >
 <DESCRIPTION>Ucd for the nature of the spatial axis (pos or u,v data)</DESCRIPTION>
</FIELD>
<FIELD name="s_unit" ID="s_unit" datatype="char" arraysize="255" ucd="meta.unit" utype="obscore:Char.SpatialAxis.unit" >
 <DESCRIPTION>Unit used for spatial axis</DESCRIPTION>
</FIELD>
<FIELD name="obs_release_date" ID="obs_release_date" datatype="char" arraysize="24" >
 <DESCRIPTION>The date that this data product was released</DESCRIPTION>
</FIELD>
<FIELD name="quality_level" ID="quality_level" datatype="char" arraysize="15" ucd="meta.code.qual" >
 <DESCRIPTION>Indicator of quality level, updated by validators</DESCRIPTION>
</FIELD>
<FIELD name="thumbnail_id" ID="thumbnail_id" datatype="long" >
 <DESCRIPTION>The id of the thumbnail or preview image for this data product.</DESCRIPTION>
</FIELD>
<DATA>
<TABLEDATA>

cube	2	ASKAP Early Science Broadband Survey	1934	cube-502	https://data.csiro.au/casda_vo_proxy/vo/datalink/links?ID=cube-502	application/x-votable+xml;content=datalink	415027		333.16767306594	-45.302084636451	73.780732638883	POLYGON ICRS 339.76820580537014 -49.443580029864 326.65233789508 -49.50286732922895 327.5038361349502 -40.839037046421986 338.7583703836203 -40.78819873241401	0.005049654966844			0.0		0.214062548031738	0.2140625481845863	1.40049E9	phot.flux.density	/I/	ASKAP		cont.restored.t0	em.freq	m	1.528483173363071E-10	0.00394983877814	0.005049654966844	pos.eq	deg	2017-08-02T03:51:19.728Z	UNCERTAIN

cube	2	ASKAP Early Science Broadband Survey	1934	cube-503	https://data.csiro.au/casda_vo_proxy/vo/datalink/links?ID=cube-503	application/x-votable+xml;content=datalink	415024		333.16767306594	-45.302084636451	73.780732638883	POLYGON ICRS 339.76820580537014 -49.443580029864 326.65233789508 -49.50286732922895 327.5038361349502 -40.839037046421986 338.7583703836203 -40.78819873241401	0.0			0.0		0.214062548031738	0.2140625481845863	1.40049E9	phot.flux.density	/I/	ASKAP		cont.weight.t0	em.freq	m	1.528483173363071E-10	0.0	0.0	pos.eq	deg	2218-01-02T16:51:00.728Z	UNCERTAIN

cube	2	ASKAP Early Science Broadband Survey	1934	cube-504	https://data.csiro.au/casda_vo_proxy/vo/datalink/links?ID=cube-504	application/x-votable+xml;content=datalink	415027		333.16767306594	-45.302084636451	73.780732638883	POLYGON ICRS 339.76820580537014 -49.443580029864 326.65233789508 -49.50286732922895 327.5038361349502 -40.839037046421986 338.7583703836203 -40.78819873241401	0.005049654966844			0.0		0.214062548031738	0.2140625481845863	1.40049E9	phot.flux.density	/I/	ASKAP		cont.noise.t0	em.freq	m	1.528483173363071E-10	0.00394983877814	0.005049654966844	pos.eq	deg		UNCERTAIN

</TABLEDATA>
</DATA>

</RESOURCE>
</VOTABLE>


text:
using System.Windows;

namespace VSPackage.CPPCheckPlugin
{
	/// <summary>
	/// Interaction logic for CppcheckMessagesList.xaml
	/// </summary>
	public partial class CppcheckMessagesList : Window
	{
		public CppcheckMessagesList()
		{
			InitializeComponent();

			var panel = new ChecksPanel(Checks_Panel);
			panel.LoadSettings();
		}
	}
}


text:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/synch.h>
#include <winpr/dsparse.h>
#include <winpr/crypto.h>

#include <freerdp/log.h>

#include <openssl/bio.h>

#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif

#include "../proxy.h"
#include "http.h"
#include "ntlm.h"
#include "ncacn_http.h"
#include "rpc_bind.h"
#include "rpc_fault.h"
#include "rpc_client.h"

#include "rpc.h"

#define TAG FREERDP_TAG("core.gateway.rpc")

/* Security Verification Trailer Signature */

static const rpc_sec_verification_trailer RPC_SEC_VERIFICATION_TRAILER =
{ { 0x8a, 0xe3, 0x13, 0x71, 0x02, 0xf4, 0x36, 0x71 } };

static const char* PTYPE_STRINGS[] =
{
	"PTYPE_REQUEST",
	"PTYPE_PING",
	"PTYPE_RESPONSE",
	"PTYPE_FAULT",
	"PTYPE_WORKING",
	"PTYPE_NOCALL",
	"PTYPE_REJECT",
	"PTYPE_ACK",
	"PTYPE_CL_CANCEL",
	"PTYPE_FACK",
	"PTYPE_CANCEL_ACK",
	"PTYPE_BIND",
	"PTYPE_BIND_ACK",
	"PTYPE_BIND_NAK",
	"PTYPE_ALTER_CONTEXT",
	"PTYPE_ALTER_CONTEXT_RESP",
	"PTYPE_RPC_AUTH_3",
	"PTYPE_SHUTDOWN",
	"PTYPE_CO_CANCEL",
	"PTYPE_ORPHANED",
	"PTYPE_RTS",
	""
};

static const RPC_SECURITY_PROVIDER_INFO RPC_SECURITY_PROVIDER_INFO_TABLE[] =
{
	{ RPC_C_AUTHN_NONE, TRUE, -1 },
	{ RPC_C_AUTHN_GSS_NEGOTIATE, TRUE, -1 },
	{ RPC_C_AUTHN_WINNT, FALSE, 3 },
	{ RPC_C_AUTHN_GSS_SCHANNEL, TRUE, -1 },
	{ RPC_C_AUTHN_GSS_KERBEROS, TRUE, -1 },
	{ RPC_C_AUTHN_DEFAULT, -1, -1 },
	{ 0, -1, -1 }
};

/**
 * [MS-RPCH]: Remote Procedure Call over HTTP Protocol Specification:
 * http://msdn.microsoft.com/en-us/library/cc243950/
 */

/**
 *                                      Connection Establishment\n
 *
 *     Client                  Outbound Proxy           Inbound Proxy                 Server\n
 *        |                         |                         |                         |\n
 *        |-----------------IN Channel Request--------------->|                         |\n
 *        |---OUT Channel Request-->|                         |<-Legacy Server Response-|\n
 *        |                         |<--------------Legacy Server Response--------------|\n
 *        |                         |                         |                         |\n
 *        |---------CONN_A1-------->|                         |                         |\n
 *        |----------------------CONN_B1--------------------->|                         |\n
 *        |                         |----------------------CONN_A2--------------------->|\n
 *        |                         |                         |                         |\n
 *        |<--OUT Channel Response--|                         |---------CONN_B2-------->|\n
 *        |<--------CONN_A3---------|                         |                         |\n
 *        |                         |<---------------------CONN_C1----------------------|\n
 *        |                         |                         |<--------CONN_B3---------|\n
 *        |<--------CONN_C2---------|                         |                         |\n
 *        |                         |                         |                         |\n
 *
 */

void rpc_pdu_header_print(rpcconn_hdr_t* header)
{
	WLog_INFO(TAG,  "rpc_vers: %"PRIu8"", header->common.rpc_vers);
	WLog_INFO(TAG,  "rpc_vers_minor: %"PRIu8"", header->common.rpc_vers_minor);

	if (header->common.ptype > PTYPE_RTS)
		WLog_INFO(TAG,  "ptype: %s (%"PRIu8")", "PTYPE_UNKNOWN", header->common.ptype);
	else
		WLog_INFO(TAG,  "ptype: %s (%"PRIu8")", PTYPE_STRINGS[header->common.ptype], header->common.ptype);

	WLog_INFO(TAG,  "pfc_flags (0x%02"PRIX8") = {", header->common.pfc_flags);

	if (header->common.pfc_flags & PFC_FIRST_FRAG)
		WLog_INFO(TAG,  " PFC_FIRST_FRAG");

	if (header->common.pfc_flags & PFC_LAST_FRAG)
		WLog_INFO(TAG,  " PFC_LAST_FRAG");

	if (header->common.pfc_flags & PFC_PENDING_CANCEL)
		WLog_INFO(TAG,  " PFC_PENDING_CANCEL");

	if (header->common.pfc_flags & PFC_RESERVED_1)
		WLog_INFO(TAG,  " PFC_RESERVED_1");

	if (header->common.pfc_flags & PFC_CONC_MPX)
		WLog_INFO(TAG,  " PFC_CONC_MPX");

	if (header->common.pfc_flags & PFC_DID_NOT_EXECUTE)
		WLog_INFO(TAG,  " PFC_DID_NOT_EXECUTE");

	if (header->common.pfc_flags & PFC_OBJECT_UUID)
		WLog_INFO(TAG,  " PFC_OBJECT_UUID");

	WLog_INFO(TAG,  " }");
	WLog_INFO(TAG,  "packed_drep[4]: %02"PRIX8" %02"PRIX8" %02"PRIX8" %02"PRIX8"",
	          header->common.packed_drep[0], header->common.packed_drep[1],
	          header->common.packed_drep[2], header->common.packed_drep[3]);
	WLog_INFO(TAG,  "frag_length: %"PRIu16"", header->common.frag_length);
	WLog_INFO(TAG,  "auth_length: %"PRIu16"", header->common.auth_length);
	WLog_INFO(TAG,  "call_id: %"PRIu32"", header->common.call_id);

	if (header->common.ptype == PTYPE_RESPONSE)
	{
		WLog_INFO(TAG,  "alloc_hint: %"PRIu32"", header->response.alloc_hint);
		WLog_INFO(TAG,  "p_cont_id: %"PRIu16"", header->response.p_cont_id);
		WLog_INFO(TAG,  "cancel_count: %"PRIu8"", header->response.cancel_count);
		WLog_INFO(TAG,  "reserved: %"PRIu8"", header->response.reserved);
	}
}

void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header)
{
	header->common.rpc_vers = rpc->rpc_vers;
	header->common.rpc_vers_minor = rpc->rpc_vers_minor;
	header->common.packed_drep[0] = rpc->packed_drep[0];
	header->common.packed_drep[1] = rpc->packed_drep[1];
	header->common.packed_drep[2] = rpc->packed_drep[2];
	header->common.packed_drep[3] = rpc->packed_drep[3];
}

UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment)
{
	UINT32 pad;
	pad = *offset;
	*offset = (*offset + alignment - 1) & ~(alignment - 1);
	pad = *offset - pad;
	return pad;
}

UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad)
{
	*offset += pad;
	return pad;
}

/**
 * PDU Segments:
 *  ________________________________
 * |                                |
 * |           PDU Header           |
 * |________________________________|
 * |                                |
 * |                                |
 * |            PDU Body            |
 * |                                |
 * |________________________________|
 * |                                |
 * |        Security Trailer        |
 * |________________________________|
 * |                                |
 * |      Authentication Token      |
 * |________________________________|
 */

/**
 * PDU Structure with verification trailer
 *
 * MUST only appear in a request PDU!
 *  ________________________________
 * |                                |
 * |           PDU Header           |
 * |________________________________| _______
 * |                                |   /|\
 * |                                |    |
 * |           Stub Data            |    |
 * |                                |    |
 * |________________________________|    |
 * |                                | PDU Body
 * |            Stub Pad            |    |
 * |________________________________|    |
 * |                                |    |
 * |      Verification Trailer      |    |
 * |________________________________|    |
 * |                                |    |
 * |       Authentication Pad       |    |
 * |________________________________| __\|/__
 * |                                |
 * |        Security Trailer        |
 * |________________________________|
 * |                                |
 * |      Authentication Token      |
 * |________________________________|
 *
 */

/**
 * Security Trailer:
 *
 * The sec_trailer structure MUST be placed at the end of the PDU, including past stub data,
 * when present. The sec_trailer structure MUST be 4-byte aligned with respect to the beginning
 * of the PDU. Padding octets MUST be used to align the sec_trailer structure if its natural
 * beginning is not already 4-byte aligned.
 *
 * All PDUs that carry sec_trailer information share certain common fields:
 * frag_length and auth_length. The beginning of the sec_trailer structure for each PDU MUST be
 * calculated to start from offset (frag_length – auth_length – 8) from the beginning of the PDU.
 *
 * Immediately after the sec_trailer structure, there MUST be a BLOB carrying the authentication
 * information produced by the security provider. This BLOB is called the authentication token and
 * MUST be of size auth_length. The size MUST also be equal to the length from the first octet
 * immediately after the sec_trailer structure all the way to the end of the fragment;
 * the two values MUST be the same.
 *
 * A client or a server that (during composing of a PDU) has allocated more space for the
 * authentication token than the security provider fills in SHOULD fill in the rest of
 * the allocated space with zero octets. These zero octets are still considered to belong
 * to the authentication token part of the PDU.
 *
 */

BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* length)
{
	UINT32 alloc_hint = 0;
	rpcconn_hdr_t* header;
	UINT32 frag_length;
	UINT32 auth_length;
	UINT32 auth_pad_length;
	UINT32 sec_trailer_offset;
	rpc_sec_trailer* sec_trailer;
	*offset = RPC_COMMON_FIELDS_LENGTH;
	header = ((rpcconn_hdr_t*) buffer);

	switch (header->common.ptype)
	{
		case PTYPE_RESPONSE:
			*offset += 8;
			rpc_offset_align(offset, 8);
			alloc_hint = header->response.alloc_hint;
			break;

		case PTYPE_REQUEST:
			*offset += 4;
			rpc_offset_align(offset, 8);
			alloc_hint = header->request.alloc_hint;
			break;

		case PTYPE_RTS:
			*offset += 4;
			break;

		default:
			WLog_ERR(TAG, "Unknown PTYPE: 0x%02"PRIX8"", header->common.ptype);
			return FALSE;
	}

	if (!length)
		return TRUE;

	if (header->common.ptype == PTYPE_REQUEST)
	{
		UINT32 sec_trailer_offset;
		sec_trailer_offset = header->common.frag_length - header->common.auth_length - 8;
		*length = sec_trailer_offset - *offset;
		return TRUE;
	}

	frag_length = header->common.frag_length;
	auth_length = header->common.auth_length;
	sec_trailer_offset = frag_length - auth_length - 8;
	sec_trailer = (rpc_sec_trailer*) &buffer[sec_trailer_offset];
	auth_pad_length = sec_trailer->auth_pad_length;
#if 0
	WLog_DBG(TAG,
	         "sec_trailer: type: %"PRIu8" level: %"PRIu8" pad_length: %"PRIu8" reserved: %"PRIu8" context_id: %"PRIu32"",
	         sec_trailer->auth_type, sec_trailer->auth_level,
	         sec_trailer->auth_pad_length, sec_trailer->auth_reserved,
	         sec_trailer->auth_context_id);
#endif

	/**
	 * According to [MS-RPCE], auth_pad_length is the number of padding
	 * octets used to 4-byte align the security trailer, but in practice
	 * we get values up to 15, which indicates 16-byte alignment.
	 */

	if ((frag_length - (sec_trailer_offset + 8)) != auth_length)
	{
		WLog_ERR(TAG, "invalid auth_length: actual: %"PRIu32", expected: %"PRIu32"", auth_length,
		         (frag_length - (sec_trailer_offset + 8)));
	}

	*length = frag_length - auth_length - 24 - 8 - auth_pad_length;
	return TRUE;
}

int rpc_out_channel_read(RpcOutChannel* outChannel, BYTE* data, int length)
{
	int status;
	status = BIO_read(outChannel->tls->bio, data, length);

	if (status > 0)
	{
#ifdef HAVE_VALGRIND_MEMCHECK_H
		VALGRIND_MAKE_MEM_DEFINED(data, status);
#endif
		return status;
	}

	if (BIO_should_retry(outChannel->tls->bio))
		return 0;

	return -1;
}

int rpc_in_channel_write(RpcInChannel* inChannel, const BYTE* data, int length)
{
	int status;
	status = tls_write_all(inChannel->tls, data, length);
	return status;
}

int rpc_out_channel_write(RpcOutChannel* outChannel, const BYTE* data, int length)
{
	int status;
	status = tls_write_all(outChannel->tls, data, length);
	return status;
}

int rpc_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
{
	int status = 1;
	const char* str = "CLIENT_IN_CHANNEL_STATE_UNKNOWN";

	switch (state)
	{
		case CLIENT_IN_CHANNEL_STATE_INITIAL:
			str = "CLIENT_IN_CHANNEL_STATE_INITIAL";
			break;

		case CLIENT_IN_CHANNEL_STATE_CONNECTED:
			str = "CLIENT_IN_CHANNEL_STATE_CONNECTED";
			break;

		case CLIENT_IN_CHANNEL_STATE_SECURITY:
			str = "CLIENT_IN_CHANNEL_STATE_SECURITY";
			break;

		case CLIENT_IN_CHANNEL_STATE_NEGOTIATED:
			str = "CLIENT_IN_CHANNEL_STATE_NEGOTIATED";
			break;

		case CLIENT_IN_CHANNEL_STATE_OPENED:
			str = "CLIENT_IN_CHANNEL_STATE_OPENED";
			break;

		case CLIENT_IN_CHANNEL_STATE_OPENED_A4W:
			str = "CLIENT_IN_CHANNEL_STATE_OPENED_A4W";
			break;

		case CLIENT_IN_CHANNEL_STATE_FINAL:
			str = "CLIENT_IN_CHANNEL_STATE_FINAL";
			break;
	}

	inChannel->State = state;
	WLog_DBG(TAG, "%s", str);
	return status;
}

static int rpc_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel)
{
	HttpContext* http;
	inChannel->ntlm = ntlm_new();

	if (!inChannel->ntlm)
		return -1;

	inChannel->http = http_context_new();

	if (!inChannel->http)
		return -1;

	http = inChannel->http;
	http_context_set_method(http, "RPC_IN_DATA");
	http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388");
	http_context_set_accept(http, "application/rpc");
	http_context_set_cache_control(http, "no-cache");
	http_context_set_connection(http, "Keep-Alive");
	http_context_set_user_agent(http, "MSRPC");
	http_context_set_host(http, rpc->settings->GatewayHostname);
	http_context_set_pragma(http, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729");
	return 1;
}

static int rpc_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel)
{
	rts_generate_cookie((BYTE*) &inChannel->Cookie);
	inChannel->rpc = rpc;
	inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL;
	inChannel->BytesSent = 0;
	inChannel->SenderAvailableWindow = rpc->ReceiveWindow;
	inChannel->PingOriginator.ConnectionTimeout = 30;
	inChannel->PingOriginator.KeepAliveInterval = 0;

	if (rpc_in_channel_rpch_init(rpc, inChannel) < 0)
		return -1;

	return 1;
}

static void rpc_in_channel_rpch_uninit(RpcInChannel* inChannel)
{
	if (inChannel->ntlm)
	{
		ntlm_free(inChannel->ntlm);
		inChannel->ntlm = NULL;
	}

	if (inChannel->http)
	{
		http_context_free(inChannel->http);
		inChannel->http = NULL;
	}
}

static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc)
{
	RpcInChannel* inChannel = NULL;
	inChannel = (RpcInChannel*) calloc(1, sizeof(RpcInChannel));

	if (inChannel)
	{
		rpc_in_channel_init(rpc, inChannel);
	}

	return inChannel;
}

static void rpc_in_channel_free(RpcInChannel* inChannel)
{
	if (!inChannel)
		return;

	rpc_in_channel_rpch_uninit(inChannel);

	if (inChannel->tls)
	{
		tls_free(inChannel->tls);
		inChannel->tls = NULL;
	}

	free(inChannel);
}

int rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
{
	int status = 1;
	const char* str = "CLIENT_OUT_CHANNEL_STATE_UNKNOWN";

	switch (state)
	{
		case CLIENT_OUT_CHANNEL_STATE_INITIAL:
			str = "CLIENT_OUT_CHANNEL_STATE_INITIAL";
			break;

		case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
			str = "CLIENT_OUT_CHANNEL_STATE_CONNECTED";
			break;

		case CLIENT_OUT_CHANNEL_STATE_SECURITY:
			str = "CLIENT_OUT_CHANNEL_STATE_SECURITY";
			break;

		case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
			str = "CLIENT_OUT_CHANNEL_STATE_NEGOTIATED";
			break;

		case CLIENT_OUT_CHANNEL_STATE_OPENED:
			str = "CLIENT_OUT_CHANNEL_STATE_OPENED";
			break;

		case CLIENT_OUT_CHANNEL_STATE_OPENED_A6W:
			str = "CLIENT_OUT_CHANNEL_STATE_OPENED_A6W";
			break;

		case CLIENT_OUT_CHANNEL_STATE_OPENED_A10W:
			str = "CLIENT_OUT_CHANNEL_STATE_OPENED_A10W";
			break;

		case CLIENT_OUT_CHANNEL_STATE_OPENED_B3W:
			str = "CLIENT_OUT_CHANNEL_STATE_OPENED_B3W";
			break;

		case CLIENT_OUT_CHANNEL_STATE_RECYCLED:
			str = "CLIENT_OUT_CHANNEL_STATE_RECYCLED";
			break;

		case CLIENT_OUT_CHANNEL_STATE_FINAL:
			str = "CLIENT_OUT_CHANNEL_STATE_FINAL";
			break;
	}

	outChannel->State = state;
	WLog_DBG(TAG, "%s", str);
	return status;
}

static int rpc_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel)
{
	HttpContext* http;
	outChannel->ntlm = ntlm_new();

	if (!outChannel->ntlm)
		return -1;

	outChannel->http = http_context_new();

	if (!outChannel->http)
		return -1;

	http = outChannel->http;
	http_context_set_method(http, "RPC_OUT_DATA");
	http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388");
	http_context_set_accept(http, "application/rpc");
	http_context_set_cache_control(http, "no-cache");
	http_context_set_connection(http, "Keep-Alive");
	http_context_set_user_agent(http, "MSRPC");
	http_context_set_host(http, rpc->settings->GatewayHostname);
	http_context_set_pragma(http,
	                        "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, "
	                        "SessionId=fbd9c34f-397d-471d-a109-1b08cc554624");
	return 1;
}

static int rpc_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel)
{
	rts_generate_cookie((BYTE*) &outChannel->Cookie);
	outChannel->rpc = rpc;
	outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
	outChannel->BytesReceived = 0;
	outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
	outChannel->ReceiveWindow = rpc->ReceiveWindow;
	outChannel->ReceiveWindowSize = rpc->ReceiveWindow;
	outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;

	if (rpc_out_channel_rpch_init(rpc, outChannel) < 0)
		return -1;

	return 1;
}

static void rpc_out_channel_rpch_uninit(RpcOutChannel* outChannel)
{
	if (outChannel->ntlm)
	{
		ntlm_free(outChannel->ntlm);
		outChannel->ntlm = NULL;
	}

	if (outChannel->http)
	{
		http_context_free(outChannel->http);
		outChannel->http = NULL;
	}
}

RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc)
{
	RpcOutChannel* outChannel = NULL;
	outChannel = (RpcOutChannel*) calloc(1, sizeof(RpcOutChannel));

	if (outChannel)
	{
		rpc_out_channel_init(rpc, outChannel);
	}

	return outChannel;
}

void rpc_out_channel_free(RpcOutChannel* outChannel)
{
	if (!outChannel)
		return;

	rpc_out_channel_rpch_uninit(outChannel);

	if (outChannel->tls)
	{
		tls_free(outChannel->tls);
		outChannel->tls = NULL;
	}

	free(outChannel);
}

int rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
        RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state)
{
	int status = 1;
	const char* str = "VIRTUAL_CONNECTION_STATE_UNKNOWN";

	switch (state)
	{
		case VIRTUAL_CONNECTION_STATE_INITIAL:
			str = "VIRTUAL_CONNECTION_STATE_INITIAL";
			break;

		case VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT:
			str = "VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT";
			break;

		case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
			str = "VIRTUAL_CONNECTION_STATE_WAIT_A3W";
			break;

		case VIRTUAL_CONNECTION_STATE_WAIT_C2:
			str = "VIRTUAL_CONNECTION_STATE_WAIT_C2";
			break;

		case VIRTUAL_CONNECTION_STATE_OPENED:
			str = "VIRTUAL_CONNECTION_STATE_OPENED";
			break;

		case VIRTUAL_CONNECTION_STATE_FINAL:
			str = "VIRTUAL_CONNECTION_STATE_FINAL";
			break;
	}

	connection->State = state;
	WLog_DBG(TAG, "%s", str);
	return status;
}

static RpcVirtualConnection* rpc_virtual_connection_new(rdpRpc* rpc)
{
	RpcVirtualConnection* connection;
	connection = (RpcVirtualConnection*) calloc(1, sizeof(RpcVirtualConnection));

	if (!connection)
		return NULL;

	rts_generate_cookie((BYTE*) & (connection->Cookie));
	rts_generate_cookie((BYTE*) & (connection->AssociationGroupId));
	connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
	connection->DefaultInChannel = rpc_in_channel_new(rpc);

	if (!connection->DefaultInChannel)
		goto out_free;

	connection->DefaultOutChannel = rpc_out_channel_new(rpc);

	if (!connection->DefaultOutChannel)
		goto out_default_in;

	return connection;
out_default_in:
	free(connection->DefaultInChannel);
out_free:
	free(connection);
	return NULL;
}

static void rpc_virtual_connection_free(RpcVirtualConnection* connection)
{
	if (!connection)
		return;

	rpc_in_channel_free(connection->DefaultInChannel);
	rpc_in_channel_free(connection->NonDefaultInChannel);
	rpc_out_channel_free(connection->DefaultOutChannel);
	rpc_out_channel_free(connection->NonDefaultOutChannel);
	free(connection);
}

static int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
{
	int sockfd;
	rdpTls* tls;
	int tlsStatus;
	BIO* socketBio;
	BIO* bufferedBio;
	rdpRpc* rpc = channel->rpc;
	rdpContext* context = rpc->context;
	rdpSettings* settings = context->settings;
	const char* peerHostname = settings->GatewayHostname;
	UINT16 peerPort = settings->GatewayPort;
	const char *proxyUsername = settings->ProxyUsername, *proxyPassword = settings->ProxyPassword;
	BOOL isProxyConnection = proxy_prepare(settings, &peerHostname, &peerPort, &proxyUsername, &proxyPassword);
	sockfd = freerdp_tcp_connect(context, settings, peerHostname,
	                             peerPort, timeout);

	if (sockfd < 1)
		return -1;

	socketBio = BIO_new(BIO_s_simple_socket());

	if (!socketBio)
		return FALSE;

	BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
	bufferedBio = BIO_new(BIO_s_buffered_socket());

	if (!bufferedBio)
		return FALSE;

	bufferedBio = BIO_push(bufferedBio, socketBio);

	if (!BIO_set_nonblock(bufferedBio, TRUE))
		return -1;

	if (isProxyConnection)
	{
		if (!proxy_connect(settings, bufferedBio, proxyUsername, proxyPassword,	settings->GatewayHostname, settings->GatewayPort))
			return -1;
	}

	channel->bio = bufferedBio;
	tls = channel->tls = tls_new(settings);

	if (!tls)
		return -1;

	tls->hostname = settings->GatewayHostname;
	tls->port = settings->GatewayPort;
	tls->isGatewayTransport = TRUE;
	tlsStatus = tls_connect(tls, bufferedBio);

	if (tlsStatus < 1)
	{
		if (tlsStatus < 0)
		{
			if (!freerdp_get_last_error(context))
				freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
		}
		else
		{
			if (!freerdp_get_last_error(context))
				freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
		}

		return -1;
	}

	return 1;
}

static int rpc_in_channel_connect(RpcInChannel* inChannel, int timeout)
{
	rdpRpc* rpc = inChannel->rpc;

	/* Connect IN Channel */

	if (rpc_channel_tls_connect((RpcChannel*) inChannel, timeout) < 0)
		return -1;

	rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);

	if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) inChannel) < 0)
		return -1;

	/* Send IN Channel Request */

	if (rpc_ncacn_http_send_in_channel_request(rpc, inChannel) < 0)
	{
		WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure");
		return -1;
	}

	rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY);
	return 1;
}

static int rpc_out_channel_connect(RpcOutChannel* outChannel, int timeout)
{
	rdpRpc* rpc = outChannel->rpc;

	/* Connect OUT Channel */

	if (rpc_channel_tls_connect((RpcChannel*) outChannel, timeout) < 0)
		return -1;

	rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);

	if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) outChannel) < 0)
		return FALSE;

	/* Send OUT Channel Request */

	if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel, FALSE) < 0)
	{
		WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
		return FALSE;
	}

	rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
	return 1;
}

int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout)
{
	rdpRpc* rpc = outChannel->rpc;

	/* Connect OUT Channel */

	if (rpc_channel_tls_connect((RpcChannel*) outChannel, timeout) < 0)
		return -1;

	rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);

	if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) outChannel) < 0)
		return FALSE;

	/* Send OUT Channel Request */

	if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel, TRUE) < 0)
	{
		WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
		return FALSE;
	}

	rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
	return 1;
}

BOOL rpc_connect(rdpRpc* rpc, int timeout)
{
	RpcInChannel* inChannel;
	RpcOutChannel* outChannel;
	RpcVirtualConnection* connection;
	rpc->VirtualConnection = rpc_virtual_connection_new(rpc);

	if (!rpc->VirtualConnection)
		return FALSE;

	connection = rpc->VirtualConnection;
	inChannel = connection->DefaultInChannel;
	outChannel = connection->DefaultOutChannel;
	rpc_virtual_connection_transition_to_state(rpc, connection, VIRTUAL_CONNECTION_STATE_INITIAL);

	if (rpc_in_channel_connect(inChannel, timeout) < 0)
		return FALSE;

	if (rpc_out_channel_connect(outChannel, timeout) < 0)
		return FALSE;

	return TRUE;
}

rdpRpc* rpc_new(rdpTransport* transport)
{
	rdpRpc* rpc = (rdpRpc*) calloc(1, sizeof(rdpRpc));

	if (!rpc)
		return NULL;

	rpc->State = RPC_CLIENT_STATE_INITIAL;
	rpc->transport = transport;
	rpc->settings = transport->settings;
	rpc->context = transport->context;
	rpc->SendSeqNum = 0;
	rpc->ntlm = ntlm_new();

	if (!rpc->ntlm)
		goto out_free;

	rpc->PipeCallId = 0;
	rpc->StubCallId = 0;
	rpc->StubFragCount = 0;
	rpc->rpc_vers = 5;
	rpc->rpc_vers_minor = 0;
	/* little-endian data representation */
	rpc->packed_drep[0] = 0x10;
	rpc->packed_drep[1] = 0x00;
	rpc->packed_drep[2] = 0x00;
	rpc->packed_drep[3] = 0x00;
	rpc->max_xmit_frag = 0x0FF8;
	rpc->max_recv_frag = 0x0FF8;
	rpc->ReceiveWindow = 0x00010000;
	rpc->ChannelLifetime = 0x40000000;
	rpc->KeepAliveInterval = 300000;
	rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
	rpc->CurrentKeepAliveTime = 0;
	rpc->CallId = 2;

	if (rpc_client_new(rpc) < 0)
		goto out_free_rpc_client;

	return rpc;
out_free_rpc_client:
	rpc_client_free(rpc);
out_free:
	free(rpc);
	return NULL;
}

void rpc_free(rdpRpc* rpc)
{
	if (rpc)
	{
		rpc_client_free(rpc);

		if (rpc->ntlm)
		{
			ntlm_client_uninit(rpc->ntlm);
			ntlm_free(rpc->ntlm);
			rpc->ntlm = NULL;
		}

		if (rpc->VirtualConnection)
		{
			rpc_virtual_connection_free(rpc->VirtualConnection);
			rpc->VirtualConnection = NULL;
		}

		free(rpc);
	}
}


text:
module EventMachine
  module WPN
    VERSION = "1.1.0"
  end
end


text:
import React, {PureComponent} from 'react'
import {Link} from 'react-router-dom'
import {connect, ConnectedProps} from 'react-redux'
import {get} from 'lodash'

//Actions
import {dismissNotification as dismissNotificationAction} from 'src/shared/actions/notifications'

import {Notification, ComponentSize, Gradients} from '@influxdata/clockface'

//Types
import {AppState, NotificationStyle} from 'src/types'

type ReduxProps = ConnectedProps<typeof connector>
type Props = ReduxProps

const matchGradientToColor = (style: NotificationStyle): Gradients => {
  const converter = {
    [NotificationStyle.Primary]: Gradients.Primary,
    [NotificationStyle.Warning]: Gradients.WarningLight,
    [NotificationStyle.Success]: Gradients.HotelBreakfast,
    [NotificationStyle.Error]: Gradients.DangerDark,
    [NotificationStyle.Info]: Gradients.DefaultLight,
  }
  return get(converter, style, Gradients.DefaultLight)
}

class Notifications extends PureComponent<Props> {
  public static defaultProps = {
    notifications: [],
  }

  public render() {
    const {notifications} = this.props

    return (
      <>
        {notifications.map(
          ({id, style, icon, duration, message, link, linkText}) => {
            const gradient = matchGradientToColor(style)

            let button

            if (link && linkText) {
              button = (
                <Link
                  to={link}
                  className="notification--button cf-button cf-button-xs cf-button-default"
                >
                  {linkText}
                </Link>
              )
            }

            return (
              <Notification
                key={id}
                id={id}
                icon={icon}
                duration={duration}
                size={ComponentSize.ExtraSmall}
                gradient={gradient}
                onTimeout={this.props.dismissNotification}
                onDismiss={this.props.dismissNotification}
                testID={`notification-${style}`}
              >
                {message}
                {button}
              </Notification>
            )
          }
        )}
      </>
    )
  }
}

const mstp = ({notifications}: AppState) => ({
  notifications,
})

const mdtp = {
  dismissNotification: dismissNotificationAction,
}

const connector = connect(mstp, mdtp)

export default connector(Notifications)