Sync with trunk r63383 .
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 20 May 2014 17:04:19 +0000 (17:04 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 20 May 2014 17:04:19 +0000 (17:04 +0000)
svn path=/branches/condrv_restructure/; revision=63384

358 files changed:
1  2 
CMakeLists.txt
base/applications/cacls/lang/ru-RU.rc
base/applications/dxdiag/lang/ru-RU.rc
base/applications/fontview/lang/ru-RU.rc
base/applications/mplay32/lang/ru-RU.rc
base/applications/rapps/rapps/7zip.txt
base/applications/rapps/rapps/abiword.txt
base/applications/rapps/rapps/abiword26.txt
base/applications/rapps/rapps/abyss.txt
base/applications/rapps/rapps/ac97forvirtualbox.txt
base/applications/rapps/rapps/alreader.txt
base/applications/rapps/rapps/ants.txt
base/applications/rapps/rapps/audiograbber.txt
base/applications/rapps/rapps/bittorrent.txt
base/applications/rapps/rapps/bochs.txt
base/applications/rapps/rapps/boswars.txt
base/applications/rapps/rapps/boundaround.txt
base/applications/rapps/rapps/christmasbound.txt
base/applications/rapps/rapps/chromium.txt
base/applications/rapps/rapps/cnt.txt
base/applications/rapps/rapps/codeblocks.txt
base/applications/rapps/rapps/codeblocks_gcc.txt
base/applications/rapps/rapps/codeblocks_gcc_2.txt
base/applications/rapps/rapps/comctl32ocx.txt
base/applications/rapps/rapps/devcpp_mingw32.txt
base/applications/rapps/rapps/devcpp_tdm_gcc_x64.txt
base/applications/rapps/rapps/diablo2.txt
base/applications/rapps/rapps/dosblaster.txt
base/applications/rapps/rapps/dosbox.txt
base/applications/rapps/rapps/doublecommander.txt
base/applications/rapps/rapps/dplus.txt
base/applications/rapps/rapps/dvdwritenow.txt
base/applications/rapps/rapps/excelview.txt
base/applications/rapps/rapps/fap.txt
base/applications/rapps/rapps/fira.txt
base/applications/rapps/rapps/firefox.txt
base/applications/rapps/rapps/firefox2.txt
base/applications/rapps/rapps/firefox3.txt
base/applications/rapps/rapps/firefox36.txt
base/applications/rapps/rapps/freebasic.txt
base/applications/rapps/rapps/glidewrapzbag.txt
base/applications/rapps/rapps/globulation2.txt
base/applications/rapps/rapps/hover.txt
base/applications/rapps/rapps/hxd.txt
base/applications/rapps/rapps/indiftpd.txt
base/applications/rapps/rapps/irfanview.txt
base/applications/rapps/rapps/irfanviewplugins.txt
base/applications/rapps/rapps/kdewin.txt
base/applications/rapps/rapps/kyodai.txt
base/applications/rapps/rapps/lazaruside.txt
base/applications/rapps/rapps/lbreakout2.txt
base/applications/rapps/rapps/lgeneral.txt
base/applications/rapps/rapps/libreoffice.txt
base/applications/rapps/rapps/lmarbles.txt
base/applications/rapps/rapps/mcwin32.txt
base/applications/rapps/rapps/mfc40.txt
base/applications/rapps/rapps/mirandaim.txt
base/applications/rapps/rapps/mirc.txt
base/applications/rapps/rapps/mirc6.txt
base/applications/rapps/rapps/mono2.txt
base/applications/rapps/rapps/mpc.txt
base/applications/rapps/rapps/mpxplay.txt
base/applications/rapps/rapps/msxml3.txt
base/applications/rapps/rapps/net11.txt
base/applications/rapps/rapps/net20.txt
base/applications/rapps/rapps/net20sp2.txt
base/applications/rapps/rapps/npp.txt
base/applications/rapps/rapps/offbyone.txt
base/applications/rapps/rapps/opencodecs.txt
base/applications/rapps/rapps/openoffice.txt
base/applications/rapps/rapps/openoffice2.4.txt
base/applications/rapps/rapps/openttd.txt
base/applications/rapps/rapps/opera.txt
base/applications/rapps/rapps/opera9.txt
base/applications/rapps/rapps/peazip.txt
base/applications/rapps/rapps/pengupop.txt
base/applications/rapps/rapps/photofiltre.txt
base/applications/rapps/rapps/pingus.txt
base/applications/rapps/rapps/pptview.txt
base/applications/rapps/rapps/pspad.txt
base/applications/rapps/rapps/ptanks.txt
base/applications/rapps/rapps/putty.txt
base/applications/rapps/rapps/python.txt
base/applications/rapps/rapps/python2.txt
base/applications/rapps/rapps/qb64sdl.txt
base/applications/rapps/rapps/qmmp.txt
base/applications/rapps/rapps/remood.txt
base/applications/rapps/rapps/reshack.txt
base/applications/rapps/rapps/rocks.txt
base/applications/rapps/rapps/rosbe.txt
base/applications/rapps/rapps/rosbeamd64.txt
base/applications/rapps/rapps/rosbearm.txt
base/applications/rapps/rapps/sambatng.txt
base/applications/rapps/rapps/sbforvmware.txt
base/applications/rapps/rapps/scite.txt
base/applications/rapps/rapps/scummvm.txt
base/applications/rapps/rapps/sdl_mixer.txt
base/applications/rapps/rapps/sdl_runtime.txt
base/applications/rapps/rapps/seamonkey.txt
base/applications/rapps/rapps/smplayer.txt
base/applications/rapps/rapps/snoopy.txt
base/applications/rapps/rapps/stamina.txt
base/applications/rapps/rapps/steam.txt
base/applications/rapps/rapps/sumatrapdf.txt
base/applications/rapps/rapps/summerbound.txt
base/applications/rapps/rapps/superdxb.txt
base/applications/rapps/rapps/superfinder.txt
base/applications/rapps/rapps/supertux.txt
base/applications/rapps/rapps/tahoma.txt
base/applications/rapps/rapps/thunderbird.txt
base/applications/rapps/rapps/thunderbird3.txt
base/applications/rapps/rapps/tileworld.txt
base/applications/rapps/rapps/totalcommander.txt
base/applications/rapps/rapps/tuxpaint.txt
base/applications/rapps/rapps/ultravnc.txt
base/applications/rapps/rapps/utorrent.txt
base/applications/rapps/rapps/vb5run.txt
base/applications/rapps/rapps/vb6run.txt
base/applications/rapps/rapps/vc2005sp1run.txt
base/applications/rapps/rapps/vc2008sp1run.txt
base/applications/rapps/rapps/vc2010run.txt
base/applications/rapps/rapps/vc6run.txt
base/applications/rapps/rapps/vlc.txt
base/applications/rapps/rapps/winboard.txt
base/applications/rapps/rapps/wme9.txt
base/applications/rapps/rapps/wordview.txt
base/applications/rapps/rapps/zaz.txt
base/applications/regedit/lang/ru-RU.rc
base/applications/shutdown/lang/ru-RU.rc
base/applications/sndrec32/lang/ru-RU.rc
base/applications/sndrec32/rsrc.rc
base/applications/sndvol32/lang/ru-RU.rc
base/setup/reactos/lang/ru-RU.rc
base/setup/usetup/bootsup.c
base/setup/usetup/interface/consup.c
base/setup/usetup/interface/usetup.c
base/setup/usetup/native/console.c
base/setup/usetup/native/fslist.c
base/setup/usetup/native/utils/console.c
base/setup/usetup/native/utils/console.h
base/setup/usetup/partlist.c
base/setup/usetup/partlist.h
base/shell/explorer-new/lang/ru-RU.rc
boot/bootdata/hivesys.inf
boot/bootdata/packages/reactos.dff.in
dll/3rdparty/libjpeg/README
dll/3rdparty/libjpeg/change.log
dll/3rdparty/libjpeg/cjpeg.c
dll/3rdparty/libjpeg/jcapistd.c
dll/3rdparty/libjpeg/jcarith.c
dll/3rdparty/libjpeg/jccolor.c
dll/3rdparty/libjpeg/jcdctmgr.c
dll/3rdparty/libjpeg/jchuff.c
dll/3rdparty/libjpeg/jcinit.c
dll/3rdparty/libjpeg/jcmarker.c
dll/3rdparty/libjpeg/jcmaster.c
dll/3rdparty/libjpeg/jcparam.c
dll/3rdparty/libjpeg/jctrans.c
dll/3rdparty/libjpeg/jdapimin.c
dll/3rdparty/libjpeg/jdapistd.c
dll/3rdparty/libjpeg/jdarith.c
dll/3rdparty/libjpeg/jdcolor.c
dll/3rdparty/libjpeg/jddctmgr.c
dll/3rdparty/libjpeg/jdhuff.c
dll/3rdparty/libjpeg/jdinput.c
dll/3rdparty/libjpeg/jdmarker.c
dll/3rdparty/libjpeg/jdmaster.c
dll/3rdparty/libjpeg/jdmerge.c
dll/3rdparty/libjpeg/jfdctint.c
dll/3rdparty/libjpeg/jidctint.c
dll/3rdparty/libjpeg/jpegtran.c
dll/3rdparty/libjpeg/transupp.c
dll/cpl/desk/lang/ru-RU.rc
dll/cpl/mmsys/lang/ru-RU.rc
dll/cpl/wined3dcfg/general.c
dll/cpl/wined3dcfg/lang/cs-CZ.rc
dll/cpl/wined3dcfg/lang/de-DE.rc
dll/cpl/wined3dcfg/lang/en-US.rc
dll/cpl/wined3dcfg/lang/he-IL.rc
dll/cpl/wined3dcfg/lang/pl-PL.rc
dll/cpl/wined3dcfg/lang/ro-RO.rc
dll/cpl/wined3dcfg/lang/sq-AL.rc
dll/cpl/wined3dcfg/lang/tr-TR.rc
dll/cpl/wined3dcfg/resource.h
dll/cpl/wined3dcfg/wined3dcfg.h
dll/opengl/opengl32/wgl_font.c
dll/win32/CMakeLists.txt
dll/win32/aclui/lang/ru-RU.rc
dll/win32/browseui/browseui.rc
dll/win32/browseui/lang/ru-RU.rc
dll/win32/kernel32/client/proc.c
dll/win32/kernel32/client/vdm.c
dll/win32/winscard/CMakeLists.txt
dll/win32/winscard/precomp.h
dll/win32/winscard/stubs.c
dll/win32/winscard/winscard.c
dll/win32/winscard/winscard.spec
drivers/bus/acpi/busmgr/bus.c
drivers/bus/acpi/buspdo.c
drivers/bus/acpi/include/acpi_bus.h
drivers/bus/acpi/include/acpisys.h
drivers/input/i8042prt/pnp.c
drivers/input/kbdclass/kbdclass.c
drivers/input/mouclass/mouclass.c
drivers/network/ndis/ndis/miniport.c
include/psdk/winscard.h
include/reactos/libs/fast486/fast486.h
include/reactos/libs/libjpeg/jconfig.h
include/reactos/libs/libjpeg/jmorecfg.h
include/reactos/libs/libjpeg/jpegint.h
include/reactos/libs/libjpeg/jpeglib.h
include/reactos/libs/libjpeg/jversion.h
include/reactos/libs/libjpeg/transupp.h
lib/3rdparty/freetype/ChangeLog
lib/3rdparty/freetype/README
lib/3rdparty/freetype/devel/ftoption.h
lib/3rdparty/freetype/include/config/ftconfig.h
lib/3rdparty/freetype/include/config/ftoption.h
lib/3rdparty/freetype/include/freetype.h
lib/3rdparty/freetype/include/ftautoh.h
lib/3rdparty/freetype/include/ftbdf.h
lib/3rdparty/freetype/include/ftchapters.h
lib/3rdparty/freetype/include/ftoutln.h
lib/3rdparty/freetype/include/internal/ftrfork.h
lib/3rdparty/freetype/include/internal/fttrace.h
lib/3rdparty/freetype/src/autofit/afblue.c
lib/3rdparty/freetype/src/autofit/afblue.cin
lib/3rdparty/freetype/src/autofit/afblue.h
lib/3rdparty/freetype/src/autofit/afblue.hin
lib/3rdparty/freetype/src/autofit/afcjk.c
lib/3rdparty/freetype/src/autofit/afcjk.h
lib/3rdparty/freetype/src/autofit/afcover.h
lib/3rdparty/freetype/src/autofit/afdummy.c
lib/3rdparty/freetype/src/autofit/afdummy.h
lib/3rdparty/freetype/src/autofit/afglobal.c
lib/3rdparty/freetype/src/autofit/afglobal.h
lib/3rdparty/freetype/src/autofit/afhints.c
lib/3rdparty/freetype/src/autofit/afhints.h
lib/3rdparty/freetype/src/autofit/afindic.c
lib/3rdparty/freetype/src/autofit/afindic.h
lib/3rdparty/freetype/src/autofit/aflatin.c
lib/3rdparty/freetype/src/autofit/aflatin.h
lib/3rdparty/freetype/src/autofit/aflatin2.c
lib/3rdparty/freetype/src/autofit/aflatin2.h
lib/3rdparty/freetype/src/autofit/afloader.c
lib/3rdparty/freetype/src/autofit/afloader.h
lib/3rdparty/freetype/src/autofit/afmodule.c
lib/3rdparty/freetype/src/autofit/afmodule.h
lib/3rdparty/freetype/src/autofit/afpic.c
lib/3rdparty/freetype/src/autofit/afpic.h
lib/3rdparty/freetype/src/autofit/afranges.c
lib/3rdparty/freetype/src/autofit/afranges.h
lib/3rdparty/freetype/src/autofit/afscript.h
lib/3rdparty/freetype/src/autofit/afstyles.h
lib/3rdparty/freetype/src/autofit/aftypes.h
lib/3rdparty/freetype/src/autofit/afwrtsys.h
lib/3rdparty/freetype/src/autofit/autofit.c
lib/3rdparty/freetype/src/autofit/hbshim.c
lib/3rdparty/freetype/src/autofit/hbshim.h
lib/3rdparty/freetype/src/base/basepic.c
lib/3rdparty/freetype/src/base/ftbitmap.c
lib/3rdparty/freetype/src/base/ftcalc.c
lib/3rdparty/freetype/src/base/ftobjs.c
lib/3rdparty/freetype/src/base/ftoutln.c
lib/3rdparty/freetype/src/base/ftrfork.c
lib/3rdparty/freetype/src/bdf/bdfdrivr.c
lib/3rdparty/freetype/src/bdf/bdflib.c
lib/3rdparty/freetype/src/cff/cf2blues.c
lib/3rdparty/freetype/src/cff/cf2font.c
lib/3rdparty/freetype/src/cff/cf2ft.c
lib/3rdparty/freetype/src/cff/cf2hints.c
lib/3rdparty/freetype/src/cff/cffload.c
lib/3rdparty/freetype/src/cff/cffobjs.c
lib/3rdparty/freetype/src/cff/cffparse.c
lib/3rdparty/freetype/src/cid/cidload.c
lib/3rdparty/freetype/src/cid/cidobjs.c
lib/3rdparty/freetype/src/cid/cidparse.c
lib/3rdparty/freetype/src/cid/cidparse.h
lib/3rdparty/freetype/src/pcf/pcfread.c
lib/3rdparty/freetype/src/pfr/pfrload.c
lib/3rdparty/freetype/src/pfr/pfrobjs.c
lib/3rdparty/freetype/src/psaux/psobjs.c
lib/3rdparty/freetype/src/pshinter/pshalgo.c
lib/3rdparty/freetype/src/raster/ftraster.c
lib/3rdparty/freetype/src/sfnt/sfdriver.c
lib/3rdparty/freetype/src/sfnt/ttcmap.c
lib/3rdparty/freetype/src/sfnt/ttsbit.c
lib/3rdparty/freetype/src/smooth/ftgrays.c
lib/3rdparty/freetype/src/tools/afblue.pl
lib/3rdparty/freetype/src/truetype/ttgload.c
lib/3rdparty/freetype/src/truetype/ttinterp.c
lib/3rdparty/freetype/src/truetype/ttinterp.h
lib/3rdparty/freetype/src/type1/t1gload.c
lib/3rdparty/freetype/src/type1/t1load.c
lib/3rdparty/freetype/src/type1/t1objs.c
lib/3rdparty/freetype/src/type1/t1parse.c
lib/3rdparty/freetype/src/type42/t42objs.c
lib/3rdparty/freetype/src/type42/t42parse.c
lib/3rdparty/freetype/src/winfonts/winfnt.c
lib/fast486/fast486.c
lib/fast486/opcodes.c
lib/sdk/crt/stdio/file.c
lib/sdk/crt/stdlib/mbtowc.c
lib/sdk/crt/string/ctype.c
media/doc/3rd Party Files.txt
media/doc/README.WINE
media/fonts/tahoma.ttf
media/fonts/tahomabd.ttf
ntoskrnl/ex/mutant.c
ntoskrnl/fstub/disksup.c
ntoskrnl/include/internal/amd64/mm.h
ntoskrnl/io/iomgr/driver.c
ntoskrnl/io/pnpmgr/pnpinit.c
ntoskrnl/io/pnpmgr/pnpmgr.c
ntoskrnl/mm/ARM3/miarm.h
ntoskrnl/mm/ARM3/pagfault.c
ntoskrnl/mm/ARM3/procsup.c
ntoskrnl/mm/ARM3/section.c
ntoskrnl/mm/ARM3/vadnode.c
ntoskrnl/mm/ARM3/virtual.c
subsystems/ntvdm/bios/bios.c
subsystems/ntvdm/bios/bios.h
subsystems/ntvdm/bios/bios32/bios32.c
subsystems/ntvdm/bios/bios32/bios32p.h
subsystems/ntvdm/bios/bios32/kbdbios32.c
subsystems/ntvdm/bios/vidbios.c
subsystems/ntvdm/bop.c
subsystems/ntvdm/callback.c
subsystems/ntvdm/callback.h
subsystems/ntvdm/dos/dem.c
subsystems/ntvdm/dos/dos32krnl/bios.c
subsystems/ntvdm/dos/dos32krnl/dos.c
subsystems/ntvdm/dos/dos32krnl/dos.h
subsystems/ntvdm/dos/dos32krnl/dosfiles.c
subsystems/ntvdm/emulator.c
subsystems/ntvdm/emulator.h
subsystems/ntvdm/hardware/cmos.c
subsystems/ntvdm/lang/cs-CZ.rc
subsystems/ntvdm/lang/de-DE.rc
subsystems/ntvdm/lang/en-US.rc
subsystems/ntvdm/lang/es-ES.rc
subsystems/ntvdm/lang/fr-FR.rc
subsystems/ntvdm/lang/it-IT.rc
subsystems/ntvdm/lang/pl-PL.rc
subsystems/ntvdm/ntvdm.c
subsystems/ntvdm/resource.h
subsystems/win/basesrv/vdm.c
win32ss/drivers/miniport/vga_new/vbemodes.c
win32ss/gdi/ntgdi/bitmaps.c
win32ss/include/callback.h
win32ss/user/ntuser/callback.c
win32ss/user/ntuser/menu.c
win32ss/user/ntuser/menu.h
win32ss/user/ntuser/window.c
win32ss/user/user32/misc/dllmain.c
win32ss/user/user32/windows/menu.c
win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
win32ss/user/winsrv/consrv/frontends/gui/guiterm.c

diff --cc CMakeLists.txt
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,a798508..a798508
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
index 0000000,c7b54e3..c7b54e3
mode 000000,100644..100644
--- /dev/null
Simple merge
index 0000000,25253ff..25253ff
mode 000000,100644..100644
--- /dev/null
Simple merge
index 0000000,a20d780..a20d780
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index d597694,4f68d1e..4f68d1e
Binary files differ
index 007f9ad,c01f9e1..c01f9e1
Binary files differ
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 35942be,0000000..3fb9bd5
mode 100644,000000..100644
--- /dev/null
@@@ -1,2161 -1,0 +1,2185 @@@
 +/*
 + * COPYRIGHT:       See COPYING in the top level directory
 + * PROJECT:         ReactOS Console Server DLL
 + * FILE:            frontends/gui/conwnd.c
 + * PURPOSE:         GUI Console Window Class
 + * PROGRAMMERS:     Gé van Geldorp
 + *                  Johannes Anderwald
 + *                  Jeffrey Morlan
 + *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
 + */
 +
 +/* INCLUDES *******************************************************************/
 +
 +#include <consrv.h>
 +
 +#include <windowsx.h>
 +
 +#define NDEBUG
 +#include <debug.h>
 +
 +#include "guiterm.h"
 +#include "conwnd.h"
 +#include "resource.h"
 +
 +/* GLOBALS ********************************************************************/
 +
 +// #define PM_CREATE_CONSOLE       (WM_APP + 1)
 +// #define PM_DESTROY_CONSOLE      (WM_APP + 2)
 +
 +// See guiterm.c
 +#define CONGUI_MIN_WIDTH      10
 +#define CONGUI_MIN_HEIGHT     10
 +#define CONGUI_UPDATE_TIME    0
 +#define CONGUI_UPDATE_TIMER   1
 +
 +#define CURSOR_BLINK_TIME 500
 +
 +
 +/**************************************************************\
 +\** Define the Console Leader Process for the console window **/
 +#define GWLP_CONWND_ALLOC      (2 * sizeof(LONG_PTR))
 +#define GWLP_CONSOLE_LEADER_PID 0
 +#define GWLP_CONSOLE_LEADER_TID 4
 +
 +VOID
 +SetConWndConsoleLeaderCID(IN PGUI_CONSOLE_DATA GuiData)
 +{
 +    PCONSOLE_PROCESS_DATA ProcessData;
 +    CLIENT_ID ConsoleLeaderCID;
 +
 +    ProcessData = ConSrvGetConsoleLeaderProcess(GuiData->Console);
 +    ConsoleLeaderCID = ProcessData->Process->ClientId;
 +    SetWindowLongPtrW(GuiData->hWindow, GWLP_CONSOLE_LEADER_PID,
 +                      (LONG_PTR)(ConsoleLeaderCID.UniqueProcess));
 +    SetWindowLongPtrW(GuiData->hWindow, GWLP_CONSOLE_LEADER_TID,
 +                      (LONG_PTR)(ConsoleLeaderCID.UniqueThread));
 +}
 +/**************************************************************/
 +
 +HICON   ghDefaultIcon = NULL;
 +HICON   ghDefaultIconSm = NULL;
 +HCURSOR ghDefaultCursor = NULL;
 +
 +typedef struct _GUICONSOLE_MENUITEM
 +{
 +    UINT uID;
 +    const struct _GUICONSOLE_MENUITEM *SubMenu;
 +    WORD wCmdID;
 +} GUICONSOLE_MENUITEM, *PGUICONSOLE_MENUITEM;
 +
 +static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems[] =
 +{
 +    { IDS_MARK,         NULL, ID_SYSTEM_EDIT_MARK       },
 +    { IDS_COPY,         NULL, ID_SYSTEM_EDIT_COPY       },
 +    { IDS_PASTE,        NULL, ID_SYSTEM_EDIT_PASTE      },
 +    { IDS_SELECTALL,    NULL, ID_SYSTEM_EDIT_SELECTALL  },
 +    { IDS_SCROLL,       NULL, ID_SYSTEM_EDIT_SCROLL     },
 +    { IDS_FIND,         NULL, ID_SYSTEM_EDIT_FIND       },
 +
 +    { 0, NULL, 0 } /* End of list */
 +};
 +
 +static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems[] =
 +{
 +    { IDS_EDIT,         GuiConsoleEditMenuItems, 0 },
 +    { IDS_DEFAULTS,     NULL, ID_SYSTEM_DEFAULTS   },
 +    { IDS_PROPERTIES,   NULL, ID_SYSTEM_PROPERTIES },
 +
 +    { 0, NULL, 0 } /* End of list */
 +};
 +
 +/*
 + * Default 16-color palette for foreground and background
 + * (corresponding flags in comments).
 + */
 +const COLORREF s_Colors[16] =
 +{
 +    RGB(0, 0, 0),       // (Black)
 +    RGB(0, 0, 128),     // BLUE
 +    RGB(0, 128, 0),     // GREEN
 +    RGB(0, 128, 128),   // BLUE  | GREEN
 +    RGB(128, 0, 0),     // RED
 +    RGB(128, 0, 128),   // BLUE  | RED
 +    RGB(128, 128, 0),   // GREEN | RED
 +    RGB(192, 192, 192), // BLUE  | GREEN | RED
 +
 +    RGB(128, 128, 128), // (Grey)  INTENSITY
 +    RGB(0, 0, 255),     // BLUE  | INTENSITY
 +    RGB(0, 255, 0),     // GREEN | INTENSITY
 +    RGB(0, 255, 255),   // BLUE  | GREEN | INTENSITY
 +    RGB(255, 0, 0),     // RED   | INTENSITY
 +    RGB(255, 0, 255),   // BLUE  | RED   | INTENSITY
 +    RGB(255, 255, 0),   // GREEN | RED   | INTENSITY
 +    RGB(255, 255, 255)  // BLUE  | GREEN | RED | INTENSITY
 +};
 +
 +/* FUNCTIONS ******************************************************************/
 +
 +static LRESULT CALLBACK
 +ConWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
 +
 +BOOLEAN
 +RegisterConWndClass(IN HINSTANCE hInstance)
 +{
 +    WNDCLASSEXW WndClass;
 +    ATOM WndClassAtom;
 +
 +    ghDefaultIcon   = LoadImageW(hInstance,
 +                                 MAKEINTRESOURCEW(IDI_TERMINAL),
 +                                 IMAGE_ICON,
 +                                 GetSystemMetrics(SM_CXICON),
 +                                 GetSystemMetrics(SM_CYICON),
 +                                 LR_SHARED);
 +    ghDefaultIconSm = LoadImageW(hInstance,
 +                                 MAKEINTRESOURCEW(IDI_TERMINAL),
 +                                 IMAGE_ICON,
 +                                 GetSystemMetrics(SM_CXSMICON),
 +                                 GetSystemMetrics(SM_CYSMICON),
 +                                 LR_SHARED);
 +    ghDefaultCursor = LoadCursorW(NULL, IDC_ARROW);
 +
 +    WndClass.cbSize = sizeof(WNDCLASSEXW);
 +    WndClass.lpszClassName = GUI_CONWND_CLASS;
 +    WndClass.lpfnWndProc = ConWndProc;
 +    WndClass.style = CS_DBLCLKS /* | CS_HREDRAW | CS_VREDRAW */;
 +    WndClass.hInstance = hInstance;
 +    WndClass.hIcon = ghDefaultIcon;
 +    WndClass.hIconSm = ghDefaultIconSm;
 +    WndClass.hCursor = ghDefaultCursor;
 +    WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // The color of a terminal when it is switched off.
 +    WndClass.lpszMenuName = NULL;
 +    WndClass.cbClsExtra = 0;
 +    WndClass.cbWndExtra = GWLP_CONWND_ALLOC;
 +
 +    WndClassAtom = RegisterClassExW(&WndClass);
 +    if (WndClassAtom == 0)
 +    {
 +        DPRINT1("Failed to register GUI console class\n");
 +    }
 +    else
 +    {
 +        NtUserConsoleControl(GuiConsoleWndClassAtom, &WndClassAtom, sizeof(ATOM));
 +    }
 +
 +    return (WndClassAtom != 0);
 +}
 +
 +BOOLEAN
 +UnRegisterConWndClass(HINSTANCE hInstance)
 +{
 +    return !!UnregisterClassW(GUI_CONWND_CLASS, hInstance);
 +}
 +
 +
 +
 +static VOID
 +GetScreenBufferSizeUnits(IN PCONSOLE_SCREEN_BUFFER Buffer,
 +                         IN PGUI_CONSOLE_DATA GuiData,
 +                         OUT PUINT WidthUnit,
 +                         OUT PUINT HeightUnit)
 +{
 +    if (Buffer == NULL || GuiData == NULL ||
 +        WidthUnit == NULL || HeightUnit == NULL)
 +    {
 +        return;
 +    }
 +
 +    if (GetType(Buffer) == TEXTMODE_BUFFER)
 +    {
 +        *WidthUnit  = GuiData->CharWidth ;
 +        *HeightUnit = GuiData->CharHeight;
 +    }
 +    else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
 +    {
 +        *WidthUnit  = 1;
 +        *HeightUnit = 1;
 +    }
 +}
 +
 +static VOID
 +AppendMenuItems(HMENU hMenu,
 +                const GUICONSOLE_MENUITEM *Items)
 +{
 +    UINT i = 0;
 +    WCHAR szMenuString[255];
 +    HMENU hSubMenu;
 +
 +    do
 +    {
 +        if (Items[i].uID != (UINT)-1)
 +        {
 +            if (LoadStringW(ConSrvDllInstance,
 +                            Items[i].uID,
 +                            szMenuString,
 +                            sizeof(szMenuString) / sizeof(szMenuString[0])) > 0)
 +            {
 +                if (Items[i].SubMenu != NULL)
 +                {
 +                    hSubMenu = CreatePopupMenu();
 +                    if (hSubMenu != NULL)
 +                    {
 +                        AppendMenuItems(hSubMenu, Items[i].SubMenu);
 +
 +                        if (!AppendMenuW(hMenu,
 +                                         MF_STRING | MF_POPUP,
 +                                         (UINT_PTR)hSubMenu,
 +                                         szMenuString))
 +                        {
 +                            DestroyMenu(hSubMenu);
 +                        }
 +                    }
 +                }
 +                else
 +                {
 +                    AppendMenuW(hMenu,
 +                                MF_STRING,
 +                                Items[i].wCmdID,
 +                                szMenuString);
 +                }
 +            }
 +        }
 +        else
 +        {
 +            AppendMenuW(hMenu,
 +                        MF_SEPARATOR,
 +                        0,
 +                        NULL);
 +        }
 +        i++;
 +    } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
 +}
 +
 +static VOID
 +CreateSysMenu(HWND hWnd)
 +{
++    MENUITEMINFOW mii;
++    WCHAR szMenuStringBack[255];
++    WCHAR *ptrTab;
 +    HMENU hMenu = GetSystemMenu(hWnd, FALSE);
 +    if (hMenu != NULL)
 +    {
++        mii.cbSize = sizeof(mii);
++        mii.fMask = MIIM_STRING;   
++        mii.dwTypeData = szMenuStringBack;
++        mii.cch = sizeof(szMenuStringBack)/sizeof(WCHAR);
++
++        GetMenuItemInfoW(hMenu, SC_CLOSE, FALSE, &mii);
++
++        ptrTab = wcschr(szMenuStringBack, '\t');
++        if (ptrTab)
++        {
++           *ptrTab = '\0';
++           mii.cch = wcslen(szMenuStringBack);
++
++           SetMenuItemInfoW(hMenu, SC_CLOSE, FALSE, &mii);
++        }
++
 +        AppendMenuItems(hMenu, GuiConsoleMainMenuItems);
 +        DrawMenuBar(hWnd);
 +    }
 +}
 +
 +static VOID
 +SendMenuEvent(PCONSOLE Console, UINT CmdId)
 +{
 +    INPUT_RECORD er;
 +
 +    DPRINT1("Menu item ID: %d\n", CmdId);
 +
 +    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 +
 +    er.EventType = MENU_EVENT;
 +    er.Event.MenuEvent.dwCommandId = CmdId;
 +    ConioProcessInputEvent(Console, &er);
 +
 +    LeaveCriticalSection(&Console->Lock);
 +}
 +
 +static VOID
 +Copy(PGUI_CONSOLE_DATA GuiData);
 +static VOID
 +Paste(PGUI_CONSOLE_DATA GuiData);
 +static VOID
 +UpdateSelection(PGUI_CONSOLE_DATA GuiData, PCOORD coord);
 +
 +static VOID
 +Mark(PGUI_CONSOLE_DATA GuiData)
 +{
 +    PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
 +
 +    /* Clear the old selection */
 +    // UpdateSelection(GuiData, NULL);
 +    GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
 +
 +    /* Restart a new selection */
 +    GuiData->dwSelectionCursor.X = ActiveBuffer->ViewOrigin.X;
 +    GuiData->dwSelectionCursor.Y = ActiveBuffer->ViewOrigin.Y;
 +    GuiData->Selection.dwSelectionAnchor = GuiData->dwSelectionCursor;
 +    UpdateSelection(GuiData, &GuiData->Selection.dwSelectionAnchor);
 +}
 +
 +static VOID
 +SelectAll(PGUI_CONSOLE_DATA GuiData)
 +{
 +    PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
 +
 +    /* Clear the old selection */
 +    // UpdateSelection(GuiData, NULL);
 +    GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
 +
 +    /*
 +     * The selection area extends to the whole screen buffer's width.
 +     */
 +    GuiData->Selection.dwSelectionAnchor.X = 0;
 +    GuiData->Selection.dwSelectionAnchor.Y = 0;
 +    GuiData->dwSelectionCursor.X = ActiveBuffer->ScreenBufferSize.X - 1;
 +
 +    /*
 +     * Determine whether the selection must extend to just some part
 +     * (for text-mode screen buffers) or to all of the screen buffer's
 +     * height (for graphics ones).
 +     */
 +    if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
 +    {
 +        /*
 +         * We select all the characters from the first line
 +         * to the line where the cursor is positioned.
 +         */
 +        GuiData->dwSelectionCursor.Y = ActiveBuffer->CursorPosition.Y;
 +    }
 +    else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
 +    {
 +        /*
 +         * We select all the screen buffer area.
 +         */
 +        GuiData->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
 +    }
 +
 +    /* Restart a new selection */
 +    GuiData->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION;
 +    UpdateSelection(GuiData, &GuiData->dwSelectionCursor);
 +}
 +
 +static LRESULT
 +OnCommand(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam)
 +{
 +    LRESULT Ret = TRUE;
 +    PCONSOLE Console = GuiData->Console;
 +
 +    /*
 +     * In case the selected menu item belongs to the user-reserved menu id range,
 +     * send to him a menu event and return directly. The user must handle those
 +     * reserved menu commands...
 +     */
 +    if (GuiData->CmdIdLow <= (UINT)wParam && (UINT)wParam <= GuiData->CmdIdHigh)
 +    {
 +        SendMenuEvent(Console, (UINT)wParam);
 +        goto Quit;
 +    }
 +
 +    /* ... otherwise, perform actions. */
 +    switch (wParam)
 +    {
 +        case ID_SYSTEM_EDIT_MARK:
 +            Mark(GuiData);
 +            break;
 +
 +        case ID_SYSTEM_EDIT_COPY:
 +            Copy(GuiData);
 +            break;
 +
 +        case ID_SYSTEM_EDIT_PASTE:
 +            Paste(GuiData);
 +            break;
 +
 +        case ID_SYSTEM_EDIT_SELECTALL:
 +            SelectAll(GuiData);
 +            break;
 +
 +        case ID_SYSTEM_EDIT_SCROLL:
 +            DPRINT1("Scrolling is not handled yet\n");
 +            break;
 +
 +        case ID_SYSTEM_EDIT_FIND:
 +            DPRINT1("Finding is not handled yet\n");
 +            break;
 +
 +        case ID_SYSTEM_DEFAULTS:
 +            GuiConsoleShowConsoleProperties(GuiData, TRUE);
 +            break;
 +
 +        case ID_SYSTEM_PROPERTIES:
 +            GuiConsoleShowConsoleProperties(GuiData, FALSE);
 +            break;
 +
 +        default:
 +            Ret = FALSE;
 +            break;
 +    }
 +
 +Quit:
 +    if (!Ret)
 +        Ret = DefWindowProcW(GuiData->hWindow, WM_SYSCOMMAND, wParam, lParam);
 +
 +    return Ret;
 +}
 +
 +static PGUI_CONSOLE_DATA
 +GuiGetGuiData(HWND hWnd)
 +{
 +    /* This function ensures that the console pointer is not NULL */
 +    PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
 +    return ( ((GuiData == NULL) || (GuiData->hWindow == hWnd && GuiData->Console != NULL)) ? GuiData : NULL );
 +}
 +
 +static VOID
 +ResizeConWnd(PGUI_CONSOLE_DATA GuiData, DWORD WidthUnit, DWORD HeightUnit)
 +{
 +    PCONSOLE_SCREEN_BUFFER Buff = GuiData->ActiveBuffer;
 +    SCROLLINFO sInfo;
 +
 +    DWORD Width, Height;
 +
 +    Width  = Buff->ViewSize.X * WidthUnit  +
 +             2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
 +    Height = Buff->ViewSize.Y * HeightUnit +
 +             2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
 +
 +    /* Set scrollbar sizes */
 +    sInfo.cbSize = sizeof(SCROLLINFO);
 +    sInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
 +    sInfo.nMin = 0;
 +    if (Buff->ScreenBufferSize.Y > Buff->ViewSize.Y)
 +    {
 +        sInfo.nMax  = Buff->ScreenBufferSize.Y - 1;
 +        sInfo.nPage = Buff->ViewSize.Y;
 +        sInfo.nPos  = Buff->ViewOrigin.Y;
 +        SetScrollInfo(GuiData->hWindow, SB_VERT, &sInfo, TRUE);
 +        Width += GetSystemMetrics(SM_CXVSCROLL);
 +        ShowScrollBar(GuiData->hWindow, SB_VERT, TRUE);
 +    }
 +    else
 +    {
 +        ShowScrollBar(GuiData->hWindow, SB_VERT, FALSE);
 +    }
 +
 +    if (Buff->ScreenBufferSize.X > Buff->ViewSize.X)
 +    {
 +        sInfo.nMax  = Buff->ScreenBufferSize.X - 1;
 +        sInfo.nPage = Buff->ViewSize.X;
 +        sInfo.nPos  = Buff->ViewOrigin.X;
 +        SetScrollInfo(GuiData->hWindow, SB_HORZ, &sInfo, TRUE);
 +        Height += GetSystemMetrics(SM_CYHSCROLL);
 +        ShowScrollBar(GuiData->hWindow, SB_HORZ, TRUE);
 +    }
 +    else
 +    {
 +        ShowScrollBar(GuiData->hWindow, SB_HORZ, FALSE);
 +    }
 +
 +    /* Resize the window  */
 +    SetWindowPos(GuiData->hWindow, NULL, 0, 0, Width, Height,
 +                 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS);
 +    // NOTE: The SWP_NOCOPYBITS flag can be replaced by a subsequent call
 +    // to: InvalidateRect(GuiData->hWindow, NULL, TRUE);
 +}
 +
 +static BOOL
 +OnNcCreate(HWND hWnd, LPCREATESTRUCTW Create)
 +{
 +    PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)Create->lpCreateParams;
 +    PCONSOLE Console;
 +    HDC hDC;
 +    HFONT OldFont;
 +    TEXTMETRICW Metrics;
 +    SIZE CharSize;
 +
 +    if (NULL == GuiData)
 +    {
 +        DPRINT1("GuiConsoleNcCreate: No GUI data\n");
 +        return FALSE;
 +    }
 +
 +    Console = GuiData->Console;
 +
 +    GuiData->hWindow = hWnd;
 +
 +    GuiData->Font = CreateFontW(LOWORD(GuiData->GuiInfo.FontSize),
 +                                0, // HIWORD(GuiData->GuiInfo.FontSize),
 +                                0,
 +                                TA_BASELINE,
 +                                GuiData->GuiInfo.FontWeight,
 +                                FALSE,
 +                                FALSE,
 +                                FALSE,
 +                                OEM_CHARSET,
 +                                OUT_DEFAULT_PRECIS,
 +                                CLIP_DEFAULT_PRECIS,
 +                                NONANTIALIASED_QUALITY,
 +                                FIXED_PITCH | GuiData->GuiInfo.FontFamily /* FF_DONTCARE */,
 +                                GuiData->GuiInfo.FaceName);
 +
 +    if (NULL == GuiData->Font)
 +    {
 +        DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
 +        GuiData->hWindow = NULL;
 +        SetEvent(GuiData->hGuiInitEvent);
 +        return FALSE;
 +    }
 +    hDC = GetDC(GuiData->hWindow);
 +    if (NULL == hDC)
 +    {
 +        DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
 +        DeleteObject(GuiData->Font);
 +        GuiData->hWindow = NULL;
 +        SetEvent(GuiData->hGuiInitEvent);
 +        return FALSE;
 +    }
 +    OldFont = SelectObject(hDC, GuiData->Font);
 +    if (NULL == OldFont)
 +    {
 +        DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
 +        ReleaseDC(GuiData->hWindow, hDC);
 +        DeleteObject(GuiData->Font);
 +        GuiData->hWindow = NULL;
 +        SetEvent(GuiData->hGuiInitEvent);
 +        return FALSE;
 +    }
 +    if (!GetTextMetricsW(hDC, &Metrics))
 +    {
 +        DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
 +        SelectObject(hDC, OldFont);
 +        ReleaseDC(GuiData->hWindow, hDC);
 +        DeleteObject(GuiData->Font);
 +        GuiData->hWindow = NULL;
 +        SetEvent(GuiData->hGuiInitEvent);
 +        return FALSE;
 +    }
 +    GuiData->CharWidth  = Metrics.tmMaxCharWidth;
 +    GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
 +
 +    /* Measure real char width more precisely if possible. */
 +    if (GetTextExtentPoint32W(hDC, L"R", 1, &CharSize))
 +        GuiData->CharWidth = CharSize.cx;
 +
 +    SelectObject(hDC, OldFont);
 +
 +    ReleaseDC(GuiData->hWindow, hDC);
 +
 +    /* Initialize the terminal framebuffer */
 +    GuiData->hMemDC  = CreateCompatibleDC(NULL);
 +    GuiData->hBitmap = NULL;
 +    GuiData->hSysPalette = NULL; /* Original system palette */
 +
 +    /* Update the icons of the window */
 +    if (GuiData->hIcon != ghDefaultIcon)
 +    {
 +        DefWindowProcW(GuiData->hWindow, WM_SETICON, ICON_BIG  , (LPARAM)GuiData->hIcon  );
 +        DefWindowProcW(GuiData->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)GuiData->hIconSm);
 +    }
 +
 +    // FIXME: Keep these instructions here ? ///////////////////////////////////
 +    Console->ActiveBuffer->CursorBlinkOn = TRUE;
 +    Console->ActiveBuffer->ForceCursorOff = FALSE;
 +    ////////////////////////////////////////////////////////////////////////////
 +
 +    SetWindowLongPtrW(GuiData->hWindow, GWLP_USERDATA, (DWORD_PTR)GuiData);
 +
 +    SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL);
 +    CreateSysMenu(GuiData->hWindow);
 +
 +    DPRINT("OnNcCreate - setting start event\n");
 +    SetEvent(GuiData->hGuiInitEvent);
 +
 +    return (BOOL)DefWindowProcW(GuiData->hWindow, WM_NCCREATE, 0, (LPARAM)Create);
 +}
 +
 +
 +BOOL
 +EnterFullScreen(PGUI_CONSOLE_DATA GuiData);
 +VOID
 +LeaveFullScreen(PGUI_CONSOLE_DATA GuiData);
 +VOID
 +SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen);
 +VOID
 +GuiConsoleSwitchFullScreen(PGUI_CONSOLE_DATA GuiData);
 +
 +static VOID
 +OnActivate(PGUI_CONSOLE_DATA GuiData, WPARAM wParam)
 +{
 +    PCONSOLE Console = GuiData->Console;
 +    WORD ActivationState = LOWORD(wParam);
 +
 +    DPRINT1("WM_ACTIVATE - ActivationState = %d\n");
 +
 +    if ( ActivationState == WA_ACTIVE ||
 +         ActivationState == WA_CLICKACTIVE )
 +    {
 +        if (GuiData->GuiInfo.FullScreen)
 +        {
 +            EnterFullScreen(GuiData);
 +            // // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
 +            // SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
 +        }
 +    }
 +    else // if (ActivationState == WA_INACTIVE)
 +    {
 +        if (GuiData->GuiInfo.FullScreen)
 +        {
 +            SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
 +            LeaveFullScreen(GuiData);
 +            // // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
 +            // SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
 +        }
 +    }
 +
 +    /*
 +     * When we are in QuickEdit mode, ignore the next mouse signal
 +     * when we are going to be enabled again via the mouse, in order
 +     * to prevent e.g. an erroneous right-click from the user which
 +     * would have as an effect to paste some unwanted text...
 +     */
 +    if (Console->QuickEdit && (ActivationState == WA_CLICKACTIVE))
 +        GuiData->IgnoreNextMouseSignal = TRUE;
 +}
 +
 +static VOID
 +OnFocus(PGUI_CONSOLE_DATA GuiData, BOOL SetFocus)
 +{
 +    PCONSOLE Console = GuiData->Console;
 +    INPUT_RECORD er;
 +
 +    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 +
 +    er.EventType = FOCUS_EVENT;
 +    er.Event.FocusEvent.bSetFocus = SetFocus;
 +    ConioProcessInputEvent(Console, &er);
 +
 +    LeaveCriticalSection(&Console->Lock);
 +
 +    if (SetFocus)
 +        DPRINT1("TODO: Create console caret\n");
 +    else
 +        DPRINT1("TODO: Destroy console caret\n");
 +}
 +
 +static VOID
 +SmallRectToRect(PGUI_CONSOLE_DATA GuiData, PRECT Rect, PSMALL_RECT SmallRect)
 +{
 +    PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
 +    UINT WidthUnit, HeightUnit;
 +
 +    GetScreenBufferSizeUnits(Buffer, GuiData, &WidthUnit, &HeightUnit);
 +
 +    Rect->left   = (SmallRect->Left       - Buffer->ViewOrigin.X) * WidthUnit ;
 +    Rect->top    = (SmallRect->Top        - Buffer->ViewOrigin.Y) * HeightUnit;
 +    Rect->right  = (SmallRect->Right  + 1 - Buffer->ViewOrigin.X) * WidthUnit ;
 +    Rect->bottom = (SmallRect->Bottom + 1 - Buffer->ViewOrigin.Y) * HeightUnit;
 +}
 +
 +static VOID
 +UpdateSelection(PGUI_CONSOLE_DATA GuiData, PCOORD coord)
 +{
 +    PCONSOLE Console = GuiData->Console;
 +    RECT oldRect;
 +
 +    SmallRectToRect(GuiData, &oldRect, &GuiData->Selection.srSelection);
 +
 +    if (coord != NULL)
 +    {
 +        RECT newRect;
 +        SMALL_RECT rc;
 +
 +        /* Exchange left/top with right/bottom if required */
 +        rc.Left   = min(GuiData->Selection.dwSelectionAnchor.X, coord->X);
 +        rc.Top    = min(GuiData->Selection.dwSelectionAnchor.Y, coord->Y);
 +        rc.Right  = max(GuiData->Selection.dwSelectionAnchor.X, coord->X);
 +        rc.Bottom = max(GuiData->Selection.dwSelectionAnchor.Y, coord->Y);
 +
 +        SmallRectToRect(GuiData, &newRect, &rc);
 +
 +        if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
 +        {
 +            if (memcmp(&rc, &GuiData->Selection.srSelection, sizeof(SMALL_RECT)) != 0)
 +            {
 +                HRGN rgn1, rgn2;
 +
 +                /* Calculate the region that needs to be updated */
 +                if ((rgn1 = CreateRectRgnIndirect(&oldRect)))
 +                {
 +                    if ((rgn2 = CreateRectRgnIndirect(&newRect)))
 +                    {
 +                        if (CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR)
 +                        {
 +                            InvalidateRgn(GuiData->hWindow, rgn1, FALSE);
 +                        }
 +                        DeleteObject(rgn2);
 +                    }
 +                    DeleteObject(rgn1);
 +                }
 +            }
 +        }
 +        else
 +        {
 +            InvalidateRect(GuiData->hWindow, &newRect, FALSE);
 +        }
 +
 +        GuiData->Selection.dwFlags |= CONSOLE_SELECTION_NOT_EMPTY;
 +        GuiData->Selection.srSelection = rc;
 +        GuiData->dwSelectionCursor = *coord;
 +
 +        if ((GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) == 0)
 +        {
 +            LPWSTR SelectionType, WindowTitle = NULL;
 +            SIZE_T Length = 0;
 +
 +            /* Clear the old selection */
 +            if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
 +            {
 +                InvalidateRect(GuiData->hWindow, &oldRect, FALSE);
 +            }
 +
 +            if (GuiData->Selection.dwFlags & CONSOLE_MOUSE_SELECTION)
 +            {
 +                SelectionType = L"Selection - ";
 +            }
 +            else
 +            {
 +                SelectionType = L"Mark - ";
 +            }
 +
 +            Length = Console->Title.Length + wcslen(SelectionType) + 1;
 +            WindowTitle = ConsoleAllocHeap(0, Length * sizeof(WCHAR));
 +            wcscpy(WindowTitle, SelectionType);
 +            wcscat(WindowTitle, Console->Title.Buffer);
 +            SetWindowText(GuiData->hWindow, WindowTitle);
 +            ConsoleFreeHeap(WindowTitle);
 +
 +            GuiData->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS;
 +            ConioPause(Console, PAUSED_FROM_SELECTION);
 +        }
 +    }
 +    else
 +    {
 +        /* Clear the selection */
 +        if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
 +        {
 +            InvalidateRect(GuiData->hWindow, &oldRect, FALSE);
 +        }
 +
 +        GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
 +        ConioUnpause(Console, PAUSED_FROM_SELECTION);
 +
 +        SetWindowText(GuiData->hWindow, Console->Title.Buffer);
 +    }
 +}
 +
 +
 +VOID
 +GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
 +                       PGUI_CONSOLE_DATA GuiData,
 +                       PRECT rcView,
 +                       PRECT rcFramebuffer);
 +VOID
 +GuiPaintGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
 +                       PGUI_CONSOLE_DATA GuiData,
 +                       PRECT rcView,
 +                       PRECT rcFramebuffer);
 +
 +static VOID
 +OnPaint(PGUI_CONSOLE_DATA GuiData)
 +{
 +    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
 +    PAINTSTRUCT ps;
 +    RECT rcPaint;
 +
 +    ActiveBuffer = GuiData->ActiveBuffer;
 +
 +    BeginPaint(GuiData->hWindow, &ps);
 +    if (ps.hdc != NULL &&
 +        ps.rcPaint.left < ps.rcPaint.right &&
 +        ps.rcPaint.top < ps.rcPaint.bottom)
 +    {
 +        EnterCriticalSection(&GuiData->Lock);
 +
 +        /* Compose the current screen-buffer on-memory */
 +        if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
 +        {
 +            GuiPaintTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
 +                                   GuiData, &ps.rcPaint, &rcPaint);
 +        }
 +        else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
 +        {
 +            GuiPaintGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)ActiveBuffer,
 +                                   GuiData, &ps.rcPaint, &rcPaint);
 +        }
 +
 +        /* Send it to screen */
 +        BitBlt(ps.hdc,
 +               ps.rcPaint.left,
 +               ps.rcPaint.top,
 +               rcPaint.right  - rcPaint.left,
 +               rcPaint.bottom - rcPaint.top,
 +               GuiData->hMemDC,
 +               rcPaint.left,
 +               rcPaint.top,
 +               SRCCOPY);
 +
 +        if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
 +        {
 +            SmallRectToRect(GuiData, &rcPaint, &GuiData->Selection.srSelection);
 +
 +            /* Invert the selection */
 +            if (IntersectRect(&rcPaint, &ps.rcPaint, &rcPaint))
 +            {
 +                InvertRect(ps.hdc, &rcPaint);
 +            }
 +        }
 +
 +        LeaveCriticalSection(&GuiData->Lock);
 +    }
 +    EndPaint(GuiData->hWindow, &ps);
 +
 +    return;
 +}
 +
 +static VOID
 +OnPaletteChanged(PGUI_CONSOLE_DATA GuiData)
 +{
 +    PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
 +
 +    // See WM_PALETTECHANGED message
 +    // if ((HWND)wParam == hWnd) break;
 +
 +    // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
 +    if (ActiveBuffer->PaletteHandle)
 +    {
 +        DPRINT("WM_PALETTECHANGED changing palette\n");
 +
 +        /* Specify the use of the system palette for the framebuffer */
 +        SetSystemPaletteUse(GuiData->hMemDC, ActiveBuffer->PaletteUsage);
 +
 +        /* Realize the (logical) palette */
 +        RealizePalette(GuiData->hMemDC);
 +    }
 +}
 +
 +static BOOL
 +IsSystemKey(WORD VirtualKeyCode)
 +{
 +    switch (VirtualKeyCode)
 +    {
 +        /* From MSDN, "Virtual-Key Codes" */
 +        case VK_RETURN:
 +        case VK_SHIFT:
 +        case VK_CONTROL:
 +        case VK_MENU:
 +        case VK_PAUSE:
 +        case VK_CAPITAL:
 +        case VK_ESCAPE:
 +        case VK_LWIN:
 +        case VK_RWIN:
 +        case VK_NUMLOCK:
 +        case VK_SCROLL:
 +            return TRUE;
 +        default:
 +            return FALSE;
 +    }
 +}
 +
 +static VOID
 +OnKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
 +{
 +    PCONSOLE Console = GuiData->Console;
 +    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
 +
 +    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 +
 +    ActiveBuffer = GuiData->ActiveBuffer;
 +
 +    if (GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS)
 +    {
 +        WORD VirtualKeyCode = LOWORD(wParam);
 +
 +        if (msg != WM_KEYDOWN) goto Quit;
 +
 +        if (VirtualKeyCode == VK_RETURN)
 +        {
 +            /* Copy (and clear) selection if ENTER is pressed */
 +            Copy(GuiData);
 +            goto Quit;
 +        }
 +        else if ( VirtualKeyCode == VK_ESCAPE ||
 +                 (VirtualKeyCode == 'C' && GetKeyState(VK_CONTROL) & 0x8000) )
 +        {
 +            /* Cancel selection if ESC or Ctrl-C are pressed */
 +            UpdateSelection(GuiData, NULL);
 +            goto Quit;
 +        }
 +
 +        if ((GuiData->Selection.dwFlags & CONSOLE_MOUSE_SELECTION) == 0)
 +        {
 +            /* Keyboard selection mode */
 +            BOOL Interpreted = FALSE;
 +            BOOL MajPressed  = (GetKeyState(VK_SHIFT) & 0x8000);
 +
 +            switch (VirtualKeyCode)
 +            {
 +                case VK_LEFT:
 +                {
 +                    Interpreted = TRUE;
 +                    if (GuiData->dwSelectionCursor.X > 0)
 +                        GuiData->dwSelectionCursor.X--;
 +
 +                    break;
 +                }
 +
 +                case VK_RIGHT:
 +                {
 +                    Interpreted = TRUE;
 +                    if (GuiData->dwSelectionCursor.X < ActiveBuffer->ScreenBufferSize.X - 1)
 +                        GuiData->dwSelectionCursor.X++;
 +
 +                    break;
 +                }
 +
 +                case VK_UP:
 +                {
 +                    Interpreted = TRUE;
 +                    if (GuiData->dwSelectionCursor.Y > 0)
 +                        GuiData->dwSelectionCursor.Y--;
 +
 +                    break;
 +                }
 +
 +                case VK_DOWN:
 +                {
 +                    Interpreted = TRUE;
 +                    if (GuiData->dwSelectionCursor.Y < ActiveBuffer->ScreenBufferSize.Y - 1)
 +                        GuiData->dwSelectionCursor.Y++;
 +
 +                    break;
 +                }
 +
 +                case VK_HOME:
 +                {
 +                    Interpreted = TRUE;
 +                    GuiData->dwSelectionCursor.X = 0;
 +                    GuiData->dwSelectionCursor.Y = 0;
 +                    break;
 +                }
 +
 +                case VK_END:
 +                {
 +                    Interpreted = TRUE;
 +                    GuiData->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
 +                    break;
 +                }
 +
 +                case VK_PRIOR:
 +                {
 +                    Interpreted = TRUE;
 +                    GuiData->dwSelectionCursor.Y -= ActiveBuffer->ViewSize.Y;
 +                    if (GuiData->dwSelectionCursor.Y < 0)
 +                        GuiData->dwSelectionCursor.Y = 0;
 +
 +                    break;
 +                }
 +
 +                case VK_NEXT:
 +                {
 +                    Interpreted = TRUE;
 +                    GuiData->dwSelectionCursor.Y += ActiveBuffer->ViewSize.Y;
 +                    if (GuiData->dwSelectionCursor.Y >= ActiveBuffer->ScreenBufferSize.Y)
 +                        GuiData->dwSelectionCursor.Y  = ActiveBuffer->ScreenBufferSize.Y - 1;
 +
 +                    break;
 +                }
 +
 +                default:
 +                    break;
 +            }
 +
 +            if (Interpreted)
 +            {
 +                if (!MajPressed)
 +                    GuiData->Selection.dwSelectionAnchor = GuiData->dwSelectionCursor;
 +
 +                UpdateSelection(GuiData, &GuiData->dwSelectionCursor);
 +            }
 +            else if (!IsSystemKey(VirtualKeyCode))
 +            {
 +                /* Emit an error beep sound */
 +                SendNotifyMessage(GuiData->hWindow, PM_CONSOLE_BEEP, 0, 0);
 +            }
 +
 +            goto Quit;
 +        }
 +        else
 +        {
 +            /* Mouse selection mode */
 +
 +            if (!IsSystemKey(VirtualKeyCode))
 +            {
 +                /* Clear the selection and send the key into the input buffer */
 +                UpdateSelection(GuiData, NULL);
 +            }
 +            else
 +            {
 +                goto Quit;
 +            }
 +        }
 +    }
 +
 +    if ((GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) == 0)
 +    {
 +        MSG Message;
 +
 +        Message.hwnd = GuiData->hWindow;
 +        Message.message = msg;
 +        Message.wParam = wParam;
 +        Message.lParam = lParam;
 +
 +        ConioProcessKey(Console, &Message);
 +    }
 +
 +Quit:
 +    LeaveCriticalSection(&Console->Lock);
 +}
 +
 +
 +// FIXME: Remove after fixing OnTimer
 +VOID
 +InvalidateCell(PGUI_CONSOLE_DATA GuiData,
 +               SHORT x, SHORT y);
 +
 +static VOID
 +OnTimer(PGUI_CONSOLE_DATA GuiData)
 +{
 +    PCONSOLE Console = GuiData->Console;
 +    PCONSOLE_SCREEN_BUFFER Buff;
 +
 +    SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CURSOR_BLINK_TIME, NULL);
 +
 +    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 +
 +    Buff = GuiData->ActiveBuffer;
 +
 +    if (GetType(Buff) == TEXTMODE_BUFFER)
 +    {
 +        InvalidateCell(GuiData, Buff->CursorPosition.X, Buff->CursorPosition.Y);
 +        Buff->CursorBlinkOn = !Buff->CursorBlinkOn;
 +
 +        if ((GuiData->OldCursor.x != Buff->CursorPosition.X) ||
 +            (GuiData->OldCursor.y != Buff->CursorPosition.Y))
 +        {
 +            SCROLLINFO xScroll;
 +            int OldScrollX = -1, OldScrollY = -1;
 +            int NewScrollX = -1, NewScrollY = -1;
 +
 +            xScroll.cbSize = sizeof(SCROLLINFO);
 +            xScroll.fMask = SIF_POS;
 +            // Capture the original position of the scroll bars and save them.
 +            if (GetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll)) OldScrollX = xScroll.nPos;
 +            if (GetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll)) OldScrollY = xScroll.nPos;
 +
 +            // If we successfully got the info for the horizontal scrollbar
 +            if (OldScrollX >= 0)
 +            {
 +                if ((Buff->CursorPosition.X < Buff->ViewOrigin.X) ||
 +                    (Buff->CursorPosition.X >= (Buff->ViewOrigin.X + Buff->ViewSize.X)))
 +                {
 +                    // Handle the horizontal scroll bar
 +                    if (Buff->CursorPosition.X >= Buff->ViewSize.X)
 +                        NewScrollX = Buff->CursorPosition.X - Buff->ViewSize.X + 1;
 +                    else
 +                        NewScrollX = 0;
 +                }
 +                else
 +                {
 +                    NewScrollX = OldScrollX;
 +                }
 +            }
 +            // If we successfully got the info for the vertical scrollbar
 +            if (OldScrollY >= 0)
 +            {
 +                if ((Buff->CursorPosition.Y < Buff->ViewOrigin.Y) ||
 +                    (Buff->CursorPosition.Y >= (Buff->ViewOrigin.Y + Buff->ViewSize.Y)))
 +                {
 +                    // Handle the vertical scroll bar
 +                    if (Buff->CursorPosition.Y >= Buff->ViewSize.Y)
 +                        NewScrollY = Buff->CursorPosition.Y - Buff->ViewSize.Y + 1;
 +                    else
 +                        NewScrollY = 0;
 +                }
 +                else
 +                {
 +                    NewScrollY = OldScrollY;
 +                }
 +            }
 +
 +            // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
 +            // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
 +            //       was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
 +            //       and their associated scrollbar is left alone.
 +            if ((OldScrollX != NewScrollX) || (OldScrollY != NewScrollY))
 +            {
 +                Buff->ViewOrigin.X = NewScrollX;
 +                Buff->ViewOrigin.Y = NewScrollY;
 +                ScrollWindowEx(GuiData->hWindow,
 +                               (OldScrollX - NewScrollX) * GuiData->CharWidth,
 +                               (OldScrollY - NewScrollY) * GuiData->CharHeight,
 +                               NULL,
 +                               NULL,
 +                               NULL,
 +                               NULL,
 +                               SW_INVALIDATE);
 +                if (NewScrollX >= 0)
 +                {
 +                    xScroll.nPos = NewScrollX;
 +                    SetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll, TRUE);
 +                }
 +                if (NewScrollY >= 0)
 +                {
 +                    xScroll.nPos = NewScrollY;
 +                    SetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll, TRUE);
 +                }
 +                UpdateWindow(GuiData->hWindow);
 +                // InvalidateRect(GuiData->hWindow, NULL, FALSE);
 +                GuiData->OldCursor.x = Buff->CursorPosition.X;
 +                GuiData->OldCursor.y = Buff->CursorPosition.Y;
 +            }
 +        }
 +    }
 +    else /* if (GetType(Buff) == GRAPHICS_BUFFER) */
 +    {
 +    }
 +
 +    LeaveCriticalSection(&Console->Lock);
 +}
 +
 +static BOOL
 +OnClose(PGUI_CONSOLE_DATA GuiData)
 +{
 +    PCONSOLE Console = GuiData->Console;
 +
 +    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
 +        return TRUE;
 +
 +    // TODO: Prompt for termination ? (Warn the user about possible apps running in this console)
 +
 +    /*
 +     * FIXME: Windows will wait up to 5 seconds for the thread to exit.
 +     * We shouldn't wait here, though, since the console lock is entered.
 +     * A copy of the thread list probably needs to be made.
 +     */
 +    ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT);
 +
 +    LeaveCriticalSection(&Console->Lock);
 +    return FALSE;
 +}
 +
 +static LRESULT
 +OnNcDestroy(HWND hWnd)
 +{
 +    PGUI_CONSOLE_DATA GuiData = GuiGetGuiData(hWnd);
 +
 +    KillTimer(hWnd, CONGUI_UPDATE_TIMER);
 +    GetSystemMenu(hWnd, TRUE);
 +
 +    if (GuiData)
 +    {
 +        /* Free the terminal framebuffer */
 +        if (GuiData->hMemDC ) DeleteDC(GuiData->hMemDC);
 +        if (GuiData->hBitmap) DeleteObject(GuiData->hBitmap);
 +        // if (GuiData->hSysPalette) DeleteObject(GuiData->hSysPalette);
 +        if (GuiData->Font) DeleteObject(GuiData->Font);
 +    }
 +
 +    /* Free the GuiData registration */
 +    SetWindowLongPtrW(hWnd, GWLP_USERDATA, (DWORD_PTR)NULL);
 +
 +    return DefWindowProcW(hWnd, WM_NCDESTROY, 0, 0);
 +}
 +
 +static COORD
 +PointToCoord(PGUI_CONSOLE_DATA GuiData, LPARAM lParam)
 +{
 +    PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
 +    COORD Coord;
 +    UINT  WidthUnit, HeightUnit;
 +
 +    GetScreenBufferSizeUnits(Buffer, GuiData, &WidthUnit, &HeightUnit);
 +
 +    Coord.X = Buffer->ViewOrigin.X + ((SHORT)LOWORD(lParam) / (int)WidthUnit );
 +    Coord.Y = Buffer->ViewOrigin.Y + ((SHORT)HIWORD(lParam) / (int)HeightUnit);
 +
 +    /* Clip coordinate to ensure it's inside buffer */
 +    if (Coord.X < 0)
 +        Coord.X = 0;
 +    else if (Coord.X >= Buffer->ScreenBufferSize.X)
 +        Coord.X = Buffer->ScreenBufferSize.X - 1;
 +
 +    if (Coord.Y < 0)
 +        Coord.Y = 0;
 +    else if (Coord.Y >= Buffer->ScreenBufferSize.Y)
 +        Coord.Y = Buffer->ScreenBufferSize.Y - 1;
 +
 +    return Coord;
 +}
 +
 +static LRESULT
 +OnMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
 +{
 +    BOOL Err = FALSE;
 +    PCONSOLE Console = GuiData->Console;
 +
 +    if (GuiData->IgnoreNextMouseSignal)
 +    {
 +        if (msg != WM_LBUTTONDOWN &&
 +            msg != WM_MBUTTONDOWN &&
 +            msg != WM_RBUTTONDOWN &&
 +            msg != WM_MOUSEMOVE)
 +        {
 +            /*
 +             * If this mouse signal is not a button-down action or a move,
 +             * then it is the last signal being ignored.
 +             */
 +            GuiData->IgnoreNextMouseSignal = FALSE;
 +        }
 +        else
 +        {
 +            /*
 +             * This mouse signal is a button-down action or a move.
 +             * Ignore it and perform default action.
 +             */
 +            Err = TRUE;
 +        }
 +        goto Quit;
 +    }
 +
 +    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
 +    {
 +        Err = TRUE;
 +        goto Quit;
 +    }
 +
 +    if ( (GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) ||
 +         (Console->QuickEdit) )
 +    {
 +        switch (msg)
 +        {
 +            case WM_LBUTTONDOWN:
 +            {
 +                /* Clear the old selection */
 +                // UpdateSelection(GuiData, NULL);
 +                GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
 +
 +                /* Restart a new selection */
 +                GuiData->Selection.dwSelectionAnchor = PointToCoord(GuiData, lParam);
 +                SetCapture(GuiData->hWindow);
 +                GuiData->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
 +                UpdateSelection(GuiData, &GuiData->Selection.dwSelectionAnchor);
 +
 +                break;
 +            }
 +
 +            case WM_LBUTTONUP:
 +            {
 +                // COORD c;
 +
 +                if (!(GuiData->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
 +
 +                // c = PointToCoord(GuiData, lParam);
 +                GuiData->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN;
 +                // UpdateSelection(GuiData, &c);
 +                ReleaseCapture();
 +
 +                break;
 +            }
 +
 +            case WM_LBUTTONDBLCLK:
 +            {
 +                PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
 +
 +                if (GetType(Buffer) == TEXTMODE_BUFFER)
 +                {
 +#ifdef IS_WHITESPACE
 +#undef IS_WHITESPACE
 +#endif
 +#define IS_WHITESPACE(c)    \
 +    ((c) == L'\0' || (c) == L' ' || (c) == L'\t' || (c) == L'\r' || (c) == L'\n')
 +
 +                    PTEXTMODE_SCREEN_BUFFER TextBuffer = (PTEXTMODE_SCREEN_BUFFER)Buffer;
 +                    COORD cL, cR;
 +                    PCHAR_INFO ptrL, ptrR;
 +
 +                    /* Starting point */
 +                    cL = cR = PointToCoord(GuiData, lParam);
 +                    ptrL = ptrR = ConioCoordToPointer(TextBuffer, cL.X, cL.Y);
 +
 +                    /* Enlarge the selection by checking for whitespace */
 +                    while ((0 < cL.X) && !IS_WHITESPACE(ptrL->Char.UnicodeChar)
 +                                      && !IS_WHITESPACE((ptrL-1)->Char.UnicodeChar))
 +                    {
 +                        --cL.X;
 +                        --ptrL;
 +                    }
 +                    while ((cR.X < TextBuffer->ScreenBufferSize.X - 1) &&
 +                           !IS_WHITESPACE(ptrR->Char.UnicodeChar)      &&
 +                           !IS_WHITESPACE((ptrR+1)->Char.UnicodeChar))
 +                    {
 +                        ++cR.X;
 +                        ++ptrR;
 +                    }
 +
 +                    /*
 +                     * Update the selection started with the single
 +                     * left-click that preceded this double-click.
 +                     */
 +                    GuiData->Selection.dwSelectionAnchor = cL;
 +                    GuiData->dwSelectionCursor           = cR;
 +
 +                    GuiData->Selection.dwFlags |= CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
 +                    UpdateSelection(GuiData, &GuiData->dwSelectionCursor);
 +
 +                    /* Ignore the next mouse move signal */
 +                    GuiData->IgnoreNextMouseSignal = TRUE;
 +                }
 +
 +                break;
 +            }
 +
 +            case WM_RBUTTONDOWN:
 +            case WM_RBUTTONDBLCLK:
 +            {
 +                if (!(GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
 +                {
 +                    Paste(GuiData);
 +                }
 +                else
 +                {
 +                    Copy(GuiData);
 +                }
 +
 +                /* Ignore the next mouse move signal */
 +                GuiData->IgnoreNextMouseSignal = TRUE;
 +                break;
 +            }
 +
 +            case WM_MOUSEMOVE:
 +            {
 +                COORD c;
 +
 +                if (!(wParam & MK_LBUTTON)) break;
 +                if (!(GuiData->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
 +
 +                c = PointToCoord(GuiData, lParam); /* TODO: Scroll buffer to bring c into view */
 +                UpdateSelection(GuiData, &c);
 +
 +                break;
 +            }
 +
 +            default:
 +                Err = FALSE; // TRUE;
 +                break;
 +        }
 +    }
 +    else if (Console->InputBuffer.Mode & ENABLE_MOUSE_INPUT)
 +    {
 +        INPUT_RECORD er;
 +        WORD  wKeyState         = GET_KEYSTATE_WPARAM(wParam);
 +        DWORD dwButtonState     = 0;
 +        DWORD dwControlKeyState = 0;
 +        DWORD dwEventFlags      = 0;
 +
 +        switch (msg)
 +        {
 +            case WM_LBUTTONDOWN:
 +                SetCapture(GuiData->hWindow);
 +                dwButtonState = FROM_LEFT_1ST_BUTTON_PRESSED;
 +                dwEventFlags  = 0;
 +                break;
 +
 +            case WM_MBUTTONDOWN:
 +                SetCapture(GuiData->hWindow);
 +                dwButtonState = FROM_LEFT_2ND_BUTTON_PRESSED;
 +                dwEventFlags  = 0;
 +                break;
 +
 +            case WM_RBUTTONDOWN:
 +                SetCapture(GuiData->hWindow);
 +                dwButtonState = RIGHTMOST_BUTTON_PRESSED;
 +                dwEventFlags  = 0;
 +                break;
 +
 +            case WM_LBUTTONUP:
 +                ReleaseCapture();
 +                dwButtonState = 0;
 +                dwEventFlags  = 0;
 +                break;
 +
 +            case WM_MBUTTONUP:
 +                ReleaseCapture();
 +                dwButtonState = 0;
 +                dwEventFlags  = 0;
 +                break;
 +
 +            case WM_RBUTTONUP:
 +                ReleaseCapture();
 +                dwButtonState = 0;
 +                dwEventFlags  = 0;
 +                break;
 +
 +            case WM_LBUTTONDBLCLK:
 +                dwButtonState = FROM_LEFT_1ST_BUTTON_PRESSED;
 +                dwEventFlags  = DOUBLE_CLICK;
 +                break;
 +
 +            case WM_MBUTTONDBLCLK:
 +                dwButtonState = FROM_LEFT_2ND_BUTTON_PRESSED;
 +                dwEventFlags  = DOUBLE_CLICK;
 +                break;
 +
 +            case WM_RBUTTONDBLCLK:
 +                dwButtonState = RIGHTMOST_BUTTON_PRESSED;
 +                dwEventFlags  = DOUBLE_CLICK;
 +                break;
 +
 +            case WM_MOUSEMOVE:
 +                dwButtonState = 0;
 +                dwEventFlags  = MOUSE_MOVED;
 +                break;
 +
 +            case WM_MOUSEWHEEL:
 +                dwButtonState = GET_WHEEL_DELTA_WPARAM(wParam) << 16;
 +                dwEventFlags  = MOUSE_WHEELED;
 +                break;
 +
 +            case WM_MOUSEHWHEEL:
 +                dwButtonState = GET_WHEEL_DELTA_WPARAM(wParam) << 16;
 +                dwEventFlags  = MOUSE_HWHEELED;
 +                break;
 +
 +            default:
 +                Err = TRUE;
 +                break;
 +        }
 +
 +        if (!Err)
 +        {
 +            if (wKeyState & MK_LBUTTON)
 +                dwButtonState |= FROM_LEFT_1ST_BUTTON_PRESSED;
 +            if (wKeyState & MK_MBUTTON)
 +                dwButtonState |= FROM_LEFT_2ND_BUTTON_PRESSED;
 +            if (wKeyState & MK_RBUTTON)
 +                dwButtonState |= RIGHTMOST_BUTTON_PRESSED;
 +
 +            if (GetKeyState(VK_RMENU) & 0x8000)
 +                dwControlKeyState |= RIGHT_ALT_PRESSED;
 +            if (GetKeyState(VK_LMENU) & 0x8000)
 +                dwControlKeyState |= LEFT_ALT_PRESSED;
 +            if (GetKeyState(VK_RCONTROL) & 0x8000)
 +                dwControlKeyState |= RIGHT_CTRL_PRESSED;
 +            if (GetKeyState(VK_LCONTROL) & 0x8000)
 +                dwControlKeyState |= LEFT_CTRL_PRESSED;
 +            if (GetKeyState(VK_SHIFT) & 0x8000)
 +                dwControlKeyState |= SHIFT_PRESSED;
 +            if (GetKeyState(VK_NUMLOCK) & 0x0001)
 +                dwControlKeyState |= NUMLOCK_ON;
 +            if (GetKeyState(VK_SCROLL) & 0x0001)
 +                dwControlKeyState |= SCROLLLOCK_ON;
 +            if (GetKeyState(VK_CAPITAL) & 0x0001)
 +                dwControlKeyState |= CAPSLOCK_ON;
 +            /* See WM_CHAR MSDN documentation for instance */
 +            if (lParam & 0x01000000)
 +                dwControlKeyState |= ENHANCED_KEY;
 +
 +            er.EventType = MOUSE_EVENT;
 +            er.Event.MouseEvent.dwMousePosition   = PointToCoord(GuiData, lParam);
 +            er.Event.MouseEvent.dwButtonState     = dwButtonState;
 +            er.Event.MouseEvent.dwControlKeyState = dwControlKeyState;
 +            er.Event.MouseEvent.dwEventFlags      = dwEventFlags;
 +
 +            ConioProcessInputEvent(Console, &er);
 +        }
 +    }
 +    else
 +    {
 +        Err = TRUE;
 +    }
 +
 +    LeaveCriticalSection(&Console->Lock);
 +
 +Quit:
 +    if (Err)
 +        return DefWindowProcW(GuiData->hWindow, msg, wParam, lParam);
 +    else
 +        return 0;
 +}
 +
 +VOID
 +GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
 +                          PGUI_CONSOLE_DATA GuiData);
 +VOID
 +GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
 +                          PGUI_CONSOLE_DATA GuiData);
 +
 +static VOID
 +Copy(PGUI_CONSOLE_DATA GuiData)
 +{
 +    if (OpenClipboard(GuiData->hWindow) == TRUE)
 +    {
 +        PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
 +
 +        if (GetType(Buffer) == TEXTMODE_BUFFER)
 +        {
 +            GuiCopyFromTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer, GuiData);
 +        }
 +        else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
 +        {
 +            GuiCopyFromGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer, GuiData);
 +        }
 +
 +        CloseClipboard();
 +    }
 +
 +    /* Clear the selection */
 +    UpdateSelection(GuiData, NULL);
 +}
 +
 +VOID
 +GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
 +                         PGUI_CONSOLE_DATA GuiData);
 +VOID
 +GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
 +                         PGUI_CONSOLE_DATA GuiData);
 +
 +static VOID
 +Paste(PGUI_CONSOLE_DATA GuiData)
 +{
 +    if (OpenClipboard(GuiData->hWindow) == TRUE)
 +    {
 +        PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
 +
 +        if (GetType(Buffer) == TEXTMODE_BUFFER)
 +        {
 +            GuiPasteToTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer, GuiData);
 +        }
 +        else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
 +        {
 +            GuiPasteToGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer, GuiData);
 +        }
 +
 +        CloseClipboard();
 +    }
 +}
 +
 +static VOID
 +OnGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData, PMINMAXINFO minMaxInfo)
 +{
 +    PCONSOLE Console = GuiData->Console;
 +    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
 +    DWORD windx, windy;
 +    UINT  WidthUnit, HeightUnit;
 +
 +    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 +
 +    ActiveBuffer = GuiData->ActiveBuffer;
 +
 +    GetScreenBufferSizeUnits(ActiveBuffer, GuiData, &WidthUnit, &HeightUnit);
 +
 +    windx = CONGUI_MIN_WIDTH  * WidthUnit  + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
 +    windy = CONGUI_MIN_HEIGHT * HeightUnit + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
 +
 +    minMaxInfo->ptMinTrackSize.x = windx;
 +    minMaxInfo->ptMinTrackSize.y = windy;
 +
 +    windx = (ActiveBuffer->ScreenBufferSize.X) * WidthUnit  + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
 +    windy = (ActiveBuffer->ScreenBufferSize.Y) * HeightUnit + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
 +
 +    if (ActiveBuffer->ViewSize.X < ActiveBuffer->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL);    // window currently has a horizontal scrollbar
 +    if (ActiveBuffer->ViewSize.Y < ActiveBuffer->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL);    // window currently has a vertical scrollbar
 +
 +    minMaxInfo->ptMaxTrackSize.x = windx;
 +    minMaxInfo->ptMaxTrackSize.y = windy;
 +
 +    LeaveCriticalSection(&Console->Lock);
 +}
 +
 +static VOID
 +OnSize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam)
 +{
 +    PCONSOLE Console = GuiData->Console;
 +
 +    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 +
 +    if ((GuiData->WindowSizeLock == FALSE) &&
 +        (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED))
 +    {
 +        PCONSOLE_SCREEN_BUFFER Buff = GuiData->ActiveBuffer;
 +        DWORD windx, windy, charx, chary;
 +        UINT  WidthUnit, HeightUnit;
 +
 +        GetScreenBufferSizeUnits(Buff, GuiData, &WidthUnit, &HeightUnit);
 +
 +        GuiData->WindowSizeLock = TRUE;
 +
 +        windx = LOWORD(lParam);
 +        windy = HIWORD(lParam);
 +
 +        // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
 +        if (Buff->ViewSize.X < Buff->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL);    // window currently has a horizontal scrollbar
 +        if (Buff->ViewSize.Y < Buff->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL);    // window currently has a vertical scrollbar
 +
 +        charx = windx / (int)WidthUnit ;
 +        chary = windy / (int)HeightUnit;
 +
 +        // Character alignment (round size up or down)
 +        if ((windx % WidthUnit ) >= (WidthUnit  / 2)) ++charx;
 +        if ((windy % HeightUnit) >= (HeightUnit / 2)) ++chary;
 +
 +        // Compensate for added scroll bars in new window
 +        if (charx < Buff->ScreenBufferSize.X) windy -= GetSystemMetrics(SM_CYHSCROLL);    // new window will have a horizontal scroll bar
 +        if (chary < Buff->ScreenBufferSize.Y) windx -= GetSystemMetrics(SM_CXVSCROLL);    // new window will have a vertical scroll bar
 +
 +        charx = windx / (int)WidthUnit ;
 +        chary = windy / (int)HeightUnit;
 +
 +        // Character alignment (round size up or down)
 +        if ((windx % WidthUnit ) >= (WidthUnit  / 2)) ++charx;
 +        if ((windy % HeightUnit) >= (HeightUnit / 2)) ++chary;
 +
 +        // Resize window
 +        if ((charx != Buff->ViewSize.X) || (chary != Buff->ViewSize.Y))
 +        {
 +            Buff->ViewSize.X = (charx <= Buff->ScreenBufferSize.X) ? charx : Buff->ScreenBufferSize.X;
 +            Buff->ViewSize.Y = (chary <= Buff->ScreenBufferSize.Y) ? chary : Buff->ScreenBufferSize.Y;
 +        }
 +
 +        ResizeConWnd(GuiData, WidthUnit, HeightUnit);
 +
 +        // Adjust the start of the visible area if we are attempting to show nonexistent areas
 +        if ((Buff->ScreenBufferSize.X - Buff->ViewOrigin.X) < Buff->ViewSize.X) Buff->ViewOrigin.X = Buff->ScreenBufferSize.X - Buff->ViewSize.X;
 +        if ((Buff->ScreenBufferSize.Y - Buff->ViewOrigin.Y) < Buff->ViewSize.Y) Buff->ViewOrigin.Y = Buff->ScreenBufferSize.Y - Buff->ViewSize.Y;
 +        InvalidateRect(GuiData->hWindow, NULL, TRUE);
 +
 +        GuiData->WindowSizeLock = FALSE;
 +    }
 +
 +    LeaveCriticalSection(&Console->Lock);
 +}
 +
 +static VOID
 +OnMove(PGUI_CONSOLE_DATA GuiData)
 +{
 +    RECT rcWnd;
 +
 +    // TODO: Simplify the code.
 +    // See: GuiConsoleNotifyWndProc() PM_CREATE_CONSOLE.
 +
 +    /* Retrieve our real position */
 +    GetWindowRect(GuiData->hWindow, &rcWnd);
 +    GuiData->GuiInfo.WindowOrigin.x = rcWnd.left;
 +    GuiData->GuiInfo.WindowOrigin.y = rcWnd.top;
 +}
 +
 +/*
 +// HACK: This functionality is standard for general scrollbars. Don't add it by hand.
 +
 +VOID
 +GuiConsoleHandleScrollbarMenu(VOID)
 +{
 +    HMENU hMenu;
 +
 +    hMenu = CreatePopupMenu();
 +    if (hMenu == NULL)
 +    {
 +        DPRINT("CreatePopupMenu failed\n");
 +        return;
 +    }
 +
 +    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
 +    //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
 +    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
 +    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
 +    //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
 +    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
 +    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
 +    //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
 +    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
 +    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
 +}
 +*/
 +
 +static LRESULT
 +OnScroll(PGUI_CONSOLE_DATA GuiData, UINT uMsg, WPARAM wParam)
 +{
 +    PCONSOLE Console = GuiData->Console;
 +    PCONSOLE_SCREEN_BUFFER Buff;
 +    SCROLLINFO sInfo;
 +    int fnBar;
 +    int old_pos, Maximum;
 +    PSHORT pShowXY;
 +
 +    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return 0;
 +
 +    Buff = GuiData->ActiveBuffer;
 +
 +    if (uMsg == WM_HSCROLL)
 +    {
 +        fnBar = SB_HORZ;
 +        Maximum = Buff->ScreenBufferSize.X - Buff->ViewSize.X;
 +        pShowXY = &Buff->ViewOrigin.X;
 +    }
 +    else
 +    {
 +        fnBar = SB_VERT;
 +        Maximum = Buff->ScreenBufferSize.Y - Buff->ViewSize.Y;
 +        pShowXY = &Buff->ViewOrigin.Y;
 +    }
 +
 +    /* set scrollbar sizes */
 +    sInfo.cbSize = sizeof(SCROLLINFO);
 +    sInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS;
 +
 +    if (!GetScrollInfo(GuiData->hWindow, fnBar, &sInfo)) goto Quit;
 +
 +    old_pos = sInfo.nPos;
 +
 +    switch (LOWORD(wParam))
 +    {
 +        case SB_LINELEFT:
 +            sInfo.nPos -= 1;
 +            break;
 +
 +        case SB_LINERIGHT:
 +            sInfo.nPos += 1;
 +            break;
 +
 +        case SB_PAGELEFT:
 +            sInfo.nPos -= sInfo.nPage;
 +            break;
 +
 +        case SB_PAGERIGHT:
 +            sInfo.nPos += sInfo.nPage;
 +            break;
 +
 +        case SB_THUMBTRACK:
 +            sInfo.nPos = sInfo.nTrackPos;
 +            ConioPause(Console, PAUSED_FROM_SCROLLBAR);
 +            break;
 +
 +        case SB_THUMBPOSITION:
 +            ConioUnpause(Console, PAUSED_FROM_SCROLLBAR);
 +            break;
 +
 +        case SB_TOP:
 +            sInfo.nPos = sInfo.nMin;
 +            break;
 +
 +        case SB_BOTTOM:
 +            sInfo.nPos = sInfo.nMax;
 +            break;
 +
 +        default:
 +            break;
 +    }
 +
 +    sInfo.nPos = max(sInfo.nPos, 0);
 +    sInfo.nPos = min(sInfo.nPos, Maximum);
 +
 +    if (old_pos != sInfo.nPos)
 +    {
 +        USHORT OldX = Buff->ViewOrigin.X;
 +        USHORT OldY = Buff->ViewOrigin.Y;
 +        UINT   WidthUnit, HeightUnit;
 +
 +        *pShowXY = sInfo.nPos;
 +
 +        GetScreenBufferSizeUnits(Buff, GuiData, &WidthUnit, &HeightUnit);
 +
 +        ScrollWindowEx(GuiData->hWindow,
 +                       (OldX - Buff->ViewOrigin.X) * WidthUnit ,
 +                       (OldY - Buff->ViewOrigin.Y) * HeightUnit,
 +                       NULL,
 +                       NULL,
 +                       NULL,
 +                       NULL,
 +                       SW_INVALIDATE);
 +
 +        sInfo.fMask = SIF_POS;
 +        SetScrollInfo(GuiData->hWindow, fnBar, &sInfo, TRUE);
 +
 +        UpdateWindow(GuiData->hWindow);
 +        // InvalidateRect(GuiData->hWindow, NULL, FALSE);
 +    }
 +
 +Quit:
 +    LeaveCriticalSection(&Console->Lock);
 +    return 0;
 +}
 +
 +
 +static LRESULT CALLBACK
 +ConWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 +{
 +    LRESULT Result = 0;
 +    PGUI_CONSOLE_DATA GuiData = NULL;
 +    PCONSOLE Console = NULL;
 +
 +    /*
 +     * - If it's the first time we create a window for the terminal,
 +     *   just initialize it and return.
 +     *
 +     * - If we are destroying the window, just do it and return.
 +     */
 +    if (msg == WM_NCCREATE)
 +    {
 +        return (LRESULT)OnNcCreate(hWnd, (LPCREATESTRUCTW)lParam);
 +    }
 +    else if (msg == WM_NCDESTROY)
 +    {
 +        return OnNcDestroy(hWnd);
 +    }
 +
 +    /*
 +     * Now the terminal window is initialized.
 +     * Get the terminal data via the window's data.
 +     * If there is no data, just go away.
 +     */
 +    GuiData = GuiGetGuiData(hWnd);
 +    if (GuiData == NULL) return DefWindowProcW(hWnd, msg, wParam, lParam);
 +
 +    // TEMPORARY HACK until all of the functions can deal with a NULL GuiData->ActiveBuffer ...
 +    if (GuiData->ActiveBuffer == NULL) return DefWindowProcW(hWnd, msg, wParam, lParam);
 +
 +    /*
 +     * Just retrieve a pointer to the console in case somebody needs it.
 +     * It is not NULL because it was checked in GuiGetGuiData.
 +     * Each helper function which needs the console has to validate and lock it.
 +     */
 +    Console = GuiData->Console;
 +
 +    /* We have a console, start message dispatching */
 +    switch (msg)
 +    {
 +        case WM_ACTIVATE:
 +            OnActivate(GuiData, wParam);
 +            break;
 +
 +        case WM_CLOSE:
 +            if (OnClose(GuiData)) goto Default;
 +            break;
 +
 +        case WM_PAINT:
 +            OnPaint(GuiData);
 +            break;
 +
 +        case WM_TIMER:
 +            OnTimer(GuiData);
 +            break;
 +
 +        case WM_PALETTECHANGED:
 +        {
 +            DPRINT("WM_PALETTECHANGED called\n");
 +
 +            /*
 +             * Protects against infinite loops:
 +             * "... A window that receives this message must not realize
 +             * its palette, unless it determines that wParam does not contain
 +             * its own window handle." (WM_PALETTECHANGED description - MSDN)
 +             *
 +             * This message is sent to all windows, including the one that
 +             * changed the system palette and caused this message to be sent.
 +             * The wParam of this message contains the handle of the window
 +             * that caused the system palette to change. To avoid an infinite
 +             * loop, care must be taken to check that the wParam of this message
 +             * does not match the window's handle.
 +             */
 +            if ((HWND)wParam == hWnd) break;
 +
 +            DPRINT("WM_PALETTECHANGED ok\n");
 +            OnPaletteChanged(GuiData);
 +            DPRINT("WM_PALETTECHANGED quit\n");
 +            break;
 +        }
 +
 +        case WM_KEYDOWN:
 +        case WM_KEYUP:
 +        case WM_CHAR:
 +        case WM_DEADCHAR:
 +        case WM_SYSKEYDOWN:
 +        case WM_SYSKEYUP:
 +        case WM_SYSCHAR:
 +        case WM_SYSDEADCHAR:
 +        {
 +            /* Detect Alt-Enter presses and switch back and forth to fullscreen mode */
 +            if (msg == WM_SYSKEYDOWN && (HIWORD(lParam) & KF_ALTDOWN) && wParam == VK_RETURN)
 +            {
 +                /* Switch only at first Alt-Enter press, and ignore subsequent key repetitions */
 +                if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) != KF_REPEAT)
 +                    GuiConsoleSwitchFullScreen(GuiData);
 +
 +                break;
 +            }
++            /* Detect Alt-Esc/Space/Tab presses defer to DefWindowProc */
++            if ( (HIWORD(lParam) & KF_ALTDOWN) && (wParam == VK_ESCAPE || wParam == VK_SPACE || wParam == VK_TAB))
++            {
++               return DefWindowProcW(hWnd, msg, wParam, lParam);
++            }
 +
 +            OnKey(GuiData, msg, wParam, lParam);
 +            break;
 +        }
 +
 +        case WM_SETCURSOR:
 +        {
 +            /*
 +             * The message was sent because we are manually triggering a change.
 +             * Check whether the mouse is indeed present on this console window
 +             * and take appropriate decisions.
 +             */
 +            if (wParam == -1 && lParam == -1)
 +            {
 +                POINT mouseCoords;
 +                HWND  hWndHit;
 +
 +                /* Get the placement of the mouse */
 +                GetCursorPos(&mouseCoords);
 +
 +                /* On which window is placed the mouse ? */
 +                hWndHit = WindowFromPoint(mouseCoords);
 +
 +                /* It's our window. Perform the hit-test to be used later on. */
 +                if (hWndHit == hWnd)
 +                {
 +                    wParam = (WPARAM)hWnd;
 +                    lParam = DefWindowProcW(hWndHit, WM_NCHITTEST, 0,
 +                                            MAKELPARAM(mouseCoords.x, mouseCoords.y));
 +                }
 +            }
 +
 +            /* Set the mouse cursor only when we are in the client area */
 +            if ((HWND)wParam == hWnd && LOWORD(lParam) == HTCLIENT)
 +            {
 +                if (GuiData->MouseCursorRefCount >= 0)
 +                {
 +                    /* Show the cursor */
 +                    SetCursor(GuiData->hCursor);
 +                }
 +                else
 +                {
 +                    /* Hide the cursor if the reference count is negative */
 +                    SetCursor(NULL);
 +                }
 +                return TRUE;
 +            }
 +            else
 +            {
 +                goto Default;
 +            }
 +        }
 +
 +        case WM_LBUTTONDOWN:
 +        case WM_MBUTTONDOWN:
 +        case WM_RBUTTONDOWN:
 +        case WM_LBUTTONUP:
 +        case WM_MBUTTONUP:
 +        case WM_RBUTTONUP:
 +        case WM_LBUTTONDBLCLK:
 +        case WM_MBUTTONDBLCLK:
 +        case WM_RBUTTONDBLCLK:
 +        case WM_MOUSEMOVE:
 +        case WM_MOUSEWHEEL:
 +        case WM_MOUSEHWHEEL:
 +        {
 +            Result = OnMouse(GuiData, msg, wParam, lParam);
 +            break;
 +        }
 +
 +        case WM_HSCROLL:
 +        case WM_VSCROLL:
 +        {
 +            Result = OnScroll(GuiData, msg, wParam);
 +            break;
 +        }
 +
 +        case WM_CONTEXTMENU:
 +        {
 +            if (DefWindowProcW(hWnd /*GuiData->hWindow*/, WM_NCHITTEST, 0, lParam) == HTCLIENT)
 +            {
 +                HMENU hMenu = CreatePopupMenu();
 +                if (hMenu != NULL)
 +                {
 +                    AppendMenuItems(hMenu, GuiConsoleEditMenuItems);
 +                    TrackPopupMenuEx(hMenu,
 +                                     TPM_RIGHTBUTTON,
 +                                     GET_X_LPARAM(lParam),
 +                                     GET_Y_LPARAM(lParam),
 +                                     hWnd,
 +                                     NULL);
 +                    DestroyMenu(hMenu);
 +                }
 +                break;
 +            }
 +            else
 +            {
 +                goto Default;
 +            }
 +        }
 +
 +        case WM_INITMENU:
 +        {
 +            HMENU hMenu = (HMENU)wParam;
 +            if (hMenu != NULL)
 +            {
 +                /* Enable or disable the Close menu item */
 +                EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND |
 +                               (GuiData->IsCloseButtonEnabled ? MF_ENABLED : MF_GRAYED));
 +
 +                /* Enable or disable the Copy and Paste items */
 +                EnableMenuItem(hMenu, ID_SYSTEM_EDIT_COPY , MF_BYCOMMAND |
 +                               ((GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
 +                                (GuiData->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) ? MF_ENABLED : MF_GRAYED));
 +                // FIXME: Following whether the active screen buffer is text-mode
 +                // or graphics-mode, search for CF_UNICODETEXT or CF_BITMAP formats.
 +                EnableMenuItem(hMenu, ID_SYSTEM_EDIT_PASTE, MF_BYCOMMAND |
 +                               (!(GuiData->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
 +                                IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED));
 +            }
 +
 +            SendMenuEvent(Console, WM_INITMENU);
 +            break;
 +        }
 +
 +        case WM_MENUSELECT:
 +        {
 +            if (HIWORD(wParam) == 0xFFFF) // Allow all the menu flags
 +            {
 +                SendMenuEvent(Console, WM_MENUSELECT);
 +            }
 +            break;
 +        }
 +
 +        case WM_COMMAND:
 +        case WM_SYSCOMMAND:
 +        {
 +            Result = OnCommand(GuiData, wParam, lParam);
 +            break;
 +        }
 +
 +        case WM_SETFOCUS:
 +        case WM_KILLFOCUS:
 +            OnFocus(GuiData, (msg == WM_SETFOCUS));
 +            break;
 +
 +        case WM_GETMINMAXINFO:
 +            OnGetMinMaxInfo(GuiData, (PMINMAXINFO)lParam);
 +            break;
 +
 +        case WM_MOVE:
 +            OnMove(GuiData);
 +            break;
 +
 +#if 0 // This code is here to prepare & control dynamic console SB resizing.
 +        case WM_SIZING:
 +        {
 +            PRECT dragRect = (PRECT)lParam;
 +            switch (wParam)
 +            {
 +                case WMSZ_LEFT:
 +                    DPRINT1("WMSZ_LEFT\n");
 +                    break;
 +                case WMSZ_RIGHT:
 +                    DPRINT1("WMSZ_RIGHT\n");
 +                    break;
 +                case WMSZ_TOP:
 +                    DPRINT1("WMSZ_TOP\n");
 +                    break;
 +                case WMSZ_TOPLEFT:
 +                    DPRINT1("WMSZ_TOPLEFT\n");
 +                    break;
 +                case WMSZ_TOPRIGHT:
 +                    DPRINT1("WMSZ_TOPRIGHT\n");
 +                    break;
 +                case WMSZ_BOTTOM:
 +                    DPRINT1("WMSZ_BOTTOM\n");
 +                    break;
 +                case WMSZ_BOTTOMLEFT:
 +                    DPRINT1("WMSZ_BOTTOMLEFT\n");
 +                    break;
 +                case WMSZ_BOTTOMRIGHT:
 +                    DPRINT1("WMSZ_BOTTOMRIGHT\n");
 +                    break;
 +                default:
 +                    DPRINT1("wParam = %d\n", wParam);
 +                    break;
 +            }
 +            DPRINT1("dragRect = {.left = %d ; .top = %d ; .right = %d ; .bottom = %d}\n",
 +                    dragRect->left, dragRect->top, dragRect->right, dragRect->bottom);
 +            break;
 +        }
 +#endif
 +
 +        case WM_SIZE:
 +            OnSize(GuiData, wParam, lParam);
 +            break;
 +
 +        case PM_RESIZE_TERMINAL:
 +        {
 +            PCONSOLE_SCREEN_BUFFER Buff = GuiData->ActiveBuffer;
 +            HDC hDC;
 +            HBITMAP hnew, hold;
 +
 +            DWORD Width, Height;
 +            UINT  WidthUnit, HeightUnit;
 +
 +            GetScreenBufferSizeUnits(Buff, GuiData, &WidthUnit, &HeightUnit);
 +
 +            Width  = Buff->ScreenBufferSize.X * WidthUnit ;
 +            Height = Buff->ScreenBufferSize.Y * HeightUnit;
 +
 +            /* Recreate the framebuffer */
 +            hDC  = GetDC(GuiData->hWindow);
 +            hnew = CreateCompatibleBitmap(hDC, Width, Height);
 +            ReleaseDC(GuiData->hWindow, hDC);
 +            hold = SelectObject(GuiData->hMemDC, hnew);
 +            if (GuiData->hBitmap)
 +            {
 +                if (hold == GuiData->hBitmap) DeleteObject(GuiData->hBitmap);
 +            }
 +            GuiData->hBitmap = hnew;
 +
 +            /* Resize the window to the user's values */
 +            GuiData->WindowSizeLock = TRUE;
 +            ResizeConWnd(GuiData, WidthUnit, HeightUnit);
 +            GuiData->WindowSizeLock = FALSE;
 +            break;
 +        }
 +
 +        case PM_APPLY_CONSOLE_INFO:
 +        {
 +            GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam);
 +            break;
 +        }
 +
 +        case PM_CONSOLE_BEEP:
 +            DPRINT1("Beep !!\n");
 +            Beep(800, 200);
 +            break;
 +
 +        // case PM_CONSOLE_SET_TITLE:
 +            // SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
 +            // break;
 +
 +        default: Default:
 +            Result = DefWindowProcW(hWnd, msg, wParam, lParam);
 +            break;
 +    }
 +
 +    return Result;
 +}
 +
 +/* EOF */
