diff --git a/README.md b/README.md index 35d3f63bb..9343baa21 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ Build instructions are in the README.md file for each platform: - [DOS] - [OS/2] +- [Plan9] - [SDL 1.x] - [SDL 2.x] - [Windows] @@ -59,6 +60,7 @@ William McBrine [docs]: docs/README.md [DOS]: dos/README.md [OS/2]: os2/README.md +[Plan9]: plan9/README.md [SDL 1.x]: sdl1/README.md [SDL 2.x]: sdl2/README.md [Windows]: wincon/README.md diff --git a/plan9/README.md b/plan9/README.md new file mode 100644 index 000000000..49648ce9e --- /dev/null +++ b/plan9/README.md @@ -0,0 +1,57 @@ +PDCurses for Plan9 +================== + +This directory contains PDCurses source code files specific to Plan9. + + +Building +-------- + +- cd to the plan9 sub directory + +- Build it: + + mk + mk install + +- Optionally, you can cross compile by setting the variable $objtype, + for example: + + objtype=amd64 mk + +Distribution Status +------------------- + +Copyright (c) 2007 Federico G. Benavento + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Federico G. Benavento +January 2008 +benavento@gmail.com + + +Acknowledgements +---------------- + +Federico G. Benavento made the original port to PDCurses 3.0 + +Jens Staal updated it + diff --git a/plan9/header.patch b/plan9/header.patch new file mode 100644 index 000000000..027e074fd --- /dev/null +++ b/plan9/header.patch @@ -0,0 +1,11 @@ +--- curses.h 2020-06-29 15:03:16.675718137 +0200 ++++ curses.h.ape 2020-06-29 19:09:31.624238344 +0200 +@@ -5,6 +5,8 @@ + #ifndef __PDCURSES__ + #define __PDCURSES__ 1 + ++#pragma lib "/$M/lib/ape/libcurses.a" ++ + /*man-start************************************************************** + + Define before inclusion (only those needed): diff --git a/plan9/mkfile b/plan9/mkfile new file mode 100644 index 000000000..41f2af413 --- /dev/null +++ b/plan9/mkfile @@ -0,0 +1,101 @@ + +#include +#include +#include "pdcplan9.h" + + +static char *clip = NULL; + +int PDC_getclipboard(char **sp, long *np) +{ + long n; + + PDC_LOG(("PDC_getclipboard() - called\n")); + if (!clip) + return PDC_CLIP_EMPTY; + + n = strlen(clip); + if ((*sp = malloc(n + 1)) == NULL) + return PDC_CLIP_MEMORY_ERROR; + + memmove(*sp, clip, n); + *np = n; + + return PDC_CLIP_SUCCESS; +} + + +int PDC_setclipboard(const char *s, long n) +{ + PDC_LOG(("PDC_setclipboard() - called\n")); + if (clip) + { + free(clip); + clip = NULL; + } + if (s) + { + if ((clip = malloc(n + 1)) == NULL) + return PDC_CLIP_MEMORY_ERROR; + memmove(clip, s, n); + clip[n] = 0; + } + + return PDC_CLIP_SUCCESS; +} + + +int PDC_freeclipboard(char *s) +{ + PDC_LOG(("PDC_freeclipboard() - called\n")); + free(s); + + return PDC_CLIP_SUCCESS; +} + + +int PDC_clearclipboard(void) +{ + PDC_LOG(("PDC_clearclipboard() - called\n")); + if (clip) + { + free(clip); + clip = NULL; + } + + return PDC_CLIP_SUCCESS; +} diff --git a/plan9/pdcdisp.c b/plan9/pdcdisp.c new file mode 100644 index 000000000..f9f154f79 --- /dev/null +++ b/plan9/pdcdisp.c @@ -0,0 +1,65 @@ +#include +#include "pdcplan9.h" + +#ifdef CHTYPE_LONG +# define A(x) ((chtype)x | A_ALTCHARSET) +chtype acs_map[128] = { + A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), + A(19), A(20), A(21), A(22), A(23), A(24), A(25), A(26), A(27), + A(28), A(29), A(30), A(31), ' ', '!', '"', '#', '$', '%', '&', + '\'', '(', ')', '*', + + 0x2192, 0x2190, 0x2191, 0x2193, + + '/', + + 0x2588, + + '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', + '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + + 0x25c6, 0x2592, + + 'b', 'c', 'd', 'e', + + 0x00ba, 0x00b1, 0x0023, 0x0023, 0x2518, 0x2510, 0x250c, 0x2514, + 0x253c, 'o', + 'p', 0x2500, 'r', 's', 0x2524, 0x251c, 0x2534, 0x252c, 0x2502, + 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x2022, + + A(127) +}; + +# undef A +#endif + + +void PDC_gotoyx(int y, int x) +{ + chtype *ch; + + PDC_LOG(("PDC_gotoyx() - called: y %d x %d\n", y, x)); + p9setcur(SP->cursrow, SP->curscol, y, x, SP->visibility); +} + + +void PDC_transform_line(int y, int x, int len, const chtype * srcp) +{ + int i; + + PDC_LOG(("PDC_transform_line() - called: line %d\n", lineno)); + for (i = 0; i < len; i++) + { + p9putc(y, x + i, srcp[i]); + } +} + +void PDC_doupdate(void) +{ + p9napms(1); +} + + diff --git a/plan9/pdcgetsc.c b/plan9/pdcgetsc.c new file mode 100644 index 000000000..e5d272fe1 --- /dev/null +++ b/plan9/pdcgetsc.c @@ -0,0 +1,28 @@ +#include +#include "pdcplan9.h" + +int PDC_get_columns(void) +{ + int i; + + i = p9getcols(); + PDC_LOG(("PDC_get_columns() returns: %d\n", i)); + return i; +} + + +int PDC_get_cursor_mode(void) +{ + PDC_LOG(("PDC_get_cursor_mode() - called\n")); + return 0; +} + + +int PDC_get_rows(void) +{ + int i; + + i = p9getrows(); + PDC_LOG(("PDC_get_rows() - returns: %d\n", i)); + return i; +} diff --git a/plan9/pdckbd.c b/plan9/pdckbd.c new file mode 100644 index 000000000..f4f38ceaa --- /dev/null +++ b/plan9/pdckbd.c @@ -0,0 +1,53 @@ +#include +#include "pdcplan9.h" + + +unsigned long pdc_key_modifiers = 0L; + + +bool PDC_check_key(void) +{ + PDC_LOG(("PDC_check_key() - called\n")); + return p9ecan(); +} + + +int PDC_get_key(void) +{ + PDC_LOG(("PDC_check_key() - called\n")); + return p9eget(); +} + + +void PDC_flushinp(void) +{ + PDC_LOG(("PDC_flushinp() - called\n")); +} + + +int PDC_modifiers_set(void) +{ + PDC_LOG(("PDC_modifiers_set() - called\n")); + return OK; +} + + +int PDC_mouse_set(void) +{ + PDC_LOG(("PDC_mouse_set() - called\n")); + return OK; +} + + +void PDC_set_keyboard_binary(bool) +{ + PDC_LOG(("PDC_mouse_set() - called\n")); +} + +bool PDC_has_mouse(void) +{ + return TRUE; +} + + + diff --git a/plan9/pdcplan9.c b/plan9/pdcplan9.c new file mode 100644 index 000000000..129084211 --- /dev/null +++ b/plan9/pdcplan9.c @@ -0,0 +1,348 @@ +#define _LOCK_EXTENSION +#define _QLOCK_EXTENSION +#define _PLAN9_SOURCE +#define _RESEARCH_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define border curborder +#include +#undef border +#include +#include +#include +#include "pdcplan9.h" + +enum { + Ncolors = 18, + Eresized = 3, +}; + +uint rgbacolors[Ncolors] = { + 0x000000FF, /* black */ + 0x0000FFFF, /* blue */ + 0x00AA00FF, /* green */ + 0x00AAAAFF, /* cyan */ + 0xAA0000FF, /* red */ + 0xAA00AAFF, /* purple */ + 0xFF5500FF, /* brown */ + 0x7F7F7FFF, /* white */ + 0x555555FF, /* light black aka grey */ + 0x5555FFFF, /* light blue */ + 0x55FF55FF, /* light green */ + 0x55FFFFFF, /* light cyan */ + 0xFF5555FF, /* light red */ + 0xFF55FFFF, /* light purple */ + 0xFFFF55FF, /* light brown aka yellow */ + 0xFFFFFFFF, /* light grey aka white */ + 0x9EEEEFF, + 0x9EE9EFF, +}; + +static Image *colors[Ncolors]; + +static void fatal(char *s) +{ + fprint(2, "curses: %s: %r\n", s); + abort(); +} + + +void p9napms(int ms) +{ + _SLEEP(ms); +} + + +void p9setlabel(char *s) +{ + int fd; + + fd = open("/dev/label", 1); + if (fd >= 0) + { + fprint(fd, "%s", s); + close(fd); + } +} + + +void p9resize(int nl, int nc) +{ + int fd; + + fd = open("/dev/wctl", 1); + if (fd >= 0) + { + fprint(fd, "resize -dx %d -dy %d", + nc * stringwidth(font, "0") + 8, nl * font->height + 8); + close(fd); + } +} + + +int p9getrows(void) +{ + return Dy(screen->r) / font->height; +} + + +int p9getcols(void) +{ + return Dx(screen->r) / stringwidth(font, "0"); +} + + +#define ms SP->mouse_status /* I don't like this var name */ +static void setms(Mouse m) +{ + static uint clickmsec; + MOUSE_STATUS oldms; + int but, b, x, y; + + oldms = ms; + memset(&ms, 0, sizeof(ms)); + ms.x = (m.xy.x - screen->r.min.x) / stringwidth(font, "0"); + ms.y = (m.xy.y - screen->r.min.y) / font->height; + if (ms.x != oldms.x || ms.y != oldms.y) + ms.changes |= PDC_MOUSE_MOVED; + + /*scroll wheel */ + if (m.buttons & (8 | 16)) + { + if (m.buttons & 8) + ms.changes |= PDC_MOUSE_WHEEL_UP; + else + ms.changes |= PDC_MOUSE_WHEEL_DOWN; + SP->key_code = TRUE; + return; + } + but = 0; + if (m.buttons & 1) + but = 1; + else if (m.buttons & 2) + but = 2; + else if (m.buttons & 4) + but = 3; + + if (but == 0) + return; + + b = m.buttons; + if (m.msec - clickmsec < 500) + { + ms.button[but - 1] = BUTTON_DOUBLE_CLICKED; + x = m.xy.x; + y = m.xy.y; + /* stay here until something interesting happens */ + do + m = emouse(); + while (m.buttons == b && abs(m.xy.x - x) < 3 + && abs(m.xy.y - y) < 3); + } + if (m.buttons == b) + { + uint msec = m.msec; + do + m = emouse(); + while (m.buttons == b); + if (m.msec - msec < 250) + ms.button[but - 1] = BUTTON_CLICKED; + else + ms.button[but - 1] = BUTTON_PRESSED; + } + if (oldms.x == ms.x && oldms.y == ms.y) + { + if (m.msec - clickmsec < 500) + ms.button[but - 1] = BUTTON_DOUBLE_CLICKED; + else + clickmsec = m.msec; + } + /* choording should be here */ + while (m.buttons == b) + m = emouse(); + + ms.changes |= 1 << (but - 1); + SP->key_code = FALSE; +} +#undef ms + + +static int transk(Rune k) +{ + switch (k) + { + case Khome: + return KEY_HOME; + case Kup: + return KEY_UP; + case Kpgup: + return KEY_PPAGE; + case Kprint: + return KEY_PRINT; + case Kleft: + return KEY_LEFT; + case Kright: + return KEY_RIGHT; + case Kdown: + return KEY_DOWN; + case Kpgdown: + return KEY_NPAGE; + case Kins: + return KEY_IC; + case Kend: + return KEY_END; + default: + return k; + } +} + +static int resized; + +void eresized(int) +{ + if (getwindow(display, Refnone) < 0) + fatal("can't reattach to window"); + + draw(screen, screen->r, display->black, nil, ZP); + resized = TRUE; +} + + +int p9ecan(void) +{ + return ecanread(Ekeyboard | Emouse); +} + + +int p9eget(void) +{ + char c; + Event e; + int x = 0; + + if (resized) + { + resized = FALSE; + SP->resized = TRUE; + x = KEY_RESIZE; + } + switch (event(&e)) + { + case Emouse: + setms(e.mouse); + x = KEY_MOUSE; + case Ekeyboard: + if (e.kbdc == Kdel) + raise(SIGINT); + x = transk(e.kbdc); + }; + return x; +} + +void p9init(void) +{ + int i; + + if (initdraw(0, "/lib/font/bit/fixed/unicode.9x15.font", "curses") < 0) + fatal("can't open display"); + + draw(screen, screen->r, display->black, nil, ZP); + einit(Ekeyboard | Emouse); + for (i = 0; i < Ncolors; i++) + { + colors[i] = + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, + rgbacolors[i]); + if (colors[i] == nil) + fatal("can't allocate image"); + } +} + +static Point getcur(int y, int x) +{ + Point p; + + p.x = screen->r.min.x + stringwidth(font, "0") * x; + p.y = screen->r.min.y + font->height * y; + + return p; +} + + +void p9putc(int y, int x, chtype ch) +{ + chtype attr; + int c, t; + short fg, bg; + Point p0, p1; + Rune buf[1]; + + attr = ch & A_ATTRIBUTES; + if (pair_content(PAIR_NUMBER(attr), &fg, &bg) == ERR) + { + fg = COLOR_WHITE; + bg = COLOR_BLACK; + } + + fg |= attr & A_BOLD ? 8 : 0; + bg |= attr & A_BLINK ? 8 : 0; + if (attr & A_REVERSE) + { + t = fg; + fg = bg; + bg = t; + } + if (attr & A_ALTCHARSET && !(ch & 0xff80)) + ch = acs_map[ch & 0x7f]; + + c = ch & A_CHARTEXT; + + buf[0] = c; + p0 = getcur(y, x); + runestringnbg(screen, p0, colors[fg], ZP, font, buf, 1, colors[bg], ZP); + if (attr & A_UNDERLINE) + { + p1 = p0; + p1.x += runestringnwidth(font, buf, 1); + line(screen, p0, p1, Enddisc, Enddisc, 0, colors[fg], ZP); + } +} + + +void p9setcur(int oy, int ox, int y, int x, int vis) +{ + Image *c; + chtype *ch; + Point p; + + ch = curscr->_y[oy] + ox; + p9putc(oy, ox, *ch); + if (vis == 0) + return; + + if (vis == 1) + c = colors[Ncolors - 2]; + else + c = colors[Ncolors - 1]; + + p = getcur(y, x); + draw(screen, + Rect(p.x, p.y + font->height - 2, p.x + stringwidth(font, "0"), + p.y + font->height), c, nil, ZP); + + flushimage(display, 1); +} diff --git a/plan9/pdcplan9.h b/plan9/pdcplan9.h new file mode 100644 index 000000000..7791289d4 --- /dev/null +++ b/plan9/pdcplan9.h @@ -0,0 +1,10 @@ +void p9init(void); +int p9ecan(void); +int p9eget(void); +int p9getcols(void); +int p9getrows(void); +void p9napms(int); +void p9putc(int, int, chtype); +void p9resize(int, int); +void p9setlabel(char *); +void p9setcur(int, int, int, int, int); diff --git a/plan9/pdcscrn.c b/plan9/pdcscrn.c new file mode 100644 index 000000000..57ff69286 --- /dev/null +++ b/plan9/pdcscrn.c @@ -0,0 +1,114 @@ +#include +#include +#include "pdcplan9.h" + +bool PDC_can_change_color(void) +{ + PDC_LOG(("PDC_can_change_color() - called.\n")); + + return FALSE; +} + + +int PDC_color_content(short color, short *red, short *green, short *blue) +{ + PDC_LOG(("PDC_color_content() - called.\n")); + + return ERR; +} + + +int PDC_init_color(short color, short red, short green, short blue) +{ + PDC_LOG(("PDC_init_color() - called. Lines: %d Cols: %d\n", color, + red, green, blue)); + + return OK; +} + + +int PDC_scr_open(void) +{ + PDC_LOG(("PDC_scr_open() - called\n")); + + SP = calloc(1, sizeof(SCREEN)); + if (!SP) + return ERR; + + p9init(); + SP->cols = PDC_get_columns(); + SP->lines = PDC_get_rows(); + SP->cursrow = SP->curscol = 0; + SP->orig_attr = FALSE; + SP->orig_cursor = 0; + + return OK; +} + + +void PDC_scr_close(void) +{ + PDC_LOG(("PDC_scr_close() - called\n")); +} + + +void PDC_reset_shell_mode(void) +{ + PDC_LOG(("PDC_reset_shell_mode() - called\n")); +} + + +int PDC_resize_screen(int nlines, int ncols) +{ + PDC_LOG(("PDC_resize_screen() - called. Lines: %d Cols: %d\n", + nlines, ncols)); + + if (nlines == 0 && ncols == 0) + return OK; + + p9resize(nlines, ncols); + SP->resized = FALSE; + SP->cursrow = SP->curscol = 0; + + return OK; +} + + +void PDC_reset_prog_mode(void) +{ + PDC_LOG(("PDC_reset_prog_mode() - called.\n")); +} + + +void PDC_restore_screen_mode(int) +{ + PDC_LOG(("PDC_restore_screen_mode() - called.\n")); +} + + +void PDC_save_screen_mode(int) +{ + PDC_LOG(("PDC_save_screen_mode() - called.\n")); +} + + +void PDC_scr_free(void) +{ + free(SP); +} + +static struct {short f, b;} atrtab[PDC_COLOR_PAIRS]; + +void PDC_init_pair(short pair, short fg, short bg) +{ + atrtab[pair].f = fg; + atrtab[pair].b = bg; +} + +int PDC_pair_content(short pair, short *fg, short *bg) +{ + *fg = atrtab[pair].f; + *bg = atrtab[pair].b; + + return OK; +} diff --git a/plan9/pdcsetsc.c b/plan9/pdcsetsc.c new file mode 100644 index 000000000..3a0747724 --- /dev/null +++ b/plan9/pdcsetsc.c @@ -0,0 +1,51 @@ +#include +#include "pdcplan9.h" + + +int PDC_curs_set(int vis) +{ + int rvis; + chtype *ch; + + PDC_LOG(("PDC_curs_set() - called: visibility=%d\n", vis)); + rvis = SP->visibility; + p9setcur(SP->cursrow, SP->curscol, SP->cursrow, SP->curscol, vis); + SP->visibility = vis; + + return rvis; +} + + +void PDC_set_title(const char *title) +{ + PDC_LOG(("PDC_set_title() - called:<%s>\n", title)); + p9setlabel(title); +} + + +int PDC_set_blink(bool blinkon) +{ + PDC_LOG(("PDC_set_title() - called:<%d>\n", blinkon)); + if (SP->color_started) + COLORS = 16; + + return blinkon ? ERR : OK; +} + +int PDC_set_bold(bool boldon) +{ + if (!SP) + return ERR; + +#ifdef PDC_WIDE + if (boldon) + SP->termattrs |= A_BOLD; + else + SP->termattrs &= ~A_BOLD; + + return OK; +#else + return boldon ? ERR : OK; +#endif +} + diff --git a/plan9/pdcutil.c b/plan9/pdcutil.c new file mode 100644 index 000000000..7a8641944 --- /dev/null +++ b/plan9/pdcutil.c @@ -0,0 +1,24 @@ +#include +#include +#include "pdcplan9.h" + + +void PDC_beep(void) +{ + PDC_LOG(("PDC_beep() - called\n")); +} + + +void PDC_napms(int ms) +{ + PDC_LOG(("PDC_napms() - called\n")); + p9napms(ms); +} + + +const char *PDC_sysname(void) +{ + PDC_LOG(("PDC_sysname() - called\n")); + + return "PLAN9"; +}