Shell : scroll, new keyboard layout, history
This commit is contained in:
parent
f69383330f
commit
589ce20818
|
@ -34,6 +34,8 @@
|
||||||
void IoEnableCursor(void);
|
void IoEnableCursor(void);
|
||||||
void IoDisableCursor(void);
|
void IoDisableCursor(void);
|
||||||
void IoUpdateCursor(int, int);
|
void IoUpdateCursor(int, int);
|
||||||
|
int IoGetCursorX(void);
|
||||||
|
int IoGetCursorY(void);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
|
|
@ -36,17 +36,25 @@ void IoChangeCodePage(char *);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
#define KEY_ESC 27
|
#define K_BACKSPACE 8
|
||||||
#define KEY_BS 8
|
#define K_BELL 7
|
||||||
#define KEY_BEL 7
|
|
||||||
|
|
||||||
#define KEY_DC1 17 // Arrow Up
|
#define K_ARRW_UP 17
|
||||||
#define KEY_DC2 18 // Arrow Down
|
#define K_ARRW_DOWN 18
|
||||||
#define KEY_DC3 19 // Arrow Left
|
#define K_ARRW_LEFT 19
|
||||||
#define KEY_DC4 20 // Arrow Right
|
#define K_ARRW_RIGHT 20
|
||||||
|
|
||||||
#define KEY_DC5 17 // Page Up
|
#define K_PAGE_UP 21
|
||||||
#define KEY_DC6 18 // Page Down
|
#define K_PAGE_DOWN 22
|
||||||
|
|
||||||
|
#define K_INSERT 23
|
||||||
|
|
||||||
|
#define K_HOME 24
|
||||||
|
#define K_END 25
|
||||||
|
|
||||||
|
#define K_ESCAPE 27
|
||||||
|
|
||||||
|
#define K_DEL 127
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,10 @@ void IoScrollDown(void);
|
||||||
|
|
||||||
void IoChangeTermColor(int, int);
|
void IoChangeTermColor(int, int);
|
||||||
|
|
||||||
|
|
||||||
|
int IoGetCursorOffset(void);
|
||||||
|
void IoSetCursorOffset(int);
|
||||||
|
|
||||||
error_t IoInitVGABuffer(void);
|
error_t IoInitVGABuffer(void);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef _LIB_LIST_H
|
||||||
|
#include <lib/list.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _KALKERN_PROC_H
|
#ifndef _KALKERN_PROC_H
|
||||||
#define _KALKERN_PROC_H
|
#define _KALKERN_PROC_H
|
||||||
|
|
||||||
|
@ -44,6 +48,9 @@ enum ProcState_t
|
||||||
//
|
//
|
||||||
struct Process_t
|
struct Process_t
|
||||||
{
|
{
|
||||||
|
// Scheduler internals
|
||||||
|
ListNode_t schedNode;
|
||||||
|
|
||||||
// Identifier
|
// Identifier
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
|
@ -67,9 +74,6 @@ struct Process_t
|
||||||
|
|
||||||
// Default time-slice
|
// Default time-slice
|
||||||
ulong defTimeSlice;
|
ulong defTimeSlice;
|
||||||
|
|
||||||
// Scheduler internals
|
|
||||||
ListNode_t *schedNode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
|
@ -211,7 +211,7 @@ noreturn void KeStartPanic(const char *, ...);
|
||||||
while(_vga<(volatile ushort*)(0xB8000+(80*25*2))) \
|
while(_vga<(volatile ushort*)(0xB8000+(80*25*2))) \
|
||||||
*_vga++=(c|(0xf<<8)); \
|
*_vga++=(c|(0xf<<8)); \
|
||||||
asm volatile("cli\nhlt"); \
|
asm volatile("cli\nhlt"); \
|
||||||
}while(0)
|
}while(1)
|
||||||
#define BUG() XBUG('B')
|
#define BUG() XBUG('B')
|
||||||
#define BUGON(x) if(x)BUG()
|
#define BUGON(x) if(x)BUG()
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,8 @@ struct ListNode_t
|
||||||
//
|
//
|
||||||
// Create a list head with an extern lock
|
// Create a list head with an extern lock
|
||||||
//
|
//
|
||||||
static inline ListHead_t
|
static inline
|
||||||
*ExCreateListHead(Lock_t *lock)
|
ListHead_t *ExCreateListHead()
|
||||||
{
|
{
|
||||||
ListHead_t *head = malloc(sizeof(ListHead_t));
|
ListHead_t *head = malloc(sizeof(ListHead_t));
|
||||||
|
|
||||||
|
@ -70,11 +70,24 @@ static inline ListHead_t
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
ListNode_t *ExCreateNode()
|
||||||
|
{
|
||||||
|
ListNode_t *node = malloc(sizeof(ListNode_t));
|
||||||
|
|
||||||
|
if (node == NULL) return NULL;
|
||||||
|
|
||||||
|
node->prev = node->next = NULL;
|
||||||
|
node->head = NULL;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Prepend node at beginning of list
|
// Prepend node at beginning of list
|
||||||
//
|
//
|
||||||
static inline ListHead_t
|
static inline
|
||||||
*ExPrependNode(ListHead_t *head, ListNode_t *node)
|
ListHead_t *ExPrependNode(ListHead_t *head, ListNode_t *node)
|
||||||
{
|
{
|
||||||
assert(head && node);
|
assert(head && node);
|
||||||
|
|
||||||
|
@ -101,8 +114,8 @@ static inline ListHead_t
|
||||||
//
|
//
|
||||||
// Append node at end of list
|
// Append node at end of list
|
||||||
//
|
//
|
||||||
static inline ListHead_t
|
static inline
|
||||||
*ExAppendNode(ListHead_t *head, ListNode_t *node)
|
ListHead_t *ExAppendNode(ListHead_t *head, ListNode_t *node)
|
||||||
{
|
{
|
||||||
assert(head && node);
|
assert(head && node);
|
||||||
|
|
||||||
|
@ -182,6 +195,9 @@ static inline ListHead_t
|
||||||
static inline ListHead_t
|
static inline ListHead_t
|
||||||
*ExRemoveNode(ListHead_t *head, ListNode_t *node)
|
*ExRemoveNode(ListHead_t *head, ListNode_t *node)
|
||||||
{
|
{
|
||||||
|
assert(head);
|
||||||
|
assert(node);
|
||||||
|
assert(head->length > 0);
|
||||||
assert(head && node && head->length > 0 && node->head == head);
|
assert(head && node && head->length > 0 && node->head == head);
|
||||||
|
|
||||||
if (head->length == 1) {
|
if (head->length == 1) {
|
||||||
|
@ -221,6 +237,8 @@ ExDestroyListHead(ListHead_t *head)
|
||||||
free(head);
|
free(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ExGetNodeData(list, type) ((type)list)
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
#define CMDBUFSIZE 256
|
|
||||||
|
|
||||||
typedef struct Command_t Command_t;
|
typedef struct Command_t Command_t;
|
||||||
|
|
||||||
struct Command_t
|
struct Command_t
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <ke/idt.h>
|
#include <ke/idt.h>
|
||||||
#include <ke/time.h>
|
#include <ke/time.h>
|
||||||
#include <ke/cpuid.h>
|
#include <ke/cpuid.h>
|
||||||
|
#include <ke/sched.h>
|
||||||
#include <sh/shell.h>
|
#include <sh/shell.h>
|
||||||
#include <io/vga.h>
|
#include <io/vga.h>
|
||||||
#include <io/keyb.h>
|
#include <io/keyb.h>
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <init/boot.h>
|
#include <init/boot.h>
|
||||||
#include <io/cursor.h>
|
#include <io/cursor.h>
|
||||||
|
|
||||||
|
static int _curX = 0, _curY = 0;
|
||||||
|
|
||||||
void IoEnableCursor(void)
|
void IoEnableCursor(void)
|
||||||
{
|
{
|
||||||
IoWriteByteOnPort(0x3D4, 0xA);
|
IoWriteByteOnPort(0x3D4, 0xA);
|
||||||
|
@ -42,6 +44,9 @@ void IoDisableCursor(void)
|
||||||
|
|
||||||
void IoUpdateCursor(int x, int y)
|
void IoUpdateCursor(int x, int y)
|
||||||
{
|
{
|
||||||
|
_curX = x;
|
||||||
|
_curY = y;
|
||||||
|
|
||||||
const ushort pos = y * BtVideoInfo.framebufferWidth + x;
|
const ushort pos = y * BtVideoInfo.framebufferWidth + x;
|
||||||
|
|
||||||
IoWriteByteOnPort(0x3D4, 0x0F);
|
IoWriteByteOnPort(0x3D4, 0x0F);
|
||||||
|
@ -49,3 +54,7 @@ void IoUpdateCursor(int x, int y)
|
||||||
IoWriteByteOnPort(0x3D4, 0x0E);
|
IoWriteByteOnPort(0x3D4, 0x0E);
|
||||||
IoWriteByteOnPort(0x3D5, ((pos >> 8) & 0xFF));
|
IoWriteByteOnPort(0x3D5, ((pos >> 8) & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IoGetCursorX(void) { return _curX; }
|
||||||
|
int IoGetCursorY(void) { return _curY; }
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,10 @@
|
||||||
#define FLAGS(code) (table[2*(code)+1])
|
#define FLAGS(code) (table[2*(code)+1])
|
||||||
|
|
||||||
static bool capsLockActive = 0;
|
static bool capsLockActive = 0;
|
||||||
|
|
||||||
|
static bool e0received = 0;
|
||||||
static bool altPressed = 0;
|
static bool altPressed = 0;
|
||||||
|
static bool altGrPressed = 0;
|
||||||
static bool shiftPressed = 0;
|
static bool shiftPressed = 0;
|
||||||
static bool controlPressed = 0;
|
static bool controlPressed = 0;
|
||||||
|
|
||||||
|
@ -40,11 +43,18 @@ static void KeybPrint(uchar _code)
|
||||||
{
|
{
|
||||||
uint code = (uint)_code;
|
uint code = (uint)_code;
|
||||||
|
|
||||||
const uint *table =
|
const uint *table;
|
||||||
(altPressed ? LeftAltScanCodes
|
|
||||||
: (controlPressed ? LeftControlScanCodes
|
if (!e0received) {
|
||||||
: (shiftPressed ? LeftShiftScanCodes
|
table = (altPressed ? LeftAltScanCodes
|
||||||
: RegularScanCodes)));
|
: (controlPressed ? LeftControlScanCodes
|
||||||
|
: (shiftPressed ? LeftShiftScanCodes
|
||||||
|
: (altGrPressed ? AltGrScanCodes
|
||||||
|
: RegularScanCodes))));
|
||||||
|
} else {
|
||||||
|
table = E0ScanCodes;
|
||||||
|
e0received = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((capsLockActive && (FLAGS(code) & CAPSLOCK))
|
if ((capsLockActive && (FLAGS(code) & CAPSLOCK))
|
||||||
&& !(altPressed || controlPressed)) {
|
&& !(altPressed || controlPressed)) {
|
||||||
|
@ -58,8 +68,14 @@ static void KeybPrint(uchar _code)
|
||||||
|
|
||||||
if (!ch) {
|
if (!ch) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 0x38: altPressed = 1; break;
|
case 0xE0: e0received = 1; break;
|
||||||
case 0xB8: altPressed = 0; break;
|
|
||||||
|
case 0x38: if (table == E0ScanCodes) altGrPressed = 1;
|
||||||
|
else altPressed = 1;
|
||||||
|
break;
|
||||||
|
case 0xB8: if (table == E0ScanCodes) altGrPressed = 0;
|
||||||
|
else altPressed = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x36: case 0x2A: shiftPressed = 1; break;
|
case 0x36: case 0x2A: shiftPressed = 1; break;
|
||||||
case 0xB6: case 0xAA: shiftPressed = 0; break;
|
case 0xB6: case 0xAA: shiftPressed = 0; break;
|
||||||
|
@ -73,10 +89,6 @@ static void KeybPrint(uchar _code)
|
||||||
}
|
}
|
||||||
|
|
||||||
bputc(BStdIn, ch);
|
bputc(BStdIn, ch);
|
||||||
if (code && (FLAGS(code) & INVISIBLE) == 0) {
|
|
||||||
bputc(BStdOut, table[2 * code]);
|
|
||||||
BStdOut->flusher(BStdOut);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void KeybHandler(ISRFrame_t *regs)
|
static void KeybHandler(ISRFrame_t *regs)
|
||||||
|
|
|
@ -22,8 +22,6 @@
|
||||||
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
#define WANT_AZERTY 1
|
|
||||||
|
|
||||||
#define NONE 0
|
#define NONE 0
|
||||||
#define INVISIBLE 1
|
#define INVISIBLE 1
|
||||||
#define CAPSLOCK 2
|
#define CAPSLOCK 2
|
||||||
|
@ -35,7 +33,7 @@
|
||||||
const uint RegularScanCodes[2 * 256] =
|
const uint RegularScanCodes[2 * 256] =
|
||||||
{
|
{
|
||||||
ENTRY (0x00, 0, INVISIBLE|INVALID),
|
ENTRY (0x00, 0, INVISIBLE|INVALID),
|
||||||
ENTRY (0x01, KEY_ESC, INVISIBLE),
|
ENTRY (0x01, K_ESCAPE, INVISIBLE),
|
||||||
|
|
||||||
ENTRY (0x02, '&', NONE),
|
ENTRY (0x02, '&', NONE),
|
||||||
ENTRY (0x03, 'e', NONE),
|
ENTRY (0x03, 'e', NONE),
|
||||||
|
@ -49,7 +47,7 @@ const uint RegularScanCodes[2 * 256] =
|
||||||
ENTRY (0x0B, 'a', NONE),
|
ENTRY (0x0B, 'a', NONE),
|
||||||
ENTRY (0x0C, ')', NONE),
|
ENTRY (0x0C, ')', NONE),
|
||||||
ENTRY (0x0D, '=', NONE),
|
ENTRY (0x0D, '=', NONE),
|
||||||
ENTRY (0x0E, KEY_BS, NONE), // Backspace
|
ENTRY (0x0E, '\b', NONE),
|
||||||
ENTRY (0x0F, '\t', NONE),
|
ENTRY (0x0F, '\t', NONE),
|
||||||
|
|
||||||
ENTRY (0x10, 'a', CAPSLOCK),
|
ENTRY (0x10, 'a', CAPSLOCK),
|
||||||
|
@ -96,17 +94,32 @@ const uint RegularScanCodes[2 * 256] =
|
||||||
ENTRY (0x35, '!', CAPSLOCK),
|
ENTRY (0x35, '!', CAPSLOCK),
|
||||||
|
|
||||||
ENTRY (0x39, ' ', NONE),
|
ENTRY (0x39, ' ', NONE),
|
||||||
|
|
||||||
ENTRY (0x48, KEY_DC1, INVISIBLE), // UP arrow
|
ENTRY (0x40, '\a', INVISIBLE), // F6
|
||||||
ENTRY (0x4B, KEY_DC3, INVISIBLE), // LEFT arrow
|
|
||||||
ENTRY (0x4D, KEY_DC4, INVISIBLE), // RIGHT arrow
|
// Numpad keys
|
||||||
ENTRY (0x50, KEY_DC2, INVISIBLE), // DOWN arrow
|
ENTRY (0x37, '*', NONE),
|
||||||
|
ENTRY (0x47, '7', NONE),
|
||||||
|
ENTRY (0x48, '8', NONE),
|
||||||
|
ENTRY (0x49, '9', NONE),
|
||||||
|
ENTRY (0x4A, '-', NONE),
|
||||||
|
ENTRY (0x4B, '4', NONE),
|
||||||
|
ENTRY (0x4C, '5', NONE),
|
||||||
|
ENTRY (0x4D, '6', NONE),
|
||||||
|
ENTRY (0x4E, '+', NONE),
|
||||||
|
ENTRY (0x4F, '1', NONE),
|
||||||
|
ENTRY (0x50, '2', NONE),
|
||||||
|
ENTRY (0x51, '3', NONE),
|
||||||
|
ENTRY (0x52, '0', NONE),
|
||||||
|
ENTRY (0x53, '.', NONE),
|
||||||
|
|
||||||
|
ENTRY (0xE0, 0, INVISIBLE),
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint LeftShiftScanCodes[2 * 256] =
|
const uint LeftShiftScanCodes[2 * 256] =
|
||||||
{
|
{
|
||||||
ENTRY (0x00, 0, INVISIBLE|INVALID),
|
ENTRY (0x00, 0, INVISIBLE|INVALID),
|
||||||
ENTRY (0x01, KEY_ESC, INVISIBLE),
|
ENTRY (0x01, K_ESCAPE, INVISIBLE),
|
||||||
|
|
||||||
ENTRY (0x02, '1', NONE),
|
ENTRY (0x02, '1', NONE),
|
||||||
ENTRY (0x03, '2', NONE),
|
ENTRY (0x03, '2', NONE),
|
||||||
|
@ -120,7 +133,7 @@ const uint LeftShiftScanCodes[2 * 256] =
|
||||||
ENTRY (0x0B, '0', NONE),
|
ENTRY (0x0B, '0', NONE),
|
||||||
ENTRY (0x0C, 'o', NONE),
|
ENTRY (0x0C, 'o', NONE),
|
||||||
ENTRY (0x0D, '+', NONE),
|
ENTRY (0x0D, '+', NONE),
|
||||||
ENTRY (0x0E, KEY_BS, NONE), // Backspace
|
ENTRY (0x0E, '\b', NONE),
|
||||||
ENTRY (0x0F, '\t', NONE),
|
ENTRY (0x0F, '\t', NONE),
|
||||||
|
|
||||||
ENTRY (0x10, 'A', CAPSLOCK),
|
ENTRY (0x10, 'A', CAPSLOCK),
|
||||||
|
@ -167,8 +180,54 @@ const uint LeftShiftScanCodes[2 * 256] =
|
||||||
ENTRY (0x35, '!', NONE),
|
ENTRY (0x35, '!', NONE),
|
||||||
|
|
||||||
ENTRY (0x39, ' ', NONE),
|
ENTRY (0x39, ' ', NONE),
|
||||||
|
|
||||||
|
// Numpad keys
|
||||||
|
ENTRY (0x47, K_HOME, INVISIBLE),
|
||||||
|
ENTRY (0x48, K_ARRW_UP, INVISIBLE),
|
||||||
|
ENTRY (0x49, K_PAGE_UP, INVISIBLE),
|
||||||
|
ENTRY (0x4B, K_ARRW_LEFT, INVISIBLE),
|
||||||
|
ENTRY (0x4D, K_ARRW_RIGHT, INVISIBLE),
|
||||||
|
ENTRY (0x4F, K_END, INVISIBLE),
|
||||||
|
ENTRY (0x50, K_ARRW_DOWN, INVISIBLE),
|
||||||
|
ENTRY (0x51, K_PAGE_DOWN, INVISIBLE),
|
||||||
|
ENTRY (0x52, K_INSERT, INVISIBLE),
|
||||||
|
ENTRY (0x53, K_DEL, INVISIBLE),
|
||||||
|
|
||||||
|
ENTRY (0xE0, 0, INVISIBLE),
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint LeftAltScanCodes[2 * 256];
|
const uint AltGrScanCodes[2 * 256] = {
|
||||||
const uint LeftControlScanCodes[2 * 256];
|
ENTRY (0x03, '~', NONE),
|
||||||
|
ENTRY (0x04, '#', NONE),
|
||||||
|
ENTRY (0x05, '{', NONE),
|
||||||
|
ENTRY (0x06, '[', NONE),
|
||||||
|
ENTRY (0x07, '|', NONE),
|
||||||
|
ENTRY (0x08, '`', NONE),
|
||||||
|
ENTRY (0x09, '\\', NONE),
|
||||||
|
ENTRY (0x0A, '^', NONE),
|
||||||
|
ENTRY (0x0B, '@', NONE),
|
||||||
|
ENTRY (0x0C, ']', NONE),
|
||||||
|
ENTRY (0x0D, '}', NONE),
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint LeftAltScanCodes[2 * 256] = { 0 };
|
||||||
|
|
||||||
|
const uint LeftControlScanCodes[2 * 256] = {
|
||||||
|
ENTRY (0x2E, K_ESCAPE, INVISIBLE), // Ctrl+C
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint E0ScanCodes[2 * 256] = {
|
||||||
|
ENTRY (0x1C, '\n', NONE), // Numpad Enter
|
||||||
|
ENTRY (0x35, '/', NONE), // Numpad Slash
|
||||||
|
ENTRY (0x47, K_HOME, INVISIBLE), // Home key
|
||||||
|
ENTRY (0x48, K_ARRW_UP, INVISIBLE), // Cursor UP
|
||||||
|
ENTRY (0x49, K_PAGE_UP, INVISIBLE), // Page UP
|
||||||
|
ENTRY (0x4B, K_ARRW_LEFT, INVISIBLE), // Cursor LEFT
|
||||||
|
ENTRY (0x4D, K_ARRW_RIGHT, INVISIBLE), // Cursor RIGHT
|
||||||
|
ENTRY (0x4F, K_END, INVISIBLE), // End key
|
||||||
|
ENTRY (0x50, K_ARRW_DOWN, INVISIBLE), // Cursor DOWN
|
||||||
|
ENTRY (0x51, K_PAGE_DOWN, INVISIBLE), // Page DOWN
|
||||||
|
ENTRY (0x52, K_INSERT, INVISIBLE), // Insert mode
|
||||||
|
ENTRY (0x53, K_DEL, INVISIBLE), // Delete key
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,8 @@ static uint bscroll = 0;
|
||||||
static int bfg = VGA_COLOR_LIGHT_GREY;
|
static int bfg = VGA_COLOR_LIGHT_GREY;
|
||||||
static int bbg = VGA_COLOR_BLACK;
|
static int bbg = VGA_COLOR_BLACK;
|
||||||
|
|
||||||
|
static int cursorOffset = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// VGA Buffer Flusher
|
// VGA Buffer Flusher
|
||||||
//
|
//
|
||||||
|
@ -86,11 +88,12 @@ error_t bvgaflusher(Buffer_t *buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the cursor
|
// Update the cursor
|
||||||
size_t curX = ((size_t)ptr - (size_t)bufStart - cols) % buf->lineLen;
|
size_t curX = ((size_t)ptr - (size_t)bufStart - cols) % buf->lineLen;
|
||||||
size_t curY = ((size_t)ptr - (size_t)bufStart) / buf->lineLen;
|
size_t curY = ((size_t)ptr - (size_t)bufStart) / buf->lineLen;
|
||||||
|
|
||||||
IoUpdateCursor(curX, curY);
|
IoUpdateCursor(max(min(curX + cursorOffset, buf->lineLen), 0), curY);
|
||||||
|
|
||||||
// Empty the rest of the buffer
|
// Empty the rest of the buffer
|
||||||
|
|
||||||
|
@ -108,6 +111,14 @@ error_t bvgaflusher(Buffer_t *buf)
|
||||||
return EOK;
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IoGetCursorOffset(void) {
|
||||||
|
return cursorOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IoSetCursorOffset(int ins) {
|
||||||
|
cursorOffset = ins;
|
||||||
|
}
|
||||||
|
|
||||||
uint IoGetScroll(void)
|
uint IoGetScroll(void)
|
||||||
{
|
{
|
||||||
return bscroll;
|
return bscroll;
|
||||||
|
|
|
@ -27,25 +27,21 @@
|
||||||
#include <ke/sched.h>
|
#include <ke/sched.h>
|
||||||
#include <lib/list.h>
|
#include <lib/list.h>
|
||||||
|
|
||||||
// XXX not ready
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// For test purpose only
|
// For test purpose only
|
||||||
//
|
//
|
||||||
int procslen = 10;
|
int procslen = 10;
|
||||||
Process_t procs[] = {
|
Process_t procs[] = {
|
||||||
{ 0, 0, 0, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 0, 0, 0, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
{ 1, 2, 2, 16, 16, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 1, 2, 2, 16, 16, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
{ 2, 3, 3, 31, 31, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 2, 3, 3, 31, 31, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
{ 3, 2, 2, 1, 1, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 3, 2, 2, 1, 1, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
{ 4, 3, 3, 5, 5, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 4, 3, 3, 5, 5, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
{ 5, 0, 0, 30, 30, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 5, 0, 0, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
{ 6, 1, 1, 19, 19, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 6, 1, 1, 19, 19, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
{ 7, 1, 1, 0, 0, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 7, 1, 1, 0, 0, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
{ 8, 3, 3, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 8, 3, 3, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
{ 9, 2, 2, 21, 21, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
|
{ {0}, 9, 2, 2, 21, 21, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
@ -65,8 +61,8 @@ Process_t procs[] = {
|
||||||
//
|
//
|
||||||
static void SetCurProc(Process_t *proc)
|
static void SetCurProc(Process_t *proc)
|
||||||
{
|
{
|
||||||
PsCurProc = proc;
|
KeCurProc = proc;
|
||||||
if (PsCurProc) PsCurProc->procState = STATE_RUNNING;
|
if (KeCurProc) KeCurProc->procState = STATE_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -80,7 +76,7 @@ void PsLockSched(void) {
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void PsUnlockSched(void) {
|
void PsUnlockSched(void) {
|
||||||
//KeEnableIRQs();
|
KeEnableIRQs();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -104,7 +100,7 @@ static ListHead_t *GetPrioClassHead(int prioClass)
|
||||||
case SERV_PRIO_PROC: return ServPrioProcs;
|
case SERV_PRIO_PROC: return ServPrioProcs;
|
||||||
case REGL_PRIO_PROC: return ReglPrioProcs;
|
case REGL_PRIO_PROC: return ReglPrioProcs;
|
||||||
case IDLE_PRIO_PROC: return IdlePrioProcs;
|
case IDLE_PRIO_PROC: return IdlePrioProcs;
|
||||||
default: KalAssert(FALSE && "Unknown priority class");
|
default: assert(!"Unknown priority class");
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -116,7 +112,7 @@ static ListHead_t *GetPrioClassHead(int prioClass)
|
||||||
//
|
//
|
||||||
static Process_t *CompareProcs(Process_t *proc1, Process_t *proc2)
|
static Process_t *CompareProcs(Process_t *proc1, Process_t *proc2)
|
||||||
{
|
{
|
||||||
KalAssert(proc1 && proc2);
|
assert(proc1 && proc2);
|
||||||
|
|
||||||
if (proc1->prioClass < proc2->prioClass) return proc1;
|
if (proc1->prioClass < proc2->prioClass) return proc1;
|
||||||
if (proc1->prioClass > proc2->prioClass) return proc2;
|
if (proc1->prioClass > proc2->prioClass) return proc2;
|
||||||
|
@ -132,26 +128,21 @@ static Process_t *CompareProcs(Process_t *proc1, Process_t *proc2)
|
||||||
//
|
//
|
||||||
static void SchedThisProcUnlocked(Process_t *proc)
|
static void SchedThisProcUnlocked(Process_t *proc)
|
||||||
{
|
{
|
||||||
KalAssert(proc && proc->procState == STATE_RUNNABLE && !proc->schedNode);
|
assert(proc && proc->procState == STATE_RUNNABLE);
|
||||||
|
|
||||||
bool found = 0;
|
bool found = 0;
|
||||||
ListNode_t *iterNode = NULL;
|
ListNode_t *iterNode = NULL;
|
||||||
ListNode_t *procNode = ExCreateNode(proc);
|
|
||||||
ListHead_t *head = GetPrioClassHead(proc->prioClass);
|
ListHead_t *head = GetPrioClassHead(proc->prioClass);
|
||||||
|
assert(head);
|
||||||
KalAssert(head);
|
|
||||||
KalAssert(procNode);
|
|
||||||
|
|
||||||
proc->schedNode = procNode;
|
|
||||||
|
|
||||||
// Find a process with lesser priority
|
// Find a process with lesser priority
|
||||||
for (iterNode = head->first; iterNode; iterNode = iterNode->next) {
|
for (iterNode = head->first; iterNode; iterNode = iterNode->next) {
|
||||||
if (proc->prioLevel > ExGetNodeData(iterNode, Process_t *)->prioLevel) {
|
if (proc->prioLevel > ExGetNodeData(iterNode, Process_t *)->prioLevel) {
|
||||||
// Detect double insertions
|
// Detect double insertions
|
||||||
KalAssert(proc->pid != ExGetNodeData(iterNode, Process_t *)->pid);
|
assert(proc->pid != ExGetNodeData(iterNode, Process_t *)->pid);
|
||||||
|
|
||||||
// Add process to schedule
|
// Add process to schedule
|
||||||
ExAddNodeBefore(head, iterNode, procNode);
|
ExAddNodeBefore(head, iterNode, &proc->schedNode);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +150,7 @@ static void SchedThisProcUnlocked(Process_t *proc)
|
||||||
|
|
||||||
// Didn't find any process with lesser priority
|
// Didn't find any process with lesser priority
|
||||||
if (found == false) {
|
if (found == false) {
|
||||||
ExAppendNode(head, procNode);
|
ExAppendNode(head, &proc->schedNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,36 +192,29 @@ static Process_t *SelectSchedNext(void)
|
||||||
//
|
//
|
||||||
void PsBlockCurProc(void)
|
void PsBlockCurProc(void)
|
||||||
{
|
{
|
||||||
KalAssert(PsCurProc && PsCurProc->procState == STATE_RUNNING);
|
assert(KeCurProc && KeCurProc->procState == STATE_RUNNING);
|
||||||
|
|
||||||
ListNode_t *procNode = PsCurProc->schedNode;
|
KeCurProc->procState = STATE_BLOCKED;
|
||||||
|
ExRemoveNode(KeCurProc->schedNode.head, &KeCurProc->schedNode);
|
||||||
|
|
||||||
KalAssert(procNode && "Blocking non-scheduled process");
|
|
||||||
|
|
||||||
PsCurProc->procState = STATE_BLOCKED;
|
|
||||||
ExRemoveNode(procNode->head, procNode);
|
|
||||||
|
|
||||||
PsCurProc->schedNode = NULL;
|
|
||||||
SetCurProc(SelectSchedNext());
|
SetCurProc(SelectSchedNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReSchedCurProc(void)
|
static void ReSchedCurProc(void)
|
||||||
{
|
{
|
||||||
KalAssert(PsCurProc && PsCurProc->procState == STATE_RUNNING);
|
assert(KeCurProc && KeCurProc->procState == STATE_RUNNING);
|
||||||
KalAssert(PsCurProc->schedNode);
|
|
||||||
|
|
||||||
// Restore default attributes, cancelling boosts
|
// Restore default attributes, cancelling boosts
|
||||||
PsCurProc->prioClass = PsCurProc->defPrioClass;
|
KeCurProc->prioClass = KeCurProc->defPrioClass;
|
||||||
PsCurProc->prioLevel = PsCurProc->defPrioLevel;
|
KeCurProc->prioLevel = KeCurProc->defPrioLevel;
|
||||||
PsCurProc->timeSlice = PsCurProc->defTimeSlice;
|
KeCurProc->timeSlice = KeCurProc->defTimeSlice;
|
||||||
PsCurProc->procState = STATE_RUNNABLE;
|
KeCurProc->procState = STATE_RUNNABLE;
|
||||||
|
|
||||||
// Remove from list
|
// Remove from list
|
||||||
ExRemoveNode(PsCurProc->schedNode->head, PsCurProc->schedNode);
|
ExRemoveNode(KeCurProc->schedNode.head, &KeCurProc->schedNode);
|
||||||
PsCurProc->schedNode = NULL;
|
|
||||||
|
|
||||||
// Schedule again, with default attributes now
|
// Schedule again, with default attributes now
|
||||||
SchedThisProcUnlocked(PsCurProc);
|
SchedThisProcUnlocked(KeCurProc);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -241,30 +225,30 @@ void PsSchedOnTick(void)
|
||||||
{
|
{
|
||||||
PsLockSched();
|
PsLockSched();
|
||||||
|
|
||||||
Process_t *procNext, *winner, *previous = PsCurProc;
|
Process_t *procNext, *winner, *previous = KeCurProc;
|
||||||
|
|
||||||
// We're either idle or running something
|
// We're either idle or running something
|
||||||
KalAssert(PsCurProc == NULL || PsCurProc->procState == STATE_RUNNING);
|
assert(KeCurProc == NULL || KeCurProc->procState == STATE_RUNNING);
|
||||||
|
|
||||||
// Have the current process spent its timeslice?
|
// Has the current process spent its timeslice?
|
||||||
// (To be handled in CPU decisions function)
|
// (To be handled in CPU decisions function)
|
||||||
if (PsCurProc != NULL) {
|
if (KeCurProc != NULL) {
|
||||||
if (PsCurProc->timeSlice <= 1) {
|
if (KeCurProc->timeSlice <= 1) {
|
||||||
// Re-schedule
|
// Re-schedule
|
||||||
ReSchedCurProc();
|
ReSchedCurProc();
|
||||||
|
|
||||||
// See next 'if' statement
|
// See next 'if' statement
|
||||||
PsCurProc = NULL;
|
KeCurProc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, make it lose a tick
|
// Otherwise, make it lose a tick
|
||||||
else {
|
else {
|
||||||
PsCurProc->timeSlice--;
|
KeCurProc->timeSlice--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we idle, or scheduling next process?
|
// Are we idle, or scheduling next process?
|
||||||
if (PsCurProc == NULL) {
|
if (KeCurProc == NULL) {
|
||||||
SetCurProc(SelectSchedNext());
|
SetCurProc(SelectSchedNext());
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +258,7 @@ void PsSchedOnTick(void)
|
||||||
|
|
||||||
// Is there a higher priority process that is runnable?
|
// Is there a higher priority process that is runnable?
|
||||||
procNext = SelectSchedNext();
|
procNext = SelectSchedNext();
|
||||||
winner = CompareProcs(PsCurProc, procNext);
|
winner = CompareProcs(KeCurProc, procNext);
|
||||||
|
|
||||||
// Yes, procNext should preempt current process
|
// Yes, procNext should preempt current process
|
||||||
if (winner == procNext) {
|
if (winner == procNext) {
|
||||||
|
@ -290,7 +274,7 @@ void PsSchedOnTick(void)
|
||||||
leave:
|
leave:
|
||||||
PsUnlockSched();
|
PsUnlockSched();
|
||||||
|
|
||||||
if (PsCurProc != NULL && PsCurProc != previous) {
|
if (KeCurProc != NULL && KeCurProc != previous) {
|
||||||
// dispatch & context switch
|
// dispatch & context switch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,7 +293,7 @@ void PsInitSched(void)
|
||||||
ReglPrioProcs = ExCreateListHead();
|
ReglPrioProcs = ExCreateListHead();
|
||||||
IdlePrioProcs = ExCreateListHead();
|
IdlePrioProcs = ExCreateListHead();
|
||||||
|
|
||||||
KalAssert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs);
|
assert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs);
|
||||||
|
|
||||||
for (pid = 0; pid < procslen; pid++) {
|
for (pid = 0; pid < procslen; pid++) {
|
||||||
if (procs[pid].procState == STATE_RUNNABLE) {
|
if (procs[pid].procState == STATE_RUNNABLE) {
|
||||||
|
@ -325,7 +309,7 @@ void PsInitSched(void)
|
||||||
//
|
//
|
||||||
void PsFiniSched(void)
|
void PsFiniSched(void)
|
||||||
{
|
{
|
||||||
KalAssert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs);
|
assert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs);
|
||||||
|
|
||||||
PsLockSched();
|
PsLockSched();
|
||||||
|
|
||||||
|
@ -356,12 +340,12 @@ void PsFiniSched(void)
|
||||||
//
|
//
|
||||||
void PrintList(ListHead_t *head)
|
void PrintList(ListHead_t *head)
|
||||||
{
|
{
|
||||||
KalAssert(head);
|
assert(head);
|
||||||
|
|
||||||
Process_t *proc;
|
Process_t *proc;
|
||||||
ListNode_t *node = head->first;
|
ListNode_t *node = head->first;
|
||||||
|
|
||||||
KernLog("len: %lu\n", head->length);
|
KernLog("len %lu\n", head->length);
|
||||||
|
|
||||||
while (node) {
|
while (node) {
|
||||||
proc = ExGetNodeData(node, Process_t *);
|
proc = ExGetNodeData(node, Process_t *);
|
||||||
|
@ -394,7 +378,7 @@ void pstest(void)
|
||||||
|
|
||||||
while (tick < 100) {
|
while (tick < 100) {
|
||||||
//if (tick%25==0)ClearTerm(StdOut);
|
//if (tick%25==0)ClearTerm(StdOut);
|
||||||
if (tick > 0 && tick != 50 && tick % 10 == 0 && PsCurProc) {
|
if (tick > 0 && tick != 50 && tick % 10 == 0 && KeCurProc) {
|
||||||
KernLog("Blocking current process\n");
|
KernLog("Blocking current process\n");
|
||||||
PsBlockCurProc();
|
PsBlockCurProc();
|
||||||
}
|
}
|
||||||
|
@ -406,12 +390,12 @@ void pstest(void)
|
||||||
|
|
||||||
KernLog("Tick %d - Running: ", tick);
|
KernLog("Tick %d - Running: ", tick);
|
||||||
|
|
||||||
if (PsCurProc == NULL) {
|
if (KeCurProc == NULL) {
|
||||||
KernLog("IDLE\n");
|
KernLog("IDLE\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
PrintProc(PsCurProc);
|
PrintProc(KeCurProc);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsSchedOnTick();
|
PsSchedOnTick();
|
||||||
|
@ -423,5 +407,3 @@ void pstest(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <sh/argv.h>
|
#include <sh/argv.h>
|
||||||
#include <sh/shell.h>
|
#include <sh/shell.h>
|
||||||
#include <po/shtdwn.h>
|
#include <po/shtdwn.h>
|
||||||
|
#include <io/cursor.h>
|
||||||
|
|
||||||
int shargc = 0;
|
int shargc = 0;
|
||||||
char **shargv = 0;
|
char **shargv = 0;
|
||||||
|
@ -65,13 +66,27 @@ void ExecuteCommand(char *cmdbuf, Command_t *cmdtable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CMDBUFSIZE (BStdOut->lineLen - 9) // strlen("%Cshell> %C" = 9
|
||||||
|
|
||||||
void ShStartShell(void)
|
void ShStartShell(void)
|
||||||
{
|
{
|
||||||
uchar ch;
|
uchar ch;
|
||||||
error_t rc;
|
error_t rc;
|
||||||
|
char *ptr; // temp
|
||||||
|
|
||||||
|
// Current line - beginning & current pos
|
||||||
char *cmdbuf = malloc(CMDBUFSIZE);
|
char *cmdbuf = malloc(CMDBUFSIZE);
|
||||||
char *bufptr = cmdbuf;
|
char *bufptr = cmdbuf;
|
||||||
|
char *bufend = cmdbuf;
|
||||||
|
|
||||||
|
// History...
|
||||||
|
// We use a basic N-entries command history
|
||||||
|
#define N 10 // must be >1
|
||||||
|
char *history = malloc(CMDBUFSIZE * N);
|
||||||
|
int historyIndex = 0;
|
||||||
|
int historyScroll = 0;
|
||||||
|
|
||||||
|
bool insertMode = 0;
|
||||||
|
|
||||||
argvbuf = malloc(ARG_MAX * 2);
|
argvbuf = malloc(ARG_MAX * 2);
|
||||||
memzero(argvbuf, ARG_MAX * 2);
|
memzero(argvbuf, ARG_MAX * 2);
|
||||||
|
@ -98,57 +113,179 @@ void ShStartShell(void)
|
||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
|
||||||
case KEY_BS:
|
// Backspace character
|
||||||
*bufptr = 0;
|
case K_BACKSPACE:
|
||||||
if (bufptr > cmdbuf) {
|
if (bufptr == cmdbuf)
|
||||||
bufptr--;
|
break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KEY_BEL:
|
memmove(bufptr-1, bufptr, bufend-bufptr+1);
|
||||||
if (rand() % 16 == 0) {
|
bufptr--;
|
||||||
IoDoStarWars();
|
bufend--;
|
||||||
}
|
goto print_current_line;
|
||||||
else IoDoBeep();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KEY_DC1:
|
// DEL character
|
||||||
IoScrollUp();
|
case K_DEL:
|
||||||
break;
|
if (bufptr == bufend)
|
||||||
|
break;
|
||||||
|
|
||||||
case KEY_DC2:
|
memmove(bufptr, bufptr+1, bufend-bufptr+1);
|
||||||
IoScrollDown();
|
IoSetCursorOffset(IoGetCursorOffset()+1);
|
||||||
break;
|
bufend--;
|
||||||
|
goto print_current_line;
|
||||||
|
|
||||||
case KEY_ESC:
|
case K_BELL: IoDoBeep(); break;
|
||||||
PoShutdown();
|
case K_ESCAPE: PoShutdown(); break;
|
||||||
|
case K_PAGE_UP: IoScrollUp(); break;
|
||||||
|
case K_PAGE_DOWN: IoScrollDown(); break;
|
||||||
|
|
||||||
|
case K_INSERT:
|
||||||
|
insertMode = 1 - insertMode;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Move within buffer
|
||||||
|
case K_ARRW_LEFT:
|
||||||
|
if (!(bufptr > cmdbuf))
|
||||||
|
break;
|
||||||
|
|
||||||
|
bufptr--;
|
||||||
|
|
||||||
|
IoSetCursorOffset(IoGetCursorOffset()-1);
|
||||||
|
BFlushBuf(BStdOut);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_ARRW_RIGHT:
|
||||||
|
if (bufptr == bufend)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bufptr++;
|
||||||
|
IoSetCursorOffset(IoGetCursorOffset()+1);
|
||||||
|
BFlushBuf(BStdOut);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_HOME:
|
||||||
|
if (bufptr == cmdbuf)
|
||||||
|
break;
|
||||||
|
|
||||||
|
IoSetCursorOffset(IoGetCursorOffset()-(int)(bufptr-cmdbuf));
|
||||||
|
bufptr = cmdbuf;
|
||||||
|
BFlushBuf(BStdOut);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case K_END:
|
||||||
IoSetScroll(1);
|
if (bufptr == bufend)
|
||||||
IoScrollDown();
|
break;
|
||||||
|
|
||||||
*bufptr++ = (char)ch;
|
IoSetCursorOffset(IoGetCursorOffset()+(int)(bufend-bufptr));
|
||||||
|
bufptr = bufend;
|
||||||
|
BFlushBuf(BStdOut);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Handle history scroll up/down
|
||||||
|
case K_ARRW_UP:
|
||||||
|
case K_ARRW_DOWN:
|
||||||
|
if (historyIndex == 0)
|
||||||
|
break; // No history yet
|
||||||
|
|
||||||
|
if (ch == K_ARRW_UP) {
|
||||||
|
memmove(cmdbuf, &history[historyScroll*CMDBUFSIZE], CMDBUFSIZE);
|
||||||
|
if (historyScroll > 0)
|
||||||
|
historyScroll--;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (historyScroll < historyIndex-1) {
|
||||||
|
historyScroll++;
|
||||||
|
memmove(cmdbuf, &history[historyScroll*CMDBUFSIZE], CMDBUFSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (bufend = cmdbuf; *bufend && bufend < cmdbuf+CMDBUFSIZE; bufend++);
|
||||||
|
bufptr = bufend;
|
||||||
|
|
||||||
|
IoSetCursorOffset(0);
|
||||||
|
goto print_current_line;
|
||||||
|
|
||||||
|
// Regular character
|
||||||
|
default:
|
||||||
|
if (bufptr >= bufend) {
|
||||||
|
*bufptr++ = (char)ch;
|
||||||
|
|
||||||
|
bufend = bufptr;
|
||||||
|
*bufptr = 0;
|
||||||
|
|
||||||
|
// Advance cursor
|
||||||
|
if (IoGetCursorOffset() < 0)
|
||||||
|
IoSetCursorOffset(IoGetCursorOffset() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
if (!insertMode) {
|
||||||
|
*++bufend = 0;
|
||||||
|
for (ptr = bufend-1; ptr != bufptr; ptr--)
|
||||||
|
*ptr = *(ptr - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else { // insertMode
|
||||||
|
// Advance cursor
|
||||||
|
if (IoGetCursorOffset() < 0)
|
||||||
|
IoSetCursorOffset(IoGetCursorOffset() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
*bufptr++ = (char)ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_current_line:
|
||||||
|
|
||||||
|
BLockBuf(BStdOut);
|
||||||
|
|
||||||
|
BStdOut->wp -= BStdOut->lastLF;
|
||||||
|
BStdOut->size -= BStdOut->lastLF;
|
||||||
|
BStdOut->lastLF = 0;
|
||||||
|
bprintf(BStdOut, "%Cshell> %C%s", VGA_COLOR_WHITE, shcol, cmdbuf);
|
||||||
|
|
||||||
|
BUnlockBuf(BStdOut);
|
||||||
|
|
||||||
|
IoSetScroll(1);
|
||||||
|
IoScrollDown(); // This calls the flusher
|
||||||
|
|
||||||
// End of buffer?
|
// End of buffer?
|
||||||
if (bufptr != cmdbuf+CMDBUFSIZE-1) {
|
if (bufend != cmdbuf+CMDBUFSIZE-1) {
|
||||||
break; // No
|
break; // No
|
||||||
}
|
}
|
||||||
|
|
||||||
KernLog("\n");
|
// Else, *FALLTHROUGH* to case '\n'
|
||||||
// Else, fallthrough to case '\n'
|
|
||||||
|
|
||||||
case '\n':
|
case '\n':
|
||||||
|
BPutOnBuf(BStdOut, '\n');
|
||||||
|
|
||||||
while (IoGetScroll() > 0) {
|
while (IoGetScroll() > 0) {
|
||||||
IoScrollDown();
|
IoScrollDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
*bufptr = 0;
|
IoSetCursorOffset(0);
|
||||||
bufptr = cmdbuf;
|
|
||||||
ExecuteCommand(cmdbuf, shcmdtable);
|
bufptr = cmdbuf; // Reset bufptr
|
||||||
|
bufend = cmdbuf;
|
||||||
|
|
||||||
|
if (cmdbuf[0] && !isspace(cmdbuf[0])) {
|
||||||
|
// Forget old commands
|
||||||
|
if (historyIndex >= N) {
|
||||||
|
assert(historyIndex == N);
|
||||||
|
memmove(history, history+CMDBUFSIZE, CMDBUFSIZE * (N-1));
|
||||||
|
historyIndex = historyScroll = N-1;
|
||||||
|
|
||||||
|
}
|
||||||
|
// Update history
|
||||||
|
memmove(&history[historyIndex*CMDBUFSIZE], cmdbuf, CMDBUFSIZE);
|
||||||
|
historyScroll = historyIndex;
|
||||||
|
historyIndex++;
|
||||||
|
|
||||||
|
// Execute & reset
|
||||||
|
ExecuteCommand(cmdbuf, shcmdtable);
|
||||||
|
memzero(cmdbuf, CMDBUFSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
memzero(cmdbuf, CMDBUFSIZE);
|
|
||||||
KernLog("%Cshell> %C", VGA_COLOR_WHITE, shcol);
|
KernLog("%Cshell> %C", VGA_COLOR_WHITE, shcol);
|
||||||
BFlushBuf(BStdIn);
|
BFlushBuf(BStdIn);
|
||||||
BFlushBuf(BStdOut);
|
BFlushBuf(BStdOut);
|
||||||
|
@ -157,5 +294,4 @@ void ShStartShell(void)
|
||||||
|
|
||||||
KePauseCPU();
|
KePauseCPU();
|
||||||
}
|
}
|
||||||
KernLog("[EOI]\n");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,6 +303,14 @@ error_t CmdPF(int argc, char **argv, char *cmdline)
|
||||||
return EOK;
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void pstest(void);
|
||||||
|
|
||||||
|
error_t CmdPS(int argc, char **argv, char *cmdline)
|
||||||
|
{
|
||||||
|
pstest();
|
||||||
|
return EOK;
|
||||||
|
}
|
||||||
|
|
||||||
error_t CmdShell(int argc, char **argv, char *cmdline)
|
error_t CmdShell(int argc, char **argv, char *cmdline)
|
||||||
{
|
{
|
||||||
ShStartShell();
|
ShStartShell();
|
||||||
|
@ -358,6 +366,7 @@ static Command_t testcmdtable[] =
|
||||||
"with z flags"},
|
"with z flags"},
|
||||||
{ "pfree", CmdPageFree, "Free a page block of id x" },
|
{ "pfree", CmdPageFree, "Free a page block of id x" },
|
||||||
{ "pf", CmdPF, "Provoke a PF. Usage: pfault <address>"},
|
{ "pf", CmdPF, "Provoke a PF. Usage: pfault <address>"},
|
||||||
|
{ "ps", CmdPS, "Scheduler algorithm test" },
|
||||||
{ "shell", CmdShell, "Start a new shell (nested)", },
|
{ "shell", CmdShell, "Start a new shell (nested)", },
|
||||||
{ "stkov", CmdStackOverflow, "Provoke a stack overflow" },
|
{ "stkov", CmdStackOverflow, "Provoke a stack overflow" },
|
||||||
{ "stkun", CmdStackUnderflow, "Provoke a stack underflow" },
|
{ "stkun", CmdStackUnderflow, "Provoke a stack underflow" },
|
||||||
|
|
|
@ -43,9 +43,6 @@ error_t BGetFromBuf(Buffer_t *buf, uchar *ch)
|
||||||
ExReleaseLock(&buf->lock);
|
ExReleaseLock(&buf->lock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX for now, at most 4096 characters can be inputed in BStdIn
|
|
||||||
|
|
||||||
error_t bgetc(Buffer_t *buf, uchar *ch)
|
error_t bgetc(Buffer_t *buf, uchar *ch)
|
||||||
{
|
{
|
||||||
error_t rc = EOK;
|
error_t rc = EOK;
|
||||||
|
@ -72,7 +69,7 @@ error_t bgetc(Buffer_t *buf, uchar *ch)
|
||||||
// (so that BStdIn works; don't make anything else)
|
// (so that BStdIn works; don't make anything else)
|
||||||
while (buf->rp >= buf->wp) {
|
while (buf->rp >= buf->wp) {
|
||||||
#ifdef _KALEID_KERNEL
|
#ifdef _KALEID_KERNEL
|
||||||
KeSleep(1);
|
KeSleep(1); // XXX synchronization with keyboard driver
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <lib/buf.h>
|
#include <lib/buf.h>
|
||||||
#include <io/spkr.h>
|
#include <io/spkr.h>
|
||||||
|
|
||||||
|
#include <io/keyb.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// Writes a character on a buffer
|
// Writes a character on a buffer
|
||||||
//
|
//
|
||||||
|
@ -78,10 +80,6 @@ error_t bputc(Buffer_t *buf, uchar ch)
|
||||||
if (buf->flusher) buf->flusher(buf);
|
if (buf->flusher) buf->flusher(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (ch == '\a') {
|
|
||||||
IoDoBeep();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deal with carriage returns
|
// Deal with carriage returns
|
||||||
else if (ch == '\r') {
|
else if (ch == '\r') {
|
||||||
buf->wp -= buf->lastLF;
|
buf->wp -= buf->lastLF;
|
||||||
|
@ -89,7 +87,7 @@ error_t bputc(Buffer_t *buf, uchar ch)
|
||||||
assert(buf->wp >= buf->buf);
|
assert(buf->wp >= buf->buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deal with tabs... we need a tabSize field
|
// Deal with tabs... should be dealt with elsewhere tho
|
||||||
// We assume tabs are 4 characters long for now
|
// We assume tabs are 4 characters long for now
|
||||||
else if (ch == '\t') {
|
else if (ch == '\t') {
|
||||||
rc = bputc(buf, ' ');
|
rc = bputc(buf, ' ');
|
||||||
|
@ -98,25 +96,6 @@ error_t bputc(Buffer_t *buf, uchar ch)
|
||||||
rc = bputc(buf, ' ');
|
rc = bputc(buf, ' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backspace
|
|
||||||
else if (ch == 8) {
|
|
||||||
if (buf->wp > buf->buf && buf->lastLF > 0) {
|
|
||||||
buf->wp--;
|
|
||||||
buf->lastLF--;
|
|
||||||
rc = bputc(buf, ' ');
|
|
||||||
if (!rc) {
|
|
||||||
buf->wp--;
|
|
||||||
buf->lastLF--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEL character, XXX lastLF
|
|
||||||
else if (ch == 127) {
|
|
||||||
rc = bputc(buf, ' ');
|
|
||||||
if (!rc) buf->wp--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just a regular character
|
// Just a regular character
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Reference in New Issue