From 7f0f0d4287434aefbd05cc7896b0caf3a1265cd7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?K=C3=A1roly=20Balogh?= <karoly@freepascal.org>
Date: Sat, 20 Jan 2007 00:27:08 +0000
Subject: [PATCH]   + added required units to compile IDE     they're a total
 mess ATM, under fixing/cleanup, but IDE start up at least

git-svn-id: trunk@6086 -
---
 .gitattributes           |   4 +
 rtl/morphos/Makefile.fpc |  16 +-
 rtl/morphos/keyboard.pp  | 998 +++++++++++++++++++++++++++++++++++++++
 rtl/morphos/kvm.pp       |  78 +++
 rtl/morphos/mouse.pp     | 275 +++++++++++
 rtl/morphos/video.pp     | 428 +++++++++++++++++
 6 files changed, 1798 insertions(+), 1 deletion(-)
 create mode 100644 rtl/morphos/keyboard.pp
 create mode 100644 rtl/morphos/kvm.pp
 create mode 100644 rtl/morphos/mouse.pp
 create mode 100644 rtl/morphos/video.pp

diff --git a/.gitattributes b/.gitattributes
index b2ce034a18..e9974ad97a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -4769,7 +4769,10 @@ rtl/morphos/graphics.pas svneol=native#text/plain
 rtl/morphos/hardware.pas svneol=native#text/plain
 rtl/morphos/inputevent.pas svneol=native#text/plain
 rtl/morphos/intuition.pas svneol=native#text/plain
+rtl/morphos/keyboard.pp svneol=native#text/plain
+rtl/morphos/kvm.pp svneol=native#text/plain
 rtl/morphos/layers.pas svneol=native#text/plain
+rtl/morphos/mouse.pp svneol=native#text/plain
 rtl/morphos/mui.pas -text
 rtl/morphos/muihelper.pas -text
 rtl/morphos/prt0.as -text
@@ -4791,6 +4794,7 @@ rtl/morphos/utild2.inc svneol=native#text/plain
 rtl/morphos/utilf.inc svneol=native#text/plain
 rtl/morphos/utility.pp svneol=native#text/plain
 rtl/morphos/varutils.pp svneol=native#text/plain
+rtl/morphos/video.pp svneol=native#text/plain
 rtl/nds/Makefile svneol=native#text/plain
 rtl/nds/Makefile.fpc -text
 rtl/nds/classes.pp -text
diff --git a/rtl/morphos/Makefile.fpc b/rtl/morphos/Makefile.fpc
index e9875bd3ae..95fae54eea 100644
--- a/rtl/morphos/Makefile.fpc
+++ b/rtl/morphos/Makefile.fpc
@@ -14,8 +14,10 @@ units=$(SYSTEMUNIT) objpas macpas strings \
       variants types rtlconsts sysconst dateutil objects \
       exec timer doslib utility hardware inputevent graphics layers \
       intuition aboxlib mui \
+# these units are here, because they depend on system interface units above
+      kvm video keyboard mouse \
 # these can be moved to packages later
-      clipboard datatypes asl ahi tinygl get9 muihelper \
+      clipboard datatypes asl ahi tinygl get9 muihelper
 rsts=math rtlconsts varutils typinfo variants classes sysconst dateutil
 
 [require]
@@ -222,3 +224,15 @@ tinygl$(PPUEXT): tinygl.pp exec$(PPUEXT)
 get9$(PPUEXT): get9.pas exec$(PPUEXT)
 
 muihelper$(PPUEXT): muihelper.pas intuition$(PPUEXT) mui$(PPUEXT) doslib$(PPUEXT) utility$(PPUEXT)
