stfl-0.22/0000755000000000000000000000000011651202747011110 5ustar rootrootstfl-0.22/python/0000755000000000000000000000000011651202747012431 5ustar rootrootstfl-0.22/python/stfl.i0000644000000000000000000000013610630375145013552 0ustar rootroot%include "../swig/shortnames.i" %include "../swig/basedecls.i" %include "../swig/setlocale.i" stfl-0.22/python/example.py0000644000000000000000000000434210634452540014437 0ustar rootroot#!/usr/bin/env python __author__ = "chrysn " __copyright__ = "Copyright 2007, chrysn" __license__ = "GPL" import sys import csv import stfl class CSV(object): def __init__(self,file,delimiter): self.file=file self.delimiter=delimiter self.data=[l for l in csv.reader(open(self.file),delimiter=self.delimiter)] maxlen=max([len(l) for l in self.data]) for l in self.data: while len(l) # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 3 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA # PYTHON_VERSION = $(shell python -V 2>&1 | cut -f2 -d' ' | cut -f1-2 -d'.') PYTHON_SITEARCH = $(shell python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)") all: python/_stfl.so python/stfl.py python/stfl.pyc install: install_python python/_stfl.so python/stfl.py python/stfl.pyc: libstfl.a stfl.h python/stfl.i swig/*.i cd python && swig -python -threads stfl.i gcc -shared -pthread -fPIC python/stfl_wrap.c -I/usr/include/python$(PYTHON_VERSION) \ -I. libstfl.a -lncursesw -o python/_stfl.so cd python && python -c 'import stfl' install_python: python/_stfl.so python/stfl.py python/stfl.pyc mkdir -p $(DESTDIR)$(PYTHON_SITEARCH)/ mkdir -p $(DESTDIR)$(PYTHON_SITEARCH)/lib-dynload/ cp python/_stfl.so $(DESTDIR)$(PYTHON_SITEARCH)/lib-dynload/ cp python/stfl.pyc $(DESTDIR)$(PYTHON_SITEARCH)/ cp python/stfl.py $(DESTDIR)$(PYTHON_SITEARCH)/ stfl-0.22/style.c0000644000000000000000000001153111216745205012413 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * style.c: Helper functions for text colors and attributes */ #include "stfl_internals.h" #include #include #include static wchar_t *wcssep(wchar_t **stringp, const wchar_t *delim) { register wchar_t *tmp=*stringp; register wchar_t *tmp2=tmp; register const wchar_t *tmp3; if (!*stringp) return 0; for (tmp2=tmp; *tmp2; ++tmp2) { for (tmp3=delim; *tmp3; ++tmp3) if (*tmp2==*tmp3) { /* delimiter found */ *tmp2=0; *stringp=tmp2+1; return tmp; } } *stringp=0; return tmp; } #define STFL_MAX_COLOR_PAIRS 256 static int stfl_colorpair_bg[STFL_MAX_COLOR_PAIRS]; static int stfl_colorpair_fg[STFL_MAX_COLOR_PAIRS]; int stfl_colorpair_counter = 1; void stfl_style(WINDOW *win, const wchar_t *style) { int bg_color = -1, fg_color = -1, attr = A_NORMAL; style += wcsspn(style, L" \t"); while (*style) { int field_len = wcscspn(style, L","); wchar_t field[field_len+1]; wmemcpy(field, style, field_len); field[field_len] = 0; style += field_len; if (*style == L',') style++; wchar_t *sepp = field; wchar_t *key = wcssep(&sepp, L"="); wchar_t *value = wcssep(&sepp, L""); if (!key || !value) continue; key += wcsspn(key, L" \t"); key = wcssep(&key, L" \t"); value += wcsspn(value, L" \t"); value = wcssep(&value, L" \t"); if (!wcscmp(key, L"bg") || !wcscmp(key, L"fg")) { int color = -1; if (!wcscmp(value, L"black")) color = COLOR_BLACK; else if (!wcscmp(value, L"red")) color = COLOR_RED; else if (!wcscmp(value, L"green")) color = COLOR_GREEN; else if (!wcscmp(value, L"yellow")) color = COLOR_YELLOW; else if (!wcscmp(value, L"blue")) color = COLOR_BLUE; else if (!wcscmp(value, L"magenta")) color = COLOR_MAGENTA; else if (!wcscmp(value, L"cyan")) color = COLOR_CYAN; else if (!wcscmp(value, L"white")) color = COLOR_WHITE; else if (!wcsncmp(value, L"color", 5)) { color = wcstoul(value + 5, NULL, 0); } else { fprintf(stderr, "STFL Style Error: Unknown %ls color: '%ls'\n", key, value); abort(); } if (!wcscmp(key, L"bg")) bg_color = color; else fg_color = color; } else if (!wcscmp(key, L"attr")) { if (!wcscmp(value, L"standout")) attr |= A_STANDOUT; else if (!wcscmp(value, L"underline")) attr |= A_UNDERLINE; else if (!wcscmp(value, L"reverse")) attr |= A_REVERSE; else if (!wcscmp(value, L"blink")) attr |= A_BLINK; else if (!wcscmp(value, L"dim")) attr |= A_DIM; else if (!wcscmp(value, L"bold")) attr |= A_BOLD; else if (!wcscmp(value, L"protect")) attr |= A_PROTECT; else if (!wcscmp(value, L"invis")) attr |= A_INVIS; else { fprintf(stderr, "STFL Style Error: Unknown attribute: '%ls'\n", value); abort(); } } else { fprintf(stderr, "STFL Style Error: Unknown keyword: '%ls'\n", key); abort(); } } short f, b; pair_content(0, &f, &b); if (fg_color < 0 || fg_color >= COLORS) fg_color = f; if (bg_color < 0 || bg_color >= COLORS) bg_color = b; int i; for (i=1; icurrent_focus_id == w->id) style = stfl_widget_getkv_str(w, L"style_focus", L""); if (*style == 0) style = stfl_widget_getkv_str(w, L"style_normal", L""); stfl_style(win, style); } stfl-0.22/ruby/0000755000000000000000000000000011651202747012071 5ustar rootrootstfl-0.22/ruby/stfl.i0000644000000000000000000000017510630375145013215 0ustar rootroot%include "../swig/shortnames.i" %include "../swig/basedecls.i" %include "../swig/nonullptr.i" %include "../swig/setlocale.i" stfl-0.22/ruby/extconf.rb0000644000000000000000000000004710444070521014055 0ustar rootrootrequire 'mkmf' create_makefile('stfl') stfl-0.22/ruby/example.rb0000644000000000000000000000517210651364131014051 0ustar rootroot#!/usr/bin/env ruby # # STFL - The Structured Terminal Forms Language/Library # Copyright (C) 2006 Andreas Krennmair # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 3 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA # # example.rb: A little STFL Ruby example require 'stfl' layout = < # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 3 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA # all: ruby/build_ok install: install_ruby ruby/build_ok: libstfl.a stfl.h ruby/stfl.i swig/*.i cd ruby && swig -ruby stfl.i && ruby extconf.rb $(MAKE) -C ruby clean && $(MAKE) -C ruby LIBS+="../libstfl.a -lncursesw" CFLAGS+="-pthread -I.." DLDFLAGS+="-pthread" DESTDIR=$(DESTDIR) prefix=$(prefix) sitedir=$(prefix)/$(libdir)/ruby touch ruby/build_ok install_ruby: ruby/build_ok $(MAKE) -C ruby DESTDIR=$(DESTDIR) prefix=$(prefix) sitedir='$(DESTDIR)$(prefix)/$(libdir)/ruby' install stfl-0.22/perl5/0000755000000000000000000000000011651202747012137 5ustar rootrootstfl-0.22/perl5/stfl.i0000644000000000000000000000007710443565001013256 0ustar rootroot%include "../swig/shortnames.i" %include "../swig/basedecls.i" stfl-0.22/perl5/example.pl0000644000000000000000000000635410674327636014150 0ustar rootroot#!/usr/bin/perl -w # # STFL - The Structured Terminal Forms Language/Library # Copyright (C) 2006, 2007 Clifford Wolf # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 3 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA # # example.pl: A little STFL Perl example # use strict; use stfl; my @files; { my $dirlist = join " ", @ARGV; open(F, "find $dirlist -iname '*.mp3' -o -iname '*.ogg' |"); while () { chomp; push @files, $_; } close F; } if ($#files == -1) { print STDERR "Usage: $0 \n"; exit 1 } my $f = stfl::create( <get("searchterm"); for (my $i = 0; $i <= $#files; $i++) { push @templist, $i if $files[$i] =~ /$searchterm/i; } $f->run(-3); my $w = $f->get("filelist:w") - 4; my $code = "{list"; for (1..$f->get("filelist:h")) { last if $#templist < 0; my $tempid = int(rand($#templist + 1)); my $id = $templist[$tempid]; splice @templist, $tempid, 1; my $filename = $files[$id]; $filename =~ s/.*\/(.*?\/.*?)$/$1/; $filename =~ s/.{4,}(.{$w})/...$1/; $filename = stfl::quote($filename); $code .= "{listitem[file_$id] text:$filename}"; } $code .= "}"; $f->modify("filelist", "replace_inner", $code); $f->set("listpos", "0"); } sub play { $f->get("listposname") =~ /(\d+)/; my $filename = $files[$1]; $filename =~ s/'/'\\''/g; if (system("pidof xmms > /dev/null") != 0) { system("xmms -p '$filename' > /dev/null 2>&1 &"); } else { system("xmms -e '$filename' > /dev/null 2>&1 &"); } } sub helpmsg { my $focus = $f->get_focus(); $f->set("helpmsg", "[ F1 or ENTER = regenerate list | ESC = exit ]") if defined $focus and $focus eq "search"; $f->set("helpmsg", "[ F1 = regenerate list | ENTER = send to xmms | ESC = exit ]") if defined $focus and $focus eq "filelist"; } newlist; helpmsg; while (1) { my $event = $f->run(0); my $focus = $f->get_focus(); helpmsg; next unless defined $event; newlist if $event eq "F1"; newlist if $event eq "ENTER" and defined $focus and $focus eq "search"; play if $event eq "ENTER" and defined $focus and $focus eq "filelist"; last if $event eq "ESC"; } stfl-0.22/perl5/Makefile.PL0000644000000000000000000000051410667031275014113 0ustar rootrootuse ExtUtils::MakeMaker; WriteMakefile( "NAME" => "stfl", # The -D_LARGEFILE64_SOURCE -D_GNU_SOURCE are needed by perl (not STFL!) on some systems "CCFLAGS" => "-pthread -I.. -D_LARGEFILE64_SOURCE -D_GNU_SOURCE", "LIBS" => ["-lpthread -lncursesw"], "OBJECT" => "stfl_wrap.o ../libstfl.a" ); stfl-0.22/perl5/Makefile.snippet0000644000000000000000000000230410651364131015252 0ustar rootroot# # STFL - The Structured Terminal Forms Language/Library # Copyright (C) 2006, 2007 Clifford Wolf # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 3 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA # all: perl5/build_ok install: install_perl5 perl5/build_ok: libstfl.a stfl.h perl5/stfl.i swig/*.i test ! -f perl5/Makefile || $(MAKE) -C perl5 clean cd perl5 && swig -perl5 stfl.i && perl Makefile.PL $(MAKE) -C perl5 && touch perl5/build_ok install_perl5: perl5/build_ok $(MAKE) -C perl5 DESTDIR=$(DESTDIR) PREFIX=$(prefix) install_vendor stfl-0.22/dump.c0000644000000000000000000000705011175231521012214 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * dump.c: Create STFL code from a widget tree */ #include "stfl_internals.h" #include "stfl_compat.h" #include #include #include struct txtnode { struct txtnode *prev; wchar_t *value; int len; }; static void newtxt(struct txtnode **o, const wchar_t *fmt, ...) /* __attribute__ ((format (wprintf, 2, 3))) */ { struct txtnode *n = calloc(1, sizeof(struct txtnode)); n->prev = *o; *o = n; va_list ap; va_start(ap, fmt); wchar_t *buf = malloc(4096 * sizeof(wchar_t)); int buf_len = 4096; while (1) { int rc = vswprintf(buf, buf_len, fmt, ap); if (rc < 0) { free(buf); buf = NULL; break; } if ((rc + 1) < buf_len) { buf = realloc(buf, (rc + 1) * sizeof(wchar_t)); break; } buf_len = buf_len * 2; buf = realloc(buf, buf_len * sizeof(wchar_t)); } n->value = buf; if (n->value) n->len = wcslen(n->value); else n->len = 0; va_end(ap); } static void myquote(struct txtnode **txt, const wchar_t *text) { wchar_t q[2] = {L'"', 0}; int segment_len; if (wcscspn(text, L"'") > wcscspn(text, L"\"")) q[0] = L'\''; while (*text) { segment_len = wcscspn(text, q); newtxt(txt, L"%c%.*ls%c", q[0], segment_len, text, q[0]); q[0] = q[0] == L'"' ? L'\'' : L'"'; text += segment_len; } } static void mydump(struct stfl_widget *w, const wchar_t *prefix, int focus_id, struct txtnode **txt) { newtxt(txt, L"{%ls%ls", w->id == focus_id ? L"!" : L"", w->type->name); if (w->cls) newtxt(txt, L"#%ls", w->cls); if (w->name) { newtxt(txt, L"["); myquote(txt, prefix); myquote(txt, w->name); newtxt(txt, L"]"); } struct stfl_kv *kv = w->kv_list; while (kv) { if (kv->name) { newtxt(txt, L" %ls[", kv->key); myquote(txt, prefix); myquote(txt, kv->name); newtxt(txt, L"]:"); } else newtxt(txt, L" %ls:", kv->key); myquote(txt, kv->value); kv = kv->next; } struct stfl_widget *c = w->first_child; while (c) { mydump(c, prefix, focus_id, txt); c = c->next_sibling; } newtxt(txt, L"}"); } static wchar_t *txt2string(struct txtnode *txt) { int string_len = 0; struct txtnode *t, *prev; for (t=txt; t; t=t->prev) string_len += t->len; wchar_t *string = malloc(sizeof(wchar_t)*(string_len+1)); int i = string_len; for (t=txt; t; t=prev) { i -= t->len; wmemcpy(string+i, t->value, t->len); prev = t->prev; free(t->value); free(t); } string[string_len] = 0; return string; } wchar_t *stfl_quote_backend(const wchar_t *text) { struct txtnode *txt = 0; myquote(&txt, text); return txt2string(txt); } wchar_t *stfl_widget_dump(struct stfl_widget *w, const wchar_t *prefix, int focus_id) { struct txtnode *txt = 0; mydump(w, prefix, focus_id, &txt); return txt2string(txt); } stfl-0.22/spl/0000755000000000000000000000000011651202747011706 5ustar rootrootstfl-0.22/spl/example.spl0000644000000000000000000001014411566455674014077 0ustar rootroot#!/usr/bin/env splrun_norl /* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * example.spl: A little STFL SPL example */ load "sql"; load "sql_utils"; load "stfl"; var db = sql_connect("sqlite", "example.db"); { var count = sql_value(db, "SELECT count(*) FROM people"); var message = "$count addresses in database"; stfl_run(stfl_create("{vbox tie:c {table{label .border:lrtb " "text:${stfl::message}}}}"), 3000); } function search() { var f = stfl_create(<:> : table : @input#style_normal:bg=blue,fg=black : @input#style_focus:bg=blue,fg=white,attr=bold : label : .expand:0 : .border:lt : .spacer:r : text:"Name:" : input[in_name] : .expand:h : .border:rt : .colspan:2 : text[in_name_val]:"" : tablebr : label : .expand:0 : .border:lb : .spacer:r : text:"E-Mail:" : input[in_email] : .expand:h : .border:b : text[in_email_val]:"" : label : .expand:0 : .border:lrtb : text:"Press ENTER to search" : tablebr : list[result] : pos_name[result_rowid]: : style_focus:bg=blue,fg=white,attr=bold : style_selected:bg=blue,fg=black : .colspan:3 : .border:lrtb ); function perform_search() { var in_name = stfl_get(f, "in_name_val"); var in_email = stfl_get(f, "in_email_val"); var tuples = sql(db, <:> : SELECT rowid, * FROM people WHERE 1 : AND name LIKE ${sql::"%$in_name%"} : AND email LIKE ${sql::"%$in_email%"} : LIMIT 50 ); stfl_modify(f, "result", "replace_inner", <:> : list : listitem[rowid_${t.rowid}] : text:${stfl::t['name']}" <"${stfl::t['email']}">" ); } while (1) { switch { var event = stfl_run(f, 0); case event ~== "ENTER" and stfl_get_focus(f) =~ /^in_/: perform_search(); case event ~== "ENTER" and stfl_get_focus(f) ~== "result": if (stfl_get(f, "result_rowid") =~ /rowid_(\d+)/) edit($1); perform_search(); case event ~== "ESC": stfl_reset(); return; } } } function edit(rowid) { var tuple = sql_tuple(db, "SELECT * FROM people WHERE rowid = $rowid"); var fields = [ name: "Name", email: "E-Mail", web: "WWW Address", description: "Description", addr: "Address" ]; var f = stfl_create(<:> : table : @input#style_normal:bg=blue,fg=black : @input#style_focus:bg=blue,fg=white,attr=bold : @input#.expand:h : @input#.border:rtb : @label#.expand:0 : @label#.border:ltb : @label#.spacer:r : label : text:${stfl::fields[i]}: : input[in_$i] : text[in_${i}_val]:${stfl::tuple[i]} : tablebr : vbox : .colspan:2 : .border:lrtb : label .tie:r : text:"Press ENTER to save and ESC to cancel" ); while (1) { switch { var event = stfl_run(f, 0); case event ~== "ENTER": sql(db, <:> : UPDATE people SET : $i = ${sql::stfl_get(f, "in_${i}_val")} : ${ $] ? "" : ","} : WHERE rowid = $rowid ); return; case event ~== "ESC": return; } } } search(); stfl-0.22/spl/genexampledb.spl0000644000000000000000000000321310651364131015053 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * genexampledb.spl: Generate example database for SPL/STFL example */ load "file"; load "sql"; var db = sql_connect("sqlite", "example.db"); var current; sql(db, "CREATE TABLE people (name, email, web, description, addr)"); function addtuple() { if (elementsof current == 0) return; sql(db, <:> : INSERT INTO people : (name, email, web, description, addr) : VALUES : ( : ${sql::current['N']}, : ${sql::current['E']}, : ${sql::current['W']}, : ${sql::current['D']}, : ${sql::current['S']} : ) ); } foreach[] line (file_read("/usr/src/linux/CREDITS", "ascii") =~ /\n/Sg) { if (line =~ /^N:/) { addtuple(); current = undef; } if (line =~ /^(.):\s+(.*)/) { if (current[$1] ~!= "") current[$1] ~= ", "; current[$1] ~= $2; } } addtuple(); stfl-0.22/spl/mod_stfl.c0000644000000000000000000002044611566455674013705 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * mod_stfl.c: STFL bindings for SPL */ /** * STFL module * * This module provides bindings to the Structured Terminal Forms * Language/Library (STFL). */ #include "stfl.h" #include #include #include static struct stfl_ipool *ipool = 0; extern void SPL_ABI(spl_mod_stfl_init)(struct spl_vm *vm, struct spl_module *mod, int restore); extern void SPL_ABI(spl_mod_stfl_done)(struct spl_vm *vm, struct spl_module *mod); static void handler_stfl_form_node(struct spl_task *task, struct spl_vm *vm, struct spl_node *node, struct spl_hnode_args *args, void *data) { if (args->action == SPL_HNODE_ACTION_PUT) { if (node->hnode_data) stfl_free((struct stfl_form *)node->hnode_data); } } static struct stfl_form *clib_get_stfl_form(struct spl_task *task) { struct spl_node *n = spl_cleanup(task, spl_clib_get_node(task)); struct stfl_form *f = n ? n->hnode_data : 0; if (!f || !n->hnode_name || strcmp(n->hnode_name, "stfl_form")) { spl_report(SPL_REPORT_RUNTIME, task, "Expected a STFL-Form as 1st argument!\n"); return 0; } return f; } static struct spl_node *spl_new_nullable_ascii(const char *text) { return text ? SPL_NEW_STRING_DUP(text) : spl_get(0); } /** * Quote a string to be used in STFL code. * * This function is designed to be used with the encoding/quoting operator (::). */ // builtin encode_stfl(text) /** * Parse an STFL description text and return the form handler */ // builtin stfl_create(text) static struct spl_node *handler_stfl_create(struct spl_task *task, void *data) { struct spl_node *n = SPL_NEW_STRING_DUP("STFL Form"); n->hnode_name = strdup("stfl_form"); n->hnode_data = stfl_create(stfl_ipool_towc(ipool, spl_clib_get_string(task))); stfl_ipool_flush(ipool); return n; } /** * Display the form and process one input character */ // builtin stfl_run(form, timeout) static struct spl_node *handler_stfl_run(struct spl_task *task, void *data) { struct stfl_form *f = clib_get_stfl_form(task); struct spl_node *ret = f ? spl_new_nullable_ascii(stfl_ipool_fromwc(ipool, stfl_run(f, spl_clib_get_int(task)))) : 0; stfl_ipool_flush(ipool); return ret; } /** * Return to standard text mode */ // builtin stfl_reset() static struct spl_node *handler_stfl_reset(struct spl_task *task, void *data) { stfl_reset(); return 0; } /** * Get the value of an STFL variable */ // builtin stfl_get(form, name) static struct spl_node *handler_stfl_get(struct spl_task *task, void *data) { struct stfl_form *f = clib_get_stfl_form(task); struct spl_node *ret = f ? spl_new_nullable_ascii(stfl_ipool_fromwc(ipool, stfl_get(f, stfl_ipool_towc(ipool, spl_clib_get_string(task))))) : 0; stfl_ipool_flush(ipool); return ret; } /** * Set an STFL variable */ // builtin stfl_set(form, name, value) static struct spl_node *handler_stfl_set(struct spl_task *task, void *data) { struct stfl_form *f = clib_get_stfl_form(task); char *name = spl_clib_get_string(task); char *value = spl_clib_get_string(task); stfl_set(f, stfl_ipool_towc(ipool, name), stfl_ipool_towc(ipool, value)); stfl_ipool_flush(ipool); return 0; } /** * Get the name of the widget currently having the focus */ // builtin stfl_get_focus(form) static struct spl_node *handler_stfl_get_focus(struct spl_task *task, void *data) { struct stfl_form *f = clib_get_stfl_form(task); struct spl_node *ret = f ? spl_new_nullable_ascii(stfl_ipool_fromwc(ipool, stfl_get_focus(f))) : 0; stfl_ipool_flush(ipool); return ret; } /** * Set the focus to the specified widget */ // builtin stfl_set_focus(form, name) static struct spl_node *handler_stfl_set_focus(struct spl_task *task, void *data) { struct stfl_form *f = clib_get_stfl_form(task); stfl_set_focus(f, stfl_ipool_towc(ipool, spl_clib_get_string(task))); stfl_ipool_flush(ipool); return 0; } /** * Quote a string to be used in STFL code */ // builtin stfl_quote(text) static struct spl_node *handler_stfl_quote(struct spl_task *task, void *data) { struct spl_node *n = spl_new_nullable_ascii(stfl_ipool_fromwc(ipool, stfl_quote(stfl_ipool_towc(ipool, spl_clib_get_string(task))))); stfl_ipool_flush(ipool); return n; } /** * Dump the STFL Code for this form */ // builtin stfl_dump(form, name, prefix, focus) static struct spl_node *handler_stfl_dump(struct spl_task *task, void *data) { struct stfl_form *f = clib_get_stfl_form(task); char *name = spl_clib_get_string(task); char *prefix = spl_clib_get_string(task); int focus = spl_clib_get_int(task); const char *text = stfl_ipool_fromwc(ipool, stfl_dump(f, stfl_ipool_towc(ipool, name), stfl_ipool_towc(ipool, prefix), focus)); struct spl_node *n = spl_new_nullable_ascii(text); stfl_ipool_flush(ipool); return n; } /** * Import STFL code to an existing form */ // builtin stfl_modify(form, name, mode, text) static struct spl_node *handler_stfl_modify(struct spl_task *task, void *data) { struct stfl_form *f = clib_get_stfl_form(task); char *name = spl_clib_get_string(task); char *mode = spl_clib_get_string(task); char *text = spl_clib_get_string(task); stfl_modify(f, stfl_ipool_towc(ipool, name), stfl_ipool_towc(ipool, mode), stfl_ipool_towc(ipool, text)); stfl_ipool_flush(ipool); return 0; } /** * Lookup widgets in the form using a path and optionally assign a new name */ // builtin stfl_lookup(form, path, newname) static struct spl_node *handler_stfl_lookup(struct spl_task *task, void *data) { struct stfl_form *f = clib_get_stfl_form(task); char *path = spl_clib_get_string(task); char *newname = spl_clib_get_string(task); struct spl_node *ret = spl_new_nullable_ascii(stfl_ipool_fromwc(ipool, stfl_lookup(f, stfl_ipool_towc(ipool, path), stfl_ipool_towc(ipool, newname)))); stfl_ipool_flush(ipool); return ret; } /** * Return error message of last stfl call or undef. */ // builtin stfl_error() static struct spl_node *handler_stfl_error(struct spl_task *task, void *data) { struct spl_node *ret = spl_new_nullable_ascii(stfl_ipool_fromwc(ipool, stfl_error())); stfl_ipool_flush(ipool); return ret; } /** * Set error handling algorithm. */ // builtin stfl_error_action(mode) static struct spl_node *handler_stfl_error_action(struct spl_task *task, void *data) { char *mode = spl_clib_get_string(task); stfl_error_action(stfl_ipool_towc(ipool, mode)); stfl_ipool_flush(ipool); return 0; } static void destroy_ipool_atexit() { stfl_ipool_destroy(ipool); ipool = 0; } void SPL_ABI(spl_mod_stfl_init)(struct spl_vm *vm, struct spl_module *mod, int restore) { if (!ipool) { ipool = stfl_ipool_create("UTF8"); atexit(destroy_ipool_atexit); setlocale(LC_ALL,""); } spl_hnode_reg(vm, "stfl_form", handler_stfl_form_node, 0); spl_clib_reg(vm, "stfl_create", handler_stfl_create, 0); spl_clib_reg(vm, "stfl_run", handler_stfl_run, 0); spl_clib_reg(vm, "stfl_reset", handler_stfl_reset, 0); spl_clib_reg(vm, "stfl_get", handler_stfl_get, 0); spl_clib_reg(vm, "stfl_set", handler_stfl_set, 0); spl_clib_reg(vm, "stfl_get_focus", handler_stfl_get_focus, 0); spl_clib_reg(vm, "stfl_set_focus", handler_stfl_set_focus, 0); spl_clib_reg(vm, "encode_stfl", handler_stfl_quote, 0); spl_clib_reg(vm, "stfl_quote", handler_stfl_quote, 0); spl_clib_reg(vm, "stfl_dump", handler_stfl_dump, 0); spl_clib_reg(vm, "stfl_modify", handler_stfl_modify, 0); spl_clib_reg(vm, "stfl_lookup", handler_stfl_lookup, 0); spl_clib_reg(vm, "stfl_error", handler_stfl_error, 0); spl_clib_reg(vm, "stfl_error_action", handler_stfl_error_action, 0); } void SPL_ABI(spl_mod_stfl_done)(struct spl_vm *vm, struct spl_module *mod) { stfl_reset(); } stfl-0.22/spl/Makefile.snippet0000644000000000000000000000240511210546505015022 0ustar rootroot# # STFL - The Structured Terminal Forms Language/Library # Copyright (C) 2006, 2007 Clifford Wolf # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 3 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA # all: spl/mod_stfl.so install: install_spl spl/mod_stfl.so: CFLAGS += $(shell spl-config --cflags) spl/mod_stfl.so: libstfl.a stfl.h spl/mod_stfl.c gcc -pthread -shared -fPIC $(CFLAGS) $(LDFLAGS) spl/mod_stfl.c \ -L. libstfl.a $(LDLIBS) -o spl/mod_stfl.so install_spl: spl/mod_stfl.so mkdir -p $(DESTDIR)$(prefix)/$(libdir)/spl_modules install spl/mod_stfl.so $(DESTDIR)$(prefix)/$(libdir)/spl_modules/ stfl-0.22/base.c0000644000000000000000000003607211651201700012162 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * base.c: Core functions */ #include "stfl_internals.h" #include "stfl_compat.h" #include #include #include #include #include struct stfl_widget_type *stfl_widget_types[] = { &stfl_widget_type_label, &stfl_widget_type_input, &stfl_widget_type_vbox, &stfl_widget_type_hbox, &stfl_widget_type_table, &stfl_widget_type_tablebr, &stfl_widget_type_list, &stfl_widget_type_listitem, &stfl_widget_type_textview, 0 }; int id_counter = 0; int curses_active = 0; struct stfl_widget *stfl_widget_new(const wchar_t *type) { struct stfl_widget_type *t; int setfocus = 0; int i; while (*type == '!') { setfocus = 1; type++; } for (i=0; (t = stfl_widget_types[i]) != 0; i++) if (!wcscmp(t->name, type)) break; if (!t) return 0; struct stfl_widget *w = calloc(1, sizeof(struct stfl_widget)); w->id = ++id_counter; w->type = t; w->setfocus = setfocus; if (w->type->f_init) w->type->f_init(w); return w; } void stfl_widget_free(struct stfl_widget *w) { while (w->first_child) stfl_widget_free(w->first_child); if (w->type->f_done) w->type->f_done(w); struct stfl_kv *kv = w->kv_list; while (kv) { struct stfl_kv *next = kv->next; free(kv->key); free(kv->value); if (kv->name) free(kv->name); free(kv); kv = next; } if (w->parent) { struct stfl_widget **pp = &w->parent->first_child; while (*pp != w) { pp = &(*pp)->next_sibling; } *pp = w->next_sibling; if (w->parent->last_child == w) { struct stfl_widget *p = w->parent->first_child; w->parent->last_child = 0; while (p) { w->parent->last_child = p; p = p->next_sibling; } } } if (w->name) free(w->name); if (w->cls) free(w->cls); free(w); } extern struct stfl_kv *stfl_widget_setkv_int(struct stfl_widget *w, const wchar_t *key, int value) { wchar_t newtext[64]; swprintf(newtext, 64, L"%d", value); return stfl_widget_setkv_str(w, key, newtext); } struct stfl_kv *stfl_widget_setkv_str(struct stfl_widget *w, const wchar_t *key, const wchar_t *value) { struct stfl_kv *kv = w->kv_list; while (kv) { if (!wcscmp(kv->key, key)) { free(kv->value); kv->value = compat_wcsdup(value); return kv; } kv = kv->next; } kv = calloc(1, sizeof(struct stfl_kv)); kv->widget = w; kv->key = compat_wcsdup(key); kv->value = compat_wcsdup(value); kv->id = ++id_counter; kv->next = w->kv_list; w->kv_list = kv; return kv; } extern struct stfl_kv *stfl_setkv_by_name_int(struct stfl_widget *w, const wchar_t *name, int value) { wchar_t newtext[64]; swprintf(newtext, 64, L"%d", value); return stfl_setkv_by_name_str(w, name, newtext); } extern struct stfl_kv *stfl_setkv_by_name_str(struct stfl_widget *w, const wchar_t *name, const wchar_t *value) { struct stfl_kv *kv = stfl_kv_by_name(w, name); if (!kv) return 0; free(kv->value); kv->value = compat_wcsdup(value); return kv; } static struct stfl_kv *stfl_widget_getkv_worker(struct stfl_widget *w, const wchar_t *key) { struct stfl_kv *kv = w->kv_list; while (kv) { if (!wcscmp(kv->key, key)) return kv; kv = kv->next; } return 0; } struct stfl_kv *stfl_widget_getkv(struct stfl_widget *w, const wchar_t *key) { struct stfl_kv *kv = stfl_widget_getkv_worker(w, key); if (kv) return kv; int key1_len = wcslen(key) + 2; wchar_t key1[key1_len]; int key2_len = key1_len + wcslen(w->type->name) + 1; wchar_t key2[key2_len]; int key3_len = w->cls ? key1_len + wcslen(w->cls) + 1 : 0; wchar_t key3[key3_len]; swprintf(key1, key1_len, L"@%ls", key); swprintf(key2, key2_len, L"@%ls#%ls", w->type->name, key); if (key3_len) swprintf(key3, key3_len, L"@%ls#%ls", w->cls, key); while (w) { if (key3_len) { kv = stfl_widget_getkv_worker(w, key3); if (kv) return kv; } kv = stfl_widget_getkv_worker(w, key2); if (kv) return kv; kv = stfl_widget_getkv_worker(w, key1); if (kv) return kv; w = w->parent; } return 0; } int stfl_widget_getkv_int(struct stfl_widget *w, const wchar_t *key, int defval) { struct stfl_kv *kv = stfl_widget_getkv(w, key); int ret; if (!kv || !kv->value[0]) return defval; if (swscanf(kv->value,L"%d",&ret) < 1) return defval; return ret; } const wchar_t *stfl_widget_getkv_str(struct stfl_widget *w, const wchar_t *key, const wchar_t *defval) { struct stfl_kv *kv = stfl_widget_getkv(w, key); return kv ? kv->value : defval; } int stfl_getkv_by_name_int(struct stfl_widget *w, const wchar_t *name, int defval) { struct stfl_kv *kv = stfl_kv_by_name(w, name); int ret; if (!kv || !kv->value[0]) return defval; if (swscanf(kv->value,L"%d",&ret) < 1) return defval; return ret; } const wchar_t *stfl_getkv_by_name_str(struct stfl_widget *w, const wchar_t *name, const wchar_t *defval) { struct stfl_kv *kv = stfl_kv_by_name(w, name); return kv ? kv->value : defval; } struct stfl_widget *stfl_widget_by_name(struct stfl_widget *w, const wchar_t *name) { if (w->name && !wcscmp(w->name, name)) return w; w = w->first_child; while (w) { struct stfl_widget *r = stfl_widget_by_name(w, name); if (r) return r; w = w->next_sibling; } return 0; } struct stfl_widget *stfl_widget_by_id(struct stfl_widget *w, int id) { if (w->id == id) return w; w = w->first_child; while (w) { struct stfl_widget *r = stfl_widget_by_id(w, id); if (r) return r; w = w->next_sibling; } return 0; } struct stfl_kv *stfl_kv_by_name(struct stfl_widget *w, const wchar_t *name) { struct stfl_kv *kv = w->kv_list; while (kv) { if (kv->name && !wcscmp(kv->name, name)) return kv; kv = kv->next; } w = w->first_child; while (w) { struct stfl_kv *r = stfl_kv_by_name(w, name); if (r) return r; w = w->next_sibling; } return 0; } struct stfl_kv *stfl_kv_by_id(struct stfl_widget *w, int id) { struct stfl_kv *kv = w->kv_list; while (kv) { if (kv->id == id) return kv; kv = kv->next; } w = w->first_child; while (w) { struct stfl_kv *r = stfl_kv_by_id(w, id); if (r) return r; w = w->next_sibling; } return 0; } struct stfl_widget *stfl_find_child_tree(struct stfl_widget *w, struct stfl_widget *c) { while (c) { if (c->parent == w) return c; c = c->parent; } return 0; } extern struct stfl_widget *stfl_find_first_focusable(struct stfl_widget *w) { if (w->allow_focus) return w; struct stfl_widget *c = w->first_child; while (c) { struct stfl_widget *r = stfl_find_first_focusable(c); if (r) return r; c = c->next_sibling; } return 0; } int stfl_focus_prev(struct stfl_widget *w, struct stfl_widget *old_fw, struct stfl_form *f) { struct stfl_widget *stop = stfl_find_child_tree(w, old_fw); assert(stop); while (w->first_child != stop) { struct stfl_widget *c = w->first_child; while (c->next_sibling != stop) c = c->next_sibling; struct stfl_widget *new_fw = stfl_find_first_focusable(c); if (new_fw) { if (old_fw->type->f_leave) old_fw->type->f_leave(old_fw, f); if (new_fw->type->f_enter) new_fw->type->f_enter(new_fw, f); f->current_focus_id = new_fw->id; return 1; } stop = c; } return 0; } int stfl_focus_next(struct stfl_widget *w, struct stfl_widget *old_fw, struct stfl_form *f) { struct stfl_widget *c = stfl_find_child_tree(w, old_fw); assert(c); c = c->next_sibling; while (c) { struct stfl_widget *new_fw = stfl_find_first_focusable(c); if (new_fw) { if (old_fw->type->f_leave) old_fw->type->f_leave(old_fw, f); if (new_fw->type->f_enter) new_fw->type->f_enter(new_fw, f); f->current_focus_id = new_fw->id; return 1; } c = c->next_sibling; } return 0; } int stfl_switch_focus(struct stfl_widget *old_fw, struct stfl_widget *new_fw, struct stfl_form *f) { if (!new_fw || !new_fw->allow_focus) return 0; if (!old_fw && f->current_focus_id) old_fw = stfl_widget_by_id(f->root, f->current_focus_id); if (old_fw && old_fw->type->f_leave) old_fw->type->f_leave(old_fw, f); if (new_fw->type->f_enter) new_fw->type->f_enter(new_fw, f); f->current_focus_id = new_fw->id; return 1; } struct stfl_form *stfl_form_new() { struct stfl_form *f = calloc(1, sizeof(struct stfl_form)); if (f) { pthread_mutex_init(&f->mtx, NULL); } return f; } void stfl_form_event(struct stfl_form *f, wchar_t *event) { struct stfl_event **ep = &f->event_queue; struct stfl_event *e = calloc(1, sizeof(struct stfl_event)); e->event = event; while (*ep) ep = &(*ep)->next; *ep = e; } static struct stfl_widget* stfl_gather_focus_widget(struct stfl_form* f) { struct stfl_widget *fw = stfl_widget_by_id(f->root, f->current_focus_id); if (fw == 0) { fw = stfl_find_first_focusable(f->root); if (fw && fw->type->f_enter) fw->type->f_enter(fw, f); } return fw; } void stfl_form_run(struct stfl_form *f, int timeout) { wchar_t *on_handler = 0; pthread_mutex_lock(&f->mtx); if (f->event) free(f->event); f->event = 0; if (timeout >= 0 && f->event_queue) goto unshift_next_event; if (timeout == -2) goto unshift_next_event; if (!f->root) { fprintf(stderr, "STFL Fatal Error: Called stfl_form_run() without root widget.\n"); abort(); } if (!curses_active) { initscr(); cbreak(); noecho(); nonl(); keypad(stdscr, TRUE); doupdate(); start_color(); use_default_colors(); wbkgdset(stdscr, ' '); curses_active = 1; } stfl_colorpair_counter = 1; f->root->type->f_prepare(f->root, f); struct stfl_widget *fw = stfl_gather_focus_widget(f); f->current_focus_id = fw ? fw->id : 0; getbegyx(stdscr, f->root->y, f->root->x); getmaxyx(stdscr, f->root->h, f->root->w); if (timeout == -3) { WINDOW *dummywin = newwin(0, 0, 0, 0); if (dummywin == NULL) { fprintf(stderr, "STFL Fatal Error: stfl_form_run() got a NULL pointer from newwin(0, 0, 0, 0).\n"); abort(); } f->root->type->f_draw(f->root, f, dummywin); delwin(dummywin); pthread_mutex_unlock(&f->mtx); return; } werase(stdscr); f->root->type->f_draw(f->root, f, stdscr); if (timeout == -1 && f->root->cur_y != -1 && f->root->cur_x != -1) { wmove(stdscr, f->root->cur_y, f->root->cur_x); } refresh(); if (timeout < 0) { pthread_mutex_unlock(&f->mtx); return; } wtimeout(stdscr, timeout == 0 ? -1 : timeout); wmove(stdscr, f->cursor_y, f->cursor_x); wint_t wch; pthread_mutex_unlock(&f->mtx); int rc = wget_wch(stdscr, &wch); pthread_mutex_lock(&f->mtx); /* fw may be invalid, regather it */ fw = stfl_gather_focus_widget(f); f->current_focus_id = fw ? fw->id : 0; struct stfl_widget *w = fw; if (rc == ERR) { stfl_form_event(f, compat_wcsdup(L"TIMEOUT")); goto unshift_next_event; } wchar_t *on_event = stfl_keyname(wch, rc == KEY_CODE_YES); int on_handler_len = wcslen(on_event) + 4; on_handler = malloc(on_handler_len * sizeof(wchar_t)); swprintf(on_handler, on_handler_len, L"on_%ls", on_event); free(on_event); while (w) { const wchar_t *event = stfl_widget_getkv_str(w, on_handler, 0); if (event) { stfl_form_event(f, compat_wcsdup(event)); goto unshift_next_event; } if (w->type->f_process && w->type->f_process(w, fw, f, wch, rc == KEY_CODE_YES)) goto unshift_next_event; if (stfl_widget_getkv_int(w, L"modal", 0)) goto generate_event; w = w->parent; } if (rc != KEY_CODE_YES && wch == L'\t') { struct stfl_widget *old_fw = fw = stfl_widget_by_id(f->root, f->current_focus_id); if (!fw) goto generate_event; do { if (fw->first_child) fw = fw->first_child; else if (fw->next_sibling) fw = fw->next_sibling; else { while (fw->parent && !fw->parent->next_sibling) fw = fw->parent; fw = fw->parent ? fw->parent->next_sibling : 0; } if (!fw && old_fw) fw = f->root; } while (fw && !fw->allow_focus); if (old_fw != fw) { if (old_fw && old_fw->type->f_leave) old_fw->type->f_leave(old_fw, f); if (fw && fw->type->f_enter) fw->type->f_enter(fw, f); f->current_focus_id = fw ? fw->id : 0; } goto unshift_next_event; } generate_event: stfl_form_event(f, stfl_keyname(wch, rc == KEY_CODE_YES)); unshift_next_event:; struct stfl_event *e = f->event_queue; if (e) { f->event_queue = e->next; f->event = e->event; free(e); } pthread_mutex_unlock(&f->mtx); free(on_handler); } void stfl_form_reset() { if (curses_active) { endwin(); curses_active = 0; } } void stfl_form_free(struct stfl_form *f) { pthread_mutex_lock(&f->mtx); if (f->root) stfl_widget_free(f->root); if (f->event) free(f->event); pthread_mutex_unlock(&f->mtx); free(f); } void stfl_check_setfocus(struct stfl_form *f, struct stfl_widget *w) { if (w->setfocus) { f->current_focus_id = w->id; w->setfocus = 0; } w = w->first_child; while (w) { stfl_check_setfocus(f, w); w = w->next_sibling; } } static unsigned int compute_len_from_width(const wchar_t *p, unsigned int width) { unsigned int len = 0; unsigned int end_loop = 0; while (p && *p && !end_loop) { if (wcwidth(*p) > width) { end_loop = 1; } else { width -= wcwidth(*p); p++; len++; } } return len; } unsigned int stfl_print_richtext(struct stfl_widget *w, WINDOW *win, unsigned int y, unsigned int x, const wchar_t * text, unsigned int width, const wchar_t * style_normal, int has_focus) { const wchar_t *p = text; unsigned int retval = 0; unsigned int end_col = x + width; while (*p) { unsigned int len = compute_len_from_width(p, end_col - x); const wchar_t *p1 = wcschr(p, L'<'); if (NULL == p1) { mvwaddnwstr(win, y, x, p, len); retval += len; break; } else { const wchar_t *p2 = wcschr(p1 + 1, L'>'); if (len > (p1 - p)) len = p1 - p; mvwaddnwstr(win, y, x, p, len); retval += len; x += wcswidth(p, len); if (p2) { wchar_t stylename[p2 - p1]; wmemcpy(stylename, p1 + 1, p2 - p1 - 1); stylename[p2 - p1 - 1] = L'\0'; if (wcscmp(stylename,L"")==0) { mvwaddnwstr(win, y, x, L"<", 1); retval += 1; ++x; } else if (wcscmp(stylename, L"/")==0) { stfl_style(win, style_normal); } else { wchar_t lookup_stylename[128]; const wchar_t * style; if (has_focus) swprintf(lookup_stylename, sizeof(lookup_stylename)/sizeof(*lookup_stylename), L"style_%ls_focus", stylename); else swprintf(lookup_stylename, sizeof(lookup_stylename)/sizeof(*lookup_stylename), L"style_%ls_normal", stylename); style = stfl_widget_getkv_str(w, lookup_stylename, L""); stfl_style(win, style); } p = p2 + 1; } else { break; } } } return retval; } stfl-0.22/binding.c0000644000000000000000000000600410651364131012661 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * binding.c: Helper functions for key bindings and stuff */ #include "stfl_internals.h" #include "stfl_compat.h" #include #include #include wchar_t *stfl_keyname(wchar_t ch, int isfunckey) { if (!isfunckey) { if (ch == L'\r' || ch == L'\n') return compat_wcsdup(L"ENTER"); if (ch == L' ') return compat_wcsdup(L"SPACE"); if (ch == L'\t') return compat_wcsdup(L"TAB"); if (ch == 27) return compat_wcsdup(L"ESC"); if (ch == 127) return compat_wcsdup(L"BACKSPACE"); wchar_t *ret; if (ch < 32) { const char * key = keyname(ch); unsigned int keylen = strlen(key) + 1, i; ret = malloc(keylen * sizeof(wchar_t)); for (i=0; i 0 && len == event_len && !wcsncmp(desc, event, len)) { free(event); return 1; } desc += len; } if (retry_auto_desc > 0) { retry_auto_desc = -1; desc = auto_desc; goto retry_auto_desc; } free(event); return 0; } stfl-0.22/README0000644000000000000000000006653011564440245012002 0ustar rootroot ########################################################################## # # # STFL - The Structured Terminal Forms Language/Library # # Copyright (C) 2006, 2007 Clifford Wolf # # # # This library is free software; you can redistribute it and/or # # modify it under the terms of the GNU Lesser General Public # # License as published by the Free Software Foundation; either # # version 3 of the License, or (at your option) any later version. # # # ########################################################################## STFL - Structured Terminal Forms Language/Library ================================================= STFL is a library which implements a curses-based widget set for text terminals. The STFL API can be used from C, SPL, Python, Perl and Ruby. The public STFL API is only 14 simple function calls big and there are already generic SWIG bindings. Thus is very easy to port STFL to additional scripting languages. A special language (the Structured Terminal Forms Language) is used to describe STFL GUIs. The language is designed to be easy and fast to write so an application programmer does not need to spend ages fiddling around with the GUI and can concentrate on the more interesting programming tasks. There are two different syntaxes for STFL code, one designed to make handwriting of STFL code as easy as possible and one aiming at generated STFL code. The STFL GUI descriptions (written in STFL code) do not contain any concrete layouting information such as x/y coordinates of widgets. Instead container widgets such as vertical and horizontal boxes as well as tables are used to group widgets and the actual layouting work is done by the STFL library. Thus STFL GUIs can handle terminals of different sizes and terminal resize events transparently for the application programmer. Building and Installing STFL ---------------------------- Simply run 'make' and 'make install'. You might want to edit the Makefile.cfg file before building and installing STFL. In order to build a full-featured STFL with all scripting language bindings enabled you need to have the following packages installed (including the development packages): ncursesw The wide-character ncurses library. On some distributions this might be part of the ncurses package, on other distrubutions this might be an extra package. SWIG STFL is using SWIG for generating the Perl, Python and Ruby language bindings. Perl, Python, Ruby, SPL In order to create the language bindings you need to have the languages themself installed. Since STFL is a wide-character library it will only work on systems which do have wide-character support in the system libraries. This might not be the case for in older Linux distributions or other UNIXes. The Structured Terminal Forms Language -------------------------------------- STFL Forms consist of (instances of) widgets which are organized in a tree. A special language - the Structured Terminal Forms Language - can be used to describe such trees in an efficient and still easy to read and maintain way. The Structured Terminal Forms Language has only two syntactical constructs: Variable declarations and widget instanciations. Each widget instanciation may contain variable declarations and child widget instanciations. A widget can be instanciated by simly writing down the type of the widget. Example given: vbox Sometimes one wants to give the instanciated widget a name so the widget can be easily accesed later. This can be done by appending the widget name using square brackets: label[foobar] Child widgets are instanciated the same way but must be indented: vbox label[label1] label[label2] Note that one must not use tabs for the indenting. Only blanks are allowed. Variables are declared like child widgets. A variable consists of a key and a value, seperated by a colon. Values can be quoted using single or double quotes when they contain blanks. vbox label[label1] text:"Hello World!" label[label2] text:"This is a test.." It is also possible to append an additional name to variables using square brackets so the application can read and write the variable value: vbox label[label1] text[label1_text]:"Hello World!" label[label2] text[label2_text]:"This is a test.." Usually variables configure the widget they are directly associated with or store status information from that widget. But sometimes variables contain information about the relationship of the widget they are directly associated with and its parent widget. This variables are always start with a dot. Example given the .border variable can be used to configure the borders of table cells: table label .border:lrtb text:"Hello" label .border:lrtb text:"World!" Sometimes one wants to set a variable not only for the current widget but also for all its child widgets. This can be done by prefixing the variable name with he at-sign. Example given: vbox @style_normal:fg=white,bg=blue label text:"White text.." label text:"..on blue background." This kind of variables can also be defined for only one widget type: vbox @style_normal:fg=white,bg=blue @input#style_normal:fg=black,bg=red label text:"White text on blue background." input text:"Black text on red background." Alternatively it is possible to postfix the widget types with '#classname' and prefix the variables with 'classname#': vbox @style_normal:fg=white,bg=blue @foobar#style_normal:fg=black,bg=red label text:"White text on blue background." input#foobar text:"Black text on red background." While widget instanciations must alsways be on a new line, variable declarions can also be written on the same line as the widget they are for and it is possible to declare more than one variable in one line: table label .border:lrtb text:"Hello" label .border:lrtb text:"World!" Sometimes one wants to generate STFL code from scripts. In this cases it can become hard to automatically generate the indenting correctly. For such situations it is possible to use a different format with curly brackets. The following two code fragmentsa are identical: vbox hbox label .expand:0 text:"Foo: " input[foo] text:"Hello" hbox label .expand:0 text:"Bar: " input[bar] text:"World!" {vbox{hbox{label .expand:0 text:"Foo: "}{input[foo] text:"Hello"} {hbox{label .expand:0 text:"Bar: "}{input[bar] text:"World!"}}} Newline characters are not allowed inside of an STFL code fragment in curly brackets (the example above is just broken up in two line to improve the readability). It is even possible to embed an STFL code fragment in curly brackets in a normal indented code block. Example given: vbox {hbox{label .expand:0 text:"Foo: "}{input[foo] text:"Hello"}} {hbox{label .expand:0 text:"Bar: "}{input[bar] text:"World!"}} It is also possible to include the focus information in STFL code: Simply prefix the widget which shall have the focus with a '!'. Only one widget may have the focus at a time. The STFL parser can also read external files. This can be done by putting the filename in < > brackets in the STFL file. Note that this is not a varbatim include but calls another parser instance recursively. So there is an extra indenting / curly brackets state for the external file. Comment lines in STFL code start with a '*' character. There must be no statement in the same line as the comment (i.e. only whitespaces are allowed before the '*' character). Comment are not allowed within a code fragment in curly brackets. The STFL Style Descriptions --------------------------- STFL is using a generic syntax whenever the style (color, etc.) of a text can be specified: A comma seperated key=value list, where the key can be 'bg' for background, 'fg' for foreground and 'attr' for text attributes. Example given the following style string can be used for creating bold blinking white text on blue background: bg=blue,fg=white,attr=bold,attr=blink The following colors are supported: black red green yellow blue magenta cyan white And the following attributes: standout underline reverse blink dim bold protect invis On terminals that support 256 colors it's also possible to use extended colors, by using "color" as color name, where "" is a number between 0 and 255. For a complete chart of numbers and their corresponding colors, please see here: http://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html The terminal default colors are used when no background or no foreground color is specified. So keep care when only specifying one value. Example given text printed using the style string 'fg=white' can't be seen on terminals with a white default background. Key and Keybinding Descriptions ------------------------------- Key descriptings are strings describing a key press event. With some exceptions this are the return values of the ncurses keyname() and key_name() functions. The exceptions are: ENTER The return key has been pressed. SPACE The space key has been pressed. TAB The tabulator key has been pressed. ESC The escape key has been pressed. F0 .. F63 A function key has been pressed. UNKNOWN An unkown key has been pressed. (Usually this is the result of a broken multibyte sequence) A key binding description is a whitespace-seperated list of key descriptions used in bind_* variables to bind keys to widget actions. Each widget provides default bindings for all its actions. If you want to extend the list of bind keys instead of overwriting them you must use the special key-description "**" in the keybinding description to refer to the default bindings. Key values can e.g. be dumped using the following little Perl script: perl -mstfl -le '$_ = stfl::create("label text:\"Press a key\"")->run(0); stfl::reset(); print;' The STFL Widget Library ----------------------- vbox and hbox ~~~~~~~~~~~~~ This widgets simply layouts its child widgets vertically or horizontally repectively. The following variables are supported by both widgets: bind_left, bind_right The keybindings in a hbox for changing the focus to the next or previous child widget. Default values are the LEFT and RIGHT keys. bind_up, bind_down The keybindings in a vbox for changing the focus to the next or previous child widget. Default values are the UP and DOWN keys. style_normal The background style. tie Tie the box containing the widgets to the specified borders. The value is a string containing the characters 'l' (left border), 'r' (right border), 't' (top border), 'b' (bottom border) and 'c' (center). The default value is 'lrtb'. .tie Tie this widget within its sub-box to the specified borders. The value is using the same syntax as the "tie" variable above. .expand Contains the information if child widgets should be expanded to fit the available space. The value is a string that may contain the characters 'v' (for vertical expansion), 'h' (for horizontal expansion) and '0' (for no expansion). The hbox widget ignores the vertical expansion information and the vbox widget the horizontal expansion information. The default value is 'vh'. .height Hardcode the height of this child widget to the specified number of lines. Usually one wants to also declare .expand:0 when declaring this variable. .width Hardcode the width of this child widget to the specified number of characters. Usually one wants to also declare .expand:0 when declaring this variable. .display Simply ignore this child widget if this variable is set to '0'. The default value is '1'. label ~~~~~ A simple text label. The following variables are supported by this widget: style_normal The style used for displaying the text. text The text to be displayed input ~~~~~ A simple input widget for one line of text input. The following variables are supported by this widget: bind_left, bind_right Move the cursor left and right. Default values are the LEFT and RIGHT keys. bind_home Move the cursor to the first character. Default values are the HOME key or Ctrl-A. bind_end Move the cursor after the last character. Default values are the END key or Ctrl-E. bind_delete Delete the character under the cursor. Default value is the DEL key. bind_backspace Delete the character before the cursor. Default value is the BACKSPACE key. style_normal The style of this widget when it does not have the focus. style_focus The style of this widget when it does have the focus. text The value displayed in the input box. pos The current cursor position in the input box. offset The offset of the text displayed in the input box (when the text is larger then the input box). table ~~~~~ The most important container widget. The special widget 'tablebr' is used to mark the begin of a new table row. The following variables are supported by this widget: bind_left, bind_right, bind_up, bind_down The keybindings for changing the focus within a table. Default values are the UP, DOWN, LEFT and RIGHT keys. style_normal The style for the table bordes. .expand Contains the information if child widgets should be expanded to fit the available space. The value is a string that may contain the characters 'v' (for vertical expansion), 'h' (for horizontal expansion) and '0' (for no expansion). Since there is just one width for all cells in a column and just one height for all cells in a row it still may happen that cells are expanded a bit. The default value is 'vh'. .height, .width Hardcode the height or .width of this table cell to the specified number of characters. Usually one wants to also declare .expand:0 when declaring one of this variables. .colspan, .rowspan The number of columns or rows for this cell. Default is '1'. .border The borders for this cell. This is a string which may contain the characters 'l', 'r', 't' and 'b' for left, right, top and bottom borders. .spacer Like .border, but only adds a spacer between the cells. .tie Tie this table cell within its box to the specified borders. The value is a string containing the characters 'l' (left border), 'r' (right border), 't' (top border), 'b' (bottom border) and 'c' (center). The default value is 'lrtb'. list ~~~~ The list widget can be used to display a list of items, one per line. The items are stored as 'listitem' child widgets of the 'list' widget. When there are more items then the list widget has lines the list widget is automatically scrolling. The list widget implements the following variables: bind_up, bind_down The key bindings for scrolling up or down by line. Default values are the UP and DOWN keys. bind_page_up, bind_page_down The key bindings for scrolling up or down by page. Default values are the PAGE_UP and PAGE_DOWN keys. style_focus Style of the active list item when the widget has the focus. style_selected Style of the active list item when the widget has not the focus. style_normal Style of the currently not active list items. pos The number of the current list item pos_name The widget name of the current list item. offset The numer of the list item displayed in the first line (this becomes >0 when scrolling). listitem ~~~~~~~~ An in a list widget. Implements the following variables: text The text displayed in this list item. textview ~~~~~~~~ A widget for displaying multiline text. The text itself is stored within listitem child widgets. Implements the following variables: bind_up, bind_down The key bindings for scrolling up or down by line. Default values are the UP and DOWN keys. bind_page_up, bind_page_down The key bindings for scrolling up or down by page. Default values are the PAGE_UP and PAGE_DOWN keys. style_normal The style the text itself is displayed. style_end The style used for the EOT-Markers. offset The number of the first line displayed (becomes >0 when scrolling). richtext Set to '1' to enable richtext support style_FOOBAR_normal The style for text after a . the token can be used to restore the style_normal settings. this variables are only used if the 'richtext' variable is set. Common Variables ---------------- There are some variables which are used by the STFL core to configure some widget-independent features. modal ~~~~~ A widget which has the modal variable set to '1' will not pass any events to its parent widgets. Eighter the event is handled by the widget itself or it is returned directly to the caller of stfl_run(). autobind ~~~~~~~~ Setting autobind to '0' disables all automatically assigned keybindings for this widget. Actions which aren't set explicitely bind to keys using the bind_* variables are left unbind and can't be triggered using the user interface. on_* ~~~~ The on_* variables can be used to catch keypresses in this widget and return the value of the on_* variable to the caller of stfl_run(). The on_* variables are evaluated before the keypresses are passed to the widget. The '*' part of the on_* variables is a key description. E.g. "on_^X:foobar" will let stfl_run() return the string "foobar" when Ctrl-X is beeing pressed. The Common STFL Scripting Language API -------------------------------------- STFL has a big C-API which allows a wide range of in-depth operations on widget trees. But most of this C-API is only needed for writing new STFL widgets. The common STFL scripting language API only has a small number of functions and besides the 'form handlers' this functions do only operate on read-only scalar values, so it is pretty easy to write additional bindings for scripting languages not yet supported by STFL. C API Notes ~~~~~~~~~~~ All functions listed here are also available thru the STFL C-API. All strings returned by stfl functions are constant and must not be freed or modified by the caller. When the caller wants to preserve a string for longer than until the next stfl function call the caller must copy the strings. All strings passed to STFL functions are considered read-only by STFL and are neither modified nor freed by STFL. The functions which may return an null value will return a null-pointer in C. All string parameters which are null-pointers are interpreted as they where empty strings. Unicode Support ~~~~~~~~~~~~~~~ The STFL C Library handles all strings as wide character strings (wchar_t*). So the STFL library itself has complete Unicode support. All current scripting language bindings convert all strings passed between STFL and the scripting language to UTF-8. Programs using STFL directly might use the STFL "ipool" API for easy conversion betweed wide characters and other encodings. SPL API Notes ~~~~~~~~~~~~~ The stfl_free() function is not implemented in SPL because the SPL garbage collector does call the low-level STFL free function automatically. The stfl_reset() function is automatically called when the STFL module is unloaded (i.e. on program termination). The stfl_quote() function can also be called using the name encode_stfl() so it can be used with the SPL encoding/quoting operator (::). Python API Notes ~~~~~~~~~~~~~~~~ The stfl_free() function is not implemented in Python because the garbage collector does call the low-level STFL free function automatically. The stfl_reset() function is automatically called on program termination. The functions which take a form as first parameter can also be called as method of the form. All functions are in the "stfl" namespace, so the "stfl_" prefix for the function names is replaced with "stfl." in python. Perl API Notes ~~~~~~~~~~~~~~ The stfl_free() function is not implemented in Perl because the garbage collector does call the low-level STFL free function automatically. The stfl_reset() function is automatically called on program termination. The functions which take a form as first parameter can also be called as method of the form. All functions are in the "stfl" namespace, so the "stfl_" prefix for the function names is replaced with "stfl::" in perl. Ruby API Notes ~~~~~~~~~~~~~~ The stfl_free() function is not implemented in Perl because the garbage collector does call the low-level STFL free function automatically. The stfl_reset() function is automatically called on program termination. The functions which take a form as first parameter can also be called as method of the form. All functions are in the "Stfl" namespace, so the "stfl_" prefix for the function names is replaced with "Stfl." in ruby. stfl_create(text) ~~~~~~~~~~~~~~~~~ Parses the the STFL description text passed as parameter and returns a form handler. Most of the following functions expect such a form handler as first parameter. stfl_free(form) ~~~~~~~~~~~~~~~ Free all resources associated with this form. On languages with a garbage collector calling this function is optional and might even be implemented as no-op. stfl_run(form, timeout) ~~~~~~~~~~~~~~~~~~~~~~~ Return the next event. If no more prior generated events are waiting display the form and process one input character. The event string can be an null value when something changed in the form (e.g. the user changed the focus of the current widget) but all inputs have been handled internally inside of STFL. The event string can be "TIMEOUT" when the timeout has been reached, a key description is key has been pressed that is not beeing hadled internally in STFL or the value of an on_* variable can be returned if a keypress has been catched using such a variable. The 2nd parameter is a timeout in ms. When no key has been pressed until this timeout has been reached the function returns with a "TIMEOUT" event. Set this parameter to 0 to disable the timeout. When the timeout parameter is set to -1 the form is displayed independent of the current status of the event queue and the function returns right after displaying the form without handling any input characters. In this mode always an null value is returned. When the timeout parameter is set to -2 the displayed is not updated and the next pending event is returned. If there are no pending events an null value is returned. When the timeout parameter is set to -3, rendering (and setting the :x, :y, :w and :h pseudo-variables) is done but the screen is not updated and no events are fetched. This is usefull for incrementing rendering processes where appropriate :x, :y, :w and/or :h values are needed for finishing the layout. stfl_reset() ~~~~~~~~~~~~ The stfl_run() function automatically activates ncurses. This function can be used to explicitely switch back to normal text mode. In some languages this is automatically done on program termination. stfl_get(form, name) ~~~~~~~~~~~~~~~~~~~~ Returns the current value of the specified variable. When the variable does not exist this function returns an null value. stfl_set(form, name, value) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ This sets the specified variable to the specified value. stfl_get_focus(form) ~~~~~~~~~~~~~~~~~~~~ Returns the name of the widget which currently has the focus or an null value when the widget having the focus has no name. stfl_set_focus(form, name) ~~~~~~~~~~~~~~~~~~~~~~~~~~ Set the focus to the specified widget. stfl_quote(text) ~~~~~~~~~~~~~~~~ Quote the text so it can be savely used as variable value in STFL code. stfl_dump(form, name, prefix, focus) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Return the subtree starting with the widget specified in the 2nd parameter as STFL code fragment. The entire form is return when the 2nd parameter is an empty string or null. All widget and variable names in the dump are prefixed with the string in the 3rd parameter. The information which widget has the focus is also included in the dump when the 4th parameter is an integer not equal 0. The function returns an null value when there was an error. stfl_modify(form, name, mode, text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Import the STFL code specified in the 4th parameter to an existing form. The 2nd parameter is used to specify a widget which is used as starting point for the modification. The 3rd parameter is a string specifying how the new STFL code should be added to the widget tree: delete Delete the widget. The 4th parameter is ignored in this mode. replace Replace the widget in the tree with the new tree. replace_inner Replace the child list of the widget with the child list of the root element of the new tree. insert Add the new tree at the begin of the child list of the widget. insert_inner Add the child list of the root element of the new tree at the begin of the child list of the widget. append Add the new tree at the end of the child list of the widget. append_inner Add the child list of the root element of the new tree at the end of the child list of the widget. before Add the new tree before the widget. before_inner Add the child list of the root element of the new tree before the widget. after Add the new tree after the widget. after_inner Add the child list of the root element of the new tree after the widget. The widget type of the root element of the tree passed in the 4th parameter doesn't matter in the *_inner modes. stfl_lookup(form, path, newname) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Lookup widgets in the form using a path and optionally assign a new name. This function is not implemented yet. stfl_error() ~~~~~~~~~~~~ Return the error status of the last STFL call. This is null when no error occoured and the error message otherwise. An error could e.g. be a parser error for broken STFL code. WARNING: This is a planned feature! This version of STFL simply calls abort() if an internal error is catched. stfl_error_action(mode) ~~~~~~~~~~~~~~~~~~~~~~~ Set the error handling algorithm. The following strings are valid as mode parameter: abort Print error message to stderr and call the abort() function. exit Print error message to stderr and call exit(1). print Print error message to stderr and continue execution. interactive Display a little menu and let the user decide what to do. none Do nothing - just continue program execution. The default mode is "interactive". WARNING: This is a planned feature! This version of STFL simply calls abort() if an internal error is catched. Pseudo Variables ---------------- When a widget has a name (declared using the 'widget[name]' syntax in the STFL code), there are also some special pseudo-variables which can only be accessed for reading. Note that this pseudo-variables do only have valid values after the widget has been drawed already. So it is always a good idea to run stfl_run() with a timeout of -1 before accessing the pseudo-variables. widgetname:x ~~~~~~~~~~~~ The absolute x-position of the widget on the screen. (from the left border) widgetname:y ~~~~~~~~~~~~ The absolute y-position of the widget on the screen. (from the upper border) widgetname:w ~~~~~~~~~~~~ The width of the widget. widgetname:h ~~~~~~~~~~~~ The height of the widget. widgetname:minw ~~~~~~~~~~~~~~~ The minimal width (i.e. before expanding) of the widget. widgetname:minh ~~~~~~~~~~~~~~~ The minimal height (i.e. before expanding) of the widget. TODOs ----- - Implement so far unimplemented widgets - Missing error handling and reporting - Implement stfl_lookup() function stfl-0.22/stfl.h0000644000000000000000000000470510651364131012232 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * stfl.h: The STFL C header file */ #ifndef STFL_H #define STFL_H 1 #include #ifdef __cplusplus extern "C" { #endif extern int stfl_api_allow_null_pointers; struct stfl_form; struct stfl_ipool; extern struct stfl_form *stfl_create(const wchar_t *text); extern void stfl_free(struct stfl_form *f); extern const wchar_t *stfl_run(struct stfl_form *f, int timeout); extern void stfl_reset(); extern const wchar_t * stfl_get(struct stfl_form *f, const wchar_t *name); extern void stfl_set(struct stfl_form *f, const wchar_t *name, const wchar_t *value); extern const wchar_t *stfl_get_focus(struct stfl_form *f); extern void stfl_set_focus(struct stfl_form *f, const wchar_t *name); extern const wchar_t *stfl_quote(const wchar_t *text); extern const wchar_t *stfl_dump(struct stfl_form *f, const wchar_t *name, const wchar_t *prefix, int focus); extern void stfl_modify(struct stfl_form *f, const wchar_t *name, const wchar_t *mode, const wchar_t *text); extern const wchar_t *stfl_lookup(struct stfl_form *f, const wchar_t *path, const wchar_t *newname); extern const wchar_t *stfl_error(); extern void stfl_error_action(const wchar_t *mode); extern struct stfl_ipool *stfl_ipool_create(const char *code); extern void *stfl_ipool_add(struct stfl_ipool *pool, void *data); extern const wchar_t *stfl_ipool_towc(struct stfl_ipool *pool, const char *buf); extern const char *stfl_ipool_fromwc(struct stfl_ipool *pool, const wchar_t *buf); extern void stfl_ipool_flush(struct stfl_ipool *pool); extern void stfl_ipool_destroy(struct stfl_ipool *pool); #ifdef __cplusplus } #endif #endif stfl-0.22/widgets/0000755000000000000000000000000011651202747012556 5ustar rootrootstfl-0.22/widgets/wt_table.c0000644000000000000000000004232710651364131014526 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * wt_table.c: Widget type 'table' */ #include "stfl_internals.h" #include #include #include #define MAX_ROWS 20 #define MAX_COLS 20 struct table_cell_data { struct stfl_widget *w; struct table_cell_data *mastercell; unsigned char vexpand, hexpand, spanpadding; unsigned char colspan_nr, rowspan_nr; unsigned char colspan, rowspan; unsigned char mc_border_l, mc_border_r; unsigned char mc_border_t, mc_border_b; unsigned char border_l, border_r; unsigned char border_t, border_b; }; struct table_rowcol_data { unsigned char min, size; unsigned char expand; }; struct table_data { int rows, cols; struct table_cell_data *map[MAX_COLS][MAX_ROWS]; struct table_rowcol_data *rowd; struct table_rowcol_data *cold; }; static void free_table_data(struct table_data *d) { int i, j; for (i=0; i < MAX_COLS; i++) for (j=0; j < MAX_ROWS; j++) if (d->map[i][j]) free(d->map[i][j]); free(d->rowd); free(d->cold); free(d); } static inline int max(int a, int b) { return a > b ? a : b; } static void wt_table_done(struct stfl_widget *w) { if (w->internal_data) free_table_data(w->internal_data); } static void wt_table_prepare(struct stfl_widget *w, struct stfl_form *f) { struct table_data *d = calloc(1, sizeof(struct table_data)); if (w->internal_data) free_table_data(w->internal_data); w->internal_data = d; d->rows = 1; int col_counter = 0; int row_counter = 0; int max_colspan = 0; int max_rowspan = 0; int i, j; struct stfl_widget *c = w->first_child; while (c) { if (!wcscmp(c->type->name, L"tablebr")) { if (c->next_sibling) row_counter++; col_counter = 0; } else { while (d->map[col_counter][row_counter]) col_counter++; assert(col_counter < MAX_COLS && row_counter < MAX_ROWS); int colspan = stfl_widget_getkv_int(c, L".colspan", 1); int rowspan = stfl_widget_getkv_int(c, L".rowspan", 1); max_colspan = max(max_colspan, colspan); max_rowspan = max(max_rowspan, rowspan); d->cols = max(d->cols, col_counter+colspan); d->rows = max(d->rows, row_counter+rowspan); const wchar_t *expand = stfl_widget_getkv_str(c, L".expand", L"vh"); const wchar_t *spacer = stfl_widget_getkv_str(c, L".spacer", L""); const wchar_t *border = stfl_widget_getkv_str(c, L".border", L""); for (i=col_counter; imap[i][j] = calloc(1, sizeof(struct table_cell_data)); d->map[i][j]->mastercell = d->map[col_counter][row_counter]; if (i != col_counter || j != row_counter) d->map[i][j]->spanpadding = 1; d->map[i][j]->colspan_nr = i-col_counter; d->map[i][j]->rowspan_nr = j-row_counter; d->map[i][j]->vexpand = wcschr(expand, L'v') != 0; d->map[i][j]->hexpand = wcschr(expand, L'h') != 0; if (i == col_counter) { if (wcschr(spacer, L'l') != 0) d->map[i][j]->border_l = 1; if (wcschr(border, L'l') != 0) d->map[i][j]->border_l = 2; } if (i == col_counter+colspan-1) { if (wcschr(spacer, L'r') != 0) d->map[i][j]->border_r = 1; if (wcschr(border, L'r') != 0) d->map[i][j]->border_r = 2; } if (j == row_counter) { if (wcschr(spacer, L't') != 0) d->map[i][j]->border_t = 1; if (wcschr(border, L't') != 0) d->map[i][j]->border_t = 2; } if (j == row_counter+rowspan-1) { if (wcschr(spacer, L'b') != 0) d->map[i][j]->border_b = 1; if (wcschr(border, L'b') != 0) d->map[i][j]->border_b = 2; } if (i > 0 && d->map[i-1][j]) d->map[i-1][j]->border_r = d->map[i][j]->border_l = max(d->map[i-1][j]->border_r, d->map[i][j]->border_l); if (j > 0 && d->map[i][j-1]) d->map[i][j-1]->border_b = d->map[i][j]->border_t = max(d->map[i][j-1]->border_b, d->map[i][j]->border_t); d->map[i][j]->colspan = colspan; d->map[i][j]->rowspan = rowspan; d->map[i][j]->w = c; } col_counter += colspan; } c->type->f_prepare(c, f); c = c->next_sibling; } d->rowd = calloc(d->rows, sizeof(struct table_rowcol_data)); d->cold = calloc(d->cols, sizeof(struct table_rowcol_data)); for (i=1; i<=max_colspan; i++) for (row_counter=0; row_counter < d->rows; row_counter++) for (col_counter=0; col_counter < d->cols; col_counter++) { if (d->map[col_counter][row_counter] == 0 || d->map[col_counter][row_counter]->hexpand == 0 || d->map[col_counter][row_counter]->spanpadding || d->map[col_counter][row_counter]->colspan > i) continue; int expand_ok = 0; for (j=0; j < d->map[col_counter][row_counter]->colspan; j++) if (d->cold[col_counter+j].expand) { expand_ok = 1; break; } if (expand_ok) continue; for (j=0; j < d->map[col_counter][row_counter]->colspan; j++) d->cold[col_counter+j].expand = 1; } for (i=1; i<=max_rowspan; i++) for (row_counter=0; row_counter < d->rows; row_counter++) for (col_counter=0; col_counter < d->cols; col_counter++) { if (d->map[col_counter][row_counter] == 0 || d->map[col_counter][row_counter]->vexpand == 0 || d->map[col_counter][row_counter]->spanpadding || d->map[col_counter][row_counter]->rowspan > i) continue; int expand_ok = 0; for (j=0; j < d->map[col_counter][row_counter]->rowspan; j++) if (d->rowd[row_counter+j].expand) { expand_ok = 1; break; } if (expand_ok) continue; for (j=0; j < d->map[col_counter][row_counter]->rowspan; j++) d->rowd[row_counter+j].expand = 1; } for (row_counter=0; row_counter < d->rows; row_counter++) for (col_counter=0; col_counter < d->cols; col_counter++) { struct table_cell_data *m = d->map[col_counter][row_counter]; if(m==NULL) continue; m->mastercell->mc_border_l = max(m->mastercell->mc_border_l, m->border_l); m->mastercell->mc_border_r = max(m->mastercell->mc_border_r, m->border_r); m->mastercell->mc_border_t = max(m->mastercell->mc_border_t, m->border_t); m->mastercell->mc_border_b = max(m->mastercell->mc_border_b, m->border_b); } for (i=1; i<=max_colspan; i++) for (row_counter=0; row_counter < d->rows; row_counter++) for (col_counter=0; col_counter < d->cols; col_counter++) { struct table_cell_data *m = d->map[col_counter][row_counter]; if (m == 0 || m->spanpadding || m->colspan > i) continue; int min_w = max(m->w->min_w, stfl_widget_getkv_int(m->w, L".width", 1)); if (col_counter == 0 && m->mc_border_l) min_w += 3; if (m->mc_border_r) min_w += 3; int total = min_w; for (j=0; jcolspan; j++) total -= d->cold[col_counter+j].min; if (total <= 0) continue; int expandables = 0; for (j=0; jcolspan; j++) if (d->cold[col_counter+j].expand) expandables++; if (expandables > 0) { int per = total / expandables; int extra_per = total % expandables; for (j=0; jcolspan; j++) if (d->cold[col_counter+j].expand) { d->cold[col_counter+j].min += per; if (extra_per) { d->cold[col_counter+j].min++; extra_per--; } } } else { int per = total / m->colspan; int extra_per = total % m->colspan; for (j=0; jcolspan; j++) { d->cold[col_counter+j].min += per; if (extra_per) { d->cold[col_counter+j].min++; extra_per--; } } } } for (i=1; i<=max_rowspan; i++) for (row_counter=0; row_counter < d->rows; row_counter++) for (col_counter=0; col_counter < d->cols; col_counter++) { struct table_cell_data *m = d->map[col_counter][row_counter]; if (m == 0 || m->spanpadding || m->rowspan > i) continue; int min_h = max(m->w->min_h, stfl_widget_getkv_int(m->w, L".height", 1)); if (row_counter == 0 && m->mc_border_t) min_h++; if (m->mc_border_b) min_h++; int total = min_h; for (j=0; jrowspan; j++) total -= d->rowd[row_counter+j].min; if (total <= 0) continue; int expandables = 0; for (j=0; jrowspan; j++) if (d->rowd[row_counter+j].expand) expandables++; if (expandables > 0) { int per = total / expandables; int extra_per = total % expandables; for (j=0; jrowspan; j++) if (d->rowd[row_counter+j].expand) { d->rowd[row_counter+j].min += per; if (extra_per) { d->rowd[row_counter+j].min++; extra_per--; } } } else { int per = total / m->rowspan; int extra_per = total % m->rowspan; for (j=0; jrowspan; j++) { d->rowd[row_counter+j].min += per; if (extra_per) { d->rowd[row_counter+j].min++; extra_per--; } } } } w->min_h = w->min_w = 0; for (row_counter=0; row_counter < d->rows; row_counter++) w->min_h += d->rowd[row_counter].min; for (col_counter=0; col_counter < d->cols; col_counter++) w->min_w += d->cold[col_counter].min; } void make_corner(WINDOW *win, int x, int y, int left, int right, int up, int down) { switch ((left?01000:0) | (right?00100:0) | (up?00010:0) | (down?00001:0)) { case 00000: // LEFT-RIGHT-UP-DOWN break; case 00001: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_VLINE); break; case 00010: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_VLINE); break; case 00011: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_VLINE); break; case 00100: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_HLINE); break; case 00101: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_ULCORNER); break; case 00110: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_LLCORNER); break; case 00111: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_LTEE); break; case 01000: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_HLINE); break; case 01001: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_URCORNER); break; case 01010: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_LRCORNER); break; case 01011: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_RTEE); break; case 01100: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_HLINE); break; case 01101: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_TTEE); break; case 01110: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_BTEE); break; case 01111: // LEFT-RIGHT-UP-DOWN mvwaddch(win, y, x, ACS_PLUS); break; } } static void wt_table_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win) { struct table_data *d = w->internal_data; int i, j, k, extra, extra_counter; extra = w->h - w->min_h; extra_counter = 0; for (i=0; i < d->rows; i++) { if (d->rowd[i].expand) extra_counter++; } for (i=0; i < d->rows; i++) { if (d->rowd[i].expand) { int e = extra / extra_counter--; d->rowd[i].size = d->rowd[i].min + e; extra -= e; } else d->rowd[i].size = d->rowd[i].min; } extra = w->w - w->min_w; extra_counter = 0; for (i=0; i < d->cols; i++) { if (d->cold[i].expand) extra_counter++; } for (i=0; i < d->cols; i++) { if (d->cold[i].expand) { int e = extra / extra_counter--; d->cold[i].size = d->cold[i].min + e; extra -= e; } else d->cold[i].size = d->cold[i].min; } int y = w->y; for (j=0; j < d->rows; j++) { int x = w->x; for (i=0; i < d->cols; i++) { if (d->map[i][j] && !d->map[i][j]->spanpadding) { struct table_cell_data *m = d->map[i][j]; struct stfl_widget *c = m->w; c->x = x; c->w = 0; c->y = y; c->h = 0; for (k=i; k < i + d->map[i][j]->colspan; k++) c->w += d->cold[k].size; for (k=j; k < j + d->map[i][j]->rowspan; k++) c->h += d->rowd[k].size; if (m->mc_border_l && i == 0) { c->x += 3; c->w -= 3; } if (m->mc_border_t && j == 0) { c->y++; c->h--; } if (m->mc_border_r) c->w -= 3; if (m->mc_border_b) c->h--; const wchar_t *tie = stfl_widget_getkv_str(c, L".tie", L"lrtb"); if (!wcschr(tie, L'l') && !wcschr(tie, L'r')) c->x += (c->w - c->min_w)/2; if (!wcschr(tie, L'l') && wcschr(tie, L'r')) c->x += c->w - c->min_w; if (!wcschr(tie, L'l') || !wcschr(tie, L'r')) c->w = c->min_w; if (!wcschr(tie, L't') && !wcschr(tie, L'b')) c->y += (c->h - c->min_h)/2; if (!wcschr(tie, L't') && wcschr(tie, L'b')) c->y += c->h - c->min_h; if (!wcschr(tie, L't') || !wcschr(tie, L'b')) c->h = c->min_h; c->type->f_draw(c, f, win); } x += d->cold[i].size; } y += d->rowd[j].size; } stfl_widget_style(w, f, win); y = w->y; for (j=0; j < d->rows; j++) { int x = w->x; for (i=0; i < d->cols; i++) { if (d->map[i][j]) { struct table_cell_data *m = d->map[i][j]; int box_x = x, box_w = d->cold[i].size; int box_y = y, box_h = d->rowd[j].size; if (i == 0) { if (m->border_l > 1 && box_h > (j ? 1 : 2)) { wmove(win, box_y+(j ? 0 : 1), box_x+1); wvline(win, ACS_VLINE, box_h - (j ? 1 : 2)); } } else { box_x -= 3; box_w += 3; } if (j == 0) { if (m->border_t > 1 && box_w > 4) { wmove(win, box_y, box_x+2); whline(win, ACS_HLINE, box_w-4); } } else { box_y--; box_h++; } if (m->border_r > 1 && box_h > 2) { wmove(win, box_y+1, box_x+box_w-2); wvline(win, ACS_VLINE, box_h-2); } if (m->border_b > 1 && box_w > 4) { wmove(win, box_y+box_h-1, box_x+2); whline(win, ACS_HLINE, box_w-4); } int left, right, up, down; struct table_cell_data *left_m = i > 0 ? d->map[i-1][j] : 0; struct table_cell_data *right_m = i < d->cols-1 ? d->map[i+1][j] : 0; struct table_cell_data *up_m = j > 0 ? d->map[i][j-1] : 0; struct table_cell_data *down_m = j < d->rows-1 ? d->map[i][j+1] : 0; // upper left corner if (i == 0 && j == 0) { left = left_m ? left_m->border_t : 0; right = m->border_t; up = up_m ? up_m->border_l : 0; down = m->border_l; make_corner(win, box_x+1, box_y, left>1, right>1, up>1, down>1); } // lower left corner if (i == 0) { left = left_m ? left_m->border_b : 0; right = m->border_b; up = m->border_l; down = down_m ? down_m->border_l : 0; make_corner(win, box_x+1, box_y+box_h-1, left>1, right>1, up>1, down>1); } // upper right corner if (j == 0) { left = m->border_t; right = right_m ? right_m->border_t : 0; up = up_m ? up_m->border_r : 0; down = m->border_r; make_corner(win, box_x+box_w-2, box_y, left>1, right>1, up>1, down>1); } // lower right corner left = m->border_b; right = right_m ? right_m->border_b : 0; up = m->border_r; down = down_m ? down_m->border_r : 0; make_corner(win, box_x+box_w-2, box_y+box_h-1, left>1, right>1, up>1, down>1); } x += d->cold[i].size; } y += d->rowd[j].size; } } static int wt_table_process(struct stfl_widget *w, struct stfl_widget *fw, struct stfl_form *f, wchar_t ch, int isfunckey) { struct table_data *d = w->internal_data; struct stfl_widget *n, *c; int i, j, k, event = 0; if (stfl_matchbind(w, ch, isfunckey, L"left", L"LEFT")) event = KEY_LEFT; else if (stfl_matchbind(w, ch, isfunckey, L"right", L"RIGHT")) event = KEY_RIGHT; else if (stfl_matchbind(w, ch, isfunckey, L"up", L"UP")) event = KEY_UP; else if (stfl_matchbind(w, ch, isfunckey, L"down", L"DOWN")) event = KEY_DOWN; else return 0; c = stfl_find_child_tree(w, fw); for (j=0; j < d->rows; j++) for (i=0; i < d->cols; i++) { struct table_cell_data *m = d->map[i][j]; if (!m || m->w != c) continue; switch (event) { case KEY_LEFT: for (k=i-1; k >= 0; k--) { m = d->map[k][j]; if (!m) continue; n = stfl_find_first_focusable(m->w); if (!n) continue; stfl_switch_focus(fw, n, f); return 1; } break; case KEY_RIGHT: for (k=i+1; k < d->cols; k++) { m = d->map[k][j]; if (!m) continue; n = stfl_find_first_focusable(m->w); if (!n) continue; stfl_switch_focus(fw, n, f); return 1; } break; case KEY_UP: for (k=j-1; k >= 0; k--) { m = d->map[i][k]; if (!m) continue; n = stfl_find_first_focusable(m->w); if (!n) continue; stfl_switch_focus(fw, n, f); return 1; } break; case KEY_DOWN: for (k=j+1; k < d->rows; k++) { m = d->map[i][k]; if (!m) continue; n = stfl_find_first_focusable(m->w); if (!n) continue; stfl_switch_focus(fw, n, f); return 1; } break; } } return 0; } struct stfl_widget_type stfl_widget_type_table = { L"table", 0, // f_init wt_table_done, 0, // f_enter 0, // f_leave wt_table_prepare, wt_table_draw, wt_table_process }; static void wt_tablebr_prepare(struct stfl_widget *w, struct stfl_form *f) { } static void wt_tablebr_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win) { } struct stfl_widget_type stfl_widget_type_tablebr = { L"tablebr", 0, // f_init 0, // f_done 0, // f_enter 0, // f_leave wt_tablebr_prepare, wt_tablebr_draw, 0 // f_process }; stfl-0.22/widgets/wt_box.c0000644000000000000000000001322111013565047014220 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * wt_box.c: Widget types 'hbox' and 'vbox' */ #include "stfl_internals.h" #include #include struct box_data { char type; }; static void wt_vbox_init(struct stfl_widget *w) { struct box_data *d = calloc(1, sizeof(struct box_data)); d->type = 'V'; w->internal_data = d; } static void wt_hbox_init(struct stfl_widget *w) { struct box_data *d = calloc(1, sizeof(struct box_data)); d->type = 'H'; w->internal_data = d; } static void wt_box_done(struct stfl_widget *w) { free(w->internal_data); } static void wt_box_prepare(struct stfl_widget *w, struct stfl_form *f) { struct box_data *d = w->internal_data; w->min_w = 0; w->min_h = 0; struct stfl_widget *c = w->first_child; while (c) { if (stfl_widget_getkv_int(c, L".display", 1)) { c->type->f_prepare(c, f); if (d->type == 'H') { if (w->min_h < c->min_h) w->min_h = c->min_h; w->min_w += c->min_w; } else { if (w->min_w < c->min_w) w->min_w = c->min_w; w->min_h += c->min_h; } } c = c->next_sibling; } } static void wt_box_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win) { struct box_data *d = w->internal_data; int num_dyn_children = 0; int min_w = 0, min_h = 0; int i, j; struct stfl_widget *c = w->first_child; while (c) { if (stfl_widget_getkv_int(c, L".display", 1)) { int size_w = stfl_widget_getkv_int(c, L".width", 0); if (size_w < c->min_w) size_w = c->min_w; int size_h = stfl_widget_getkv_int(c, L".height", 0); if (size_h < c->min_h) size_h = c->min_h; if (wcschr(stfl_widget_getkv_str(c, L".expand", L"vh"), d->type == 'H' ? 'h' : 'v')) num_dyn_children++; if (d->type == 'H') { min_w += size_w; if (min_h < size_h) min_h = size_h; } else { min_h += size_h; if (min_w < size_w) min_w = size_w; } } c = c->next_sibling; } int box_x = w->x, box_y = w->y; int box_w = w->w, box_h = w->h; stfl_widget_style(w, f, win); for (i=box_x; itype == 'H' ? box_w - min_w : box_h - min_h); int cursor = (d->type == 'H' ? box_x : box_y); c = w->first_child; for (i=0; c; i++) { if (stfl_widget_getkv_int(c, L".display", 1)) { int size = stfl_widget_getkv_int(c, d->type == 'H' ? L".width" : L".height", 0); if (size < (d->type == 'H' ? c->min_w : c->min_h)) size = d->type == 'H' ? c->min_w : c->min_h; if (wcschr(stfl_widget_getkv_str(c, L".expand", L"vh"), d->type == 'H' ? 'h' : 'v')) { int extra = sizes_extra / num_dyn_children--; sizes_extra -= extra; size += extra; } if (d->type == 'H') { c->y = box_y; c->x = cursor; c->h = box_h; c->w = size; cursor += c->w; } else { c->x = box_x; c->y = cursor; c->w = box_w; c->h = size; cursor += c->h; } tie = stfl_widget_getkv_str(c, L".tie", L"lrtb"); if (!wcschr(tie, L'l') && !wcschr(tie, L'r')) c->x += (c->w - c->min_w)/2; if (!wcschr(tie, L'l') && wcschr(tie, L'r')) c->x += c->w - c->min_w; if (!wcschr(tie, L'l') || !wcschr(tie, L'r')) c->w = c->min_w; if (!wcschr(tie, L't') && !wcschr(tie, L'b')) c->y += (c->h - c->min_h)/2; if (!wcschr(tie, L't') && wcschr(tie, L'b')) c->y += c->h - c->min_h; if (!wcschr(tie, L't') || !wcschr(tie, L'b')) c->h = c->min_h; c->type->f_draw(c, f, win); } c = c->next_sibling; } } static int wt_box_process(struct stfl_widget *w, struct stfl_widget *fw, struct stfl_form *f, wchar_t ch, int isfunckey) { struct box_data *d = w->internal_data; if (d->type == 'H') { if (stfl_matchbind(w, ch, isfunckey, L"left", L"LEFT")) return stfl_focus_prev(w, fw, f); if (stfl_matchbind(w, ch, isfunckey, L"right", L"RIGHT")) return stfl_focus_next(w, fw, f); } if (d->type == 'V') { if (stfl_matchbind(w, ch, isfunckey, L"up", L"UP")) return stfl_focus_prev(w, fw, f); if (stfl_matchbind(w, ch, isfunckey, L"down", L"DOWN")) return stfl_focus_next(w, fw, f); } return 0; } struct stfl_widget_type stfl_widget_type_vbox = { L"vbox", wt_vbox_init, wt_box_done, 0, // f_enter 0, // f_leave wt_box_prepare, wt_box_draw, wt_box_process }; struct stfl_widget_type stfl_widget_type_hbox = { L"hbox", wt_hbox_init, wt_box_done, 0, // f_enter 0, // f_leave wt_box_prepare, wt_box_draw, wt_box_process }; stfl-0.22/widgets/wt_list.c0000644000000000000000000001365711651176406014425 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * wt_list.c: Widget type 'list' */ #include "stfl_internals.h" #include #include static void fix_offset_pos(struct stfl_widget *w) { int offset = stfl_widget_getkv_int(w, L"offset", 0); int pos = stfl_widget_getkv_int(w, L"pos", 0); int orig_offset = offset; int orig_pos = pos; while (pos < offset) offset--; if (w->h > 0) while (pos >= offset+w->h) offset++; int maxpos = -1; struct stfl_widget *c = w->first_child; while (c) { maxpos++; c = c->next_sibling; } if (maxpos >= 0 && pos > maxpos) pos = maxpos; if (offset != orig_offset) stfl_widget_setkv_int(w, L"offset", offset); if (pos != orig_pos) stfl_widget_setkv_int(w, L"pos", pos); } static void wt_list_prepare(struct stfl_widget *w, struct stfl_form *f) { struct stfl_widget *c = w->first_child; w->min_w = 1; w->min_h = 5; if (c) w->allow_focus = 1; while (c) { const wchar_t * text = stfl_widget_getkv_str(c, L"text", L""); int len = wcswidth(text,wcslen(text)); w->min_w = len > w->min_w ? len : w->min_w; c = c->next_sibling; } } static void wt_list_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win) { const wchar_t * text; fix_offset_pos(w); int offset = stfl_widget_getkv_int(w, L"offset", 0); int pos = stfl_widget_getkv_int(w, L"pos", 0); int is_richtext = stfl_widget_getkv_int(w, L"richtext", 0); const wchar_t *style_focus = stfl_widget_getkv_str(w, L"style_focus", L""); const wchar_t *style_selected = stfl_widget_getkv_str(w, L"style_selected", L""); const wchar_t *style_normal = stfl_widget_getkv_str(w, L"style_normal", L""); const wchar_t * cur_style = NULL; struct stfl_widget *c; int i, j; unsigned int width = 0; if (f->current_focus_id == w->id) f->cursor_x = f->cursor_y = -1; for (i=0, c=w->first_child; c && i < offset+w->h; i++, c=c->next_sibling) { int has_focus = 0; if (i < offset) continue; if (i == pos) { if (f->current_focus_id == w->id) { stfl_style(win, style_focus); cur_style = style_focus; has_focus = 1; f->cursor_y = w->y+i-offset; f->cursor_x = w->x; } else { stfl_style(win, style_selected); cur_style = style_selected; } stfl_widget_setkv_str(w, L"pos_name", c->name ? c->name : L""); } else { stfl_style(win, style_normal); cur_style = style_normal; } text = stfl_widget_getkv_str(c, L"text", L""); if (1) { wchar_t *fillup = malloc(sizeof(wchar_t)*(w->w + 1)); for (j=0;j < w->w;++j) { fillup[j] = ' '; } fillup[w->w] = '\0'; mvwaddnwstr(win, w->y+i-offset, w->x, fillup, wcswidth(fillup,wcslen(fillup))); free(fillup); } if (is_richtext) width = stfl_print_richtext(w, win, w->y+i-offset, w->x, text, w->w, cur_style, has_focus); else { mvwaddnwstr(win, w->y+i-offset, w->x, text, w->w); width = wcslen(text); } } if (f->current_focus_id == w->id) { f->root->cur_y = f->cursor_y; f->root->cur_x = f->cursor_x; } } static int wt_list_process(struct stfl_widget *w, struct stfl_widget *fw, struct stfl_form *f, wchar_t ch, int isfunckey) { int pos = stfl_widget_getkv_int(w, L"pos", 0); int maxpos = -1; struct stfl_widget *c = w->first_child; while (c) { maxpos++; c = c->next_sibling; } if (pos > 0 && stfl_matchbind(w, ch, isfunckey, L"up", L"UP")) { stfl_widget_setkv_int(w, L"pos", pos-1); fix_offset_pos(w); return 1; } if (pos < maxpos && stfl_matchbind(w, ch, isfunckey, L"down", L"DOWN")) { stfl_widget_setkv_int(w, L"pos", pos+1); fix_offset_pos(w); return 1; } if (stfl_matchbind(w, ch, isfunckey, L"page_down", L"NPAGE")) { if (pos < maxpos - w->h) stfl_widget_setkv_int(w, L"pos", pos + w->h); else stfl_widget_setkv_int(w, L"pos", maxpos); fix_offset_pos(w); return 1; } if (stfl_matchbind(w, ch, isfunckey, L"page_up", L"PPAGE")) { if (pos > w->h) stfl_widget_setkv_int(w, L"pos", pos - w->h); else stfl_widget_setkv_int(w, L"pos", 0); fix_offset_pos(w); return 1; } if (stfl_matchbind(w, ch, isfunckey, L"home", L"HOME")) { stfl_widget_setkv_int(w, L"pos", 0); fix_offset_pos(w); return 1; } if (stfl_matchbind(w, ch, isfunckey, L"end", L"END")) { stfl_widget_setkv_int(w, L"pos", maxpos); fix_offset_pos(w); return 1; } return 0; } struct stfl_widget_type stfl_widget_type_list = { L"list", 0, // f_init 0, // f_done 0, // f_enter 0, // f_leave wt_list_prepare, wt_list_draw, wt_list_process, }; static void wt_listitem_init(struct stfl_widget *w) { if (w->parent && !wcscmp(w->parent->type->name, L"list")) w->parent->allow_focus = 1; } static void wt_listitem_done(struct stfl_widget *w) { if (w->parent && !wcscmp(w->parent->type->name, L"list") && w->parent->first_child == w && w->parent->last_child == w) w->parent->allow_focus = 0; } static void wt_listitem_prepare(struct stfl_widget *w, struct stfl_form *f) { } static void wt_listitem_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win) { } struct stfl_widget_type stfl_widget_type_listitem = { L"listitem", wt_listitem_init, wt_listitem_done, 0, // f_enter 0, // f_leave wt_listitem_prepare, wt_listitem_draw, 0 // f_process }; stfl-0.22/widgets/wt_input.c0000644000000000000000000001133511651176406014600 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * wt_input.c: Widget type 'input' */ #include "stfl_internals.h" #include #include #include static void wt_input_init(struct stfl_widget *w) { w->allow_focus = 1; } static void fix_offset_pos(struct stfl_widget *w) { int pos = stfl_widget_getkv_int(w, L"pos", 0); int offset = stfl_widget_getkv_int(w, L"offset", 0); const wchar_t* text = stfl_widget_getkv_str(w, L"text", L""); int text_len = wcslen(text); int changed = 0; int width; if (pos > text_len) { pos = text_len; changed = 1; } if (offset > pos) { offset = pos; changed = 1; } width = wcswidth(text + offset, pos - offset); while (width >= w->w && pos > offset) { width -= wcwidth(text[offset++]); changed = 1; } if (changed) { stfl_widget_setkv_int(w, L"pos", pos); stfl_widget_setkv_int(w, L"offset", offset); } } static void wt_input_prepare(struct stfl_widget *w, struct stfl_form *f) { int size = stfl_widget_getkv_int(w, L"size", 5); w->min_w = size; w->min_h = 1; fix_offset_pos(w); } static void wt_input_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win) { int pos = stfl_widget_getkv_int(w, L"pos", 0); int blind = stfl_widget_getkv_int(w, L"blind", 0); int offset = stfl_widget_getkv_int(w, L"offset", 0); const wchar_t * const text_off = stfl_widget_getkv_str(w, L"text", L"") + offset; int i; stfl_widget_style(w, f, win); for (i=0; iw; i++) mvwaddwstr(win, w->y, w->x+i, L" "); if (!blind) { const int off_len = wcslen(text_off); int width, len; width = wcswidth(text_off, w->w); if (w->w > off_len) len = off_len; else len = w->w; while (width > w->w) width -= wcwidth(text_off[--len]); mvwaddnwstr(win, w->y, w->x, text_off, len); } if (f->current_focus_id == w->id) { f->root->cur_x = f->cursor_x = w->x + wcswidth(text_off, pos - offset); f->root->cur_y = f->cursor_y = w->y; } } static int wt_input_process(struct stfl_widget *w, struct stfl_widget *fw, struct stfl_form *f, wchar_t ch, int isfunckey) { int pos = stfl_widget_getkv_int(w, L"pos", 0); const wchar_t *text = stfl_widget_getkv_str(w, L"text", L""); int text_len = wcslen(text); if (pos > 0 && stfl_matchbind(w, ch, isfunckey, L"left", L"LEFT")) { stfl_widget_setkv_int(w, L"pos", pos-1); fix_offset_pos(w); return 1; } if (pos < text_len && stfl_matchbind(w, ch, isfunckey, L"right", L"RIGHT")) { stfl_widget_setkv_int(w, L"pos", pos+1); fix_offset_pos(w); return 1; } // pos1 / home / Ctrl-A if (stfl_matchbind(w, ch, isfunckey, L"home", L"HOME ^A")) { stfl_widget_setkv_int(w, L"pos", 0); fix_offset_pos(w); return 1; } // end / Ctrl-E if (stfl_matchbind(w, ch, isfunckey, L"end", L"END ^E")) { stfl_widget_setkv_int(w, L"pos", text_len); fix_offset_pos(w); return 1; } // delete if (stfl_matchbind(w, ch, isfunckey, L"delete", L"DC")) { if (pos == text_len) return 0; wchar_t newtext[text_len]; wmemcpy(newtext, text, pos); wcscpy(newtext + pos, text + pos + 1); stfl_widget_setkv_str(w, L"text", newtext); fix_offset_pos(w); return 1; } // backspace if (stfl_matchbind(w, ch, isfunckey, L"backspace", L"BACKSPACE")) { if (pos == 0) return 0; wchar_t newtext[text_len]; wmemcpy(newtext, text, pos-1); wcscpy(newtext + pos - 1, text + pos); stfl_widget_setkv_str(w, L"text", newtext); stfl_widget_setkv_int(w, L"pos", pos-1); fix_offset_pos(w); return 1; } // 'normal' characters if (!isfunckey && iswprint(ch)) { wchar_t newtext[text_len + 2]; wmemcpy(newtext, text, pos); newtext[pos] = ch; wcscpy(newtext + pos + 1, text + pos); stfl_widget_setkv_str(w, L"text", newtext); stfl_widget_setkv_int(w, L"pos", pos+1); fix_offset_pos(w); return 1; } return 0; } struct stfl_widget_type stfl_widget_type_input = { L"input", wt_input_init, 0, // f_done 0, // f_enter 0, // f_leave wt_input_prepare, wt_input_draw, wt_input_process }; stfl-0.22/widgets/wt_label.c0000644000000000000000000000405111010024204014466 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * wt_label.c: Widget type 'label' */ #include "stfl_internals.h" #include #include static void wt_label_prepare(struct stfl_widget *w, struct stfl_form *f) { const wchar_t * text = stfl_widget_getkv_str(w, L"text", L""); w->min_w = wcswidth(text, wcslen(text)); w->min_h = 1; } static void wt_label_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win) { const wchar_t * text; unsigned int i; int is_richtext = stfl_widget_getkv_int(w, L"richtext", 0); const wchar_t * style = stfl_widget_getkv_str(w, L"style_normal", L""); stfl_widget_style(w, f, win); text = stfl_widget_getkv_str(w,L"text",L""); if (1) { wchar_t *fillup = malloc(sizeof(wchar_t)*(w->w + 1)); for (i=0;i < w->w;++i) { fillup[i] = L' '; } fillup[w->w] = L'\0'; mvwaddnwstr(win, w->y, w->x, fillup, wcswidth(fillup,wcslen(fillup))); free(fillup); } if (is_richtext) stfl_print_richtext(w, win, w->y, w->x, text, w->w, style, 0); else mvwaddnwstr(win, w->y, w->x, text, w->w); } struct stfl_widget_type stfl_widget_type_label = { L"label", 0, // f_init 0, // f_done 0, // f_enter 0, // f_leave wt_label_prepare, wt_label_draw, 0 // f_process }; stfl-0.22/widgets/wt_textview.c0000644000000000000000000001146011651176406015317 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * Copyright (C) 2006 Andreas Krennmair * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * wt_textview.c: Widget type 'textview' */ #include "stfl_internals.h" #include #include #if 0 static void fix_offset_pos(struct stfl_widget *w) { int offset = stfl_widget_getkv_int(w, "offset", 0); int pos = stfl_widget_getkv_int(w, "pos", 0); int orig_offset = offset; int orig_pos = pos; while (pos < offset) offset--; if (w->h > 0) while (pos >= offset+w->h) offset++; int maxpos = -1; struct stfl_widget *c = w->first_child; while (c) { maxpos++; c = c->next_sibling; } if (maxpos >= 0 && pos > maxpos) pos = maxpos; if (offset != orig_offset) stfl_widget_setkv_int(w, "offset", offset); if (pos != orig_pos) stfl_widget_setkv_int(w, "pos", pos); } #endif static void wt_textview_prepare(struct stfl_widget *w, struct stfl_form *f) { struct stfl_widget *c = w->first_child; w->min_w = 1; w->min_h = 5; if (c) w->allow_focus = 1; while (c) { const wchar_t * text = stfl_widget_getkv_str(c, L"text", L""); int len = wcswidth(text, wcslen(text)); w->min_w = len > w->min_w ? len : w->min_w; c = c->next_sibling; } } static void wt_textview_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win) { //fix_offset_pos(w); int offset = stfl_widget_getkv_int(w, L"offset", 0); int is_richtext = stfl_widget_getkv_int(w, L"richtext", 0); const wchar_t *style_normal = stfl_widget_getkv_str(w, L"style_normal", L""); const wchar_t *style_end = stfl_widget_getkv_str(w, L"style_end", L""); struct stfl_widget *c; int i; stfl_style(win, style_normal); for (i=0, c=w->first_child; c && i < offset+w->h; i++, c=c->next_sibling) { const wchar_t *text = stfl_widget_getkv_str(c, L"text", L""); if (i < offset) { if (is_richtext) stfl_print_richtext(w, win, w->y, w->x, text, 0, style_normal, 0); continue; } if (is_richtext) { stfl_print_richtext(w, win, w->y+i-offset, w->x, text, w->w, style_normal, 0); } else { mvwaddnwstr(win, w->y+i-offset, w->x, text, w->w); } } stfl_style(win, style_end); while (ih) { mvwaddnwstr(win,w->y+i-offset,w->x,L"~",w->w); ++i; } if (f->current_focus_id == w->id) f->root->cur_x = f->root->cur_y = f->cursor_x = f->cursor_y = -1; } static int wt_textview_process(struct stfl_widget *w, struct stfl_widget *fw, struct stfl_form *f, wchar_t ch, int isfunckey) { //int pos = stfl_widget_getkv_int(w, "pos", 0); int offset = stfl_widget_getkv_int(w,L"offset",0); int maxoffset = -1; struct stfl_widget *c = w->first_child; while (c) { maxoffset++; c = c->next_sibling; } if (offset > 0 && stfl_matchbind(w, ch, isfunckey, L"up", L"UP")) { stfl_widget_setkv_int(w, L"offset", offset-1); //fix_offset_pos(w); return 1; } if (offset < maxoffset && stfl_matchbind(w, ch, isfunckey, L"down", L"DOWN")) { stfl_widget_setkv_int(w, L"offset", offset+1); //fix_offset_pos(w); return 1; } if (stfl_matchbind(w, ch, isfunckey, L"page_up", L"PPAGE")) { if ((offset - w->h + 1) > 0) { // XXX: first page handling won't work with that stfl_widget_setkv_int(w, L"offset", offset - w->h + 1); } else { stfl_widget_setkv_int(w, L"offset", 0); } return 1; } if (stfl_matchbind(w, ch, isfunckey, L"page_down", L"NPAGE")) { if ((offset + w->h - 1) < maxoffset) { // XXX: last page handling won't work with that stfl_widget_setkv_int(w, L"offset", offset + w->h - 1); } else { stfl_widget_setkv_int(w, L"offset", maxoffset); } return 1; } if (stfl_matchbind(w, ch, isfunckey, L"home", L"HOME")) { stfl_widget_setkv_int(w, L"offset", 0); return 1; } if (stfl_matchbind(w, ch, isfunckey, L"end", L"END")) { stfl_widget_setkv_int(w, L"offset", (maxoffset - w->h + 2) < 0 ? 0 : maxoffset - w->h + 2); return 1; } return 0; } struct stfl_widget_type stfl_widget_type_textview = { L"textview", 0, // f_init 0, // f_done 0, // f_enter 0, // f_leave wt_textview_prepare, wt_textview_draw, wt_textview_process, }; stfl-0.22/iconv.c0000644000000000000000000001300410667031347012372 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * iconv.c: Helper functions for widechar conversion */ #include "stfl.h" #include #include #include #include #include #include struct stfl_ipool_entry { void *data; struct stfl_ipool_entry *next; }; struct stfl_ipool { iconv_t to_wc_desc; iconv_t from_wc_desc; char *code; struct stfl_ipool_entry *list; pthread_mutex_t mtx; }; struct stfl_ipool *stfl_ipool_create(const char *code) { struct stfl_ipool *pool = malloc(sizeof(struct stfl_ipool)); pthread_mutex_init(&pool->mtx, NULL); pool->to_wc_desc = (iconv_t)(-1); pool->from_wc_desc = (iconv_t)(-1); pool->code = strdup(code); pool->list = 0; return pool; } void *stfl_ipool_add(struct stfl_ipool *pool, void *data) { struct stfl_ipool_entry *entry = malloc(sizeof(struct stfl_ipool_entry)); pthread_mutex_lock(&pool->mtx); entry->data = data; entry->next = pool->list; pool->list = entry; pthread_mutex_unlock(&pool->mtx); return data; } const wchar_t *stfl_ipool_towc(struct stfl_ipool *pool, const char *buf) { if (!pool || !buf) return 0; pthread_mutex_lock(&pool->mtx); if (!strcmp("WCHAR_T", pool->code)) { pthread_mutex_unlock(&pool->mtx); return (wchar_t*)buf; } if (pool->to_wc_desc == (iconv_t)(-1)) pool->to_wc_desc = iconv_open("WCHAR_T", pool->code); if (pool->to_wc_desc == (iconv_t)(-1)) { pthread_mutex_unlock(&pool->mtx); return 0; } char *inbuf = (char*)buf; size_t inbytesleft = strlen(buf); int buffer_size = inbytesleft * 2 + 16; int buffer_pos = 0; char *buffer = NULL; grow_buffer_retry:; buffer_size += inbytesleft * 2; buffer = realloc(buffer, buffer_size); retry_without_growing:; char *outbuf = buffer + buffer_pos; size_t outbytesleft = buffer_size - buffer_pos; iconv(pool->to_wc_desc, NULL, NULL, NULL, NULL); int rc = iconv(pool->to_wc_desc, &inbuf, &inbytesleft, &outbuf, &outbytesleft); buffer_pos = outbuf - buffer; if (rc == -1 && errno == E2BIG) goto grow_buffer_retry; if (rc == -1 && (errno == EILSEQ || errno == EINVAL)) { // just copy this char as it is (e.g. when input is broken utf-8 with some latin1 chars) if (outbytesleft < sizeof(wchar_t)) goto grow_buffer_retry; *((wchar_t*)outbuf) = *(unsigned char*)inbuf; buffer_pos += sizeof(wchar_t); inbuf++; inbytesleft--; goto retry_without_growing; } if (rc == -1) { free(buffer); pthread_mutex_unlock(&pool->mtx); return 0; } if (outbytesleft < sizeof(wchar_t)) buffer = realloc(buffer, buffer_size+sizeof(wchar_t)); *((wchar_t*)outbuf) = 0; pthread_mutex_unlock(&pool->mtx); return stfl_ipool_add(pool, buffer); } const char *stfl_ipool_fromwc(struct stfl_ipool *pool, const wchar_t *buf) { if (!pool || !buf) return 0; pthread_mutex_lock(&pool->mtx); if (!strcmp("WCHAR_T", pool->code)) { pthread_mutex_unlock(&pool->mtx); return (char*)buf; } if (pool->from_wc_desc == (iconv_t)(-1)) pool->from_wc_desc = iconv_open(pool->code, "WCHAR_T"); if (pool->from_wc_desc == (iconv_t)(-1)) { pthread_mutex_unlock(&pool->mtx); return 0; } char *inbuf = (char*)buf; size_t inbytesleft = wcslen(buf)*sizeof(wchar_t); int buffer_size = inbytesleft + 16; int buffer_pos = 0; char *buffer = NULL; grow_buffer_retry:; buffer_size += inbytesleft; buffer = realloc(buffer, buffer_size); retry_without_growing:; char *outbuf = buffer + buffer_pos; size_t outbytesleft = buffer_size - buffer_pos; iconv(pool->from_wc_desc, NULL, NULL, NULL, NULL); int rc = iconv(pool->from_wc_desc, &inbuf, &inbytesleft, &outbuf, &outbytesleft); buffer_pos = outbuf - buffer; if (rc == -1 && errno == E2BIG) goto grow_buffer_retry; if (rc == -1 && (errno == EILSEQ || errno == EINVAL)) { // just copy a '?' to the output stream if (outbytesleft < 1) goto grow_buffer_retry; *outbuf = '?'; buffer_pos++; inbuf += sizeof(wchar_t); inbytesleft -= sizeof(wchar_t); goto retry_without_growing; } if (rc == -1) { free(buffer); pthread_mutex_unlock(&pool->mtx); return 0; } if (outbytesleft < 1) buffer = realloc(buffer, buffer_size+1); *outbuf = 0; pthread_mutex_unlock(&pool->mtx); return stfl_ipool_add(pool, buffer); } void stfl_ipool_flush(struct stfl_ipool *pool) { if (!pool) return; pthread_mutex_lock(&pool->mtx); while (pool->list) { struct stfl_ipool_entry *l = pool->list; pool->list = l->next; free(l->data); free(l); } pthread_mutex_unlock(&pool->mtx); } void stfl_ipool_destroy(struct stfl_ipool *pool) { if (!pool) return; stfl_ipool_flush(pool); free(pool->code); if (pool->to_wc_desc != (iconv_t)(-1)) iconv_close(pool->to_wc_desc); if (pool->from_wc_desc != (iconv_t)(-1)) iconv_close(pool->from_wc_desc); free(pool); } stfl-0.22/public.c0000644000000000000000000002140111473215052012523 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * public.c: Public STFL API */ #include "stfl_internals.h" #include #include #include #include #include int stfl_api_allow_null_pointers = 1; static const wchar_t *checkret(const wchar_t *txt) { if (!stfl_api_allow_null_pointers && !txt) return L""; return txt; } struct stfl_form *stfl_create(const wchar_t *text) { struct stfl_form *f = stfl_form_new(); f->root = stfl_parser(text ? text : L""); stfl_check_setfocus(f, f->root); return f; } void stfl_free(struct stfl_form *f) { stfl_form_free(f); } const wchar_t *stfl_run(struct stfl_form *f, int timeout) { stfl_form_run(f, timeout); return checkret(f->event); } void stfl_reset() { stfl_form_reset(); } const wchar_t *stfl_get(struct stfl_form *f, const wchar_t *name) { wchar_t *pseudovar_sep = name ? wcschr(name, L':') : 0; pthread_mutex_lock(&f->mtx); if (pseudovar_sep) { wchar_t w_name[pseudovar_sep-name+1]; wmemcpy(w_name, name, pseudovar_sep-name); w_name[pseudovar_sep-name] = 0; struct stfl_widget *w = stfl_widget_by_name(f->root, w_name); static wchar_t ret_buffer[16]; if (w == 0) goto this_is_not_a_pseudo_var; if (!wcscmp(pseudovar_sep+1, L"x")) { swprintf(ret_buffer, 16, L"%d", w->x); pthread_mutex_unlock(&f->mtx); return checkret(ret_buffer); } if (!wcscmp(pseudovar_sep+1, L"y")) { swprintf(ret_buffer, 16, L"%d", w->y); pthread_mutex_unlock(&f->mtx); return checkret(ret_buffer); } if (!wcscmp(pseudovar_sep+1, L"w")) { swprintf(ret_buffer, 16, L"%d", w->w); pthread_mutex_unlock(&f->mtx); return checkret(ret_buffer); } if (!wcscmp(pseudovar_sep+1, L"h")) { swprintf(ret_buffer, 16, L"%d", w->h); pthread_mutex_unlock(&f->mtx); return checkret(ret_buffer); } if (!wcscmp(pseudovar_sep+1, L"minw")) { swprintf(ret_buffer, 16, L"%d", w->min_w); pthread_mutex_unlock(&f->mtx); return checkret(ret_buffer); } if (!wcscmp(pseudovar_sep+1, L"minh")) { swprintf(ret_buffer, 16, L"%d", w->min_h); pthread_mutex_unlock(&f->mtx); return checkret(ret_buffer); } } this_is_not_a_pseudo_var:; const wchar_t * tmpstr = stfl_getkv_by_name_str(f->root, name ? name : L"", 0); pthread_mutex_unlock(&f->mtx); return checkret(tmpstr); } void stfl_set(struct stfl_form *f, const wchar_t *name, const wchar_t *value) { pthread_mutex_lock(&f->mtx); stfl_setkv_by_name_str(f->root, name ? name : L"", value ? value : L""); pthread_mutex_unlock(&f->mtx); } const wchar_t *stfl_get_focus(struct stfl_form *f) { struct stfl_widget *fw; const wchar_t * tmpstr; pthread_mutex_lock(&f->mtx); fw = stfl_widget_by_id(f->root, f->current_focus_id); tmpstr = checkret(fw ? fw->name : 0); pthread_mutex_unlock(&f->mtx); return tmpstr; } void stfl_set_focus(struct stfl_form *f, const wchar_t *name) { struct stfl_widget *fw; pthread_mutex_lock(&f->mtx); fw = stfl_widget_by_name(f->root, name ? name : L""); stfl_switch_focus(0, fw, f); pthread_mutex_unlock(&f->mtx); } const wchar_t *stfl_quote(const wchar_t *text) { static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t retbuffer_key; static int firstrun = 1; static wchar_t *retbuffer = 0; pthread_mutex_lock(&mtx); if (firstrun) { pthread_key_create(&retbuffer_key, free); firstrun = 0; } retbuffer = pthread_getspecific(retbuffer_key); if (retbuffer) free(retbuffer); retbuffer = stfl_quote_backend(text ? text : L""); pthread_setspecific(retbuffer_key, retbuffer); pthread_mutex_unlock(&mtx); return checkret(retbuffer); } const wchar_t *stfl_dump(struct stfl_form *f, const wchar_t *name, const wchar_t *prefix, int focus) { static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t retbuffer_key; static int firstrun = 1; static wchar_t *retbuffer = 0; struct stfl_widget *w; pthread_mutex_lock(&mtx); pthread_mutex_lock(&f->mtx); if (firstrun) { pthread_key_create(&retbuffer_key, free); firstrun = 0; } retbuffer = pthread_getspecific(retbuffer_key); if (retbuffer) free(retbuffer); w = name && *name ? stfl_widget_by_name(f->root, name) : f->root; retbuffer = stfl_widget_dump(w, prefix ? prefix : L"", focus ? f->current_focus_id : 0); pthread_setspecific(retbuffer_key, retbuffer); pthread_mutex_unlock(&f->mtx); pthread_mutex_unlock(&mtx); return checkret(retbuffer); } static void stfl_modify_before(struct stfl_widget *w, struct stfl_widget *n) { if (!n || !w || !w->parent) return; struct stfl_widget **prev_p = &w->parent->first_child; struct stfl_widget *last_n = 0; while (*prev_p != w) prev_p = &(*prev_p)->next_sibling; *prev_p = n; while (n) { last_n = n; n->parent = w->parent; n = n->next_sibling; } last_n->next_sibling = w; } static void stfl_modify_after(struct stfl_widget *w, struct stfl_widget *n) { if (!n || !w || !w->parent) return; struct stfl_widget *first_n = n; struct stfl_widget *last_n = 0; while (n) { last_n = n; n->parent = w->parent; n = n->next_sibling; } if (w->next_sibling) last_n->next_sibling = w->next_sibling; else w->parent->last_child = last_n; w->next_sibling = first_n; } static void stfl_modify_insert(struct stfl_widget *w, struct stfl_widget *n) { if (!n || !w) return; struct stfl_widget *first_n = n; struct stfl_widget *last_n = 0; while (n) { last_n = n; n->parent = w; n = n->next_sibling; } if (w->first_child) last_n->next_sibling = w->first_child; else w->last_child = last_n; w->first_child = first_n; } static void stfl_modify_append(struct stfl_widget *w, struct stfl_widget *n) { if (!n || !w) return; struct stfl_widget *first_n = n; struct stfl_widget *last_n = 0; while (n) { last_n = n; n->parent = w; n = n->next_sibling; } if (w->last_child) w->last_child->next_sibling = first_n; else w->first_child = first_n; w->last_child = last_n; } void stfl_modify(struct stfl_form *f, const wchar_t *name, const wchar_t *mode, const wchar_t *text) { struct stfl_widget *w; struct stfl_widget *n; pthread_mutex_lock(&f->mtx); w = stfl_widget_by_name(f->root, name ? name : L""); if (!w) goto unlock; mode = mode ? mode : L""; if (!wcscmp(mode, L"delete") && w != f->root) { stfl_widget_free(w); goto unlock; } n = stfl_parser(text ? text : L""); if (!n) goto unlock; if (!wcscmp(mode, L"replace")) { if (w == f->root) f->root = n; else stfl_modify_after(w, n); stfl_widget_free(w); goto finish; } if (!wcscmp(mode, L"replace_inner")) { while (w->first_child) stfl_widget_free(w->first_child); stfl_modify_insert(w, n->first_child); n->first_child = n->last_child = 0; stfl_widget_free(n); n = w; goto finish; } if (!wcscmp(mode, L"insert")) { stfl_modify_insert(w, n); goto finish; } if (!wcscmp(mode, L"insert_inner")) { stfl_modify_insert(w, n->first_child); n->first_child = n->last_child = 0; stfl_widget_free(n); n = w; goto finish; } if (!wcscmp(mode, L"append")) { stfl_modify_append(w, n); goto finish; } if (!wcscmp(mode, L"append_inner")) { stfl_modify_append(w, n->first_child); n->first_child = n->last_child = 0; stfl_widget_free(n); n = w; goto finish; } if (!wcscmp(mode, L"before")) { stfl_modify_before(w, n); goto finish; } if (!wcscmp(mode, L"before_inner")) { stfl_modify_before(w, n->first_child); n->first_child = n->last_child = 0; stfl_widget_free(n); n = w; goto finish; } if (!wcscmp(mode, L"after")) { stfl_modify_after(w, n); goto finish; } if (!wcscmp(mode, L"after_inner")) { stfl_modify_after(w, n->first_child); n->first_child = n->last_child = 0; stfl_widget_free(n); n = w; goto finish; } finish: stfl_check_setfocus(f, n); unlock: pthread_mutex_unlock(&f->mtx); return; } const wchar_t *stfl_lookup(struct stfl_form *f, const wchar_t *path, const wchar_t *newname) { return checkret(0); } const wchar_t *stfl_error() { abort(); return checkret(0); } void stfl_error_action(const wchar_t *mode) { abort(); return; } stfl-0.22/stfl_compat.h0000644000000000000000000000234310651364131013571 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * stfl_compat.h: Some compatibility hacks for b0rken architectures */ #ifndef STFL__COMPAT_H #define STFL__COMPAT_H 1 #include #include #include static inline wchar_t *compat_wcsdup(const wchar_t *src) { size_t n = (wcslen(src) + 1) * sizeof(wchar_t); wchar_t *dest = malloc(n); memcpy(dest, src, n); return dest; } #endif stfl-0.22/example.stfl0000644000000000000000000000626411003405235013431 0ustar rootroot* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * example.stfl: STFL Code for example.c * vbox hbox .expand:0 @style_normal:bg=yellow,fg=black label text:'Little STFL example program' label[label one] text[label one text]:"Line number one" label["2nd label"] text[also possible to use : here now]:"Fun! Fun! Fun!" label["quotes are needed for a closing bracket: ]"] text[c_like_names_are_still_recommended_thought]:"Whatever" table .expand:0 @input#style_focus:bg=blue,fg=white,attr=bold @input#style_normal:bg=blue,fg=black @input#.border:rtb @L#style_normal:fg=red @L#.expand:0 @L#.border:ltb @L#.spacer:r label#L text:'Field A:' input .colspan:3 text[value_a]:'foo' vbox .rowspan:2 .expand:0 .border:lrtb label text:'this' label text:'is a' label text:'test' tablebr label#L text:'Field B:' input text[value_b]:'bar' label#L text:'Field C:' input text[value_c]:'Hello'"'"'World!' hbox vbox vbox style_normal:bg=red @label#style_normal:bg=white,fg=black label .tie:tc text:"A rather long test label" label .tie:l text:"Short (left)" label .tie:rb text:"Short (right)" vbox tie:lrb style_normal:bg=blue @label#style_normal:bg=white,fg=black label .tie:c text:"A rather long test label" label .tie:l text:"Short (left)" label .tie:r text:"Short (right)" vbox tie:r style_normal:bg=green @label#style_normal:bg=white,fg=black label text:"A rather long test label" label .tie:l text:"Short (left)" label .tie:r text:"Short (right)" textview[textview] .expand:0 @style_blue_normal:fg=blue @style_red_normal:fg=red @style_bold_normal:attr=bold,attr=underline richtext:1 listitem text:"This is normal text" listitem text:"Normal blue Text red Text normal" listitem text:"Multi line: first line" listitem text:"this is the 2nd line, still blue" listitem text:"3rd line, and normal again!" listitem text:"a smaller-than sign: <>" listitem text:"a greater-than sign: >" listitem text:"bold text normal text" stfl-0.22/swig/0000755000000000000000000000000011651202747012061 5ustar rootrootstfl-0.22/swig/setlocale.i0000644000000000000000000000175510651364131014211 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * setlocale.i: Call setlocale() on startup */ %{ #include %} %init %{ setlocale(LC_ALL,""); %} stfl-0.22/swig/nonullptr.i0000644000000000000000000000174610651364131014273 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * nonullptr.i: Don't return NULL pointers in SWIG bindings */ %init %{ stfl_api_allow_null_pointers = 0; %} stfl-0.22/swig/longnames.i0000644000000000000000000000266410651364131014221 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * longnames.i: Use long function names in SWIG bindings */ %rename(stfl_create) stfl_create_wrapper; %rename(stfl_run) stfl_run_wrapper; %rename(stfl_get) stfl_get_wrapper; %rename(stfl_set) stfl_set_wrapper; %rename(stfl_get_focus) stfl_get_focus_wrapper; %rename(stfl_set_focus) stfl_set_focus_wrapper; %rename(stfl_quote) stfl_quote_wrapper; %rename(stfl_dump) stfl_dump_wrapper; %rename(stfl_modify) stfl_modify_wrapper; %rename(stfl_lookup) stfl_lookup_wrapper; %rename(stfl_error) stfl_error_wrapper; %rename(stfl_error_action) stfl_error_action_wrapper; stfl-0.22/swig/shortnames.i0000644000000000000000000000262610651364131014417 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * shortnames.i: Use short function names in SWIG bindings */ %rename(create) stfl_create_wrapper; %rename(run) stfl_run_wrapper; %rename(get) stfl_get_wrapper; %rename(set) stfl_set_wrapper; %rename(get_focus) stfl_get_focus_wrapper; %rename(set_focus) stfl_set_focus_wrapper; %rename(quote) stfl_quote_wrapper; %rename(dump) stfl_dump_wrapper; %rename(modify) stfl_modify_wrapper; %rename(lookup) stfl_lookup_wrapper; %rename(error) stfl_error_wrapper; %rename(error_action) stfl_error_action_wrapper; %rename(reset) stfl_reset; stfl-0.22/swig/basedecls.i0000644000000000000000000001202310651364131014151 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * basedecls.i: SWIG bindings core */ %module stfl %{ #include #include #include "stfl.h" typedef struct stfl_form stfl_form; struct stfl_ipool *ipool = 0; static void inline ipool_reset() { if (!ipool) ipool = stfl_ipool_create("UTF8"); stfl_ipool_flush(ipool); } static void ipool_destroy() { stfl_ipool_destroy(ipool); ipool = 0; } #define TOWC(_t) stfl_ipool_towc(ipool, _t) #define FROMWC(_t) stfl_ipool_fromwc(ipool, _t) %} typedef struct { } stfl_form; %extend stfl_form { stfl_form(char *text) { ipool_reset(); return stfl_create(TOWC(text)); } ~stfl_form() { ipool_reset(); stfl_free(self); } const char *run(int timeout) { ipool_reset(); return FROMWC(stfl_run(self, timeout)); } const char *get(const char *name) { ipool_reset(); return FROMWC(stfl_get(self, TOWC(name))); } void set(const char *name, const char *value) { ipool_reset(); return stfl_set(self, TOWC(name), TOWC(value)); } const char *get_focus() { ipool_reset(); return FROMWC(stfl_get_focus(self)); } void set_focus(const char *name) { ipool_reset(); stfl_set_focus(self, TOWC(name)); } const char *dump(const char *name, const char *prefix, int focus) { ipool_reset(); return FROMWC(stfl_dump(self, TOWC(name), TOWC(prefix), focus)); } void modify(const char *name, const char *mode, const char *text) { ipool_reset(); stfl_modify(self, TOWC(name), TOWC(mode), TOWC(text)); } const char *lookup(const char *path, const char *newname) { ipool_reset(); return FROMWC(stfl_lookup(self, TOWC(path), TOWC(newname))); } } %{ static struct stfl_form *stfl_create_wrapper(const char *text) { ipool_reset(); return stfl_create(TOWC(text)); } static const char *stfl_run_wrapper(struct stfl_form *f, int timeout) { ipool_reset(); return FROMWC(stfl_run(f, timeout)); } static const char *stfl_get_wrapper(struct stfl_form *f, const char *name) { ipool_reset(); return FROMWC(stfl_get(f, TOWC(name))); } static void stfl_set_wrapper(struct stfl_form *f, const char *name, const char *value) { ipool_reset(); return stfl_set(f, TOWC(name), TOWC(value)); } static const char *stfl_get_focus_wrapper(struct stfl_form *f) { ipool_reset(); return FROMWC(stfl_get_focus(f)); } static void stfl_set_focus_wrapper(struct stfl_form *f, const char *name) { ipool_reset(); stfl_set_focus(f, TOWC(name)); } static const char *stfl_quote_wrapper(const char *text) { ipool_reset(); return FROMWC(stfl_quote(TOWC(text))); } static const char *stfl_dump_wrapper(struct stfl_form *f, const char *name, const char *prefix, int focus) { ipool_reset(); return FROMWC(stfl_dump(f, TOWC(name), TOWC(prefix), focus)); } static void stfl_modify_wrapper(struct stfl_form *f, const char *name, const char *mode, const char *text) { ipool_reset(); stfl_modify(f, TOWC(name), TOWC(mode), TOWC(text)); } static const char *stfl_lookup_wrapper(struct stfl_form *f, const char *path, const char *newname) { ipool_reset(); return FROMWC(stfl_lookup(f, TOWC(path), TOWC(newname))); } static const char *stfl_error_wrapper() { ipool_reset(); return FROMWC(stfl_error()); } static void stfl_error_action_wrapper(const char *mode) { ipool_reset(); stfl_error_action(TOWC(mode)); } %} static struct stfl_form *stfl_create_wrapper(const char *text); static const char *stfl_run_wrapper(struct stfl_form *f, int timeout); static const char *stfl_get_wrapper(struct stfl_form *f, const char *name); static void stfl_set_wrapper(struct stfl_form *f, const char *name, const char *value); static const char *stfl_get_focus_wrapper(struct stfl_form *f); static void stfl_set_focus_wrapper(struct stfl_form *f, const char *name); static const char *stfl_quote_wrapper(const char *text); static const char *stfl_dump_wrapper(struct stfl_form *f, const char *name, const char *prefix, int focus); static void stfl_modify_wrapper(struct stfl_form *f, const char *name, const char *mode, const char *text); static const char *stfl_lookup_wrapper(struct stfl_form *f, const char *path, const char *newname); static const char *stfl_error_wrapper(); static void stfl_error_action_wrapper(const char *mode); extern void stfl_reset(); %init %{ atexit(stfl_reset); atexit(ipool_destroy); %} stfl-0.22/COPYING0000644000000000000000000001672710651364131012153 0ustar rootroot GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. stfl-0.22/Makefile.cfg0000644000000000000000000000256111210545167013307 0ustar rootroot# # STFL - The Structured Terminal Forms Language/Library # Copyright (C) 2006, 2007 Clifford Wolf # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 3 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA # export libdir ?= lib export prefix ?= /usr/local export DESTDIR ?= / ifneq ($(shell spl-config --cflags 2>/dev/null),) FOUND_SPL = 1 else FOUND_SPL = 0 endif ifneq ($(shell swig -help 2>/dev/null),) FOUND_SWIG = 1 else FOUND_SWIG = 0 endif ifneq ($(shell perl -le 'print 1' 2>/dev/null),) FOUND_PERL5 = 1 else FOUND_PERL5 = 0 endif ifneq ($(shell python -c 'print 1' 2>/dev/null),) FOUND_PYTHON = 1 else FOUND_PYTHON = 0 endif ifneq ($(shell ruby -e 'puts 1' 2>/dev/null),) FOUND_RUBY = 1 else FOUND_RUBY = 0 endif stfl-0.22/example.c0000644000000000000000000000335410651364131012707 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * example.c: A little STFL example */ #include "stfl.h" #include #include #include #include #include int main() { if (!setlocale(LC_ALL,"")) fprintf(stderr, "WARING: Can't set locale!\n"); struct stfl_ipool *ipool = stfl_ipool_create(nl_langinfo(CODESET)); struct stfl_form *f = stfl_create(L""); stfl_set(f, L"value_a", L"This is a little"); stfl_set(f, L"value_b", stfl_ipool_towc(ipool, "test for STFL!")); stfl_ipool_flush(ipool); const wchar_t *event = 0; while (!event || wcscmp(event, L"ESC")) event = stfl_run(f, 0); stfl_reset(); printf("A: %ls\n", stfl_get(f, L"value_a")); printf("B: %ls\n", stfl_get(f, L"value_b")); printf("C: %s\n", stfl_ipool_fromwc(ipool, stfl_get(f, L"value_c"))); stfl_ipool_flush(ipool); stfl_free(f); stfl_ipool_destroy(ipool); return 0; } stfl-0.22/parser.c0000644000000000000000000002464411535233447012564 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * parser.c: STFL Form description file parser */ #include "stfl_internals.h" #include "stfl_compat.h" #include #include #include #include #define MYWCSCSPN_SKIP_QUOTED 0x01 #define MYWCSCSPN_SKIP_NAMES 0x02 static size_t mywcscspn(const wchar_t *wcs, const wchar_t *reject, int flags) { enum { PLAIN, NAME_BLOCK, SINGLE_QUOTE, SINGLE_QUOTE_NAME, DOUBLE_QUOTE, DOUBLE_QUOTE_NAME, } state = PLAIN; int len = 0; int i; while (1) { if (!wcs[len]) return len; switch (state) { case PLAIN: if ((flags & MYWCSCSPN_SKIP_NAMES) && (wcs[len] == L'[')) { state = NAME_BLOCK; break; } if ((flags & MYWCSCSPN_SKIP_QUOTED) && (wcs[len] == L'\'')) { state = SINGLE_QUOTE; break; } if ((flags & MYWCSCSPN_SKIP_QUOTED) && (wcs[len] == L'\"')) { state = DOUBLE_QUOTE; break; } for (i=0; reject[i]; i++) if (wcs[len] == reject[i]) return len; break; case NAME_BLOCK: if ((flags & MYWCSCSPN_SKIP_QUOTED) && (wcs[len] == L'\'')) { state = SINGLE_QUOTE_NAME; break; } if ((flags & MYWCSCSPN_SKIP_QUOTED) && (wcs[len] == L'\"')) { state = DOUBLE_QUOTE_NAME; break; } if (wcs[len] == L']') state = PLAIN; break; case SINGLE_QUOTE: case SINGLE_QUOTE_NAME: if (wcs[len] == L'\'') state = state == SINGLE_QUOTE ? PLAIN : NAME_BLOCK; break; case DOUBLE_QUOTE: case DOUBLE_QUOTE_NAME: if (wcs[len] == L'\"') state = state == DOUBLE_QUOTE ? PLAIN : NAME_BLOCK; break; } len++; } } static wchar_t *unquote(const wchar_t *text, int tlen) { int len_v = 0, i, j; wchar_t *value; if (!text) return 0; for (i=0; text[i] && (i= 0) goto finish_len_v_loop; if (!text[i] || text[i] == L'\'') break; len_v++; } else if (text[i] == L'\"') while (1) { if (++i == tlen && tlen >= 0) goto finish_len_v_loop; if (!text[i] || text[i] == L'\"') break; len_v++; } else len_v++; finish_len_v_loop:; } value = malloc(sizeof(wchar_t)*(len_v+1)); for (i=j=0; text[i] && (i= 0) goto finish_copy_loop; if (!text[i] || text[i] == L'\'') break; value[j++] = text[i]; } else if (text[i] == L'\"') while (1) { if (++i == tlen && tlen >= 0) goto finish_copy_loop; if (!text[i] || text[i] == L'\"') break; value[j++] = text[i]; } else value[j++] = text[i]; finish_copy_loop:; } value[j] = 0; assert(j == len_v); return value; } static void extract_name(wchar_t **key, wchar_t **name) { int len = wcscspn(*key, L"["); if ((*key)[len] == 0) { *name = 0; return; } *name = compat_wcsdup(*key+len+1); *key = realloc(*key, sizeof(wchar_t)*(len+1)); (*key)[len] = 0; len = mywcscspn(*name, L"]", MYWCSCSPN_SKIP_QUOTED); (*name)[len] = 0; } static void extract_class(wchar_t **key, wchar_t **cls) { int len = wcscspn(*key, L"#"); if ((*key)[len] == 0) { *cls = 0; return; } *cls = compat_wcsdup(*key+len+1); *key = realloc(*key, sizeof(wchar_t)*(len+1)); (*key)[len] = 0; } static int read_type(const wchar_t **text, wchar_t **type, wchar_t **name, wchar_t **cls) { int len = mywcscspn(*text, L" \t\r\n:{}", MYWCSCSPN_SKIP_QUOTED|MYWCSCSPN_SKIP_NAMES); if ((*text)[len] == L':' || len == 0) return 0; *type = malloc((len+1)*sizeof(wchar_t)); wmemcpy(*type, *text, len); (*type)[len] = 0; *text += len; extract_name(type, name); extract_class(type, cls); return 1; } static int read_kv(const wchar_t **text, wchar_t **key, wchar_t **name, wchar_t **value) { int len_k = mywcscspn(*text, L" \t\r\n:{}", MYWCSCSPN_SKIP_QUOTED|MYWCSCSPN_SKIP_NAMES); if ((*text)[len_k] != L':' || len_k == 0) return 0; *key = malloc((len_k+1)*sizeof(wchar_t)); wmemcpy(*key, *text, len_k); (*key)[len_k] = 0; *text += len_k+1; extract_name(key, name); int qval_len = mywcscspn(*text, L" \t\r\n{}", MYWCSCSPN_SKIP_QUOTED); *value = unquote(*text, qval_len); *text += qval_len; return 1; } struct stfl_widget *stfl_parser(const wchar_t *text) { struct stfl_widget *root = 0; struct stfl_widget *current = 0; int bracket_indenting = -1; int bracket_level = 0; while (1) { int indenting = 0; if (bracket_indenting >= 0) { while (*text == L' ' || *text == L'\t') text++; while (*text == L'}') { bracket_level--; text++; while (*text == L' ' || *text == L'\t') text++; } while (*text == L'{') { bracket_level++; text++; while (*text == L' ' || *text == L'\t') text++; } if (bracket_level == 0) bracket_indenting = -1; if (bracket_level < 0) goto parser_error; } else if (*text == L'}') goto parser_error; if (bracket_indenting >= 0) { while (*text == L' ' || *text == L'\t') text++; if (*text == L'\r' || *text == L'\n') goto parser_error; indenting = bracket_indenting + (bracket_level-1); } else { while (*text == L' ' || *text == L'\t' || *text == L'\r' || *text == L'\n') { if (*text == L'\r' || *text == L'\n') indenting = 0; else if (*text == L'\t') indenting = -1; else if (indenting >= 0) indenting++; text++; } if (*text == L'*') { while (*text && *text != L'\r' && *text != L'\n') text++; continue; } if (*text == L'{') { bracket_indenting = indenting; continue; } } if (*text == 0) break; wchar_t *key, *name, *cls, *value; if (indenting < 0) goto parser_error; if (*text == L'<') { int filename_len = wcscspn(++text, L">"); wchar_t wfn[filename_len+1]; wmemcpy(wfn, text, filename_len+1); wfn[filename_len] = 0; size_t len = wcstombs(NULL,wfn,0)+1; char filename[len]; size_t rc = wcstombs(filename, wfn, len); assert(rc != (size_t)-1); text += filename_len; if (*text) text++; struct stfl_widget *n = stfl_parser_file(filename); if (!n) return 0; if (root) { while (current->parser_indent >= indenting) { current = current->parent; if (!current) goto parser_error; } n->parent = current; if (current->last_child) { current->last_child->next_sibling = n; current->last_child = n; } else { current->first_child = n; current->last_child = n; } n->parser_indent = indenting; current = n; } else root = n; } else if (root) { while (current->parser_indent >= indenting) { current = current->parent; if (!current) goto parser_error; } if (read_type(&text, &key, &name, &cls) == 1) { struct stfl_widget *n = stfl_widget_new(key); if (!n) goto parser_error; free(key); n->parent = current; if (current->last_child) { current->last_child->next_sibling = n; current->last_child = n; } else { current->first_child = n; current->last_child = n; } n->parser_indent = indenting; n->name = unquote(name, -1); free(name); n->cls = cls; current = n; } else if (read_kv(&text, &key, &name, &value) == 1) { struct stfl_kv *kv = stfl_widget_setkv_str(current, key, value); if (kv->name) free(kv->name); kv->name = unquote(name, -1); free(name); free(key); free(value); } else goto parser_error; } else { if (read_type(&text, &key, &name, &cls) == 0) goto parser_error; struct stfl_widget *n = stfl_widget_new(key); if (!n) goto parser_error; free(key); root = n; current = n; n->name = unquote(name, -1); free(name); n->cls = cls; } while (*text && *text != L'\n' && *text != L'\r' && *text != L'{' && *text != L'}') { while (*text == L' ' || *text == L'\t') text++; if (*text && *text != L'\n' && *text != L'\r' && *text != L'{' && *text != L'}') { if (read_kv(&text, &key, &name, &value) == 0) goto parser_error; struct stfl_kv *kv = stfl_widget_setkv_str(current, key, value); if (kv->name) free(kv->name); kv->name = unquote(name, -1); free(name); free(key); free(value); } } } if (root) return root; parser_error:; int i; fprintf(stderr, "STFL Parser Error near '"); for (i=0; *text && i<20; i++, text++) if (*text == L'\n') fprintf(stderr, "\\n"); else if (*text == L'\t') fprintf(stderr, " "); else if (*text < 32) fprintf(stderr, "\\%03lo", (long unsigned int)*text); else fprintf(stderr, "%lc", (wint_t)*text); fprintf(stderr, "'.\r\n"); abort(); return 0; } struct stfl_widget *stfl_parser_file(const char *filename) { FILE *f = fopen(filename, "r"); if (!f) { fprintf(stderr, "STFL Parser Error: Can't read file '%s'!\n", filename); abort(); return 0; } int len = 0; char *text = 0; while (1) { int pos = len; text = realloc(text, len += 4096); pos += fread(text+pos, 1, 4096, f); if (pos < len) { text[pos] = 0; fclose(f); break; } } const char * text1 = text; size_t wtextsize = mbsrtowcs(NULL,&text1,strlen(text1)+1,NULL)+1; wchar_t * wtext = malloc(sizeof(wchar_t)*wtextsize); size_t rc = mbstowcs(wtext, text, wtextsize); assert(rc != (size_t)-1); #if 0 fprintf(stderr,"strlen(text) = %u wcslen(wtext) = %u rc = %u wtextsize = %u\n", strlen(text), wcslen(wtext), rc, wtextsize); fprintf(stderr,"this is where is fucked up: `%lc' `%lc' `%lc' `%lc' `%lc'\n",text1[0],text1[1],text1[2],text1[3],text1[4]); fprintf(stderr,"original: `%s'\n", text); fprintf(stderr,"converted: `%ls'\n", wtext); #endif struct stfl_widget *w = stfl_parser(wtext); free(text); free(wtext); return w; } stfl-0.22/Makefile0000644000000000000000000000572711651201700012547 0ustar rootroot# # STFL - The Structured Terminal Forms Language/Library # Copyright (C) 2006, 2007 Clifford Wolf # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 3 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA # include Makefile.cfg export CC = gcc -pthread export CFLAGS += -I. -Wall -Os -ggdb -D_GNU_SOURCE -fPIC export LDLIBS += -lncursesw SONAME := libstfl.so.0 VERSION := 0.22 all: libstfl.so.$(VERSION) libstfl.a example example: libstfl.a example.o libstfl.a: public.o base.o parser.o dump.o style.o binding.o iconv.o \ $(patsubst %.c,%.o,$(wildcard widgets/*.c)) rm -f $@ ar qc $@ $^ ranlib $@ libstfl.so.$(VERSION): public.o base.o parser.o dump.o style.o binding.o iconv.o \ $(patsubst %.c,%.o,$(wildcard widgets/*.c)) $(CC) -shared -Wl,-soname,$(SONAME) -o $@ $(LDLIBS) $^ clean: rm -f libstfl.a example core core.* *.o Makefile.deps rm -f widgets/*.o spl/mod_stfl.so spl/example.db cd perl5 && perl Makefile.PL && make clean && rm -f Makefile.old rm -f perl5/stfl_wrap.c perl5/stfl.pm perl5/build_ok rm -f python/stfl.py python/stfl.pyc python/_stfl.so rm -f python/stfl_wrap.c python/stfl_wrap.o rm -f ruby/Makefile ruby/stfl_wrap.c ruby/stfl_wrap.o rm -f ruby/stfl.so ruby/build_ok Makefile.deps_new rm -f stfl.pc libstfl.so libstfl.so.* Makefile.deps: *.c widgets/*.c *.h $(CC) -I. -MM *.c > Makefile.deps_new $(CC) -I. -MM widgets/*.c | sed 's,^wt_[^ ]*\.o: ,widgets/&,' >> Makefile.deps_new mv -f Makefile.deps_new Makefile.deps install: all stfl.pc mkdir -p $(DESTDIR)$(prefix)/$(libdir)/pkgconfig mkdir -p $(DESTDIR)$(prefix)/include install -m 644 libstfl.a $(DESTDIR)$(prefix)/$(libdir) install -m 644 stfl.h $(DESTDIR)$(prefix)/include/ install -m 644 stfl.pc $(DESTDIR)$(prefix)/$(libdir)/pkgconfig/ install -m 644 libstfl.so.$(VERSION) $(DESTDIR)$(prefix)/$(libdir) ln -fs libstfl.so.$(VERSION) $(DESTDIR)$(prefix)/$(libdir)/libstfl.so stfl.pc: stfl.pc.in sed 's,@VERSION@,$(VERSION),g' < $< | sed 's,@PREFIX@,$(prefix),g' > $@ ifeq ($(FOUND_SPL),1) include spl/Makefile.snippet endif ifeq ($(FOUND_SWIG)$(FOUND_PERL5),11) include perl5/Makefile.snippet endif ifeq ($(FOUND_SWIG)$(FOUND_PYTHON),11) include python/Makefile.snippet endif ifeq ($(FOUND_SWIG)$(FOUND_RUBY),11) include ruby/Makefile.snippet endif .PHONY: all clean install install_spl include Makefile.deps stfl-0.22/stfl_internals.h0000644000000000000000000001355011651176406014316 0ustar rootroot/* * STFL - The Structured Terminal Forms Language/Library * Copyright (C) 2006, 2007 Clifford Wolf * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * stfl_internals.h: The STFL C header file (Internal STFL APIs) */ #ifndef STFL__INTERNALS_H #define STFL__INTERNALS_H 1 #ifdef __cplusplus extern "C" { #endif #include "stfl.h" #include #include struct stfl_widget_type; struct stfl_kv; struct stfl_widget; struct stfl_widget_type { wchar_t *name; void (*f_init)(struct stfl_widget *w); void (*f_done)(struct stfl_widget *w); void (*f_enter)(struct stfl_widget *w, struct stfl_form *f); void (*f_leave)(struct stfl_widget *w, struct stfl_form *f); void (*f_prepare)(struct stfl_widget *w, struct stfl_form *f); void (*f_draw)(struct stfl_widget *w, struct stfl_form *f, WINDOW *win); int (*f_process)(struct stfl_widget *w, struct stfl_widget *fw, struct stfl_form *f, wchar_t ch, int is_function_key); }; struct stfl_kv { struct stfl_kv *next; struct stfl_widget *widget; wchar_t *key, *value, *name; int id; }; struct stfl_widget { struct stfl_widget *parent; struct stfl_widget *next_sibling; struct stfl_widget *first_child; struct stfl_widget *last_child; struct stfl_kv *kv_list; struct stfl_widget_type *type; int id, x, y, w, h, min_w, min_h, cur_x, cur_y; int parser_indent, allow_focus; int setfocus; void *internal_data; wchar_t *name, *cls; }; struct stfl_event { struct stfl_event *next; wchar_t *event; }; struct stfl_form { struct stfl_widget *root; int current_focus_id; int cursor_x, cursor_y; struct stfl_event *event_queue; wchar_t *event; pthread_mutex_t mtx; }; extern int stfl_colorpair_counter; extern struct stfl_widget_type *stfl_widget_types[]; extern struct stfl_widget_type stfl_widget_type_label; extern struct stfl_widget_type stfl_widget_type_input; extern struct stfl_widget_type stfl_widget_type_vbox; extern struct stfl_widget_type stfl_widget_type_hbox; extern struct stfl_widget_type stfl_widget_type_table; extern struct stfl_widget_type stfl_widget_type_tablebr; extern struct stfl_widget_type stfl_widget_type_list; extern struct stfl_widget_type stfl_widget_type_listitem; extern struct stfl_widget_type stfl_widget_type_textview; extern struct stfl_widget *stfl_widget_new(const wchar_t *type); extern void stfl_widget_free(struct stfl_widget *w); extern struct stfl_kv *stfl_widget_setkv_int(struct stfl_widget *w, const wchar_t *key, int value); extern struct stfl_kv *stfl_widget_setkv_str(struct stfl_widget *w, const wchar_t *key, const wchar_t *value); extern struct stfl_kv *stfl_setkv_by_name_int(struct stfl_widget *w, const wchar_t *name, int value); extern struct stfl_kv *stfl_setkv_by_name_str(struct stfl_widget *w, const wchar_t *name, const wchar_t *value); extern struct stfl_kv *stfl_widget_getkv(struct stfl_widget *w, const wchar_t *key); extern int stfl_widget_getkv_int(struct stfl_widget *w, const wchar_t *key, int defval); extern const wchar_t *stfl_widget_getkv_str(struct stfl_widget *w, const wchar_t *key, const wchar_t *defval); extern int stfl_getkv_by_name_int(struct stfl_widget *w, const wchar_t *name, int defval); extern const wchar_t *stfl_getkv_by_name_str(struct stfl_widget *w, const wchar_t *name, const wchar_t *defval); extern struct stfl_widget *stfl_widget_by_name(struct stfl_widget *w, const wchar_t *name); extern struct stfl_widget *stfl_widget_by_id(struct stfl_widget *w, int id); extern struct stfl_kv *stfl_kv_by_name(struct stfl_widget *w, const wchar_t *name); extern struct stfl_kv *stfl_kv_by_id(struct stfl_widget *w, int id); extern struct stfl_widget *stfl_find_child_tree(struct stfl_widget *w, struct stfl_widget *c); extern struct stfl_widget *stfl_find_first_focusable(struct stfl_widget *w); extern int stfl_switch_focus(struct stfl_widget *old_fw, struct stfl_widget *new_fw, struct stfl_form *f); extern int stfl_focus_prev(struct stfl_widget *w, struct stfl_widget *old_fw, struct stfl_form *f); extern int stfl_focus_next(struct stfl_widget *w, struct stfl_widget *old_fw, struct stfl_form *f); extern struct stfl_form *stfl_form_new(); extern void stfl_form_event(struct stfl_form *f, wchar_t *event); extern void stfl_form_run(struct stfl_form *f, int timeout); extern void stfl_form_reset(); extern void stfl_form_free(struct stfl_form *f); extern void stfl_check_setfocus(struct stfl_form *f, struct stfl_widget *w); extern struct stfl_widget *stfl_parser(const wchar_t *text); extern struct stfl_widget *stfl_parser_file(const char *filename); extern wchar_t *stfl_quote_backend(const wchar_t *text); extern wchar_t *stfl_widget_dump(struct stfl_widget *w, const wchar_t *prefix, int focus_id); extern void stfl_style(WINDOW *win, const wchar_t *style); extern void stfl_widget_style(struct stfl_widget *w, struct stfl_form *f, WINDOW *win); extern wchar_t *stfl_keyname(wchar_t ch, int isfunckey); extern int stfl_matchbind(struct stfl_widget *w, wchar_t ch, int isfunckey, wchar_t *name, wchar_t *auto_desc); extern unsigned int stfl_print_richtext(struct stfl_widget *w, WINDOW *win, unsigned int y, unsigned int x, const wchar_t * text, unsigned int width, const wchar_t * style, int has_focus); #ifdef __cplusplus } #endif #endif stfl-0.22/stfl.pc.in0000644000000000000000000000044411164210201012772 0ustar rootroot# Package Information for pkg-config prefix=@PREFIX@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: STFL Description: Structured Terminal Forms Language/Library Version: @VERSION@ Libs: -L${libdir} -lstfl Libs.private: -lncursesw Cflags: -I${includedir}