src/dietline.c
author pancake
Thu Dec 10 11:06:39 2009 +0100 (2009-12-10)
changeset 1251 87579f8c5087
parent 1242 b55faadb4a4a
child 1252 59fa18b1068f
permissions -rw-r--r--
* Fix '? eip > a' bug (drop spaces in flag checks)
* Some code cleanup (-100LOC)
* Fixes in scriptedit and ruby plugins
* FIx declaration of UXX_MAX
* Added VE command to edit notes on current binary
youterm@26
     1
/*
pancake@1242
     2
 * Copyright (C) 2007, 2008, 2009
youterm@55
     3
 *       pancake <youterm.com>
youterm@26
     4
 *
youterm@26
     5
 * dietline is free software; you can redistribute it and/or modify
youterm@26
     6
 * it under the terms of the GNU General Public License as published by
youterm@26
     7
 * the Free Software Foundation; either version 2 of the License, or
youterm@26
     8
 * (at your option) any later version.
youterm@26
     9
 *
youterm@26
    10
 * dietline is distributed in the hope that it will be useful,
youterm@26
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
youterm@26
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
youterm@26
    13
 * GNU General Public License for more details.
youterm@26
    14
 *
youterm@26
    15
 * You should have received a copy of the GNU General Public License
youterm@26
    16
 * along with dietline; if not, write to the Free Software
youterm@26
    17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
youterm@26
    18
 *
youterm@26
    19
 */
youterm@26
    20
youterm@219
    21
#include "dietline.h"
youterm@219
    22
youterm@26
    23
/* dietline is a lighweight and portable library similar to GNU readline */
youterm@26
    24
youterm@27
    25
#if RADARE_CORE
youterm@26
    26
#include "main.h"
youterm@27
    27
#else
youterm@184
    28
static void cons_set_raw(int b);
youterm@184
    29
static int cons_get_real_columns();
youterm@27
    30
#define __UNIX__ 1
youterm@27
    31
#endif
youterm@27
    32
youterm@26
    33
#include <string.h>
youterm@26
    34
#include <stdlib.h>
youterm@26
    35
youterm@26
    36
#if __WINDOWS__
youterm@26
    37
#include <windows.h>
youterm@26
    38
#else
youterm@52
    39
#include <sys/ioctl.h>
youterm@26
    40
#include <termios.h>
youterm@26
    41
#include <signal.h>
youterm@26
    42
#endif
youterm@26
    43
youterm@26
    44
/* line input */
youterm@219
    45
int dl_echo = 1;
youterm@26
    46
const char *dl_prompt = "> ";
youterm@219
    47
const char *dl_clipboard = NULL;
youterm@219
    48
static char *dl_nullstr = "";
youterm@26
    49
static char dl_buffer[DL_BUFSIZE];
youterm@26
    50
static int dl_buffer_len = 0;
youterm@26
    51
static int dl_buffer_idx = 0;
youterm@26
    52
youterm@219
    53
/* autocompletion callback */
youterm@219
    54
char **(*dl_callback)(const char *text, int start, int end) = NULL;
youterm@219
    55
youterm@26
    56
/* history */
youterm@219
    57
char **dl_history = NULL;
youterm@26
    58
int dl_histsize = DL_HISTSIZE;
youterm@26
    59
int dl_histidx = 0;
youterm@26
    60
int dl_autosave = 0; // TODO
youterm@26
    61
int dl_disable = 0; // TODO use fgets..no autocompletion
youterm@26
    62
youterm@87
    63
// TODO : FULL READLINE COMPATIBILITY
youterm@87
    64
// rl_attempted_completion_function = rad_autocompletion;
youterm@87
    65
// char **rad_autocompletion(const char *text, int start, int end)
youterm@87
    66
// return  matches = rl_completion_matches (text, rad_offset_matches);
youterm@87
    67
youterm@219
    68
int dl_readchar()
youterm@26
    69
{
youterm@26
    70
	char buf[2];
youterm@26
    71
#if __WINDOWS__
youterm@26
    72
	LPDWORD out;
youterm@26
    73
	BOOL ret;
pancake@1245
    74
	DWORD mode;
youterm@26
    75
	HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
youterm@26
    76
youterm@26
    77
	GetConsoleMode(h, &mode);
youterm@26
    78
	SetConsoleMode(h, 0); // RAW
youterm@26
    79
	ret = ReadConsole(h, buf,1, &out, NULL);
youterm@55
    80
	if (!ret) {
youterm@55
    81
		// wine hack-around
youterm@55
    82
		if (read(0,buf,1) == 1)
youterm@55
    83
			return buf[0];
youterm@26
    84
		return -1;
youterm@55
    85
	}
youterm@26
    86
	SetConsoleMode(h, mode);
youterm@26
    87
#else
youterm@219
    88
	int ret = read(0,buf,1);
youterm@219
    89
	if (ret <1)
youterm@55
    90
		return -1;
youterm@26
    91
#endif
youterm@26
    92
	return buf[0];
youterm@26
    93
}
youterm@26
    94
