summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-02-03 16:11:28 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-02-03 16:11:28 +0100
commitdddd0e7b0317f02e1aad5d60d87844da8f6785e4 (patch)
tree630de21b0f7b62a9afcd6380b606cd87ff6fe2ec
parent3944c00f23f023adabb71a53d1d25b8948b7482d (diff)
downloadserenity-dddd0e7b0317f02e1aad5d60d87844da8f6785e4.zip
Get nyancat nyanning in Serenity.
I found a cute program that renders an animated nyancat in the terminal. This patch adds enough hackery to get it working correctly. :^)
-rw-r--r--AK/StringImpl.cpp3
-rw-r--r--Kernel/Process.cpp14
-rw-r--r--Kernel/Process.h1
-rw-r--r--Kernel/Syscall.cpp2
-rw-r--r--Kernel/Syscall.h1
-rw-r--r--Kernel/types.h1
-rw-r--r--LibC/string.cpp10
-rw-r--r--LibC/string.h2
-rw-r--r--LibC/sys/types.h1
-rw-r--r--LibC/time.h2
-rw-r--r--LibC/unistd.cpp5
-rw-r--r--LibC/unistd.h1
-rw-r--r--Terminal/Terminal.cpp96
-rw-r--r--Terminal/Terminal.h8
-rw-r--r--Terminal/XtermColors.h260
15 files changed, 342 insertions, 65 deletions
diff --git a/AK/StringImpl.cpp b/AK/StringImpl.cpp
index 3bf43dd1cd..396d556851 100644
--- a/AK/StringImpl.cpp
+++ b/AK/StringImpl.cpp
@@ -81,6 +81,9 @@ RetainPtr<StringImpl> StringImpl::create(const char* cstring, size_t length, Sho
if (!*cstring)
return the_empty_stringimpl();
+ if (!length)
+ return the_empty_stringimpl();
+
char* buffer;
auto new_stringimpl = create_uninitialized(length, buffer);
if (!new_stringimpl)
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index 317614cbd9..edc5bb08ca 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -1425,6 +1425,20 @@ int Process::sys$kill(pid_t pid, int signal)
return 0;
}
+int Process::sys$usleep(useconds_t usec)
+{
+ if (!usec)
+ return 0;
+
+ sleep(usec / 1000);
+ if (m_wakeup_time > system.uptime) {
+ ASSERT(m_was_interrupted_while_blocked);
+ dword ticks_left_until_original_wakeup_time = m_wakeup_time - system.uptime;
+ return ticks_left_until_original_wakeup_time / TICKS_PER_SECOND;
+ }
+ return 0;
+}
+
int Process::sys$sleep(unsigned seconds)
{
if (!seconds)
diff --git a/Kernel/Process.h b/Kernel/Process.h
index f4eb329c78..2e524e3618 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -166,6 +166,7 @@ public:
int sys$getcwd(char*, size_t);
int sys$chdir(const char*);
int sys$sleep(unsigned seconds);
+ int sys$usleep(useconds_t usec);
int sys$gettimeofday(timeval*);
int sys$gethostname(char* name, size_t length);
int sys$get_arguments(int* argc, char*** argv);
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index 848465a50a..4b2b8d4d2e 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -62,6 +62,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
break;
case Syscall::SC_sleep:
return current->sys$sleep((unsigned)arg1);
+ case Syscall::SC_usleep:
+ return current->sys$usleep((unsigned)arg1);
case Syscall::SC_gettimeofday:
return current->sys$gettimeofday((timeval*)arg1);
case Syscall::SC_get_dir_entries:
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index dd552a3abb..964426454d 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -84,6 +84,7 @@
__ENUMERATE_SYSCALL(gui_set_global_cursor_tracking_enabled) \
__ENUMERATE_SYSCALL(rmdir) \
__ENUMERATE_SYSCALL(chmod) \
+ __ENUMERATE_SYSCALL(usleep) \
#ifdef SERENITY
diff --git a/Kernel/types.h b/Kernel/types.h
index b355315b46..45cd0bb45d 100644
--- a/Kernel/types.h
+++ b/Kernel/types.h
@@ -16,6 +16,7 @@ typedef dword uid_t;
typedef dword gid_t;
typedef signed_word pid_t;
typedef dword time_t;
+typedef dword useconds_t;
typedef dword suseconds_t;
struct timeval {
diff --git a/LibC/string.cpp b/LibC/string.cpp
index 02d8d934ea..47ddf45e3f 100644
--- a/LibC/string.cpp
+++ b/LibC/string.cpp
@@ -5,6 +5,7 @@
#include <assert.h>
#include <stdlib.h>
#include <AK/Types.h>
+#include <AK/StdLibExtras.h>
extern "C" {
@@ -60,6 +61,15 @@ char* strdup(const char* str)
return new_str;
}
+char* strndup(const char* str, size_t maxlen)
+{
+ size_t len = min(strlen(str), maxlen);
+ char* new_str = (char*)malloc(len + 1);
+ memcpy(new_str, str, len);
+ new_str[len] = 0;
+ return new_str;
+}
+
int strcmp(const char* s1, const char* s2)
{
while (*s1 == *s2++)
diff --git a/LibC/string.h b/LibC/string.h
index c2d501a8a7..7783731d91 100644
--- a/LibC/string.h
+++ b/LibC/string.h
@@ -15,6 +15,8 @@ void* memchr(const void*, int c, size_t);
void bzero(void*, size_t);
void bcopy(const void*, void*, size_t);
void* memset(void*, int, size_t);
+char* strdup(const char*);
+char* strndup(const char*, size_t);
char* strcpy(char* dest, const char* src);
char* strncpy(char* dest, const char* src, size_t);
char* strchr(const char*, int c);
diff --git a/LibC/sys/types.h b/LibC/sys/types.h
index 18a3fcb1aa..8a80a4c340 100644
--- a/LibC/sys/types.h
+++ b/LibC/sys/types.h
@@ -29,6 +29,7 @@ typedef uint32_t nlink_t;
typedef uint32_t blksize_t;
typedef uint32_t blkcnt_t;
typedef uint32_t time_t;
+typedef uint32_t useconds_t;
typedef uint32_t suseconds_t;
typedef uint32_t clock_t;
typedef uint32_t socklen_t;
diff --git a/LibC/time.h b/LibC/time.h
index fcb723a8f3..45f17cd4f5 100644
--- a/LibC/time.h
+++ b/LibC/time.h
@@ -30,5 +30,7 @@ time_t time(time_t*);
char* ctime(const time_t*);
void tzset();
+#define difftime(t1,t0) (double)(t1 - t0)
+
__END_DECLS
diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp
index 3064e438c9..6c7282e809 100644
--- a/LibC/unistd.cpp
+++ b/LibC/unistd.cpp
@@ -201,6 +201,11 @@ int sleep(unsigned seconds)
return syscall(SC_sleep, seconds);
}
+int usleep(useconds_t usec)
+{
+ return syscall(SC_usleep, usec);
+}
+
int gethostname(char* buffer, size_t size)
{
int rc = syscall(SC_gethostname, buffer, size);
diff --git a/LibC/unistd.h b/LibC/unistd.h
index a88a11b7c6..a3355cbc99 100644
--- a/LibC/unistd.h
+++ b/LibC/unistd.h
@@ -42,6 +42,7 @@ int fstat(int fd, struct stat* statbuf);
int lstat(const char* path, struct stat* statbuf);
int stat(const char* path, struct stat* statbuf);
int sleep(unsigned seconds);
+int usleep(useconds_t);
int gethostname(char*, size_t);
ssize_t readlink(const char* path, char* buffer, size_t);
char* ttyname(int fd);
diff --git a/Terminal/Terminal.cpp b/Terminal/Terminal.cpp
index bb016016c1..4d0c8aae6e 100644
--- a/Terminal/Terminal.cpp
+++ b/Terminal/Terminal.cpp
@@ -1,4 +1,5 @@
#include "Terminal.h"
+#include "XtermColors.h"
#include <AK/AKString.h>
#include <AK/StringBuilder.h>
#include <SharedGraphics/Font.h>
@@ -72,12 +73,12 @@ Terminal::Line::~Line()
delete [] attributes;
}
-void Terminal::Line::clear()
+void Terminal::Line::clear(Attribute attribute)
{
dirty = true;
memset(characters, ' ', length);
for (word i = 0 ; i < length; ++i)
- attributes[i].reset();
+ attributes[i] = attribute;
}
Terminal::~Terminal()
@@ -91,7 +92,7 @@ Terminal::~Terminal()
void Terminal::clear()
{
for (size_t i = 0; i < rows(); ++i)
- line(i).clear();
+ line(i).clear(m_current_attribute);
set_cursor(0, 0);
}
@@ -125,50 +126,22 @@ unsigned parse_uint(const String& str, bool& ok)
return value;
}
-enum ANSIColor : byte {
- Black = 0,
- Red,
- Green,
- Brown,
- Blue,
- Magenta,
- Cyan,
- LightGray,
- DarkGray,
- BrightRed,
- BrightGreen,
- Yellow,
- BrightBlue,
- BrightMagenta,
- BrightCyan,
- White,
-};
-
-static inline Color ansi_color(unsigned color)
-{
- static const RGBA32 s_ansi_color[16] = {
- make_rgb(0, 0, 0), // Black
- make_rgb(225, 56, 43), // Red
- make_rgb(57, 181, 74), // Green
- make_rgb(255, 199, 6), // Brown
- make_rgb(0, 111, 184), // Blue
- make_rgb(118, 38, 113), // Magenta
- make_rgb(44, 181, 233), // Cyan
- make_rgb(204, 204, 204), // LightGray
- make_rgb(128, 128, 128), // DarkGray
- make_rgb(255, 0, 0), // BrightRed
- make_rgb(0, 255, 0), // BrightGreen
- make_rgb(255, 255, 0), // Yellow
- make_rgb(0, 0, 255), // BrightBlue
- make_rgb(255, 0, 255), // BrightMagenta
- make_rgb(0, 255, 255), // BrightCyan
- make_rgb(255, 255, 255), // White
- };
- return s_ansi_color[color];
+static inline Color lookup_color(unsigned color)
+{
+ return xterm_colors[color];
}
void Terminal::escape$m(const Vector<unsigned>& params)
{
+ if (params.size() == 3 && params[1] == 5) {
+ if (params[0] == 38) {
+ m_current_attribute.foreground_color = params[2];
+ return;
+ } else if (params[0] == 48) {
+ m_current_attribute.background_color = params[2];
+ return;
+ }
+ }
for (auto param : params) {
switch (param) {
case 0:
@@ -364,6 +337,8 @@ void Terminal::execute_xterm_command()
if (ok) {
switch (value) {
case 0:
+ case 1:
+ case 2:
set_window_title(String((const char*)m_xterm_param2.data(), m_xterm_param2.size()));
break;
default:
@@ -384,6 +359,8 @@ void Terminal::execute_escape_sequence(byte final)
bool ok;
unsigned value = parse_uint(parampart, ok);
if (!ok) {
+ m_parameters.clear_with_capacity();
+ m_intermediates.clear_with_capacity();
// FIXME: Should we do something else?
return;
}
@@ -406,8 +383,8 @@ void Terminal::execute_escape_sequence(byte final)
break;
}
- m_parameters.clear();
- m_intermediates.clear();
+ m_parameters.clear_with_capacity();
+ m_intermediates.clear_with_capacity();
}
void Terminal::newline()
@@ -463,7 +440,7 @@ void Terminal::put_character_at(unsigned row, unsigned column, byte ch)
void Terminal::on_char(byte ch)
{
#ifdef TERMINAL_DEBUG
- dbgprintf("Terminal::on_char: %b (%c)\n", ch, ch);
+ dbgprintf("Terminal::on_char: %b (%c), fg=%u, bg=%u\n", ch, ch, m_current_attribute.foreground_color, m_current_attribute.background_color);
#endif
switch (m_escape_state) {
case ExpectBracket:
@@ -617,14 +594,9 @@ Rect Terminal::glyph_rect(word row, word column)
Rect Terminal::row_rect(word row)
{
int y = row * m_line_height;
- return { m_inset, y + m_inset, font().glyph_width() * m_columns, font().glyph_height() };
-}
-
-inline Terminal::Attribute& Terminal::attribute_at(word row, word column)
-{
- ASSERT(row < m_rows);
- ASSERT(column < m_columns);
- return line(row).attributes[column];
+ Rect rect = { m_inset, y + m_inset, font().glyph_width() * m_columns, font().glyph_height() };
+ rect.inflate(0, m_line_spacing);
+ return rect;
}
bool Terminal::Line::has_only_one_background_color() const
@@ -671,25 +643,29 @@ void Terminal::paint()
continue;
line.dirty = false;
bool has_only_one_background_color = line.has_only_one_background_color();
- if (has_only_one_background_color)
- painter.fill_rect(row_rect(row), line.attributes[0].background_color);
+ if (has_only_one_background_color) {
+ painter.fill_rect(row_rect(row), lookup_color(line.attributes[0].background_color));
+ }
for (word column = 0; column < m_columns; ++column) {
bool should_reverse_fill_for_cursor = m_in_active_window && row == m_cursor_row && column == m_cursor_column;
auto& attribute = line.attributes[column];
line.did_paint = true;
char ch = line.characters[column];
auto character_rect = glyph_rect(row, column);
- if (!has_only_one_background_color || should_reverse_fill_for_cursor)
- painter.fill_rect(character_rect, ansi_color(should_reverse_fill_for_cursor ? attribute.foreground_color : attribute.background_color));
+ if (!has_only_one_background_color || should_reverse_fill_for_cursor) {
+ auto cell_rect = character_rect;
+ cell_rect.inflate(0, m_line_spacing);
+ painter.fill_rect(cell_rect, lookup_color(should_reverse_fill_for_cursor ? attribute.foreground_color : attribute.background_color));
+ }
if (ch == ' ')
continue;
- painter.draw_glyph(character_rect.location(), ch, ansi_color(should_reverse_fill_for_cursor ? attribute.background_color : attribute.foreground_color));
+ painter.draw_glyph(character_rect.location(), ch, lookup_color(should_reverse_fill_for_cursor ? attribute.background_color : attribute.foreground_color));
}
}
if (!m_in_active_window) {
auto cursor_rect = glyph_rect(m_cursor_row, m_cursor_column);
- painter.draw_rect(cursor_rect, ansi_color(line(m_cursor_row).attributes[m_cursor_column].foreground_color));
+ painter.draw_rect(cursor_rect, lookup_color(line(m_cursor_row).attributes[m_cursor_column].foreground_color));
}
line(m_cursor_row).did_paint = true;
diff --git a/Terminal/Terminal.h b/Terminal/Terminal.h
index 06d8caa484..5a81b410c9 100644
--- a/Terminal/Terminal.h
+++ b/Terminal/Terminal.h
@@ -63,8 +63,8 @@ private:
background_color = 0;
//bold = false;
}
- unsigned foreground_color : 4;
- unsigned background_color : 4;
+ byte foreground_color;
+ byte background_color;
//bool bold : 1;
bool operator==(const Attribute& other) const
{
@@ -75,7 +75,7 @@ private:
struct Line {
explicit Line(word columns);
~Line();
- void clear();
+ void clear(Attribute);
bool has_only_one_background_color() const;
byte* characters { nullptr };
Attribute* attributes { nullptr };
@@ -98,8 +98,6 @@ private:
Attribute m_current_attribute;
- Attribute& attribute_at(word row, word column);
-
void execute_escape_sequence(byte final);
void execute_xterm_command();
diff --git a/Terminal/XtermColors.h b/Terminal/XtermColors.h
new file mode 100644
index 0000000000..8d9239dbba
--- /dev/null
+++ b/Terminal/XtermColors.h
@@ -0,0 +1,260 @@
+#pragma once
+
+static const unsigned xterm_colors[256] = {
+ 0x000000,
+ 0xcc0000,
+ 0x3e9a06,
+ 0xc4a000,
+ 0x3465a4,
+ 0x75507b,
+ 0x06989a,
+ 0xeeeeec,
+ 0x555753,
+ 0xef2929,
+ 0x8ae234,
+ 0xfce94f,
+ 0x729fcf,
+ 0xad7fa8,
+ 0x34e2e2,
+ 0xFFFFFF,
+ 0x000000,
+ 0x00005f,
+ 0x000087,
+ 0x0000af,
+ 0x0000d7,
+ 0x0000ff,
+ 0x005f00,
+ 0x005f5f,
+ 0x005f87,
+ 0x005faf,
+ 0x005fd7,
+ 0x005fff,
+ 0x008700,
+ 0x00875f,
+ 0x008787,
+ 0x0087af,
+ 0x0087d7,
+ 0x0087ff,
+ 0x00af00,
+ 0x00af5f,
+ 0x00af87,
+ 0x00afaf,
+ 0x00afd7,
+ 0x00afff,
+ 0x00d700,
+ 0x00d75f,
+ 0x00d787,
+ 0x00d7af,
+ 0x00d7d7,
+ 0x00d7ff,
+ 0x00ff00,
+ 0x00ff5f,
+ 0x00ff87,
+ 0x00ffaf,
+ 0x00ffd7,
+ 0x00ffff,
+ 0x5f0000,
+ 0x5f005f,
+ 0x5f0087,
+ 0x5f00af,
+ 0x5f00d7,
+ 0x5f00ff,
+ 0x5f5f00,
+ 0x5f5f5f,
+ 0x5f5f87,
+ 0x5f5faf,
+ 0x5f5fd7,
+ 0x5f5fff,
+ 0x5f8700,
+ 0x5f875f,
+ 0x5f8787,
+ 0x5f87af,
+ 0x5f87d7,
+ 0x5f87ff,
+ 0x5faf00,
+ 0x5faf5f,
+ 0x5faf87,
+ 0x5fafaf,
+ 0x5fafd7,
+ 0x5fafff,
+ 0x5fd700,
+ 0x5fd75f,
+ 0x5fd787,
+ 0x5fd7af,
+ 0x5fd7d7,
+ 0x5fd7ff,
+ 0x5fff00,
+ 0x5fff5f,
+ 0x5fff87,
+ 0x5fffaf,
+ 0x5fffd7,
+ 0x5fffff,
+ 0x870000,
+ 0x87005f,
+ 0x870087,
+ 0x8700af,
+ 0x8700d7,
+ 0x8700ff,
+ 0x875f00,
+ 0x875f5f,
+ 0x875f87,
+ 0x875faf,
+ 0x875fd7,
+ 0x875fff,
+ 0x878700,
+ 0x87875f,
+ 0x878787,
+ 0x8787af,
+ 0x8787d7,
+ 0x8787ff,
+ 0x87af00,
+ 0x87af5f,
+ 0x87af87,
+ 0x87afaf,
+ 0x87afd7,
+ 0x87afff,
+ 0x87d700,
+ 0x87d75f,
+ 0x87d787,
+ 0x87d7af,
+ 0x87d7d7,
+ 0x87d7ff,
+ 0x87ff00,
+ 0x87ff5f,
+ 0x87ff87,
+ 0x87ffaf,
+ 0x87ffd7,
+ 0x87ffff,
+ 0xaf0000,
+ 0xaf005f,
+ 0xaf0087,
+ 0xaf00af,
+ 0xaf00d7,
+ 0xaf00ff,
+ 0xaf5f00,
+ 0xaf5f5f,
+ 0xaf5f87,
+ 0xaf5faf,
+ 0xaf5fd7,
+ 0xaf5fff,
+ 0xaf8700,
+ 0xaf875f,
+ 0xaf8787,
+ 0xaf87af,
+ 0xaf87d7,
+ 0xaf87ff,
+ 0xafaf00,
+ 0xafaf5f,
+ 0xafaf87,
+ 0xafafaf,
+ 0xafafd7,
+ 0xafafff,
+ 0xafd700,
+ 0xafd75f,
+ 0xafd787,
+ 0xafd7af,
+ 0xafd7d7,
+ 0xafd7ff,
+ 0xafff00,
+ 0xafff5f,
+ 0xafff87,
+ 0xafffaf,
+ 0xafffd7,
+ 0xafffff,
+ 0xd70000,
+ 0xd7005f,
+ 0xd70087,
+ 0xd700af,
+ 0xd700d7,
+ 0xd700ff,
+ 0xd75f00,
+ 0xd75f5f,
+ 0xd75f87,
+ 0xd75faf,
+ 0xd75fd7,
+ 0xd75fff,
+ 0xd78700,
+ 0xd7875f,
+ 0xd78787,
+ 0xd787af,
+ 0xd787d7,
+ 0xd787ff,
+ 0xd7af00,
+ 0xd7af5f,
+ 0xd7af87,
+ 0xd7afaf,
+ 0xd7afd7,
+ 0xd7afff,
+ 0xd7d700,
+ 0xd7d75f,
+ 0xd7d787,
+ 0xd7d7af,
+ 0xd7d7d7,
+ 0xd7d7ff,
+ 0xd7ff00,
+ 0xd7ff5f,
+ 0xd7ff87,
+ 0xd7ffaf,
+ 0xd7ffd7,
+ 0xd7ffff,
+ 0xff0000,
+ 0xff005f,
+ 0xff0087,
+ 0xff00af,
+ 0xff00d7,
+ 0xff00ff,
+ 0xff5f00,
+ 0xff5f5f,
+ 0xff5f87,
+ 0xff5faf,
+ 0xff5fd7,
+ 0xff5fff,
+ 0xff8700,
+ 0xff875f,
+ 0xff8787,
+ 0xff87af,
+ 0xff87d7,
+ 0xff87ff,
+ 0xffaf00,
+ 0xffaf5f,
+ 0xffaf87,
+ 0xffafaf,
+ 0xffafd7,
+ 0xffafff,
+ 0xffd700,
+ 0xffd75f,
+ 0xffd787,
+ 0xffd7af,
+ 0xffd7d7,
+ 0xffd7ff,
+ 0xffff00,
+ 0xffff5f,
+ 0xffff87,
+ 0xffffaf,
+ 0xffffd7,
+ 0xffffff,
+ 0x080808,
+ 0x121212,
+ 0x1c1c1c,
+ 0x262626,
+ 0x303030,
+ 0x3a3a3a,
+ 0x444444,
+ 0x4e4e4e,
+ 0x585858,
+ 0x626262,
+ 0x6c6c6c,
+ 0x767676,
+ 0x808080,
+ 0x8a8a8a,
+ 0x949494,
+ 0x9e9e9e,
+ 0xa8a8a8,
+ 0xb2b2b2,
+ 0xbcbcbc,
+ 0xc6c6c6,
+ 0xd0d0d0,
+ 0xdadada,
+ 0xe4e4e4,
+ 0xeeeeee,
+};