diff --git a/neercs/neercs.cpp b/neercs/neercs.cpp index d8aae1f..e12f283 100644 --- a/neercs/neercs.cpp +++ b/neercs/neercs.cpp @@ -1,64 +1 @@ -// -// Neercs -// -// Copyright: (c) 2012-2013 Sam Hocevar -// - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include - -#include "core.h" - -using namespace std; -using namespace lol; - -#include "neercs.h" -#include "video/render.h" - -extern "C" -{ -#include "old/neercs.h" -} - -Neercs::Neercs(int argc, char **argv) - : m_term(new Term(ivec2(45, 16))), - m_render(new Render(m_term->GetCaca())), - m_ready(false) -{ - Ticker::Ref(m_term); - Ticker::Ref(m_render); -} - -void Neercs::TickGame(float seconds) -{ - WorldEntity::TickGame(seconds); -} - -void Neercs::TickDraw(float seconds) -{ - WorldEntity::TickDraw(seconds); -} - -Neercs::~Neercs() -{ - Ticker::Unref(m_term); - Ticker::Unref(m_render); -} - -int main(int argc, char **argv) -{ - System::Init(argc, argv); - - Application app("Neercs", ivec2(800, 600), 60.0f); - - new Neercs(argc, argv); - app.ShowPointer(false); - - app.Run(); - - return EXIT_SUCCESS; -} +// // Neercs // // Copyright: (c) 2012-2013 Sam Hocevar // #if defined HAVE_CONFIG_H # include "config.h" #endif #include #include #include "core.h" using namespace std; using namespace lol; #include "neercs.h" #include "video/render.h" extern "C" { #include "old/neercs.h" } Neercs::Neercs(int argc, char **argv) : m_term(new Term(ivec2(45, 16))), m_render(new Render(m_term->GetCaca())), m_ready(false) { Ticker::Ref(m_term); Ticker::Ref(m_render); } void Neercs::TickGame(float seconds) { WorldEntity::TickGame(seconds); } void Neercs::TickDraw(float seconds) { WorldEntity::TickDraw(seconds); } Neercs::~Neercs() { Ticker::Unref(m_term); Ticker::Unref(m_render); } int main(int argc, char **argv) { System::Init(argc, argv); Application app("Neercs", ivec2(800, 600), 60.0f); new Neercs(argc, argv); app.ShowPointer(false); app.Run(); return EXIT_SUCCESS; } \ No newline at end of file diff --git a/neercs/neercs.h b/neercs/neercs.h index 41c4289..1c479d6 100644 --- a/neercs/neercs.h +++ b/neercs/neercs.h @@ -1,40 +1 @@ -// -// Neercs -// -// Copyright: (c) 2012 Sam Hocevar -// - -#if !defined __NEERCS_H__ -#define __NEERCS_H__ - -#include - -#include "video/render.h" -#include "term/term.h" - -extern "C" -{ -#include "old/neercs.h" -} - -class Neercs : public WorldEntity -{ -public: - Neercs(int argc, char **argv); - virtual ~Neercs(); - - char const *GetName() { return ""; } - -protected: - virtual void TickGame(float seconds); - virtual void TickDraw(float seconds); - -private: - Term *m_term; - Render *m_render; - - bool m_ready; -}; - -#endif // __NEERCS_H__ - +// // Neercs // // Copyright: (c) 2012 Sam Hocevar // #if !defined __NEERCS_H__ #define __NEERCS_H__ #include #include "video/render.h" #include "term/term.h" extern "C" { #include "old/neercs.h" } class Neercs : public WorldEntity { public: Neercs(int argc, char **argv); virtual ~Neercs(); char const *GetName() { return ""; } protected: virtual void TickGame(float seconds); virtual void TickDraw(float seconds); private: Term *m_term; Render *m_render; bool m_ready; }; #endif // __NEERCS_H__ \ No newline at end of file diff --git a/neercs/old/actions.c b/neercs/old/actions.c index 55877b9..55e65c9 100644 --- a/neercs/old/actions.c +++ b/neercs/old/actions.c @@ -1,66 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include -#include "neercs.h" - -void dump_to_file(struct screen_list *screen_list) -{ - char filename[14] = "hardcopy.0"; - int n = 0; - struct stat bufstat; - void * export; - size_t len, wrote; - FILE * out; - - /* FIXME maybe use glob and get next one directly */ - while (n<9999 && !stat(filename, &bufstat)) - { - n++; - sprintf(&filename[9], "%d", n); - } - if (n>=9999) - { - debug("Too many hardcopy files in current directory\n"); - return; - } - - export = caca_export_canvas_to_memory(screen_list->cv, "ansi", &len); - if (!export) - { - debug("Failed to export to ansi\n"); - return; - } - - out = fopen(filename, "w"); - if (!out) - { - debug("Failed to open output file %s: %s\n", filename, strerror(errno)); - return; - } - wrote = fwrite(export, len, 1, out); - if (!wrote) - { - debug("Failed to write to output file: %s\n", strerror(errno)); - return; - } - free(export); -} +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include "neercs.h" void dump_to_file(struct screen_list *screen_list) { char filename[14] = "hardcopy.0"; int n = 0; struct stat bufstat; void * export; size_t len, wrote; FILE * out; /* FIXME maybe use glob and get next one directly */ while (n<9999 && !stat(filename, &bufstat)) { n++; sprintf(&filename[9], "%d", n); } if (n>=9999) { debug("Too many hardcopy files in current directory\n"); return; } export = caca_export_canvas_to_memory(screen_list->cv, "ansi", &len); if (!export) { debug("Failed to export to ansi\n"); return; } out = fopen(filename, "w"); if (!out) { debug("Failed to open output file %s: %s\n", filename, strerror(errno)); return; } wrote = fwrite(export, len, 1, out); if (!wrote) { debug("Failed to write to output file: %s\n", strerror(errno)); return; } free(export); } \ No newline at end of file diff --git a/neercs/old/ansi.c b/neercs/old/ansi.c index 1f53ad6..4550760 100644 --- a/neercs/old/ansi.c +++ b/neercs/old/ansi.c @@ -1,1156 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if defined _MSC_VER -# define inline __inline -#endif - -#include -#include -#include "neercs.h" - - -/* DEC ACS with common extensions */ -static uint32_t dec_acs(uint32_t uc) -{ - switch (uc) - { - case '+': - return 0x2192; /* RIGHTWARDS ARROW */ - case ',': - return 0x2190; /* LEFTWARDS ARROW */ - case '-': - return 0x2191; /* UPWARDS ARROW */ - case '.': - return 0x2193; /* DOWNWARDS ARROW */ - case '0': - return 0x25AE; /* BLACK VERTICAL RECTANGLE */ - case '_': - return 0x25AE; /* BLACK VERTICAL RECTANGLE */ - case '`': - return 0x25C6; /* BLACK DIAMOND */ - case 'a': - return 0x2592; /* MEDIUM SHADE */ - case 'b': - return 0x2409; /* SYMBOL FOR HORIZONTAL TABULATION */ - case 'c': - return 0x240C; /* SYMBOL FOR FORM FEED */ - case 'd': - return 0x240D; /* SYMBOL FOR CARRIAGE RETURN */ - case 'e': - return 0x240A; /* SYMBOL FOR LINE FEED */ - case 'f': - return 0x00B0; /* DEGREE SIGN */ - case 'g': - return 0x00B1; /* PLUS-MINUS SIGN */ - case 'h': - return 0x2424; /* SYMBOL FOR NEWLINE */ - case 'i': - return 0x240B; /* SYMBOL FOR VERTICAL TABULATION */ - case 'j': - return 0x2518; /* BOX DRAWINGS LIGHT UP AND LEFT */ - case 'k': - return 0x2510; /* BOX DRAWINGS LIGHT DOWN AND LEFT */ - case 'l': - return 0x250C; /* BOX DRAWINGS LIGHT DOWN AND RIGHT */ - case 'm': - return 0x2514; /* BOX DRAWINGS LIGHT UP AND RIGHT */ - case 'n': - return 0x253C; /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ - case 'o': - return 0x23BA; /* HORIZONTAL SCAN LINE-1 */ - case 'p': - return 0x23BB; /* HORIZONTAL SCAN LINE-3 */ - case 'q': - return 0x2500; /* BOX DRAWINGS LIGHT HORIZONTAL */ - case 'r': - return 0x23BC; /* HORIZONTAL SCAN LINE-7 */ - case 's': - return 0x23BD; /* HORIZONTAL SCAN LINE-9 */ - case 't': - return 0x251C; /* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ - case 'u': - return 0x2524; /* BOX DRAWINGS LIGHT VERTICAL AND LEFT */ - case 'v': - return 0x2534; /* BOX DRAWINGS LIGHT UP AND HORIZONTAL */ - case 'w': - return 0x252C; /* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ - case 'x': - return 0x2502; /* BOX DRAWINGS LIGHT VERTICAL */ - case 'y': - return 0x2264; /* LESS-THAN OR EQUAL TO */ - case 'z': - return 0x2265; /* GREATER-THAN OR EQUAL TO */ - case '{': - return 0x03C0; /* GREEK SMALL LETTER PI */ - case '|': - return 0x2260; /* NOT EQUAL TO */ - case '}': - return 0x00A3; /* POUND SIGN */ - case '~': - return 0x00B7; /* MIDDLE DOT */ - default: - return uc; - } -}; - -static void reset_conv_state(struct screen *); - -#define LITERAL2CHAR(i0,i1) (((i0) << 8) | (i1)) - -#define LITERAL3CHAR(i0,i1,i2) LITERAL2CHAR(LITERAL2CHAR(i0, i1), i2) - -static void ansi_parse_grcm(struct screen *, - unsigned int, unsigned int const *); - -inline int handle_single_char(unsigned char c, int *x, int *y, - struct screen_list *screen_list, - struct screen *sc); -static inline int handle_duplet(unsigned char const *buffer, struct screen *sc, - unsigned int *skip, int top, int bottom, int width, - int height); - - -inline int handle_single_char(unsigned char c, int *x, int *y, - struct screen_list *screen_list, - struct screen *sc) -{ - if (c == '\r') - { - *x = 0; - } - - else if (c == '\n') - { - *x = 0; - *y = *y + 1; - } - else if (c == '\a') - { - if (!sc->bell) - screen_list->in_bell = 10; - sc->bell = 1; - } - - else if (c == '\t') - { - *x = (*x + 7) & ~7; - } - - else if (c == '\x08') - { - if (*x > 0) - *x = *x - 1; - } - else if (c == '\x0b') - { - /* Vertical tab */ - /* Not sure about the real meaning of it, just y++ for now */ - if (*y < caca_get_canvas_height(sc->cv)) - *y = *y + 1; - } - else if (c == '\x0e') - { - /* Shift Out (Ctrl-N) -> Switch to Alternate Character Set: invokes - the G1 character set. */ - sc->conv_state.glr[0] = 1; - } - - else if (c == '\x0f') - { - /* Shift In (Ctrl-O) -> Switch to Standard Character Set: invokes the - G0 character set. */ - sc->conv_state.glr[0] = 0; - } - else - { - return 1; - } - return 0; -} - -static inline int handle_duplet(unsigned char const *buffer, struct screen *sc, - unsigned int *skip, int top, int bottom, int width, - int height) -{ - int i = 0, j, k; - unsigned int dummy = 0; - - /* Single Shift Select of G2 Character Set (SS2: 0x8e): affects next - character only */ - if (buffer[i] == '\033' && buffer[i + 1] == 'N') - { - sc->conv_state.ss = 2; - *skip += 1; - } - /* Reverse Index (RI) go up one line, reverse scroll if necessary */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'M') - { - /* FIXME : not sure about the meaning of 'go up one line' and 'if - necessary' words. Implemented as a scroller only. */ - for (j = bottom - 1; j > top; j--) - { - for (k = 0; k < width; k++) - { - caca_put_char(sc->cv, k, j, caca_get_char(sc->cv, k, j - 1)); - caca_put_attr(sc->cv, k, j, caca_get_attr(sc->cv, k, j - 1)); - } - } - caca_draw_line(sc->cv, 0, top - 1, width - 1, top - 1, ' '); - *skip += 1; - } - - /* Single Shift Select of G3 Character Set (SS2: 0x8f): affects next - character only */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'O') - { - sc->conv_state.ss = 3; - *skip += 1; - } - - /* LOCKING-SHIFT TWO (LS2), ISO 2022, ECMA-48 (1986), ISO 6429 : 1988 */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'n') - { - sc->conv_state.glr[0] = 2; - *skip += 1; - } - - /* LOCKING-SHIFT THREE (LS3) ISO 2022, ECMA-48 (1986), ISO 6429 : 1988 */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'o') - { - sc->conv_state.glr[0] = 3; - *skip += 1; - } - - /* RESET TO INITIAL STATE (RIS), ECMA-48 (1986), ISO 6429 : 1988 */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'c') - { - sc->dfg = CACA_DEFAULT; - sc->dbg = CACA_DEFAULT; - - caca_set_color_ansi(sc->cv, sc->dfg, sc->dbg); - sc->clearattr = caca_get_attr(sc->cv, -1, -1); - ansi_parse_grcm(sc, 1, &dummy); - - reset_conv_state(sc); - *skip += 1; - } - - /* Coding Method Delimiter (CMD), ECMA-48 (1991), ISO/IEC 6429:1992 (ISO - IR 189) */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'd') - { - reset_conv_state(sc); - *skip += 1; - } - else - { - return 1; - } - - return 0; -} - - -long int import_term(struct screen_list *screen_list, struct screen *sc, - void const *data, unsigned int size) -{ - unsigned char const *buffer = (unsigned char const *)data; - unsigned int i, j, k, skip, dummy = 0; - unsigned int width, height, top, bottom; - uint32_t savedattr; - int x = 0, y = 0, save_x = 0, save_y = 0; - char b[100]; - - debug("ansi : import_term\n"); - - width = caca_get_canvas_width(sc->cv); - height = caca_get_canvas_height(sc->cv); - x = caca_get_cursor_x(sc->cv); - y = caca_get_cursor_y(sc->cv); - top = 1; - bottom = height; - - if (!sc->init) - { - sc->dfg = CACA_LIGHTGRAY; - sc->dbg = CACA_BLACK; - - caca_set_color_ansi(sc->cv, sc->dfg, sc->dbg); - sc->clearattr = caca_get_attr(sc->cv, -1, -1); - - ansi_parse_grcm(sc, 1, &dummy); - - reset_conv_state(sc); - - sc->init = 1; - } - - for (i = 0; i < size; i += skip) - { - uint32_t ch = 0; - int wch = 0; - - skip = 1; - - /* Control codes (ASCII < \x20) */ - if (!handle_single_char(buffer[i], &x, &y, screen_list, sc)) - { - } - - /* If there are not enough characters to parse the escape sequence, - wait until the next try. We require 3. */ - - else if (buffer[i] == '\033' && i + 2 >= size) - break; - - - else if (!handle_duplet(&buffer[i], sc, &skip, - top, bottom, width, height)) - { - - } - - - /* GZDM4, G0-Designators, multi, 94^n chars [grandfathered short form - from ISO 2022:1986] */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && (buffer[i + 2] >= '@') && (buffer[i + 2] <= 'C')) - { - sc->conv_state.gn[0] = LITERAL2CHAR('$', buffer[i + 2]); - skip += 2; - } - - /* GnDMx Gn-Designators, 9x^n chars; need one more char to distinguish - these */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && (i + 3 >= size)) - break; - - /* GZD4 G0-Designator, 94 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '(') - { - sc->conv_state.gn[0] = buffer[i + 2]; - skip += 2; - } - - /* G1D4 G1-Designator, 94 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == ')') - { - sc->conv_state.gn[1] = buffer[i + 2]; - skip += 2; - } - - /* G2D4 G2-Designator, 94 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '*') - { - sc->conv_state.gn[2] = buffer[i + 2]; - skip += 2; - } - - /* G3D4 G3-Designator, 94 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '+') - { - sc->conv_state.gn[3] = buffer[i + 2]; - skip += 2; - } - - /* G2D6 G2-Designator, 96 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '.') - { - sc->conv_state.gn[2] = LITERAL2CHAR('.', buffer[i + 2]); - skip += 2; - } - - /* G3D6 G3-Designator, 96 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '/') - { - sc->conv_state.gn[3] = LITERAL2CHAR('.', buffer[i + 2]); - skip += 2; - } - - /* GZDM4 G0-Designator, 94^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '(') - { - sc->conv_state.gn[0] = LITERAL2CHAR('$', buffer[i + 3]); - skip += 3; - } - - /* G1DM4 G1-Designator, 94^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == ')') - { - sc->conv_state.gn[1] = LITERAL2CHAR('$', buffer[i + 3]); - skip += 3; - } - - /* G2DM4 G2-Designator, 94^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '*') - { - sc->conv_state.gn[2] = LITERAL2CHAR('$', buffer[i + 3]); - skip += 3; - } - - /* G3DM4 G3-Designator, 94^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '+') - { - sc->conv_state.gn[3] = LITERAL2CHAR('$', buffer[i + 3]); - skip += 3; - } - - /* G2DM6 G2-Designator, 96^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '.') - { - sc->conv_state.gn[2] = LITERAL3CHAR('$', '.', buffer[i + 3]); - skip += 3; - } - - /* G3DM6 G3-Designator, 96^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '/') - { - sc->conv_state.gn[3] = LITERAL3CHAR('$', '.', buffer[i + 3]); - skip += 3; - } - else if (buffer[i] == '\033' && buffer[i + 1] == '#') - { - debug("ansi private '#' sequence\n"); - - switch (buffer[i + 2]) - { - case '8': /* DECALN Fills the entire screen area with - uppercase Es for screen focus and - alignment. */ - for (j = 0; j < height; j++) - { - for (k = 0; k < width; k++) - { - caca_put_char(sc->cv, k, j, 'E'); - } - } - x = 0; - y = 0; - skip += 2; - break; - - default: - debug("Unknow private sequence 'ESC#%c'\n", buffer[i + 2]); - continue; - } - - } - /* Interpret escape commands, as per Standard ECMA-48 "Control - Functions for Coded Character Sets", 5.4. Control sequences. */ - else if (buffer[i] == '\033' && buffer[i + 1] == '[') - { - unsigned int argc = 0, argv[101]; - unsigned int param, inter, junk, final; - - if (buffer[i + 2] == '?') - { - debug("CSI? %c%c%c%c%c\n", - buffer[i + 3], buffer[i + 4], buffer[i + 5], - buffer[i + 6], buffer[i + 7]); - } - - /* Compute offsets to parameter bytes, intermediate bytes and to - the final byte. Only the final byte is mandatory, there can be - zero of the others. 0 param=2 inter final final+1 - +-----+------------------+---------------------+-----------------+ - | CSI | parameter bytes | intermediate bytes | final byte | | | - 0x30 - 0x3f | 0x20 - 0x2f | 0x40 - 0x7e | | ^[[ | 0123456789:;<=>? - | SPC !"#$%&'()*+,-./ | azAZ@[\]^_`{|}~ | - +-----+------------------+---------------------+-----------------+ */ - param = 2; - - /* vttest use to interleave control characters (\014 CR or \010 - BS) into CSI sequences, either directly after ESC[ or after - param. Can't find anything related to this in any documentation - nor XTerm sources, thought. */ - - for (junk = param; i + junk < size; junk++) - if (buffer[i + junk] < 0x20) - { - handle_single_char(buffer[i + junk], &x, &y, screen_list, - sc); - } - else - { - break; - } - - /* Intermediate offset */ - for (inter = junk; i + inter < size; inter++) - if (buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f) - { - break; - } - /* Interleaved character */ - for (junk = inter; i + junk < size; junk++) - if (buffer[i + junk] < 0x20) - { - handle_single_char(buffer[i + junk], &x, &y, screen_list, - sc); - } - else - { - break; - } - - /* Final Byte offset */ - for (final = junk; i + final < size; final++) - if (buffer[i + final] < 0x20 || buffer[i + final] > 0x2f) - { - break; - } - if (i + final >= size - || buffer[i + final] < 0x40 || buffer[i + final] > 0x7e) - { - debug("ansi Invalid Final Byte (%d %c)\n", buffer[i + final], - buffer[i + final]); - break; /* Invalid Final Byte */ - } - - skip += final; - - /* Sanity checks */ - if (param < inter && buffer[i + param] >= 0x3c) - { - /* Private sequence, only parse what we know */ - debug("ansi import: private sequence \"^[[%.*s\"", - final - param + 1, buffer + i + param); - /* FIXME better parsing */ - if (buffer[i + 2] == '?') - { - char arg[5], *end; - int a = 0; - int c, p, Pm; - for (p = 0; p < 4; p++) - { - if (buffer[i + 3 + p] >= '0' - && buffer[i + 3 + p] <= '9') - { - arg[a] = buffer[i + 3 + p]; - arg[a + 1] = 0; - a++; - debug("private a now '%s'\n", arg); - } - else - { - break; - } - } - Pm = strtol(arg, &end, 10); - - c = buffer[i + 3 + (end - arg)]; - - debug("ansi private mouse : command %c, arg %d", c, Pm); - if (c == 'h') /* DECSET DEC Private Mode Set */ - { - - switch (Pm) - { - /* FIXME Handle different modes */ - case 9: - debug("mouse : X10 mode\n"); - sc->report_mouse = MOUSE_X10; - break; - case 1000: /* Send Mouse X & Y on button press - and release. */ - debug("mouse : VT200 mode\n"); - sc->report_mouse = MOUSE_VT200; - break; - case 1001: /* Use Hilite Mouse Tracking. */ - debug("mouse : VT200_HIGHLIGHT mode\n"); - sc->report_mouse = MOUSE_VT200_HIGHLIGHT; - break; - case 1002: /* Use Cell Motion Mouse Tracking. */ - debug("mouse : BTN mode\n"); - sc->report_mouse = MOUSE_BTN_EVENT; - break; - case 1003: /* Use All Motion Mouse Tracking. */ - debug("mouse : ANY mode\n"); - sc->report_mouse = MOUSE_ANY_EVENT; - break; - default: - break; - } - } - else if (c == 'l') /* DECRST DEC Private Mode Reset */ - { - Pm = atoi(arg); - switch (Pm) - { - /* FIXME Handle different modes */ - case 9: - case 1000: /* Send Mouse X & Y on button press - and release. */ - case 1001: /* Use Hilite Mouse Tracking. */ - case 1002: /* Use Cell Motion Mouse Tracking. */ - case 1003: /* Use All Motion Mouse Tracking. */ - sc->report_mouse = MOUSE_NONE; - debug("ansi private mouse : NOT reporting mouse"); - break; - default: - break; - } - } - } - continue; /* Private sequence, skip it entirely */ - } - - if (final - param > 100) - continue; /* Suspiciously long sequence, skip it */ - - /* Parse parameter bytes as per ECMA-48 5.4.2: Parameter string - format */ - if (param < inter) - { - argv[0] = 0; - for (j = param; j < inter; j++) - { - if (buffer[i + j] == ';') - argv[++argc] = 0; - else if (buffer[i + j] >= '0' && buffer[i + j] <= '9') - argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0'); - } - argc++; - } - - /* Interpret final byte. The code representations are given in - ECMA-48 5.4: Control sequences, and the code definitions are - given in ECMA-48 8.3: Definition of control functions. */ - debug("ansi import: command '%c'", buffer[i + final]); - switch (buffer[i + final]) - { - case 'A': /* CUU (0x41) - Cursor Up */ - y -= argc ? argv[0] : 1; - if (y < 0) - y = 0; - break; - case 'B': /* CUD (0x42) - Cursor Down */ - y += argc ? argv[0] : 1; - break; - case 'C': /* CUF (0x43) - Cursor Right */ - x += argc ? argv[0] : 1; - break; - case 'D': /* CUB (0x44) - Cursor Left */ - x -= argc ? argv[0] : 1; - if (x < 0) - x = 0; - break; - case 'G': /* CHA (0x47) - Cursor Character Absolute */ - x = (argc && argv[0] > 0) ? argv[0] - 1 : 0; - break; - case 'H': /* CUP (0x48) - Cursor Position */ - x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0; - y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0; - debug("ansi CUP : Cursor at %dx%d\n", x, y); - break; - case 'J': /* ED (0x4a) - Erase In Page */ - savedattr = caca_get_attr(sc->cv, -1, -1); - caca_set_attr(sc->cv, sc->clearattr); - if (!argc || argv[0] == 0) - { - caca_draw_line(sc->cv, x, y, width, y, ' '); - caca_fill_box(sc->cv, 0, y + 1, width, height - 1, ' '); - } - else if (argv[0] == 1) - { - caca_fill_box(sc->cv, 0, 0, width, y, ' '); - caca_draw_line(sc->cv, 0, y, x, y, ' '); - } - else if (argv[0] == 2) - { - // x = y = 0; - caca_fill_box(sc->cv, 0, 0, width, height, ' '); - } - caca_set_attr(sc->cv, savedattr); - break; - case 'K': /* EL (0x4b) - Erase In Line */ - debug("ansi EL : cursor at %dx%d\n", x, y); - if (!argc || argv[0] == 0) - { - caca_draw_line(sc->cv, x, y, width, y, ' '); - } - else if (argv[0] == 1) - { - caca_draw_line(sc->cv, 0, y, x, y, ' '); - } - else if (argv[0] == 2) - { - caca_draw_line(sc->cv, 0, y, width, y, ' '); - } - break; - case 'L': /* IL - Insert line */ - { - unsigned int nb_lines = argc ? argv[0] : 1; - for (j = bottom - 1; j >= (unsigned int)y + nb_lines; j--) - { - for (k = 0; k < width; k++) - { - caca_put_char(sc->cv, k, j, - caca_get_char(sc->cv, k, - j - nb_lines)); - caca_put_attr(sc->cv, k, j, - caca_get_attr(sc->cv, k, - j - nb_lines)); - } - caca_draw_line(sc->cv, 0, j - nb_lines, width, - j - nb_lines, ' '); - } - } - break; - case 'P': /* DCH (0x50) - Delete Character */ - if (!argc || argv[0] == 0) - argv[0] = 1; /* echo -ne 'foobar\r\e[0P\n' */ - - for (j = x; (unsigned int)(j + argv[0]) < width; j++) - { - caca_put_char(sc->cv, j, y, - caca_get_char(sc->cv, j + argv[0], y)); - caca_put_attr(sc->cv, j, y, - caca_get_attr(sc->cv, j + argv[0], y)); - } - break; -#if 0 - savedattr = caca_get_attr(sc->cv, -1, -1); - caca_set_attr(sc->cv, sc->clearattr); - for (; (unsigned int)j < width; j++) - caca_put_char(sc->cv, j, y, ' '); - caca_set_attr(sc->cv, savedattr); -#endif - case 'X': /* ECH (0x58) - Erase Character */ - if (argc && argv[0]) - { - savedattr = caca_get_attr(sc->cv, -1, -1); - caca_set_attr(sc->cv, sc->clearattr); - caca_draw_line(sc->cv, x, y, x + argv[0] - 1, y, ' '); - caca_set_attr(sc->cv, savedattr); - } - case 'c': /* DA -- Device Attributes */ - /* - 0 Base VT100, no options 1 Processor options (STP) 2 - Advanced video option (AVO) 3 AVO and STP 4 Graphics - processor option (GPO) 5 GPO and STP 6 GPO and AVO 7 GPO, - STP, and AVO */ - /* Warning, argument is Pn */ - debug("ansi Got command c, argc %d, argv[0] (%d)\n", argc, - argv[0], argv[0]); - if (!argc || argv[0] == 0) - { - send_ansi_sequence(screen_list, "\x1b[?1;0c"); - } - else - { - switch (argv[0]) - { - case 1: - send_ansi_sequence(screen_list, "\x1b[?\x1;\x1c"); - break; - case 2: - send_ansi_sequence(screen_list, "\x1b[?\x1;\x2c"); - break; - case 3: - send_ansi_sequence(screen_list, "\x1b[?\x1;\x3c"); - break; - case 4: - send_ansi_sequence(screen_list, "\x1b[?\x1;\x4c"); - break; - case 5: - send_ansi_sequence(screen_list, "\x1b[?\x1;\x5c"); - break; - case 6: - send_ansi_sequence(screen_list, "\x1b[?\x1;\x6c"); - break; - case 7: - send_ansi_sequence(screen_list, "\x1b[?\x1;\x7c"); - break; - default: - debug("Unsupported DA option '%d'\n", argv[0]); - break; - } - } - break; - case 'd': /* VPA (0x64) - Line Position Absolute */ - y = (argc && argv[0] > 0) ? argv[0] - 1 : 0; - break; - case 'f': /* HVP (0x66) - Character And Line Position */ - x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0; - y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0; - break; - case 'g': /* TBC -- Tabulation Clear */ - break; - case 'r': /* FIXME */ - if (argc == 2) /* DCSTBM - Set top and bottom margin */ - { - debug("DCSTBM %d %d", argv[0], argv[1]); - top = argv[0]; - bottom = argv[1]; - } - else - debug("ansi import: command r with %d params", argc); - break; - case 'h': /* SM (0x68) - FIXME */ - debug("ansi import: set mode %i", argc ? (int)argv[0] : -1); - break; - case 'l': /* RM (0x6c) - FIXME */ - debug("ansi import: reset mode %i", argc ? (int)argv[0] : -1); - break; - case 'm': /* SGR (0x6d) - Select Graphic Rendition */ - if (argc) - ansi_parse_grcm(sc, argc, argv); - else - ansi_parse_grcm(sc, 1, &dummy); - break; - case 'n': - debug("ansi command n, argc %d, argv[0] %d\n", argc, argv[0]); - if (!argc) - break; - - switch (argv[0]) - { - case 5: - /* Term ok */ - send_ansi_sequence(screen_list, "\x1b[0n"); - break; - case 6: - /* Cursor Position */ - sprintf(b, "\x1b[%d;%dR", y + 1, x + 1); - send_ansi_sequence(screen_list, b); - break; - } - - break; - case 's': /* Private (save cursor position) */ - save_x = x; - save_y = y; - break; - case 'u': /* Private (reload cursor position) */ - x = save_x; - y = save_y; - break; - default: - debug("ansi import: unknown command \"^[%.*s\"", - final - param + 1, buffer + i + param); - break; - } - } - - /* Parse OSC stuff. */ - else if (buffer[i] == '\033' && buffer[i + 1] == ']') - { - char *string; - unsigned int command = 0; - unsigned int mode = 2, semicolon, final; - - for (semicolon = mode; i + semicolon < size; semicolon++) - { - if (buffer[i + semicolon] < '0' || buffer[i + semicolon] > '9') - break; - command = 10 * command + (buffer[i + semicolon] - '0'); - } - - if (i + semicolon >= size || buffer[i + semicolon] != ';') - break; /* Invalid Mode */ - - for (final = semicolon + 1; i + final < size; final++) - if (buffer[i + final] < 0x20) - break; - - if (i + final >= size || buffer[i + final] != '\a') - break; /* Not enough data or no bell found */ - /* FIXME: XTerm also reacts to and */ - /* FIXME: differenciate between not enough data (try again) and - invalid data (print shit) */ - - skip += final; - - string = (char *)malloc(final - (semicolon + 1) + 1); - memcpy(string, buffer + i + (semicolon + 1), - final - (semicolon + 1)); - string[final - (semicolon + 1)] = '\0'; - debug("ansi import: got OSC command %i string '%s'", command, - string); - if (command == 0 || command == 2) - { - if (sc->title) - free(sc->title); - sc->title = string; - } - else - free(string); - } - - /* Get the character we’re going to paste */ - else - { - size_t bytes; - - if (i + 6 < size) - { - ch = caca_utf8_to_utf32((char const *)(buffer + i), &bytes); - } - else - { - /* Add a trailing zero to what we're going to read */ - char tmp[7]; - memcpy(tmp, buffer + i, size - i); - tmp[size - i] = '\0'; - ch = caca_utf8_to_utf32(tmp, &bytes); - } - - if (!bytes) - { - /* If the Unicode is invalid, assume it was latin1. */ - ch = buffer[i]; - bytes = 1; - } - - /* very incomplete ISO-2022 implementation tailored to DEC ACS */ - if (sc->conv_state.cs == '@') - { - if (((ch > ' ') && (ch <= '~')) - && - (sc->conv_state. - gn[sc->conv_state.ss ? sc->conv_state. - gn[sc->conv_state.ss] : sc->conv_state.glr[0]] == '0')) - { - ch = dec_acs(ch); - } - else if (((ch > 0x80) && (ch < 0xff)) - && (sc->conv_state.gn[sc->conv_state.glr[1]] == '0')) - { - ch = dec_acs(ch + ' ' - 0x80); - } - } - sc->conv_state.ss = 0; /* no single-shift (GL) */ - - wch = caca_utf32_is_fullwidth(ch) ? 2 : 1; - - skip += bytes - 1; - } - - /* Wrap long lines or grow horizontally */ - while ((unsigned int)x + wch > width) - { - x -= width; - y++; - } - - /* Scroll or grow vertically */ - if ((unsigned int)y >= bottom) - { - int lines = (y - bottom) + 1; - - savedattr = caca_get_attr(sc->cv, -1, -1); - - for (j = top - 1; j + lines < bottom; j++) - { - for (k = 0; k < width; k++) - { - caca_put_char(sc->cv, k, j, - caca_get_char(sc->cv, k, j + lines)); - caca_put_attr(sc->cv, k, j, - caca_get_attr(sc->cv, k, j + lines)); - } - } - caca_set_attr(sc->cv, sc->clearattr); - caca_fill_box(sc->cv, 0, bottom - lines, width, bottom - 1, ' '); - y -= lines; - caca_set_attr(sc->cv, savedattr); - } - - /* Now paste our character, if any */ - if (wch) - { - caca_put_char(sc->cv, x, y, ch); - x += wch; - } - } - - caca_gotoxy(sc->cv, x, y); - - if (i) - sc->changed = 1; - return i; -} - -/* Coding Method Delimiter (CMD), ECMA-48 (1991), ISO/IEC 6429:1992 (ISO IR - 189) */ - -static void reset_conv_state(struct screen *sc) -{ - sc->conv_state.cs = '@'; /* ISO-2022 coding system */ - sc->conv_state.cn[0] = '@'; /* ISO 646 C0 control charset */ - sc->conv_state.cn[1] = 'C'; /* ISO 6429-1983 C1 control charset */ - sc->conv_state.glr[0] = 0; /* G0 in GL */ - sc->conv_state.glr[1] = 2; /* G2 in GR */ - sc->conv_state.gn[0] = 'B'; /* US-ASCII G0 charset */ - sc->conv_state.gn[1] = '0'; /* DEC ACS G1 charset */ - sc->conv_state.gn[2] = LITERAL2CHAR('.', 'A'); /* ISO 8859-1 G2 - charset */ - sc->conv_state.gn[3] = LITERAL2CHAR('.', 'A'); /* ISO 8859-1 G3 - charset */ - sc->conv_state.ss = 0; /* no single-shift (GL) */ - sc->conv_state.ctrl8bit = 1; -} - -/* XXX : ANSI loader helper */ - -static void ansi_parse_grcm(struct screen *sc, - unsigned int argc, unsigned int const *argv) -{ - static uint8_t const ansi2caca[] = { - CACA_BLACK, CACA_RED, CACA_GREEN, CACA_BROWN, - CACA_BLUE, CACA_MAGENTA, CACA_CYAN, CACA_LIGHTGRAY - }; - - unsigned int j; - uint8_t efg, ebg; /* Effective (libcaca) fg/bg */ - - for (j = 0; j < argc; j++) - { - /* Defined in ECMA-48 8.3.117: SGR - SELECT GRAPHIC RENDITION */ - if (argv[j] >= 30 && argv[j] <= 37) - sc->fg = ansi2caca[argv[j] - 30]; - else if (argv[j] >= 40 && argv[j] <= 47) - sc->bg = ansi2caca[argv[j] - 40]; - else if (argv[j] >= 90 && argv[j] <= 97) - sc->fg = ansi2caca[argv[j] - 90] + 8; - else if (argv[j] >= 100 && argv[j] <= 107) - sc->bg = ansi2caca[argv[j] - 100] + 8; - else - switch (argv[j]) - { - case 0: /* default rendition */ - sc->fg = sc->dfg; - sc->bg = sc->dbg; - sc->bold = sc->blink = sc->italics = sc->negative - = sc->concealed = sc->underline = sc->faint = sc->strike - = sc->proportional = 0; - break; - case 1: /* bold or increased intensity */ - sc->bold = 1; - break; - case 2: /* faint, decreased intensity or second colour - */ - sc->faint = 1; - break; - case 3: /* italicized */ - sc->italics = 1; - break; - case 4: /* singly underlined */ - sc->underline = 1; - break; - case 5: /* slowly blinking (less then 150 per minute) */ - case 6: /* rapidly blinking (150 per minute or more) */ - sc->blink = 1; - break; - case 7: /* negative image */ - sc->negative = 1; - break; - case 8: /* concealed characters */ - sc->concealed = 1; - break; - case 9: /* crossed-out (characters still legible but - marked as to be deleted */ - sc->strike = 1; - break; - case 21: /* doubly underlined */ - sc->underline = 1; - break; - case 22: /* normal colour or normal intensity (neither - bold nor faint) */ - sc->bold = sc->faint = 0; - break; - case 23: /* not italicized, not fraktur */ - sc->italics = 0; - break; - case 24: /* not underlined (neither singly nor doubly) */ - sc->underline = 0; - break; - case 25: /* steady (not blinking) */ - sc->blink = 0; - break; - case 26: /* (reserved for proportional spacing as - specified in CCITT Recommendation T.61) */ - sc->proportional = 1; - break; - case 27: /* positive image */ - sc->negative = 0; - break; - case 28: /* revealed characters */ - sc->concealed = 0; - break; - case 29: /* not crossed out */ - sc->strike = 0; - break; - case 38: /* (reserved for future standardization, - intended for setting character foreground - colour as specified in ISO 8613-6 [CCITT - Recommendation T.416]) */ - break; - case 39: /* default display colour - (implementation-defined) */ - sc->fg = sc->dfg; - break; - case 48: /* (reserved for future standardization, - intended for setting character background - colour as specified in ISO 8613-6 [CCITT - Recommendation T.416]) */ - break; - case 49: /* default background colour - (implementation-defined) */ - sc->bg = sc->dbg; - break; - case 50: /* (reserved for cancelling the effect of the - rendering aspect established by parameter - value 26) */ - sc->proportional = 0; - break; - default: - debug("ansi import: unknown sgr %i", argv[j]); - break; - } - } - - if (sc->concealed) - { - efg = ebg = CACA_TRANSPARENT; - } - else - { - efg = sc->negative ? sc->bg : sc->fg; - ebg = sc->negative ? sc->fg : sc->bg; - - if (sc->bold) - { - if (efg < 8) - efg += 8; - else if (efg == CACA_DEFAULT) - efg = CACA_WHITE; - } - } - - caca_set_color_ansi(sc->cv, efg, ebg); -} +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if defined _MSC_VER # define inline __inline #endif #include #include #include "neercs.h" /* DEC ACS with common extensions */ static uint32_t dec_acs(uint32_t uc) { switch (uc) { case '+': return 0x2192; /* RIGHTWARDS ARROW */ case ',': return 0x2190; /* LEFTWARDS ARROW */ case '-': return 0x2191; /* UPWARDS ARROW */ case '.': return 0x2193; /* DOWNWARDS ARROW */ case '0': return 0x25AE; /* BLACK VERTICAL RECTANGLE */ case '_': return 0x25AE; /* BLACK VERTICAL RECTANGLE */ case '`': return 0x25C6; /* BLACK DIAMOND */ case 'a': return 0x2592; /* MEDIUM SHADE */ case 'b': return 0x2409; /* SYMBOL FOR HORIZONTAL TABULATION */ case 'c': return 0x240C; /* SYMBOL FOR FORM FEED */ case 'd': return 0x240D; /* SYMBOL FOR CARRIAGE RETURN */ case 'e': return 0x240A; /* SYMBOL FOR LINE FEED */ case 'f': return 0x00B0; /* DEGREE SIGN */ case 'g': return 0x00B1; /* PLUS-MINUS SIGN */ case 'h': return 0x2424; /* SYMBOL FOR NEWLINE */ case 'i': return 0x240B; /* SYMBOL FOR VERTICAL TABULATION */ case 'j': return 0x2518; /* BOX DRAWINGS LIGHT UP AND LEFT */ case 'k': return 0x2510; /* BOX DRAWINGS LIGHT DOWN AND LEFT */ case 'l': return 0x250C; /* BOX DRAWINGS LIGHT DOWN AND RIGHT */ case 'm': return 0x2514; /* BOX DRAWINGS LIGHT UP AND RIGHT */ case 'n': return 0x253C; /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ case 'o': return 0x23BA; /* HORIZONTAL SCAN LINE-1 */ case 'p': return 0x23BB; /* HORIZONTAL SCAN LINE-3 */ case 'q': return 0x2500; /* BOX DRAWINGS LIGHT HORIZONTAL */ case 'r': return 0x23BC; /* HORIZONTAL SCAN LINE-7 */ case 's': return 0x23BD; /* HORIZONTAL SCAN LINE-9 */ case 't': return 0x251C; /* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ case 'u': return 0x2524; /* BOX DRAWINGS LIGHT VERTICAL AND LEFT */ case 'v': return 0x2534; /* BOX DRAWINGS LIGHT UP AND HORIZONTAL */ case 'w': return 0x252C; /* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ case 'x': return 0x2502; /* BOX DRAWINGS LIGHT VERTICAL */ case 'y': return 0x2264; /* LESS-THAN OR EQUAL TO */ case 'z': return 0x2265; /* GREATER-THAN OR EQUAL TO */ case '{': return 0x03C0; /* GREEK SMALL LETTER PI */ case '|': return 0x2260; /* NOT EQUAL TO */ case '}': return 0x00A3; /* POUND SIGN */ case '~': return 0x00B7; /* MIDDLE DOT */ default: return uc; } }; static void reset_conv_state(struct screen *); #define LITERAL2CHAR(i0,i1) (((i0) << 8) | (i1)) #define LITERAL3CHAR(i0,i1,i2) LITERAL2CHAR(LITERAL2CHAR(i0, i1), i2) static void ansi_parse_grcm(struct screen *, unsigned int, unsigned int const *); inline int handle_single_char(unsigned char c, int *x, int *y, struct screen_list *screen_list, struct screen *sc); static inline int handle_duplet(unsigned char const *buffer, struct screen *sc, unsigned int *skip, int top, int bottom, int width, int height); inline int handle_single_char(unsigned char c, int *x, int *y, struct screen_list *screen_list, struct screen *sc) { if (c == '\r') { *x = 0; } else if (c == '\n') { *x = 0; *y = *y + 1; } else if (c == '\a') { if (!sc->bell) screen_list->in_bell = 10; sc->bell = 1; } else if (c == '\t') { *x = (*x + 7) & ~7; } else if (c == '\x08') { if (*x > 0) *x = *x - 1; } else if (c == '\x0b') { /* Vertical tab */ /* Not sure about the real meaning of it, just y++ for now */ if (*y < caca_get_canvas_height(sc->cv)) *y = *y + 1; } else if (c == '\x0e') { /* Shift Out (Ctrl-N) -> Switch to Alternate Character Set: invokes the G1 character set. */ sc->conv_state.glr[0] = 1; } else if (c == '\x0f') { /* Shift In (Ctrl-O) -> Switch to Standard Character Set: invokes the G0 character set. */ sc->conv_state.glr[0] = 0; } else { return 1; } return 0; } static inline int handle_duplet(unsigned char const *buffer, struct screen *sc, unsigned int *skip, int top, int bottom, int width, int height) { int i = 0, j, k; unsigned int dummy = 0; /* Single Shift Select of G2 Character Set (SS2: 0x8e): affects next character only */ if (buffer[i] == '\033' && buffer[i + 1] == 'N') { sc->conv_state.ss = 2; *skip += 1; } /* Reverse Index (RI) go up one line, reverse scroll if necessary */ else if (buffer[i] == '\033' && buffer[i + 1] == 'M') { /* FIXME : not sure about the meaning of 'go up one line' and 'if necessary' words. Implemented as a scroller only. */ for (j = bottom - 1; j > top; j--) { for (k = 0; k < width; k++) { caca_put_char(sc->cv, k, j, caca_get_char(sc->cv, k, j - 1)); caca_put_attr(sc->cv, k, j, caca_get_attr(sc->cv, k, j - 1)); } } caca_draw_line(sc->cv, 0, top - 1, width - 1, top - 1, ' '); *skip += 1; } /* Single Shift Select of G3 Character Set (SS2: 0x8f): affects next character only */ else if (buffer[i] == '\033' && buffer[i + 1] == 'O') { sc->conv_state.ss = 3; *skip += 1; } /* LOCKING-SHIFT TWO (LS2), ISO 2022, ECMA-48 (1986), ISO 6429 : 1988 */ else if (buffer[i] == '\033' && buffer[i + 1] == 'n') { sc->conv_state.glr[0] = 2; *skip += 1; } /* LOCKING-SHIFT THREE (LS3) ISO 2022, ECMA-48 (1986), ISO 6429 : 1988 */ else if (buffer[i] == '\033' && buffer[i + 1] == 'o') { sc->conv_state.glr[0] = 3; *skip += 1; } /* RESET TO INITIAL STATE (RIS), ECMA-48 (1986), ISO 6429 : 1988 */ else if (buffer[i] == '\033' && buffer[i + 1] == 'c') { sc->dfg = CACA_DEFAULT; sc->dbg = CACA_DEFAULT; caca_set_color_ansi(sc->cv, sc->dfg, sc->dbg); sc->clearattr = caca_get_attr(sc->cv, -1, -1); ansi_parse_grcm(sc, 1, &dummy); reset_conv_state(sc); *skip += 1; } /* Coding Method Delimiter (CMD), ECMA-48 (1991), ISO/IEC 6429:1992 (ISO IR 189) */ else if (buffer[i] == '\033' && buffer[i + 1] == 'd') { reset_conv_state(sc); *skip += 1; } else { return 1; } return 0; } long int import_term(struct screen_list *screen_list, struct screen *sc, void const *data, unsigned int size) { unsigned char const *buffer = (unsigned char const *)data; unsigned int i, j, k, skip, dummy = 0; unsigned int width, height, top, bottom; uint32_t savedattr; int x = 0, y = 0, save_x = 0, save_y = 0; char b[100]; debug("ansi : import_term\n"); width = caca_get_canvas_width(sc->cv); height = caca_get_canvas_height(sc->cv); x = caca_get_cursor_x(sc->cv); y = caca_get_cursor_y(sc->cv); top = 1; bottom = height; if (!sc->init) { sc->dfg = CACA_LIGHTGRAY; sc->dbg = CACA_BLACK; caca_set_color_ansi(sc->cv, sc->dfg, sc->dbg); sc->clearattr = caca_get_attr(sc->cv, -1, -1); ansi_parse_grcm(sc, 1, &dummy); reset_conv_state(sc); sc->init = 1; } for (i = 0; i < size; i += skip) { uint32_t ch = 0; int wch = 0; skip = 1; /* Control codes (ASCII < \x20) */ if (!handle_single_char(buffer[i], &x, &y, screen_list, sc)) { } /* If there are not enough characters to parse the escape sequence, wait until the next try. We require 3. */ else if (buffer[i] == '\033' && i + 2 >= size) break; else if (!handle_duplet(&buffer[i], sc, &skip, top, bottom, width, height)) { } /* GZDM4, G0-Designators, multi, 94^n chars [grandfathered short form from ISO 2022:1986] */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && (buffer[i + 2] >= '@') && (buffer[i + 2] <= 'C')) { sc->conv_state.gn[0] = LITERAL2CHAR('$', buffer[i + 2]); skip += 2; } /* GnDMx Gn-Designators, 9x^n chars; need one more char to distinguish these */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && (i + 3 >= size)) break; /* GZD4 G0-Designator, 94 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '(') { sc->conv_state.gn[0] = buffer[i + 2]; skip += 2; } /* G1D4 G1-Designator, 94 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == ')') { sc->conv_state.gn[1] = buffer[i + 2]; skip += 2; } /* G2D4 G2-Designator, 94 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '*') { sc->conv_state.gn[2] = buffer[i + 2]; skip += 2; } /* G3D4 G3-Designator, 94 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '+') { sc->conv_state.gn[3] = buffer[i + 2]; skip += 2; } /* G2D6 G2-Designator, 96 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '.') { sc->conv_state.gn[2] = LITERAL2CHAR('.', buffer[i + 2]); skip += 2; } /* G3D6 G3-Designator, 96 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '/') { sc->conv_state.gn[3] = LITERAL2CHAR('.', buffer[i + 2]); skip += 2; } /* GZDM4 G0-Designator, 94^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '(') { sc->conv_state.gn[0] = LITERAL2CHAR('$', buffer[i + 3]); skip += 3; } /* G1DM4 G1-Designator, 94^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == ')') { sc->conv_state.gn[1] = LITERAL2CHAR('$', buffer[i + 3]); skip += 3; } /* G2DM4 G2-Designator, 94^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '*') { sc->conv_state.gn[2] = LITERAL2CHAR('$', buffer[i + 3]); skip += 3; } /* G3DM4 G3-Designator, 94^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '+') { sc->conv_state.gn[3] = LITERAL2CHAR('$', buffer[i + 3]); skip += 3; } /* G2DM6 G2-Designator, 96^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '.') { sc->conv_state.gn[2] = LITERAL3CHAR('$', '.', buffer[i + 3]); skip += 3; } /* G3DM6 G3-Designator, 96^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '/') { sc->conv_state.gn[3] = LITERAL3CHAR('$', '.', buffer[i + 3]); skip += 3; } else if (buffer[i] == '\033' && buffer[i + 1] == '#') { debug("ansi private '#' sequence\n"); switch (buffer[i + 2]) { case '8': /* DECALN Fills the entire screen area with uppercase Es for screen focus and alignment. */ for (j = 0; j < height; j++) { for (k = 0; k < width; k++) { caca_put_char(sc->cv, k, j, 'E'); } } x = 0; y = 0; skip += 2; break; default: debug("Unknow private sequence 'ESC#%c'\n", buffer[i + 2]); continue; } } /* Interpret escape commands, as per Standard ECMA-48 "Control Functions for Coded Character Sets", 5.4. Control sequences. */ else if (buffer[i] == '\033' && buffer[i + 1] == '[') { unsigned int argc = 0, argv[101]; unsigned int param, inter, junk, final; if (buffer[i + 2] == '?') { debug("CSI? %c%c%c%c%c\n", buffer[i + 3], buffer[i + 4], buffer[i + 5], buffer[i + 6], buffer[i + 7]); } /* Compute offsets to parameter bytes, intermediate bytes and to the final byte. Only the final byte is mandatory, there can be zero of the others. 0 param=2 inter final final+1 +-----+------------------+---------------------+-----------------+ | CSI | parameter bytes | intermediate bytes | final byte | | | 0x30 - 0x3f | 0x20 - 0x2f | 0x40 - 0x7e | | ^[[ | 0123456789:;<=>? | SPC !"#$%&'()*+,-./ | azAZ@[\]^_`{|}~ | +-----+------------------+---------------------+-----------------+ */ param = 2; /* vttest use to interleave control characters (\014 CR or \010 BS) into CSI sequences, either directly after ESC[ or after param. Can't find anything related to this in any documentation nor XTerm sources, thought. */ for (junk = param; i + junk < size; junk++) if (buffer[i + junk] < 0x20) { handle_single_char(buffer[i + junk], &x, &y, screen_list, sc); } else { break; } /* Intermediate offset */ for (inter = junk; i + inter < size; inter++) if (buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f) { break; } /* Interleaved character */ for (junk = inter; i + junk < size; junk++) if (buffer[i + junk] < 0x20) { handle_single_char(buffer[i + junk], &x, &y, screen_list, sc); } else { break; } /* Final Byte offset */ for (final = junk; i + final < size; final++) if (buffer[i + final] < 0x20 || buffer[i + final] > 0x2f) { break; } if (i + final >= size || buffer[i + final] < 0x40 || buffer[i + final] > 0x7e) { debug("ansi Invalid Final Byte (%d %c)\n", buffer[i + final], buffer[i + final]); break; /* Invalid Final Byte */ } skip += final; /* Sanity checks */ if (param < inter && buffer[i + param] >= 0x3c) { /* Private sequence, only parse what we know */ debug("ansi import: private sequence \"^[[%.*s\"", final - param + 1, buffer + i + param); /* FIXME better parsing */ if (buffer[i + 2] == '?') { char arg[5], *end; int a = 0; int c, p, Pm; for (p = 0; p < 4; p++) { if (buffer[i + 3 + p] >= '0' && buffer[i + 3 + p] <= '9') { arg[a] = buffer[i + 3 + p]; arg[a + 1] = 0; a++; debug("private a now '%s'\n", arg); } else { break; } } Pm = strtol(arg, &end, 10); c = buffer[i + 3 + (end - arg)]; debug("ansi private mouse : command %c, arg %d", c, Pm); if (c == 'h') /* DECSET DEC Private Mode Set */ { switch (Pm) { /* FIXME Handle different modes */ case 9: debug("mouse : X10 mode\n"); sc->report_mouse = MOUSE_X10; break; case 1000: /* Send Mouse X & Y on button press and release. */ debug("mouse : VT200 mode\n"); sc->report_mouse = MOUSE_VT200; break; case 1001: /* Use Hilite Mouse Tracking. */ debug("mouse : VT200_HIGHLIGHT mode\n"); sc->report_mouse = MOUSE_VT200_HIGHLIGHT; break; case 1002: /* Use Cell Motion Mouse Tracking. */ debug("mouse : BTN mode\n"); sc->report_mouse = MOUSE_BTN_EVENT; break; case 1003: /* Use All Motion Mouse Tracking. */ debug("mouse : ANY mode\n"); sc->report_mouse = MOUSE_ANY_EVENT; break; default: break; } } else if (c == 'l') /* DECRST DEC Private Mode Reset */ { Pm = atoi(arg); switch (Pm) { /* FIXME Handle different modes */ case 9: case 1000: /* Send Mouse X & Y on button press and release. */ case 1001: /* Use Hilite Mouse Tracking. */ case 1002: /* Use Cell Motion Mouse Tracking. */ case 1003: /* Use All Motion Mouse Tracking. */ sc->report_mouse = MOUSE_NONE; debug("ansi private mouse : NOT reporting mouse"); break; default: break; } } } continue; /* Private sequence, skip it entirely */ } if (final - param > 100) continue; /* Suspiciously long sequence, skip it */ /* Parse parameter bytes as per ECMA-48 5.4.2: Parameter string format */ if (param < inter) { argv[0] = 0; for (j = param; j < inter; j++) { if (buffer[i + j] == ';') argv[++argc] = 0; else if (buffer[i + j] >= '0' && buffer[i + j] <= '9') argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0'); } argc++; } /* Interpret final byte. The code representations are given in ECMA-48 5.4: Control sequences, and the code definitions are given in ECMA-48 8.3: Definition of control functions. */ debug("ansi import: command '%c'", buffer[i + final]); switch (buffer[i + final]) { case 'A': /* CUU (0x41) - Cursor Up */ y -= argc ? argv[0] : 1; if (y < 0) y = 0; break; case 'B': /* CUD (0x42) - Cursor Down */ y += argc ? argv[0] : 1; break; case 'C': /* CUF (0x43) - Cursor Right */ x += argc ? argv[0] : 1; break; case 'D': /* CUB (0x44) - Cursor Left */ x -= argc ? argv[0] : 1; if (x < 0) x = 0; break; case 'G': /* CHA (0x47) - Cursor Character Absolute */ x = (argc && argv[0] > 0) ? argv[0] - 1 : 0; break; case 'H': /* CUP (0x48) - Cursor Position */ x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0; y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0; debug("ansi CUP : Cursor at %dx%d\n", x, y); break; case 'J': /* ED (0x4a) - Erase In Page */ savedattr = caca_get_attr(sc->cv, -1, -1); caca_set_attr(sc->cv, sc->clearattr); if (!argc || argv[0] == 0) { caca_draw_line(sc->cv, x, y, width, y, ' '); caca_fill_box(sc->cv, 0, y + 1, width, height - 1, ' '); } else if (argv[0] == 1) { caca_fill_box(sc->cv, 0, 0, width, y, ' '); caca_draw_line(sc->cv, 0, y, x, y, ' '); } else if (argv[0] == 2) { // x = y = 0; caca_fill_box(sc->cv, 0, 0, width, height, ' '); } caca_set_attr(sc->cv, savedattr); break; case 'K': /* EL (0x4b) - Erase In Line */ debug("ansi EL : cursor at %dx%d\n", x, y); if (!argc || argv[0] == 0) { caca_draw_line(sc->cv, x, y, width, y, ' '); } else if (argv[0] == 1) { caca_draw_line(sc->cv, 0, y, x, y, ' '); } else if (argv[0] == 2) { caca_draw_line(sc->cv, 0, y, width, y, ' '); } break; case 'L': /* IL - Insert line */ { unsigned int nb_lines = argc ? argv[0] : 1; for (j = bottom - 1; j >= (unsigned int)y + nb_lines; j--) { for (k = 0; k < width; k++) { caca_put_char(sc->cv, k, j, caca_get_char(sc->cv, k, j - nb_lines)); caca_put_attr(sc->cv, k, j, caca_get_attr(sc->cv, k, j - nb_lines)); } caca_draw_line(sc->cv, 0, j - nb_lines, width, j - nb_lines, ' '); } } break; case 'P': /* DCH (0x50) - Delete Character */ if (!argc || argv[0] == 0) argv[0] = 1; /* echo -ne 'foobar\r\e[0P\n' */ for (j = x; (unsigned int)(j + argv[0]) < width; j++) { caca_put_char(sc->cv, j, y, caca_get_char(sc->cv, j + argv[0], y)); caca_put_attr(sc->cv, j, y, caca_get_attr(sc->cv, j + argv[0], y)); } break; #if 0 savedattr = caca_get_attr(sc->cv, -1, -1); caca_set_attr(sc->cv, sc->clearattr); for (; (unsigned int)j < width; j++) caca_put_char(sc->cv, j, y, ' '); caca_set_attr(sc->cv, savedattr); #endif case 'X': /* ECH (0x58) - Erase Character */ if (argc && argv[0]) { savedattr = caca_get_attr(sc->cv, -1, -1); caca_set_attr(sc->cv, sc->clearattr); caca_draw_line(sc->cv, x, y, x + argv[0] - 1, y, ' '); caca_set_attr(sc->cv, savedattr); } case 'c': /* DA -- Device Attributes */ /* 0 Base VT100, no options 1 Processor options (STP) 2 Advanced video option (AVO) 3 AVO and STP 4 Graphics processor option (GPO) 5 GPO and STP 6 GPO and AVO 7 GPO, STP, and AVO */ /* Warning, argument is Pn */ debug("ansi Got command c, argc %d, argv[0] (%d)\n", argc, argv[0], argv[0]); if (!argc || argv[0] == 0) { send_ansi_sequence(screen_list, "\x1b[?1;0c"); } else { switch (argv[0]) { case 1: send_ansi_sequence(screen_list, "\x1b[?\x1;\x1c"); break; case 2: send_ansi_sequence(screen_list, "\x1b[?\x1;\x2c"); break; case 3: send_ansi_sequence(screen_list, "\x1b[?\x1;\x3c"); break; case 4: send_ansi_sequence(screen_list, "\x1b[?\x1;\x4c"); break; case 5: send_ansi_sequence(screen_list, "\x1b[?\x1;\x5c"); break; case 6: send_ansi_sequence(screen_list, "\x1b[?\x1;\x6c"); break; case 7: send_ansi_sequence(screen_list, "\x1b[?\x1;\x7c"); break; default: debug("Unsupported DA option '%d'\n", argv[0]); break; } } break; case 'd': /* VPA (0x64) - Line Position Absolute */ y = (argc && argv[0] > 0) ? argv[0] - 1 : 0; break; case 'f': /* HVP (0x66) - Character And Line Position */ x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0; y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0; break; case 'g': /* TBC -- Tabulation Clear */ break; case 'r': /* FIXME */ if (argc == 2) /* DCSTBM - Set top and bottom margin */ { debug("DCSTBM %d %d", argv[0], argv[1]); top = argv[0]; bottom = argv[1]; } else debug("ansi import: command r with %d params", argc); break; case 'h': /* SM (0x68) - FIXME */ debug("ansi import: set mode %i", argc ? (int)argv[0] : -1); break; case 'l': /* RM (0x6c) - FIXME */ debug("ansi import: reset mode %i", argc ? (int)argv[0] : -1); break; case 'm': /* SGR (0x6d) - Select Graphic Rendition */ if (argc) ansi_parse_grcm(sc, argc, argv); else ansi_parse_grcm(sc, 1, &dummy); break; case 'n': debug("ansi command n, argc %d, argv[0] %d\n", argc, argv[0]); if (!argc) break; switch (argv[0]) { case 5: /* Term ok */ send_ansi_sequence(screen_list, "\x1b[0n"); break; case 6: /* Cursor Position */ sprintf(b, "\x1b[%d;%dR", y + 1, x + 1); send_ansi_sequence(screen_list, b); break; } break; case 's': /* Private (save cursor position) */ save_x = x; save_y = y; break; case 'u': /* Private (reload cursor position) */ x = save_x; y = save_y; break; default: debug("ansi import: unknown command \"^[%.*s\"", final - param + 1, buffer + i + param); break; } } /* Parse OSC stuff. */ else if (buffer[i] == '\033' && buffer[i + 1] == ']') { char *string; unsigned int command = 0; unsigned int mode = 2, semicolon, final; for (semicolon = mode; i + semicolon < size; semicolon++) { if (buffer[i + semicolon] < '0' || buffer[i + semicolon] > '9') break; command = 10 * command + (buffer[i + semicolon] - '0'); } if (i + semicolon >= size || buffer[i + semicolon] != ';') break; /* Invalid Mode */ for (final = semicolon + 1; i + final < size; final++) if (buffer[i + final] < 0x20) break; if (i + final >= size || buffer[i + final] != '\a') break; /* Not enough data or no bell found */ /* FIXME: XTerm also reacts to and */ /* FIXME: differenciate between not enough data (try again) and invalid data (print shit) */ skip += final; string = (char *)malloc(final - (semicolon + 1) + 1); memcpy(string, buffer + i + (semicolon + 1), final - (semicolon + 1)); string[final - (semicolon + 1)] = '\0'; debug("ansi import: got OSC command %i string '%s'", command, string); if (command == 0 || command == 2) { if (sc->title) free(sc->title); sc->title = string; } else free(string); } /* Get the character we’re going to paste */ else { size_t bytes; if (i + 6 < size) { ch = caca_utf8_to_utf32((char const *)(buffer + i), &bytes); } else { /* Add a trailing zero to what we're going to read */ char tmp[7]; memcpy(tmp, buffer + i, size - i); tmp[size - i] = '\0'; ch = caca_utf8_to_utf32(tmp, &bytes); } if (!bytes) { /* If the Unicode is invalid, assume it was latin1. */ ch = buffer[i]; bytes = 1; } /* very incomplete ISO-2022 implementation tailored to DEC ACS */ if (sc->conv_state.cs == '@') { if (((ch > ' ') && (ch <= '~')) && (sc->conv_state. gn[sc->conv_state.ss ? sc->conv_state. gn[sc->conv_state.ss] : sc->conv_state.glr[0]] == '0')) { ch = dec_acs(ch); } else if (((ch > 0x80) && (ch < 0xff)) && (sc->conv_state.gn[sc->conv_state.glr[1]] == '0')) { ch = dec_acs(ch + ' ' - 0x80); } } sc->conv_state.ss = 0; /* no single-shift (GL) */ wch = caca_utf32_is_fullwidth(ch) ? 2 : 1; skip += bytes - 1; } /* Wrap long lines or grow horizontally */ while ((unsigned int)x + wch > width) { x -= width; y++; } /* Scroll or grow vertically */ if ((unsigned int)y >= bottom) { int lines = (y - bottom) + 1; savedattr = caca_get_attr(sc->cv, -1, -1); for (j = top - 1; j + lines < bottom; j++) { for (k = 0; k < width; k++) { caca_put_char(sc->cv, k, j, caca_get_char(sc->cv, k, j + lines)); caca_put_attr(sc->cv, k, j, caca_get_attr(sc->cv, k, j + lines)); } } caca_set_attr(sc->cv, sc->clearattr); caca_fill_box(sc->cv, 0, bottom - lines, width, bottom - 1, ' '); y -= lines; caca_set_attr(sc->cv, savedattr); } /* Now paste our character, if any */ if (wch) { caca_put_char(sc->cv, x, y, ch); x += wch; } } caca_gotoxy(sc->cv, x, y); if (i) sc->changed = 1; return i; } /* Coding Method Delimiter (CMD), ECMA-48 (1991), ISO/IEC 6429:1992 (ISO IR 189) */ static void reset_conv_state(struct screen *sc) { sc->conv_state.cs = '@'; /* ISO-2022 coding system */ sc->conv_state.cn[0] = '@'; /* ISO 646 C0 control charset */ sc->conv_state.cn[1] = 'C'; /* ISO 6429-1983 C1 control charset */ sc->conv_state.glr[0] = 0; /* G0 in GL */ sc->conv_state.glr[1] = 2; /* G2 in GR */ sc->conv_state.gn[0] = 'B'; /* US-ASCII G0 charset */ sc->conv_state.gn[1] = '0'; /* DEC ACS G1 charset */ sc->conv_state.gn[2] = LITERAL2CHAR('.', 'A'); /* ISO 8859-1 G2 charset */ sc->conv_state.gn[3] = LITERAL2CHAR('.', 'A'); /* ISO 8859-1 G3 charset */ sc->conv_state.ss = 0; /* no single-shift (GL) */ sc->conv_state.ctrl8bit = 1; } /* XXX : ANSI loader helper */ static void ansi_parse_grcm(struct screen *sc, unsigned int argc, unsigned int const *argv) { static uint8_t const ansi2caca[] = { CACA_BLACK, CACA_RED, CACA_GREEN, CACA_BROWN, CACA_BLUE, CACA_MAGENTA, CACA_CYAN, CACA_LIGHTGRAY }; unsigned int j; uint8_t efg, ebg; /* Effective (libcaca) fg/bg */ for (j = 0; j < argc; j++) { /* Defined in ECMA-48 8.3.117: SGR - SELECT GRAPHIC RENDITION */ if (argv[j] >= 30 && argv[j] <= 37) sc->fg = ansi2caca[argv[j] - 30]; else if (argv[j] >= 40 && argv[j] <= 47) sc->bg = ansi2caca[argv[j] - 40]; else if (argv[j] >= 90 && argv[j] <= 97) sc->fg = ansi2caca[argv[j] - 90] + 8; else if (argv[j] >= 100 && argv[j] <= 107) sc->bg = ansi2caca[argv[j] - 100] + 8; else switch (argv[j]) { case 0: /* default rendition */ sc->fg = sc->dfg; sc->bg = sc->dbg; sc->bold = sc->blink = sc->italics = sc->negative = sc->concealed = sc->underline = sc->faint = sc->strike = sc->proportional = 0; break; case 1: /* bold or increased intensity */ sc->bold = 1; break; case 2: /* faint, decreased intensity or second colour */ sc->faint = 1; break; case 3: /* italicized */ sc->italics = 1; break; case 4: /* singly underlined */ sc->underline = 1; break; case 5: /* slowly blinking (less then 150 per minute) */ case 6: /* rapidly blinking (150 per minute or more) */ sc->blink = 1; break; case 7: /* negative image */ sc->negative = 1; break; case 8: /* concealed characters */ sc->concealed = 1; break; case 9: /* crossed-out (characters still legible but marked as to be deleted */ sc->strike = 1; break; case 21: /* doubly underlined */ sc->underline = 1; break; case 22: /* normal colour or normal intensity (neither bold nor faint) */ sc->bold = sc->faint = 0; break; case 23: /* not italicized, not fraktur */ sc->italics = 0; break; case 24: /* not underlined (neither singly nor doubly) */ sc->underline = 0; break; case 25: /* steady (not blinking) */ sc->blink = 0; break; case 26: /* (reserved for proportional spacing as specified in CCITT Recommendation T.61) */ sc->proportional = 1; break; case 27: /* positive image */ sc->negative = 0; break; case 28: /* revealed characters */ sc->concealed = 0; break; case 29: /* not crossed out */ sc->strike = 0; break; case 38: /* (reserved for future standardization, intended for setting character foreground colour as specified in ISO 8613-6 [CCITT Recommendation T.416]) */ break; case 39: /* default display colour (implementation-defined) */ sc->fg = sc->dfg; break; case 48: /* (reserved for future standardization, intended for setting character background colour as specified in ISO 8613-6 [CCITT Recommendation T.416]) */ break; case 49: /* default background colour (implementation-defined) */ sc->bg = sc->dbg; break; case 50: /* (reserved for cancelling the effect of the rendering aspect established by parameter value 26) */ sc->proportional = 0; break; default: debug("ansi import: unknown sgr %i", argv[j]); break; } } if (sc->concealed) { efg = ebg = CACA_TRANSPARENT; } else { efg = sc->negative ? sc->bg : sc->fg; ebg = sc->negative ? sc->fg : sc->bg; if (sc->bold) { if (efg < 8) efg += 8; else if (efg == CACA_DEFAULT) efg = CACA_WHITE; } } caca_set_color_ansi(sc->cv, efg, ebg); } \ No newline at end of file diff --git a/neercs/old/attach.c b/neercs/old/attach.c index f0d51d8..19e3375 100644 --- a/neercs/old/attach.c +++ b/neercs/old/attach.c @@ -1,431 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 && defined HAVE_GLOB_H - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "neercs.h" - -char *build_socket_path(char *socket_dir, char *session_name, - enum socket_type socktype) -{ - char *path, *dir; - path = (char *)malloc(PATH_MAX + 1); - dir = socket_dir; - if (!dir) - dir = getenv("NEERCSDIR"); - if (!dir) - dir = getenv("TMPDIR"); - if (!dir) - dir = "/tmp"; - if (path) - snprintf(path, PATH_MAX + 1, "%s/neercs.%s%s.sock", dir, session_name, - socktype ? "" : ".srv"); - return path; -} - -static char *socket_to_session(char const *sockpath) -{ - char *p, *s; - p = strrchr(sockpath, '/'); - if (!p) - { - debug("Invalid socket path %s", sockpath); - return NULL; - } - p += 8; /* skip neercs. */ - s = strdup(p); - p = strrchr(s, '.'); - *p = '\0'; /* drop .sock */ - p = strrchr(s, '.'); - *p = '\0'; /* drop .srv */ - p = strdup(s); - free(s); - return p; -} - -int create_socket(struct screen_list *screen_list, enum socket_type socktype) -{ - int sock; - struct sockaddr_un myaddr; - - sock = socket(AF_UNIX, SOCK_DGRAM, 0); - - if (sock < 0) - { - perror("create_socket:socket"); - return errno; - } - - memset(&myaddr, 0, sizeof(struct sockaddr_un)); - - myaddr.sun_family = AF_UNIX; - strncpy(myaddr.sun_path, screen_list->comm.socket_path[socktype], - sizeof(myaddr.sun_path) - 1); - - unlink(screen_list->comm.socket_path[socktype]); - - if (bind(sock, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_un)) < 0) - { - free(screen_list->comm.socket_path[socktype]); - screen_list->comm.socket_path[socktype] = NULL; - close(sock); - perror("create_socket:bind"); - return errno; - } - fcntl(sock, F_SETFL, O_NONBLOCK); - - debug("Listening on %s (%d)", screen_list->comm.socket_path[socktype], sock); - - screen_list->comm.socket[socktype] = sock; - - return 0; -} - -char **list_sockets(char *socket_dir, char *session_name) -{ - char *pattern, *dir; - glob_t globbuf; - - globbuf.gl_pathv = NULL; - - pattern = (char *)malloc(PATH_MAX + 1); - - dir = socket_dir; - if (!dir) - dir = getenv("NEERCSDIR"); - if (!dir) - dir = getenv("TMPDIR"); - if (!dir) - dir = "/tmp"; - - if (!pattern) - return globbuf.gl_pathv; - - if (session_name && strlen(session_name) + strlen(dir) + 13 < PATH_MAX) - sprintf(pattern, "%s/neercs.%s.srv.sock", dir, session_name); - else - snprintf(pattern, PATH_MAX, "%s/neercs.*.srv.sock", dir); - pattern[PATH_MAX] = '\0'; - - debug("Looking for sockets in the form %s", pattern); - - glob(pattern, 0, NULL, &globbuf); - - free(pattern); - - return globbuf.gl_pathv; -} - -char *connect_socket(struct screen_list *screen_list, - enum socket_type socktype) -{ - int sock; - struct sockaddr_un addr; - - debug("Connecting to %s", screen_list->comm.socket_path[socktype]); - - /* Open the socket */ - if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) - { - debug("Failed to create socket\n"); - perror("connect_server:socket"); - return NULL; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, screen_list->comm.socket_path[socktype]); - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) - { - debug("Failed to connect to %s: %s", - screen_list->comm.socket_path[socktype], strerror(errno)); - close(sock); - return NULL; - } - fcntl(sock, F_SETFL, O_NONBLOCK); - - screen_list->comm.socket[socktype] = sock; - - if (socktype == SOCK_SERVER) - { - return socket_to_session(screen_list->comm.socket_path[socktype]); - } - else - return NULL; -} - -int request_attach(struct screen_list *screen_list) -{ - char buf[41]; - int bytes; - - bytes = snprintf(buf, sizeof(buf) - 1, "ATTACH %10d %10d %10d", - caca_get_canvas_width(screen_list->cv), - caca_get_canvas_height(screen_list->cv), - screen_list->delay); - buf[bytes] = '\0'; - debug("Requesting attach: %s", buf); - return write(screen_list->comm.socket[SOCK_SERVER], buf, strlen(buf)) <= 0; -} - -static char *select_socket(struct screen_list *screen_list) -{ - char **sockets = NULL, **usable_sockets = NULL; - int i, sock, nb_usable_sockets = 0; - char *ret = NULL; - - sockets = list_sockets(screen_list->comm.socket_dir, screen_list->comm.session_name); - if (sockets) - { - for (i = 0; sockets[i]; i++); - - /* Return the socket or NULL if there is not more than one match */ - if (i <= 1) - { - if (sockets[0]) - ret = strdup(sockets[0]); - goto end; - } - - /* Else ask the user to chose one */ - usable_sockets = malloc(i * sizeof(char *)); - for (i = 0; sockets[i]; i++) - { - struct sockaddr_un addr; - if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) - { - perror("select_socket:socket"); - goto end; - } - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, sockets[i]); - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) - { - switch (errno) - { - case EACCES: - debug("Connection refused on %s", sockets[i]); - break; - case ECONNREFUSED: - fprintf(stderr, "%s is dead, removing\n", sockets[i]); - unlink(sockets[i]); - break; - default: - fprintf(stderr, "Unknown error on %s:%s\n", sockets[i], - strerror(errno)); - } - } - else - { - usable_sockets[nb_usable_sockets] = strdup(sockets[i]); - debug("%s is usable", usable_sockets[nb_usable_sockets]); - nb_usable_sockets++; - close(sock); - } - } - if (!nb_usable_sockets) - goto end; - if (nb_usable_sockets == 1) - { - ret = strdup(usable_sockets[0]); - goto end; - } - else - { - caca_event_t ev; - enum caca_event_type t; - int current_line = 1; - int refresh = 1; - screen_list->cv = caca_create_canvas(0, 0); - screen_list->dp = caca_create_display(screen_list->cv); - if (!screen_list->dp) - goto end; - caca_set_cursor(screen_list->dp, 0); - caca_set_display_title(screen_list->dp, PACKAGE_STRING); - while (1) - { - if (refresh) - { - caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); - caca_fill_box(screen_list->cv, - 0, 0, - caca_get_canvas_width(screen_list->cv), - caca_get_canvas_height(screen_list->cv), - '#'); - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, - CACA_BLUE); - caca_draw_cp437_box(screen_list->cv, 0, 0, - caca_get_canvas_width(screen_list->cv), - caca_get_canvas_height(screen_list-> - cv)); - caca_printf(screen_list->cv, 2, 2, - "Please select a session to reconnect:"); - for (i = 0; i < nb_usable_sockets; i++) - { - if (i == current_line - 1) - { - caca_set_attr(screen_list->cv, CACA_BOLD); - caca_set_color_ansi(screen_list->cv, CACA_GREEN, - CACA_BLUE); - caca_put_char(screen_list->cv, 1, i + 3, '>'); - } - else - { - caca_set_attr(screen_list->cv, 0); - caca_set_color_ansi(screen_list->cv, - CACA_LIGHTGRAY, CACA_BLUE); - caca_put_char(screen_list->cv, 1, i + 3, ' '); - } - caca_printf(screen_list->cv, - 3, i + 3, - "%s", - socket_to_session(usable_sockets[i])); - } - caca_refresh_display(screen_list->dp); - refresh = 0; - } - - if (!caca_get_event(screen_list->dp, - CACA_EVENT_KEY_PRESS - | CACA_EVENT_RESIZE - | CACA_EVENT_QUIT, &ev, 10000)) - continue; - - t = caca_get_event_type(&ev); - - if (t & CACA_EVENT_KEY_PRESS) - { - unsigned int c = caca_get_event_key_ch(&ev); - switch (c) - { - case CACA_KEY_UP: - if (current_line > 1) - current_line--; - break; - case CACA_KEY_DOWN: - if (current_line < nb_usable_sockets) - current_line++; - break; - case CACA_KEY_RETURN: - ret = strdup(usable_sockets[current_line - 1]); - goto end; - break; - case CACA_KEY_ESCAPE: - goto end; - break; - default: - break; - } - refresh = 1; - } - else if (t & CACA_EVENT_RESIZE) - { - refresh = 1; - } - else if (t & CACA_EVENT_QUIT) - goto end; - } - } - } - - end: - if (sockets) - { - for (i = 0; sockets[i]; i++) - free(sockets[i]); - free(sockets); - } - if (usable_sockets) - { - for (i = 0; i < nb_usable_sockets; i++) - free(usable_sockets[i]); - free(usable_sockets); - } - if (screen_list->dp) - { - caca_free_display(screen_list->dp); - screen_list->dp = NULL; - } - if (screen_list->cv) - { - caca_free_canvas(screen_list->cv); - screen_list->cv = NULL; - } - return ret; -} - -void attach(struct screen_list *screen_list) -{ - screen_list->comm.socket_path[SOCK_SERVER] = select_socket(screen_list); - - if (screen_list->comm.socket_path[SOCK_SERVER]) - { - char *session; - session = connect_socket(screen_list, SOCK_SERVER); - if (session) - { - debug("Connected to session %s", session); - /* Create main canvas and associated caca window */ - screen_list->cv = caca_create_canvas(0, 0); - screen_list->dp = caca_create_display(screen_list->cv); - if (!screen_list->dp) - return; - caca_set_display_time(screen_list->dp, screen_list->delay * 1000); - caca_set_cursor(screen_list->dp, 1); - - screen_list->comm.socket_path[SOCK_CLIENT] = - build_socket_path(screen_list->comm.socket_dir, session, - SOCK_CLIENT); - create_socket(screen_list, SOCK_CLIENT); - request_attach(screen_list); - if (screen_list->comm.session_name) - free(screen_list->comm.session_name); - screen_list->comm.session_name = session; - } - else - { - fprintf(stderr, "Failed to attach!\n"); - free(screen_list->comm.socket_path[SOCK_SERVER]); - screen_list->comm.socket_path[SOCK_SERVER] = NULL; - screen_list->sys.attach = 0; - } - } - else - { - fprintf(stderr, "No socket found!\n"); - screen_list->sys.attach = 0; - } -} - -#endif +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 && defined HAVE_GLOB_H #include #include #include #include #include #include #include #include #include #include #include #include #include "neercs.h" char *build_socket_path(char *socket_dir, char *session_name, enum socket_type socktype) { char *path, *dir; path = (char *)malloc(PATH_MAX + 1); dir = socket_dir; if (!dir) dir = getenv("NEERCSDIR"); if (!dir) dir = getenv("TMPDIR"); if (!dir) dir = "/tmp"; if (path) snprintf(path, PATH_MAX + 1, "%s/neercs.%s%s.sock", dir, session_name, socktype ? "" : ".srv"); return path; } static char *socket_to_session(char const *sockpath) { char *p, *s; p = strrchr(sockpath, '/'); if (!p) { debug("Invalid socket path %s", sockpath); return NULL; } p += 8; /* skip neercs. */ s = strdup(p); p = strrchr(s, '.'); *p = '\0'; /* drop .sock */ p = strrchr(s, '.'); *p = '\0'; /* drop .srv */ p = strdup(s); free(s); return p; } int create_socket(struct screen_list *screen_list, enum socket_type socktype) { int sock; struct sockaddr_un myaddr; sock = socket(AF_UNIX, SOCK_DGRAM, 0); if (sock < 0) { perror("create_socket:socket"); return errno; } memset(&myaddr, 0, sizeof(struct sockaddr_un)); myaddr.sun_family = AF_UNIX; strncpy(myaddr.sun_path, screen_list->comm.socket_path[socktype], sizeof(myaddr.sun_path) - 1); unlink(screen_list->comm.socket_path[socktype]); if (bind(sock, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_un)) < 0) { free(screen_list->comm.socket_path[socktype]); screen_list->comm.socket_path[socktype] = NULL; close(sock); perror("create_socket:bind"); return errno; } fcntl(sock, F_SETFL, O_NONBLOCK); debug("Listening on %s (%d)", screen_list->comm.socket_path[socktype], sock); screen_list->comm.socket[socktype] = sock; return 0; } char **list_sockets(char *socket_dir, char *session_name) { char *pattern, *dir; glob_t globbuf; globbuf.gl_pathv = NULL; pattern = (char *)malloc(PATH_MAX + 1); dir = socket_dir; if (!dir) dir = getenv("NEERCSDIR"); if (!dir) dir = getenv("TMPDIR"); if (!dir) dir = "/tmp"; if (!pattern) return globbuf.gl_pathv; if (session_name && strlen(session_name) + strlen(dir) + 13 < PATH_MAX) sprintf(pattern, "%s/neercs.%s.srv.sock", dir, session_name); else snprintf(pattern, PATH_MAX, "%s/neercs.*.srv.sock", dir); pattern[PATH_MAX] = '\0'; debug("Looking for sockets in the form %s", pattern); glob(pattern, 0, NULL, &globbuf); free(pattern); return globbuf.gl_pathv; } char *connect_socket(struct screen_list *screen_list, enum socket_type socktype) { int sock; struct sockaddr_un addr; debug("Connecting to %s", screen_list->comm.socket_path[socktype]); /* Open the socket */ if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { debug("Failed to create socket\n"); perror("connect_server:socket"); return NULL; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, screen_list->comm.socket_path[socktype]); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { debug("Failed to connect to %s: %s", screen_list->comm.socket_path[socktype], strerror(errno)); close(sock); return NULL; } fcntl(sock, F_SETFL, O_NONBLOCK); screen_list->comm.socket[socktype] = sock; if (socktype == SOCK_SERVER) { return socket_to_session(screen_list->comm.socket_path[socktype]); } else return NULL; } int request_attach(struct screen_list *screen_list) { char buf[41]; int bytes; bytes = snprintf(buf, sizeof(buf) - 1, "ATTACH %10d %10d %10d", caca_get_canvas_width(screen_list->cv), caca_get_canvas_height(screen_list->cv), screen_list->delay); buf[bytes] = '\0'; debug("Requesting attach: %s", buf); return write(screen_list->comm.socket[SOCK_SERVER], buf, strlen(buf)) <= 0; } static char *select_socket(struct screen_list *screen_list) { char **sockets = NULL, **usable_sockets = NULL; int i, sock, nb_usable_sockets = 0; char *ret = NULL; sockets = list_sockets(screen_list->comm.socket_dir, screen_list->comm.session_name); if (sockets) { for (i = 0; sockets[i]; i++); /* Return the socket or NULL if there is not more than one match */ if (i <= 1) { if (sockets[0]) ret = strdup(sockets[0]); goto end; } /* Else ask the user to chose one */ usable_sockets = malloc(i * sizeof(char *)); for (i = 0; sockets[i]; i++) { struct sockaddr_un addr; if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { perror("select_socket:socket"); goto end; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, sockets[i]); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { switch (errno) { case EACCES: debug("Connection refused on %s", sockets[i]); break; case ECONNREFUSED: fprintf(stderr, "%s is dead, removing\n", sockets[i]); unlink(sockets[i]); break; default: fprintf(stderr, "Unknown error on %s:%s\n", sockets[i], strerror(errno)); } } else { usable_sockets[nb_usable_sockets] = strdup(sockets[i]); debug("%s is usable", usable_sockets[nb_usable_sockets]); nb_usable_sockets++; close(sock); } } if (!nb_usable_sockets) goto end; if (nb_usable_sockets == 1) { ret = strdup(usable_sockets[0]); goto end; } else { caca_event_t ev; enum caca_event_type t; int current_line = 1; int refresh = 1; screen_list->cv = caca_create_canvas(0, 0); screen_list->dp = caca_create_display(screen_list->cv); if (!screen_list->dp) goto end; caca_set_cursor(screen_list->dp, 0); caca_set_display_title(screen_list->dp, PACKAGE_STRING); while (1) { if (refresh) { caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); caca_fill_box(screen_list->cv, 0, 0, caca_get_canvas_width(screen_list->cv), caca_get_canvas_height(screen_list->cv), '#'); caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); caca_draw_cp437_box(screen_list->cv, 0, 0, caca_get_canvas_width(screen_list->cv), caca_get_canvas_height(screen_list-> cv)); caca_printf(screen_list->cv, 2, 2, "Please select a session to reconnect:"); for (i = 0; i < nb_usable_sockets; i++) { if (i == current_line - 1) { caca_set_attr(screen_list->cv, CACA_BOLD); caca_set_color_ansi(screen_list->cv, CACA_GREEN, CACA_BLUE); caca_put_char(screen_list->cv, 1, i + 3, '>'); } else { caca_set_attr(screen_list->cv, 0); caca_set_color_ansi(screen_list->cv, CACA_LIGHTGRAY, CACA_BLUE); caca_put_char(screen_list->cv, 1, i + 3, ' '); } caca_printf(screen_list->cv, 3, i + 3, "%s", socket_to_session(usable_sockets[i])); } caca_refresh_display(screen_list->dp); refresh = 0; } if (!caca_get_event(screen_list->dp, CACA_EVENT_KEY_PRESS | CACA_EVENT_RESIZE | CACA_EVENT_QUIT, &ev, 10000)) continue; t = caca_get_event_type(&ev); if (t & CACA_EVENT_KEY_PRESS) { unsigned int c = caca_get_event_key_ch(&ev); switch (c) { case CACA_KEY_UP: if (current_line > 1) current_line--; break; case CACA_KEY_DOWN: if (current_line < nb_usable_sockets) current_line++; break; case CACA_KEY_RETURN: ret = strdup(usable_sockets[current_line - 1]); goto end; break; case CACA_KEY_ESCAPE: goto end; break; default: break; } refresh = 1; } else if (t & CACA_EVENT_RESIZE) { refresh = 1; } else if (t & CACA_EVENT_QUIT) goto end; } } } end: if (sockets) { for (i = 0; sockets[i]; i++) free(sockets[i]); free(sockets); } if (usable_sockets) { for (i = 0; i < nb_usable_sockets; i++) free(usable_sockets[i]); free(usable_sockets); } if (screen_list->dp) { caca_free_display(screen_list->dp); screen_list->dp = NULL; } if (screen_list->cv) { caca_free_canvas(screen_list->cv); screen_list->cv = NULL; } return ret; } void attach(struct screen_list *screen_list) { screen_list->comm.socket_path[SOCK_SERVER] = select_socket(screen_list); if (screen_list->comm.socket_path[SOCK_SERVER]) { char *session; session = connect_socket(screen_list, SOCK_SERVER); if (session) { debug("Connected to session %s", session); /* Create main canvas and associated caca window */ screen_list->cv = caca_create_canvas(0, 0); screen_list->dp = caca_create_display(screen_list->cv); if (!screen_list->dp) return; caca_set_display_time(screen_list->dp, screen_list->delay * 1000); caca_set_cursor(screen_list->dp, 1); screen_list->comm.socket_path[SOCK_CLIENT] = build_socket_path(screen_list->comm.socket_dir, session, SOCK_CLIENT); create_socket(screen_list, SOCK_CLIENT); request_attach(screen_list); if (screen_list->comm.session_name) free(screen_list->comm.session_name); screen_list->comm.session_name = session; } else { fprintf(stderr, "Failed to attach!\n"); free(screen_list->comm.socket_path[SOCK_SERVER]); screen_list->comm.socket_path[SOCK_SERVER] = NULL; screen_list->sys.attach = 0; } } else { fprintf(stderr, "No socket found!\n"); screen_list->sys.attach = 0; } } #endif \ No newline at end of file diff --git a/neercs/old/client.c b/neercs/old/client.c index 5cf5250..9d5a0c7 100644 --- a/neercs/old/client.c +++ b/neercs/old/client.c @@ -1,294 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2011 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "neercs.h" - -#define NEERCS_RECV_BUFSIZE 128*1024 - - -int start_client(struct screen_list *screen_list) -{ - char *sess = NULL; - create_socket(screen_list, SOCK_CLIENT); - while ((sess = connect_socket(screen_list, SOCK_SERVER)) == NULL) - usleep(100); - free(sess); - - /* Create main canvas and associated caca window */ - screen_list->cv = caca_create_canvas(0, 0); - screen_list->dp = caca_create_display(screen_list->cv); - screen_list->mouse_button = 0; - - if (!screen_list->dp) - return -3; - - caca_set_display_time(screen_list->dp, screen_list->delay * 1000); - caca_set_cursor(screen_list->dp, 1); - - request_attach(screen_list); - - return 0; -} - -int send_event(caca_event_t ev, struct screen_list *screen_list) -{ - enum caca_event_type t; - char buf[64]; - int bytes = 0; - - t = caca_get_event_type(&ev); - - if (t & CACA_EVENT_KEY_PRESS) - { - bytes = snprintf(buf, sizeof(buf) - 1, "KEY %d", - caca_get_event_key_ch(&ev)); - debug("Sending key press to server: %s", buf); - } - else if (t & CACA_EVENT_RESIZE) - { - bytes = snprintf(buf, sizeof(buf) - 1, "RESIZE %10d %10d", - caca_get_event_resize_width(&ev), - caca_get_event_resize_height(&ev)); - } - else if (t & CACA_EVENT_MOUSE_PRESS) - { - screen_list->mouse_button = caca_get_event_mouse_button(&ev); - bytes = snprintf(buf, sizeof(buf) - 1, "MOUSEP %10d %10d %10d", - caca_get_mouse_x(screen_list->dp), - caca_get_mouse_y(screen_list->dp), - screen_list->mouse_button); - } - else if (t & CACA_EVENT_MOUSE_RELEASE) - { - bytes = snprintf(buf, sizeof(buf) - 1, "MOUSER %10d %10d %10d", - caca_get_mouse_x(screen_list->dp), - caca_get_mouse_y(screen_list->dp), - screen_list->mouse_button); - screen_list->mouse_button = 0; - } - else if (t & CACA_EVENT_MOUSE_MOTION) - { - int x = caca_get_mouse_x(screen_list->dp); - int y = caca_get_mouse_y(screen_list->dp); - int b = screen_list->mouse_button; - debug("Mouse motion, button %d", b); - if (x != screen_list->old_x || y != screen_list->old_y) - { - screen_list->old_x = caca_get_mouse_x(screen_list->dp); - screen_list->old_y = caca_get_mouse_y(screen_list->dp); - - bytes = snprintf(buf, sizeof(buf) - 1, "MOUSEM %10d %10d %10d", - caca_get_mouse_x(screen_list->dp), - caca_get_mouse_y(screen_list->dp), - b>=0?b:0); - } - } - else if (t & CACA_EVENT_QUIT) - { - bytes = snprintf(buf, sizeof(buf) - 1, "QUIT"); - } - if (bytes) - { - ssize_t r; - buf[bytes] = '\0'; - debug("Sending '%s', %d bytes", buf, bytes); - r = write(screen_list->comm.socket[SOCK_SERVER], buf, bytes+1); - while (r < 0 && errno == EAGAIN) - { - usleep(20); - r = write(screen_list->comm.socket[SOCK_SERVER], buf, bytes+1); - } - return r < 0; - } - return 0; -} - -int send_delay(struct screen_list *screen_list) -{ - debug("Sending DELAY\n"); - char buf[18]; - int bytes; - bytes = snprintf(buf, sizeof(buf) - 1, "DELAY %10d", screen_list->delay); - buf[bytes] = '\0'; - return write(screen_list->comm.socket[SOCK_SERVER], buf, strlen(buf)) <= 0; -} - -/** \brief Main client loop. - * - * This is the main client loop. - * - * Repeat forever: - * - if data is available on the client socket, read it and interpret it: - * - "DETACH": exit the loop - * - "UPDATE": update screen with the given canvas data - * - "REFRESH": refresh the whole display - * - "CURSOR": set cursor position - * - "TITLE": set window or display title - * - wait for an input event with a 10ms timeout - */ -int mainloop_tick(char **pbuf, struct screen_list *screen_list) -{ - caca_event_t ev; - int ret = 0; - ssize_t n; - if (!screen_list) - return 0; - if (!*pbuf) - *pbuf = malloc(NEERCS_RECV_BUFSIZE); - if (!*pbuf) - { - debug("Failed to allocate memory"); - return 0; - } - if (screen_list->comm.socket[SOCK_CLIENT] - && (n = - read(screen_list->comm.socket[SOCK_CLIENT], *pbuf, - NEERCS_RECV_BUFSIZE - 1)) > 0) - { - (*pbuf)[n] = 0; - debug("Received from server: '%s' (%d bytes)", *pbuf, n); - if (!strncmp("DETACH", *pbuf, 6)) - { - /* ret = 1; Not used */ - return 1; - } - else if (!strncmp("UPDATE ", *pbuf, 7)) - { - int x, y; - ssize_t l2 = 0, lb = 0; - char *buf2; - size_t l = 0; - /* FIXME check the length before calling atoi */ - x = atoi(*pbuf + 8); - y = atoi(*pbuf + 19); - - /* 0 means we have valid data but incomplete, so read the rest - */ - while (l == 0) - { - buf2 = realloc(*pbuf, l2 + NEERCS_RECV_BUFSIZE); - if (!buf2) - { - debug("Failed to allocate memory"); - return 0; - } - *pbuf = buf2; - fcntl(screen_list->comm.socket[SOCK_CLIENT], F_SETFL, 0); - lb = read(screen_list->comm.socket[SOCK_CLIENT], *pbuf + l2, - NEERCS_RECV_BUFSIZE - 1); - if (lb < 0) - { - debug - ("Failed to read the end of the refresh message (%s)", - strerror(errno)); - l = -1; - } - else - { - l2 += lb; - l = caca_import_area_from_memory(screen_list->cv, x, y, - *pbuf, l2, "caca"); - } - } - fcntl(screen_list->comm.socket[SOCK_CLIENT], F_SETFL, - O_NONBLOCK); - } - else if (!strncmp("REFRESH ", *pbuf, 8)) - { - int dt, x, y; - /* FIXME check the length before calling atoi */ - x = atoi(*pbuf + 8); - y = atoi(*pbuf + 19); - caca_gotoxy(screen_list->cv, x, y); - caca_refresh_display(screen_list->dp); - dt = caca_get_display_time(screen_list->dp); - - /* Adjust refresh delay so that the server do not compute - useless things */ - if (dt > 2 * 1000 * screen_list->delay - && screen_list->delay <= 100) - { - screen_list->delay *= 2; - send_delay(screen_list); - } - else if (dt < screen_list->delay * 1000 * 1.2 && - screen_list->delay >= - 3 * screen_list->requested_delay / 2) - { - screen_list->delay = 2 * screen_list->delay / 3; - send_delay(screen_list); - } - screen_list->comm.attached = 1; - } - else if (!strncmp("CURSOR ", *pbuf, 7)) - { - caca_set_cursor(screen_list->dp, atoi(*pbuf + 7)); - } - else if (!strncmp("TITLE ", *pbuf, 6)) - { - caca_set_display_title(screen_list->dp, *pbuf + 6); - caca_refresh_display(screen_list->dp); - } - else - { - debug("Unknown message received from server: %s", *pbuf); - } - } - - /* Wait to have finished attaching before handling events */ - if (screen_list->comm.attached) - { - ret = caca_get_event(screen_list->dp, - CACA_EVENT_KEY_PRESS - | CACA_EVENT_MOUSE_PRESS - | CACA_EVENT_MOUSE_RELEASE - | CACA_EVENT_MOUSE_MOTION - | CACA_EVENT_RESIZE - | CACA_EVENT_QUIT, &ev, 10000); - if (ret) - ret = send_event(ev, screen_list); - if (ret) - { - debug("Failed send event, quitting: %s\n", strerror(errno)); - return 1; - } - } - - return 1; -} - -#endif - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2011 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "neercs.h" #define NEERCS_RECV_BUFSIZE 128*1024 int start_client(struct screen_list *screen_list) { char *sess = NULL; create_socket(screen_list, SOCK_CLIENT); while ((sess = connect_socket(screen_list, SOCK_SERVER)) == NULL) usleep(100); free(sess); /* Create main canvas and associated caca window */ screen_list->cv = caca_create_canvas(0, 0); screen_list->dp = caca_create_display(screen_list->cv); screen_list->mouse_button = 0; if (!screen_list->dp) return -3; caca_set_display_time(screen_list->dp, screen_list->delay * 1000); caca_set_cursor(screen_list->dp, 1); request_attach(screen_list); return 0; } int send_event(caca_event_t ev, struct screen_list *screen_list) { enum caca_event_type t; char buf[64]; int bytes = 0; t = caca_get_event_type(&ev); if (t & CACA_EVENT_KEY_PRESS) { bytes = snprintf(buf, sizeof(buf) - 1, "KEY %d", caca_get_event_key_ch(&ev)); debug("Sending key press to server: %s", buf); } else if (t & CACA_EVENT_RESIZE) { bytes = snprintf(buf, sizeof(buf) - 1, "RESIZE %10d %10d", caca_get_event_resize_width(&ev), caca_get_event_resize_height(&ev)); } else if (t & CACA_EVENT_MOUSE_PRESS) { screen_list->mouse_button = caca_get_event_mouse_button(&ev); bytes = snprintf(buf, sizeof(buf) - 1, "MOUSEP %10d %10d %10d", caca_get_mouse_x(screen_list->dp), caca_get_mouse_y(screen_list->dp), screen_list->mouse_button); } else if (t & CACA_EVENT_MOUSE_RELEASE) { bytes = snprintf(buf, sizeof(buf) - 1, "MOUSER %10d %10d %10d", caca_get_mouse_x(screen_list->dp), caca_get_mouse_y(screen_list->dp), screen_list->mouse_button); screen_list->mouse_button = 0; } else if (t & CACA_EVENT_MOUSE_MOTION) { int x = caca_get_mouse_x(screen_list->dp); int y = caca_get_mouse_y(screen_list->dp); int b = screen_list->mouse_button; debug("Mouse motion, button %d", b); if (x != screen_list->old_x || y != screen_list->old_y) { screen_list->old_x = caca_get_mouse_x(screen_list->dp); screen_list->old_y = caca_get_mouse_y(screen_list->dp); bytes = snprintf(buf, sizeof(buf) - 1, "MOUSEM %10d %10d %10d", caca_get_mouse_x(screen_list->dp), caca_get_mouse_y(screen_list->dp), b>=0?b:0); } } else if (t & CACA_EVENT_QUIT) { bytes = snprintf(buf, sizeof(buf) - 1, "QUIT"); } if (bytes) { ssize_t r; buf[bytes] = '\0'; debug("Sending '%s', %d bytes", buf, bytes); r = write(screen_list->comm.socket[SOCK_SERVER], buf, bytes+1); while (r < 0 && errno == EAGAIN) { usleep(20); r = write(screen_list->comm.socket[SOCK_SERVER], buf, bytes+1); } return r < 0; } return 0; } int send_delay(struct screen_list *screen_list) { debug("Sending DELAY\n"); char buf[18]; int bytes; bytes = snprintf(buf, sizeof(buf) - 1, "DELAY %10d", screen_list->delay); buf[bytes] = '\0'; return write(screen_list->comm.socket[SOCK_SERVER], buf, strlen(buf)) <= 0; } /** \brief Main client loop. * * This is the main client loop. * * Repeat forever: * - if data is available on the client socket, read it and interpret it: * - "DETACH": exit the loop * - "UPDATE": update screen with the given canvas data * - "REFRESH": refresh the whole display * - "CURSOR": set cursor position * - "TITLE": set window or display title * - wait for an input event with a 10ms timeout */ int mainloop_tick(char **pbuf, struct screen_list *screen_list) { caca_event_t ev; int ret = 0; ssize_t n; if (!screen_list) return 0; if (!*pbuf) *pbuf = malloc(NEERCS_RECV_BUFSIZE); if (!*pbuf) { debug("Failed to allocate memory"); return 0; } if (screen_list->comm.socket[SOCK_CLIENT] && (n = read(screen_list->comm.socket[SOCK_CLIENT], *pbuf, NEERCS_RECV_BUFSIZE - 1)) > 0) { (*pbuf)[n] = 0; debug("Received from server: '%s' (%d bytes)", *pbuf, n); if (!strncmp("DETACH", *pbuf, 6)) { /* ret = 1; Not used */ return 1; } else if (!strncmp("UPDATE ", *pbuf, 7)) { int x, y; ssize_t l2 = 0, lb = 0; char *buf2; size_t l = 0; /* FIXME check the length before calling atoi */ x = atoi(*pbuf + 8); y = atoi(*pbuf + 19); /* 0 means we have valid data but incomplete, so read the rest */ while (l == 0) { buf2 = realloc(*pbuf, l2 + NEERCS_RECV_BUFSIZE); if (!buf2) { debug("Failed to allocate memory"); return 0; } *pbuf = buf2; fcntl(screen_list->comm.socket[SOCK_CLIENT], F_SETFL, 0); lb = read(screen_list->comm.socket[SOCK_CLIENT], *pbuf + l2, NEERCS_RECV_BUFSIZE - 1); if (lb < 0) { debug ("Failed to read the end of the refresh message (%s)", strerror(errno)); l = -1; } else { l2 += lb; l = caca_import_area_from_memory(screen_list->cv, x, y, *pbuf, l2, "caca"); } } fcntl(screen_list->comm.socket[SOCK_CLIENT], F_SETFL, O_NONBLOCK); } else if (!strncmp("REFRESH ", *pbuf, 8)) { int dt, x, y; /* FIXME check the length before calling atoi */ x = atoi(*pbuf + 8); y = atoi(*pbuf + 19); caca_gotoxy(screen_list->cv, x, y); caca_refresh_display(screen_list->dp); dt = caca_get_display_time(screen_list->dp); /* Adjust refresh delay so that the server do not compute useless things */ if (dt > 2 * 1000 * screen_list->delay && screen_list->delay <= 100) { screen_list->delay *= 2; send_delay(screen_list); } else if (dt < screen_list->delay * 1000 * 1.2 && screen_list->delay >= 3 * screen_list->requested_delay / 2) { screen_list->delay = 2 * screen_list->delay / 3; send_delay(screen_list); } screen_list->comm.attached = 1; } else if (!strncmp("CURSOR ", *pbuf, 7)) { caca_set_cursor(screen_list->dp, atoi(*pbuf + 7)); } else if (!strncmp("TITLE ", *pbuf, 6)) { caca_set_display_title(screen_list->dp, *pbuf + 6); caca_refresh_display(screen_list->dp); } else { debug("Unknown message received from server: %s", *pbuf); } } /* Wait to have finished attaching before handling events */ if (screen_list->comm.attached) { ret = caca_get_event(screen_list->dp, CACA_EVENT_KEY_PRESS | CACA_EVENT_MOUSE_PRESS | CACA_EVENT_MOUSE_RELEASE | CACA_EVENT_MOUSE_MOTION | CACA_EVENT_RESIZE | CACA_EVENT_QUIT, &ev, 10000); if (ret) ret = send_event(ev, screen_list); if (ret) { debug("Failed send event, quitting: %s\n", strerror(errno)); return 1; } } return 1; } #endif \ No newline at end of file diff --git a/neercs/old/configuration.c b/neercs/old/configuration.c index 1bea7c8..17a746b 100644 --- a/neercs/old/configuration.c +++ b/neercs/old/configuration.c @@ -1,577 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "neercs.h" - - -struct config_line *get_config(const char *name); -int set_window_manager(const char *argv, struct screen_list *screen_list); -int set_cube_duration(const char *argv, struct screen_list *screen_list); -int set_thumbnails(const char *argv, struct screen_list *screen_list); -int set_status_bar(const char *argv, struct screen_list *screen_list); -int set_screensaver_timeout(const char *argv, struct screen_list *screen_list); -int set_autolock_timeout(const char *argv, struct screen_list *screen_list); -int set_lock_on_detach(const char *argv, struct screen_list *screen_list); -int set_socket_dir(const char *argv, struct screen_list *screen_list); -int set_delay(const char *argv, struct screen_list *screen_list); -int set_eyecandy(const char *argv, struct screen_list *screen_list); -int set_border(const char *argv, struct screen_list *screen_list); -char *get_window_manager(struct screen_list *screen_list); -char *get_cube_duration(struct screen_list *screen_list); -char *get_thumbnails(struct screen_list *screen_list); -char *get_status_bar(struct screen_list *screen_list); -char *get_screensaver_timeout(struct screen_list *screen_list); -char *get_autolock_timeout(struct screen_list *screen_list); -char *get_lock_on_detach(struct screen_list *screen_list); -char *get_socket_dir(struct screen_list *screen_list); -char *get_delay(struct screen_list *screen_list); -char *get_eyecandy(struct screen_list *screen_list); -char *get_border(struct screen_list *screen_list); - -/* Options definition and associated function pointer */ -struct config_line config_option[] = { - {.name = "window_manager",.set = set_window_manager,.get = - get_window_manager}, - {.name = "eyecandy",.set = set_eyecandy,.get = get_eyecandy}, - {.name = "borders",.set = set_border,.get = get_border}, - {.name = "cube_duration",.set = set_cube_duration,.get = - get_cube_duration}, - {.name = "thumbnails",.set = set_thumbnails,.get = get_thumbnails}, - {.name = "status_bar",.set = set_status_bar,.get = get_status_bar}, - {.name = "screensaver_timeout",.set = set_screensaver_timeout,.get = - get_screensaver_timeout}, - {.name = "autolock_timeout",.set = set_autolock_timeout,.get = - get_autolock_timeout}, - {.name = "lock_on_detach",.set = set_lock_on_detach,.get = - get_lock_on_detach}, - {.name = "socket_dir",.set = set_socket_dir,.get = get_socket_dir}, - {.name = "delay",.set = set_delay,.get = get_delay}, - - {.name = "last",.set = NULL}, -}; - - - -int read_configuration_file(char *filename, struct screen_list *screen_list) -{ - FILE *fp; - struct stat st; - int size = 0, i = 0, total = 0, offset = 0, l = 1; - char *buffer = NULL; - - screen_list->config = NULL; - - /* Check if file exist */ - if (stat(filename, &st) < 0) - { - return -1; - } - /* Get its size */ - size = st.st_size; - if (!size) - { - fprintf(stderr, "File too short\n"); - return -1; - } - - /* Open it */ - fp = fopen(filename, "r"); - if (!fp) - { - return -1; - } - - buffer = malloc(size + 1); - if (!buffer) - { - fclose(fp); - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - return -1; - } - /* Read it */ - while ((i = fread(buffer + total, 1, size, fp)) > 0) - { - total += i; - } - buffer[total] = '\n'; - - fclose(fp); - - /* Parse it */ - while ((i = - parse_conf_line(buffer + offset, total - offset, screen_list)) > 0) - { - offset += i; - l++; - } - - free(buffer); - - /* Fill neercs configuration with it */ - fill_config(screen_list); - - return 1; -} - -struct config_line *get_config_option(void) -{ - return config_option; -} - -int parse_conf_line(char *buf, int size, struct screen_list *screen_list) -{ - int i, s = 0, c = 0; - char *line = NULL; - int l = 0; - int in_quote = 0, end_spaces = 0; - static struct option *prev = NULL; - - if (size <= 0) - return -1; - - /* Find EOL */ - for (i = 0; i < size; i++) - { - if (buf[i] == '\n') - { - s = i + 1; - break; - } - } - - /* Strip comments and trailing spaces */ - for (i = 0; i < s; i++) - { - if (buf[i] == ';' && !in_quote) - { - break; - } - else if (buf[i] == '\n') - { - break; - } - else if (buf[i] == ' ' && !c) - { - } - else - { - if (line == NULL) - { - line = malloc(2); - if (!line) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", - __FUNCTION__, __LINE__); - return -1; - } - } - else - { - line = realloc(line, l + 2); - if (!line) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", - __FUNCTION__, __LINE__); - return -1; - } - } - if (buf[i] == '"') - in_quote = !in_quote; - if (buf[i] == ' ') - end_spaces++; - else - end_spaces = 0; - - line[l] = buf[i]; - line[l + 1] = 0; - l++; - c = 1; - } - } - - if (c == 0) - { - /* This line is empty, do nothing */ - } - else - { - struct option *option = malloc(sizeof(struct option)); - if (!option) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", - __FUNCTION__, __LINE__); - return -1; - } - option->next = NULL; - l -= end_spaces; - line = realloc(line, l + 1); - line[l] = 0; - - get_key_value(line, option); - - if (!screen_list->config) - screen_list->config = option; - - if (prev) - prev->next = option; - - prev = option; - } - free(line); - return s; -} - -int get_key_value(char *line, struct option *option) -{ - unsigned int i, o = 0, b = 0, end_spaces = 0; - char *cur = NULL; - option->value = NULL; - option->key = NULL; - - /* Line is a section delimiter */ - if (line[0] == '[') - { - option->value = malloc(strlen(line) - 1); - if (!option->value) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", - __FUNCTION__, __LINE__); - return -1; - } - memcpy(option->value, line + 1, strlen(line) - 1); - option->value[strlen(line) - 2] = 0; - return 0; - } - - cur = malloc(1); - if (!cur) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", - __FUNCTION__, __LINE__); - return -1; - } - cur[0] = 0; - - for (i = 0; i < strlen(line); i++) - { - if (line[i] == ' ' && !b) - continue; - - - if (line[i] == '=') - { - b = 0; - cur[o - end_spaces] = 0; - cur = realloc(cur, (o - end_spaces) + 1); - if (!cur) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", - __FUNCTION__, __LINE__); - return -1; - } - o = 0; - option->key = cur; - cur = malloc(1); - } - else - { - if (line[i] == ' ') - end_spaces++; - else - end_spaces = 0; - - cur = realloc(cur, o + 2); - if (!cur) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", - __FUNCTION__, __LINE__); - return -1; - } - cur[o] = line[i]; - o++; - b = 1; - - } - } - cur[o] = 0; - option->value = cur; - return 0; -} - - - -struct config_line *get_config(const char *name) -{ - int i = 0; - - debug("Looking for '%s'\n", name); - - while (strncmp(config_option[i].name, "last", strlen("last"))) - { - debug("%d Testing against '%s'\n", i, config_option[i].name); - if (!strncmp(name, config_option[i].name, strlen(name))) - { - debug("Found\n"); - return &config_option[i]; - } - i++; - } - return NULL; -} - - - -int fill_config(struct screen_list *screen_list) -{ - int i = 0; - struct option *option = screen_list->config; - - while (option) - { - if (option->key == NULL) - { - option = option->next; - continue; - } - - struct config_line *c = get_config(option->key); - if (c) - { - c->set((const char *)option->value, screen_list); - } - option = option->next; - } - - return i; -} - - - -/* - * Options setters - */ - -#define IS_OPTION(t) (!strncmp(argv, t, strlen(argv))) -#define IS_OPTION_TRUE (IS_OPTION("true") || IS_OPTION("True") || IS_OPTION("1")) - -int set_window_manager(const char *argv, struct screen_list *screen_list) -{ - if (IS_OPTION("full")) - screen_list->wm_type = WM_FULL; - else if (IS_OPTION("hsplit")) - screen_list->wm_type = WM_HSPLIT; - else if (IS_OPTION("vsplit")) - screen_list->wm_type = WM_VSPLIT; - else if (IS_OPTION("card")) - screen_list->wm_type = WM_CARD; - else - { - fprintf(stderr, "Unknown window manager '%s'\n", argv); - return -1; - } - return 0; -} - -int set_cube_duration(const char *argv, struct screen_list *screen_list) -{ - screen_list->cube.duration = atoi(argv) * 1000000; - return 0; -} - -int set_thumbnails(const char *argv, struct screen_list *screen_list) -{ - if (IS_OPTION_TRUE) - screen_list->modals.mini = 1; - else - screen_list->modals.mini = 0; - return 0; - -} - -int set_status_bar(const char *argv, struct screen_list *screen_list) -{ - if (IS_OPTION_TRUE) - screen_list->modals.status = 1; - else - screen_list->modals.status = 0; - return 0; -} - -int set_screensaver_timeout(const char *argv, struct screen_list *screen_list) -{ - screen_list->screensaver.timeout = atoi(argv) * 1000000; - /* if timeout is 0, set it to 0xFFFFFFFFFFFFFFFF */ - if (!screen_list->screensaver.timeout) - screen_list->screensaver.timeout -= 1; - return 0; -} - -int set_autolock_timeout(const char *argv, struct screen_list *screen_list) -{ - if (screen_list->lock.autolock_timeout == 0 || - screen_list->lock.autolock_timeout == ((long long unsigned int)0) - 1) - { - screen_list->lock.autolock_timeout = atoi(argv) * 1000000; - /* if timeout is 0, set it to 0xFFFFFFFFFFFFFFFF */ - if (!screen_list->lock.autolock_timeout) - screen_list->lock.autolock_timeout -= 1; - } - return 0; -} - -int set_lock_on_detach(const char *argv, struct screen_list *screen_list) -{ - if (IS_OPTION_TRUE) - screen_list->lock.lock_on_detach = 1; - else - screen_list->lock.lock_on_detach = 0; - return 0; -} - -int set_eyecandy(const char *argv, struct screen_list *screen_list) -{ - if (IS_OPTION_TRUE) - screen_list->eyecandy = 1; - else - screen_list->eyecandy = 0; - return 0; -} - -int set_border(const char *argv, struct screen_list *screen_list) -{ - if (IS_OPTION_TRUE) - screen_list->border_size = 1; - else - screen_list->border_size = 0; - return 0; -} - -int set_socket_dir(const char *argv, struct screen_list *screen_list) -{ - screen_list->comm.socket_dir = strdup(argv); - return 0; -} - -int set_delay(const char *argv, struct screen_list *screen_list) -{ - screen_list->requested_delay = atoi(argv); - screen_list->delay = atoi(argv); - return 0; -} - -char *get_window_manager(struct screen_list *screen_list) -{ - debug("Window manager is %d", screen_list->wm_type); - switch (screen_list->wm_type) - { - case WM_FULL: - return "full"; - case WM_CARD: - return "card"; - case WM_VSPLIT: - return "vsplit"; - case WM_HSPLIT: - return "hsplit"; - default: - return "invalid window manager"; - } - return NULL; /* Not reached */ -} - -char *get_cube_duration(struct screen_list *screen_list) -{ - char *r = malloc(100); - sprintf(r, "%f", (float)screen_list->cube.duration / 1000000.0f); - return r; -} - -char *get_thumbnails(struct screen_list *screen_list) -{ - if (screen_list->modals.mini) - return "true"; - return "false"; -} - -char *get_status_bar(struct screen_list *screen_list) -{ - if (screen_list->modals.status) - return "true"; - return "false"; -} - -char *get_eyecandy(struct screen_list *screen_list) -{ - if (screen_list->eyecandy) - return "true"; - return "false"; -} - -char *get_border(struct screen_list *screen_list) -{ - if (screen_list->border_size) - return "true"; - return "false"; -} - -char *get_screensaver_timeout(struct screen_list *screen_list) -{ - char *r = malloc(100); - sprintf(r, "%f", (float)screen_list->screensaver.timeout / 1000000.0f); - return r; -} - -char *get_autolock_timeout(struct screen_list *screen_list) -{ - char *r = malloc(100); - sprintf(r, "%f", (float)screen_list->lock.autolock_timeout / 1000000.0f); - return r; -} - -char *get_lock_on_detach(struct screen_list *screen_list) -{ - if (screen_list->lock.lock_on_detach) - return "true"; - else - return "false"; -} - -char *get_socket_dir(struct screen_list *screen_list) -{ - return screen_list->comm.socket_dir; -} - -char *get_delay(struct screen_list *screen_list) -{ - char *r = malloc(100); - sprintf(r, "%d", screen_list->requested_delay); - return r; -} - -#endif - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include #include "neercs.h" struct config_line *get_config(const char *name); int set_window_manager(const char *argv, struct screen_list *screen_list); int set_cube_duration(const char *argv, struct screen_list *screen_list); int set_thumbnails(const char *argv, struct screen_list *screen_list); int set_status_bar(const char *argv, struct screen_list *screen_list); int set_screensaver_timeout(const char *argv, struct screen_list *screen_list); int set_autolock_timeout(const char *argv, struct screen_list *screen_list); int set_lock_on_detach(const char *argv, struct screen_list *screen_list); int set_socket_dir(const char *argv, struct screen_list *screen_list); int set_delay(const char *argv, struct screen_list *screen_list); int set_eyecandy(const char *argv, struct screen_list *screen_list); int set_border(const char *argv, struct screen_list *screen_list); char *get_window_manager(struct screen_list *screen_list); char *get_cube_duration(struct screen_list *screen_list); char *get_thumbnails(struct screen_list *screen_list); char *get_status_bar(struct screen_list *screen_list); char *get_screensaver_timeout(struct screen_list *screen_list); char *get_autolock_timeout(struct screen_list *screen_list); char *get_lock_on_detach(struct screen_list *screen_list); char *get_socket_dir(struct screen_list *screen_list); char *get_delay(struct screen_list *screen_list); char *get_eyecandy(struct screen_list *screen_list); char *get_border(struct screen_list *screen_list); /* Options definition and associated function pointer */ struct config_line config_option[] = { {.name = "window_manager",.set = set_window_manager,.get = get_window_manager}, {.name = "eyecandy",.set = set_eyecandy,.get = get_eyecandy}, {.name = "borders",.set = set_border,.get = get_border}, {.name = "cube_duration",.set = set_cube_duration,.get = get_cube_duration}, {.name = "thumbnails",.set = set_thumbnails,.get = get_thumbnails}, {.name = "status_bar",.set = set_status_bar,.get = get_status_bar}, {.name = "screensaver_timeout",.set = set_screensaver_timeout,.get = get_screensaver_timeout}, {.name = "autolock_timeout",.set = set_autolock_timeout,.get = get_autolock_timeout}, {.name = "lock_on_detach",.set = set_lock_on_detach,.get = get_lock_on_detach}, {.name = "socket_dir",.set = set_socket_dir,.get = get_socket_dir}, {.name = "delay",.set = set_delay,.get = get_delay}, {.name = "last",.set = NULL}, }; int read_configuration_file(char *filename, struct screen_list *screen_list) { FILE *fp; struct stat st; int size = 0, i = 0, total = 0, offset = 0, l = 1; char *buffer = NULL; screen_list->config = NULL; /* Check if file exist */ if (stat(filename, &st) < 0) { return -1; } /* Get its size */ size = st.st_size; if (!size) { fprintf(stderr, "File too short\n"); return -1; } /* Open it */ fp = fopen(filename, "r"); if (!fp) { return -1; } buffer = malloc(size + 1); if (!buffer) { fclose(fp); fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } /* Read it */ while ((i = fread(buffer + total, 1, size, fp)) > 0) { total += i; } buffer[total] = '\n'; fclose(fp); /* Parse it */ while ((i = parse_conf_line(buffer + offset, total - offset, screen_list)) > 0) { offset += i; l++; } free(buffer); /* Fill neercs configuration with it */ fill_config(screen_list); return 1; } struct config_line *get_config_option(void) { return config_option; } int parse_conf_line(char *buf, int size, struct screen_list *screen_list) { int i, s = 0, c = 0; char *line = NULL; int l = 0; int in_quote = 0, end_spaces = 0; static struct option *prev = NULL; if (size <= 0) return -1; /* Find EOL */ for (i = 0; i < size; i++) { if (buf[i] == '\n') { s = i + 1; break; } } /* Strip comments and trailing spaces */ for (i = 0; i < s; i++) { if (buf[i] == ';' && !in_quote) { break; } else if (buf[i] == '\n') { break; } else if (buf[i] == ' ' && !c) { } else { if (line == NULL) { line = malloc(2); if (!line) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } } else { line = realloc(line, l + 2); if (!line) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } } if (buf[i] == '"') in_quote = !in_quote; if (buf[i] == ' ') end_spaces++; else end_spaces = 0; line[l] = buf[i]; line[l + 1] = 0; l++; c = 1; } } if (c == 0) { /* This line is empty, do nothing */ } else { struct option *option = malloc(sizeof(struct option)); if (!option) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } option->next = NULL; l -= end_spaces; line = realloc(line, l + 1); line[l] = 0; get_key_value(line, option); if (!screen_list->config) screen_list->config = option; if (prev) prev->next = option; prev = option; } free(line); return s; } int get_key_value(char *line, struct option *option) { unsigned int i, o = 0, b = 0, end_spaces = 0; char *cur = NULL; option->value = NULL; option->key = NULL; /* Line is a section delimiter */ if (line[0] == '[') { option->value = malloc(strlen(line) - 1); if (!option->value) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } memcpy(option->value, line + 1, strlen(line) - 1); option->value[strlen(line) - 2] = 0; return 0; } cur = malloc(1); if (!cur) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } cur[0] = 0; for (i = 0; i < strlen(line); i++) { if (line[i] == ' ' && !b) continue; if (line[i] == '=') { b = 0; cur[o - end_spaces] = 0; cur = realloc(cur, (o - end_spaces) + 1); if (!cur) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } o = 0; option->key = cur; cur = malloc(1); } else { if (line[i] == ' ') end_spaces++; else end_spaces = 0; cur = realloc(cur, o + 2); if (!cur) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } cur[o] = line[i]; o++; b = 1; } } cur[o] = 0; option->value = cur; return 0; } struct config_line *get_config(const char *name) { int i = 0; debug("Looking for '%s'\n", name); while (strncmp(config_option[i].name, "last", strlen("last"))) { debug("%d Testing against '%s'\n", i, config_option[i].name); if (!strncmp(name, config_option[i].name, strlen(name))) { debug("Found\n"); return &config_option[i]; } i++; } return NULL; } int fill_config(struct screen_list *screen_list) { int i = 0; struct option *option = screen_list->config; while (option) { if (option->key == NULL) { option = option->next; continue; } struct config_line *c = get_config(option->key); if (c) { c->set((const char *)option->value, screen_list); } option = option->next; } return i; } /* * Options setters */ #define IS_OPTION(t) (!strncmp(argv, t, strlen(argv))) #define IS_OPTION_TRUE (IS_OPTION("true") || IS_OPTION("True") || IS_OPTION("1")) int set_window_manager(const char *argv, struct screen_list *screen_list) { if (IS_OPTION("full")) screen_list->wm_type = WM_FULL; else if (IS_OPTION("hsplit")) screen_list->wm_type = WM_HSPLIT; else if (IS_OPTION("vsplit")) screen_list->wm_type = WM_VSPLIT; else if (IS_OPTION("card")) screen_list->wm_type = WM_CARD; else { fprintf(stderr, "Unknown window manager '%s'\n", argv); return -1; } return 0; } int set_cube_duration(const char *argv, struct screen_list *screen_list) { screen_list->cube.duration = atoi(argv) * 1000000; return 0; } int set_thumbnails(const char *argv, struct screen_list *screen_list) { if (IS_OPTION_TRUE) screen_list->modals.mini = 1; else screen_list->modals.mini = 0; return 0; } int set_status_bar(const char *argv, struct screen_list *screen_list) { if (IS_OPTION_TRUE) screen_list->modals.status = 1; else screen_list->modals.status = 0; return 0; } int set_screensaver_timeout(const char *argv, struct screen_list *screen_list) { screen_list->screensaver.timeout = atoi(argv) * 1000000; /* if timeout is 0, set it to 0xFFFFFFFFFFFFFFFF */ if (!screen_list->screensaver.timeout) screen_list->screensaver.timeout -= 1; return 0; } int set_autolock_timeout(const char *argv, struct screen_list *screen_list) { if (screen_list->lock.autolock_timeout == 0 || screen_list->lock.autolock_timeout == ((long long unsigned int)0) - 1) { screen_list->lock.autolock_timeout = atoi(argv) * 1000000; /* if timeout is 0, set it to 0xFFFFFFFFFFFFFFFF */ if (!screen_list->lock.autolock_timeout) screen_list->lock.autolock_timeout -= 1; } return 0; } int set_lock_on_detach(const char *argv, struct screen_list *screen_list) { if (IS_OPTION_TRUE) screen_list->lock.lock_on_detach = 1; else screen_list->lock.lock_on_detach = 0; return 0; } int set_eyecandy(const char *argv, struct screen_list *screen_list) { if (IS_OPTION_TRUE) screen_list->eyecandy = 1; else screen_list->eyecandy = 0; return 0; } int set_border(const char *argv, struct screen_list *screen_list) { if (IS_OPTION_TRUE) screen_list->border_size = 1; else screen_list->border_size = 0; return 0; } int set_socket_dir(const char *argv, struct screen_list *screen_list) { screen_list->comm.socket_dir = strdup(argv); return 0; } int set_delay(const char *argv, struct screen_list *screen_list) { screen_list->requested_delay = atoi(argv); screen_list->delay = atoi(argv); return 0; } char *get_window_manager(struct screen_list *screen_list) { debug("Window manager is %d", screen_list->wm_type); switch (screen_list->wm_type) { case WM_FULL: return "full"; case WM_CARD: return "card"; case WM_VSPLIT: return "vsplit"; case WM_HSPLIT: return "hsplit"; default: return "invalid window manager"; } return NULL; /* Not reached */ } char *get_cube_duration(struct screen_list *screen_list) { char *r = malloc(100); sprintf(r, "%f", (float)screen_list->cube.duration / 1000000.0f); return r; } char *get_thumbnails(struct screen_list *screen_list) { if (screen_list->modals.mini) return "true"; return "false"; } char *get_status_bar(struct screen_list *screen_list) { if (screen_list->modals.status) return "true"; return "false"; } char *get_eyecandy(struct screen_list *screen_list) { if (screen_list->eyecandy) return "true"; return "false"; } char *get_border(struct screen_list *screen_list) { if (screen_list->border_size) return "true"; return "false"; } char *get_screensaver_timeout(struct screen_list *screen_list) { char *r = malloc(100); sprintf(r, "%f", (float)screen_list->screensaver.timeout / 1000000.0f); return r; } char *get_autolock_timeout(struct screen_list *screen_list) { char *r = malloc(100); sprintf(r, "%f", (float)screen_list->lock.autolock_timeout / 1000000.0f); return r; } char *get_lock_on_detach(struct screen_list *screen_list) { if (screen_list->lock.lock_on_detach) return "true"; else return "false"; } char *get_socket_dir(struct screen_list *screen_list) { return screen_list->comm.socket_dir; } char *get_delay(struct screen_list *screen_list) { char *r = malloc(100); sprintf(r, "%d", screen_list->requested_delay); return r; } #endif \ No newline at end of file diff --git a/neercs/old/effects.c b/neercs/old/effects.c index 4f1be31..680a711 100644 --- a/neercs/old/effects.c +++ b/neercs/old/effects.c @@ -1,286 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "neercs.h" - -void draw_thumbnails(struct screen_list *screen_list) -{ - char const *const *fonts; - caca_dither_t *d; - caca_font_t *f; - uint8_t *buf; - int i, y = - caca_get_canvas_height(screen_list->cv) - 6 - screen_list->modals.status; - int miniw, minih; - - if (screen_list->count) - { - fonts = caca_get_font_list(); - f = caca_load_font(fonts[0], 0); - - miniw = caca_get_canvas_width(screen_list->screen[0]->cv) - * caca_get_font_width(f); - minih = caca_get_canvas_height(screen_list->screen[0]->cv) - * caca_get_font_height(f); - buf = malloc(4 * miniw * minih); - -#if defined(HAVE_ENDIAN_H) - if (__BYTE_ORDER == __BIG_ENDIAN) -#else - /* This is compile-time optimised with at least -O1 or -Os */ - uint32_t const tmp = 0x12345678; - if (*(uint8_t const *)&tmp == 0x12) -#endif - d = caca_create_dither(32, miniw, minih, 4 * miniw, - 0xff0000, 0xff00, 0xff, 0x0); - else - d = caca_create_dither(32, miniw, minih, 4 * miniw, - 0xff00, 0xff0000, 0xff000000, 0x0); - - for (i = 0; i < screen_list->count; i++) - { - if (!screen_list->screen[i]->changed && !screen_list->changed) - continue; - caca_render_canvas(screen_list->screen[i]->cv, f, buf, - miniw, minih, miniw * 4); - caca_dither_bitmap(screen_list->cv, 20 * i, y, 19, 6, d, buf); - caca_set_color_ansi(screen_list->cv, CACA_WHITE, CACA_BLUE); - - if (screen_list->pty == i) - caca_draw_cp437_box(screen_list->cv, 20 * i, y, 19, 6); - caca_printf(screen_list->cv, 20 * i, y, "(%i)", i + 1); - } - - caca_free_dither(d); - caca_free_font(f); - - free(buf); - } - -} - -/* FIXME, make this stuff more configurable */ -void draw_status(struct screen_list *screen_list) -{ - int x = 0, y = caca_get_canvas_height(screen_list->cv) - 1; - - - /* caca_fill_box(screen_list->cv, x, y, - caca_get_canvas_width(screen_list->cv), 1, '#'); */ - - /* Hour */ - { - time_t now = time((time_t *) 0); - struct tm *t = localtime(&now); - char hour[256]; - sprintf(hour, "%02d:%02d", t->tm_hour, t->tm_min); - - caca_set_color_ansi(screen_list->cv, CACA_LIGHTBLUE, CACA_BLUE); - caca_printf(screen_list->cv, x, y, "["); - - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); - caca_printf(screen_list->cv, x + 1, y, hour); - caca_set_color_ansi(screen_list->cv, CACA_LIGHTBLUE, CACA_BLUE); - caca_printf(screen_list->cv, x + strlen(hour) + 1, y, "]"); - x += 7; - - } - - /* Window */ - { - char text[256]; - sprintf(text, "%d/%d", screen_list->pty + 1, screen_list->count); - caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); - caca_put_char(screen_list->cv, x, y, '#'); - x++; - caca_set_color_ansi(screen_list->cv, CACA_LIGHTBLUE, CACA_BLUE); - caca_printf(screen_list->cv, x, y, "Window:"); - caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); - caca_put_char(screen_list->cv, x + 7, y, '#'); - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); - caca_printf(screen_list->cv, x + 8, y, text); - x += 8 + strlen(text); - } - - /* Window Manager */ - { - char text[256]; - - switch (screen_list->wm_type) - { - case WM_CARD: - strcpy(text, "card"); - break; - case WM_HSPLIT: - strcpy(text, "hsplit"); - break; - case WM_VSPLIT: - strcpy(text, "vsplit"); - break; - case WM_FULL: - default: - strcpy(text, "full"); - break; - - } - - caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); - caca_put_char(screen_list->cv, x, y, '#'); - x++; - caca_set_color_ansi(screen_list->cv, CACA_LIGHTBLUE, CACA_BLUE); - caca_printf(screen_list->cv, x, y, "WM:"); - caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); - caca_put_char(screen_list->cv, x + 3, y, '#'); - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); - caca_printf(screen_list->cv, x + 4, y, text); - x += 4 + strlen(text); - } - - /* Help (must be the last one ) */ - { - char text[256]; - sprintf(text, "Help: ctrl-a-?"); - caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); - while (x < - (int)(caca_get_canvas_width(screen_list->cv) - strlen(text))) - { - caca_put_char(screen_list->cv, x, y, '#'); - x++; - } - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); - caca_printf(screen_list->cv, x, y, text); - } - - -} - - - -int update_window_list(int c, struct screen_list *screen_list) -{ - debug("Got %x\n", c); - - switch (c) - { - case 0x111: - if (screen_list->modals.cur_in_list > 0) - screen_list->modals.cur_in_list--; - break; - case 0x112: - if (screen_list->modals.cur_in_list < screen_list->count - 1) - screen_list->modals.cur_in_list++; - break; - case 0xd: - screen_list->modals.window_list = 0; - screen_list->prevpty = screen_list->pty; - screen_list->pty = screen_list->modals.cur_in_list; - break; - case 0x22: - screen_list->modals.window_list = 0; - break; - default: - break; - } - - return 1; -} - -void draw_list(struct screen_list *screen_list) -{ - int i; - int w = (caca_get_canvas_width(screen_list->cv)); - int h = (caca_get_canvas_height(screen_list->cv)); - - debug("Drawing list\n"); - caca_set_color_ansi(screen_list->cv, CACA_BLACK, CACA_BLACK); - caca_fill_box(screen_list->cv, 0, 0, w, h, '#'); - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT); - caca_draw_cp437_box(screen_list->cv, 0, 0, w, h); - - caca_printf(screen_list->cv, 2, 1, "Num Name"); - for (i = 0; i < screen_list->count; i++) - { - char line[1024]; - if (screen_list->modals.cur_in_list == i) - caca_set_color_ansi(screen_list->cv, CACA_BLACK, CACA_WHITE); - else - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT); - sprintf(line, "%d %s", i + 1, screen_list->screen[i]->title); - - caca_printf(screen_list->cv, 2, i + 3, line); - } -} - -/* Close a window by animating it collapsing */ -/* Total close time */ -#define DELAY 500000.0f -int close_screen_recurrent(struct screen_list *screen_list, - struct recurrent *rec, void *user, - long long unsigned int t) -{ - long long unsigned int delta = t - rec->start_time; - - screen_list->dont_update_coords = 1; - screen_list->delay = 0; - rec->kill_me = 0; - if (delta >= DELAY || (!screen_list->eyecandy)) - { - rec->kill_me = 1; - remove_screen(screen_list, screen_list->pty, 1); - screen_list->pty = screen_list->prevpty>screen_list->count?screen_list->count:screen_list->prevpty; - screen_list->prevpty = 0; - screen_list->dont_update_coords = 0; - } - else - { - float r = 1 - ((DELAY - (DELAY - delta)) / DELAY); - caca_canvas_t *old, *new; - struct screen *s = screen_list->screen[screen_list->pty]; - int w = s->orig_w * r; - int h = s->orig_h * r; - - /* libcaca canvas resize function is bugged, do it by hand */ - old = s->cv; - new = caca_create_canvas(w, h); - caca_blit(new, 0, 0, old, NULL); - s->cv = new; - caca_free_canvas(old); - set_tty_size(s->fd, w, h); - - s->w = w; - s->h = h; - - s->x = (s->orig_x * r) + ((s->orig_w / 2) - s->w / 2); - s->y = (s->orig_y * r) + ((s->orig_h / 2) - s->h / 2); - } - screen_list->changed = 1; - return 1; -} - -#endif - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include #include "neercs.h" void draw_thumbnails(struct screen_list *screen_list) { char const *const *fonts; caca_dither_t *d; caca_font_t *f; uint8_t *buf; int i, y = caca_get_canvas_height(screen_list->cv) - 6 - screen_list->modals.status; int miniw, minih; if (screen_list->count) { fonts = caca_get_font_list(); f = caca_load_font(fonts[0], 0); miniw = caca_get_canvas_width(screen_list->screen[0]->cv) * caca_get_font_width(f); minih = caca_get_canvas_height(screen_list->screen[0]->cv) * caca_get_font_height(f); buf = malloc(4 * miniw * minih); #if defined(HAVE_ENDIAN_H) if (__BYTE_ORDER == __BIG_ENDIAN) #else /* This is compile-time optimised with at least -O1 or -Os */ uint32_t const tmp = 0x12345678; if (*(uint8_t const *)&tmp == 0x12) #endif d = caca_create_dither(32, miniw, minih, 4 * miniw, 0xff0000, 0xff00, 0xff, 0x0); else d = caca_create_dither(32, miniw, minih, 4 * miniw, 0xff00, 0xff0000, 0xff000000, 0x0); for (i = 0; i < screen_list->count; i++) { if (!screen_list->screen[i]->changed && !screen_list->changed) continue; caca_render_canvas(screen_list->screen[i]->cv, f, buf, miniw, minih, miniw * 4); caca_dither_bitmap(screen_list->cv, 20 * i, y, 19, 6, d, buf); caca_set_color_ansi(screen_list->cv, CACA_WHITE, CACA_BLUE); if (screen_list->pty == i) caca_draw_cp437_box(screen_list->cv, 20 * i, y, 19, 6); caca_printf(screen_list->cv, 20 * i, y, "(%i)", i + 1); } caca_free_dither(d); caca_free_font(f); free(buf); } } /* FIXME, make this stuff more configurable */ void draw_status(struct screen_list *screen_list) { int x = 0, y = caca_get_canvas_height(screen_list->cv) - 1; /* caca_fill_box(screen_list->cv, x, y, caca_get_canvas_width(screen_list->cv), 1, '#'); */ /* Hour */ { time_t now = time((time_t *) 0); struct tm *t = localtime(&now); char hour[256]; sprintf(hour, "%02d:%02d", t->tm_hour, t->tm_min); caca_set_color_ansi(screen_list->cv, CACA_LIGHTBLUE, CACA_BLUE); caca_printf(screen_list->cv, x, y, "["); caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); caca_printf(screen_list->cv, x + 1, y, hour); caca_set_color_ansi(screen_list->cv, CACA_LIGHTBLUE, CACA_BLUE); caca_printf(screen_list->cv, x + strlen(hour) + 1, y, "]"); x += 7; } /* Window */ { char text[256]; sprintf(text, "%d/%d", screen_list->pty + 1, screen_list->count); caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); caca_put_char(screen_list->cv, x, y, '#'); x++; caca_set_color_ansi(screen_list->cv, CACA_LIGHTBLUE, CACA_BLUE); caca_printf(screen_list->cv, x, y, "Window:"); caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); caca_put_char(screen_list->cv, x + 7, y, '#'); caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); caca_printf(screen_list->cv, x + 8, y, text); x += 8 + strlen(text); } /* Window Manager */ { char text[256]; switch (screen_list->wm_type) { case WM_CARD: strcpy(text, "card"); break; case WM_HSPLIT: strcpy(text, "hsplit"); break; case WM_VSPLIT: strcpy(text, "vsplit"); break; case WM_FULL: default: strcpy(text, "full"); break; } caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); caca_put_char(screen_list->cv, x, y, '#'); x++; caca_set_color_ansi(screen_list->cv, CACA_LIGHTBLUE, CACA_BLUE); caca_printf(screen_list->cv, x, y, "WM:"); caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); caca_put_char(screen_list->cv, x + 3, y, '#'); caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); caca_printf(screen_list->cv, x + 4, y, text); x += 4 + strlen(text); } /* Help (must be the last one ) */ { char text[256]; sprintf(text, "Help: ctrl-a-?"); caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); while (x < (int)(caca_get_canvas_width(screen_list->cv) - strlen(text))) { caca_put_char(screen_list->cv, x, y, '#'); x++; } caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); caca_printf(screen_list->cv, x, y, text); } } int update_window_list(int c, struct screen_list *screen_list) { debug("Got %x\n", c); switch (c) { case 0x111: if (screen_list->modals.cur_in_list > 0) screen_list->modals.cur_in_list--; break; case 0x112: if (screen_list->modals.cur_in_list < screen_list->count - 1) screen_list->modals.cur_in_list++; break; case 0xd: screen_list->modals.window_list = 0; screen_list->prevpty = screen_list->pty; screen_list->pty = screen_list->modals.cur_in_list; break; case 0x22: screen_list->modals.window_list = 0; break; default: break; } return 1; } void draw_list(struct screen_list *screen_list) { int i; int w = (caca_get_canvas_width(screen_list->cv)); int h = (caca_get_canvas_height(screen_list->cv)); debug("Drawing list\n"); caca_set_color_ansi(screen_list->cv, CACA_BLACK, CACA_BLACK); caca_fill_box(screen_list->cv, 0, 0, w, h, '#'); caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT); caca_draw_cp437_box(screen_list->cv, 0, 0, w, h); caca_printf(screen_list->cv, 2, 1, "Num Name"); for (i = 0; i < screen_list->count; i++) { char line[1024]; if (screen_list->modals.cur_in_list == i) caca_set_color_ansi(screen_list->cv, CACA_BLACK, CACA_WHITE); else caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT); sprintf(line, "%d %s", i + 1, screen_list->screen[i]->title); caca_printf(screen_list->cv, 2, i + 3, line); } } /* Close a window by animating it collapsing */ /* Total close time */ #define DELAY 500000.0f int close_screen_recurrent(struct screen_list *screen_list, struct recurrent *rec, void *user, long long unsigned int t) { long long unsigned int delta = t - rec->start_time; screen_list->dont_update_coords = 1; screen_list->delay = 0; rec->kill_me = 0; if (delta >= DELAY || (!screen_list->eyecandy)) { rec->kill_me = 1; remove_screen(screen_list, screen_list->pty, 1); screen_list->pty = screen_list->prevpty>screen_list->count?screen_list->count:screen_list->prevpty; screen_list->prevpty = 0; screen_list->dont_update_coords = 0; } else { float r = 1 - ((DELAY - (DELAY - delta)) / DELAY); caca_canvas_t *old, *new; struct screen *s = screen_list->screen[screen_list->pty]; int w = s->orig_w * r; int h = s->orig_h * r; /* libcaca canvas resize function is bugged, do it by hand */ old = s->cv; new = caca_create_canvas(w, h); caca_blit(new, 0, 0, old, NULL); s->cv = new; caca_free_canvas(old); set_tty_size(s->fd, w, h); s->w = w; s->h = h; s->x = (s->orig_x * r) + ((s->orig_w / 2) - s->w / 2); s->y = (s->orig_y * r) + ((s->orig_h / 2) - s->h / 2); } screen_list->changed = 1; return 1; } #endif \ No newline at end of file diff --git a/neercs/old/grab.c b/neercs/old/grab.c index cd3501d..0c3a451 100644 --- a/neercs/old/grab.c +++ b/neercs/old/grab.c @@ -1,400 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 && defined HAVE_GLOB_H - -#define _XOPEN_SOURCE 500 /* getsid() */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined HAVE_LINUX_KDEV_T_H -# include -# include -#endif - -#include "neercs.h" -#include "mytrace.h" - -int grab_process(long pid, char *ptyname, int ptyfd, int *newpid) -{ -#if defined HAVE_LINUX_KDEV_T_H - char fdstr[1024]; - struct mytrace *parent, *child; - int i = 0, fd = 0, ret; - char to_open[128]; - int mode[128]; - int fds[128]; - struct stat stat_buf; - struct termios tos; - int validtos = 0; - DIR *fddir; - struct dirent *fddirent; - - debug("pty is %s", ptyname); - - parent = mytrace_attach(pid); - if (!parent) - { - fprintf(stderr, "Cannot access process %ld\n", pid); - return -1; - } - - child = mytrace_fork(parent); - - snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd", pid); - fddir = opendir(fdstr); - - /* Look for file descriptors that are PTYs */ - while ((fddirent = readdir(fddir)) && i < (int)sizeof(to_open) - 1) - { - fd = atoi(fddirent->d_name); - fds[i] = fd; - to_open[i] = 0; - lstat(fdstr, &stat_buf); - if ((stat_buf.st_mode & S_IRUSR) && (stat_buf.st_mode & S_IWUSR)) - mode[i] = O_RDWR; - else if (stat_buf.st_mode & S_IWUSR) - mode[i] = O_WRONLY; - else - mode[i] = O_RDONLY; - - snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd/%s", pid, - fddirent->d_name); - - if (stat(fdstr, &stat_buf) < 0) - continue; - - if (!S_ISCHR(stat_buf.st_mode) - || MAJOR(stat_buf.st_rdev) != UNIX98_PTY_SLAVE_MAJOR) - continue; - - debug("found pty %d for pid %d", fd, pid); - - if (!validtos) - { - ret = mytrace_tcgets(child, fd, &tos); - if (ret < 0) - { - perror("mytrace_tcgets"); - } - else - { - validtos = 1; - } - } - to_open[i] = 1; - i++; - } - closedir(fddir); - - if (i >= (int)sizeof(to_open) - 1) - { - fprintf(stderr, "too many open pty\n"); - mytrace_detach(child); - return -1; - } - - ret = mytrace_exec(parent, "/usr/bin/reset"); - if (ret < 0) - mytrace_exit(parent, 0); - mytrace_detach(parent); - waitpid(pid, NULL, 0); /* Wait for reset to finish before displaying */ - mytrace_write(child, 2, "\033[H\033[2J", 7); - mytrace_write(child, 2, "\n[Process stolen by neercs]\r\n\n", 30); - - pid = mytrace_getpid(child); - *newpid = pid; - - /* Set the process's session ID */ - debug("Running setsid on process %ld (sid=%d)", pid, getsid(pid)); - - ret = mytrace_setpgid(child, 0, getsid(pid)); - if (ret < 0) - { - fprintf(stderr, "syscall setpgid failed\n"); - mytrace_detach(child); - return -1; - } - - if (ret != 0) - { - fprintf(stderr, "setpgid returned %d\n", ret); - mytrace_detach(child); - return -1; - } - - ret = mytrace_setsid(child); - if (ret < 0) - { - fprintf(stderr, "syscall setsid failed\n"); - mytrace_detach(child); - return -1; - } - - debug("pid %ld has now sid %d", pid, getsid(pid)); - - /* Reopen PTY file descriptors */ - for (; i >= 0; i--) - { - if (!to_open[i]) - continue; - ret = mytrace_close(child, fds[i]); - if (ret < 0) - { - perror("mytrace_close"); - continue; - } - fd = mytrace_open(child, ptyname, mode[i]); - if (fd < 0) - { - perror("mytrace_open"); - continue; - } - - /* FIXME Only needed once */ - mytrace_sctty(child, fd); - - if (validtos) - { - ret = mytrace_tcsets(child, fd, &tos); - if (ret < 0) - { - perror("mytrace_tcsets"); - } - validtos = 0; - } - ret = mytrace_dup2(child, fd, fds[i]); - if (ret < 0) - { - perror("mytrace_dup2"); - } - } - - kill(pid, SIGWINCH); - mytrace_detach(child); - - close(ptyfd); - return 0; -#else - errno = ENOSYS; - return -1; -#endif -} - -struct process -{ - long pid; - char *cmdline; -}; - -static int list_process(struct process **process_list) -{ - glob_t pglob; - unsigned int i, n = 0; - glob("/proc/[0-9]*", GLOB_NOSORT, NULL, &pglob); - *process_list = malloc(pglob.gl_pathc * sizeof(struct process)); - for (i = 0; i < pglob.gl_pathc; i++) - { - glob_t pglob2; - unsigned int j; - char *fds; - (*process_list)[n].pid = atoi(basename(pglob.gl_pathv[i])); - /* Don't allow grabbing ourselves */ - if ((*process_list)[n].pid == getpid()) - continue; - /* FIXME check value of r */ - int r = asprintf(&fds, "%s/fd/*", pglob.gl_pathv[i]); - (void) r; - glob(fds, GLOB_NOSORT, NULL, &pglob2); - free(fds); - for (j = 0; j < pglob2.gl_pathc; j++) - { - char path[4096]; - ssize_t l = readlink(pglob2.gl_pathv[j], path, sizeof(path)); - if (l <= 0) - continue; - path[l] = '\0'; - if (strstr(path, "/dev/pt")) - { - char *cmdfile; - int fd; - /* FIXME check value of r */ - r = asprintf(&cmdfile, "%s/cmdline", pglob.gl_pathv[i]); - (void) r; - fd = open(cmdfile, O_RDONLY); - free(cmdfile); - if (fd) - { - /* FIXME check value of r */ - r = read(fd, path, sizeof(path)); - (void) r; - (*process_list)[n].cmdline = strdup(path); - close(fd); - n++; - break; - } - } - } - globfree(&pglob2); - } - globfree(&pglob); - return n; -} - -long select_process(struct screen_list *screen_list) -{ - caca_event_t ev; - enum caca_event_type t; - int current_line = 1; - int refresh = 1; - int nb_process, i; - int ret = 0; - int start = 0; - struct process *process_list; - - nb_process = list_process(&process_list); - - screen_list->cv = caca_create_canvas(0, 0); - screen_list->dp = caca_create_display(screen_list->cv); - if (!screen_list->dp) - goto end; - caca_set_cursor(screen_list->dp, 0); - caca_set_display_title(screen_list->dp, PACKAGE_STRING); - while (1) - { - if (refresh) - { - caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); - caca_fill_box(screen_list->cv, - 0, 0, - caca_get_canvas_width(screen_list->cv), - caca_get_canvas_height(screen_list->cv), '#'); - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); - caca_draw_cp437_box(screen_list->cv, - 0, 0, - caca_get_canvas_width(screen_list->cv), - caca_get_canvas_height(screen_list->cv)); - caca_printf(screen_list->cv, 2, 2, - "Please select a process to grab:"); - for (i = 0; - i < nb_process - && i < caca_get_canvas_height(screen_list->cv) - 4; i++) - { - if (i == current_line - 1) - { - caca_set_attr(screen_list->cv, CACA_BOLD); - caca_set_color_ansi(screen_list->cv, CACA_GREEN, - CACA_BLUE); - caca_put_char(screen_list->cv, 1, i + 3, '>'); - } - else - { - caca_set_attr(screen_list->cv, 0); - caca_set_color_ansi(screen_list->cv, CACA_LIGHTGRAY, - CACA_BLUE); - caca_put_char(screen_list->cv, 1, i + 3, ' '); - } - caca_printf(screen_list->cv, - 3, i + 3, - "%5d %s", - process_list[i + start].pid, - process_list[i + start].cmdline); - } - caca_refresh_display(screen_list->dp); - refresh = 0; - } - - if (!caca_get_event(screen_list->dp, - CACA_EVENT_KEY_PRESS - | CACA_EVENT_RESIZE | CACA_EVENT_QUIT, &ev, 10000)) - continue; - - t = caca_get_event_type(&ev); - - if (t & CACA_EVENT_KEY_PRESS) - { - unsigned int c = caca_get_event_key_ch(&ev); - switch (c) - { - case CACA_KEY_UP: - if (current_line > 1) - current_line--; - if (current_line < start && start > 0) - start--; - break; - case CACA_KEY_DOWN: - if (current_line < nb_process) - current_line++; - if (current_line > - start + caca_get_canvas_height(screen_list->cv) - 3) - start++; - break; - case CACA_KEY_RETURN: - ret = process_list[current_line - 1].pid; - goto end; - break; - case CACA_KEY_ESCAPE: - goto end; - break; - default: - break; - } - refresh = 1; - } - else if (t & CACA_EVENT_RESIZE) - { - refresh = 1; - } - else if (t & CACA_EVENT_QUIT) - goto end; - } - - end: - if (screen_list->dp) - { - caca_free_display(screen_list->dp); - screen_list->dp = NULL; - } - if (screen_list->cv) - { - caca_free_canvas(screen_list->cv); - screen_list->cv = NULL; - } - if (nb_process > 0) - { - for (i = 0; i < nb_process; i++) - { - free(process_list[i].cmdline); - } - free(process_list); - } - return ret; -} - -#endif - +/* * neercs console-based window manager * Copyright (c) 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 && defined HAVE_GLOB_H #define _XOPEN_SOURCE 500 /* getsid() */ #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined HAVE_LINUX_KDEV_T_H # include # include #endif #include "neercs.h" #include "mytrace.h" int grab_process(long pid, char *ptyname, int ptyfd, int *newpid) { #if defined HAVE_LINUX_KDEV_T_H char fdstr[1024]; struct mytrace *parent, *child; int i = 0, fd = 0, ret; char to_open[128]; int mode[128]; int fds[128]; struct stat stat_buf; struct termios tos; int validtos = 0; DIR *fddir; struct dirent *fddirent; debug("pty is %s", ptyname); parent = mytrace_attach(pid); if (!parent) { fprintf(stderr, "Cannot access process %ld\n", pid); return -1; } child = mytrace_fork(parent); snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd", pid); fddir = opendir(fdstr); /* Look for file descriptors that are PTYs */ while ((fddirent = readdir(fddir)) && i < (int)sizeof(to_open) - 1) { fd = atoi(fddirent->d_name); fds[i] = fd; to_open[i] = 0; lstat(fdstr, &stat_buf); if ((stat_buf.st_mode & S_IRUSR) && (stat_buf.st_mode & S_IWUSR)) mode[i] = O_RDWR; else if (stat_buf.st_mode & S_IWUSR) mode[i] = O_WRONLY; else mode[i] = O_RDONLY; snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd/%s", pid, fddirent->d_name); if (stat(fdstr, &stat_buf) < 0) continue; if (!S_ISCHR(stat_buf.st_mode) || MAJOR(stat_buf.st_rdev) != UNIX98_PTY_SLAVE_MAJOR) continue; debug("found pty %d for pid %d", fd, pid); if (!validtos) { ret = mytrace_tcgets(child, fd, &tos); if (ret < 0) { perror("mytrace_tcgets"); } else { validtos = 1; } } to_open[i] = 1; i++; } closedir(fddir); if (i >= (int)sizeof(to_open) - 1) { fprintf(stderr, "too many open pty\n"); mytrace_detach(child); return -1; } ret = mytrace_exec(parent, "/usr/bin/reset"); if (ret < 0) mytrace_exit(parent, 0); mytrace_detach(parent); waitpid(pid, NULL, 0); /* Wait for reset to finish before displaying */ mytrace_write(child, 2, "\033[H\033[2J", 7); mytrace_write(child, 2, "\n[Process stolen by neercs]\r\n\n", 30); pid = mytrace_getpid(child); *newpid = pid; /* Set the process's session ID */ debug("Running setsid on process %ld (sid=%d)", pid, getsid(pid)); ret = mytrace_setpgid(child, 0, getsid(pid)); if (ret < 0) { fprintf(stderr, "syscall setpgid failed\n"); mytrace_detach(child); return -1; } if (ret != 0) { fprintf(stderr, "setpgid returned %d\n", ret); mytrace_detach(child); return -1; } ret = mytrace_setsid(child); if (ret < 0) { fprintf(stderr, "syscall setsid failed\n"); mytrace_detach(child); return -1; } debug("pid %ld has now sid %d", pid, getsid(pid)); /* Reopen PTY file descriptors */ for (; i >= 0; i--) { if (!to_open[i]) continue; ret = mytrace_close(child, fds[i]); if (ret < 0) { perror("mytrace_close"); continue; } fd = mytrace_open(child, ptyname, mode[i]); if (fd < 0) { perror("mytrace_open"); continue; } /* FIXME Only needed once */ mytrace_sctty(child, fd); if (validtos) { ret = mytrace_tcsets(child, fd, &tos); if (ret < 0) { perror("mytrace_tcsets"); } validtos = 0; } ret = mytrace_dup2(child, fd, fds[i]); if (ret < 0) { perror("mytrace_dup2"); } } kill(pid, SIGWINCH); mytrace_detach(child); close(ptyfd); return 0; #else errno = ENOSYS; return -1; #endif } struct process { long pid; char *cmdline; }; static int list_process(struct process **process_list) { glob_t pglob; unsigned int i, n = 0; glob("/proc/[0-9]*", GLOB_NOSORT, NULL, &pglob); *process_list = malloc(pglob.gl_pathc * sizeof(struct process)); for (i = 0; i < pglob.gl_pathc; i++) { glob_t pglob2; unsigned int j; char *fds; (*process_list)[n].pid = atoi(basename(pglob.gl_pathv[i])); /* Don't allow grabbing ourselves */ if ((*process_list)[n].pid == getpid()) continue; /* FIXME check value of r */ int r = asprintf(&fds, "%s/fd/*", pglob.gl_pathv[i]); (void) r; glob(fds, GLOB_NOSORT, NULL, &pglob2); free(fds); for (j = 0; j < pglob2.gl_pathc; j++) { char path[4096]; ssize_t l = readlink(pglob2.gl_pathv[j], path, sizeof(path)); if (l <= 0) continue; path[l] = '\0'; if (strstr(path, "/dev/pt")) { char *cmdfile; int fd; /* FIXME check value of r */ r = asprintf(&cmdfile, "%s/cmdline", pglob.gl_pathv[i]); (void) r; fd = open(cmdfile, O_RDONLY); free(cmdfile); if (fd) { /* FIXME check value of r */ r = read(fd, path, sizeof(path)); (void) r; (*process_list)[n].cmdline = strdup(path); close(fd); n++; break; } } } globfree(&pglob2); } globfree(&pglob); return n; } long select_process(struct screen_list *screen_list) { caca_event_t ev; enum caca_event_type t; int current_line = 1; int refresh = 1; int nb_process, i; int ret = 0; int start = 0; struct process *process_list; nb_process = list_process(&process_list); screen_list->cv = caca_create_canvas(0, 0); screen_list->dp = caca_create_display(screen_list->cv); if (!screen_list->dp) goto end; caca_set_cursor(screen_list->dp, 0); caca_set_display_title(screen_list->dp, PACKAGE_STRING); while (1) { if (refresh) { caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); caca_fill_box(screen_list->cv, 0, 0, caca_get_canvas_width(screen_list->cv), caca_get_canvas_height(screen_list->cv), '#'); caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); caca_draw_cp437_box(screen_list->cv, 0, 0, caca_get_canvas_width(screen_list->cv), caca_get_canvas_height(screen_list->cv)); caca_printf(screen_list->cv, 2, 2, "Please select a process to grab:"); for (i = 0; i < nb_process && i < caca_get_canvas_height(screen_list->cv) - 4; i++) { if (i == current_line - 1) { caca_set_attr(screen_list->cv, CACA_BOLD); caca_set_color_ansi(screen_list->cv, CACA_GREEN, CACA_BLUE); caca_put_char(screen_list->cv, 1, i + 3, '>'); } else { caca_set_attr(screen_list->cv, 0); caca_set_color_ansi(screen_list->cv, CACA_LIGHTGRAY, CACA_BLUE); caca_put_char(screen_list->cv, 1, i + 3, ' '); } caca_printf(screen_list->cv, 3, i + 3, "%5d %s", process_list[i + start].pid, process_list[i + start].cmdline); } caca_refresh_display(screen_list->dp); refresh = 0; } if (!caca_get_event(screen_list->dp, CACA_EVENT_KEY_PRESS | CACA_EVENT_RESIZE | CACA_EVENT_QUIT, &ev, 10000)) continue; t = caca_get_event_type(&ev); if (t & CACA_EVENT_KEY_PRESS) { unsigned int c = caca_get_event_key_ch(&ev); switch (c) { case CACA_KEY_UP: if (current_line > 1) current_line--; if (current_line < start && start > 0) start--; break; case CACA_KEY_DOWN: if (current_line < nb_process) current_line++; if (current_line > start + caca_get_canvas_height(screen_list->cv) - 3) start++; break; case CACA_KEY_RETURN: ret = process_list[current_line - 1].pid; goto end; break; case CACA_KEY_ESCAPE: goto end; break; default: break; } refresh = 1; } else if (t & CACA_EVENT_RESIZE) { refresh = 1; } else if (t & CACA_EVENT_QUIT) goto end; } end: if (screen_list->dp) { caca_free_display(screen_list->dp); screen_list->dp = NULL; } if (screen_list->cv) { caca_free_canvas(screen_list->cv); screen_list->cv = NULL; } if (nb_process > 0) { for (i = 0; i < nb_process; i++) { free(process_list[i].cmdline); } free(process_list); } return ret; } #endif \ No newline at end of file diff --git a/neercs/old/help.c b/neercs/old/help.c index 1a98319..fa89d2b 100644 --- a/neercs/old/help.c +++ b/neercs/old/help.c @@ -1,82 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include - -#include "neercs.h" - -int help_handle_key(struct screen_list *screen_list, unsigned int c) -{ - if (c == CACA_KEY_ESCAPE || c == '?') - { - screen_list->modals.help = 0; - screen_list->changed = 1; - return 1; - } - else - { - return 0; - } -} - -void draw_help(struct screen_list *screen_list) -{ - int w = 65, h = 20; - int x = (caca_get_canvas_width(screen_list->cv) - w) / 2; - int y = (caca_get_canvas_height(screen_list->cv) - h) / 2; - - - caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); - caca_fill_box(screen_list->cv, x, y, w, h, '#'); - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); - caca_draw_cp437_box(screen_list->cv, x, y, w, h); - - x += 2; - y++; - caca_printf(screen_list->cv, - (caca_get_canvas_width(screen_list->cv) - - strlen(PACKAGE_STRING)) / 2, y - 1, PACKAGE_STRING); - caca_printf(screen_list->cv, x, y++, "Copyright (c) 2006-2010"); - caca_printf(screen_list->cv, x, y++, " Sam Hocevar "); - caca_printf(screen_list->cv, x, y++, " Jean-Yves Lamoureux "); - caca_printf(screen_list->cv, x, y++, " Pascal Terjan "); - caca_printf(screen_list->cv, x, y++, ""); - caca_printf(screen_list->cv, x, y++, ""); - caca_printf(screen_list->cv, x, y++, "All shortcuts are in format 'ctrl-a-X' where X is :"); - caca_printf(screen_list->cv, x, y++, "n: Next window"); - caca_printf(screen_list->cv, x, y++, "p: Previous window"); - caca_printf(screen_list->cv, x, y++, "w: Switch window manager"); - caca_printf(screen_list->cv, x, y++, "c: Create new window"); - caca_printf(screen_list->cv, x, y++, "m: Thumbnails"); - caca_printf(screen_list->cv, x, y++, "d: Detach"); - caca_printf(screen_list->cv, x, y++, "k: Close window and kill associated process"); - caca_printf(screen_list->cv, x, y++, "h: Dump screen into a file"); - caca_printf(screen_list->cv, x, y++, "?: This help"); - caca_printf(screen_list->cv, x, y++, ""); - caca_printf(screen_list->cv, x, y++, ""); - caca_printf(screen_list->cv, x, y, "See http://caca.zoy.org/wiki/neercs for more informations"); -} - -#endif +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include "neercs.h" int help_handle_key(struct screen_list *screen_list, unsigned int c) { if (c == CACA_KEY_ESCAPE || c == '?') { screen_list->modals.help = 0; screen_list->changed = 1; return 1; } else { return 0; } } void draw_help(struct screen_list *screen_list) { int w = 65, h = 20; int x = (caca_get_canvas_width(screen_list->cv) - w) / 2; int y = (caca_get_canvas_height(screen_list->cv) - h) / 2; caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); caca_fill_box(screen_list->cv, x, y, w, h, '#'); caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); caca_draw_cp437_box(screen_list->cv, x, y, w, h); x += 2; y++; caca_printf(screen_list->cv, (caca_get_canvas_width(screen_list->cv) - strlen(PACKAGE_STRING)) / 2, y - 1, PACKAGE_STRING); caca_printf(screen_list->cv, x, y++, "Copyright (c) 2006-2010"); caca_printf(screen_list->cv, x, y++, " Sam Hocevar "); caca_printf(screen_list->cv, x, y++, " Jean-Yves Lamoureux "); caca_printf(screen_list->cv, x, y++, " Pascal Terjan "); caca_printf(screen_list->cv, x, y++, ""); caca_printf(screen_list->cv, x, y++, ""); caca_printf(screen_list->cv, x, y++, "All shortcuts are in format 'ctrl-a-X' where X is :"); caca_printf(screen_list->cv, x, y++, "n: Next window"); caca_printf(screen_list->cv, x, y++, "p: Previous window"); caca_printf(screen_list->cv, x, y++, "w: Switch window manager"); caca_printf(screen_list->cv, x, y++, "c: Create new window"); caca_printf(screen_list->cv, x, y++, "m: Thumbnails"); caca_printf(screen_list->cv, x, y++, "d: Detach"); caca_printf(screen_list->cv, x, y++, "k: Close window and kill associated process"); caca_printf(screen_list->cv, x, y++, "h: Dump screen into a file"); caca_printf(screen_list->cv, x, y++, "?: This help"); caca_printf(screen_list->cv, x, y++, ""); caca_printf(screen_list->cv, x, y++, ""); caca_printf(screen_list->cv, x, y, "See http://caca.zoy.org/wiki/neercs for more informations"); } #endif \ No newline at end of file diff --git a/neercs/old/input.c b/neercs/old/input.c index 5697d4a..82dc2cc 100644 --- a/neercs/old/input.c +++ b/neercs/old/input.c @@ -1,198 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include "neercs.h" - -struct kconv -{ - unsigned int key; - char *val; - int size; -}; - -struct kconv kconv[] = { - {CACA_KEY_UP, "\033OA", 3}, - {CACA_KEY_DOWN, "\033OB", 3}, - {CACA_KEY_RIGHT, "\033OC", 3}, - {CACA_KEY_LEFT, "\033OD", 3}, - {CACA_KEY_PAGEUP, "\033[5~", 4}, - {CACA_KEY_PAGEDOWN, "\033[6~", 4}, - {CACA_KEY_HOME, "\033[1~", 4}, - {CACA_KEY_INSERT, "\033[2~", 4}, - {CACA_KEY_DELETE, "\033[3~", 4}, - {CACA_KEY_END, "\033[4~", 4}, - {CACA_KEY_F1, "\033[11~", 5}, - {CACA_KEY_F2, "\033[12~", 5}, - {CACA_KEY_F3, "\033[13~", 5}, - {CACA_KEY_F4, "\033[14~", 5}, - {CACA_KEY_F5, "\033[15~", 5}, - {CACA_KEY_F6, "\033[17~", 5}, - {CACA_KEY_F7, "\033[18~", 5}, - {CACA_KEY_F8, "\033[19~", 5}, - {CACA_KEY_F9, "\033[20~", 5}, - {CACA_KEY_F10, "\033[21~", 5}, - {CACA_KEY_F11, "\033[23~", 5}, - {CACA_KEY_F12, "\033[24~", 5}, -}; - - - -void *convert_input_ansi(unsigned int *c, int *size) -{ - unsigned int i; - for (i = 0; i < sizeof(kconv) / sizeof(struct kconv); i++) - { - if (*c == kconv[i].key) - { - *size = kconv[i].size; - return kconv[i].val; - } - } - - *size = 1; - return c; -} - - - -int handle_command_input(struct screen_list *screen_list, unsigned int c) -{ - int refresh = 0; - -#if !defined _WIN32 - debug("Key %x\n", c); - screen_list->changed = 1; - - if (c >= '0' && c <= '9') - { - int n = c - 49; - if (n < screen_list->count) - { - screen_list->prevpty = screen_list->pty; - screen_list->pty = n == -1 ? 10 : n; - return 1; - } - else - { - return 0; - } - } - - switch (c) - { - case 0x01: // CACA_KEY_CTRL_A: - screen_list->pty ^= screen_list->prevpty; - screen_list->prevpty ^= screen_list->pty; - screen_list->pty ^= screen_list->prevpty; - refresh = 1; - break; - case 'm': - case 0x0d: // CACA_KEY_CTRL_M: - screen_list->modals.mini = !screen_list->modals.mini; - refresh = 1; - break; - case 'n': - case ' ': - case '\0': - case 0x0e: // CACA_KEY_CTRL_N: - screen_list->prevpty = screen_list->pty; - screen_list->pty = (screen_list->pty + 1) % screen_list->count; - if (screen_list->pty != screen_list->prevpty) - { - screen_list->last_switch = get_us(); - screen_list->cube.in_switch = 1; - screen_list->cube.side = 0; - } - refresh = 1; - break; - case 'p': - case 0x10: // CACA_KEY_CTRL_P: - screen_list->prevpty = screen_list->pty; - screen_list->pty = - (screen_list->pty + screen_list->count - 1) % screen_list->count; - if (screen_list->pty != screen_list->prevpty) - { - screen_list->last_switch = get_us(); - screen_list->cube.in_switch = 1; - screen_list->cube.side = 1; - } - refresh = 1; - break; - case 'c': - case 0x03: // CACA_KEY_CTRL_C: - screen_list->prevpty = screen_list->pty; - screen_list->pty = - add_screen(screen_list, - create_screen(screen_list->width, - screen_list->height, - screen_list->sys.default_shell)); - refresh = 1; - break; - case 'w': - case 0x17: // CACA_KEY_CTRL_W: - screen_list->wm_type = (screen_list->wm_type == (WM_MAX - 1) ? - screen_list->wm_type = 0 : - screen_list->wm_type + 1); - refresh = 1; - break; - case 'k': - case 0x0b: // CACA_KEY_CTRL_K: - add_recurrent(screen_list->recurrent_list, close_screen_recurrent, - screen_list->cv); - refresh = 1; - break; - case 'x': - case 0x18: // CACA_KEY_CTRL_X: - memset(screen_list->lock.lockpass, 0, 1024); - screen_list->lock.locked = 1; - screen_list->lock.lock_offset = 0; - refresh = 1; - break; - case 'h': - case 0x08: // CACA_KEY_CTRL_H: - dump_to_file(screen_list); - break; - case '?': - screen_list->modals.help = !screen_list->modals.help; - refresh = 1; - break; - case '"': - case 0x34: // CTRL+" - screen_list->modals.cur_in_list = screen_list->pty; - screen_list->modals.window_list = !screen_list->modals.window_list; - refresh = 1; - break; - case 'd': - case 0x04: // CACA_KEY_CTRL_D: - detach(screen_list); - break; -#ifdef USE_PYTHON - case 'e': - case 0x05: - debug("py : command is %d, setting to 1 (at %p)\n", screen_list->modals.python_command, &screen_list->modals.python_command); - screen_list->modals.python_command = 1; - refresh = 1; - break; -#endif - } -#endif /* _WIN32 */ - return refresh; - -} +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include #include #include "neercs.h" struct kconv { unsigned int key; char *val; int size; }; struct kconv kconv[] = { {CACA_KEY_UP, "\033OA", 3}, {CACA_KEY_DOWN, "\033OB", 3}, {CACA_KEY_RIGHT, "\033OC", 3}, {CACA_KEY_LEFT, "\033OD", 3}, {CACA_KEY_PAGEUP, "\033[5~", 4}, {CACA_KEY_PAGEDOWN, "\033[6~", 4}, {CACA_KEY_HOME, "\033[1~", 4}, {CACA_KEY_INSERT, "\033[2~", 4}, {CACA_KEY_DELETE, "\033[3~", 4}, {CACA_KEY_END, "\033[4~", 4}, {CACA_KEY_F1, "\033[11~", 5}, {CACA_KEY_F2, "\033[12~", 5}, {CACA_KEY_F3, "\033[13~", 5}, {CACA_KEY_F4, "\033[14~", 5}, {CACA_KEY_F5, "\033[15~", 5}, {CACA_KEY_F6, "\033[17~", 5}, {CACA_KEY_F7, "\033[18~", 5}, {CACA_KEY_F8, "\033[19~", 5}, {CACA_KEY_F9, "\033[20~", 5}, {CACA_KEY_F10, "\033[21~", 5}, {CACA_KEY_F11, "\033[23~", 5}, {CACA_KEY_F12, "\033[24~", 5}, }; void *convert_input_ansi(unsigned int *c, int *size) { unsigned int i; for (i = 0; i < sizeof(kconv) / sizeof(struct kconv); i++) { if (*c == kconv[i].key) { *size = kconv[i].size; return kconv[i].val; } } *size = 1; return c; } int handle_command_input(struct screen_list *screen_list, unsigned int c) { int refresh = 0; #if !defined _WIN32 debug("Key %x\n", c); screen_list->changed = 1; if (c >= '0' && c <= '9') { int n = c - 49; if (n < screen_list->count) { screen_list->prevpty = screen_list->pty; screen_list->pty = n == -1 ? 10 : n; return 1; } else { return 0; } } switch (c) { case 0x01: // CACA_KEY_CTRL_A: screen_list->pty ^= screen_list->prevpty; screen_list->prevpty ^= screen_list->pty; screen_list->pty ^= screen_list->prevpty; refresh = 1; break; case 'm': case 0x0d: // CACA_KEY_CTRL_M: screen_list->modals.mini = !screen_list->modals.mini; refresh = 1; break; case 'n': case ' ': case '\0': case 0x0e: // CACA_KEY_CTRL_N: screen_list->prevpty = screen_list->pty; screen_list->pty = (screen_list->pty + 1) % screen_list->count; if (screen_list->pty != screen_list->prevpty) { screen_list->last_switch = get_us(); screen_list->cube.in_switch = 1; screen_list->cube.side = 0; } refresh = 1; break; case 'p': case 0x10: // CACA_KEY_CTRL_P: screen_list->prevpty = screen_list->pty; screen_list->pty = (screen_list->pty + screen_list->count - 1) % screen_list->count; if (screen_list->pty != screen_list->prevpty) { screen_list->last_switch = get_us(); screen_list->cube.in_switch = 1; screen_list->cube.side = 1; } refresh = 1; break; case 'c': case 0x03: // CACA_KEY_CTRL_C: screen_list->prevpty = screen_list->pty; screen_list->pty = add_screen(screen_list, create_screen(screen_list->width, screen_list->height, screen_list->sys.default_shell)); refresh = 1; break; case 'w': case 0x17: // CACA_KEY_CTRL_W: screen_list->wm_type = (screen_list->wm_type == (WM_MAX - 1) ? screen_list->wm_type = 0 : screen_list->wm_type + 1); refresh = 1; break; case 'k': case 0x0b: // CACA_KEY_CTRL_K: add_recurrent(screen_list->recurrent_list, close_screen_recurrent, screen_list->cv); refresh = 1; break; case 'x': case 0x18: // CACA_KEY_CTRL_X: memset(screen_list->lock.lockpass, 0, 1024); screen_list->lock.locked = 1; screen_list->lock.lock_offset = 0; refresh = 1; break; case 'h': case 0x08: // CACA_KEY_CTRL_H: dump_to_file(screen_list); break; case '?': screen_list->modals.help = !screen_list->modals.help; refresh = 1; break; case '"': case 0x34: // CTRL+" screen_list->modals.cur_in_list = screen_list->pty; screen_list->modals.window_list = !screen_list->modals.window_list; refresh = 1; break; case 'd': case 0x04: // CACA_KEY_CTRL_D: detach(screen_list); break; #ifdef USE_PYTHON case 'e': case 0x05: debug("py : command is %d, setting to 1 (at %p)\n", screen_list->modals.python_command, &screen_list->modals.python_command); screen_list->modals.python_command = 1; refresh = 1; break; #endif } #endif /* _WIN32 */ return refresh; } \ No newline at end of file diff --git a/neercs/old/lock.c b/neercs/old/lock.c index bbc0ac1..ae8e1b7 100644 --- a/neercs/old/lock.c +++ b/neercs/old/lock.c @@ -1,227 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include - -#if defined USE_LOCK -#if defined HAVE_PAM_PAM_MISC_H -# include -# include -#else -# include -# include -#endif -# include -#endif - -#include "neercs.h" - -#if defined USE_LOCK -static int convpam(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr); -#endif - -int update_lock(int c, struct screen_list *screen_list) -{ - int refresh = 0; - -#if defined USE_LOCK - if (!screen_list->lock.locked) - return 0; - - if (c == 0x08) // BACKSPACE - { - if (screen_list->lock.lock_offset) - { - screen_list->lock.lockpass[screen_list->lock.lock_offset - 1] = 0; - screen_list->lock.lock_offset--; - } - } - else if (c == 0x0d) // RETURN - { - memset(screen_list->lock.lockmsg, 0, 1024); - if (validate_lock(screen_list, getenv("USER"), screen_list->lock.lockpass)) - { - memset(screen_list->lock.lockpass, 0, 1024); - screen_list->lock.locked = 0; - screen_list->lock.lock_offset = 0; - refresh = 1; - } - else - { - memset(screen_list->lock.lockpass, 0, 1024); - screen_list->lock.lock_offset = 0; - refresh = 1; - } - } - else - { - if (screen_list->lock.lock_offset < 1023) - { - screen_list->lock.lockpass[screen_list->lock.lock_offset++] = c; - screen_list->lock.lockpass[screen_list->lock.lock_offset] = 0; - } - } -#endif - - return refresh; -} - -void draw_lock(struct screen_list *screen_list) -{ -#if defined USE_LOCK - unsigned int i; - char buffer[1024]; - caca_canvas_t *cv = screen_list->cv; - - gethostname(buffer, sizeof(buffer) - 1); - - int w = 65, h = 20; - int x = (caca_get_canvas_width(cv) - w) / 2; - int y = (caca_get_canvas_height(cv) - h) / 2; - - - caca_set_color_ansi(cv, CACA_BLUE, CACA_BLUE); - caca_fill_box(cv, x, y, w, h, '#'); - caca_set_color_ansi(cv, CACA_DEFAULT, CACA_BLUE); - caca_draw_cp437_box(cv, x, y, w, h); - - x += 2; - y++; - caca_printf(cv, - (caca_get_canvas_width(cv) - - strlen(PACKAGE_STRING " locked")) / 2, y - 1, - PACKAGE_STRING " locked"); - - caca_printf(cv, x, y++, "Please type in your password for %s@%s :", - getenv("USER"), buffer); - y += 2; - - x = (caca_get_canvas_width(cv) / 2) - - ((strlen(screen_list->lock.lockpass) / 2) + strlen("Password : ")); - caca_printf(cv, x, y, "Password : "); - x += strlen("Password : "); - for (i = 0; i < strlen(screen_list->lock.lockpass); i++) - { - caca_put_str(cv, x, y, "*"); - x++; - } - - - if (strlen(screen_list->lock.lockmsg)) - { - x = ((caca_get_canvas_width(cv) - w) / 2) + - (strlen(screen_list->lock.lockmsg)); - y += 2; - caca_set_color_ansi(cv, CACA_RED, CACA_BLUE); - caca_printf(cv, x, y, "Error : %s", screen_list->lock.lockmsg); - } -#endif -} - - -#if defined USE_LOCK - -/* FIXME, handle this without assuming this is a password auth */ -static int convpam(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr) -{ - - struct pam_response *aresp; - int i; - aresp = calloc(num_msg, sizeof(*aresp)); - - for (i = 0; i < num_msg; ++i) - { - switch (msg[i]->msg_style) - { - case PAM_PROMPT_ECHO_ON: - case PAM_PROMPT_ECHO_OFF: - aresp[i].resp = strdup(appdata_ptr); - aresp[i].resp_retcode = 0; - break; - case PAM_ERROR_MSG: - break; - default: - printf("Unknow message type from PAM\n"); - break; - } - } - - *resp = aresp; - return (PAM_SUCCESS); -} -#endif - -int validate_lock(struct screen_list *screen_list, char *user, char *pass) -{ -#if USE_LOCK - int ret; - pam_handle_t *pamh = NULL; - char buffer[100]; - const char *service = "neercs"; - struct pam_conv conv = { - convpam, - pass, - }; - - ret = pam_start(service, user, &conv, &pamh); - if (ret != PAM_SUCCESS) - return 0; - pam_set_item(pamh, PAM_RUSER, user); - - ret = gethostname(buffer, sizeof(buffer) - 1); - if (ret) - { - perror("failed to look up hostname"); - ret = pam_end(pamh, PAM_ABORT); - sprintf(screen_list->lock.lockmsg, "Can't get hostname"); - pam_end(pamh, PAM_SUCCESS); - return 0; - } - - ret = pam_set_item(pamh, PAM_RHOST, buffer); - if (ret != PAM_SUCCESS) - { - sprintf(screen_list->lock.lockmsg, "Can't set hostname"); - pam_end(pamh, PAM_SUCCESS); - return 0; - } - - ret = pam_authenticate(pamh, 0); - if (ret != PAM_SUCCESS) - { - sprintf(screen_list->lock.lockmsg, "Can't authenticate"); - pam_end(pamh, PAM_SUCCESS); - return 0; - } - - ret = pam_end(pamh, PAM_SUCCESS); -#endif - - return 1; -} - -#endif +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #if defined USE_LOCK #if defined HAVE_PAM_PAM_MISC_H # include # include #else # include # include #endif # include #endif #include "neercs.h" #if defined USE_LOCK static int convpam(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); #endif int update_lock(int c, struct screen_list *screen_list) { int refresh = 0; #if defined USE_LOCK if (!screen_list->lock.locked) return 0; if (c == 0x08) // BACKSPACE { if (screen_list->lock.lock_offset) { screen_list->lock.lockpass[screen_list->lock.lock_offset - 1] = 0; screen_list->lock.lock_offset--; } } else if (c == 0x0d) // RETURN { memset(screen_list->lock.lockmsg, 0, 1024); if (validate_lock(screen_list, getenv("USER"), screen_list->lock.lockpass)) { memset(screen_list->lock.lockpass, 0, 1024); screen_list->lock.locked = 0; screen_list->lock.lock_offset = 0; refresh = 1; } else { memset(screen_list->lock.lockpass, 0, 1024); screen_list->lock.lock_offset = 0; refresh = 1; } } else { if (screen_list->lock.lock_offset < 1023) { screen_list->lock.lockpass[screen_list->lock.lock_offset++] = c; screen_list->lock.lockpass[screen_list->lock.lock_offset] = 0; } } #endif return refresh; } void draw_lock(struct screen_list *screen_list) { #if defined USE_LOCK unsigned int i; char buffer[1024]; caca_canvas_t *cv = screen_list->cv; gethostname(buffer, sizeof(buffer) - 1); int w = 65, h = 20; int x = (caca_get_canvas_width(cv) - w) / 2; int y = (caca_get_canvas_height(cv) - h) / 2; caca_set_color_ansi(cv, CACA_BLUE, CACA_BLUE); caca_fill_box(cv, x, y, w, h, '#'); caca_set_color_ansi(cv, CACA_DEFAULT, CACA_BLUE); caca_draw_cp437_box(cv, x, y, w, h); x += 2; y++; caca_printf(cv, (caca_get_canvas_width(cv) - strlen(PACKAGE_STRING " locked")) / 2, y - 1, PACKAGE_STRING " locked"); caca_printf(cv, x, y++, "Please type in your password for %s@%s :", getenv("USER"), buffer); y += 2; x = (caca_get_canvas_width(cv) / 2) - ((strlen(screen_list->lock.lockpass) / 2) + strlen("Password : ")); caca_printf(cv, x, y, "Password : "); x += strlen("Password : "); for (i = 0; i < strlen(screen_list->lock.lockpass); i++) { caca_put_str(cv, x, y, "*"); x++; } if (strlen(screen_list->lock.lockmsg)) { x = ((caca_get_canvas_width(cv) - w) / 2) + (strlen(screen_list->lock.lockmsg)); y += 2; caca_set_color_ansi(cv, CACA_RED, CACA_BLUE); caca_printf(cv, x, y, "Error : %s", screen_list->lock.lockmsg); } #endif } #if defined USE_LOCK /* FIXME, handle this without assuming this is a password auth */ static int convpam(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { struct pam_response *aresp; int i; aresp = calloc(num_msg, sizeof(*aresp)); for (i = 0; i < num_msg; ++i) { switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_ON: case PAM_PROMPT_ECHO_OFF: aresp[i].resp = strdup(appdata_ptr); aresp[i].resp_retcode = 0; break; case PAM_ERROR_MSG: break; default: printf("Unknow message type from PAM\n"); break; } } *resp = aresp; return (PAM_SUCCESS); } #endif int validate_lock(struct screen_list *screen_list, char *user, char *pass) { #if USE_LOCK int ret; pam_handle_t *pamh = NULL; char buffer[100]; const char *service = "neercs"; struct pam_conv conv = { convpam, pass, }; ret = pam_start(service, user, &conv, &pamh); if (ret != PAM_SUCCESS) return 0; pam_set_item(pamh, PAM_RUSER, user); ret = gethostname(buffer, sizeof(buffer) - 1); if (ret) { perror("failed to look up hostname"); ret = pam_end(pamh, PAM_ABORT); sprintf(screen_list->lock.lockmsg, "Can't get hostname"); pam_end(pamh, PAM_SUCCESS); return 0; } ret = pam_set_item(pamh, PAM_RHOST, buffer); if (ret != PAM_SUCCESS) { sprintf(screen_list->lock.lockmsg, "Can't set hostname"); pam_end(pamh, PAM_SUCCESS); return 0; } ret = pam_authenticate(pamh, 0); if (ret != PAM_SUCCESS) { sprintf(screen_list->lock.lockmsg, "Can't authenticate"); pam_end(pamh, PAM_SUCCESS); return 0; } ret = pam_end(pamh, PAM_SUCCESS); #endif return 1; } #endif \ No newline at end of file diff --git a/neercs/old/main.c b/neercs/old/main.c index 63e2268..57d2d9f 100644 --- a/neercs/old/main.c +++ b/neercs/old/main.c @@ -1,318 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined HAVE_GETOPT_LONG -# include "mygetopt.h" -#elif defined HAVE_GETOPT_H -# include -#endif -#if defined HAVE_GETOPT_LONG -# define mygetopt getopt_long -# define myoptind optind -# define myoptarg optarg -# define myoption option -#endif -#include -#include - -#include "neercs.h" - - -void version(void) -{ - printf("%s\n", PACKAGE_STRING); - printf("Copyright (C) 2006, 2008 Sam Hocevar \n"); - printf - (" Jean-Yves Lamoureux \n\n"); - printf - ("This is free software. You may redistribute copies of it under the\n"); - printf - ("terms of the Do What The Fuck You Want To Public License, Version 2\n"); - printf(".\n"); - printf("There is NO WARRANTY, to the extent permitted by law.\n"); - printf("\n"); - printf - ("For more informations, visit http://libcaca.zoy.org/wiki/neercs\n"); -} - -void usage(int argc, char **argv) -{ - printf("%s\n", PACKAGE_STRING); - printf("Usage : %s [command1] [command2] ... [commandN]\n", argv[0]); - printf("Example : %s zsh top \n\n", argv[0]); - printf("Options :\n"); - printf("\t--config\t-c \t\tuse given config file\n"); - printf("\t--pid\t\t-P [pid]\t\tgrab process\n"); - printf("\t\t\t-r [session]\t\treattach to a detached neercs\n"); - printf - ("\t\t\t-R [session]\t\treattach if possible, otherwise start a new session\n"); - printf("\t\t\t-S \t\tname this session instead of \n"); - printf("\t--lock-after\t-l [n]\t\t\tlock screen after n seconds\n"); - printf("\t--version\t-v \t\t\tdisplay version and exit\n"); - printf("\t--help\t\t-h \t\t\tthis help\n"); -} - -struct screen_list *init_neercs(int argc, char **argv) -{ - struct screen_list *screen_list = NULL; - int args; - - int mainret = -1; - - screen_list = create_screen_list(); - screen_list->sys.default_shell = getenv("SHELL"); - - args = argc - 1; - if (screen_list->sys.default_shell == NULL && args <= 0) - { - fprintf(stderr, - "Environment variable SHELL not set and no arguments given. kthxbye.\n"); - free_screen_list(screen_list); - return NULL; - } - - if (handle_command_line(argc, argv, screen_list) < 0) - { - free_screen_list(screen_list); - return NULL; - } - - /* Read global configuration first */ - read_configuration_file("/etc/neercsrc", screen_list); - - /* Then local one */ - if (screen_list->sys.user_path) - { - read_configuration_file(screen_list->sys.user_path, screen_list); - free(screen_list->sys.user_path); - } - - if (screen_list->sys.attach) - { - if (screen_list->sys.nb_to_grab || screen_list->sys.to_start) - { - fprintf(stderr, - "-R can not be associated with commands or pids!\n"); - free_screen_list(screen_list); - return NULL; - } - - attach(screen_list); - - if (screen_list->sys.forceattach && !screen_list->sys.attach) - { - free_screen_list(screen_list); - return NULL; - } - } - - /* Build default session name */ - if (!screen_list->comm.session_name) - { - char mypid[32]; /* FIXME Compute the length of PID_MAX ? */ - snprintf(mypid, 31, "%d", getpid()); - mypid[31] = '\0'; - screen_list->comm.session_name = strdup(mypid); - if (!screen_list->comm.session_name) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - free_screen_list(screen_list); - return NULL; - } - } - if (!screen_list->comm.socket_path[SOCK_CLIENT]) - screen_list->comm.socket_path[SOCK_CLIENT] = - build_socket_path(screen_list->comm.socket_dir, - screen_list->comm.session_name, SOCK_CLIENT); - - if (!screen_list->comm.socket_path[SOCK_SERVER]) - screen_list->comm.socket_path[SOCK_SERVER] = - build_socket_path(screen_list->comm.socket_dir, - screen_list->comm.session_name, SOCK_SERVER); - - /* Fork the server if needed */ - if (!screen_list->sys.attach) - { - debug("Spawning a new server"); - if (start_server(screen_list)) - { - free_screen_list(screen_list); - return NULL; - } - if (start_client(screen_list)) - { - free_screen_list(screen_list); - return NULL; - } - } - - return screen_list; -} - -int handle_command_line(int argc, char *argv[], - struct screen_list *screen_list) -{ - int s = 0, i; - for (;;) - { - int option_index = 0; - int pidopt; - static struct myoption long_options[] = { - {"config", 1, NULL, 'c'}, -#if defined USE_GRAB - {"pid", 0, NULL, 'P'}, -#endif - {"lock-after", 1, NULL, 'l'}, - {"help", 0, NULL, 'h'}, - {"version", 0, NULL, 'v'}, - {NULL, 0, NULL, 0}, - }; -#if defined USE_GRAB - int c = - mygetopt(argc, argv, "c:S:R::l::r::P::hv", long_options, - &option_index); -#else - int c = - mygetopt(argc, argv, "c:S:R::l::r::hv", long_options, - &option_index); -#endif - if (c == -1) - break; - - switch (c) - { - case 'c': /* --config */ - if (screen_list->sys.user_path) - free(screen_list->sys.user_path); - screen_list->sys.user_path = strdup(myoptarg); - s += 2; - break; - case 'S': - if (!screen_list->comm.session_name) - screen_list->comm.session_name = strdup(myoptarg); - s += 2; - break; - case 'P': /* --pid */ - if (myoptarg) - { - pidopt = atoi(myoptarg); - if (pidopt <= 0) - { - fprintf(stderr, "Invalid pid %d\n", pidopt); - if (screen_list->sys.to_grab) - free(screen_list->sys.to_grab); - return -1; - } - } - else - pidopt = select_process(screen_list); - if (pidopt <= 0) - { - s += 1; - break; - } - if (!screen_list->sys.to_grab) - { - /* At most argc-1-s times -P + final 0 */ - screen_list->sys.to_grab = - (int *)malloc(((argc - 1 - s) / 2 + 1) * sizeof(int)); - if (!screen_list->sys.to_grab) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", - __FUNCTION__, __LINE__); - return -1; - } - } - screen_list->sys.to_grab[screen_list->sys.nb_to_grab++] = pidopt; - screen_list->sys.to_grab[screen_list->sys.nb_to_grab] = 0; - s += 2; - break; - case 'l': - screen_list->lock.autolock_timeout = atoi(myoptarg) * 1000000; - if (screen_list->lock.autolock_timeout == 0) - screen_list->lock.autolock_timeout -= 1; - break; - case 'r': - screen_list->sys.forceattach = 1; - case 'R': - if (screen_list->sys.attach) - { - fprintf(stderr, "Attaching can only be requested once\n"); - return -1; - } - if (myoptarg) - { - if (screen_list->comm.session_name) - free(screen_list->comm.session_name); - screen_list->comm.session_name = strdup(myoptarg); - s += 1; - } - screen_list->sys.attach = 1; - s += 1; - break; - case 'h': /* --help */ - usage(argc, argv); - return -1; - break; - case 'v': /* --version */ - version(); - return -1; - break; - case -2: - return -1; - default: - fprintf(stderr, "Unknown argument #%d\n", myoptind); - return -1; - break; - } - } - if (s >= 0 && s < argc - 1) - { - screen_list->sys.to_start = (char **)malloc((argc - s) * sizeof(char *)); - if (!screen_list->sys.to_start) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - return -1; - } - for (i = 0; i < (argc - 1) - s; i++) - { - screen_list->sys.to_start[i] = strdup(argv[i + s + 1]); - } - screen_list->sys.to_start[argc - 1 - s] = NULL; - } - return s; -} - -#endif - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include #include #include #include #if !defined HAVE_GETOPT_LONG # include "mygetopt.h" #elif defined HAVE_GETOPT_H # include #endif #if defined HAVE_GETOPT_LONG # define mygetopt getopt_long # define myoptind optind # define myoptarg optarg # define myoption option #endif #include #include #include "neercs.h" void version(void) { printf("%s\n", PACKAGE_STRING); printf("Copyright (C) 2006, 2008 Sam Hocevar \n"); printf (" Jean-Yves Lamoureux \n\n"); printf ("This is free software. You may redistribute copies of it under the\n"); printf ("terms of the Do What The Fuck You Want To Public License, Version 2\n"); printf(".\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n"); printf("\n"); printf ("For more informations, visit http://libcaca.zoy.org/wiki/neercs\n"); } void usage(int argc, char **argv) { printf("%s\n", PACKAGE_STRING); printf("Usage : %s [command1] [command2] ... [commandN]\n", argv[0]); printf("Example : %s zsh top \n\n", argv[0]); printf("Options :\n"); printf("\t--config\t-c \t\tuse given config file\n"); printf("\t--pid\t\t-P [pid]\t\tgrab process\n"); printf("\t\t\t-r [session]\t\treattach to a detached neercs\n"); printf ("\t\t\t-R [session]\t\treattach if possible, otherwise start a new session\n"); printf("\t\t\t-S \t\tname this session instead of \n"); printf("\t--lock-after\t-l [n]\t\t\tlock screen after n seconds\n"); printf("\t--version\t-v \t\t\tdisplay version and exit\n"); printf("\t--help\t\t-h \t\t\tthis help\n"); } struct screen_list *init_neercs(int argc, char **argv) { struct screen_list *screen_list = NULL; int args; int mainret = -1; screen_list = create_screen_list(); screen_list->sys.default_shell = getenv("SHELL"); args = argc - 1; if (screen_list->sys.default_shell == NULL && args <= 0) { fprintf(stderr, "Environment variable SHELL not set and no arguments given. kthxbye.\n"); free_screen_list(screen_list); return NULL; } if (handle_command_line(argc, argv, screen_list) < 0) { free_screen_list(screen_list); return NULL; } /* Read global configuration first */ read_configuration_file("/etc/neercsrc", screen_list); /* Then local one */ if (screen_list->sys.user_path) { read_configuration_file(screen_list->sys.user_path, screen_list); free(screen_list->sys.user_path); } if (screen_list->sys.attach) { if (screen_list->sys.nb_to_grab || screen_list->sys.to_start) { fprintf(stderr, "-R can not be associated with commands or pids!\n"); free_screen_list(screen_list); return NULL; } attach(screen_list); if (screen_list->sys.forceattach && !screen_list->sys.attach) { free_screen_list(screen_list); return NULL; } } /* Build default session name */ if (!screen_list->comm.session_name) { char mypid[32]; /* FIXME Compute the length of PID_MAX ? */ snprintf(mypid, 31, "%d", getpid()); mypid[31] = '\0'; screen_list->comm.session_name = strdup(mypid); if (!screen_list->comm.session_name) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); free_screen_list(screen_list); return NULL; } } if (!screen_list->comm.socket_path[SOCK_CLIENT]) screen_list->comm.socket_path[SOCK_CLIENT] = build_socket_path(screen_list->comm.socket_dir, screen_list->comm.session_name, SOCK_CLIENT); if (!screen_list->comm.socket_path[SOCK_SERVER]) screen_list->comm.socket_path[SOCK_SERVER] = build_socket_path(screen_list->comm.socket_dir, screen_list->comm.session_name, SOCK_SERVER); /* Fork the server if needed */ if (!screen_list->sys.attach) { debug("Spawning a new server"); if (start_server(screen_list)) { free_screen_list(screen_list); return NULL; } if (start_client(screen_list)) { free_screen_list(screen_list); return NULL; } } return screen_list; } int handle_command_line(int argc, char *argv[], struct screen_list *screen_list) { int s = 0, i; for (;;) { int option_index = 0; int pidopt; static struct myoption long_options[] = { {"config", 1, NULL, 'c'}, #if defined USE_GRAB {"pid", 0, NULL, 'P'}, #endif {"lock-after", 1, NULL, 'l'}, {"help", 0, NULL, 'h'}, {"version", 0, NULL, 'v'}, {NULL, 0, NULL, 0}, }; #if defined USE_GRAB int c = mygetopt(argc, argv, "c:S:R::l::r::P::hv", long_options, &option_index); #else int c = mygetopt(argc, argv, "c:S:R::l::r::hv", long_options, &option_index); #endif if (c == -1) break; switch (c) { case 'c': /* --config */ if (screen_list->sys.user_path) free(screen_list->sys.user_path); screen_list->sys.user_path = strdup(myoptarg); s += 2; break; case 'S': if (!screen_list->comm.session_name) screen_list->comm.session_name = strdup(myoptarg); s += 2; break; case 'P': /* --pid */ if (myoptarg) { pidopt = atoi(myoptarg); if (pidopt <= 0) { fprintf(stderr, "Invalid pid %d\n", pidopt); if (screen_list->sys.to_grab) free(screen_list->sys.to_grab); return -1; } } else pidopt = select_process(screen_list); if (pidopt <= 0) { s += 1; break; } if (!screen_list->sys.to_grab) { /* At most argc-1-s times -P + final 0 */ screen_list->sys.to_grab = (int *)malloc(((argc - 1 - s) / 2 + 1) * sizeof(int)); if (!screen_list->sys.to_grab) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } } screen_list->sys.to_grab[screen_list->sys.nb_to_grab++] = pidopt; screen_list->sys.to_grab[screen_list->sys.nb_to_grab] = 0; s += 2; break; case 'l': screen_list->lock.autolock_timeout = atoi(myoptarg) * 1000000; if (screen_list->lock.autolock_timeout == 0) screen_list->lock.autolock_timeout -= 1; break; case 'r': screen_list->sys.forceattach = 1; case 'R': if (screen_list->sys.attach) { fprintf(stderr, "Attaching can only be requested once\n"); return -1; } if (myoptarg) { if (screen_list->comm.session_name) free(screen_list->comm.session_name); screen_list->comm.session_name = strdup(myoptarg); s += 1; } screen_list->sys.attach = 1; s += 1; break; case 'h': /* --help */ usage(argc, argv); return -1; break; case 'v': /* --version */ version(); return -1; break; case -2: return -1; default: fprintf(stderr, "Unknown argument #%d\n", myoptind); return -1; break; } } if (s >= 0 && s < argc - 1) { screen_list->sys.to_start = (char **)malloc((argc - s) * sizeof(char *)); if (!screen_list->sys.to_start) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } for (i = 0; i < (argc - 1) - s; i++) { screen_list->sys.to_start[i] = strdup(argv[i + s + 1]); } screen_list->sys.to_start[argc - 1 - s] = NULL; } return s; } #endif \ No newline at end of file diff --git a/neercs/old/mini-client.c b/neercs/old/mini-client.c index 5b234be..bfe15af 100644 --- a/neercs/old/mini-client.c +++ b/neercs/old/mini-client.c @@ -1,94 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2011 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include /* BUFSIZ */ -#include /* strncmp() */ - -#include - -#include "mini-neercs.h" -#include "mini-socket.h" - -static caca_display_t *dp; -static caca_canvas_t *cv; -static nrx_socket_t *insock, *outsock; - -void client_init(void) -{ - int i, usec = 10000; - - cv = caca_create_canvas(0, 0); - dp = caca_create_display(cv); - caca_set_display_title(dp, "Press Esc to quit"); - - insock = socket_open("/tmp/neercs.sock.client", 1); - - for (i = 0; i < 10; i++) - { - outsock = socket_open("/tmp/neercs.sock", 0); - if (outsock) - break; - usleep(usec); - usec += usec; - } - - socket_puts(outsock, "CONNECT /tmp/neercs.sock.client"); -} - -int client_step(void) -{ - caca_event_t ev; - int ret; - - /* Handle client sockets */ - ret = socket_select(insock, 1000); - if (ret > 0) - { - char buf[BUFSIZ]; - ssize_t bytes = socket_read(insock, buf, BUFSIZ); - if (bytes <= 0) - return 1; - - /* Parse message */ - if (!strncmp(buf, "OK", strlen("OK"))) - { - fprintf(stderr, "neercs: connection established\n"); -socket_puts(insock, "TEST insock"); - } - } - - /* Handle libcaca events */ - if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 1000) - && caca_get_event_key_ch(&ev) == CACA_KEY_ESCAPE) - return 0; - - return 1; -} - -void client_fini(void) -{ - socket_puts(outsock, "QUIT /tmp/neercs.sock.client"); - - caca_free_display(dp); - caca_free_canvas(cv); - if (insock) - socket_close(insock); - if (outsock) - socket_close(outsock); -} - +/* * neercs console-based window manager * Copyright (c) 2006-2011 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include /* BUFSIZ */ #include /* strncmp() */ #include #include "mini-neercs.h" #include "mini-socket.h" static caca_display_t *dp; static caca_canvas_t *cv; static nrx_socket_t *insock, *outsock; void client_init(void) { int i, usec = 10000; cv = caca_create_canvas(0, 0); dp = caca_create_display(cv); caca_set_display_title(dp, "Press Esc to quit"); insock = socket_open("/tmp/neercs.sock.client", 1); for (i = 0; i < 10; i++) { outsock = socket_open("/tmp/neercs.sock", 0); if (outsock) break; usleep(usec); usec += usec; } socket_puts(outsock, "CONNECT /tmp/neercs.sock.client"); } int client_step(void) { caca_event_t ev; int ret; /* Handle client sockets */ ret = socket_select(insock, 1000); if (ret > 0) { char buf[BUFSIZ]; ssize_t bytes = socket_read(insock, buf, BUFSIZ); if (bytes <= 0) return 1; /* Parse message */ if (!strncmp(buf, "OK", strlen("OK"))) { fprintf(stderr, "neercs: connection established\n"); socket_puts(insock, "TEST insock"); } } /* Handle libcaca events */ if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 1000) && caca_get_event_key_ch(&ev) == CACA_KEY_ESCAPE) return 0; return 1; } void client_fini(void) { socket_puts(outsock, "QUIT /tmp/neercs.sock.client"); caca_free_display(dp); caca_free_canvas(cv); if (insock) socket_close(insock); if (outsock) socket_close(outsock); } \ No newline at end of file diff --git a/neercs/old/mini-neercs.c b/neercs/old/mini-neercs.c index 4ca4252..d291a7f 100644 --- a/neercs/old/mini-neercs.c +++ b/neercs/old/mini-neercs.c @@ -1,52 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include /* perror() */ -#include /* fork() */ - -#include "mini-neercs.h" - -int main(void) -{ - pid_t pid; - - pid = fork(); - - if (pid < 0) - { - perror("fork"); - return EXIT_FAILURE; - } - - if (pid > 0) - { - client_init(); - while(client_step()) ; - client_fini(); - } - else - { - server_init(); - while(server_step()) ; - server_fini(); - } - - return EXIT_SUCCESS; -} - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include #include /* perror() */ #include /* fork() */ #include "mini-neercs.h" int main(void) { pid_t pid; pid = fork(); if (pid < 0) { perror("fork"); return EXIT_FAILURE; } if (pid > 0) { client_init(); while(client_step()) ; client_fini(); } else { server_init(); while(server_step()) ; server_fini(); } return EXIT_SUCCESS; } \ No newline at end of file diff --git a/neercs/old/mini-neercs.h b/neercs/old/mini-neercs.h index 6e5d6ef..0381878 100644 --- a/neercs/old/mini-neercs.h +++ b/neercs/old/mini-neercs.h @@ -1,22 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -void client_init(void); -int client_step(void); -void client_fini(void); - -void server_init(void); -int server_step(void); -void server_fini(void); - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ void client_init(void); int client_step(void); void client_fini(void); void server_init(void); int server_step(void); void server_fini(void); \ No newline at end of file diff --git a/neercs/old/mini-server.c b/neercs/old/mini-server.c index 4254b0e..002e2f8 100644 --- a/neercs/old/mini-server.c +++ b/neercs/old/mini-server.c @@ -1,80 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2011 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include /* BUFSIZ */ -#include /* strncmp() */ - -#include "mini-neercs.h" -#include "mini-socket.h" - -static nrx_socket_t *insock, *outsock; - -void server_init(void) -{ -while (!insock) - insock = socket_open("/tmp/neercs.sock", 1); -} - -int server_step(void) -{ - char buf[BUFSIZ]; - ssize_t bytes; - int ret; - - if (outsock) - { - ret = socket_select(outsock, 1000); - if (ret <= 0) - goto nothing; - - bytes = socket_read(outsock, buf, BUFSIZ); - if (bytes <= 0) - goto nothing; - } -nothing: - - ret = socket_select(insock, 1000); - if (ret <= 0) - return 1; - - bytes = socket_read(insock, buf, BUFSIZ); - if (bytes <= 0) - return 1; - - /* Parse message */ - if (!strncmp(buf, "CONNECT ", strlen("CONNECT "))) - { - outsock = socket_open(buf + strlen("CONNECT "), 0); - socket_puts(outsock, "OK"); - } - else if (!strncmp(buf, "QUIT ", strlen("QUIT "))) - { - return 0; - } - - return 1; -} - -void server_fini(void) -{ - if (insock) - socket_close(insock); - if (outsock) - socket_close(outsock); -} - +/* * neercs console-based window manager * Copyright (c) 2006-2011 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include /* BUFSIZ */ #include /* strncmp() */ #include "mini-neercs.h" #include "mini-socket.h" static nrx_socket_t *insock, *outsock; void server_init(void) { while (!insock) insock = socket_open("/tmp/neercs.sock", 1); } int server_step(void) { char buf[BUFSIZ]; ssize_t bytes; int ret; if (outsock) { ret = socket_select(outsock, 1000); if (ret <= 0) goto nothing; bytes = socket_read(outsock, buf, BUFSIZ); if (bytes <= 0) goto nothing; } nothing: ret = socket_select(insock, 1000); if (ret <= 0) return 1; bytes = socket_read(insock, buf, BUFSIZ); if (bytes <= 0) return 1; /* Parse message */ if (!strncmp(buf, "CONNECT ", strlen("CONNECT "))) { outsock = socket_open(buf + strlen("CONNECT "), 0); socket_puts(outsock, "OK"); } else if (!strncmp(buf, "QUIT ", strlen("QUIT "))) { return 0; } return 1; } void server_fini(void) { if (insock) socket_close(insock); if (outsock) socket_close(outsock); } \ No newline at end of file diff --git a/neercs/old/mini-socket.c b/neercs/old/mini-socket.c index aa3ad94..094b36d 100644 --- a/neercs/old/mini-socket.c +++ b/neercs/old/mini-socket.c @@ -1,297 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2011 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include /* perror() */ -#include /* malloc(), free() */ -#include /* unlink() */ -#include /* fcntl() */ -#include /* memcpy() */ -#include /* select() */ -#include /* bind(), connect() */ -#include /* bind(), connect() */ -#include /* stat(), struct stat */ -#include /* AF_UNIX */ -#include /* AF_UNIX */ -#include /* time */ - -#include "mini-neercs.h" -#include "mini-socket.h" - -#define SIZEOF_SUN_PATH (sizeof(((struct sockaddr_un *)NULL)->sun_path)) - -#define offsetof(s, f) ((int)(intptr_t)((s *)NULL)->f) - -struct nrx_socket -{ -#if 1 - /* Linux sockets */ - int fd; - int server; - int connected; - char path[SIZEOF_SUN_PATH]; -#else -# error No socket implementation -#endif -}; - -#define QLEN 10 - -int -serv_listen(const char *name) -{ - int fd, len, err, rval; - struct sockaddr_un un; - - /* create a UNIX domain stream socket */ - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - return(-1); - unlink(name); /* in case it already exists */ - - /* fill in socket address structure */ - memset(&un, 0, sizeof(un)); - un.sun_family = AF_UNIX; - strcpy(un.sun_path, name); - len = offsetof(struct sockaddr_un, sun_path) + strlen(name); - - /* bind the name to the descriptor */ - if (bind(fd, (struct sockaddr *)&un, len) < 0) { - rval = -2; - goto errout; - } - if (listen(fd, QLEN) < 0) { /* tell kernel we're a server */ - rval = -3; - goto errout; - } - return(fd); - -errout: - err = errno; - close(fd); - errno = err; - return(rval); -} - -#define STALE 30 /* client's name can't be older than this (sec) */ - -/* - * Wait for a client connection to arrive, and accept it. - * We also obtain the client's user ID from the pathname - * that it must bind before calling us. - * Returns new fd if all OK, <0 on error - */ -int -serv_accept(int listenfd, uid_t *uidptr) -{ - int clifd, len, err, rval; - time_t staletime; - struct sockaddr_un un; - struct stat statbuf; - - len = sizeof(un); - if ((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0) - return(-1); /* often errno=EINTR, if signal caught */ - - /* obtain the client's uid from its calling address */ - len -= offsetof(struct sockaddr_un, sun_path); /* len of pathname */ - un.sun_path[len] = 0; /* null terminate */ - - if (stat(un.sun_path, &statbuf) < 0) { - rval = -2; - goto errout; - } -#ifdef S_ISSOCK /* not defined for SVR4 */ - if (S_ISSOCK(statbuf.st_mode) == 0) { - rval = -3; /* not a socket */ - goto errout; - } -#endif - if ((statbuf.st_mode & (S_IRWXG | S_IRWXO)) || - (statbuf.st_mode & S_IRWXU) != S_IRWXU) { - rval = -4; /* is not rwx------ */ - goto errout; - } - - staletime = time(NULL) - STALE; - if (statbuf.st_atime < staletime || - statbuf.st_ctime < staletime || - statbuf.st_mtime < staletime) { - rval = -5; /* i-node is too old */ - goto errout; - } - if (uidptr != NULL) - *uidptr = statbuf.st_uid; /* return uid of caller */ - unlink(un.sun_path); /* we're done with pathname now */ - return(clifd); - -errout: - err = errno; - close(clifd); - errno = err; - return(rval); -} - -#define CLI_PATH "/var/tmp/" /* +5 for pid = 14 chars */ -#define CLI_PERM S_IRWXU /* rwx for user only */ - -/* - * Create a client endpoint and connect to a server. - * Returns fd if all OK, <0 on error. - */ -int -cli_conn(const char *name) -{ - int fd, len, err, rval; - struct sockaddr_un un; - - /* create a UNIX domain stream socket */ - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - return(-1); - - /* fill socket address structure with our address */ - memset(&un, 0, sizeof(un)); - un.sun_family = AF_UNIX; - sprintf(un.sun_path, "%s%05d", CLI_PATH, getpid()); - len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path); - - unlink(un.sun_path); /* in case it already exists */ - if (bind(fd, (struct sockaddr *)&un, len) < 0) { - rval = -2; - goto errout; - } - if (chmod(un.sun_path, CLI_PERM) < 0) { - rval = -3; - goto errout; - } - /* fill socket address structure with server's address */ - memset(&un, 0, sizeof(un)); - un.sun_family = AF_UNIX; - strcpy(un.sun_path, name); - len = offsetof(struct sockaddr_un, sun_path) + strlen(name); - if (connect(fd, (struct sockaddr *)&un, len) < 0) { - rval = -4; - goto errout; - } - return(fd); - -errout: - err = errno; - close(fd); - errno = err; - return(rval); -} - -nrx_socket_t * socket_open(char const *path, int server) -{ - nrx_socket_t * sock; - struct sockaddr_un addr; - int ret, fd; - -#if 0 - fd = socket(AF_UNIX, SOCK_STREAM, 0); - //fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (fd < 0) - { - perror("socket creation"); - return NULL; - } - - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, path, SIZEOF_SUN_PATH - 1); - - if (server) - { - unlink(path); - ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); - } - else - { - ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); - } - - if (ret < 0) - { - perror(server ? "socket binding" : "socket connection"); - close(fd); - return NULL; - } - - fcntl(fd, F_SETFL, O_NONBLOCK); -#endif -if (server) - fd = serv_listen(path); -else - fd = cli_conn(path); -if (fd < 0) return NULL; - - sock = malloc(sizeof(*sock)); - sock->fd = fd; - sock->server = server; - sock->connected = 0; - strncpy(sock->path, path, SIZEOF_SUN_PATH - 1); - - return sock; -} - -int socket_select(nrx_socket_t *sock, int usecs) -{ - fd_set rfds; - struct timeval tv; - int ret; - - FD_ZERO(&rfds); - FD_SET(sock->fd, &rfds); - - tv.tv_sec = usecs / 1000000; - tv.tv_usec = usecs % 1000000; - - ret = select(sock->fd + 1, &rfds, NULL, NULL, &tv); - if (ret < 0) - return -1; - - if (FD_ISSET(sock->fd, &rfds)) - return 1; - - return 0; -} - -int socket_puts(nrx_socket_t *sock, char const *str) -{ - int ret; -fprintf(stderr, "pid %i sending %i bytes on %s: %s\n", getpid(), (int)strlen(str), sock->path, str); - ret = write(sock->fd, str, strlen(str)); - return ret; -} - -ssize_t socket_read(nrx_socket_t *sock, void *buf, size_t count) -{ - int ret; - ret = read(sock->fd, buf, count); -if (ret >= 0) ((char *)buf)[ret] = 0; -if (ret >= 0) fprintf(stderr, "pid %i recving %i bytes on %s: %s\n", getpid(), ret, sock->path, (char *)buf); - return ret; -} - -void socket_close(nrx_socket_t *sock) -{ - close(sock->fd); - if (sock->server) - unlink(sock->path); - free(sock); -} - +/* * neercs console-based window manager * Copyright (c) 2006-2011 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include /* perror() */ #include /* malloc(), free() */ #include /* unlink() */ #include /* fcntl() */ #include /* memcpy() */ #include /* select() */ #include /* bind(), connect() */ #include /* bind(), connect() */ #include /* stat(), struct stat */ #include /* AF_UNIX */ #include /* AF_UNIX */ #include /* time */ #include "mini-neercs.h" #include "mini-socket.h" #define SIZEOF_SUN_PATH (sizeof(((struct sockaddr_un *)NULL)->sun_path)) #define offsetof(s, f) ((int)(intptr_t)((s *)NULL)->f) struct nrx_socket { #if 1 /* Linux sockets */ int fd; int server; int connected; char path[SIZEOF_SUN_PATH]; #else # error No socket implementation #endif }; #define QLEN 10 int serv_listen(const char *name) { int fd, len, err, rval; struct sockaddr_un un; /* create a UNIX domain stream socket */ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) return(-1); unlink(name); /* in case it already exists */ /* fill in socket address structure */ memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; strcpy(un.sun_path, name); len = offsetof(struct sockaddr_un, sun_path) + strlen(name); /* bind the name to the descriptor */ if (bind(fd, (struct sockaddr *)&un, len) < 0) { rval = -2; goto errout; } if (listen(fd, QLEN) < 0) { /* tell kernel we're a server */ rval = -3; goto errout; } return(fd); errout: err = errno; close(fd); errno = err; return(rval); } #define STALE 30 /* client's name can't be older than this (sec) */ /* * Wait for a client connection to arrive, and accept it. * We also obtain the client's user ID from the pathname * that it must bind before calling us. * Returns new fd if all OK, <0 on error */ int serv_accept(int listenfd, uid_t *uidptr) { int clifd, len, err, rval; time_t staletime; struct sockaddr_un un; struct stat statbuf; len = sizeof(un); if ((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0) return(-1); /* often errno=EINTR, if signal caught */ /* obtain the client's uid from its calling address */ len -= offsetof(struct sockaddr_un, sun_path); /* len of pathname */ un.sun_path[len] = 0; /* null terminate */ if (stat(un.sun_path, &statbuf) < 0) { rval = -2; goto errout; } #ifdef S_ISSOCK /* not defined for SVR4 */ if (S_ISSOCK(statbuf.st_mode) == 0) { rval = -3; /* not a socket */ goto errout; } #endif if ((statbuf.st_mode & (S_IRWXG | S_IRWXO)) || (statbuf.st_mode & S_IRWXU) != S_IRWXU) { rval = -4; /* is not rwx------ */ goto errout; } staletime = time(NULL) - STALE; if (statbuf.st_atime < staletime || statbuf.st_ctime < staletime || statbuf.st_mtime < staletime) { rval = -5; /* i-node is too old */ goto errout; } if (uidptr != NULL) *uidptr = statbuf.st_uid; /* return uid of caller */ unlink(un.sun_path); /* we're done with pathname now */ return(clifd); errout: err = errno; close(clifd); errno = err; return(rval); } #define CLI_PATH "/var/tmp/" /* +5 for pid = 14 chars */ #define CLI_PERM S_IRWXU /* rwx for user only */ /* * Create a client endpoint and connect to a server. * Returns fd if all OK, <0 on error. */ int cli_conn(const char *name) { int fd, len, err, rval; struct sockaddr_un un; /* create a UNIX domain stream socket */ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) return(-1); /* fill socket address structure with our address */ memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; sprintf(un.sun_path, "%s%05d", CLI_PATH, getpid()); len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path); unlink(un.sun_path); /* in case it already exists */ if (bind(fd, (struct sockaddr *)&un, len) < 0) { rval = -2; goto errout; } if (chmod(un.sun_path, CLI_PERM) < 0) { rval = -3; goto errout; } /* fill socket address structure with server's address */ memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; strcpy(un.sun_path, name); len = offsetof(struct sockaddr_un, sun_path) + strlen(name); if (connect(fd, (struct sockaddr *)&un, len) < 0) { rval = -4; goto errout; } return(fd); errout: err = errno; close(fd); errno = err; return(rval); } nrx_socket_t * socket_open(char const *path, int server) { nrx_socket_t * sock; struct sockaddr_un addr; int ret, fd; #if 0 fd = socket(AF_UNIX, SOCK_STREAM, 0); //fd = socket(AF_UNIX, SOCK_DGRAM, 0); if (fd < 0) { perror("socket creation"); return NULL; } memset(&addr, 0, sizeof(struct sockaddr_un)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, path, SIZEOF_SUN_PATH - 1); if (server) { unlink(path); ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); } else { ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); } if (ret < 0) { perror(server ? "socket binding" : "socket connection"); close(fd); return NULL; } fcntl(fd, F_SETFL, O_NONBLOCK); #endif if (server) fd = serv_listen(path); else fd = cli_conn(path); if (fd < 0) return NULL; sock = malloc(sizeof(*sock)); sock->fd = fd; sock->server = server; sock->connected = 0; strncpy(sock->path, path, SIZEOF_SUN_PATH - 1); return sock; } int socket_select(nrx_socket_t *sock, int usecs) { fd_set rfds; struct timeval tv; int ret; FD_ZERO(&rfds); FD_SET(sock->fd, &rfds); tv.tv_sec = usecs / 1000000; tv.tv_usec = usecs % 1000000; ret = select(sock->fd + 1, &rfds, NULL, NULL, &tv); if (ret < 0) return -1; if (FD_ISSET(sock->fd, &rfds)) return 1; return 0; } int socket_puts(nrx_socket_t *sock, char const *str) { int ret; fprintf(stderr, "pid %i sending %i bytes on %s: %s\n", getpid(), (int)strlen(str), sock->path, str); ret = write(sock->fd, str, strlen(str)); return ret; } ssize_t socket_read(nrx_socket_t *sock, void *buf, size_t count) { int ret; ret = read(sock->fd, buf, count); if (ret >= 0) ((char *)buf)[ret] = 0; if (ret >= 0) fprintf(stderr, "pid %i recving %i bytes on %s: %s\n", getpid(), ret, sock->path, (char *)buf); return ret; } void socket_close(nrx_socket_t *sock) { close(sock->fd); if (sock->server) unlink(sock->path); free(sock); } \ No newline at end of file diff --git a/neercs/old/mini-socket.h b/neercs/old/mini-socket.h index bf6ef3a..2e0042c 100644 --- a/neercs/old/mini-socket.h +++ b/neercs/old/mini-socket.h @@ -1,24 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#include - -typedef struct nrx_socket nrx_socket_t; - -nrx_socket_t * socket_open(char const *path, int server); -int socket_select(nrx_socket_t *sock, int usecs); -int socket_puts(nrx_socket_t *sock, char const *str); -ssize_t socket_read(nrx_socket_t *sock, void *buf, size_t count); -void socket_close(nrx_socket_t *socket); - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #include typedef struct nrx_socket nrx_socket_t; nrx_socket_t * socket_open(char const *path, int server); int socket_select(nrx_socket_t *sock, int usecs); int socket_puts(nrx_socket_t *sock, char const *str); ssize_t socket_read(nrx_socket_t *sock, void *buf, size_t count); void socket_close(nrx_socket_t *socket); \ No newline at end of file diff --git a/neercs/old/mygetopt.c b/neercs/old/mygetopt.c index 7b779e8..677db4f 100644 --- a/neercs/old/mygetopt.c +++ b/neercs/old/mygetopt.c @@ -1,127 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -/* - * mygetopt.c: getopt_long reimplementation - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include - -#include "caca_types.h" - -#include "mygetopt.h" - -int myoptind = 1; -char *myoptarg = NULL; - -/* XXX: this getopt_long implementation should not be trusted for other - applications without any serious peer reviewing. It “just works” with - zzuf but may fail miserably in other programs. */ -int mygetopt(int argc, char *const _argv[], const char *optstring, - const struct myoption *longopts, int *longindex) -{ - char **argv = (char **)(uintptr_t) _argv; - char *flag; - int i; - - if (myoptind >= argc) - return -1; - - flag = argv[myoptind]; - - if (flag[0] == '-' && flag[1] != '-') - { - char const *tmp; - int ret = flag[1]; - - if (ret == '\0') - return -1; - - tmp = strchr(optstring, ret); - if (!tmp || ret == ':') - return '?'; - - myoptind++; - if (tmp[1] == ':') - { - if (flag[2] != '\0') - myoptarg = flag + 2; - else if (myoptind >= argc) - { - if (tmp[2] != ':') - { - fprintf(stderr, "%s: `%s' needs an argument\n", argv[0], - flag); - return -2; - } - } - else - myoptarg = argv[myoptind++]; - return ret; - } - - if (flag[2] != '\0') - { - flag[1] = '-'; - myoptind--; - argv[myoptind]++; - } - - return ret; - } - - if (flag[0] == '-' && flag[1] == '-') - { - if (flag[2] == '\0') - return -1; - - for (i = 0; longopts[i].name; i++) - { - size_t l = strlen(longopts[i].name); - - if (strncmp(flag + 2, longopts[i].name, l)) - continue; - - switch (flag[2 + l]) - { - case '=': - if (!longopts[i].has_arg) - goto bad_opt; - if (longindex) - *longindex = i; - myoptind++; - myoptarg = flag + 2 + l + 1; - return longopts[i].val; - case '\0': - if (longindex) - *longindex = i; - myoptind++; - if (longopts[i].has_arg) - myoptarg = argv[myoptind++]; - return longopts[i].val; - default: - break; - } - } - bad_opt: - fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag); - return '?'; - } - - return -1; -} +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ /* * mygetopt.c: getopt_long reimplementation */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include #include #include "caca_types.h" #include "mygetopt.h" int myoptind = 1; char *myoptarg = NULL; /* XXX: this getopt_long implementation should not be trusted for other applications without any serious peer reviewing. It “just works” with zzuf but may fail miserably in other programs. */ int mygetopt(int argc, char *const _argv[], const char *optstring, const struct myoption *longopts, int *longindex) { char **argv = (char **)(uintptr_t) _argv; char *flag; int i; if (myoptind >= argc) return -1; flag = argv[myoptind]; if (flag[0] == '-' && flag[1] != '-') { char const *tmp; int ret = flag[1]; if (ret == '\0') return -1; tmp = strchr(optstring, ret); if (!tmp || ret == ':') return '?'; myoptind++; if (tmp[1] == ':') { if (flag[2] != '\0') myoptarg = flag + 2; else if (myoptind >= argc) { if (tmp[2] != ':') { fprintf(stderr, "%s: `%s' needs an argument\n", argv[0], flag); return -2; } } else myoptarg = argv[myoptind++]; return ret; } if (flag[2] != '\0') { flag[1] = '-'; myoptind--; argv[myoptind]++; } return ret; } if (flag[0] == '-' && flag[1] == '-') { if (flag[2] == '\0') return -1; for (i = 0; longopts[i].name; i++) { size_t l = strlen(longopts[i].name); if (strncmp(flag + 2, longopts[i].name, l)) continue; switch (flag[2 + l]) { case '=': if (!longopts[i].has_arg) goto bad_opt; if (longindex) *longindex = i; myoptind++; myoptarg = flag + 2 + l + 1; return longopts[i].val; case '\0': if (longindex) *longindex = i; myoptind++; if (longopts[i].has_arg) myoptarg = argv[myoptind++]; return longopts[i].val; default: break; } } bad_opt: fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag); return '?'; } return -1; } \ No newline at end of file diff --git a/neercs/old/mygetopt.h b/neercs/old/mygetopt.h index 1f1264c..dcf32e4 100644 --- a/neercs/old/mygetopt.h +++ b/neercs/old/mygetopt.h @@ -1,30 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -/* - * mygetopt.h: getopt_long reimplementation - */ - -struct myoption -{ - const char *name; - int has_arg; - int *flag; - int val; -}; - -extern int myoptind; -extern char *myoptarg; - -int mygetopt(int, char * const[], const char *, const struct myoption *, int *); - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ /* * mygetopt.h: getopt_long reimplementation */ struct myoption { const char *name; int has_arg; int *flag; int val; }; extern int myoptind; extern char *myoptarg; int mygetopt(int, char * const[], const char *, const struct myoption *, int *); \ No newline at end of file diff --git a/neercs/old/mytrace.c b/neercs/old/mytrace.c index c70a99f..21e0668 100644 --- a/neercs/old/mytrace.c +++ b/neercs/old/mytrace.c @@ -1,792 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2008-2010 Pascal Terjan - * 2008-2010 Sam Hocevar - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include - -#if defined USE_GRAB -# include -# include -# include -# include -# include -# include -#endif - -#include "neercs.h" -#include "mytrace.h" - -#if defined USE_GRAB -static int memcpy_from_target(struct mytrace *t, - char *dest, long src, size_t n); -static int memcpy_into_target(struct mytrace *t, - long dest, char const *src, size_t n); -static long remote_syscall(struct mytrace *t, long call, - long arg1, long arg2, long arg3); -# if defined DEBUG -static void print_registers(pid_t pid); -# else -# define print_registers(x) do {} while(0) -# endif - -#define X(x) #x -#define STRINGIFY(x) X(x) - -#define SYSCALL_X86 0x80cd /* CD 80 = int $0x80 */ -#define SYSCALL_X86_NEW 0xf3eb /* EB F3 = jmp <__kernel_vsyscall+0x3> */ -#define SYSENTER 0x340f /* 0F 34 = sysenter */ -#define SYSCALL_AMD64 0x050fL /* 0F 05 = syscall */ - -#if defined __x86_64__ -# define RAX rax -# define RBX rbx -# define RCX rcx -# define RDX rdx -# define RSP rsp -# define RBP rbp -# define RIP rip -# define RDI rdi -# define RSI rsi -# define FMT "%016lx" -#else -# define RAX eax -# define RBX ebx -# define RCX ecx -# define RDX edx -# define RSP esp -# define RBP ebp -# define RIP eip -# define RDI edi -# define RSI esi -# define FMT "%08lx" -#endif - -#define MYCALL_OPEN 0 -#define MYCALL_CLOSE 1 -#define MYCALL_WRITE 2 -#define MYCALL_DUP2 3 -#define MYCALL_SETPGID 4 -#define MYCALL_SETSID 5 -#define MYCALL_KILL 6 -#define MYCALL_FORK 7 -#define MYCALL_EXIT 8 -#define MYCALL_EXECVE 9 -#define MYCALL_IOCTL 10 - -#if defined __x86_64__ -/* from unistd_32.h on an amd64 system */ -int syscalls32[] = { 5, 6, 4, 63, 57, 66, 37, 2, 1, 11, 54 }; - -int syscalls64[] = -#else -int syscalls32[] = -#endif -{ SYS_open, SYS_close, SYS_write, SYS_dup2, SYS_setpgid, SYS_setsid, - SYS_kill, SYS_fork, SYS_exit, SYS_execve, SYS_ioctl -}; - -char const *syscallnames[] = - { "open", "close", "write", "dup2", "setpgid", "setsid", "kill", "fork", - "exit", "execve", "ioctl" -}; - -#endif /* USE_GRAB */ - -struct mytrace -{ - pid_t pid, child; -}; - -struct mytrace *mytrace_attach(long int pid) -{ -#if defined USE_GRAB - struct mytrace *t; - int status; - - if (ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) - { - perror("PTRACE_ATTACH (attach)"); - return NULL; - } - if (waitpid(pid, &status, 0) < 0) - { - perror("waitpid"); - return NULL; - } - if (!WIFSTOPPED(status)) - { - fprintf(stderr, "traced process was not stopped\n"); - ptrace(PTRACE_DETACH, pid, 0, 0); - return NULL; - } - - t = malloc(sizeof(struct mytrace)); - t->pid = pid; - t->child = 0; - - return t; -#else - errno = ENOSYS; - return NULL; -#endif -} - -struct mytrace *mytrace_fork(struct mytrace *t) -{ -#if defined USE_GRAB - struct mytrace *child; - - ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEFORK); - remote_syscall(t, MYCALL_FORK, 0, 0, 0); - waitpid(t->child, NULL, 0); - - child = malloc(sizeof(struct mytrace)); - child->pid = t->child; - child->child = 0; - - return child; -#else - errno = ENOSYS; - return NULL; -#endif -} - -int mytrace_detach(struct mytrace *t) -{ -#if defined USE_GRAB - ptrace(PTRACE_DETACH, t->pid, 0, 0); - free(t); - - return 0; -#else - errno = ENOSYS; - return -1; -#endif -} - -long mytrace_getpid(struct mytrace *t) -{ -#if defined USE_GRAB - return t->pid; -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_open(struct mytrace *t, char const *path, int mode) -{ -#if defined USE_GRAB - char backup_data[4096]; - struct user_regs_struct regs; - size_t size = strlen(path) + 1; - int ret, err; - - if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) - { - perror("PTRACE_GETREGS (open)\n"); - return -1; - } - - /* Backup the data that we will use */ - if (memcpy_from_target(t, backup_data, regs.RSP, size) < 0) - return -1; - - memcpy_into_target(t, regs.RSP, path, size); - - ret = remote_syscall(t, MYCALL_OPEN, regs.RSP, O_RDWR, 0755); - err = errno; - - /* Restore the data */ - memcpy_into_target(t, regs.RSP, backup_data, size); - - errno = err; - return ret; -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_close(struct mytrace *t, int fd) -{ -#if defined USE_GRAB - return remote_syscall(t, MYCALL_CLOSE, fd, 0, 0); -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_write(struct mytrace *t, int fd, char const *data, size_t len) -{ -#if defined USE_GRAB - struct user_regs_struct regs; - char *backup_data; - int ret, err; - - if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) - { - perror("PTRACE_GETREGS (write)\n"); - return -1; - } - - backup_data = malloc(len); - - /* Backup the data that we will use */ - if (memcpy_from_target(t, backup_data, regs.RSP, len) < 0) - return -1; - - memcpy_into_target(t, regs.RSP, data, len); - - ret = remote_syscall(t, MYCALL_WRITE, fd, regs.RSP, len); - err = errno; - - /* Restore the data */ - memcpy_into_target(t, regs.RSP, backup_data, len); - - errno = err; - return ret; -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_dup2(struct mytrace *t, int oldfd, int newfd) -{ -#if defined USE_GRAB - return remote_syscall(t, MYCALL_DUP2, oldfd, newfd, 0); -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_setpgid(struct mytrace *t, long pid, long pgid) -{ -#if defined USE_GRAB - return remote_syscall(t, MYCALL_SETPGID, pid, pgid, 0); -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_setsid(struct mytrace *t) -{ -#if defined USE_GRAB - return remote_syscall(t, MYCALL_SETSID, 0, 0, 0); -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_kill(struct mytrace *t, long pid, int sig) -{ -#if defined USE_GRAB - return remote_syscall(t, MYCALL_KILL, pid, sig, 0); -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_exit(struct mytrace *t, int status) -{ -#if defined USE_GRAB - ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEEXIT); - return remote_syscall(t, MYCALL_EXIT, status, 0, 0); -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_exec(struct mytrace *t, char const *command) -{ -#if defined USE_GRAB - struct user_regs_struct regs; - char *env, *p; - long p2, envaddr, argvaddr, envptraddr; - char envpath[PATH_MAX + 1]; - ssize_t envsize = 16 * 1024; - int ret, fd, l, l2; - char *nullp = NULL; - ssize_t r; - - ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEEXEC); - - if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) - { - perror("PTRACE_GETREGS (exec)\n"); - return -1; - } - - debug("PTRACE_GETREGS done"); - env = malloc(envsize); - if (!env) - return -1; - - snprintf(envpath, PATH_MAX, "/proc/%d/environ", t->pid); - - fd = open(envpath, O_RDONLY); - if (fd == -1) - return -1; - r = read(fd, env, envsize); - close(fd); - if (r == -1) - return -1; - while (r == envsize) - { - free(env); - env = malloc(envsize); - if (!env) - return -1; - fd = open(envpath, O_RDONLY); - r = read(fd, env, envsize); - close(fd); - if (r == -1) - return -1; - } - envsize = r; - l2 = sizeof(char *); /* Size of a pointer */ - p2 = regs.RSP; - - /* First argument is the command string */ - l = strlen(command) + 1; - memcpy_into_target(t, p2, command, l); - p2 += l; - - /* Second argument is argv */ - argvaddr = p2; - /* argv[0] is a pointer to the command string */ - memcpy_into_target(t, p2, (char *)®s.RSP, l2); - p2 += l2; - /* Then follows a NULL pointer */ - memcpy_into_target(t, p2, (char *)&nullp, l2); - p2 += l2; - - /* Third argument is the environment */ - /* First, copy all the strings */ - memcpy_into_target(t, p2, env, envsize); - envaddr = p2; - p2 += envsize; - /* Then write an array of pointers to the strings */ - envptraddr = p2; - p = env; - while (p < env + envsize) - { - long diffp = p - env + envaddr; - memcpy_into_target(t, p2, (char *)&diffp, l2); - p2 += l2; - p += strlen(p) + 1; - } - /* And have a NULL pointer at the end of the array */ - memcpy_into_target(t, p2, (char *)&nullp, l2); - free(env); - - ret = remote_syscall(t, MYCALL_EXECVE, regs.RSP, argvaddr, envptraddr); - - return ret; -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_tcgets(struct mytrace *t, int fd, struct termios *tos) -{ -#if defined USE_GRAB - char backup_data[4096]; - struct user_regs_struct regs; - size_t size = sizeof(struct termios); - int ret, err; - - if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) - { - perror("PTRACE_GETREGS (tcgets)\n"); - return -1; - } - - /* Backup the data that we will use */ - if (memcpy_from_target(t, backup_data, regs.RSP, size) < 0) - return -1; - - ret = remote_syscall(t, MYCALL_IOCTL, fd, TCGETS, regs.RSP); - err = errno; - - memcpy_from_target(t, (char *)tos, regs.RSP, size); - - /* Restore the data */ - memcpy_into_target(t, regs.RSP, backup_data, size); - - errno = err; - return ret; -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_tcsets(struct mytrace *t, int fd, struct termios *tos) -{ -#if defined USE_GRAB - char backup_data[4096]; - struct user_regs_struct regs; - size_t size = sizeof(struct termios); - int ret, err; - - if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) - { - perror("PTRACE_GETREGS (tcsets)\n"); - return -1; - } - - /* Backup the data that we will use */ - if (memcpy_from_target(t, backup_data, regs.RSP, size) < 0) - return -1; - - memcpy_into_target(t, regs.RSP, (char *)tos, size); - - ret = remote_syscall(t, MYCALL_IOCTL, fd, TCSETS, regs.RSP); - err = errno; - - /* Restore the data */ - memcpy_into_target(t, regs.RSP, backup_data, size); - - errno = err; - return ret; -#else - errno = ENOSYS; - return -1; -#endif -} - -int mytrace_sctty(struct mytrace *t, int fd) -{ -#if defined USE_GRAB - ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEEXIT); - return remote_syscall(t, MYCALL_IOCTL, fd, TIOCSCTTY, 0); -#else - errno = ENOSYS; - return -1; -#endif -} - -/* - * XXX: the following functions are local - */ - -#if defined USE_GRAB -static int memcpy_from_target(struct mytrace *t, - char *dest, long src, size_t n) -{ - static int const align = sizeof(long) - 1; - - while (n) - { - long data; - size_t todo = sizeof(long) - (src & align); - - if (n < todo) - todo = n; - - data = ptrace(PTRACE_PEEKTEXT, t->pid, src - (src & align), 0); - if (errno) - { - perror("ptrace_peektext (memcpy_from_target)"); - return -1; - } - memcpy(dest, (char *)&data + (src & align), todo); - - dest += todo; - src += todo; - n -= todo; - } - - return 0; -} - -static int memcpy_into_target(struct mytrace *t, - long dest, char const *src, size_t n) -{ - static int const align = sizeof(long) - 1; - - while (n) - { - long data; - size_t todo = sizeof(long) - (dest & align); - - if (n < todo) - todo = n; - if (todo != sizeof(long)) - { - data = ptrace(PTRACE_PEEKTEXT, t->pid, dest - (dest & align), 0); - if (errno) - { - perror("ptrace_peektext (memcpy_into_target)"); - return -1; - } - } - - memcpy((char *)&data + (dest & align), src, todo); - if (ptrace(PTRACE_POKETEXT, t->pid, dest - (dest & align), data) < 0) - { - perror("ptrace_poketext (memcpy_into_target)"); - return -1; - } - - src += todo; - dest += todo; - n -= todo; - } - - return 0; -} - -static long remote_syscall(struct mytrace *t, long call, - long arg1, long arg2, long arg3) -{ - /* Method for remote syscall: - wait until the traced application exits - from a syscall - save registers - rewind eip/rip to point on the - syscall instruction - single step: execute syscall instruction - - retrieve resulting registers - restore registers */ - struct user_regs_struct regs, oldregs; - long oinst; - int bits; - int offset = 2; - - if (call < 0 - || call >= (long)(sizeof(syscallnames) / sizeof(*syscallnames))) - { - fprintf(stderr, "unknown remote syscall %li\n", call); - return -1; - } - - debug("remote syscall %s(0x%lx, 0x%lx, 0x%lx)", - syscallnames[call], arg1, arg2, arg3); - -#if defined __x86_64__ - bits = 64; -#else - bits = 32; -#endif - - for (;;) - { - if (ptrace(PTRACE_GETREGS, t->pid, NULL, &oldregs) < 0) - { - perror("PTRACE_GETREGS (syscall 1)\n"); - return -1; - } - - oinst = ptrace(PTRACE_PEEKTEXT, t->pid, oldregs.RIP - 2, 0) & 0xffff; - -#if defined __x86_64__ - if (oinst == SYSCALL_AMD64) - break; -#endif - if (oinst == SYSCALL_X86 || oinst == SYSCALL_X86_NEW) - { - bits = 32; - break; - } - - if (ptrace(PTRACE_SYSCALL, t->pid, NULL, 0) < 0) - { - perror("ptrace_syscall (1)"); - return -1; - } - waitpid(t->pid, NULL, 0); - if (ptrace(PTRACE_SYSCALL, t->pid, NULL, 0) < 0) - { - perror("ptrace_syscall (2)"); - return -1; - } - waitpid(t->pid, NULL, 0); - } - - print_registers(t->pid); - - if (oinst == SYSCALL_X86_NEW) - { - /* Get back to sysenter */ - while ((ptrace(PTRACE_PEEKTEXT, t->pid, oldregs.RIP - offset, 0) & - 0xffff) != 0x340f) - offset++; - oldregs.RBP = oldregs.RSP; - } - - regs = oldregs; - regs.RIP = regs.RIP - offset; -#if defined __x86_64__ - if (bits == 64) - { - regs.RAX = syscalls64[call]; - regs.RDI = arg1; - regs.RSI = arg2; - regs.RDX = arg3; - } - else -#endif - { - regs.RAX = syscalls32[call]; - regs.RBX = arg1; - regs.RCX = arg2; - regs.RDX = arg3; - } - - if (ptrace(PTRACE_SETREGS, t->pid, NULL, ®s) < 0) - { - perror("PTRACE_SETREGS (syscall 1)\n"); - return -1; - } - - for (;;) - { - int status; - - print_registers(t->pid); - - if (ptrace(PTRACE_SINGLESTEP, t->pid, NULL, NULL) < 0) - { - perror("PTRACE_SINGLESTEP (syscall)\n"); - return -1; - } - waitpid(t->pid, &status, 0); - - if (WIFEXITED(status)) - return 0; - - if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGTRAP) - continue; - - /* Fuck Linux: there is no macro for this */ - switch ((status >> 16) & 0xffff) - { - case PTRACE_EVENT_FORK: - if (ptrace(PTRACE_GETEVENTMSG, t->pid, 0, &t->child) < 0) - { - perror("PTRACE_GETEVENTMSG (syscall)\n"); - return -1; - } - debug("PTRACE_GETEVENTMSG %d", t->child); - continue; - case PTRACE_EVENT_EXIT: - debug("PTRACE_EVENT_EXIT"); - /* The process is about to exit, don't do anything else */ - return 0; - case PTRACE_EVENT_EXEC: - debug("PTRACE_EVENT_EXEC"); - return 0; - } - - break; - } - - print_registers(t->pid); - - if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) - { - perror("PTRACE_GETREGS (syscall 2)\n"); - return -1; - } - - if (ptrace(PTRACE_SETREGS, t->pid, NULL, &oldregs) < 0) - { - perror("PTRACE_SETREGS (syscall 2)\n"); - return -1; - } - print_registers(t->pid); - - debug("syscall %s returned %ld", syscallnames[call], regs.RAX); - - if ((long)regs.RAX < 0) - { - errno = -(long)regs.RAX; - perror("syscall"); - return -1; - } - - return regs.RAX; -} - -/* For debugging purposes only. Prints register and stack information. */ -#if defined DEBUG -static void print_registers(pid_t pid) -{ - union - { - long int l; - unsigned char data[sizeof(long int)]; - } inst; - struct user_regs_struct regs; - int i; - - if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) - { - perror("PTRACE_GETREGS (syscall 2)"); - exit(errno); - } - - fprintf(stderr, " / %s: " FMT " ", STRINGIFY(RAX), regs.RAX); - fprintf(stderr, "%s: " FMT "\n", STRINGIFY(RBX), regs.RBX); - fprintf(stderr, " | %s: " FMT " ", STRINGIFY(RCX), regs.RCX); - fprintf(stderr, "%s: " FMT "\n", STRINGIFY(RDX), regs.RDX); - fprintf(stderr, " | %s: " FMT " ", STRINGIFY(RDI), regs.RDI); - fprintf(stderr, "%s: " FMT "\n", STRINGIFY(RSI), regs.RSI); - fprintf(stderr, " | %s: " FMT " ", STRINGIFY(RSP), regs.RSP); - fprintf(stderr, "%s: " FMT "\n", STRINGIFY(RIP), regs.RIP); - - inst.l = ptrace(PTRACE_PEEKTEXT, pid, regs.RIP - 4, 0); - fprintf(stderr, " | code: ... %02x %02x %02x %02x <---> ", - inst.data[0], inst.data[1], inst.data[2], inst.data[3]); - inst.l = ptrace(PTRACE_PEEKTEXT, pid, regs.RIP, 0); - fprintf(stderr, "%02x %02x %02x %02x ...\n", - inst.data[0], inst.data[1], inst.data[2], inst.data[3]); - - fprintf(stderr, " \\ stack: ... "); - for (i = -16; i < 24; i += sizeof(long)) - { - inst.l = ptrace(PTRACE_PEEKDATA, pid, regs.RSP + i, 0); -#if defined __x86_64__ - fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x %02x ", - inst.data[0], inst.data[1], inst.data[2], inst.data[3], - inst.data[4], inst.data[5], inst.data[6], inst.data[7]); -#else - fprintf(stderr, "%02x %02x %02x %02x ", - inst.data[0], inst.data[1], inst.data[2], inst.data[3]); -#endif - if (i == 0) - fprintf(stderr, "[%s] ", STRINGIFY(RSP)); - } - fprintf(stderr, "...\n"); -} -#endif /* DEBUG */ - -#endif /* USE_GRAB */ - -#endif /* _WIN32 */ - +/* * neercs console-based window manager * Copyright (c) 2008-2010 Pascal Terjan * 2008-2010 Sam Hocevar * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #if defined USE_GRAB # include # include # include # include # include # include #endif #include "neercs.h" #include "mytrace.h" #if defined USE_GRAB static int memcpy_from_target(struct mytrace *t, char *dest, long src, size_t n); static int memcpy_into_target(struct mytrace *t, long dest, char const *src, size_t n); static long remote_syscall(struct mytrace *t, long call, long arg1, long arg2, long arg3); # if defined DEBUG static void print_registers(pid_t pid); # else # define print_registers(x) do {} while(0) # endif #define X(x) #x #define STRINGIFY(x) X(x) #define SYSCALL_X86 0x80cd /* CD 80 = int $0x80 */ #define SYSCALL_X86_NEW 0xf3eb /* EB F3 = jmp <__kernel_vsyscall+0x3> */ #define SYSENTER 0x340f /* 0F 34 = sysenter */ #define SYSCALL_AMD64 0x050fL /* 0F 05 = syscall */ #if defined __x86_64__ # define RAX rax # define RBX rbx # define RCX rcx # define RDX rdx # define RSP rsp # define RBP rbp # define RIP rip # define RDI rdi # define RSI rsi # define FMT "%016lx" #else # define RAX eax # define RBX ebx # define RCX ecx # define RDX edx # define RSP esp # define RBP ebp # define RIP eip # define RDI edi # define RSI esi # define FMT "%08lx" #endif #define MYCALL_OPEN 0 #define MYCALL_CLOSE 1 #define MYCALL_WRITE 2 #define MYCALL_DUP2 3 #define MYCALL_SETPGID 4 #define MYCALL_SETSID 5 #define MYCALL_KILL 6 #define MYCALL_FORK 7 #define MYCALL_EXIT 8 #define MYCALL_EXECVE 9 #define MYCALL_IOCTL 10 #if defined __x86_64__ /* from unistd_32.h on an amd64 system */ int syscalls32[] = { 5, 6, 4, 63, 57, 66, 37, 2, 1, 11, 54 }; int syscalls64[] = #else int syscalls32[] = #endif { SYS_open, SYS_close, SYS_write, SYS_dup2, SYS_setpgid, SYS_setsid, SYS_kill, SYS_fork, SYS_exit, SYS_execve, SYS_ioctl }; char const *syscallnames[] = { "open", "close", "write", "dup2", "setpgid", "setsid", "kill", "fork", "exit", "execve", "ioctl" }; #endif /* USE_GRAB */ struct mytrace { pid_t pid, child; }; struct mytrace *mytrace_attach(long int pid) { #if defined USE_GRAB struct mytrace *t; int status; if (ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) { perror("PTRACE_ATTACH (attach)"); return NULL; } if (waitpid(pid, &status, 0) < 0) { perror("waitpid"); return NULL; } if (!WIFSTOPPED(status)) { fprintf(stderr, "traced process was not stopped\n"); ptrace(PTRACE_DETACH, pid, 0, 0); return NULL; } t = malloc(sizeof(struct mytrace)); t->pid = pid; t->child = 0; return t; #else errno = ENOSYS; return NULL; #endif } struct mytrace *mytrace_fork(struct mytrace *t) { #if defined USE_GRAB struct mytrace *child; ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEFORK); remote_syscall(t, MYCALL_FORK, 0, 0, 0); waitpid(t->child, NULL, 0); child = malloc(sizeof(struct mytrace)); child->pid = t->child; child->child = 0; return child; #else errno = ENOSYS; return NULL; #endif } int mytrace_detach(struct mytrace *t) { #if defined USE_GRAB ptrace(PTRACE_DETACH, t->pid, 0, 0); free(t); return 0; #else errno = ENOSYS; return -1; #endif } long mytrace_getpid(struct mytrace *t) { #if defined USE_GRAB return t->pid; #else errno = ENOSYS; return -1; #endif } int mytrace_open(struct mytrace *t, char const *path, int mode) { #if defined USE_GRAB char backup_data[4096]; struct user_regs_struct regs; size_t size = strlen(path) + 1; int ret, err; if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) { perror("PTRACE_GETREGS (open)\n"); return -1; } /* Backup the data that we will use */ if (memcpy_from_target(t, backup_data, regs.RSP, size) < 0) return -1; memcpy_into_target(t, regs.RSP, path, size); ret = remote_syscall(t, MYCALL_OPEN, regs.RSP, O_RDWR, 0755); err = errno; /* Restore the data */ memcpy_into_target(t, regs.RSP, backup_data, size); errno = err; return ret; #else errno = ENOSYS; return -1; #endif } int mytrace_close(struct mytrace *t, int fd) { #if defined USE_GRAB return remote_syscall(t, MYCALL_CLOSE, fd, 0, 0); #else errno = ENOSYS; return -1; #endif } int mytrace_write(struct mytrace *t, int fd, char const *data, size_t len) { #if defined USE_GRAB struct user_regs_struct regs; char *backup_data; int ret, err; if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) { perror("PTRACE_GETREGS (write)\n"); return -1; } backup_data = malloc(len); /* Backup the data that we will use */ if (memcpy_from_target(t, backup_data, regs.RSP, len) < 0) return -1; memcpy_into_target(t, regs.RSP, data, len); ret = remote_syscall(t, MYCALL_WRITE, fd, regs.RSP, len); err = errno; /* Restore the data */ memcpy_into_target(t, regs.RSP, backup_data, len); errno = err; return ret; #else errno = ENOSYS; return -1; #endif } int mytrace_dup2(struct mytrace *t, int oldfd, int newfd) { #if defined USE_GRAB return remote_syscall(t, MYCALL_DUP2, oldfd, newfd, 0); #else errno = ENOSYS; return -1; #endif } int mytrace_setpgid(struct mytrace *t, long pid, long pgid) { #if defined USE_GRAB return remote_syscall(t, MYCALL_SETPGID, pid, pgid, 0); #else errno = ENOSYS; return -1; #endif } int mytrace_setsid(struct mytrace *t) { #if defined USE_GRAB return remote_syscall(t, MYCALL_SETSID, 0, 0, 0); #else errno = ENOSYS; return -1; #endif } int mytrace_kill(struct mytrace *t, long pid, int sig) { #if defined USE_GRAB return remote_syscall(t, MYCALL_KILL, pid, sig, 0); #else errno = ENOSYS; return -1; #endif } int mytrace_exit(struct mytrace *t, int status) { #if defined USE_GRAB ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEEXIT); return remote_syscall(t, MYCALL_EXIT, status, 0, 0); #else errno = ENOSYS; return -1; #endif } int mytrace_exec(struct mytrace *t, char const *command) { #if defined USE_GRAB struct user_regs_struct regs; char *env, *p; long p2, envaddr, argvaddr, envptraddr; char envpath[PATH_MAX + 1]; ssize_t envsize = 16 * 1024; int ret, fd, l, l2; char *nullp = NULL; ssize_t r; ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEEXEC); if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) { perror("PTRACE_GETREGS (exec)\n"); return -1; } debug("PTRACE_GETREGS done"); env = malloc(envsize); if (!env) return -1; snprintf(envpath, PATH_MAX, "/proc/%d/environ", t->pid); fd = open(envpath, O_RDONLY); if (fd == -1) return -1; r = read(fd, env, envsize); close(fd); if (r == -1) return -1; while (r == envsize) { free(env); env = malloc(envsize); if (!env) return -1; fd = open(envpath, O_RDONLY); r = read(fd, env, envsize); close(fd); if (r == -1) return -1; } envsize = r; l2 = sizeof(char *); /* Size of a pointer */ p2 = regs.RSP; /* First argument is the command string */ l = strlen(command) + 1; memcpy_into_target(t, p2, command, l); p2 += l; /* Second argument is argv */ argvaddr = p2; /* argv[0] is a pointer to the command string */ memcpy_into_target(t, p2, (char *)®s.RSP, l2); p2 += l2; /* Then follows a NULL pointer */ memcpy_into_target(t, p2, (char *)&nullp, l2); p2 += l2; /* Third argument is the environment */ /* First, copy all the strings */ memcpy_into_target(t, p2, env, envsize); envaddr = p2; p2 += envsize; /* Then write an array of pointers to the strings */ envptraddr = p2; p = env; while (p < env + envsize) { long diffp = p - env + envaddr; memcpy_into_target(t, p2, (char *)&diffp, l2); p2 += l2; p += strlen(p) + 1; } /* And have a NULL pointer at the end of the array */ memcpy_into_target(t, p2, (char *)&nullp, l2); free(env); ret = remote_syscall(t, MYCALL_EXECVE, regs.RSP, argvaddr, envptraddr); return ret; #else errno = ENOSYS; return -1; #endif } int mytrace_tcgets(struct mytrace *t, int fd, struct termios *tos) { #if defined USE_GRAB char backup_data[4096]; struct user_regs_struct regs; size_t size = sizeof(struct termios); int ret, err; if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) { perror("PTRACE_GETREGS (tcgets)\n"); return -1; } /* Backup the data that we will use */ if (memcpy_from_target(t, backup_data, regs.RSP, size) < 0) return -1; ret = remote_syscall(t, MYCALL_IOCTL, fd, TCGETS, regs.RSP); err = errno; memcpy_from_target(t, (char *)tos, regs.RSP, size); /* Restore the data */ memcpy_into_target(t, regs.RSP, backup_data, size); errno = err; return ret; #else errno = ENOSYS; return -1; #endif } int mytrace_tcsets(struct mytrace *t, int fd, struct termios *tos) { #if defined USE_GRAB char backup_data[4096]; struct user_regs_struct regs; size_t size = sizeof(struct termios); int ret, err; if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) { perror("PTRACE_GETREGS (tcsets)\n"); return -1; } /* Backup the data that we will use */ if (memcpy_from_target(t, backup_data, regs.RSP, size) < 0) return -1; memcpy_into_target(t, regs.RSP, (char *)tos, size); ret = remote_syscall(t, MYCALL_IOCTL, fd, TCSETS, regs.RSP); err = errno; /* Restore the data */ memcpy_into_target(t, regs.RSP, backup_data, size); errno = err; return ret; #else errno = ENOSYS; return -1; #endif } int mytrace_sctty(struct mytrace *t, int fd) { #if defined USE_GRAB ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEEXIT); return remote_syscall(t, MYCALL_IOCTL, fd, TIOCSCTTY, 0); #else errno = ENOSYS; return -1; #endif } /* * XXX: the following functions are local */ #if defined USE_GRAB static int memcpy_from_target(struct mytrace *t, char *dest, long src, size_t n) { static int const align = sizeof(long) - 1; while (n) { long data; size_t todo = sizeof(long) - (src & align); if (n < todo) todo = n; data = ptrace(PTRACE_PEEKTEXT, t->pid, src - (src & align), 0); if (errno) { perror("ptrace_peektext (memcpy_from_target)"); return -1; } memcpy(dest, (char *)&data + (src & align), todo); dest += todo; src += todo; n -= todo; } return 0; } static int memcpy_into_target(struct mytrace *t, long dest, char const *src, size_t n) { static int const align = sizeof(long) - 1; while (n) { long data; size_t todo = sizeof(long) - (dest & align); if (n < todo) todo = n; if (todo != sizeof(long)) { data = ptrace(PTRACE_PEEKTEXT, t->pid, dest - (dest & align), 0); if (errno) { perror("ptrace_peektext (memcpy_into_target)"); return -1; } } memcpy((char *)&data + (dest & align), src, todo); if (ptrace(PTRACE_POKETEXT, t->pid, dest - (dest & align), data) < 0) { perror("ptrace_poketext (memcpy_into_target)"); return -1; } src += todo; dest += todo; n -= todo; } return 0; } static long remote_syscall(struct mytrace *t, long call, long arg1, long arg2, long arg3) { /* Method for remote syscall: - wait until the traced application exits from a syscall - save registers - rewind eip/rip to point on the syscall instruction - single step: execute syscall instruction - retrieve resulting registers - restore registers */ struct user_regs_struct regs, oldregs; long oinst; int bits; int offset = 2; if (call < 0 || call >= (long)(sizeof(syscallnames) / sizeof(*syscallnames))) { fprintf(stderr, "unknown remote syscall %li\n", call); return -1; } debug("remote syscall %s(0x%lx, 0x%lx, 0x%lx)", syscallnames[call], arg1, arg2, arg3); #if defined __x86_64__ bits = 64; #else bits = 32; #endif for (;;) { if (ptrace(PTRACE_GETREGS, t->pid, NULL, &oldregs) < 0) { perror("PTRACE_GETREGS (syscall 1)\n"); return -1; } oinst = ptrace(PTRACE_PEEKTEXT, t->pid, oldregs.RIP - 2, 0) & 0xffff; #if defined __x86_64__ if (oinst == SYSCALL_AMD64) break; #endif if (oinst == SYSCALL_X86 || oinst == SYSCALL_X86_NEW) { bits = 32; break; } if (ptrace(PTRACE_SYSCALL, t->pid, NULL, 0) < 0) { perror("ptrace_syscall (1)"); return -1; } waitpid(t->pid, NULL, 0); if (ptrace(PTRACE_SYSCALL, t->pid, NULL, 0) < 0) { perror("ptrace_syscall (2)"); return -1; } waitpid(t->pid, NULL, 0); } print_registers(t->pid); if (oinst == SYSCALL_X86_NEW) { /* Get back to sysenter */ while ((ptrace(PTRACE_PEEKTEXT, t->pid, oldregs.RIP - offset, 0) & 0xffff) != 0x340f) offset++; oldregs.RBP = oldregs.RSP; } regs = oldregs; regs.RIP = regs.RIP - offset; #if defined __x86_64__ if (bits == 64) { regs.RAX = syscalls64[call]; regs.RDI = arg1; regs.RSI = arg2; regs.RDX = arg3; } else #endif { regs.RAX = syscalls32[call]; regs.RBX = arg1; regs.RCX = arg2; regs.RDX = arg3; } if (ptrace(PTRACE_SETREGS, t->pid, NULL, ®s) < 0) { perror("PTRACE_SETREGS (syscall 1)\n"); return -1; } for (;;) { int status; print_registers(t->pid); if (ptrace(PTRACE_SINGLESTEP, t->pid, NULL, NULL) < 0) { perror("PTRACE_SINGLESTEP (syscall)\n"); return -1; } waitpid(t->pid, &status, 0); if (WIFEXITED(status)) return 0; if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGTRAP) continue; /* Fuck Linux: there is no macro for this */ switch ((status >> 16) & 0xffff) { case PTRACE_EVENT_FORK: if (ptrace(PTRACE_GETEVENTMSG, t->pid, 0, &t->child) < 0) { perror("PTRACE_GETEVENTMSG (syscall)\n"); return -1; } debug("PTRACE_GETEVENTMSG %d", t->child); continue; case PTRACE_EVENT_EXIT: debug("PTRACE_EVENT_EXIT"); /* The process is about to exit, don't do anything else */ return 0; case PTRACE_EVENT_EXEC: debug("PTRACE_EVENT_EXEC"); return 0; } break; } print_registers(t->pid); if (ptrace(PTRACE_GETREGS, t->pid, NULL, ®s) < 0) { perror("PTRACE_GETREGS (syscall 2)\n"); return -1; } if (ptrace(PTRACE_SETREGS, t->pid, NULL, &oldregs) < 0) { perror("PTRACE_SETREGS (syscall 2)\n"); return -1; } print_registers(t->pid); debug("syscall %s returned %ld", syscallnames[call], regs.RAX); if ((long)regs.RAX < 0) { errno = -(long)regs.RAX; perror("syscall"); return -1; } return regs.RAX; } /* For debugging purposes only. Prints register and stack information. */ #if defined DEBUG static void print_registers(pid_t pid) { union { long int l; unsigned char data[sizeof(long int)]; } inst; struct user_regs_struct regs; int i; if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) { perror("PTRACE_GETREGS (syscall 2)"); exit(errno); } fprintf(stderr, " / %s: " FMT " ", STRINGIFY(RAX), regs.RAX); fprintf(stderr, "%s: " FMT "\n", STRINGIFY(RBX), regs.RBX); fprintf(stderr, " | %s: " FMT " ", STRINGIFY(RCX), regs.RCX); fprintf(stderr, "%s: " FMT "\n", STRINGIFY(RDX), regs.RDX); fprintf(stderr, " | %s: " FMT " ", STRINGIFY(RDI), regs.RDI); fprintf(stderr, "%s: " FMT "\n", STRINGIFY(RSI), regs.RSI); fprintf(stderr, " | %s: " FMT " ", STRINGIFY(RSP), regs.RSP); fprintf(stderr, "%s: " FMT "\n", STRINGIFY(RIP), regs.RIP); inst.l = ptrace(PTRACE_PEEKTEXT, pid, regs.RIP - 4, 0); fprintf(stderr, " | code: ... %02x %02x %02x %02x <---> ", inst.data[0], inst.data[1], inst.data[2], inst.data[3]); inst.l = ptrace(PTRACE_PEEKTEXT, pid, regs.RIP, 0); fprintf(stderr, "%02x %02x %02x %02x ...\n", inst.data[0], inst.data[1], inst.data[2], inst.data[3]); fprintf(stderr, " \\ stack: ... "); for (i = -16; i < 24; i += sizeof(long)) { inst.l = ptrace(PTRACE_PEEKDATA, pid, regs.RSP + i, 0); #if defined __x86_64__ fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x %02x ", inst.data[0], inst.data[1], inst.data[2], inst.data[3], inst.data[4], inst.data[5], inst.data[6], inst.data[7]); #else fprintf(stderr, "%02x %02x %02x %02x ", inst.data[0], inst.data[1], inst.data[2], inst.data[3]); #endif if (i == 0) fprintf(stderr, "[%s] ", STRINGIFY(RSP)); } fprintf(stderr, "...\n"); } #endif /* DEBUG */ #endif /* USE_GRAB */ #endif /* _WIN32 */ \ No newline at end of file diff --git a/neercs/old/mytrace.h b/neercs/old/mytrace.h index f186cd5..8fe5ac5 100644 --- a/neercs/old/mytrace.h +++ b/neercs/old/mytrace.h @@ -1,37 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2008-2010 Sam Hocevar - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if !defined _WIN32 - -#include - -struct mytrace; - -struct mytrace* mytrace_attach(long int pid); -struct mytrace* mytrace_fork(struct mytrace *t); -int mytrace_detach(struct mytrace *t); -long mytrace_getpid(struct mytrace *t); - -int mytrace_open(struct mytrace *t, char const *path, int mode); -int mytrace_write(struct mytrace *t, int fd, char const *data, size_t len); -int mytrace_close(struct mytrace *t, int fd); -int mytrace_dup2(struct mytrace *t, int oldfd, int newfd); -int mytrace_setpgid(struct mytrace *t, long pid, long pgid); -int mytrace_setsid(struct mytrace *t); -int mytrace_kill(struct mytrace *t, long pid, int sig); -int mytrace_exit(struct mytrace *t, int status); -int mytrace_exec(struct mytrace *t, char const *command); -int mytrace_tcgets(struct mytrace *t, int fd, struct termios *tos); -int mytrace_tcsets(struct mytrace *t, int fd, struct termios *tos); -int mytrace_sctty(struct mytrace *t, int fd); - -#endif +/* * neercs console-based window manager * Copyright (c) 2008-2010 Sam Hocevar * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if !defined _WIN32 #include struct mytrace; struct mytrace* mytrace_attach(long int pid); struct mytrace* mytrace_fork(struct mytrace *t); int mytrace_detach(struct mytrace *t); long mytrace_getpid(struct mytrace *t); int mytrace_open(struct mytrace *t, char const *path, int mode); int mytrace_write(struct mytrace *t, int fd, char const *data, size_t len); int mytrace_close(struct mytrace *t, int fd); int mytrace_dup2(struct mytrace *t, int oldfd, int newfd); int mytrace_setpgid(struct mytrace *t, long pid, long pgid); int mytrace_setsid(struct mytrace *t); int mytrace_kill(struct mytrace *t, long pid, int sig); int mytrace_exit(struct mytrace *t, int status); int mytrace_exec(struct mytrace *t, char const *command); int mytrace_tcgets(struct mytrace *t, int fd, struct termios *tos); int mytrace_tcsets(struct mytrace *t, int fd, struct termios *tos); int mytrace_sctty(struct mytrace *t, int fd); #endif \ No newline at end of file diff --git a/neercs/old/neercs.h b/neercs/old/neercs.h index 5d7e37f..c4c100f 100644 --- a/neercs/old/neercs.h +++ b/neercs/old/neercs.h @@ -1,430 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#ifndef _NEERCS_H_ -#define _NEERCS_H_ - -#include -#include - -#include "widgets.h" - -enum wm_types -{ - WM_FULL, - WM_CARD, - WM_HSPLIT, - WM_VSPLIT, - - WM_MAX, -}; - -enum mouse_report -{ - MOUSE_NONE, - MOUSE_X10, - MOUSE_VT200, - MOUSE_VT200_HIGHLIGHT, - MOUSE_BTN_EVENT, - MOUSE_ANY_EVENT, -}; - - -/* ISO-2022 Conversion State */ -struct iso2022_conv_state -{ - /* cs = coding system/coding method: */ - /* (with standard return) */ - /* '@' = ISO-2022, */ - /* 'G' = UTF-8 without implementation level, */ - /* '8' = UTF-8 (Linux console and imitators), */ - /* and many others that are rarely used; */ - /* (without standard return) */ - /* '/G' = UTF-8 Level 1, */ - /* '/H' = UTF-8 Level 2, */ - /* '/I' = UTF-8 Level 3, */ - /* and many others that are rarely used */ - uint32_t cs; - /* ctrl8bit = allow 8-bit controls */ - uint8_t ctrl8bit; - /* cn[0] = C0 control charset (0x00 ... 0x1f): - * '@' = ISO 646, - * '~' = empty, - * and many others that are rarely used */ - /* cn[1] = C1 control charset (0x80 ... 0x9f): - * 'C' = ISO 6429-1983, - * '~' = empty, - * and many others that are rarely used */ - uint32_t cn[2]; - /* glr[0] = GL graphic charset (94-char. 0x21 ... 0x7e, - * 94x94-char. 0x21/0x21 ... 0x7e/0x7e), - * and - * glr[1] = GR graphic charset (94-char. 0xa1 ... 0xfe, - * 96-char. 0xa0 ... 0xff, - * 94x94-char. 0xa1/0xa1 ... 0xfe/0xfe, - * 96x96-char. 0xa0/0xa0 ... 0xff/0xff): - * 0 = G0, 1 = G1, 2 = G2, 3 = G3 */ - uint8_t glr[2]; - /* gn[i] = G0/G1/G2/G3 graphic charset state: - * (94-char. sets) - * '0' = DEC ACS (VT100 and imitators), - * 'B' = US-ASCII, - * and many others that are rarely used for e.g. various national ASCII variations; - * (96-char. sets) - * '.A' = ISO 8859-1 "Latin 1" GR, - * '.~' = empty 96-char. set, - * and many others that are rarely used for e.g. ISO 8859-n GR; - * (double-byte 94x94-charsets) - * '$@' = Japanese Character Set ("old JIS") (JIS C 6226:1978), - * '$A' = Chinese Character Set (GB 2312), - * '$B' = Japanese Character Set (JIS X0208/JIS C 6226:1983), - * '$C' = Korean Graphic Character Set (KSC 5601:1987), - * '$D' = Supplementary Japanese Graphic Character Set (JIS X0212), - * '$E' = CCITT Chinese Set (GB 2312 + GB 8565), - * '$G' = CNS 11643 plane 1, - * '$H' = CNS 11643 plane 2, - * '$I' = CNS 11643 plane 3, - * '$J' = CNS 11643 plane 4, - * '$K' = CNS 11643 plane 5, - * '$L' = CNS 11643 plane 6, - * '$M' = CNS 11643 plane 7, - * '$O' = JIS X 0213 plane 1, - * '$P' = JIS X 0213 plane 2, - * '$Q' = JIS X 0213-2004 Plane 1, - * and many others that are rarely used for e.g. traditional - * ideographic Vietnamese and BlissSymbolics; - * (double-byte 96x96-charsets) - * none standardized or in use on terminals AFAIK (Mule does use - * some internally) - */ - uint32_t gn[4]; - /* ss = single-shift state: 0 = GL, 2 = G2, 3 = G3 */ - uint8_t ss; -}; - -struct screen -{ - /* Graphics stuff */ - int init; - caca_canvas_t *cv; - uint32_t clearattr; - uint8_t fg, bg; /* ANSI-context fg/bg */ - uint8_t dfg, dbg; /* Default fg/bg */ - uint8_t bold, blink, italics, negative, concealed, underline; - uint8_t faint, strike, proportional; /* unsupported */ - struct iso2022_conv_state conv_state; /* charset mess */ - - /* Other stuff */ - int visible; /* Draw canvas and border flag */ - int fd; /* pty fd */ - unsigned char *buf; /* text buffer */ - long int total; /* buffer length */ - char *title; /* tty title */ - int bell; /* bell occuring */ - unsigned int scroll, s1, s2; /* FIXME, ANSI scroll properties */ - int pid; /* running program pid */ - int changed; /* content was updated */ - - int x, y; /* Canvas position */ - int w, h; /* Canvas size */ - - int orig_x, orig_y; /* Used by recurrents */ - int orig_w, orig_h; /* Used by recurrents */ - - int report_mouse; /* ANSI */ -}; - -enum socket_type -{ - SOCK_SERVER=0, - SOCK_CLIENT=1 -}; - -struct cube_props -{ - int in_switch; - int side; - long long unsigned int duration; -}; - -struct interpreter_props -{ - /* Input box */ - struct input_box *box; -}; - -struct screensaver -{ - /* ScreenSaver stuff */ - long long unsigned int timeout; /* Screensaver timeout in us */ - int in_screensaver; - void *data; -}; - -struct comm -{ - /* Detaching */ - int attached; /* Are we attached to a terminal or a server */ - int socket[2]; /* Sockets to write to the server / to the client */ - char *socket_path[2]; /* Sockets to write to the server / to the client */ - char *socket_dir; /* Where to create the socket */ - char *session_name; /* Name of the session */ -}; - -struct lock -{ - int locked; - int lock_offset; - int lock_on_detach; - long long unsigned int autolock_timeout; - char lockpass[1024]; - char lockmsg[1024]; -}; - -struct modals -{ - /* Add-ons*/ - int mini; /* Thumbnails */ - int status; /* Status bar */ - int help; /* Help */ - int python_command; /* Python command */ - int window_list; /* Window list */ - int cur_in_list; /* Window list */ -}; - -struct sys -{ - char *default_shell; - char *user_path; - int *to_grab; - char **to_start; - int nb_to_grab; - int attach, forceattach; -}; - -struct screen_list -{ - int outfd; /* Debug */ - int in_bell; /* Bell occuring in a window */ - int was_in_bell; - int dont_update_coords; /* Used by recurrents */ - int changed; /* Global redraw (e.g. adding a screen) */ - int delay; /* Minimal time between two refresh (ms) */ - int requested_delay; - int force_refresh; - int need_refresh; /* If we skipped a refresh, do it next time */ - int command; - int eyecandy; /* Eye Candy */ - - long long unsigned int last_key_time; - long long unsigned int last_refresh_time; - - struct comm comm; /* Client/Server communications */ - struct lock lock; /* Lock */ - struct modals modals; /* Modal windows */ - struct interpreter_props interpreter_props; /* Python interpreter */ - struct screensaver screensaver;/* Screensaver stuff */ - - int pty, prevpty; /* Current and previous window */ - int count; /* Window count */ - int wm_type; /* Window manager type */ - int border_size; /* Borders */ - struct cube_props cube; /* Cube */ - long long unsigned int last_switch; /* Cube */ - - struct screen **screen; /* Windows */ - struct option *config; /* Option parsing and configuration */ - struct sys sys; /* System stuff */ - - struct recurrent_list *recurrent_list; /* Recurrents functions */ - - char *title; /* Window title */ - int width, height; /* caca window size */ - int old_x, old_y; /* Mouse */ - int mouse_button; - caca_canvas_t *cv; - caca_display_t *dp; -}; - -/* Configuration */ -struct option -{ - char *key; - char *value; - - struct option *next; -}; -struct config_line -{ - const char name[32]; - int (*set) (const char *argv, struct screen_list * screen_list); - char* (*get) (struct screen_list * screen_list); -}; - -/* Recurrents */ -struct recurrent -{ - int (*function)(struct screen_list*, struct recurrent* rec, void *user, long long unsigned int t); - void *user; - long long unsigned int start_time; - int kill_me; -}; - -struct recurrent_list -{ - int count; - struct recurrent **recurrent; -}; - - - -void version(void); -void usage(int argc, char **argv); -struct screen_list *init_neercs(int argc, char **argv); - -int handle_command_line(int argc, char *argv[], struct screen_list *screen_list); - -struct screen_list *create_screen_list(void); -void free_screen_list(struct screen_list *screen_list); - -int start_client(struct screen_list * screen_list); -/** \defgroup client neercs client - * @{ */ -void mainloop(struct screen_list *screen_list); -int mainloop_tick(char **pbuf, struct screen_list *screen_list); -/** }@ */ - - -int create_pty(char *cmd, unsigned int w, unsigned int h, int *cpid); -int create_pty_grab(long pid, unsigned int w, unsigned int h, int *cpid); -int grab_process(long pid, char *ptyname, int ptyfd, int *newpid); -long select_process(struct screen_list* screen_list); - -long int import_term(struct screen_list *screen_list, struct screen *sc, void const *data, unsigned int size); -int set_tty_size(int fd, unsigned int w, unsigned int h); -int update_terms(struct screen_list* screen_list); -void refresh_screens(struct screen_list *screen_list); -int update_screens_contents(struct screen_list* screen_list); -int install_fds(struct screen_list *screen_list); -long long get_us(void); - -void attach(struct screen_list* screen_list); -int detach(struct screen_list* screen_list); -int request_attach(struct screen_list* screen_list); -char * build_socket_path(char *socket_dir, char *session_name, enum socket_type socktype); -int create_socket(struct screen_list* screen_list, enum socket_type socktype); -char * connect_socket(struct screen_list* screen_list, enum socket_type socktype); -char ** list_sockets(char *socket_dir, char *session_name); -int start_server(struct screen_list *screen_list); -int send_event(caca_event_t ev, struct screen_list* screen_list); -int send_delay(struct screen_list* screen_list); -int send_ansi_sequence(struct screen_list *screen_list, char *str); - -/* Screens management */ -struct screen* create_screen(int w, int h, char *command); -struct screen* create_screen_grab(int w, int h, int pid); -int destroy_screen(struct screen *s); -int add_screen(struct screen_list *list, struct screen *s); -int remove_screen(struct screen_list *list, int n, int please_kill); -void resize_screen(struct screen *s, int z, int h); - -/* Window managers */ -void update_windows_props(struct screen_list *screen_list); -void update_windows_props_cards(struct screen_list *screen_list); -void update_windows_props_hsplit(struct screen_list *screen_list); -void update_windows_props_full(struct screen_list *screen_list); -void update_windows_props_vsplit(struct screen_list *screen_list); -void update_windows_props_cube(struct screen_list *screen_list); - -void wm_refresh(struct screen_list *screen_list); -void wm_refresh_card(struct screen_list *screen_list); -void wm_refresh_cube(struct screen_list *screen_list); -void wm_refresh_full(struct screen_list *screen_list); -void wm_refresh_hsplit(struct screen_list *screen_list); -void wm_refresh_vsplit(struct screen_list *screen_list); -int switch_screen_recurrent(struct screen_list* screen_list, struct recurrent* rec, void *user, long long unsigned int t); - - -/* Effects and addons */ -void draw_thumbnails(struct screen_list *screen_list); -void draw_status(struct screen_list *screen_list); -void draw_help(struct screen_list *screen_list); -int help_handle_key(struct screen_list *screen_list, unsigned int c); -int update_window_list(int c, struct screen_list *screen_list); -void draw_list(struct screen_list *screen_list); -void draw_lock(struct screen_list *screen_list); -int update_lock(int c, struct screen_list *screen_list); -int validate_lock(struct screen_list *screen_list, char *user, char *pass); - -int close_screen_recurrent(struct screen_list*, struct recurrent* rec, void *user, long long unsigned int t); - -/* Input to ANSI */ -void *convert_input_ansi(unsigned int *c, int *size); -int handle_command_input(struct screen_list*screen_list, unsigned int c); - - -/* Screensavers */ -void screensaver_init(struct screen_list *screen_list); -void screensaver_kill(struct screen_list *screen_list); - -void draw_screensaver(struct screen_list *screen_list); -void screensaver_flying_toasters(struct screen_list *screen_list); - -void screensaver_flying_toasters_init(struct screen_list *screen_list); - -void screensaver_flying_toasters_kill(struct screen_list *screen_list); - -/* Actions */ -void dump_to_file(struct screen_list *screen_list); - -/* Recurrents */ -int handle_recurrents(struct screen_list* screen_list); -int add_recurrent(struct recurrent_list *list, - int (*function)(struct screen_list*, struct recurrent* rec, void *user, long long unsigned int t), - void *user); -int remove_recurrent(struct recurrent_list *list, int n); - - - -/* Configuration file */ -int read_configuration_file(char *filename, struct screen_list *screen_list); -int parse_conf_line(char *buf, int size, struct screen_list *screen_list); -int get_key_value(char *line, struct option *option); -int fill_config(struct screen_list *screen_list); -struct config_line *get_config(const char *name); -struct config_line *get_config_option(void); - -/* Python interpreter */ -#ifdef USE_PYTHON -int python_init(struct screen_list *sl); -int python_close(struct screen_list *sl); -int python_command_handle_key(struct screen_list *screen_list, unsigned int c); -void draw_python_command(struct screen_list *screen_list); -#endif - -#if defined DEBUG -# include -# include -static inline void debug(const char *format, ...) -{ - va_list args; - va_start(args, format); - fprintf(stderr, "** neercs debug ** "); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - va_end(args); -} -#else -# define debug(format, ...) do {} while(0) -#endif -#endif /* _NEERCS_H_ */ +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #ifndef _NEERCS_H_ #define _NEERCS_H_ #include #include #include "widgets.h" enum wm_types { WM_FULL, WM_CARD, WM_HSPLIT, WM_VSPLIT, WM_MAX, }; enum mouse_report { MOUSE_NONE, MOUSE_X10, MOUSE_VT200, MOUSE_VT200_HIGHLIGHT, MOUSE_BTN_EVENT, MOUSE_ANY_EVENT, }; /* ISO-2022 Conversion State */ struct iso2022_conv_state { /* cs = coding system/coding method: */ /* (with standard return) */ /* '@' = ISO-2022, */ /* 'G' = UTF-8 without implementation level, */ /* '8' = UTF-8 (Linux console and imitators), */ /* and many others that are rarely used; */ /* (without standard return) */ /* '/G' = UTF-8 Level 1, */ /* '/H' = UTF-8 Level 2, */ /* '/I' = UTF-8 Level 3, */ /* and many others that are rarely used */ uint32_t cs; /* ctrl8bit = allow 8-bit controls */ uint8_t ctrl8bit; /* cn[0] = C0 control charset (0x00 ... 0x1f): * '@' = ISO 646, * '~' = empty, * and many others that are rarely used */ /* cn[1] = C1 control charset (0x80 ... 0x9f): * 'C' = ISO 6429-1983, * '~' = empty, * and many others that are rarely used */ uint32_t cn[2]; /* glr[0] = GL graphic charset (94-char. 0x21 ... 0x7e, * 94x94-char. 0x21/0x21 ... 0x7e/0x7e), * and * glr[1] = GR graphic charset (94-char. 0xa1 ... 0xfe, * 96-char. 0xa0 ... 0xff, * 94x94-char. 0xa1/0xa1 ... 0xfe/0xfe, * 96x96-char. 0xa0/0xa0 ... 0xff/0xff): * 0 = G0, 1 = G1, 2 = G2, 3 = G3 */ uint8_t glr[2]; /* gn[i] = G0/G1/G2/G3 graphic charset state: * (94-char. sets) * '0' = DEC ACS (VT100 and imitators), * 'B' = US-ASCII, * and many others that are rarely used for e.g. various national ASCII variations; * (96-char. sets) * '.A' = ISO 8859-1 "Latin 1" GR, * '.~' = empty 96-char. set, * and many others that are rarely used for e.g. ISO 8859-n GR; * (double-byte 94x94-charsets) * '$@' = Japanese Character Set ("old JIS") (JIS C 6226:1978), * '$A' = Chinese Character Set (GB 2312), * '$B' = Japanese Character Set (JIS X0208/JIS C 6226:1983), * '$C' = Korean Graphic Character Set (KSC 5601:1987), * '$D' = Supplementary Japanese Graphic Character Set (JIS X0212), * '$E' = CCITT Chinese Set (GB 2312 + GB 8565), * '$G' = CNS 11643 plane 1, * '$H' = CNS 11643 plane 2, * '$I' = CNS 11643 plane 3, * '$J' = CNS 11643 plane 4, * '$K' = CNS 11643 plane 5, * '$L' = CNS 11643 plane 6, * '$M' = CNS 11643 plane 7, * '$O' = JIS X 0213 plane 1, * '$P' = JIS X 0213 plane 2, * '$Q' = JIS X 0213-2004 Plane 1, * and many others that are rarely used for e.g. traditional * ideographic Vietnamese and BlissSymbolics; * (double-byte 96x96-charsets) * none standardized or in use on terminals AFAIK (Mule does use * some internally) */ uint32_t gn[4]; /* ss = single-shift state: 0 = GL, 2 = G2, 3 = G3 */ uint8_t ss; }; struct screen { /* Graphics stuff */ int init; caca_canvas_t *cv; uint32_t clearattr; uint8_t fg, bg; /* ANSI-context fg/bg */ uint8_t dfg, dbg; /* Default fg/bg */ uint8_t bold, blink, italics, negative, concealed, underline; uint8_t faint, strike, proportional; /* unsupported */ struct iso2022_conv_state conv_state; /* charset mess */ /* Other stuff */ int visible; /* Draw canvas and border flag */ int fd; /* pty fd */ unsigned char *buf; /* text buffer */ long int total; /* buffer length */ char *title; /* tty title */ int bell; /* bell occuring */ unsigned int scroll, s1, s2; /* FIXME, ANSI scroll properties */ int pid; /* running program pid */ int changed; /* content was updated */ int x, y; /* Canvas position */ int w, h; /* Canvas size */ int orig_x, orig_y; /* Used by recurrents */ int orig_w, orig_h; /* Used by recurrents */ int report_mouse; /* ANSI */ }; enum socket_type { SOCK_SERVER=0, SOCK_CLIENT=1 }; struct cube_props { int in_switch; int side; long long unsigned int duration; }; struct interpreter_props { /* Input box */ struct input_box *box; }; struct screensaver { /* ScreenSaver stuff */ long long unsigned int timeout; /* Screensaver timeout in us */ int in_screensaver; void *data; }; struct comm { /* Detaching */ int attached; /* Are we attached to a terminal or a server */ int socket[2]; /* Sockets to write to the server / to the client */ char *socket_path[2]; /* Sockets to write to the server / to the client */ char *socket_dir; /* Where to create the socket */ char *session_name; /* Name of the session */ }; struct lock { int locked; int lock_offset; int lock_on_detach; long long unsigned int autolock_timeout; char lockpass[1024]; char lockmsg[1024]; }; struct modals { /* Add-ons*/ int mini; /* Thumbnails */ int status; /* Status bar */ int help; /* Help */ int python_command; /* Python command */ int window_list; /* Window list */ int cur_in_list; /* Window list */ }; struct sys { char *default_shell; char *user_path; int *to_grab; char **to_start; int nb_to_grab; int attach, forceattach; }; struct screen_list { int outfd; /* Debug */ int in_bell; /* Bell occuring in a window */ int was_in_bell; int dont_update_coords; /* Used by recurrents */ int changed; /* Global redraw (e.g. adding a screen) */ int delay; /* Minimal time between two refresh (ms) */ int requested_delay; int force_refresh; int need_refresh; /* If we skipped a refresh, do it next time */ int command; int eyecandy; /* Eye Candy */ long long unsigned int last_key_time; long long unsigned int last_refresh_time; struct comm comm; /* Client/Server communications */ struct lock lock; /* Lock */ struct modals modals; /* Modal windows */ struct interpreter_props interpreter_props; /* Python interpreter */ struct screensaver screensaver;/* Screensaver stuff */ int pty, prevpty; /* Current and previous window */ int count; /* Window count */ int wm_type; /* Window manager type */ int border_size; /* Borders */ struct cube_props cube; /* Cube */ long long unsigned int last_switch; /* Cube */ struct screen **screen; /* Windows */ struct option *config; /* Option parsing and configuration */ struct sys sys; /* System stuff */ struct recurrent_list *recurrent_list; /* Recurrents functions */ char *title; /* Window title */ int width, height; /* caca window size */ int old_x, old_y; /* Mouse */ int mouse_button; caca_canvas_t *cv; caca_display_t *dp; }; /* Configuration */ struct option { char *key; char *value; struct option *next; }; struct config_line { const char name[32]; int (*set) (const char *argv, struct screen_list * screen_list); char* (*get) (struct screen_list * screen_list); }; /* Recurrents */ struct recurrent { int (*function)(struct screen_list*, struct recurrent* rec, void *user, long long unsigned int t); void *user; long long unsigned int start_time; int kill_me; }; struct recurrent_list { int count; struct recurrent **recurrent; }; void version(void); void usage(int argc, char **argv); struct screen_list *init_neercs(int argc, char **argv); int handle_command_line(int argc, char *argv[], struct screen_list *screen_list); struct screen_list *create_screen_list(void); void free_screen_list(struct screen_list *screen_list); int start_client(struct screen_list * screen_list); /** \defgroup client neercs client * @{ */ void mainloop(struct screen_list *screen_list); int mainloop_tick(char **pbuf, struct screen_list *screen_list); /** }@ */ int create_pty(char *cmd, unsigned int w, unsigned int h, int *cpid); int create_pty_grab(long pid, unsigned int w, unsigned int h, int *cpid); int grab_process(long pid, char *ptyname, int ptyfd, int *newpid); long select_process(struct screen_list* screen_list); long int import_term(struct screen_list *screen_list, struct screen *sc, void const *data, unsigned int size); int set_tty_size(int fd, unsigned int w, unsigned int h); int update_terms(struct screen_list* screen_list); void refresh_screens(struct screen_list *screen_list); int update_screens_contents(struct screen_list* screen_list); int install_fds(struct screen_list *screen_list); long long get_us(void); void attach(struct screen_list* screen_list); int detach(struct screen_list* screen_list); int request_attach(struct screen_list* screen_list); char * build_socket_path(char *socket_dir, char *session_name, enum socket_type socktype); int create_socket(struct screen_list* screen_list, enum socket_type socktype); char * connect_socket(struct screen_list* screen_list, enum socket_type socktype); char ** list_sockets(char *socket_dir, char *session_name); int start_server(struct screen_list *screen_list); int send_event(caca_event_t ev, struct screen_list* screen_list); int send_delay(struct screen_list* screen_list); int send_ansi_sequence(struct screen_list *screen_list, char *str); /* Screens management */ struct screen* create_screen(int w, int h, char *command); struct screen* create_screen_grab(int w, int h, int pid); int destroy_screen(struct screen *s); int add_screen(struct screen_list *list, struct screen *s); int remove_screen(struct screen_list *list, int n, int please_kill); void resize_screen(struct screen *s, int z, int h); /* Window managers */ void update_windows_props(struct screen_list *screen_list); void update_windows_props_cards(struct screen_list *screen_list); void update_windows_props_hsplit(struct screen_list *screen_list); void update_windows_props_full(struct screen_list *screen_list); void update_windows_props_vsplit(struct screen_list *screen_list); void update_windows_props_cube(struct screen_list *screen_list); void wm_refresh(struct screen_list *screen_list); void wm_refresh_card(struct screen_list *screen_list); void wm_refresh_cube(struct screen_list *screen_list); void wm_refresh_full(struct screen_list *screen_list); void wm_refresh_hsplit(struct screen_list *screen_list); void wm_refresh_vsplit(struct screen_list *screen_list); int switch_screen_recurrent(struct screen_list* screen_list, struct recurrent* rec, void *user, long long unsigned int t); /* Effects and addons */ void draw_thumbnails(struct screen_list *screen_list); void draw_status(struct screen_list *screen_list); void draw_help(struct screen_list *screen_list); int help_handle_key(struct screen_list *screen_list, unsigned int c); int update_window_list(int c, struct screen_list *screen_list); void draw_list(struct screen_list *screen_list); void draw_lock(struct screen_list *screen_list); int update_lock(int c, struct screen_list *screen_list); int validate_lock(struct screen_list *screen_list, char *user, char *pass); int close_screen_recurrent(struct screen_list*, struct recurrent* rec, void *user, long long unsigned int t); /* Input to ANSI */ void *convert_input_ansi(unsigned int *c, int *size); int handle_command_input(struct screen_list*screen_list, unsigned int c); /* Screensavers */ void screensaver_init(struct screen_list *screen_list); void screensaver_kill(struct screen_list *screen_list); void draw_screensaver(struct screen_list *screen_list); void screensaver_flying_toasters(struct screen_list *screen_list); void screensaver_flying_toasters_init(struct screen_list *screen_list); void screensaver_flying_toasters_kill(struct screen_list *screen_list); /* Actions */ void dump_to_file(struct screen_list *screen_list); /* Recurrents */ int handle_recurrents(struct screen_list* screen_list); int add_recurrent(struct recurrent_list *list, int (*function)(struct screen_list*, struct recurrent* rec, void *user, long long unsigned int t), void *user); int remove_recurrent(struct recurrent_list *list, int n); /* Configuration file */ int read_configuration_file(char *filename, struct screen_list *screen_list); int parse_conf_line(char *buf, int size, struct screen_list *screen_list); int get_key_value(char *line, struct option *option); int fill_config(struct screen_list *screen_list); struct config_line *get_config(const char *name); struct config_line *get_config_option(void); /* Python interpreter */ #ifdef USE_PYTHON int python_init(struct screen_list *sl); int python_close(struct screen_list *sl); int python_command_handle_key(struct screen_list *screen_list, unsigned int c); void draw_python_command(struct screen_list *screen_list); #endif #if defined DEBUG # include # include static inline void debug(const char *format, ...) { va_list args; va_start(args, format); fprintf(stderr, "** neercs debug ** "); vfprintf(stderr, format, args); fprintf(stderr, "\n"); va_end(args); } #else # define debug(format, ...) do {} while(0) #endif #endif /* _NEERCS_H_ */ \ No newline at end of file diff --git a/neercs/old/python/interpreter.c b/neercs/old/python/interpreter.c index c485e03..a10f7ed 100644 --- a/neercs/old/python/interpreter.c +++ b/neercs/old/python/interpreter.c @@ -1,199 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2009-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef USE_PYTHON - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "neercs.h" -#include "py_module.h" - -static int python_execute(struct screen_list *sl); -char *getStringFromPyObject(PyObject * p); -static char *getPythonError(void); - -#if ! defined HAVE_PYTHON26 -static PyObject *PyUnicode_FromString(char const *str) -{ - PyObject *tmp, *ret; - tmp = PyString_FromString(str); - if (!tmp) - return NULL; - ret = PyString_AsDecodedObject(tmp, "utf-8", "replace"); - Py_DECREF(tmp); - return ret; -} -#endif - -int python_command_handle_key(struct screen_list *screen_list, unsigned int c) -{ - int ret = widget_ibox_handle_key(screen_list->interpreter_props.box, c); - - if (ret == INPUT_BOX_ESC) - { - widget_ibox_destroy(screen_list->interpreter_props.box); - screen_list->interpreter_props.box = NULL; - screen_list->modals.python_command = 0; - } - else if (ret == INPUT_BOX_RET) - { - python_execute(screen_list); - } - screen_list->changed = 1; - - return 1; -} - -void draw_python_command(struct screen_list *screen_list) -{ - if (!screen_list->interpreter_props.box) - { - screen_list->interpreter_props.box = - widget_ibox_init(screen_list->cv, 65, 6); - debug("py Init %p\n", screen_list->interpreter_props.box); - } - widget_ibox_draw(screen_list->interpreter_props.box); -} - -/* Actual Python interpreter stuff */ -int python_init(struct screen_list *sl) -{ - initNeercsModule(sl); - - return 0; -} - -int python_close(struct screen_list *sl) -{ - widget_ibox_destroy(sl->interpreter_props.box); - sl->interpreter_props.box = NULL; - - Py_Finalize(); - return 0; -} - - -static int python_execute(struct screen_list *sl) -{ - char *command = widget_ibox_get_text(sl->interpreter_props.box); - if (!command || strlen(command) < 1) - return -1; - int err = 0; - - debug("py Executing '%s'\n", command); - - - PyObject *pModule, *pName; - - /* Module from which to call the function */ - pName = PyUnicode_FromString("neercs"); - if (!pName) - { - widget_ibox_set_error(sl->interpreter_props.box, getPythonError()); - err = 1; - debug("py Error 1\n"); - goto end; - } - - pModule = PyImport_Import(pName); - Py_DECREF(pName); - - if (pModule != NULL) - { - PyObject *dictionary = PyModule_GetDict(pModule); - - getExportedValues(dictionary); - - PyObject *o = - PyRun_String(command, Py_single_input, - dictionary, NULL); - if (!o) - { - widget_ibox_set_error(sl->interpreter_props.box, getPythonError()); - err = 1; - } - else - { - setExportedValues(dictionary); - - widget_ibox_set_msg(sl->interpreter_props.box, getStringFromPyObject(o)); - err = 1; - } - - Py_DECREF(pModule); - } - else - { - widget_ibox_set_error(sl->interpreter_props.box, getPythonError()); - err = 1; - } - - end: - - if (!err) - { - widget_ibox_destroy(sl->interpreter_props.box); - sl->interpreter_props.box = NULL; - sl->modals.python_command = 0; - } - sl->changed = 1; - - return 0; -} - -static char *getPythonError(void) -{ - char *err; - PyObject *type, *value, *traceback; - PyErr_Fetch(&type, &value, &traceback); - - char *evalue = getStringFromPyObject(value); - - int r = asprintf(&err, "%s", evalue); - (void)r; - return err; -} - -char *getStringFromPyObject(PyObject * p) -{ - PyObject *str = PyObject_Repr(p); - char *tmp; -#if defined HAVE_PYTHON26 - tmp = PyBytes_AS_STRING(PyUnicode_AsEncodedString(str, "utf-8", "Error ~")); -#else - tmp = PyString_AsString(str); -#endif - return strdup(tmp); -} - - -#endif +/* * neercs console-based window manager * Copyright (c) 2009-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #ifdef USE_PYTHON #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "neercs.h" #include "py_module.h" static int python_execute(struct screen_list *sl); char *getStringFromPyObject(PyObject * p); static char *getPythonError(void); #if ! defined HAVE_PYTHON26 static PyObject *PyUnicode_FromString(char const *str) { PyObject *tmp, *ret; tmp = PyString_FromString(str); if (!tmp) return NULL; ret = PyString_AsDecodedObject(tmp, "utf-8", "replace"); Py_DECREF(tmp); return ret; } #endif int python_command_handle_key(struct screen_list *screen_list, unsigned int c) { int ret = widget_ibox_handle_key(screen_list->interpreter_props.box, c); if (ret == INPUT_BOX_ESC) { widget_ibox_destroy(screen_list->interpreter_props.box); screen_list->interpreter_props.box = NULL; screen_list->modals.python_command = 0; } else if (ret == INPUT_BOX_RET) { python_execute(screen_list); } screen_list->changed = 1; return 1; } void draw_python_command(struct screen_list *screen_list) { if (!screen_list->interpreter_props.box) { screen_list->interpreter_props.box = widget_ibox_init(screen_list->cv, 65, 6); debug("py Init %p\n", screen_list->interpreter_props.box); } widget_ibox_draw(screen_list->interpreter_props.box); } /* Actual Python interpreter stuff */ int python_init(struct screen_list *sl) { initNeercsModule(sl); return 0; } int python_close(struct screen_list *sl) { widget_ibox_destroy(sl->interpreter_props.box); sl->interpreter_props.box = NULL; Py_Finalize(); return 0; } static int python_execute(struct screen_list *sl) { char *command = widget_ibox_get_text(sl->interpreter_props.box); if (!command || strlen(command) < 1) return -1; int err = 0; debug("py Executing '%s'\n", command); PyObject *pModule, *pName; /* Module from which to call the function */ pName = PyUnicode_FromString("neercs"); if (!pName) { widget_ibox_set_error(sl->interpreter_props.box, getPythonError()); err = 1; debug("py Error 1\n"); goto end; } pModule = PyImport_Import(pName); Py_DECREF(pName); if (pModule != NULL) { PyObject *dictionary = PyModule_GetDict(pModule); getExportedValues(dictionary); PyObject *o = PyRun_String(command, Py_single_input, dictionary, NULL); if (!o) { widget_ibox_set_error(sl->interpreter_props.box, getPythonError()); err = 1; } else { setExportedValues(dictionary); widget_ibox_set_msg(sl->interpreter_props.box, getStringFromPyObject(o)); err = 1; } Py_DECREF(pModule); } else { widget_ibox_set_error(sl->interpreter_props.box, getPythonError()); err = 1; } end: if (!err) { widget_ibox_destroy(sl->interpreter_props.box); sl->interpreter_props.box = NULL; sl->modals.python_command = 0; } sl->changed = 1; return 0; } static char *getPythonError(void) { char *err; PyObject *type, *value, *traceback; PyErr_Fetch(&type, &value, &traceback); char *evalue = getStringFromPyObject(value); int r = asprintf(&err, "%s", evalue); (void)r; return err; } char *getStringFromPyObject(PyObject * p) { PyObject *str = PyObject_Repr(p); char *tmp; #if defined HAVE_PYTHON26 tmp = PyBytes_AS_STRING(PyUnicode_AsEncodedString(str, "utf-8", "Error ~")); #else tmp = PyString_AsString(str); #endif return strdup(tmp); } #endif \ No newline at end of file diff --git a/neercs/old/python/py_module.c b/neercs/old/python/py_module.c index 367d090..73bcea1 100644 --- a/neercs/old/python/py_module.c +++ b/neercs/old/python/py_module.c @@ -1,195 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2009-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef USE_PYTHON - -#include -#include "py_module.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "neercs.h" - -/* FIXME : Find a way to pass a user pointer to PyModuleDef or something */ -static struct screen_list *screen_list; - -#if defined HAVE_PYTHON3 -static PyObject *PyInit_neercs(void); -#else -static void PyInit_neercs(void); -#endif -static void removeTrailingStuff(char *b); - - -static void addVariableFromConfig(PyObject * dictionary, - const char *varname, const char *configname) -{ - char *v = get_config(configname)->get(screen_list); - if (v != NULL) - { - PyObject *value = Py_BuildValue("s", v); - PyDict_SetItemString(dictionary, varname, value); - } - - debug("py get '%s' to '%s'\n", varname, - get_config(configname)->get(screen_list)); -} - -static void removeTrailingStuff(char *b) -{ - if(!b) - return; - if(b[0]=='\'') - { - memmove(b, &b[1], strlen(b)-1); - b[strlen(b)-2] = 0; - } -} - -void setExportedValues(PyObject * dictionary) -{ - struct config_line *config_option = get_config_option(); - int i = 0; - - while (strncmp(config_option[i].name, "last", strlen("last"))) - { - /* Get variable */ - PyObject *res = - PyDict_GetItemString(dictionary, config_option[i].name); - - /* Got it */ - if (res) - { - /* Get object representation - * FIXME : find a way to check object's type */ - PyObject *str = PyObject_Repr(res); - - /* Make sure it's a string */ - char *err = -#if defined HAVE_PYTHON3 - PyBytes_AS_STRING(PyUnicode_AsEncodedString - (str, "utf-8", "Error ~")); -#elif defined HAVE_PYTHON2 - PyString_AsString(str); -#endif - /* FIXME leak leak leak */ - char *s = strdup(err); - - if (s != NULL) - { - /* Representation can include '' around strings */ - removeTrailingStuff(s); - get_config(config_option[i].name)->set(s, screen_list); - } - } - i++; - } -} - -void getExportedValues(PyObject * dictionary) -{ - struct config_line *config_option = get_config_option(); - int i = 0; - while (strncmp(config_option[i].name, "last", strlen("last"))) - { - addVariableFromConfig(dictionary, config_option[i].name, - config_option[i].name); - i++; - } -} - -static PyObject *neercs_get(PyObject * self, PyObject * args) -{ - char *s = NULL; - - debug("Get using list at %p", screen_list); - - if (!PyArg_ParseTuple(args, "s", &s)) - { - PyErr_SetString(PyExc_ValueError, "Can't parse argument"); - debug("py Can't parse"); - return NULL; - } - debug("py Argument : '%s'", s); - struct config_line *c = get_config(s); - - if (c) - return Py_BuildValue("s", c->get(screen_list)); - - - PyErr_SetString(PyExc_ValueError, - "Can't get value for specified variable"); - return NULL; -} - -static PyObject *neercs_version(PyObject * self, PyObject * args) -{ - return Py_BuildValue("s", PACKAGE_VERSION); -} - -static PyMethodDef NeercsMethods[] = -{ - { "version", neercs_version, METH_NOARGS, "Return the neercs version." }, - { "get", neercs_get, METH_VARARGS, - "Return the specified variable's value." }, - { NULL, NULL, 0, NULL } -}; - -#if defined HAVE_PYTHON3 -static PyObject *PyInit_neercs(void) -{ - static PyModuleDef NeercsModule = - { - PyModuleDef_HEAD_INIT, "neercs", NULL, -1, NeercsMethods, - NULL, NULL, NULL, NULL - }; - - return PyModule_Create(&NeercsModule); -} - -#elif defined HAVE_PYTHON2 -static void PyInit_neercs(void) -{ - PyMethodDef *m = NeercsMethods; - PyObject *mod = PyModule_New("neercs"); - PyModule_AddStringConstant(mod, "__file__", ""); - - for (m = NeercsMethods; m->ml_name; m++) - PyModule_AddObject(mod, m->ml_name, PyCFunction_New(m, NULL)); -} -#endif - -void initNeercsModule(struct screen_list *sl) -{ - screen_list = sl; - PyImport_AppendInittab("neercs", &PyInit_neercs); - Py_Initialize(); -} - -#endif +/* * neercs console-based window manager * Copyright (c) 2009-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #ifdef USE_PYTHON #include #include "py_module.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "neercs.h" /* FIXME : Find a way to pass a user pointer to PyModuleDef or something */ static struct screen_list *screen_list; #if defined HAVE_PYTHON3 static PyObject *PyInit_neercs(void); #else static void PyInit_neercs(void); #endif static void removeTrailingStuff(char *b); static void addVariableFromConfig(PyObject * dictionary, const char *varname, const char *configname) { char *v = get_config(configname)->get(screen_list); if (v != NULL) { PyObject *value = Py_BuildValue("s", v); PyDict_SetItemString(dictionary, varname, value); } debug("py get '%s' to '%s'\n", varname, get_config(configname)->get(screen_list)); } static void removeTrailingStuff(char *b) { if(!b) return; if(b[0]=='\'') { memmove(b, &b[1], strlen(b)-1); b[strlen(b)-2] = 0; } } void setExportedValues(PyObject * dictionary) { struct config_line *config_option = get_config_option(); int i = 0; while (strncmp(config_option[i].name, "last", strlen("last"))) { /* Get variable */ PyObject *res = PyDict_GetItemString(dictionary, config_option[i].name); /* Got it */ if (res) { /* Get object representation * FIXME : find a way to check object's type */ PyObject *str = PyObject_Repr(res); /* Make sure it's a string */ char *err = #if defined HAVE_PYTHON3 PyBytes_AS_STRING(PyUnicode_AsEncodedString (str, "utf-8", "Error ~")); #elif defined HAVE_PYTHON2 PyString_AsString(str); #endif /* FIXME leak leak leak */ char *s = strdup(err); if (s != NULL) { /* Representation can include '' around strings */ removeTrailingStuff(s); get_config(config_option[i].name)->set(s, screen_list); } } i++; } } void getExportedValues(PyObject * dictionary) { struct config_line *config_option = get_config_option(); int i = 0; while (strncmp(config_option[i].name, "last", strlen("last"))) { addVariableFromConfig(dictionary, config_option[i].name, config_option[i].name); i++; } } static PyObject *neercs_get(PyObject * self, PyObject * args) { char *s = NULL; debug("Get using list at %p", screen_list); if (!PyArg_ParseTuple(args, "s", &s)) { PyErr_SetString(PyExc_ValueError, "Can't parse argument"); debug("py Can't parse"); return NULL; } debug("py Argument : '%s'", s); struct config_line *c = get_config(s); if (c) return Py_BuildValue("s", c->get(screen_list)); PyErr_SetString(PyExc_ValueError, "Can't get value for specified variable"); return NULL; } static PyObject *neercs_version(PyObject * self, PyObject * args) { return Py_BuildValue("s", PACKAGE_VERSION); } static PyMethodDef NeercsMethods[] = { { "version", neercs_version, METH_NOARGS, "Return the neercs version." }, { "get", neercs_get, METH_VARARGS, "Return the specified variable's value." }, { NULL, NULL, 0, NULL } }; #if defined HAVE_PYTHON3 static PyObject *PyInit_neercs(void) { static PyModuleDef NeercsModule = { PyModuleDef_HEAD_INIT, "neercs", NULL, -1, NeercsMethods, NULL, NULL, NULL, NULL }; return PyModule_Create(&NeercsModule); } #elif defined HAVE_PYTHON2 static void PyInit_neercs(void) { PyMethodDef *m = NeercsMethods; PyObject *mod = PyModule_New("neercs"); PyModule_AddStringConstant(mod, "__file__", ""); for (m = NeercsMethods; m->ml_name; m++) PyModule_AddObject(mod, m->ml_name, PyCFunction_New(m, NULL)); } #endif void initNeercsModule(struct screen_list *sl) { screen_list = sl; PyImport_AppendInittab("neercs", &PyInit_neercs); Py_Initialize(); } #endif \ No newline at end of file diff --git a/neercs/old/python/py_module.h b/neercs/old/python/py_module.h index 1294ac4..134edbd 100644 --- a/neercs/old/python/py_module.h +++ b/neercs/old/python/py_module.h @@ -1,23 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2009-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#ifdef USE_PYTHON - -#include -#include "neercs.h" - -void initNeercsModule(struct screen_list *sl); -void getExportedValues(PyObject * dictionary); -void setExportedValues(PyObject * dictionary); - - -#endif +/* * neercs console-based window manager * Copyright (c) 2009-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #ifdef USE_PYTHON #include #include "neercs.h" void initNeercsModule(struct screen_list *sl); void getExportedValues(PyObject * dictionary); void setExportedValues(PyObject * dictionary); #endif \ No newline at end of file diff --git a/neercs/old/recurrent.c b/neercs/old/recurrent.c index 56e6bd6..5be2a43 100644 --- a/neercs/old/recurrent.c +++ b/neercs/old/recurrent.c @@ -1,118 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "neercs.h" - - -int handle_recurrents(struct screen_list *screen_list) -{ - int refresh = 0, i; - /* Recurrent functions */ - for (i = 0; i < screen_list->recurrent_list->count; i++) - { - if (screen_list->recurrent_list->recurrent[i]->function) - { - refresh |= - screen_list->recurrent_list->recurrent[i]-> - function(screen_list, - screen_list->recurrent_list->recurrent[i], - screen_list->recurrent_list->recurrent[i]->user, - get_us()); - } - } - /* Delete recurrent functions */ - for (i = 0; i < screen_list->recurrent_list->count; i++) - { - if (screen_list->recurrent_list->recurrent[i]->kill_me) - { - remove_recurrent(screen_list->recurrent_list, i); - refresh = 1; - i = 0; - } - } - return refresh; -} - - -/* Add recurrent function. It will be called at each main loop iteration, - unless it is removed */ -int add_recurrent(struct recurrent_list *list, - int (*func) (struct screen_list *, struct recurrent * rec, - void *user, long long unsigned int t), - void *user) -{ - if (list == NULL || func == NULL) - return -1; - - list->recurrent = (struct recurrent **)realloc(list->recurrent, - sizeof(struct recurrent *) - * (list->count + 1)); - - if (!list->recurrent) - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - - list->recurrent[list->count] = malloc(sizeof(struct recurrent)); - - list->recurrent[list->count]->kill_me = 0; - list->recurrent[list->count]->function = func; - list->recurrent[list->count]->user = user; - list->recurrent[list->count]->start_time = get_us(); - list->count++; - - return list->count - 1; -} - - -/* Remove recurrent. Do *NOT* call this from a recurrent function. */ -int remove_recurrent(struct recurrent_list *list, int n) -{ - - if (n >= list->count) - return -1; - - memmove(&list->recurrent[n], - &list->recurrent[n + 1], - sizeof(struct recurrent *) * (list->count - (n + 1))); - - free(list->recurrent[n]); - list->recurrent = (struct recurrent **)realloc(list->recurrent, - sizeof(sizeof - (struct recurrent *)) - * (list->count)); - if (!list->recurrent) - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - - - - list->count--; - return 0; -} - -#endif +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include #include "neercs.h" int handle_recurrents(struct screen_list *screen_list) { int refresh = 0, i; /* Recurrent functions */ for (i = 0; i < screen_list->recurrent_list->count; i++) { if (screen_list->recurrent_list->recurrent[i]->function) { refresh |= screen_list->recurrent_list->recurrent[i]-> function(screen_list, screen_list->recurrent_list->recurrent[i], screen_list->recurrent_list->recurrent[i]->user, get_us()); } } /* Delete recurrent functions */ for (i = 0; i < screen_list->recurrent_list->count; i++) { if (screen_list->recurrent_list->recurrent[i]->kill_me) { remove_recurrent(screen_list->recurrent_list, i); refresh = 1; i = 0; } } return refresh; } /* Add recurrent function. It will be called at each main loop iteration, unless it is removed */ int add_recurrent(struct recurrent_list *list, int (*func) (struct screen_list *, struct recurrent * rec, void *user, long long unsigned int t), void *user) { if (list == NULL || func == NULL) return -1; list->recurrent = (struct recurrent **)realloc(list->recurrent, sizeof(struct recurrent *) * (list->count + 1)); if (!list->recurrent) fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); list->recurrent[list->count] = malloc(sizeof(struct recurrent)); list->recurrent[list->count]->kill_me = 0; list->recurrent[list->count]->function = func; list->recurrent[list->count]->user = user; list->recurrent[list->count]->start_time = get_us(); list->count++; return list->count - 1; } /* Remove recurrent. Do *NOT* call this from a recurrent function. */ int remove_recurrent(struct recurrent_list *list, int n) { if (n >= list->count) return -1; memmove(&list->recurrent[n], &list->recurrent[n + 1], sizeof(struct recurrent *) * (list->count - (n + 1))); free(list->recurrent[n]); list->recurrent = (struct recurrent **)realloc(list->recurrent, sizeof(sizeof (struct recurrent *)) * (list->count)); if (!list->recurrent) fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); list->count--; return 0; } #endif \ No newline at end of file diff --git a/neercs/old/screen_list.c b/neercs/old/screen_list.c index e961694..58e1873 100644 --- a/neercs/old/screen_list.c +++ b/neercs/old/screen_list.c @@ -1,223 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "neercs.h" - -struct screen_list *create_screen_list(void) -{ - - struct screen_list *screen_list = NULL; - struct passwd *user_info; - char *user_dir = NULL; - - /* Create screen list */ - screen_list = (struct screen_list *)malloc(sizeof(struct screen_list)); - if (!screen_list) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - return NULL; - } - screen_list->screen = - (struct screen **)malloc(sizeof(sizeof(struct screen *))); - if (!screen_list->screen) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - free(screen_list); - return NULL; - } - - screen_list->count = 0; - screen_list->modals.mini = 1; - screen_list->modals.help = 0; - screen_list->modals.status = 1; - screen_list->modals.window_list = 0; - screen_list->modals.python_command = 0; - screen_list->eyecandy = 1; - screen_list->border_size = 1; - screen_list->title = NULL; - screen_list->wm_type = WM_VSPLIT; - screen_list->in_bell = 0; - screen_list->changed = 0; - screen_list->requested_delay = 0; - screen_list->delay = 1000 / 60; /* Don't refresh more than 60 times - per second */ - screen_list->pty = screen_list->prevpty = 0; - screen_list->dont_update_coords = 0; - screen_list->screensaver.timeout = (60*5) * 1000000; - screen_list->screensaver.data = NULL; - screen_list->screensaver.in_screensaver = 0; - screen_list->lock.autolock_timeout = -1; - screen_list->lock.locked = 0; - screen_list->lock.lock_offset = 0; - screen_list->lock.lock_on_detach = 0; - screen_list->comm.attached = 0; - screen_list->comm.socket[SOCK_SERVER] = 0; - screen_list->comm.socket[SOCK_CLIENT] = 0; - screen_list->comm.socket_dir = NULL; - screen_list->comm.socket_path[SOCK_SERVER] = NULL; - screen_list->comm.socket_path[SOCK_CLIENT] = NULL; - screen_list->comm.session_name = NULL; - screen_list->sys.default_shell = NULL; - screen_list->sys.user_path = NULL; - screen_list->sys.to_grab = NULL; - screen_list->sys.to_start = NULL; - screen_list->sys.nb_to_grab = 0; - screen_list->sys.attach = 0; - screen_list->sys.forceattach = 0; - screen_list->need_refresh = 0; - - screen_list->force_refresh = 0; - screen_list->cube.in_switch = 0; - screen_list->cube.duration = 1000000; - - screen_list->interpreter_props.box = NULL; - - screen_list->recurrent_list = NULL; - screen_list->cv = NULL; - screen_list->dp = NULL; - - memset(screen_list->lock.lockmsg, 0, 1024); - memset(screen_list->lock.lockpass, 0, 1024); - - /* Build local config file path */ - user_dir = getenv("HOME"); - if (!user_dir) - { - user_info = getpwuid(getuid()); - if (user_info) - { - user_dir = user_info->pw_dir; - } - } - if (user_dir) - { - screen_list->sys.user_path = - malloc(strlen(user_dir) + strlen("/.neercsrc") + 1); - sprintf(screen_list->sys.user_path, "%s/%s", user_dir, ".neercsrc"); - } - - - screen_list->recurrent_list = - (struct recurrent_list *)malloc(sizeof(struct recurrent_list)); - screen_list->recurrent_list->recurrent = - (struct recurrent **)malloc(sizeof(struct recurrent *)); - if (!screen_list->recurrent_list->recurrent) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - free(screen_list); - free(screen_list->screen); - return NULL; - } - screen_list->recurrent_list->count = 0; - - return screen_list; -} - -void free_screen_list(struct screen_list *screen_list) -{ - int i; - struct option *option; - - if (screen_list->dp) - caca_free_display(screen_list->dp); - - if (screen_list->cv) - caca_free_canvas(screen_list->cv); - - for (i = 0; i < screen_list->count; i++) - { - destroy_screen(screen_list->screen[i]); - } - - if (screen_list->comm.socket_path[SOCK_SERVER]) - { - /* FIXME test that we are the server */ - if (!screen_list->dp) - unlink(screen_list->comm.socket_path[SOCK_SERVER]); - free(screen_list->comm.socket_path[SOCK_SERVER]); - } - - if (screen_list->comm.socket_path[SOCK_CLIENT]) - { - /* FIXME test that we are the client */ - if (screen_list->dp) - - unlink(screen_list->comm.socket_path[SOCK_CLIENT]); - free(screen_list->comm.socket_path[SOCK_CLIENT]); - } - - if (screen_list->comm.socket[SOCK_CLIENT]) - close(screen_list->comm.socket[SOCK_CLIENT]); - - if (screen_list->comm.socket[SOCK_SERVER]) - close(screen_list->comm.socket[SOCK_SERVER]); - - if (screen_list->screen) - free(screen_list->screen); - - option = screen_list->config; - - while (option) - { - struct option *kromeugnon = option; - option = option->next; - if (kromeugnon->key) - free(kromeugnon->key); - if (kromeugnon->value) - free(kromeugnon->value); - free(kromeugnon); - } - - for (i = 0; i < screen_list->recurrent_list->count; i++) - { - remove_recurrent(screen_list->recurrent_list, i); - i = 0; - } - - if (screen_list->recurrent_list->recurrent) - free(screen_list->recurrent_list->recurrent); - if (screen_list->recurrent_list) - free(screen_list->recurrent_list); - - if (screen_list->comm.session_name) - free(screen_list->comm.session_name); - - if (screen_list->title) - free(screen_list->title); - - free(screen_list); -} - -#endif - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include #include #include #include "neercs.h" struct screen_list *create_screen_list(void) { struct screen_list *screen_list = NULL; struct passwd *user_info; char *user_dir = NULL; /* Create screen list */ screen_list = (struct screen_list *)malloc(sizeof(struct screen_list)); if (!screen_list) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return NULL; } screen_list->screen = (struct screen **)malloc(sizeof(sizeof(struct screen *))); if (!screen_list->screen) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); free(screen_list); return NULL; } screen_list->count = 0; screen_list->modals.mini = 1; screen_list->modals.help = 0; screen_list->modals.status = 1; screen_list->modals.window_list = 0; screen_list->modals.python_command = 0; screen_list->eyecandy = 1; screen_list->border_size = 1; screen_list->title = NULL; screen_list->wm_type = WM_VSPLIT; screen_list->in_bell = 0; screen_list->changed = 0; screen_list->requested_delay = 0; screen_list->delay = 1000 / 60; /* Don't refresh more than 60 times per second */ screen_list->pty = screen_list->prevpty = 0; screen_list->dont_update_coords = 0; screen_list->screensaver.timeout = (60*5) * 1000000; screen_list->screensaver.data = NULL; screen_list->screensaver.in_screensaver = 0; screen_list->lock.autolock_timeout = -1; screen_list->lock.locked = 0; screen_list->lock.lock_offset = 0; screen_list->lock.lock_on_detach = 0; screen_list->comm.attached = 0; screen_list->comm.socket[SOCK_SERVER] = 0; screen_list->comm.socket[SOCK_CLIENT] = 0; screen_list->comm.socket_dir = NULL; screen_list->comm.socket_path[SOCK_SERVER] = NULL; screen_list->comm.socket_path[SOCK_CLIENT] = NULL; screen_list->comm.session_name = NULL; screen_list->sys.default_shell = NULL; screen_list->sys.user_path = NULL; screen_list->sys.to_grab = NULL; screen_list->sys.to_start = NULL; screen_list->sys.nb_to_grab = 0; screen_list->sys.attach = 0; screen_list->sys.forceattach = 0; screen_list->need_refresh = 0; screen_list->force_refresh = 0; screen_list->cube.in_switch = 0; screen_list->cube.duration = 1000000; screen_list->interpreter_props.box = NULL; screen_list->recurrent_list = NULL; screen_list->cv = NULL; screen_list->dp = NULL; memset(screen_list->lock.lockmsg, 0, 1024); memset(screen_list->lock.lockpass, 0, 1024); /* Build local config file path */ user_dir = getenv("HOME"); if (!user_dir) { user_info = getpwuid(getuid()); if (user_info) { user_dir = user_info->pw_dir; } } if (user_dir) { screen_list->sys.user_path = malloc(strlen(user_dir) + strlen("/.neercsrc") + 1); sprintf(screen_list->sys.user_path, "%s/%s", user_dir, ".neercsrc"); } screen_list->recurrent_list = (struct recurrent_list *)malloc(sizeof(struct recurrent_list)); screen_list->recurrent_list->recurrent = (struct recurrent **)malloc(sizeof(struct recurrent *)); if (!screen_list->recurrent_list->recurrent) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); free(screen_list); free(screen_list->screen); return NULL; } screen_list->recurrent_list->count = 0; return screen_list; } void free_screen_list(struct screen_list *screen_list) { int i; struct option *option; if (screen_list->dp) caca_free_display(screen_list->dp); if (screen_list->cv) caca_free_canvas(screen_list->cv); for (i = 0; i < screen_list->count; i++) { destroy_screen(screen_list->screen[i]); } if (screen_list->comm.socket_path[SOCK_SERVER]) { /* FIXME test that we are the server */ if (!screen_list->dp) unlink(screen_list->comm.socket_path[SOCK_SERVER]); free(screen_list->comm.socket_path[SOCK_SERVER]); } if (screen_list->comm.socket_path[SOCK_CLIENT]) { /* FIXME test that we are the client */ if (screen_list->dp) unlink(screen_list->comm.socket_path[SOCK_CLIENT]); free(screen_list->comm.socket_path[SOCK_CLIENT]); } if (screen_list->comm.socket[SOCK_CLIENT]) close(screen_list->comm.socket[SOCK_CLIENT]); if (screen_list->comm.socket[SOCK_SERVER]) close(screen_list->comm.socket[SOCK_SERVER]); if (screen_list->screen) free(screen_list->screen); option = screen_list->config; while (option) { struct option *kromeugnon = option; option = option->next; if (kromeugnon->key) free(kromeugnon->key); if (kromeugnon->value) free(kromeugnon->value); free(kromeugnon); } for (i = 0; i < screen_list->recurrent_list->count; i++) { remove_recurrent(screen_list->recurrent_list, i); i = 0; } if (screen_list->recurrent_list->recurrent) free(screen_list->recurrent_list->recurrent); if (screen_list->recurrent_list) free(screen_list->recurrent_list); if (screen_list->comm.session_name) free(screen_list->comm.session_name); if (screen_list->title) free(screen_list->title); free(screen_list); } #endif \ No newline at end of file diff --git a/neercs/old/screens.c b/neercs/old/screens.c index 83e5971..60f5cbe 100644 --- a/neercs/old/screens.c +++ b/neercs/old/screens.c @@ -1,341 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "neercs.h" - -struct screen *create_screen_grab(int w, int h, int pid) -{ - struct screen *s = (struct screen *)malloc(sizeof(struct screen)); - - s->cv = caca_create_canvas(w, h); - caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK); - caca_clear_canvas(s->cv); - s->init = 0; - - s->buf = NULL; - s->title = NULL; - s->total = 0; - s->w = w; - s->h = h; - s->bell = 0; - s->report_mouse = MOUSE_NONE; - - s->fd = create_pty_grab(pid, w, h, &s->pid); - - if (s->fd < 0) - { - caca_free_canvas(s->cv); - free(s); - return NULL; - } - return s; -} - -struct screen *create_screen(int w, int h, char *command) -{ - struct screen *s = (struct screen *)malloc(sizeof(struct screen)); - - s->cv = caca_create_canvas(w, h); - caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK); - caca_clear_canvas(s->cv); - s->init = 0; - - s->buf = NULL; - s->title = NULL; - s->total = 0; - s->w = w + 1; - s->h = h + 1; - s->bell = 0; - s->visible = 1; - s->scroll = 0; - s->report_mouse = MOUSE_NONE; - s->fd = create_pty(command, w, h, &s->pid); - - s->orig_w = s->w; - s->orig_h = s->h; - s->orig_x = s->x; - s->orig_y = s->y; - - - if (s->fd < 0) - { - caca_free_canvas(s->cv); - free(s); - return NULL; - } - return s; -} - -int destroy_screen(struct screen *s) -{ - if (s->fd >= 0) - close(s->fd); - if (s->buf) - free(s->buf); - if (s->title) - free(s->title); - s->buf = NULL; - if (s->cv) - caca_free_canvas(s->cv); - s->cv = NULL; - free(s); - return 1; -} - -int add_screen(struct screen_list *list, struct screen *s) -{ - if (list == NULL || s == NULL) - return -1; - - else - { - list->screen = (struct screen **)realloc(list->screen, - sizeof(sizeof - (struct screen *)) * - (list->count + 1)); - if (!list->screen) - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - list->screen[list->count] = s; - list->count++; - } - - list->changed = 1; - - return list->count - 1; -} - -int remove_screen(struct screen_list *list, int n, int please_kill) -{ - - if (n >= list->count) - return -1; - - if (please_kill) - { - int status = 0; - int ret = 0; - /* FIXME */ - close(list->screen[n]->fd); - list->screen[n]->fd = -1; - kill(list->screen[n]->pid, SIGINT); - ret = waitpid(list->screen[n]->pid, &status, - WNOHANG | WUNTRACED | WCONTINUED); - if (!ret) - kill(list->screen[n]->pid, SIGQUIT); - ret = waitpid(list->screen[n]->pid, &status, - WNOHANG | WUNTRACED | WCONTINUED); - if (!ret) - kill(list->screen[n]->pid, SIGABRT); - ret = waitpid(list->screen[n]->pid, &status, - WNOHANG | WUNTRACED | WCONTINUED); - if (!ret) - kill(list->screen[n]->pid, SIGKILL); - - } - destroy_screen(list->screen[n]); - - memmove(&list->screen[n], - &list->screen[n + 1], - sizeof(struct screen *) * (list->count - (n + 1))); - - list->screen = (struct screen **)realloc(list->screen, - sizeof(sizeof(struct screen *)) - * (list->count)); - if (!list->screen) - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - - - - list->count--; - list->changed = 1; - return 1; -} - - - -void refresh_screens(struct screen_list *screen_list) -{ - int i; - - if (!screen_list->count) - return; - - - screen_list->width = caca_get_canvas_width(screen_list->cv); - screen_list->height = - caca_get_canvas_height(screen_list->cv) - (screen_list->modals.mini * 6) - - screen_list->modals.status; - - if (!screen_list->dont_update_coords) - { - update_windows_props(screen_list); - } - - if (screen_list->changed) - { - caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT); - caca_clear_canvas(screen_list->cv); - } - - wm_refresh(screen_list); - - caca_gotoxy(screen_list->cv, - screen_list->screen[screen_list->pty]->x + - caca_get_cursor_x(screen_list->screen[screen_list->pty]->cv), - screen_list->screen[screen_list->pty]->y + - caca_get_cursor_y(screen_list->screen[screen_list->pty]->cv)); - - - if (screen_list->modals.mini) - { - draw_thumbnails(screen_list); - } - if (screen_list->modals.status) - { - draw_status(screen_list); - } - if (screen_list->modals.help) - { - draw_help(screen_list); - } - if (screen_list->modals.window_list) - { - draw_list(screen_list); - } -#ifdef USE_PYTHON - debug("py : command is %d (at %p)\n", screen_list->modals.python_command, &screen_list->modals.python_command); - if(screen_list->modals.python_command) - { - draw_python_command(screen_list); - } -#endif - screen_list->changed = 0; - for (i = screen_list->count - 1; i >= 0; i--) - screen_list->screen[i]->changed = 0; -} - - -int update_screens_contents(struct screen_list *screen_list) -{ - int i, refresh = 0; - int maxfd = 0; - struct timeval tv; - fd_set fdset; - int ret; - - /* Read data, if any */ - FD_ZERO(&fdset); - for (i = 0; i < screen_list->count; i++) - { - if (screen_list->screen[i]->fd >= 0) - FD_SET(screen_list->screen[i]->fd, &fdset); - if (screen_list->screen[i]->fd > maxfd) - maxfd = screen_list->screen[i]->fd; - } - tv.tv_sec = 0; - tv.tv_usec = 50000; - ret = select(maxfd + 1, &fdset, NULL, NULL, &tv); - - if (ret < 0) - { - if (errno == EINTR) - ; /* We probably got a SIGWINCH, ignore it */ - else - { - /* FIXME: Useless since break will mean that we return 0 But I - don't know what was the purpose of this code */ - for (i = 0; i < screen_list->count; i++) - if (screen_list->screen[i]->total) - break; - if (i == screen_list->count) - return 0; - } - } - else if (ret) - { - - for (i = 0; i < screen_list->count; i++) - { - /* FIXME: try a new strategy: read all filedescriptors until each - of them starved at least once. */ - - if (screen_list->screen[i]->fd < 0 || - !FD_ISSET(screen_list->screen[i]->fd, &fdset)) - continue; - - for (;;) - { - ssize_t nr; - - screen_list->screen[i]->buf = - realloc(screen_list->screen[i]->buf, - screen_list->screen[i]->total + 1024); - if (!screen_list->screen[i]->buf) - fprintf(stderr, "Can't allocate memory at %s:%d\n", - __FUNCTION__, __LINE__); - - nr = read(screen_list->screen[i]->fd, - screen_list->screen[i]->buf + - screen_list->screen[i]->total, 1024); - - if (nr > 0) - { - screen_list->screen[i]->total += nr; - continue; - } - - if (nr == 0 || errno != EWOULDBLOCK) - { - remove_screen(screen_list, i, 0); - if (i < screen_list->prevpty) - screen_list->prevpty--; - if (i == screen_list->pty) - { - screen_list->pty = screen_list->prevpty; - screen_list->prevpty = 0; - } - if (i < (screen_list->pty)) - (screen_list->pty)--; - /* Don't skip the element which is now at position i */ - i--; - refresh = 1; - } - - break; - } - } - } - return refresh; -} - -#endif - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include #include #include "neercs.h" struct screen *create_screen_grab(int w, int h, int pid) { struct screen *s = (struct screen *)malloc(sizeof(struct screen)); s->cv = caca_create_canvas(w, h); caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK); caca_clear_canvas(s->cv); s->init = 0; s->buf = NULL; s->title = NULL; s->total = 0; s->w = w; s->h = h; s->bell = 0; s->report_mouse = MOUSE_NONE; s->fd = create_pty_grab(pid, w, h, &s->pid); if (s->fd < 0) { caca_free_canvas(s->cv); free(s); return NULL; } return s; } struct screen *create_screen(int w, int h, char *command) { struct screen *s = (struct screen *)malloc(sizeof(struct screen)); s->cv = caca_create_canvas(w, h); caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK); caca_clear_canvas(s->cv); s->init = 0; s->buf = NULL; s->title = NULL; s->total = 0; s->w = w + 1; s->h = h + 1; s->bell = 0; s->visible = 1; s->scroll = 0; s->report_mouse = MOUSE_NONE; s->fd = create_pty(command, w, h, &s->pid); s->orig_w = s->w; s->orig_h = s->h; s->orig_x = s->x; s->orig_y = s->y; if (s->fd < 0) { caca_free_canvas(s->cv); free(s); return NULL; } return s; } int destroy_screen(struct screen *s) { if (s->fd >= 0) close(s->fd); if (s->buf) free(s->buf); if (s->title) free(s->title); s->buf = NULL; if (s->cv) caca_free_canvas(s->cv); s->cv = NULL; free(s); return 1; } int add_screen(struct screen_list *list, struct screen *s) { if (list == NULL || s == NULL) return -1; else { list->screen = (struct screen **)realloc(list->screen, sizeof(sizeof (struct screen *)) * (list->count + 1)); if (!list->screen) fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); list->screen[list->count] = s; list->count++; } list->changed = 1; return list->count - 1; } int remove_screen(struct screen_list *list, int n, int please_kill) { if (n >= list->count) return -1; if (please_kill) { int status = 0; int ret = 0; /* FIXME */ close(list->screen[n]->fd); list->screen[n]->fd = -1; kill(list->screen[n]->pid, SIGINT); ret = waitpid(list->screen[n]->pid, &status, WNOHANG | WUNTRACED | WCONTINUED); if (!ret) kill(list->screen[n]->pid, SIGQUIT); ret = waitpid(list->screen[n]->pid, &status, WNOHANG | WUNTRACED | WCONTINUED); if (!ret) kill(list->screen[n]->pid, SIGABRT); ret = waitpid(list->screen[n]->pid, &status, WNOHANG | WUNTRACED | WCONTINUED); if (!ret) kill(list->screen[n]->pid, SIGKILL); } destroy_screen(list->screen[n]); memmove(&list->screen[n], &list->screen[n + 1], sizeof(struct screen *) * (list->count - (n + 1))); list->screen = (struct screen **)realloc(list->screen, sizeof(sizeof(struct screen *)) * (list->count)); if (!list->screen) fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); list->count--; list->changed = 1; return 1; } void refresh_screens(struct screen_list *screen_list) { int i; if (!screen_list->count) return; screen_list->width = caca_get_canvas_width(screen_list->cv); screen_list->height = caca_get_canvas_height(screen_list->cv) - (screen_list->modals.mini * 6) - screen_list->modals.status; if (!screen_list->dont_update_coords) { update_windows_props(screen_list); } if (screen_list->changed) { caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT); caca_clear_canvas(screen_list->cv); } wm_refresh(screen_list); caca_gotoxy(screen_list->cv, screen_list->screen[screen_list->pty]->x + caca_get_cursor_x(screen_list->screen[screen_list->pty]->cv), screen_list->screen[screen_list->pty]->y + caca_get_cursor_y(screen_list->screen[screen_list->pty]->cv)); if (screen_list->modals.mini) { draw_thumbnails(screen_list); } if (screen_list->modals.status) { draw_status(screen_list); } if (screen_list->modals.help) { draw_help(screen_list); } if (screen_list->modals.window_list) { draw_list(screen_list); } #ifdef USE_PYTHON debug("py : command is %d (at %p)\n", screen_list->modals.python_command, &screen_list->modals.python_command); if(screen_list->modals.python_command) { draw_python_command(screen_list); } #endif screen_list->changed = 0; for (i = screen_list->count - 1; i >= 0; i--) screen_list->screen[i]->changed = 0; } int update_screens_contents(struct screen_list *screen_list) { int i, refresh = 0; int maxfd = 0; struct timeval tv; fd_set fdset; int ret; /* Read data, if any */ FD_ZERO(&fdset); for (i = 0; i < screen_list->count; i++) { if (screen_list->screen[i]->fd >= 0) FD_SET(screen_list->screen[i]->fd, &fdset); if (screen_list->screen[i]->fd > maxfd) maxfd = screen_list->screen[i]->fd; } tv.tv_sec = 0; tv.tv_usec = 50000; ret = select(maxfd + 1, &fdset, NULL, NULL, &tv); if (ret < 0) { if (errno == EINTR) ; /* We probably got a SIGWINCH, ignore it */ else { /* FIXME: Useless since break will mean that we return 0 But I don't know what was the purpose of this code */ for (i = 0; i < screen_list->count; i++) if (screen_list->screen[i]->total) break; if (i == screen_list->count) return 0; } } else if (ret) { for (i = 0; i < screen_list->count; i++) { /* FIXME: try a new strategy: read all filedescriptors until each of them starved at least once. */ if (screen_list->screen[i]->fd < 0 || !FD_ISSET(screen_list->screen[i]->fd, &fdset)) continue; for (;;) { ssize_t nr; screen_list->screen[i]->buf = realloc(screen_list->screen[i]->buf, screen_list->screen[i]->total + 1024); if (!screen_list->screen[i]->buf) fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); nr = read(screen_list->screen[i]->fd, screen_list->screen[i]->buf + screen_list->screen[i]->total, 1024); if (nr > 0) { screen_list->screen[i]->total += nr; continue; } if (nr == 0 || errno != EWOULDBLOCK) { remove_screen(screen_list, i, 0); if (i < screen_list->prevpty) screen_list->prevpty--; if (i == screen_list->pty) { screen_list->pty = screen_list->prevpty; screen_list->prevpty = 0; } if (i < (screen_list->pty)) (screen_list->pty)--; /* Don't skip the element which is now at position i */ i--; refresh = 1; } break; } } } return refresh; } #endif \ No newline at end of file diff --git a/neercs/old/screensaver.c b/neercs/old/screensaver.c index 533af9d..15d5e30 100644 --- a/neercs/old/screensaver.c +++ b/neercs/old/screensaver.c @@ -1,193 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "neercs.h" - - -void screensaver_init(struct screen_list *screen_list) -{ - screensaver_flying_toasters_init(screen_list); -} - -void screensaver_kill(struct screen_list *screen_list) -{ - screensaver_flying_toasters_kill(screen_list); -} - -void draw_screensaver(struct screen_list *screen_list) -{ - screensaver_flying_toasters(screen_list); -} - - - - -/* Flying Toasters */ - -#define COUNT 15 -#define PRECISION 100 - -char toaster_text[3][99] = { { - " __._ \n" - " .-'== _',\n" - " <|_= .-' |\n" - " | --| \\'.-_ \n" - " | | \\ \" _.\n" - " `-_|.-\\_.-\n"}, -{ - " __._ \n" - " .-'== _',\n" - " \\|_= .-' |\n" - " | --| __'-.\n" - " | | ___.-\n" - " `-_|.-\n"}, -{ - " _- __._\n" - " /.-'== _',_.-.\n" - " \\|_= .-'/ _.'\n" - " | --| / .-\n" - " | | _.|\n" - " `-_|.-\n"} -}; - -char toaster_mask[3][99] = { { - - " __._ \n" - " .-'== _',\n" - " <|_=X.-'XX|\n" - " |X--|XXX\\'.-_ \n" - " |XXX|X\\XX\"X_.\n" - " `-_|.-\\_.-\n"}, - { - - " __._ \n" - " .-'== _',\n" - " \\|_= .-'XX|\n" - " |X--|XX__'-.\n" - " |XXX|X___.-\n" - " `-_|.-\n"}, -{ - " _- __._\n" - " /.-'== _',_.-.\n" - " \\|_= .-'/XX_.'\n" - " |X--|X/X.-\n" - " |XXX|XX_.|\n" - " `-_|.-\n"} -}; - -struct flying_toaster -{ - int x[COUNT], y[COUNT], s[COUNT]; - caca_canvas_t **toaster; - caca_canvas_t **mask; -}; - -void screensaver_flying_toasters_init(struct screen_list *screen_list) -{ - struct flying_toaster *flying_toaster; - int w = caca_get_canvas_width(screen_list->cv); - int h = caca_get_canvas_height(screen_list->cv); - int i; - - flying_toaster = malloc(sizeof(struct flying_toaster)); - flying_toaster->toaster = - (caca_canvas_t **) malloc(sizeof(caca_canvas_t *) * 3); - flying_toaster->mask = - (caca_canvas_t **) malloc(sizeof(caca_canvas_t *) * 3); - - for (i = 0; i < 3; i++) - { - flying_toaster->toaster[i] = caca_create_canvas(0, 0); - flying_toaster->mask[i] = caca_create_canvas(0, 0); - caca_import_canvas_from_memory(flying_toaster->toaster[i], - toaster_text[i], - strlen(toaster_text[i]), "utf8"); - caca_import_canvas_from_memory(flying_toaster->mask[i], - toaster_mask[i], - strlen(toaster_mask[i]), "utf8"); - } - - for (i = 0; i < COUNT; i++) - { - flying_toaster->x[i] = (rand() % w) * PRECISION; - flying_toaster->y[i] = (rand() % h) * PRECISION; - flying_toaster->s[i] = (rand() % 3) * PRECISION; - } - - - screen_list->screensaver.data = flying_toaster; -} - -void screensaver_flying_toasters_kill(struct screen_list *screen_list) -{ - struct flying_toaster *flying_toaster = screen_list->screensaver.data; - - caca_free_canvas(flying_toaster->toaster[0]); - caca_free_canvas(flying_toaster->toaster[1]); - caca_free_canvas(flying_toaster->toaster[2]); - free(flying_toaster->toaster); - free(flying_toaster); - screen_list->screensaver.data = NULL; -} - -void screensaver_flying_toasters(struct screen_list *screen_list) -{ - struct flying_toaster *d = screen_list->screensaver.data; - int i, w, h, x, y, s; - if (!d) - return; - - w = caca_get_canvas_width(screen_list->cv); - h = caca_get_canvas_height(screen_list->cv); - - caca_set_color_ansi(screen_list->cv, CACA_WHITE, CACA_BLACK); - caca_clear_canvas(screen_list->cv); - - for (i = 0; i < COUNT; i++) - { - x = d->x[i] / PRECISION; - y = d->y[i] / PRECISION; - s = d->s[i] / PRECISION; - - caca_blit(screen_list->cv, x, y, d->toaster[s], d->mask[s]); - - d->x[i] -= 40; - d->y[i] += 10; - - if (d->x[i] / PRECISION + caca_get_canvas_width(d->toaster[s]) <= 0) - d->x[i] = ((rand() % w) / 3 + w) * PRECISION; - if (d->y[i] / PRECISION >= h) - d->y[i] = ((rand() % h) / 2 - h) * PRECISION; - - d->s[i] = ((d->s[i] + 24) % (3 * PRECISION)); - } -} - -#endif +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include #include #include "neercs.h" void screensaver_init(struct screen_list *screen_list) { screensaver_flying_toasters_init(screen_list); } void screensaver_kill(struct screen_list *screen_list) { screensaver_flying_toasters_kill(screen_list); } void draw_screensaver(struct screen_list *screen_list) { screensaver_flying_toasters(screen_list); } /* Flying Toasters */ #define COUNT 15 #define PRECISION 100 char toaster_text[3][99] = { { " __._ \n" " .-'== _',\n" " <|_= .-' |\n" " | --| \\'.-_ \n" " | | \\ \" _.\n" " `-_|.-\\_.-\n"}, { " __._ \n" " .-'== _',\n" " \\|_= .-' |\n" " | --| __'-.\n" " | | ___.-\n" " `-_|.-\n"}, { " _- __._\n" " /.-'== _',_.-.\n" " \\|_= .-'/ _.'\n" " | --| / .-\n" " | | _.|\n" " `-_|.-\n"} }; char toaster_mask[3][99] = { { " __._ \n" " .-'== _',\n" " <|_=X.-'XX|\n" " |X--|XXX\\'.-_ \n" " |XXX|X\\XX\"X_.\n" " `-_|.-\\_.-\n"}, { " __._ \n" " .-'== _',\n" " \\|_= .-'XX|\n" " |X--|XX__'-.\n" " |XXX|X___.-\n" " `-_|.-\n"}, { " _- __._\n" " /.-'== _',_.-.\n" " \\|_= .-'/XX_.'\n" " |X--|X/X.-\n" " |XXX|XX_.|\n" " `-_|.-\n"} }; struct flying_toaster { int x[COUNT], y[COUNT], s[COUNT]; caca_canvas_t **toaster; caca_canvas_t **mask; }; void screensaver_flying_toasters_init(struct screen_list *screen_list) { struct flying_toaster *flying_toaster; int w = caca_get_canvas_width(screen_list->cv); int h = caca_get_canvas_height(screen_list->cv); int i; flying_toaster = malloc(sizeof(struct flying_toaster)); flying_toaster->toaster = (caca_canvas_t **) malloc(sizeof(caca_canvas_t *) * 3); flying_toaster->mask = (caca_canvas_t **) malloc(sizeof(caca_canvas_t *) * 3); for (i = 0; i < 3; i++) { flying_toaster->toaster[i] = caca_create_canvas(0, 0); flying_toaster->mask[i] = caca_create_canvas(0, 0); caca_import_canvas_from_memory(flying_toaster->toaster[i], toaster_text[i], strlen(toaster_text[i]), "utf8"); caca_import_canvas_from_memory(flying_toaster->mask[i], toaster_mask[i], strlen(toaster_mask[i]), "utf8"); } for (i = 0; i < COUNT; i++) { flying_toaster->x[i] = (rand() % w) * PRECISION; flying_toaster->y[i] = (rand() % h) * PRECISION; flying_toaster->s[i] = (rand() % 3) * PRECISION; } screen_list->screensaver.data = flying_toaster; } void screensaver_flying_toasters_kill(struct screen_list *screen_list) { struct flying_toaster *flying_toaster = screen_list->screensaver.data; caca_free_canvas(flying_toaster->toaster[0]); caca_free_canvas(flying_toaster->toaster[1]); caca_free_canvas(flying_toaster->toaster[2]); free(flying_toaster->toaster); free(flying_toaster); screen_list->screensaver.data = NULL; } void screensaver_flying_toasters(struct screen_list *screen_list) { struct flying_toaster *d = screen_list->screensaver.data; int i, w, h, x, y, s; if (!d) return; w = caca_get_canvas_width(screen_list->cv); h = caca_get_canvas_height(screen_list->cv); caca_set_color_ansi(screen_list->cv, CACA_WHITE, CACA_BLACK); caca_clear_canvas(screen_list->cv); for (i = 0; i < COUNT; i++) { x = d->x[i] / PRECISION; y = d->y[i] / PRECISION; s = d->s[i] / PRECISION; caca_blit(screen_list->cv, x, y, d->toaster[s], d->mask[s]); d->x[i] -= 40; d->y[i] += 10; if (d->x[i] / PRECISION + caca_get_canvas_width(d->toaster[s]) <= 0) d->x[i] = ((rand() % w) / 3 + w) * PRECISION; if (d->y[i] / PRECISION >= h) d->y[i] = ((rand() % h) / 2 - h) * PRECISION; d->s[i] = ((d->s[i] + 24) % (3 * PRECISION)); } } #endif \ No newline at end of file diff --git a/neercs/old/server.c b/neercs/old/server.c index 65d0a8b..47b909d 100644 --- a/neercs/old/server.c +++ b/neercs/old/server.c @@ -1,691 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "neercs.h" - -static void server_init(struct screen_list *screen_list); -static void refresh_screen(struct screen_list *screen_list, int refresh); -static int handle_key(struct screen_list *screen_list, unsigned int c, - int refresh); -static int handle_attach(struct screen_list *screen_list, char *buf); - -static int send_to_client(const char *msg, int size, - struct screen_list *screen_list) -{ - int ret; - if (!screen_list->comm.socket[SOCK_CLIENT]) - connect_socket(screen_list, SOCK_CLIENT); - if (!screen_list->comm.socket[SOCK_CLIENT]) - ret = -1; - else - ret = write(screen_list->comm.socket[SOCK_CLIENT], msg, size); - if (ret < 0 && errno != EAGAIN) - { - fprintf(stderr, "Failed to send message to client: %s\n", - strerror(errno)); - if (screen_list->comm.attached) - detach(screen_list); - } - return ret; -} - -static int set_title(struct screen_list *screen_list) -{ - char buf[1024]; - int bytes; - char *title = NULL; - - if (screen_list->comm.attached) - { - if (screen_list->pty < screen_list->count && - screen_list->screen[screen_list->pty]->title) - title = screen_list->screen[screen_list->pty]->title; - else - title = PACKAGE_STRING; - } - - if (screen_list->title) - { - if (!strcmp(screen_list->title, title)) - return 0; - free(screen_list->title); - } - - screen_list->title = strdup(title); - - bytes = snprintf(buf, sizeof(buf) - 1, "TITLE %s", title); - buf[bytes] = '\0'; - return send_to_client(buf, strlen(buf), screen_list); -} - -static int set_cursor(int state, struct screen_list *screen_list) -{ - char buf[16]; - int bytes; - - bytes = snprintf(buf, sizeof(buf) - 1, "CURSOR %d", state); - buf[bytes] = '\0'; - - return send_to_client(buf, strlen(buf), screen_list); -} - -static int request_refresh(struct screen_list *screen_list) -{ - int ndirty = caca_get_dirty_rect_count(screen_list->cv); - if (!ndirty) - return 0; - if (!screen_list->comm.socket[SOCK_CLIENT]) - connect_socket(screen_list, SOCK_CLIENT); - if (screen_list->comm.socket[SOCK_CLIENT]) - { - size_t bufsize, towrite; - ssize_t written, ret; - socklen_t optlen = sizeof(bufsize); - size_t bytes; - void *buf; - char buf2[32]; - int x, y, i; - - getsockopt(screen_list->comm.socket[SOCK_CLIENT], SOL_SOCKET, - SO_SNDBUF, &bufsize, &optlen); - bufsize /= 2; - debug("bufsize=%d", bufsize); - - for (i = 0; i < ndirty; i++) - { - int w, h; - caca_get_dirty_rect(screen_list->cv, i, &x, &y, &w, &h); - debug("dirty @%d,%d %dx%d [%dx%d]", x, y, w, h, - caca_get_canvas_width(screen_list->cv), - caca_get_canvas_height(screen_list->cv)); - buf = - caca_export_area_to_memory(screen_list->cv, x, y, w, h, "caca", - &bytes); - debug("Requesting refresh for %d", bytes); - towrite = bytes; - written = 0; - sprintf(buf2, "UPDATE %10d %10d", x, y); - ret = send_to_client(buf2, strlen(buf2) + 1, screen_list); - if (ret < 29) - { - free(buf); - return -1; - } - /* Block to write the end of the message */ - fcntl(screen_list->comm.socket[SOCK_CLIENT], F_SETFL, 0); - while (towrite > 0) - { - ssize_t n; - debug("Wrote %d, %d remaining", written, towrite); - n = send_to_client((char *)buf + written, - towrite > bufsize ? bufsize : towrite, - screen_list); - if (n < 0) - { - debug("Can't refresh (%s), with %d bytes (out of %d)", - strerror(errno), - towrite > bufsize ? bufsize : towrite, towrite); - return -1; - } - written += n; - towrite -= n; - } - fcntl(screen_list->comm.socket[SOCK_CLIENT], F_SETFL, O_NONBLOCK); - free(buf); - } - sprintf(buf2, "REFRESH %10d %10d", caca_get_cursor_x(screen_list->cv), - caca_get_cursor_y(screen_list->cv)); - /* FIXME check value of r */ - int r = send_to_client(buf2, strlen(buf2) + 1, screen_list); - (void)r; - caca_clear_dirty_rect_list(screen_list->cv); - } - return 0; -} - -int detach(struct screen_list *screen_list) -{ - screen_list->comm.attached = 0; - if (screen_list->lock.lock_on_detach) - screen_list->lock.locked = 1; - if (screen_list->comm.socket[SOCK_CLIENT]) - { - send_to_client("DETACH", 6, screen_list); - close(screen_list->comm.socket[SOCK_CLIENT]); - screen_list->comm.socket[SOCK_CLIENT] = 0; - } - return 0; -} - -static int server_iteration(struct screen_list *screen_list) -{ - int i; - int eof = 0, refresh; - - int quit = 0; - ssize_t n; - char buf[128]; - - /* Read program output */ - refresh = update_screens_contents(screen_list); - - /* Check if we got something from the client */ - while (screen_list->comm.socket[SOCK_SERVER] - && (n = - read(screen_list->comm.socket[SOCK_SERVER], buf, - sizeof(buf) - 1)) > 0) - { - buf[n] = 0; - debug("Received command %s", buf); - if (!strncmp("ATTACH ", buf, 7)) - { - refresh |= handle_attach(screen_list, buf); - } - else if (!strncmp("QUIT", buf, 4)) - { - quit = 1; - } - else if (!strncmp("DELAY ", buf, 6)) - { - /* FIXME check the length before calling atoi */ - screen_list->delay = atoi(buf + 6); - } - else if (!strncmp("RESIZE ", buf, 7)) - { - caca_free_canvas(screen_list->cv); - /* FIXME check the length before calling atoi */ - screen_list->cv = - caca_create_canvas(atoi(buf + 7), atoi(buf + 18)); - screen_list->changed = 1; - refresh = 1; - } - else if (!strncmp("KEY ", buf, 4)) - { - unsigned int c = atoi(buf + 4); - refresh |= handle_key(screen_list, c, refresh); - } - else if (!strncmp("MOUSEP ", buf, 6)) - { - debug("Got mouse press '%s'\n", buf); - int x, y, b; - x = 1 + atoi(buf + 7) - screen_list->screen[screen_list->pty]->x; - y = 1 + atoi(buf + 18) - screen_list->screen[screen_list->pty]->y; - b = atoi(buf + 28); - - switch (screen_list->screen[screen_list->pty]->report_mouse) - { - case MOUSE_VT200: - case MOUSE_VT200_HIGHLIGHT: - case MOUSE_BTN_EVENT: - case MOUSE_ANY_EVENT: - sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), x + 32, y + 32); - debug("mousea send ESC[M %d %d %d", (b - 1), x + 32, y + 32); - send_ansi_sequence(screen_list, buf); - break; - case MOUSE_X10: - sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), 32 + x, 32 + y); - debug("mousex send ESC[M %d %d %d", 32 + (b - 1), 32 + x, - 32 + y); - send_ansi_sequence(screen_list, buf); - break; - case MOUSE_NONE: - break; - - } - } - else if (!strncmp("MOUSER ", buf, 6)) - { - debug("Got mouse release '%s'\n", buf); - int x, y, b; - x = 1 + atoi(buf + 7) - screen_list->screen[screen_list->pty]->x; - y = 1 + atoi(buf + 18) - screen_list->screen[screen_list->pty]->y; - b = atoi(buf + 28); - - switch (screen_list->screen[screen_list->pty]->report_mouse) - { - case MOUSE_VT200: - case MOUSE_VT200_HIGHLIGHT: - case MOUSE_BTN_EVENT: - case MOUSE_ANY_EVENT: - sprintf(buf, "\x1b[M%c%c%c", 32 + 3, x + 32, y + 32); - send_ansi_sequence(screen_list, buf); - break; - case MOUSE_X10: - sprintf(buf, "\x1b[M%c%c%c", 32 + 3, 32 + x, 32 + y); - send_ansi_sequence(screen_list, buf); - break; - case MOUSE_NONE: - break; - } - } - - else if (!strncmp("MOUSEM ", buf, 6)) - { - debug("Got mouse motion '%s'\n", buf); - int x, y, b; - x = 1 + atoi(buf + 7) - screen_list->screen[screen_list->pty]->x; - y = 1 + atoi(buf + 18) - screen_list->screen[screen_list->pty]->y; - b = atoi(buf + 28); - - switch (screen_list->screen[screen_list->pty]->report_mouse) - { - case MOUSE_X10: // X10 reports mouse clicks only - if (b) - { - sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), x + 32, y + 32); - send_ansi_sequence(screen_list, buf); - } - break; - case MOUSE_VT200: - case MOUSE_VT200_HIGHLIGHT: - case MOUSE_BTN_EVENT: - if (b) - { - sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), x + 32, y + 32); - send_ansi_sequence(screen_list, buf); - } - case MOUSE_ANY_EVENT: - sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), x + 32, y + 32); - send_ansi_sequence(screen_list, buf); - break; - case MOUSE_NONE: - break; - } - } - else - { - fprintf(stderr, "Unknown command received: %s\n", buf); - } - } - - /* No more screens, exit */ - if (!screen_list->count) - return -1; - - /* User requested to exit */ - if (quit) - return -2; - - /* Update each screen canvas */ - refresh |= update_terms(screen_list); - - /* Launch recurrents if any */ - refresh |= handle_recurrents(screen_list); - - /* Refresh screen */ - refresh_screen(screen_list, refresh); - - eof = 1; - for (i = 0; i < screen_list->count; i++) - if (screen_list->screen[i]->fd >= 0) - eof = 0; - if (eof) - return -3; - - return 0; -} - -static void server_main(struct screen_list *screen_list) -{ - screen_list->last_key_time = 0; - screen_list->comm.attached = 0; - screen_list->command = 0; - screen_list->was_in_bell = 0; - screen_list->last_refresh_time = 0; - - server_init(screen_list); -#ifdef USE_PYTHON - python_init(screen_list); -#endif - - for (;;) - { - if (server_iteration(screen_list)) - break; - } - - detach(screen_list); - - free_screen_list(screen_list); - -#ifdef USE_PYTHON - python_close(screen_list); -#endif - - exit(0); -} - -static void refresh_screen(struct screen_list *screen_list, int refresh) -{ - if (!screen_list->comm.attached) - { - /* No need to refresh Don't use the CPU too much Would be better to - select on terms + socket */ - sleep(1); - } - else - { - long long unsigned int current_time = get_us(); - long long int tdiff = - (current_time - screen_list->last_refresh_time) / 1000; - - refresh |= screen_list->need_refresh; - - if (screen_list->force_refresh) - { - wm_refresh(screen_list); - refresh = 1; - } - - /* Draw lock window */ - if (screen_list->lock.locked) - { - /* FIXME don't redraw it each iteration */ - draw_lock(screen_list); - refresh = 1; - } -#ifdef USE_LOCK - else if ((current_time - screen_list->last_key_time >= - screen_list->lock.autolock_timeout)) - { - screen_list->lock.locked = 1; - refresh = 1; - } -#endif - else if ((current_time - screen_list->last_key_time >= - screen_list->screensaver.timeout)) - { - if (!screen_list->screensaver.in_screensaver) - { - screensaver_init(screen_list); - screen_list->screensaver.in_screensaver = 1; - set_cursor(0, screen_list); - } - draw_screensaver(screen_list); - refresh = 1; - } - else if (refresh || screen_list->was_in_bell) - { - if (tdiff >= screen_list->delay) - { - refresh_screens(screen_list); - set_title(screen_list); - refresh = 1; - } - } - if (refresh) - { - if (tdiff >= screen_list->delay) - { - request_refresh(screen_list); - screen_list->last_refresh_time = current_time; - screen_list->need_refresh = 0; - } - else - { - debug("Skipping refresh (%lld < %d)", tdiff, - screen_list->delay); - screen_list->need_refresh = 1; - } - } - } -} - -static void server_init(struct screen_list *screen_list) -{ - int i; - debug("Screen list at %p\n", screen_list); - - /* Create socket and bind it */ - create_socket(screen_list, SOCK_SERVER); - - /* Connect to the client */ - connect_socket(screen_list, SOCK_CLIENT); - - screen_list->width = screen_list->height = 80; - - /* Create main canvas */ - screen_list->cv = caca_create_canvas(screen_list->width, - screen_list->height - + screen_list->modals.mini * 6 - + screen_list->modals.status); - - if (!screen_list->sys.to_grab && !screen_list->sys.to_start) - { - add_screen(screen_list, - create_screen(screen_list->width, - screen_list->height, - screen_list->sys.default_shell)); - } - - /* Attach processes */ - if (screen_list->sys.to_grab) - { - for (i = 0; screen_list->sys.to_grab[i]; i++) - { - add_screen(screen_list, - create_screen_grab(screen_list->width, - screen_list->height, - screen_list->sys.to_grab[i])); - } - free(screen_list->sys.to_grab); - screen_list->sys.to_grab = NULL; - } - - /* Launch command line processes */ - if (screen_list->sys.to_start) - { - for (i = 0; screen_list->sys.to_start[i]; i++) - { - add_screen(screen_list, - create_screen(screen_list->width, - screen_list->height, - screen_list->sys.to_start[i])); - free(screen_list->sys.to_start[i]); - } - free(screen_list->sys.to_start); - screen_list->sys.to_start = NULL; - } - - screen_list->last_key_time = get_us(); -} - -static int handle_attach(struct screen_list *screen_list, char *buf) -{ - /* If we were attached to someone else, detach first */ - if (screen_list->comm.attached) - detach(screen_list); - screen_list->comm.attached = 1; - caca_free_canvas(screen_list->cv); - screen_list->cv = caca_create_canvas(atoi(buf + 7), atoi(buf + 18)); - screen_list->delay = atoi(buf + 29); - screen_list->changed = 1; - return 1; -} - -static int handle_key(struct screen_list *screen_list, unsigned int c, - int refresh) -{ - char *str = NULL; - int size = 0; - - if (screen_list->modals.help) - { - return help_handle_key(screen_list, c); - } -#ifdef USE_PYTHON - if (screen_list->modals.python_command) - { - return python_command_handle_key(screen_list, c); - } -#endif - - /* CTRL-A has been pressed before, handle this as a command, except that - CTRL-A a sends literal CTRL-A */ - if (screen_list->command && (c != 'a')) - { - screen_list->command = 0; - refresh |= handle_command_input(screen_list, c); - } - else - { - /* Not in command mode */ - screen_list->last_key_time = get_us(); - set_cursor(1, screen_list); - - /* Kill screensaver */ - if (screen_list->screensaver.in_screensaver) - { - screensaver_kill(screen_list); - screen_list->screensaver.in_screensaver = 0; - screen_list->changed = 1; - refresh = 1; - return refresh; - } - /* Handle lock window */ - if (screen_list->lock.locked) - { - refresh |= update_lock(c, screen_list); - screen_list->changed = 1; - } - else if (screen_list->modals.window_list) - { - refresh |= update_window_list(c, screen_list); - screen_list->changed = 1; - } - else - { - switch (c) - { - case 0x01: // CACA_KEY_CTRL_A: - screen_list->command = 1; - break; - default: - /* CTRL-A a sends literal CTRL-A */ - if (screen_list->command && (c == 'a')) - { - c = 0x01; - } - /* Normal key, convert it if needed */ - str = convert_input_ansi(&c, &size); - /* FIXME check value of r */ - int r = write(screen_list->screen[screen_list->pty]->fd, str, - size); - (void)r; - break; - } - } - } - return refresh; -} - -int send_ansi_sequence(struct screen_list *screen_list, char *str) -{ - debug("Sending ansi '%s'\n", str); - return write(screen_list->screen[screen_list->pty]->fd, str, strlen(str)); -} - - -int install_fds(struct screen_list *screen_list) -{ - int fd; - close(0); - close(1); - close(2); - fd = open("/dev/null", O_RDWR, 0); - if (fd < 0) - { - perror("Failed to open /dev/null"); - return -2; - } - dup2(fd, 0); -#ifndef DEBUG - dup2(fd, 1); - dup2(fd, 2); - if (fd > 2) - close(fd); -#else - if (fd != 0) - close(fd); - screen_list->outfd = - open("/tmp/neercs-debug.txt", O_TRUNC | O_RDWR | O_CREAT, - S_IRUSR | S_IWUSR); - dup2(screen_list->outfd, 1); - dup2(screen_list->outfd, 2); - if (screen_list->outfd > 2) - close(screen_list->outfd); -#endif - return 0; -} - -int start_server(struct screen_list *screen_list) -{ - pid_t pid; - - pid = fork(); - if (pid < 0) - { - perror("Failed to create child process"); - return -1; - } - if (pid == 0) - { - int r = install_fds(screen_list); - if (r) - return r; - setsid(); - - server_main(screen_list); - /* Never returns */ - } - - return 0; -} - -long long get_us(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return (tv.tv_sec * (1000000) + tv.tv_usec); -} - -#else -/* FIXME: unimplemented */ -long long get_us(void) { return 0; } -int send_ansi_sequence(struct screen_list *screen_list, char *str) { return 0; } -#endif - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "neercs.h" static void server_init(struct screen_list *screen_list); static void refresh_screen(struct screen_list *screen_list, int refresh); static int handle_key(struct screen_list *screen_list, unsigned int c, int refresh); static int handle_attach(struct screen_list *screen_list, char *buf); static int send_to_client(const char *msg, int size, struct screen_list *screen_list) { int ret; if (!screen_list->comm.socket[SOCK_CLIENT]) connect_socket(screen_list, SOCK_CLIENT); if (!screen_list->comm.socket[SOCK_CLIENT]) ret = -1; else ret = write(screen_list->comm.socket[SOCK_CLIENT], msg, size); if (ret < 0 && errno != EAGAIN) { fprintf(stderr, "Failed to send message to client: %s\n", strerror(errno)); if (screen_list->comm.attached) detach(screen_list); } return ret; } static int set_title(struct screen_list *screen_list) { char buf[1024]; int bytes; char *title = NULL; if (screen_list->comm.attached) { if (screen_list->pty < screen_list->count && screen_list->screen[screen_list->pty]->title) title = screen_list->screen[screen_list->pty]->title; else title = PACKAGE_STRING; } if (screen_list->title) { if (!strcmp(screen_list->title, title)) return 0; free(screen_list->title); } screen_list->title = strdup(title); bytes = snprintf(buf, sizeof(buf) - 1, "TITLE %s", title); buf[bytes] = '\0'; return send_to_client(buf, strlen(buf), screen_list); } static int set_cursor(int state, struct screen_list *screen_list) { char buf[16]; int bytes; bytes = snprintf(buf, sizeof(buf) - 1, "CURSOR %d", state); buf[bytes] = '\0'; return send_to_client(buf, strlen(buf), screen_list); } static int request_refresh(struct screen_list *screen_list) { int ndirty = caca_get_dirty_rect_count(screen_list->cv); if (!ndirty) return 0; if (!screen_list->comm.socket[SOCK_CLIENT]) connect_socket(screen_list, SOCK_CLIENT); if (screen_list->comm.socket[SOCK_CLIENT]) { size_t bufsize, towrite; ssize_t written, ret; socklen_t optlen = sizeof(bufsize); size_t bytes; void *buf; char buf2[32]; int x, y, i; getsockopt(screen_list->comm.socket[SOCK_CLIENT], SOL_SOCKET, SO_SNDBUF, &bufsize, &optlen); bufsize /= 2; debug("bufsize=%d", bufsize); for (i = 0; i < ndirty; i++) { int w, h; caca_get_dirty_rect(screen_list->cv, i, &x, &y, &w, &h); debug("dirty @%d,%d %dx%d [%dx%d]", x, y, w, h, caca_get_canvas_width(screen_list->cv), caca_get_canvas_height(screen_list->cv)); buf = caca_export_area_to_memory(screen_list->cv, x, y, w, h, "caca", &bytes); debug("Requesting refresh for %d", bytes); towrite = bytes; written = 0; sprintf(buf2, "UPDATE %10d %10d", x, y); ret = send_to_client(buf2, strlen(buf2) + 1, screen_list); if (ret < 29) { free(buf); return -1; } /* Block to write the end of the message */ fcntl(screen_list->comm.socket[SOCK_CLIENT], F_SETFL, 0); while (towrite > 0) { ssize_t n; debug("Wrote %d, %d remaining", written, towrite); n = send_to_client((char *)buf + written, towrite > bufsize ? bufsize : towrite, screen_list); if (n < 0) { debug("Can't refresh (%s), with %d bytes (out of %d)", strerror(errno), towrite > bufsize ? bufsize : towrite, towrite); return -1; } written += n; towrite -= n; } fcntl(screen_list->comm.socket[SOCK_CLIENT], F_SETFL, O_NONBLOCK); free(buf); } sprintf(buf2, "REFRESH %10d %10d", caca_get_cursor_x(screen_list->cv), caca_get_cursor_y(screen_list->cv)); /* FIXME check value of r */ int r = send_to_client(buf2, strlen(buf2) + 1, screen_list); (void)r; caca_clear_dirty_rect_list(screen_list->cv); } return 0; } int detach(struct screen_list *screen_list) { screen_list->comm.attached = 0; if (screen_list->lock.lock_on_detach) screen_list->lock.locked = 1; if (screen_list->comm.socket[SOCK_CLIENT]) { send_to_client("DETACH", 6, screen_list); close(screen_list->comm.socket[SOCK_CLIENT]); screen_list->comm.socket[SOCK_CLIENT] = 0; } return 0; } static int server_iteration(struct screen_list *screen_list) { int i; int eof = 0, refresh; int quit = 0; ssize_t n; char buf[128]; /* Read program output */ refresh = update_screens_contents(screen_list); /* Check if we got something from the client */ while (screen_list->comm.socket[SOCK_SERVER] && (n = read(screen_list->comm.socket[SOCK_SERVER], buf, sizeof(buf) - 1)) > 0) { buf[n] = 0; debug("Received command %s", buf); if (!strncmp("ATTACH ", buf, 7)) { refresh |= handle_attach(screen_list, buf); } else if (!strncmp("QUIT", buf, 4)) { quit = 1; } else if (!strncmp("DELAY ", buf, 6)) { /* FIXME check the length before calling atoi */ screen_list->delay = atoi(buf + 6); } else if (!strncmp("RESIZE ", buf, 7)) { caca_free_canvas(screen_list->cv); /* FIXME check the length before calling atoi */ screen_list->cv = caca_create_canvas(atoi(buf + 7), atoi(buf + 18)); screen_list->changed = 1; refresh = 1; } else if (!strncmp("KEY ", buf, 4)) { unsigned int c = atoi(buf + 4); refresh |= handle_key(screen_list, c, refresh); } else if (!strncmp("MOUSEP ", buf, 6)) { debug("Got mouse press '%s'\n", buf); int x, y, b; x = 1 + atoi(buf + 7) - screen_list->screen[screen_list->pty]->x; y = 1 + atoi(buf + 18) - screen_list->screen[screen_list->pty]->y; b = atoi(buf + 28); switch (screen_list->screen[screen_list->pty]->report_mouse) { case MOUSE_VT200: case MOUSE_VT200_HIGHLIGHT: case MOUSE_BTN_EVENT: case MOUSE_ANY_EVENT: sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), x + 32, y + 32); debug("mousea send ESC[M %d %d %d", (b - 1), x + 32, y + 32); send_ansi_sequence(screen_list, buf); break; case MOUSE_X10: sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), 32 + x, 32 + y); debug("mousex send ESC[M %d %d %d", 32 + (b - 1), 32 + x, 32 + y); send_ansi_sequence(screen_list, buf); break; case MOUSE_NONE: break; } } else if (!strncmp("MOUSER ", buf, 6)) { debug("Got mouse release '%s'\n", buf); int x, y, b; x = 1 + atoi(buf + 7) - screen_list->screen[screen_list->pty]->x; y = 1 + atoi(buf + 18) - screen_list->screen[screen_list->pty]->y; b = atoi(buf + 28); switch (screen_list->screen[screen_list->pty]->report_mouse) { case MOUSE_VT200: case MOUSE_VT200_HIGHLIGHT: case MOUSE_BTN_EVENT: case MOUSE_ANY_EVENT: sprintf(buf, "\x1b[M%c%c%c", 32 + 3, x + 32, y + 32); send_ansi_sequence(screen_list, buf); break; case MOUSE_X10: sprintf(buf, "\x1b[M%c%c%c", 32 + 3, 32 + x, 32 + y); send_ansi_sequence(screen_list, buf); break; case MOUSE_NONE: break; } } else if (!strncmp("MOUSEM ", buf, 6)) { debug("Got mouse motion '%s'\n", buf); int x, y, b; x = 1 + atoi(buf + 7) - screen_list->screen[screen_list->pty]->x; y = 1 + atoi(buf + 18) - screen_list->screen[screen_list->pty]->y; b = atoi(buf + 28); switch (screen_list->screen[screen_list->pty]->report_mouse) { case MOUSE_X10: // X10 reports mouse clicks only if (b) { sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), x + 32, y + 32); send_ansi_sequence(screen_list, buf); } break; case MOUSE_VT200: case MOUSE_VT200_HIGHLIGHT: case MOUSE_BTN_EVENT: if (b) { sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), x + 32, y + 32); send_ansi_sequence(screen_list, buf); } case MOUSE_ANY_EVENT: sprintf(buf, "\x1b[M%c%c%c", 32 + (b - 1), x + 32, y + 32); send_ansi_sequence(screen_list, buf); break; case MOUSE_NONE: break; } } else { fprintf(stderr, "Unknown command received: %s\n", buf); } } /* No more screens, exit */ if (!screen_list->count) return -1; /* User requested to exit */ if (quit) return -2; /* Update each screen canvas */ refresh |= update_terms(screen_list); /* Launch recurrents if any */ refresh |= handle_recurrents(screen_list); /* Refresh screen */ refresh_screen(screen_list, refresh); eof = 1; for (i = 0; i < screen_list->count; i++) if (screen_list->screen[i]->fd >= 0) eof = 0; if (eof) return -3; return 0; } static void server_main(struct screen_list *screen_list) { screen_list->last_key_time = 0; screen_list->comm.attached = 0; screen_list->command = 0; screen_list->was_in_bell = 0; screen_list->last_refresh_time = 0; server_init(screen_list); #ifdef USE_PYTHON python_init(screen_list); #endif for (;;) { if (server_iteration(screen_list)) break; } detach(screen_list); free_screen_list(screen_list); #ifdef USE_PYTHON python_close(screen_list); #endif exit(0); } static void refresh_screen(struct screen_list *screen_list, int refresh) { if (!screen_list->comm.attached) { /* No need to refresh Don't use the CPU too much Would be better to select on terms + socket */ sleep(1); } else { long long unsigned int current_time = get_us(); long long int tdiff = (current_time - screen_list->last_refresh_time) / 1000; refresh |= screen_list->need_refresh; if (screen_list->force_refresh) { wm_refresh(screen_list); refresh = 1; } /* Draw lock window */ if (screen_list->lock.locked) { /* FIXME don't redraw it each iteration */ draw_lock(screen_list); refresh = 1; } #ifdef USE_LOCK else if ((current_time - screen_list->last_key_time >= screen_list->lock.autolock_timeout)) { screen_list->lock.locked = 1; refresh = 1; } #endif else if ((current_time - screen_list->last_key_time >= screen_list->screensaver.timeout)) { if (!screen_list->screensaver.in_screensaver) { screensaver_init(screen_list); screen_list->screensaver.in_screensaver = 1; set_cursor(0, screen_list); } draw_screensaver(screen_list); refresh = 1; } else if (refresh || screen_list->was_in_bell) { if (tdiff >= screen_list->delay) { refresh_screens(screen_list); set_title(screen_list); refresh = 1; } } if (refresh) { if (tdiff >= screen_list->delay) { request_refresh(screen_list); screen_list->last_refresh_time = current_time; screen_list->need_refresh = 0; } else { debug("Skipping refresh (%lld < %d)", tdiff, screen_list->delay); screen_list->need_refresh = 1; } } } } static void server_init(struct screen_list *screen_list) { int i; debug("Screen list at %p\n", screen_list); /* Create socket and bind it */ create_socket(screen_list, SOCK_SERVER); /* Connect to the client */ connect_socket(screen_list, SOCK_CLIENT); screen_list->width = screen_list->height = 80; /* Create main canvas */ screen_list->cv = caca_create_canvas(screen_list->width, screen_list->height + screen_list->modals.mini * 6 + screen_list->modals.status); if (!screen_list->sys.to_grab && !screen_list->sys.to_start) { add_screen(screen_list, create_screen(screen_list->width, screen_list->height, screen_list->sys.default_shell)); } /* Attach processes */ if (screen_list->sys.to_grab) { for (i = 0; screen_list->sys.to_grab[i]; i++) { add_screen(screen_list, create_screen_grab(screen_list->width, screen_list->height, screen_list->sys.to_grab[i])); } free(screen_list->sys.to_grab); screen_list->sys.to_grab = NULL; } /* Launch command line processes */ if (screen_list->sys.to_start) { for (i = 0; screen_list->sys.to_start[i]; i++) { add_screen(screen_list, create_screen(screen_list->width, screen_list->height, screen_list->sys.to_start[i])); free(screen_list->sys.to_start[i]); } free(screen_list->sys.to_start); screen_list->sys.to_start = NULL; } screen_list->last_key_time = get_us(); } static int handle_attach(struct screen_list *screen_list, char *buf) { /* If we were attached to someone else, detach first */ if (screen_list->comm.attached) detach(screen_list); screen_list->comm.attached = 1; caca_free_canvas(screen_list->cv); screen_list->cv = caca_create_canvas(atoi(buf + 7), atoi(buf + 18)); screen_list->delay = atoi(buf + 29); screen_list->changed = 1; return 1; } static int handle_key(struct screen_list *screen_list, unsigned int c, int refresh) { char *str = NULL; int size = 0; if (screen_list->modals.help) { return help_handle_key(screen_list, c); } #ifdef USE_PYTHON if (screen_list->modals.python_command) { return python_command_handle_key(screen_list, c); } #endif /* CTRL-A has been pressed before, handle this as a command, except that CTRL-A a sends literal CTRL-A */ if (screen_list->command && (c != 'a')) { screen_list->command = 0; refresh |= handle_command_input(screen_list, c); } else { /* Not in command mode */ screen_list->last_key_time = get_us(); set_cursor(1, screen_list); /* Kill screensaver */ if (screen_list->screensaver.in_screensaver) { screensaver_kill(screen_list); screen_list->screensaver.in_screensaver = 0; screen_list->changed = 1; refresh = 1; return refresh; } /* Handle lock window */ if (screen_list->lock.locked) { refresh |= update_lock(c, screen_list); screen_list->changed = 1; } else if (screen_list->modals.window_list) { refresh |= update_window_list(c, screen_list); screen_list->changed = 1; } else { switch (c) { case 0x01: // CACA_KEY_CTRL_A: screen_list->command = 1; break; default: /* CTRL-A a sends literal CTRL-A */ if (screen_list->command && (c == 'a')) { c = 0x01; } /* Normal key, convert it if needed */ str = convert_input_ansi(&c, &size); /* FIXME check value of r */ int r = write(screen_list->screen[screen_list->pty]->fd, str, size); (void)r; break; } } } return refresh; } int send_ansi_sequence(struct screen_list *screen_list, char *str) { debug("Sending ansi '%s'\n", str); return write(screen_list->screen[screen_list->pty]->fd, str, strlen(str)); } int install_fds(struct screen_list *screen_list) { int fd; close(0); close(1); close(2); fd = open("/dev/null", O_RDWR, 0); if (fd < 0) { perror("Failed to open /dev/null"); return -2; } dup2(fd, 0); #ifndef DEBUG dup2(fd, 1); dup2(fd, 2); if (fd > 2) close(fd); #else if (fd != 0) close(fd); screen_list->outfd = open("/tmp/neercs-debug.txt", O_TRUNC | O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); dup2(screen_list->outfd, 1); dup2(screen_list->outfd, 2); if (screen_list->outfd > 2) close(screen_list->outfd); #endif return 0; } int start_server(struct screen_list *screen_list) { pid_t pid; pid = fork(); if (pid < 0) { perror("Failed to create child process"); return -1; } if (pid == 0) { int r = install_fds(screen_list); if (r) return r; setsid(); server_main(screen_list); /* Never returns */ } return 0; } long long get_us(void) { struct timeval tv; gettimeofday(&tv, NULL); return (tv.tv_sec * (1000000) + tv.tv_usec); } #else /* FIXME: unimplemented */ long long get_us(void) { return 0; } int send_ansi_sequence(struct screen_list *screen_list, char *str) { return 0; } #endif \ No newline at end of file diff --git a/neercs/old/term.c b/neercs/old/term.c index 24df2f1..e975162 100644 --- a/neercs/old/term.c +++ b/neercs/old/term.c @@ -1,143 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined _WIN32 - -#define _XOPEN_SOURCE -#include -#include -#include -#include -#include -#include -#if defined HAVE_PTY_H -# include /* for openpty and forkpty */ -#elif defined HAVE_UTIL_H -# include /* for OS X, OpenBSD and NetBSD */ -#elif defined HAVE_LIBUTIL_H -# include /* for FreeBSD */ -#endif -#include -#include - -#include - -#include "neercs.h" - - -int create_pty(char *cmd, unsigned int w, unsigned int h, int *cpid) -{ - char **argv; - int fd; - pid_t pid; - - pid = forkpty(&fd, NULL, NULL, NULL); - if (pid < 0) - { - fprintf(stderr, "forkpty() error\n"); - return -1; - } - else if (pid == 0) - { - set_tty_size(0, w, h); - putenv("CACA_DRIVER=slang"); - putenv("TERM=xterm"); - argv = malloc(2 * sizeof(char *)); - if (!argv) - { - fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, - __LINE__); - return -1; - } - argv[0] = cmd; - argv[1] = NULL; - execvp(cmd, argv); - fprintf(stderr, "execvp() error\n"); - return -1; - } - - *cpid = pid; - - fcntl(fd, F_SETFL, O_NDELAY); - return fd; -} - -int create_pty_grab(long pid, unsigned int w, unsigned int h, int *newpid) -{ - int fdm, fds; - - int ret = openpty(&fdm, &fds, NULL, NULL, NULL); - - if (ret < 0) - { - fprintf(stderr, "open() error\n"); - return -1; - } - - set_tty_size(0, w, h); - grab_process(pid, ptsname(fdm), fds, newpid); - - fcntl(fdm, F_SETFL, O_NDELAY); - return fdm; -} - -int set_tty_size(int fd, unsigned int w, unsigned int h) -{ - struct winsize ws; - - memset(&ws, 0, sizeof(ws)); - ws.ws_row = h; - ws.ws_col = w; - ioctl(fd, TIOCSWINSZ, (char *)&ws); - - return 0; -} - - - -int update_terms(struct screen_list *screen_list) -{ - int i, refresh = 0; - for (i = 0; i < screen_list->count; i++) - { - if (screen_list->screen[i]->total && !screen_list->dont_update_coords) - { - unsigned long int bytes; - - bytes = import_term(screen_list, - screen_list->screen[i], - screen_list->screen[i]->buf, - screen_list->screen[i]->total); - - if (bytes > 0) - { - screen_list->screen[i]->total -= bytes; - memmove(screen_list->screen[i]->buf, - screen_list->screen[i]->buf + bytes, - screen_list->screen[i]->total); - if (screen_list->screen[i]->visible || screen_list->modals.mini) - refresh = 1; - } - } - } - return refresh; -} - -#else -/* FIXME: unimplemented */ -int set_tty_size(int fd, unsigned int w, unsigned int h) { return 0; } -#endif - +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if !defined _WIN32 #define _XOPEN_SOURCE #include #include #include #include #include #include #if defined HAVE_PTY_H # include /* for openpty and forkpty */ #elif defined HAVE_UTIL_H # include /* for OS X, OpenBSD and NetBSD */ #elif defined HAVE_LIBUTIL_H # include /* for FreeBSD */ #endif #include #include #include #include "neercs.h" int create_pty(char *cmd, unsigned int w, unsigned int h, int *cpid) { char **argv; int fd; pid_t pid; pid = forkpty(&fd, NULL, NULL, NULL); if (pid < 0) { fprintf(stderr, "forkpty() error\n"); return -1; } else if (pid == 0) { set_tty_size(0, w, h); putenv("CACA_DRIVER=slang"); putenv("TERM=xterm"); argv = malloc(2 * sizeof(char *)); if (!argv) { fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__); return -1; } argv[0] = cmd; argv[1] = NULL; execvp(cmd, argv); fprintf(stderr, "execvp() error\n"); return -1; } *cpid = pid; fcntl(fd, F_SETFL, O_NDELAY); return fd; } int create_pty_grab(long pid, unsigned int w, unsigned int h, int *newpid) { int fdm, fds; int ret = openpty(&fdm, &fds, NULL, NULL, NULL); if (ret < 0) { fprintf(stderr, "open() error\n"); return -1; } set_tty_size(0, w, h); grab_process(pid, ptsname(fdm), fds, newpid); fcntl(fdm, F_SETFL, O_NDELAY); return fdm; } int set_tty_size(int fd, unsigned int w, unsigned int h) { struct winsize ws; memset(&ws, 0, sizeof(ws)); ws.ws_row = h; ws.ws_col = w; ioctl(fd, TIOCSWINSZ, (char *)&ws); return 0; } int update_terms(struct screen_list *screen_list) { int i, refresh = 0; for (i = 0; i < screen_list->count; i++) { if (screen_list->screen[i]->total && !screen_list->dont_update_coords) { unsigned long int bytes; bytes = import_term(screen_list, screen_list->screen[i], screen_list->screen[i]->buf, screen_list->screen[i]->total); if (bytes > 0) { screen_list->screen[i]->total -= bytes; memmove(screen_list->screen[i]->buf, screen_list->screen[i]->buf + bytes, screen_list->screen[i]->total); if (screen_list->screen[i]->visible || screen_list->modals.mini) refresh = 1; } } } return refresh; } #else /* FIXME: unimplemented */ int set_tty_size(int fd, unsigned int w, unsigned int h) { return 0; } #endif \ No newline at end of file diff --git a/neercs/old/widgets.c b/neercs/old/widgets.c index 2e6dfb4..4ec27a2 100644 --- a/neercs/old/widgets.c +++ b/neercs/old/widgets.c @@ -1,176 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2009-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - - -#include "widgets.h" - -static void widget_ibox_add_char(struct input_box *box, unsigned int c); -static void widget_ibox_del_char(struct input_box *box); - -struct input_box *widget_ibox_init(caca_canvas_t *cv, int w, int h) -{ - struct input_box *box = (struct input_box *)malloc(sizeof(struct input_box)); - if (!box) - return NULL; - box->cv = cv; - box->w = w; - box->h = h; - box->command = NULL; - box->output_err = NULL; - box->output_res = NULL; - - return box; -} - - -int widget_ibox_draw(struct input_box *box) -{ - int x = (caca_get_canvas_width(box->cv) - box->w) / 2; - int y = (caca_get_canvas_height(box->cv) - box->h) / 2; - - caca_set_color_ansi(box->cv, CACA_BLUE, CACA_BLUE); - caca_fill_box(box->cv, x, y, box->w, box->h, '#'); - caca_set_color_ansi(box->cv, CACA_DEFAULT, CACA_BLUE); - caca_draw_cp437_box(box->cv, x, y, box->w, box->h); - caca_printf(box->cv, x, y, "Mini-command"); - - caca_printf(box->cv, x + 2, y + 2, - "[___________________________________________________________]"); - - if (box->command) - { - caca_printf(box->cv, x + 3, y + 2, "%s", box->command); - caca_gotoxy(box->cv, x + 3 + box->x, y + 2); - } - else - { - caca_gotoxy(box->cv, x + 3, y + 2); - } - - if (box->output_err) - { - caca_set_color_ansi(box->cv, CACA_RED, CACA_BLUE); - caca_printf(box->cv, x + 2, y + 4, box->output_err); - } - if (box->output_res) - { - caca_set_color_ansi(box->cv, CACA_LIGHTGREEN, CACA_BLUE); - caca_printf(box->cv, x + 2, y + 4, box->output_res); - } - - return 0; -} - -char *widget_ibox_get_text(struct input_box *box) -{ - return box->command; -} - -void widget_ibox_destroy(struct input_box *box) -{ - if(!box) return; - if (box->command) - free(box->command); - if (box->output_err) - free(box->output_err); - if (box->output_res) - free(box->output_res); -} - -void widget_ibox_set_error(struct input_box *box, char *err) -{ - box->output_err = err; -} - -void widget_ibox_set_msg(struct input_box *box, char *msg) -{ - box->output_res = msg; -} - -int widget_ibox_handle_key(struct input_box *box, unsigned int c) -{ - if (c == CACA_KEY_ESCAPE) - { - if (box->command) - { - free(box->command); - box->command = NULL; - } - return INPUT_BOX_ESC; - } - else if (c == CACA_KEY_LEFT) - { - if (box->x) - box->x--; - } - else if (c == CACA_KEY_RIGHT) - { - if (box->x < box->size - 1) - box->x++; - } - else if (c == CACA_KEY_RETURN) - { - return INPUT_BOX_RET; - } - else - { - if (c >= ' ' && c < 127) - widget_ibox_add_char(box, c); - else if (c == 8) - { - widget_ibox_del_char(box); - } - } - return INPUT_BOX_NOTHING; -} - - - -static void widget_ibox_add_char(struct input_box *box, unsigned int c) -{ - /* FIXME handle return values */ - if (!box->command) - { - box->size = 1; - box->x = 0; - box->command = (char *)malloc(2); - box->command[0] = 0; - } - else - { - box->command = (char *)realloc(box->command, box->size + 1); - } - memmove(&box->command[box->x + 1], - &box->command[box->x], (box->size - box->x)); - - box->command[box->x] = c; - box->x++; - box->size++; -} - -static void widget_ibox_del_char(struct input_box *box) -{ - if (box->x < 1) - return; - if (box->size > 1) - box->size--; - else - return; - - memcpy(&box->command[box->x - 1], &box->command[box->x], box->size - box->x); - - box->command = (char *)realloc(box->command, box->size); - - if (box->x) - box->x--; - box->command[box->size - 1] = 0; -} +/* * neercs console-based window manager * Copyright (c) 2009-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #include "widgets.h" static void widget_ibox_add_char(struct input_box *box, unsigned int c); static void widget_ibox_del_char(struct input_box *box); struct input_box *widget_ibox_init(caca_canvas_t *cv, int w, int h) { struct input_box *box = (struct input_box *)malloc(sizeof(struct input_box)); if (!box) return NULL; box->cv = cv; box->w = w; box->h = h; box->command = NULL; box->output_err = NULL; box->output_res = NULL; return box; } int widget_ibox_draw(struct input_box *box) { int x = (caca_get_canvas_width(box->cv) - box->w) / 2; int y = (caca_get_canvas_height(box->cv) - box->h) / 2; caca_set_color_ansi(box->cv, CACA_BLUE, CACA_BLUE); caca_fill_box(box->cv, x, y, box->w, box->h, '#'); caca_set_color_ansi(box->cv, CACA_DEFAULT, CACA_BLUE); caca_draw_cp437_box(box->cv, x, y, box->w, box->h); caca_printf(box->cv, x, y, "Mini-command"); caca_printf(box->cv, x + 2, y + 2, "[___________________________________________________________]"); if (box->command) { caca_printf(box->cv, x + 3, y + 2, "%s", box->command); caca_gotoxy(box->cv, x + 3 + box->x, y + 2); } else { caca_gotoxy(box->cv, x + 3, y + 2); } if (box->output_err) { caca_set_color_ansi(box->cv, CACA_RED, CACA_BLUE); caca_printf(box->cv, x + 2, y + 4, box->output_err); } if (box->output_res) { caca_set_color_ansi(box->cv, CACA_LIGHTGREEN, CACA_BLUE); caca_printf(box->cv, x + 2, y + 4, box->output_res); } return 0; } char *widget_ibox_get_text(struct input_box *box) { return box->command; } void widget_ibox_destroy(struct input_box *box) { if(!box) return; if (box->command) free(box->command); if (box->output_err) free(box->output_err); if (box->output_res) free(box->output_res); } void widget_ibox_set_error(struct input_box *box, char *err) { box->output_err = err; } void widget_ibox_set_msg(struct input_box *box, char *msg) { box->output_res = msg; } int widget_ibox_handle_key(struct input_box *box, unsigned int c) { if (c == CACA_KEY_ESCAPE) { if (box->command) { free(box->command); box->command = NULL; } return INPUT_BOX_ESC; } else if (c == CACA_KEY_LEFT) { if (box->x) box->x--; } else if (c == CACA_KEY_RIGHT) { if (box->x < box->size - 1) box->x++; } else if (c == CACA_KEY_RETURN) { return INPUT_BOX_RET; } else { if (c >= ' ' && c < 127) widget_ibox_add_char(box, c); else if (c == 8) { widget_ibox_del_char(box); } } return INPUT_BOX_NOTHING; } static void widget_ibox_add_char(struct input_box *box, unsigned int c) { /* FIXME handle return values */ if (!box->command) { box->size = 1; box->x = 0; box->command = (char *)malloc(2); box->command[0] = 0; } else { box->command = (char *)realloc(box->command, box->size + 1); } memmove(&box->command[box->x + 1], &box->command[box->x], (box->size - box->x)); box->command[box->x] = c; box->x++; box->size++; } static void widget_ibox_del_char(struct input_box *box) { if (box->x < 1) return; if (box->size > 1) box->size--; else return; memcpy(&box->command[box->x - 1], &box->command[box->x], box->size - box->x); box->command = (char *)realloc(box->command, box->size); if (box->x) box->x--; box->command[box->size - 1] = 0; } \ No newline at end of file diff --git a/neercs/old/widgets.h b/neercs/old/widgets.h index a28462a..95b0d4c 100644 --- a/neercs/old/widgets.h +++ b/neercs/old/widgets.h @@ -1,45 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2009-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#include -#include -#include -#include - -#include - - -enum input_box_code -{ - INPUT_BOX_ESC, - INPUT_BOX_RET, - INPUT_BOX_NOTHING, -}; - -struct input_box -{ - caca_canvas_t *cv; - int x, y; - int w, h; - int size; - char *command; - char *output_err; - char *output_res; -}; - -struct input_box *widget_ibox_init(caca_canvas_t * cv, int w, int h); -int widget_ibox_draw(struct input_box *box); -int widget_ibox_handle_key(struct input_box *box, unsigned int c); -char* widget_ibox_get_text(struct input_box *box); -void widget_ibox_destroy(struct input_box *box); -void widget_ibox_set_error(struct input_box *box, char *err); -void widget_ibox_set_msg(struct input_box *box, char *msg); +/* * neercs console-based window manager * Copyright (c) 2009-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #include #include #include #include #include enum input_box_code { INPUT_BOX_ESC, INPUT_BOX_RET, INPUT_BOX_NOTHING, }; struct input_box { caca_canvas_t *cv; int x, y; int w, h; int size; char *command; char *output_err; char *output_res; }; struct input_box *widget_ibox_init(caca_canvas_t * cv, int w, int h); int widget_ibox_draw(struct input_box *box); int widget_ibox_handle_key(struct input_box *box, unsigned int c); char* widget_ibox_get_text(struct input_box *box); void widget_ibox_destroy(struct input_box *box); void widget_ibox_set_error(struct input_box *box, char *err); void widget_ibox_set_msg(struct input_box *box, char *msg); \ No newline at end of file diff --git a/neercs/old/wm.cpp b/neercs/old/wm.cpp index 03a1f2f..4556a1c 100644 --- a/neercs/old/wm.cpp +++ b/neercs/old/wm.cpp @@ -1,521 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include - -#include "core.h" - -using namespace lol; - -extern "C" { -#include "neercs.h" -} - -void resize_screen(struct screen *s, int w, int h) -{ - caca_canvas_t *oldc, *newc; - - if (w == s->w && h == s->h) - return; - if (w <= 0 || h <= 0) - return; - - s->changed = 1; - - s->w = w; - s->h = h; - - /* - * caca_set_canvas_boundaries() is bugged as hell, so let's resize it by - * hands - */ - oldc = s->cv; - newc = caca_create_canvas(w, h); - caca_blit(newc, 0, 0, oldc, NULL); - s->cv = newc; - caca_gotoxy(newc, caca_get_cursor_x(oldc), caca_get_cursor_y(oldc)); - caca_free_canvas(oldc); - /* FIXME: disabled */ - //set_tty_size(s->fd, w, h); - - s->orig_w = s->w; - s->orig_h = s->h; - s->orig_x = s->x; - s->orig_y = s->y; -} - -void update_windows_props(struct screen_list *screen_list) -{ - debug("%s, %d screens, type %d\n", __FUNCTION__, screen_list->count, - screen_list->wm_type); - - if (!screen_list->count) - return; - - switch (screen_list->wm_type) - { - case WM_CARD: - update_windows_props_cards(screen_list); - break; - case WM_HSPLIT: - update_windows_props_hsplit(screen_list); - break; - case WM_VSPLIT: - update_windows_props_vsplit(screen_list); - break; - case WM_FULL: - default: - update_windows_props_full(screen_list); - break; - } -} - -void update_windows_props_hsplit(struct screen_list *screen_list) -{ - int i; - int w = - (screen_list->width / screen_list->count) - - (screen_list->border_size * 2); - int h = screen_list->height - (screen_list->border_size * 2); - - for (i = 0; i < screen_list->count; i++) - { - screen_list->screen[i]->x = (i * w) + screen_list->border_size; - screen_list->screen[i]->y = screen_list->border_size; - screen_list->screen[i]->visible = 1; - if (i != screen_list->count - 1) - { - resize_screen(screen_list->screen[i], w - 1, h); - } - else - { - resize_screen(screen_list->screen[i], - screen_list->width - i * w - 2, h); - } - } -} - -void update_windows_props_vsplit(struct screen_list *screen_list) -{ - int i; - int w = screen_list->width - (screen_list->border_size * 2); - int h = (screen_list->height) / screen_list->count; - - for (i = 0; i < screen_list->count; i++) - { - screen_list->screen[i]->x = screen_list->border_size; - screen_list->screen[i]->y = (i * h) + (screen_list->border_size); - screen_list->screen[i]->visible = 1; - if (i != screen_list->count - 1) - { - resize_screen(screen_list->screen[i], w, - h - (screen_list->border_size * 2)); - } - else - { - resize_screen(screen_list->screen[i], - w, - screen_list->height - i * h - - (screen_list->border_size * 2)); - } - } -} - - -void update_windows_props_full(struct screen_list *screen_list) -{ - int i; - int w = screen_list->width - (screen_list->border_size * 2); - int h = screen_list->height - (screen_list->border_size * 2); - - for (i = 0; i < screen_list->count; i++) - { - screen_list->screen[i]->visible = 0; - screen_list->screen[i]->x = screen_list->border_size; - screen_list->screen[i]->y = screen_list->border_size; - - resize_screen(screen_list->screen[i], w, h); - } - screen_list->screen[screen_list->pty]->visible = 1; -} - - -void update_windows_props_cards(struct screen_list *screen_list) -{ - int i; - int w = (screen_list->width - screen_list->count * 3) + 1; - int h = (screen_list->height - screen_list->count) - 1; - int x = 1; - int y = screen_list->count; - - for (i = 0; i < screen_list->count; i++) - { - screen_list->screen[i]->visible = 1; - screen_list->screen[i]->x = x; - screen_list->screen[i]->y = y; - - resize_screen(screen_list->screen[i], w, h); - x += 3; - y--; - } -} - -/* Window managers refresh */ - -void wm_refresh(struct screen_list *screen_list) -{ - /* FIXME : move set_color to a relevant place */ - caca_set_color_ansi(screen_list->cv, CACA_LIGHTRED, CACA_BLACK); - - switch (screen_list->wm_type) - { - case WM_CARD: - wm_refresh_card(screen_list); - break; - case WM_HSPLIT: - wm_refresh_hsplit(screen_list); - break; - case WM_VSPLIT: - wm_refresh_hsplit(screen_list); - break; - case WM_FULL: - default: - wm_refresh_cube(screen_list); - break; - } -} - -static void wm_bell(struct screen_list *screen_list) -{ - if (screen_list->screen[screen_list->pty]->bell) - { - caca_set_color_ansi(screen_list->cv, CACA_RED, CACA_BLACK); - screen_list->in_bell--; - screen_list->force_refresh = 1; - if (!screen_list->in_bell) - { - screen_list->was_in_bell = 1; - screen_list->screen[screen_list->pty]->bell = 0; - } - } - else - { - if (screen_list->was_in_bell) - { - screen_list->screen[screen_list->pty]->bell = 0; - screen_list->force_refresh = 1; - screen_list->was_in_bell = 0; - screen_list->changed = 1; - } - caca_set_color_ansi(screen_list->cv, CACA_LIGHTGREEN, CACA_BLACK); - } -} - -static void wm_box(struct screen_list *screen_list, int pty) -{ - if (!screen_list->screen[pty]->changed && !screen_list->changed) - return; - - if (!screen_list->border_size) - return; - - /* Color determined by wm_bell() */ - caca_draw_cp437_box(screen_list->cv, - screen_list->screen[pty]->x - 1, - screen_list->screen[pty]->y - 1, - screen_list->screen[pty]->w + 2, - screen_list->screen[pty]->h + 2); - - if (screen_list->screen[pty]->title) - { - caca_printf(screen_list->cv, - screen_list->screen[pty]->x, - screen_list->screen[pty]->y - 1, - " %.*s ", - screen_list->screen[pty]->w - 3, - screen_list->screen[pty]->title); - } -} - -static void wm_blit_current_screen(struct screen_list *screen_list) -{ - if (screen_list->screen[screen_list->pty]->changed || screen_list->changed) - caca_blit(screen_list->cv, - screen_list->screen[screen_list->pty]->x, - screen_list->screen[screen_list->pty]->y, - screen_list->screen[screen_list->pty]->cv, NULL); -} - -void wm_refresh_card(struct screen_list *screen_list) -{ - int i; - - for (i = screen_list->count - 1; i >= 0; i--) - { - if (i != screen_list->pty && screen_list->screen[i]->visible && - (screen_list->screen[i]->changed || screen_list->changed)) - { - caca_blit(screen_list->cv, - screen_list->screen[i]->x, - screen_list->screen[i]->y, - screen_list->screen[i]->cv, NULL); - - wm_box(screen_list, i); - } - } - - /* Force 'changed' to force redraw */ - screen_list->screen[screen_list->pty]->changed = 1; - wm_blit_current_screen(screen_list); - wm_bell(screen_list); - wm_box(screen_list, screen_list->pty); -} - -void wm_refresh_full(struct screen_list *screen_list) -{ - wm_blit_current_screen(screen_list); - wm_bell(screen_list); - wm_box(screen_list, screen_list->pty); -} - -void wm_refresh_vsplit(struct screen_list *screen_list) -{ - int i; - - for (i = screen_list->count - 1; i >= 0; i--) - { - if (i != screen_list->pty && screen_list->screen[i]->visible && - (screen_list->screen[i]->changed || screen_list->changed)) - { - caca_blit(screen_list->cv, - screen_list->screen[i]->x, - screen_list->screen[i]->y, - screen_list->screen[i]->cv, NULL); - - wm_box(screen_list, i); - } - } - - wm_blit_current_screen(screen_list); - wm_bell(screen_list); - wm_box(screen_list, screen_list->pty); -} - -void wm_refresh_hsplit(struct screen_list *screen_list) -{ - int i; - - for (i = screen_list->count - 1; i >= 0; i--) - { - if (i != screen_list->pty && screen_list->screen[i]->visible && - (screen_list->screen[i]->changed || screen_list->changed)) - { - caca_blit(screen_list->cv, - screen_list->screen[i]->x, - screen_list->screen[i]->y, - screen_list->screen[i]->cv, NULL); - - wm_box(screen_list, i); - } - } - - wm_blit_current_screen(screen_list); - wm_bell(screen_list); - wm_box(screen_list, screen_list->pty); -} - - -static float -get_direction(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) -{ - float d1x, d1y, d2x, d2y; - - d1x = p3x - p1x; - d1y = p3y - p1y; - d2x = p3x - p2x; - d2y = p3y - p2y; - return (d1x * d2y) - (d1y * d2x); -} - - -/* 3D Cube. Yeah I know, it's a mess. Just look anywhere else. */ -static void draw_face(caca_canvas_t * cv, - int p1x, int p1y, - int p2x, int p2y, - int p3x, int p3y, - int p4x, int p4y, caca_canvas_t * tex, - int color, int borders) -{ - if (get_direction(p1x, p1y, p2x, p2y, p3x, p3y) >= 0) - { - int coords[6]; - float uv[6]; - coords[0] = p1x; - coords[1] = p1y; - coords[2] = p2x; - coords[3] = p2y; - coords[4] = p3x; - coords[5] = p3y; - uv[0] = 1; - uv[1] = 1; - uv[2] = 0; - uv[3] = 1; - uv[4] = 0; - uv[5] = 0; - caca_fill_triangle_textured(cv, coords, tex, uv); - coords[0] = p1x; - coords[1] = p1y; - coords[2] = p3x; - coords[3] = p3y; - coords[4] = p4x; - coords[5] = p4y; - uv[0] = 1; - uv[1] = 1; - uv[2] = 0; - uv[3] = 0; - uv[4] = 1; - uv[5] = 0; - caca_fill_triangle_textured(cv, coords, tex, uv); - caca_set_color_ansi(cv, color, CACA_BLACK); - if (borders) - { - caca_draw_thin_line(cv, p1x, p1y, p2x, p2y); - caca_draw_thin_line(cv, p2x, p2y, p3x, p3y); - caca_draw_thin_line(cv, p3x, p3y, p4x, p4y); - caca_draw_thin_line(cv, p4x, p4y, p1x, p1y); - } - } -} - - -void wm_refresh_cube(struct screen_list *screen_list) -{ - int i; - - if (!screen_list->cube.in_switch || !screen_list->eyecandy) - { - wm_refresh_full(screen_list); - // screen_list->force_refresh = 0; - } - else - { - long long unsigned int cur_time = get_us() - screen_list->last_switch; - - if (cur_time >= screen_list->cube.duration || screen_list->count == 1) - { - screen_list->changed = 1; - screen_list->force_refresh = 1; - screen_list->cube.in_switch = 0; - } - else - { - float cube[12][3] = { - {-1, -1, 1}, - {1, -1, 1}, - {1, 1, 1}, - {-1, 1, 1}, - - {1, -1, 1}, - {1, -1, -1}, - {1, 1, -1}, - {1, 1, 1}, - - {-1, -1, -1}, - {-1, -1, 1}, - {-1, 1, 1}, - {-1, 1, -1}, - }; - - float cube_transformed[12][3]; - float cube_projected[12][2]; - float fov = 0.5f; - float angle = - 90.0f * ((float)cur_time / (float)screen_list->cube.duration); - - angle *= (F_PI / 180.0f); - - if (screen_list->cube.side == 1) - angle = -angle; - - float sina = lol::sin(angle); - float cosa = lol::cos(angle); - - for (i = 0; i < 12; i++) - { - cube_transformed[i][2] = cube[i][2] * cosa - cube[i][0] * sina; - cube_transformed[i][0] = cube[i][2] * sina + cube[i][0] * cosa; - cube_transformed[i][1] = cube[i][1]; - - cube_transformed[i][2] -= 3; - - cube_projected[i][0] = - cube_transformed[i][0] / (cube_transformed[i][2] * fov); - cube_projected[i][1] = - cube_transformed[i][1] / (cube_transformed[i][2] * fov); - - cube_projected[i][0] /= 2.0f; - cube_projected[i][1] /= 2.0f; - cube_projected[i][0] += 0.5f; - cube_projected[i][1] += 0.5f; - - cube_projected[i][0] *= screen_list->width; - cube_projected[i][1] *= screen_list->height; - } - - caca_set_color_ansi(screen_list->cv, CACA_WHITE, CACA_BLACK); - caca_clear_canvas(screen_list->cv); - - caca_canvas_t *first = - screen_list->screen[screen_list->prevpty]->cv; - caca_canvas_t *second = screen_list->screen[screen_list->pty]->cv; - - draw_face(screen_list->cv, - cube_projected[0][0], cube_projected[0][1], - cube_projected[1][0], cube_projected[1][1], - cube_projected[2][0], cube_projected[2][1], - cube_projected[3][0], cube_projected[3][1], - first, CACA_LIGHTGREEN, screen_list->border_size); - - - if (screen_list->cube.side) - { - draw_face(screen_list->cv, - cube_projected[4][0], cube_projected[4][1], - cube_projected[5][0], cube_projected[5][1], - cube_projected[6][0], cube_projected[6][1], - cube_projected[7][0], cube_projected[7][1], - second, CACA_LIGHTGREEN, screen_list->border_size); - } - else - { - draw_face(screen_list->cv, - cube_projected[8][0], cube_projected[8][1], - cube_projected[9][0], cube_projected[9][1], - cube_projected[10][0], cube_projected[10][1], - cube_projected[11][0], cube_projected[11][1], - second, CACA_LIGHTGREEN, screen_list->border_size); - } - - screen_list->changed = 1; - screen_list->force_refresh = 1; - screen_list->cube.in_switch = 1; - } - } -} +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include "core.h" using namespace lol; extern "C" { #include "neercs.h" } void resize_screen(struct screen *s, int w, int h) { caca_canvas_t *oldc, *newc; if (w == s->w && h == s->h) return; if (w <= 0 || h <= 0) return; s->changed = 1; s->w = w; s->h = h; /* * caca_set_canvas_boundaries() is bugged as hell, so let's resize it by * hands */ oldc = s->cv; newc = caca_create_canvas(w, h); caca_blit(newc, 0, 0, oldc, NULL); s->cv = newc; caca_gotoxy(newc, caca_get_cursor_x(oldc), caca_get_cursor_y(oldc)); caca_free_canvas(oldc); /* FIXME: disabled */ //set_tty_size(s->fd, w, h); s->orig_w = s->w; s->orig_h = s->h; s->orig_x = s->x; s->orig_y = s->y; } void update_windows_props(struct screen_list *screen_list) { debug("%s, %d screens, type %d\n", __FUNCTION__, screen_list->count, screen_list->wm_type); if (!screen_list->count) return; switch (screen_list->wm_type) { case WM_CARD: update_windows_props_cards(screen_list); break; case WM_HSPLIT: update_windows_props_hsplit(screen_list); break; case WM_VSPLIT: update_windows_props_vsplit(screen_list); break; case WM_FULL: default: update_windows_props_full(screen_list); break; } } void update_windows_props_hsplit(struct screen_list *screen_list) { int i; int w = (screen_list->width / screen_list->count) - (screen_list->border_size * 2); int h = screen_list->height - (screen_list->border_size * 2); for (i = 0; i < screen_list->count; i++) { screen_list->screen[i]->x = (i * w) + screen_list->border_size; screen_list->screen[i]->y = screen_list->border_size; screen_list->screen[i]->visible = 1; if (i != screen_list->count - 1) { resize_screen(screen_list->screen[i], w - 1, h); } else { resize_screen(screen_list->screen[i], screen_list->width - i * w - 2, h); } } } void update_windows_props_vsplit(struct screen_list *screen_list) { int i; int w = screen_list->width - (screen_list->border_size * 2); int h = (screen_list->height) / screen_list->count; for (i = 0; i < screen_list->count; i++) { screen_list->screen[i]->x = screen_list->border_size; screen_list->screen[i]->y = (i * h) + (screen_list->border_size); screen_list->screen[i]->visible = 1; if (i != screen_list->count - 1) { resize_screen(screen_list->screen[i], w, h - (screen_list->border_size * 2)); } else { resize_screen(screen_list->screen[i], w, screen_list->height - i * h - (screen_list->border_size * 2)); } } } void update_windows_props_full(struct screen_list *screen_list) { int i; int w = screen_list->width - (screen_list->border_size * 2); int h = screen_list->height - (screen_list->border_size * 2); for (i = 0; i < screen_list->count; i++) { screen_list->screen[i]->visible = 0; screen_list->screen[i]->x = screen_list->border_size; screen_list->screen[i]->y = screen_list->border_size; resize_screen(screen_list->screen[i], w, h); } screen_list->screen[screen_list->pty]->visible = 1; } void update_windows_props_cards(struct screen_list *screen_list) { int i; int w = (screen_list->width - screen_list->count * 3) + 1; int h = (screen_list->height - screen_list->count) - 1; int x = 1; int y = screen_list->count; for (i = 0; i < screen_list->count; i++) { screen_list->screen[i]->visible = 1; screen_list->screen[i]->x = x; screen_list->screen[i]->y = y; resize_screen(screen_list->screen[i], w, h); x += 3; y--; } } /* Window managers refresh */ void wm_refresh(struct screen_list *screen_list) { /* FIXME : move set_color to a relevant place */ caca_set_color_ansi(screen_list->cv, CACA_LIGHTRED, CACA_BLACK); switch (screen_list->wm_type) { case WM_CARD: wm_refresh_card(screen_list); break; case WM_HSPLIT: wm_refresh_hsplit(screen_list); break; case WM_VSPLIT: wm_refresh_hsplit(screen_list); break; case WM_FULL: default: wm_refresh_cube(screen_list); break; } } static void wm_bell(struct screen_list *screen_list) { if (screen_list->screen[screen_list->pty]->bell) { caca_set_color_ansi(screen_list->cv, CACA_RED, CACA_BLACK); screen_list->in_bell--; screen_list->force_refresh = 1; if (!screen_list->in_bell) { screen_list->was_in_bell = 1; screen_list->screen[screen_list->pty]->bell = 0; } } else { if (screen_list->was_in_bell) { screen_list->screen[screen_list->pty]->bell = 0; screen_list->force_refresh = 1; screen_list->was_in_bell = 0; screen_list->changed = 1; } caca_set_color_ansi(screen_list->cv, CACA_LIGHTGREEN, CACA_BLACK); } } static void wm_box(struct screen_list *screen_list, int pty) { if (!screen_list->screen[pty]->changed && !screen_list->changed) return; if (!screen_list->border_size) return; /* Color determined by wm_bell() */ caca_draw_cp437_box(screen_list->cv, screen_list->screen[pty]->x - 1, screen_list->screen[pty]->y - 1, screen_list->screen[pty]->w + 2, screen_list->screen[pty]->h + 2); if (screen_list->screen[pty]->title) { caca_printf(screen_list->cv, screen_list->screen[pty]->x, screen_list->screen[pty]->y - 1, " %.*s ", screen_list->screen[pty]->w - 3, screen_list->screen[pty]->title); } } static void wm_blit_current_screen(struct screen_list *screen_list) { if (screen_list->screen[screen_list->pty]->changed || screen_list->changed) caca_blit(screen_list->cv, screen_list->screen[screen_list->pty]->x, screen_list->screen[screen_list->pty]->y, screen_list->screen[screen_list->pty]->cv, NULL); } void wm_refresh_card(struct screen_list *screen_list) { int i; for (i = screen_list->count - 1; i >= 0; i--) { if (i != screen_list->pty && screen_list->screen[i]->visible && (screen_list->screen[i]->changed || screen_list->changed)) { caca_blit(screen_list->cv, screen_list->screen[i]->x, screen_list->screen[i]->y, screen_list->screen[i]->cv, NULL); wm_box(screen_list, i); } } /* Force 'changed' to force redraw */ screen_list->screen[screen_list->pty]->changed = 1; wm_blit_current_screen(screen_list); wm_bell(screen_list); wm_box(screen_list, screen_list->pty); } void wm_refresh_full(struct screen_list *screen_list) { wm_blit_current_screen(screen_list); wm_bell(screen_list); wm_box(screen_list, screen_list->pty); } void wm_refresh_vsplit(struct screen_list *screen_list) { int i; for (i = screen_list->count - 1; i >= 0; i--) { if (i != screen_list->pty && screen_list->screen[i]->visible && (screen_list->screen[i]->changed || screen_list->changed)) { caca_blit(screen_list->cv, screen_list->screen[i]->x, screen_list->screen[i]->y, screen_list->screen[i]->cv, NULL); wm_box(screen_list, i); } } wm_blit_current_screen(screen_list); wm_bell(screen_list); wm_box(screen_list, screen_list->pty); } void wm_refresh_hsplit(struct screen_list *screen_list) { int i; for (i = screen_list->count - 1; i >= 0; i--) { if (i != screen_list->pty && screen_list->screen[i]->visible && (screen_list->screen[i]->changed || screen_list->changed)) { caca_blit(screen_list->cv, screen_list->screen[i]->x, screen_list->screen[i]->y, screen_list->screen[i]->cv, NULL); wm_box(screen_list, i); } } wm_blit_current_screen(screen_list); wm_bell(screen_list); wm_box(screen_list, screen_list->pty); } static float get_direction(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { float d1x, d1y, d2x, d2y; d1x = p3x - p1x; d1y = p3y - p1y; d2x = p3x - p2x; d2y = p3y - p2y; return (d1x * d2y) - (d1y * d2x); } /* 3D Cube. Yeah I know, it's a mess. Just look anywhere else. */ static void draw_face(caca_canvas_t * cv, int p1x, int p1y, int p2x, int p2y, int p3x, int p3y, int p4x, int p4y, caca_canvas_t * tex, int color, int borders) { if (get_direction(p1x, p1y, p2x, p2y, p3x, p3y) >= 0) { int coords[6]; float uv[6]; coords[0] = p1x; coords[1] = p1y; coords[2] = p2x; coords[3] = p2y; coords[4] = p3x; coords[5] = p3y; uv[0] = 1; uv[1] = 1; uv[2] = 0; uv[3] = 1; uv[4] = 0; uv[5] = 0; caca_fill_triangle_textured(cv, coords, tex, uv); coords[0] = p1x; coords[1] = p1y; coords[2] = p3x; coords[3] = p3y; coords[4] = p4x; coords[5] = p4y; uv[0] = 1; uv[1] = 1; uv[2] = 0; uv[3] = 0; uv[4] = 1; uv[5] = 0; caca_fill_triangle_textured(cv, coords, tex, uv); caca_set_color_ansi(cv, color, CACA_BLACK); if (borders) { caca_draw_thin_line(cv, p1x, p1y, p2x, p2y); caca_draw_thin_line(cv, p2x, p2y, p3x, p3y); caca_draw_thin_line(cv, p3x, p3y, p4x, p4y); caca_draw_thin_line(cv, p4x, p4y, p1x, p1y); } } } void wm_refresh_cube(struct screen_list *screen_list) { int i; if (!screen_list->cube.in_switch || !screen_list->eyecandy) { wm_refresh_full(screen_list); // screen_list->force_refresh = 0; } else { long long unsigned int cur_time = get_us() - screen_list->last_switch; if (cur_time >= screen_list->cube.duration || screen_list->count == 1) { screen_list->changed = 1; screen_list->force_refresh = 1; screen_list->cube.in_switch = 0; } else { float cube[12][3] = { {-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1}, {1, -1, 1}, {1, -1, -1}, {1, 1, -1}, {1, 1, 1}, {-1, -1, -1}, {-1, -1, 1}, {-1, 1, 1}, {-1, 1, -1}, }; float cube_transformed[12][3]; float cube_projected[12][2]; float fov = 0.5f; float angle = 90.0f * ((float)cur_time / (float)screen_list->cube.duration); angle *= (F_PI / 180.0f); if (screen_list->cube.side == 1) angle = -angle; float sina = lol::sin(angle); float cosa = lol::cos(angle); for (i = 0; i < 12; i++) { cube_transformed[i][2] = cube[i][2] * cosa - cube[i][0] * sina; cube_transformed[i][0] = cube[i][2] * sina + cube[i][0] * cosa; cube_transformed[i][1] = cube[i][1]; cube_transformed[i][2] -= 3; cube_projected[i][0] = cube_transformed[i][0] / (cube_transformed[i][2] * fov); cube_projected[i][1] = cube_transformed[i][1] / (cube_transformed[i][2] * fov); cube_projected[i][0] /= 2.0f; cube_projected[i][1] /= 2.0f; cube_projected[i][0] += 0.5f; cube_projected[i][1] += 0.5f; cube_projected[i][0] *= screen_list->width; cube_projected[i][1] *= screen_list->height; } caca_set_color_ansi(screen_list->cv, CACA_WHITE, CACA_BLACK); caca_clear_canvas(screen_list->cv); caca_canvas_t *first = screen_list->screen[screen_list->prevpty]->cv; caca_canvas_t *second = screen_list->screen[screen_list->pty]->cv; draw_face(screen_list->cv, cube_projected[0][0], cube_projected[0][1], cube_projected[1][0], cube_projected[1][1], cube_projected[2][0], cube_projected[2][1], cube_projected[3][0], cube_projected[3][1], first, CACA_LIGHTGREEN, screen_list->border_size); if (screen_list->cube.side) { draw_face(screen_list->cv, cube_projected[4][0], cube_projected[4][1], cube_projected[5][0], cube_projected[5][1], cube_projected[6][0], cube_projected[6][1], cube_projected[7][0], cube_projected[7][1], second, CACA_LIGHTGREEN, screen_list->border_size); } else { draw_face(screen_list->cv, cube_projected[8][0], cube_projected[8][1], cube_projected[9][0], cube_projected[9][1], cube_projected[10][0], cube_projected[10][1], cube_projected[11][0], cube_projected[11][1], second, CACA_LIGHTGREEN, screen_list->border_size); } screen_list->changed = 1; screen_list->force_refresh = 1; screen_list->cube.in_switch = 1; } } } \ No newline at end of file diff --git a/neercs/term/ansi.cpp b/neercs/term/ansi.cpp index a064540..abce47c 100644 --- a/neercs/term/ansi.cpp +++ b/neercs/term/ansi.cpp @@ -1,1146 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2010 Sam Hocevar - * 2008-2010 Jean-Yves Lamoureux - * 2008-2010 Pascal Terjan - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "core.h" - -using namespace std; -using namespace lol; - -#include "../neercs.h" -#include "term.h" - -/* DEC ACS with common extensions */ -static uint32_t dec_acs(uint32_t uc) -{ - switch (uc) - { - case '+': - return 0x2192; /* RIGHTWARDS ARROW */ - case ',': - return 0x2190; /* LEFTWARDS ARROW */ - case '-': - return 0x2191; /* UPWARDS ARROW */ - case '.': - return 0x2193; /* DOWNWARDS ARROW */ - case '0': - return 0x25AE; /* BLACK VERTICAL RECTANGLE */ - case '_': - return 0x25AE; /* BLACK VERTICAL RECTANGLE */ - case '`': - return 0x25C6; /* BLACK DIAMOND */ - case 'a': - return 0x2592; /* MEDIUM SHADE */ - case 'b': - return 0x2409; /* SYMBOL FOR HORIZONTAL TABULATION */ - case 'c': - return 0x240C; /* SYMBOL FOR FORM FEED */ - case 'd': - return 0x240D; /* SYMBOL FOR CARRIAGE RETURN */ - case 'e': - return 0x240A; /* SYMBOL FOR LINE FEED */ - case 'f': - return 0x00B0; /* DEGREE SIGN */ - case 'g': - return 0x00B1; /* PLUS-MINUS SIGN */ - case 'h': - return 0x2424; /* SYMBOL FOR NEWLINE */ - case 'i': - return 0x240B; /* SYMBOL FOR VERTICAL TABULATION */ - case 'j': - return 0x2518; /* BOX DRAWINGS LIGHT UP AND LEFT */ - case 'k': - return 0x2510; /* BOX DRAWINGS LIGHT DOWN AND LEFT */ - case 'l': - return 0x250C; /* BOX DRAWINGS LIGHT DOWN AND RIGHT */ - case 'm': - return 0x2514; /* BOX DRAWINGS LIGHT UP AND RIGHT */ - case 'n': - return 0x253C; /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ - case 'o': - return 0x23BA; /* HORIZONTAL SCAN LINE-1 */ - case 'p': - return 0x23BB; /* HORIZONTAL SCAN LINE-3 */ - case 'q': - return 0x2500; /* BOX DRAWINGS LIGHT HORIZONTAL */ - case 'r': - return 0x23BC; /* HORIZONTAL SCAN LINE-7 */ - case 's': - return 0x23BD; /* HORIZONTAL SCAN LINE-9 */ - case 't': - return 0x251C; /* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ - case 'u': - return 0x2524; /* BOX DRAWINGS LIGHT VERTICAL AND LEFT */ - case 'v': - return 0x2534; /* BOX DRAWINGS LIGHT UP AND HORIZONTAL */ - case 'w': - return 0x252C; /* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ - case 'x': - return 0x2502; /* BOX DRAWINGS LIGHT VERTICAL */ - case 'y': - return 0x2264; /* LESS-THAN OR EQUAL TO */ - case 'z': - return 0x2265; /* GREATER-THAN OR EQUAL TO */ - case '{': - return 0x03C0; /* GREEK SMALL LETTER PI */ - case '|': - return 0x2260; /* NOT EQUAL TO */ - case '}': - return 0x00A3; /* POUND SIGN */ - case '~': - return 0x00B7; /* MIDDLE DOT */ - default: - return uc; - } -}; - -#define LITERAL2CHAR(i0,i1) (((i0) << 8) | (i1)) - -#define LITERAL3CHAR(i0,i1,i2) LITERAL2CHAR(LITERAL2CHAR(i0, i1), i2) - -inline int Term::ReadChar(unsigned char c, int *x, int *y) -{ - if (c == '\r') - { - *x = 0; - } - - else if (c == '\n') - { - *x = 0; - *y = *y + 1; - } - else if (c == '\a') - { - /* FIXME TODO: in_bell ? */ -// if (!m_bell) -// screen_list->in_bell = 10; - m_bell = 1; - } - - else if (c == '\t') - { - *x = (*x + 7) & ~7; - } - - else if (c == '\x08') - { - if (*x > 0) - *x = *x - 1; - } - else if (c == '\x0b') - { - /* Vertical tab */ - /* Not sure about the real meaning of it, just y++ for now */ - if (*y < caca_get_canvas_height(m_caca)) - *y = *y + 1; - } - else if (c == '\x0e') - { - /* Shift Out (Ctrl-N) -> Switch to Alternate Character Set: invokes - the G1 character set. */ - m_conv_state.glr[0] = 1; - } - - else if (c == '\x0f') - { - /* Shift In (Ctrl-O) -> Switch to Standard Character Set: invokes the - G0 character set. */ - m_conv_state.glr[0] = 0; - } - else - { - return 1; - } - return 0; -} - -inline int Term::ReadDuplet(unsigned char const *buffer, unsigned int *skip, - int top, int bottom, int width, int height) -{ - int i = 0, j, k; - unsigned int dummy = 0; - - /* Single Shift Select of G2 Character Set (SS2: 0x8e): affects next - character only */ - if (buffer[i] == '\033' && buffer[i + 1] == 'N') - { - m_conv_state.ss = 2; - *skip += 1; - } - /* Reverse Index (RI) go up one line, reverse scroll if necessary */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'M') - { - /* FIXME : not sure about the meaning of 'go up one line' and 'if - necessary' words. Implemented as a scroller only. */ - for (j = bottom - 1; j > top; j--) - { - for (k = 0; k < width; k++) - { - caca_put_char(m_caca, k, j, caca_get_char(m_caca, k, j - 1)); - caca_put_attr(m_caca, k, j, caca_get_attr(m_caca, k, j - 1)); - } - } - caca_draw_line(m_caca, 0, top - 1, width - 1, top - 1, ' '); - *skip += 1; - } - - /* Single Shift Select of G3 Character Set (SS2: 0x8f): affects next - character only */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'O') - { - m_conv_state.ss = 3; - *skip += 1; - } - - /* LOCKING-SHIFT TWO (LS2), ISO 2022, ECMA-48 (1986), ISO 6429 : 1988 */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'n') - { - m_conv_state.glr[0] = 2; - *skip += 1; - } - - /* LOCKING-SHIFT THREE (LS3) ISO 2022, ECMA-48 (1986), ISO 6429 : 1988 */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'o') - { - m_conv_state.glr[0] = 3; - *skip += 1; - } - - /* RESET TO INITIAL STATE (RIS), ECMA-48 (1986), ISO 6429 : 1988 */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'c') - { - m_dfg = CACA_DEFAULT; - m_dbg = CACA_DEFAULT; - - caca_set_color_ansi(m_caca, m_dfg, m_dbg); - m_clearattr = caca_get_attr(m_caca, -1, -1); - ReadGrcm(1, &dummy); - - m_conv_state.Reset(); - *skip += 1; - } - - /* Coding Method Delimiter (CMD), ECMA-48 (1991), ISO/IEC 6429:1992 (ISO - IR 189) */ - else if (buffer[i] == '\033' && buffer[i + 1] == 'd') - { - m_conv_state.Reset(); - *skip += 1; - } - else - { - return 1; - } - - return 0; -} - -size_t Term::ReadAnsi(void const *data, size_t size) -{ - unsigned char const *buffer = (unsigned char const *)data; - unsigned int i, j, k, skip, dummy = 0; - unsigned int width, height, top, bottom; - uint32_t savedattr; - int x = 0, y = 0, save_x = 0, save_y = 0; - char b[100]; - - debug("ansi : import_term\n"); - - width = caca_get_canvas_width(m_caca); - height = caca_get_canvas_height(m_caca); - x = caca_get_cursor_x(m_caca); - y = caca_get_cursor_y(m_caca); - top = 1; - bottom = height; - - if (!m_init) - { - m_fg = m_dfg = CACA_LIGHTGRAY; - m_bg = m_dbg = CACA_BLACK; - - m_bold = m_blink = m_italics = m_negative = m_concealed - = m_underline = m_faint = m_strike = m_proportional = 0; - - caca_set_color_ansi(m_caca, m_dfg, m_dbg); - m_clearattr = caca_get_attr(m_caca, -1, -1); - - ReadGrcm(1, &dummy); - - m_conv_state.Reset(); - - m_init = 1; - } - - for (i = 0; i < size; i += skip) - { - uint32_t ch = 0; - int wch = 0; - - skip = 1; - - /* Control codes (ASCII < \x20) */ - if (!ReadChar(buffer[i], &x, &y)) - { - } - - /* If there are not enough characters to parse the escape sequence, - wait until the next try. We require 3. */ - - else if (buffer[i] == '\033' && i + 2 >= size) - break; - - - else if (!ReadDuplet(&buffer[i], &skip, top, bottom, width, height)) - { - - } - - - /* GZDM4, G0-Designators, multi, 94^n chars [grandfathered short form - from ISO 2022:1986] */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && (buffer[i + 2] >= '@') && (buffer[i + 2] <= 'C')) - { - m_conv_state.gn[0] = LITERAL2CHAR('$', buffer[i + 2]); - skip += 2; - } - - /* GnDMx Gn-Designators, 9x^n chars; need one more char to distinguish - these */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && (i + 3 >= size)) - break; - - /* GZD4 G0-Designator, 94 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '(') - { - m_conv_state.gn[0] = buffer[i + 2]; - skip += 2; - } - - /* G1D4 G1-Designator, 94 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == ')') - { - m_conv_state.gn[1] = buffer[i + 2]; - skip += 2; - } - - /* G2D4 G2-Designator, 94 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '*') - { - m_conv_state.gn[2] = buffer[i + 2]; - skip += 2; - } - - /* G3D4 G3-Designator, 94 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '+') - { - m_conv_state.gn[3] = buffer[i + 2]; - skip += 2; - } - - /* G2D6 G2-Designator, 96 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '.') - { - m_conv_state.gn[2] = LITERAL2CHAR('.', buffer[i + 2]); - skip += 2; - } - - /* G3D6 G3-Designator, 96 chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '/') - { - m_conv_state.gn[3] = LITERAL2CHAR('.', buffer[i + 2]); - skip += 2; - } - - /* GZDM4 G0-Designator, 94^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '(') - { - m_conv_state.gn[0] = LITERAL2CHAR('$', buffer[i + 3]); - skip += 3; - } - - /* G1DM4 G1-Designator, 94^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == ')') - { - m_conv_state.gn[1] = LITERAL2CHAR('$', buffer[i + 3]); - skip += 3; - } - - /* G2DM4 G2-Designator, 94^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '*') - { - m_conv_state.gn[2] = LITERAL2CHAR('$', buffer[i + 3]); - skip += 3; - } - - /* G3DM4 G3-Designator, 94^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '+') - { - m_conv_state.gn[3] = LITERAL2CHAR('$', buffer[i + 3]); - skip += 3; - } - - /* G2DM6 G2-Designator, 96^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '.') - { - m_conv_state.gn[2] = LITERAL3CHAR('$', '.', buffer[i + 3]); - skip += 3; - } - - /* G3DM6 G3-Designator, 96^n chars */ - else if (buffer[i] == '\033' && buffer[i + 1] == '$' - && buffer[i + 2] == '/') - { - m_conv_state.gn[3] = LITERAL3CHAR('$', '.', buffer[i + 3]); - skip += 3; - } - else if (buffer[i] == '\033' && buffer[i + 1] == '#') - { - debug("ansi private '#' sequence\n"); - - switch (buffer[i + 2]) - { - case '8': /* DECALN Fills the entire screen area with - uppercase Es for screen focus and - alignment. */ - for (j = 0; j < height; j++) - { - for (k = 0; k < width; k++) - { - caca_put_char(m_caca, k, j, 'E'); - } - } - x = 0; - y = 0; - skip += 2; - break; - - default: - debug("Unknow private sequence 'ESC#%c'\n", buffer[i + 2]); - continue; - } - - } - /* Interpret escape commands, as per Standard ECMA-48 "Control - Functions for Coded Character Sets", 5.4. Control sequences. */ - else if (buffer[i] == '\033' && buffer[i + 1] == '[') - { - unsigned int argc = 0, argv[101]; - unsigned int param, inter, junk, final; - - if (buffer[i + 2] == '?') - { - debug("CSI? %c%c%c%c%c\n", - buffer[i + 3], buffer[i + 4], buffer[i + 5], - buffer[i + 6], buffer[i + 7]); - } - - /* Compute offsets to parameter bytes, intermediate bytes and to - the final byte. Only the final byte is mandatory, there can be - zero of the others. 0 param=2 inter final final+1 - +-----+------------------+---------------------+-----------------+ - | CSI | parameter bytes | intermediate bytes | final byte | | | - 0x30 - 0x3f | 0x20 - 0x2f | 0x40 - 0x7e | | ^[[ | 0123456789:;<=>? - | SPC !"#$%&'()*+,-./ | azAZ@[\]^_`{|}~ | - +-----+------------------+---------------------+-----------------+ */ - param = 2; - - /* vttest use to interleave control characters (\014 CR or \010 - BS) into CSI sequences, either directly after ESC[ or after - param. Can't find anything related to this in any documentation - nor XTerm sources, thought. */ - - for (junk = param; i + junk < size; junk++) - if (buffer[i + junk] < 0x20) - { - ReadChar(buffer[i + junk], &x, &y); - } - else - { - break; - } - - /* Intermediate offset */ - for (inter = junk; i + inter < size; inter++) - if (buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f) - { - break; - } - /* Interleaved character */ - for (junk = inter; i + junk < size; junk++) - if (buffer[i + junk] < 0x20) - { - ReadChar(buffer[i + junk], &x, &y); - } - else - { - break; - } - - /* Final Byte offset */ - for (final = junk; i + final < size; final++) - if (buffer[i + final] < 0x20 || buffer[i + final] > 0x2f) - { - break; - } - if (i + final >= size - || buffer[i + final] < 0x40 || buffer[i + final] > 0x7e) - { - debug("ansi Invalid Final Byte (%d %c)\n", buffer[i + final], - buffer[i + final]); - break; /* Invalid Final Byte */ - } - - skip += final; - - /* Sanity checks */ - if (param < inter && buffer[i + param] >= 0x3c) - { - /* Private sequence, only parse what we know */ - debug("ansi import: private sequence \"^[[%.*s\"", - final - param + 1, buffer + i + param); - /* FIXME better parsing */ - if (buffer[i + 2] == '?') - { - char arg[5], *end; - int a = 0; - int c, p, Pm; - for (p = 0; p < 4; p++) - { - if (buffer[i + 3 + p] >= '0' - && buffer[i + 3 + p] <= '9') - { - arg[a] = buffer[i + 3 + p]; - arg[a + 1] = 0; - a++; - debug("private a now '%s'\n", arg); - } - else - { - break; - } - } - Pm = strtol(arg, &end, 10); - - c = buffer[i + 3 + (end - arg)]; - - debug("ansi private mouse : command %c, arg %d", c, Pm); - if (c == 'h') /* DECSET DEC Private Mode Set */ - { - - switch (Pm) - { - /* FIXME Handle different modes */ - case 9: - debug("mouse : X10 mode\n"); - m_report_mouse = MOUSE_X10; - break; - case 1000: /* Send Mouse X & Y on button press - and release. */ - debug("mouse : VT200 mode\n"); - m_report_mouse = MOUSE_VT200; - break; - case 1001: /* Use Hilite Mouse Tracking. */ - debug("mouse : VT200_HIGHLIGHT mode\n"); - m_report_mouse = MOUSE_VT200_HIGHLIGHT; - break; - case 1002: /* Use Cell Motion Mouse Tracking. */ - debug("mouse : BTN mode\n"); - m_report_mouse = MOUSE_BTN_EVENT; - break; - case 1003: /* Use All Motion Mouse Tracking. */ - debug("mouse : ANY mode\n"); - m_report_mouse = MOUSE_ANY_EVENT; - break; - default: - break; - } - } - else if (c == 'l') /* DECRST DEC Private Mode Reset */ - { - Pm = atoi(arg); - switch (Pm) - { - /* FIXME Handle different modes */ - case 9: - case 1000: /* Send Mouse X & Y on button press - and release. */ - case 1001: /* Use Hilite Mouse Tracking. */ - case 1002: /* Use Cell Motion Mouse Tracking. */ - case 1003: /* Use All Motion Mouse Tracking. */ - m_report_mouse = MOUSE_NONE; - debug("ansi private mouse : NOT reporting mouse"); - break; - default: - break; - } - } - } - continue; /* Private sequence, skip it entirely */ - } - - if (final - param > 100) - continue; /* Suspiciously long sequence, skip it */ - - /* Parse parameter bytes as per ECMA-48 5.4.2: Parameter string - format */ - if (param < inter) - { - argv[0] = 0; - for (j = param; j < inter; j++) - { - if (buffer[i + j] == ';') - argv[++argc] = 0; - else if (buffer[i + j] >= '0' && buffer[i + j] <= '9') - argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0'); - } - argc++; - } - - /* Interpret final byte. The code representations are given in - ECMA-48 5.4: Control sequences, and the code definitions are - given in ECMA-48 8.3: Definition of control functions. */ - debug("ansi import: command '%c'", buffer[i + final]); - switch (buffer[i + final]) - { - case 'A': /* CUU (0x41) - Cursor Up */ - y -= argc ? argv[0] : 1; - if (y < 0) - y = 0; - break; - case 'B': /* CUD (0x42) - Cursor Down */ - y += argc ? argv[0] : 1; - break; - case 'C': /* CUF (0x43) - Cursor Right */ - x += argc ? argv[0] : 1; - break; - case 'D': /* CUB (0x44) - Cursor Left */ - x -= argc ? argv[0] : 1; - if (x < 0) - x = 0; - break; - case 'G': /* CHA (0x47) - Cursor Character Absolute */ - x = (argc && argv[0] > 0) ? argv[0] - 1 : 0; - break; - case 'H': /* CUP (0x48) - Cursor Position */ - x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0; - y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0; - debug("ansi CUP : Cursor at %dx%d\n", x, y); - break; - case 'J': /* ED (0x4a) - Erase In Page */ - savedattr = caca_get_attr(m_caca, -1, -1); - caca_set_attr(m_caca, m_clearattr); - if (!argc || argv[0] == 0) - { - caca_draw_line(m_caca, x, y, width, y, ' '); - caca_fill_box(m_caca, 0, y + 1, width, height - 1, ' '); - } - else if (argv[0] == 1) - { - caca_fill_box(m_caca, 0, 0, width, y, ' '); - caca_draw_line(m_caca, 0, y, x, y, ' '); - } - else if (argv[0] == 2) - { - // x = y = 0; - caca_fill_box(m_caca, 0, 0, width, height, ' '); - } - caca_set_attr(m_caca, savedattr); - break; - case 'K': /* EL (0x4b) - Erase In Line */ - debug("ansi EL : cursor at %dx%d\n", x, y); - if (!argc || argv[0] == 0) - { - caca_draw_line(m_caca, x, y, width, y, ' '); - } - else if (argv[0] == 1) - { - caca_draw_line(m_caca, 0, y, x, y, ' '); - } - else if (argv[0] == 2) - { - caca_draw_line(m_caca, 0, y, width, y, ' '); - } - break; - case 'L': /* IL - Insert line */ - { - unsigned int nb_lines = argc ? argv[0] : 1; - for (j = bottom - 1; j >= (unsigned int)y + nb_lines; j--) - { - for (k = 0; k < width; k++) - { - caca_put_char(m_caca, k, j, - caca_get_char(m_caca, k, - j - nb_lines)); - caca_put_attr(m_caca, k, j, - caca_get_attr(m_caca, k, - j - nb_lines)); - } - caca_draw_line(m_caca, 0, j - nb_lines, width, - j - nb_lines, ' '); - } - } - break; - case 'P': /* DCH (0x50) - Delete Character */ - if (!argc || argv[0] == 0) - argv[0] = 1; /* echo -ne 'foobar\r\e[0P\n' */ - - for (j = x; (unsigned int)(j + argv[0]) < width; j++) - { - caca_put_char(m_caca, j, y, - caca_get_char(m_caca, j + argv[0], y)); - caca_put_attr(m_caca, j, y, - caca_get_attr(m_caca, j + argv[0], y)); - } - break; -#if 0 - savedattr = caca_get_attr(m_caca, -1, -1); - caca_set_attr(m_caca, m_clearattr); - for (; (unsigned int)j < width; j++) - caca_put_char(m_caca, j, y, ' '); - caca_set_attr(m_caca, savedattr); -#endif - case 'X': /* ECH (0x58) - Erase Character */ - if (argc && argv[0]) - { - savedattr = caca_get_attr(m_caca, -1, -1); - caca_set_attr(m_caca, m_clearattr); - caca_draw_line(m_caca, x, y, x + argv[0] - 1, y, ' '); - caca_set_attr(m_caca, savedattr); - } - case 'c': /* DA -- Device Attributes */ - /* - 0 Base VT100, no options 1 Processor options (STP) 2 - Advanced video option (AVO) 3 AVO and STP 4 Graphics - processor option (GPO) 5 GPO and STP 6 GPO and AVO 7 GPO, - STP, and AVO */ - /* Warning, argument is Pn */ - debug("ansi Got command c, argc %d, argv[0] (%d)\n", argc, - argv[0], argv[0]); - if (!argc || argv[0] == 0) - { - SendAnsi("\x1b[?1;0c"); - } - else - { - switch (argv[0]) - { - case 1: - SendAnsi("\x1b[?\x1;\x1c"); - break; - case 2: - SendAnsi("\x1b[?\x1;\x2c"); - break; - case 3: - SendAnsi("\x1b[?\x1;\x3c"); - break; - case 4: - SendAnsi("\x1b[?\x1;\x4c"); - break; - case 5: - SendAnsi("\x1b[?\x1;\x5c"); - break; - case 6: - SendAnsi("\x1b[?\x1;\x6c"); - break; - case 7: - SendAnsi("\x1b[?\x1;\x7c"); - break; - default: - debug("Unsupported DA option '%d'\n", argv[0]); - break; - } - } - break; - case 'd': /* VPA (0x64) - Line Position Absolute */ - y = (argc && argv[0] > 0) ? argv[0] - 1 : 0; - break; - case 'f': /* HVP (0x66) - Character And Line Position */ - x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0; - y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0; - break; - case 'g': /* TBC -- Tabulation Clear */ - break; - case 'r': /* FIXME */ - if (argc == 2) /* DCSTBM - Set top and bottom margin */ - { - debug("DCSTBM %d %d", argv[0], argv[1]); - top = argv[0]; - bottom = argv[1]; - } - else - debug("ansi import: command r with %d params", argc); - break; - case 'h': /* SM (0x68) - FIXME */ - debug("ansi import: set mode %i", argc ? (int)argv[0] : -1); - break; - case 'l': /* RM (0x6c) - FIXME */ - debug("ansi import: reset mode %i", argc ? (int)argv[0] : -1); - break; - case 'm': /* SGR (0x6d) - Select Graphic Rendition */ - if (argc) - ReadGrcm(argc, argv); - else - ReadGrcm(1, &dummy); - break; - case 'n': - debug("ansi command n, argc %d, argv[0] %d\n", argc, argv[0]); - if (!argc) - break; - - switch (argv[0]) - { - case 5: - /* Term ok */ - SendAnsi("\x1b[0n"); - break; - case 6: - /* Cursor Position */ - sprintf(b, "\x1b[%d;%dR", y + 1, x + 1); - SendAnsi(b); - break; - } - - break; - case 's': /* Private (save cursor position) */ - save_x = x; - save_y = y; - break; - case 'u': /* Private (reload cursor position) */ - x = save_x; - y = save_y; - break; - default: - debug("ansi import: unknown command \"^[%.*s\"", - final - param + 1, buffer + i + param); - break; - } - } - - /* Parse OSC stuff. */ - else if (buffer[i] == '\033' && buffer[i + 1] == ']') - { - char *string; - unsigned int command = 0; - unsigned int mode = 2, semicolon, final; - - for (semicolon = mode; i + semicolon < size; semicolon++) - { - if (buffer[i + semicolon] < '0' || buffer[i + semicolon] > '9') - break; - command = 10 * command + (buffer[i + semicolon] - '0'); - } - - if (i + semicolon >= size || buffer[i + semicolon] != ';') - break; /* Invalid Mode */ - - for (final = semicolon + 1; i + final < size; final++) - if (buffer[i + final] < 0x20) - break; - - if (i + final >= size || buffer[i + final] != '\a') - break; /* Not enough data or no bell found */ - /* FIXME: XTerm also reacts to and */ - /* FIXME: differenciate between not enough data (try again) and - invalid data (print shit) */ - - skip += final; - - string = (char *)malloc(final - (semicolon + 1) + 1); - memcpy(string, buffer + i + (semicolon + 1), - final - (semicolon + 1)); - string[final - (semicolon + 1)] = '\0'; - debug("ansi import: got OSC command %i string '%s'", command, - string); - if (command == 0 || command == 2) - { - if (m_title) - free(m_title); - m_title = string; - } - else - free(string); - } - - /* Get the character we’re going to paste */ - else - { - size_t bytes; - - if (i + 6 < size) - { - ch = caca_utf8_to_utf32((char const *)(buffer + i), &bytes); - } - else - { - /* Add a trailing zero to what we're going to read */ - char tmp[7]; - memcpy(tmp, buffer + i, size - i); - tmp[size - i] = '\0'; - ch = caca_utf8_to_utf32(tmp, &bytes); - } - - if (!bytes) - { - /* If the Unicode is invalid, assume it was latin1. */ - ch = buffer[i]; - bytes = 1; - } - - /* very incomplete ISO-2022 implementation tailored to DEC ACS */ - if (m_conv_state.cs == '@') - { - if (((ch > ' ') && (ch <= '~')) - && - (m_conv_state. - gn[m_conv_state.ss ? m_conv_state. - gn[m_conv_state.ss] : m_conv_state.glr[0]] == '0')) - { - ch = dec_acs(ch); - } - else if (((ch > 0x80) && (ch < 0xff)) - && (m_conv_state.gn[m_conv_state.glr[1]] == '0')) - { - ch = dec_acs(ch + ' ' - 0x80); - } - } - m_conv_state.ss = 0; /* no single-shift (GL) */ - - wch = caca_utf32_is_fullwidth(ch) ? 2 : 1; - - skip += bytes - 1; - } - - /* Wrap long lines or grow horizontally */ - while ((unsigned int)x + wch > width) - { - x -= width; - y++; - } - - /* Scroll or grow vertically */ - if ((unsigned int)y >= bottom) - { - int lines = (y - bottom) + 1; - - savedattr = caca_get_attr(m_caca, -1, -1); - - for (j = top - 1; j + lines < bottom; j++) - { - for (k = 0; k < width; k++) - { - caca_put_char(m_caca, k, j, - caca_get_char(m_caca, k, j + lines)); - caca_put_attr(m_caca, k, j, - caca_get_attr(m_caca, k, j + lines)); - } - } - caca_set_attr(m_caca, m_clearattr); - caca_fill_box(m_caca, 0, bottom - lines, width, bottom - 1, ' '); - y -= lines; - caca_set_attr(m_caca, savedattr); - } - - /* Now paste our character, if any */ - if (wch) - { - caca_put_char(m_caca, x, y, ch); - x += wch; - } - } - - caca_gotoxy(m_caca, x, y); - - if (i) - m_changed = 1; - return i; -} - -size_t Term::SendAnsi(char const *str) -{ - size_t ret = strlen(str); - - /* FIXME TODO: not implemented */ - Log::Debug("Sending %d-character ANSI sequence\n", (int)ret); - - return ret; -} - -/* Coding Method Delimiter (CMD), ECMA-48 (1991), ISO/IEC 6429:1992 (ISO IR - 189) */ -void Iso2022Conversion::Reset() -{ - cs = '@'; /* ISO-2022 coding system */ - cn[0] = '@'; /* ISO 646 C0 control charset */ - cn[1] = 'C'; /* ISO 6429-1983 C1 control charset */ - glr[0] = 0; /* G0 in GL */ - glr[1] = 2; /* G2 in GR */ - gn[0] = 'B'; /* US-ASCII G0 charset */ - gn[1] = '0'; /* DEC ACS G1 charset */ - gn[2] = LITERAL2CHAR('.', 'A'); /* ISO 8859-1 G2 charset */ - gn[3] = LITERAL2CHAR('.', 'A'); /* ISO 8859-1 G3 charset */ - ss = 0; /* no single-shift (GL) */ - ctrl8bit = 1; -} - -/* XXX : ANSI loader helper */ - -void Term::ReadGrcm(unsigned int argc, unsigned int const *argv) -{ - static uint8_t const ansi2caca[] = { - CACA_BLACK, CACA_RED, CACA_GREEN, CACA_BROWN, - CACA_BLUE, CACA_MAGENTA, CACA_CYAN, CACA_LIGHTGRAY - }; - - unsigned int j; - uint8_t efg, ebg; /* Effective (libcaca) fg/bg */ - - for (j = 0; j < argc; j++) - { - /* Defined in ECMA-48 8.3.117: SGR - SELECT GRAPHIC RENDITION */ - if (argv[j] >= 30 && argv[j] <= 37) - m_fg = ansi2caca[argv[j] - 30]; - else if (argv[j] >= 40 && argv[j] <= 47) - m_bg = ansi2caca[argv[j] - 40]; - else if (argv[j] >= 90 && argv[j] <= 97) - m_fg = ansi2caca[argv[j] - 90] + 8; - else if (argv[j] >= 100 && argv[j] <= 107) - m_bg = ansi2caca[argv[j] - 100] + 8; - else - switch (argv[j]) - { - case 0: /* default rendition */ - m_fg = m_dfg; - m_bg = m_dbg; - m_bold = m_blink = m_italics = m_negative - = m_concealed = m_underline = m_faint = m_strike - = m_proportional = 0; - break; - case 1: /* bold or increased intensity */ - m_bold = 1; - break; - case 2: /* faint, decreased intensity or second colour - */ - m_faint = 1; - break; - case 3: /* italicized */ - m_italics = 1; - break; - case 4: /* singly underlined */ - m_underline = 1; - break; - case 5: /* slowly blinking (less then 150 per minute) */ - case 6: /* rapidly blinking (150 per minute or more) */ - m_blink = 1; - break; - case 7: /* negative image */ - m_negative = 1; - break; - case 8: /* concealed characters */ - m_concealed = 1; - break; - case 9: /* crossed-out (characters still legible but - marked as to be deleted */ - m_strike = 1; - break; - case 21: /* doubly underlined */ - m_underline = 1; - break; - case 22: /* normal colour or normal intensity (neither - bold nor faint) */ - m_bold = m_faint = 0; - break; - case 23: /* not italicized, not fraktur */ - m_italics = 0; - break; - case 24: /* not underlined (neither singly nor doubly) */ - m_underline = 0; - break; - case 25: /* steady (not blinking) */ - m_blink = 0; - break; - case 26: /* (reserved for proportional spacing as - specified in CCITT Recommendation T.61) */ - m_proportional = 1; - break; - case 27: /* positive image */ - m_negative = 0; - break; - case 28: /* revealed characters */ - m_concealed = 0; - break; - case 29: /* not crossed out */ - m_strike = 0; - break; - case 38: /* (reserved for future standardization, - intended for setting character foreground - colour as specified in ISO 8613-6 [CCITT - Recommendation T.416]) */ - break; - case 39: /* default display colour - (implementation-defined) */ - m_fg = m_dfg; - break; - case 48: /* (reserved for future standardization, - intended for setting character background - colour as specified in ISO 8613-6 [CCITT - Recommendation T.416]) */ - break; - case 49: /* default background colour - (implementation-defined) */ - m_bg = m_dbg; - break; - case 50: /* (reserved for cancelling the effect of the - rendering aspect established by parameter - value 26) */ - m_proportional = 0; - break; - default: - debug("ansi import: unknown sgr %i", argv[j]); - break; - } - } - - if (m_concealed) - { - efg = ebg = CACA_TRANSPARENT; - } - else - { - efg = m_negative ? m_bg : m_fg; - ebg = m_negative ? m_fg : m_bg; - - if (m_bold) - { - if (efg < 8) - efg += 8; - else if (efg == CACA_DEFAULT) - efg = CACA_WHITE; - } - } - - caca_set_color_ansi(m_caca, efg, ebg); -} +/* * neercs console-based window manager * Copyright (c) 2006-2010 Sam Hocevar * 2008-2010 Jean-Yves Lamoureux * 2008-2010 Pascal Terjan * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include #include "core.h" using namespace std; using namespace lol; #include "../neercs.h" #include "term.h" /* DEC ACS with common extensions */ static uint32_t dec_acs(uint32_t uc) { switch (uc) { case '+': return 0x2192; /* RIGHTWARDS ARROW */ case ',': return 0x2190; /* LEFTWARDS ARROW */ case '-': return 0x2191; /* UPWARDS ARROW */ case '.': return 0x2193; /* DOWNWARDS ARROW */ case '0': return 0x25AE; /* BLACK VERTICAL RECTANGLE */ case '_': return 0x25AE; /* BLACK VERTICAL RECTANGLE */ case '`': return 0x25C6; /* BLACK DIAMOND */ case 'a': return 0x2592; /* MEDIUM SHADE */ case 'b': return 0x2409; /* SYMBOL FOR HORIZONTAL TABULATION */ case 'c': return 0x240C; /* SYMBOL FOR FORM FEED */ case 'd': return 0x240D; /* SYMBOL FOR CARRIAGE RETURN */ case 'e': return 0x240A; /* SYMBOL FOR LINE FEED */ case 'f': return 0x00B0; /* DEGREE SIGN */ case 'g': return 0x00B1; /* PLUS-MINUS SIGN */ case 'h': return 0x2424; /* SYMBOL FOR NEWLINE */ case 'i': return 0x240B; /* SYMBOL FOR VERTICAL TABULATION */ case 'j': return 0x2518; /* BOX DRAWINGS LIGHT UP AND LEFT */ case 'k': return 0x2510; /* BOX DRAWINGS LIGHT DOWN AND LEFT */ case 'l': return 0x250C; /* BOX DRAWINGS LIGHT DOWN AND RIGHT */ case 'm': return 0x2514; /* BOX DRAWINGS LIGHT UP AND RIGHT */ case 'n': return 0x253C; /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ case 'o': return 0x23BA; /* HORIZONTAL SCAN LINE-1 */ case 'p': return 0x23BB; /* HORIZONTAL SCAN LINE-3 */ case 'q': return 0x2500; /* BOX DRAWINGS LIGHT HORIZONTAL */ case 'r': return 0x23BC; /* HORIZONTAL SCAN LINE-7 */ case 's': return 0x23BD; /* HORIZONTAL SCAN LINE-9 */ case 't': return 0x251C; /* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ case 'u': return 0x2524; /* BOX DRAWINGS LIGHT VERTICAL AND LEFT */ case 'v': return 0x2534; /* BOX DRAWINGS LIGHT UP AND HORIZONTAL */ case 'w': return 0x252C; /* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ case 'x': return 0x2502; /* BOX DRAWINGS LIGHT VERTICAL */ case 'y': return 0x2264; /* LESS-THAN OR EQUAL TO */ case 'z': return 0x2265; /* GREATER-THAN OR EQUAL TO */ case '{': return 0x03C0; /* GREEK SMALL LETTER PI */ case '|': return 0x2260; /* NOT EQUAL TO */ case '}': return 0x00A3; /* POUND SIGN */ case '~': return 0x00B7; /* MIDDLE DOT */ default: return uc; } }; #define LITERAL2CHAR(i0,i1) (((i0) << 8) | (i1)) #define LITERAL3CHAR(i0,i1,i2) LITERAL2CHAR(LITERAL2CHAR(i0, i1), i2) inline int Term::ReadChar(unsigned char c, int *x, int *y) { if (c == '\r') { *x = 0; } else if (c == '\n') { *x = 0; *y = *y + 1; } else if (c == '\a') { /* FIXME TODO: in_bell ? */ // if (!m_bell) // screen_list->in_bell = 10; m_bell = 1; } else if (c == '\t') { *x = (*x + 7) & ~7; } else if (c == '\x08') { if (*x > 0) *x = *x - 1; } else if (c == '\x0b') { /* Vertical tab */ /* Not sure about the real meaning of it, just y++ for now */ if (*y < caca_get_canvas_height(m_caca)) *y = *y + 1; } else if (c == '\x0e') { /* Shift Out (Ctrl-N) -> Switch to Alternate Character Set: invokes the G1 character set. */ m_conv_state.glr[0] = 1; } else if (c == '\x0f') { /* Shift In (Ctrl-O) -> Switch to Standard Character Set: invokes the G0 character set. */ m_conv_state.glr[0] = 0; } else { return 1; } return 0; } inline int Term::ReadDuplet(unsigned char const *buffer, unsigned int *skip, int top, int bottom, int width, int height) { int i = 0, j, k; unsigned int dummy = 0; /* Single Shift Select of G2 Character Set (SS2: 0x8e): affects next character only */ if (buffer[i] == '\033' && buffer[i + 1] == 'N') { m_conv_state.ss = 2; *skip += 1; } /* Reverse Index (RI) go up one line, reverse scroll if necessary */ else if (buffer[i] == '\033' && buffer[i + 1] == 'M') { /* FIXME : not sure about the meaning of 'go up one line' and 'if necessary' words. Implemented as a scroller only. */ for (j = bottom - 1; j > top; j--) { for (k = 0; k < width; k++) { caca_put_char(m_caca, k, j, caca_get_char(m_caca, k, j - 1)); caca_put_attr(m_caca, k, j, caca_get_attr(m_caca, k, j - 1)); } } caca_draw_line(m_caca, 0, top - 1, width - 1, top - 1, ' '); *skip += 1; } /* Single Shift Select of G3 Character Set (SS2: 0x8f): affects next character only */ else if (buffer[i] == '\033' && buffer[i + 1] == 'O') { m_conv_state.ss = 3; *skip += 1; } /* LOCKING-SHIFT TWO (LS2), ISO 2022, ECMA-48 (1986), ISO 6429 : 1988 */ else if (buffer[i] == '\033' && buffer[i + 1] == 'n') { m_conv_state.glr[0] = 2; *skip += 1; } /* LOCKING-SHIFT THREE (LS3) ISO 2022, ECMA-48 (1986), ISO 6429 : 1988 */ else if (buffer[i] == '\033' && buffer[i + 1] == 'o') { m_conv_state.glr[0] = 3; *skip += 1; } /* RESET TO INITIAL STATE (RIS), ECMA-48 (1986), ISO 6429 : 1988 */ else if (buffer[i] == '\033' && buffer[i + 1] == 'c') { m_dfg = CACA_DEFAULT; m_dbg = CACA_DEFAULT; caca_set_color_ansi(m_caca, m_dfg, m_dbg); m_clearattr = caca_get_attr(m_caca, -1, -1); ReadGrcm(1, &dummy); m_conv_state.Reset(); *skip += 1; } /* Coding Method Delimiter (CMD), ECMA-48 (1991), ISO/IEC 6429:1992 (ISO IR 189) */ else if (buffer[i] == '\033' && buffer[i + 1] == 'd') { m_conv_state.Reset(); *skip += 1; } else { return 1; } return 0; } size_t Term::ReadAnsi(void const *data, size_t size) { unsigned char const *buffer = (unsigned char const *)data; unsigned int i, j, k, skip, dummy = 0; unsigned int width, height, top, bottom; uint32_t savedattr; int x = 0, y = 0, save_x = 0, save_y = 0; char b[100]; debug("ansi : import_term\n"); width = caca_get_canvas_width(m_caca); height = caca_get_canvas_height(m_caca); x = caca_get_cursor_x(m_caca); y = caca_get_cursor_y(m_caca); top = 1; bottom = height; if (!m_init) { m_fg = m_dfg = CACA_LIGHTGRAY; m_bg = m_dbg = CACA_BLACK; m_bold = m_blink = m_italics = m_negative = m_concealed = m_underline = m_faint = m_strike = m_proportional = 0; caca_set_color_ansi(m_caca, m_dfg, m_dbg); m_clearattr = caca_get_attr(m_caca, -1, -1); ReadGrcm(1, &dummy); m_conv_state.Reset(); m_init = 1; } for (i = 0; i < size; i += skip) { uint32_t ch = 0; int wch = 0; skip = 1; /* Control codes (ASCII < \x20) */ if (!ReadChar(buffer[i], &x, &y)) { } /* If there are not enough characters to parse the escape sequence, wait until the next try. We require 3. */ else if (buffer[i] == '\033' && i + 2 >= size) break; else if (!ReadDuplet(&buffer[i], &skip, top, bottom, width, height)) { } /* GZDM4, G0-Designators, multi, 94^n chars [grandfathered short form from ISO 2022:1986] */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && (buffer[i + 2] >= '@') && (buffer[i + 2] <= 'C')) { m_conv_state.gn[0] = LITERAL2CHAR('$', buffer[i + 2]); skip += 2; } /* GnDMx Gn-Designators, 9x^n chars; need one more char to distinguish these */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && (i + 3 >= size)) break; /* GZD4 G0-Designator, 94 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '(') { m_conv_state.gn[0] = buffer[i + 2]; skip += 2; } /* G1D4 G1-Designator, 94 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == ')') { m_conv_state.gn[1] = buffer[i + 2]; skip += 2; } /* G2D4 G2-Designator, 94 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '*') { m_conv_state.gn[2] = buffer[i + 2]; skip += 2; } /* G3D4 G3-Designator, 94 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '+') { m_conv_state.gn[3] = buffer[i + 2]; skip += 2; } /* G2D6 G2-Designator, 96 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '.') { m_conv_state.gn[2] = LITERAL2CHAR('.', buffer[i + 2]); skip += 2; } /* G3D6 G3-Designator, 96 chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '/') { m_conv_state.gn[3] = LITERAL2CHAR('.', buffer[i + 2]); skip += 2; } /* GZDM4 G0-Designator, 94^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '(') { m_conv_state.gn[0] = LITERAL2CHAR('$', buffer[i + 3]); skip += 3; } /* G1DM4 G1-Designator, 94^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == ')') { m_conv_state.gn[1] = LITERAL2CHAR('$', buffer[i + 3]); skip += 3; } /* G2DM4 G2-Designator, 94^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '*') { m_conv_state.gn[2] = LITERAL2CHAR('$', buffer[i + 3]); skip += 3; } /* G3DM4 G3-Designator, 94^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '+') { m_conv_state.gn[3] = LITERAL2CHAR('$', buffer[i + 3]); skip += 3; } /* G2DM6 G2-Designator, 96^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '.') { m_conv_state.gn[2] = LITERAL3CHAR('$', '.', buffer[i + 3]); skip += 3; } /* G3DM6 G3-Designator, 96^n chars */ else if (buffer[i] == '\033' && buffer[i + 1] == '$' && buffer[i + 2] == '/') { m_conv_state.gn[3] = LITERAL3CHAR('$', '.', buffer[i + 3]); skip += 3; } else if (buffer[i] == '\033' && buffer[i + 1] == '#') { debug("ansi private '#' sequence\n"); switch (buffer[i + 2]) { case '8': /* DECALN Fills the entire screen area with uppercase Es for screen focus and alignment. */ for (j = 0; j < height; j++) { for (k = 0; k < width; k++) { caca_put_char(m_caca, k, j, 'E'); } } x = 0; y = 0; skip += 2; break; default: debug("Unknow private sequence 'ESC#%c'\n", buffer[i + 2]); continue; } } /* Interpret escape commands, as per Standard ECMA-48 "Control Functions for Coded Character Sets", 5.4. Control sequences. */ else if (buffer[i] == '\033' && buffer[i + 1] == '[') { unsigned int argc = 0, argv[101]; unsigned int param, inter, junk, final; if (buffer[i + 2] == '?') { debug("CSI? %c%c%c%c%c\n", buffer[i + 3], buffer[i + 4], buffer[i + 5], buffer[i + 6], buffer[i + 7]); } /* Compute offsets to parameter bytes, intermediate bytes and to the final byte. Only the final byte is mandatory, there can be zero of the others. 0 param=2 inter final final+1 +-----+------------------+---------------------+-----------------+ | CSI | parameter bytes | intermediate bytes | final byte | | | 0x30 - 0x3f | 0x20 - 0x2f | 0x40 - 0x7e | | ^[[ | 0123456789:;<=>? | SPC !"#$%&'()*+,-./ | azAZ@[\]^_`{|}~ | +-----+------------------+---------------------+-----------------+ */ param = 2; /* vttest use to interleave control characters (\014 CR or \010 BS) into CSI sequences, either directly after ESC[ or after param. Can't find anything related to this in any documentation nor XTerm sources, thought. */ for (junk = param; i + junk < size; junk++) if (buffer[i + junk] < 0x20) { ReadChar(buffer[i + junk], &x, &y); } else { break; } /* Intermediate offset */ for (inter = junk; i + inter < size; inter++) if (buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f) { break; } /* Interleaved character */ for (junk = inter; i + junk < size; junk++) if (buffer[i + junk] < 0x20) { ReadChar(buffer[i + junk], &x, &y); } else { break; } /* Final Byte offset */ for (final = junk; i + final < size; final++) if (buffer[i + final] < 0x20 || buffer[i + final] > 0x2f) { break; } if (i + final >= size || buffer[i + final] < 0x40 || buffer[i + final] > 0x7e) { debug("ansi Invalid Final Byte (%d %c)\n", buffer[i + final], buffer[i + final]); break; /* Invalid Final Byte */ } skip += final; /* Sanity checks */ if (param < inter && buffer[i + param] >= 0x3c) { /* Private sequence, only parse what we know */ debug("ansi import: private sequence \"^[[%.*s\"", final - param + 1, buffer + i + param); /* FIXME better parsing */ if (buffer[i + 2] == '?') { char arg[5], *end; int a = 0; int c, p, Pm; for (p = 0; p < 4; p++) { if (buffer[i + 3 + p] >= '0' && buffer[i + 3 + p] <= '9') { arg[a] = buffer[i + 3 + p]; arg[a + 1] = 0; a++; debug("private a now '%s'\n", arg); } else { break; } } Pm = strtol(arg, &end, 10); c = buffer[i + 3 + (end - arg)]; debug("ansi private mouse : command %c, arg %d", c, Pm); if (c == 'h') /* DECSET DEC Private Mode Set */ { switch (Pm) { /* FIXME Handle different modes */ case 9: debug("mouse : X10 mode\n"); m_report_mouse = MOUSE_X10; break; case 1000: /* Send Mouse X & Y on button press and release. */ debug("mouse : VT200 mode\n"); m_report_mouse = MOUSE_VT200; break; case 1001: /* Use Hilite Mouse Tracking. */ debug("mouse : VT200_HIGHLIGHT mode\n"); m_report_mouse = MOUSE_VT200_HIGHLIGHT; break; case 1002: /* Use Cell Motion Mouse Tracking. */ debug("mouse : BTN mode\n"); m_report_mouse = MOUSE_BTN_EVENT; break; case 1003: /* Use All Motion Mouse Tracking. */ debug("mouse : ANY mode\n"); m_report_mouse = MOUSE_ANY_EVENT; break; default: break; } } else if (c == 'l') /* DECRST DEC Private Mode Reset */ { Pm = atoi(arg); switch (Pm) { /* FIXME Handle different modes */ case 9: case 1000: /* Send Mouse X & Y on button press and release. */ case 1001: /* Use Hilite Mouse Tracking. */ case 1002: /* Use Cell Motion Mouse Tracking. */ case 1003: /* Use All Motion Mouse Tracking. */ m_report_mouse = MOUSE_NONE; debug("ansi private mouse : NOT reporting mouse"); break; default: break; } } } continue; /* Private sequence, skip it entirely */ } if (final - param > 100) continue; /* Suspiciously long sequence, skip it */ /* Parse parameter bytes as per ECMA-48 5.4.2: Parameter string format */ if (param < inter) { argv[0] = 0; for (j = param; j < inter; j++) { if (buffer[i + j] == ';') argv[++argc] = 0; else if (buffer[i + j] >= '0' && buffer[i + j] <= '9') argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0'); } argc++; } /* Interpret final byte. The code representations are given in ECMA-48 5.4: Control sequences, and the code definitions are given in ECMA-48 8.3: Definition of control functions. */ debug("ansi import: command '%c'", buffer[i + final]); switch (buffer[i + final]) { case 'A': /* CUU (0x41) - Cursor Up */ y -= argc ? argv[0] : 1; if (y < 0) y = 0; break; case 'B': /* CUD (0x42) - Cursor Down */ y += argc ? argv[0] : 1; break; case 'C': /* CUF (0x43) - Cursor Right */ x += argc ? argv[0] : 1; break; case 'D': /* CUB (0x44) - Cursor Left */ x -= argc ? argv[0] : 1; if (x < 0) x = 0; break; case 'G': /* CHA (0x47) - Cursor Character Absolute */ x = (argc && argv[0] > 0) ? argv[0] - 1 : 0; break; case 'H': /* CUP (0x48) - Cursor Position */ x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0; y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0; debug("ansi CUP : Cursor at %dx%d\n", x, y); break; case 'J': /* ED (0x4a) - Erase In Page */ savedattr = caca_get_attr(m_caca, -1, -1); caca_set_attr(m_caca, m_clearattr); if (!argc || argv[0] == 0) { caca_draw_line(m_caca, x, y, width, y, ' '); caca_fill_box(m_caca, 0, y + 1, width, height - 1, ' '); } else if (argv[0] == 1) { caca_fill_box(m_caca, 0, 0, width, y, ' '); caca_draw_line(m_caca, 0, y, x, y, ' '); } else if (argv[0] == 2) { // x = y = 0; caca_fill_box(m_caca, 0, 0, width, height, ' '); } caca_set_attr(m_caca, savedattr); break; case 'K': /* EL (0x4b) - Erase In Line */ debug("ansi EL : cursor at %dx%d\n", x, y); if (!argc || argv[0] == 0) { caca_draw_line(m_caca, x, y, width, y, ' '); } else if (argv[0] == 1) { caca_draw_line(m_caca, 0, y, x, y, ' '); } else if (argv[0] == 2) { caca_draw_line(m_caca, 0, y, width, y, ' '); } break; case 'L': /* IL - Insert line */ { unsigned int nb_lines = argc ? argv[0] : 1; for (j = bottom - 1; j >= (unsigned int)y + nb_lines; j--) { for (k = 0; k < width; k++) { caca_put_char(m_caca, k, j, caca_get_char(m_caca, k, j - nb_lines)); caca_put_attr(m_caca, k, j, caca_get_attr(m_caca, k, j - nb_lines)); } caca_draw_line(m_caca, 0, j - nb_lines, width, j - nb_lines, ' '); } } break; case 'P': /* DCH (0x50) - Delete Character */ if (!argc || argv[0] == 0) argv[0] = 1; /* echo -ne 'foobar\r\e[0P\n' */ for (j = x; (unsigned int)(j + argv[0]) < width; j++) { caca_put_char(m_caca, j, y, caca_get_char(m_caca, j + argv[0], y)); caca_put_attr(m_caca, j, y, caca_get_attr(m_caca, j + argv[0], y)); } break; #if 0 savedattr = caca_get_attr(m_caca, -1, -1); caca_set_attr(m_caca, m_clearattr); for (; (unsigned int)j < width; j++) caca_put_char(m_caca, j, y, ' '); caca_set_attr(m_caca, savedattr); #endif case 'X': /* ECH (0x58) - Erase Character */ if (argc && argv[0]) { savedattr = caca_get_attr(m_caca, -1, -1); caca_set_attr(m_caca, m_clearattr); caca_draw_line(m_caca, x, y, x + argv[0] - 1, y, ' '); caca_set_attr(m_caca, savedattr); } case 'c': /* DA -- Device Attributes */ /* 0 Base VT100, no options 1 Processor options (STP) 2 Advanced video option (AVO) 3 AVO and STP 4 Graphics processor option (GPO) 5 GPO and STP 6 GPO and AVO 7 GPO, STP, and AVO */ /* Warning, argument is Pn */ debug("ansi Got command c, argc %d, argv[0] (%d)\n", argc, argv[0], argv[0]); if (!argc || argv[0] == 0) { SendAnsi("\x1b[?1;0c"); } else { switch (argv[0]) { case 1: SendAnsi("\x1b[?\x1;\x1c"); break; case 2: SendAnsi("\x1b[?\x1;\x2c"); break; case 3: SendAnsi("\x1b[?\x1;\x3c"); break; case 4: SendAnsi("\x1b[?\x1;\x4c"); break; case 5: SendAnsi("\x1b[?\x1;\x5c"); break; case 6: SendAnsi("\x1b[?\x1;\x6c"); break; case 7: SendAnsi("\x1b[?\x1;\x7c"); break; default: debug("Unsupported DA option '%d'\n", argv[0]); break; } } break; case 'd': /* VPA (0x64) - Line Position Absolute */ y = (argc && argv[0] > 0) ? argv[0] - 1 : 0; break; case 'f': /* HVP (0x66) - Character And Line Position */ x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0; y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0; break; case 'g': /* TBC -- Tabulation Clear */ break; case 'r': /* FIXME */ if (argc == 2) /* DCSTBM - Set top and bottom margin */ { debug("DCSTBM %d %d", argv[0], argv[1]); top = argv[0]; bottom = argv[1]; } else debug("ansi import: command r with %d params", argc); break; case 'h': /* SM (0x68) - FIXME */ debug("ansi import: set mode %i", argc ? (int)argv[0] : -1); break; case 'l': /* RM (0x6c) - FIXME */ debug("ansi import: reset mode %i", argc ? (int)argv[0] : -1); break; case 'm': /* SGR (0x6d) - Select Graphic Rendition */ if (argc) ReadGrcm(argc, argv); else ReadGrcm(1, &dummy); break; case 'n': debug("ansi command n, argc %d, argv[0] %d\n", argc, argv[0]); if (!argc) break; switch (argv[0]) { case 5: /* Term ok */ SendAnsi("\x1b[0n"); break; case 6: /* Cursor Position */ sprintf(b, "\x1b[%d;%dR", y + 1, x + 1); SendAnsi(b); break; } break; case 's': /* Private (save cursor position) */ save_x = x; save_y = y; break; case 'u': /* Private (reload cursor position) */ x = save_x; y = save_y; break; default: debug("ansi import: unknown command \"^[%.*s\"", final - param + 1, buffer + i + param); break; } } /* Parse OSC stuff. */ else if (buffer[i] == '\033' && buffer[i + 1] == ']') { char *string; unsigned int command = 0; unsigned int mode = 2, semicolon, final; for (semicolon = mode; i + semicolon < size; semicolon++) { if (buffer[i + semicolon] < '0' || buffer[i + semicolon] > '9') break; command = 10 * command + (buffer[i + semicolon] - '0'); } if (i + semicolon >= size || buffer[i + semicolon] != ';') break; /* Invalid Mode */ for (final = semicolon + 1; i + final < size; final++) if (buffer[i + final] < 0x20) break; if (i + final >= size || buffer[i + final] != '\a') break; /* Not enough data or no bell found */ /* FIXME: XTerm also reacts to and */ /* FIXME: differenciate between not enough data (try again) and invalid data (print shit) */ skip += final; string = (char *)malloc(final - (semicolon + 1) + 1); memcpy(string, buffer + i + (semicolon + 1), final - (semicolon + 1)); string[final - (semicolon + 1)] = '\0'; debug("ansi import: got OSC command %i string '%s'", command, string); if (command == 0 || command == 2) { if (m_title) free(m_title); m_title = string; } else free(string); } /* Get the character we’re going to paste */ else { size_t bytes; if (i + 6 < size) { ch = caca_utf8_to_utf32((char const *)(buffer + i), &bytes); } else { /* Add a trailing zero to what we're going to read */ char tmp[7]; memcpy(tmp, buffer + i, size - i); tmp[size - i] = '\0'; ch = caca_utf8_to_utf32(tmp, &bytes); } if (!bytes) { /* If the Unicode is invalid, assume it was latin1. */ ch = buffer[i]; bytes = 1; } /* very incomplete ISO-2022 implementation tailored to DEC ACS */ if (m_conv_state.cs == '@') { if (((ch > ' ') && (ch <= '~')) && (m_conv_state. gn[m_conv_state.ss ? m_conv_state. gn[m_conv_state.ss] : m_conv_state.glr[0]] == '0')) { ch = dec_acs(ch); } else if (((ch > 0x80) && (ch < 0xff)) && (m_conv_state.gn[m_conv_state.glr[1]] == '0')) { ch = dec_acs(ch + ' ' - 0x80); } } m_conv_state.ss = 0; /* no single-shift (GL) */ wch = caca_utf32_is_fullwidth(ch) ? 2 : 1; skip += bytes - 1; } /* Wrap long lines or grow horizontally */ while ((unsigned int)x + wch > width) { x -= width; y++; } /* Scroll or grow vertically */ if ((unsigned int)y >= bottom) { int lines = (y - bottom) + 1; savedattr = caca_get_attr(m_caca, -1, -1); for (j = top - 1; j + lines < bottom; j++) { for (k = 0; k < width; k++) { caca_put_char(m_caca, k, j, caca_get_char(m_caca, k, j + lines)); caca_put_attr(m_caca, k, j, caca_get_attr(m_caca, k, j + lines)); } } caca_set_attr(m_caca, m_clearattr); caca_fill_box(m_caca, 0, bottom - lines, width, bottom - 1, ' '); y -= lines; caca_set_attr(m_caca, savedattr); } /* Now paste our character, if any */ if (wch) { caca_put_char(m_caca, x, y, ch); x += wch; } } caca_gotoxy(m_caca, x, y); if (i) m_changed = 1; return i; } size_t Term::SendAnsi(char const *str) { size_t ret = strlen(str); /* FIXME TODO: not implemented */ Log::Debug("Sending %d-character ANSI sequence\n", (int)ret); return ret; } /* Coding Method Delimiter (CMD), ECMA-48 (1991), ISO/IEC 6429:1992 (ISO IR 189) */ void Iso2022Conversion::Reset() { cs = '@'; /* ISO-2022 coding system */ cn[0] = '@'; /* ISO 646 C0 control charset */ cn[1] = 'C'; /* ISO 6429-1983 C1 control charset */ glr[0] = 0; /* G0 in GL */ glr[1] = 2; /* G2 in GR */ gn[0] = 'B'; /* US-ASCII G0 charset */ gn[1] = '0'; /* DEC ACS G1 charset */ gn[2] = LITERAL2CHAR('.', 'A'); /* ISO 8859-1 G2 charset */ gn[3] = LITERAL2CHAR('.', 'A'); /* ISO 8859-1 G3 charset */ ss = 0; /* no single-shift (GL) */ ctrl8bit = 1; } /* XXX : ANSI loader helper */ void Term::ReadGrcm(unsigned int argc, unsigned int const *argv) { static uint8_t const ansi2caca[] = { CACA_BLACK, CACA_RED, CACA_GREEN, CACA_BROWN, CACA_BLUE, CACA_MAGENTA, CACA_CYAN, CACA_LIGHTGRAY }; unsigned int j; uint8_t efg, ebg; /* Effective (libcaca) fg/bg */ for (j = 0; j < argc; j++) { /* Defined in ECMA-48 8.3.117: SGR - SELECT GRAPHIC RENDITION */ if (argv[j] >= 30 && argv[j] <= 37) m_fg = ansi2caca[argv[j] - 30]; else if (argv[j] >= 40 && argv[j] <= 47) m_bg = ansi2caca[argv[j] - 40]; else if (argv[j] >= 90 && argv[j] <= 97) m_fg = ansi2caca[argv[j] - 90] + 8; else if (argv[j] >= 100 && argv[j] <= 107) m_bg = ansi2caca[argv[j] - 100] + 8; else switch (argv[j]) { case 0: /* default rendition */ m_fg = m_dfg; m_bg = m_dbg; m_bold = m_blink = m_italics = m_negative = m_concealed = m_underline = m_faint = m_strike = m_proportional = 0; break; case 1: /* bold or increased intensity */ m_bold = 1; break; case 2: /* faint, decreased intensity or second colour */ m_faint = 1; break; case 3: /* italicized */ m_italics = 1; break; case 4: /* singly underlined */ m_underline = 1; break; case 5: /* slowly blinking (less then 150 per minute) */ case 6: /* rapidly blinking (150 per minute or more) */ m_blink = 1; break; case 7: /* negative image */ m_negative = 1; break; case 8: /* concealed characters */ m_concealed = 1; break; case 9: /* crossed-out (characters still legible but marked as to be deleted */ m_strike = 1; break; case 21: /* doubly underlined */ m_underline = 1; break; case 22: /* normal colour or normal intensity (neither bold nor faint) */ m_bold = m_faint = 0; break; case 23: /* not italicized, not fraktur */ m_italics = 0; break; case 24: /* not underlined (neither singly nor doubly) */ m_underline = 0; break; case 25: /* steady (not blinking) */ m_blink = 0; break; case 26: /* (reserved for proportional spacing as specified in CCITT Recommendation T.61) */ m_proportional = 1; break; case 27: /* positive image */ m_negative = 0; break; case 28: /* revealed characters */ m_concealed = 0; break; case 29: /* not crossed out */ m_strike = 0; break; case 38: /* (reserved for future standardization, intended for setting character foreground colour as specified in ISO 8613-6 [CCITT Recommendation T.416]) */ break; case 39: /* default display colour (implementation-defined) */ m_fg = m_dfg; break; case 48: /* (reserved for future standardization, intended for setting character background colour as specified in ISO 8613-6 [CCITT Recommendation T.416]) */ break; case 49: /* default background colour (implementation-defined) */ m_bg = m_dbg; break; case 50: /* (reserved for cancelling the effect of the rendering aspect established by parameter value 26) */ m_proportional = 0; break; default: debug("ansi import: unknown sgr %i", argv[j]); break; } } if (m_concealed) { efg = ebg = CACA_TRANSPARENT; } else { efg = m_negative ? m_bg : m_fg; ebg = m_negative ? m_fg : m_bg; if (m_bold) { if (efg < 8) efg += 8; else if (efg == CACA_DEFAULT) efg = CACA_WHITE; } } caca_set_color_ansi(m_caca, efg, ebg); } \ No newline at end of file diff --git a/neercs/term/pty.cpp b/neercs/term/pty.cpp index 3219295..8a6770f 100644 --- a/neercs/term/pty.cpp +++ b/neercs/term/pty.cpp @@ -1,242 +1 @@ -/* - * neercs console-based window manager - * Copyright (c) 2006-2013 Sam Hocevar - * All Rights Reserved - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://www.wtfpl.net/ for more details. - */ - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#if defined HAVE_FORKPTY -# define _XOPEN_SOURCE -# include -# include -# include -# include -# include -# include -# if defined HAVE_PTY_H -# include /* for openpty and forkpty */ -# elif defined HAVE_UTIL_H -# include /* for OS X, OpenBSD and NetBSD */ -# elif defined HAVE_LIBUTIL_H -# include /* for FreeBSD */ -# endif -# include -# include -#endif - -#include "core.h" -#include "loldebug.h" - -using namespace std; -using namespace lol; - -#include "../neercs.h" - -Pty::Pty() - : m_fd(-1), - m_pid(-1), - m_eof(false), - m_unread_data(0), - m_unread_len(0), - m_size(-1, -1) -{ - ; -} - -Pty::~Pty() -{ -#if defined HAVE_FORKPTY - delete[] m_unread_data; - - if (m_fd >= 0) - { - close((int)m_fd); - } -#endif -} - -void Pty::Run(char const *command, ivec2 size) -{ -#if defined HAVE_FORKPTY - int fd; - pid_t pid; - - m_pid = -1; - m_fd = -1; - - pid = forkpty(&fd, NULL, NULL, NULL); - if (pid < 0) - { - fprintf(stderr, "forkpty() error\n"); - return; - } - else if (pid == 0) - { - SetWindowSize(size, 0); - - /* putenv() eats the string, they need to be writable */ - static char tmp1[] = "CACA_DRIVER=slang"; - static char tmp2[] = "TERM=xterm"; - putenv(tmp1); - putenv(tmp2); - - m_argv[0] = command; - m_argv[1] = NULL; - /* The following const cast is valid. The Open Group Base - * Specification guarantees that the objects are completely - * constant. */ - execvp(command, const_cast(m_argv)); - fprintf(stderr, "execvp() error\n"); - return; - } - - fcntl(fd, F_SETFL, O_NDELAY); - - m_pid = pid; - m_fd = fd; -#endif -} - -bool Pty::IsEof() const -{ - return m_eof; -} - -/* Read data from the PTY. We only perform one read() call so that the - * caller can decide whether to ask for more data or not. This lets us - * prioritise data in some way. */ -size_t Pty::ReadData(char *data, size_t maxlen) -{ -#if defined HAVE_FORKPTY - size_t sent = 0; - - /* Do we have data from previous call? */ - if (m_unread_len) - { - size_t tocopy = min(maxlen, m_unread_len); - - memcpy(data, m_unread_data, tocopy); - - data += tocopy; - sent += tocopy; - maxlen -= tocopy; - - if (tocopy < m_unread_len) - { - m_unread_len -= tocopy; - memmove(m_unread_data, m_unread_data + tocopy, m_unread_len); - } - else - { - delete[] m_unread_data; - m_unread_data = 0; - m_unread_len = 0; - } - } - - fd_set fdset; - int maxfd = -1; - - FD_ZERO(&fdset); - if (m_fd >= 0) - { - FD_SET((int)m_fd, &fdset); - maxfd = std::max(maxfd, (int)m_fd); - } - - if (maxfd >= 0) - { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 50000; - int ret = select(maxfd + 1, &fdset, NULL, NULL, &tv); - - if (ret < 0) - { - Log::Error("cannot read from PTY\n"); - m_eof = true; - return 0; - } - else if (ret) - { - if (FD_ISSET((int)m_fd, &fdset)) - { - ssize_t nr = read((int)m_fd, data, maxlen); - - /* Data available but zero-length read: EOF */ - if (nr <= 0) - m_eof = true; - else - sent += nr; - - if (sent >= 0) - return sent; - } - } - } -#endif - - return 0; -} - -void Pty::UnreadData(char *data, size_t len) -{ -#if defined HAVE_FORKPTY - /* Prepare unread buffer */ - if (m_unread_data) - { - char *tmp = new char[m_unread_len + len]; - memcpy(tmp + len, m_unread_data, m_unread_len); - delete[] m_unread_data; - m_unread_data = tmp; - m_unread_len += len; - } - else - { - m_unread_data = new char[len]; - m_unread_len = len; - } - - /* Copy data to the unread buffer */ - memcpy(m_unread_data, data, len); -#endif -} - -size_t Pty::WriteData(char const *data, size_t len) -{ -#if defined HAVE_FORKPTY - /* FIXME: can we be more naive than that? */ - return write((int)m_fd, data, len); -#endif - - return 0; -} - -void Pty::SetWindowSize(ivec2 size, int64_t fd /* = -1 */) -{ -#if defined HAVE_FORKPTY - if (m_size == size) - return; - - if (fd < 0) - fd = m_fd; - - m_size = size; - - struct winsize ws; - - memset(&ws, 0, sizeof(ws)); - ws.ws_row = size.y; - ws.ws_col = size.x; - ioctl((int)fd, TIOCSWINSZ, (char *)&ws); -#endif -} +/* * neercs console-based window manager * Copyright (c) 2006-2013 Sam Hocevar * All Rights Reserved * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #if defined HAVE_FORKPTY # define _XOPEN_SOURCE # include # include # include # include # include # include # if defined HAVE_PTY_H # include /* for openpty and forkpty */ # elif defined HAVE_UTIL_H # include /* for OS X, OpenBSD and NetBSD */ # elif defined HAVE_LIBUTIL_H # include /* for FreeBSD */ # endif # include # include #endif #include "core.h" #include "loldebug.h" using namespace std; using namespace lol; #include "../neercs.h" Pty::Pty() : m_fd(-1), m_pid(-1), m_eof(false), m_unread_data(0), m_unread_len(0), m_size(-1, -1) { ; } Pty::~Pty() { #if defined HAVE_FORKPTY delete[] m_unread_data; if (m_fd >= 0) { close((int)m_fd); } #endif } void Pty::Run(char const *command, ivec2 size) { #if defined HAVE_FORKPTY int fd; pid_t pid; m_pid = -1; m_fd = -1; pid = forkpty(&fd, NULL, NULL, NULL); if (pid < 0) { fprintf(stderr, "forkpty() error\n"); return; } else if (pid == 0) { SetWindowSize(size, 0); /* putenv() eats the string, they need to be writable */ static char tmp1[] = "CACA_DRIVER=slang"; static char tmp2[] = "TERM=xterm"; putenv(tmp1); putenv(tmp2); m_argv[0] = command; m_argv[1] = NULL; /* The following const cast is valid. The Open Group Base * Specification guarantees that the objects are completely * constant. */ execvp(command, const_cast(m_argv)); fprintf(stderr, "execvp() error\n"); return; } fcntl(fd, F_SETFL, O_NDELAY); m_pid = pid; m_fd = fd; #endif } bool Pty::IsEof() const { return m_eof; } /* Read data from the PTY. We only perform one read() call so that the * caller can decide whether to ask for more data or not. This lets us * prioritise data in some way. */ size_t Pty::ReadData(char *data, size_t maxlen) { #if defined HAVE_FORKPTY size_t sent = 0; /* Do we have data from previous call? */ if (m_unread_len) { size_t tocopy = min(maxlen, m_unread_len); memcpy(data, m_unread_data, tocopy); data += tocopy; sent += tocopy; maxlen -= tocopy; if (tocopy < m_unread_len) { m_unread_len -= tocopy; memmove(m_unread_data, m_unread_data + tocopy, m_unread_len); } else { delete[] m_unread_data; m_unread_data = 0; m_unread_len = 0; } } fd_set fdset; int maxfd = -1; FD_ZERO(&fdset); if (m_fd >= 0) { FD_SET((int)m_fd, &fdset); maxfd = std::max(maxfd, (int)m_fd); } if (maxfd >= 0) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 50000; int ret = select(maxfd + 1, &fdset, NULL, NULL, &tv); if (ret < 0) { Log::Error("cannot read from PTY\n"); m_eof = true; return 0; } else if (ret) { if (FD_ISSET((int)m_fd, &fdset)) { ssize_t nr = read((int)m_fd, data, maxlen); /* Data available but zero-length read: EOF */ if (nr <= 0) m_eof = true; else sent += nr; if (sent >= 0) return sent; } } } #endif return 0; } void Pty::UnreadData(char *data, size_t len) { #if defined HAVE_FORKPTY /* Prepare unread buffer */ if (m_unread_data) { char *tmp = new char[m_unread_len + len]; memcpy(tmp + len, m_unread_data, m_unread_len); delete[] m_unread_data; m_unread_data = tmp; m_unread_len += len; } else { m_unread_data = new char[len]; m_unread_len = len; } /* Copy data to the unread buffer */ memcpy(m_unread_data, data, len); #endif } size_t Pty::WriteData(char const *data, size_t len) { #if defined HAVE_FORKPTY /* FIXME: can we be more naive than that? */ return write((int)m_fd, data, len); #endif return 0; } void Pty::SetWindowSize(ivec2 size, int64_t fd /* = -1 */) { #if defined HAVE_FORKPTY if (m_size == size) return; if (fd < 0) fd = m_fd; m_size = size; struct winsize ws; memset(&ws, 0, sizeof(ws)); ws.ws_row = size.y; ws.ws_col = size.x; ioctl((int)fd, TIOCSWINSZ, (char *)&ws); #endif } \ No newline at end of file diff --git a/neercs/term/pty.h b/neercs/term/pty.h index 02fc78b..73e325d 100644 --- a/neercs/term/pty.h +++ b/neercs/term/pty.h @@ -1,34 +1 @@ -// -// Neercs -// - -#if !defined __TERM_PTY_H__ -#define __TERM_PTY_H__ - -class Pty -{ -public: - Pty(); - ~Pty(); - - void Run(char const *command, ivec2 size); - bool IsEof() const; - - size_t ReadData(char *data, size_t maxlen); - void UnreadData(char *data, size_t len); - size_t WriteData(char const *data, size_t len); - - void SetWindowSize(ivec2 size, int64_t fd = -1); - -private: - int64_t m_fd; - int64_t m_pid; - bool m_eof; - char const *m_argv[2]; - char *m_unread_data; - size_t m_unread_len; - ivec2 m_size; -}; - -#endif // __TERM_PTY_H__ - +// // Neercs // #if !defined __TERM_PTY_H__ #define __TERM_PTY_H__ class Pty { public: Pty(); ~Pty(); void Run(char const *command, ivec2 size); bool IsEof() const; size_t ReadData(char *data, size_t maxlen); void UnreadData(char *data, size_t len); size_t WriteData(char const *data, size_t len); void SetWindowSize(ivec2 size, int64_t fd = -1); private: int64_t m_fd; int64_t m_pid; bool m_eof; char const *m_argv[2]; char *m_unread_data; size_t m_unread_len; ivec2 m_size; }; #endif // __TERM_PTY_H__ \ No newline at end of file diff --git a/neercs/term/term.cpp b/neercs/term/term.cpp index c02765c..91dcd2b 100644 --- a/neercs/term/term.cpp +++ b/neercs/term/term.cpp @@ -1,262 +1 @@ -// -// Neercs -// - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include "core.h" - -using namespace std; -using namespace lol; - -#include "../neercs.h" -#include "term.h" - -extern bool g_setup; - -Term::Term(ivec2 size) - : m_pty(0), - m_caca(caca_create_canvas(size.x, size.y)), - m_size(size), - m_title(0), - m_bell(0), - m_init(0), - m_report_mouse(0), - m_changed(0), - m_time(0.f), - m_debug(false) -{ -#if defined HAVE_PTY_H || defined HAVE_UTIL_H || defined HAVE_LIBUTIL_H - m_pty = new Pty(); - char const *shell = getenv("SHELL"); - if (!shell) - shell = "/bin/sh"; - m_pty->Run(shell, size); -#endif -} - -void Term::TickGame(float seconds) -{ - Entity::TickGame(seconds); - -#if defined HAVE_PTY_H || defined HAVE_UTIL_H || defined HAVE_LIBUTIL_H - if (!g_setup) - { - bool have_ctrl = Input::GetStatus(Key::LeftCtrl) - || Input::GetStatus(Key::RightCtrl); - bool have_shift = Input::GetStatus(Key::LeftShift) - || Input::GetStatus(Key::RightShift); - - /* Check for standard ASCII keys */ - for (int i = 0x0; i < 0x7f; ++i) - { - if (Input::WasPressed((Key::Value)i)) - { - if (have_ctrl && i >= 'a' && i <= 'z') - { - char c = i + 1 - 'a'; - m_pty->WriteData(&c, 1); - } - else if (have_shift && i >= 'a' && i <= 'z') - { - char c = i + 'A' - 'a'; - m_pty->WriteData(&c, 1); - } - else - { - char c = i; - m_pty->WriteData(&c, 1); - } - } - } - - /* Check for special keys */ - static struct { Key::Value k; char const *str; int len; } const lut[] = - { - { Key::Up, "\033OA", 3 }, - { Key::Down, "\033OB", 3 }, - { Key::Right, "\033OC", 3 }, - { Key::Left, "\033OD", 3 }, - { Key::PageUp, "\033[5~", 4 }, - { Key::PageDown, "\033[6~", 4 }, - { Key::Home, "\033[1~", 4 }, - { Key::Insert, "\033[2~", 4 }, - { Key::Delete, "\033[3~", 4 }, - { Key::End, "\033[4~", 4 }, -#if 0 /* FIXME: disabled for now (used by the theme system */ - { Key::F1, "\033[11~", 5 }, - { Key::F2, "\033[12~", 5 }, - { Key::F3, "\033[13~", 5 }, - { Key::F4, "\033[14~", 5 }, - { Key::F5, "\033[15~", 5 }, - { Key::F6, "\033[17~", 5 }, - { Key::F7, "\033[18~", 5 }, - { Key::F8, "\033[19~", 5 }, - { Key::F9, "\033[20~", 5 }, - { Key::F10, "\033[21~", 5 }, - { Key::F11, "\033[23~", 5 }, - { Key::F12, "\033[24~", 5 }, -#endif - }; - - for (size_t i = 0; i < sizeof(lut) / sizeof(*lut); i++) - { - if (!have_ctrl && !have_shift) - if (Input::WasPressed(lut[i].k)) - m_pty->WriteData(lut[i].str, lut[i].len); - } - } - - m_time += seconds; - - if (m_pty->IsEof()) - { - /* FIXME: we could do more interesting things here… */ - Ticker::Shutdown(); - } - - m_pty->SetWindowSize(ivec2(caca_get_canvas_width(m_caca), - caca_get_canvas_height(m_caca))); - - /* This is the real terminal code */ - size_t total = 0; - for (;;) - { - char buf[BUFSIZ]; - size_t current = m_pty->ReadData(buf, BUFSIZ); - if (current <= 0) - break; - /* FIXME: by the time we're finished decoding the ANSI data, some - * new data may be available. We need to avoid reading it because - * it's time rendering the canvas isntead. */ - size_t processed = ReadAnsi(buf, current); - if (processed < current) - m_pty->UnreadData(buf + processed, current - processed); - total += processed; - if (processed == 0) - break; - - /* FIXME: when do we know when to stop? If we read too much - * data, some of our frames will not be rendered because they'll - * be overwritten by new data. If we don't read enough, we will - * start rendering even if a frame isn't finished. */ - if (total > 12000) - break; - } - - /* Some fancy shit if we press F3 */ - if (Input::WasPressed(Key::F3)) - m_debug = !m_debug; - - if (m_debug) - { - DrawFancyShit(); - } -#else - /* Unsupported platform - draw some fancy shit instead */ - m_time += seconds; - DrawFancyShit(); -#endif -} - -void Term::TickDraw(float seconds) -{ - Entity::TickDraw(seconds); -} - -Term::~Term() -{ -#if defined HAVE_PTY_H || defined HAVE_UTIL_H || defined HAVE_LIBUTIL_H - delete m_pty; -#endif - caca_free_canvas(m_caca); -} - -/* - * XXX: fancy shit below - */ - -static uint32_t hex_color(float r, float g, float b) -{ - return ((uint32_t)(r * 15.99f) << 8) | - ((uint32_t)(g * 15.99f) << 4) | - (uint32_t)(b * 15.99f); -} - -void Term::DrawFancyShit() -{ - /* draw something awesome */ - int bg_color = 0x000; - int w = caca_get_canvas_width(m_caca); - int h = caca_get_canvas_height(m_caca); - - caca_set_color_argb(m_caca, 0xfff, bg_color); - caca_clear_canvas(m_caca); - - caca_set_color_argb(m_caca, 0x0f0, bg_color); - for(int i = 0; i < h; i++) - { - float a = F_PI / 180 * i * 16 + m_time * 4; - float b = F_PI / 180 * i * 12; - int x = w / 2 - 14 + w / 4 * lol::cos(a) + w / 4 * lol::sin(b); - caca_put_str(m_caca, x, i, "LOL WUT! NEERCS SI TEH RULEZ"); - } - - caca_set_color_argb(m_caca, 0x444, bg_color); - for(int i = 0; i < w; i++) - { - float a = m_time * 1 + F_PI / 180 * i * 8; - float b = m_time * -2 + F_PI / 180 * i * 5; - int y = h / 2 + h / 4 * lol::cos(a) + h / 4 * lol::sin(b); - caca_set_color_argb(m_caca, hex_color(0.25f + 0.5f / w * i - 0.25f / h * y, 0.25f, 0.25f + 0.25f / w * i + 0.25f / h * y), bg_color); - caca_draw_line(m_caca, i, y - 1, i, y + 1,'%'); - } - -/* __ _________ ______ ______ ______ ______ - / \/ / __ > __ > __ > ___// ___/ \x0a9 - / / ____/ ____/ __ < <____\___ \ -/__/\__/\_______________/ \________________\ */ - - int logo_x = (w - 46) / 2; - int logo_y = h / 2 - 2; - - caca_set_color_argb(m_caca, 0xbac, bg_color); - caca_put_str(m_caca, logo_x + 3, logo_y ,"__ _________ ______ ______ ______ ______"); - caca_put_str(m_caca, logo_x + 2, logo_y + 1, "/ \\/ / __ > __ > __ > ___// ___/ \x0a9"); - caca_put_str(m_caca, logo_x + 1, logo_y + 2, "/ / ____/ ____/ __ < <____\\___ \\"); - caca_put_str(m_caca, logo_x , logo_y + 3, "/__/\\__/\\_______________/ \\________________\\"); - caca_set_color_argb(m_caca, 0x269, bg_color); - caca_put_str(m_caca, logo_x + 5, logo_y + 5, "ALL YOUR TERMINALS ARE BELONG TO US"); - - caca_set_color_argb(m_caca, 0x777, bg_color); - caca_printf(m_caca, 2, h - 3, "W=%i", w); - caca_printf(m_caca, 2, h - 2, "H=%i", h); - - caca_set_color_argb(m_caca, hex_color(0.6f + 0.4f * lol::cos(m_time * 2), 0.2f, 0.2f), bg_color); - caca_put_str(m_caca, w - 12, h - 2, "CACA RULEZ"); - -/*_______ - / /| -/______/ | -| | | -| :D | / -|______|/ -*/ -/* - int lolcube_x = w - 12; - int lolcube_y = h - 8; - - caca_set_color_argb(m_caca, 0x777, bg_color); - caca_put_str(m_caca, lolcube_x + 2, lolcube_y , "_______"); - caca_put_str(m_caca, lolcube_x + 1, lolcube_y + 1, "/ /|"); - caca_put_str(m_caca, lolcube_x , lolcube_y + 2, "/______/ |"); - caca_put_str(m_caca, lolcube_x , lolcube_y + 3, "| | |"); - caca_put_str(m_caca, lolcube_x , lolcube_y + 4, "| :D | /"); - caca_put_str(m_caca, lolcube_x , lolcube_y + 5, "|______|/"); -*/ - - caca_set_color_argb(m_caca, 0x777, bg_color); - caca_put_str(m_caca, 0, 0, "rez@lol:~/code/neercs/"); -} +// // Neercs // #if defined HAVE_CONFIG_H # include "config.h" #endif #include "core.h" using namespace std; using namespace lol; #include "../neercs.h" #include "term.h" extern bool g_setup; Term::Term(ivec2 size) : m_pty(0), m_caca(caca_create_canvas(size.x, size.y)), m_size(size), m_title(0), m_bell(0), m_init(0), m_report_mouse(0), m_changed(0), m_time(0.f), m_debug(false) { #if defined HAVE_PTY_H || defined HAVE_UTIL_H || defined HAVE_LIBUTIL_H m_pty = new Pty(); char const *shell = getenv("SHELL"); if (!shell) shell = "/bin/sh"; m_pty->Run(shell, size); #endif } void Term::TickGame(float seconds) { Entity::TickGame(seconds); #if defined HAVE_PTY_H || defined HAVE_UTIL_H || defined HAVE_LIBUTIL_H if (!g_setup) { bool have_ctrl = Input::GetStatus(Key::LeftCtrl) || Input::GetStatus(Key::RightCtrl); bool have_shift = Input::GetStatus(Key::LeftShift) || Input::GetStatus(Key::RightShift); /* Check for standard ASCII keys */ for (int i = 0x0; i < 0x7f; ++i) { if (Input::WasPressed((Key::Value)i)) { if (have_ctrl && i >= 'a' && i <= 'z') { char c = i + 1 - 'a'; m_pty->WriteData(&c, 1); } else if (have_shift && i >= 'a' && i <= 'z') { char c = i + 'A' - 'a'; m_pty->WriteData(&c, 1); } else { char c = i; m_pty->WriteData(&c, 1); } } } /* Check for special keys */ static struct { Key::Value k; char const *str; int len; } const lut[] = { { Key::Up, "\033OA", 3 }, { Key::Down, "\033OB", 3 }, { Key::Right, "\033OC", 3 }, { Key::Left, "\033OD", 3 }, { Key::PageUp, "\033[5~", 4 }, { Key::PageDown, "\033[6~", 4 }, { Key::Home, "\033[1~", 4 }, { Key::Insert, "\033[2~", 4 }, { Key::Delete, "\033[3~", 4 }, { Key::End, "\033[4~", 4 }, #if 0 /* FIXME: disabled for now (used by the theme system */ { Key::F1, "\033[11~", 5 }, { Key::F2, "\033[12~", 5 }, { Key::F3, "\033[13~", 5 }, { Key::F4, "\033[14~", 5 }, { Key::F5, "\033[15~", 5 }, { Key::F6, "\033[17~", 5 }, { Key::F7, "\033[18~", 5 }, { Key::F8, "\033[19~", 5 }, { Key::F9, "\033[20~", 5 }, { Key::F10, "\033[21~", 5 }, { Key::F11, "\033[23~", 5 }, { Key::F12, "\033[24~", 5 }, #endif }; for (size_t i = 0; i < sizeof(lut) / sizeof(*lut); i++) { if (!have_ctrl && !have_shift) if (Input::WasPressed(lut[i].k)) m_pty->WriteData(lut[i].str, lut[i].len); } } m_time += seconds; if (m_pty->IsEof()) { /* FIXME: we could do more interesting things here… */ Ticker::Shutdown(); } m_pty->SetWindowSize(ivec2(caca_get_canvas_width(m_caca), caca_get_canvas_height(m_caca))); /* This is the real terminal code */ size_t total = 0; for (;;) { char buf[BUFSIZ]; size_t current = m_pty->ReadData(buf, BUFSIZ); if (current <= 0) break; /* FIXME: by the time we're finished decoding the ANSI data, some * new data may be available. We need to avoid reading it because * it's time rendering the canvas isntead. */ size_t processed = ReadAnsi(buf, current); if (processed < current) m_pty->UnreadData(buf + processed, current - processed); total += processed; if (processed == 0) break; /* FIXME: when do we know when to stop? If we read too much * data, some of our frames will not be rendered because they'll * be overwritten by new data. If we don't read enough, we will * start rendering even if a frame isn't finished. */ if (total > 12000) break; } /* Some fancy shit if we press F3 */ if (Input::WasPressed(Key::F3)) m_debug = !m_debug; if (m_debug) { DrawFancyShit(); } #else /* Unsupported platform - draw some fancy shit instead */ m_time += seconds; DrawFancyShit(); #endif } void Term::TickDraw(float seconds) { Entity::TickDraw(seconds); } Term::~Term() { #if defined HAVE_PTY_H || defined HAVE_UTIL_H || defined HAVE_LIBUTIL_H delete m_pty; #endif caca_free_canvas(m_caca); } /* * XXX: fancy shit below */ static uint32_t hex_color(float r, float g, float b) { return ((uint32_t)(r * 15.99f) << 8) | ((uint32_t)(g * 15.99f) << 4) | (uint32_t)(b * 15.99f); } void Term::DrawFancyShit() { /* draw something awesome */ int bg_color = 0x000; int w = caca_get_canvas_width(m_caca); int h = caca_get_canvas_height(m_caca); caca_set_color_argb(m_caca, 0xfff, bg_color); caca_clear_canvas(m_caca); caca_set_color_argb(m_caca, 0x0f0, bg_color); for(int i = 0; i < h; i++) { float a = F_PI / 180 * i * 16 + m_time * 4; float b = F_PI / 180 * i * 12; int x = w / 2 - 14 + w / 4 * lol::cos(a) + w / 4 * lol::sin(b); caca_put_str(m_caca, x, i, "LOL WUT! NEERCS SI TEH RULEZ"); } caca_set_color_argb(m_caca, 0x444, bg_color); for(int i = 0; i < w; i++) { float a = m_time * 1 + F_PI / 180 * i * 8; float b = m_time * -2 + F_PI / 180 * i * 5; int y = h / 2 + h / 4 * lol::cos(a) + h / 4 * lol::sin(b); caca_set_color_argb(m_caca, hex_color(0.25f + 0.5f / w * i - 0.25f / h * y, 0.25f, 0.25f + 0.25f / w * i + 0.25f / h * y), bg_color); caca_draw_line(m_caca, i, y - 1, i, y + 1,'%'); } /* __ _________ ______ ______ ______ ______ / \/ / __ > __ > __ > ___// ___/ \x0a9 / / ____/ ____/ __ < <____\___ \ /__/\__/\_______________/ \________________\ */ int logo_x = (w - 46) / 2; int logo_y = h / 2 - 2; caca_set_color_argb(m_caca, 0xbac, bg_color); caca_put_str(m_caca, logo_x + 3, logo_y ,"__ _________ ______ ______ ______ ______"); caca_put_str(m_caca, logo_x + 2, logo_y + 1, "/ \\/ / __ > __ > __ > ___// ___/ \x0a9"); caca_put_str(m_caca, logo_x + 1, logo_y + 2, "/ / ____/ ____/ __ < <____\\___ \\"); caca_put_str(m_caca, logo_x , logo_y + 3, "/__/\\__/\\_______________/ \\________________\\"); caca_set_color_argb(m_caca, 0x269, bg_color); caca_put_str(m_caca, logo_x + 5, logo_y + 5, "ALL YOUR TERMINALS ARE BELONG TO US"); caca_set_color_argb(m_caca, 0x777, bg_color); caca_printf(m_caca, 2, h - 3, "W=%i", w); caca_printf(m_caca, 2, h - 2, "H=%i", h); caca_set_color_argb(m_caca, hex_color(0.6f + 0.4f * lol::cos(m_time * 2), 0.2f, 0.2f), bg_color); caca_put_str(m_caca, w - 12, h - 2, "CACA RULEZ"); /*_______ / /| /______/ | | | | | :D | / |______|/ */ /* int lolcube_x = w - 12; int lolcube_y = h - 8; caca_set_color_argb(m_caca, 0x777, bg_color); caca_put_str(m_caca, lolcube_x + 2, lolcube_y , "_______"); caca_put_str(m_caca, lolcube_x + 1, lolcube_y + 1, "/ /|"); caca_put_str(m_caca, lolcube_x , lolcube_y + 2, "/______/ |"); caca_put_str(m_caca, lolcube_x , lolcube_y + 3, "| | |"); caca_put_str(m_caca, lolcube_x , lolcube_y + 4, "| :D | /"); caca_put_str(m_caca, lolcube_x , lolcube_y + 5, "|______|/"); */ caca_set_color_argb(m_caca, 0x777, bg_color); caca_put_str(m_caca, 0, 0, "rez@lol:~/code/neercs/"); } \ No newline at end of file diff --git a/neercs/term/term.h b/neercs/term/term.h index 0baa460..702de31 100644 --- a/neercs/term/term.h +++ b/neercs/term/term.h @@ -1,133 +1 @@ -// -// Neercs -// - -#if !defined __TERM_TERM_H__ -#define __TERM_TERM_H__ - -#include "term/pty.h" - -struct Iso2022Conversion -{ - Iso2022Conversion() { Reset(); } - void Reset(); - - /* cs = coding system/coding method: */ - /* (with standard return) */ - /* '@' = ISO-2022, */ - /* 'G' = UTF-8 without implementation level, */ - /* '8' = UTF-8 (Linux console and imitators), */ - /* and many others that are rarely used; */ - /* (without standard return) */ - /* '/G' = UTF-8 Level 1, */ - /* '/H' = UTF-8 Level 2, */ - /* '/I' = UTF-8 Level 3, */ - /* and many others that are rarely used */ - uint32_t cs; - /* ctrl8bit = allow 8-bit controls */ - uint8_t ctrl8bit; - /* cn[0] = C0 control charset (0x00 ... 0x1f): - * '@' = ISO 646, - * '~' = empty, - * and many others that are rarely used */ - /* cn[1] = C1 control charset (0x80 ... 0x9f): - * 'C' = ISO 6429-1983, - * '~' = empty, - * and many others that are rarely used */ - uint32_t cn[2]; - /* glr[0] = GL graphic charset (94-char. 0x21 ... 0x7e, - * 94x94-char. 0x21/0x21 ... 0x7e/0x7e), - * and - * glr[1] = GR graphic charset (94-char. 0xa1 ... 0xfe, - * 96-char. 0xa0 ... 0xff, - * 94x94-char. 0xa1/0xa1 ... 0xfe/0xfe, - * 96x96-char. 0xa0/0xa0 ... 0xff/0xff): - * 0 = G0, 1 = G1, 2 = G2, 3 = G3 */ - uint8_t glr[2]; - /* gn[i] = G0/G1/G2/G3 graphic charset state: - * (94-char. sets) - * '0' = DEC ACS (VT100 and imitators), - * 'B' = US-ASCII, - * and many others that are rarely used for e.g. various national ASCII variations; - * (96-char. sets) - * '.A' = ISO 8859-1 "Latin 1" GR, - * '.~' = empty 96-char. set, - * and many others that are rarely used for e.g. ISO 8859-n GR; - * (double-byte 94x94-charsets) - * '$@' = Japanese Character Set ("old JIS") (JIS C 6226:1978), - * '$A' = Chinese Character Set (GB 2312), - * '$B' = Japanese Character Set (JIS X0208/JIS C 6226:1983), - * '$C' = Korean Graphic Character Set (KSC 5601:1987), - * '$D' = Supplementary Japanese Graphic Character Set (JIS X0212), - * '$E' = CCITT Chinese Set (GB 2312 + GB 8565), - * '$G' = CNS 11643 plane 1, - * '$H' = CNS 11643 plane 2, - * '$I' = CNS 11643 plane 3, - * '$J' = CNS 11643 plane 4, - * '$K' = CNS 11643 plane 5, - * '$L' = CNS 11643 plane 6, - * '$M' = CNS 11643 plane 7, - * '$O' = JIS X 0213 plane 1, - * '$P' = JIS X 0213 plane 2, - * '$Q' = JIS X 0213-2004 Plane 1, - * and many others that are rarely used for e.g. traditional - * ideographic Vietnamese and BlissSymbolics; - * (double-byte 96x96-charsets) - * none standardized or in use on terminals AFAIK (Mule does use - * some internally) - */ - uint32_t gn[4]; - /* ss = single-shift state: 0 = GL, 2 = G2, 3 = G3 */ - uint8_t ss; -}; - -class Term : public Entity -{ -public: - Term(ivec2 size); - ~Term(); - - char const *GetName() { return ""; } - caca_canvas_t *GetCaca() { return m_caca; } - -protected: - virtual void TickGame(float seconds); - virtual void TickDraw(float seconds); - -private: - /* Terminal emulation main entry point */ - size_t ReadAnsi(void const *data, size_t size); - size_t SendAnsi(char const *str); - - /* Utility functions for terminal emulation */ - void ReadGrcm(unsigned int argc, unsigned int const *argv); - inline int ReadChar(unsigned char c, int *x, int *y); - inline int ReadDuplet(unsigned char const *buffer, unsigned int *skip, - int top, int bottom, int width, int height); - -private: - Pty *m_pty; - caca_canvas_t *m_caca; - ivec2 m_size; - - /* Terminal attributes */ - char *m_title; - - int m_bell, m_init, m_report_mouse; - int m_changed; /* content was updated */ - Iso2022Conversion m_conv_state; /* charset mess */ - - uint8_t m_fg, m_bg; /* ANSI-context fg/bg */ - uint8_t m_dfg, m_dbg; /* Default fg/bg */ - uint8_t m_bold, m_blink, m_italics, m_negative, m_concealed, m_underline; - uint8_t m_faint, m_strike, m_proportional; /* unsupported */ - uint32_t m_clearattr; - - /* Mostly for fancy shit */ - void DrawFancyShit(); - float m_time; - bool m_debug; -}; - -#endif // __TERM_TERM_H__ - +// // Neercs // #if !defined __TERM_TERM_H__ #define __TERM_TERM_H__ #include "term/pty.h" struct Iso2022Conversion { Iso2022Conversion() { Reset(); } void Reset(); /* cs = coding system/coding method: */ /* (with standard return) */ /* '@' = ISO-2022, */ /* 'G' = UTF-8 without implementation level, */ /* '8' = UTF-8 (Linux console and imitators), */ /* and many others that are rarely used; */ /* (without standard return) */ /* '/G' = UTF-8 Level 1, */ /* '/H' = UTF-8 Level 2, */ /* '/I' = UTF-8 Level 3, */ /* and many others that are rarely used */ uint32_t cs; /* ctrl8bit = allow 8-bit controls */ uint8_t ctrl8bit; /* cn[0] = C0 control charset (0x00 ... 0x1f): * '@' = ISO 646, * '~' = empty, * and many others that are rarely used */ /* cn[1] = C1 control charset (0x80 ... 0x9f): * 'C' = ISO 6429-1983, * '~' = empty, * and many others that are rarely used */ uint32_t cn[2]; /* glr[0] = GL graphic charset (94-char. 0x21 ... 0x7e, * 94x94-char. 0x21/0x21 ... 0x7e/0x7e), * and * glr[1] = GR graphic charset (94-char. 0xa1 ... 0xfe, * 96-char. 0xa0 ... 0xff, * 94x94-char. 0xa1/0xa1 ... 0xfe/0xfe, * 96x96-char. 0xa0/0xa0 ... 0xff/0xff): * 0 = G0, 1 = G1, 2 = G2, 3 = G3 */ uint8_t glr[2]; /* gn[i] = G0/G1/G2/G3 graphic charset state: * (94-char. sets) * '0' = DEC ACS (VT100 and imitators), * 'B' = US-ASCII, * and many others that are rarely used for e.g. various national ASCII variations; * (96-char. sets) * '.A' = ISO 8859-1 "Latin 1" GR, * '.~' = empty 96-char. set, * and many others that are rarely used for e.g. ISO 8859-n GR; * (double-byte 94x94-charsets) * '$@' = Japanese Character Set ("old JIS") (JIS C 6226:1978), * '$A' = Chinese Character Set (GB 2312), * '$B' = Japanese Character Set (JIS X0208/JIS C 6226:1983), * '$C' = Korean Graphic Character Set (KSC 5601:1987), * '$D' = Supplementary Japanese Graphic Character Set (JIS X0212), * '$E' = CCITT Chinese Set (GB 2312 + GB 8565), * '$G' = CNS 11643 plane 1, * '$H' = CNS 11643 plane 2, * '$I' = CNS 11643 plane 3, * '$J' = CNS 11643 plane 4, * '$K' = CNS 11643 plane 5, * '$L' = CNS 11643 plane 6, * '$M' = CNS 11643 plane 7, * '$O' = JIS X 0213 plane 1, * '$P' = JIS X 0213 plane 2, * '$Q' = JIS X 0213-2004 Plane 1, * and many others that are rarely used for e.g. traditional * ideographic Vietnamese and BlissSymbolics; * (double-byte 96x96-charsets) * none standardized or in use on terminals AFAIK (Mule does use * some internally) */ uint32_t gn[4]; /* ss = single-shift state: 0 = GL, 2 = G2, 3 = G3 */ uint8_t ss; }; class Term : public Entity { public: Term(ivec2 size); ~Term(); char const *GetName() { return ""; } caca_canvas_t *GetCaca() { return m_caca; } protected: virtual void TickGame(float seconds); virtual void TickDraw(float seconds); private: /* Terminal emulation main entry point */ size_t ReadAnsi(void const *data, size_t size); size_t SendAnsi(char const *str); /* Utility functions for terminal emulation */ void ReadGrcm(unsigned int argc, unsigned int const *argv); inline int ReadChar(unsigned char c, int *x, int *y); inline int ReadDuplet(unsigned char const *buffer, unsigned int *skip, int top, int bottom, int width, int height); private: Pty *m_pty; caca_canvas_t *m_caca; ivec2 m_size; /* Terminal attributes */ char *m_title; int m_bell, m_init, m_report_mouse; int m_changed; /* content was updated */ Iso2022Conversion m_conv_state; /* charset mess */ uint8_t m_fg, m_bg; /* ANSI-context fg/bg */ uint8_t m_dfg, m_dbg; /* Default fg/bg */ uint8_t m_bold, m_blink, m_italics, m_negative, m_concealed, m_underline; uint8_t m_faint, m_strike, m_proportional; /* unsupported */ uint32_t m_clearattr; /* Mostly for fancy shit */ void DrawFancyShit(); float m_time; bool m_debug; }; #endif // __TERM_TERM_H__ \ No newline at end of file diff --git a/neercs/video/blurh.lolfx b/neercs/video/blurh.lolfx index 4c4dbee..ce06a9e 100644 --- a/neercs/video/blurh.lolfx +++ b/neercs/video/blurh.lolfx @@ -1,38 +1 @@ -[vert.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -void main() -{ - gl_Position = gl_Vertex; - pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; -} - -[frag.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -uniform sampler2D texture; -uniform vec2 radius; - -void main(void) -{ - vec4 total = vec4(0.0); - vec2 p = pass_TexCoord; - float mask = 2.0-p.x*(6.0-p.x*6.0)*p.y*(6.0-p.y*6.0); - float b = radius.x+radius.y*mask; - total += texture2D(texture,vec2(p.x-b*4.0,p.y))*0.04; - total += texture2D(texture,vec2(p.x-b*3.0,p.y))*0.08; - total += texture2D(texture,vec2(p.x-b*2.0,p.y))*0.12; - total += texture2D(texture,vec2(p.x-b ,p.y))*0.16; - total += texture2D(texture,vec2(p.x ,p.y))*0.20; - total += texture2D(texture,vec2(p.x+b ,p.y))*0.16; - total += texture2D(texture,vec2(p.x+b*2.0,p.y))*0.12; - total += texture2D(texture,vec2(p.x+b*3.0,p.y))*0.08; - total += texture2D(texture,vec2(p.x+b*4.0,p.y))*0.04; - gl_FragColor = total; -} +[vert.glsl] #version 120 varying vec2 pass_TexCoord; void main() { gl_Position = gl_Vertex; pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; } [frag.glsl] #version 120 varying vec2 pass_TexCoord; uniform sampler2D texture; uniform vec2 radius; void main(void) { vec4 total = vec4(0.0); vec2 p = pass_TexCoord; float mask = 2.0-p.x*(6.0-p.x*6.0)*p.y*(6.0-p.y*6.0); float b = radius.x+radius.y*mask; total += texture2D(texture,vec2(p.x-b*4.0,p.y))*0.04; total += texture2D(texture,vec2(p.x-b*3.0,p.y))*0.08; total += texture2D(texture,vec2(p.x-b*2.0,p.y))*0.12; total += texture2D(texture,vec2(p.x-b ,p.y))*0.16; total += texture2D(texture,vec2(p.x ,p.y))*0.20; total += texture2D(texture,vec2(p.x+b ,p.y))*0.16; total += texture2D(texture,vec2(p.x+b*2.0,p.y))*0.12; total += texture2D(texture,vec2(p.x+b*3.0,p.y))*0.08; total += texture2D(texture,vec2(p.x+b*4.0,p.y))*0.04; gl_FragColor = total; } \ No newline at end of file diff --git a/neercs/video/blurv.lolfx b/neercs/video/blurv.lolfx index c719180..419d836 100644 --- a/neercs/video/blurv.lolfx +++ b/neercs/video/blurv.lolfx @@ -1,39 +1 @@ -[vert.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -void main() -{ - gl_Position = gl_Vertex; - pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; -} - -[frag.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -uniform sampler2D texture; -uniform vec2 radius; - -void main(void) -{ - vec4 total = vec4(0.0); - vec2 p = pass_TexCoord; - float mask = 2.0-p.x*(6.0-p.x*6.0)*p.y*(6.0-p.y*6.0); - float b = radius.x+radius.y*mask; - total += texture2D(texture,vec2(p.x,p.y-b*4.0))*0.04; - total += texture2D(texture,vec2(p.x,p.y-b*3.0))*0.08; - total += texture2D(texture,vec2(p.x,p.y-b*2.0))*0.12; - total += texture2D(texture,vec2(p.x,p.y-b ))*0.16; - total += texture2D(texture,vec2(p.x,p.y ))*0.20; - total += texture2D(texture,vec2(p.x,p.y+b ))*0.16; - total += texture2D(texture,vec2(p.x,p.y+b*2.0))*0.12; - total += texture2D(texture,vec2(p.x,p.y+b*3.0))*0.08; - total += texture2D(texture,vec2(p.x,p.y+b*4.0))*0.04; - gl_FragColor = total; -} - +[vert.glsl] #version 120 varying vec2 pass_TexCoord; void main() { gl_Position = gl_Vertex; pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; } [frag.glsl] #version 120 varying vec2 pass_TexCoord; uniform sampler2D texture; uniform vec2 radius; void main(void) { vec4 total = vec4(0.0); vec2 p = pass_TexCoord; float mask = 2.0-p.x*(6.0-p.x*6.0)*p.y*(6.0-p.y*6.0); float b = radius.x+radius.y*mask; total += texture2D(texture,vec2(p.x,p.y-b*4.0))*0.04; total += texture2D(texture,vec2(p.x,p.y-b*3.0))*0.08; total += texture2D(texture,vec2(p.x,p.y-b*2.0))*0.12; total += texture2D(texture,vec2(p.x,p.y-b ))*0.16; total += texture2D(texture,vec2(p.x,p.y ))*0.20; total += texture2D(texture,vec2(p.x,p.y+b ))*0.16; total += texture2D(texture,vec2(p.x,p.y+b*2.0))*0.12; total += texture2D(texture,vec2(p.x,p.y+b*3.0))*0.08; total += texture2D(texture,vec2(p.x,p.y+b*4.0))*0.04; gl_FragColor = total; } \ No newline at end of file diff --git a/neercs/video/color.lolfx b/neercs/video/color.lolfx index e28bd6f..72e710f 100644 --- a/neercs/video/color.lolfx +++ b/neercs/video/color.lolfx @@ -1,34 +1 @@ -[vert.glsl] - -#version 120 - -void main() -{ - gl_Position = gl_Vertex; -} - -[frag.glsl] - -#version 120 - -uniform sampler2D texture; -uniform vec2 screen_size; -uniform vec3 filter; -uniform vec4 color; -uniform float flash; - -void main(void) -{ - vec2 p = gl_FragCoord.xy / screen_size.xy; - vec3 c = texture2D(texture,p).xyz; - - float a = (c.x + c.y + c.z) / 3.0; - c = mix(c, vec3(a), color.w); // grayscale - c *= filter; // filter - c += color.z * 0.1; // level - c *= color.x; // brightness - c = 0.5 + (c - 0.5) * color.y; // contrast - c += flash; // flash - - gl_FragColor = vec4(c, 1.0); -} +[vert.glsl] #version 120 void main() { gl_Position = gl_Vertex; } [frag.glsl] #version 120 uniform sampler2D texture; uniform vec2 screen_size; uniform vec3 filter; uniform vec4 color; uniform float flash; void main(void) { vec2 p = gl_FragCoord.xy / screen_size.xy; vec3 c = texture2D(texture,p).xyz; float a = (c.x + c.y + c.z) / 3.0; c = mix(c, vec3(a), color.w); // grayscale c *= filter; // filter c += color.z * 0.1; // level c *= color.x; // brightness c = 0.5 + (c - 0.5) * color.y; // contrast c += flash; // flash gl_FragColor = vec4(c, 1.0); } \ No newline at end of file diff --git a/neercs/video/copper.lolfx b/neercs/video/copper.lolfx index 9f6e2cf..9acc36a 100644 --- a/neercs/video/copper.lolfx +++ b/neercs/video/copper.lolfx @@ -1,42 +1 @@ -[vert.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -void main() -{ - gl_Position = gl_Vertex; - pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; -} - -[frag.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -uniform sampler2D texture; -uniform vec2 screen_size; -uniform float time; -uniform vec4 copper; -uniform vec3 mask_color; - -void main(void) -{ - vec2 p = pass_TexCoord; - vec3 source = texture2D(texture, p).xyz; - - vec3 color = vec3(0.5); - - color.x += 0.5 * cos(p.y*float(screen_size.y / copper.w) + time); - color.z += 0.5 * sin(p.y*float(screen_size.y / copper.w) + time); - - color *= copper.x + copper.y * cos(p.y * float(screen_size.x / copper.z));// - time); - - color.x = float(int(color.x * 8.0) * 32) / 256.0; - color.y = float(int(color.y * 8.0) * 32) / 256.0; - color.z = float(int(color.z * 8.0) * 32) / 256.0; - -gl_FragColor = vec4((abs(source.x - mask_color.x) < 0.025 && abs(source.y - mask_color.y) < 0.025 && abs(source.z - mask_color.z) < 0.025) ? color : source, 1.0); -} +[vert.glsl] #version 120 varying vec2 pass_TexCoord; void main() { gl_Position = gl_Vertex; pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; } [frag.glsl] #version 120 varying vec2 pass_TexCoord; uniform sampler2D texture; uniform vec2 screen_size; uniform float time; uniform vec4 copper; uniform vec3 mask_color; void main(void) { vec2 p = pass_TexCoord; vec3 source = texture2D(texture, p).xyz; vec3 color = vec3(0.5); color.x += 0.5 * cos(p.y*float(screen_size.y / copper.w) + time); color.z += 0.5 * sin(p.y*float(screen_size.y / copper.w) + time); color *= copper.x + copper.y * cos(p.y * float(screen_size.x / copper.z));// - time); color.x = float(int(color.x * 8.0) * 32) / 256.0; color.y = float(int(color.y * 8.0) * 32) / 256.0; color.z = float(int(color.z * 8.0) * 32) / 256.0; gl_FragColor = vec4((abs(source.x - mask_color.x) < 0.025 && abs(source.y - mask_color.y) < 0.025 && abs(source.z - mask_color.z) < 0.025) ? color : source, 1.0); } \ No newline at end of file diff --git a/neercs/video/glow.lolfx b/neercs/video/glow.lolfx index 0a74056..6039c5a 100644 --- a/neercs/video/glow.lolfx +++ b/neercs/video/glow.lolfx @@ -1,28 +1 @@ -[vert.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -void main() -{ - gl_Position = gl_Vertex; - pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; -} - -[frag.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -uniform sampler2D glow; -uniform sampler2D source; -uniform vec2 mix; - -void main(void) -{ - gl_FragColor = texture2D(source, pass_TexCoord) * mix.x - + texture2D(glow, pass_TexCoord) * mix.y; -} - +[vert.glsl] #version 120 varying vec2 pass_TexCoord; void main() { gl_Position = gl_Vertex; pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; } [frag.glsl] #version 120 varying vec2 pass_TexCoord; uniform sampler2D glow; uniform sampler2D source; uniform vec2 mix; void main(void) { gl_FragColor = texture2D(source, pass_TexCoord) * mix.x + texture2D(glow, pass_TexCoord) * mix.y; } \ No newline at end of file diff --git a/neercs/video/mirror.lolfx b/neercs/video/mirror.lolfx index f19aa93..1dda84d 100644 --- a/neercs/video/mirror.lolfx +++ b/neercs/video/mirror.lolfx @@ -1,35 +1 @@ -[vert.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -void main() -{ - gl_Position = gl_Vertex; - pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; -} - -[frag.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -uniform sampler2D texture; -uniform vec2 screen_size; -uniform vec4 mirror; - -void main(void) -{ - vec2 p = pass_TexCoord; - vec3 s = texture2D(texture, p).xyz; - - vec3 c = vec3(0.0); - if(p.x < mirror.x) c += texture2D(texture, vec2(mirror.x + (mirror.x - p.x) * mirror.w, p.y * (0.8 + 2.0 * p.x) + 0.1 - 1.0 * p.x)).xyz * (mirror.z / mirror.x * p.x); - if(p.x > 1.0 - mirror.x) c += texture2D(texture, vec2(- mirror.x - (mirror.x + p.x) * mirror.w, p.y * (0.8 + 2.0 * (1.0 - p.x)) + 0.1 - 1.0 * (1.0 - p.x))).xyz * (mirror.z / mirror.x * (1.0 - p.x)); - if(p.y < mirror.y) c += texture2D(texture, vec2(p.x * (0.8 + 2.0 * p.y) + 0.1 - 1.0 * p.y, mirror.y + (mirror.y - p.y) * mirror.w)).xyz * (mirror.z / mirror.y * p.y); - if(p.y > 1.0 - mirror.y) c += texture2D(texture, vec2(p.x * (0.8 + 2.0 * (1.0 - p.y)) + 0.1 - 1.0 * (1.0 - p.y), - mirror.y - (mirror.y + p.y) * mirror.w)).xyz * (mirror.z / mirror.y * (1.0 - p.y)); - - gl_FragColor = vec4(s + c, 1.0); -} +[vert.glsl] #version 120 varying vec2 pass_TexCoord; void main() { gl_Position = gl_Vertex; pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; } [frag.glsl] #version 120 varying vec2 pass_TexCoord; uniform sampler2D texture; uniform vec2 screen_size; uniform vec4 mirror; void main(void) { vec2 p = pass_TexCoord; vec3 s = texture2D(texture, p).xyz; vec3 c = vec3(0.0); if(p.x < mirror.x) c += texture2D(texture, vec2(mirror.x + (mirror.x - p.x) * mirror.w, p.y * (0.8 + 2.0 * p.x) + 0.1 - 1.0 * p.x)).xyz * (mirror.z / mirror.x * p.x); if(p.x > 1.0 - mirror.x) c += texture2D(texture, vec2(- mirror.x - (mirror.x + p.x) * mirror.w, p.y * (0.8 + 2.0 * (1.0 - p.x)) + 0.1 - 1.0 * (1.0 - p.x))).xyz * (mirror.z / mirror.x * (1.0 - p.x)); if(p.y < mirror.y) c += texture2D(texture, vec2(p.x * (0.8 + 2.0 * p.y) + 0.1 - 1.0 * p.y, mirror.y + (mirror.y - p.y) * mirror.w)).xyz * (mirror.z / mirror.y * p.y); if(p.y > 1.0 - mirror.y) c += texture2D(texture, vec2(p.x * (0.8 + 2.0 * (1.0 - p.y)) + 0.1 - 1.0 * (1.0 - p.y), - mirror.y - (mirror.y + p.y) * mirror.w)).xyz * (mirror.z / mirror.y * (1.0 - p.y)); gl_FragColor = vec4(s + c, 1.0); } \ No newline at end of file diff --git a/neercs/video/noise.lolfx b/neercs/video/noise.lolfx index 0b817ce..8c25c01 100644 --- a/neercs/video/noise.lolfx +++ b/neercs/video/noise.lolfx @@ -1,38 +1 @@ -[vert.glsl] - -#version 120 - -void main() -{ - gl_Position = gl_Vertex; -} - -[frag.glsl] - -#version 120 - -uniform sampler2D texture; -uniform vec2 screen_size; -uniform float time; -uniform vec2 offset; -uniform float noise; -uniform vec3 retrace; - -float rand(in vec2 p, in float t, in float v) -{ - return fract(sin(dot(p + mod(t, 1.0), vec2(12.9898, 78.2333))) * v); -} - -void main(void) -{ - vec2 p=gl_FragCoord.xy/screen_size.xy; - - float r1=rand(p,time,43758.5453); - float r2=rand(p,time,70425.2854); - vec2 o=(offset-offset*2.0*r1)/screen_size; - - vec3 c=texture2D(texture,p+o).xyz; // offset - c*=1.0+(noise-noise*2.0*r1); // noise - c-=retrace.x*0.01*mod(p.y*retrace.y+time*retrace.z,1.0); // retrace - gl_FragColor=vec4(c,1.0); -} +[vert.glsl] #version 120 void main() { gl_Position = gl_Vertex; } [frag.glsl] #version 120 uniform sampler2D texture; uniform vec2 screen_size; uniform float time; uniform vec2 offset; uniform float noise; uniform vec3 retrace; float rand(in vec2 p, in float t, in float v) { return fract(sin(dot(p + mod(t, 1.0), vec2(12.9898, 78.2333))) * v); } void main(void) { vec2 p=gl_FragCoord.xy/screen_size.xy; float r1=rand(p,time,43758.5453); float r2=rand(p,time,70425.2854); vec2 o=(offset-offset*2.0*r1)/screen_size; vec3 c=texture2D(texture,p+o).xyz; // offset c*=1.0+(noise-noise*2.0*r1); // noise c-=retrace.x*0.01*mod(p.y*retrace.y+time*retrace.z,1.0); // retrace gl_FragColor=vec4(c,1.0); } \ No newline at end of file diff --git a/neercs/video/postfx.lolfx b/neercs/video/postfx.lolfx index acf17d2..4e16e5e 100644 --- a/neercs/video/postfx.lolfx +++ b/neercs/video/postfx.lolfx @@ -1,110 +1 @@ -[vert.glsl] - -#version 120 - -void main() -{ - gl_Position = gl_Vertex; -} - -[frag.glsl] - -#version 120 - -uniform sampler2D texture; -uniform vec2 screen_size; -uniform vec2 ratio_2d; -uniform float time; -uniform vec2 deform; -uniform vec4 ghost1; -uniform vec4 ghost2; -uniform vec4 glass; -uniform vec3 gradient; -uniform vec3 gradient_color; -uniform float vignetting; -uniform float aberration; -uniform vec4 moire_h; -uniform vec4 moire_v; -uniform vec4 scanline_h; -uniform vec4 scanline_v; -uniform vec3 corner; -uniform float sync; -uniform float beat; - -const float PI=3.14159265358979323846; -vec2 angle=screen_size*PI; - -vec2 screen(in vec2 p,in float bend,in float radius) -{ - float d=bend+sync*0.0625+beat*0.0375; - return p*(1.5-(radius*cos(p.x*d)+radius*cos(p.y*d)))-0.5; -} - -vec3 get_color(in sampler2D tex,in vec2 p) -{ - return texture2D(tex,clamp(p,-1.0,0.0)).xyz; -} - -float letterbox(in vec2 p,in float w,in float radius,in float smooth) -{ - return 1.0-smoothstep(smooth,1.0,length(max(abs(p*w+w/2.0)-vec2(radius),0.0))+radius); -} - -void main(void) -{ - vec2 q=gl_FragCoord.xy/screen_size.xy; - vec2 p=-1.0+2.0*gl_FragCoord.xy/screen_size.xy; - p.y+=0.025*sync; - vec2 z=screen(p,deform.x,deform.y); - vec2 z1=screen(p,deform.x,deform.y+ghost1.z); - vec2 z2=screen(p,deform.x,deform.y+ghost2.z); - vec2 z3=screen(p,glass.w,deform.y+glass.x-glass.y); - vec2 z4=screen(p,glass.w,deform.y+glass.x+glass.y); - float mask=q.x*(6.0-q.x*6.0)*q.y*(6.0-q.y*6.0); - - vec3 source=get_color(texture,z); - vec3 g1=get_color(texture,z1-ghost1.xy); - vec3 g2=get_color(texture,z2-ghost2.xy); - vec3 g3=get_color(texture,z3); - vec3 g4=get_color(texture,z4); - - vec3 c=source+g1*ghost1.w+g2*ghost2.w; // mix - - float v=aberration/float(screen_size.x/ratio_2d.x); //+aberration/float(screen_size.x)*(2.0-mask); - vec3 ca1=get_color(texture,vec2(z.x-v,z.y)); - vec3 ca2=get_color(texture,vec2(z.x+v,z.y)); - c+=vec3(ca1.x,c.y,ca2.z); // chromatic aberration - - vec3 c1=vec3(gradient_color.x,gradient_color.y,gradient_color.z); - vec3 c2=vec3(gradient_color.x,gradient_color.y,gradient_color.z)/4; - vec3 c3=vec3(1.0,1.0,1.0); - vec3 c4=vec3(gradient_color.z,gradient_color.y,gradient_color.x); - vec3 c5=vec3(gradient_color.z,gradient_color.y,gradient_color.x)/4; - vec3 r; - float r_p=gradient.x; - float r_h=gradient.y; - float r_h2=gradient.y/2; - float k=z.y+1.0; - - if (k <= r_p - r_h2) - r = mix(c1,c2,k*(1/(r_p-r_h2))); - else if (k <= r_p) - r = mix(c2,c3,(k-(r_p-r_h2))*(1/r_h2)); - else if (k < r_p + r_h) - r = mix(c3,c4,(k-r_p)*(1/r_h)); - else - r = mix(c4,c5,k*((k-(r_p+r_h))/(r_p-r_h))); - - //c*=moire_h.x+moire_h.y*sin(z.y*float(screen_size.y*moire_h.z)/ratio_2d.y)*sin(0.5+z.x*float(screen_size.x*moire_h.w)/ratio_2d.x); // moire h - //c*=moire_v.x+moire_v.y*sin(z.x*float(screen_size.x*moire_v.z)/ratio_2d.x)*sin(0.5+z.y*float(screen_size.y*moire_v.w)/ratio_2d.y); // moire v - - c*=moire_h.x+moire_h.y*sin(z.y*float(angle.y*moire_h.z)/ratio_2d.y)*sin(PI+z.x*float(screen_size.x*moire_h.w)/ratio_2d.x); // moire h - c*=moire_v.x+moire_v.y*sin(z.x*float(angle.x*moire_v.z)/ratio_2d.x)*sin(PI+z.y*float(screen_size.y*moire_v.w)/ratio_2d.y); // moire v - c*=scanline_h.x+scanline_h.y*cos(z.y*float(angle.y*scanline_h.z+scanline_h.w)/ratio_2d.y); // scanline h - c*=scanline_v.x+scanline_v.y*cos(z.x*float(angle.x*scanline_v.z+scanline_v.w)/ratio_2d.x); // scanline v - c+=r*gradient.z; // gradient - c*=mix(1.0,mask,vignetting); // vignetting - c*=letterbox(z,corner.x+2.0,corner.y,corner.z); // corner - c+=(g3+g4)*glass.z; // glass - gl_FragColor=vec4(c,1.0); -} +[vert.glsl] #version 120 void main() { gl_Position = gl_Vertex; } [frag.glsl] #version 120 uniform sampler2D texture; uniform vec2 screen_size; uniform vec2 ratio_2d; uniform float time; uniform vec2 deform; uniform vec4 ghost1; uniform vec4 ghost2; uniform vec4 glass; uniform vec3 gradient; uniform vec3 gradient_color; uniform float vignetting; uniform float aberration; uniform vec4 moire_h; uniform vec4 moire_v; uniform vec4 scanline_h; uniform vec4 scanline_v; uniform vec3 corner; uniform float sync; uniform float beat; const float PI=3.14159265358979323846; vec2 angle=screen_size*PI; vec2 screen(in vec2 p,in float bend,in float radius) { float d=bend+sync*0.0625+beat*0.0375; return p*(1.5-(radius*cos(p.x*d)+radius*cos(p.y*d)))-0.5; } vec3 get_color(in sampler2D tex,in vec2 p) { return texture2D(tex,clamp(p,-1.0,0.0)).xyz; } float letterbox(in vec2 p,in float w,in float radius,in float smooth) { return 1.0-smoothstep(smooth,1.0,length(max(abs(p*w+w/2.0)-vec2(radius),0.0))+radius); } void main(void) { vec2 q=gl_FragCoord.xy/screen_size.xy; vec2 p=-1.0+2.0*gl_FragCoord.xy/screen_size.xy; p.y+=0.025*sync; vec2 z=screen(p,deform.x,deform.y); vec2 z1=screen(p,deform.x,deform.y+ghost1.z); vec2 z2=screen(p,deform.x,deform.y+ghost2.z); vec2 z3=screen(p,glass.w,deform.y+glass.x-glass.y); vec2 z4=screen(p,glass.w,deform.y+glass.x+glass.y); float mask=q.x*(6.0-q.x*6.0)*q.y*(6.0-q.y*6.0); vec3 source=get_color(texture,z); vec3 g1=get_color(texture,z1-ghost1.xy); vec3 g2=get_color(texture,z2-ghost2.xy); vec3 g3=get_color(texture,z3); vec3 g4=get_color(texture,z4); vec3 c=source+g1*ghost1.w+g2*ghost2.w; // mix float v=aberration/float(screen_size.x/ratio_2d.x); //+aberration/float(screen_size.x)*(2.0-mask); vec3 ca1=get_color(texture,vec2(z.x-v,z.y)); vec3 ca2=get_color(texture,vec2(z.x+v,z.y)); c+=vec3(ca1.x,c.y,ca2.z); // chromatic aberration vec3 c1=vec3(gradient_color.x,gradient_color.y,gradient_color.z); vec3 c2=vec3(gradient_color.x,gradient_color.y,gradient_color.z)/4; vec3 c3=vec3(1.0,1.0,1.0); vec3 c4=vec3(gradient_color.z,gradient_color.y,gradient_color.x); vec3 c5=vec3(gradient_color.z,gradient_color.y,gradient_color.x)/4; vec3 r; float r_p=gradient.x; float r_h=gradient.y; float r_h2=gradient.y/2; float k=z.y+1.0; if (k <= r_p - r_h2) r = mix(c1,c2,k*(1/(r_p-r_h2))); else if (k <= r_p) r = mix(c2,c3,(k-(r_p-r_h2))*(1/r_h2)); else if (k < r_p + r_h) r = mix(c3,c4,(k-r_p)*(1/r_h)); else r = mix(c4,c5,k*((k-(r_p+r_h))/(r_p-r_h))); //c*=moire_h.x+moire_h.y*sin(z.y*float(screen_size.y*moire_h.z)/ratio_2d.y)*sin(0.5+z.x*float(screen_size.x*moire_h.w)/ratio_2d.x); // moire h //c*=moire_v.x+moire_v.y*sin(z.x*float(screen_size.x*moire_v.z)/ratio_2d.x)*sin(0.5+z.y*float(screen_size.y*moire_v.w)/ratio_2d.y); // moire v c*=moire_h.x+moire_h.y*sin(z.y*float(angle.y*moire_h.z)/ratio_2d.y)*sin(PI+z.x*float(screen_size.x*moire_h.w)/ratio_2d.x); // moire h c*=moire_v.x+moire_v.y*sin(z.x*float(angle.x*moire_v.z)/ratio_2d.x)*sin(PI+z.y*float(screen_size.y*moire_v.w)/ratio_2d.y); // moire v c*=scanline_h.x+scanline_h.y*cos(z.y*float(angle.y*scanline_h.z+scanline_h.w)/ratio_2d.y); // scanline h c*=scanline_v.x+scanline_v.y*cos(z.x*float(angle.x*scanline_v.z+scanline_v.w)/ratio_2d.x); // scanline v c+=r*gradient.z; // gradient c*=mix(1.0,mask,vignetting); // vignetting c*=letterbox(z,corner.x+2.0,corner.y,corner.z); // corner c+=(g3+g4)*glass.z; // glass gl_FragColor=vec4(c,1.0); } \ No newline at end of file diff --git a/neercs/video/radial.lolfx b/neercs/video/radial.lolfx index 7cb606e..7768220 100644 --- a/neercs/video/radial.lolfx +++ b/neercs/video/radial.lolfx @@ -1,48 +1 @@ -[vert.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -void main() -{ - gl_Position = gl_Vertex; - pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; -} - -[frag.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -uniform sampler2D texture; -uniform vec2 screen_size; -uniform vec4 radial; - -vec3 deform(in vec2 p) - { - float zoom = 0.5; - vec2 uv = p * zoom - 0.5; - return texture2D(texture, uv).xyz; - } - -void main(void) -{ - vec2 p = -1.0 + 2.0 * pass_TexCoord; - vec2 s = p; - vec3 source=deform(s); - - vec3 color = vec3(1.0,1.0,1.0); - - vec2 d = -p / float(radial.z * radial.x); - float w = 1.0; - for(int i = 0; i < radial.z; i++) - { - vec3 c = deform(s); - color += c * w; - w *= radial.y; - s += d; - } - gl_FragColor = vec4(source + color * radial.w, 1.0); -} +[vert.glsl] #version 120 varying vec2 pass_TexCoord; void main() { gl_Position = gl_Vertex; pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; } [frag.glsl] #version 120 varying vec2 pass_TexCoord; uniform sampler2D texture; uniform vec2 screen_size; uniform vec4 radial; vec3 deform(in vec2 p) { float zoom = 0.5; vec2 uv = p * zoom - 0.5; return texture2D(texture, uv).xyz; } void main(void) { vec2 p = -1.0 + 2.0 * pass_TexCoord; vec2 s = p; vec3 source=deform(s); vec3 color = vec3(1.0,1.0,1.0); vec2 d = -p / float(radial.z * radial.x); float w = 1.0; for(int i = 0; i < radial.z; i++) { vec3 c = deform(s); color += c * w; w *= radial.y; s += d; } gl_FragColor = vec4(source + color * radial.w, 1.0); } \ No newline at end of file diff --git a/neercs/video/remanence.lolfx b/neercs/video/remanence.lolfx index 3bef08e..238bedd 100644 --- a/neercs/video/remanence.lolfx +++ b/neercs/video/remanence.lolfx @@ -1,34 +1 @@ -[vert.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -void main() -{ - gl_Position = gl_Vertex; - pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; -} - -[frag.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -uniform sampler2D source; -uniform sampler2D buffer; -uniform vec2 mix; - -void main(void) -{ - vec4 old_color = texture2D(buffer, pass_TexCoord); - vec4 new_color = texture2D(source, pass_TexCoord); - - /* The old way */ - //gl_FragColor = new_color * mix.x + old_color * mix.y; - - /* The new way: if new_color > old_color we want faster updates */ - gl_FragColor = max(new_color, new_color * mix.x + old_color * mix.y); -} - +[vert.glsl] #version 120 varying vec2 pass_TexCoord; void main() { gl_Position = gl_Vertex; pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; } [frag.glsl] #version 120 varying vec2 pass_TexCoord; uniform sampler2D source; uniform sampler2D buffer; uniform vec2 mix; void main(void) { vec4 old_color = texture2D(buffer, pass_TexCoord); vec4 new_color = texture2D(source, pass_TexCoord); /* The old way */ //gl_FragColor = new_color * mix.x + old_color * mix.y; /* The new way: if new_color > old_color we want faster updates */ gl_FragColor = max(new_color, new_color * mix.x + old_color * mix.y); } \ No newline at end of file diff --git a/neercs/video/render.cpp b/neercs/video/render.cpp index 95212b6..ef3ea12 100644 --- a/neercs/video/render.cpp +++ b/neercs/video/render.cpp @@ -1,1727 +1 @@ -// -// Neercs -// - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include -#include - -#include "core.h" -#include "lolgl.h" -#include "loldebug.h" - -using namespace std; -using namespace lol; - -#include "../neercs.h" -#include "render.h" -#include "text-render.h" - -LOLFX_RESOURCE_DECLARE(simple); -LOLFX_RESOURCE_DECLARE(blurh); -LOLFX_RESOURCE_DECLARE(blurv); -LOLFX_RESOURCE_DECLARE(glow); -LOLFX_RESOURCE_DECLARE(remanence); -LOLFX_RESOURCE_DECLARE(copper); -LOLFX_RESOURCE_DECLARE(color); -LOLFX_RESOURCE_DECLARE(noise); -LOLFX_RESOURCE_DECLARE(postfx); -LOLFX_RESOURCE_DECLARE(mirror); -LOLFX_RESOURCE_DECLARE(radial); - -#define PID F_PI/180.0f // pi ratio - -/* - * Global variable -- ugly ( sam: c'est toi qui est ugly! \:D/) - */ -bool g_setup = false; - -/* - * Various variables - */ - -int active = true; // window active flag -float nearplane = 0.1f; // nearplane -float farplane = 1000.0f; // farplane -/* timer variable */ -float timer = 0; // timer -/* window variable */ -ivec2 screen_size; // screen size -/* object variable */ -float main_angle = 0.0f; // main angle -float part_angle = 0.0f; // part angle -float fx_angle; // current angle -/* fs_quad variable */ -float fs_quad_vtx[] = -{ - -1.0f, 1.0f, 0, 1.0f, - -1.0f, -1.0f, 0, 1.0f, - 1.0f, -1.0f, 0, 1.0f, - 1.0f, 1.0f, 0, 1.0f -}; -/* flash variable */ -bool flash_flag = false; // flag -float flash_angle = 0; // angle -float flash_value = 0; // value -float flash_speed = 2.0f; // speed -/* fade variable */ -bool fade_flag = false; // flag -float fade_angle = 0; // angle -float fade_value = 0; // value -float fade_speed = 0.2f; // speed -/* sync variable */ -bool sync_flag = false; // flagsh -float sync_angle = 0; // angle -float sync_value = 0; // value -float sync_speed = 1.0f; // speed -/* beat variable */ -bool beat_flag = false; // flag -float beat_angle = 0; // angle -float beat_value = 0; // value -float beat_speed = 2.0f; // speed -/* common variable */ -float value, angle, radius, scale, speed; -/* text variable */ -ivec2 map_size(256,256); // texture map size -ivec2 canvas_char(0,0); // canvas char number -ivec2 canvas_size(0,0); // caca size -ivec2 font_size(8,8); // font size -ivec2 ratio_2d(1,1); // 2d ratio -ivec2 border(0,0); // border width -/* shader variable */ -vec2 buffer; // [new frame mix,old frame mix] -vec2 remanence; // remanence [source mix,buffer mix] -vec2 glow_mix; // glow mix [source mix,glow mix] -vec2 glow_large; // large glow radius [center,corner] -vec2 glow_small; // small glow radius [center,corner] -vec2 blur; // blur radius [center,corner] -vec4 copper_copper; // copper [base,variable,repeat,color cycle] -vec3 copper_mask_color; // color [red,green,blue] -vec3 color_filter; // color filter [red,green,blue] -vec4 color_color; // color modifier [brightness,contrast,level,grayscale] -vec2 noise_offset; // random line [horizontal,vertical] -float noise_noise; // noise -vec3 noise_retrace; // retrace [strength,length,speed] -vec2 postfx_deform; // deformation [ratio,zoom] -float postfx_vignetting; // vignetting strength -float postfx_aberration; // chromatic aberration -vec4 postfx_ghost1; // ghost picture 1 [position x,position y,position z,strength] -vec4 postfx_ghost2; // ghost picture 2 [position x,position y,position z,strength] -vec3 postfx_gradient; // gradient [position y,height,strength] -vec3 postfx_gradient_color;// gradient color [red,green,blue] -vec4 postfx_glass; // glass [depth,thickness,strength,deform ratio] -vec4 postfx_moire_h; // vertical moire [base,variable,repeat,shift] -vec4 postfx_moire_v; // horizontal moire [base,variable,repeat,shift] -vec4 postfx_scanline_h; // vertical scanline [base,variable,repeat,shift] -vec4 postfx_scanline_v; // horizontal scanline [base,variable,repeat,shift] -vec3 postfx_corner; // corner [width,radius,blur] -vec4 mirror; // mirror [width,height,strength,ratio] -vec4 radial; // radial [distance,fade ratio,iteration,strength] -/* theme variable */ -int theme_i = 0; // current theme -const int theme_n = 5; // theme number -int theme_var_key = 0; // theme array key -/* setup variable */ -bool setup_switch = false; // switch [option/item] -int setup_n = 0; // item/option number -int setup_h = 8; // height -int setup_cursor = 0; // cursor position -int setup_option_i = 0; // selected option -const int setup_option_n = 15; // option number -int setup_option_p = 0; // option position -int setup_item_i = 0; // selected item -int setup_item_n = 8; // item number -int setup_item_p = 0; // item position -int setup_item_key = 0; // item array key -ivec3 setup_size(29, 9, 12); // size [w,h,split] -ivec2 setup_canvas_size(ivec2(setup_size.x + 1, setup_size.y + 1) * font_size * ivec2(2,4)); -ivec2 setup_color(0xaaa, 0x222);// color [foreground,background] 0x678,0x234 -char const *setup_text[]={ - "main", - "2d ratio w", - "2d ratio h", - "border w", - "border h", - "", - "", - "", - "", - "remanence", - "buffer new frame", - "buffer old frame", - "source mix", - "buffer mix", - "", - "", - "", - "", - "glow", - "source mix", - "glow mix", - "large center", - "large corner", - "small center", - "small corner", - "", - "", - "blur", - "blur center", - "blur corner", - "", - "", - "", - "", - "", - "", - "screen", - "deform ratio", - "zoom base", - "corner width", - "corner radius", - "corner blur", - "vignetting", - "", - "", - "copper", - "base", - "variable", - "repeat", - "color cycle", - "color r", - "color g", - "color b", - "", - "color", - "filter red", - "filter green", - "filter blue", - "brightness", - "contrast", - "level", - "grayscale", - "aberration", - "noise", - "offset h", - "offset v", - "noise", - "retrace strength", - "retrace length", - "retrace speed", - "", - "", - "ghost", - "back x", - "back y", - "back z", - "back strength", - "front x", - "front y", - "front z", - "front strength", - "gradient", - "position", - "thickness", - "strength", - "color r", - "color g", - "color b", - "", - "", - "glass", - "depth", - "thickness", - "strength", - "deform ratio", - "", - "", - "", - "", - "moire", - "h base", - "h variable", - "h repeat", - "h shift", - "v base", - "v variable", - "v repeat", - "v shift", - "scanline", - "h base", - "h variable", - "h repeat", - "h shift", - "v base", - "v variable", - "v repeat", - "v shift", - "mirror", - "enable", - "width", - "height", - "strength", - "ratio", - "", - "", - "", - "radial", - "distance", - "fade ratio", - "iteration", - "strength", - "", - "", - "", - "", - "" - }; - -vec4 setup_conf[]={ // setup variable [start,end,step,value] -vec4(0), /* main */ - vec4(1, 8, 1, 0), // ratio_2d.x - vec4(1, 8, 1, 0), // ratio_2d.y - vec4(0, 16, 1, 0), // border.x - vec4(0, 16, 1, 0), // border.y - vec4(0), - vec4(0), - vec4(0), - vec4(0), -vec4(0), /* remanence */ - vec4(0.0f, 1.0f, 0.1f, 0), // buffer.x - vec4(0.0f, 1.0f, 0.1f, 0), // buffer.y - vec4(0.0f, 1.0f, 0.1f, 0), // remanence.x - vec4(0.0f, 1.0f, 0.1f, 0), // remanence.y - vec4(0), - vec4(0), - vec4(0), - vec4(0), -vec4(0), /* glow */ - vec4(0.0f, 1.0f, 0.1f, 0), // glow_mix.x - vec4(0.0f, 1.0f, 0.1f, 0), // glow_mix.y - vec4(0.0f, 4.0f, 0.1f, 0), // glow_large.x - vec4(0.0f, 4.0f, 0.1f, 0), // glow_large.y - vec4(0.0f, 2.0f, 0.1f, 0), // glow_small.x - vec4(0.0f, 2.0f, 0.1f, 0), // glow_small.y - vec4(0), - vec4(0), -vec4(0), /* blur */ - vec4(0, 2, 0.05f, 0), // blur.x - vec4(0, 2, 0.05f, 0), // blur.y - vec4(0), - vec4(0), - vec4(0), - vec4(0), - vec4(0), - vec4(0), -vec4(0), /* screen */ - vec4(0.0f, 1.0f, 0.05f, 0), // postfx_deform.x - vec4(0.2f, 0.7f, 0.01f, 0), // postfx_deform.y - vec4(0.0f, 4.0f, 0.10f, 0), // postfx_corner.x - vec4(0.0f, 1.0f, 0.05f, 0), // postfx_corner.y - vec4(0.8f, 1.0f, 0.01f, 0), // postfx_corner.z - vec4(0.0f, 1.0f, 0.10f, 0), // postfx_vignetting - vec4(0), - vec4(0), -vec4(0), /* copper */ - vec4(0.0f, 1.0f, 0.05f, 0), // copper_copper.x - vec4(0.0f, 1.0f, 0.05f, 0), // copper_copper.y - vec4(0.0f, 1.0f, 0.02f, 0), // copper_copper.z - vec4(1.0f, 8.0f, 0.25f, 0), // copper_copper.w - vec4(0.0f, 1.0f, 0.05f, 0), // copper_mask_color.x - vec4(0.0f, 1.0f, 0.05f, 0), // copper_mask_color.y - vec4(0.0f, 1.0f, 0.05f, 0), // copper_mask_color.z - vec4(0), -vec4(0), /* color */ - vec4( 0.0f, 1.0f, 0.05f, 0), // color_filter.x - vec4( 0.0f, 1.0f, 0.05f, 0), // color_filter.y - vec4( 0.0f, 1.0f, 0.05f, 0), // color_filter.z - vec4( 0.0f, 2.0f, 0.05f, 0), // color_color.x - vec4( 0.0f, 2.0f, 0.05f, 0), // color_color.y - vec4(-1.0f, 1.0f, 0.05f, 0), // color_color.z - vec4( 0.0f, 1.0f, 0.05f, 0), // color_color.w - vec4( 0.0f, 8.0f, 0.50f, 0), // postfx_aberration -vec4(0), /* noise */ - vec4(0.0f, 4.0f, 0.50f, 0), // noise_offset.x - vec4(0.0f, 4.0f, 0.50f, 0), // noise_offset.y - vec4(0.0f, 0.5f, 0.05f, 0), // noise_noise - vec4(0.0f, 4.0f, 0.25f, 0), // noise_retrace.x - vec4(0.0f, 8.0f, 0.50f, 0), // noise_retrace.y - vec4(0.0f, 4.0f, 0.25f, 0), // noise_retrace.z - vec4(0), - vec4(0), -vec4(0), /* ghost */ - vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost1.x - vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost1.y - vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost1.z - vec4(-1.0f, 1.0f, 0.05f, 0), // postfx_ghost1.w - vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost2.x - vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost2.y - vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost2.z - vec4(-1.0f, 1.0f, 0.05f, 0), // postfx_ghost2.w -vec4(0), /* gradient */ - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_gradient.x - vec4( 0.0f, 0.5f, 0.05f, 0), // postfx_gradient.y - vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_gradient.z - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_gradient_color.x - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_gradient_color.y - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_gradient_color.z - vec4(0), - vec4(0), -vec4(0), /* glass */ - vec4(0.0f, 16.0f, 0.50f, 0), // postfx_glass.x - vec4(0.0f, 1.0f, 0.05f, 0), // postfx_glass.y - vec4(0.0f, 2.0f, 0.05f, 0), // postfx_glass.z - vec4(0.0f, 1.0f, 0.05f, 0), // postfx_glass.w - vec4(0), - vec4(0), - vec4(0), - vec4(0), -vec4(0), /* moire */ - vec4( 0.5f, 1.0f, 0.05f, 0), // postfx_moire_h.x - vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_moire_h.y - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_moire_h.z - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_moire_h.w - vec4( 0.5f, 1.0f, 0.05f, 0), // postfx_moire_v.x - vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_moire_v.y - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_moire_v.z - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_moire_v.w -vec4(0), /* scanline */ - vec4( 0.5f, 1.0f, 0.05f, 0), // postfx_scanline_h.x - vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_scanline_h.y - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_scanline_h.z - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_scanline_h.w - vec4( 0.5f, 1.0f, 0.05f, 0), // postfx_scanline_v.x - vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_scanline_v.y - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_scanline_v.z - vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_scanline_v.w -vec4(0), /* mirror */ - vec4(0.0f, 2.0f, 0.05f, 0), // mirror.x - vec4(0.0f, 2.0f, 0.05f, 0), // mirror.y - vec4(0.0f, 1.0f, 0.05f, 0), // mirror.z - vec4(1.0f, 8.0f, 1.00f, 0), // mirror.w - vec4(0), - vec4(0), - vec4(0), - vec4(0), -vec4(0), /* radial blur */ - vec4(2.0f, 8.0f, 0.25f, 0), // radial.x - vec4(0.8f, 1.0f, 0.01f, 0), // radial.y - vec4(2.0f,32.0f, 2.00f, 0), // radial.z - vec4(0.0f, 1.0f, 0.05f, 0), // radial.w - vec4(0), - vec4(0), - vec4(0), - vec4(0), -vec4(0) /* ? */ -}; - -float theme_var[]={ -/* default */ -0, - 1,1, // ratio_2d - 0,0, // border - 0,0,0,0, -0, - 1.0f,0.8f, // buffer - 0.0f,0.0f, // remanence - 0,0,0,0, -0, - 0.5f,0.0f, // glow_mix - 0.0f,0.0f, // glow_large - 0.0f,0.0f, // glow_small - 0,0, -0, - 0.0f,0.0f, // blur - 0,0,0,0,0,0, -0, - 0.0f,0.5f, // postfx_deform - 0.0f,1.0f,1.0f, // postfx_corner - 0.0f, // postfx_vignetting - 0,0, -0, - 0.75f,0.25f,0.42f,4.0f, // copper_copper - 0.05f,1.0f,0.0f, // copper_mask_color - 0, -0, - 1.0f,1.0f,1.0f, // color_filter - 1.0f,1.0f,0.0f,0.0f, // color_color - 0.0f, // postfx_aberration -0, - 0.0f,0.0f, // noise_offset - 0.0f, // noise_noise - 0.0f,0.0f,0.0f, // noise_retrace - 0,0, -0, - 0.0f,0.0f,0.0f,0.0f, // postfx_ghost1 - 0.0f,0.0f,0.0f,0.0f, // postfx_ghost2 -0, - 0.5f,0.0f,0.0f, // postfx_gradient - 0.0f,0.0f,0.0f, // postfx_gradient_color - 0,0, -0, - 8.0f,0.0f,0.0f,0.0f, // postfx_glass - 0,0,0,0, -0, - 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h - 1.0f,0.0f,0.0f,0.0f, // postfx_moire_v -0, - 1.0f,0.0f,0.0f,0.0f, // postfx_scanline_h - 1.0f,0.0f,0.0f,0.0f, // postfx_scanline_v -0, - 0.0f,0.0f,0.0f,1.0f, // mirror - 0,0,0,0, -0, - 4.0f,0.9f,1,0.0f, // radial - 0,0,0,0, -/* crt */ -0, - 2,3, // ratio_2d - 2,1, // border - 0,0,0,0, -0, - 0.2f,0.8f, // buffer - 0.6f,0.4f, // remanence - 0,0,0,0, -0, - 0.7f,0.3f, // glow_mix - 3.0f,0.0f, // glow_large - 1.5f,0.0f, // glow_small - 0,0, -0, - 0.5f,0.0f, // blur - 0,0,0,0,0,0, -0, - 0.8f,0.48f, // postfx_deform - 0.0f,0.8f,0.96f, // postfx_corner - 0.5f, // postfx_vignetting - 0,0, -0, - 0.75f,0.25f,0.42f,4.0f, // copper_copper - 0.05f,1.0f,0.0f, // copper_mask_color - 0, -0, - 0.9f,0.95f,0.85f, // color_filter - 1.0f,1.25f,0.1f,0.4f, // color_color - 4.0f, // postfx_aberration -0, - 1.0f,1.0f, // noise_offset - 0.15f, // noise_noise - 1.0f,1.0f,0.5f, // noise_retrace - 0,0, -0, - 1.0f,0.0f,0.0f,-0.25f, // postfx_ghost1 - 1.5f,0.0f,0.0f,0.25f, // postfx_ghost2 -0, - 0.5f,0.25f,0.05f, // postfx_gradient - 0.9f,0.8f,0.5f, // postfx_gradient_color - 0,0, -0, - 8.0f,0.25f,0.75f,0.2f, // postfx_glass - 0,0,0,0, -0, - 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h - 0.75f,-0.25f,0.25f,0.25f, // postfx_moire_v -0, - 1.0f,0.0f,0.0f,0.0f, // postfx_scanline_h - 0.75f,-0.25f,0.5f,0.0f, // postfx_scanline_v -0, - 0.95f,0.9f,0.5f,4.0f, // mirror - 0,0,0,0, -0, - 4.0f,0.9f,16,0.25f, // radial - 0,0,0,0, -/* amber screen */ -0, - 2,4, // ratio_2d - 1,0, // border - 0,0,0,0, -0, - 0.2f,0.8f, // buffer - 0.6f,0.4f, // remanence - 0,0,0,0, -0, - 0.4f,0.6f, // glow_mix - 4.0f,0.0f, // glow_large - 2.0f,0.0f, // glow_small - 0,0, -0, - 0.5f,0.0f, // blur - 0,0,0,0,0,0, -0, - 0.7f,0.5f, // postfx_deform - 0.0f,0.85f,0.98f, // postfx_corner - 0.5f, // postfx_vignetting - 0,0, -0, - 0.75f,0.25f,0.42f,4.0f, // copper_copper - 0.05f,1.0f,0.0f, // copper_mask_color - 0, -0, - 1.0f,0.7f,0.0f, // color_filter - 1.0f,1.25f,0.1f,1.0f, // color_color - 1.5f, // postfx_aberration -0, - 1.0f,0.0f, // noise_offset - 0.25f, // noise_noise - 1.0f,2.0f,2.0f, // noise_retrace - 0,0, -0, - 1.0f,0.0f,0.0f,-0.25f, // postfx_ghost1 - 1.5f,0.0f,0.0f,0.25f, // postfx_ghost2 -0, - 0.0f,0.25f,0.1f, // postfx_gradient - 0.25f,0.5f,0.5f, // postfx_gradient_color - 0,0, -0, - 8.0f,0.0f,0.0f,0.0f, // postfx_glass - 0,0,0,0, -0, - 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h - 1.0f,0.0f,0.0f,0.0f, // postfx_moire_v -0, - 0.6f,0.4f,1.0f,0.0f, // postfx_scanline_h - 0.9f,0.1f,0.75f,0.0f, // postfx_scanline_v -0, - 0.6f,0.6f,0.5f,4.0f, // mirror - 0,0,0,0, -0, - 4.0f,0.84f,16,0.25f, // radial - 0,0,0,0, -/* lcd */ -0, - 2,2, // ratio_2d - 1,1, // border - 0,0,0,0, -0, - 0.7f,0.3f, // buffer - 0.5f,0.5f, // remanence - 0,0,0,0, -0, - 0.5f,0.5f, // glow_mix - 2.4f,0.0f, // glow_large - 1.2f,0.0f, // glow_small - 0,0, -0, - 0.25f,0.0f, // blur - 0,0,0,0,0,0, -0, - 0.0f,0.5f, // postfx_deform - 0.0f,1.0f,1.0f, // postfx_corner - 0.0f, // postfx_vignetting - 0,0, -0, - 0.75f,0.25f,0.42f,4.0f, // copper_copper - 0.05f,1.0f,0.0f, // copper_mask_color - 0, -0, - 1.0f,1.0f,0.9f, // color_filter - 1.15f,1.25f,-0.1f,0.25f, // color_color - 3.0f, // postfx_aberration -0, - 0.0f,0.0f, // noise_offset - 0.15f, // noise_noise - 0.0f,0.0f,0.0f, // noise_retrace - 0,0, -0, - 0.0f,0.0f,0.0f,0.0f, // postfx_ghost1 - 0.0f,0.0f,0.0f,0.0f, // postfx_ghost2 -0, - 0.25f,0.5f,0.1f , // postfx_gradient - 0.7f,0.9f,1.0f, // postfx_gradient_color - 0,0, -0, - 8.0f,0.0f,0.0f,0.0f, // postfx_glass - 0,0,0,0, -0, - 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h - 1.0f,0.0f,0.0f,0.0f, // postfx_moire_v -0, - 0.75f,0.25f,0.7f,0.0f, // postfx_scanline_h - 0.75f,0.25f,0.7f,0.0f, // postfx_scanline_v -0, - 0.0f,0.0f,0.0f,1.0f, // mirror - 0,0,0,0, -0, - 4.0f,0.9f,1,0.0f, // radial - 0,0,0,0, -/* granpa tv */ -0, - 2,4, // ratio_2d - 1,0, // border - 0,0,0,0, -0, - 0.2f,0.8f, // buffer - 0.6f,0.4f, // remanence - 0,0,0,0, -0, - 0.4f,0.6f, // glow_mix - 2.4f,2.0f, // glow_large - 1.2f,1.0f, // glow_small - 0,0, -0, - 0.5f,0.5f, // blur - 0,0,0,0,0,0, -0, - 1.0f,0.5f, // postfx_deform - 0.0f,0.5f,0.9f, // postfx_corner - 0.5f, // postfx_vignetting - 0,0, -0, - 0.75f,0.25f,0.42f,4.0f, // copper_copper - 0.05f,1.0f,0.0f, // copper_mask_color - 0, -0, - 0.7f,0.8f,1.0f, // color_filter - 0.9f,1.1f,0.0f,1.0f, // color_color - 0.0f, // postfx_aberration -0, - 2.0f,0.0f, // noise_offset - 0.25f, // noise_noise - 1.0f,1.0f,4.0f, // noise_retrace - 0,0, -0, - -1.0f,0.0f,0.0f,-0.25f, // postfx_ghost1 - 1.0f,0.0f,0.0f,-0.25f, // postfx_ghost2 -0, - 0.5f,0.25f,0.05f, // postfx_gradient - 0.9f,0.8f,0.5f, // postfx_gradient_color - 0,0, -0, - 8.0f,0.0f,0.0f,0.0f, // postfx_glass - 0,0,0,0, -0, - 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h - 1.0f,0.0f,0.0f,0.0f, // postfx_moire_v -0, - 0.75f,-0.25f,0.75f,0.0f, // postfx_scanline_h - 1.0f,0.0f,0.0f,0.0f, // postfx_scanline_v -0, - 0.95f,0.9f,0.5f,4.0f, // mirror - 0,0,0,0, -0, - 4.0f,0.9f,16,0.5f, // radial - 0,0,0,0, -/* intex system 4000 */ -0}; - -void Render::InitShaderVar() -{ - int k = theme_i * setup_option_n * 9 + 1; /* main */ - ratio_2d = vec2(theme_var[k], theme_var[k + 1]); k += 2; - border = vec2(theme_var[k], theme_var[k + 1]); k += 2; - k += 5; /* remanence */ - buffer = vec2(theme_var[k], theme_var[k + 1]); k += 2; - remanence = vec2(theme_var[k], theme_var[k + 1]); k += 2; - k += 5; /* glow */ - glow_mix = vec2(theme_var[k], theme_var[k + 1]); k += 2; - glow_large = vec2(theme_var[k], theme_var[k + 1]); k += 2; - glow_small = vec2(theme_var[k], theme_var[k + 1]); k += 2; - k += 3; /* blur */ - blur = vec2(theme_var[k], theme_var[k + 1]); k += 2; - k += 7; /* screen */ - postfx_deform = vec2(theme_var[k], theme_var[k + 1]); k += 2; - postfx_corner = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; - postfx_vignetting = theme_var[k]; k++; - k += 3; /* copper */ - copper_copper = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - copper_mask_color = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; - k += 2; /* color */ - color_filter = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; - color_color = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - postfx_aberration = theme_var[k]; k++; - k += 1; /* noise */ - noise_offset = vec2(theme_var[k], theme_var[k + 1]); k += 2; - noise_noise = theme_var[k]; k++; - noise_retrace = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; - k += 3; /* ghost */ - postfx_ghost1 = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - postfx_ghost2 = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - k += 1; /* gradient */ - postfx_gradient = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; - postfx_gradient_color = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; - k += 3; /* glass */ - postfx_glass = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - k += 5; /* moire */ - postfx_moire_h = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - postfx_moire_v = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - k += 1; /* scanline */ - postfx_scanline_h = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - postfx_scanline_v = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - k += 1; /* mirror */ - mirror = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; - k += 5; /* radial blur */ - radial = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; -} - -void Render::UpdateSize() -{ - screen_size = Video::GetSize(); - canvas_char = (screen_size - border * ratio_2d * font_size * 2) / (font_size * ratio_2d); - canvas_char = max(canvas_char, ivec2(1, 1)); - canvas_size = canvas_char * font_size * ratio_2d; - - border = (screen_size - canvas_size) / 2; - - caca_set_canvas_size(m_cv_screen, canvas_char.x, canvas_char.y); - caca_set_canvas_size(m_cv_setup, setup_size.x + 1, setup_size.y + 1); -} - -int calc_item_length() -{ - int n = !setup_switch ? setup_option_n : setup_item_n; - for (int i = 0; i < n; i++) - { - int k = !setup_switch ? (i * (setup_item_n + 1)) : (setup_option_i * (setup_item_n + 1) + 1 + i); - if (setup_text[k][0] == '\0') return i - 1; - } - return n - 1; -} - -Shader *shader_simple; -Shader *shader_blur_h, *shader_blur_v, *shader_glow; -Shader *shader_remanence, *shader_copper, *shader_color; -Shader *shader_noise, *shader_postfx, *shader_mirror, *shader_radial; -// shader variables -ShaderUniform shader_simple_texture; -ShaderUniform shader_blur_h_texture, - shader_blur_h_radius, - shader_blur_v_texture, - shader_blur_v_radius; -ShaderUniform shader_glow_glow, - shader_glow_source, - shader_glow_mix; -ShaderUniform shader_remanence_source, - shader_remanence_buffer, - shader_remanence_mix; -ShaderUniform shader_copper_texture, - shader_copper_screen_size, - shader_copper_time, - shader_copper_copper, - shader_copper_mask_color; -ShaderUniform shader_color_texture, - shader_color_screen_size, - shader_color_filter, - shader_color_color, - shader_color_flash; -ShaderUniform shader_noise_texture, - shader_noise_screen_size, - shader_noise_time, - shader_noise_offset, - shader_noise_noise, - shader_noise_retrace; -ShaderUniform shader_postfx_texture, - shader_postfx_texture_2d, - shader_postfx_screen_size, - shader_postfx_ratio_2d, - shader_postfx_time, - shader_postfx_deform, - shader_postfx_ghost1, - shader_postfx_ghost2, - shader_postfx_glass, - shader_postfx_vignetting, - shader_postfx_gradient, - shader_postfx_gradient_color, - shader_postfx_aberration, - shader_postfx_moire_h, - shader_postfx_moire_v, - shader_postfx_scanline_h, - shader_postfx_scanline_v, - shader_postfx_corner, - shader_postfx_sync, - shader_postfx_beat; -ShaderUniform shader_mirror_texture, - shader_mirror_screen_size, - shader_mirror_mirror; -ShaderUniform shader_radial_texture, - shader_radial_screen_size, - shader_radial_radial; - -Framebuffer *fbo_back, *fbo_front, *fbo_screen; -Framebuffer *fbo_blur_h, *fbo_blur_v; -Framebuffer *fbo_tmp, *fbo_buffer; - -void Render::TraceQuad() -{ - glLoadIdentity(); - glDrawArrays(GL_QUADS, 0, 4); -} - -void Render::ShaderSimple(Framebuffer *fbo_output, int n) -{ - shader_simple->Bind(); - shader_simple->SetUniform(shader_simple_texture, fbo_output->GetTexture(), n); - TraceQuad(); - shader_simple->Unbind(); -} - -int Render::InitDraw(void) -{ - glDepthMask(GL_TRUE); // do not write z-buffer - - /* initialise framebuffer objects */ - fbo_back = new Framebuffer(screen_size); - fbo_screen = new Framebuffer(screen_size); - fbo_front = new Framebuffer(screen_size); - fbo_buffer = new Framebuffer(screen_size); - fbo_blur_h = new Framebuffer(screen_size); - fbo_blur_v = new Framebuffer(screen_size); - fbo_tmp = new Framebuffer(screen_size); - // shader simple - shader_simple = Shader::Create(LOLFX_RESOURCE_NAME(simple)); - shader_simple_texture = shader_simple->GetUniformLocation("texture"); - // shader glow - shader_glow = Shader::Create(LOLFX_RESOURCE_NAME(glow)); - shader_glow_glow = shader_glow->GetUniformLocation("glow"); - shader_glow_source = shader_glow->GetUniformLocation("source"); - shader_glow_mix = shader_glow->GetUniformLocation("mix"); - // shader blur horizontal - shader_blur_h = Shader::Create(LOLFX_RESOURCE_NAME(blurh)); - shader_blur_h_texture = shader_blur_h->GetUniformLocation("texture"); - shader_blur_h_radius = shader_blur_h->GetUniformLocation("radius"); - // shader blur vertical - shader_blur_v = Shader::Create(LOLFX_RESOURCE_NAME(blurv)); - shader_blur_v_texture = shader_blur_v->GetUniformLocation("texture"); - shader_blur_v_radius = shader_blur_v->GetUniformLocation("radius"); - // shader remanence - shader_remanence = Shader::Create(LOLFX_RESOURCE_NAME(remanence)); - shader_remanence_source = shader_remanence->GetUniformLocation("source"); - shader_remanence_buffer = shader_remanence->GetUniformLocation("buffer"); - shader_remanence_mix = shader_remanence->GetUniformLocation("mix"); - // shader copper - shader_copper = Shader::Create(LOLFX_RESOURCE_NAME(copper)); - shader_copper_texture = shader_copper->GetUniformLocation("texture"); - shader_copper_screen_size = shader_copper->GetUniformLocation("screen_size"); - shader_copper_time = shader_copper->GetUniformLocation("time"); - shader_copper_copper = shader_copper->GetUniformLocation("copper"); - shader_copper_mask_color = shader_copper->GetUniformLocation("mask_color"); - // shader color - shader_color = Shader::Create(LOLFX_RESOURCE_NAME(color)); - shader_color_texture = shader_color->GetUniformLocation("texture"); - shader_color_screen_size = shader_color->GetUniformLocation("screen_size"); - shader_color_filter = shader_color->GetUniformLocation("filter"); - shader_color_color = shader_color->GetUniformLocation("color"); - shader_color_flash = shader_color->GetUniformLocation("flash"); - // shader noise - shader_noise = Shader::Create(LOLFX_RESOURCE_NAME(noise)); - shader_noise_texture = shader_noise->GetUniformLocation("texture"); - shader_noise_screen_size = shader_noise->GetUniformLocation("screen_size"); - shader_noise_time = shader_noise->GetUniformLocation("time"); - shader_noise_offset = shader_noise->GetUniformLocation("offset"); - shader_noise_noise = shader_noise->GetUniformLocation("noise"); - shader_noise_retrace = shader_noise->GetUniformLocation("retrace"); - // shader postfx - shader_postfx = Shader::Create(LOLFX_RESOURCE_NAME(postfx)); - shader_postfx_texture = shader_postfx->GetUniformLocation("texture"); - shader_postfx_texture_2d = shader_postfx->GetUniformLocation("texture_2d"); - shader_postfx_screen_size = shader_postfx->GetUniformLocation("screen_size"); - shader_postfx_ratio_2d = shader_postfx->GetUniformLocation("ratio_2d"); - shader_postfx_time = shader_postfx->GetUniformLocation("time"); - shader_postfx_deform = shader_postfx->GetUniformLocation("deform"); - shader_postfx_ghost1 = shader_postfx->GetUniformLocation("ghost1"); - shader_postfx_ghost2 = shader_postfx->GetUniformLocation("ghost2"); - shader_postfx_glass = shader_postfx->GetUniformLocation("glass"); - shader_postfx_gradient = shader_postfx->GetUniformLocation("gradient"); - shader_postfx_gradient_color = shader_postfx->GetUniformLocation("gradient_color"); - shader_postfx_vignetting = shader_postfx->GetUniformLocation("vignetting"); - shader_postfx_aberration = shader_postfx->GetUniformLocation("aberration"); - shader_postfx_moire_h = shader_postfx->GetUniformLocation("moire_h"); - shader_postfx_moire_v = shader_postfx->GetUniformLocation("moire_v"); - shader_postfx_scanline_h = shader_postfx->GetUniformLocation("scanline_h"); - shader_postfx_scanline_v = shader_postfx->GetUniformLocation("scanline_v"); - shader_postfx_corner = shader_postfx->GetUniformLocation("corner"); - shader_postfx_sync = shader_postfx->GetUniformLocation("sync"); - shader_postfx_beat = shader_postfx->GetUniformLocation("beat"); - // shader mirror - shader_mirror = Shader::Create(LOLFX_RESOURCE_NAME(mirror)); - shader_mirror_texture = shader_mirror->GetUniformLocation("texture"); - shader_mirror_screen_size = shader_mirror->GetUniformLocation("screen_size"); - shader_mirror_mirror = shader_mirror->GetUniformLocation("mirror"); - // shader radial blur - shader_radial = Shader::Create(LOLFX_RESOURCE_NAME(radial)); - shader_radial_texture = shader_radial->GetUniformLocation("texture"); - shader_radial_screen_size = shader_radial->GetUniformLocation("screen_size"); - shader_radial_radial = shader_radial->GetUniformLocation("radial"); - // initialize setup - setup_n = calc_item_length(); - return true; -} - -int Render::CreateGLWindow() -{ - InitShaderVar(); - UpdateSize(); - InitDraw(); - return true; -} - -Render::Render(caca_canvas_t *caca) - : m_cv_screen(caca), - m_cv_setup(caca_create_canvas(1, 1)), - m_fps_debug(0), - m_ready(false), - m_pause(false), - m_shader(true), - m_shader_remanence(true), - m_shader_glow(true), - m_shader_blur(true), - m_shader_postfx(true), - m_shader_copper(true), - m_shader_color(true), - m_shader_noise(true), - m_shader_mirror(true), - m_shader_radial(true) -{ - m_txt_screen = new TextRender(m_cv_screen, font_size); - m_txt_setup = new TextRender(m_cv_setup, font_size); -} - -void Render::TickGame(float seconds) -{ - Entity::TickGame(seconds); - /* draw setup */ - if (g_setup) - { - /* background */ - caca_set_color_argb(m_cv_setup, setup_color.x, setup_color.y); - caca_fill_box(m_cv_setup, 0, 0, setup_size.x + 1, setup_size.y,' '); - caca_draw_line(m_cv_setup, setup_size.z - 1, 1, setup_size.z - 1, setup_size.y - 1,'|'); - /* title */ - caca_set_color_argb(m_cv_setup, setup_color.y, setup_color.x); - caca_draw_line(m_cv_setup, 0, 0, setup_size.x, 0, ' '); - caca_put_str(m_cv_setup, setup_size.x / 2 - 3, 0, "SETUP"); - /* informations */ - /* - int w = caca_get_canvas_width(m_cv_screen); - int h = caca_get_canvas_height(m_cv_screen); - caca_set_color_argb(m_cv_setup, setup_color.y, setup_color.x); - caca_printf(m_cv_setup, 1, 0, "%i*%i", w, h); - */ - /* display option */ - for (int i = 0; i < setup_h; i++) - { - int y = 1 + i; - int k = (setup_option_p + i) * (setup_item_n + 1); - if (setup_option_i != setup_option_p + i || setup_switch) - { - caca_set_color_argb(m_cv_setup, setup_color.x, setup_color.y); - caca_put_str(m_cv_setup, 1, y, setup_text[k]); - } - else - { - caca_set_color_argb(m_cv_setup, setup_color.y, 0x0f0);//setup_color.x); - caca_draw_line(m_cv_setup, 0, y, setup_size.z - 2, y,' '); - caca_put_str(m_cv_setup, 1, y, setup_text[k]); - } - } - /* display item */ - for (int i = 0; i < setup_h; i++) - { - int y = 1 + i; - int k = setup_option_i * (setup_item_n + 1) + 1 + setup_item_p + i; - if (setup_item_i != setup_item_p + i || !setup_switch) - { - caca_set_color_argb(m_cv_setup, setup_color.x, setup_color.y); - caca_put_str(m_cv_setup, setup_size.z + 1, y, setup_text[k]); - } - else - { - caca_set_color_argb(m_cv_setup, setup_color.y, 0x0f0);//setup_color.x); - caca_draw_line(m_cv_setup, setup_size.z, y, setup_size.x, y,' '); - caca_put_str(m_cv_setup, setup_size.z + 1, y, setup_text[k]); - } - } - /* display variable */ - int y = setup_size.y; - setup_item_key = setup_option_i * (setup_item_n + 1) + 1 + setup_item_i; - theme_var_key = theme_i * setup_option_n * 9 + setup_item_key; - caca_set_color_argb(m_cv_setup, setup_color.y, setup_color.x); - caca_draw_line(m_cv_setup, 0, y, setup_size.x, y,' '); - if (setup_switch) - { - int x = 1; - int w = setup_size.x - 3 - 4; - float bar_w = w / (setup_conf[setup_item_key].y - setup_conf[setup_item_key].x); - int bar_x = bar_w * setup_conf[setup_item_key].x; - if ((setup_conf[setup_item_key].y - setup_conf[setup_item_key].x) / setup_conf[setup_item_key].z > 1) - { - /* work around a bug in libcaca */ - if (setup_size.x - 4 < caca_get_canvas_width(m_cv_setup)) caca_printf(m_cv_setup, setup_size.x - 4, y, "%4.2f", theme_var[theme_var_key]); - caca_draw_line(m_cv_setup, x, y, x - bar_x + int(bar_w * setup_conf[setup_item_key].y), y,'.'); - if (theme_var[theme_var_key] != setup_conf[setup_item_key].x) caca_draw_line(m_cv_setup, x, y, x - bar_x + int(bar_w * theme_var[theme_var_key]), y, 'x'); - } - else - { - if (setup_conf[setup_item_key] != vec4(0)) - { - caca_put_str(m_cv_setup, setup_size.x - 3, y, (theme_var[theme_var_key] == setup_conf[setup_item_key].y)?"YES":" NO"); - } - } - } - else - { - caca_printf(m_cv_setup, 1, y, "%d/%d", setup_option_i, setup_n); - } - } - -} - -void Render::Pause() -{ - m_pause=!m_pause; -} - -void Render::TickDraw(float seconds) -{ - /* keyboard manager */ - if (Input::WasPressed(Key::F1)) - { - g_setup = !g_setup; - if (g_setup) setup_n = calc_item_length(); - sync_flag = true; - sync_angle = main_angle; - if (m_fps_debug) - { - Ticker::Unref(m_fps_debug); - m_fps_debug = NULL; - } - if (g_setup) - { - m_fps_debug = new DebugFps(2, 2); - Ticker::Ref(m_fps_debug); - } - } - if (Input::WasPressed(Key::F2)) - { - m_shader_remanence = !m_shader_remanence; - m_shader_glow = !m_shader_glow; - m_shader_blur = !m_shader_blur; - m_shader_postfx = !m_shader_postfx; - //m_shader_copper = !m_shader_copper; - m_shader_color = !m_shader_color; - m_shader_noise = !m_shader_noise; - m_shader_mirror = !m_shader_mirror; - m_shader_radial = !m_shader_radial; - } - if (Input::WasPressed(Key::F4)) - { - theme_i--; - if(theme_i < 0) theme_i = theme_n - 1; - InitShaderVar(); - UpdateSize(); - } - if (Input::WasPressed(Key::F5)) - { - theme_i++; - if(theme_i > theme_n - 1) theme_i = 0; - InitShaderVar(); - UpdateSize(); - } - if (Input::WasPressed(Key::Tab)) - { - if (g_setup) - { - setup_switch = !setup_switch; - setup_n = calc_item_length(); - setup_cursor = (!setup_switch?setup_option_i:setup_item_i) - (!setup_switch?setup_option_p:setup_item_p); - } - } - if (Input::WasPressed(Key::Up)) - { - if (g_setup) - { - if (!setup_switch) - { - if (setup_cursor > 0) - { - setup_cursor--; - } - else - { - if (setup_cursor == 0) setup_option_p--; - } - if (setup_option_i > 0) - { - setup_option_i--; - } - else - { - setup_option_i = setup_option_n - 1; - setup_option_p = setup_option_n - setup_h; - setup_cursor = setup_h - 1; - } - setup_item_i = 0; - setup_item_p = 0; - } - else - { - if (setup_cursor > 0) - { - setup_cursor--; - } - else - { - if (setup_cursor == 0) setup_item_p--; - } - if (setup_item_i > 0) - { - setup_item_i--; - } - else - { - setup_item_i = setup_n; - setup_item_p = (setup_n < setup_h) ? 0 : setup_n - setup_h + 1; - setup_cursor = (setup_n < setup_h) ? setup_n : setup_h - 1; - } - } - } - } - if (Input::WasPressed(Key::Down)) - { - if (g_setup) - { - if (!setup_switch) - { - if (setup_cursor < setup_h - 1) - { - setup_cursor++; - } - else - { - if (setup_cursor == setup_h - 1) setup_option_p++; - } - if (setup_option_i < setup_option_n - 1) - { - setup_option_i++; - } - else - { - setup_option_i = 0; - setup_option_p = 0; - setup_cursor = 0; - } - setup_item_i = 0; - setup_item_p = 0; - } - else - { - if (setup_cursor < setup_h - 1) - { - setup_cursor++; - } - else - { - if (setup_cursor == setup_h - 1) setup_item_p++; - } - if (setup_item_i < setup_n) - { - setup_item_i++; - } - else - { - setup_item_i = 0; - setup_item_p = 0; - setup_cursor = 0; - } - } - } - } - if (Input::WasPressed(Key::PageUp)) - { - if (g_setup) - { - if (!setup_switch) - { - if (setup_cursor > 0) - { - setup_option_i -= setup_cursor; - setup_cursor = 0; - } - else - { - if (setup_option_i > setup_h) - { - setup_option_i -= setup_h; - setup_option_p -= setup_h; - } - else - { - setup_option_i = 0; - setup_option_p = 0; - } - } - setup_item_i = 0; - } - else - { - if (setup_cursor > 0) - { - setup_item_i -= setup_cursor; - setup_cursor = 0; - } - else - { - if (setup_item_i > setup_h) - { - setup_item_i -= setup_h; - setup_item_p -= setup_h; - } - else - { - setup_item_i = 0; - setup_item_p = 0; - } - } - } - } - } - if (Input::WasPressed(Key::PageDown)) - { - if (g_setup) - { - if (!setup_switch) - { - if (setup_cursor < setup_h - 1) - { - setup_option_i += setup_h - setup_cursor - 1; - setup_cursor = setup_h - 1; - setup_item_i = 0; - } - else - { - if (setup_option_i < setup_option_n - setup_h - 1) - { - setup_option_i += setup_h; - setup_option_p += setup_h; - } - else - { - setup_option_i = setup_option_n - 1; - setup_option_p = setup_option_n - setup_h; - } - } - } - else - { - if (setup_cursor < setup_h - 1) - { - setup_item_i += (setup_n < setup_h) ? setup_n - setup_cursor : setup_h - setup_cursor - 1; - setup_cursor = (setup_n < setup_h) ? setup_n : setup_h - 1; - } - else - { - if (setup_item_i < setup_n - setup_h + 1) - { - setup_item_i += setup_h; - setup_item_p += setup_h; - } - else - { - setup_item_i = setup_n; - setup_item_p = setup_n - setup_h + 1; - } - } - } - } - } - if (Input::WasPressed(Key::Left)) - { - if (g_setup && setup_switch) - { - theme_var[theme_var_key] -= setup_conf[setup_item_key].z; - if (theme_var[theme_var_key] < setup_conf[setup_item_key].x) theme_var[theme_var_key] = setup_conf[setup_item_key].x; - InitShaderVar(); - UpdateSize(); - } - } - if (Input::WasPressed(Key::Right)) - { - if (g_setup && setup_switch) - { - theme_var[theme_var_key] += setup_conf[setup_item_key].z; - if (theme_var[theme_var_key] > setup_conf[setup_item_key].y) theme_var[theme_var_key] = setup_conf[setup_item_key].y; - InitShaderVar(); - UpdateSize(); - } - } - if (Input::WasPressed(Key::Home)) - { - if (g_setup && setup_switch) - { - theme_var[theme_var_key] = setup_conf[setup_item_key].x; - InitShaderVar(); - UpdateSize(); - } - } - if (Input::WasPressed(Key::End)) - { - if (g_setup && setup_switch) - { - theme_var[theme_var_key] = setup_conf[setup_item_key].y; - InitShaderVar(); - UpdateSize(); - } - } - if (Input::WasPressed(Key::Return)) - { - beat_flag = true; - beat_angle = main_angle; - //flash_flag = true; - //flash_angle = main_angle; - } - - Entity::TickDraw(seconds); - - if (!m_ready) - { - CreateGLWindow(); - m_txt_screen->Init(); - m_txt_setup->Init(); - m_ready = true; - } - - // timer - if (!m_pause) - { - timer += seconds; - main_angle = timer * 100.0f * PID; - } - if (sync_flag) - { - angle = (main_angle - sync_angle) * sync_speed; - sync_value = 1.0f - sinf(angle); - if (angle > 90.0f * PID) - { - sync_value = 0; - sync_flag = false; - } - } - if (beat_flag) - { - angle = (main_angle - beat_angle) * beat_speed; - beat_value = 1.0f - sinf(angle); - if (angle > 90.0f * PID) - { - beat_value = 0; - beat_flag = false; - } - } - if (flash_flag) - { - angle = (main_angle - flash_angle) * flash_speed; - flash_value = 1.0f - sinf(angle); - if (angle > 90.0f * PID) - { - flash_value = 0; - flash_flag = false; - } - } - if (fade_flag) - { - angle = (main_angle - fade_angle) * fade_speed; - fade_value = 1.0f - sinf(angle); - if (angle > 90.0f * PID) - { - fade_value = 0; - fade_flag = false; - } - } - - Draw2D(); - Draw3D(); -} - -void Render::Draw2D() -{ - /* Draw text in an offline buffer */ - m_txt_screen->Render(); - - if (g_setup) - m_txt_setup->Render(); - - if (m_shader) - fbo_back->Bind(); - - glViewport(0, 0, screen_size.x, screen_size.y); - - /* Clear the back buffer */ - - RenderContext rc; - rc.SetBlendFunc(BlendFunc::SrcColor, BlendFunc::DstAlpha); - rc.SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f)); - rc.SetClearDepth(1.0f); // set depth buffer - - glEnable(GL_TEXTURE_2D); - - g_renderer->Clear(ClearMask::Color | ClearMask::Depth); - - m_txt_screen->Blit(border, canvas_size); - if (g_setup) - m_txt_setup->Blit((screen_size - setup_canvas_size) / 2, setup_canvas_size); - - glMatrixMode(GL_PROJECTION); - mat4 m = mat4::ortho(0, screen_size.x, screen_size.y, 0, -1.f, 1.f); - glLoadMatrixf(&m[0][0]); - glMatrixMode(GL_MODELVIEW); - - fx_angle = main_angle - part_angle; -} - -void Render::Draw3D() -{ - if (!m_shader) - return; - - RenderContext rc; - rc.SetBlendFunc(BlendFunc::Disabled, BlendFunc::Disabled); - rc.SetDepthFunc(DepthFunc::Disabled); - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(4, GL_FLOAT, 0, fs_quad_vtx); - - if (m_shader_copper) - { - // shader copper - fbo_tmp->Bind(); - shader_copper->Bind(); - shader_copper->SetUniform(shader_copper_texture, fbo_back->GetTexture(), 0); - shader_copper->SetUniform(shader_copper_screen_size, (vec2)screen_size); - shader_copper->SetUniform(shader_copper_time, fx_angle); - shader_copper->SetUniform(shader_copper_copper, vec4(copper_copper.x, copper_copper.y, copper_copper.z * 16.0f, copper_copper.w * 16.0f)); - shader_copper->SetUniform(shader_copper_mask_color, copper_mask_color); - TraceQuad(); - shader_color->Unbind(); - fbo_tmp->Unbind(); - // shader simple - fbo_back->Bind(); - ShaderSimple(fbo_tmp, 0); - fbo_back->Unbind(); - } - - if (m_shader_remanence) - { - // shader remanence - fbo_tmp->Bind(); - shader_remanence->Bind(); - shader_remanence->SetUniform(shader_remanence_source, fbo_back->GetTexture(), 0); - shader_remanence->SetUniform(shader_remanence_buffer, fbo_buffer->GetTexture(), 1); - shader_remanence->SetUniform(shader_remanence_mix, remanence); - TraceQuad(); - shader_remanence->Unbind(); - fbo_tmp->Unbind(); - // shader simple - fbo_back->Bind(); - ShaderSimple(fbo_tmp, 0); - fbo_back->Unbind(); - // save previous fbo - fbo_tmp->Bind(); - shader_remanence->Bind(); - shader_remanence->SetUniform(shader_remanence_source, fbo_screen->GetTexture(), 0); - shader_remanence->SetUniform(shader_remanence_buffer, fbo_buffer->GetTexture(), 1); - shader_remanence->SetUniform(shader_remanence_mix, buffer); - TraceQuad(); - shader_remanence->Unbind(); - fbo_tmp->Unbind(); - // shader simple - fbo_buffer->Bind(); - ShaderSimple(fbo_tmp, 0); - fbo_buffer->Unbind(); - } - - // shader glow - if (m_shader_glow) - { - // shader blur horizontal - fbo_blur_h->Bind(); - shader_blur_h->Bind(); - shader_blur_h->SetUniform(shader_blur_h_texture, fbo_back->GetTexture(), 0); - shader_blur_h->SetUniform(shader_blur_h_radius, glow_large / (float)screen_size.x); - TraceQuad(); - shader_blur_h->Unbind(); - fbo_blur_h->Unbind(); - // shader blur vertical - fbo_blur_v->Bind(); - shader_blur_v->Bind(); - shader_blur_v->SetUniform(shader_blur_v_texture, fbo_blur_h->GetTexture(), 0); - shader_blur_v->SetUniform(shader_blur_v_radius, glow_large / (float)screen_size.y); - TraceQuad(); - shader_blur_v->Unbind(); - fbo_blur_v->Unbind(); - // shader blur horizontal - fbo_blur_h->Bind(); - shader_blur_h->Bind(); - shader_blur_h->SetUniform(shader_blur_h_texture, fbo_blur_v->GetTexture(), 0); - shader_blur_h->SetUniform(shader_blur_h_radius, glow_small / (float)screen_size.x); - TraceQuad(); - shader_blur_h->Unbind(); - fbo_blur_h->Unbind(); - // shader blur vertical - fbo_blur_v->Bind(); - shader_blur_v->Bind(); - shader_blur_v->SetUniform(shader_blur_v_texture, fbo_blur_h->GetTexture(), 0); - shader_blur_v->SetUniform(shader_blur_v_radius, glow_small / (float)screen_size.y); - TraceQuad(); - shader_blur_v->Unbind(); - fbo_blur_v->Unbind(); - // shader glow - fbo_screen->Bind(); - shader_glow->Bind(); - shader_glow->SetUniform(shader_glow_glow, fbo_blur_v->GetTexture(), 0); - shader_glow->SetUniform(shader_glow_source, fbo_back->GetTexture(), 1); - shader_glow->SetUniform(shader_glow_mix, glow_mix); - TraceQuad(); - shader_glow->Unbind(); - fbo_screen->Unbind(); - } - else - { - // shader simple - fbo_screen->Bind(); - ShaderSimple(fbo_back, 0); - fbo_screen->Unbind(); - } - - if (m_shader_color) - { - // shader color - fbo_tmp->Bind(); - shader_color->Bind(); - shader_color->SetUniform(shader_color_texture, fbo_screen->GetTexture(), 0); - shader_color->SetUniform(shader_color_screen_size, (vec2)screen_size); - shader_color->SetUniform(shader_color_filter, color_filter); - shader_color->SetUniform(shader_color_color, color_color); - shader_color->SetUniform(shader_color_flash, flash_value); - TraceQuad(); - shader_color->Unbind(); - fbo_tmp->Unbind(); - // shader simple - fbo_screen->Bind(); - ShaderSimple(fbo_tmp, 0); - fbo_screen->Unbind(); - } - - if (m_shader_noise) - { - // shader noise - fbo_tmp->Bind(); - shader_noise->Bind(); - shader_noise->SetUniform(shader_noise_texture, fbo_screen->GetTexture(), 0); - shader_noise->SetUniform(shader_noise_screen_size, (vec2)screen_size); - shader_noise->SetUniform(shader_noise_time, fx_angle); - shader_noise->SetUniform(shader_noise_offset, noise_offset); - shader_noise->SetUniform(shader_noise_noise, noise_noise); - shader_noise->SetUniform(shader_noise_retrace, noise_retrace); - TraceQuad(); - shader_noise->Unbind(); - fbo_tmp->Unbind(); - // shader simple - fbo_screen->Bind(); - ShaderSimple(fbo_tmp, 0); - fbo_screen->Unbind(); - } - - if (m_shader_blur) - { - // shader blur horizontal - fbo_tmp->Bind(); - shader_blur_h->Bind(); - shader_blur_h->SetUniform(shader_blur_h_texture, fbo_screen->GetTexture(), 0); - shader_blur_h->SetUniform(shader_blur_h_radius, blur / (float)screen_size.x); - TraceQuad(); - shader_blur_h->Unbind(); - fbo_tmp->Unbind(); - // shader blur vertical - fbo_screen->Bind(); - shader_blur_v->Bind(); - shader_blur_v->SetUniform(shader_blur_v_texture, fbo_tmp->GetTexture(), 0); - shader_blur_v->SetUniform(shader_blur_v_radius, blur / (float)screen_size.y); - TraceQuad(); - shader_blur_v->Unbind(); - fbo_screen->Unbind(); - } - - if (m_shader_postfx) - { - // shader postfx - fbo_front->Bind(); - shader_postfx->Bind(); - shader_postfx->SetUniform(shader_postfx_texture, fbo_screen->GetTexture(), 0); - shader_postfx->SetUniform(shader_postfx_screen_size, (vec2)screen_size); - shader_postfx->SetUniform(shader_postfx_ratio_2d, (vec2)ratio_2d * 0.5f); - shader_postfx->SetUniform(shader_postfx_time, fx_angle); - shader_postfx->SetUniform(shader_postfx_deform, postfx_deform); - shader_postfx->SetUniform(shader_postfx_ghost1, vec4(postfx_ghost1.xyz * 0.01f, postfx_ghost1.w)); - shader_postfx->SetUniform(shader_postfx_ghost2, vec4(postfx_ghost2.xyz * 0.01f, postfx_ghost2.w)); - shader_postfx->SetUniform(shader_postfx_glass, vec4(postfx_glass.xy * 0.01f, postfx_glass.z * 0.1f, postfx_glass.w)); - shader_postfx->SetUniform(shader_postfx_gradient, postfx_gradient); - shader_postfx->SetUniform(shader_postfx_gradient_color, postfx_gradient_color); - shader_postfx->SetUniform(shader_postfx_vignetting, postfx_vignetting); - shader_postfx->SetUniform(shader_postfx_aberration, postfx_aberration); - shader_postfx->SetUniform(shader_postfx_moire_h, vec4(postfx_moire_h.xyz, postfx_moire_h.w * (2 * F_PI))); - shader_postfx->SetUniform(shader_postfx_moire_v, vec4(postfx_moire_v.xyz, postfx_moire_v.w * (2 * F_PI))); - shader_postfx->SetUniform(shader_postfx_scanline_h, vec4(postfx_scanline_h.xyz, postfx_scanline_h.w * (2 * F_PI))); - shader_postfx->SetUniform(shader_postfx_scanline_v, vec4(postfx_scanline_v.xyz, postfx_scanline_v.w * (2 * F_PI))); - shader_postfx->SetUniform(shader_postfx_corner, postfx_corner); - shader_postfx->SetUniform(shader_postfx_sync, (float)fabs(sync_value * cosf((main_angle - sync_angle) * 6.0f))); - shader_postfx->SetUniform(shader_postfx_beat, (float)fabs(beat_value * cosf((main_angle - beat_angle) * 6.0f))); - TraceQuad(); - shader_postfx->Unbind(); - fbo_front->Unbind(); - } - else - { - // shader simple - fbo_front->Bind(); - ShaderSimple(fbo_screen, 0); - fbo_front->Unbind(); - } - - if (m_shader_mirror) - { - // shader mirror - fbo_tmp->Bind(); - shader_mirror->Bind(); - shader_mirror->SetUniform(shader_mirror_texture, fbo_front->GetTexture(), 0); - shader_mirror->SetUniform(shader_mirror_screen_size, (vec2)screen_size); - shader_mirror->SetUniform(shader_mirror_mirror, vec4(mirror.x * 0.1f, mirror.y * 0.1f, mirror.z, mirror.w)); - TraceQuad(); - shader_mirror->Unbind(); - fbo_tmp->Unbind(); - // shader simple - fbo_front->Bind(); - ShaderSimple(fbo_tmp, 0); - fbo_front->Unbind(); - } - - if (m_shader_radial) - { - // shader radial blur - fbo_tmp->Bind(); - shader_radial->Bind(); - shader_radial->SetUniform(shader_radial_texture, fbo_front->GetTexture(), 0); - shader_radial->SetUniform(shader_radial_screen_size, (vec2)screen_size); - shader_radial->SetUniform(shader_radial_radial, vec4(radial.x, radial.y, radial.z, radial.w * 0.1f)); - TraceQuad(); - shader_radial->Unbind(); - fbo_tmp->Unbind(); - // shader simple - fbo_front->Bind(); - ShaderSimple(fbo_tmp, 0); - fbo_front->Unbind(); - } - - // shader simple - ShaderSimple(fbo_front, 0); - - glDisableClientState(GL_VERTEX_ARRAY); -} - -Render::~Render() -{ - if (m_fps_debug) - Ticker::Unref(m_fps_debug); -} +// // Neercs // #if defined HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include "core.h" #include "lolgl.h" #include "loldebug.h" using namespace std; using namespace lol; #include "../neercs.h" #include "render.h" #include "text-render.h" LOLFX_RESOURCE_DECLARE(simple); LOLFX_RESOURCE_DECLARE(blurh); LOLFX_RESOURCE_DECLARE(blurv); LOLFX_RESOURCE_DECLARE(glow); LOLFX_RESOURCE_DECLARE(remanence); LOLFX_RESOURCE_DECLARE(copper); LOLFX_RESOURCE_DECLARE(color); LOLFX_RESOURCE_DECLARE(noise); LOLFX_RESOURCE_DECLARE(postfx); LOLFX_RESOURCE_DECLARE(mirror); LOLFX_RESOURCE_DECLARE(radial); #define PID F_PI/180.0f // pi ratio /* * Global variable -- ugly ( sam: c'est toi qui est ugly! \:D/) */ bool g_setup = false; /* * Various variables */ int active = true; // window active flag float nearplane = 0.1f; // nearplane float farplane = 1000.0f; // farplane /* timer variable */ float timer = 0; // timer /* window variable */ ivec2 screen_size; // screen size /* object variable */ float main_angle = 0.0f; // main angle float part_angle = 0.0f; // part angle float fx_angle; // current angle /* fs_quad variable */ float fs_quad_vtx[] = { -1.0f, 1.0f, 0, 1.0f, -1.0f, -1.0f, 0, 1.0f, 1.0f, -1.0f, 0, 1.0f, 1.0f, 1.0f, 0, 1.0f }; /* flash variable */ bool flash_flag = false; // flag float flash_angle = 0; // angle float flash_value = 0; // value float flash_speed = 2.0f; // speed /* fade variable */ bool fade_flag = false; // flag float fade_angle = 0; // angle float fade_value = 0; // value float fade_speed = 0.2f; // speed /* sync variable */ bool sync_flag = false; // flagsh float sync_angle = 0; // angle float sync_value = 0; // value float sync_speed = 1.0f; // speed /* beat variable */ bool beat_flag = false; // flag float beat_angle = 0; // angle float beat_value = 0; // value float beat_speed = 2.0f; // speed /* common variable */ float value, angle, radius, scale, speed; /* text variable */ ivec2 map_size(256,256); // texture map size ivec2 canvas_char(0,0); // canvas char number ivec2 canvas_size(0,0); // caca size ivec2 font_size(8,8); // font size ivec2 ratio_2d(1,1); // 2d ratio ivec2 border(0,0); // border width /* shader variable */ vec2 buffer; // [new frame mix,old frame mix] vec2 remanence; // remanence [source mix,buffer mix] vec2 glow_mix; // glow mix [source mix,glow mix] vec2 glow_large; // large glow radius [center,corner] vec2 glow_small; // small glow radius [center,corner] vec2 blur; // blur radius [center,corner] vec4 copper_copper; // copper [base,variable,repeat,color cycle] vec3 copper_mask_color; // color [red,green,blue] vec3 color_filter; // color filter [red,green,blue] vec4 color_color; // color modifier [brightness,contrast,level,grayscale] vec2 noise_offset; // random line [horizontal,vertical] float noise_noise; // noise vec3 noise_retrace; // retrace [strength,length,speed] vec2 postfx_deform; // deformation [ratio,zoom] float postfx_vignetting; // vignetting strength float postfx_aberration; // chromatic aberration vec4 postfx_ghost1; // ghost picture 1 [position x,position y,position z,strength] vec4 postfx_ghost2; // ghost picture 2 [position x,position y,position z,strength] vec3 postfx_gradient; // gradient [position y,height,strength] vec3 postfx_gradient_color;// gradient color [red,green,blue] vec4 postfx_glass; // glass [depth,thickness,strength,deform ratio] vec4 postfx_moire_h; // vertical moire [base,variable,repeat,shift] vec4 postfx_moire_v; // horizontal moire [base,variable,repeat,shift] vec4 postfx_scanline_h; // vertical scanline [base,variable,repeat,shift] vec4 postfx_scanline_v; // horizontal scanline [base,variable,repeat,shift] vec3 postfx_corner; // corner [width,radius,blur] vec4 mirror; // mirror [width,height,strength,ratio] vec4 radial; // radial [distance,fade ratio,iteration,strength] /* theme variable */ int theme_i = 0; // current theme const int theme_n = 5; // theme number int theme_var_key = 0; // theme array key /* setup variable */ bool setup_switch = false; // switch [option/item] int setup_n = 0; // item/option number int setup_h = 8; // height int setup_cursor = 0; // cursor position int setup_option_i = 0; // selected option const int setup_option_n = 15; // option number int setup_option_p = 0; // option position int setup_item_i = 0; // selected item int setup_item_n = 8; // item number int setup_item_p = 0; // item position int setup_item_key = 0; // item array key ivec3 setup_size(29, 9, 12); // size [w,h,split] ivec2 setup_canvas_size(ivec2(setup_size.x + 1, setup_size.y + 1) * font_size * ivec2(2,4)); ivec2 setup_color(0xaaa, 0x222);// color [foreground,background] 0x678,0x234 char const *setup_text[]={ "main", "2d ratio w", "2d ratio h", "border w", "border h", "", "", "", "", "remanence", "buffer new frame", "buffer old frame", "source mix", "buffer mix", "", "", "", "", "glow", "source mix", "glow mix", "large center", "large corner", "small center", "small corner", "", "", "blur", "blur center", "blur corner", "", "", "", "", "", "", "screen", "deform ratio", "zoom base", "corner width", "corner radius", "corner blur", "vignetting", "", "", "copper", "base", "variable", "repeat", "color cycle", "color r", "color g", "color b", "", "color", "filter red", "filter green", "filter blue", "brightness", "contrast", "level", "grayscale", "aberration", "noise", "offset h", "offset v", "noise", "retrace strength", "retrace length", "retrace speed", "", "", "ghost", "back x", "back y", "back z", "back strength", "front x", "front y", "front z", "front strength", "gradient", "position", "thickness", "strength", "color r", "color g", "color b", "", "", "glass", "depth", "thickness", "strength", "deform ratio", "", "", "", "", "moire", "h base", "h variable", "h repeat", "h shift", "v base", "v variable", "v repeat", "v shift", "scanline", "h base", "h variable", "h repeat", "h shift", "v base", "v variable", "v repeat", "v shift", "mirror", "enable", "width", "height", "strength", "ratio", "", "", "", "radial", "distance", "fade ratio", "iteration", "strength", "", "", "", "", "" }; vec4 setup_conf[]={ // setup variable [start,end,step,value] vec4(0), /* main */ vec4(1, 8, 1, 0), // ratio_2d.x vec4(1, 8, 1, 0), // ratio_2d.y vec4(0, 16, 1, 0), // border.x vec4(0, 16, 1, 0), // border.y vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), /* remanence */ vec4(0.0f, 1.0f, 0.1f, 0), // buffer.x vec4(0.0f, 1.0f, 0.1f, 0), // buffer.y vec4(0.0f, 1.0f, 0.1f, 0), // remanence.x vec4(0.0f, 1.0f, 0.1f, 0), // remanence.y vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), /* glow */ vec4(0.0f, 1.0f, 0.1f, 0), // glow_mix.x vec4(0.0f, 1.0f, 0.1f, 0), // glow_mix.y vec4(0.0f, 4.0f, 0.1f, 0), // glow_large.x vec4(0.0f, 4.0f, 0.1f, 0), // glow_large.y vec4(0.0f, 2.0f, 0.1f, 0), // glow_small.x vec4(0.0f, 2.0f, 0.1f, 0), // glow_small.y vec4(0), vec4(0), vec4(0), /* blur */ vec4(0, 2, 0.05f, 0), // blur.x vec4(0, 2, 0.05f, 0), // blur.y vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), /* screen */ vec4(0.0f, 1.0f, 0.05f, 0), // postfx_deform.x vec4(0.2f, 0.7f, 0.01f, 0), // postfx_deform.y vec4(0.0f, 4.0f, 0.10f, 0), // postfx_corner.x vec4(0.0f, 1.0f, 0.05f, 0), // postfx_corner.y vec4(0.8f, 1.0f, 0.01f, 0), // postfx_corner.z vec4(0.0f, 1.0f, 0.10f, 0), // postfx_vignetting vec4(0), vec4(0), vec4(0), /* copper */ vec4(0.0f, 1.0f, 0.05f, 0), // copper_copper.x vec4(0.0f, 1.0f, 0.05f, 0), // copper_copper.y vec4(0.0f, 1.0f, 0.02f, 0), // copper_copper.z vec4(1.0f, 8.0f, 0.25f, 0), // copper_copper.w vec4(0.0f, 1.0f, 0.05f, 0), // copper_mask_color.x vec4(0.0f, 1.0f, 0.05f, 0), // copper_mask_color.y vec4(0.0f, 1.0f, 0.05f, 0), // copper_mask_color.z vec4(0), vec4(0), /* color */ vec4( 0.0f, 1.0f, 0.05f, 0), // color_filter.x vec4( 0.0f, 1.0f, 0.05f, 0), // color_filter.y vec4( 0.0f, 1.0f, 0.05f, 0), // color_filter.z vec4( 0.0f, 2.0f, 0.05f, 0), // color_color.x vec4( 0.0f, 2.0f, 0.05f, 0), // color_color.y vec4(-1.0f, 1.0f, 0.05f, 0), // color_color.z vec4( 0.0f, 1.0f, 0.05f, 0), // color_color.w vec4( 0.0f, 8.0f, 0.50f, 0), // postfx_aberration vec4(0), /* noise */ vec4(0.0f, 4.0f, 0.50f, 0), // noise_offset.x vec4(0.0f, 4.0f, 0.50f, 0), // noise_offset.y vec4(0.0f, 0.5f, 0.05f, 0), // noise_noise vec4(0.0f, 4.0f, 0.25f, 0), // noise_retrace.x vec4(0.0f, 8.0f, 0.50f, 0), // noise_retrace.y vec4(0.0f, 4.0f, 0.25f, 0), // noise_retrace.z vec4(0), vec4(0), vec4(0), /* ghost */ vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost1.x vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost1.y vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost1.z vec4(-1.0f, 1.0f, 0.05f, 0), // postfx_ghost1.w vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost2.x vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost2.y vec4(-2.0f, 2.0f, 0.10f, 0), // postfx_ghost2.z vec4(-1.0f, 1.0f, 0.05f, 0), // postfx_ghost2.w vec4(0), /* gradient */ vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_gradient.x vec4( 0.0f, 0.5f, 0.05f, 0), // postfx_gradient.y vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_gradient.z vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_gradient_color.x vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_gradient_color.y vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_gradient_color.z vec4(0), vec4(0), vec4(0), /* glass */ vec4(0.0f, 16.0f, 0.50f, 0), // postfx_glass.x vec4(0.0f, 1.0f, 0.05f, 0), // postfx_glass.y vec4(0.0f, 2.0f, 0.05f, 0), // postfx_glass.z vec4(0.0f, 1.0f, 0.05f, 0), // postfx_glass.w vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), /* moire */ vec4( 0.5f, 1.0f, 0.05f, 0), // postfx_moire_h.x vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_moire_h.y vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_moire_h.z vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_moire_h.w vec4( 0.5f, 1.0f, 0.05f, 0), // postfx_moire_v.x vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_moire_v.y vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_moire_v.z vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_moire_v.w vec4(0), /* scanline */ vec4( 0.5f, 1.0f, 0.05f, 0), // postfx_scanline_h.x vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_scanline_h.y vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_scanline_h.z vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_scanline_h.w vec4( 0.5f, 1.0f, 0.05f, 0), // postfx_scanline_v.x vec4(-0.5f, 0.5f, 0.05f, 0), // postfx_scanline_v.y vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_scanline_v.z vec4( 0.0f, 1.0f, 0.05f, 0), // postfx_scanline_v.w vec4(0), /* mirror */ vec4(0.0f, 2.0f, 0.05f, 0), // mirror.x vec4(0.0f, 2.0f, 0.05f, 0), // mirror.y vec4(0.0f, 1.0f, 0.05f, 0), // mirror.z vec4(1.0f, 8.0f, 1.00f, 0), // mirror.w vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), /* radial blur */ vec4(2.0f, 8.0f, 0.25f, 0), // radial.x vec4(0.8f, 1.0f, 0.01f, 0), // radial.y vec4(2.0f,32.0f, 2.00f, 0), // radial.z vec4(0.0f, 1.0f, 0.05f, 0), // radial.w vec4(0), vec4(0), vec4(0), vec4(0), vec4(0) /* ? */ }; float theme_var[]={ /* default */ 0, 1,1, // ratio_2d 0,0, // border 0,0,0,0, 0, 1.0f,0.8f, // buffer 0.0f,0.0f, // remanence 0,0,0,0, 0, 0.5f,0.0f, // glow_mix 0.0f,0.0f, // glow_large 0.0f,0.0f, // glow_small 0,0, 0, 0.0f,0.0f, // blur 0,0,0,0,0,0, 0, 0.0f,0.5f, // postfx_deform 0.0f,1.0f,1.0f, // postfx_corner 0.0f, // postfx_vignetting 0,0, 0, 0.75f,0.25f,0.42f,4.0f, // copper_copper 0.05f,1.0f,0.0f, // copper_mask_color 0, 0, 1.0f,1.0f,1.0f, // color_filter 1.0f,1.0f,0.0f,0.0f, // color_color 0.0f, // postfx_aberration 0, 0.0f,0.0f, // noise_offset 0.0f, // noise_noise 0.0f,0.0f,0.0f, // noise_retrace 0,0, 0, 0.0f,0.0f,0.0f,0.0f, // postfx_ghost1 0.0f,0.0f,0.0f,0.0f, // postfx_ghost2 0, 0.5f,0.0f,0.0f, // postfx_gradient 0.0f,0.0f,0.0f, // postfx_gradient_color 0,0, 0, 8.0f,0.0f,0.0f,0.0f, // postfx_glass 0,0,0,0, 0, 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h 1.0f,0.0f,0.0f,0.0f, // postfx_moire_v 0, 1.0f,0.0f,0.0f,0.0f, // postfx_scanline_h 1.0f,0.0f,0.0f,0.0f, // postfx_scanline_v 0, 0.0f,0.0f,0.0f,1.0f, // mirror 0,0,0,0, 0, 4.0f,0.9f,1,0.0f, // radial 0,0,0,0, /* crt */ 0, 2,3, // ratio_2d 2,1, // border 0,0,0,0, 0, 0.2f,0.8f, // buffer 0.6f,0.4f, // remanence 0,0,0,0, 0, 0.7f,0.3f, // glow_mix 3.0f,0.0f, // glow_large 1.5f,0.0f, // glow_small 0,0, 0, 0.5f,0.0f, // blur 0,0,0,0,0,0, 0, 0.8f,0.48f, // postfx_deform 0.0f,0.8f,0.96f, // postfx_corner 0.5f, // postfx_vignetting 0,0, 0, 0.75f,0.25f,0.42f,4.0f, // copper_copper 0.05f,1.0f,0.0f, // copper_mask_color 0, 0, 0.9f,0.95f,0.85f, // color_filter 1.0f,1.25f,0.1f,0.4f, // color_color 4.0f, // postfx_aberration 0, 1.0f,1.0f, // noise_offset 0.15f, // noise_noise 1.0f,1.0f,0.5f, // noise_retrace 0,0, 0, 1.0f,0.0f,0.0f,-0.25f, // postfx_ghost1 1.5f,0.0f,0.0f,0.25f, // postfx_ghost2 0, 0.5f,0.25f,0.05f, // postfx_gradient 0.9f,0.8f,0.5f, // postfx_gradient_color 0,0, 0, 8.0f,0.25f,0.75f,0.2f, // postfx_glass 0,0,0,0, 0, 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h 0.75f,-0.25f,0.25f,0.25f, // postfx_moire_v 0, 1.0f,0.0f,0.0f,0.0f, // postfx_scanline_h 0.75f,-0.25f,0.5f,0.0f, // postfx_scanline_v 0, 0.95f,0.9f,0.5f,4.0f, // mirror 0,0,0,0, 0, 4.0f,0.9f,16,0.25f, // radial 0,0,0,0, /* amber screen */ 0, 2,4, // ratio_2d 1,0, // border 0,0,0,0, 0, 0.2f,0.8f, // buffer 0.6f,0.4f, // remanence 0,0,0,0, 0, 0.4f,0.6f, // glow_mix 4.0f,0.0f, // glow_large 2.0f,0.0f, // glow_small 0,0, 0, 0.5f,0.0f, // blur 0,0,0,0,0,0, 0, 0.7f,0.5f, // postfx_deform 0.0f,0.85f,0.98f, // postfx_corner 0.5f, // postfx_vignetting 0,0, 0, 0.75f,0.25f,0.42f,4.0f, // copper_copper 0.05f,1.0f,0.0f, // copper_mask_color 0, 0, 1.0f,0.7f,0.0f, // color_filter 1.0f,1.25f,0.1f,1.0f, // color_color 1.5f, // postfx_aberration 0, 1.0f,0.0f, // noise_offset 0.25f, // noise_noise 1.0f,2.0f,2.0f, // noise_retrace 0,0, 0, 1.0f,0.0f,0.0f,-0.25f, // postfx_ghost1 1.5f,0.0f,0.0f,0.25f, // postfx_ghost2 0, 0.0f,0.25f,0.1f, // postfx_gradient 0.25f,0.5f,0.5f, // postfx_gradient_color 0,0, 0, 8.0f,0.0f,0.0f,0.0f, // postfx_glass 0,0,0,0, 0, 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h 1.0f,0.0f,0.0f,0.0f, // postfx_moire_v 0, 0.6f,0.4f,1.0f,0.0f, // postfx_scanline_h 0.9f,0.1f,0.75f,0.0f, // postfx_scanline_v 0, 0.6f,0.6f,0.5f,4.0f, // mirror 0,0,0,0, 0, 4.0f,0.84f,16,0.25f, // radial 0,0,0,0, /* lcd */ 0, 2,2, // ratio_2d 1,1, // border 0,0,0,0, 0, 0.7f,0.3f, // buffer 0.5f,0.5f, // remanence 0,0,0,0, 0, 0.5f,0.5f, // glow_mix 2.4f,0.0f, // glow_large 1.2f,0.0f, // glow_small 0,0, 0, 0.25f,0.0f, // blur 0,0,0,0,0,0, 0, 0.0f,0.5f, // postfx_deform 0.0f,1.0f,1.0f, // postfx_corner 0.0f, // postfx_vignetting 0,0, 0, 0.75f,0.25f,0.42f,4.0f, // copper_copper 0.05f,1.0f,0.0f, // copper_mask_color 0, 0, 1.0f,1.0f,0.9f, // color_filter 1.15f,1.25f,-0.1f,0.25f, // color_color 3.0f, // postfx_aberration 0, 0.0f,0.0f, // noise_offset 0.15f, // noise_noise 0.0f,0.0f,0.0f, // noise_retrace 0,0, 0, 0.0f,0.0f,0.0f,0.0f, // postfx_ghost1 0.0f,0.0f,0.0f,0.0f, // postfx_ghost2 0, 0.25f,0.5f,0.1f , // postfx_gradient 0.7f,0.9f,1.0f, // postfx_gradient_color 0,0, 0, 8.0f,0.0f,0.0f,0.0f, // postfx_glass 0,0,0,0, 0, 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h 1.0f,0.0f,0.0f,0.0f, // postfx_moire_v 0, 0.75f,0.25f,0.7f,0.0f, // postfx_scanline_h 0.75f,0.25f,0.7f,0.0f, // postfx_scanline_v 0, 0.0f,0.0f,0.0f,1.0f, // mirror 0,0,0,0, 0, 4.0f,0.9f,1,0.0f, // radial 0,0,0,0, /* granpa tv */ 0, 2,4, // ratio_2d 1,0, // border 0,0,0,0, 0, 0.2f,0.8f, // buffer 0.6f,0.4f, // remanence 0,0,0,0, 0, 0.4f,0.6f, // glow_mix 2.4f,2.0f, // glow_large 1.2f,1.0f, // glow_small 0,0, 0, 0.5f,0.5f, // blur 0,0,0,0,0,0, 0, 1.0f,0.5f, // postfx_deform 0.0f,0.5f,0.9f, // postfx_corner 0.5f, // postfx_vignetting 0,0, 0, 0.75f,0.25f,0.42f,4.0f, // copper_copper 0.05f,1.0f,0.0f, // copper_mask_color 0, 0, 0.7f,0.8f,1.0f, // color_filter 0.9f,1.1f,0.0f,1.0f, // color_color 0.0f, // postfx_aberration 0, 2.0f,0.0f, // noise_offset 0.25f, // noise_noise 1.0f,1.0f,4.0f, // noise_retrace 0,0, 0, -1.0f,0.0f,0.0f,-0.25f, // postfx_ghost1 1.0f,0.0f,0.0f,-0.25f, // postfx_ghost2 0, 0.5f,0.25f,0.05f, // postfx_gradient 0.9f,0.8f,0.5f, // postfx_gradient_color 0,0, 0, 8.0f,0.0f,0.0f,0.0f, // postfx_glass 0,0,0,0, 0, 1.0f,0.0f,0.0f,0.0f, // postfx_moire_h 1.0f,0.0f,0.0f,0.0f, // postfx_moire_v 0, 0.75f,-0.25f,0.75f,0.0f, // postfx_scanline_h 1.0f,0.0f,0.0f,0.0f, // postfx_scanline_v 0, 0.95f,0.9f,0.5f,4.0f, // mirror 0,0,0,0, 0, 4.0f,0.9f,16,0.5f, // radial 0,0,0,0, /* intex system 4000 */ 0}; void Render::InitShaderVar() { int k = theme_i * setup_option_n * 9 + 1; /* main */ ratio_2d = vec2(theme_var[k], theme_var[k + 1]); k += 2; border = vec2(theme_var[k], theme_var[k + 1]); k += 2; k += 5; /* remanence */ buffer = vec2(theme_var[k], theme_var[k + 1]); k += 2; remanence = vec2(theme_var[k], theme_var[k + 1]); k += 2; k += 5; /* glow */ glow_mix = vec2(theme_var[k], theme_var[k + 1]); k += 2; glow_large = vec2(theme_var[k], theme_var[k + 1]); k += 2; glow_small = vec2(theme_var[k], theme_var[k + 1]); k += 2; k += 3; /* blur */ blur = vec2(theme_var[k], theme_var[k + 1]); k += 2; k += 7; /* screen */ postfx_deform = vec2(theme_var[k], theme_var[k + 1]); k += 2; postfx_corner = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; postfx_vignetting = theme_var[k]; k++; k += 3; /* copper */ copper_copper = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; copper_mask_color = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; k += 2; /* color */ color_filter = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; color_color = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; postfx_aberration = theme_var[k]; k++; k += 1; /* noise */ noise_offset = vec2(theme_var[k], theme_var[k + 1]); k += 2; noise_noise = theme_var[k]; k++; noise_retrace = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; k += 3; /* ghost */ postfx_ghost1 = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; postfx_ghost2 = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; k += 1; /* gradient */ postfx_gradient = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; postfx_gradient_color = vec3(theme_var[k], theme_var[k + 1], theme_var[k + 2]); k += 3; k += 3; /* glass */ postfx_glass = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; k += 5; /* moire */ postfx_moire_h = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; postfx_moire_v = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; k += 1; /* scanline */ postfx_scanline_h = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; postfx_scanline_v = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; k += 1; /* mirror */ mirror = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; k += 5; /* radial blur */ radial = vec4(theme_var[k], theme_var[k + 1], theme_var[k + 2], theme_var[k + 3]); k += 4; } void Render::UpdateSize() { screen_size = Video::GetSize(); canvas_char = (screen_size - border * ratio_2d * font_size * 2) / (font_size * ratio_2d); canvas_char = max(canvas_char, ivec2(1, 1)); canvas_size = canvas_char * font_size * ratio_2d; border = (screen_size - canvas_size) / 2; caca_set_canvas_size(m_cv_screen, canvas_char.x, canvas_char.y); caca_set_canvas_size(m_cv_setup, setup_size.x + 1, setup_size.y + 1); } int calc_item_length() { int n = !setup_switch ? setup_option_n : setup_item_n; for (int i = 0; i < n; i++) { int k = !setup_switch ? (i * (setup_item_n + 1)) : (setup_option_i * (setup_item_n + 1) + 1 + i); if (setup_text[k][0] == '\0') return i - 1; } return n - 1; } Shader *shader_simple; Shader *shader_blur_h, *shader_blur_v, *shader_glow; Shader *shader_remanence, *shader_copper, *shader_color; Shader *shader_noise, *shader_postfx, *shader_mirror, *shader_radial; // shader variables ShaderUniform shader_simple_texture; ShaderUniform shader_blur_h_texture, shader_blur_h_radius, shader_blur_v_texture, shader_blur_v_radius; ShaderUniform shader_glow_glow, shader_glow_source, shader_glow_mix; ShaderUniform shader_remanence_source, shader_remanence_buffer, shader_remanence_mix; ShaderUniform shader_copper_texture, shader_copper_screen_size, shader_copper_time, shader_copper_copper, shader_copper_mask_color; ShaderUniform shader_color_texture, shader_color_screen_size, shader_color_filter, shader_color_color, shader_color_flash; ShaderUniform shader_noise_texture, shader_noise_screen_size, shader_noise_time, shader_noise_offset, shader_noise_noise, shader_noise_retrace; ShaderUniform shader_postfx_texture, shader_postfx_texture_2d, shader_postfx_screen_size, shader_postfx_ratio_2d, shader_postfx_time, shader_postfx_deform, shader_postfx_ghost1, shader_postfx_ghost2, shader_postfx_glass, shader_postfx_vignetting, shader_postfx_gradient, shader_postfx_gradient_color, shader_postfx_aberration, shader_postfx_moire_h, shader_postfx_moire_v, shader_postfx_scanline_h, shader_postfx_scanline_v, shader_postfx_corner, shader_postfx_sync, shader_postfx_beat; ShaderUniform shader_mirror_texture, shader_mirror_screen_size, shader_mirror_mirror; ShaderUniform shader_radial_texture, shader_radial_screen_size, shader_radial_radial; Framebuffer *fbo_back, *fbo_front, *fbo_screen; Framebuffer *fbo_blur_h, *fbo_blur_v; Framebuffer *fbo_tmp, *fbo_buffer; void Render::TraceQuad() { glLoadIdentity(); glDrawArrays(GL_QUADS, 0, 4); } void Render::ShaderSimple(Framebuffer *fbo_output, int n) { shader_simple->Bind(); shader_simple->SetUniform(shader_simple_texture, fbo_output->GetTexture(), n); TraceQuad(); shader_simple->Unbind(); } int Render::InitDraw(void) { glDepthMask(GL_TRUE); // do not write z-buffer /* initialise framebuffer objects */ fbo_back = new Framebuffer(screen_size); fbo_screen = new Framebuffer(screen_size); fbo_front = new Framebuffer(screen_size); fbo_buffer = new Framebuffer(screen_size); fbo_blur_h = new Framebuffer(screen_size); fbo_blur_v = new Framebuffer(screen_size); fbo_tmp = new Framebuffer(screen_size); // shader simple shader_simple = Shader::Create(LOLFX_RESOURCE_NAME(simple)); shader_simple_texture = shader_simple->GetUniformLocation("texture"); // shader glow shader_glow = Shader::Create(LOLFX_RESOURCE_NAME(glow)); shader_glow_glow = shader_glow->GetUniformLocation("glow"); shader_glow_source = shader_glow->GetUniformLocation("source"); shader_glow_mix = shader_glow->GetUniformLocation("mix"); // shader blur horizontal shader_blur_h = Shader::Create(LOLFX_RESOURCE_NAME(blurh)); shader_blur_h_texture = shader_blur_h->GetUniformLocation("texture"); shader_blur_h_radius = shader_blur_h->GetUniformLocation("radius"); // shader blur vertical shader_blur_v = Shader::Create(LOLFX_RESOURCE_NAME(blurv)); shader_blur_v_texture = shader_blur_v->GetUniformLocation("texture"); shader_blur_v_radius = shader_blur_v->GetUniformLocation("radius"); // shader remanence shader_remanence = Shader::Create(LOLFX_RESOURCE_NAME(remanence)); shader_remanence_source = shader_remanence->GetUniformLocation("source"); shader_remanence_buffer = shader_remanence->GetUniformLocation("buffer"); shader_remanence_mix = shader_remanence->GetUniformLocation("mix"); // shader copper shader_copper = Shader::Create(LOLFX_RESOURCE_NAME(copper)); shader_copper_texture = shader_copper->GetUniformLocation("texture"); shader_copper_screen_size = shader_copper->GetUniformLocation("screen_size"); shader_copper_time = shader_copper->GetUniformLocation("time"); shader_copper_copper = shader_copper->GetUniformLocation("copper"); shader_copper_mask_color = shader_copper->GetUniformLocation("mask_color"); // shader color shader_color = Shader::Create(LOLFX_RESOURCE_NAME(color)); shader_color_texture = shader_color->GetUniformLocation("texture"); shader_color_screen_size = shader_color->GetUniformLocation("screen_size"); shader_color_filter = shader_color->GetUniformLocation("filter"); shader_color_color = shader_color->GetUniformLocation("color"); shader_color_flash = shader_color->GetUniformLocation("flash"); // shader noise shader_noise = Shader::Create(LOLFX_RESOURCE_NAME(noise)); shader_noise_texture = shader_noise->GetUniformLocation("texture"); shader_noise_screen_size = shader_noise->GetUniformLocation("screen_size"); shader_noise_time = shader_noise->GetUniformLocation("time"); shader_noise_offset = shader_noise->GetUniformLocation("offset"); shader_noise_noise = shader_noise->GetUniformLocation("noise"); shader_noise_retrace = shader_noise->GetUniformLocation("retrace"); // shader postfx shader_postfx = Shader::Create(LOLFX_RESOURCE_NAME(postfx)); shader_postfx_texture = shader_postfx->GetUniformLocation("texture"); shader_postfx_texture_2d = shader_postfx->GetUniformLocation("texture_2d"); shader_postfx_screen_size = shader_postfx->GetUniformLocation("screen_size"); shader_postfx_ratio_2d = shader_postfx->GetUniformLocation("ratio_2d"); shader_postfx_time = shader_postfx->GetUniformLocation("time"); shader_postfx_deform = shader_postfx->GetUniformLocation("deform"); shader_postfx_ghost1 = shader_postfx->GetUniformLocation("ghost1"); shader_postfx_ghost2 = shader_postfx->GetUniformLocation("ghost2"); shader_postfx_glass = shader_postfx->GetUniformLocation("glass"); shader_postfx_gradient = shader_postfx->GetUniformLocation("gradient"); shader_postfx_gradient_color = shader_postfx->GetUniformLocation("gradient_color"); shader_postfx_vignetting = shader_postfx->GetUniformLocation("vignetting"); shader_postfx_aberration = shader_postfx->GetUniformLocation("aberration"); shader_postfx_moire_h = shader_postfx->GetUniformLocation("moire_h"); shader_postfx_moire_v = shader_postfx->GetUniformLocation("moire_v"); shader_postfx_scanline_h = shader_postfx->GetUniformLocation("scanline_h"); shader_postfx_scanline_v = shader_postfx->GetUniformLocation("scanline_v"); shader_postfx_corner = shader_postfx->GetUniformLocation("corner"); shader_postfx_sync = shader_postfx->GetUniformLocation("sync"); shader_postfx_beat = shader_postfx->GetUniformLocation("beat"); // shader mirror shader_mirror = Shader::Create(LOLFX_RESOURCE_NAME(mirror)); shader_mirror_texture = shader_mirror->GetUniformLocation("texture"); shader_mirror_screen_size = shader_mirror->GetUniformLocation("screen_size"); shader_mirror_mirror = shader_mirror->GetUniformLocation("mirror"); // shader radial blur shader_radial = Shader::Create(LOLFX_RESOURCE_NAME(radial)); shader_radial_texture = shader_radial->GetUniformLocation("texture"); shader_radial_screen_size = shader_radial->GetUniformLocation("screen_size"); shader_radial_radial = shader_radial->GetUniformLocation("radial"); // initialize setup setup_n = calc_item_length(); return true; } int Render::CreateGLWindow() { InitShaderVar(); UpdateSize(); InitDraw(); return true; } Render::Render(caca_canvas_t *caca) : m_cv_screen(caca), m_cv_setup(caca_create_canvas(1, 1)), m_fps_debug(0), m_ready(false), m_pause(false), m_shader(true), m_shader_remanence(true), m_shader_glow(true), m_shader_blur(true), m_shader_postfx(true), m_shader_copper(true), m_shader_color(true), m_shader_noise(true), m_shader_mirror(true), m_shader_radial(true) { m_txt_screen = new TextRender(m_cv_screen, font_size); m_txt_setup = new TextRender(m_cv_setup, font_size); } void Render::TickGame(float seconds) { Entity::TickGame(seconds); /* draw setup */ if (g_setup) { /* background */ caca_set_color_argb(m_cv_setup, setup_color.x, setup_color.y); caca_fill_box(m_cv_setup, 0, 0, setup_size.x + 1, setup_size.y,' '); caca_draw_line(m_cv_setup, setup_size.z - 1, 1, setup_size.z - 1, setup_size.y - 1,'|'); /* title */ caca_set_color_argb(m_cv_setup, setup_color.y, setup_color.x); caca_draw_line(m_cv_setup, 0, 0, setup_size.x, 0, ' '); caca_put_str(m_cv_setup, setup_size.x / 2 - 3, 0, "SETUP"); /* informations */ /* int w = caca_get_canvas_width(m_cv_screen); int h = caca_get_canvas_height(m_cv_screen); caca_set_color_argb(m_cv_setup, setup_color.y, setup_color.x); caca_printf(m_cv_setup, 1, 0, "%i*%i", w, h); */ /* display option */ for (int i = 0; i < setup_h; i++) { int y = 1 + i; int k = (setup_option_p + i) * (setup_item_n + 1); if (setup_option_i != setup_option_p + i || setup_switch) { caca_set_color_argb(m_cv_setup, setup_color.x, setup_color.y); caca_put_str(m_cv_setup, 1, y, setup_text[k]); } else { caca_set_color_argb(m_cv_setup, setup_color.y, 0x0f0);//setup_color.x); caca_draw_line(m_cv_setup, 0, y, setup_size.z - 2, y,' '); caca_put_str(m_cv_setup, 1, y, setup_text[k]); } } /* display item */ for (int i = 0; i < setup_h; i++) { int y = 1 + i; int k = setup_option_i * (setup_item_n + 1) + 1 + setup_item_p + i; if (setup_item_i != setup_item_p + i || !setup_switch) { caca_set_color_argb(m_cv_setup, setup_color.x, setup_color.y); caca_put_str(m_cv_setup, setup_size.z + 1, y, setup_text[k]); } else { caca_set_color_argb(m_cv_setup, setup_color.y, 0x0f0);//setup_color.x); caca_draw_line(m_cv_setup, setup_size.z, y, setup_size.x, y,' '); caca_put_str(m_cv_setup, setup_size.z + 1, y, setup_text[k]); } } /* display variable */ int y = setup_size.y; setup_item_key = setup_option_i * (setup_item_n + 1) + 1 + setup_item_i; theme_var_key = theme_i * setup_option_n * 9 + setup_item_key; caca_set_color_argb(m_cv_setup, setup_color.y, setup_color.x); caca_draw_line(m_cv_setup, 0, y, setup_size.x, y,' '); if (setup_switch) { int x = 1; int w = setup_size.x - 3 - 4; float bar_w = w / (setup_conf[setup_item_key].y - setup_conf[setup_item_key].x); int bar_x = bar_w * setup_conf[setup_item_key].x; if ((setup_conf[setup_item_key].y - setup_conf[setup_item_key].x) / setup_conf[setup_item_key].z > 1) { /* work around a bug in libcaca */ if (setup_size.x - 4 < caca_get_canvas_width(m_cv_setup)) caca_printf(m_cv_setup, setup_size.x - 4, y, "%4.2f", theme_var[theme_var_key]); caca_draw_line(m_cv_setup, x, y, x - bar_x + int(bar_w * setup_conf[setup_item_key].y), y,'.'); if (theme_var[theme_var_key] != setup_conf[setup_item_key].x) caca_draw_line(m_cv_setup, x, y, x - bar_x + int(bar_w * theme_var[theme_var_key]), y, 'x'); } else { if (setup_conf[setup_item_key] != vec4(0)) { caca_put_str(m_cv_setup, setup_size.x - 3, y, (theme_var[theme_var_key] == setup_conf[setup_item_key].y)?"YES":" NO"); } } } else { caca_printf(m_cv_setup, 1, y, "%d/%d", setup_option_i, setup_n); } } } void Render::Pause() { m_pause=!m_pause; } void Render::TickDraw(float seconds) { /* keyboard manager */ if (Input::WasPressed(Key::F1)) { g_setup = !g_setup; if (g_setup) setup_n = calc_item_length(); sync_flag = true; sync_angle = main_angle; if (m_fps_debug) { Ticker::Unref(m_fps_debug); m_fps_debug = NULL; } if (g_setup) { m_fps_debug = new DebugFps(2, 2); Ticker::Ref(m_fps_debug); } } if (Input::WasPressed(Key::F2)) { m_shader_remanence = !m_shader_remanence; m_shader_glow = !m_shader_glow; m_shader_blur = !m_shader_blur; m_shader_postfx = !m_shader_postfx; //m_shader_copper = !m_shader_copper; m_shader_color = !m_shader_color; m_shader_noise = !m_shader_noise; m_shader_mirror = !m_shader_mirror; m_shader_radial = !m_shader_radial; } if (Input::WasPressed(Key::F4)) { theme_i--; if(theme_i < 0) theme_i = theme_n - 1; InitShaderVar(); UpdateSize(); } if (Input::WasPressed(Key::F5)) { theme_i++; if(theme_i > theme_n - 1) theme_i = 0; InitShaderVar(); UpdateSize(); } if (Input::WasPressed(Key::Tab)) { if (g_setup) { setup_switch = !setup_switch; setup_n = calc_item_length(); setup_cursor = (!setup_switch?setup_option_i:setup_item_i) - (!setup_switch?setup_option_p:setup_item_p); } } if (Input::WasPressed(Key::Up)) { if (g_setup) { if (!setup_switch) { if (setup_cursor > 0) { setup_cursor--; } else { if (setup_cursor == 0) setup_option_p--; } if (setup_option_i > 0) { setup_option_i--; } else { setup_option_i = setup_option_n - 1; setup_option_p = setup_option_n - setup_h; setup_cursor = setup_h - 1; } setup_item_i = 0; setup_item_p = 0; } else { if (setup_cursor > 0) { setup_cursor--; } else { if (setup_cursor == 0) setup_item_p--; } if (setup_item_i > 0) { setup_item_i--; } else { setup_item_i = setup_n; setup_item_p = (setup_n < setup_h) ? 0 : setup_n - setup_h + 1; setup_cursor = (setup_n < setup_h) ? setup_n : setup_h - 1; } } } } if (Input::WasPressed(Key::Down)) { if (g_setup) { if (!setup_switch) { if (setup_cursor < setup_h - 1) { setup_cursor++; } else { if (setup_cursor == setup_h - 1) setup_option_p++; } if (setup_option_i < setup_option_n - 1) { setup_option_i++; } else { setup_option_i = 0; setup_option_p = 0; setup_cursor = 0; } setup_item_i = 0; setup_item_p = 0; } else { if (setup_cursor < setup_h - 1) { setup_cursor++; } else { if (setup_cursor == setup_h - 1) setup_item_p++; } if (setup_item_i < setup_n) { setup_item_i++; } else { setup_item_i = 0; setup_item_p = 0; setup_cursor = 0; } } } } if (Input::WasPressed(Key::PageUp)) { if (g_setup) { if (!setup_switch) { if (setup_cursor > 0) { setup_option_i -= setup_cursor; setup_cursor = 0; } else { if (setup_option_i > setup_h) { setup_option_i -= setup_h; setup_option_p -= setup_h; } else { setup_option_i = 0; setup_option_p = 0; } } setup_item_i = 0; } else { if (setup_cursor > 0) { setup_item_i -= setup_cursor; setup_cursor = 0; } else { if (setup_item_i > setup_h) { setup_item_i -= setup_h; setup_item_p -= setup_h; } else { setup_item_i = 0; setup_item_p = 0; } } } } } if (Input::WasPressed(Key::PageDown)) { if (g_setup) { if (!setup_switch) { if (setup_cursor < setup_h - 1) { setup_option_i += setup_h - setup_cursor - 1; setup_cursor = setup_h - 1; setup_item_i = 0; } else { if (setup_option_i < setup_option_n - setup_h - 1) { setup_option_i += setup_h; setup_option_p += setup_h; } else { setup_option_i = setup_option_n - 1; setup_option_p = setup_option_n - setup_h; } } } else { if (setup_cursor < setup_h - 1) { setup_item_i += (setup_n < setup_h) ? setup_n - setup_cursor : setup_h - setup_cursor - 1; setup_cursor = (setup_n < setup_h) ? setup_n : setup_h - 1; } else { if (setup_item_i < setup_n - setup_h + 1) { setup_item_i += setup_h; setup_item_p += setup_h; } else { setup_item_i = setup_n; setup_item_p = setup_n - setup_h + 1; } } } } } if (Input::WasPressed(Key::Left)) { if (g_setup && setup_switch) { theme_var[theme_var_key] -= setup_conf[setup_item_key].z; if (theme_var[theme_var_key] < setup_conf[setup_item_key].x) theme_var[theme_var_key] = setup_conf[setup_item_key].x; InitShaderVar(); UpdateSize(); } } if (Input::WasPressed(Key::Right)) { if (g_setup && setup_switch) { theme_var[theme_var_key] += setup_conf[setup_item_key].z; if (theme_var[theme_var_key] > setup_conf[setup_item_key].y) theme_var[theme_var_key] = setup_conf[setup_item_key].y; InitShaderVar(); UpdateSize(); } } if (Input::WasPressed(Key::Home)) { if (g_setup && setup_switch) { theme_var[theme_var_key] = setup_conf[setup_item_key].x; InitShaderVar(); UpdateSize(); } } if (Input::WasPressed(Key::End)) { if (g_setup && setup_switch) { theme_var[theme_var_key] = setup_conf[setup_item_key].y; InitShaderVar(); UpdateSize(); } } if (Input::WasPressed(Key::Return)) { beat_flag = true; beat_angle = main_angle; //flash_flag = true; //flash_angle = main_angle; } Entity::TickDraw(seconds); if (!m_ready) { CreateGLWindow(); m_txt_screen->Init(); m_txt_setup->Init(); m_ready = true; } // timer if (!m_pause) { timer += seconds; main_angle = timer * 100.0f * PID; } if (sync_flag) { angle = (main_angle - sync_angle) * sync_speed; sync_value = 1.0f - sinf(angle); if (angle > 90.0f * PID) { sync_value = 0; sync_flag = false; } } if (beat_flag) { angle = (main_angle - beat_angle) * beat_speed; beat_value = 1.0f - sinf(angle); if (angle > 90.0f * PID) { beat_value = 0; beat_flag = false; } } if (flash_flag) { angle = (main_angle - flash_angle) * flash_speed; flash_value = 1.0f - sinf(angle); if (angle > 90.0f * PID) { flash_value = 0; flash_flag = false; } } if (fade_flag) { angle = (main_angle - fade_angle) * fade_speed; fade_value = 1.0f - sinf(angle); if (angle > 90.0f * PID) { fade_value = 0; fade_flag = false; } } Draw2D(); Draw3D(); } void Render::Draw2D() { /* Draw text in an offline buffer */ m_txt_screen->Render(); if (g_setup) m_txt_setup->Render(); if (m_shader) fbo_back->Bind(); glViewport(0, 0, screen_size.x, screen_size.y); /* Clear the back buffer */ RenderContext rc; rc.SetBlendFunc(BlendFunc::SrcColor, BlendFunc::DstAlpha); rc.SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f)); rc.SetClearDepth(1.0f); // set depth buffer glEnable(GL_TEXTURE_2D); g_renderer->Clear(ClearMask::Color | ClearMask::Depth); m_txt_screen->Blit(border, canvas_size); if (g_setup) m_txt_setup->Blit((screen_size - setup_canvas_size) / 2, setup_canvas_size); glMatrixMode(GL_PROJECTION); mat4 m = mat4::ortho(0, screen_size.x, screen_size.y, 0, -1.f, 1.f); glLoadMatrixf(&m[0][0]); glMatrixMode(GL_MODELVIEW); fx_angle = main_angle - part_angle; } void Render::Draw3D() { if (!m_shader) return; RenderContext rc; rc.SetBlendFunc(BlendFunc::Disabled, BlendFunc::Disabled); rc.SetDepthFunc(DepthFunc::Disabled); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(4, GL_FLOAT, 0, fs_quad_vtx); if (m_shader_copper) { // shader copper fbo_tmp->Bind(); shader_copper->Bind(); shader_copper->SetUniform(shader_copper_texture, fbo_back->GetTexture(), 0); shader_copper->SetUniform(shader_copper_screen_size, (vec2)screen_size); shader_copper->SetUniform(shader_copper_time, fx_angle); shader_copper->SetUniform(shader_copper_copper, vec4(copper_copper.x, copper_copper.y, copper_copper.z * 16.0f, copper_copper.w * 16.0f)); shader_copper->SetUniform(shader_copper_mask_color, copper_mask_color); TraceQuad(); shader_color->Unbind(); fbo_tmp->Unbind(); // shader simple fbo_back->Bind(); ShaderSimple(fbo_tmp, 0); fbo_back->Unbind(); } if (m_shader_remanence) { // shader remanence fbo_tmp->Bind(); shader_remanence->Bind(); shader_remanence->SetUniform(shader_remanence_source, fbo_back->GetTexture(), 0); shader_remanence->SetUniform(shader_remanence_buffer, fbo_buffer->GetTexture(), 1); shader_remanence->SetUniform(shader_remanence_mix, remanence); TraceQuad(); shader_remanence->Unbind(); fbo_tmp->Unbind(); // shader simple fbo_back->Bind(); ShaderSimple(fbo_tmp, 0); fbo_back->Unbind(); // save previous fbo fbo_tmp->Bind(); shader_remanence->Bind(); shader_remanence->SetUniform(shader_remanence_source, fbo_screen->GetTexture(), 0); shader_remanence->SetUniform(shader_remanence_buffer, fbo_buffer->GetTexture(), 1); shader_remanence->SetUniform(shader_remanence_mix, buffer); TraceQuad(); shader_remanence->Unbind(); fbo_tmp->Unbind(); // shader simple fbo_buffer->Bind(); ShaderSimple(fbo_tmp, 0); fbo_buffer->Unbind(); } // shader glow if (m_shader_glow) { // shader blur horizontal fbo_blur_h->Bind(); shader_blur_h->Bind(); shader_blur_h->SetUniform(shader_blur_h_texture, fbo_back->GetTexture(), 0); shader_blur_h->SetUniform(shader_blur_h_radius, glow_large / (float)screen_size.x); TraceQuad(); shader_blur_h->Unbind(); fbo_blur_h->Unbind(); // shader blur vertical fbo_blur_v->Bind(); shader_blur_v->Bind(); shader_blur_v->SetUniform(shader_blur_v_texture, fbo_blur_h->GetTexture(), 0); shader_blur_v->SetUniform(shader_blur_v_radius, glow_large / (float)screen_size.y); TraceQuad(); shader_blur_v->Unbind(); fbo_blur_v->Unbind(); // shader blur horizontal fbo_blur_h->Bind(); shader_blur_h->Bind(); shader_blur_h->SetUniform(shader_blur_h_texture, fbo_blur_v->GetTexture(), 0); shader_blur_h->SetUniform(shader_blur_h_radius, glow_small / (float)screen_size.x); TraceQuad(); shader_blur_h->Unbind(); fbo_blur_h->Unbind(); // shader blur vertical fbo_blur_v->Bind(); shader_blur_v->Bind(); shader_blur_v->SetUniform(shader_blur_v_texture, fbo_blur_h->GetTexture(), 0); shader_blur_v->SetUniform(shader_blur_v_radius, glow_small / (float)screen_size.y); TraceQuad(); shader_blur_v->Unbind(); fbo_blur_v->Unbind(); // shader glow fbo_screen->Bind(); shader_glow->Bind(); shader_glow->SetUniform(shader_glow_glow, fbo_blur_v->GetTexture(), 0); shader_glow->SetUniform(shader_glow_source, fbo_back->GetTexture(), 1); shader_glow->SetUniform(shader_glow_mix, glow_mix); TraceQuad(); shader_glow->Unbind(); fbo_screen->Unbind(); } else { // shader simple fbo_screen->Bind(); ShaderSimple(fbo_back, 0); fbo_screen->Unbind(); } if (m_shader_color) { // shader color fbo_tmp->Bind(); shader_color->Bind(); shader_color->SetUniform(shader_color_texture, fbo_screen->GetTexture(), 0); shader_color->SetUniform(shader_color_screen_size, (vec2)screen_size); shader_color->SetUniform(shader_color_filter, color_filter); shader_color->SetUniform(shader_color_color, color_color); shader_color->SetUniform(shader_color_flash, flash_value); TraceQuad(); shader_color->Unbind(); fbo_tmp->Unbind(); // shader simple fbo_screen->Bind(); ShaderSimple(fbo_tmp, 0); fbo_screen->Unbind(); } if (m_shader_noise) { // shader noise fbo_tmp->Bind(); shader_noise->Bind(); shader_noise->SetUniform(shader_noise_texture, fbo_screen->GetTexture(), 0); shader_noise->SetUniform(shader_noise_screen_size, (vec2)screen_size); shader_noise->SetUniform(shader_noise_time, fx_angle); shader_noise->SetUniform(shader_noise_offset, noise_offset); shader_noise->SetUniform(shader_noise_noise, noise_noise); shader_noise->SetUniform(shader_noise_retrace, noise_retrace); TraceQuad(); shader_noise->Unbind(); fbo_tmp->Unbind(); // shader simple fbo_screen->Bind(); ShaderSimple(fbo_tmp, 0); fbo_screen->Unbind(); } if (m_shader_blur) { // shader blur horizontal fbo_tmp->Bind(); shader_blur_h->Bind(); shader_blur_h->SetUniform(shader_blur_h_texture, fbo_screen->GetTexture(), 0); shader_blur_h->SetUniform(shader_blur_h_radius, blur / (float)screen_size.x); TraceQuad(); shader_blur_h->Unbind(); fbo_tmp->Unbind(); // shader blur vertical fbo_screen->Bind(); shader_blur_v->Bind(); shader_blur_v->SetUniform(shader_blur_v_texture, fbo_tmp->GetTexture(), 0); shader_blur_v->SetUniform(shader_blur_v_radius, blur / (float)screen_size.y); TraceQuad(); shader_blur_v->Unbind(); fbo_screen->Unbind(); } if (m_shader_postfx) { // shader postfx fbo_front->Bind(); shader_postfx->Bind(); shader_postfx->SetUniform(shader_postfx_texture, fbo_screen->GetTexture(), 0); shader_postfx->SetUniform(shader_postfx_screen_size, (vec2)screen_size); shader_postfx->SetUniform(shader_postfx_ratio_2d, (vec2)ratio_2d * 0.5f); shader_postfx->SetUniform(shader_postfx_time, fx_angle); shader_postfx->SetUniform(shader_postfx_deform, postfx_deform); shader_postfx->SetUniform(shader_postfx_ghost1, vec4(postfx_ghost1.xyz * 0.01f, postfx_ghost1.w)); shader_postfx->SetUniform(shader_postfx_ghost2, vec4(postfx_ghost2.xyz * 0.01f, postfx_ghost2.w)); shader_postfx->SetUniform(shader_postfx_glass, vec4(postfx_glass.xy * 0.01f, postfx_glass.z * 0.1f, postfx_glass.w)); shader_postfx->SetUniform(shader_postfx_gradient, postfx_gradient); shader_postfx->SetUniform(shader_postfx_gradient_color, postfx_gradient_color); shader_postfx->SetUniform(shader_postfx_vignetting, postfx_vignetting); shader_postfx->SetUniform(shader_postfx_aberration, postfx_aberration); shader_postfx->SetUniform(shader_postfx_moire_h, vec4(postfx_moire_h.xyz, postfx_moire_h.w * (2 * F_PI))); shader_postfx->SetUniform(shader_postfx_moire_v, vec4(postfx_moire_v.xyz, postfx_moire_v.w * (2 * F_PI))); shader_postfx->SetUniform(shader_postfx_scanline_h, vec4(postfx_scanline_h.xyz, postfx_scanline_h.w * (2 * F_PI))); shader_postfx->SetUniform(shader_postfx_scanline_v, vec4(postfx_scanline_v.xyz, postfx_scanline_v.w * (2 * F_PI))); shader_postfx->SetUniform(shader_postfx_corner, postfx_corner); shader_postfx->SetUniform(shader_postfx_sync, (float)fabs(sync_value * cosf((main_angle - sync_angle) * 6.0f))); shader_postfx->SetUniform(shader_postfx_beat, (float)fabs(beat_value * cosf((main_angle - beat_angle) * 6.0f))); TraceQuad(); shader_postfx->Unbind(); fbo_front->Unbind(); } else { // shader simple fbo_front->Bind(); ShaderSimple(fbo_screen, 0); fbo_front->Unbind(); } if (m_shader_mirror) { // shader mirror fbo_tmp->Bind(); shader_mirror->Bind(); shader_mirror->SetUniform(shader_mirror_texture, fbo_front->GetTexture(), 0); shader_mirror->SetUniform(shader_mirror_screen_size, (vec2)screen_size); shader_mirror->SetUniform(shader_mirror_mirror, vec4(mirror.x * 0.1f, mirror.y * 0.1f, mirror.z, mirror.w)); TraceQuad(); shader_mirror->Unbind(); fbo_tmp->Unbind(); // shader simple fbo_front->Bind(); ShaderSimple(fbo_tmp, 0); fbo_front->Unbind(); } if (m_shader_radial) { // shader radial blur fbo_tmp->Bind(); shader_radial->Bind(); shader_radial->SetUniform(shader_radial_texture, fbo_front->GetTexture(), 0); shader_radial->SetUniform(shader_radial_screen_size, (vec2)screen_size); shader_radial->SetUniform(shader_radial_radial, vec4(radial.x, radial.y, radial.z, radial.w * 0.1f)); TraceQuad(); shader_radial->Unbind(); fbo_tmp->Unbind(); // shader simple fbo_front->Bind(); ShaderSimple(fbo_tmp, 0); fbo_front->Unbind(); } // shader simple ShaderSimple(fbo_front, 0); glDisableClientState(GL_VERTEX_ARRAY); } Render::~Render() { if (m_fps_debug) Ticker::Unref(m_fps_debug); } \ No newline at end of file diff --git a/neercs/video/render.h b/neercs/video/render.h index 0bcb2fc..9396459 100644 --- a/neercs/video/render.h +++ b/neercs/video/render.h @@ -1,53 +1 @@ -// -// Neercs -// - -#if !defined __VIDEO_RENDER_H__ -#define __VIDEO_RENDER_H__ - -class Render : public WorldEntity -{ -public: - Render(caca_canvas_t *caca); - virtual ~Render(); - - char const *GetName() { return ""; } - -protected: - virtual void TickGame(float seconds); - virtual void TickDraw(float seconds); - - void Draw2D(); - void Draw3D(); - -private: - int CreateGLWindow(); - int InitDraw(); - void ShaderSimple(Framebuffer *fbo_output, int n); - void TraceQuad(); - void Pause(); - void Shader(); - void InitShaderVar(); - void UpdateVar(); - void UpdateSize(); - - caca_canvas_t *m_cv_screen, *m_cv_setup; - class TextRender *m_txt_screen, *m_txt_setup; - - Entity *m_fps_debug; - - bool m_ready; - bool m_pause; - bool m_shader; - bool m_shader_remanence; - bool m_shader_glow; - bool m_shader_blur; - bool m_shader_postfx; - bool m_shader_copper; - bool m_shader_color; - bool m_shader_noise; - bool m_shader_mirror; - bool m_shader_radial; -}; - -#endif // __VIDEO_RENDER_H__ +// // Neercs // #if !defined __VIDEO_RENDER_H__ #define __VIDEO_RENDER_H__ class Render : public WorldEntity { public: Render(caca_canvas_t *caca); virtual ~Render(); char const *GetName() { return "<title>"; } protected: virtual void TickGame(float seconds); virtual void TickDraw(float seconds); void Draw2D(); void Draw3D(); private: int CreateGLWindow(); int InitDraw(); void ShaderSimple(Framebuffer *fbo_output, int n); void TraceQuad(); void Pause(); void Shader(); void InitShaderVar(); void UpdateVar(); void UpdateSize(); caca_canvas_t *m_cv_screen, *m_cv_setup; class TextRender *m_txt_screen, *m_txt_setup; Entity *m_fps_debug; bool m_ready; bool m_pause; bool m_shader; bool m_shader_remanence; bool m_shader_glow; bool m_shader_blur; bool m_shader_postfx; bool m_shader_copper; bool m_shader_color; bool m_shader_noise; bool m_shader_mirror; bool m_shader_radial; }; #endif // __VIDEO_RENDER_H__ \ No newline at end of file diff --git a/neercs/video/simple.lolfx b/neercs/video/simple.lolfx index eaa5cfe..fdc8ac9 100644 --- a/neercs/video/simple.lolfx +++ b/neercs/video/simple.lolfx @@ -1,25 +1 @@ -[vert.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -void main() -{ - gl_Position = gl_Vertex; - pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; -} - -[frag.glsl] - -#version 120 - -varying vec2 pass_TexCoord; - -uniform sampler2D texture; - -void main(void) -{ - gl_FragColor = texture2D(texture, pass_TexCoord); -} - +[vert.glsl] #version 120 varying vec2 pass_TexCoord; void main() { gl_Position = gl_Vertex; pass_TexCoord = vec2(0.5, 0.5) + 0.5 * gl_Vertex.xy; } [frag.glsl] #version 120 varying vec2 pass_TexCoord; uniform sampler2D texture; void main(void) { gl_FragColor = texture2D(texture, pass_TexCoord); } \ No newline at end of file diff --git a/neercs/video/text-render.cpp b/neercs/video/text-render.cpp index 914ee2d..177294a 100644 --- a/neercs/video/text-render.cpp +++ b/neercs/video/text-render.cpp @@ -1,209 +1 @@ -// -// Neercs -// - -#if defined HAVE_CONFIG_H -# include "config.h" -#endif - -#include <cmath> -#include <cstdio> -#include <cstdlib> -#include <ctime> -#include <string> - -#include "core.h" -#include "lolgl.h" - -using namespace std; -using namespace lol; - -#include "../neercs.h" -#include "render.h" -#include "text-render.h" - -LOLFX_RESOURCE_DECLARE(text); - -#define HAVE_SHADER_4 1 - -/* - * Text rendering interface - */ - -TextRender::TextRender(caca_canvas_t *caca, ivec2 font_size) - : m_caca(caca), - m_font_size(font_size), - m_canvas_size(caca_get_canvas_width(m_caca), - caca_get_canvas_height(m_caca)), - m_fbo_size(m_font_size * m_canvas_size), - m_cells(m_canvas_size.x * m_canvas_size.y), - m_vbo1(0), m_vbo2(0), m_vbo3(0), m_fbo(0) -{ -} - -void TextRender::Init() -{ - m_font = new TileSet("video/resource/charset_amiga.png", - ivec2(256, 256), ivec2(1)); - - m_shader = Shader::Create(LOLFX_RESOURCE_NAME(text)); - m_color = m_shader->GetAttribLocation("in_Attr", - VertexUsage::Color, 0); - m_char = m_shader->GetAttribLocation("in_Char", - VertexUsage::Color, 1); -#if !HAVE_SHADER_4 - m_vertexid = m_shader->GetAttribLocation("in_VertexID", - VertexUsage::Position, 0); -#endif - m_texture = m_shader->GetUniformLocation("u_Texture"); - m_transform = m_shader->GetUniformLocation("u_Transform"); - m_datasize = m_shader->GetUniformLocation("u_DataSize"); - m_vdecl -#if HAVE_SHADER_4 - = new VertexDeclaration(VertexStream<uint32_t>(VertexUsage::Color), - VertexStream<uint32_t>(VertexUsage::Color)); -#else - = new VertexDeclaration(VertexStream<u8vec4>(VertexUsage::Color), - VertexStream<u8vec4>(VertexUsage::Color), - VertexStream<float>(VertexUsage::Position)); -#endif - - CreateBuffers(); -} - -void TextRender::CreateBuffers() -{ -#if HAVE_SHADER_4 - m_vbo1 = new VertexBuffer(m_cells * sizeof(uint32_t)); - m_vbo2 = new VertexBuffer(m_cells * sizeof(uint32_t)); -#else - m_vbo1 = new VertexBuffer(m_cells * sizeof(u8vec4)); - m_vbo2 = new VertexBuffer(m_cells * sizeof(u8vec4)); - m_vbo3 = new VertexBuffer(4 * m_cells * sizeof(float)); - - float *idx = (float *)m_vbo3->Lock(0, 0); - for (int i = 0; i < m_cells; i++) - idx[i] = (float)i; - m_vbo3->Unlock(); -#endif - - m_fbo = new Framebuffer(m_fbo_size); -} - -void TextRender::Render() -{ - /* Handle canvas size changes */ - ivec2 current_size(caca_get_canvas_width(m_caca), - caca_get_canvas_height(m_caca)); - if (current_size != m_canvas_size) - { - delete m_vbo1; - delete m_vbo2; - delete m_vbo3; - delete m_fbo; - - m_canvas_size = current_size; - m_fbo_size = m_font_size * m_canvas_size; - m_cells = m_canvas_size.x * m_canvas_size.y; - - CreateBuffers(); - } - - /* Transform matrix for the scene: - * - translate to the centre of the glyph - * - scale by 2.f * font_size / fbo_size - * - translate to the lower left corner */ - mat4 xform = mat4::translate(-1.f, -1.f + 2.0f * m_font_size.y - * m_canvas_size.y / m_fbo_size.y, 0.f) - * mat4::scale(vec3((vec2)m_font_size / (vec2)m_fbo_size, 1.f) - * vec3(2.f, -2.f, 1.f)) - * mat4::translate(0.5f, 0.5f, 0.f); - - /* Upload libcaca canvas contents to the vertex buffers */ - uint32_t *colors = (uint32_t *)m_vbo1->Lock(0, 0); - uint32_t savedattr = caca_get_attr(m_caca, -1, -1); - for (int j = 0; j < m_canvas_size.y; j++) - for (int i = 0; i < m_canvas_size.x; i++) - { - uint32_t attr = caca_get_attr(m_caca, i, j); - uint16_t fg = caca_attr_to_rgb12_fg(attr); - uint16_t bg = caca_attr_to_rgb12_bg(attr); - caca_set_color_argb(m_caca, fg, bg); - attr = caca_get_attr(m_caca, -1, -1); - caca_put_attr(m_caca, i, j, attr); - } - caca_set_attr(m_caca, savedattr); - memcpy(colors, caca_get_canvas_attrs(m_caca), - m_cells * sizeof(uint32_t)); - m_vbo1->Unlock(); - - uint32_t *chars = (uint32_t *)m_vbo2->Lock(0, 0); - memcpy(chars, caca_get_canvas_chars(m_caca), - m_cells * sizeof(uint32_t)); - m_vbo2->Unlock(); - - m_fbo->Bind(); - { - RenderContext rc; - rc.SetDepthFunc(DepthFunc::Disabled); - - glViewport(0, 0, m_fbo_size.x, m_fbo_size.y); -#if !defined HAVE_GLES_2X - glEnable(GL_POINT_SPRITE); - //glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - glDisable(GL_POINT_SMOOTH); - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); -#endif - m_shader->Bind(); - m_font->Bind(); - m_shader->SetUniform(m_texture, 0); - m_shader->SetUniform(m_transform, xform); - m_shader->SetUniform(m_datasize, vec2(m_canvas_size.x, - max(m_font_size.x, m_font_size.y))); - m_vdecl->SetStream(m_vbo1, m_color); - m_vdecl->SetStream(m_vbo2, m_char); -#if !HAVE_SHADER_4 - m_vdecl->SetStream(m_vbo3, m_vertexid); -#endif - m_vdecl->Bind(); - m_vdecl->DrawElements(MeshPrimitive::Points, 0, m_cells); - m_vdecl->Unbind(); - m_font->Unbind(); - m_shader->Unbind(); -#if !defined HAVE_GLES_2X - glDisable(GL_POINT_SPRITE); -#endif - } - m_fbo->Unbind(); -} - -void TextRender::Blit(ivec2 pos, ivec2 size) -{ - /* FIXME: this is ugly! But we will get rid of it when we - * do the Direct3D port, so don't worry too much. */ - ShaderTexture t = m_fbo->GetTexture(); - uint64_t const &x = *(uint64_t const *)&t; - - RenderContext rc; - rc.SetBlendFunc(BlendFunc::Disabled, BlendFunc::Disabled); - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, (int)x); - glColor3f(1.0f, 1.0f, 1.0f); - - vec2 tc = (vec2)m_canvas_size * (vec2)m_font_size / (vec2)m_fbo_size; - - glLoadIdentity(); - glBegin(GL_QUADS); - glTexCoord2f(tc.x, tc.y); - glVertex2i(pos.x + size.x, pos.y); - glTexCoord2f(0.0f, tc.y); - glVertex2i(pos.x, pos.y); - glTexCoord2f(0.0f, 0.0f); - glVertex2i(pos.x, pos.y + size.y); - glTexCoord2f(tc.x, 0.0f); - glVertex2i(pos.x + size.x, pos.y + size.y); - glEnd(); -} - +// // Neercs // #if defined HAVE_CONFIG_H # include "config.h" #endif #include <cmath> #include <cstdio> #include <cstdlib> #include <ctime> #include <string> #include "core.h" #include "lolgl.h" using namespace std; using namespace lol; #include "../neercs.h" #include "render.h" #include "text-render.h" LOLFX_RESOURCE_DECLARE(text); #define HAVE_SHADER_4 1 /* * Text rendering interface */ TextRender::TextRender(caca_canvas_t *caca, ivec2 font_size) : m_caca(caca), m_font_size(font_size), m_canvas_size(caca_get_canvas_width(m_caca), caca_get_canvas_height(m_caca)), m_fbo_size(m_font_size * m_canvas_size), m_cells(m_canvas_size.x * m_canvas_size.y), m_vbo1(0), m_vbo2(0), m_vbo3(0), m_fbo(0) { } void TextRender::Init() { m_font = new TileSet("video/resource/charset_amiga.png", ivec2(256, 256), ivec2(1)); m_shader = Shader::Create(LOLFX_RESOURCE_NAME(text)); m_color = m_shader->GetAttribLocation("in_Attr", VertexUsage::Color, 0); m_char = m_shader->GetAttribLocation("in_Char", VertexUsage::Color, 1); #if !HAVE_SHADER_4 m_vertexid = m_shader->GetAttribLocation("in_VertexID", VertexUsage::Position, 0); #endif m_texture = m_shader->GetUniformLocation("u_Texture"); m_transform = m_shader->GetUniformLocation("u_Transform"); m_datasize = m_shader->GetUniformLocation("u_DataSize"); m_vdecl #if HAVE_SHADER_4 = new VertexDeclaration(VertexStream<uint32_t>(VertexUsage::Color), VertexStream<uint32_t>(VertexUsage::Color)); #else = new VertexDeclaration(VertexStream<u8vec4>(VertexUsage::Color), VertexStream<u8vec4>(VertexUsage::Color), VertexStream<float>(VertexUsage::Position)); #endif CreateBuffers(); } void TextRender::CreateBuffers() { #if HAVE_SHADER_4 m_vbo1 = new VertexBuffer(m_cells * sizeof(uint32_t)); m_vbo2 = new VertexBuffer(m_cells * sizeof(uint32_t)); #else m_vbo1 = new VertexBuffer(m_cells * sizeof(u8vec4)); m_vbo2 = new VertexBuffer(m_cells * sizeof(u8vec4)); m_vbo3 = new VertexBuffer(4 * m_cells * sizeof(float)); float *idx = (float *)m_vbo3->Lock(0, 0); for (int i = 0; i < m_cells; i++) idx[i] = (float)i; m_vbo3->Unlock(); #endif m_fbo = new Framebuffer(m_fbo_size); } void TextRender::Render() { /* Handle canvas size changes */ ivec2 current_size(caca_get_canvas_width(m_caca), caca_get_canvas_height(m_caca)); if (current_size != m_canvas_size) { delete m_vbo1; delete m_vbo2; delete m_vbo3; delete m_fbo; m_canvas_size = current_size; m_fbo_size = m_font_size * m_canvas_size; m_cells = m_canvas_size.x * m_canvas_size.y; CreateBuffers(); } /* Transform matrix for the scene: * - translate to the centre of the glyph * - scale by 2.f * font_size / fbo_size * - translate to the lower left corner */ mat4 xform = mat4::translate(-1.f, -1.f + 2.0f * m_font_size.y * m_canvas_size.y / m_fbo_size.y, 0.f) * mat4::scale(vec3((vec2)m_font_size / (vec2)m_fbo_size, 1.f) * vec3(2.f, -2.f, 1.f)) * mat4::translate(0.5f, 0.5f, 0.f); /* Upload libcaca canvas contents to the vertex buffers */ uint32_t *colors = (uint32_t *)m_vbo1->Lock(0, 0); uint32_t savedattr = caca_get_attr(m_caca, -1, -1); for (int j = 0; j < m_canvas_size.y; j++) for (int i = 0; i < m_canvas_size.x; i++) { uint32_t attr = caca_get_attr(m_caca, i, j); uint16_t fg = caca_attr_to_rgb12_fg(attr); uint16_t bg = caca_attr_to_rgb12_bg(attr); caca_set_color_argb(m_caca, fg, bg); attr = caca_get_attr(m_caca, -1, -1); caca_put_attr(m_caca, i, j, attr); } caca_set_attr(m_caca, savedattr); memcpy(colors, caca_get_canvas_attrs(m_caca), m_cells * sizeof(uint32_t)); m_vbo1->Unlock(); uint32_t *chars = (uint32_t *)m_vbo2->Lock(0, 0); memcpy(chars, caca_get_canvas_chars(m_caca), m_cells * sizeof(uint32_t)); m_vbo2->Unlock(); m_fbo->Bind(); { RenderContext rc; rc.SetDepthFunc(DepthFunc::Disabled); glViewport(0, 0, m_fbo_size.x, m_fbo_size.y); #if !defined HAVE_GLES_2X glEnable(GL_POINT_SPRITE); //glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); glDisable(GL_POINT_SMOOTH); glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); #endif m_shader->Bind(); m_font->Bind(); m_shader->SetUniform(m_texture, 0); m_shader->SetUniform(m_transform, xform); m_shader->SetUniform(m_datasize, vec2(m_canvas_size.x, max(m_font_size.x, m_font_size.y))); m_vdecl->SetStream(m_vbo1, m_color); m_vdecl->SetStream(m_vbo2, m_char); #if !HAVE_SHADER_4 m_vdecl->SetStream(m_vbo3, m_vertexid); #endif m_vdecl->Bind(); m_vdecl->DrawElements(MeshPrimitive::Points, 0, m_cells); m_vdecl->Unbind(); m_font->Unbind(); m_shader->Unbind(); #if !defined HAVE_GLES_2X glDisable(GL_POINT_SPRITE); #endif } m_fbo->Unbind(); } void TextRender::Blit(ivec2 pos, ivec2 size) { /* FIXME: this is ugly! But we will get rid of it when we * do the Direct3D port, so don't worry too much. */ ShaderTexture t = m_fbo->GetTexture(); uint64_t const &x = *(uint64_t const *)&t; RenderContext rc; rc.SetBlendFunc(BlendFunc::Disabled, BlendFunc::Disabled); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, (int)x); glColor3f(1.0f, 1.0f, 1.0f); vec2 tc = (vec2)m_canvas_size * (vec2)m_font_size / (vec2)m_fbo_size; glLoadIdentity(); glBegin(GL_QUADS); glTexCoord2f(tc.x, tc.y); glVertex2i(pos.x + size.x, pos.y); glTexCoord2f(0.0f, tc.y); glVertex2i(pos.x, pos.y); glTexCoord2f(0.0f, 0.0f); glVertex2i(pos.x, pos.y + size.y); glTexCoord2f(tc.x, 0.0f); glVertex2i(pos.x + size.x, pos.y + size.y); glEnd(); } \ No newline at end of file diff --git a/neercs/video/text-render.h b/neercs/video/text-render.h index ee37433..02a846a 100644 --- a/neercs/video/text-render.h +++ b/neercs/video/text-render.h @@ -1,35 +1 @@ -// -// Neercs -// - -#if !defined __TEXT_RENDER_H__ -#define __TEXT_RENDER_H__ - -class TextRender -{ -public: - TextRender(caca_canvas_t *caca, ivec2 font_size); - void Init(); - void Render(); - void Blit(ivec2 pos, ivec2 size); - -private: - void CreateBuffers(); - - caca_canvas_t *m_caca; - ivec2 m_font_size, m_canvas_size, m_fbo_size; - int m_cells; - - TileSet *m_font; - - Shader *m_shader; - ShaderAttrib m_color, m_char, m_vertexid; - ShaderUniform m_texture, m_transform, m_datasize; - VertexDeclaration *m_vdecl; - VertexBuffer *m_vbo1, *m_vbo2, *m_vbo3; - - Framebuffer *m_fbo; -}; - -#endif // __TEXT_RENDER_H__ - +// // Neercs // #if !defined __TEXT_RENDER_H__ #define __TEXT_RENDER_H__ class TextRender { public: TextRender(caca_canvas_t *caca, ivec2 font_size); void Init(); void Render(); void Blit(ivec2 pos, ivec2 size); private: void CreateBuffers(); caca_canvas_t *m_caca; ivec2 m_font_size, m_canvas_size, m_fbo_size; int m_cells; TileSet *m_font; Shader *m_shader; ShaderAttrib m_color, m_char, m_vertexid; ShaderUniform m_texture, m_transform, m_datasize; VertexDeclaration *m_vdecl; VertexBuffer *m_vbo1, *m_vbo2, *m_vbo3; Framebuffer *m_fbo; }; #endif // __TEXT_RENDER_H__ \ No newline at end of file diff --git a/neercs/video/text.lolfx b/neercs/video/text.lolfx index 56a16da..391cde0 100644 --- a/neercs/video/text.lolfx +++ b/neercs/video/text.lolfx @@ -1,104 +1 @@ -[vert.glsl] - -#version 130 - -#define HAVE_SHADER_4 1 - -#if HAVE_SHADER_4 -in uint in_Char, in_Attr; -#else -attribute vec4 in_Char, in_Attr; -attribute float in_VertexID; -# define out varying -#endif - -out vec4 pass_Foreground; -out vec4 pass_Background; -out vec2 pass_UV; - -uniform vec2 u_DataSize; -uniform mat4 u_Transform; - -void main() -{ -#if HAVE_SHADER_4 - float u = float(in_Char & 0xfu) / 32.0 + 0.0; - float v = float((in_Char >> 4u) & 0xfu) / 32.0 + 0.5; -#else - vec4 tmp_Char = in_Char * 255.0; - - float u = mod(tmp_Char.x, 16.0) / 32.0 + 0.0; - float v = floor(tmp_Char.x / 16.0) / 32.0 + 0.5; -#endif - pass_UV = vec2(u, v); - -#if HAVE_SHADER_4 - float A = float(in_Attr >> 29u) / 7.0; - float B = float((in_Attr >> 25u) & 0xfu) / 15.0; - float C = float((in_Attr >> 21u) & 0xfu) / 15.0; - float D = float((in_Attr >> 18u) & 0x7u) / 7.0; - - float E = float((in_Attr >> 15u) & 0x7u) / 7.0; - float F = float((in_Attr >> 11u) & 0xfu) / 15.0; - float G = float((in_Attr >> 7u) & 0xfu) / 15.0; - float H = float((in_Attr >> 4u) & 0x7u) / 7.0; -#else - vec4 tmp_Attr = in_Attr * 255.0; - - float A = floor(tmp_Attr.w / 32.0) / 7.0; - float B = mod(floor(tmp_Attr.w / 2.0), 16.0) / 15.0; - float C = (mod(tmp_Attr.w, 2.0) * 8.0 + floor(tmp_Attr.z / 32.0)) / 15.0; - float D = mod(floor(tmp_Attr.z / 4.0), 8.0) / 7.0; - - float E = (mod(tmp_Attr.z, 4.0) * 2.0 + floor(tmp_Attr.y / 128.0)) / 7.0; - float F = mod(floor(tmp_Attr.y / 8.0), 16.0) / 15.0; - float G = (mod(tmp_Attr.y, 8.0) * 2.0 + floor(tmp_Attr.x / 128.0)) / 15.0; - float H = mod(floor(tmp_Attr.x / 16.0), 8.0) / 7.0; -#endif - - pass_Background = vec4(B + 0.0625, C + 0.125, D + 0.125, 1.0 - A); - pass_Foreground = vec4(F, G, H, 1.0 - E); - if (B + C + D < 0.01) A = 1.0; - if (F + G + H < 0.01) E = 1.0; - - // This only works with glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - gl_PointSize = u_DataSize[1]; - -#if HAVE_SHADER_4 - vec2 coord = vec2(gl_VertexID % int(u_DataSize[0]), - gl_VertexID / int(u_DataSize[0])); -#else - vec2 coord = vec2(mod(in_VertexID, u_DataSize[0]), - floor(in_VertexID / u_DataSize[0])); -#endif - - gl_Position = u_Transform * vec4(coord, 0.0, 1.0); -} - -[frag.glsl] - -#version 130 - -#define HAVE_SHADER_4 1 - -#if HAVE_SHADER_4 -out vec4 out_Color; -#else -# define out_Color gl_FragColor -# define in varying -# define out -#endif - -in vec4 pass_Foreground; -in vec4 pass_Background; -in vec2 pass_UV; - -uniform sampler2D u_Texture; - -void main(void) -{ - vec2 c = gl_PointCoord * (1.0 / 32.0) + pass_UV; - float t = texture2D(u_Texture, c).x; - out_Color = mix(pass_Background, pass_Foreground, t); -} - +[vert.glsl] #version 130 #define HAVE_SHADER_4 1 #if HAVE_SHADER_4 in uint in_Char, in_Attr; #else attribute vec4 in_Char, in_Attr; attribute float in_VertexID; # define out varying #endif out vec4 pass_Foreground; out vec4 pass_Background; out vec2 pass_UV; uniform vec2 u_DataSize; uniform mat4 u_Transform; void main() { #if HAVE_SHADER_4 float u = float(in_Char & 0xfu) / 32.0 + 0.0; float v = float((in_Char >> 4u) & 0xfu) / 32.0 + 0.5; #else vec4 tmp_Char = in_Char * 255.0; float u = mod(tmp_Char.x, 16.0) / 32.0 + 0.0; float v = floor(tmp_Char.x / 16.0) / 32.0 + 0.5; #endif pass_UV = vec2(u, v); #if HAVE_SHADER_4 float A = float(in_Attr >> 29u) / 7.0; float B = float((in_Attr >> 25u) & 0xfu) / 15.0; float C = float((in_Attr >> 21u) & 0xfu) / 15.0; float D = float((in_Attr >> 18u) & 0x7u) / 7.0; float E = float((in_Attr >> 15u) & 0x7u) / 7.0; float F = float((in_Attr >> 11u) & 0xfu) / 15.0; float G = float((in_Attr >> 7u) & 0xfu) / 15.0; float H = float((in_Attr >> 4u) & 0x7u) / 7.0; #else vec4 tmp_Attr = in_Attr * 255.0; float A = floor(tmp_Attr.w / 32.0) / 7.0; float B = mod(floor(tmp_Attr.w / 2.0), 16.0) / 15.0; float C = (mod(tmp_Attr.w, 2.0) * 8.0 + floor(tmp_Attr.z / 32.0)) / 15.0; float D = mod(floor(tmp_Attr.z / 4.0), 8.0) / 7.0; float E = (mod(tmp_Attr.z, 4.0) * 2.0 + floor(tmp_Attr.y / 128.0)) / 7.0; float F = mod(floor(tmp_Attr.y / 8.0), 16.0) / 15.0; float G = (mod(tmp_Attr.y, 8.0) * 2.0 + floor(tmp_Attr.x / 128.0)) / 15.0; float H = mod(floor(tmp_Attr.x / 16.0), 8.0) / 7.0; #endif pass_Background = vec4(B + 0.0625, C + 0.125, D + 0.125, 1.0 - A); pass_Foreground = vec4(F, G, H, 1.0 - E); if (B + C + D < 0.01) A = 1.0; if (F + G + H < 0.01) E = 1.0; // This only works with glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); gl_PointSize = u_DataSize[1]; #if HAVE_SHADER_4 vec2 coord = vec2(gl_VertexID % int(u_DataSize[0]), gl_VertexID / int(u_DataSize[0])); #else vec2 coord = vec2(mod(in_VertexID, u_DataSize[0]), floor(in_VertexID / u_DataSize[0])); #endif gl_Position = u_Transform * vec4(coord, 0.0, 1.0); } [frag.glsl] #version 130 #define HAVE_SHADER_4 1 #if HAVE_SHADER_4 out vec4 out_Color; #else # define out_Color gl_FragColor # define in varying # define out #endif in vec4 pass_Foreground; in vec4 pass_Background; in vec2 pass_UV; uniform sampler2D u_Texture; void main(void) { vec2 c = gl_PointCoord * (1.0 / 32.0) + pass_UV; float t = texture2D(u_Texture, c).x; out_Color = mix(pass_Background, pass_Foreground, t); } \ No newline at end of file