youterm@509
    95
/* scripting */
youterm@509
    96
youterm@509
    97
#define BLOCK 4096
youterm@509
    98
static char *labels = NULL;
pancake@907
    99
static unsigned int size = 0;
pancake@907
   100
static unsigned int lsize = 0;
youterm@509
   101
pancake@1242
   102
static int label_get(const char *name)
youterm@509
   103
{
youterm@509
   104
	int i, n;
youterm@509
   105
	for(i=0;i<size;i++) {
youterm@509
   106
		if (!strcmp(name, labels+i+4)) {
youterm@509
   107
			memcpy(&n, labels+i, 4);
youterm@509
   108
			return n;
youterm@509
   109
		}
youterm@509
   110
		i+=strlen(labels+i+4)+4;
youterm@509
   111
	}
youterm@509
   112
	return -1;
youterm@509
   113
}
youterm@509
   114
youterm@509
   115
static void label_add (const char *str) {
pancake@907
   116
	unsigned int size = dl_histidx;
pancake@907
   117
	unsigned int len = strlen(str)-1;
youterm@542
   118
pancake@907
   119
	//eprintf("New label(%s)\n",str);
youterm@509
   120
	memset(labels+lsize+4, '\0', BLOCK-((lsize+len+4)%BLOCK));
youterm@509
   121
	memcpy(labels+lsize, &size, 4);
youterm@509
   122
	memcpy(labels+lsize+4, str, len);
youterm@509
   123
	lsize+=len+4+1;
youterm@509
   124
}
youterm@509
   125
youterm@509
   126
void dl_label_show()
youterm@509
   127
{
pancake@907
   128
	unsigned int i, p, n = 0;
youterm@509
   129
	for(i=0;i<lsize;i++,n++) {
youterm@509
   130
		memcpy(&p, labels+i, 4);
youterm@542
   131
		printf(" %03d %03d  %s\n", i, p, labels+i+4);
youterm@509
   132
		i+=strlen(labels+i+4)+4;
youterm@509
   133
	}
youterm@509
   134
}
youterm@509
   135
youterm@509
   136
static void label_reset()
youterm@509
   137
{
youterm@509
   138
	lsize = 0;
youterm@509
   139
	free(labels);
youterm@509
   140
	labels = NULL;
youterm@509
   141
}
youterm@509
   142
youterm@509
   143
static int is_label(const char *str)
youterm@509
   144
{
@788
   145
	/* crappy hack */
@788
   146
	return 0;
@788
   147
youterm@542
   148
	if (str[0]=='\0')
youterm@542
   149
		return 0;
youterm@509
   150
	if (str[strlen(str)-1]==':') {
youterm@542
   151
		if (str[0]==':') {
youterm@509
   152
			dl_label_show();
youterm@509
   153
			return 2;
youterm@509
   154
		}
youterm@509
   155
		return 1;
youterm@509
   156
	}
youterm@509
   157
	return 0;
youterm@509
   158
}
youterm@26
   159
youterm@26
   160
/* history stuff */
youterm@509
   161
youterm@509
   162
int dl_hist_label(const char *label, void (*cb)(const char*))
youterm@509
   163
{
@590
   164
	int i;
youterm@787
   165
#if 1
youterm@787
   166
	/* labelling stuff */
youterm@509
   167
	if (label[0]=='.') {
youterm@509
   168
		if (!is_label(label+1))
youterm@509
   169
			return 0;
youterm@509
   170
	} else {
youterm@509
   171
		switch(is_label(label)) {
youterm@509
   172
		case 0:
youterm@509
   173
		case 2:
youterm@509
   174
			return 0;
youterm@509
   175
		}
youterm@509
   176
	}
youterm@509
   177
youterm@509
   178
	i = label_get(label);
youterm@509
   179
	if (i == -1) {
youterm@509
   180
		label_add(label);
youterm@509
   181
		return 1;
youterm@509
   182
	}
youterm@787
   183
#endif
youterm@509
   184
	if (dl_history != NULL)
pancake@1242
   185
	for(i=0; i<dl_histsize; i++) {
youterm@509
   186
		if (dl_history[i] == NULL)
youterm@509
   187
			break;
@590
   188
		fprintf(stderr, "%s\n", dl_history[i]);
youterm@509
   189
		if (cb != NULL)
youterm@509
   190
			cb(dl_history[i]);
@590
   191
		else	fprintf(stderr, "%s\n", dl_history[i]);
youterm@509
   192
	}
youterm@509
   193
youterm@509
   194
	return 1;
youterm@509
   195
}
youterm@509
   196
