code: drawterm

Download patch

ref: 5ce54979cf257881bdbfe1e3754cb1d5df4d84cc
parent: 31e15655e642339a90344e6d97d5a788154000e6
author: iyzsong <iyzsong@envs.net>
date: Sat Mar 2 11:00:42 EST 2024

add Haiku port

diff: cannot open b/gui-haiku//null: file does not exist: 'b/gui-haiku//null'
--- /dev/null
+++ b/Make.haiku
@@ -1,0 +1,21 @@
+# Haiku
+AR=ar
+AS=as
+RANLIB=ranlib
+CC=gcc
+CXX=g++
+CFLAGS=-Wall -Wno-missing-braces -Wno-parentheses -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -D_THREAD_SAFE -D_POSIX_C_SOURCE -O2
+O=o
+OS=posix
+GUI=haiku
+AUDIO=haiku
+LDADD=-ggdb -lbe -lnetwork -lmedia -lstdc++
+LDFLAGS=
+TARG=drawterm
+
+
+all: default
+
+libmachdep.a:
+	arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/; s/armv[567].*/arm/; s/aarch64/arm64/'`; \
+	(cd posix-$$arch &&  make)
--- /dev/null
+++ b/gui-haiku/Makefile
@@ -1,0 +1,13 @@
+ROOT=..
+include ../Make.config
+LIB=libgui.a
+
+OFILES=screen.$O
+
+default: $(LIB)
+$(LIB): $(OFILES)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
+
+screen.$O: screen.cpp
+	$(CXX) -o $@ $(CFLAGS) $<
--- /dev/null
+++ b/gui-haiku/screen.cpp
@@ -1,0 +1,376 @@
+#include <memory>
+#include <Autolock.h>
+#include <Application.h>
+#include <Bitmap.h>
+#include <Clipboard.h>
+#include <Screen.h>
+#include <Window.h>
+#include <Input.h>
+#include <private/input/InputServerTypes.h>
+#include <private/interface/input_globals.h>
+
+extern "C" {
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "devaudio.h"
+#include "draw.h"
+#include "memdraw.h"
+#include "cursor.h"
+#include "keyboard.h"
+#include "screen.h"
+}
+
+Memimage *gscreen = (Memimage *)nil;
+
+class View : public BView {
+private:
+  std::unique_ptr<BBitmap> bitmap;
+  Mousestate ms;
+
+public:
+  View(BRect frame)
+      : BView(frame, NULL, B_FOLLOW_ALL_SIDES,
+              B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE) {
+    SetViewColor(B_TRANSPARENT_COLOR);
+    bitmap = std::make_unique<BBitmap>(frame, B_RGBA32);
+  }
+
+  void *GetFrameBuffer() { return bitmap->Bits(); }
+
+  void Draw(BRect updateRect) override {
+    qlock(&drawlock);
+    DrawBitmap(bitmap.get(), updateRect, updateRect);
+    qunlock(&drawlock);
+  }
+
+  void MessageReceived(BMessage *message) override {
+    switch (message->what) {
+    case B_VIEW_RESIZED: {
+      int32 width, height;
+      width = message->GetInt32("width", 0);
+      height = message->GetInt32("height", 0);
+      qlock(&drawlock);
+      bitmap = std::make_unique<BBitmap>(BRect(0, 0, width, height), B_RGBA32);
+      memset(bitmap->Bits(), 0xff, bitmap->BitsLength());
+      qunlock(&drawlock);
+      screenresize(Rect(0, 0, width + 1, height + 1));
+      break;
+    }
+
+    case B_KEY_DOWN:
+    case B_UNMAPPED_KEY_DOWN:
+    case B_KEY_UP:
+    case B_UNMAPPED_KEY_UP: {
+      static struct {
+         int8 byte;
+         int32 key;
+         Rune k;
+      } transtab[] = {
+         0x00, 0x3b, Kcaps,
+         0x00, 0x5C, Kctl,
+         0x00, 0x60, Kctl,
+         0x00, 0x4b, Kshift,
+         0x00, 0x56, Kshift,
+         0x00, 0x5d, Kalt,
+         0x00, 0x5f, Kalt,
+         0x00, 0x66, Kmod4,
+
+         0x10, B_F1_KEY, KF | 1,
+         0x10, B_F2_KEY, KF | 2,
+         0x10, B_F3_KEY, KF | 3,
+         0x10, B_F4_KEY, KF | 4,
+         0x10, B_F5_KEY, KF | 5,
+         0x10, B_F6_KEY, KF | 6,
+         0x10, B_F7_KEY, KF | 7,
+         0x10, B_F8_KEY, KF | 8,
+         0x10, B_F9_KEY, KF | 9,
+         0x10, B_F10_KEY, KF | 10,
+         0x10, B_F11_KEY, KF | 11,
+         0x10, B_F12_KEY, KF | 12,
+         0x10, B_PRINT_KEY, Kprint,
+         0x10, B_SCROLL_KEY, Kscroll,
+         0x10, B_PAUSE_KEY, Kbreak,
+
+         B_DELETE, 0x34, Kdel,
+         B_INSERT, 0x1f, Kins,
+         B_HOME, 0x20, Khome,
+         B_END, 0x35, Kend,
+         B_PAGE_UP, 0x21, Kpgup,
+         B_PAGE_DOWN, 0x36, Kpgdown,
+         B_UP_ARROW, 0x57, Kup,
+         B_RIGHT_ARROW, 0x63, Kright,
+         B_LEFT_ARROW, 0x61, Kleft,
+         B_DOWN_ARROW, 0x62, Kdown,
+      };
+      int32 key = message->GetInt32("key", 0);
+      int8 byte = message->GetInt8("byte", 0);
+      bool down =
+          message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN;
+      Rune k = 0;
+      for (int i = 0; i < nelem(transtab); i++){
+        if (key != transtab[i].key || byte != transtab[i].byte)
+          continue;
+        k = transtab[i].k;
+        break;
+      }
+      kbdkey(k == 0 ? byte : k, down);
+      break;
+    }
+
+    case B_MOUSE_MOVED: {
+      BPoint where = message->GetPoint("where", BPoint(0, 0));
+      ms.xy.x = where.x;
+      ms.xy.y = where.y;
+      ms.msec = message->GetInt64("when", 0) / 1000;
+      absmousetrack(ms.xy.x, ms.xy.y, ms.buttons, ms.msec);
+      break;
+    }
+
+    case B_MOUSE_WHEEL_CHANGED: {
+      float delta_y = message->GetFloat("be:wheel_delta_y", 0);
+      int32 buttons = delta_y < 0 ? 8 : 16;
+      ms.msec = message->GetInt64("when", 0) / 1000;
+      absmousetrack(ms.xy.x, ms.xy.y, buttons, ms.msec);
+      break;
+    }
+
+    case B_MOUSE_DOWN:
+    case B_MOUSE_UP: {
+      int32 buttons = message->GetInt32("buttons", 0);
+      ms.msec = message->GetInt64("when", 0) / 1000;
+      ms.buttons = 0;
+      if (buttons & B_MOUSE_BUTTON(1))
+        ms.buttons |= 1;
+      if (buttons & B_MOUSE_BUTTON(2))
+        ms.buttons |= 4;
+      if (buttons & B_MOUSE_BUTTON(3))
+        ms.buttons |= 2;
+      absmousetrack(ms.xy.x, ms.xy.y, ms.buttons, ms.msec);
+      break;
+    }
+
+    default:
+      BView::MessageReceived(message);
+    }
+  }
+};
+
+static void winproc(void *arg) {
+  BWindow *window = (BWindow *)arg;
+  thread_id tid = find_thread(NULL);
+  rename_thread(tid, "window");
+  BAutolock locker(window);
+  window->Loop();
+}
+
+static const uint32 kToggleFullScreen = 'TFSn';
+
+class Window : public BWindow {
+private:
+  BRect fSavedFrame;
+  bool fFullScreen;
+
+  void _ToggleFullScreen() {
+    if (fFullScreen) {
+      ResizeTo(fSavedFrame.Width(), fSavedFrame.Height());
+      MoveTo(fSavedFrame.left, fSavedFrame.top);
+      SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE));
+      fFullScreen = false;
+    } else {
+      BScreen screen(this);
+      BRect frame = screen.Frame();
+      fSavedFrame = Frame();
+      ResizeTo(frame.Width() + 1, frame.Height() + 1);
+      MoveTo(frame.left, frame.top);
+      SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_MOVABLE));
+      fFullScreen = true;
+    }
+  }
+
+public:
+  Window(BRect frame)
+      : BWindow(frame, "drawterm", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE) {
+    fFullScreen = false;
+
+    BMessage *message = new BMessage(kToggleFullScreen);
+    AddShortcut(B_ENTER, B_COMMAND_KEY, message);
+  }
+
+  ~Window() {
+    status_t exit_value;
+    wait_for_thread(Thread(), &exit_value);
+  }
+
+  thread_id Run() override {
+    thread_id tid = 0;
+    if (IsLocked()) {
+      kproc("window", winproc, this);
+      while (tid == 0) {
+        tid = find_thread("window");
+        osmsleep(10);
+      }
+      Unlock();
+    }
+    return tid;
+  }
+
+  bool QuitRequested() override {
+    status_t exit_value;
+    thread_id tid = find_thread("cpu");
+    audiodevclose();
+    kill_thread(tid);
+    wait_for_thread(tid, &exit_value);
+    return BLooper::QuitRequested();
+  }
+
+  void MessageReceived(BMessage *message) override {
+    switch (message->what) {
+    case kToggleFullScreen:
+      _ToggleFullScreen();
+      break;
+    default:
+      BWindow::MessageReceived(message);
+    }
+  }
+};
+
+class Application : public BApplication {
+public:
+  Window *window;
+  View *view;
+
+  Application() : BApplication("application/x-vnd.9front-drawterm") {
+    BRect frame(0, 0, 640 - 1, 480 - 1);
+    window = new Window(frame);
+    view = new View(frame);
+    window->AddChild(view);
+    window->CenterOnScreen();
+    view->MakeFocus();
+    window->Show();
+  }
+};
+#define sApp ((Application *)be_app)
+
+char *clipread(void) {
+  const void *data = NULL;
+  char *ret = NULL;
+  ssize_t textLen;
+  if (be_clipboard->Lock()) {
+    BMessage *clip = be_clipboard->Data();
+    if (clip){
+      clip->FindData("text/plain", B_MIME_TYPE, &data, &textLen);
+      ret = (char*)malloc(textLen + 1);
+      if (ret != NULL){
+        memcpy(ret, data, textLen);
+        ret[textLen] = '\0';
+      }
+    }
+    be_clipboard->Unlock();
+  }
+  return ret;
+}
+
+int clipwrite(char *text) {
+  ssize_t textLen = strlen(text);
+  if (be_clipboard->Lock()) {
+    BMessage *clip = be_clipboard->Data();
+    if (clip) {
+      be_clipboard->Clear();
+      clip->AddData("text/plain", B_MIME_TYPE, text, textLen);
+      be_clipboard->Commit();
+    }
+    be_clipboard->Unlock();
+  }
+  return textLen;
+}
+
+void flushmemscreen(Rectangle r) {
+  BRect rect(r.min.x, r.min.y, r.max.x - 1, r.max.y - 1);
+  BMessage message(B_INVALIDATE);
+  message.AddRect("be:area", rect);
+  sApp->window->PostMessage(&message, sApp->view);
+}
+
+Memdata *attachscreen(Rectangle *r, ulong *chan, int *depth, int *width,
+                      int *softscreen) {
+  *r = gscreen->clipr;
+  *chan = gscreen->chan;
+  *depth = gscreen->depth;
+  *width = gscreen->width;
+  *softscreen = 1;
+  gscreen->data->ref++;
+  return gscreen->data;
+}
+
+void getcolor(ulong i, ulong *r, ulong *g, ulong *b) {
+  ulong v;
+  v = cmap2rgb(i);
+  *r = (v >> 16) & 0xFF;
+  *g = (v >> 8) & 0xFF;
+  *b = v & 0xFF;
+}
+
+void setcolor(ulong i, ulong r, ulong g, ulong b) {}
+
+void setcursor(void) {
+  static uint8 data[68];
+  uint8 *p = data;
+  lock(&cursor.lk);
+  *p++ = 16;
+  *p++ = 1;
+  *p++ = -cursor.offset.x;
+  *p++ = -cursor.offset.y;
+  for (int i = 0; i < 32; i++) {
+    p[i] = cursor.set[i];
+    p[i + 32] = cursor.set[i] | cursor.clr[i];
+  }
+  sApp->SetCursor(data);
+  unlock(&cursor.lk);
+}
+
+void mouseset(Point xy) {
+  BAutolock locker(sApp->window);
+  BMessage message(IS_SET_MOUSE_POSITION);
+  BMessage reply;
+  BPoint where(xy.x, xy.y);
+  sApp->view->ConvertToScreen(&where);
+  message.AddPoint("where", where);
+  _control_input_server_(&message, &reply);
+}
+
+void screeninit(void) {
+  BAutolock locker(sApp->window);
+  BRect bounds = sApp->view->Bounds();
+  Rectangle r = Rect(0, 0, bounds.right + 1, bounds.bottom + 1);
+  memimageinit();
+  screensize(r, XRGB32);
+  gscreen->clipr = r;
+  terminit();
+}
+
+static void cpuproc(void *arg) {
+  rename_thread(find_thread(NULL), "cpu");
+  cpubody();
+}
+
+void guimain(void) {
+  Application app;
+  kproc("cpu", cpuproc, nil);
+  app.Run();
+}
+
+void screensize(Rectangle r, ulong chan) {
+  static Memdata md = {
+      .base = 0,
+      .allocd = 0,
+  };
+  if (gscreen != nil)
+    freememimage(gscreen);
+  md.ref = 1;
+  md.bdata = (uchar *)sApp->view->GetFrameBuffer();
+  gscreen = allocmemimaged(r, chan, &md);
+  gscreen->clipr = ZR;
+}
--- a/include/dtos.h
+++ b/include/dtos.h
@@ -1,4 +1,4 @@
-#if defined(linux) || defined(IRIX) || defined(SOLARIS) || defined(OSF1) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined(__sun) || defined(sun) || defined(__OpenBSD__) || defined(__DragonFly__)
+#if defined(linux) || defined(IRIX) || defined(SOLARIS) || defined(OSF1) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined(__sun) || defined(sun) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__HAIKU__)
 #	include "unix.h"
 #	ifdef __APPLE__
 #		define panic dt_panic
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -48,3 +48,5 @@
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
 
