1 /***************************************************************************
2  *  Pinfo is a ncurses based lynx style info documentation browser
3  *
4  *  Copyright (C) 1999  Przemek Borys <pborys@dione.ids.pl>
5  *  Copyright (C) 2005  Bas Zoetekouw <bas@debian.org>
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of version 2 of the GNU General Public License as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful, but
12  *  WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
19  *  USA
20  ***************************************************************************/
21 #include "common_includes.h"
22 
23 char **rlhistory = 0;
24 int rlhistorylen = 0;
25 int rlhistorypos = 0;
26 
27 #define KEY_BCKSPC 8
28 
29 char *
readlinewrapper(char * prompt)30 readlinewrapper(char *prompt)
31 {
32 	/* number of keys pressed */
33 	int numkeys = 0;
34 	/* initial buffer for the read line */
35 	char *buf = xmalloc(1024);
36 	/* start coords of input line */
37 	int origx, origy;
38 	/* cursor position in input string */
39 	int cursor = 0;
40 	/* key - a variable for getch() */
41 	int key = 0, i;
42 	/* initial value of line - "" */
43 	buf[0] = 0;
44 	/* print prompt */
45 	addstr(prompt);
46 	/* get origx,origy coordinates */
47 	getyx(stdscr, origy, origx);
48 	/* turn off echoing chars by getch() */
49 	noecho();
50 	/* create input line bar */
51 	mvhline(origy, origx, ' ', maxx - origx);
52 
53 	/* history entry for this line */
54 	rlhistorylen++;
55 	/* move history pos to current entry */
56 	rlhistorypos = rlhistorylen;
57 	/* alloc memory for this entry */
58 	if (!rlhistory)
59 		rlhistory = xmalloc(sizeof(char *));
60 	else
61 		rlhistory = xrealloc(rlhistory, sizeof(char *) * rlhistorylen);
62 	rlhistory[rlhistorylen - 1] = xmalloc(1024);
63 	/* and copy there the current value of input line */
64 	strcpy(rlhistory[rlhistorylen - 1], buf);
65 	/* call history to be present */
66 	if (CallReadlineHistory)
67 	{
68 		ungetch(KEY_UP);
69 		numkeys = -1;
70 	}
71 
72 	while (key != '\n')
73 	{
74 		/* read key */
75 		key = getch();
76 		switch(key)
77 		{
78 			/* move cursor left */
79 			case KEY_LEFT:
80 				if (cursor > 0)
81 					cursor--;
82 				break;
83 			/* move cursor right */
84 			case KEY_RIGHT:
85 				if (cursor < strlen(buf))
86 					cursor++;
87 				break;
88 			case KEY_END:
89 				cursor = strlen(buf);
90 				break;
91 			/* handle backspace: copy all */
92 			case KEY_BCKSPC:
93 			/* chars starting from curpos */
94 			case KEY_BACKSPACE:
95 				/* - 1 from buf[n+1] to buf   */
96 				if (cursor > 0)
97 				{
98 					for (i = cursor - 1; buf[i] != 0; i++)
99 						buf[i] = buf[i + 1];
100 					cursor--;
101 				}
102 				break;
103 			/* handle delete key. As above */
104 			case KEY_DC:
105 				if (cursor <= strlen(buf) - 1)
106 				{
107 					for (i = cursor; buf[i] != 0; i++)
108 						buf[i] = buf[i + 1];
109 				}
110 				break;
111 			/* backwards-history call */
112 			case KEY_UP:
113 				/* if there is history */
114 				if (rlhistorylen)
115 					/* and we have */
116 					if (rlhistorypos > 1)
117 					{			/* where to move */
118 						/* decrement history position */
119 						rlhistorypos--;
120 						/* if the previous pos was the input line */
121 						/* save it's value to history */
122 						if (rlhistorypos == rlhistorylen - 1)
123 							strcpy(rlhistory[rlhistorylen - 1], buf);
124 						/*  recall value from history to input buf */
125 						strcpy(buf, rlhistory[rlhistorypos - 1]);
126 					}
127 				cursor = strlen(buf);
128 				numkeys = -1;
129 				break;
130 			/* forwards-history call */
131 			case KEY_DOWN:
132 				if (rlhistorylen)
133 					if (rlhistorypos < rlhistorylen)
134 					{
135 						rlhistorypos++;
136 						strcpy(buf, rlhistory[rlhistorypos - 1]);
137 					}
138 				cursor = strlen(buf);
139 				numkeys = -1;
140 				break;
141 				/* eliminate nonprintable chars */
142 			case '\n':
143 			case KEY_PPAGE:
144 			case KEY_NPAGE:
145 			case KEY_F(1):
146 			case KEY_F(2):
147 			case KEY_F(3):
148 			case KEY_F(4):
149 			case KEY_F(5):
150 			case KEY_F(6):
151 			case KEY_F(7):
152 			case KEY_F(8):
153 			case KEY_F(9):
154 			case KEY_F(10):
155 				break;
156 			default:
157 				if (key >= 32)
158 				{
159 					/* if this is the first key, delete the buffer */
160 					if (numkeys==0 && cursor!=0)
161 					{
162 						for (i=0; buf[i]!=0; i++)
163 							buf[i] = 0;
164 						cursor = 0;
165 						/* and empty the line */
166 						move(origy, origx);
167 						for (i = origx; i < maxx; i++)
168 							addch(' ');
169 						move(origy, origx + cursor);
170 					}
171 
172 					/* if the cursor is not at the last pos */
173 					if (strlen(buf + cursor))
174 					{
175 						char *tmp = 0;
176 						tmp = xmalloc(strlen(buf + cursor) + 1);
177 						strcpy(tmp, buf + cursor);
178 						buf[cursor] = key;
179 						buf[cursor + 1] = 0;
180 						strcat(&buf[cursor + 1], tmp);
181 						xfree(tmp);
182 						cursor++;
183 					}
184 					else
185 					{
186 						buf[cursor + 1] = 0;
187 						buf[cursor] = key;
188 						cursor++;
189 					}
190 				}
191 		}
192 		move(origy, origx);
193 		for (i = origx; i < maxx; i++)
194 			addch(' ');
195 		move(origy, origx);
196 		addstr(buf);
197 		move(origy, origx + cursor);
198 
199 		numkeys++;
200 
201 	}
202 	strcpy(rlhistory[rlhistorylen - 1], buf);
203 	if (strlen(buf))
204 	{
205 		rlhistory[rlhistorylen - 1] = xrealloc(rlhistory[rlhistorylen - 1],
206 				strlen(rlhistory[rlhistorylen - 1]) + 1);
207 	}
208 	else
209 	{
210 		xfree(rlhistory[rlhistorylen - 1]);
211 		rlhistorylen--;
212 		rlhistorypos = rlhistorylen;
213 	}
214 	buf = xrealloc(buf, strlen(buf) + 1);
215 	return buf;
216 }
217