youterm@26
   197
int dl_hist_add(const char *line)
youterm@26
   198
{
youterm@345
   199
#if HAVE_LIB_READLINE
youterm@345
   200
	add_history(line);
youterm@542
   201
#endif
youterm@107
   202
	if (dl_histidx>=dl_histsize)
youterm@107
   203
		dl_histidx = 0; // workaround
youterm@107
   204
	if (*line) { // && dl_histidx < dl_histsize) {
youterm@26
   205
		dl_history[dl_histidx++] = strdup(line);
youterm@26
   206
		return 1;
youterm@26
   207
	}
youterm@26
   208
	return 0;
youterm@542
   209
//#endif
youterm@26
   210
}
youterm@26
   211
youterm@26
   212
int dl_hist_up()
youterm@26
   213
{
youterm@26
   214
	if (dl_histidx>0) {
youterm@26
   215
		strncpy(dl_buffer, dl_history[--dl_histidx], DL_BUFSIZE-1);
youterm@82
   216
		dl_buffer_idx=
youterm@26
   217
		dl_buffer_len = strlen(dl_buffer);
youterm@26
   218
		return 1;
youterm@26
   219
	}
youterm@26
   220
	return 0;
youterm@26
   221
}
youterm@26
   222
youterm@26
   223
int dl_hist_down()
youterm@26
   224
{
youterm@26
   225
	dl_buffer_idx=0;
youterm@26
   226
	if (dl_histidx<dl_histsize) {
youterm@82
   227
		if (dl_history[dl_histidx] == NULL) {
youterm@82
   228
			dl_buffer[0]='\0';
youterm@82
   229
			dl_buffer_idx = dl_buffer_len = 0;
youterm@26
   230
			return 0;
youterm@82
   231
		}
youterm@26
   232
		strncpy(dl_buffer, dl_history[dl_histidx++], DL_BUFSIZE-1);
youterm@82
   233
		dl_buffer_idx=
youterm@26
   234
		dl_buffer_len = strlen(dl_buffer);
youterm@26
   235
		return 1;
youterm@26
   236
	}
youterm@26
   237
	return 0;
youterm@26
   238
}
youterm@26
   239
youterm@219
   240
int dl_hist_list()
youterm@219
   241
{
@297
   242
	int i = 0;
youterm@219
   243
youterm@219
   244
	if (dl_history != NULL)
youterm@219
   245
	for(i=0;i<dl_histsize; i++) {
youterm@219
   246
		if (dl_history[i] == NULL)
youterm@219
   247
			break;
youterm@219
   248
		printf("%.3d  %s\n", i, dl_history[i]);
youterm@219
   249
	}
youterm@263
   250
youterm@263
   251
	return i;
youterm@219
   252
}
youterm@219
   253
youterm@26
   254
int dl_hist_free()
youterm@26
   255
{
youterm@26
   256
	int i;
youterm@219
   257
	if (dl_history != NULL)
youterm@219
   258
	for(i=0;i<dl_histsize; i++) {
youterm@26
   259
		free(dl_history[i]);
youterm@26
   260
		dl_history[i] = NULL;
youterm@26
   261
	}
youterm@26
   262
	return dl_histidx=0, dl_histsize;
youterm@26
   263
}
youterm@26
   264
youterm@26
   265
void dl_free()
youterm@26
   266
{
youterm@26
   267
	printf("Bye!\n");
youterm@26
   268
	dl_hist_free();
@590
   269
	label_reset();
youterm@26
   270
	free(dl_history);
youterm@26
   271
}
youterm@26
   272
youterm@26
   273
/* load history from file. if file == NULL load from ~/.<prg>.history or so */
youterm@26
   274
int dl_hist_load(const char *file)
youterm@26
   275
{
youterm@354
   276
#if HAVE_LIB_READLINE
youterm@354
   277
	rad_readline_init();
youterm@354
   278
	return 0;
youterm@354
   279
#else
youterm@107
   280
	char buf[1024];
youterm@107
   281
	FILE *fd;
youterm@107
   282
pancake@1201
   283
	snprintf(buf, 1023, "%s/%s", get_home_directory(), file);
youterm@107
   284
	fd = fopen(buf, "r");
youterm@107
   285
	if (fd == NULL)
youterm@107
   286
		return 0;
youterm@107
   287
youterm@107
   288
	fgets(buf, 1023, fd);
youterm@107
   289
	while (!feof(fd)) {
youterm@107
   290
		buf[strlen(buf)-1]='\0';
youterm@107
   291
		dl_hist_add(buf);
youterm@107
   292
		fgets(buf, 1023, fd);
youterm@107
   293
	}
youterm@107
   294
	fclose(fd);
youterm@107
   295
youterm@107
   296
	return 1;
youterm@354
   297
#endif
youterm@26
   298
}
youterm@26
   299
