Ver Fonte

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. :^)
Andreas Kling há 6 anos atrás
pai
commit
dddd0e7b03

+ 3 - 0
AK/StringImpl.cpp

@@ -81,6 +81,9 @@ RetainPtr<StringImpl> StringImpl::create(const char* cstring, size_t length, Sho
     if (!*cstring)
     if (!*cstring)
         return the_empty_stringimpl();
         return the_empty_stringimpl();
 
 
+    if (!length)
+        return the_empty_stringimpl();
+
     char* buffer;
     char* buffer;
     auto new_stringimpl = create_uninitialized(length, buffer);
     auto new_stringimpl = create_uninitialized(length, buffer);
     if (!new_stringimpl)
     if (!new_stringimpl)

+ 14 - 0
Kernel/Process.cpp

@@ -1425,6 +1425,20 @@ int Process::sys$kill(pid_t pid, int signal)
     return 0;
     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)
 int Process::sys$sleep(unsigned seconds)
 {
 {
     if (!seconds)
     if (!seconds)

+ 1 - 0
Kernel/Process.h

@@ -166,6 +166,7 @@ public:
     int sys$getcwd(char*, size_t);
     int sys$getcwd(char*, size_t);
     int sys$chdir(const char*);
     int sys$chdir(const char*);
     int sys$sleep(unsigned seconds);
     int sys$sleep(unsigned seconds);
+    int sys$usleep(useconds_t usec);
     int sys$gettimeofday(timeval*);
     int sys$gettimeofday(timeval*);
     int sys$gethostname(char* name, size_t length);
     int sys$gethostname(char* name, size_t length);
     int sys$get_arguments(int* argc, char*** argv);
     int sys$get_arguments(int* argc, char*** argv);

+ 2 - 0
Kernel/Syscall.cpp

@@ -62,6 +62,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
         break;
         break;
     case Syscall::SC_sleep:
     case Syscall::SC_sleep:
         return current->sys$sleep((unsigned)arg1);
         return current->sys$sleep((unsigned)arg1);
+    case Syscall::SC_usleep:
+        return current->sys$usleep((unsigned)arg1);
     case Syscall::SC_gettimeofday:
     case Syscall::SC_gettimeofday:
         return current->sys$gettimeofday((timeval*)arg1);
         return current->sys$gettimeofday((timeval*)arg1);
     case Syscall::SC_get_dir_entries:
     case Syscall::SC_get_dir_entries:

+ 1 - 0
Kernel/Syscall.h

@@ -84,6 +84,7 @@
     __ENUMERATE_SYSCALL(gui_set_global_cursor_tracking_enabled) \
     __ENUMERATE_SYSCALL(gui_set_global_cursor_tracking_enabled) \
     __ENUMERATE_SYSCALL(rmdir) \
     __ENUMERATE_SYSCALL(rmdir) \
     __ENUMERATE_SYSCALL(chmod) \
     __ENUMERATE_SYSCALL(chmod) \
+    __ENUMERATE_SYSCALL(usleep) \
 
 
 
 
 #ifdef SERENITY
 #ifdef SERENITY

+ 1 - 0
Kernel/types.h

@@ -16,6 +16,7 @@ typedef dword uid_t;
 typedef dword gid_t;
 typedef dword gid_t;
 typedef signed_word pid_t;
 typedef signed_word pid_t;
 typedef dword time_t;
 typedef dword time_t;
+typedef dword useconds_t;
 typedef dword suseconds_t;
 typedef dword suseconds_t;
 
 
 struct timeval {
 struct timeval {

+ 10 - 0
LibC/string.cpp

@@ -5,6 +5,7 @@
 #include <assert.h>
 #include <assert.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <AK/Types.h>
 #include <AK/Types.h>
+#include <AK/StdLibExtras.h>
 
 
 extern "C" {
 extern "C" {
 
 
@@ -60,6 +61,15 @@ char* strdup(const char* str)
     return new_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)
 int strcmp(const char* s1, const char* s2)
 {
 {
     while (*s1 == *s2++)
     while (*s1 == *s2++)

+ 2 - 0
LibC/string.h

@@ -15,6 +15,8 @@ void* memchr(const void*, int c, size_t);
 void bzero(void*, size_t);
 void bzero(void*, size_t);
 void bcopy(const void*, void*, size_t);
 void bcopy(const void*, void*, size_t);
 void* memset(void*, int, 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* strcpy(char* dest, const char* src);
 char* strncpy(char* dest, const char* src, size_t);
 char* strncpy(char* dest, const char* src, size_t);
 char* strchr(const char*, int c);
 char* strchr(const char*, int c);

+ 1 - 0
LibC/sys/types.h

@@ -29,6 +29,7 @@ typedef uint32_t nlink_t;
 typedef uint32_t blksize_t;
 typedef uint32_t blksize_t;
 typedef uint32_t blkcnt_t;
 typedef uint32_t blkcnt_t;
 typedef uint32_t time_t;
 typedef uint32_t time_t;
+typedef uint32_t useconds_t;
 typedef uint32_t suseconds_t;
 typedef uint32_t suseconds_t;
 typedef uint32_t clock_t;
 typedef uint32_t clock_t;
 typedef uint32_t socklen_t;
 typedef uint32_t socklen_t;

+ 2 - 0
LibC/time.h

@@ -30,5 +30,7 @@ time_t time(time_t*);
 char* ctime(const time_t*);
 char* ctime(const time_t*);
 void tzset();
 void tzset();
 
 
+#define difftime(t1,t0) (double)(t1 - t0)
+
 __END_DECLS
 __END_DECLS
 
 

+ 5 - 0
LibC/unistd.cpp

@@ -201,6 +201,11 @@ int sleep(unsigned seconds)
     return syscall(SC_sleep, seconds);
     return syscall(SC_sleep, seconds);
 }
 }
 
 
+int usleep(useconds_t usec)
+{
+    return syscall(SC_usleep, usec);
+}
+
 int gethostname(char* buffer, size_t size)
 int gethostname(char* buffer, size_t size)
 {
 {
     int rc = syscall(SC_gethostname, buffer, size);
     int rc = syscall(SC_gethostname, buffer, size);

+ 1 - 0
LibC/unistd.h

@@ -42,6 +42,7 @@ int fstat(int fd, struct stat* statbuf);
 int lstat(const char* path, struct stat* statbuf);
 int lstat(const char* path, struct stat* statbuf);
 int stat(const char* path, struct stat* statbuf);
 int stat(const char* path, struct stat* statbuf);
 int sleep(unsigned seconds);
 int sleep(unsigned seconds);
+int usleep(useconds_t);
 int gethostname(char*, size_t);
 int gethostname(char*, size_t);
 ssize_t readlink(const char* path, char* buffer, size_t);
 ssize_t readlink(const char* path, char* buffer, size_t);
 char* ttyname(int fd);
 char* ttyname(int fd);

+ 36 - 60
Terminal/Terminal.cpp

@@ -1,4 +1,5 @@
 #include "Terminal.h"
 #include "Terminal.h"
+#include "XtermColors.h"
 #include <AK/AKString.h>
 #include <AK/AKString.h>
 #include <AK/StringBuilder.h>
 #include <AK/StringBuilder.h>
 #include <SharedGraphics/Font.h>
 #include <SharedGraphics/Font.h>
@@ -72,12 +73,12 @@ Terminal::Line::~Line()
     delete [] attributes;
     delete [] attributes;
 }
 }
 
 
-void Terminal::Line::clear()
+void Terminal::Line::clear(Attribute attribute)
 {
 {
     dirty = true;
     dirty = true;
     memset(characters, ' ', length);
     memset(characters, ' ', length);
     for (word i = 0 ; i < length; ++i)
     for (word i = 0 ; i < length; ++i)
-        attributes[i].reset();
+        attributes[i] = attribute;
 }
 }
 
 
 Terminal::~Terminal()
 Terminal::~Terminal()
@@ -91,7 +92,7 @@ Terminal::~Terminal()
 void Terminal::clear()
 void Terminal::clear()
 {
 {
     for (size_t i = 0; i < rows(); ++i)
     for (size_t i = 0; i < rows(); ++i)
-        line(i).clear();
+        line(i).clear(m_current_attribute);
     set_cursor(0, 0);
     set_cursor(0, 0);
 }
 }
 
 
@@ -125,50 +126,22 @@ unsigned parse_uint(const String& str, bool& ok)
     return value;
     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)
 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) {
     for (auto param : params) {
         switch (param) {
         switch (param) {
         case 0:
         case 0:
@@ -364,6 +337,8 @@ void Terminal::execute_xterm_command()
     if (ok) {
     if (ok) {
         switch (value) {
         switch (value) {
         case 0:
         case 0:
+        case 1:
+        case 2:
             set_window_title(String((const char*)m_xterm_param2.data(), m_xterm_param2.size()));
             set_window_title(String((const char*)m_xterm_param2.data(), m_xterm_param2.size()));
             break;
             break;
         default:
         default:
@@ -384,6 +359,8 @@ void Terminal::execute_escape_sequence(byte final)
         bool ok;
         bool ok;
         unsigned value = parse_uint(parampart, ok);
         unsigned value = parse_uint(parampart, ok);
         if (!ok) {
         if (!ok) {
+            m_parameters.clear_with_capacity();
+            m_intermediates.clear_with_capacity();
             // FIXME: Should we do something else?
             // FIXME: Should we do something else?
             return;
             return;
         }
         }
@@ -406,8 +383,8 @@ void Terminal::execute_escape_sequence(byte final)
         break;
         break;
     }
     }
 
 
-    m_parameters.clear();
-    m_intermediates.clear();
+    m_parameters.clear_with_capacity();
+    m_intermediates.clear_with_capacity();
 }
 }
 
 
 void Terminal::newline()
 void Terminal::newline()
@@ -463,7 +440,7 @@ void Terminal::put_character_at(unsigned row, unsigned column, byte ch)
 void Terminal::on_char(byte ch)
 void Terminal::on_char(byte ch)
 {
 {
 #ifdef TERMINAL_DEBUG
 #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
 #endif
     switch (m_escape_state) {
     switch (m_escape_state) {
     case ExpectBracket:
     case ExpectBracket:
@@ -617,14 +594,9 @@ Rect Terminal::glyph_rect(word row, word column)
 Rect Terminal::row_rect(word row)
 Rect Terminal::row_rect(word row)
 {
 {
     int y = row * m_line_height;
     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
 bool Terminal::Line::has_only_one_background_color() const
@@ -671,25 +643,29 @@ void Terminal::paint()
             continue;
             continue;
         line.dirty = false;
         line.dirty = false;
         bool has_only_one_background_color = line.has_only_one_background_color();
         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) {
         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;
             bool should_reverse_fill_for_cursor = m_in_active_window && row == m_cursor_row && column == m_cursor_column;
             auto& attribute = line.attributes[column];
             auto& attribute = line.attributes[column];
             line.did_paint = true;
             line.did_paint = true;
             char ch = line.characters[column];
             char ch = line.characters[column];
             auto character_rect = glyph_rect(row, 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 == ' ')
             if (ch == ' ')
                 continue;
                 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) {
     if (!m_in_active_window) {
         auto cursor_rect = glyph_rect(m_cursor_row, m_cursor_column);
         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;
     line(m_cursor_row).did_paint = true;

+ 3 - 5
Terminal/Terminal.h

@@ -63,8 +63,8 @@ private:
             background_color = 0;
             background_color = 0;
             //bold = false;
             //bold = false;
         }
         }
-        unsigned foreground_color : 4;
-        unsigned background_color : 4;
+        byte foreground_color;
+        byte background_color;
         //bool bold : 1;
         //bool bold : 1;
         bool operator==(const Attribute& other) const
         bool operator==(const Attribute& other) const
         {
         {
@@ -75,7 +75,7 @@ private:
     struct Line {
     struct Line {
         explicit Line(word columns);
         explicit Line(word columns);
         ~Line();
         ~Line();
-        void clear();
+        void clear(Attribute);
         bool has_only_one_background_color() const;
         bool has_only_one_background_color() const;
         byte* characters { nullptr };
         byte* characters { nullptr };
         Attribute* attributes { nullptr };
         Attribute* attributes { nullptr };
@@ -98,8 +98,6 @@ private:
 
 
     Attribute m_current_attribute;
     Attribute m_current_attribute;
 
 
-    Attribute& attribute_at(word row, word column);
-
     void execute_escape_sequence(byte final);
     void execute_escape_sequence(byte final);
     void execute_xterm_command();
     void execute_xterm_command();
 
 

+ 260 - 0
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,
+};