+
+
+kvm$(PPUEXT) : kvm.pp
+
+video$(PPUEXT) : video.pp 
+#windows$(PPUEXT) dos$(PPUEXT)
+
+mouse$(PPUEXT) : mouse.pp 
+#windows$(PPUEXT) dos$(PPUEXT) winevent$(PPUEXT)
+
+keyboard$(PPUEXT) : keyboard.pp 
+#windows$(PPUEXT) dos$(PPUEXT) winevent$(PPUEXT)
diff --git a/rtl/morphos/keyboard.pp b/rtl/morphos/keyboard.pp
new file mode 100644
index 0000000000..44d0235a2d
--- /dev/null
+++ b/rtl/morphos/keyboard.pp
@@ -0,0 +1,998 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Florian Klaempfl
+    member of the Free Pascal development team
+
+    Keyboard unit for Win32
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit Keyboard;
+interface
+{$ifdef DEBUG}
+//uses
+//  windows;
+
+//var
+//  last_ir : Input_Record;
+{$endif DEBUG}
+
+{$i keybrdh.inc}
+
+implementation
+
+{ WARNING: Keyboard-Drivers (i.e. german) will only work under WinNT.
+           95 and 98 do not support keyboard-drivers other than us for win32
+           console-apps. So we always get the keys in us-keyboard layout
+           from Win9x.
+}
+
+//uses
+{ifndef DEBUG}
+//   Windows,
+{endif DEBUG}
+//   Dos,
+//   WinEvent;
+uses
+   video,
+   exec,intuition;
+
+{$i keyboard.inc}
+
+{*
+const MaxQueueSize = 120;
+      FrenchKeyboard = $040C040C;
+
+var
+   keyboardeventqueue : array[0..maxqueuesize] of TKeyEventRecord;
+   nextkeyevent,nextfreekeyevent : longint;
+   newKeyEvent    : THandle;            {sinaled if key is available}
+   lockVar        : TCriticalSection;   {for queue access}
+   lastShiftState : byte;               {set by handler for PollShiftStateEvent}
+   altNumActive   : boolean;            {for alt+0..9}
+   altNumBuffer   : string [3];
+   { used for keyboard specific stuff }
+   KeyBoardLayout : HKL;
+   Inited : Boolean;
+   HasAltGr  : Boolean = false;
+
+
+
+procedure incqueueindex(var l : longint);
+
+  begin
+     inc(l);
+     { wrap around? }
+     if l>maxqueuesize then
+       l:=0;
+  end;
+
+function keyEventsInQueue : boolean;
+begin
+  keyEventsInQueue := (nextkeyevent <> nextfreekeyevent);
+end;
+
+function rightistruealt(dw:cardinal):boolean; // inline ?
+// used to wrap checks for right alt/altgr.
+begin
+  rightistruealt:=true;
+  if hasaltgr then
+    rightistruealt:=(dw and RIGHT_ALT_PRESSED)=0;
+end;
+
+
+{ gets or peeks the next key from the queue, does not wait for new keys }
+function getKeyEventFromQueue (VAR t : TKeyEventRecord; Peek : boolean) : boolean;
+begin
+  if not Inited then
+    begin
+    getKeyEventFromQueue := false;
+    exit;
+    end;
+  EnterCriticalSection (lockVar);
+  if keyEventsInQueue then
+  begin
+    t := keyboardeventqueue[nextkeyevent];
+    if not peek then incqueueindex (nextkeyevent);
+    getKeyEventFromQueue := true;
+    if not keyEventsInQueue then ResetEvent (newKeyEvent);
+  end else
+  begin
+    getKeyEventFromQueue := false;
+    ResetEvent (newKeyEvent);
+  end;
+  LeaveCriticalSection (lockVar);
+end;
+
+
+{ gets the next key from the queue, does wait for new keys }
+function getKeyEventFromQueueWait (VAR t : TKeyEventRecord) : boolean;
+begin
+  if not Inited then
+    begin
+      getKeyEventFromQueueWait := false;
+      exit;
+    end;
+  WaitForSingleObject (newKeyEvent, dword(INFINITE));
+  getKeyEventFromQueueWait := getKeyEventFromQueue (t, false);
+end;
+
+{ translate win32 shift-state to keyboard shift state }
+function transShiftState (ControlKeyState : dword) : byte;
+var b : byte;
+begin
+  b := 0;
+  if ControlKeyState and SHIFT_PRESSED <> 0 then  { win32 makes no difference between left and right shift }
+    b := b or kbShift;
+  if (ControlKeyState and LEFT_CTRL_PRESSED <> 0) or
+     (ControlKeyState  and RIGHT_CTRL_PRESSED <> 0) then
+    b := b or kbCtrl;
+  if (ControlKeyState and LEFT_ALT_PRESSED <> 0) or
+     (ControlKeyState and RIGHT_ALT_PRESSED <> 0) then
+    b := b or kbAlt;
+  transShiftState := b;
+end;
+
+{ The event-Handler thread from the unit event will call us if a key-event
+  is available }
+
+procedure HandleKeyboard(var ir:INPUT_RECORD);
+var
+   i      : longint;
+   c      : word;
+   altc : char;
+   addThis: boolean;
+begin
+         with ir.Event.KeyEvent do
+           begin
+              { key up events are ignored (except alt) }
+              if bKeyDown then
+                begin
+                   EnterCriticalSection (lockVar);
+                   for i:=1 to wRepeatCount do
+                     begin
+                        addThis := true;
+                        if (dwControlKeyState and LEFT_ALT_PRESSED <> 0) or
+                           (dwControlKeyState and RIGHT_ALT_PRESSED <> 0) then            {alt pressed}
+                          if ((wVirtualKeyCode >= $60) and (wVirtualKeyCode <= $69)) or
+                             ((dwControlKeyState and ENHANCED_KEY = 0) and
+                              (wVirtualKeyCode in [$C{VK_CLEAR generated by keypad 5},
+                                                   $21 {VK_PRIOR (PgUp) 9},
+                                                   $22 {VK_NEXT (PgDown) 3},
+                                                   $23 {VK_END 1},
+                                                   $24 {VK_HOME 7},
+                                                   $25 {VK_LEFT 4},
+                                                   $26 {VK_UP 8},
+                                                   $27 {VK_RIGHT 6},
+                                                   $28 {VK_DOWN 2},
+                                                   $2D {VK_INSERT 0}])) then   {0..9 on NumBlock}
+                          begin
+                            if length (altNumBuffer) = 3 then
+                              delete (altNumBuffer,1,1);
+                            case wVirtualKeyCode of
+                              $60..$69 : altc:=char (wVirtualKeyCode-48);
+                              $c  : altc:='5';
+                              $21 : altc:='9';
+                              $22 : altc:='3';
+                              $23 : altc:='1';
+                              $24 : altc:='7';
+                              $25 : altc:='4';
+                              $26 : altc:='8';
+                              $27 : altc:='6';
+                              $28 : altc:='2';
+                              $2D : altc:='0';
+                            end;
+                            altNumBuffer := altNumBuffer + altc;
+                            altNumActive   := true;
+                            addThis := false;
+                          end else
+                          begin
+                            altNumActive   := false;
+                            altNumBuffer   := '';
+                          end;
+                        if addThis then
+                        begin
+                          keyboardeventqueue[nextfreekeyevent]:=
+                            ir.Event.KeyEvent;
+                          incqueueindex(nextfreekeyevent);
+                        end;
+                     end;
+
+                   lastShiftState := transShiftState (dwControlKeyState);  {save it for PollShiftStateEvent}
+                   SetEvent (newKeyEvent);             {event that a new key is available}
+                   LeaveCriticalSection (lockVar);
+                end
+              else
+                begin
+                  lastShiftState := transShiftState (dwControlKeyState);   {save it for PollShiftStateEvent}
+                  {for alt-number we have to look for alt-key release}
+                  if altNumActive then
+                   begin
+                     if (wVirtualKeyCode = $12) then    {alt-released}
+                      begin
+                        if altNumBuffer <> '' then       {numbers with alt pressed?}
+                         begin
+                           Val (altNumBuffer, c, i);
+                           if (i = 0) and (c <= 255) then {valid number?}
+                            begin                          {add to queue}
+                              fillchar (ir, sizeof (ir), 0);
+                              bKeyDown := true;
+                              AsciiChar := char (c);
+                                                       {and add to queue}
+                              EnterCriticalSection (lockVar);
+                              keyboardeventqueue[nextfreekeyevent]:=ir.Event.KeyEvent;
+                              incqueueindex(nextfreekeyevent);
+                              SetEvent (newKeyEvent);      {event that a new key is available}
+                              LeaveCriticalSection (lockVar);
+                            end;
+                         end;
+                        altNumActive   := false;         {clear alt-buffer}
+                        altNumBuffer   := '';
+                      end;
+                   end;
+                end;
+           end;
+end;
+*}
+
+{*
+procedure CheckAltGr;
+
+var ahkl : HKL;
+    i    : integer;
+
+ begin
+   HasAltGr:=false;
+
+   ahkl:=GetKeyboardLayout(0);
+   i:=$20;
+   while i<$100 do
+     begin
+       // <MSDN>
+       // For keyboard layouts that use the right-hand ALT key as ashift key
+       // (for example, the French keyboard layout), the shift state is
+       // represented by the value 6, because the right-hand ALT key is
+       // converted internally into CTRL+ALT.
+       // </MSDN>
+      if (HIBYTE(VkKeyScanEx(chr(i),ahkl))=6) then
+        begin
+          HasAltGr:=true;
+          break;
+        end;
+     inc(i);
+    end;
+end;
+*}
+
+
+
+procedure SysInitKeyboard;
+begin
+  writeln('sysinitkeyboard');
+{*
+   KeyBoardLayout:=GetKeyboardLayout(0);
+   lastShiftState := 0;
+   FlushConsoleInputBuffer(StdInputHandle);
+   newKeyEvent := CreateEvent (nil,        // address of security attributes
+                               true,       // flag for manual-reset event
+                               false,      // flag for initial state
+                               nil);       // address of event-object name
+   if newKeyEvent = INVALID_HANDLE_VALUE then
+    begin
+      // what to do here ????
+      RunError (217);
+    end;
+   InitializeCriticalSection (lockVar);
+   altNumActive := false;
+   altNumBuffer := '';
+
+   nextkeyevent:=0;
+   nextfreekeyevent:=0;
+   checkaltgr;
+   SetKeyboardEventHandler (@HandleKeyboard);
+   Inited:=true;
+*}
+end;
+
+procedure SysDoneKeyboard;
+begin
+{*
+  SetKeyboardEventHandler(nil);     {hangs???}
+  DeleteCriticalSection (lockVar);
+  FlushConsoleInputBuffer(StdInputHandle);
+  closeHandle (newKeyEvent);
+  Inited:=false;
+*}
+end;
+
+{$define USEKEYCODES}
+
+{Translatetable Win32 -> Dos for Special Keys = Function Key, Cursor Keys
+ and Keys other than numbers on numblock (to make fv happy) }
+{combinations under dos: Shift+Ctrl: same as Ctrl
+                         Shift+Alt : same as alt
+ 
+{*                        Ctrl+Alt  : nothing (here we get it like alt)}
+{ifdef USEKEYCODES}
+   { use positive values for ScanCode we want to set
+   0 for key where we should leave the scancode
+   -1 for OEM specifc keys
+   -2 for unassigned
+   -3 for Kanji systems ???
+   }
+
+const
+  Unassigned = -2;
+  Kanji = -3;
+  OEM_specific = -1;
+  KeyToQwertyScan : array [0..255] of integer =
+  (
+  { 00 } 0,
+  { 01 VK_LBUTTON } 0,
+  { 02 VK_RBUTTON } 0,
+  { 03 VK_CANCEL } 0,
+  { 04 VK_MBUTTON } 0,
+  { 05 unassigned } -2,
+  { 06 unassigned } -2,
+  { 07 unassigned } -2,
+  { 08 VK_BACK } $E,
+  { 09 VK_TAB } $F,
+  { 0A unassigned } -2,
+  { 0B unassigned } -2,
+  { 0C VK_CLEAR ?? } 0,
+  { 0D VK_RETURN } 0,
+  { 0E unassigned } -2,
+  { 0F unassigned } -2,
+  { 10 VK_SHIFT } 0,
+  { 11 VK_CONTROL } 0,
+  { 12 VK_MENU (Alt key) } 0,
+  { 13 VK_PAUSE } 0,
+  { 14 VK_CAPITAL (Caps Lock) } 0,
+  { 15 Reserved for Kanji systems} -3,
+  { 16 Reserved for Kanji systems} -3,
+  { 17 Reserved for Kanji systems} -3,
+  { 18 Reserved for Kanji systems} -3,
+  { 19 Reserved for Kanji systems} -3,
+  { 1A unassigned } -2,
+  { 1B VK_ESCAPE } $1,
+  { 1C Reserved for Kanji systems} -3,
+  { 1D Reserved for Kanji systems} -3,
+  { 1E Reserved for Kanji systems} -3,
+  { 1F Reserved for Kanji systems} -3,
+  { 20 VK_SPACE} 0,
+  { 21 VK_PRIOR (PgUp) } 0,
+  { 22 VK_NEXT (PgDown) } 0,
+  { 23 VK_END } 0,
+  { 24 VK_HOME } 0,
+  { 25 VK_LEFT } 0,
+  { 26 VK_UP } 0,
+  { 27 VK_RIGHT } 0,
+  { 28 VK_DOWN } 0,
+  { 29 VK_SELECT ??? } 0,
+  { 2A OEM specific !! } -1,
+  { 2B VK_EXECUTE } 0,
+  { 2C VK_SNAPSHOT } 0,
+  { 2D VK_INSERT } 0,
+  { 2E VK_DELETE } 0,
+  { 2F VK_HELP } 0,
+  { 30 VK_0 '0' } 11,
+  { 31 VK_1 '1' } 2,
+  { 32 VK_2 '2' } 3,
+  { 33 VK_3 '3' } 4,
+  { 34 VK_4 '4' } 5,
+  { 35 VK_5 '5' } 6,
+  { 36 VK_6 '6' } 7,
+  { 37 VK_7 '7' } 8,
+  { 38 VK_8 '8' } 9,
+  { 39 VK_9 '9' } 10,
+  { 3A unassigned } -2,
+  { 3B unassigned } -2,
+  { 3C unassigned } -2,
+  { 3D unassigned } -2,
+  { 3E unassigned } -2,
+  { 3F unassigned } -2,
+  { 40 unassigned } -2,
+  { 41 VK_A 'A' } $1E,
+  { 42 VK_B 'B' } $30,
+  { 43 VK_C 'C' } $2E,
+  { 44 VK_D 'D' } $20,
+  { 45 VK_E 'E' } $12,
+  { 46 VK_F 'F' } $21,
+  { 47 VK_G 'G' } $22,
+  { 48 VK_H 'H' } $23,
+  { 49 VK_I 'I' } $17,
+  { 4A VK_J 'J' } $24,
+  { 4B VK_K 'K' } $25,
+  { 4C VK_L 'L' } $26,
+  { 4D VK_M 'M' } $32,
+  { 4E VK_N 'N' } $31,
+  { 4F VK_O 'O' } $18,
+  { 50 VK_P 'P' } $19,
+  { 51 VK_Q 'Q' } $10,
+  { 52 VK_R 'R' } $13,
+  { 53 VK_S 'S' } $1F,
+  { 54 VK_T 'T' } $14,
+  { 55 VK_U 'U' } $16,
+  { 56 VK_V 'V' } $2F,
+  { 57 VK_W 'W' } $11,
+  { 58 VK_X 'X' } $2D,
+  { 59 VK_Y 'Y' } $15,
+  { 5A VK_Z 'Z' } $2C,
+  { 5B unassigned } -2,
+  { 5C unassigned } -2,
+  { 5D unassigned } -2,
+  { 5E unassigned } -2,
+  { 5F unassigned } -2,
+  { 60 VK_NUMPAD0 NumKeyPad '0' } 11,
+  { 61 VK_NUMPAD1 NumKeyPad '1' } 2,
+  { 62 VK_NUMPAD2 NumKeyPad '2' } 3,
+  { 63 VK_NUMPAD3 NumKeyPad '3' } 4,
+  { 64 VK_NUMPAD4 NumKeyPad '4' } 5,
+  { 65 VK_NUMPAD5 NumKeyPad '5' } 6,
+  { 66 VK_NUMPAD6 NumKeyPad '6' } 7,
+  { 67 VK_NUMPAD7 NumKeyPad '7' } 8,
+  { 68 VK_NUMPAD8 NumKeyPad '8' } 9,
+  { 69 VK_NUMPAD9 NumKeyPad '9' } 10,
+  { 6A VK_MULTIPLY } 0,
+  { 6B VK_ADD } 0,
+  { 6C VK_SEPARATOR } 0,
+  { 6D VK_SUBSTRACT } 0,
+  { 6E VK_DECIMAL } 0,
+  { 6F VK_DIVIDE } 0,
+  { 70 VK_F1 'F1' } $3B,
+  { 71 VK_F2 'F2' } $3C,
+  { 72 VK_F3 'F3' } $3D,
+  { 73 VK_F4 'F4' } $3E,
+  { 74 VK_F5 'F5' } $3F,
+  { 75 VK_F6 'F6' } $40,
+  { 76 VK_F7 'F7' } $41,
+  { 77 VK_F8 'F8' } $42,
+  { 78 VK_F9 'F9' } $43,
+  { 79 VK_F10 'F10' } $44,
+  { 7A VK_F11 'F11' } $57,
+  { 7B VK_F12 'F12' } $58,
+  { 7C VK_F13 } 0,
+  { 7D VK_F14 } 0,
+  { 7E VK_F15 } 0,
+  { 7F VK_F16 } 0,
+  { 80 VK_F17 } 0,
+  { 81 VK_F18 } 0,
+  { 82 VK_F19 } 0,
+  { 83 VK_F20 } 0,
+  { 84 VK_F21 } 0,
+  { 85 VK_F22 } 0,
+  { 86 VK_F23 } 0,
+  { 87 VK_F24 } 0,
+  { 88 unassigned } -2,
+  { 89 VK_NUMLOCK } 0,
+  { 8A VK_SCROLL } 0,
+  { 8B unassigned } -2,
+  { 8C unassigned } -2,
+  { 8D unassigned } -2,
+  { 8E unassigned } -2,
+  { 8F unassigned } -2,
+  { 90 unassigned } -2,
+  { 91 unassigned } -2,
+  { 92 unassigned } -2,
+  { 93 unassigned } -2,
+  { 94 unassigned } -2,
+  { 95 unassigned } -2,
+  { 96 unassigned } -2,
+  { 97 unassigned } -2,
+  { 98 unassigned } -2,
+  { 99 unassigned } -2,
+  { 9A unassigned } -2,
+  { 9B unassigned } -2,
+  { 9C unassigned } -2,
+  { 9D unassigned } -2,
+  { 9E unassigned } -2,
+  { 9F unassigned } -2,
+  { A0 unassigned } -2,
+  { A1 unassigned } -2,
+  { A2 unassigned } -2,
+  { A3 unassigned } -2,
+  { A4 unassigned } -2,
+  { A5 unassigned } -2,
+  { A6 unassigned } -2,
+  { A7 unassigned } -2,
+  { A8 unassigned } -2,
+  { A9 unassigned } -2,
+  { AA unassigned } -2,
+  { AB unassigned } -2,
+  { AC unassigned } -2,
+  { AD unassigned } -2,
+  { AE unassigned } -2,
+  { AF unassigned } -2,
+  { B0 unassigned } -2,
+  { B1 unassigned } -2,
+  { B2 unassigned } -2,
+  { B3 unassigned } -2,
+  { B4 unassigned } -2,
+  { B5 unassigned } -2,
+  { B6 unassigned } -2,
+  { B7 unassigned } -2,
+  { B8 unassigned } -2,
+  { B9 unassigned } -2,
+  { BA OEM specific } 0,
+  { BB OEM specific } 0,
+  { BC OEM specific } 0,
+  { BD OEM specific } 0,
+  { BE OEM specific } 0,
+  { BF OEM specific } 0,
+  { C0 OEM specific } 0,
+  { C1 unassigned } -2,
+  { C2 unassigned } -2,
+  { C3 unassigned } -2,
+  { C4 unassigned } -2,
+  { C5 unassigned } -2,
+  { C6 unassigned } -2,
+  { C7 unassigned } -2,
+  { C8 unassigned } -2,
+  { C9 unassigned } -2,
+  { CA unassigned } -2,
+  { CB unassigned } -2,
+  { CC unassigned } -2,
+  { CD unassigned } -2,
+  { CE unassigned } -2,
+  { CF unassigned } -2,
+  { D0 unassigned } -2,
+  { D1 unassigned } -2,
+  { D2 unassigned } -2,
+  { D3 unassigned } -2,
+  { D4 unassigned } -2,
+  { D5 unassigned } -2,
+  { D6 unassigned } -2,
+  { D7 unassigned } -2,
+  { D8 unassigned } -2,
+  { D9 unassigned } -2,
+  { DA unassigned } -2,
+  { DB OEM specific } 0,
+  { DC OEM specific } 0,
+  { DD OEM specific } 0,
+  { DE OEM specific } 0,
+  { DF OEM specific } 0,
+  { E0 OEM specific } 0,
+  { E1 OEM specific } 0,
+  { E2 OEM specific } 0,
+  { E3 OEM specific } 0,
+  { E4 OEM specific } 0,
+  { E5 unassigned } -2,
+  { E6 OEM specific } 0,
+  { E7 unassigned } -2,
+  { E8 unassigned } -2,
+  { E9 OEM specific } 0,
+  { EA OEM specific } 0,
+  { EB OEM specific } 0,
+  { EC OEM specific } 0,
+  { ED OEM specific } 0,
+  { EE OEM specific } 0,
+  { EF OEM specific } 0,
+  { F0 OEM specific } 0,
+  { F1 OEM specific } 0,
+  { F2 OEM specific } 0,
+  { F3 OEM specific } 0,
+  { F4 OEM specific } 0,
+  { F5 OEM specific } 0,
+  { F6 unassigned } -2,
+  { F7 unassigned } -2,
+  { F8 unassigned } -2,
+  { F9 unassigned } -2,
+  { FA unassigned } -2,
+  { FB unassigned } -2,
+  { FC unassigned } -2,
+  { FD unassigned } -2,
+  { FE unassigned } -2,
+  { FF unassigned } -2
+  );
+{$endif  USEKEYCODES}
+type TTEntryT = packed record
+                  n,s,c,a : byte;   {normal,shift, ctrl, alt, normal only for f11,f12}
+                end;
+*}
+{*
+CONST
+ DosTT : ARRAY [$3B..$58] OF TTEntryT =
+  ((n : $3B; s : $54; c : $5E; a: $68),      {3B F1}
+   (n : $3C; s : $55; c : $5F; a: $69),      {3C F2}
+   (n : $3D; s : $56; c : $60; a: $6A),      {3D F3}
+   (n : $3E; s : $57; c : $61; a: $6B),      {3E F4}
+   (n : $3F; s : $58; c : $62; a: $6C),      {3F F5}
+   (n : $40; s : $59; c : $63; a: $6D),      {40 F6}
+   (n : $41; s : $5A; c : $64; a: $6E),      {41 F7}
+   (n : $42; s : $5B; c : $65; a: $6F),      {42 F8}
+   (n : $43; s : $5C; c : $66; a: $70),      {43 F9}
+   (n : $44; s : $5D; c : $67; a: $71),      {44 F10}
+   (n : $45; s : $00; c : $00; a: $00),      {45 ???}
+   (n : $46; s : $00; c : $00; a: $00),      {46 ???}
+   (n : $47; s : $47; c : $77; a: $97),      {47 Home}
+   (n : $48; s : $00; c : $8D; a: $98),      {48 Up}
+   (n : $49; s : $49; c : $84; a: $99),      {49 PgUp}
+   (n : $4A; s : $00; c : $8E; a: $4A),      {4A -}
+   (n : $4B; s : $4B; c : $73; a: $9B),      {4B Left}
+   (n : $4C; s : $00; c : $00; a: $00),      {4C ???}
+   (n : $4D; s : $4D; c : $74; a: $9D),      {4D Right}
+   (n : $4E; s : $00; c : $90; a: $4E),      {4E +}
+   (n : $4F; s : $4F; c : $75; a: $9F),      {4F End}
+   (n : $50; s : $50; c : $91; a: $A0),      {50 Down}
+   (n : $51; s : $51; c : $76; a: $A1),      {51 PgDown}
+   (n : $52; s : $52; c : $92; a: $A2),      {52 Insert}
+   (n : $53; s : $53; c : $93; a: $A3),      {53 Del}
+   (n : $54; s : $00; c : $00; a: $00),      {54 ???}
+   (n : $55; s : $00; c : $00; a: $00),      {55 ???}
+   (n : $56; s : $00; c : $00; a: $00),      {56 ???}
+   (n : $85; s : $87; c : $89; a: $8B),      {57 F11}
+   (n : $86; s : $88; c : $8A; a: $8C));     {58 F12}
+
+ DosTT09 : ARRAY [$02..$0F] OF TTEntryT =
+  ((n : $00; s : $00; c : $00; a: $78),      {02 1 }
+   (n : $00; s : $00; c : $00; a: $79),      {03 2 }
+   (n : $00; s : $00; c : $00; a: $7A),      {04 3 }
+   (n : $00; s : $00; c : $00; a: $7B),      {05 4 }
+   (n : $00; s : $00; c : $00; a: $7C),      {06 5 }
+   (n : $00; s : $00; c : $00; a: $7D),      {07 6 }
+   (n : $00; s : $00; c : $00; a: $7E),      {08 7 }
+   (n : $00; s : $00; c : $00; a: $7F),      {09 8 }
+   (n : $00; s : $00; c : $00; a: $80),      {0A 9 }
+   (n : $00; s : $00; c : $00; a: $81),      {0B 0 }
+   (n : $00; s : $00; c : $00; a: $82),      {0C � }
+   (n : $00; s : $00; c : $00; a: $00),      {0D}
+   (n : $00; s : $09; c : $00; a: $00),      {0E Backspace}
+   (n : $00; s : $0F; c : $94; a: $00));     {0F Tab }
+
+*}
+
+{*
+function TranslateKey (t : TKeyEventRecord) : TKeyEvent;
+var key : TKeyEvent;
+    ss  : byte;
+{$ifdef  USEKEYCODES}
+    ScanCode  : byte;
+{$endif  USEKEYCODES}
+    b   : byte;
+begin
+  Key := 0;
+  if t.bKeyDown then
+  begin
+    { ascii-char is <> 0 if not a specal key }
+    { we return it here otherwise we have to translate more later }
+    if t.AsciiChar <> #0 then
+    begin
+      if (t.dwControlKeyState and ENHANCED_KEY <> 0) and
+         (t.wVirtualKeyCode = $DF) then
+        begin
+          t.dwControlKeyState:=t.dwControlKeyState and not ENHANCED_KEY;
+          t.wVirtualKeyCode:=VK_DIVIDE;
+          t.AsciiChar:='/';
+        end;
+      {drivers needs scancode, we return it here as under dos and linux
+       with $03000000 = the lowest two bytes is the physical representation}
+{$ifdef  USEKEYCODES}
+      Scancode:=KeyToQwertyScan[t.wVirtualKeyCode AND $00FF];
+      If ScanCode>0 then
+        t.wVirtualScanCode:=ScanCode;
+      Key := byte (t.AsciiChar) + (t.wVirtualScanCode shl 8) + $03000000;
+      ss := transShiftState (t.dwControlKeyState);
+      key := key or (ss shl 16);
+      if (ss and kbAlt <> 0) and rightistruealt(t.dwControlKeyState) then
+        key := key and $FFFFFF00;
+{$else not USEKEYCODES}
+      Key := byte (t.AsciiChar) + ((t.wVirtualScanCode AND $00FF) shl 8) + $03000000;
+{$endif not USEKEYCODES}
+    end else
+    begin
+{$ifdef  USEKEYCODES}
+      Scancode:=KeyToQwertyScan[t.wVirtualKeyCode AND $00FF];
+      If ScanCode>0 then
+        t.wVirtualScanCode:=ScanCode;
+{$endif not USEKEYCODES}
+      translateKey := 0;
+      { ignore shift,ctrl,alt,numlock,capslock alone }
+      case t.wVirtualKeyCode of
+        $0010,         {shift}
+        $0011,         {ctrl}
+        $0012,         {alt}
+        $0014,         {capslock}
+        $0090,         {numlock}
+        $0091,         {scrollock}
+        { This should be handled !! }
+        { these last two are OEM specific
+          this is not good !!! }
+        $00DC,         {^ : next key i.e. a is modified }
+        { Strange on my keyboard this corresponds to double point over i or u PM }
+        $00DD: exit;   {� and ` : next key i.e. e is modified }
+      end;
+
+      key := $03000000 + (t.wVirtualScanCode shl 8);  { make lower 8 bit=0 like under dos }
+    end;
+    { Handling of ~ key as AltGr 2 }
+    { This is also French keyboard specific !! }
+    { but without this I can not get a ~ !! PM }
+    { MvdV: not rightruealtised, since it already has frenchkbd guard}
+    if (t.wVirtualKeyCode=$32) and
+       (KeyBoardLayout = FrenchKeyboard) and
+       (t.dwControlKeyState and RIGHT_ALT_PRESSED <> 0) then
+      key:=(key and $ffffff00) or ord('~');
+    { ok, now add Shift-State }
+    ss := transShiftState (t.dwControlKeyState);
+    key := key or (ss shl 16);
+
+    { Reset Ascii-Char if Alt+Key, fv needs that, may be we
+      need it for other special keys too
+      18 Sept 1999 AD: not for right Alt i.e. for AltGr+� = \ on german keyboard }
+    if ((ss and kbAlt <> 0) and rightistruealt(t.dwControlKeyState)) or
+    (*
+      { yes, we need it for cursor keys, 25=left, 26=up, 27=right,28=down}
+      {aggg, this will not work because esc is also virtualKeyCode 27!!}
+      {if (t.wVirtualKeyCode >= 25) and (t.wVirtualKeyCode <= 28) then}
+        no VK_ESCAPE is $1B !!
+        there was a mistake :
+         VK_LEFT is $25 not 25 !! *)
+       { not $2E VK_DELETE because its only the Keypad point !! PM }
+      (t.wVirtualKeyCode in [$21..$28,$2C,$2D,$2F]) then
+      { if t.wVirtualScanCode in [$47..$49,$4b,$4d,$4f,$50..$53] then}
+        key := key and $FFFFFF00;
+
+    {and translate to dos-scancodes to make fv happy, we will convert this
+     back in translateKeyEvent}
+
+     if rightistruealt(t.dwControlKeyState) then {not for alt-gr}
+     if (t.wVirtualScanCode >= low (DosTT)) and
+        (t.wVirtualScanCode <= high (dosTT)) then
+     begin
+       b := 0;
+       if (ss and kbAlt) <> 0 then
+         b := DosTT[t.wVirtualScanCode].a
+       else
+       if (ss and kbCtrl) <> 0 then
+         b := DosTT[t.wVirtualScanCode].c
+       else
+       if (ss and kbShift) <> 0 then
+         b := DosTT[t.wVirtualScanCode].s
+       else
+         b := DosTT[t.wVirtualScanCode].n;
+       if b <> 0 then
+         key := (key and $FFFF00FF) or (longint (b) shl 8);
+     end;
+
+     {Alt-0 to Alt-9}
+     if rightistruealt(t.dwControlKeyState) then {not for alt-gr}
+       if (t.wVirtualScanCode >= low (DosTT09)) and
+          (t.wVirtualScanCode <= high (dosTT09)) then
+       begin
+         b := 0;
+         if (ss and kbAlt) <> 0 then
+           b := DosTT09[t.wVirtualScanCode].a
+         else
+         if (ss and kbCtrl) <> 0 then
+           b := DosTT09[t.wVirtualScanCode].c
+         else
+         if (ss and kbShift) <> 0 then
+           b := DosTT09[t.wVirtualScanCode].s
+         else
+           b := DosTT09[t.wVirtualScanCode].n;
+         if b <> 0 then
+           key := (key and $FFFF0000) or (longint (b) shl 8);
+       end;
+
+     TranslateKey := key;
+  end;
+  translateKey := Key;
+end;
+*}
+
+
+//#define IsMsgPortEmpty(x)  (((x)->mp_MsgList.lh_TailPred) == (struct Node *)(&(x)->mp_MsgList))
+
+function IsMsgPortEmpty(port: PMsgPort): boolean;
+begin
+  IsMsgPortEmpty:=(port^.mp_MsgList.lh_TailPred = @(port^.mp_MsgList));
+end;
+
+
+function SysPollKeyEvent: TKeyEvent;
+//var t   : TKeyEventRecord;
+//    k   : TKeyEvent;
+var
+  iMsg : PIntuiMessage;
+  KeyCode: longint;
+begin
+  KeyCode:=0;
+  SysPollKeyEvent:=0;
+//  writeln('keyboard/SysPollKeyEvent');
+  if videoWindow<>nil then begin
+    if IsMsgPortEmpty(videoWindow^.UserPort) then exit;
+  end;
+    PMessage(iMsg):=GetMsg(videoWindow^.UserPort);
+    if (iMsg<>nil) then begin
+//      writeln('got msg!');
+      case (iMsg^.iClass) of
+        IDCMP_VANILLAKEY: begin
+            writeln('vanilla keycode: ',iMsg^.code);
+            KeyCode:=iMsg^.code;
+            case (iMsg^.code) of
+               09: KeyCode:=$0F09; // Tab
+               13: KeyCode:=$1C0D; // Enter 
+               27: KeyCode:=$011B; // ESC
+              
+              127: KeyCode:=$5300; // Del
+
+              164: KeyCode:=$1200; // Alt-E
+              215: KeyCode:=$2D00; // Alt-X
+
+            end;
+          end;
+        IDCMP_RAWKEY: begin
+            writeln('raw keycode: ',iMsg^.code);
+            case (iMsg^.code) of
+               35: KeyCode:=$2100; // Alt-F
+               
+               71: KeyCode:=$5200; // Ins (Alt/Shift/Ctrl codes needs processing!)
+
+               72: KeyCode:=$4900; // PgUP
+               73: KeyCode:=$5100; // PgDOWN
+
+               76: KeyCode:=$4800; // UP
+               77: KeyCode:=$5000; // DOWN
+               78: KeyCode:=$4D00; // RIGHT
+               79: KeyCode:=$4B00; // LEFT
+
+               80..89: KeyCode:=($3B+(iMsg^.code-80)) shl 8; // F1..F10
+
+              112: KeyCode:=$4700; // HOME
+              113: KeyCode:=$4F00; // END
+
+              else
+                KeyCode:=-1;
+            end;
+          end;
+        else begin
+            KeyCode:=-1;
+          end;
+      end;
+      ReplyMsg(PMessage(iMsg));
+    end;
+//  end;
+
+  // XXX: huh :)
+  if KeyCode>=0 then begin
+    SysPollKeyEvent:=KeyCode or (kbPhys shl 24);
+  end else begin
+    SysPollKeyEvent:=0;
+  end;
+{*
+  SysPollKeyEvent := 0;
+  if getKeyEventFromQueue (t, true) then
+  begin
+    { we get an enty for shift, ctrl, alt... }
+    k := translateKey (t);
+    while (k = 0) do
+    begin
+      getKeyEventFromQueue (t, false);  {remove it}
+      if not getKeyEventFromQueue (t, true) then exit;
+      k := translateKey (t)
+    end;
+    SysPollKeyEvent := k;
+  end;
+*}
+end;
+
+
+
+function SysGetKeyEvent: TKeyEvent;
+//var t   : TKeyEventRecord;
+//    key : TKeyEvent;
+var
+  iMsg : PIntuiMessage;
+  res: TKeyEvent;
+begin
+{*
+  key := 0;
+  repeat
+     if getKeyEventFromQueueWait (t) then
+       key := translateKey (t);
+  until key <> 0;
+{$ifdef DEBUG}
+  last_ir.Event.KeyEvent:=t;
+{$endif DEBUG}
+  SysGetKeyEvent := key;
+*}
+
+//  writeln('keyboard/SysGetKeyEvent');
+  if videoWindow<>nil then begin
+    repeat
+      WaitPort(videoWindow^.UserPort);
+      res:=SysPollKeyEvent;
+    until res<>0;
+  end;
+{*
+  if videoWindow<>nil then begin
+    WaitPort(videoWindow^.UserPort);
+    PMessage(iMsg):=GetMsg(videoWindow^.UserPort);
+    if (iMsg<>nil) then begin
+      writeln('got msg!');
+      ReplyMsg(PMessage(iMsg));
+    end;
+  end;
+*}
+end;
+
+
+
+function SysTranslateKeyEvent(KeyEvent: TKeyEvent): TKeyEvent;
+begin
+{*
+  if KeyEvent and $03000000 = $03000000 then
+   begin
+     if KeyEvent and $000000FF <> 0 then
+     begin
+       SysTranslateKeyEvent := KeyEvent and $00FFFFFF;
+       exit;
+     end;
+     {translate function-keys and other specials, ascii-codes are already ok}
+     case (KeyEvent AND $0000FF00) shr 8 of
+       {F1..F10}
+       $3B..$44     : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF1 + ((KeyEvent AND $0000FF00) SHR 8) - $3B + $02000000;
+       {F11,F12}
+       $85..$86     : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF11 + ((KeyEvent AND $0000FF00) SHR 8) - $85 + $02000000;
+       {Shift F1..F10}
+       $54..$5D     : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF1 + ((KeyEvent AND $0000FF00) SHR 8) - $54 + $02000000;
+       {Shift F11,F12}
+       $87..$88     : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF11 + ((KeyEvent AND $0000FF00) SHR 8) - $87 + $02000000;
+       {Alt F1..F10}
+       $68..$71     : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF1 + ((KeyEvent AND $0000FF00) SHR 8) - $68 + $02000000;
+       {Alt F11,F12}
+       $8B..$8C     : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF11 + ((KeyEvent AND $0000FF00) SHR 8) - $8B + $02000000;
+       {Ctrl F1..F10}
+       $5E..$67     : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF1 + ((KeyEvent AND $0000FF00) SHR 8) - $5E + $02000000;
+       {Ctrl F11,F12}
+       $89..$8A     : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdF11 + ((KeyEvent AND $0000FF00) SHR 8) - $89 + $02000000;
+
+       {normal,ctrl,alt}
+       $47,$77,$97  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdHome + $02000000;
+       $48,$8D,$98  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdUp + $02000000;
+       $49,$84,$99  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdPgUp + $02000000;
+       $4b,$73,$9B  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdLeft + $02000000;
+       $4d,$74,$9D  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdRight + $02000000;
+       $4f,$75,$9F  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdEnd + $02000000;
+       $50,$91,$A0  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdDown + $02000000;
+       $51,$76,$A1  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdPgDn + $02000000;
+       $52,$92,$A2  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdInsert + $02000000;
+       $53,$93,$A3  : SysTranslateKeyEvent := (KeyEvent AND $FCFF0000) + kbdDelete + $02000000;
+     else
+       SysTranslateKeyEvent := KeyEvent;
+     end;
+   end else
+     SysTranslateKeyEvent := KeyEvent;
+*}
+end;
+
+
+function SysGetShiftState: Byte;
+
+begin
+  {may be better to save the last state and return that if no key is in buffer???}
+//  SysGetShiftState:= lastShiftState;
+end;
+
+Const
+  SysKeyboardDriver : TKeyboardDriver = (
+    InitDriver : @SysInitKeyBoard;
+    DoneDriver : @SysDoneKeyBoard;
+    GetKeyevent : @SysGetKeyEvent;
+    PollKeyEvent : @SysPollKeyEvent;
+    GetShiftState : @SysGetShiftState;
+//    TranslateKeyEvent : @SysTranslateKeyEvent;
+    TranslateKeyEvent : Nil;
+    TranslateKeyEventUnicode : Nil;
+  );
+
+
+begin
+  SetKeyBoardDriver(SysKeyBoardDriver);
+end.
diff --git a/rtl/morphos/kvm.pp b/rtl/morphos/kvm.pp
new file mode 100644
index 0000000000..a16d920821
--- /dev/null
+++ b/rtl/morphos/kvm.pp
@@ -0,0 +1,78 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2006 Karoly Balogh
+    member of the Free Pascal Development Team
+
+    Keyboard/Video/Mouse helper unit for Amiga/MorphOS
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+unit kvm;
+
+interface
+
+uses
+  exec, intuition, graphics;
+
+
+function initKVM: boolean;
+procedure doneKVM;
+
+
+
+implementation
+
+
+var
+  kvmWindow: PWindow;
+
+const
+  DEFAULT_WINWIDTH  = 80;
+  DEFAULT_WINHEIGHT = 25;
+
+const
+  CHAR_XSIZE = 8;
+  CHAR_YSIZE = 16;
+
+
+
+
+function initKVM: boolean;
+begin
+  initKVM:=false;
+  kvmWindow:=OpenWindowTags(nil, [
+      WA_Left,50,
+      WA_Top, 50,
+      WA_InnerWidth, DEFAULT_WINWIDTH *CHAR_XSIZE,
+      WA_InnerHeight,DEFAULT_WINHEIGHT*CHAR_YSIZE,
+      WA_IDCMP, IDCMP_VANILLAKEY or IDCMP_RAWKEY,
+      WA_Title,DWord(PChar('Free Pascal Video Output')),
+      WA_Flags,(WFLG_GIMMEZEROZERO or 
+                WFLG_SMART_REFRESH or 
+                WFLG_NOCAREREFRESH or 
+                WFLG_ACTIVATE      or 
+                WFLG_DRAGBAR       or 
+                WFLG_DEPTHGADGET)
+    ]);
+
+  if kvmWindow<>nil then initKVM:=true;
+end;
+
+
+procedure doneKVM;
+begin
+  if kvmWindow <> nil then CloseWindow(kvmWindow);
+end;
+
+
+begin
+  InitGraphicsLibrary;
+  InitIntuitionLibrary;
+end.
diff --git a/rtl/morphos/mouse.pp b/rtl/morphos/mouse.pp
new file mode 100644
index 0000000000..9798bad401
--- /dev/null
+++ b/rtl/morphos/mouse.pp
@@ -0,0 +1,275 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2006 Karoly Balogh
+    member of the Free Pascal development team
+
+    Mouse unit for Amiga/MorphOS
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit Mouse;
+interface
+
+{$i mouseh.inc}
+
+implementation
+
+//uses
+//   windows,dos,Winevent;
+
+{$i mouse.inc}
+
+//var
+//   ChangeMouseEvents : TCriticalSection;
+//   LastHandlerMouseEvent : TMouseEvent;
+
+{
+procedure MouseEventHandler(var ir:INPUT_RECORD);
+  var
+     e : TMouseEvent;
+
+  begin
+    EnterCriticalSection(ChangeMouseEvents);
+    e.x:=ir.Event.MouseEvent.dwMousePosition.x;
+    e.y:=ir.Event.MouseEvent.dwMousePosition.y;
+    e.buttons:=0;
+    e.action:=0;
+    if (ir.Event.MouseEvent.dwButtonState and FROM_LEFT_1ST_BUTTON_PRESSED<>0) then
+      e.buttons:=e.buttons or MouseLeftButton;
+    if (ir.Event.MouseEvent.dwButtonState and FROM_LEFT_2ND_BUTTON_PRESSED<>0) then
+      e.buttons:=e.buttons or MouseMiddleButton;
+    if (ir.Event.MouseEvent.dwButtonState and RIGHTMOST_BUTTON_PRESSED<>0) then
+      e.buttons:=e.buttons or MouseRightButton;
+
+    if (Lasthandlermouseevent.x<>e.x) or (LasthandlerMouseEvent.y<>e.y) then
+      e.Action:=MouseActionMove;
+    if (LastHandlerMouseEvent.Buttons<>e.Buttons) then
+     begin
+      if (LasthandlerMouseEvent.Buttons and e.buttons<>LasthandlerMouseEvent.Buttons) then
+        e.Action:=MouseActionUp
+      else
+        e.Action:=MouseActionDown;
+     end;
+
+
+//
+//  The mouse event compression here was flawed and could lead
+//  to "zero" mouse actions if the new (x,y) was the same as the
+//  previous one. (bug 2312)
+//
+
+     { can we compress the events? }
+   if (PendingMouseEvents>0) and
+      (e.buttons=PendingMouseTail^.buttons) and
+      (e.action=PendingMouseTail^.action) then
+      begin
+         PendingMouseTail^.x:=e.x;
+         PendingMouseTail^.y:=e.y;
+      end
+    else
+      begin
+         if e.action<>0 then
+           begin
+             LastHandlermouseEvent:=e;
+
+             { what till there is again space in the mouse event queue }
+             while PendingMouseEvents>=MouseEventBufSize do
+               begin
+                 LeaveCriticalSection(ChangeMouseEvents);
+                 sleep(0);
+                 EnterCriticalSection(ChangeMouseEvents);
+               end;
+
+             PutMouseEvent(e);
+           end;
+         // this should be done in PutMouseEvent, now it is PM
+         // inc(PendingMouseEvents);
+      end;
+    LastMouseEvent:=e;
+    LeaveCriticalSection(ChangeMouseEvents);
+  end;
+}
+procedure SysInitMouse;
+
+var
+   mode : dword;
+
+begin
+{
+  // enable mouse events
+  GetConsoleMode(StdInputHandle,@mode);
+  mode:=mode or ENABLE_MOUSE_INPUT;
+  SetConsoleMode(StdInputHandle,mode);
+
+  PendingMouseHead:=@PendingMouseEvent;
+  PendingMouseTail:=@PendingMouseEvent;
+  PendingMouseEvents:=0;
+  FillChar(LastMouseEvent,sizeof(TMouseEvent),0);
+  InitializeCriticalSection(ChangeMouseEvents);
+  SetMouseEventHandler(@MouseEventHandler);
+  ShowMouse;
+}
+end;
+
+
+procedure SysDoneMouse;
+var
+   mode : dword;
+begin
+{
+  HideMouse;
+  // disable mouse events
+  GetConsoleMode(StdInputHandle,@mode);
+  mode:=mode and (not ENABLE_MOUSE_INPUT);
+  SetConsoleMode(StdInputHandle,mode);
+
+  SetMouseEventHandler(nil);
+  DeleteCriticalSection(ChangeMouseEvents);
+}
+end;
+
+
+function SysDetectMouse:byte;
+var
+  num : dword;
+begin
+  // Under Amiga/MorphOS, mouse is always there, and it's unable to easily
+  // detect number of buttons. So lets report 3, which is common nowadays. (KB)
+  SysDetectMouse:=3;
+end;
+
+
+procedure SysGetMouseEvent(var MouseEvent: TMouseEvent);
+
+var
+   b : byte;
+
+begin
+{
+  repeat
+    EnterCriticalSection(ChangeMouseEvents);
+    b:=PendingMouseEvents;
+    LeaveCriticalSection(ChangeMouseEvents);
+    if b>0 then
+      break
+    else
+      sleep(50);
+  until false;
+  EnterCriticalSection(ChangeMouseEvents);
+  MouseEvent:=PendingMouseHead^;
+  inc(PendingMouseHead);
+  if ptrint(PendingMouseHead)=ptrint(@PendingMouseEvent)+sizeof(PendingMouseEvent) then
+   PendingMouseHead:=@PendingMouseEvent;
+  dec(PendingMouseEvents);
+
+  { LastMouseEvent is already set at the end of the mouse event handler,
+    so this code might compare LastMouseEvent with itself leading to
+    "empty" events (FK)
+
+  if (LastMouseEvent.x<>MouseEvent.x) or (LastMouseEvent.y<>MouseEvent.y) then
+   MouseEvent.Action:=MouseActionMove;
+  if (LastMouseEvent.Buttons<>MouseEvent.Buttons) then
+   begin
+     if (LastMouseEvent.Buttons and MouseEvent.buttons<>LastMouseEvent.Buttons) then
+       MouseEvent.Action:=MouseActionUp
+     else
+       MouseEvent.Action:=MouseActionDown;
+   end;
+  if MouseEvent.action=0 then
+    MousEevent.action:=MouseActionMove; // can sometimes happen due to compression of events.
+  LastMouseEvent:=MouseEvent;
+  }
+
+  LeaveCriticalSection(ChangeMouseEvents);
+}
+end;
+
+
+function SysPollMouseEvent(var MouseEvent: TMouseEvent):boolean;
+begin
+{
+  EnterCriticalSection(ChangeMouseEvents);
+  if PendingMouseEvents>0 then
+   begin
+     MouseEvent:=PendingMouseHead^;
+     SysPollMouseEvent:=true;
+   end
+  else
+   SysPollMouseEvent:=false;
+  LeaveCriticalSection(ChangeMouseEvents);
+}
+end;
+
+
+procedure SysPutMouseEvent(const MouseEvent: TMouseEvent);
+begin
+{
+  if PendingMouseEvents<MouseEventBufSize then
+   begin
+     PendingMouseTail^:=MouseEvent;
+     inc(PendingMouseTail);
+     if ptrint(PendingMouseTail)=ptrint(@PendingMouseEvent)+sizeof(PendingMouseEvent) then
+      PendingMouseTail:=@PendingMouseEvent;
+      { why isn't this done here ?
+        so the win32 version do this by hand:}
+       inc(PendingMouseEvents);
+   end;
+}
+end;
+
+
+function SysGetMouseX:word;
+begin
+{
+  EnterCriticalSection(ChangeMouseEvents);
+  SysGetMouseX:=LastMouseEvent.x;
+  LeaveCriticalSection(ChangeMouseEvents);
+}
+end;
+
+
+function SysGetMouseY:word;
+begin
+{
+  EnterCriticalSection(ChangeMouseEvents);
+  SysGetMouseY:=LastMouseEvent.y;
+  LeaveCriticalSection(ChangeMouseEvents);
+}
+end;
+
+
+function SysGetMouseButtons:word;
+begin
+{
+  EnterCriticalSection(ChangeMouseEvents);
+  SysGetMouseButtons:=LastMouseEvent.Buttons;
+  LeaveCriticalSection(ChangeMouseEvents);
+}
+end;
+
+const
+  SysMouseDriver : TMouseDriver = (
+    UseDefaultQueue : False;
+    InitDriver      : @SysInitMouse;
+    DoneDriver      : @SysDoneMouse;
+    DetectMouse     : @SysDetectMouse;
+    ShowMouse       : Nil;
+    HideMouse       : Nil;
+    GetMouseX       : @SysGetMouseX;
+    GetMouseY       : @SysGetMouseY;
+    GetMouseButtons : @SysGetMouseButtons;
+    SetMouseXY      : Nil;
+    GetMouseEvent   : @SysGetMouseEvent;
+    PollMouseEvent  : @SysPollMouseEvent;
+    PutMouseEvent   : @SysPutMouseEvent;
+  );
+
+begin
+  SetMouseDriver(SysMouseDriver);
+end.
diff --git a/rtl/morphos/video.pp b/rtl/morphos/video.pp
new file mode 100644
index 0000000000..d17a9dc169
--- /dev/null
+++ b/rtl/morphos/video.pp
@@ -0,0 +1,428 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2006 by Karoly Balogh
+    member of the Free Pascal development team
+
+    Video unit for Amiga and MorphOS
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit Video;
+
+interface
+
+uses
+  intuition;
+
+{$i videoh.inc}
+
+var
+   videoWindow   : pWindow; 
+
+implementation
+
+uses
+//   dos
+   exec,graphics;
+
+{$i video.inc}
+
+{$i videodata.inc}
+
+const
+    LastCursorType: word = crUnderline;
+    OrigScreen: PVideoBuf = nil;
+    OrigScreenSize: cardinal = 0;
+
+var
+   videoColorMap : pColorMap;
+   videoPens     : array[0..15] of longint;
+
+   oldCursorX, oldCursorY: longint;
+   visibleCursor: boolean;
+   oldvisibleCursor: boolean;
+
+procedure SysInitVideo;
+var counter: longint;
+begin
+   writeln('sysinitvideo');
+   InitGraphicsLibrary;
+   InitIntuitionLibrary;
+{
+  ScreenColor:=true;
+  GetConsoleScreenBufferInfo(TextRec(Output).Handle, OrigConsoleInfo);
+  GetConsoleCursorInfo(TextRec(Output).Handle, OrigConsoleCursorInfo);
+  OrigCP := GetConsoleCP;
+  ConsoleInfo:=OrigConsoleInfo;
+  ConsoleCursorInfo:=OrigConsoleCursorInfo;
+  {
+    About the ConsoleCursorInfo record: There are 3 possible
+    structures in it that can be regarded as the 'screen':
+    - dwsize   : contains the cols & row in current screen buffer.
+    - srwindow : Coordinates (relative to buffer) of upper left
+                 & lower right corners of visible console.
+    - dmMaximumWindowSize : Maximal size of Screen buffer.
+    The first implementation of video used srWindow. After some
+    bug-reports, this was switched to dwMaximumWindowSize.
+  }
+  with ConsoleInfo.dwMaximumWindowSize do
+    begin
+    ScreenWidth:=X;
+    ScreenHeight:=Y;
+    end;
+  { TDrawBuffer only has FVMaxWidth elements
+    larger values lead to crashes }
+  if ScreenWidth> FVMaxWidth then
+    ScreenWidth:=FVMaxWidth;
+  CursorX:=ConsoleInfo.dwCursorPosition.x;
+  CursorY:=ConsoleInfo.dwCursorPosition.y;
+  if not ConsoleCursorInfo.bvisible then
+    CursorLines:=0
+  else
+    CursorLines:=ConsoleCursorInfo.dwSize;
+}
+   videoWindow:=OpenWindowTags(Nil, [
+      WA_Left,50,
+      WA_Top,50,
+      WA_InnerWidth,80*8,
+      WA_InnerHeight,25*16,
+//      WA_IDCMP,IDCMP_MOUSEBUTTONS Or IDCMP_RAWKEYS,
+      WA_IDCMP,IDCMP_VANILLAKEY Or IDCMP_RAWKEY,
+      WA_Title,DWord(PChar('Free Pascal Video Output')),
+      WA_Flags,(WFLG_GIMMEZEROZERO Or WFLG_SMART_REFRESH Or WFLG_NOCAREREFRESH Or WFLG_ACTIVATE Or WFLG_DRAGBAR Or WFLG_DEPTHGADGET)
+   ]);
+
+   ScreenWidth := 80;
+   ScreenHeight := 25;
+
+   videoColorMap := pScreen(videoWindow^.WScreen)^.ViewPort.ColorMap;
+   for counter:=0 to 15 do begin
+     videoPens[counter]:=ObtainPen(videoColorMap,-1,
+         vgacolors[counter,0] shl 24,vgacolors[counter,1] shl 24,vgacolors[counter,2] shl 24,
+         PEN_EXCLUSIVE);
+//     writeln(videoPens[counter]);
+     // XXX: do checks for -1 colors (KB)
+   end;
+
+   CursorX:=0;
+   CursorY:=0;
+   oldCursorX:=0;
+   oldCursorY:=0;
+   visibleCursor:=true;
+   oldvisibleCursor:=true;
+end;
+
+
+procedure SysDoneVideo;
+var counter: longint;
+begin
+   if videoWindow<>nil then CloseWindow(videoWindow);
+   for counter:=0 to 15 do ReleasePen(videoColorMap,videoPens[counter]);
+ 
+{
+  SetConsoleScreenBufferSize (TextRec (Output).Handle, OrigConsoleInfo.dwSize);
+  SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, OrigConsoleInfo.srWindow);
+  SetConsoleCursorInfo(TextRec(Output).Handle, OrigConsoleCursorInfo);
+  SetConsoleCP(OrigCP);
+}
+end;
+
+
+
+function SysVideoModeSelector (const VideoMode: TVideoMode): boolean;
+
+{
+var MI: Console_Screen_Buffer_Info;
+    C: Coord;
+    SR: Small_Rect;
+}
+begin
+{
+  if not (GetConsoleScreenBufferInfo (TextRec (Output).Handle, MI)) then
+    SysVideoModeSelector := false
+  else
+    begin
+      with MI do
+        begin
+          C.X := VideoMode.Col;
+          C.Y := VideoMode.Row;
+        end;
+      with SR do
+        begin
+          Top := 0;
+          Left := 0;
+          { First, we need to make sure we reach the minimum window size
+            to always fit in the new buffer after changing buffer size. }
+          Right := MI.srWindow.Right - MI.srWindow.Left;
+          if VideoMode.Col <= Right then
+            Right := Pred (VideoMode.Col);
+          Bottom := MI.srWindow.Bottom - MI.srWindow.Top;
+          if VideoMode.Row <= Bottom then
+            Bottom := Pred (VideoMode.Row);
+        end;
+      if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
+        if SetConsoleScreenBufferSize (TextRec (Output).Handle, C) then
+          begin
+            with SR do
+              begin
+                { Now, we can resize the window to the final size. }
+                Right := Pred (VideoMode.Col);
+                Bottom := Pred (VideoMode.Row);
+              end;
+            if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
+              begin
+                SysVideoModeSelector := true;
+                SetCursorType (LastCursorType);
+                ClearScreen;
+              end
+            else
+              begin
+                SysVideoModeSelector := false;
+                SetConsoleScreenBufferSize (TextRec (Output).Handle, MI.dwSize);
+                SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
+                SetCursorType (LastCursorType);
+              end
+          end
+        else
+          begin
+            SysVideoModeSelector := false;
+            SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
+            SetCursorType (LastCursorType);
+          end
+      else
+        SysVideoModeSelector := false;
+    end;
+}
+end;
+
+Const
+  SysVideoModeCount = 6;
+  SysVMD : Array[0..SysVideoModeCount-1] of TVideoMode = (
+   (Col: 40; Row: 25; Color: True),
+   (Col: 80; Row: 25; Color: True),
+   (Col: 80; Row: 30; Color: True),
+   (Col: 80; Row: 43; Color: True),
+   (Col: 80; Row: 50; Color: True),
+   (Col: 80; Row: 25; Color: True) // Reserved for TargetEntry
+  );
+
+
+Function SysSetVideoMode (Const Mode : TVideoMode) : Boolean;
+
+Var
+  I : Integer;
+
+begin
+{
+  I:=SysVideoModeCount-1;
+  SysSetVideoMode:=False;
+  While (I>=0) and Not SysSetVideoMode do
+    If (Mode.col=SysVMD[i].col) and
+       (Mode.Row=SysVMD[i].Row) and
+       (Mode.Color=SysVMD[i].Color) then
+      SysSetVideoMode:=True
+    else
+      Dec(I);
+  If SysSetVideoMode then
+    begin
+    if SysVideoModeSelector(Mode) then
+      begin
+      ScreenWidth:=SysVMD[I].Col;
+      ScreenHeight:=SysVMD[I].Row;
+      ScreenColor:=SysVMD[I].Color;
+      end else SysSetVideoMode := false;
+    end;
+}
+end;
+
+Function SysGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
+
+begin
+  SysGetVideoModeData:=(Index<=high(SysVMD));
+  If SysGetVideoModeData then
+    Data:=SysVMD[Index];
+end;
+
+Function SysGetVideoModeCount : Word;
+
+begin
+  SysGetVideoModeCount:=SysVideoModeCount;
+end;
+
+procedure SysClearScreen;
+begin
+  UpdateScreen(true);
+end;
+
+
+procedure DrawChar(x,y: longint; bitmap: pBitmap; drawCursor: boolean);
+var tmpCharData: word;
+    tmpChar    : byte;
+    tmpRow     : byte;
+    tmpFGColor : byte;
+    tmpBGColor : byte;
+var
+    counterX, counterY:longint;
+    sX,sY: longint;
+begin
+  tmpCharData:=VideoBuf^[y*ScreenWidth+x];
+  tmpChar    :=tmpCharData and $0ff;
+  tmpFGColor :=(tmpCharData shr 8) and %00001111;
+  tmpBGColor :=(tmpCharData shr 12) and %00000111;
+  
+//  write('"',char(tmpChar),'" ',tmpChar);
+  sX:=x*8;
+  sY:=y*16;
+
+  SetAPen(videoWindow^.RPort,videoPens[tmpBGColor]);
+  RectFill(videoWindow^.RPort, sX, sY, sX + 7, sY + 15);
+
+  SetAPen(videoWindow^.Rport,videoPens[tmpFGColor]);
+  for counterY:=0 to 15 do begin
+    tmpRow:=vgafont[tmpChar,counterY];
+    if (tmpRow>0) then begin
+      for counterX:=0 to 7 do begin
+         if ((tmpRow and (1 shl counterX)) > 0) then
+            WritePixel(videoWindow^.RPort,sX+counterX,sY+counterY);
+      end;
+    end;
+  end;
+  if drawCursor then begin
+     gfxMove(videoWindow^.RPort,sX,sY+14); Draw(videoWindow^.RPort,sX+7,sY+14);
+     gfxMove(videoWindow^.RPort,sX,sY+15); Draw(videoWindow^.RPort,sX+7,sY+15);
+  end;
+
+end;
+
+
+procedure SysUpdateScreen(force: boolean);
+var
+   BufCounter  : Longint;
+   smallforce  : boolean;
+
+   counter, counterX, counterY: longint;
+var
+   tmpBitmap   : tBitmap;
+begin
+  if force then
+    smallforce:=true
+  else begin
+    counter:=0;
+    while not smallforce and (counter<(VideoBufSize div 4)-1) do begin
+      if PDWord(VideoBuf)[counter]<>PDWord(OldVideoBuf)[counter] then smallforce:=true;
+      counter+=1;
+    end;
+  end;
+
+  BufCounter:=0;
+  if smallforce then begin
+    for counterY:=0 to ScreenHeight-1 do begin
+      for counterX:=0 to ScreenWidth-1 do begin
+        if VideoBuf^[BufCounter]<>OldVideoBuf^[BufCounter] then
+          DrawChar(counterX,counterY,@tmpBitmap,false);
+        Inc(BufCounter);
+      end;
+    end;
+    move(VideoBuf^,OldVideoBuf^,VideoBufSize);
+  end;
+
+  if (oldvisibleCursor<>visibleCursor) or (CursorX<>oldCursorX) or (CursorY<>oldCursorY) then begin
+    writeln('kurzor:',cursorx,' ',cursory);
+    DrawChar(oldCursorY,oldCursorX,@tmpBitmap,false);
+    DrawChar(CursorY,CursorX,@tmpBitmap,visibleCursor);
+    oldCursorX:=CursorX;
+    oldCursorY:=CursorY;
+    oldVisibleCursor:=visibleCursor;
+  end;
+end;
+
+
+procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
+begin
+  CursorX:=NewCursorY;
+  CursorY:=NewCursorX;
+  SysUpdateScreen(false);
+end;
+
+function SysGetCapabilities: Word;
+begin
+  SysGetCapabilities:=cpColor or cpChangeCursor;
+end;
+
+function SysGetCursorType: Word;
+begin
+  if not visibleCursor then SysGetCursorType:=crHidden 
+                       else SysGetCursorType:=crUnderline;
+ 
+{
+   GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
+   if not ConsoleCursorInfo.bvisible then
+     SysGetCursorType:=crHidden
+   else
+     case ConsoleCursorInfo.dwSize of
+        1..30:
+          SysGetCursorType:=crUnderline;
+        31..70:
+          SysGetCursorType:=crHalfBlock;
+        71..100:
+          SysGetCursorType:=crBlock;
+     end;
+}
+end;
+
+
+procedure SysSetCursorType(NewType: Word);
+begin
+  if newType=crHidden then visibleCursor:=false
+                      else visibleCursor:=true;
+  SysUpdateScreen(false);
+{
+   GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
+   if newType=crHidden then
+     ConsoleCursorInfo.bvisible:=false
+   else
+     begin
+        ConsoleCursorInfo.bvisible:=true;
+        case NewType of
+           crUnderline:
+             ConsoleCursorInfo.dwSize:=10;
+
+           crHalfBlock:
+             ConsoleCursorInfo.dwSize:=50;
+
+           crBlock:
+             ConsoleCursorInfo.dwSize:=99;
+        end
+     end;
+   SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
+}
+end;
+
+
+
+const
+  SysVideoDriver : TVideoDriver = (
+    InitDriver : @SysInitVideo;
+    DoneDriver : @SysDoneVideo;
+    UpdateScreen : @SysUpdateScreen;
+    ClearScreen : @SysClearScreen;
+    SetVideoMode : @SysSetVideoMode;
+    GetVideoModeCount : @SysGetVideoModeCount;
+    GetVideoModeData : @SysGetVideoModeData;
+    SetCursorPos : @SysSetCursorPos;
+    GetCursorType : @SysGetCursorType;
+    SetCursorType : @SysSetCursorType;
+    GetCapabilities : @SysGetCapabilities
+
+  );
+
+
+initialization
+  SetVideoDriver(SysVideoDriver);
+end.