youterm@26
   300
int dl_hist_save(const char *file)
youterm@26
   301
{
youterm@375
   302
#if HAVE_LIB_READLINE
youterm@375
   303
	rad_readline_finish();
youterm@375
   304
#else
youterm@107
   305
	char buf[1024];
youterm@107
   306
	FILE *fd;
youterm@107
   307
	int i;
youterm@107
   308
pancake@1201
   309
	snprintf(buf, 1023, "%s/%s", get_home_directory(), file);
@148
   310
	fd = fopen(buf, "w");
youterm@107
   311
	if (fd == NULL)
youterm@107
   312
		return 0;
youterm@107
   313
	for(i=0;i<dl_histidx;i++) {
youterm@107
   314
		fputs(dl_history[i], fd);
youterm@107
   315
		fputs("\n", fd);
youterm@107
   316
	}
youterm@107
   317
	fclose(fd);
youterm@107
   318
	
youterm@107
   319
	return 1;
youterm@375
   320
#endif
youterm@107
   321
}
youterm@107
   322
youterm@107
   323
int dl_hist_chop(const char *file, int limit)
youterm@107
   324
{
youterm@107
   325
	/* TODO */
youterm@72
   326
	return 0;
youterm@26
   327
}
youterm@26
   328
youterm@26
   329
/* initialize history stuff */
youterm@26
   330
int dl_init()
youterm@26
   331
{
@348
   332
#if HAVE_LIB_READLINE
@348
   333
	rad_readline_init();
@348
   334
#endif
youterm@509
   335
	if (labels==NULL)
youterm@509
   336
		labels = malloc(BLOCK);
youterm@26
   337
	dl_history = (char **)malloc(dl_histsize*sizeof(char *));
youterm@72
   338
	if (dl_history==NULL)
youterm@72
   339
		return 0;
youterm@219
   340
	memset(dl_history, '\0', dl_histsize*sizeof(char *));
youterm@26
   341
	dl_histidx = 0;
youterm@219
   342
	dl_histsize = DL_HISTSIZE;
youterm@219
   343
	dl_histidx = 0;
youterm@219
   344
	dl_autosave = 0;
youterm@219
   345
	dl_disable = 0;
youterm@72
   346
	return 1;
youterm@26
   347
}
youterm@26
   348
youterm@26
   349
/* test */
youterm@26
   350
int dl_printchar()
youterm@26
   351
{
youterm@26
   352
	unsigned char buf[10];
youterm@26
   353
youterm@184
   354
	cons_set_raw(1);
youterm@26
   355
	buf[0]=dl_readchar();
youterm@26
   356
youterm@26
   357
	switch(buf[0]) {
youterm@26
   358
		case 226:
youterm@26
   359
		case 197:
youterm@26
   360
		case 195:
youterm@26
   361
		case 194:
youterm@26
   362
			buf[0] = dl_readchar();
youterm@26
   363
			printf("unicode-%02x-%02x\n", buf[0],buf[1]);
youterm@26
   364
			break;
youterm@115
   365
		case 8: // wtf is 127?
youterm@26
   366
		case 127: printf("backspace\n"); break;
youterm@26
   367
		case 32: printf("space\n"); break;
youterm@26
   368
		case 27:
youterm@26
   369
			read(0, buf, 5);
youterm@26
   370
			printf("esc-%02x-%02x-%02x-%02x\n",
youterm@26
   371
					buf[0],buf[1],buf[2],buf[3]);
youterm@26
   372
			break;
youterm@26
   373
		case 12: printf("^L\n"); break;
youterm@26
   374
		case 13: printf("intro\n"); break;
youterm@82
   375
		case 18: printf("^R\n"); break;
youterm@26
   376
		case 9: printf("tab\n"); break;
youterm@26
   377
		case 3: printf("control-c\n"); break;
youterm@26
   378
		case 0: printf("control-space\n"); break;
youterm@26
   379
		default:
youterm@26
   380
			printf("(code:%d)\n", buf[0]);
youterm@26
   381
			break;
youterm@26
   382
	}
youterm@26
   383
youterm@184
   384
	cons_set_raw(0);
youterm@263
   385
youterm@263
   386
	return buf[0];
youterm@26
   387
}
youterm@26
   388
youterm@26
   389
