Hello,

this patch includes
 – framebuffer pages for the kernel console.
 – a german keyboard layout


Greetings

Sebastian Köln
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [email protected]\
#   xb0q6vcatglacxwn
# target_branch: file:///home/sebk/src/HelenOS_amd64/
# testament_sha1: e7442271c9bcea188d9cfcb401f8a6e238efbdd1
# timestamp: 2014-03-15 16:51:12 +0100
# source_branch: bzr://bzr.helenos.org/mainline
# base_revision_id: [email protected]\
#   knzz139kseh0g2zl
# 
# Begin patch
=== modified file 'kernel/genarch/src/fb/fb.c'
--- kernel/genarch/src/fb/fb.c	2013-04-09 17:42:52 +0000
+++ kernel/genarch/src/fb/fb.c	2014-03-15 15:48:26 +0000
@@ -54,6 +54,7 @@
 #define BG_COLOR     0x001620
 #define FG_COLOR     0xf3cf65
 #define INV_COLOR    0xaaaaaa
+#define FB_PAGES 10 /* how many pages the pager contains */
 
 #define RED(x, bits)    (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
 #define GREEN(x, bits)  (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
@@ -69,7 +70,7 @@
 	((y) * (instance)->scanline + (x) * (instance)->pixelbytes)
 
 #define BB_POS(instance, col, row) \
-	((row) * (instance)->cols + (col))
+	((((instance)->first_row + (row)) % (instance)->rows) * (instance)->cols + (col))
 
 #define GLYPH_POS(instance, glyph, y) \
 	((glyph) * (instance)->glyphbytes + (y) * (instance)->glyphscanline)
@@ -91,7 +92,7 @@
 	unsigned int xres;
 	unsigned int yres;
 	
-	unsigned int rowtrim;
+	unsigned int rowtrim; /** number of rows that fit on the screen */
 	
 	unsigned int scanline;
 	unsigned int glyphscanline;
@@ -101,9 +102,14 @@
 	unsigned int bgscanbytes;
 	
 	unsigned int cols;
-	unsigned int rows;
-	
-	unsigned int position;
+	unsigned int rows; /** Number of rows in the backbuffer */
+	unsigned int first_row; /** First row of backbuffer that is visible on the screen */
+	
+	unsigned int position; /** Position relative to first_row */
+	
+	/** Visible offset in rows between active write and view row.
+	 *  Valid range: [ 0, rows - rowtrim ) */
+	unsigned int page_row_offset;
 } fb_instance_t;
 
 static void fb_putchar(outdev_t *dev, wchar_t ch);
@@ -239,7 +245,7 @@
 	if ((!instance->parea.mapped) || (console_override)) {
 		unsigned int row;
 		
-		for (row = 0; row < instance->rows; row++) {
+		for (row = 0; row < instance->rowtrim; row++) {
 			unsigned int y = ROW2Y(row);
 			unsigned int yd;
 			
@@ -251,7 +257,7 @@
 				    col++, x += FONT_WIDTH) {
 					uint16_t glyph;
 					
-					if (row < instance->rows - 1) {
+					if (row < instance->rowtrim - 1) {
 						if (instance->backbuf[BB_POS(instance, col, row)] ==
 						    instance->backbuf[BB_POS(instance, col, row + 1)])
 							continue;
@@ -268,9 +274,11 @@
 		}
 	}
 	
-	memmove(instance->backbuf, &instance->backbuf[BB_POS(instance, 0, 1)],
-	    instance->cols * (instance->rows - 1) * sizeof(uint16_t));
-	memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
+	instance->first_row++;
+	if( instance->first_row >= 2 * instance->rows )
+		instance->first_row -= instance->rows;
+	
+	memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rowtrim - 1)],
 	    instance->cols, 0);
 }
 
@@ -343,44 +351,92 @@
 	fb_instance_t *instance = (fb_instance_t *) dev->data;
 	spinlock_lock(&instance->lock);
 	
