qemacs-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemacs-commit] qemacs Makefile configure haiku-pe2qe.sh haiku.cpp


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs Makefile configure haiku-pe2qe.sh haiku.cpp
Date: Tue, 17 Dec 2013 16:08:56 +0000

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        13/12/17 16:08:56

Modified files:
        .              : Makefile configure 
Added files:
        .              : haiku-pe2qe.sh haiku.cpp 

Log message:
        work-in-progress Haiku port from Francois Revol
        
        * Fix hardcoded -ldl and -lm in the Makefile
        * BeOS does not have -lm (it's part of libroot)
        * Add Haiku GUI driver haiku.cpp
        * Add helper script haiku-pe2qe.sh to clone color settings from Pe to 
Qemacs

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/Makefile?cvsroot=qemacs&r1=1.52&r2=1.53
http://cvs.savannah.gnu.org/viewcvs/qemacs/configure?cvsroot=qemacs&r1=1.18&r2=1.19
http://cvs.savannah.gnu.org/viewcvs/qemacs/haiku-pe2qe.sh?cvsroot=qemacs&rev=1.3
http://cvs.savannah.gnu.org/viewcvs/qemacs/haiku.cpp?cvsroot=qemacs&rev=1.3

Patches:
Index: Makefile
===================================================================
RCS file: /sources/qemacs/qemacs/Makefile,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -b -r1.52 -r1.53
--- Makefile    23 Nov 2013 10:54:32 -0000      1.52
+++ Makefile    17 Dec 2013 16:08:55 -0000      1.53
@@ -1,7 +1,7 @@
 # QEmacs, tiny but powerful multimode editor
 #
 # Copyright (c) 2000-2002 Fabrice Bellard.
-# Copyright (c) 2000-2008 Charlie Gordon.
+# Copyright (c) 2000-2013 Charlie Gordon.
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -63,7 +63,7 @@
 endif
 
 ifdef CONFIG_DLL
-  LIBS+=-ldl
+  LIBS+=$(DLLIBS)
   # export some qemacs symbols
   LDFLAGS+=-Wl,-E
 endif
@@ -72,6 +72,11 @@
   TARGETS+= qe-doc.html
 endif
 
+ifdef CONFIG_HAIKU
+  OBJS+= haiku.o
+  LIBS+= -lbe
+endif
+
 ifdef CONFIG_WIN32
   OBJS+= unix.o
   TOBJS+= unix.o
@@ -84,7 +89,7 @@
 else
   OBJS+= unix.o tty.o
   TOBJS+= unix.o tty.o
-  LIBS+= -lm
+  LIBS+= $(EXTRALIBS)
 endif
 
 ifdef CONFIG_QSCRIPT
@@ -226,6 +231,9 @@
 $(OBJS_DIR)/%.o: %.c qe.h qestyles.h config.h config.mak Makefile
        $(CC) $(DEFINES) $(CFLAGS) -o $@ -c $<
 
+$(OBJS_DIR)/haiku.o: haiku.cpp qe.h qestyles.h config.h config.mak Makefile
+       g++ $(DEFINES) $(CFLAGS) -Wno-multichar -o $@ -c $<
+
 #
 # Test for bidir algorithm
 #
@@ -392,7 +400,8 @@
        charsetjis.def charsetmore.c clang.c config.eg config.h      \
        configure cptoqe.c cutils.c cutils.h dired.c display.c       \
        display.h docbook.c extras.c fbffonts.c fbfrender.c          \
-       fbfrender.h fbftoqe.c hex.c html.c html2png.c htmlsrc.c      \
+       fbfrender.h fbftoqe.c haiku.cpp haiku-pe2qe.sh hex.c html.c  \
+       html2png.c htmlsrc.c                                         \
        image.c indic.c input.c jistoqe.c kmap.c kmaptoqe.c          \
        latex-mode.c libfbf.c libfbf.h ligtoqe.c list.c makemode.c   \
        mpeg.c perl.c qe-doc.html qe-doc.texi qe.1 qe.c qe.h qe.tcc  \

Index: configure
===================================================================
RCS file: /sources/qemacs/qemacs/configure,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -r1.18 -r1.19
--- configure   23 Nov 2013 10:55:20 -0000      1.18
+++ configure   17 Dec 2013 16:08:55 -0000      1.19
@@ -1,6 +1,9 @@
 #!/bin/bash
 #
-# qemacs configure script (c) 2002 Fabrice Bellard
+# QEmacs configure script
+#
+# Copyright (c) 2002 Fabrice Bellard
+# Copyright (c) 2002-2013 Charlie Gordon
 #
 
 # set temporary file name
@@ -50,7 +53,9 @@
 win32="no"
 cygwin="no"
 darwin="no"
+haiku="no"
 lshared="no"
+dllibs="-ldl"
 extralibs=""
 simpleidct="yes"
 bigendian="no"
@@ -82,10 +87,10 @@
     # no need for libm, but the inet stuff
     # Check for BONE
     if (echo $BEINCLUDES|grep 'headers/be/bone' >/dev/null); then
-        extralibs="-lbind -lsocket -lm"
+        extralibs="-lbind -lsocket"
     else
         echo "Not sure building for net_server will succeed... good luck."
-        extralibs="-lsocket -lm"
+        extralibs="-lsocket"
     fi
     ;;
   BSD/OS)