/* main readline function */
youterm@107
   390
char *dl_readline(int argc, const char **argv)
youterm@26
   391
{
youterm@26
   392
	int buf[10];
@297
   393
	int i, len = 0;
@297
   394
	int opt = 0;
youterm@184
   395
	int columns = cons_get_real_columns()-2;
youterm@26
   396
youterm@26
   397
	dl_buffer_idx = dl_buffer_len = 0;
youterm@30
   398
	dl_buffer[0]='\0';
youterm@26
   399
youterm@494
   400
#if RADARE_CORE
youterm@477
   401
	dl_echo = config.verbose;
youterm@494
   402
#endif
youterm@477
   403
youterm@26
   404
	if (dl_disable) {
youterm@26
   405
		dl_buffer[0]='\0';
youterm@26
   406
		fgets(dl_buffer, DL_BUFSIZE-1, stdin);
youterm@26
   407
		dl_buffer[strlen(dl_buffer)] = '\0';
youterm@26
   408
		return (*dl_buffer)? dl_buffer : NULL;
youterm@26
   409
	}
youterm@26
   410
youterm@26
   411
	memset(&buf,0,sizeof buf);
youterm@184
   412
	cons_set_raw(1);
youterm@26
   413
youterm@219
   414
	if (dl_echo) {
youterm@219
   415
		printf("%s", dl_prompt);
youterm@219
   416
		fflush(stdout);
youterm@219
   417
	}
youterm@26
   418
youterm@30
   419
#if __UNIX__
youterm@30
   420
	if (feof(stdin))
youterm@30
   421
		return NULL;
youterm@30
   422
#endif
youterm@30
   423
youterm@26
   424
	while(1) {
youterm@219
   425
#if 0
youterm@26
   426
		if (dl_echo) {
youterm@26
   427
			printf("  (");
youterm@26
   428
			for(i=1;i<argc;i++) {
youterm@26
   429
				if (dl_buffer_len==0||!strncmp(argv[i], dl_buffer, dl_buffer_len)) {
youterm@26
   430
					len+=strlen(argv[i])+1;
youterm@26
   431
					if (len+dl_buffer_len+4 >= columns) break;
youterm@26
   432
					printf("%s ", argv[i]);
youterm@26
   433
				}
youterm@26
   434
			}
youterm@26
   435
			printf(")");
youterm@26
   436
			fflush(stdout);
youterm@26
   437
		}
youterm@219
   438
#endif
youterm@26
   439
youterm@26
   440
		dl_buffer[dl_buffer_len]='\0';
youterm@26
   441
		buf[0] = dl_readchar();
youterm@52
   442
		
pancake@402
   443
//		printf("\x1b[K\r");
youterm@184
   444
		columns = cons_get_real_columns()-2;
youterm@219
   445
		if (columns <1)
youterm@219
   446
			columns = 40;
youterm@477
   447
		if (dl_echo)
youterm@26
   448
		printf("\r%*c\r", columns, ' ');
youterm@26
   449
youterm@26
   450
		switch(buf[0]) {
youterm@55
   451
			case -1:
youterm@55
   452
				return NULL;
youterm@84
   453
			case 0: // control-space
youterm@84
   454
				/* ignore atm */
youterm@84
   455
				break;
youterm@26
   456
			case 1: // ^A
youterm@26
   457
				dl_buffer_idx = 0;
youterm@26
   458
				break;
youterm@26
   459
			case 5: // ^E
youterm@26
   460
				dl_buffer_idx = dl_buffer_len;
youterm@26
   461
				break;
youterm@26
   462
			case 3: // ^C 
youterm@477
   463
				if (dl_echo)
youterm@477
   464
					printf("\n^C\n");
youterm@26
   465
				dl_buffer[dl_buffer_idx = dl_buffer_len = 0] = '\0';
youterm@26
   466
				goto _end;
youterm@26
   467
			case 4: // ^D
youterm@477
   468
				if (dl_echo)
youterm@477
   469
					printf("^D\n");
youterm@26
   470
				if (!dl_buffer[0]) { /* eof */
youterm@184
   471
					cons_set_raw(0);
youterm@26
   472
					return NULL;
youterm@26
   473
				}
youterm@26
   474
				break;
youterm@219
   475
			case 10: // ^J -- ignore
youterm@219
   476
				return dl_buffer;
youterm@219
   477
			case 11: // ^K -- ignore
youterm@219
   478
				break;
youterm@26
   479
			case 19: // ^S -- backspace
youterm@26
   480
				dl_buffer_idx = dl_buffer_idx?dl_buffer_idx-1:0;
youterm@26
   481
				break;
youterm@26
   482
			case 12: // ^L -- right
youterm@26
   483
				dl_buffer_idx = dl_buffer_idx<dl_buffer_len?dl_buffer_idx+1:dl_buffer_len;
youterm@477
   484
				if (dl_echo)
youterm@477
   485
					printf("\x1b[2J\x1b[0;0H");
youterm@110
   486
				fflush(stdout);
youterm@26
   487
				break;
youterm@219
   488
			case 21: // ^U - cut
youterm@219
   489
				dl_clipboard = strdup(dl_buffer);
youterm@219
   490
				dl_buffer[0]='\0';
youterm@219
   491
				dl_buffer_len = 0;
youterm@219
   492
				dl_buffer_idx = 0;
youterm@219
   493
				break;
youterm@84
   494
			case 23: // ^W
youterm@26
   495
				if (dl_buffer_idx>0) {
youterm@84
   496
					for(i=dl_buffer_idx-1;i&&dl_buffer[i]==' ';i--);
youterm@228
   497
					for(;i&&dl_buffer[i]!=' ';i--);
youterm@228
   498
					for(;i>0&&dl_buffer[i]==' ';i--);
youterm@228
   499
					if (i>1) {
youterm@228
   500
						if (dl_buffer[i+1]==' ')
youterm@84
   501
						i+=2;
youterm@228
   502
					} else if (i<0) i=0;
youterm@26
   503
					strcpy(dl_buffer+i, dl_buffer+dl_buffer_idx);
youterm@26
   504
					dl_buffer_len = strlen(dl_buffer);
youterm@110
   505
					dl_buffer_idx = i;
youterm@26
   506
				}
youterm@26
   507
				break;
youterm@219
   508
			case 25: // ^Y - paste
youterm@219
   509
				if (dl_clipboard != NULL) {
youterm@219
   510
					dl_buffer_len += strlen(dl_clipboard);
youterm@219
   511
					// TODO: support endless strings
youterm@219
   512
					if (dl_buffer_len < DL_BUFSIZE) {
youterm@219
   513
						dl_buffer_idx = dl_buffer_len;
youterm@219
   514
						strcat(dl_buffer, dl_clipboard);
youterm@219
   515
					} else dl_buffer_len -= strlen(dl_clipboard);
youterm@219
   516
				}
youterm@219
   517
				break;
youterm@26
   518
			case 16:
youterm@26
   519
				dl_hist_up();
youterm@26
   520
				break;
youterm@26
   521
			case 14:
youterm@26
   522
				dl_hist_down();
youterm@26
   523
				break;
youterm@26
   524
			case 27: //esc-5b-41-00-00
youterm@26
   525
				buf[0] = dl_readchar();
youterm@26
   526
				buf[1] = dl_readchar();
youterm@26
   527
				if (buf[0]==0x5b) {
youterm@26
   528
					switch(buf[1]) {
youterm@26
   529
					case 0x33: // supr
youterm@26
   530
						if (dl_buffer_idx<dl_buffer_len)
youterm@26
   531
							strcpy(dl_buffer, dl_buffer+1);
youterm@26
   532
						break;
youterm@26
   533
					/* arrows */
youterm@26
   534
					case 0x41:
youterm@26
   535
						dl_hist_up();
youterm@26
   536
						break;
youterm@26
   537
					case 0x42:
youterm@26
   538
						dl_hist_down();
youterm@26
   539
						break;
youterm@26
   540
					case 0x43:
youterm@26
   541
						dl_buffer_idx = dl_buffer_idx<dl_buffer_len?dl_buffer_idx+1:dl_buffer_len;
youterm@26
   542
						break;
youterm@26
   543
					case 0x44:
youterm@26
   544
						dl_buffer_idx = dl_buffer_idx?dl_buffer_idx-1:0;
youterm@26
   545
						break;
youterm@26
   546
					}
youterm@26
   547
				}
youterm@26
   548
youterm@26
   549
				break;
youterm@26
   550
			case 8:
youterm@26
   551
			case 127:
youterm@26
   552
				if (dl_buffer_idx < dl_buffer_len) {
youterm@26
   553
					if (dl_buffer_idx>0) {
youterm@26
   554
						dl_buffer_idx--;
youterm@26
   555
						memcpy(dl_buffer+dl_buffer_idx, dl_buffer+dl_buffer_idx+1,strlen(dl_buffer+dl_buffer_idx));
youterm@26
   556
					}
youterm@26
   557
				} else {
youterm@26
   558
					dl_buffer_idx = --dl_buffer_len;
youterm@26
   559
					if (dl_buffer_len<0) dl_buffer_len=0;
youterm@26
   560
					dl_buffer[dl_buffer_len]='\0';
youterm@26
   561
				}
youterm@115
   562
				if (dl_buffer_idx<0)
youterm@115
   563
					dl_buffer_idx = 0;
youterm@26
   564
				break;
youterm@26
   565
			case 9:// tab
youterm@26
   566
				/* autocomplete */
youterm@26
   567
				// XXX does not autocompletes correctly
youterm@26
   568
				// XXX needs to check if valid results have the same prefix (from 1 to N)
youterm@219
   569
				if (dl_callback != NULL) {
youterm@263
   570
					//const char *from = strrchr(dl_buffer, ' ');
youterm@263
   571
					//char **res = dl_callback(dl_buffer, (from==NULL)?dl_buffer_idx:from-dl_buffer, dl_buffer_len);
youterm@219
   572
					/* TODO: manage res */
youterm@219
   573
				} else {
youterm@219
   574
					if (dl_buffer_idx>0)
youterm@219
   575
					for(i=1,opt=0;i<argc;i++)
youterm@219
   576
						if (!strncmp(argv[i], dl_buffer, dl_buffer_idx))
youterm@219
   577
							opt++;
youterm@26
   578
youterm@219
   579
					if (dl_buffer_len>0&&opt==1)
youterm@219
   580
						for(i=1;i<argc;i++) {
youterm@221
   581
							if (!strncmp(dl_buffer, argv[i], dl_buffer_len)) {
youterm@219
   582
								strcpy(dl_buffer, argv[i]);
youterm@219
   583
								dl_buffer_idx = dl_buffer_len = strlen(dl_buffer);
youterm@219
   584
								// TODO: if only 1 keyword hits:
youterm@219
   585
								//		if (argv[i][dl_buffer_len]=='\0') {
youterm@219
   586
								//			strcat(dl_buffer, " ");
youterm@219
   587
								//			dl_buffer_len++;
youterm@219
   588
								//		}
youterm@219
   589
								break;
youterm@219
   590
							}
youterm@26
   591
						}
youterm@219
   592
youterm@219
   593
					/* show options */
youterm@219
   594
					if (dl_buffer_idx==0 || opt>1) {
youterm@477
   595
						if (dl_echo)
youterm@477
   596
							printf("%s%s\n",dl_prompt,dl_buffer);
youterm@219
   597
						for(i=1;i<argc;i++) {
youterm@219
   598
							if (dl_buffer_len==0||!strncmp(argv[i], dl_buffer, dl_buffer_len)) {
youterm@219
   599
								len+=strlen(argv[i]);
youterm@219
   600
					//			if (len+dl_buffer_len+4 >= columns) break;
youterm@477
   601
								if (dl_echo)
youterm@477
   602
									printf("%s ", argv[i]);
youterm@219
   603
							}
youterm@219
   604
						}
youterm@477
   605
						if (dl_echo)
youterm@477
   606
							printf("\n");
youterm@26
   607
					}
youterm@219
   608
					fflush(stdout);
youterm@26
   609
				}
youterm@26
   610
				break;
youterm@82
   611
			case 18:
youterm@82
   612
				// TODO: SUPPORT FOR ^R (search command in history)
youterm@82
   613
				break;
youterm@26
   614
			case 13: 
youterm@26
   615
				goto _end;
youterm@26
   616
#if 0
youterm@26
   617
				// force command fit
youterm@26
   618
				for(i=1;i<argc;i++) {
youterm@26
   619
					if (dl_buffer_len==0 || !strncmp(argv[i], dl_buffer, dl_buffer_len)) {
youterm@26
   620
						printf("%*c", columns, ' ');
youterm@26
   621
						printf("\r");
youterm@26
   622
						printf("\n\n(%s)\n\n", dl_buffer);
youterm@184
   623
						cons_set_raw(0);
youterm@26
   624
						return dl_buffer;
youterm@26
   625
					}
youterm@26
   626
				}
youterm@26
   627
#endif
youterm@26
   628
			default:
youterm@26
   629
				/* XXX use ^A & ^E */
youterm@26
   630
				if (dl_buffer_idx<dl_buffer_len) {
youterm@26
   631
					for(i = ++dl_buffer_len;i>dl_buffer_idx;i--)
youterm@26
   632
						dl_buffer[i] = dl_buffer[i-1];
youterm@26
   633
					dl_buffer[dl_buffer_idx] = buf[0];
youterm@26
   634
				} else {
youterm@26
   635
					dl_buffer[dl_buffer_len]=buf[0];
youterm@26
   636
					dl_buffer_len++;
youterm@26
   637
					if (dl_buffer_len>1000)
youterm@26
   638
						dl_buffer_len--;
youterm@26
   639
					dl_buffer[dl_buffer_len]='\0';
youterm@26
   640
				}
youterm@26
   641
				dl_buffer_idx++;
youterm@26
   642
				break;
youterm@26
   643
		}
youterm@219
   644
		if (dl_echo) {
youterm@219
   645
			printf("\r%s%s", dl_prompt, dl_buffer);
youterm@219
   646
			printf("\r%s", dl_prompt);
youterm@219
   647
		
youterm@219
   648
			for(i=0;i<dl_buffer_idx;i++)
youterm@219
   649
				printf("%c", dl_buffer[i]);
youterm@219
   650
			fflush(stdout);
youterm@219
   651
		}
youterm@26
   652
	}
youterm@26
   653
youterm@26
   654
_end:
youterm@184
   655
	cons_set_raw(0);
youterm@219
   656
	if (dl_echo) {
youterm@219
   657
		printf("\r%s%s\n", dl_prompt, dl_buffer);
youterm@219
   658
		fflush(stdout);
youterm@219
   659
	}
youterm@219
   660
youterm@219
   661
	if (dl_buffer[0]=='!' && dl_buffer[1]=='\0') {
youterm@219
   662
		dl_hist_list();
youterm@219
   663
		return dl_nullstr;
youterm@219
   664
	}
youterm@30
   665
	//write(1,"\n",1);
youterm@26
   666
	return dl_buffer;
youterm@26
   667
}
youterm@26
   668
