blob: 4597d3fb11b21608ec42149e00e16e9d71613bf0 [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
5 * Copyright (C) 1999 Chris Allegretta *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 1, or (at your option) *
9 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
22#include <stdarg.h>
23#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000024#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000025#include <unistd.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000026#include "config.h"
27#include "proto.h"
28#include "nano.h"
29
30#ifndef NANO_SMALL
31#include <libintl.h>
32#define _(string) gettext(string)
33#else
34#define _(string) (string)
35#endif
36
37static int statblank = 0; /* Number of keystrokes left after
38 we call statubar() before we
39 actually blank the statusbar */
Robert Siemborskid8510b22000-06-06 23:04:06 +000040
41/* Local Function Prototypes for only winio.c */
42inline int get_page_from_virtual(int virtual);
43inline int get_page_start_virtual(int page);
44inline int get_page_end_virtual(int page);
45
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000046/* Window I/O */
47
48int do_first_line(void)
49{
50 current = fileage;
51 placewewant = 0;
52 current_x = 0;
Chris Allegretta234a34d2000-07-29 04:33:38 +000053 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000054 return 1;
55}
56
57int do_last_line(void)
58{
59 current = filebot;
60 placewewant = 0;
61 current_x = 0;
Chris Allegretta234a34d2000-07-29 04:33:38 +000062 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000063 return 1;
64}
65
66/* Like xplustabs, but for a specifc index of a speficific filestruct */
67int xpt(filestruct * fileptr, int index)
68{
69 int i, tabs = 0;
70
71 if (fileptr == NULL || fileptr->data == NULL)
72 return 0;
73
74 for (i = 0; i < index && fileptr->data[i] != 0; i++) {
75 tabs++;
76
77 if (fileptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +000078 if (tabs % tabsize == 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000079 else
Chris Allegretta6d690a32000-08-03 22:51:21 +000080 tabs += tabsize - (tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000081 } else if (fileptr->data[i] & 0x80)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000082 /* Make 8 bit chars only 1 collumn! */
83 ;
84 else if (fileptr->data[i] < 32)
85 tabs++;
86 }
87
88 return tabs;
89}
90
91
92/* Return the actual place on the screen of current->data[current_x], which
93 should always be > current_x */
94int xplustabs(void)
95{
96 return xpt(current, current_x);
97}
98
99
Robert Siemborskid8510b22000-06-06 23:04:06 +0000100/* Return what current_x should be, given xplustabs() for the line,
101 * given a start position in the filestruct's data */
102int actual_x_from_start(filestruct * fileptr, int xplus, int start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000103{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000104 int i, tot = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000105
106 if (fileptr == NULL || fileptr->data == NULL)
107 return 0;
108
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000109 for (i = start; tot <= xplus && fileptr->data[i] != 0; i++, tot++)
Robert Siemborskid8510b22000-06-06 23:04:06 +0000110 if (fileptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000111 if (tot % tabsize == 0)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000112 tot++;
113 else
Chris Allegretta6d690a32000-08-03 22:51:21 +0000114 tot += tabsize - (tot % tabsize);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000115 } else if (fileptr->data[i] & 0x80)
116 tot++; /* Make 8 bit chars only 1 column (again) */
117 else if (fileptr->data[i] < 32)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000118 tot += 2;
119
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000120#ifdef DEBUG
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000121 fprintf(stderr, _("actual_x_from_start for xplus=%d returned %d\n"),
122 xplus, i);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000123#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +0000124 return i - start;
125}
126
127/* Opposite of xplustabs */
128inline int actual_x(filestruct * fileptr, int xplus)
129{
130 return actual_x_from_start(fileptr, xplus, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000131}
132
133/* a strlen with tabs factored in, similar to xplustabs() */
134int strlenpt(char *buf)
135{
136 int i, tabs = 0;
137
138 if (buf == NULL)
139 return 0;
140
141 for (i = 0; buf[i] != 0; i++) {
142 tabs++;
143
144 if (buf[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000145 if (tabs % tabsize == 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000146 else
Chris Allegretta6d690a32000-08-03 22:51:21 +0000147 tabs += tabsize - (tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000148 } else if (buf[i] & 0x80)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000149 /* Make 8 bit chars only 1 collumn! */
150 ;
151 else if (buf[i] < 32)
152 tabs++;
153 }
154
155 return tabs;
156}
157
158
159/* resets current_y based on the position of current and puts the cursor at
160 (current_y, current_x) */
161void reset_cursor(void)
162{
163 filestruct *ptr = edittop;
164 int x;
165
166 current_y = 0;
167
168 while (ptr != current && ptr != editbot && ptr->next != NULL) {
169 ptr = ptr->next;
170 current_y++;
171 }
172
173 x = xplustabs();
174 if (x <= COLS - 2)
Robert Siemborskid8510b22000-06-06 23:04:06 +0000175 wmove(edit, current_y, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000176 else
Robert Siemborskid8510b22000-06-06 23:04:06 +0000177 wmove(edit, current_y, x -
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000178 get_page_start_virtual(get_page_from_virtual(x)));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000179
180}
181
182void blank_bottombars(void)
183{
184 int i = no_help()? 3 : 1;
185
186 for (; i <= 2; i++)
187 mvwaddstr(bottomwin, i, 0, hblank);
188
189}
190
191void blank_edit(void)
192{
193 int i;
194 for (i = 0; i <= editwinrows - 1; i++)
195 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000196}
197
198
199void blank_statusbar(void)
200{
201 mvwaddstr(bottomwin, 0, 0, hblank);
202}
203
204void blank_statusbar_refresh(void)
205{
206 blank_statusbar();
207 wrefresh(bottomwin);
208}
209
210void check_statblank(void)
211{
212
213 if (statblank > 1)
214 statblank--;
215 else if (statblank == 1 && !ISSET(CONSTUPDATE)) {
216 statblank--;
217 blank_statusbar_refresh();
218 }
219}
220
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000221/* Repaint the statusbar when getting a character in nanogetstr */
222void nanoget_repaint(char *buf, char *inputbuf, int x)
223{
Chris Allegretta0d1e8d62000-11-02 15:30:24 +0000224 int len = strlen(buf);
225 int wid = COLS - len;
226
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000227 blank_statusbar();
Chris Allegretta0d1e8d62000-11-02 15:30:24 +0000228 if (x <= COLS - 1) {
229 /* Black magic */
230 buf[len - 1] = ' ';
Chris Allegretta31925e42000-11-02 04:40:39 +0000231
Chris Allegretta0d1e8d62000-11-02 15:30:24 +0000232 mvwaddstr(bottomwin, 0, 0, buf);
233 waddnstr(bottomwin, inputbuf, wid);
234 wmove(bottomwin, 0, (x % COLS));
235 }
236 else {
237 /* Black magic */
238 buf[len - 1] = '$';
Chris Allegretta31925e42000-11-02 04:40:39 +0000239
Chris Allegretta0d1e8d62000-11-02 15:30:24 +0000240 mvwaddstr(bottomwin, 0, 0, buf);
241 waddnstr(bottomwin, &inputbuf[wid * ((x - len) / (wid))], wid);
242 wmove(bottomwin, 0, ((x - len) % wid) + len);
243 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000244}
245
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000246/* Get the input from the kb, this should only be called from statusq */
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000247int nanogetstr(int allowtabs, char *buf, char *def, shortcut s[], int slen,
248 int start_x)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000249{
250 int kbinput = 0, j = 0, x = 0, xend;
Chris Allegrettabe77c612000-11-24 14:00:16 +0000251 int x_left = 0, inputlen, tabbed = 0;
Chris Allegretta31925e42000-11-02 04:40:39 +0000252 char *inputbuf;
Chris Allegrettabe77c612000-11-24 14:00:16 +0000253#ifndef DISABLE_TABCOMP
254 int shift = 0;
255#endif
Chris Allegretta31925e42000-11-02 04:40:39 +0000256
257 inputbuf = nmalloc(strlen(def) + 1);
258 inputbuf[0] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000259
260 x_left = strlen(buf);
261 x = strlen(def) + x_left;
262
263 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +0000264 if (strlen(def) > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000265 strcpy(inputbuf, def);
Chris Allegretta31925e42000-11-02 04:40:39 +0000266
267 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000268
Chris Allegretta022b96f2000-11-14 17:47:58 +0000269 /* Make sure any editor screen updates are displayed before getting input */
270 wrefresh(edit);
271
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000272 while ((kbinput = wgetch(bottomwin)) != 13) {
273 for (j = 0; j <= slen - 1; j++) {
274 if (kbinput == s[j].val) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +0000275
276 /* We shouldn't discard the answer it gave, just because
277 we hit a keystroke, GEEZ! */
278 answer = mallocstrcpy(answer, inputbuf);
Chris Allegretta92d2bab2000-11-02 14:53:46 +0000279 free(inputbuf);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000280 return s[j].val;
281 }
282 }
283 xend = strlen(buf) + strlen(inputbuf);
284
Chris Allegretta04d848e2000-11-05 17:54:41 +0000285 if (kbinput != '\t')
286 tabbed = 0;
287
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000288 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000289 /* Stuff we want to equate with <enter>, ASCII 13 */
290 case 343:
Chris Allegrettaf9b6c9b2000-10-18 19:35:59 +0000291 ungetch(13); /* Enter on iris-ansi $TERM, sometimes */
292 break;
Chris Allegretta75155df2000-11-28 23:04:24 +0000293 /* Stuff we want to ignore */
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000294#ifdef PDCURSES
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000295 case 541:
296 case 542:
Chris Allegretta72623582000-11-29 23:43:28 +0000297 case 543: /* Right ctrl again */
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000298 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +0000299 case 545: /* Right alt again */
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000300#endif
Chris Allegretta75155df2000-11-28 23:04:24 +0000301 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000302 case KEY_HOME:
303 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000304 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000305 break;
306 case KEY_END:
307 x = x_left + strlen(inputbuf);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000308 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000309 break;
310 case KEY_RIGHT:
311
312 if (x < xend)
313 x++;
314 wmove(bottomwin, 0, x);
315 break;
316 case NANO_CONTROL_D:
317 if (strlen(inputbuf) > 0 && (x - x_left) != strlen(inputbuf)) {
318 memmove(inputbuf + (x - x_left),
319 inputbuf + (x - x_left) + 1,
320 strlen(inputbuf) - (x - x_left) - 1);
321 inputbuf[strlen(inputbuf) - 1] = 0;
322 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000323 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000324 break;
325 case NANO_CONTROL_K:
326 case NANO_CONTROL_U:
327 *inputbuf = 0;
328 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000329 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000330 break;
331 case KEY_BACKSPACE:
332 case KEY_DC:
333 case 127:
334 case NANO_CONTROL_H:
335 if (strlen(inputbuf) > 0) {
336 if (x == (x_left + strlen(inputbuf)))
337 inputbuf[strlen(inputbuf) - 1] = 0;
338 else if (x - x_left) {
339 memmove(inputbuf + (x - x_left) - 1,
340 inputbuf + (x - x_left),
341 strlen(inputbuf) - (x - x_left));
342 inputbuf[strlen(inputbuf) - 1] = 0;
343 }
344 }
Chris Allegretta04d848e2000-11-05 17:54:41 +0000345 if (x > strlen(buf))
346 x--;
Chris Allegretta31925e42000-11-02 04:40:39 +0000347 nanoget_repaint(buf, inputbuf, x);
Chris Allegretta04d848e2000-11-05 17:54:41 +0000348 break;
Chris Allegrettabe77c612000-11-24 14:00:16 +0000349#ifndef DISABLE_TABCOMP
Chris Allegretta04d848e2000-11-05 17:54:41 +0000350 case NANO_CONTROL_I:
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000351 if (allowtabs) {
Chris Allegretta442f2c52000-11-14 17:46:06 +0000352 shift = 0;
353 inputbuf = input_tab(inputbuf, (x - x_left),
Chris Allegrettab5b89ae2000-11-14 18:25:26 +0000354 &tabbed, &shift);
Chris Allegretta442f2c52000-11-14 17:46:06 +0000355 x += shift;
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000356 nanoget_repaint(buf, inputbuf, x);
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000357 }
Chris Allegretta04d848e2000-11-05 17:54:41 +0000358 break;
Chris Allegrettabe77c612000-11-24 14:00:16 +0000359#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000360 case KEY_LEFT:
361 if (x > strlen(buf))
362 x--;
363 wmove(bottomwin, 0, x);
364 break;
365 case KEY_UP:
366 case KEY_DOWN:
367 break;
368
369 case 27:
370 switch (kbinput = wgetch(edit)) {
371 case 79:
372 switch (kbinput = wgetch(edit)) {
373 case 70:
374 x = x_left + strlen(inputbuf);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000375 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000376 break;
377 case 72:
378 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000379 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000380 break;
381 }
382 break;
383 case 91:
384 switch (kbinput = wgetch(edit)) {
385 case 'C':
386 if (x < xend)
387 x++;
388 wmove(bottomwin, 0, x);
389 break;
390 case 'D':
391 if (x > strlen(buf))
392 x--;
393 wmove(bottomwin, 0, x);
394 break;
395 case 49:
396 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000397 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000398 goto skip_126;
399 case 51:
400 if (strlen(inputbuf) > 0
401 && (x - x_left) != strlen(inputbuf)) {
402 memmove(inputbuf + (x - x_left),
403 inputbuf + (x - x_left) + 1,
404 strlen(inputbuf) - (x - x_left) - 1);
405 inputbuf[strlen(inputbuf) - 1] = 0;
406 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000407 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000408 goto skip_126;
409 case 52:
410 x = x_left + strlen(inputbuf);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000411 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000412 goto skip_126;
413 skip_126:
414 nodelay(edit, TRUE);
415 kbinput = wgetch(edit);
416 if (kbinput == 126 || kbinput == ERR)
417 kbinput = -1;
418 nodelay(edit, FALSE);
419 break;
420 }
421 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000422 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000423 break;
424
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000425 default:
426 if (kbinput < 32)
427 break;
Chris Allegretta31925e42000-11-02 04:40:39 +0000428
429 inputlen = strlen(inputbuf);
430 inputbuf = nrealloc(inputbuf, inputlen + 2);
431
432 memmove(&inputbuf[x - x_left + 1],
433 &inputbuf[x - x_left],
434 inputlen - (x - x_left) + 1);
435 inputbuf[x - x_left] = kbinput;
436
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000437 x++;
438
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000439 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000440#ifdef DEBUG
441 fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput);
442#endif
443 }
444 wrefresh(bottomwin);
445 }
446
Chris Allegretta31925e42000-11-02 04:40:39 +0000447 answer = mallocstrcpy(answer, inputbuf);
Chris Allegretta92d2bab2000-11-02 14:53:46 +0000448 free(inputbuf);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000449
Chris Allegretta105da332000-10-31 05:10:10 +0000450 /* Now that the text is editable instead of bracketed, we have to
451 check for answer == def, instead of answer == "" */
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000452 if (((ISSET(PICO_MODE)) && !strcmp(answer, "")) ||
453 ((!ISSET(PICO_MODE)) && !strcmp(answer, def)))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000454 return -2;
455 else
456 return 0;
457}
458
459void horizbar(WINDOW * win, int y)
460{
461 wattron(win, A_REVERSE);
462 mvwaddstr(win, 0, 0, hblank);
463 wattroff(win, A_REVERSE);
464}
465
466void titlebar(void)
467{
468 int namelen, space;
469
470 horizbar(topwin, 0);
471 wattron(topwin, A_REVERSE);
472 mvwaddstr(topwin, 0, 3, VERMSG);
473
474 space = COLS - strlen(VERMSG) - strlen(VERSION) - 21;
475
476 namelen = strlen(filename);
477
478 if (!strcmp(filename, ""))
479 mvwaddstr(topwin, 0, center_x - 6, _("New Buffer"));
480 else {
481 if (namelen > space) {
482 waddstr(topwin, _(" File: ..."));
483 waddstr(topwin, &filename[namelen - space]);
484 } else {
485 mvwaddstr(topwin, 0, center_x - (namelen / 2 + 1), "File: ");
486 waddstr(topwin, filename);
487 }
488 }
489 if (ISSET(MODIFIED))
490 mvwaddstr(topwin, 0, COLS - 10, _("Modified"));
491 wattroff(topwin, A_REVERSE);
492 wrefresh(topwin);
493 reset_cursor();
494}
495
496void onekey(char *keystroke, char *desc)
497{
498 char description[80];
499
Chris Allegrettae7034c62000-09-15 03:31:09 +0000500 snprintf(description, 12, " %-10s", desc);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000501 wattron(bottomwin, A_REVERSE);
502 waddstr(bottomwin, keystroke);
503 wattroff(bottomwin, A_REVERSE);
504 waddstr(bottomwin, description);
505}
506
507void clear_bottomwin(void)
508{
509 if (ISSET(NO_HELP))
510 return;
511
512 mvwaddstr(bottomwin, 1, 0, hblank);
513 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000514}
515
516void bottombars(shortcut s[], int slen)
517{
518 int i, j, k;
519 char keystr[10];
520
521 if (ISSET(NO_HELP))
522 return;
523
524 /* Determine how many extra spaces are needed to fill the bottom of the screen */
525 k = COLS / 6 - 13;
526
527 clear_bottomwin();
528 wmove(bottomwin, 1, 0);
529 for (i = 0; i <= slen - 1; i += 2) {
Robert Siemborski6af14312000-07-01 21:34:26 +0000530 snprintf(keystr, 10, "^%c", s[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000531 onekey(keystr, s[i].desc);
532
533 for (j = 0; j < k; j++)
534 waddch(bottomwin, ' ');
535 }
536
537 wmove(bottomwin, 2, 0);
538 for (i = 1; i <= slen - 1; i += 2) {
Robert Siemborski6af14312000-07-01 21:34:26 +0000539 snprintf(keystr, 10, "^%c", s[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000540 onekey(keystr, s[i].desc);
541
542 for (j = 0; j < k; j++)
543 waddch(bottomwin, ' ');
544 }
545
546 wrefresh(bottomwin);
547
548}
549
550/* If modified is not already set, set it and update titlebar */
551void set_modified(void)
552{
553 if (!ISSET(MODIFIED)) {
554 SET(MODIFIED);
555 titlebar();
556 wrefresh(topwin);
557 }
558}
559
Robert Siemborski9d584552000-07-08 00:41:29 +0000560/* And so start the display update routines */
561/* Given a column, this returns the "page" it is on */
562/* "page" in the case of the display columns, means which set of 80 */
563/* characters is viewable (ie: page 1 shows from 1 to COLS) */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000564inline int get_page_from_virtual(int virtual)
565{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000566 int page = 2;
567
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000568 if (virtual <= COLS - 2)
569 return 1;
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000570 virtual -= (COLS - 2);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000571
572 while (virtual > COLS - 2 - 7) {
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000573 virtual -= (COLS - 2 - 7);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000574 page++;
575 }
576
577 return page;
578}
579
Robert Siemborski9d584552000-07-08 00:41:29 +0000580/* The inverse of the above function */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000581inline int get_page_start_virtual(int page)
582{
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000583 int virtual;
584 virtual = --page * (COLS - 7);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000585 if (page)
586 virtual -= 2 * page - 1;
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000587 return virtual;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000588}
589
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000590inline int get_page_end_virtual(int page)
591{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000592 return get_page_start_virtual(page) + COLS - 1;
593}
594
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000595#ifndef NANO_SMALL
Robert Siemborski9d584552000-07-08 00:41:29 +0000596/* This takes care of the case where there is a mark that covers only */
597/* the current line. */
598
Chris Allegrettab275aac2000-07-08 01:22:33 +0000599/* It expects a line with no tab characers (ie: the type that edit_add */
Robert Siemborski9d584552000-07-08 00:41:29 +0000600/* deals with */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000601void add_marked_sameline(int begin, int end, filestruct * fileptr, int y,
602 int virt_cur_x, int this_page)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000603{
Robert Siemborski9d584552000-07-08 00:41:29 +0000604 /*
605 * The general idea is to break the line up into 3 sections: before
606 * the mark, the mark, and after the mark. We then paint each in
607 * turn (for those that are currently visible, of course
608 *
609 * 3 start points: 0 -> begin, begin->end, end->strlen(data)
610 * in data : pre sel post
611 */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000612 int this_page_start = get_page_start_virtual(this_page),
Robert Siemborski53875912000-06-16 04:25:30 +0000613 this_page_end = get_page_end_virtual(this_page);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000614
Robert Siemborskid8510b22000-06-06 23:04:06 +0000615 /* likewise, 3 data lengths */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000616 int pre_data_len = begin, sel_data_len = end - begin, post_data_len = 0; /* Determined from the other two */
Robert Siemborskid8510b22000-06-06 23:04:06 +0000617
618 /* now fix the start locations & lengths according to the cursor's
619 * position (ie: our page) */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000620 if (pre_data_len < this_page_start)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000621 pre_data_len = 0;
622 else
623 pre_data_len -= this_page_start;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000624
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000625 if (begin < this_page_start)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000626 begin = this_page_start;
627
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000628 if (end < this_page_start)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000629 end = this_page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000630
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000631 if (begin > this_page_end)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000632 begin = this_page_end;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000633
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000634 if (end > this_page_end)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000635 end = this_page_end;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000636
Robert Siemborski9d584552000-07-08 00:41:29 +0000637 /* Now calculate the lengths */
Robert Siemborskia9addc72000-06-17 06:06:35 +0000638 sel_data_len = end - begin;
639 post_data_len = this_page_end - end;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000640
Robert Siemborski9d584552000-07-08 00:41:29 +0000641 /* Paint this line! */
Robert Siemborski53875912000-06-16 04:25:30 +0000642 mvwaddnstr(edit, y, 0, &fileptr->data[this_page_start], pre_data_len);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000643 wattron(edit, A_REVERSE);
Robert Siemborskia9addc72000-06-17 06:06:35 +0000644 mvwaddnstr(edit, y, begin - this_page_start,
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000645 &fileptr->data[begin], sel_data_len);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000646 wattroff(edit, A_REVERSE);
Robert Siemborskia9addc72000-06-17 06:06:35 +0000647 mvwaddnstr(edit, y, end - this_page_start,
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000648 &fileptr->data[end], post_data_len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000649}
650#endif
651
Robert Siemborski9d584552000-07-08 00:41:29 +0000652/* edit_add takes care of the job of actually painting a line into the
653 * edit window.
654 *
655 * Called only from update_line. Expects a converted-to-not-have-tabs
Robert Siemborski53875912000-06-16 04:25:30 +0000656 * line */
657void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000658 int virt_mark_beginx, int this_page)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000659{
660#ifndef NANO_SMALL
Robert Siemborski9d584552000-07-08 00:41:29 +0000661 /* There are quite a few cases that could take place, we'll deal
662 * with them each in turn */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000663 if (ISSET(MARK_ISSET)
Robert Siemborski9d584552000-07-08 00:41:29 +0000664 && !((fileptr->lineno > mark_beginbuf->lineno
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000665 && fileptr->lineno > current->lineno)
666 || (fileptr->lineno < mark_beginbuf->lineno
667 && fileptr->lineno < current->lineno))) {
668 /* If we get here we are on a line that is atleast
669 * partially selected. The lineno checks above determined
670 * that */
671 if (fileptr != mark_beginbuf && fileptr != current) {
672 /* We are on a completely marked line, paint it all
673 * inverse */
674 wattron(edit, A_REVERSE);
675 mvwaddnstr(edit, yval, 0, fileptr->data, COLS);
676 wattroff(edit, A_REVERSE);
677 } else if (fileptr == mark_beginbuf && fileptr == current) {
678 /* Special case, we're still on the same line we started
679 * marking -- so we call our helper function */
680 if (virt_cur_x < virt_mark_beginx) {
681 /* To the right of us is marked */
682 add_marked_sameline(virt_cur_x, virt_mark_beginx,
683 fileptr, yval, virt_cur_x, this_page);
684 } else {
685 /* To the left of us is marked */
686 add_marked_sameline(virt_mark_beginx, virt_cur_x,
687 fileptr, yval, virt_cur_x, this_page);
688 }
689 } else if (fileptr == mark_beginbuf) {
690 /*
691 * we're updating the line that was first marked
692 * but we're not currently on it. So we want to
693 * figur out which half to invert based on our
694 * relative line numbers.
695 *
696 * i.e. If we're above the "beginbuf" line, we want to
697 * mark the left side. Otherwise we're below, so we
698 * mark the right
699 */
700 int target;
701
702 if (mark_beginbuf->lineno > current->lineno)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000703 wattron(edit, A_REVERSE);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000704
705 target =
706 (virt_mark_beginx <
707 COLS - 1) ? virt_mark_beginx : COLS - 1;
708
709 mvwaddnstr(edit, yval, 0, fileptr->data, target);
710
711 if (mark_beginbuf->lineno < current->lineno)
712 wattron(edit, A_REVERSE);
713 else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000714 wattroff(edit, A_REVERSE);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000715
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000716 target = (COLS - 1) - virt_mark_beginx;
717 if (target < 0)
718 target = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000719
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000720 mvwaddnstr(edit, yval, virt_mark_beginx,
721 &fileptr->data[virt_mark_beginx], target);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000722
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000723 if (mark_beginbuf->lineno < current->lineno)
724 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000725
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000726 } else if (fileptr == current) {
727 /* we're on the cursors line, but it's not the first
728 * one we marked. Similar to the previous logic. */
729 int this_page_start = get_page_start_virtual(this_page),
730 this_page_end = get_page_end_virtual(this_page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000731
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000732 if (mark_beginbuf->lineno < current->lineno)
733 wattron(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000734
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000735 if (virt_cur_x > COLS - 2) {
736 mvwaddnstr(edit, yval, 0,
737 &fileptr->data[this_page_start],
738 virt_cur_x - this_page_start);
739 } else {
740 mvwaddnstr(edit, yval, 0, fileptr->data, virt_cur_x);
741 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000742
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000743 if (mark_beginbuf->lineno > current->lineno)
744 wattron(edit, A_REVERSE);
745 else
746 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000747
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000748 if (virt_cur_x > COLS - 2)
749 mvwaddnstr(edit, yval, virt_cur_x - this_page_start,
750 &fileptr->data[virt_cur_x],
751 this_page_end - virt_cur_x);
752 else
753 mvwaddnstr(edit, yval, virt_cur_x,
754 &fileptr->data[virt_cur_x], COLS - virt_cur_x);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000755
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000756 if (mark_beginbuf->lineno > current->lineno)
757 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000758 }
759
760 } else
761#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000762 /* Just paint the string (no mark on this line) */
Robert Siemborskia9addc72000-06-17 06:06:35 +0000763 mvwaddnstr(edit, yval, 0, &fileptr->data[start],
Chris Allegretta908805a2000-12-04 04:42:56 +0000764 get_page_end_virtual(this_page) - start + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000765}
766
767/*
Robert Siemborski9d584552000-07-08 00:41:29 +0000768 * Just update one line in the edit buffer. Basically a wrapper for
769 * edit_add
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000770 *
771 * index gives is a place in the string to update starting from.
772 * Likely args are current_x or 0.
773 */
774void update_line(filestruct * fileptr, int index)
775{
776 filestruct *filetmp;
Robert Siemborski53875912000-06-16 04:25:30 +0000777 int line = 0, col = 0;
778 int virt_cur_x = current_x, virt_mark_beginx = mark_beginx;
779 char *realdata, *tmp;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000780 int i, pos, len, page;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000781
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000782 if (!fileptr)
783 return;
Robert Siemborski53154a72000-06-18 00:11:03 +0000784
Robert Siemborski53875912000-06-16 04:25:30 +0000785 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000786 for (filetmp = edittop; filetmp != fileptr && filetmp != editbot;
787 filetmp = filetmp->next)
788 line++;
789
790 mvwaddstr(edit, line, 0, hblank);
791
Robert Siemborski53875912000-06-16 04:25:30 +0000792 /* Next, convert all the tabs to spaces so everything else is easy */
793 index = xpt(fileptr, index);
794
795 realdata = fileptr->data;
796 len = strlen(realdata);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000797 fileptr->data = nmalloc(xpt(fileptr, len) + 1);
Robert Siemborski53875912000-06-16 04:25:30 +0000798
799 pos = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000800 for (i = 0; i < len; i++) {
801 if (realdata[i] == '\t') {
Robert Siemborski53875912000-06-16 04:25:30 +0000802 do {
803 fileptr->data[pos++] = ' ';
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000804 if (i < current_x)
805 virt_cur_x++;
806 if (i < mark_beginx)
807 virt_mark_beginx++;
Chris Allegretta6d690a32000-08-03 22:51:21 +0000808 } while (pos % tabsize);
Robert Siemborski53875912000-06-16 04:25:30 +0000809 /* must decrement once to account for tab-is-one-character */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000810 if (i < current_x)
811 virt_cur_x--;
812 if (i < mark_beginx)
813 virt_mark_beginx--;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000814 } else if (realdata[i] >= 1 && realdata[i] <= 26) {
815 /* Treat control characters as ^letter */
Chris Allegretta6306a112000-09-02 07:55:41 +0000816 fileptr->data[pos++] = '^';
817 fileptr->data[pos++] = realdata[i] + 64;
Robert Siemborski53875912000-06-16 04:25:30 +0000818 } else {
819 fileptr->data[pos++] = realdata[i];
820 }
821 }
822
823 fileptr->data[pos] = '\0';
824
825 /* Now, Paint the line */
826 if (current == fileptr && index > COLS - 2) {
Robert Siemborskia9addc72000-06-17 06:06:35 +0000827 /* This handles when the current line is beyond COLS */
828 /* It requires figureing out what page we're at */
829 page = get_page_from_virtual(index);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000830 col = get_page_start_virtual(page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000831
Robert Siemborskia9addc72000-06-17 06:06:35 +0000832 edit_add(filetmp, line, col, virt_cur_x, virt_mark_beginx, page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000833 mvwaddch(edit, line, 0, '$');
834
Chris Allegrettafb62f732000-12-05 11:36:41 +0000835 if (strlenpt(fileptr->data) > get_page_end_virtual(page) + 1)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000836 mvwaddch(edit, line, COLS - 1, '$');
Robert Siemborskid8510b22000-06-06 23:04:06 +0000837 } else {
Robert Siemborskia9addc72000-06-17 06:06:35 +0000838 /* It's not the current line means that it's at x=0 and page=1 */
839 /* If it is the current line, then we're in the same boat */
840 edit_add(filetmp, line, 0, virt_cur_x, virt_mark_beginx, 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000841
Robert Siemborski53875912000-06-16 04:25:30 +0000842 if (strlenpt(&filetmp->data[col]) > COLS)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000843 mvwaddch(edit, line, COLS - 1, '$');
Robert Siemborskid8510b22000-06-06 23:04:06 +0000844 }
Robert Siemborski53875912000-06-16 04:25:30 +0000845
846 /* Clean up our mess */
847 tmp = fileptr->data;
848 fileptr->data = realdata;
849 free(tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000850}
851
852void center_cursor(void)
853{
854 current_y = editwinrows / 2;
855 wmove(edit, current_y, current_x);
856}
857
858/* Refresh the screen without changing the position of lines */
859void edit_refresh(void)
860{
Chris Allegrettaed022162000-08-03 16:54:11 +0000861 static int noloop = 0;
Chris Allegretta95b0b522000-07-28 02:58:06 +0000862 int lines = 0, i = 0, currentcheck = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000863 filestruct *temp, *hold = current;
864
865 if (current == NULL)
866 return;
867
868 temp = edittop;
869
870 while (lines <= editwinrows - 1 && lines <= totlines && temp != NULL) {
871 hold = temp;
872 update_line(temp, current_x);
Chris Allegretta95b0b522000-07-28 02:58:06 +0000873 if (temp == current)
874 currentcheck = 1;
875
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000876 temp = temp->next;
877 lines++;
878 }
Chris Allegrettaed022162000-08-03 16:54:11 +0000879 /* If noloop == 1, then we already did an edit_update without finishing
880 this function. So we don't run edit_update again */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000881 if (!currentcheck && !noloop) { /* Then current has run off the screen... */
Chris Allegrettada721be2000-07-31 01:26:42 +0000882 edit_update(current, CENTER);
Chris Allegrettaed022162000-08-03 16:54:11 +0000883 noloop = 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000884 } else if (noloop)
Chris Allegrettaed022162000-08-03 16:54:11 +0000885 noloop = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000886
887 if (lines <= editwinrows - 1)
888 while (lines <= editwinrows - 1) {
889 mvwaddstr(edit, lines, i, hblank);
890 lines++;
891 }
892 if (temp == NULL)
893 editbot = hold;
894 else
895 editbot = temp;
896}
897
898/*
Chris Allegrettaf1d33d32000-08-19 03:53:39 +0000899 * Same as above, but touch the window first so everything is redrawn.
900 */
901void edit_refresh_clearok(void)
902{
903 clearok(edit, TRUE);
904 edit_refresh();
905 clearok(edit, FALSE);
906}
907
908/*
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000909 * Nice generic routine to update the edit buffer given a pointer to the
910 * file struct =)
911 */
Chris Allegretta234a34d2000-07-29 04:33:38 +0000912void edit_update(filestruct * fileptr, int topmidbot)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000913{
Robert Siemborski29e9a762000-07-05 03:16:04 +0000914 int i = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000915 filestruct *temp;
916
917 if (fileptr == NULL)
918 return;
919
920 temp = fileptr;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000921 if (topmidbot == 2);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000922 else if (topmidbot == 0)
923 for (i = 0; i <= editwinrows - 1 && temp->prev != NULL; i++)
924 temp = temp->prev;
925 else
926 for (i = 0; i <= editwinrows / 2 && temp->prev != NULL; i++)
927 temp = temp->prev;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000928
Robert Siemborski29e9a762000-07-05 03:16:04 +0000929 edittop = temp;
930 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000931
932 edit_refresh();
933}
934
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000935/* This function updates current based on where current_y is, reset_cursor
936 does the opposite */
937void update_cursor(void)
938{
939 int i = 0;
940
941#ifdef DEBUG
942 fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
943 current_x);
944#endif
945
946 current = edittop;
947 while (i <= current_y - 1 && current->next != NULL) {
948 current = current->next;
949 i++;
950 }
951
952#ifdef DEBUG
953 fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
954#endif
955
956}
957
958/*
959 * Ask a question on the statusbar. Answer will be stored in answer
960 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
961 * otherwise, the valid shortcut key caught, Def is any editable text we
962 * want to put up by default.
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000963 *
964 * New arg tabs tells whether or not to allow tab completion.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000965 */
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000966int statusq(int tabs, shortcut s[], int slen, char *def, char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000967{
968 va_list ap;
969 char foo[133];
970 int ret;
971
972 bottombars(s, slen);
973
974 va_start(ap, msg);
975 vsnprintf(foo, 132, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000976 va_end(ap);
Chris Allegrettaa4d21622000-07-08 23:57:03 +0000977 strncat(foo, ": ", 132);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000978
979 wattron(bottomwin, A_REVERSE);
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000980 ret = nanogetstr(tabs, foo, def, s, slen, (strlen(foo) + 3));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000981 wattroff(bottomwin, A_REVERSE);
982
983 switch (ret) {
984
985 case NANO_FIRSTLINE_KEY:
986 do_first_line();
987 break;
988 case NANO_LASTLINE_KEY:
989 do_last_line();
990 break;
991 case NANO_CANCEL_KEY:
992 return -1;
993 default:
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000994 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000995 }
996
997#ifdef DEBUG
998 fprintf(stderr, _("I got \"%s\"\n"), answer);
999#endif
1000
1001 return ret;
1002}
1003
1004/*
1005 * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0 for
1006 * N, 2 for All (if all is non-zero when passed in) and -1 for abort (^C)
1007 */
1008int do_yesno(int all, int leavecursor, char *msg, ...)
1009{
1010 va_list ap;
1011 char foo[133];
1012 int kbinput, ok = -1;
1013
1014 /* Write the bottom of the screen */
1015 clear_bottomwin();
1016 wattron(bottomwin, A_REVERSE);
1017 blank_statusbar_refresh();
1018 wattroff(bottomwin, A_REVERSE);
1019
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001020 /* Remove gettext call for keybindings until we clear the thing up */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001021 if (!ISSET(NO_HELP)) {
1022 wmove(bottomwin, 1, 0);
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001023 onekey(" Y", _("Yes"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001024 if (all)
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001025 onekey(" A", _("All"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001026 wmove(bottomwin, 2, 0);
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001027 onekey(" N", _("No"));
1028 onekey("^C", _("Cancel"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001029 }
1030 va_start(ap, msg);
1031 vsnprintf(foo, 132, msg, ap);
1032 va_end(ap);
1033 wattron(bottomwin, A_REVERSE);
1034 mvwaddstr(bottomwin, 0, 0, foo);
1035 wattroff(bottomwin, A_REVERSE);
1036 wrefresh(bottomwin);
1037
1038 if (leavecursor == 1)
1039 reset_cursor();
1040
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001041 while (ok == -1) {
1042 kbinput = wgetch(edit);
1043
1044 switch (kbinput) {
1045 case 'Y':
1046 case 'y':
1047 ok = 1;
1048 break;
1049 case 'N':
1050 case 'n':
1051 ok = 0;
1052 break;
1053 case 'A':
1054 case 'a':
1055 if (all)
1056 ok = 2;
1057 break;
1058 case NANO_CONTROL_C:
1059 ok = -2;
1060 break;
1061 }
1062 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001063
1064 /* Then blank the screen */
1065 blank_statusbar_refresh();
1066
1067 if (ok == -2)
1068 return -1;
1069 else
1070 return ok;
1071}
1072
1073void statusbar(char *msg, ...)
1074{
1075 va_list ap;
1076 char foo[133];
1077 int start_x = 0;
1078
1079 va_start(ap, msg);
1080 vsnprintf(foo, 132, msg, ap);
1081 va_end(ap);
1082
1083 start_x = center_x - strlen(foo) / 2 - 1;
1084
1085 /* Blank out line */
1086 blank_statusbar();
1087
1088 wmove(bottomwin, 0, start_x);
1089
1090 wattron(bottomwin, A_REVERSE);
1091
1092 waddstr(bottomwin, "[ ");
1093 waddstr(bottomwin, foo);
1094 waddstr(bottomwin, " ]");
1095 wattroff(bottomwin, A_REVERSE);
1096 wrefresh(bottomwin);
1097
1098 if (ISSET(CONSTUPDATE))
1099 statblank = 1;
1100 else
1101 statblank = 25;
1102}
1103
1104void display_main_list(void)
1105{
1106 bottombars(main_list, MAIN_VISIBLE);
1107}
1108
1109int total_refresh(void)
1110{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001111 clearok(edit, TRUE);
1112 clearok(topwin, TRUE);
1113 clearok(bottomwin, TRUE);
1114 wnoutrefresh(edit);
1115 wnoutrefresh(topwin);
1116 wnoutrefresh(bottomwin);
1117 doupdate();
1118 clearok(edit, FALSE);
1119 clearok(topwin, FALSE);
1120 clearok(bottomwin, FALSE);
Chris Allegrettaf1d33d32000-08-19 03:53:39 +00001121 edit_refresh();
Chris Allegretta2a42af12000-09-12 23:02:49 +00001122 titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001123 return 1;
1124}
1125
1126void previous_line(void)
1127{
1128 if (current_y > 0)
1129 current_y--;
1130}
1131
1132int do_cursorpos(void)
1133{
1134 filestruct *fileptr;
1135 float linepct, bytepct;
1136 int i, tot = 0;
1137
1138 if (current == NULL || fileage == NULL)
1139 return 0;
1140
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001141 for (fileptr = fileage; fileptr != current && fileptr != NULL;
1142 fileptr = fileptr->next)
1143 tot += strlen(fileptr->data) + 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001144
1145 if (fileptr == NULL)
1146 return -1;
1147
1148 i = tot + current_x;;
1149
1150 for (fileptr = current->next; fileptr != NULL; fileptr = fileptr->next)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001151 tot += strlen(fileptr->data) + 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001152
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001153 if (totlines > 0)
1154 linepct = 100 * current->lineno / totlines;
1155 else
1156 linepct = 0;
1157
1158 if (totsize > 0)
1159 bytepct = 100 * i / totsize;
1160 else
1161 bytepct = 0;
1162
1163#ifdef DEBUG
1164 fprintf(stderr, _("do_cursorpos: linepct = %f, bytepct = %f\n"),
1165 linepct, bytepct);
1166#endif
1167
1168 statusbar(_("line %d of %d (%.0f%%), character %d of %d (%.0f%%)"),
1169 current->lineno, totlines, linepct, i, totsize, bytepct);
1170 reset_cursor();
1171 return 1;
1172}
1173
1174/* Our broken, non-shortcut list compliant help function.
1175 But hey, it's better than nothing, and it's dynamic! */
1176int do_help(void)
1177{
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001178#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001179 char *ptr = help_text, *end;
1180 int i, j, row = 0, page = 1, kbinput = 0, no_more = 0;
1181 int no_help_flag = 0;
1182
Chris Allegrettad1627cf2000-12-18 05:03:16 +00001183
1184 /* Oh well, they've asked for the help menu, if the keypad is not on now
1185 we're going to have to turn it on */
1186 keypad_on(TRUE);
1187
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001188 blank_edit();
1189 curs_set(0);
1190 blank_statusbar();
1191
1192 if (ISSET(NO_HELP)) {
1193
1194 no_help_flag = 1;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001195 delwin(bottomwin);
1196 bottomwin = newwin(3, COLS, LINES - 3, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001197 keypad(bottomwin, TRUE);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001198
1199 editwinrows -= no_help();
1200 UNSET(NO_HELP);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001201 bottombars(help_list, HELP_LIST_LEN);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001202 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001203 bottombars(help_list, HELP_LIST_LEN);
1204
1205 do {
1206 ptr = help_text;
1207 switch (kbinput) {
1208 case NANO_NEXTPAGE_KEY:
1209 case NANO_NEXTPAGE_FKEY:
1210 case KEY_NPAGE:
1211 if (!no_more) {
1212 blank_edit();
1213 page++;
1214 }
1215 break;
1216 case NANO_PREVPAGE_KEY:
1217 case NANO_PREVPAGE_FKEY:
1218 case KEY_PPAGE:
1219 if (page > 1) {
1220 no_more = 0;
1221 blank_edit();
1222 page--;
1223 }
1224 break;
1225 }
1226
1227 /* Calculate where in the text we should be based on the page */
1228 for (i = 1; i < page; i++) {
1229 row = 0;
1230 j = 0;
Chris Allegretta44e73df2000-09-07 03:37:38 +00001231
1232 while (row < editwinrows - 2 && *ptr != '\0') {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001233 if (*ptr == '\n' || j == COLS - 5) {
1234 j = 0;
1235 row++;
1236 }
1237 ptr++;
1238 j++;
1239 }
1240 }
1241
Chris Allegretta44e73df2000-09-07 03:37:38 +00001242 if (i > 1) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001243
Chris Allegretta44e73df2000-09-07 03:37:38 +00001244 }
1245
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001246 i = 0;
1247 j = 0;
1248 while (i < editwinrows && *ptr != '\0') {
1249 end = ptr;
1250 while (*end != '\n' && *end != '\0' && j != COLS - 5) {
1251 end++;
1252 j++;
1253 }
1254 if (j == COLS - 5) {
1255
1256 /* Don't print half a word if we've run of of space */
1257 while (*end != ' ' && *end != '\0') {
1258 end--;
1259 j--;
1260 }
1261 }
1262 mvwaddnstr(edit, i, 0, ptr, j);
1263 j = 0;
1264 i++;
1265 if (*end == '\n')
1266 end++;
1267 ptr = end;
1268 }
1269 if (*ptr == '\0') {
1270 no_more = 1;
1271 continue;
1272 }
Chris Allegrettad1627cf2000-12-18 05:03:16 +00001273 } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY &&
1274 kbinput != NANO_EXIT_FKEY);
1275
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001276 if (no_help_flag) {
1277 werase(bottomwin);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001278 wrefresh(bottomwin);
1279 delwin(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001280 SET(NO_HELP);
1281 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
1282 keypad(bottomwin, TRUE);
1283 editwinrows += no_help();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001284 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001285 display_main_list();
1286
1287 curs_set(1);
1288 edit_refresh();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001289#elif defined(NANO_SMALL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001290 nano_small_msg();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001291#elif defined(DISABLE_HELP)
1292 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001293#endif
1294
1295 return 1;
1296}
1297
1298/* Dump the current file structure to stderr */
1299void dump_buffer(filestruct * inptr)
1300{
1301#ifdef DEBUG
1302 filestruct *fileptr;
1303
1304 if (inptr == fileage)
1305 fprintf(stderr, _("Dumping file buffer to stderr...\n"));
1306 else if (inptr == cutbuffer)
1307 fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
1308 else
1309 fprintf(stderr, _("Dumping a buffer to stderr...\n"));
1310
1311 fileptr = inptr;
1312 while (fileptr != NULL) {
1313 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1314 fflush(stderr);
1315 fileptr = fileptr->next;
1316 }
1317#endif /* DEBUG */
1318}
1319
1320void dump_buffer_reverse(filestruct * inptr)
1321{
1322#ifdef DEBUG
1323 filestruct *fileptr;
1324
1325 fileptr = filebot;
1326 while (fileptr != NULL) {
1327 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1328 fflush(stderr);
1329 fileptr = fileptr->prev;
1330 }
1331#endif /* DEBUG */
1332}
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001333
1334/* Fix editbot based on the assumption that edittop is correct */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001335void fix_editbot(void)
1336{
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001337 int i;
1338 editbot = edittop;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001339 for (i = 0; (i <= editwinrows - 1) && (editbot->next != NULL)
1340 && (editbot != filebot); i++, editbot = editbot->next);
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001341}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001342
Chris Allegrettafb62f732000-12-05 11:36:41 +00001343/* highlight the current word being replaced or spell checked */
1344void do_replace_highlight(int highlight_flag, char *word)
1345{
1346 char *highlight_word = NULL;
1347 int x, y;
1348
1349 highlight_word = mallocstrcpy(highlight_word, &current->data[current_x]);
1350 highlight_word[strlen(word)] = '\0';
1351
1352 /* adjust output when word extends beyond screen*/
1353
1354 x = xplustabs();
1355 y = get_page_end_virtual(get_page_from_virtual(x)) + 1;
1356
1357 if ((COLS - (y - x) + strlen(word)) > COLS) {
1358 highlight_word[y - x - 1] = '$';
1359 highlight_word[y - x] = '\0';
1360 }
1361
1362 /* OK display the output */
1363
1364 reset_cursor();
1365
1366 if (highlight_flag)
1367 wattron(edit, A_REVERSE);
1368
1369 waddstr(edit, highlight_word);
1370
1371 if (highlight_flag)
1372 wattroff(edit, A_REVERSE);
1373
1374 free(highlight_word);
1375}
1376
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001377#ifdef NANO_EXTRA
Chris Allegretta7cd9f742000-11-25 20:17:28 +00001378#define CREDIT_LEN 45
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001379void do_credits(void)
1380{
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001381 int i, j = 0, k, place = 0, start_x;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001382 char *what;
1383
1384 char *nanotext = _("The nano text editor");
1385 char *version = _("version ");
1386 char *brought = _("Brought to you by:");
1387 char *specialthx = _("Special thanks to:");
1388 char *fsf = _("The Free Software Foundation");
1389 char *ncurses = _("Pavel Curtis, Zeyd Ben-Halim and Eric S. Raymond for ncurses");
1390 char *anyonelse = _("and anyone else we forgot...");
1391 char *thankyou = _("Thank you for using nano!\n");
1392
1393 char *credits[CREDIT_LEN] = {nanotext,
1394 version,
1395 VERSION,
1396 "",
1397 brought,
1398 "Chris Allegretta",
1399 "Jordi Mallach",
1400 "Adam Rogoyski",
1401 "Rob Siemborski",
1402 "Rocco Corsi",
1403 "Ken Tyler",
1404 "Sven Guckes",
1405 "Florian König",
1406 "Pauli Virtanen",
1407 "Daniele Medri",
1408 "Clement Laforet",
1409 "Tedi Heriyanto",
Chris Allegrettaa131c7c2000-11-25 19:59:41 +00001410 "Bill Soudan",
Chris Allegretta7cd9f742000-11-25 20:17:28 +00001411 "Christian Weisgerber",
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001412 "Erik Anderson",
1413 "Big Gaute",
1414 "Joshua Jensen",
1415 "",
1416 specialthx,
1417 "Plattsburgh State University",
1418 "Benet Laboratories",
1419 "Amy Allegretta",
1420 "Linda Young",
1421 "Jeremy Robichaud",
1422 "Richard Kolb II",
1423 fsf,
1424 "Linus Torvalds",
1425 ncurses,
1426 anyonelse,
1427 thankyou,
1428 "", "", "", "",
1429 "(c) 2000 Chris Allegretta",
1430 "", "", "", "",
1431 "www.nano-editor.org"
1432 };
1433
1434 curs_set(0);
1435 nodelay(edit, TRUE);
1436 blank_bottombars();
1437 mvwaddstr(topwin, 0, 0, hblank);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001438 blank_edit();
1439 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001440 wrefresh(bottomwin);
1441 wrefresh(topwin);
1442
1443 while (wgetch(edit) == ERR) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001444 for (k = 0; k <= 1; k++) {
1445 blank_edit();
1446 for (i = editwinrows / 2 - 1; i >= (editwinrows / 2 - 1 - j); i--) {
1447 mvwaddstr(edit, i * 2 - k, 0, hblank);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001448
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001449 if (place - (editwinrows / 2 - 1 - i) < CREDIT_LEN)
1450 what = credits[place - (editwinrows / 2 - 1 - i)];
1451 else
1452 what = "";
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001453
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001454 start_x = center_x - strlen(what) / 2 - 1;
1455 mvwaddstr(edit, i * 2 - k, start_x, what);
1456 }
1457 usleep(700000);
1458 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001459 }
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001460 if (j < editwinrows / 2 - 1)
1461 j++;
1462
1463 place++;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001464
1465 if (place >= CREDIT_LEN + editwinrows / 2)
1466 break;
1467 }
1468
1469 nodelay(edit, FALSE);
1470 curs_set(1);
1471 display_main_list();
1472 total_refresh();
1473 }
1474#endif