-	switch (ch) {
-	case '\n':
-		cursor_remove(instance);
-		instance->position += instance->cols;
-		instance->position -= instance->position % instance->cols;
-		break;
-	case '\r':
-		cursor_remove(instance);
-		instance->position -= instance->position % instance->cols;
-		break;
-	case '\b':
-		cursor_remove(instance);
-		if (instance->position % instance->cols)
-			instance->position--;
-		break;
-	case '\t':
-		cursor_remove(instance);
-		do {
-			glyph_draw(instance, fb_font_glyph(' '),
-			    instance->position % instance->cols,
-			    instance->position / instance->cols, false);
-			instance->position++;
-		} while (((instance->position % instance->cols) % 8 != 0) &&
-		    (instance->position < instance->cols * instance->rows));
-		break;
-	default:
-		glyph_draw(instance, fb_font_glyph(ch),
-		    instance->position % instance->cols,
-		    instance->position / instance->cols, false);
-		instance->position++;
-	}
-	
-	if (instance->position >= instance->cols * instance->rows) {
-		instance->position -= instance->cols;
-		screen_scroll(instance);
-	}
-	
-	cursor_put(instance);
+	if (ch == U_PAGE_UP) {
+		unsigned int move_rows = instance->rowtrim / 2;
+		
+		/* are we still in the valid range? */
+		if (move_rows + instance->page_row_offset >= instance->rows - instance->rowtrim) {
+			/* out of range. scroll to the maximum possible offset */
+			move_rows = instance->rows - instance->rowtrim - 1 - instance->page_row_offset;
+		} else if (move_rows > instance->first_row) {
+			/* avoid moving into empty areas */
+			move_rows = instance->first_row;
+		}
+		
+		if (move_rows) {
+			instance->first_row -= move_rows;
+			instance->page_row_offset += move_rows;
+			
+			fb_redraw_internal(instance);
+		}
+	} else if (ch == U_PAGE_DOWN) {
+		unsigned int move_rows = instance->rowtrim / 2;
+		
+		/* are we still in the valid range? */
+		if (move_rows > instance->page_row_offset) {
+			/* out of range. scroll to the maximum possible offset */
+			move_rows = instance->page_row_offset;
+		}
+		
+		if (move_rows) {
+			instance->first_row += move_rows;
+			instance->page_row_offset -= move_rows;
+			
+			fb_redraw_internal(instance);
+			
+			/* if we reached the active screen, restore the cursor */
+			if (instance->page_row_offset == 0)
+				cursor_put(instance);
+		}
+	} else {
+		/* ensure we display the last part of the buffer */
+		if( instance->page_row_offset ) {
+			/* correct offset into backbuffer */
+			instance->first_row += instance->page_row_offset;
+			instance->page_row_offset = 0;
+			
+			fb_redraw_internal(instance);
+		}
+		
+		switch (ch) {
+			case '\n':
+				cursor_remove(instance);
+				instance->position += instance->cols;
+				instance->position -= instance->position % instance->cols;
+				break;
+			case '\r':
+				cursor_remove(instance);
+				instance->position -= instance->position % instance->cols;
+				break;
+			case '\b':
+				cursor_remove(instance);
+				if (instance->position % instance->cols)
+					instance->position--;
+				break;
+			case '\t':
+				cursor_remove(instance);
+				do {
+					glyph_draw(instance, fb_font_glyph(' '),
+						instance->position % instance->cols,
+						instance->position / instance->cols, false);
+					instance->position++;
+				} while (((instance->position % instance->cols) % 8 != 0) &&
+					(instance->position < instance->cols * instance->rowtrim));
+				break;
+			default:
+				glyph_draw(instance, fb_font_glyph(ch),
+					instance->position % instance->cols,
+					instance->position / instance->cols, false);
+				instance->position++;
+		}
+		
+		if (instance->position >= instance->cols * instance->rowtrim) {
+			instance->position -= instance->cols;
+			screen_scroll(instance);
+		}
+		
+		cursor_put(instance);
+	}
 	
 	spinlock_unlock(&instance->lock);
 }
@@ -522,12 +578,14 @@
 	instance->xres = props->x;
 	instance->yres = props->y;
 	instance->scanline = props->scan;
+	instance->first_row = 0;
+	instance->page_row_offset = 0;
 	instance->position = 0;
 	
 	instance->cols = X2COL(instance->xres);
-	instance->rows = Y2ROW(instance->yres);
+	instance->rowtrim = Y2ROW(instance->yres);
 	
-	instance->rowtrim = instance->rows;
+	instance->rows = FB_PAGES * instance->rowtrim;
 	
 	instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
 	instance->glyphbytes = ROW2Y(instance->glyphscanline);

=== modified file 'uspace/drv/bus/usb/usbhid/kbd/conv.c'
--- uspace/drv/bus/usb/usbhid/kbd/conv.c	2012-04-02 15:52:07 +0000
+++ uspace/drv/bus/usb/usbhid/kbd/conv.c	2014-03-15 15:50:37 +0000
@@ -136,7 +136,7 @@
 	[0x51] = KC_DOWN,
 	[0x52] = KC_UP,
 