youterm@26
   669
#ifndef RADARE_CORE
youterm@26
   670
youterm@110
   671
youterm@110
   672
#if __UNIX__
youterm@110
   673
static struct termios tio_old, tio_new;
youterm@110
   674
#include "main.h"
youterm@110
   675
#include <stdarg.h>
youterm@110
   676
#include <termios.h>
youterm@110
   677
#include <sys/ioctl.h>
youterm@110
   678
#include <sys/wait.h>
youterm@110
   679
#include <sys/socket.h>
youterm@110
   680
#endif
youterm@110
   681
youterm@184
   682
static void cons_set_raw(int b)
youterm@26
   683
{
youterm@26
   684
#if __UNIX__
youterm@26
   685
	if (b) {
youterm@26
   686
		tcgetattr(0, &tio_old);
youterm@26
   687
		memcpy ((char *)&tio_new, (char *)&tio_old, sizeof(struct termios));
youterm@26
   688
		tio_new.c_iflag &= ~(BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
youterm@26
   689
		tio_new.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
youterm@26
   690
		tio_new.c_cflag &= ~(CSIZE|PARENB);
youterm@26
   691
		tio_new.c_cflag |= CS8;
youterm@26
   692
		tio_new.c_cc[VMIN]=1; // Solaris stuff hehe
youterm@26
   693
		tcsetattr(0, TCSANOW, &tio_new);
youterm@26
   694
		fflush(stdout);
youterm@26
   695
		return;
youterm@26
   696
	}
youterm@26
   697
youterm@26
   698
	tcsetattr(0, TCSANOW, &tio_old);
youterm@26
   699
	fflush(stdout);
youterm@26
   700
#endif
youterm@26
   701
}
youterm@26
   702
youterm@184
   703
static int cons_get_real_columns()
youterm@52
   704
{
youterm@52
   705
#if __WINDOWS__
youterm@52
   706
        return 78;
youterm@52
   707
#endif
youterm@52
   708
        struct winsize win;
youterm@52
   709
youterm@52
   710
        if (ioctl(1, TIOCGWINSZ, &win)) {
youterm@52
   711
                /* default values */
youterm@52
   712
//                win.ws_col = 80;
youterm@52
   713
 //               win.ws_row = 23;
youterm@52
   714
        }
youterm@52
   715
youterm@52
   716
        return win.ws_col;
youterm@52
   717
}
youterm@26
   718
youterm@219
   719
int main(int argc, const char **argv)
youterm@26
   720
{
youterm@26
   721
	char *ret;
youterm@26
   722
youterm@26
   723
	dl_histsize = 100;
youterm@26
   724
	dl_prompt = "$ ";
youterm@26
   725
	dl_init();
youterm@26
   726
youterm@26
   727
	dl_printchar();
youterm@26
   728
youterm@26
   729
	do {
youterm@26
   730
		ret = dl_readline(argc, argv);
youterm@26
   731
		if (ret) {
youterm@26
   732
			printf(" [line] '%s'\n", ret);
youterm@26
   733
			dl_hist_add(ret);
youterm@26
   734
		}
youterm@26
   735
	} while(ret!=NULL);
youterm@26
   736
	dl_free();
youterm@26
   737
	return 0;
youterm@26
   738
}
youterm@26
   739
youterm@26
   740
#endif