@@ -114,6 +119,19 @@
     extralibs="-lm"
     strip_args="-x -S"
     ;;
+  Haiku)
+    prefix="`finddir B_COMMON_DIRECTORY`"
+    # no need for libm, but the network stuff
+    extralibs="-lnetwork"
+    # dlopen() is in libroot already
+    dllibs=""
+    # use Haiku GUI; avoid building for X11 even if there are headers around
+    haiku="yes"
+    html="yes"
+    png="yes"
+    x11="no"
+    xv="no"
+    ;;
   *)
     extralibs="-lm"
     unlockio="yes"
@@ -298,6 +316,9 @@
 if test "$x11" = "no" ; then
     xv="no"
     xrender="no"
+fi
+
+if test "$x11" = "no" -a "$haiku" = "no" ; then
     png="no"
     ffmpeg="no"
     html="no"
@@ -498,6 +519,7 @@
   echo "BUILD_SHARED=yes" >> $TMPMAK
   echo "PIC=-fPIC" >> $TMPMAK
 fi
+echo "DLLIBS=$dllibs" >> $TMPMAK
 echo "EXTRALIBS=$extralibs" >> $TMPMAK
 echo -n "VERSION=" >> $TMPMAK
 echo -n `head $source_path/VERSION` >> $TMPMAK
@@ -525,6 +547,11 @@
   echo "CONFIG_DARWIN=yes" >> $TMPMAK
 fi
 
+if test "$haiku" = "yes" ; then
+  echo "#define CONFIG_HAIKU 1" >> $TMPH
+  echo "CONFIG_HAIKU=yes" >> $TMPMAK
+fi
+
 if test "$x11" = "yes" ; then
   echo "#define CONFIG_X11 1" >> $TMPH
   echo "CONFIG_X11=yes" >> $TMPMAK

Index: haiku-pe2qe.sh
===================================================================
RCS file: haiku-pe2qe.sh
diff -N haiku-pe2qe.sh
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ haiku-pe2qe.sh      17 Dec 2013 16:08:55 -0000      1.3
@@ -0,0 +1,85 @@
+#!/bin/sh
+
+pesettings=`finddir B_USER_SETTINGS_DIRECTORY`/pe/settings
+
+fgmap=(
+"alt comment:"
+"alt error:"
+"alt keyword:"
+"alt number:"
+"alt operator:"
+"alt separator:"
+"altprocessor:"
+"attribute:"
+"char constant:html-entity"
+"comment:comment html-comment"
+"error:"
+"highlight:highlight"
+"invisibles:"
+"keyword:keyword preprocess"
+"low:window-border"
+"mark:status"
+"number:number"
+"operator:function"
+"preprocessor:"
+"selection:selection"
+"separator:"
+"string:string string-q html-string"
+"system identifier:type"
+"tag:tag"
+"tagstring:html-tag"
+"text:default mode-line minibuf"
+"user identifier:variable"
+)
+
+bgmap=(
+"low:default"
+"selection:mode-line window-border region-hilite"
+)
+
+map_pe_fg () {
+       for item in "address@hidden"; do
+               if [ "$1" = "${item%:*}" ]; then
+                       echo "${item#*:}"
+                       return
+               fi
+       done
+}
+
+map_pe_bg () {
+       for item in "address@hidden"; do
+               if [ "$1" = "${item%:*}" ]; then
+                       echo "${item#*:}"
+                       return
+               fi
+       done
+}
+
+out_style () {
+       echo "set_style(\"$1\", \"$2\", \"$3\")"
+}
+
+echo "// map Pe settings to QEmacs"
+echo "// generated by $(basename "$0") on `date`"
+
+while read line; do
+       token="${line%=*}"
+       value="${line#*=}"
+       case "$token" in
+               *color)
+                       name="${token% color}"
+                       qenames="$(map_pe_fg "$name")"
+                       for qename in ${qenames}; do
+                               #echo "color: $name -> $qename" >&2
+                               out_style "$qename" "color" "$value"
+                       done
+                       qenames="$(map_pe_bg "$name")"
+                       for qename in ${qenames}; do
+                               #echo "bgcolor: $name -> $qename" >&2
+                               out_style "$qename" "background-color" "$value"
+                       done
+                       ;;
+               *)
+                       ;;
+       esac
+done < "$pesettings"

