tcat... comes out to play fir the first time. not final... but a start.

SVN revision: 83385
devs/lucas/wip
Carsten Haitzler 10 years ago
parent e280319301
commit 2781da8076
  1. 10
      README
  2. 1
      configure.ac
  3. 10
      src/bin/Makefile.am
  4. 33
      src/bin/media.c
  5. 11
      src/bin/media.h
  6. 147
      src/bin/tcat.c
  7. 157
      src/bin/termio.c
  8. 77
      src/bin/termpty.c
  9. 65
      src/bin/termpty.h
  10. 28
      src/bin/termptyesc.c

@ -54,7 +54,7 @@ Shift+Keypad-Multiply = Reset font size to 10
Shift+Keypad-Divide = Copy highlight to Clipboard (same as ctrl+c in gui apps)
Ctrl+PgUp = switch focus to previous terminal inside a window
Ctrl+PgDn = switch focus to next terminal inside a window
Ctrl+t = create new terminal on top of current inside window (tabs) (not implemented)
Ctrl+Shift+t = create new terminal on top of current inside window (tabs) (not implemented)
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)
@ -123,3 +123,11 @@ at[on/true/yes/off/false/no]
ap[on/true/yes/off/false/no]
= set the terminal alpha state to be on, or off permanently
qs
= query grid and font size. stdin will have written to it:
W;H;FW;FH\n
where W is the width of the terminal grid in characters
where H is the height of the terminal grid in characters
where FW is the width of 1 character cell in pixels
where FH is the height of 1 character cell in pixels

@ -24,6 +24,7 @@ requirements="\
eet >= 1.7.0 \
evas >= 1.7.0 \
ecore >= 1.7.0 \
ecore-evas >= 1.7.0 \
edje >= 1.7.0 \
emotion >= 1.7.0 \
ecore-input >= 1.7.0 \

@ -1,6 +1,6 @@
MAINTAINERCLEANFILES = Makefile.in
bin_PROGRAMS = terminology
bin_PROGRAMS = terminology tcat
terminology_CPPFLAGS = -I. \
-DPACKAGE_BIN_DIR=\"$(bindir)\" -DPACKAGE_LIB_DIR=\"$(libdir)\" \
@ -38,3 +38,11 @@ termptyext.c termptyext.h \
utf8.c utf8.h \
win.c win.h \
utils.c utils.h
tcat_SOURCES = tcat.c
tcat_CPPFLAGS = -I. \
-DPACKAGE_BIN_DIR=\"$(bindir)\" -DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" @TERMINOLOGY_CFLAGS@
tcat_LDADD = @TERMINOLOGY_LIBS@

