Hey there, here is a work-in-progress Haiku port patch. It's mostly working, although I will have to fix a few things about the install target, after our recent adoption of a package management system. I had this one sitting here for a while, and sent a mail to Fabrice but I guess he's very busy, so after having to merge with the latest commits I thought I'd upstream this ASAP.
See also the port recipe at: http://bb.haikuports.org/haikuports/src/5d2152bbb48aa72881ab879ab95c80e5c19f525d/app-editors/qemacs/?at=master * Fix hardcoded -ldl and -lm in the Makefile * BeOS does not have -lm (it's part of libroot) * renamed "private" field to "priv_data" in QEFont to avoid clashing with C++ private keyword. * Fix in vt100 code to handle alternative codes for arrows, if I recall correctly. * Add Haiku GUI driver * Add helper script to clone color settings from Pe to Qemacs Cheers, François.
work-in-progress Haiku port * Fix hardcoded -ldl and -lm in the Makefile * BeOS does not have -lm (it's part of libroot) * renamed "private" field to "priv_data" in QEFont for C++ compatibility * Fix in vt100 code to handle alternative codes for arrows * Add Haiku GUI driver * Add helper script to clone color settings from Pe to Qemacs Index: Makefile =================================================================== RCS file: /sources/qemacs/qemacs/Makefile,v retrieving revision 1.52 diff -u -r1.52 Makefile --- Makefile 23 Nov 2013 10:54:32 -0000 1.52 +++ Makefile 15 Dec 2013 18:19:13 -0000 @@ -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 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: cfb.c =================================================================== RCS file: /sources/qemacs/qemacs/cfb.c,v retrieving revision 1.8 diff -u -r1.8 cfb.c --- cfb.c 8 Apr 2008 06:55:44 -0000 1.8 +++ cfb.c 15 Dec 2013 18:19:13 -0000 @@ -50,7 +50,7 @@ static void cfb16_fill_rectangle(QEditScreen *s, int x1, int y1, int w, int h, QEColor color) { - CFBContext *cfb = s->private; + CFBContext *cfb = s->priv_data; unsigned char *dest, *d; int y, n; unsigned int col; @@ -101,7 +101,7 @@ static void cfb32_fill_rectangle(QEditScreen *s, int x1, int y1, int w, int h, QEColor color) { - CFBContext *cfb = s->private; + CFBContext *cfb = s->priv_data; unsigned char *dest, *d; int y, n; unsigned int col; @@ -145,7 +145,7 @@ int x1, int y1, int w, int h, QEColor color, unsigned char *glyph, int glyph_wrap) { - CFBContext *cfb = s1->private; + CFBContext *cfb = s1->priv_data; unsigned char *dest, *d, *s, *src; int n; unsigned int col; @@ -189,7 +189,7 @@ int x1, int y1, int w, int h, QEColor color, unsigned char *glyph, int glyph_wrap) { - CFBContext *cfb = s1->private; + CFBContext *cfb = s1->priv_data; unsigned char *dest, *d, *s, *src; int n; unsigned int col; @@ -233,7 +233,7 @@ int x_start, int y, const unsigned int *str, int len, QEColor color) { - CFBContext *cfb = s->private; + CFBContext *cfb = s->priv_data; GlyphCache *g; unsigned char *glyph_ptr; int i, x1, y1, x2, y2, wrap, x; @@ -309,7 +309,7 @@ int cfb_init(QEditScreen *s, void *base, int wrap, int depth, const char *font_path) { - CFBContext *cfb = s->private; + CFBContext *cfb = s->priv_data; cfb->base = base; cfb->wrap = wrap; Index: configure =================================================================== RCS file: /sources/qemacs/qemacs/configure,v retrieving revision 1.18 diff -u -r1.18 configure --- configure 23 Nov 2013 10:55:20 -0000 1.18 +++ configure 15 Dec 2013 18:19:13 -0000 @@ -47,10 +47,12 @@ ptsname="yes" gprof="no" network="yes" +haiku="no" win32="no" cygwin="no" darwin="no" lshared="no" +dllibs="-ldl" extralibs="" simpleidct="yes" bigendian="no" @@ -82,10 +84,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 +116,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,8 +313,11 @@ if test "$x11" = "no" ; then xv="no" xrender="no" - png="no" +fi + +if test "$x11" = "no" -a "$haiku" = "no" ; then ffmpeg="no" + png="no" html="no" fi @@ -498,6 +516,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 @@ -510,6 +529,11 @@ echo "CONFIG_NETWORK=yes" >> $TMPMAK fi +if test "$haiku" = "yes" ; then + echo "#define CONFIG_HAIKU 1" >> $TMPH + echo "CONFIG_HAIKU=yes" >> $TMPMAK +fi + if test "$win32" = "yes" ; then echo "#define CONFIG_WIN32 1" >> $TMPH echo "CONFIG_WIN32=yes" >> $TMPMAK Index: display.h =================================================================== RCS file: /sources/qemacs/qemacs/display.h,v retrieving revision 1.11 diff -u -r1.11 display.h --- display.h 11 Jan 2008 11:29:28 -0000 1.11 +++ display.h 15 Dec 2013 18:19:13 -0000 @@ -53,7 +53,7 @@ int refcount; int ascent; int descent; - void *private; + void *priv_data; int system_font; /* TRUE if system font */ /* cache data */ int style; @@ -148,12 +148,12 @@ QECharset *charset; /* the charset of the TTY, XXX: suppress that, use a system in fonts instead */ int media; /* media type (see CSS_MEDIA_xxx) */ - int bitmap_format; /* supported bitmap format */ - int video_format; /* supported video format */ + QEBitmapFormat bitmap_format; /* supported bitmap format */ + QEBitmapFormat video_format; /* supported video format */ /* clip region handling */ int clip_x1, clip_y1; int clip_x2, clip_y2; - void *private; + void *priv_data; }; int qe_register_display(QEDisplay *dpy); Index: fbfrender.c =================================================================== RCS file: /sources/qemacs/qemacs/fbfrender.c,v retrieving revision 1.10 diff -u -r1.10 fbfrender.c --- fbfrender.c 8 Jan 2008 16:37:54 -0000 1.10 +++ fbfrender.c 15 Dec 2013 18:19:13 -0000 @@ -124,7 +124,7 @@ static GlyphCache *fbf_decode_glyph1(QEFont *font, int code) { - UniFontData *uf = font->private; + UniFontData *uf = font->priv_data; int glyph_index, size, src_width, src_height; GlyphCache *glyph_cache; GlyphEntry *fbf_glyph_entry; @@ -270,7 +270,7 @@ } } } - font->private = uf_found; + font->priv_data = uf_found; font->ascent = uf_found->ascent; font->descent = uf_found->descent; return font; Index: html2png.c =================================================================== RCS file: /sources/qemacs/qemacs/html2png.c,v retrieving revision 1.12 diff -u -r1.12 html2png.c --- html2png.c 11 Jan 2008 11:29:28 -0000 1.12 +++ html2png.c 15 Dec 2013 18:19:13 -0000 @@ -135,7 +135,7 @@ /* realloc ppm bitmap */ static int ppm_resize(QEditScreen *s, int w, int h) { - CFBContext *cfb = s->private; + CFBContext *cfb = s->priv_data; /* alloc bitmap */ if (!qe_realloc(&cfb->base, w * h * sizeof(int))) { @@ -160,7 +160,7 @@ if (!cfb) return -1; - s->private = cfb; + s->priv_data = cfb; s->media = CSS_MEDIA_SCREEN; if (cfb_init(s, NULL, w * sizeof(int), 32, ".") < 0) @@ -169,7 +169,7 @@ if (ppm_resize(s, w, h) < 0) { fail: qe_free(&cfb->base); - qe_free(&s->private); + qe_free(&s->priv_data); return -1; } return 0; @@ -177,15 +177,15 @@ static void ppm_close(QEditScreen *s) { - CFBContext *cfb = s->private; + CFBContext *cfb = s->priv_data; qe_free(&cfb->base); - qe_free(&s->private); + qe_free(&s->priv_data); } static int ppm_save(QEditScreen *s, const char *filename) { - CFBContext *cfb = s->private; + CFBContext *cfb = s->priv_data; int w, h, x, y; unsigned int r, g, b, v; unsigned int *data; @@ -219,7 +219,7 @@ static int png_save(QEditScreen *s, const char *filename) { - CFBContext *cfb = s->private; + CFBContext *cfb = s->priv_data; struct png_save_data { FILE *f; png_structp png_ptr; Index: qe.h =================================================================== RCS file: /sources/qemacs/qemacs/qe.h,v retrieving revision 1.99 diff -u -r1.99 qe.h --- qe.h 3 Dec 2013 17:35:06 -0000 1.99 +++ qe.h 15 Dec 2013 18:19:15 -0000 @@ -272,11 +272,11 @@ int ustristart(const unsigned int *str, const char *val, const unsigned int **ptr); static inline unsigned int *umemmove(unsigned int *dest, unsigned int *src, int count) { - return memmove(dest, src, count * sizeof(unsigned int)); + return (unsigned int *)memmove(dest, src, count * sizeof(unsigned int)); } static inline unsigned int *umemcpy(unsigned int *dest, unsigned int *src, int count) { - return memcpy(dest, src, count * sizeof(unsigned int)); + return (unsigned int *)memcpy(dest, src, count * sizeof(unsigned int)); } int umemcmp(const unsigned int *s1, const unsigned int *s2, int count); Index: tty.c =================================================================== RCS file: /sources/qemacs/qemacs/tty.c,v retrieving revision 1.50 diff -u -r1.50 tty.c --- tty.c 23 Apr 2008 15:30:33 -0000 1.50 +++ tty.c 15 Dec 2013 18:19:16 -0000 @@ -118,7 +118,7 @@ tty_screen = s; ts = &tty_state; - s->private = ts; + s->priv_data = ts; s->media = CSS_MEDIA_TTY; /* Derive some settings from the TERM environment variable */ @@ -263,7 +263,7 @@ static void tty_term_exit(void) { QEditScreen *s = tty_screen; - TTYState *ts = s->private; + TTYState *ts = s->priv_data; tcsetattr(fileno(s->STDIN), TCSANOW, &ts->oldtty); } @@ -271,7 +271,7 @@ static void tty_resize(__unused__ int sig) { QEditScreen *s = tty_screen; - TTYState *ts = s->private; + TTYState *ts = s->priv_data; struct winsize ws; int i, count, size; TTYChar tc; @@ -318,7 +318,7 @@ static void tty_term_cursor_at(QEditScreen *s, int x1, int y1, __unused__ int w, __unused__ int h) { - TTYState *ts = s->private; + TTYState *ts = s->priv_data; ts->cursor_x = x1; ts->cursor_y = y1; } @@ -380,7 +380,7 @@ { QEditScreen *s = opaque; QEmacsState *qs = &qe_state; - TTYState *ts = s->private; + TTYState *ts = s->priv_data; int ch; QEEvent ev1, *ev = &ev1; @@ -425,6 +425,7 @@ ts->input_param = 0; } else if (ch == 'O') { ts->input_state = IS_ESC2; + ts->input_param = 0; } else { ch = KEY_META(ch); ts->input_state = IS_NORM; @@ -826,7 +827,7 @@ static void tty_term_fill_rectangle(QEditScreen *s, int x1, int y1, int w, int h, QEColor color) { - TTYState *ts = s->private; + TTYState *ts = s->priv_data; int x2 = x1 + w; int y2 = y1 + h; int x, y; @@ -869,7 +870,7 @@ font->ascent = 0; font->descent = 1; - font->private = NULL; + font->priv_data = NULL; return font; } @@ -958,7 +959,7 @@ int x, int y, const unsigned int *str, int len, QEColor color) { - TTYState *ts = s->private; + TTYState *ts = s->priv_data; TTYChar *ptr; int fgcolor, w, n; unsigned int cc; @@ -1021,7 +1022,7 @@ static void tty_term_flush(QEditScreen *s) { - TTYState *ts = s->private; + TTYState *ts = s->priv_data; TTYChar *ptr, *ptr1, *ptr2, *ptr3, *ptr4, cc, blankcc; int y, shadow, ch, bgcolor, fgcolor, shifted; Index: win32.c =================================================================== RCS file: /sources/qemacs/qemacs/win32.c,v retrieving revision 1.15 diff -u -r1.15 win32.c --- win32.c 23 Apr 2008 15:29:35 -0000 1.15 +++ win32.c 15 Dec 2013 18:19:16 -0000 @@ -139,7 +139,7 @@ if (!_hPrev) init_application(); - s->private = NULL; + s->priv_data = NULL; s->media = CSS_MEDIA_SCREEN; win_ctx.font = CreateFont(-12, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, @@ -452,7 +452,7 @@ GetTextMetrics(win_ctx.hdc, &tm); font->ascent = tm.tmAscent; font->descent = tm.tmDescent; - font->private = NULL; + font->priv_data = NULL; return font; } Index: x11.c =================================================================== RCS file: /sources/qemacs/qemacs/x11.c,v retrieving revision 1.28 diff -u -r1.28 x11.c --- x11.c 15 Apr 2008 23:24:04 -0000 1.28 +++ x11.c 15 Dec 2013 18:19:16 -0000 @@ -194,7 +194,7 @@ QEStyleDef default_style; XGCValues gc_val; - s->private = NULL; + s->priv_data = NULL; s->media = CSS_MEDIA_SCREEN; if (!display_str) @@ -564,13 +564,13 @@ } font->ascent = renderFont->ascent; font->descent = renderFont->descent; - font->private = renderFont; + font->priv_data = renderFont; return font; } static void term_close_font(QEditScreen *s, QEFont *font) { - XftFont *renderFont = font->private; + XftFont *renderFont = font->priv_data; XftFontClose(display, renderFont); /* Clear structure to force crash if font is still used after @@ -582,7 +582,7 @@ static int term_glyph_width(QEditScreen *s, QEFont *font, unsigned int cc) { - XftFont *renderFont = font->private; + XftFont *renderFont = font->priv_data; XGlyphInfo gi; XftTextExtents32(display, renderFont, &cc, 1, &gi); @@ -593,7 +593,7 @@ int x, int y, const unsigned int *str, int len, QEColor color) { - XftFont *renderFont = font->private; + XftFont *renderFont = font->priv_data; XftColor col; int r, g, b, a; @@ -764,7 +764,7 @@ font->ascent = xfont->ascent; font->descent = xfont->descent; - font->private = xfont; + font->priv_data = xfont; return font; fail: XFreeFontNames(list); @@ -774,7 +774,7 @@ static void term_close_font(__unused__ QEditScreen *s, QEFont *font) { - XFontStruct *xfont = font->private; + XFontStruct *xfont = font->priv_data; XFreeFont(display, xfont); /* Clear structure to force crash if font is still used after @@ -788,7 +788,7 @@ associated. */ static XCharStruct *get_char_struct(QEFont *font, int cc) { - XFontStruct *xfont = font->private; + XFontStruct *xfont = font->priv_data; int b1, b2; XCharStruct *cs; @@ -856,7 +856,7 @@ /* really no glyph : use default char in current font */ /* Should have half-width and full-width default char patterns */ - xfont = font->private; + xfont = font->priv_data; cs = get_char_struct(font, xfont->default_char); *out_font = lock_font(s, font); return cs; @@ -928,13 +928,13 @@ cs = handle_fallback(s, &font1, font, cc); if (!cs) { /* still no char: use default glyph */ - xfont = font->private; + xfont = font->priv_data; cc = xfont->default_char; } } /* flush previous chars if font change needed */ if (font1 != last_font && q > x11_str) { - xfont = last_font->private; + xfont = last_font->priv_data; l = q - x11_str; XSetFont(display, gc, xfont->fid); XDrawString16(display, dbuffer, gc, x_start, y, x11_str, l); @@ -950,7 +950,7 @@ } if (q > x11_str) { /* flush remaining chars (more common case) */ - xfont = last_font->private; + xfont = last_font->priv_data; l = q - x11_str; XSetFont(display, gc, xfont->fid); XDrawString16(display, dbuffer, gc, x_start, y, x11_str, l); --- /dev/null 2013-12-15 19:57:20.442676000 +0100 +++ haiku.cpp 2013-03-14 20:51:17.995622912 +0100 @@ -0,0 +1,883 @@ +/* + * Haiku driver for QEmacs + * Copyright (c) 2013 François 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; + 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", ×tamp_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; +} + +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); --- /dev/null 2013-12-15 19:57:20.442676000 +0100 +++ contrib/haiku-pe2qe.sh 2013-03-14 19:17:29.552599552 +0100 @@ -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 "${fgmap[@]}"; do + if [ "$1" = "${item%:*}" ]; then + echo "${item#*:}" + return + fi + done +} + +map_pe_bg () { + for item in "${bgmap[@]}"; 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"
_______________________________________________ Qemacs-devel mailing list Qemacs-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/qemacs-devel