Index: haiku.cpp
===================================================================
RCS file: haiku.cpp
diff -N haiku.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ haiku.cpp   17 Dec 2013 16:08:56 -0000      1.3
@@ -0,0 +1,883 @@
+/*
+ * Haiku driver for QEmacs
+ * Copyright (c) 2013 Francois Revol.
+ * Copyright (c) 2002 Fabrice Bellard.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+
+extern "C" {
+#include "qe.h"
+}
+
+#include <Application.h>
+#include <Bitmap.h>
+#include <FindDirectory.h>
+#include <Font.h>
+#include <InterfaceDefs.h>
+#include <Path.h>
+#include <Region.h>
+#include <String.h>
+#include <View.h>
+#include <Window.h>
+
+extern QEDisplay haiku_dpy;
+
+static int force_tty = 0;
+
+static int font_xsize;
+
+class QEWindow;
+class QEView;
+
+/* state of a single window */
+typedef struct WindowState {
+    BWindow *w;
+    BView *v;
+    BFont font;
+    int events_rd;
+    int events_wr;
+} WindowState;
+
+WindowState haiku_ctx;
+static thread_id bapp_thid;
+static int bapp_ref_count = 0;
+static int events_wr;
+
+/* count of pending repaints */
+static vint32 repaints = 0;
+//TODO:use double-buffering with a BBitmap
+
+static void haiku_handle_event(void *opaque);
+
+static status_t bmessage_input(QEWindow *win, QEView *view, BMessage *message)
+{
+    if (!message)
+        return EINVAL;
+    /* push the message into the pipe */
+    if (write(events_wr, &message, sizeof(BMessage *)) < 0)
+        return errno;
+    return B_OK;
+}
+
+class QEWindow : public BWindow {
+    public:
+        QEWindow(BRect frame, const char *name, QEView *view)
+                : BWindow(frame, name, B_TITLED_WINDOW, 0)
+                , fView(view)
+        {}
+
+        virtual ~QEWindow() {}
+
+        //virtual void Show();
+        //virtual void Hide();
+        //virtual void Minimize(bool minimize);
+        virtual bool QuitRequested();
+        virtual void DispatchMessage(BMessage *message, BHandler *handler);
+
+    private:
+        QEView *fView;
+};
+
+class QEView : public BView {
+    public:
+        QEView(BRect frame, const char *name);
+        virtual ~QEView();
+
+        virtual void MouseDown(BPoint where);
+        virtual void MouseUp(BPoint where);
+        virtual void MouseMoved(BPoint where, uint32 code, const BMessage 
*a_message);
+        virtual void KeyDown(const char *bytes, int32 numBytes);
+        virtual void KeyUp(const char *bytes, int32 numBytes);
+        virtual void Draw(BRect updateRect);
+        virtual void FrameResized(float new_width, float new_height);
+#if 0
+        virtual void WindowActivated(bool state);
+        virtual void MessageReceived(BMessage *message);
+#endif
+};
+
+
+bool QEWindow::QuitRequested()
+{
+    BMessage *message = new BMessage(B_QUIT_REQUESTED);
+    bmessage_input(this, NULL, message);
+    return false;
+}
+
+void QEWindow::DispatchMessage(BMessage *message, BHandler *handler)
+{
+    uint32 mods;
+
+    switch (message->what) {
+    case B_MOUSE_WHEEL_CHANGED:
+        {
+            BMessage *message = DetachCurrentMessage();
+            bmessage_input(this, NULL, message);
+        }
+        break;
+    case B_KEY_DOWN:
+        if ((message->FindInt32("modifiers", (int32 *)&mods) == B_OK) && 
+              (mods & B_COMMAND_KEY)) {
+            /* BWindow swallows KEY_DOWN when ALT is down...
+             * so this hack is needed.
+             */
+            fView->KeyDown(NULL, 0);
+            return;
+        }
+        break;
+    case B_UNMAPPED_KEY_DOWN:
+    case B_UNMAPPED_KEY_UP:
+    case B_KEY_UP:
+        //message->PrintToStream();
+        break;
+    }
+    BWindow::DispatchMessage(message, handler);
+}
+
+QEView::QEView(BRect frame, const char *name)
+        : BView(frame, name, B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_FRAME_EVENTS)
+{
+    SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
+    //SetViewColor(0, 255, 0);
+}
+
+QEView::~QEView()
+{
+}
+
+void QEView::MouseDown(BPoint where)
+{
+    BMessage *message = Window()->DetachCurrentMessage();
+    bmessage_input(NULL, this, message);
+}
+
+void QEView::MouseUp(BPoint where)
+{
+    BMessage *message = Window()->DetachCurrentMessage();
+    bmessage_input(NULL, this, message);
+}
+
+void QEView::MouseMoved(BPoint where, uint32 code, const BMessage *a_message)
+{
+    BMessage *message = Window()->DetachCurrentMessage();
+    bmessage_input(NULL, this, message);
+}
+
+void QEView::KeyDown(const char *bytes, int32 numBytes)
+{
+    BMessage *message = Window()->DetachCurrentMessage();
+    //message->PrintToStream();
+    bmessage_input(NULL, this, message);
+}
+
+void QEView::KeyUp(const char *bytes, int32 numBytes)
+{
+    uint32 mods;
+    BMessage *message = Window()->DetachCurrentMessage();
+    //message->PrintToStream();
+    bmessage_input(NULL, this, message);
+}
+
+void QEView::Draw(BRect updateRect)
+{
+    BMessage *message = new BMessage(_UPDATE_);
+    message->AddRect("update_rect", updateRect);
+    atomic_add(&repaints, 1);
+    bmessage_input(NULL, this, message);
+}
+
+void QEView::FrameResized(float new_width, float new_height)
+{
+    BMessage *message = Window()->DetachCurrentMessage();
+    atomic_set(&repaints, 0);
+    bmessage_input(NULL, this, message);
+    BView::FrameResized(new_width, new_height);
+}
+
+static int haiku_probe(void)
+{
+    if (force_tty)
+        return 0;
+    return 2;
+}
+
+static int32 bapp_quit_thread(void *arg)
+{
+    be_app->Lock();
+    be_app->Quit();
+    return 0;
+}
+
+static int32 bapp_thread(void *arg)
+{
+    be_app->Lock();
+    be_app->Run();
+    return 0;
+}
+
+static void init_application(void)
+{
+    bapp_ref_count++;
+
+    if (be_app)
+        return; /* done already! */
+
+    new BApplication("application/x-vnd.Bellard-QEmacs");
+    //new XEmacsApp;
+    bapp_thid = spawn_thread(bapp_thread, "BApplication(QEmacs)",
+                             B_NORMAL_PRIORITY, (void *)find_thread(NULL));
+    if (bapp_thid < B_OK)
+        return; /* #### handle errors */
+    if (resume_thread(bapp_thid) < B_OK)
+        return;
+    // This way we ensure we don't create BWindows before be_app is created
+    // (creating it in the thread doesn't ensure this)
+    be_app->Unlock();
+}
+
+static void uninit_application(void)
+{
+    status_t err;
+    if (--bapp_ref_count)
+        return;
+    be_app->Lock();
+    be_app->Quit();
+    //XXX:HACK
+    be_app->Unlock();
+    //be_app_messenger.SendMessage(B_QUIT_REQUESTED);
+    wait_for_thread(bapp_thid, &err);
+    //FIXME:leak or crash
+    //delete be_app;
+    be_app = NULL;
+}
+
+static int haiku_init(QEditScreen *s, int w, int h)
+{
+    int xsize, ysize, font_ysize;
+    WindowState *ctx;
+    
+    if (!be_app) 
+        init_application();
+
+    memcpy(&s->dpy, &haiku_dpy, sizeof(QEDisplay));
+
+    ctx = (WindowState *)malloc(sizeof(WindowState));
+    if (ctx == NULL)
+        return -1;
+    s->priv_data = ctx;
+    s->media = CSS_MEDIA_SCREEN;
+
+    s->bitmap_format = QEBITMAP_FORMAT_RGBA32;
+    /* BBitmap supports overlay, but not planar data */
+    //s->video_format = QEBITMAP_FORMAT_RGBA32;
+
+    int event_pipe[2];
+    if (pipe(event_pipe) < 0)
+        return -1;
+
+    fcntl(event_pipe[0], F_SETFD, FD_CLOEXEC);
+    fcntl(event_pipe[1], F_SETFD, FD_CLOEXEC);
+
+    ctx->events_rd = event_pipe[0];
+    ctx->events_wr = events_wr = event_pipe[1];
+
+    set_read_handler(event_pipe[0], haiku_handle_event, s);
+
+    ctx->font = BFont(be_fixed_font);
+
+    font_height height;
+    ctx->font.GetHeight(&height);
+
+    font_xsize = (int)ctx->font.StringWidth("n");
+    font_ysize = (int)(height.ascent + height.descent + height.leading + 1);
+
+    if (w == 0)
+        w = 80;
+    if (h == 0)
+        h = 25;
+    xsize = w * font_xsize;
+    ysize = h * font_ysize;
+
+    s->width = xsize;
+    s->height = ysize;
+    s->charset = &charset_utf8;
+
+    s->clip_x1 = 0;
+    s->clip_y1 = 0;
+    s->clip_x2 = s->width;
+    s->clip_y2 = s->height;
+
+    BRect frame(0, 0, s->width - 1, s->height - 1);
+
+    QEView *v = new QEView(frame, "qemacs");
+    ctx->v = v;
+
+    frame.OffsetTo(200, 200);
+
+    ctx->w = new QEWindow(frame, "qemacs", v);
+    ctx->w->AddChild(ctx->v);
+    ctx->v->MakeFocus();
+    //ctx->v->SetViewColor(B_TRANSPARENT_COLOR);
+    ctx->v->SetDrawingMode(B_OP_OVER);
+
+    ctx->w->Show();
+    
+    return 0;
+}
+
+static void haiku_close(QEditScreen *s)
+{
+    WindowState *ctx = (WindowState *)s->priv_data;
+    ctx->w->Lock();
+    ctx->w->Quit();
+    free(s->priv_data);
+}
+
+static void haiku_flush(QEditScreen *s)
+{
+    WindowState *ctx = (WindowState *)s->priv_data;
+    //fprintf(stderr, "%s()\n", __FUNCTION__);
+
+    ctx->v->LockLooper();
+
+    // doesn't really help
+    ctx->v->Sync();
+
+    ctx->v->UnlockLooper();
+}
+
+static int haiku_is_user_input_pending(QEditScreen *s)
+{
+    /* XXX: do it */
+    return 0;
+}
+
+/* called when an BMessage is forwarded. dispatch events to qe_handle_event() 
*/
+static void haiku_handle_event(void *opaque)
+{
+    QEditScreen *s = (QEditScreen *)opaque;
+    WindowState *ctx = (WindowState *)s->priv_data;
+    unsigned char buf[16];
+    bigtime_t timestamp_ms;
+    BMessage *event;
+    //fprintf(stderr, "%s()\n", __FUNCTION__);
+    /*
+    KeySym keysym;
+    */
+    int shift, ctrl, meta, len, key = 0;
+    QEEvent ev1, *ev = &ev1;
+
+    if (read(ctx->events_rd, &event, sizeof(BMessage *)) < sizeof(BMessage *))
+        return;
+    //event->PrintToStream();
+
+    switch(event->what) {
+    case B_QUIT_REQUESTED:
+        // cancel pending operation
+        ev->key_event.type = QE_KEY_EVENT;
+        ev->key_event.key = KEY_CTRL('g');
+        qe_handle_event(ev);
+
+        // simulate C-x C-c
+        ev->key_event.type = QE_KEY_EVENT;
+        ev->key_event.key = KEY_CTRL('x');
+        qe_handle_event(ev);
+        ev->key_event.type = QE_KEY_EVENT;
+        ev->key_event.key = KEY_CTRL('c');
+        qe_handle_event(ev);
+        break;
+
+    case _UPDATE_:
+        // flush queued repaints
+        if (atomic_set(&repaints, 0)) {
+            ev->expose_event.type = QE_EXPOSE_EVENT;
+            qe_handle_event(ev);
+        }
+        break;
+
+    case B_VIEW_RESIZED:
+        {
+            int32 width, height;
+            int columns, rows;
+            //event->PrintToStream();
+/*
+            if (event->FindInt32("width", &width) < B_OK)
+                break;
+            if (event->FindInt32("height", &height) < B_OK)
+                break;
+*/
+            ctx->v->LockLooper();
+
+            width = ctx->v->Bounds().IntegerWidth() + 1;
+            height = ctx->v->Bounds().IntegerHeight() + 1;
+
+            if (width != s->width || height != s->height)
+                ctx->v->Invalidate(ctx->v->Bounds());
+
+            s->width = width;
+            s->height = height;
+            
+            ctx->v->UnlockLooper();
+
+            //ev->expose_event.type = QE_EXPOSE_EVENT;
+            //qe_handle_event(ev);
+        }
+        break;
+
+    case B_MOUSE_MOVED:
+        {
+            BPoint pt;
+
+            ev->button_event.type = QE_MOTION_EVENT;
+            ev->button_event.x = (int)pt.x;
+            ev->button_event.y = (int)pt.y;
+            qe_handle_event(ev);
+        }
+        break;
+
+    case B_MOUSE_DOWN:
+    case B_MOUSE_UP:
+        {
+            BPoint pt;
+            uint32 buttons;
+
+            if (event->what == B_MOUSE_DOWN)
+                ev->button_event.type = QE_BUTTON_PRESS_EVENT;
+            else
+                ev->button_event.type = QE_BUTTON_RELEASE_EVENT;
+
+            if (event->FindPoint("where", &pt) < B_OK)
+                pt = BPoint(0,0);
+            ev->button_event.x = (int)pt.x;
+            ev->button_event.y = (int)pt.y;
+
+            if (event->FindInt32("buttons", (int32 *)&buttons) < B_OK)
+                buttons = (event->what == B_MOUSE_UP)?0:B_PRIMARY_MOUSE_BUTTON;
+
+
+            if (buttons & B_PRIMARY_MOUSE_BUTTON)
+                ev->button_event.button = QE_BUTTON_LEFT;
+            else if (buttons & B_SECONDARY_MOUSE_BUTTON)
+                ev->button_event.button = QE_BUTTON_MIDDLE;
+            else if (buttons & B_TERTIARY_MOUSE_BUTTON)
+                ev->button_event.button = QE_BUTTON_RIGHT;
+
+            qe_handle_event(ev);
+        }
+        break;
+
+    case B_MOUSE_WHEEL_CHANGED:
+        {
+            float delta;
+
+            ev->button_event.type = QE_BUTTON_PRESS_EVENT;
+
+            if (event->FindFloat("be:wheel_delta_y", &delta) < B_OK)
+                delta = 0.0;
+
+            if (delta > 0)
+                ev->button_event.button = QE_WHEEL_DOWN;
+            else if (delta < 0)
+                ev->button_event.button = QE_WHEEL_UP;
+            else
+                break;
+
+            qe_handle_event(ev);
+        }
+        break;
+
+    case B_KEY_UP:
+        break;
+
+    case B_KEY_DOWN:
+        {
+            unsigned int mods = 0;
+            uint32 state;
+            //event->PrintToStream();
+            uint32 scancode;
+            uint32 raw_char;
+            const char *bytes;
+            char buff[6];
+            int numbytes = 0;
+            int i;
+
+            if (event->FindInt64("when", &timestamp_ms) < B_OK)
+                timestamp_ms = 0LL;
+            if (event->FindInt32("modifiers", (int32 *)&state) < B_OK)
+                state = modifiers();
+            if (event->FindInt32("key", (int32 *)&scancode) < B_OK)
+                scancode = 0;
+            if (event->FindInt32("raw_char", (int32 *)&raw_char) < B_OK)
+                raw_char = 0;
+
+            /* check for byte[] first,
+             * because C-space gives bytes="" (and byte[0] = '\0')
+             */
+            for (i = 0; i < 5; i++) {
+                buff[i] = '\0';
+                if (event->FindInt8("byte", i, (int8 *)&buff[i]) < B_OK)
+                    break;
+            }
+
+            if (i) {
+                bytes = buff;
+                numbytes = i;
+            } else
+            if (event->FindString("bytes", &bytes) < B_OK) {
+                bytes = "";
+            }
+
+            if (!numbytes)
+                numbytes = strlen(bytes);
+
+            shift = (state & B_SHIFT_KEY);
+            ctrl = (state & B_CONTROL_KEY);
+            meta = (state & (B_LEFT_OPTION_KEY | B_COMMAND_KEY));
+
+            //fprintf(stderr, "%cshift %cctrl %cmeta numbytes %d \n",
+            //        shift ? ' ' : '!', ctrl ? ' ' : '!', meta ? ' ' : '!', 
numbytes);
+
+            char byte = 0;
+            if (numbytes == 1) {
+                byte = bytes[0];
+                if (state & B_CONTROL_KEY)
+                    byte = (char)raw_char;
+                switch (byte) {
+                case B_BACKSPACE:
+                    key = KEY_BS;
+                    if (meta)
+                        key = KEY_META(KEY_BS);
+                    break;
+                case B_TAB:
+                    key = KEY_TAB;
+                    break;
+                case B_ENTER:
+                    key = KEY_RET;
+                    break;
+                case B_ESCAPE:
+                    key = KEY_ESC;
+                    break;
+                case B_SPACE:
+                    key = KEY_SPC;
+                    break;
+                case B_DELETE:
+                    key = KEY_DELETE;
+                    break;
+                case B_INSERT:
+                    key = KEY_INSERT;
+                    break;
+                case B_HOME:
+                    key = ctrl ? KEY_CTRL_HOME : KEY_HOME;
+                    break;
+                case B_END:
+                    key = ctrl ? KEY_CTRL_END : KEY_END;
+                    break;
+                case B_PAGE_UP:
+                    key = KEY_PAGEUP;
+                    break;
+                case B_PAGE_DOWN:
+                    key = KEY_PAGEDOWN;
+                    break;
+                case B_LEFT_ARROW:
+                    key = ctrl ? KEY_CTRL_LEFT : KEY_LEFT;
+                    break;
+                case B_RIGHT_ARROW:
+                    key = ctrl ? KEY_CTRL_RIGHT : KEY_RIGHT;
+                    break;
+                case B_UP_ARROW:
+                    key = KEY_UP;
+                    break;
+                case B_DOWN_ARROW:
+                    key = KEY_DOWN;
+                    break;
+                case B_FUNCTION_KEY:
+                    switch (scancode) {
+                    case B_F1_KEY:
+                    case B_F2_KEY:
+                    case B_F3_KEY:
+                    case B_F4_KEY:
+                    case B_F5_KEY:
+                    case B_F6_KEY:
+                    case B_F7_KEY:
+                    case B_F8_KEY:
+                    case B_F9_KEY:
+                    case B_F10_KEY:
+                    case B_F11_KEY:
+                    case B_F12_KEY:
+                        key = KEY_F1 + scancode - B_F1_KEY;
+                        break;
+                    case B_PRINT_KEY:
+                    case B_SCROLL_KEY:
+                    case B_PAUSE_KEY:
+                    default:
+                        break;
+                    }
+                    break;
+                case 0:
+                    break;
+                default:
+                    if (byte >= ' ' && byte <= '~') {
+                        if (meta)
+                            key = KEY_META(' ') + byte - ' ';
+                        else if (ctrl)
+                            key = KEY_CTRL(byte);
+                        else
+                            key = byte;
+                    }
+                }
+            } else {
+                const char *p = bytes;
+                key = utf8_decode(&p);
+            }
+
+        got_key:
+            if (key) {
+                ev->key_event.type = QE_KEY_EVENT;
+                ev->key_event.key = key;
+                qe_handle_event(ev);
+            }
+        }
+        break;
+    }
+
+    delete event;
+}
+
+static void haiku_fill_rectangle(QEditScreen *s,
+                                 int x1, int y1, int w, int h, QEColor color)
+{
+    WindowState *ctx = (WindowState *)s->priv_data;
+    //fprintf(stderr, "%s()\n", __FUNCTION__);
+    drawing_mode oldMode;
+
+    BRect r(x1, y1, x1 + w - 1, y1 + h - 1);
+    rgb_color c = { (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, 
0xff };
+
+    ctx->v->LockLooper();
+
+    oldMode = ctx->v->DrawingMode();
+
+    /* XXX: suppress XOR mode */
+    if (color == QECOLOR_XOR)
+        ctx->v->SetDrawingMode(B_OP_INVERT);
+    else
+        ctx->v->SetHighColor(c);
+    ctx->v->FillRect(r);
+
+    /* XXX: suppress XOR mode */
+    if (color == QECOLOR_XOR)
+        ctx->v->SetDrawingMode(oldMode);
+    
+    ctx->v->UnlockLooper();
+}
+
+static QEFont *haiku_open_font(QEditScreen *s, int style, int size)
+{
+    WindowState *ctx = (WindowState *)s->priv_data;
+    //fprintf(stderr, "%s()\n", __FUNCTION__);
+    QEFont *font;
+
+    font = (QEFont *)malloc(sizeof(QEFont));
+    if (!font)
+        return NULL;
+
+    // TODO: use style / size
+    BFont *f = new BFont(ctx->font);
+
+    font_height height;
+    f->GetHeight(&height);
+    font->ascent = (int)height.ascent;
+    font->descent = (int)(height.descent + height.leading + 1);
+    font->priv_data = f;
+    return font;
+}
+
+static void haiku_close_font(QEditScreen *s, QEFont *font)
+{
+    BFont *f = (BFont *)font->priv_data;
+    delete f;
+    free(font);
+}
+
+static void haiku_text_metrics(QEditScreen *s, QEFont *font, 
+                               QECharMetrics *metrics,
+                               const unsigned int *str, int len)
+{
+    //TODO: use BFont::GetEscapements() or StringWidth()
+    int i, x;
+
+    metrics->font_ascent = font->ascent;
+    metrics->font_descent = font->descent;
+    x = 0;
+    for (i = 0; i < len; i++)
+        x += font_xsize;
+    metrics->width = x;
+}
+
+static void haiku_draw_text(QEditScreen *s, QEFont *font,
+                            int x1, int y, const unsigned int *str, int len,
+                            QEColor color)
+{
+    WindowState *ctx = (WindowState *)s->priv_data;
+    BFont *f = (BFont *)(font->priv_data);
+    int i;
+    //fprintf(stderr, "%s()\n", __FUNCTION__);
+
+   /* XXX: suppress XOR mode */
+   if (color == QECOLOR_XOR)
+       color = QERGB(0xff, 0xff, 0xff);
+
+    rgb_color c = { (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, 
0xff };
+
+    ctx->v->LockLooper();
+
+    ctx->v->SetHighColor(c);
+    ctx->v->SetLowColor(B_TRANSPARENT_COLOR);
+    ctx->v->SetFont(f);
+    ctx->v->MovePenTo(x1, y - 1);
+
+    char buf[10];
+    unsigned int cc;
+
+    BString text;
+    for (i = 0; i < len; i++) {
+        cc = str[i];
+        unicode_to_charset(buf, cc, &charset_utf8);
+        text << buf;
+        //ctx->v->DrawString(buf);
+    }
+    ctx->v->DrawString(text.String());
+
+    ctx->v->UnlockLooper();
+
+    //TextOutW(haiku_ctx.hdc, x1, y - font->ascent, buf, len);
+}
+
+static void haiku_set_clip(QEditScreen *s,
+                           int x, int y, int w, int h)
+{
+    WindowState *ctx = (WindowState *)s->priv_data;
+    //fprintf(stderr, "%s(,%d, %d, %d, %d)\n", __FUNCTION__, x, y, w, h);
+
+    BRegion clip(BRect(x, y, x + w - 1, y + h - 1));
+
+    ctx->v->LockLooper();
+
+    ctx->v->ConstrainClippingRegion(&clip);
+
+    ctx->v->UnlockLooper();
+}
+
+static int haiku_bmp_alloc(QEditScreen *s, QEBitmap *b)
+{
+    BBitmap *bitmap;
+    color_space space = B_RGBA32;
+    uint32 flags = 0;
+
+    b->format = s->bitmap_format;
+    if (b->flags & QEBITMAP_FLAG_VIDEO) {
+        b->format = s->video_format;
+    }
+    //fprintf(stderr, "%s(, [w %d, h %d])\n", __FUNCTION__, b->width, 
b->height);
+    switch (b->format) {
+    case QEBITMAP_FORMAT_RGB565:
+        space = B_RGB16;
+        break;
+    case QEBITMAP_FORMAT_RGB555:
+        space = B_RGB15;
+        break;
+    case QEBITMAP_FORMAT_RGB24:
+        space = B_RGB24;
+        break;
+    case QEBITMAP_FORMAT_RGBA32:
+        space = B_RGBA32;
+        break;
+    case QEBITMAP_FORMAT_YUV420P:
+        // we don't support planar overlays
+    default:
+        return -1;
+    }
+
+    BRect bounds(0, 0, b->width - 1, b->height - 1);
+    bitmap = new BBitmap(bounds, flags, space);
+    if (bitmap->InitCheck() != B_OK) {
+        delete bitmap;
+        return -1;
+    }
+    b->priv_data = bitmap;
+
+    return 0;
+}
+
+static void haiku_bmp_free(__unused__ QEditScreen *s, QEBitmap *b)
+{
+    BBitmap *bitmap = (BBitmap *)b->priv_data;
+    delete bitmap;
+    b->priv_data = NULL;
+}
+
+extern QEDisplay haiku_dpy = {
+    "haiku",
+    haiku_probe,
+    haiku_init,
+    haiku_close,
+    haiku_flush,
+    haiku_is_user_input_pending,
+    haiku_fill_rectangle,
+    haiku_open_font,
+    haiku_close_font,
+    haiku_text_metrics,
+    haiku_draw_text,
+    haiku_set_clip,
+    NULL, /* no selection handling */
+    NULL, /* no selection handling */
+    NULL, /* dpy_invalidate */
+    NULL, /* dpy_cursor_at */
+    haiku_bmp_alloc, /* dpy_bmp_alloc */
+    haiku_bmp_free, /* dpy_bmp_free */
+    NULL, /* dpy_bmp_draw */
+    NULL, /* dpy_bmp_lock */
+    NULL, /* dpy_bmp_unlock */
+    NULL, /* dpy_full_screen */
+    NULL, /* next */
+};
+
+static CmdOptionDef cmd_options[] = {
+    { "no-windows", "nw", NULL, CMD_OPT_BOOL, "force tty terminal usage",
+       { int_ptr: &force_tty }},
+    { NULL, NULL, NULL, 0, NULL, { NULL }},
+};
+
+static int haiku_init(void)
+{
+    QEmacsState *qs = &qe_state;
+
+    /* override default res path, to find config file at native location */
+    BPath path;
+    BString old(":");
+    old << qs->res_path;
+    qs->res_path[0] = '\0';
+    if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
+        path.Append("qemacs");
+        pstrcat(qs->res_path, sizeof(qs->res_path), path.Path());
+    }
+    pstrcat(qs->res_path, sizeof(qs->res_path), old.String());
+
+    qe_register_cmd_line_options(cmd_options);
+    return qe_register_display(&haiku_dpy);
+}
+
+qe_module_init(haiku_init);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]