index 30a394a,0000000..1863497
mode 100644,000000..100644
--- /dev/null
@@@ -1,1281 -1,0 +1,1282 @@@
-         DefWindowProcW(msg->hwnd, msg->message, msg->wParam, msg->lParam);
-         return TRUE;
 +/*
 + * COPYRIGHT:       See COPYING in the top level directory
 + * PROJECT:         ReactOS Console Server DLL
 + * FILE:            win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
 + * PURPOSE:         GUI Terminal Front-End
 + * PROGRAMMERS:     Gé van Geldorp
 + *                  Johannes Anderwald
 + *                  Jeffrey Morlan
 + *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
 + */
 +
 +/* INCLUDES *******************************************************************/
 +
 +#include <consrv.h>
 +
 +#define COBJMACROS
 +#include <shlobj.h>
 +
 +#define NDEBUG
 +#include <debug.h>
 +
 +#include "guiterm.h"
 +#include "resource.h"
 +
 +// HACK!! Remove it when the hack in GuiWriteStream is fixed
 +#define CONGUI_UPDATE_TIME    0
 +#define CONGUI_UPDATE_TIMER   1
 +
 +#define PM_CREATE_CONSOLE       (WM_APP + 1)
 +#define PM_DESTROY_CONSOLE      (WM_APP + 2)
 +
 +
 +/* Not defined in any header file */
 +extern VOID NTAPI PrivateCsrssManualGuiCheck(LONG Check);
 +// See winsrv/usersrv/init.c line 234
 +
 +
 +/* GLOBALS ********************************************************************/
 +
 +typedef struct _GUI_INIT_INFO
 +{
 +    PCONSOLE_INFO ConsoleInfo;
 +    PCONSOLE_START_INFO ConsoleStartInfo;
 +    ULONG ProcessId;
 +} GUI_INIT_INFO, *PGUI_INIT_INFO;
 +
 +static BOOL    ConsInitialized = FALSE;
 +static HWND    NotifyWnd = NULL;
 +
 +extern HICON   ghDefaultIcon;
 +extern HICON   ghDefaultIconSm;
 +extern HCURSOR ghDefaultCursor;
 +
 +VOID
 +SetConWndConsoleLeaderCID(IN PGUI_CONSOLE_DATA GuiData);
 +BOOLEAN
 +RegisterConWndClass(IN HINSTANCE hInstance);
 +BOOLEAN
 +UnRegisterConWndClass(HINSTANCE hInstance);
 +
 +/* FUNCTIONS ******************************************************************/
 +
 +static VOID
 +GetScreenBufferSizeUnits(IN PCONSOLE_SCREEN_BUFFER Buffer,
 +                         IN PGUI_CONSOLE_DATA GuiData,
 +                         OUT PUINT WidthUnit,
 +                         OUT PUINT HeightUnit)
 +{
 +    if (Buffer == NULL || GuiData == NULL ||
 +        WidthUnit == NULL || HeightUnit == NULL)
 +    {
 +        return;
 +    }
 +
 +    if (GetType(Buffer) == TEXTMODE_BUFFER)
 +    {
 +        *WidthUnit  = GuiData->CharWidth ;
 +        *HeightUnit = GuiData->CharHeight;
 +    }
 +    else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
 +    {
 +        *WidthUnit  = 1;
 +        *HeightUnit = 1;
 +    }
 +}
 +
 +VOID
 +GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData)
 +{
 +    /* Move the window if needed (not positioned by the system) */
 +    if (!GuiData->GuiInfo.AutoPosition)
 +    {
 +        SetWindowPos(GuiData->hWindow,
 +                     NULL,
 +                     GuiData->GuiInfo.WindowOrigin.x,
 +                     GuiData->GuiInfo.WindowOrigin.y,
 +                     0, 0,
 +                     SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
 +    }
 +}
 +
 +static VOID
 +SmallRectToRect(PGUI_CONSOLE_DATA GuiData, PRECT Rect, PSMALL_RECT SmallRect)
 +{
 +    PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
 +    UINT WidthUnit, HeightUnit;
 +
 +    GetScreenBufferSizeUnits(Buffer, GuiData, &WidthUnit, &HeightUnit);
 +
 +    Rect->left   = (SmallRect->Left       - Buffer->ViewOrigin.X) * WidthUnit ;
 +    Rect->top    = (SmallRect->Top        - Buffer->ViewOrigin.Y) * HeightUnit;
 +    Rect->right  = (SmallRect->Right  + 1 - Buffer->ViewOrigin.X) * WidthUnit ;
 +    Rect->bottom = (SmallRect->Bottom + 1 - Buffer->ViewOrigin.Y) * HeightUnit;
 +}
 +
 +static VOID
 +DrawRegion(PGUI_CONSOLE_DATA GuiData,
 +           SMALL_RECT* Region)
 +{
 +    RECT RegionRect;
 +
 +    SmallRectToRect(GuiData, &RegionRect, Region);
 +    /* Do not erase the background: it speeds up redrawing and reduce flickering */
 +    InvalidateRect(GuiData->hWindow, &RegionRect, FALSE);
 +    /**UpdateWindow(GuiData->hWindow);**/
 +}
 +
 +VOID
 +InvalidateCell(PGUI_CONSOLE_DATA GuiData,
 +               SHORT x, SHORT y)
 +{
 +    SMALL_RECT CellRect = { x, y, x, y };
 +    DrawRegion(GuiData, &CellRect);
 +}
 +
 +
 +/******************************************************************************
 + *                        GUI Terminal Initialization                         *
 + ******************************************************************************/
 +
 +VOID
 +SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen);
 +
 +static LRESULT CALLBACK
 +GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 +{
 +    HWND NewWindow;
 +    LONG WindowCount;
 +    MSG Msg;
 +
 +    switch (msg)
 +    {
 +        case WM_CREATE:
 +        {
 +            SetWindowLongW(hWnd, GWL_USERDATA, 0);
 +            return 0;
 +        }
 +    
 +        case PM_CREATE_CONSOLE:
 +        {
 +            PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam;
 +            PCONSOLE Console = GuiData->Console;
 +            RECT rcWnd;
 +
 +            DPRINT("PM_CREATE_CONSOLE -- creating window\n");
 +
 +            NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE,
 +                                        GUI_CONWND_CLASS,
 +                                        Console->Title.Buffer,
 +                                        WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
 +                                        CW_USEDEFAULT,
 +                                        CW_USEDEFAULT,
 +                                        CW_USEDEFAULT,
 +                                        CW_USEDEFAULT,
 +                                        NULL,
 +                                        NULL,
 +                                        ConSrvDllInstance,
 +                                        (PVOID)GuiData);
 +            if (NULL != NewWindow)
 +            {
 +                ASSERT(NewWindow == GuiData->hWindow);
 +
 +                WindowCount = GetWindowLongW(hWnd, GWL_USERDATA);
 +                WindowCount++;
 +                SetWindowLongW(hWnd, GWL_USERDATA, WindowCount);
 +
 +                //
 +                // FIXME: TODO: Move everything there into conwnd.c!OnNcCreate()
 +                //
 +
 +                /* Retrieve our real position */
 +                // See conwnd.c!OnMove()
 +                GetWindowRect(GuiData->hWindow, &rcWnd);
 +                GuiData->GuiInfo.WindowOrigin.x = rcWnd.left;
 +                GuiData->GuiInfo.WindowOrigin.y = rcWnd.top;
 +
 +                /* Move and resize the window to the user's values */
 +                /* CAN WE DEADLOCK ?? */
 +                GuiConsoleMoveWindow(GuiData); // FIXME: This MUST be done via the CreateWindowExW call.
 +                SendMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
 +
 +                /* Switch to full-screen mode if necessary */
 +                // FIXME: Move elsewhere, it cause misdrawings of the window.
 +                if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE);
 +
 +                DPRINT("PM_CREATE_CONSOLE -- showing window\n");
 +                // ShowWindow(NewWindow, (int)wParam);
 +                ShowWindowAsync(NewWindow, (int)wParam);
 +                DPRINT("Window showed\n");
 +            }
 +
 +            return (LRESULT)NewWindow;
 +        }
 +
 +        case PM_DESTROY_CONSOLE:
 +        {
 +            PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam;
 +
 +            /* Exit the full screen mode if it was already set */
 +            // LeaveFullScreen(GuiData);
 +
 +            /*
 +             * Window creation is done using a PostMessage(), so it's possible
 +             * that the window that we want to destroy doesn't exist yet.
 +             * So first empty the message queue.
 +             */
 +            /*
 +            while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE))
 +            {
 +                TranslateMessage(&Msg);
 +                DispatchMessageW(&Msg);
 +            }*/
 +            while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) ;
 +
 +            if (GuiData->hWindow != NULL) /* && DestroyWindow(GuiData->hWindow) */
 +            {
 +                DestroyWindow(GuiData->hWindow);
 +
 +                WindowCount = GetWindowLongW(hWnd, GWL_USERDATA);
 +                WindowCount--;
 +                SetWindowLongW(hWnd, GWL_USERDATA, WindowCount);
 +                if (0 == WindowCount)
 +                {
 +                    NotifyWnd = NULL;
 +                    DestroyWindow(hWnd);
 +                    DPRINT("CONSRV: Going to quit the Gui Thread!!\n");
 +                    PostQuitMessage(0);
 +                }
 +            }
 +
 +            return 0;
 +        }
 +
 +        default:
 +            return DefWindowProcW(hWnd, msg, wParam, lParam);
 +    }
 +}
 +
 +static DWORD NTAPI
 +GuiConsoleGuiThread(PVOID Data)
 +{
 +    MSG msg;
 +    PHANDLE GraphicsStartupEvent = (PHANDLE)Data;
 +
 +    /*
 +     * This thread dispatches all the console notifications to the notify window.
 +     * It is common for all the console windows.
 +     */
 +
 +    PrivateCsrssManualGuiCheck(+1);
 +
 +    NotifyWnd = CreateWindowW(L"ConSrvCreateNotify",
 +                              L"",
 +                              WS_OVERLAPPEDWINDOW,
 +                              CW_USEDEFAULT,
 +                              CW_USEDEFAULT,
 +                              CW_USEDEFAULT,
 +                              CW_USEDEFAULT,
 +                              NULL,
 +                              NULL,
 +                              ConSrvDllInstance,
 +                              NULL);
 +    if (NULL == NotifyWnd)
 +    {
 +        PrivateCsrssManualGuiCheck(-1);
 +        SetEvent(*GraphicsStartupEvent);
 +        return 1;
 +    }
 +
 +    SetEvent(*GraphicsStartupEvent);
 +
 +    while (GetMessageW(&msg, NULL, 0, 0))
 +    {
 +        TranslateMessage(&msg);
 +        DispatchMessageW(&msg);
 +    }
 +
 +    DPRINT("CONSRV: Quit the Gui Thread!!\n");
 +    PrivateCsrssManualGuiCheck(-1);
 +
 +    return 1;
 +}
 +
 +static BOOL
 +GuiInit(VOID)
 +{
 +    WNDCLASSEXW wc;
 +
 +    /* Exit if we were already initialized */
 +    // if (ConsInitialized) return TRUE;
 +
 +    /*
 +     * Initialize and register the different window classes, if needed.
 +     */
 +    if (!ConsInitialized)
 +    {
 +        /* Initialize the notification window class */
 +        wc.cbSize = sizeof(WNDCLASSEXW);
 +        wc.lpszClassName = L"ConSrvCreateNotify";
 +        wc.lpfnWndProc = GuiConsoleNotifyWndProc;
 +        wc.style = 0;
 +        wc.hInstance = ConSrvDllInstance;
 +        wc.hIcon = NULL;
 +        wc.hIconSm = NULL;
 +        wc.hCursor = NULL;
 +        wc.hbrBackground = NULL;
 +        wc.lpszMenuName = NULL;
 +        wc.cbClsExtra = 0;
 +        wc.cbWndExtra = 0;
 +        if (RegisterClassExW(&wc) == 0)
 +        {
 +            DPRINT1("Failed to register GUI notify wndproc\n");
 +            return FALSE;
 +        }
 +
 +        /* Initialize the console window class */
 +        if (!RegisterConWndClass(ConSrvDllInstance))
 +            return FALSE;
 +
 +        ConsInitialized = TRUE;
 +    }
 +
 +    /*
 +     * Set-up the notification window
 +     */
 +    if (NULL == NotifyWnd)
 +    {
 +        HANDLE ThreadHandle;
 +        HANDLE GraphicsStartupEvent;
 +
 +        GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
 +        if (NULL == GraphicsStartupEvent) return FALSE;
 +
 +        ThreadHandle = CreateThread(NULL,
 +                                    0,
 +                                    GuiConsoleGuiThread,
 +                                    (PVOID)&GraphicsStartupEvent,
 +                                    0,
 +                                    NULL);
 +        if (NULL == ThreadHandle)
 +        {
 +            CloseHandle(GraphicsStartupEvent);
 +            DPRINT1("CONSRV: Failed to create graphics console thread. Expect problems\n");
 +            return FALSE;
 +        }
 +        SetThreadPriority(ThreadHandle, THREAD_PRIORITY_HIGHEST);
 +        CloseHandle(ThreadHandle);
 +
 +        WaitForSingleObject(GraphicsStartupEvent, INFINITE);
 +        CloseHandle(GraphicsStartupEvent);
 +
 +        if (NULL == NotifyWnd)
 +        {
 +            DPRINT1("CONSRV: Failed to create notification window.\n");
 +            return FALSE;
 +        }
 +    }
 +
 +    // ConsInitialized = TRUE;
 +
 +    return TRUE;
 +}
 +
 +
 +
 +/******************************************************************************
 + *                             GUI Console Driver                             *
 + ******************************************************************************/
 +
 +static VOID NTAPI
 +GuiDeinitFrontEnd(IN OUT PFRONTEND This);
 +
 +NTSTATUS NTAPI
 +GuiInitFrontEnd(IN OUT PFRONTEND This,
 +                IN PCONSOLE Console)
 +{
 +    PGUI_INIT_INFO GuiInitInfo;
 +    PCONSOLE_INFO  ConsoleInfo;
 +    PCONSOLE_START_INFO ConsoleStartInfo;
 +
 +    PGUI_CONSOLE_DATA GuiData;
 +    GUI_CONSOLE_INFO  TermInfo;
 +
 +    SIZE_T Length    = 0;
 +    LPWSTR IconPath  = NULL;
 +    INT    IconIndex = 0;
 +
 +    if (This == NULL || Console == NULL || This->OldData == NULL)
 +        return STATUS_INVALID_PARAMETER;
 +
 +    ASSERT(This->Console == Console);
 +
 +    GuiInitInfo = This->OldData;
 +
 +    if (GuiInitInfo->ConsoleInfo == NULL || GuiInitInfo->ConsoleStartInfo == NULL)
 +        return STATUS_INVALID_PARAMETER;
 +
 +    ConsoleInfo      = GuiInitInfo->ConsoleInfo;
 +    ConsoleStartInfo = GuiInitInfo->ConsoleStartInfo;
 +
 +    IconPath  = ConsoleStartInfo->IconPath;
 +    IconIndex = ConsoleStartInfo->IconIndex;
 +
 +
 +    /* Terminal data allocation */
 +    GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
 +    if (!GuiData)
 +    {
 +        DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
 +        return STATUS_UNSUCCESSFUL;
 +    }
 +    ///// /* HACK */ Console->FrontEndIFace.Data = (PVOID)GuiData; /* HACK */
 +    GuiData->Console      = Console;
 +    GuiData->ActiveBuffer = Console->ActiveBuffer;
 +    GuiData->hWindow = NULL;
 +
 +    /* The console can be resized */
 +    Console->FixedSize = FALSE;
 +
 +    InitializeCriticalSection(&GuiData->Lock);
 +
 +
 +    /*
 +     * Load terminal settings
 +     */
 +
 +    /* 1. Load the default settings */
 +    GuiConsoleGetDefaultSettings(&TermInfo, GuiInitInfo->ProcessId);
 +
 +    /* 3. Load the remaining console settings via the registry. */
 +    if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
 +    {
 +        /* Load the terminal infos from the registry. */
 +        GuiConsoleReadUserSettings(&TermInfo,
 +                                   ConsoleInfo->ConsoleTitle,
 +                                   GuiInitInfo->ProcessId);
 +
 +        /*
 +         * Now, update them with the properties the user might gave to us
 +         * via the STARTUPINFO structure before calling CreateProcess
 +         * (and which was transmitted via the ConsoleStartInfo structure).
 +         * We therefore overwrite the values read in the registry.
 +         */
 +        if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW)
 +        {
 +            TermInfo.ShowWindow = ConsoleStartInfo->wShowWindow;
 +        }
 +        if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
 +        {
 +            TermInfo.AutoPosition = FALSE;
 +            TermInfo.WindowOrigin.x = ConsoleStartInfo->dwWindowOrigin.X;
 +            TermInfo.WindowOrigin.y = ConsoleStartInfo->dwWindowOrigin.Y;
 +        }
 +        if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
 +        {
 +            TermInfo.FullScreen = TRUE;
 +        }
 +    }
 +
 +
 +    /*
 +     * Set up GUI data
 +     */
 +
 +    Length = min(wcslen(TermInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen
 +    wcsncpy(GuiData->GuiInfo.FaceName, TermInfo.FaceName, LF_FACESIZE);
 +    GuiData->GuiInfo.FaceName[Length] = L'\0';
 +    GuiData->GuiInfo.FontFamily     = TermInfo.FontFamily;
 +    GuiData->GuiInfo.FontSize       = TermInfo.FontSize;
 +    GuiData->GuiInfo.FontWeight     = TermInfo.FontWeight;
 +    GuiData->GuiInfo.UseRasterFonts = TermInfo.UseRasterFonts;
 +    GuiData->GuiInfo.FullScreen     = TermInfo.FullScreen;
 +    GuiData->GuiInfo.ShowWindow     = TermInfo.ShowWindow;
 +    GuiData->GuiInfo.AutoPosition   = TermInfo.AutoPosition;
 +    GuiData->GuiInfo.WindowOrigin   = TermInfo.WindowOrigin;
 +
 +    /* Initialize the icon handles to their default values */
 +    GuiData->hIcon   = ghDefaultIcon;
 +    GuiData->hIconSm = ghDefaultIconSm;
 +
 +    /* Get the associated icon, if any */
 +    if (IconPath == NULL || IconPath[0] == L'\0')
 +    {
 +        IconPath  = ConsoleStartInfo->AppPath;
 +        IconIndex = 0;
 +    }
 +    DPRINT("IconPath = %S ; IconIndex = %lu\n", (IconPath ? IconPath : L"n/a"), IconIndex);
 +    if (IconPath && IconPath[0] != L'\0')
 +    {
 +        HICON hIcon = NULL, hIconSm = NULL;
 +        PrivateExtractIconExW(IconPath,
 +                              IconIndex,
 +                              &hIcon,
 +                              &hIconSm,
 +                              1);
 +        DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm);
 +        if (hIcon   != NULL) GuiData->hIcon   = hIcon;
 +        if (hIconSm != NULL) GuiData->hIconSm = hIconSm;
 +    }
 +    ASSERT(GuiData->hIcon && GuiData->hIconSm);
 +
 +    /* Mouse is shown by default with its default cursor shape */
 +    GuiData->hCursor = ghDefaultCursor;
 +    GuiData->MouseCursorRefCount = 0;
 +
 +    /* A priori don't ignore mouse signals */
 +    GuiData->IgnoreNextMouseSignal = FALSE;
 +
 +    /* Close button and the corresponding system menu item are enabled by default */
 +    GuiData->IsCloseButtonEnabled = TRUE;
 +
 +    /* There is no user-reserved menu id range by default */
 +    GuiData->CmdIdLow = GuiData->CmdIdHigh = 0;
 +
 +    /* Initialize the selection */
 +    RtlZeroMemory(&GuiData->Selection, sizeof(CONSOLE_SELECTION_INFO));
 +    GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
 +
 +    /*
 +     * We need to wait until the GUI has been fully initialized
 +     * to retrieve custom settings i.e. WindowSize etc...
 +     * Ideally we could use SendNotifyMessage for this but its not
 +     * yet implemented.
 +     */
 +    GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
 +
 +    DPRINT("GUI - Checkpoint\n");
 +
 +    /* Create the terminal window */
 +    PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, GuiData->GuiInfo.ShowWindow, (LPARAM)GuiData);
 +
 +    /* Wait until initialization has finished */
 +    WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
 +    DPRINT("OK we created the console window\n");
 +    CloseHandle(GuiData->hGuiInitEvent);
 +    GuiData->hGuiInitEvent = NULL;
 +
 +    /* Check whether we really succeeded in initializing the terminal window */
 +    if (GuiData->hWindow == NULL)
 +    {
 +        DPRINT("GuiInitConsole - We failed at creating a new terminal window\n");
 +        GuiDeinitFrontEnd(This);
 +        return STATUS_UNSUCCESSFUL;
 +    }
 +
 +    /* Finally, finish to initialize the frontend structure */
 +    This->Data = GuiData;
 +    if (This->OldData) ConsoleFreeHeap(This->OldData);
 +    This->OldData = NULL;
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +static VOID NTAPI
 +GuiDeinitFrontEnd(IN OUT PFRONTEND This)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
 +
 +    DPRINT("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n",
 +            GuiData->hIcon, ghDefaultIcon, GuiData->hIconSm, ghDefaultIconSm);
 +    if (GuiData->hIcon != NULL && GuiData->hIcon != ghDefaultIcon)
 +    {
 +        DPRINT("Destroy hIcon\n");
 +        DestroyIcon(GuiData->hIcon);
 +    }
 +    if (GuiData->hIconSm != NULL && GuiData->hIconSm != ghDefaultIconSm)
 +    {
 +        DPRINT("Destroy hIconSm\n");
 +        DestroyIcon(GuiData->hIconSm);
 +    }
 +
 +    This->Data = NULL;
 +    DeleteCriticalSection(&GuiData->Lock);
 +    ConsoleFreeHeap(GuiData);
 +
 +    DPRINT("Quit GuiDeinitFrontEnd\n");
 +}
 +
 +static VOID NTAPI
 +GuiDrawRegion(IN OUT PFRONTEND This,
 +              SMALL_RECT* Region)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    DrawRegion(GuiData, Region);
 +}
 +
 +static VOID NTAPI
 +GuiWriteStream(IN OUT PFRONTEND This,
 +               SMALL_RECT* Region,
 +               SHORT CursorStartX,
 +               SHORT CursorStartY,
 +               UINT ScrolledLines,
 +               PWCHAR Buffer,
 +               UINT Length)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    PCONSOLE_SCREEN_BUFFER Buff;
 +    SHORT CursorEndX, CursorEndY;
 +    RECT ScrollRect;
 +
 +    if (NULL == GuiData || NULL == GuiData->hWindow) return;
 +
 +    Buff = GuiData->ActiveBuffer;
 +    if (GetType(Buff) != TEXTMODE_BUFFER) return;
 +
 +    if (0 != ScrolledLines)
 +    {
 +        ScrollRect.left = 0;
 +        ScrollRect.top = 0;
 +        ScrollRect.right = Buff->ViewSize.X * GuiData->CharWidth;
 +        ScrollRect.bottom = Region->Top * GuiData->CharHeight;
 +
 +        ScrollWindowEx(GuiData->hWindow,
 +                       0,
 +                       -(int)(ScrolledLines * GuiData->CharHeight),
 +                       &ScrollRect,
 +                       NULL,
 +                       NULL,
 +                       NULL,
 +                       SW_INVALIDATE);
 +    }
 +
 +    DrawRegion(GuiData, Region);
 +
 +    if (CursorStartX < Region->Left || Region->Right < CursorStartX
 +            || CursorStartY < Region->Top || Region->Bottom < CursorStartY)
 +    {
 +        InvalidateCell(GuiData, CursorStartX, CursorStartY);
 +    }
 +
 +    CursorEndX = Buff->CursorPosition.X;
 +    CursorEndY = Buff->CursorPosition.Y;
 +    if ((CursorEndX < Region->Left || Region->Right < CursorEndX
 +            || CursorEndY < Region->Top || Region->Bottom < CursorEndY)
 +            && (CursorEndX != CursorStartX || CursorEndY != CursorStartY))
 +    {
 +        InvalidateCell(GuiData, CursorEndX, CursorEndY);
 +    }
 +
 +    // HACK!!
 +    // Set up the update timer (very short interval) - this is a "hack" for getting the OS to
 +    // repaint the window without having it just freeze up and stay on the screen permanently.
 +    Buff->CursorBlinkOn = TRUE;
 +    SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL);
 +}
 +
 +static BOOL NTAPI
 +GuiSetCursorInfo(IN OUT PFRONTEND This,
 +                 PCONSOLE_SCREEN_BUFFER Buff)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    if (GuiData->ActiveBuffer == Buff)
 +    {
 +        InvalidateCell(GuiData, Buff->CursorPosition.X, Buff->CursorPosition.Y);
 +    }
 +
 +    return TRUE;
 +}
 +
 +static BOOL NTAPI
 +GuiSetScreenInfo(IN OUT PFRONTEND This,
 +                 PCONSOLE_SCREEN_BUFFER Buff,
 +                 SHORT OldCursorX,
 +                 SHORT OldCursorY)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    if (GuiData->ActiveBuffer == Buff)
 +    {
 +        /* Redraw char at old position (remove cursor) */
 +        InvalidateCell(GuiData, OldCursorX, OldCursorY);
 +        /* Redraw char at new position (show cursor) */
 +        InvalidateCell(GuiData, Buff->CursorPosition.X, Buff->CursorPosition.Y);
 +    }
 +
 +    return TRUE;
 +}
 +
 +static VOID NTAPI
 +GuiResizeTerminal(IN OUT PFRONTEND This)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    /* Resize the window to the user's values */
 +    PostMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
 +}
 +
 +static VOID NTAPI
 +GuiSetActiveScreenBuffer(IN OUT PFRONTEND This)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
 +    HPALETTE hPalette;
 +
 +    EnterCriticalSection(&GuiData->Lock);
 +    GuiData->WindowSizeLock = TRUE;
 +
 +    InterlockedExchangePointer(&GuiData->ActiveBuffer,
 +                               ConDrvGetActiveScreenBuffer(GuiData->Console));
 +
 +    GuiData->WindowSizeLock = FALSE;
 +    LeaveCriticalSection(&GuiData->Lock);
 +
 +    ActiveBuffer = GuiData->ActiveBuffer;
 +
 +    /* Change the current palette */
 +    if (ActiveBuffer->PaletteHandle == NULL)
 +    {
 +        hPalette = GuiData->hSysPalette;
 +    }
 +    else
 +    {
 +        hPalette = ActiveBuffer->PaletteHandle;
 +    }
 +
 +    DPRINT1("GuiSetActiveScreenBuffer using palette 0x%p\n", hPalette);
 +
 +    /* Set the new palette for the framebuffer */
 +    SelectPalette(GuiData->hMemDC, hPalette, FALSE);
 +
 +    /* Specify the use of the system palette for the framebuffer */
 +    SetSystemPaletteUse(GuiData->hMemDC, ActiveBuffer->PaletteUsage);
 +
 +    /* Realize the (logical) palette */
 +    RealizePalette(GuiData->hMemDC);
 +
 +    GuiResizeTerminal(This);
 +    // ConioDrawConsole(Console);
 +}
 +
 +static VOID NTAPI
 +GuiReleaseScreenBuffer(IN OUT PFRONTEND This,
 +                       IN PCONSOLE_SCREEN_BUFFER ScreenBuffer)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    /*
 +     * If we were notified to release a screen buffer that is not actually
 +     * ours, then just ignore the notification...
 +     */
 +    if (ScreenBuffer != GuiData->ActiveBuffer) return;
 +
 +    /*
 +     * ... else, we must release our active buffer. Two cases are present:
 +     * - If ScreenBuffer (== GuiData->ActiveBuffer) IS NOT the console
 +     *   active screen buffer, then we can safely switch to it.
 +     * - If ScreenBuffer IS the console active screen buffer, we must release
 +     *   it ONLY.
 +     */
 +
 +    /* Release the old active palette and set the default one */
 +    if (GetCurrentObject(GuiData->hMemDC, OBJ_PAL) == ScreenBuffer->PaletteHandle)
 +    {
 +        /* Set the new palette */
 +        SelectPalette(GuiData->hMemDC, GuiData->hSysPalette, FALSE);
 +    }
 +
 +    /* Set the adequate active screen buffer */
 +    if (ScreenBuffer != GuiData->Console->ActiveBuffer)
 +    {
 +        GuiSetActiveScreenBuffer(This);
 +    }
 +    else
 +    {
 +        EnterCriticalSection(&GuiData->Lock);
 +        GuiData->WindowSizeLock = TRUE;
 +
 +        InterlockedExchangePointer(&GuiData->ActiveBuffer, NULL);
 +
 +        GuiData->WindowSizeLock = FALSE;
 +        LeaveCriticalSection(&GuiData->Lock);
 +    }
 +}
 +
 +static BOOL NTAPI
 +GuiProcessKeyCallback(IN OUT PFRONTEND This,
 +                      MSG* msg,
 +                      BYTE KeyStateMenu,
 +                      DWORD ShiftState,
 +                      UINT VirtualKeyCode,
 +                      BOOL Down)
 +{
 +    if ((ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) || KeyStateMenu & 0x80) &&
 +        (VirtualKeyCode == VK_ESCAPE || VirtualKeyCode == VK_TAB || VirtualKeyCode == VK_SPACE))
 +    {
++        DPRINT1("GuiProcessKeyCallback\n");
++        //DefWindowProcW(msg->hwnd, msg->message, msg->wParam, msg->lParam);
++        //return TRUE;
 +    }
 +
 +    return FALSE;
 +}
 +
 +static BOOL NTAPI
 +GuiSetMouseCursor(IN OUT PFRONTEND This,
 +                  HCURSOR CursorHandle);
 +
 +static VOID NTAPI
 +GuiRefreshInternalInfo(IN OUT PFRONTEND This)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    /* Update the console leader information held by the window */
 +    SetConWndConsoleLeaderCID(GuiData);
 +
 +    /*
 +     * HACK:
 +     * We reset the cursor here so that, when a console app quits, we reset
 +     * the cursor to the default one. It's quite a hack since it doesn't proceed
 +     * per - console process... This must be fixed.
 +     *
 +     * See GuiInitConsole(...) for more information.
 +     */
 +
 +    /* Mouse is shown by default with its default cursor shape */
 +    GuiData->MouseCursorRefCount = 0; // Reinitialize the reference counter
 +    GuiSetMouseCursor(This, NULL);
 +}
 +
 +static VOID NTAPI
 +GuiChangeTitle(IN OUT PFRONTEND This)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    // PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0);
 +    SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
 +}
 +
 +static BOOL NTAPI
 +GuiChangeIcon(IN OUT PFRONTEND This,
 +              HICON IconHandle)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    HICON hIcon, hIconSm;
 +
 +    if (IconHandle == NULL)
 +    {
 +        hIcon   = ghDefaultIcon;
 +        hIconSm = ghDefaultIconSm;
 +    }
 +    else
 +    {
 +        hIcon   = CopyIcon(IconHandle);
 +        hIconSm = CopyIcon(IconHandle);
 +    }
 +
 +    if (hIcon == NULL)
 +    {
 +        return FALSE;
 +    }
 +
 +    if (hIcon != GuiData->hIcon)
 +    {
 +        if (GuiData->hIcon != NULL && GuiData->hIcon != ghDefaultIcon)
 +        {
 +            DestroyIcon(GuiData->hIcon);
 +        }
 +        if (GuiData->hIconSm != NULL && GuiData->hIconSm != ghDefaultIconSm)
 +        {
 +            DestroyIcon(GuiData->hIconSm);
 +        }
 +
 +        GuiData->hIcon   = hIcon;
 +        GuiData->hIconSm = hIconSm;
 +
 +        DPRINT("Set icons in GuiChangeIcon\n");
 +        PostMessageW(GuiData->hWindow, WM_SETICON, ICON_BIG  , (LPARAM)GuiData->hIcon  );
 +        PostMessageW(GuiData->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)GuiData->hIconSm);
 +    }
 +
 +    return TRUE;
 +}
 +
 +static HWND NTAPI
 +GuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    return GuiData->hWindow;
 +}
 +
 +static VOID NTAPI
 +GuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
 +                               PCOORD pSize)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
 +    RECT WorkArea;
 +    LONG width, height;
 +    UINT WidthUnit, HeightUnit;
 +
 +    if (!pSize) return;
 +
 +    if (!SystemParametersInfoW(SPI_GETWORKAREA, 0, &WorkArea, 0))
 +    {
 +        DPRINT1("SystemParametersInfoW failed - What to do ??\n");
 +        return;
 +    }
 +
 +    ActiveBuffer = GuiData->ActiveBuffer;
 +    if (ActiveBuffer)
 +    {
 +        GetScreenBufferSizeUnits(ActiveBuffer, GuiData, &WidthUnit, &HeightUnit);
 +    }
 +    else
 +    {
 +        /* Default: text mode */
 +        WidthUnit  = GuiData->CharWidth ;
 +        HeightUnit = GuiData->CharHeight;
 +    }
 +
 +    width  = WorkArea.right;
 +    height = WorkArea.bottom;
 +
 +    width  -= (2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE)));
 +    height -= (2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION));
 +
 +    if (width  < 0) width  = 0;
 +    if (height < 0) height = 0;
 +
 +    pSize->X = (SHORT)(width  / (int)WidthUnit ) /* HACK */ + 2;
 +    pSize->Y = (SHORT)(height / (int)HeightUnit) /* HACK */ + 1;
 +}
 +
 +static BOOL NTAPI
 +GuiGetSelectionInfo(IN OUT PFRONTEND This,
 +                    PCONSOLE_SELECTION_INFO pSelectionInfo)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    if (pSelectionInfo == NULL) return FALSE;
 +
 +    ZeroMemory(pSelectionInfo, sizeof(CONSOLE_SELECTION_INFO));
 +    if (GuiData->Selection.dwFlags != CONSOLE_NO_SELECTION)
 +        RtlCopyMemory(pSelectionInfo, &GuiData->Selection, sizeof(CONSOLE_SELECTION_INFO));
 +
 +    return TRUE;
 +}
 +
 +static BOOL NTAPI
 +GuiSetPalette(IN OUT PFRONTEND This,
 +              HPALETTE PaletteHandle,
 +              UINT PaletteUsage)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    HPALETTE OldPalette;
 +
 +    // if (GetType(GuiData->ActiveBuffer) != GRAPHICS_BUFFER) return FALSE;
 +    if (PaletteHandle == NULL) return FALSE;
 +
 +    /* Set the new palette for the framebuffer */
 +    OldPalette = SelectPalette(GuiData->hMemDC, PaletteHandle, FALSE);
 +    if (OldPalette == NULL) return FALSE;
 +
 +    /* Specify the use of the system palette for the framebuffer */
 +    SetSystemPaletteUse(GuiData->hMemDC, PaletteUsage);
 +
 +    /* Realize the (logical) palette */
 +    RealizePalette(GuiData->hMemDC);
 +
 +    /* Save the original system palette handle */
 +    if (GuiData->hSysPalette == NULL) GuiData->hSysPalette = OldPalette;
 +
 +    return TRUE;
 +}
 +
 +static ULONG NTAPI
 +GuiGetDisplayMode(IN OUT PFRONTEND This)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    ULONG DisplayMode = 0;
 +
 +    if (GuiData->GuiInfo.FullScreen)
 +        DisplayMode |= CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN
 +    else
 +        DisplayMode |= CONSOLE_WINDOWED;
 +
 +    return DisplayMode;
 +}
 +
 +static BOOL NTAPI
 +GuiSetDisplayMode(IN OUT PFRONTEND This,
 +                  ULONG NewMode)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    BOOL FullScreen;
 +
 +    if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
 +        return FALSE;
 +
 +    FullScreen = ((NewMode & CONSOLE_FULLSCREEN_MODE) != 0);
 +
 +    if (FullScreen != GuiData->GuiInfo.FullScreen)
 +    {
 +        SwitchFullScreen(GuiData, FullScreen);
 +    }
 +
 +    return TRUE;
 +}
 +
 +static INT NTAPI
 +GuiShowMouseCursor(IN OUT PFRONTEND This,
 +                   BOOL Show)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    /* Set the reference count */
 +    if (Show) ++GuiData->MouseCursorRefCount;
 +    else      --GuiData->MouseCursorRefCount;
 +
 +    /* Effectively show (or hide) the cursor (use special values for (w|l)Param) */
 +    PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
 +
 +    return GuiData->MouseCursorRefCount;
 +}
 +
 +static BOOL NTAPI
 +GuiSetMouseCursor(IN OUT PFRONTEND This,
 +                  HCURSOR CursorHandle)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    /*
 +     * Set the cursor's handle. If the given handle is NULL,
 +     * then restore the default cursor.
 +     */
 +    GuiData->hCursor = (CursorHandle ? CursorHandle : ghDefaultCursor);
 +
 +    /* Effectively modify the shape of the cursor (use special values for (w|l)Param) */
 +    PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
 +
 +    return TRUE;
 +}
 +
 +static HMENU NTAPI
 +GuiMenuControl(IN OUT PFRONTEND This,
 +               UINT CmdIdLow,
 +               UINT CmdIdHigh)
 +{
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +
 +    GuiData->CmdIdLow  = CmdIdLow ;
 +    GuiData->CmdIdHigh = CmdIdHigh;
 +
 +    return GetSystemMenu(GuiData->hWindow, FALSE);
 +}
 +
 +static BOOL NTAPI
 +GuiSetMenuClose(IN OUT PFRONTEND This,
 +                BOOL Enable)
 +{
 +    /*
 +     * NOTE: See http://www.mail-archive.com/harbour@harbour-project.org/msg27509.html
 +     * or http://harbour-devel.1590103.n2.nabble.com/Question-about-hb-gt-win-CtrlHandler-usage-td4670862i20.html
 +     * for more information.
 +     */
 +
 +    PGUI_CONSOLE_DATA GuiData = This->Data;
 +    HMENU hSysMenu = GetSystemMenu(GuiData->hWindow, FALSE);
 +
 +    if (hSysMenu == NULL) return FALSE;
 +
 +    GuiData->IsCloseButtonEnabled = Enable;
 +    EnableMenuItem(hSysMenu, SC_CLOSE, MF_BYCOMMAND | (Enable ? MF_ENABLED : MF_GRAYED));
 +
 +    return TRUE;
 +}
 +
 +static FRONTEND_VTBL GuiVtbl =
 +{
 +    GuiInitFrontEnd,
 +    GuiDeinitFrontEnd,
 +    GuiDrawRegion,
 +    GuiWriteStream,
 +    GuiSetCursorInfo,
 +    GuiSetScreenInfo,
 +    GuiResizeTerminal,
 +    GuiSetActiveScreenBuffer,
 +    GuiReleaseScreenBuffer,
 +    GuiProcessKeyCallback,
 +    GuiRefreshInternalInfo,
 +    GuiChangeTitle,
 +    GuiChangeIcon,
 +    GuiGetConsoleWindowHandle,
 +    GuiGetLargestConsoleWindowSize,
 +    GuiGetSelectionInfo,
 +    GuiSetPalette,
 +    GuiGetDisplayMode,
 +    GuiSetDisplayMode,
 +    GuiShowMouseCursor,
 +    GuiSetMouseCursor,
 +    GuiMenuControl,
 +    GuiSetMenuClose,
 +};
 +
 +
 +static BOOL
 +LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
 +                         IN OUT PCONSOLE_INFO ConsoleInfo)
 +{
 +#define PATH_SEPARATOR L'\\'
 +
 +    BOOL    RetVal   = FALSE;
 +    HRESULT hRes     = S_OK;
 +    LPWSTR  LinkName = NULL;
 +    SIZE_T  Length   = 0;
 +
 +    if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
 +        return FALSE;
 +
 +    ConsoleStartInfo->IconPath[0] = L'\0';
 +    ConsoleStartInfo->IconIndex   = 0;
 +
 +    /* 1- Find the last path separator if any */
 +    LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR);
 +    if (LinkName == NULL)
 +    {
 +        LinkName = ConsoleStartInfo->ConsoleTitle;
 +    }
 +    else
 +    {
 +        /* Skip the path separator */
 +        ++LinkName;
 +    }
 +
 +    /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
 +    Length = wcslen(LinkName);
 +    if ( (Length <= 4) || (wcsicmp(LinkName + (Length - 4), L".lnk") != 0) )
 +        return FALSE;
 +
 +    /* 3- It may be a link. Try to retrieve some properties */
 +    hRes = CoInitialize(NULL);
 +    if (SUCCEEDED(hRes))
 +    {
 +        /* Get a pointer to the IShellLink interface */
 +        IShellLinkW* pshl = NULL;
 +        hRes = CoCreateInstance(&CLSID_ShellLink,
 +                                NULL, 
 +                                CLSCTX_INPROC_SERVER,
 +                                &IID_IShellLinkW,
 +                                (LPVOID*)&pshl);
 +        if (SUCCEEDED(hRes))
 +        {
 +            /* Get a pointer to the IPersistFile interface */
 +            IPersistFile* ppf = NULL;
 +            hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
 +            if (SUCCEEDED(hRes))
 +            {
 +                /* Load the shortcut */
 +                hRes = IPersistFile_Load(ppf, ConsoleStartInfo->ConsoleTitle, STGM_READ);
 +                if (SUCCEEDED(hRes))
 +                {
 +                    /*
 +                     * Finally we can get the properties !
 +                     * Update the old ones if needed.
 +                     */
 +                    INT ShowCmd = 0;
 +                    // WORD HotKey = 0;
 +
 +                    /* Reset the name of the console with the name of the shortcut */
 +                    Length = min(/*Length*/ Length - 4, // 4 == len(".lnk")
 +                                 sizeof(ConsoleInfo->ConsoleTitle) / sizeof(ConsoleInfo->ConsoleTitle[0]) - 1);
 +                    wcsncpy(ConsoleInfo->ConsoleTitle, LinkName, Length);
 +                    ConsoleInfo->ConsoleTitle[Length] = L'\0';
 +
 +                    /* Get the window showing command */
 +                    hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd);
 +                    if (SUCCEEDED(hRes)) ConsoleStartInfo->wShowWindow = (WORD)ShowCmd;
 +
 +                    /* Get the hotkey */
 +                    // hRes = pshl->GetHotkey(&ShowCmd);
 +                    // if (SUCCEEDED(hRes)) ConsoleStartInfo->HotKey = HotKey;
 +
 +                    /* Get the icon location, if any */
 +
 +                    hRes = IShellLinkW_GetIconLocation(pshl,
 +                                                       ConsoleStartInfo->IconPath,
 +                                                       sizeof(ConsoleStartInfo->IconPath)/sizeof(ConsoleStartInfo->IconPath[0]) - 1, // == MAX_PATH
 +                                                       &ConsoleStartInfo->IconIndex);
 +                    if (!SUCCEEDED(hRes))
 +                    {
 +                        ConsoleStartInfo->IconPath[0] = L'\0';
 +                        ConsoleStartInfo->IconIndex   = 0;
 +                    }
 +
 +                    // FIXME: Since we still don't load console properties from the shortcut,
 +                    // return false. When this will be done, we will return true instead.
 +                    RetVal = FALSE;
 +                }
 +                IPersistFile_Release(ppf);
 +            }
 +            IShellLinkW_Release(pshl);
 +        }
 +    }
 +    CoUninitialize();
 +
 +    return RetVal;
 +}
 +
 +NTSTATUS NTAPI
 +GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
 +                IN OUT PCONSOLE_INFO ConsoleInfo,
 +                IN OUT PVOID ExtraConsoleInfo,
 +                IN ULONG ProcessId)
 +{
 +    PCONSOLE_START_INFO ConsoleStartInfo = ExtraConsoleInfo;
 +    PGUI_INIT_INFO GuiInitInfo;
 +
 +    if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleStartInfo == NULL)
 +        return STATUS_INVALID_PARAMETER;
 +
 +    /* Initialize GUI terminal emulator common functionalities */
 +    if (!GuiInit()) return STATUS_UNSUCCESSFUL;
 +
 +    /*
 +     * Load per-application terminal settings.
 +     *
 +     * Check whether the process creating the console was launched via
 +     * a shell-link. ConsoleInfo->ConsoleTitle may be updated with the
 +     * name of the shortcut, and ConsoleStartInfo->Icon[Path|Index] too.
 +     */
 +    if (ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME)
 +    {
 +        if (!LoadShellLinkConsoleInfo(ConsoleStartInfo, ConsoleInfo))
 +        {
 +            ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
 +        }
 +    }
 +
 +    /*
 +     * Initialize a private initialization info structure for later use.
 +     * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
 +     */
 +    GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_INIT_INFO));
 +    if (GuiInitInfo == NULL) return STATUS_NO_MEMORY;
 +
 +    // HACK: We suppose that the pointers will be valid in GuiInitFrontEnd...
 +    GuiInitInfo->ConsoleInfo      = ConsoleInfo;
 +    GuiInitInfo->ConsoleStartInfo = ConsoleStartInfo;
 +    GuiInitInfo->ProcessId        = ProcessId;
 +
 +    /* Finally, initialize the frontend structure */
 +    FrontEnd->Vtbl    = &GuiVtbl;
 +    FrontEnd->Data    = NULL;
 +    FrontEnd->OldData = GuiInitInfo;
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +NTSTATUS NTAPI
 +GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
 +{
 +    if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
 +
 +    if (FrontEnd->Data)    GuiDeinitFrontEnd(FrontEnd);
 +    if (FrontEnd->OldData) ConsoleFreeHeap(FrontEnd->OldData);
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +/* EOF */