-	//[0x64] = // some funny key
+	[0x64] = KC_BAR, // only some non-US keyboards
 
 	[0xe0] = KC_LCTRL,
 	[0xe1] = KC_LSHIFT,

=== modified file 'uspace/drv/char/xtkbd/xtkbd.c'
--- uspace/drv/char/xtkbd/xtkbd.c	2012-08-17 11:37:03 +0000
+++ uspace/drv/char/xtkbd/xtkbd.c	2014-03-15 15:50:37 +0000
@@ -95,6 +95,7 @@
 	[0x2b] = KC_BACKSLASH,
 
 	[0x2a] = KC_LSHIFT,
+	[0x56] = KC_BAR,
 
 	[0x2c] = KC_Z,
 	[0x2d] = KC_X,
@@ -281,7 +282,7 @@
 		const kbd_event_type_t type =
 		    (code & 0x80) ? KEY_RELEASE : KEY_PRESS;
 		code &= ~0x80;
-
+		
 		const unsigned key = (code < map_size) ? map[code] : 0;
 		if (key != 0) {
 			async_exch_t *exch =

=== modified file 'uspace/lib/c/include/io/keycode.h'
--- uspace/lib/c/include/io/keycode.h	2012-04-02 15:52:07 +0000
+++ uspace/lib/c/include/io/keycode.h	2014-03-15 15:50:37 +0000
@@ -112,6 +112,8 @@
 	/* Main block row 4 */
 
 	KC_LSHIFT,
+	
+	KC_BAR, /* present on some non-US keyboards: mostly with labels '<' and '>' */
 
 	KC_Z,
 	KC_X,

=== modified file 'uspace/srv/hid/compositor/compositor.c'
--- uspace/srv/hid/compositor/compositor.c	2014-03-01 23:05:38 +0000
+++ uspace/srv/hid/compositor/compositor.c	2014-03-15 15:50:37 +0000
@@ -81,6 +81,7 @@
 #ifndef ANIMATE_WINDOW_TRANSFORMS
 #define ANIMATE_WINDOW_TRANSFORMS 0
 #endif
+#define HID_COMPOSITOR_MOD_KEY KM_LALT
 
 static char *server_name;
 static sysarg_t coord_origin;
@@ -1799,20 +1800,20 @@
 static int comp_key_press(input_t *input, kbd_event_type_t type, keycode_t key,
     keymod_t mods, wchar_t c)
 {
-	bool win_transform = (mods & KM_ALT) && (
+	bool win_transform = (mods & HID_COMPOSITOR_MOD_KEY) && (
 	    key == KC_W || key == KC_S || key == KC_A || key == KC_D ||
 	    key == KC_Q || key == KC_E || key == KC_R || key == KC_F);
-	bool win_resize = (mods & KM_ALT) && (
+	bool win_resize = (mods & HID_COMPOSITOR_MOD_KEY) && (
 	    key == KC_T || key == KC_G || key == KC_B || key == KC_N);
-	bool win_opacity = (mods & KM_ALT) && (
+	bool win_opacity = (mods & HID_COMPOSITOR_MOD_KEY) && (
 	    key == KC_C || key == KC_V);
-	bool win_close = (mods & KM_ALT) && (key == KC_X);
-	bool win_switch = (mods & KM_ALT) && (key == KC_TAB);
-	bool viewport_move = (mods & KM_ALT) && (
+	bool win_close = (mods & HID_COMPOSITOR_MOD_KEY) && (key == KC_X);
+	bool win_switch = (mods & HID_COMPOSITOR_MOD_KEY) && (key == KC_TAB);
+	bool viewport_move = (mods & HID_COMPOSITOR_MOD_KEY) && (
 	    key == KC_I || key == KC_K || key == KC_J || key == KC_L);
-	bool viewport_change = (mods & KM_ALT) && (
+	bool viewport_change = (mods & HID_COMPOSITOR_MOD_KEY) && (
 	    key == KC_O || key == KC_P);
-	bool kconsole_switch = (mods & KM_ALT) && (key == KC_M);
+	bool kconsole_switch = (mods & HID_COMPOSITOR_MOD_KEY) && (key == KC_M);
 
 	bool filter = (type == KEY_RELEASE) && (win_transform || win_resize ||
 	    win_opacity || win_close || win_switch || viewport_move ||

=== modified file 'uspace/srv/hid/input/Makefile'
--- uspace/srv/hid/input/Makefile	2013-03-12 21:07:15 +0000
+++ uspace/srv/hid/input/Makefile	2014-03-15 15:50:37 +0000
@@ -35,6 +35,7 @@
 	layout/us_qwerty.c \
 	layout/us_dvorak.c \
 	layout/ar.c \
+	layout/de.c \
 	port/adb.c \
 	port/adb_mouse.c \
 	port/chardev.c \

=== modified file 'uspace/srv/hid/input/ctl/pc.c'
--- uspace/srv/hid/input/ctl/pc.c	2012-08-16 19:14:03 +0000
+++ uspace/srv/hid/input/ctl/pc.c	2014-03-15 15:50:37 +0000
@@ -127,6 +127,7 @@
 	[0x2b] = KC_BACKSLASH,
 
 	[0x2a] = KC_LSHIFT,
+	[0x56] = KC_BAR, // only some non-US keyboards
 
 	[0x2c] = KC_Z,
 	[0x2d] = KC_X,

=== modified file 'uspace/srv/hid/input/input.c'
--- uspace/srv/hid/input/input.c	2013-09-10 16:32:35 +0000
+++ uspace/srv/hid/input/input.c	2014-03-15 15:50:37 +0000
@@ -61,13 +61,14 @@
 #include "mouse_proto.h"
 #include "input.h"
 
-#define NUM_LAYOUTS  4
+#define NUM_LAYOUTS  5
 
 static layout_ops_t *layout[NUM_LAYOUTS] = {
 	&us_qwerty_ops,
 	&us_dvorak_ops,
 	&cz_ops,
-	&ar_ops
+	&ar_ops,
+	&de_ops,
 };
 
 static void kbd_devs_yield(void);
@@ -170,6 +171,13 @@
 		return;
 	}
 	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F5) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[4]);
+		return;
+	}
+	
 	ev.type = type;
 	ev.key = key;
 	ev.mods = kdev->mods;

=== modified file 'uspace/srv/hid/input/layout.h'
--- uspace/srv/hid/input/layout.h	2012-12-17 21:36:02 +0000
+++ uspace/srv/hid/input/layout.h	2014-03-15 15:50:37 +0000
@@ -60,6 +60,7 @@
 extern layout_ops_t us_dvorak_ops;
 extern layout_ops_t cz_ops;
 extern layout_ops_t ar_ops;
+extern layout_ops_t de_ops;
 
 extern layout_t *layout_create(layout_ops_t *);
 extern void layout_destroy(layout_t *);

=== added file 'uspace/srv/hid/input/layout/de.c'
--- uspace/srv/hid/input/layout/de.c	1970-01-01 00:00:00 +0000
+++ uspace/srv/hid/input/layout/de.c	2014-03-15 15:50:37 +0000
@@ -0,0 +1,689 @@
+/*
+ * Copyright (c) 2014 Sebastian Köln
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup input
+ * @brief German QWERTZ layout.
+ * @{
+ */
+
+#include <errno.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <io/log.h>
+#include "../input.h"
+#include "../layout.h"
+
+static int de_create(layout_t*);
+static void de_destroy(layout_t*);
+static wchar_t de_parse_ev(layout_t*, kbd_event_t* ev);
+
+enum m_state
+{
+    ms_normal,
+    ms_acute,
+    ms_grave,
+    ms_circumflex
+};
+
+typedef struct
+{
+	enum m_state mstate;
+} layout_de_t;
+
+layout_ops_t de_ops =
+{
+	.create = de_create,
+	.destroy = de_destroy,
+	.parse_ev = de_parse_ev
+};
+
+/** Keys affected by either SHIFT or CAPS-LOCK (lowercase variant) */
+static wchar_t map_lcase[] =
+{
+	[KC_Q] = 'q',
+	[KC_W] = 'w',
+	[KC_E] = 'e',
+	[KC_R] = 'r',
+	[KC_T] = 't',
+	[KC_Y] = 'z',
+	[KC_U] = 'u',
+	[KC_I] = 'i',
+	[KC_O] = 'o',
+	[KC_P] = 'p',
+
+	[KC_LBRACKET] = L'ü',
+
+	[KC_A] = 'a',
+	[KC_S] = 's',
+	[KC_D] = 'd',
+	[KC_F] = 'f',
+	[KC_G] = 'g',
+	[KC_H] = 'h',
+	[KC_J] = 'j',
+	[KC_K] = 'k',
+	[KC_L] = 'l',
+
+	[KC_SEMICOLON] = L'ö',
+	[KC_QUOTE] = L'ä',
+
+	[KC_Z] = 'y',
+	[KC_X] = 'x',
+	[KC_C] = 'c',
+	[KC_V] = 'v',
+	[KC_B] = 'b',
+	[KC_N] = 'n',
+	[KC_M] = 'm',
+};
+
+/** Keys affected by either SHIFT or CAPS-LOCK (uppercase variant) */
+static wchar_t map_ucase[] =
+{
+	[KC_Q] = 'Q',
+	[KC_W] = 'W',
+	[KC_E] = 'E',
+	[KC_R] = 'R',
+	[KC_T] = 'T',
+	[KC_Y] = 'Z',
+	[KC_U] = 'U',
+	[KC_I] = 'I',
+	[KC_O] = 'O',
+	[KC_P] = 'P',
+
+	[KC_LBRACKET] = L'Ü',
+
+	[KC_A] = 'A',
+	[KC_S] = 'S',
+	[KC_D] = 'D',
+	[KC_F] = 'F',
+	[KC_G] = 'G',
+	[KC_H] = 'H',
+	[KC_J] = 'J',
+	[KC_K] = 'K',
+	[KC_L] = 'L',
+
+	[KC_SEMICOLON] = L'Ö',
+	[KC_QUOTE] = L'Ä',
+
+	[KC_Z] = 'Y',
+	[KC_X] = 'X',
+	[KC_C] = 'C',
+	[KC_V] = 'V',
+	[KC_B] = 'B',
+	[KC_N] = 'N',
+	[KC_M] = 'M',
+};
+
+/** Keys that only depend on the SHIFT-state (inactive) */
+static wchar_t map_not_shifted[] =
+{
+	[KC_BACKTICK] = '^',
+	[KC_1] = '1',
+	[KC_2] = '2',
+	[KC_3] = '3',
+	[KC_4] = '4',
+	[KC_5] = '5',
+	[KC_6] = '6',
+	[KC_7] = '7',
+	[KC_8] = '8',
+	[KC_9] = '9',
+	[KC_0] = '0',
+
+	[KC_MINUS] = L'ß',
+	[KC_EQUALS] = L'´',
+
+	[KC_RBRACKET] = '+',
+
+	[KC_BACKSLASH] = '#',
+
+	[KC_BAR] = '<',
+	[KC_COMMA] = ',',
+	[KC_PERIOD] = '.',
+	[KC_SLASH] = '-',
+};
+
+/** Keys that only depend on the SHIFT-state (active) */
+static wchar_t map_shifted[] =
+{
+	[KC_BACKTICK] = L'°',
+
+	[KC_1] = '!',
+	[KC_2] = '"',
+	[KC_3] = L'§',
+	[KC_4] = '$',
+	[KC_5] = '%',
+	[KC_6] = '&',
+	[KC_7] = '/',
+	[KC_8] = '(',
+	[KC_9] = ')',
+	[KC_0] = '=',
+
+	[KC_MINUS] = '?',
+	[KC_EQUALS] = L'`',
+
+	[KC_RBRACKET] = '*',
+
+	[KC_BACKSLASH] = '\'',
+
+	[KC_BAR] = '>',
+	[KC_COMMA] = ';',
+	[KC_PERIOD] = ':',
+	[KC_SLASH] = '_',
+};
+
+/** Keys affected by disabled CAPS-LOCK during inactive SHIFT state */
+static wchar_t map_ns_nocaps[] =
+{
+	[KC_EQUALS] = L'ß'
+};
+
+/** Keys affected by enabled CAPS-LOCK during inactive SHIFT state */
+static wchar_t map_ns_caps[] =
+{
+	[KC_EQUALS] = L'ẞ'
+};
+
+/** Keys affected by ALT-GR without SHIFT */
+static wchar_t map_altgr_not_shifted[] =
+{
+	[KC_1] = L'¹',
+	[KC_2] = L'²',
+	[KC_3] = L'³',
+	[KC_4] = L'¼',
+	[KC_5] = L'½',
+	[KC_6] = L'¬',
+	[KC_7] = '{',
+	[KC_8] = '[',
+	[KC_9] = ']',
+	[KC_0] = '}',
+
+	[KC_MINUS] = '\\',
+
+	[KC_Q] = '@',
+	[KC_W] = L'ł',
+	[KC_E] = L'€',
+	[KC_R] = L'¶',
+	[KC_T] = L'ŧ',
+	[KC_Y] = L'←',
+	[KC_U] = L'↓',
+	[KC_I] = L'→',
+	[KC_O] = L'ø',
+	[KC_P] = L'þ',
+
+	[KC_RBRACKET] = '~',
+
+	[KC_A] = L'æ',
+	[KC_S] = L'ſ',
+	[KC_D] = L'ð',
+	[KC_F] = L'đ',
+	[KC_G] = L'ŋ',
+	[KC_H] = L'ħ',
+	[KC_K] = L'ĸ',
+
+	[KC_BACKSLASH] = L'’',
+
+	[KC_BAR] = L'|',
+	[KC_Z] = L'»',
+	[KC_X] = L'«',
+	[KC_C] = L'¢',
+	[KC_V] = L'„',
+	[KC_B] = L'“',
+	[KC_N] = L'”',
+	[KC_M] = L'µ',
+
+	[KC_COMMA] = L'·',
+	[KC_PERIOD] = L'…',
+	[KC_SLASH] = L'–',
+};
+
+/** Keys affected by ALT-GR with SHIFT */
+static wchar_t map_altgr_shifted[] =
+{
+	[KC_1] = L'¡',
+	[KC_2] = L'⅛',
+	[KC_3] = L'£',
+	[KC_4] = L'¤',
+	[KC_5] = L'⅜',
+	[KC_6] = L'⅝',
+	[KC_7] = L'⅞',
+	[KC_8] = L'™',
+	[KC_9] = L'±',
+	[KC_MINUS] = L'¿',
+
+	[KC_Q] = L'Ω',
+	[KC_W] = L'Ł',
+	[KC_E] = L'€',
+	[KC_R] = L'®',
+	[KC_T] = L'Ŧ',
+	[KC_Y] = L'¥',
+	[KC_U] = L'↑',
+	[KC_I] = L'ı',
+	[KC_O] = L'Ø',
+	[KC_P] = L'Þ',
+
+	[KC_RBRACKET] = '~',
+
+	[KC_A] = L'Æ',
+	[KC_D] = L'Ð',
+	[KC_F] = L'ª',
+	[KC_G] = L'Ŋ',
+	[KC_H] = L'Ħ',
+	[KC_L] = L'Ł',
+
+	[KC_BAR] = L'¦',
+	[KC_Z] = L'›',
+	[KC_X] = L'‹',
+	[KC_C] = L'©',
+	[KC_V] = L'‚',
+	[KC_B] = L'‘',
+	[KC_N] = L'’',
+	[KC_M] = L'º',
+
+	[KC_COMMA] = L'×',
+	[KC_PERIOD] = L'÷',
+	[KC_SLASH] = L'—',
+};
+
+/** keys affected by acute modifier (lower case variant) */
+static wchar_t map_acute_lcase[] =
+{
+	[KC_EQUALS] = L'´',
+	
+	[KC_W] = L'ẃ',
+	[KC_E] = L'é',
+	[KC_R] = L'ŕ',
+	[KC_Y] = L'ź',
+	[KC_U] = L'ú',
+	[KC_I] = L'í',
+	[KC_O] = L'ó',
+	[KC_P] = L'ṕ',
+
+	[KC_A] = L'á',
+	[KC_S] = L'ś',
+	[KC_G] = L'ǵ',
+
+	[KC_Z] = L'ý',
+	[KC_C] = L'ć',
+	[KC_V] = L'ǘ',
+	[KC_N] = L'ń',
+	[KC_M] = L'ḿ',
+	
+	[KC_SPACE] = '\'',
+};
+
+/** keys affected by acute modifier (upper case variant) */
+static wchar_t map_acute_ucase[] =
+{
+	[KC_W] = L'Ẃ',
+	[KC_E] = L'É',
+	[KC_R] = L'Ŕ',
+	[KC_Y] = L'Ź',
+	[KC_U] = L'Ú',
+	[KC_I] = L'Í',
+	[KC_O] = L'Ó',
+	[KC_P] = L'Ṕ',
+
+	[KC_A] = L'Á',
+	[KC_S] = L'Ś',
+	[KC_G] = L'Ǵ',
+
+	[KC_Z] = L'Ý',
+	[KC_C] = L'Ć',
+	[KC_V] = L'Ǘ',
+	[KC_N] = L'Ń',
+	[KC_M] = L'Ḿ',
+	
+	[KC_SPACE] = '\'',
+};
+
+/** keys affected by grave modifier (lower case variant) */
+static wchar_t map_grave_lcase[] =
+{
+	[KC_W] = L'ẁ',
+	[KC_E] = L'è',
+	[KC_U] = L'ù',
+	[KC_I] = L'ì',
+	[KC_O] = L'ò',
+
+	[KC_A] = L'à',
+
+	[KC_Z] = L'ỳ',
+	[KC_V] = L'ǜ',
+	[KC_N] = L'ǹ',
+	
+	[KC_SPACE] = '`',
+};
+
+/** keys affected by grave modifier (upper case variant) */
+static wchar_t map_grave_ucase[] =
+{
+	[KC_EQUALS] = L'`',
+	
+	[KC_W] = L'Ẁ',
+	[KC_E] = L'È',
+	[KC_U] = L'Ù',
+	[KC_I] = L'Ì',
+	[KC_O] = L'Ò',
+
+	[KC_A] = L'À',
+
+	[KC_Z] = L'Ỳ',
+	[KC_V] = L'Ǜ',
+	[KC_N] = L'Ǹ',
+	
+	[KC_SPACE] = '`',
+};
+
+
+/** keys affected by circumvlex modifier (lower case variant) */
+static wchar_t map_circumflex_lcase[] =
+{
+	[KC_BACKTICK] = '^',
+	
+	[KC_1] = L'¹',
+	[KC_2] = L'²',
+	[KC_3] = L'³',
+	[KC_4] = L'⁴',
+	[KC_5] = L'⁵',
+	[KC_6] = L'⁶',
+	[KC_7] = L'⁷',
+	[KC_8] = L'⁸',
+	[KC_9] = L'⁹',
+	[KC_0] = L'⁰',
+	
+	[KC_W] = L'ŵ',
+	[KC_E] = L'ê',
+	[KC_Y] = L'ẑ',
+	[KC_U] = L'û',
+	[KC_I] = L'î',
+	[KC_O] = L'ô',
+
+	[KC_A] = L'â',
+	[KC_S] = L'ŝ',
+	[KC_G] = L'ĝ',
+	[KC_H] = L'ĥ',
+	[KC_J] = L'ĵ',
+
+	[KC_Z] = L'ŷ',
+	[KC_C] = L'ĉ',
+	
+	[KC_SPACE] = '^',
+};
+
+/** keys affected by circumvlex modifier (upper case variant) */
+static wchar_t map_circumflex_ucase[] =
+{
+	[KC_W] = L'Ŵ',
+	[KC_E] = L'Ê',
+	[KC_Y] = L'Ẑ',
+	[KC_U] = L'Û',
+	[KC_I] = L'Î',
+	[KC_O] = L'Ô',
+
+	[KC_A] = L'Â',
+	[KC_S] = L'Ŝ',
+	[KC_G] = L'Ĝ',
+	[KC_H] = L'Ĥ',
+	[KC_J] = L'Ĵ',
+
+	[KC_Z] = L'Ŷ',
+	[KC_C] = L'Ĉ',
+	
+	[KC_SPACE] = '^',
+};
+
+/** keys that are independend of SHIFT-state. */
+static wchar_t map_neutral[] =
+{
+	[KC_BACKSPACE] = '\b',
+	[KC_TAB] = '\t',
+	[KC_ENTER] = '\n',
+	[KC_SPACE] = ' ',
+
+	[KC_NSLASH] = '/',
+	[KC_NTIMES] = '*',
+	[KC_NMINUS] = '-',
+	[KC_NPLUS] = '+',
+	[KC_NENTER] = '\n'
+};
+
+static wchar_t map_numeric[] =
+{
+	[KC_N7] = '7',
+	[KC_N8] = '8',
+	[KC_N9] = '9',
+	[KC_N4] = '4',
+	[KC_N5] = '5',
+	[KC_N6] = '6',
+	[KC_N1] = '1',
+	[KC_N2] = '2',
+	[KC_N3] = '3',
+
+	[KC_N0] = '0',
+	[KC_NPERIOD] = '.'
+};
+
+static wchar_t translate(unsigned int key, wchar_t* map, size_t map_length)
+{
+	if (key >= map_length)
+		return 0;
+
+	return map[key];
+}
+
+/** @brief: handle key sequences of modifier key and an additional key */
+static wchar_t parse_ms_modifier(layout_de_t* de_state, kbd_event_t* ev)
+{
+	wchar_t* map_table = NULL;
+	size_t map_size = 0;
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+	{
+		switch (de_state->mstate)
+		{
+		case ms_acute:
+			map_table = map_acute_ucase;
+			map_size = sizeof(map_acute_ucase) / sizeof(wchar_t);
+			break;
+
+		case ms_grave:
+			map_table = map_grave_ucase;
+			map_size = sizeof(map_grave_ucase) / sizeof(wchar_t);
+			break;
+
+		case ms_circumflex:
+			map_table = map_circumflex_ucase;
+			map_size = sizeof(map_circumflex_ucase) / sizeof(wchar_t);
+			break;
+
+		default:
+			break;
+		}
+	}
+	else
+	{
+		switch (de_state->mstate)
+		{
+		case ms_acute:
+			map_table = map_acute_lcase;
+			map_size = sizeof(map_acute_lcase) / sizeof(wchar_t);
+			break;
+
+		case ms_grave:
+			map_table = map_grave_lcase;
+			map_size = sizeof(map_grave_lcase) / sizeof(wchar_t);
+			break;
+
+		case ms_circumflex:
+			map_table = map_circumflex_lcase;
+			map_size = sizeof(map_circumflex_lcase) / sizeof(wchar_t);
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	if (map_table)
+		return translate(ev->key, map_table, map_size);
+	else
+		return 0;
+}
+
+static wchar_t parse_ms_normal(layout_de_t* de_state, kbd_event_t* ev)
+{
+	wchar_t c;
+
+	/* AltGr combinations */
+	if ((ev->mods & KM_RALT) != 0)
+	{
+		if ((ev->mods & KM_SHIFT) != 0)
+			c = translate(ev->key, map_altgr_shifted, sizeof(map_altgr_shifted) / sizeof(wchar_t));
+		else
+			c = translate(ev->key, map_altgr_not_shifted, sizeof(map_altgr_not_shifted) / sizeof(wchar_t));
+
+		return c;
+	}
+
+	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+	
+	/* Caps-Lock effects */
+	if ((ev->mods & KM_SHIFT) == 0)
+	{
+		if ((ev->mods & KM_CAPS_LOCK) != 0)
+			c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t));
+		else
+			c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t));
+
+		if (c != 0)
+			return c;
+	}
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_SHIFT) != 0)
+		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_NUM_LOCK) != 0)
+		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
+	else
+		c = 0;
+
+	return c;
+}
+
+static bool key_is_mod(unsigned key)
+{
+	switch (key)
+	{
+	case KC_LSHIFT:
+	case KC_RSHIFT:
+	case KC_LALT:
+	case KC_RALT:
+	case KC_LCTRL:
+	case KC_RCTRL:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static int de_create(layout_t* state)
+{
+	layout_de_t* de_state;
+
+	de_state = malloc(sizeof(layout_de_t));
+
+	if (de_state == NULL)
+	{
+		printf("%s: Out of memory.\n", NAME);
+		return ENOMEM;
+	}
+
+	de_state->mstate = ms_normal;
+	state->layout_priv = (void*) de_state;
+	return EOK;
+}
+
+static void de_destroy(layout_t* state)
+{
+	free(state->layout_priv);
+}
+
+static wchar_t de_parse_ev(layout_t* state, kbd_event_t* ev)
+{
+	layout_de_t* de_state = (layout_de_t*) state->layout_priv;
+	int c = 0;
+	
+	if (ev->type != KEY_PRESS)
+		return 0;
+
+	if (key_is_mod(ev->key))
+		return 0;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_LALT)) != 0)
+		return 0;
+
+	if (de_state->mstate == ms_normal ) {
+		/* handle mode changes by '^', '´' and '`' keys */
+		if ((ev->key == KC_BACKTICK) && ((ev->mods & KM_SHIFT) == 0))
+			de_state->mstate = ms_circumflex;
+		else if ((ev->key == KC_EQUALS) && ((ev->mods & KM_SHIFT) == 0))
+			de_state->mstate = ms_acute;
+		else if ((ev->key == KC_EQUALS) && ((ev->mods & KM_SHIFT) != 0))
+			de_state->mstate = ms_grave;
+		else
+			c = parse_ms_normal(de_state, ev);
+	} else {
+		c = parse_ms_modifier(de_state, ev);
+		de_state->mstate = ms_normal;
+	}
+	
+	return c;
+}
+
+/**
+ * @}
+ */

# Begin bundle
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

Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________
HelenOS-devel mailing list
[email protected]
http://lists.modry.cz/listinfo/helenos-devel

Reply via email to