+devaudio-haiku.$O: devaudio-haiku.cpp
+	$(CXX) $(CFLAGS) $<
--- /dev/null
+++ b/kern/devaudio-haiku.cpp
@@ -1,0 +1,85 @@
+#include <Autolock.h>
+#include <SoundPlayer.h>
+#include <memory>
+
+extern "C" {
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "devaudio.h"
+}
+
+static struct {
+  BLocker locker;
+  std::unique_ptr<BSoundPlayer> player;
+  uint8 buffer[44100 * 4 / 10];
+  size_t written;
+} snd;
+
+static void play(void *cookie, void *buffer, size_t size,
+                 const media_raw_audio_format &format) {
+  BAutolock locker(&snd.locker);
+  if (snd.written >= size) {
+    memcpy(buffer, snd.buffer, size);
+    snd.written -= size;
+    if (snd.written > 0)
+      memmove(snd.buffer, snd.buffer + size, snd.written);
+  } else {
+    memset(buffer, 0, size);
+  }
+}
+
+void audiodevopen(void) {
+  const media_raw_audio_format format = {
+      .frame_rate = 44100,
+      .channel_count = 2,
+      .format = media_raw_audio_format::B_AUDIO_SHORT,
+      .byte_order = B_MEDIA_LITTLE_ENDIAN,
+      .buffer_size = 4096,
+  };
+  snd.player = std::make_unique<BSoundPlayer>(&format, "devaudio", play);
+  snd.written = 0;
+  if (snd.player->InitCheck() != B_OK) {
+    snd.player.reset(nullptr);
+    return;
+  }
+  snd.player->Start();
+}
+
+void audiodevclose(void) { snd.player.reset(nullptr); }
+
+int audiodevread(void *a, int n) {
+  error("no reading");
+  return -1;
+}
+
+int audiodevwrite(void *a, int n) {
+  int w = n;
+  uint8 *p = (uint8 *)a;
+
+  if (snd.player.get() == nullptr)
+    return -1;
+
+  while (n > 0) {
+    snd.locker.Lock();
+    int max = sizeof(snd.buffer) - snd.written;
+    int x = n > max ? max : n;
+    if (x < 1) {
+      snd.locker.Unlock();
+      osmsleep(10);
+    } else {
+      memcpy(snd.buffer + snd.written, p, x);
+      snd.written += x;
+      p += x;
+      n -= x;
+      snd.locker.Unlock();
+    }
+  }
+  return w;
+}
+
+void audiodevsetvol(int what, int left, int right) { error("not supported"); }
+
+void audiodevgetvol(int what, int *left, int *right) { error("not supported"); }