@ -158,7 +158,7 @@ _type_img_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_
{
int iw = 1, ih = 1;
if (sd->mode == MEDIA_BG)
if ((sd->mode & MEDIA_SIZE_MASK) == MEDIA_BG)
{
iw = w;
ih = (sd->ih * w) / sd->iw;
@ -169,7 +169,7 @@ _type_img_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_
if (iw < w) iw = w;
}
}
else if (sd->mode == MEDIA_POP)
else if ((sd->mode & MEDIA_SIZE_MASK) == MEDIA_POP)
{
iw = w;
ih = (sd->ih * w) / sd->iw;
@ -185,6 +185,11 @@ _type_img_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_
ih = sd->ih;
}
}
else if ((sd->mode & MEDIA_SIZE_MASK) == MEDIA_STRETCH)
{
iw = w;
ih = h;
}
x += ((w - iw) / 2);
y += ((h - ih) / 2);
w = iw;
@ -247,7 +252,7 @@ _type_scale_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Eva
{
int iw = 1, ih = 1;
if (sd->mode == MEDIA_BG)
if ((sd->mode & MEDIA_SIZE_MASK) == MEDIA_BG)
{
iw = w;
ih = (sd->ih * w) / sd->iw;
@ -258,7 +263,7 @@ _type_scale_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Eva
if (iw < w) iw = w;
}
}
else if (sd->mode == MEDIA_POP)
else if ((sd->mode & MEDIA_SIZE_MASK) == MEDIA_POP)
{
iw = w;
ih = (sd->ih * w) / sd->iw;
@ -269,6 +274,11 @@ _type_scale_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Eva
if (iw > w) iw = w;
}
}
else if ((sd->mode & MEDIA_SIZE_MASK) == MEDIA_STRETCH)
{
iw = w;
ih = h;
}
x += ((w - iw) / 2);
y += ((h - ih) / 2);
w = iw;
@ -514,6 +524,9 @@ _type_mov_init(Evas_Object *obj)
evas_object_smart_callback_add(o, "ref_change",
_cb_mov_ref, obj);
emotion_object_file_set(o, sd->realf);
if (((sd->mode & MEDIA_OPTIONS_MASK) & MEDIA_RECOVER)
&& (sd->type == TYPE_MOV) && (sd->o_img))
emotion_object_last_position_load(sd->o_img);
evas_object_smart_member_add(o, obj);
evas_object_clip_set(o, sd->clip);
@ -568,7 +581,7 @@ _type_mov_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_
if (ratio > 0.0) sd->iw = (sd->ih * ratio) + 0.5;
else ratio = (double)sd->iw / (double)sd->ih;
if (sd->mode == MEDIA_BG)
if ((sd->mode & MEDIA_SIZE_MASK) == MEDIA_BG)
{
iw = w;
ih = w / ratio;
@ -579,7 +592,7 @@ _type_mov_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_
if (iw < w) iw = w;
}
}
else if (sd->mode == MEDIA_POP)
else if ((sd->mode & MEDIA_SIZE_MASK) == MEDIA_POP)
{
iw = w;
ih = w / ratio;
@ -590,6 +603,11 @@ _type_mov_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_
if (iw > w) iw = w;
}
}
else if ((sd->mode & MEDIA_SIZE_MASK) == MEDIA_STRETCH)
{
iw = w;
ih = h;
}
x += ((w - iw) / 2);
y += ((h - ih) / 2);
w = iw;
@ -624,6 +642,9 @@ _smart_del(Evas_Object *obj)
{
Media *sd = evas_object_smart_data_get(obj);
if (!sd) return;
if (((sd->mode & MEDIA_OPTIONS_MASK) & MEDIA_SAVE)
&& (sd->type == TYPE_MOV) && (sd->o_img))
emotion_object_last_position_save(sd->o_img);
if (sd->url)
{
ecore_event_handler_del(sd->url_prog_hand);

@ -1,8 +1,15 @@
#ifndef _MEDIA_H__
#define _MEDIA_H__ 1
#define MEDIA_BG 0
#define MEDIA_POP 1
#define MEDIA_SIZE_MASK 0x000f
#define MEDIA_OPTIONS_MASK 0x00f0
// enum list types
#define MEDIA_BG 0x0000
#define MEDIA_POP 0x0001
#define MEDIA_STRETCH 0x0002
// bitmask for options - on or off
#define MEDIA_RECOVER 0x0010
#define MEDIA_SAVE 0x0020
#define TYPE_UNKNOWN -1
#define TYPE_IMG 0

@ -0,0 +1,147 @@
#include <Eina.h>
#include <Ecore.h>
#include <Evas.h>
#include <Ecore_Evas.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
enum {
CENTER,
FILL,
STRETCH
};
Ecore_Evas *ee = NULL;
Evas *evas = NULL;
Evas_Object *o = NULL;
struct termios told, tnew;
int tw = 0, th = 0, cw = 0, ch = 0;
int w = 0, h = 0;
int iw = 0, ih = 0;
static int
echo_off(void)
{
if (tcgetattr(0, &told) != 0) return -1;
tnew = told;
tnew.c_lflag &= ~ECHO;
if (tcsetattr(0, TCSAFLUSH, &tnew) != 0) return -1;
return 0;
}
static int
echo_on(void)
{
return tcsetattr(0, TCSAFLUSH, &told);
}
int
main(int argc, char **argv)
{
char buf[8192];
if (!getenv("TERMINOLOGY")) return 0;
if (argc <= 1)
{
printf("Usage: %s [-s|-f|-c] FILE1 [FILE2 ...]\n"
"\n"
" -s Stretch file to fill nearest character cell size\n"
" -f Fill file to totally cover character cells with no gaps\n"
" -c Center file in nearest character cells but only scale down (default)\n",
argv[0]);
return 0;
}
eina_init();
ecore_init();
evas_init();
ecore_evas_init();
ee = ecore_evas_buffer_new(1, 1);
if (ee)
{
int i, mode = CENTER;
evas = ecore_evas_get(ee);
o = evas_object_image_add(evas);
for (i = 1; i < argc; i++)
{
char *path;
if (!strcmp(argv[i], "-c"))
{
mode = CENTER;
i++;
if (i >= argc) return 0;
}
else if (!strcmp(argv[i], "-s"))
{
mode = STRETCH;
i++;
if (i >= argc) return 0;
}
else if (!strcmp(argv[i], "-f"))
{
mode = FILL;
i++;
if (i >= argc) return 0;
}
path = argv[i];
evas_object_image_file_set(o, path, NULL);
evas_object_image_size_get(o, &w, &h);
if ((w >= 0) && (h > 0))
{
int x, y;
echo_off();
snprintf(buf, sizeof(buf), "%c}qs", 0x1b);
write(0, buf, strlen(buf) + 1);
if (scanf("%i;%i;%i;%i", &tw, &th, &cw, &ch) != 4)
{
echo_on();
continue;
}
echo_on();
if ((tw <= 0) || (th <= 0) || (cw <= 1) || (ch <= 1))
continue;
if (w > (tw * cw))
{
iw = tw;
ih = ((h * (tw * cw) / w) + (ch - 1)) / ch;
}
else
{
iw = (w + (cw - 1)) / cw;
ih = (h + (ch - 1)) / ch;
}
if (mode == CENTER)
snprintf(buf, sizeof(buf), "%c}ic%i;%i;%s",
0x1b, iw, ih, path);
else if (mode == FILL)
snprintf(buf, sizeof(buf), "%c}if%i;%i;%s",
0x1b, iw, ih, path);
else
snprintf(buf, sizeof(buf), "%c}is%i;%i;%s",
0x1b, iw, ih, path);
write(0, buf, strlen(buf) + 1);
for (y = 0; y < ih; y++)
{
for (x = 0; x < iw; x++)
{
write(0, "#", 1);
}
write(0, "\n", 1);
}
}
}
// ecore_main_loop_begin();
ecore_evas_free(ee);
}
ecore_evas_shutdown();
evas_shutdown();
ecore_shutdown();
eina_shutdown();
return 0;
}

@ -388,11 +388,18 @@ _smart_apply(Evas_Object *obj)
{
Termio *sd = evas_object_smart_data_get(obj);
Evas_Coord ox, oy, ow, oh;
Eina_List *l, *ln;
Termblock *blk;
int j, x, y, w, ch1 = 0, ch2 = 0, inv = 0;
if (!sd) return;
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
EINA_LIST_FOREACH(sd->pty->block.active, l, blk)
{
blk->was_active = blk->active;
blk->active = EINA_FALSE;
}
inv = sd->pty->state.reverse;
for (y = 0; y < sd->grid.h; y++)
{
@ -428,7 +435,67 @@ _smart_apply(Evas_Object *obj)
}
else
{
if (cells[j].att.invisible)
int bid, bx = 0, by = 0;
bid = termpty_block_id_get(&(cells[j]), &bx, &by);
if (bid >= 0)
{
if (ch1 < 0) ch1 = x;
ch2 = x;
tc[x].codepoint = 0;
tc[x].fg_extended = 0;
tc[x].bg_extended = 0;
tc[x].underline = 0;
tc[x].strikethrough = 0;
tc[x].fg = COL_INVIS;
tc[x].bg = COL_INVIS;
#if defined(SUPPORT_DBLWIDTH)
tc[x].double_width = 0;
#endif
blk = termpty_block_get(sd->pty, bid);
if (blk)
{
if (!blk->active)
{
blk->active = EINA_TRUE;
if (!blk->obj)
{
int type = 0;
int media = MEDIA_STRETCH;
if (blk->scale_stretch)
media = MEDIA_STRETCH;
else if (blk->scale_center)
media = MEDIA_POP;
else if (blk->scale_fill)
media = MEDIA_BG;
if (!blk->was_active_before)
media |= MEDIA_SAVE;
else
media |= MEDIA_RECOVER | MEDIA_SAVE;
blk->obj = media_add(obj, blk->path,
sd->config,
media, &type);
blk->type = type;
evas_object_smart_member_add(blk->obj, obj);
evas_object_stack_above(blk->obj, sd->grid.obj);
evas_object_show(blk->obj);
}
blk->was_active_before = EINA_TRUE;
if (!blk->was_active)
sd->pty->block.active = eina_list_append(sd->pty->block.active, blk);
}
blk->x = (x - bx);
blk->y = (y - by);
evas_object_move(blk->obj,
ox + (blk->x * sd->font.chw),
oy + (blk->y * sd->font.chh));
evas_object_resize(blk->obj,
blk->w * sd->font.chw,
blk->h * sd->font.chh);
}
}
else if (cells[j].att.invisible)
{
if ((tc[x].codepoint != 0) ||
(tc[x].bg != COL_INVIS) ||
@ -546,6 +613,21 @@ _smart_apply(Evas_Object *obj)
ch2 - ch1 + 1, 1);
}
EINA_LIST_FOREACH_SAFE(sd->pty->block.active, l, ln, blk)
{
if (!blk->active)
{
blk->was_active = EINA_FALSE;
if (blk->obj)
{
evas_object_del(blk->obj);
blk->obj = NULL;
}
sd->pty->block.active = eina_list_remove_list
(sd->pty->block.active, l);
}
}
if ((sd->scroll != 0) || (sd->pty->state.hidecursor))
evas_object_hide(sd->cur.obj);
else
@ -992,11 +1074,6 @@ _smart_cb_key_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
evas_object_smart_callback_call(data, "next", NULL);
goto end;
}
else if (!strcmp(ev->keyname, "t"))
{
evas_object_smart_callback_call(data, "new", NULL);
goto end;
}
}
if ((!evas_key_modifier_is_set(ev->modifiers, "Alt")) &&
(evas_key_modifier_is_set(ev->modifiers, "Control")) &&
@ -1012,6 +1089,11 @@ _smart_cb_key_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
evas_object_smart_callback_call(data, "split,v", NULL);
goto end;
}
else if (!strcmp(ev->keyname, "t"))
{
evas_object_smart_callback_call(data, "new", NULL);
goto end;
}
}
if ((evas_key_modifier_is_set(ev->modifiers, "Alt")) &&
(!evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
@ -2521,6 +2603,67 @@ _smart_pty_command(void *data)
sd = evas_object_smart_data_get(obj);
if (!sd) return;
if (!sd->pty->cur_cmd) return;
if (sd->pty->cur_cmd[0] == 'i')
{
if ((sd->pty->cur_cmd[1] == 's') ||
(sd->pty->cur_cmd[1] == 'c') ||
(sd->pty->cur_cmd[1] == 'f'))
{
const char *p, *p0, *path;
int ww = 0, hh = 0;
// exact size in CHAR CELLS - WW (decimal) width CELLS,
// HH (decimal) in CELLS.
//
// isWW;HH;PATH
for (p0 = p = &(sd->pty->cur_cmd[2]); *p; p++)
{
if (*p == ';')
{
ww = strtol(p0, NULL, 10);
p++;
break;
}
}
for (p0 = p; *p; p++)
{
if (*p == ';')
{
hh = strtol(p0, NULL, 10);
p++;
break;
}
}
path = p;
if ((ww < 512) && (hh < 512))
{
Termblock *blk = termpty_block_new(sd->pty, ww, hh, path);
if (blk)
{
if (sd->pty->cur_cmd[1] == 's')
blk->scale_stretch = EINA_TRUE;
else if (sd->pty->cur_cmd[1] == 'c')
blk->scale_center = EINA_TRUE;
else if (sd->pty->cur_cmd[1] == 'f')
blk->scale_fill = EINA_TRUE;
termpty_block_insert(sd->pty, blk);
}
}
return;
}
}
else if (sd->pty->cur_cmd[0] == 'q')
{
if (sd->pty->cur_cmd[1] == 's')
{
char buf[256];
snprintf(buf, sizeof(buf), "%i;%i;%i;%i\n",
sd->grid.w, sd->grid.h, sd->font.chw, sd->font.chh);
termpty_write(sd->pty, buf, strlen(buf));
return;
}
}
evas_object_smart_callback_call(obj, "command", (void *)sd->pty->cur_cmd);
}

@ -377,6 +377,8 @@ err:
void
termpty_free(Termpty *ty)
{
if (ty->block.blocks) eina_hash_free(ty->block.blocks);
if (ty->block.active) eina_list_free(ty->block.active);
if (ty->fd >= 0) close(ty->fd);
if (ty->slavefd >= 0) close(ty->slavefd);
if (ty->pid >= 0)
@ -548,3 +550,78 @@ termpty_pid_get(const Termpty *ty)
{
return ty->pid;
}
void
termpty_block_free(Termblock *tb)
{
if (tb->path) eina_stringshare_del(tb->path);
if (tb->obj) evas_object_del(tb->obj);
free(tb);
}
Termblock *
termpty_block_new(Termpty *ty, int w, int h, const char *path)
{
Termblock *tb;
int id;
id = ty->block.curid;
if (!ty->block.blocks)
ty->block.blocks = eina_hash_int32_new((Eina_Free_Cb)termpty_block_free);
if (!ty->block.blocks) return NULL;
tb = eina_hash_find(ty->block.blocks, &id);
if (tb)
{
if (tb->active)
ty->block.active = eina_list_remove(ty->block.active, tb);
eina_hash_del(ty->block.blocks, &id, tb);
}
tb = calloc(1, sizeof(Termblock));
if (!tb) return NULL;
tb->id = id;
tb->w = w;
tb->h = h;
tb->path = eina_stringshare_add(path);
eina_hash_add(ty->block.blocks, &id, tb);
ty->block.curid++;
if (ty->block.curid >= 8192) ty->block.curid = 0;
return tb;
}
void
termpty_block_insert(Termpty *ty, Termblock *blk)
{
// bit 0-8 = y (9b 0->511)
// bit 9-17 = x (9b 0->511)
// bit 18-30 = id (13b 0->8191)
// bit 31 = 1
//
// fg/bg = 8+8bit unused. (use for extra id bits? so 16 + 13 == 29bit?)
//
// cp = (1 << 31) | ((id 0x1fff) << 18) | ((x & 0x1ff) << 9) | (y & 0x1ff);
ty->block.expecting.left = blk->w * blk->h;
ty->block.expecting.x = 0;
ty->block.expecting.y = 0;
ty->block.expecting.id = blk->id;
ty->block.expecting.w = blk->w;
ty->block.expecting.h = blk->h;
}
int
termpty_block_id_get(Termcell *cell, int *x, int *y)
{
int id;
if (!(cell->codepoint & 0x80000000)) return -1;
id = (cell->codepoint >> 18) & 0x1fff;
*x = (cell->codepoint >> 9) & 0x1ff;
*y = cell->codepoint & 0x1ff;
return id;
}
Termblock *
termpty_block_get(Termpty *ty, int id)
{
return eina_hash_find(ty->block.blocks, &id);
}

@ -3,6 +3,7 @@ typedef struct _Termcell Termcell;
typedef struct _Termatt Termatt;
typedef struct _Termstate Termstate;
typedef struct _Termsave Termsave;
typedef struct _Termblock Termblock;
#define COL_DEF 0
#define COL_BLACK 1
@ -96,22 +97,30 @@ struct _Termpty
} change, scroll, set_title, set_icon, cancel_sel, exited, bell, command;
} cb;
struct {
const char *title;
const char *icon;
const char *title, *icon;
} prop;
int w, h;
int fd, slavefd;
pid_t pid;
const char *cur_cmd;
Termcell *screen, *screen2;
Termsave **back;
int *buf;
int buflen;
int w, h;
int fd, slavefd;
int circular_offset;
int backmax, backpos;
int backscroll_num;
int *buf;
int buflen;
struct {
int curid;
Eina_Hash *blocks;
Eina_List *active;
struct {
int left, id;
int x, y, w, h;
} expecting;
} block;
Termstate state, save, swap;
int exit_code;
pid_t pid;
unsigned int altbuf : 1;
unsigned int mouse_mode : 3;
unsigned int mouse_ext : 2;
@ -129,17 +138,39 @@ struct _Termsave
Termcell cell[1];
};
void termpty_init(void);
void termpty_shutdown(void);
Termpty *termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd, int w, int h, int backscroll);
void termpty_free(Termpty *ty);
Termcell *termpty_cellrow_get(Termpty *ty, int y, int *wret);
void termpty_write(Termpty *ty, const char *input, int len);
void termpty_resize(Termpty *ty, int w, int h);
void termpty_backscroll_set(Termpty *ty, int size);
struct _Termblock
{
int id;
int type;
short w, h;
short x, y;
const char *path;
Evas_Object *obj;
Eina_Bool scale_stretch : 1;
Eina_Bool scale_center : 1;
Eina_Bool scale_fill : 1;
Eina_Bool active : 1;
Eina_Bool was_active : 1;
Eina_Bool was_active_before : 1;
};
pid_t termpty_pid_get(const Termpty *ty);
void termpty_init(void);
void termpty_shutdown(void);
Termpty *termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd, int w, int h, int backscroll);
void termpty_free(Termpty *ty);
Termcell *termpty_cellrow_get(Termpty *ty, int y, int *wret);
void termpty_write(Termpty *ty, const char *input, int len);
void termpty_resize(Termpty *ty, int w, int h);
void termpty_backscroll_set(Termpty *ty, int size);
pid_t termpty_pid_get(const Termpty *ty);
void termpty_block_free(Termblock *tb);
Termblock *termpty_block_new(Termpty *ty, int w, int h, const char *path);
void termpty_block_insert(Termpty *ty, Termblock *blk);
int termpty_block_id_get(Termcell *cell, int *x, int *y);
Termblock *termpty_block_get(Termpty *ty, int id);
extern int _termpty_log_dom;

@ -1310,7 +1310,33 @@ _termpty_handle_seq(Termpty *ty, Eina_Unicode *c, Eina_Unicode *ce)
if (len == 0) return 0;
return 1 + len;
}
else if (ty->block.expecting.left > 0)
{
if (c[0] == '#')
{
Eina_Unicode cp;
cp = (1 << 31) |
((ty->block.expecting.id & 0x1fff) << 18) |
((ty->block.expecting.x & 0x1ff) << 9) |
(ty->block.expecting.y & 0x1ff);
ty->block.expecting.x++;
if (ty->block.expecting.x >= ty->block.expecting.w)
{
ty->block.expecting.x = 0;
ty->block.expecting.y++;
}
ty->block.expecting.left--;
_termpty_text_append(ty, &cp, 1);
return 1;
}
else
{
_termpty_text_append(ty, c, 1);
ty->state.had_cr = 0;
return 1;
}
}
cc = (int *)c;
DBG("txt: [");
while ((cc < ce) && (*cc >= 0x20) && (*cc != 0x7f))

Loading…
Cancel
Save