add tysend cmdline and support in escapes for sending single files
this allows you to send a file via escapes to terminology which will pop up a file save dialog and ask what to save it as and where (based on the original name). terminology will show a progress bar too. this is not useful locally but remotely (e.g. you ssh'd into another machine) it's a VERY handy way of fetching a file from the remote machine to the local machine with a display just with tysend FILE. you can send multiple in a sequence with tysend FILE1 FILE2 FILE3 ... ... and terminology will ask for a location and filename per file you send (just hit cancel if you don't want to do it). note - it needs new theme features to work. it'll fail without them. @feature
This commit is contained in:
parent
076093da5e
commit
125d475068
19
README
19
README
|
@ -299,3 +299,22 @@ ib
|
|||
|
||||
ie
|
||||
= end media replace sequence run
|
||||
|
||||
fr[PATH/FILE]
|
||||
= begin file send for a file named PATH/FILE
|
||||
|
||||
fs[SIZE_BYTES]
|
||||
= set the size in bytes of a file send started with the above fr escape
|
||||
|
||||
fd[CHECKSUM DATA]
|
||||
= block of data for the current file transfer with checksum as a
|
||||
string decimal which is the sum of every byte when taken as an
|
||||
unsigned char per byte. the checksum is a signed 32bit integer.
|
||||
the checksum is the sum of the data after escaping. data will be
|
||||
escaped using a 0xff byte as the escape header. the escape sequence
|
||||
of 0xff 0x01 represents a 0x00 (nul) bytes, and 0xff 0x02 represents
|
||||
a 0xff byte. all other bytes are transitted as-is.
|
||||
|
||||
fx
|
||||
= exit file send mode (normally at the end of the file or when it's
|
||||
complete)
|
||||
|
|
|
@ -651,6 +651,171 @@ collections {
|
|||
target: "terminology.tabmissed.label";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// sendfile request
|
||||
part { name: "sendfile_request_clip"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
color: 255 255 255 0;
|
||||
visible: 0;
|
||||
}
|
||||
description { state: "on" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 1;
|
||||
color: 255 255 255 255;
|
||||
}
|
||||
}
|
||||
part { name: "sendfile_request_shadow";
|
||||
mouse_events: 0;
|
||||
clip_to: "sendfile_request_clip";
|
||||
description { state: "default" 0.0;
|
||||
fixed: 1 1;
|
||||
rel.to: "sendfile_request_bg";
|
||||
rel1.offset: -32 -32;
|
||||
rel2.offset: 31 31;
|
||||
image.normal: "pm_shadow.png";
|
||||
image.border: 64 64 64 64;
|
||||
fill.smooth: 0;
|
||||
}
|
||||
}
|
||||
part { name: "sendfile_request_bg"; type: RECT;
|
||||
clip_to: "sendfile_request_clip";
|
||||
description { state: "default" 0.0;
|
||||
color: 64 64 64 255;
|
||||
rel1.relative: 0.0 -1.0;
|
||||
rel2.relative: 1.0 0.0;
|
||||
}
|
||||
description { state: "on" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
rel1.relative: 0.0 0.0;
|
||||
rel2.relative: 1.0 1.0;
|
||||
}
|
||||
}
|
||||
part { name: "terminology.sendfile.request"; type: SWALLOW;
|
||||
clip_to: "sendfile_request_clip";
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "sendfile_request_bg";
|
||||
rel1.offset: 4 4;
|
||||
rel2.offset: -5 -5;
|
||||
offscale;
|
||||
}
|
||||
description { state: "on" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
rel1.relative: 0.0 0.0;
|
||||
rel2.relative: 1.0 1.0;
|
||||
}
|
||||
}
|
||||
program {
|
||||
signal: "sendfile,request,on"; source: "terminology";
|
||||
action: ACTION_STOP;
|
||||
target: "sendfile_request_on";
|
||||
target: "sendfile_request_off";
|
||||
}
|
||||
program {
|
||||
signal: "sendfile,request,off"; source: "terminology";
|
||||
action: ACTION_STOP;
|
||||
target: "sendfile_request_on";
|
||||
target: "sendfile_request_off";
|
||||
}
|
||||
program { name: "sendfile_request_on";
|
||||
signal: "sendfile,request,on"; source: "terminology";
|
||||
in: 0.5 0.0;
|
||||
action: STATE_SET "on" 0.0;
|
||||
transition: DECELERATE 0.5;
|
||||
target: "sendfile_request_clip";
|
||||
target: "sendfile_request_bg";
|
||||
}
|
||||
program { name: "sendfile_request_off";
|
||||
signal: "sendfile,request,off"; source: "terminology";
|
||||
action: STATE_SET "default" 0.0;
|
||||
transition: DECELERATE 0.5;
|
||||
target: "sendfile_request_clip";
|
||||
target: "sendfile_request_bg";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// sendfile progress
|
||||
part { name: "sendfile_progress_clip"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
color: 255 255 255 0;
|
||||
visible: 0;
|
||||
}
|
||||
description { state: "on" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 1;
|
||||
color: 255 255 255 255;
|
||||
}
|
||||
}
|
||||
part { name: "sendfile_progress_shadow";
|
||||
mouse_events: 0;
|
||||
clip_to: "sendfile_progress_clip";
|
||||
description { state: "default" 0.0;
|
||||
fixed: 1 1;
|
||||
rel.to: "sendfile_progress_bg";
|
||||
rel1.offset: -32 -32;
|
||||
rel2.offset: 31 31;
|
||||
image.normal: "pm_shadow.png";
|
||||
image.border: 64 64 64 64;
|
||||
fill.smooth: 0;
|
||||
}
|
||||
}
|
||||
part { name: "sendfile_progress_bg"; type: RECT;
|
||||
clip_to: "sendfile_progress_clip";
|
||||
scale : 1;
|
||||
description { state: "default" 0.0;
|
||||
color: 64 64 64 255;
|
||||
rel.to: "terminology.sendfile.progress";
|
||||
rel1.offset: -4 -4;
|
||||
rel2.offset: 4 4;
|
||||
offscale;
|
||||
}
|
||||
}
|
||||
part { name: "terminology.sendfile.progress"; type: SWALLOW;
|
||||
clip_to: "sendfile_progress_clip";
|
||||
scale : 1;
|
||||
description { state: "default" 0.0;
|
||||
rel1.relative: 0.0 0.0;
|
||||
rel1.offset: 4 -5;
|
||||
rel2.relative: 1.0 0.0;
|
||||
rel2.offset: -5 -5;
|
||||
align: 0.5 1.0;
|
||||
offscale;
|
||||
}
|
||||
description { state: "on" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
rel1.offset: 4 4;
|
||||
rel2.offset: -5 4;
|
||||
align: 0.5 0.0;
|
||||
}
|
||||
}
|
||||
program {
|
||||
signal: "sendfile,progress,on"; source: "terminology";
|
||||
action: ACTION_STOP;
|
||||
target: "sendfile_progress_on";
|
||||
target: "sendfile_progress_off";
|
||||
}
|
||||
program {
|
||||
signal: "sendfile,progress,off"; source: "terminology";
|
||||
action: ACTION_STOP;
|
||||
target: "sendfile_progress_on";
|
||||
target: "sendfile_progress_off";
|
||||
}
|
||||
program { name: "sendfile_progress_on";
|
||||
signal: "sendfile,progress,on"; source: "terminology";
|
||||
in: 0.5 0.0;
|
||||
action: STATE_SET "on" 0.0;
|
||||
transition: DECELERATE 0.5;
|
||||
target: "sendfile_progress_clip";
|
||||
target: "terminology.sendfile.progress";
|
||||
}
|
||||
program { name: "sendfile_progress_off";
|
||||
signal: "sendfile,progress,off"; source: "terminology";
|
||||
action: STATE_SET "default" 0.0;
|
||||
transition: DECELERATE 0.5;
|
||||
target: "sendfile_progress_clip";
|
||||
target: "terminology.sendfile.progress";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// miniview
|
||||
part { name: "terminology.miniview"; type: SWALLOW;
|
||||
|
|
|
@ -47,6 +47,7 @@ typop_sources = ['tycommon.c', 'tycommon.h', 'typop.c']
|
|||
tyq_sources = ['tycommon.c', 'tycommon.h', 'tyq.c']
|
||||
tycat_sources = ['tycommon.c', 'tycommon.h', 'tycat.c', 'extns.c', 'extns.h']
|
||||
tyls_sources = ['extns.c', 'extns.h', 'tyls.c', 'tycommon.c', 'tycommon.h']
|
||||
tysend_sources = ['tycommon.c', 'tycommon.h', 'tysend.c']
|
||||
tyfuzz_sources = ['termptyesc.c', 'termptyesc.h',
|
||||
'termptysave.c', 'termptysave.h',
|
||||
'termptyops.c', 'termptyops.h',
|
||||
|
@ -94,6 +95,11 @@ executable('tyls',
|
|||
install: true,
|
||||
include_directories: config_dir,
|
||||
dependencies: terminology_dependencies)
|
||||
executable('tysend',
|
||||
tysend_sources,
|
||||
install: true,
|
||||
include_directories: config_dir,
|
||||
dependencies: terminology_dependencies)
|
||||
|
||||
if fuzzing
|
||||
executable('tyfuzz',
|
||||
|
|
196
src/bin/termio.c
196
src/bin/termio.c
|
@ -62,6 +62,13 @@ struct _Termio
|
|||
unsigned char dndobjdel : 1;
|
||||
} down;
|
||||
} link;
|
||||
struct {
|
||||
const char *file;
|
||||
FILE *f;
|
||||
double progress;
|
||||
unsigned long long total, size;
|
||||
Eina_Bool active : 1;
|
||||
} sendfile;
|
||||
Evas_Object *ctxpopup;
|
||||
int zoom_fontsize_start;
|
||||
int scroll;
|
||||
|
@ -4729,6 +4736,70 @@ _smart_cb_gest_zoom_abort(void *data, void *_event EINA_UNUSED)
|
|||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
Eina_Bool
|
||||
termio_file_send_ok(const Evas_Object *obj, const char *file)
|
||||
{
|
||||
Termio *sd = evas_object_smart_data_get(obj);
|
||||
Termpty *ty;
|
||||
|
||||
if (!sd) return EINA_FALSE;
|
||||
if (!file) return EINA_FALSE;
|
||||
ty = sd->pty;
|
||||
sd->sendfile.f = fopen(file, "w");
|
||||
if (sd->sendfile.f)
|
||||
{
|
||||
if (sd->sendfile.file) eina_stringshare_del(sd->sendfile.file);
|
||||
sd->sendfile.file = eina_stringshare_add(file);
|
||||
sd->sendfile.active = EINA_TRUE;
|
||||
termpty_write(ty, "k\n", 2);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
if (sd->sendfile.file) eina_stringshare_del(sd->sendfile.file);
|
||||
sd->sendfile.file = NULL;
|
||||
sd->sendfile.active = EINA_FALSE;
|
||||
termpty_write(ty, "n\n", 2);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
termio_file_send_cancel(const Evas_Object *obj)
|
||||
{
|
||||
Termio *sd = evas_object_smart_data_get(obj);
|
||||
Termpty *ty;
|
||||
|
||||
if (!sd) return;
|
||||
ty = sd->pty;
|
||||
if (!sd->sendfile.active) goto done;
|
||||
sd->sendfile.progress = 0.0;
|
||||
sd->sendfile.total = 0;
|
||||
sd->sendfile.size = 0;
|
||||
if (sd->sendfile.file)
|
||||
{
|
||||
ecore_file_unlink(sd->sendfile.file);
|
||||
eina_stringshare_del(sd->sendfile.file);
|
||||
sd->sendfile.file = NULL;
|
||||
}
|
||||
if (sd->sendfile.f)
|
||||
{
|
||||
fclose(sd->sendfile.f);
|
||||
sd->sendfile.f = NULL;
|
||||
}
|
||||
sd->sendfile.active = EINA_FALSE;
|
||||
done:
|
||||
termpty_write(ty, "n\n", 2);
|
||||
}
|
||||
|
||||
double
|
||||
termio_file_send_progress_get(const Evas_Object *obj)
|
||||
{
|
||||
Termio *sd = evas_object_smart_data_get(obj);
|
||||
|
||||
if (!sd) return 0.0;
|
||||
if (!sd->sendfile.active) return 0.0;
|
||||
return sd->sendfile.progress;
|
||||
}
|
||||
|
||||
/* {{{ Smart */
|
||||
|
||||
static void
|
||||
|
@ -5431,6 +5502,21 @@ _smart_del(Evas_Object *obj)
|
|||
evas_object_del(o);
|
||||
}
|
||||
if (sd->link.down.dndobj) evas_object_del(sd->link.down.dndobj);
|
||||
if (sd->sendfile.active)
|
||||
{
|
||||
if (sd->sendfile.file)
|
||||
{
|
||||
ecore_file_unlink(sd->sendfile.file);
|
||||
eina_stringshare_del(sd->sendfile.file);
|
||||
sd->sendfile.file = NULL;
|
||||
}
|
||||
if (sd->sendfile.f)
|
||||
{
|
||||
fclose(sd->sendfile.f);
|
||||
sd->sendfile.f = NULL;
|
||||
}
|
||||
sd->sendfile.active = EINA_FALSE;
|
||||
}
|
||||
keyin_compose_seq_reset(&sd->khdl);
|
||||
if (sd->sel_str) eina_stringshare_del(sd->sel_str);
|
||||
if (sd->preedit_str) eina_stringshare_del(sd->preedit_str);
|
||||
|
@ -5927,6 +6013,116 @@ _smart_pty_command(void *data)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (ty->cur_cmd[0] == 'f') // file...
|
||||
{
|
||||
if (ty->cur_cmd[1] == 'r') // receive
|
||||
{
|
||||
sd->sendfile.progress = 0.0;
|
||||
sd->sendfile.total = 0;
|
||||
sd->sendfile.size = 0;
|
||||
}
|
||||
else if (ty->cur_cmd[1] == 's') // file size
|
||||
{
|
||||
sd->sendfile.total = 0;
|
||||
sd->sendfile.size = atoll(&(ty->cur_cmd[2]));
|
||||
}
|
||||
else if (ty->cur_cmd[1] == 'd') // data packet
|
||||
{
|
||||
int pksum = atoi(&(ty->cur_cmd[2]));
|
||||
int sum;
|
||||
char *p = strchr(ty->cur_cmd, ' ');
|
||||
Eina_Bool valid = EINA_TRUE;
|
||||
|
||||
if (p)
|
||||
{
|
||||
Eina_Binbuf *bb = eina_binbuf_new();
|
||||
unsigned char v;
|
||||
int inp = 0;
|
||||
|
||||
if (bb)
|
||||
{
|
||||
p++;
|
||||
sum = 0;
|
||||
for (; *p; p++)
|
||||
{
|
||||
v = (unsigned char)(*p);
|
||||
sum += v;
|
||||
inp++;
|
||||
if ((v == 0x1b) || (v == 0x07))
|
||||
{
|
||||
p++;
|
||||
v = *p;
|
||||
inp++;
|
||||
sum += (unsigned char)(*p);
|
||||
if (*p == 0x01) v = 0x00;
|
||||
else if (*p == 0x02) v = 0xff;
|
||||
else valid = EINA_FALSE;
|
||||
}
|
||||
eina_binbuf_append_char(bb, v);
|
||||
}
|
||||
if ((valid) && (sum == pksum) && (sd->sendfile.active))
|
||||
{
|
||||
// write "ok" (k) to term
|
||||
size_t size = eina_binbuf_length_get(bb);
|
||||
|
||||
sd->sendfile.total += size;
|
||||
if (sd->sendfile.size > 0.0)
|
||||
{
|
||||
sd->sendfile.progress =
|
||||
(double)sd->sendfile.total /
|
||||
(double)sd->sendfile.size;
|
||||
evas_object_smart_callback_call
|
||||
(obj, "send,progress", NULL);
|
||||
}
|
||||
fwrite(eina_binbuf_string_get(bb), size, 1,
|
||||
sd->sendfile.f);
|
||||
termpty_write(ty, "k\n", 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// write "not valid" (n) to term
|
||||
if (sd->sendfile.file)
|
||||
{
|
||||
ecore_file_unlink(sd->sendfile.file);
|
||||
eina_stringshare_del(sd->sendfile.file);
|
||||
sd->sendfile.file = NULL;
|
||||
}
|
||||
if (sd->sendfile.f)
|
||||
{
|
||||
fclose(sd->sendfile.f);
|
||||
sd->sendfile.f = NULL;
|
||||
}
|
||||
sd->sendfile.active = EINA_FALSE;
|
||||
termpty_write(ty, "n\n", 2);
|
||||
evas_object_smart_callback_call
|
||||
(obj, "send,end", NULL);
|
||||
}
|
||||
eina_binbuf_free(bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ty->cur_cmd[1] == 'x') // exit data stream
|
||||
{
|
||||
if (sd->sendfile.active)
|
||||
{
|
||||
sd->sendfile.progress = 0.0;
|
||||
sd->sendfile.size = 0;
|
||||
if (sd->sendfile.file)
|
||||
{
|
||||
eina_stringshare_del(sd->sendfile.file);
|
||||
sd->sendfile.file = NULL;
|
||||
}
|
||||
if (sd->sendfile.f)
|
||||
{
|
||||
fclose(sd->sendfile.f);
|
||||
sd->sendfile.f = NULL;
|
||||
}
|
||||
sd->sendfile.active = EINA_FALSE;
|
||||
evas_object_smart_callback_call
|
||||
(obj, "send,end", NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
evas_object_smart_callback_call(obj, "command", (void *)ty->cur_cmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,9 @@ void termio_media_mute_set(Evas_Object *obj, Eina_Bool mute);
|
|||
void termio_media_visualize_set(Evas_Object *obj, Eina_Bool visualize);
|
||||
void termio_config_set(Evas_Object *obj, Config *config);
|
||||
Config *termio_config_get(const Evas_Object *obj);
|
||||
Eina_Bool termio_file_send_ok(const Evas_Object *obj, const char *file);
|
||||
void termio_file_send_cancel(const Evas_Object *obj);
|
||||
double termio_file_send_progress_get(const Evas_Object *obj);
|
||||
|
||||
Termpty *termio_pty_get(const Evas_Object *obj);
|
||||
Evas_Object * termio_miniview_get(const Evas_Object *obj);
|
||||
|
|
|
@ -46,7 +46,7 @@ main(int argc, char **argv)
|
|||
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) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
if (write(1, tbuf, strlen(tbuf) + 1) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ main(int argc, char **argv)
|
|||
{
|
||||
char tbuf[32];
|
||||
snprintf(tbuf, sizeof(tbuf), "%c}bt", 0x1b);
|
||||
if (write(0, tbuf, strlen(tbuf) + 1) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
if (write(1, tbuf, strlen(tbuf) + 1) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
return 0;
|
||||
}
|
||||
for (i = 1; i < argc; i++)
|
||||
|
@ -50,7 +50,7 @@ main(int argc, char **argv)
|
|||
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) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
if (write(1, tbuf, strlen(tbuf) + 1) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ prnt(const char *path, int w, int h, int mode)
|
|||
snprintf(buf, sizeof(buf), "%c}if#%i;%i;%s", 0x1b, w, h, path);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%c}is#%i;%i;%s", 0x1b, w, h, path);
|
||||
if (write(0, buf, strlen(buf) + 1) < 0) perror("write");
|
||||
if (write(1, buf, strlen(buf) + 1) < 0) perror("write");
|
||||
i = 0;
|
||||
line[i++] = 0x1b;
|
||||
line[i++] = '}';
|
||||
|
@ -113,7 +113,7 @@ prnt(const char *path, int w, int h, int mode)
|
|||
line[i++] = '\n';
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
if (write(0, line, i) < 0) perror("write");
|
||||
if (write(1, line, i) < 0) perror("write");
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
|
@ -336,7 +336,7 @@ main(int argc, char **argv)
|
|||
evas = ecore_evas_get(ee);
|
||||
echo_off();
|
||||
snprintf(buf, sizeof(buf), "%c}qs", 0x1b);
|
||||
if (write(0, buf, strlen(buf) + 1) < 0) perror("write");
|
||||
if (write(1, buf, strlen(buf) + 1) < 0) perror("write");
|
||||
if (scanf("%i;%i;%i;%i", &tw, &th, &cw, &ch) != 4 ||
|
||||
((tw <= 0) || (th <= 0) || (cw <= 1) || (ch <= 1)))
|
||||
{
|
||||
|
|
|
@ -765,7 +765,7 @@ main(int argc, char **argv)
|
|||
echo_off();
|
||||
snprintf(buf, sizeof(buf), "%c}qs", 0x1b);
|
||||
len = strlen(buf);
|
||||
if (write(0, buf, len + 1) < (signed)len + 1) perror("write");
|
||||
if (write(1, buf, len + 1) < (signed)len + 1) perror("write");
|
||||
if ((scanf("%i;%i;%i;%i", &tw, &th, &cw, &ch) != 4)
|
||||
|| (tw <= 0) || (th <= 0) || (cw <= 1) || (ch <= 1))
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ main(int argc, char **argv)
|
|||
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) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
if (write(1, tbuf, strlen(tbuf) + 1) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ main(int argc, char **argv)
|
|||
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) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
if (write(1, tbuf, strlen(tbuf) + 1) != (signed)(strlen(tbuf) + 1)) perror("write");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
#include "private.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <Eina.h>
|
||||
#include "tycommon.h"
|
||||
|
||||
static void
|
||||
print_usage(const char *argv0)
|
||||
{
|
||||
printf("Usage: %s"HELP_ARGUMENT_SHORT" FILE1 [FILE2 ...]\n"
|
||||
" Send file(s) to the terminal to save\n"
|
||||
HELP_ARGUMENT_DOC"\n"
|
||||
"\n",
|
||||
argv0);
|
||||
}
|
||||
|
||||
static struct termios told, tnew;
|
||||
|
||||
static int
|
||||
echo_off(void)
|
||||
{
|
||||
if (tcgetattr(0, &told) != 0) return -1;
|
||||
tnew = told;
|
||||
tnew.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||
tnew.c_oflag &= ~(OPOST);
|
||||
tnew.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
|
||||
tnew.c_cflag &= ~(CSIZE | PARENB);
|
||||
tnew.c_cflag |= CS8;
|
||||
tnew.c_cc[VMIN] = 1;
|
||||
tnew.c_cc[VTIME] = 0;
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
ON_NOT_RUNNING_IN_TERMINOLOGY_EXIT_1();
|
||||
ARGUMENT_ENTRY_CHECK(argc, argv, print_usage);
|
||||
|
||||
if (argc <= 1)
|
||||
{
|
||||
print_usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
echo_off();
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
char *path, buf[8192], tbuf[PATH_MAX * 3];
|
||||
unsigned char rawbuf[8192 + 128], rawbuf2[8192 + 128];
|
||||
int file_fd, pksize, pksum, bin, bout;
|
||||
|
||||
path = argv[i];
|
||||
snprintf(tbuf, sizeof(tbuf), "%c}fr%s", 0x1b, path);
|
||||
if (write(1, tbuf, strlen(tbuf) + 1) != (signed)(strlen(tbuf) + 1))
|
||||
goto err;
|
||||
file_fd = open(path, O_RDONLY);
|
||||
if (file_fd >= 0)
|
||||
{
|
||||
off_t off;
|
||||
|
||||
off = lseek(file_fd, 0, SEEK_END);
|
||||
lseek(file_fd, 0, SEEK_SET);
|
||||
snprintf(tbuf, sizeof(tbuf), "%c}fs%llu", 0x1b, (unsigned long long)off);
|
||||
if (write(1, tbuf, strlen(tbuf) + 1) != (signed)(strlen(tbuf) + 1))
|
||||
goto err;
|
||||
for (;;)
|
||||
{
|
||||
if (read(0, buf, 2) == 2)
|
||||
{
|
||||
if (buf[0] == 'k')
|
||||
{
|
||||
pksize = read(file_fd, rawbuf, 8192);
|
||||
|
||||
if (pksize > 0)
|
||||
{
|
||||
bout = 0;
|
||||
for (bin = 0; bin < pksize; bin++)
|
||||
{
|
||||
if (rawbuf[bin] == 0x00)
|
||||
{
|
||||
rawbuf2[bout++] = 0xff;
|
||||
rawbuf2[bout++] = 0x01;
|
||||
}
|
||||
else if (rawbuf[bin] == 0xff)
|
||||
{
|
||||
rawbuf2[bout++] = 0xff;
|
||||
rawbuf2[bout++] = 0x02;
|
||||
}
|
||||
else
|
||||
{
|
||||
rawbuf2[bout++] = rawbuf[bin];
|
||||
}
|
||||
}
|
||||
rawbuf2[bout] = 0;
|
||||
pksum = 0;
|
||||
for (bin = 0; bin < bout; bin++)
|
||||
{
|
||||
pksum += rawbuf2[bin];
|
||||
}
|
||||
snprintf(tbuf, sizeof(tbuf), "%c}fd%i ", 0x1b, pksum);
|
||||
if (write(1, tbuf, strlen(tbuf)) != (signed)(strlen(tbuf)))
|
||||
goto err;
|
||||
if (write(1, rawbuf2, bout + 1) != bout + 1)
|
||||
goto err;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else
|
||||
{
|
||||
echo_on();
|
||||
fprintf(stderr, "Send Fail\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else goto err;
|
||||
}
|
||||
close(file_fd);
|
||||
}
|
||||
snprintf(tbuf, sizeof(tbuf), "%c}fx", 0x1b);
|
||||
if (write(1, tbuf, strlen(tbuf) + 1) != (signed)(strlen(tbuf) + 1))
|
||||
goto err;
|
||||
tbuf[0] = 0;
|
||||
if (write(1, tbuf, 1) != 1)
|
||||
goto err;
|
||||
}
|
||||
echo_on();
|
||||
return 0;
|
||||
err:
|
||||
echo_on();
|
||||
return -1;
|
||||
}
|
314
src/bin/win.c
314
src/bin/win.c
|
@ -88,11 +88,17 @@ struct _Term
|
|||
Evas_Object *popmedia;
|
||||
Evas_Object *miniview;
|
||||
Evas_Object *sel;
|
||||
Evas_Object *sendfile_request;
|
||||
Evas_Object *sendfile_progress;
|
||||
Evas_Object *sendfile_progress_bar;
|
||||
Evas_Object *tabcount_spacer;
|
||||
Evas_Object *tab_spacer;
|
||||
Evas_Object *tab_region_base;
|
||||
Evas_Object *tab_region_bg;
|
||||
Eina_List *popmedia_queue;
|
||||
Ecore_Timer *sendfile_request_hide_timer;
|
||||
Ecore_Timer *sendfile_progress_hide_timer;
|
||||
const char *sendfile_dir;
|
||||
Media_Type poptype, mediatype;
|
||||
Tabbar tabbar;
|
||||
int step_x, step_y, min_w, min_h, req_w, req_h;
|
||||
|
@ -105,6 +111,9 @@ struct _Term
|
|||
unsigned char missed_bell : 1;
|
||||
unsigned char miniview_shown : 1;
|
||||
unsigned char popmedia_deleted : 1;
|
||||
|
||||
Eina_Bool sendfile_request_enabled : 1;
|
||||
Eina_Bool sendfile_progress_enabled : 1;
|
||||
};
|
||||
|
||||
typedef struct _Solo Solo;
|
||||
|
@ -3733,6 +3742,247 @@ _set_alpha(Config *config, const char *val, Eina_Bool save)
|
|||
if (save) config_save(config, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_sendfile_progress_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED)
|
||||
{
|
||||
Evas_Object *o = obj;
|
||||
Term *term = evas_object_data_get(o, "sendfile-progress-term");
|
||||
Ecore_Timer *t;
|
||||
|
||||
evas_object_data_del(o, "sendfile-progress-term");
|
||||
if (term)
|
||||
{
|
||||
term->sendfile_progress = NULL;
|
||||
term->sendfile_progress_bar = NULL;
|
||||
}
|
||||
t = evas_object_data_get(o, "sendfile-progress-timer");
|
||||
evas_object_data_del(o, "sendfile-progress-term");
|
||||
if (t) ecore_timer_del(t);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_sendfile_progress_reset(void *data)
|
||||
{
|
||||
Evas_Object *o = data;
|
||||
Term *term = evas_object_data_get(o, "sendfile-progress-term");
|
||||
|
||||
if (term)
|
||||
{
|
||||
term->sendfile_progress = NULL;
|
||||
term->sendfile_progress_bar = NULL;
|
||||
}
|
||||
evas_object_data_del(o, "sendfile-progress-timer");
|
||||
evas_object_data_del(o, "sendfile-progress-term");
|
||||
evas_object_del(o);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_sendfile_progress_hide_delay(void *data)
|
||||
{
|
||||
Term *term = data;
|
||||
Ecore_Timer *t;
|
||||
|
||||
term->sendfile_progress_hide_timer = NULL;
|
||||
if (!term->sendfile_progress_enabled) return EINA_FALSE;
|
||||
term->sendfile_progress_enabled = EINA_FALSE;
|
||||
edje_object_signal_emit(term->bg, "sendfile,progress,off", "terminology");
|
||||
t = evas_object_data_get(term->sendfile_progress, "sendfile-progress-timer");
|
||||
if (t) ecore_timer_del(t);
|
||||
t = ecore_timer_add(10.0, _sendfile_progress_reset, term->sendfile_progress);
|
||||
evas_object_data_set(term->sendfile_progress, "sendfile-progress-timer", t);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_sendfile_progress_hide(Term *term)
|
||||
{
|
||||
if (!term->sendfile_progress_enabled) return;
|
||||
if (term->sendfile_progress_hide_timer)
|
||||
ecore_timer_del(term->sendfile_progress_hide_timer);
|
||||
term->sendfile_progress_hide_timer =
|
||||
ecore_timer_add(0.5, _sendfile_progress_hide_delay, term);
|
||||
}
|
||||
|
||||
static void
|
||||
_sendfile_progress_cancel(void *data, Evas_Object *obj EINA_UNUSED, void *info EINA_UNUSED)
|
||||
{
|
||||
Term *term = data;
|
||||
|
||||
if (!term->sendfile_progress) return;
|
||||
termio_file_send_cancel(term->termio);
|
||||
_sendfile_progress_hide(term);
|
||||
}
|
||||
|
||||
static void
|
||||
_sendfile_progress(Term *term)
|
||||
{
|
||||
Evas_Object *o, *base;
|
||||
|
||||
if (term->sendfile_progress)
|
||||
{
|
||||
evas_object_del(term->sendfile_progress);
|
||||
term->sendfile_progress = NULL;
|
||||
}
|
||||
if (!edje_object_part_exists(term->bg, "terminology.sendfile.progress"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (term->sendfile_progress_hide_timer)
|
||||
{
|
||||
ecore_timer_del(term->sendfile_progress_hide_timer);
|
||||
term->sendfile_progress_hide_timer = NULL;
|
||||
}
|
||||
o = elm_box_add(term->wn->win);
|
||||
evas_object_data_set(o, "sendfile-progress-term", term);
|
||||
base = o;
|
||||
term->sendfile_progress = o;
|
||||
evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _sendfile_progress_del, NULL);
|
||||
elm_box_horizontal_set(o, EINA_TRUE);
|
||||
|
||||
o = elm_button_add(term->wn->win);
|
||||
elm_object_text_set(o, "Cancel");
|
||||
evas_object_smart_callback_add(o, "clicked", _sendfile_progress_cancel, term);
|
||||
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
elm_box_pack_end(base, o);
|
||||
evas_object_show(o);
|
||||
|
||||
o = elm_progressbar_add(term->wn->win);
|
||||
term->sendfile_progress_bar = o;
|
||||
elm_progressbar_unit_format_set(o, "%1.0f%%");
|
||||
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
||||
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
elm_box_pack_end(base, o);
|
||||
evas_object_show(o);
|
||||
|
||||
term->sendfile_progress_enabled = EINA_TRUE;
|
||||
edje_object_part_swallow(term->bg, "terminology.sendfile.progress", base);
|
||||
evas_object_show(base);
|
||||
edje_object_signal_emit(term->bg, "sendfile,progress,on", "terminology");
|
||||
}
|
||||
|
||||
static void
|
||||
_sendfile_request_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED)
|
||||
{
|
||||
Evas_Object *o = obj;
|
||||
Term *term = evas_object_data_get(o, "sendfile-request-term");
|
||||
Ecore_Timer *t;
|
||||
|
||||
evas_object_data_del(o, "sendfile-request-term");
|
||||
if (term) term->sendfile_request = NULL;
|
||||
t = evas_object_data_get(o, "sendfile-request-timer");
|
||||
evas_object_data_del(o, "sendfile-request-term");
|
||||
if (t) ecore_timer_del(t);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_sendfile_request_reset(void *data)
|
||||
{
|
||||
Evas_Object *o = data;
|
||||
Term *term = evas_object_data_get(o, "sendfile-request-term");
|
||||
|
||||
if (term) term->sendfile_request = NULL;
|
||||
evas_object_data_del(o, "sendfile-request-timer");
|
||||
evas_object_data_del(o, "sendfile-request-term");
|
||||
evas_object_del(o);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_sendfile_request_hide_delay(void *data)
|
||||
{
|
||||
Term *term = data;
|
||||
Ecore_Timer *t;
|
||||
|
||||
term->sendfile_request_hide_timer = NULL;
|
||||
if (!term->sendfile_request_enabled) return EINA_FALSE;
|
||||
term->sendfile_request_enabled = EINA_FALSE;
|
||||
edje_object_signal_emit(term->bg, "sendfile,request,off", "terminology");
|
||||
t = evas_object_data_get(term->sendfile_request, "sendfile-request-timer");
|
||||
if (t) ecore_timer_del(t);
|
||||
t = ecore_timer_add(10.0, _sendfile_request_reset, term->sendfile_request);
|
||||
evas_object_data_set(term->sendfile_request, "sendfile-request-timer", t);
|
||||
elm_object_focus_set(term->sendfile_request, EINA_FALSE);
|
||||
_term_focus(term);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_sendfile_request_hide(Term *term)
|
||||
{
|
||||
if (!term->sendfile_request_enabled) return;
|
||||
if (term->sendfile_request_hide_timer)
|
||||
ecore_timer_del(term->sendfile_request_hide_timer);
|
||||
term->sendfile_request_hide_timer =
|
||||
ecore_timer_add(0.2, _sendfile_request_hide_delay, term);
|
||||
}
|
||||
|
||||
static void
|
||||
_sendfile_request_done(void *data, Evas_Object *obj EINA_UNUSED, void *info)
|
||||
{
|
||||
Term *term = data;
|
||||
const char *path, *selpath = info;
|
||||
|
||||
if (!term->sendfile_request) return;
|
||||
|
||||
path = elm_fileselector_path_get(term->sendfile_request);
|
||||
eina_stringshare_replace(&term->sendfile_dir, path);
|
||||
|
||||
if (selpath)
|
||||
{
|
||||
_sendfile_progress(term);
|
||||
termio_file_send_ok(term->termio, selpath);
|
||||
}
|
||||
else termio_file_send_cancel(term->termio);
|
||||
_sendfile_request_hide(term);
|
||||
}
|
||||
|
||||
static void
|
||||
_sendfile_request(Term *term, const char *path)
|
||||
{
|
||||
Evas_Object *o;
|
||||
const char *p;
|
||||
|
||||
if (term->sendfile_request)
|
||||
{
|
||||
evas_object_del(term->sendfile_request);
|
||||
term->sendfile_request = NULL;
|
||||
}
|
||||
if (!edje_object_part_exists(term->bg, "terminology.sendfile.request"))
|
||||
{
|
||||
termio_file_send_cancel(term->termio);
|
||||
return;
|
||||
}
|
||||
if (term->sendfile_request_hide_timer)
|
||||
{
|
||||
ecore_timer_del(term->sendfile_request_hide_timer);
|
||||
term->sendfile_request_hide_timer = NULL;
|
||||
}
|
||||
o = elm_fileselector_add(term->wn->win);
|
||||
evas_object_data_set(o, "sendfile-request-term", term);
|
||||
term->sendfile_request = o;
|
||||
evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _sendfile_request_del, NULL);
|
||||
elm_fileselector_is_save_set(o, EINA_TRUE);
|
||||
elm_fileselector_expandable_set(o, EINA_FALSE);
|
||||
if (!term->sendfile_dir)
|
||||
{
|
||||
const char *dir = eina_environment_home_get();
|
||||
|
||||
if (dir) term->sendfile_dir = eina_stringshare_add(dir);
|
||||
}
|
||||
if (term->sendfile_dir) elm_fileselector_path_set(o, term->sendfile_dir);
|
||||
p = strrchr(path, '/');
|
||||
if (p) elm_fileselector_current_name_set(o, p + 1);
|
||||
else elm_fileselector_current_name_set(o, path);
|
||||
evas_object_smart_callback_add(o, "done", _sendfile_request_done, term);
|
||||
term->sendfile_request_enabled = EINA_TRUE;
|
||||
edje_object_part_swallow(term->bg, "terminology.sendfile.request", o);
|
||||
evas_object_show(o);
|
||||
edje_object_signal_emit(term->bg, "sendfile,request,on", "terminology");
|
||||
elm_object_focus_set(term->termio, EINA_FALSE);
|
||||
elm_object_focus_set(o, EINA_TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_command(void *data,
|
||||
Evas_Object *_obj EINA_UNUSED,
|
||||
|
@ -3749,7 +3999,7 @@ _cb_command(void *data,
|
|||
}
|
||||
else if (cmd[1] == 'q') // queue it to display after current one
|
||||
{
|
||||
_popmedia_queue_add(term, cmd + 2);
|
||||
_popmedia_queue_add(term, cmd + 2);
|
||||
}
|
||||
}
|
||||
else if (cmd[0] == 'b') // set background
|
||||
|
@ -3793,6 +4043,19 @@ _cb_command(void *data,
|
|||
else if (cmd[1] == 'p') // permanent
|
||||
_set_alpha(termio_config_get(term->termio), cmd + 2, EINA_TRUE);
|
||||
}
|
||||
else if (cmd[0] == 'f') // file...
|
||||
{
|
||||
if (cmd[1] == 'r') // receive
|
||||
{
|
||||
_sendfile_request(term, cmd + 2);
|
||||
}
|
||||
else if (cmd[1] == 'd') // data packet
|
||||
{
|
||||
}
|
||||
else if (cmd[1] == 'x') // exit data stream
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3872,6 +4135,28 @@ _cb_icon(void *data,
|
|||
elm_win_icon_name_set(term->wn->win, termio_icon_name_get(term->termio));
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_send_progress(void *data,
|
||||
Evas_Object *_obj EINA_UNUSED,
|
||||
void *_event EINA_UNUSED)
|
||||
{
|
||||
Term *term = data;
|
||||
|
||||
elm_progressbar_value_set(term->sendfile_progress_bar,
|
||||
termio_file_send_progress_get(term->termio));
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_send_end(void *data,
|
||||
Evas_Object *_obj EINA_UNUSED,
|
||||
void *_event EINA_UNUSED)
|
||||
{
|
||||
Term *term = data;
|
||||
if (!term->sendfile_progress) return;
|
||||
_sendfile_request_hide(term);
|
||||
_sendfile_progress_hide(term);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_cb_cmd_focus(void *data)
|
||||
{
|
||||
|
@ -4227,6 +4512,31 @@ _term_free(Term *term)
|
|||
{
|
||||
const char *s;
|
||||
|
||||
if (term->sendfile_request)
|
||||
{
|
||||
evas_object_del(term->sendfile_request);
|
||||
term->sendfile_request = NULL;
|
||||
}
|
||||
if (term->sendfile_progress)
|
||||
{
|
||||
evas_object_del(term->sendfile_progress);
|
||||
term->sendfile_progress = NULL;
|
||||
}
|
||||
if (term->sendfile_request_hide_timer)
|
||||
{
|
||||
ecore_timer_del(term->sendfile_request_hide_timer);
|
||||
term->sendfile_request_hide_timer = NULL;
|
||||
}
|
||||
if (term->sendfile_progress_hide_timer)
|
||||
{
|
||||
ecore_timer_del(term->sendfile_progress_hide_timer);
|
||||
term->sendfile_progress_hide_timer = NULL;
|
||||
}
|
||||
if (term->sendfile_dir)
|
||||
{
|
||||
eina_stringshare_del(term->sendfile_dir);
|
||||
term->sendfile_dir = NULL;
|
||||
}
|
||||
EINA_LIST_FREE(term->popmedia_queue, s)
|
||||
{
|
||||
eina_stringshare_del(s);
|
||||
|
@ -4616,6 +4926,8 @@ term_new(Win *wn, Config *config, const char *cmd,
|
|||
evas_object_smart_callback_add(o, "split,v", _cb_split_v, term);
|
||||
evas_object_smart_callback_add(o, "title,change", _cb_title, term);
|
||||
evas_object_smart_callback_add(o, "icon,change", _cb_icon, term);
|
||||
evas_object_smart_callback_add(o, "send,progress", _cb_send_progress, term);
|
||||
evas_object_smart_callback_add(o, "send,end", _cb_send_end, term);
|
||||
evas_object_show(o);
|
||||
|
||||
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
|
||||
|
|
Loading…
Reference in New Issue