diff --git a/README b/README index 4d277185..dae13894 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -Terminology 0.2.0 +Terminology 0.3.0 ****************************************************************************** @@ -10,16 +10,20 @@ Terminology 0.2.0 Requirements: ------------- - * elementary 1.1 (1.0.99 SVN latest) - * eina - * eet - * evas 1.3 (1.2.99 SVN latest) - * ecore - * edje - * emotion - * ecore-imf - * ecore-imf-evas - * ecore-input 1.3 (1.2.99 SVN latest) + * elementary (>= 1.7.0) + * eina (>= 1.7.0) + * eet (>= 1.7.0) + * evas (>= 1.7.0) + * ecore (>= 1.7.0) + * edje (>= 1.7.0) + * emotion (>= 1.7.0) + * ecore-imf (>= 1.7.0) + * ecore-imf-evas (>= 1.7.0) + * ecore-input (>= 1.7.0) + * ethumb (>= 1.7.0) + +Please note that some features may not quite function correction or +completely on EFL 1.7, and 1.8 or newer would be better. Please see http://www.enlightenment.org for information on these. @@ -59,6 +63,9 @@ Ctrl+Shift+Home = bring up "tab" switcher Ctrl+Shift+PgUp = split terminal horizontally (1 term above the other) Ctrl+Shift+PgDn = split terminal vertically (1 term to the left of the other) Alt+Home = Enter command mode (enter commands to control terminology itself) +Alt+Return = paste primary selection +Ctrl+Shift+c = copy current selection to clipboard +Ctrl+Shift+v = paste current clipboard selection Command mode commands currently understood: diff --git a/TODO b/TODO index 1391b30d..2cb2aacb 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,8 @@ here's a short list of things i think we can do in the short to medium term to make it a first-class terminal: +[ ] better info in tyls -m +[ ] tyls -b needs doing [ ] blink and blink2 attributes need to be supported [ ] general input mode handling improvements (keypad, other key input, etc.) @@ -24,32 +26,18 @@ make it a first-class terminal: [ ] dnd of file to term offer to paste path, with escapes or paste file content (if text) with or without escaping [ ] helpers when executed need to escape path/uri in command buffer -[ ] media - improve position slider to track ucr position as u play +[ ] media - improve position slider to track position as u play [ ] improve look of meida controls (youtube like better with mouse move show) -[ ] media controls for music files need to be compact for music [ ] make media controls an api where controls are provided by the media object owner so they can be custom placed/swallowed/handled better [ ] media controls need to have zoom controls for all formats [ ] media controls need next/prev page controls for paged media (ps/pdf) [ ] add better handling of music files (with just playbar+vol, no image) [ ] display queue of media visually -[ ] add escapes for displaying media [ ] add option for cjk double width mode [ ] apparently there are problems with mutt, screen and tmux? vim mousewheel scroll suport doesnt work [ ] possible evas font problem with proggy fonts: http://www.proggyfonts.com/ -[ ] alt+return doesn't copy current selection to input line. -[ ] ctrl+shift+c and ctrl+shift+v should do copy & paste -[ ] tab sel needs decent edje styling with spacing and shadows around items -[ ] tab sel needs to display term title and track changes -[ ] tab sel needs to display alert/bell state and display it -[ ] termio needs a bg mode for invisible tabs (until sel view is up) -[ ] termio needs a visible but not selected mode (for media volume?) -[ ] tab sel needs to use temio bg/visible modes -[ ] main term needs to track title in its struct and win title needs - to show it when we switch focus to that term -[ ] need an edje bg/overlay/swallow around sel that is put in the pane or - terminology main swallow for styling and bg. [ ] need mouse control for sel object (autoscroll based on position) [ ] need mouseover top of term to go into sel mode [ ] need to track bell on bg terms and indicate a bg term wants attention diff --git a/configure.ac b/configure.ac index 188ed0ee..4d0611fb 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl Process this file with autoconf to produce a configure script. # get rid of that stupid cache mechanism rm -f config.cache -AC_INIT([terminology], [0.2.0], [enlightenment-devel@lists.sourceforge.net]) +AC_INIT([terminology], [0.3.0], [enlightenment-devel@lists.sourceforge.net]) AC_PREREQ([2.60]) AC_CONFIG_SRCDIR([configure.ac]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/data/themes/default.edc b/data/themes/default.edc index cba8427b..f6e8c278 100644 --- a/data/themes/default.edc +++ b/data/themes/default.edc @@ -2261,8 +2261,16 @@ target: "4.bottom" images { image: "pm_overlay.png" COMP; image: "pm_fill.png" COMP; + image: "bg_shadow.png" COMP; } parts { + part { name: "shadow"; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "bg_shadow.png"; + fill.smooth: 0; + } + } part { name: "fill"; mouse_events: 0; description { state: "default" 0.0; @@ -2393,7 +2401,24 @@ target: "4.bottom" rel2.to: "terminology.content"; } } - + part { name: "terminology.background"; type: SWALLOW; + description { state: "default" 0.0; + rel1.to: "terminology.content"; + rel2.to: "terminology.content"; + } + description { state: "image" 0.0; + inherit: "default" 0.0; + } + description { state: "scale" 0.0; + inherit: "default" 0.0; + } + description { state: "edje" 0.0; + inherit: "default" 0.0; + } + description { state: "movie" 0.0; + inherit: "default" 0.0; + } + } part { name: "terminology.content"; type: SWALLOW; clip_to: "clip"; description { state: "default" 0.0; diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index e8734a08..ea63e6c7 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -1,6 +1,6 @@ MAINTAINERCLEANFILES = Makefile.in -bin_PROGRAMS = terminology tycat tyls +bin_PROGRAMS = terminology tybg tyalpha typop tyq tycat tyls terminology_CPPFLAGS = -I. \ -DPACKAGE_BIN_DIR=\"$(bindir)\" -DPACKAGE_LIB_DIR=\"$(libdir)\" \ @@ -41,6 +41,42 @@ win.c win.h \ utils.c utils.h \ extns.h +tybg_SOURCES = \ +tybg.c + +tybg_CPPFLAGS = -I. \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" -DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" + +tybg_LDADD = + +tyalpha_SOURCES = \ +tyalpha.c + +tyalpha_CPPFLAGS = -I. \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" -DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" + +tyalpha_LDADD = + +typop_SOURCES = \ +typop.c + +typop_CPPFLAGS = -I. \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" -DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" + +typop_LDADD = + +tyq_SOURCES = \ +tyq.c + +tyq_CPPFLAGS = -I. \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" -DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" + +tyq_LDADD = + tycat_SOURCES = \ tycat.c \ extns.h diff --git a/src/bin/about.c b/src/bin/about.c index 17fe2ffe..6f11d3bb 100644 --- a/src/bin/about.c +++ b/src/bin/about.c @@ -56,7 +56,7 @@ about_toggle(Evas_Object *win, Evas_Object *bg, Evas_Object *term) "and otherwise push the boundaries of what a modern terminal " "emulator should be. We hope you enjoy it.
" "
" - "Copyright © 2012 by:
" + "Copyright © 2012-2013 by:
" "
" "Carsten Haitzler
" "Anisse Astier
" @@ -74,6 +74,7 @@ about_toggle(Evas_Object *win, Evas_Object *bg, Evas_Object *term) "Samuel F. Baggen
" "Rafael Antognolli
" "Jerome Pinot
" + "Panagiotis Galatsanos
" "
" "
" "Distributed under the 2-clause BSD license detailed below:
" diff --git a/src/bin/main.c b/src/bin/main.c index 95622de5..441c46c1 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -90,6 +90,7 @@ static void main_term_free(Term *term); static void main_term_bg_redo(Term *term); static Term *main_term_new(Win *wn, Config *config, const char *cmd, Eina_Bool login_shell, const char *cd, int size_w, int size_h, Eina_Bool hold); static void _term_focus(Term *term); +static void _sel_restore(Split *sp); static void _split_free(Split *sp) @@ -485,6 +486,7 @@ main_close(Evas_Object *win, Evas_Object *term) if (!sp) return; if (!sp->term) return; + if (sp->sel) _sel_restore(sp); spp = sp->parent; if ((sp->term->focused) && (spp)) termfoc = _term_next_get(sp->term); sp->wn->terms = eina_list_remove(sp->wn->terms, sp->term); @@ -996,7 +998,10 @@ _cb_command(void *data, Evas_Object *obj __UNUSED__, void *event) if (config) { config->temporary = EINA_TRUE; - eina_stringshare_replace(&(config->background), cmd + 2); + if (cmd[2]) + eina_stringshare_replace(&(config->background), cmd + 2); + else + eina_stringshare_replace(&(config->background), NULL); main_media_update(config); } } @@ -1007,8 +1012,12 @@ _cb_command(void *data, Evas_Object *obj __UNUSED__, void *event) if (config) { config->temporary = EINA_FALSE; - eina_stringshare_replace(&(config->background), cmd + 2); + if (cmd[2]) + eina_stringshare_replace(&(config->background), cmd + 2); + else + eina_stringshare_replace(&(config->background), NULL); main_media_update(config); + config_save(config, NULL); } } } @@ -1025,7 +1034,7 @@ _cb_command(void *data, Evas_Object *obj __UNUSED__, void *event) (!strcasecmp(cmd + 2, "on")) || (!strcasecmp(cmd + 2, "true")) || (!strcasecmp(cmd + 2, "yes"))) - config->translucent = EINA_FALSE; + config->translucent = EINA_TRUE; else config->translucent = EINA_FALSE; main_trans_update(config); @@ -1042,10 +1051,11 @@ _cb_command(void *data, Evas_Object *obj __UNUSED__, void *event) (!strcasecmp(cmd + 2, "on")) || (!strcasecmp(cmd + 2, "true")) || (!strcasecmp(cmd + 2, "yes"))) - config->translucent = EINA_FALSE; + config->translucent = EINA_TRUE; else config->translucent = EINA_FALSE; main_trans_update(config); + config_save(config, NULL); } } } @@ -1134,7 +1144,7 @@ _sel_go(Split *sp, Term *term) { edje_object_part_unswallow(tm->bg, tm->term); evas_object_lower(tm->term); - evas_object_move(tm->term, 0, 0); + evas_object_move(tm->term, -9999, -9999); evas_object_show(tm->term); evas_object_clip_unset(tm->term); #if (EVAS_VERSION_MAJOR > 1) || (EVAS_VERSION_MINOR >= 8) @@ -1756,6 +1766,11 @@ main_term_bg_redo(Term *term) evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); theme_apply(o, term->config, "terminology/background"); + if (term->config->translucent) + edje_object_signal_emit(term->bg, "translucent,on", "terminology"); + else + edje_object_signal_emit(term->bg, "translucent,off", "terminology"); + theme_auto_reload_enable(o); evas_object_show(o); @@ -1827,6 +1842,11 @@ main_term_new(Win *wn, Config *config, const char *cmd, return NULL; } + if (term->config->translucent) + edje_object_signal_emit(term->bg, "translucent,on", "terminology"); + else + edje_object_signal_emit(term->bg, "translucent,off", "terminology"); + theme_auto_reload_enable(o); evas_object_show(o); diff --git a/src/bin/sel.c b/src/bin/sel.c index 79934064..2bd80c73 100644 --- a/src/bin/sel.c +++ b/src/bin/sel.c @@ -6,6 +6,8 @@ #include "sel.h" #include "config.h" #include "utils.h" +#include "termio.h" +#include "media.h" typedef struct _Sel Sel; typedef struct _Entry Entry; @@ -37,7 +39,7 @@ struct _Sel struct _Entry { - Evas_Object *obj, *bg; + Evas_Object *obj, *bg, *media, *termio; Eina_Bool selected : 1; Eina_Bool selected_before : 1; Eina_Bool selected_orig : 1; @@ -316,6 +318,68 @@ _transit(Evas_Object *obj, double tim) if (!sd->anim) sd->anim = ecore_animator_add(_anim_cb, obj); } +static void +_label_redo(Entry *en) +{ + const char *s; + + if (!en->obj) return; + if (!en->termio) return; + s = termio_title_get(en->termio); + if (!s) s = termio_icon_name_get(en->termio); + if (s) edje_object_part_text_set(en->bg, "terminology.label", s); +} + +static void +_title_cb(void *data, Evas_Object *obj __UNUSED__, void *info __UNUSED__) +{ + _label_redo(data); +} + +static void +_icon_cb(void *data, Evas_Object *obj __UNUSED__, void *info __UNUSED__) +{ + _label_redo(data); +} + +static void +_bell_cb(void *data, Evas_Object *obj __UNUSED__, void *info __UNUSED__) +{ + Entry *en = data; + edje_object_signal_emit(en->bg, "bell", "terminology"); +} + +static void +_media_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *info __UNUSED__) +{ + Entry *en = data; + en->media = NULL; +} + +static void +_entry_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *info __UNUSED__) +{ + Entry *en = data; + en->obj = NULL; + if (en->termio) + { + evas_object_smart_callback_del_full(en->termio, "title,change", + _title_cb, en); + evas_object_smart_callback_del_full(en->termio, "icon,change", + _icon_cb, en); + evas_object_smart_callback_del_full(en->termio, "bell", + _bell_cb, en); + en->termio = NULL; + } +} + +static void +_entry_termio_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *info __UNUSED__) +{ + Entry *en = data; + en->termio = NULL; +} + static void _smart_add(Evas_Object *obj) { @@ -346,7 +410,17 @@ _smart_del(Evas_Object *obj) if (sd->autozoom_timeout) ecore_timer_del(sd->autozoom_timeout); EINA_LIST_FREE(sd->items, en) { - evas_object_del(en->obj); + if (en->termio) + { + evas_object_smart_callback_del_full(en->termio, "title,change", + _title_cb, en); + evas_object_smart_callback_del_full(en->termio, "icon,change", + _icon_cb, en); + evas_object_smart_callback_del_full(en->termio, "bell", + _bell_cb, en); + } + if (en->obj) evas_object_del(en->obj); + if (en->media) evas_object_del(en->media); evas_object_del(en->bg); free(en); } @@ -441,7 +515,6 @@ void sel_entry_add(Evas_Object *obj, Evas_Object *entry, Eina_Bool selected, Config *config) { Sel *sd = evas_object_smart_data_get(obj); - Evas_Object *o; Entry *en = calloc(1, sizeof(Entry)); if (!en) return; sd->items = eina_list_append(sd->items, en); @@ -455,20 +528,48 @@ sel_entry_add(Evas_Object *obj, Evas_Object *entry, Eina_Bool selected, Config * evas_object_clip_set(en->bg, sd->clip); edje_object_part_swallow(en->bg, "terminology.content", en->obj); evas_object_show(en->obj); + + if (config->background) + { + Evas_Object *o; + int type = 0; + + en->media = o = media_add(obj, + config->background, config, + MEDIA_BG, &type); + evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, + _media_del_cb, en); + edje_object_part_swallow(en->bg, "terminology.background", o); + evas_object_show(o); + if (type == TYPE_IMG) + edje_object_signal_emit(en->bg, "media,image", "terminology"); + else if (type == TYPE_SCALE) + edje_object_signal_emit(en->bg, "media,scale", "terminology"); + else if (type == TYPE_EDJE) + edje_object_signal_emit(en->bg, "media,edje", "terminology"); + else if (type == TYPE_MOV) + edje_object_signal_emit(en->bg, "media,movie", "terminology"); + } + evas_object_stack_below(en->bg, sd->o_event); if (en->selected) edje_object_signal_emit(en->bg, "selected,start", "terminology"); sd->interp = 1.0; - - o = evas_object_data_get(en->obj, "termio"); - if (o) + en->termio = evas_object_data_get(en->obj, "termio"); + if (en->termio) { - const char *s; - - s = termio_title_get(o); - if (!s) s = termio_icon_name_get(o); - if (s) edje_object_part_text_set(en->bg, "terminology.label", s); + evas_object_smart_callback_add(en->termio, "title,change", + _title_cb, en); + evas_object_smart_callback_add(en->termio, "icon,change", + _icon_cb, en); + evas_object_smart_callback_add(en->termio, "bell", + _bell_cb, en); + _label_redo(en); + evas_object_event_callback_add(en->termio, EVAS_CALLBACK_DEL, + _entry_termio_del_cb, en); } + evas_object_event_callback_add(en->obj, EVAS_CALLBACK_DEL, + _entry_del_cb, en); } void diff --git a/src/bin/termio.c b/src/bin/termio.c index 4d012e9e..4c0f005c 100644 --- a/src/bin/termio.c +++ b/src/bin/termio.c @@ -1359,33 +1359,57 @@ _smart_cb_key_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, { if (!strcmp(ev->keyname, "Prior")) { + _compose_seq_reset(sd); evas_object_smart_callback_call(data, "split,h", NULL); goto end; } else if (!strcmp(ev->keyname, "Next")) { + _compose_seq_reset(sd); evas_object_smart_callback_call(data, "split,v", NULL); goto end; } else if (!strcmp(ev->keyname, "t")) { + _compose_seq_reset(sd); evas_object_smart_callback_call(data, "new", NULL); goto end; } else if (!strcmp(ev->keyname, "Home")) { + _compose_seq_reset(sd); evas_object_smart_callback_call(data, "select", NULL); goto end; } + else if (!strcmp(ev->keyname, "c")) + { + _compose_seq_reset(sd); + _take_selection(data, ELM_SEL_TYPE_CLIPBOARD); + goto end; + } + else if (!strcmp(ev->keyname, "v")) + { + _compose_seq_reset(sd); + _paste_selection(data, ELM_SEL_TYPE_CLIPBOARD); + goto end; + } } if ((evas_key_modifier_is_set(ev->modifiers, "Alt")) && (!evas_key_modifier_is_set(ev->modifiers, "Shift")) && - (!evas_key_modifier_is_set(ev->modifiers, "Control")) && - (!strcmp(ev->keyname, "Home"))) + (!evas_key_modifier_is_set(ev->modifiers, "Control"))) { - _compose_seq_reset(sd); - evas_object_smart_callback_call(data, "cmdbox", NULL); - goto end; + if (!strcmp(ev->keyname, "Home")) + { + _compose_seq_reset(sd); + evas_object_smart_callback_call(data, "cmdbox", NULL); + goto end; + } + else if (!strcmp(ev->keyname, "Return")) + { + _compose_seq_reset(sd); + _paste_selection(data, ELM_SEL_TYPE_PRIMARY); + goto end; + } } if ((evas_key_modifier_is_set(ev->modifiers, "Alt")) && (evas_key_modifier_is_set(ev->modifiers, "Control")) && diff --git a/src/bin/tyalpha.c b/src/bin/tyalpha.c new file mode 100644 index 00000000..d8e5f343 --- /dev/null +++ b/src/bin/tyalpha.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int i, perm = 0; + + if (!getenv("TERMINOLOGY")) return 0; + if (argc <= 1) + { + printf("Usage: %s [-p] on|off\n" + " Change the terminal transparency on or off\n" + " -p Make change permanent (stored in config)\n" + "\n", + argv[0]); + return 0; + } + for (i = 1; i < argc; i++) + { + char tbuf[PATH_MAX]; + + if (!strcmp(argv[i], "-p")) + { + perm = 1; + i++; + if (i >= argc) break; + } + if (perm) + snprintf(tbuf, sizeof(tbuf), "%c}ap%s", 0x1b, argv[i]); + else + snprintf(tbuf, sizeof(tbuf), "%c}at%s", 0x1b, argv[i]); + if (write(0, tbuf, strlen(tbuf)) < 1) perror("write"); + tbuf[0] = 0; + if (write(0, tbuf, 1) < 1) perror("write"); + } + exit(0); + return 0; +} diff --git a/src/bin/tybg.c b/src/bin/tybg.c new file mode 100644 index 00000000..9fd74b17 --- /dev/null +++ b/src/bin/tybg.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int i, perm = 0; + + if (!getenv("TERMINOLOGY")) return 0; + if (argc <= 1) + { + printf("Usage: %s [-p] FILE1 [FILE2 ...]\n" + " Change the terminal background to the given file/uri\n" + " -p Make change permanent (stored in config)\n" + "\n", + argv[0]); + return 0; + } + for (i = 1; i < argc; i++) + { + char *path, buf[PATH_MAX * 2], tbuf[PATH_MAX * 3]; + + if (!strcmp(argv[i], "-p")) + { + perm = 1; + i++; + if (i >= argc) break; + } + path = argv[i]; + if (realpath(path, buf)) path = buf; + if (perm) + snprintf(tbuf, sizeof(tbuf), "%c}bp%s", 0x1b, path); + else + snprintf(tbuf, sizeof(tbuf), "%c}bt%s", 0x1b, path); + if (write(0, tbuf, strlen(tbuf)) < 1) perror("write"); + tbuf[0] = 0; + if (write(0, tbuf, 1) < 1) perror("write"); + } + exit(0); + return 0; +} diff --git a/src/bin/typop.c b/src/bin/typop.c new file mode 100644 index 00000000..2686ed97 --- /dev/null +++ b/src/bin/typop.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int i; + + if (!getenv("TERMINOLOGY")) return 0; + if (argc <= 1) + { + printf("Usage: %s FILE1 [FILE2 ...]\n" + " Pop up a given media file/uri right now\n" + "\n", + argv[0]); + return 0; + } + for (i = 1; i < argc; i++) + { + char *path, buf[PATH_MAX * 2], tbuf[PATH_MAX * 3]; + + path = argv[i]; + if (realpath(path, buf)) path = buf; + snprintf(tbuf, sizeof(tbuf), "%c}pn%s", 0x1b, path); + if (write(0, tbuf, strlen(tbuf)) < 1) perror("write"); + tbuf[0] = 0; + if (write(0, tbuf, 1) < 1) perror("write"); + } + exit(0); + return 0; +} diff --git a/src/bin/tyq.c b/src/bin/tyq.c new file mode 100644 index 00000000..7e45d785 --- /dev/null +++ b/src/bin/tyq.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int i; + + if (!getenv("TERMINOLOGY")) return 0; + if (argc <= 1) + { + printf("Usage: %s FILE1 [FILE2 ...]\n" + " Queue a given media file/uri to the popped up\n" + "\n", + argv[0]); + return 0; + } + for (i = 1; i < argc; i++) + { + char *path, buf[PATH_MAX * 2], tbuf[PATH_MAX * 3]; + + path = argv[i]; + if (realpath(path, buf)) path = buf; + snprintf(tbuf, sizeof(tbuf), "%c}pq%s", 0x1b, path); + if (write(0, tbuf, strlen(tbuf)) < 1) perror("write"); + tbuf[0] = 0; + if (write(0, tbuf, 1) < 1) perror("write"); + } + exit(0); + return 0; +}