blob: db8902c45d21e11ec70f20951ebc49476c5dfe83 [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 Allegrettaa2ea1932000-06-06 05:53:49 +000025#include "config.h"
26#include "proto.h"
27#include "nano.h"
28
29#ifndef NANO_SMALL
30#include <libintl.h>
31#define _(string) gettext(string)
32#else
33#define _(string) (string)
34#endif
35
36static int statblank = 0; /* Number of keystrokes left after
37 we call statubar() before we
38 actually blank the statusbar */
Robert Siemborskid8510b22000-06-06 23:04:06 +000039
40/* Local Function Prototypes for only winio.c */
41inline int get_page_from_virtual(int virtual);
42inline int get_page_start_virtual(int page);
43inline int get_page_end_virtual(int page);
44
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000045/* Window I/O */
46
47int do_first_line(void)
48{
49 current = fileage;
50 placewewant = 0;
51 current_x = 0;
Chris Allegretta234a34d2000-07-29 04:33:38 +000052 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000053 return 1;
54}
55
56int do_last_line(void)
57{
58 current = filebot;
59 placewewant = 0;
60 current_x = 0;
Chris Allegretta234a34d2000-07-29 04:33:38 +000061 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000062 return 1;
63}
64
65/* Like xplustabs, but for a specifc index of a speficific filestruct */
66int xpt(filestruct * fileptr, int index)
67{
68 int i, tabs = 0;
69
70 if (fileptr == NULL || fileptr->data == NULL)
71 return 0;
72
73 for (i = 0; i < index && fileptr->data[i] != 0; i++) {
74 tabs++;
75
76 if (fileptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +000077 if (tabs % tabsize == 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000078 else
Chris Allegretta6d690a32000-08-03 22:51:21 +000079 tabs += tabsize - (tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000080 } else if (fileptr->data[i] & 0x80)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000081 /* Make 8 bit chars only 1 collumn! */
82 ;
83 else if (fileptr->data[i] < 32)
84 tabs++;
85 }
86
87 return tabs;
88}
89
90
91/* Return the actual place on the screen of current->data[current_x], which
92 should always be > current_x */
93int xplustabs(void)
94{
95 return xpt(current, current_x);
96}
97
98
Robert Siemborskid8510b22000-06-06 23:04:06 +000099/* Return what current_x should be, given xplustabs() for the line,
100 * given a start position in the filestruct's data */
101int actual_x_from_start(filestruct * fileptr, int xplus, int start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000102{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000103 int i, tot = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000104
105 if (fileptr == NULL || fileptr->data == NULL)
106 return 0;
107
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000108 for (i = start; tot <= xplus && fileptr->data[i] != 0; i++, tot++)
Robert Siemborskid8510b22000-06-06 23:04:06 +0000109 if (fileptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000110 if (tot % tabsize == 0)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000111 tot++;
112 else
Chris Allegretta6d690a32000-08-03 22:51:21 +0000113 tot += tabsize - (tot % tabsize);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000114 } else if (fileptr->data[i] & 0x80)
115 tot++; /* Make 8 bit chars only 1 column (again) */
116 else if (fileptr->data[i] < 32)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000117 tot += 2;
118
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000119#ifdef DEBUG
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000120 fprintf(stderr, _("actual_x_from_start for xplus=%d returned %d\n"),
121 xplus, i);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000122#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +0000123 return i - start;
124}
125
126/* Opposite of xplustabs */
127inline int actual_x(filestruct * fileptr, int xplus)
128{
129 return actual_x_from_start(fileptr, xplus, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000130}
131
132/* a strlen with tabs factored in, similar to xplustabs() */
133int strlenpt(char *buf)
134{
135 int i, tabs = 0;
136
137 if (buf == NULL)
138 return 0;
139
140 for (i = 0; buf[i] != 0; i++) {
141 tabs++;
142
143 if (buf[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000144 if (tabs % tabsize == 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000145 else
Chris Allegretta6d690a32000-08-03 22:51:21 +0000146 tabs += tabsize - (tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000147 } else if (buf[i] & 0x80)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000148 /* Make 8 bit chars only 1 collumn! */
149 ;
150 else if (buf[i] < 32)
151 tabs++;
152 }
153
154 return tabs;
155}
156
157
158/* resets current_y based on the position of current and puts the cursor at
159 (current_y, current_x) */
160void reset_cursor(void)
161{
162 filestruct *ptr = edittop;
163 int x;
164
165 current_y = 0;
166
167 while (ptr != current && ptr != editbot && ptr->next != NULL) {
168 ptr = ptr->next;
169 current_y++;
170 }
171
172 x = xplustabs();
173 if (x <= COLS - 2)
Robert Siemborskid8510b22000-06-06 23:04:06 +0000174 wmove(edit, current_y, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000175 else
Robert Siemborskid8510b22000-06-06 23:04:06 +0000176 wmove(edit, current_y, x -
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000177 get_page_start_virtual(get_page_from_virtual(x)));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000178
179}
180
181void blank_bottombars(void)
182{
183 int i = no_help()? 3 : 1;
184
185 for (; i <= 2; i++)
186 mvwaddstr(bottomwin, i, 0, hblank);
187
188}
189
190void blank_edit(void)
191{
192 int i;
193 for (i = 0; i <= editwinrows - 1; i++)
194 mvwaddstr(edit, i, 0, hblank);
195 wrefresh(edit);
196}
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 Allegretta04d848e2000-11-05 17:54:41 +0000251 int x_left = 0, inputlen, tabbed = 0;
Chris Allegretta31925e42000-11-02 04:40:39 +0000252 char *inputbuf;
253
254 inputbuf = nmalloc(strlen(def) + 1);
255 inputbuf[0] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000256
257 x_left = strlen(buf);
258 x = strlen(def) + x_left;
259
260 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +0000261 if (strlen(def) > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000262 strcpy(inputbuf, def);
Chris Allegretta31925e42000-11-02 04:40:39 +0000263
264 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000265
266 while ((kbinput = wgetch(bottomwin)) != 13) {
267 for (j = 0; j <= slen - 1; j++) {
268 if (kbinput == s[j].val) {
Chris Allegrettaf5deac32000-11-02 05:10:26 +0000269 answer = mallocstrcpy(answer, "");
Chris Allegretta92d2bab2000-11-02 14:53:46 +0000270 free(inputbuf);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000271 return s[j].val;
272 }
273 }
274 xend = strlen(buf) + strlen(inputbuf);
275
Chris Allegretta04d848e2000-11-05 17:54:41 +0000276 if (kbinput != '\t')
277 tabbed = 0;
278
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000279 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000280 /* Stuff we want to equate with <enter>, ASCII 13 */
281 case 343:
Chris Allegrettaf9b6c9b2000-10-18 19:35:59 +0000282 ungetch(13); /* Enter on iris-ansi $TERM, sometimes */
283 break;
284
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000285 case KEY_HOME:
286 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000287 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000288 break;
289 case KEY_END:
290 x = x_left + strlen(inputbuf);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000291 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000292 break;
293 case KEY_RIGHT:
294
295 if (x < xend)
296 x++;
297 wmove(bottomwin, 0, x);
298 break;
299 case NANO_CONTROL_D:
300 if (strlen(inputbuf) > 0 && (x - x_left) != strlen(inputbuf)) {
301 memmove(inputbuf + (x - x_left),
302 inputbuf + (x - x_left) + 1,
303 strlen(inputbuf) - (x - x_left) - 1);
304 inputbuf[strlen(inputbuf) - 1] = 0;
305 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000306 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000307 break;
308 case NANO_CONTROL_K:
309 case NANO_CONTROL_U:
310 *inputbuf = 0;
311 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000312 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000313 break;
314 case KEY_BACKSPACE:
315 case KEY_DC:
316 case 127:
317 case NANO_CONTROL_H:
318 if (strlen(inputbuf) > 0) {
319 if (x == (x_left + strlen(inputbuf)))
320 inputbuf[strlen(inputbuf) - 1] = 0;
321 else if (x - x_left) {
322 memmove(inputbuf + (x - x_left) - 1,
323 inputbuf + (x - x_left),
324 strlen(inputbuf) - (x - x_left));
325 inputbuf[strlen(inputbuf) - 1] = 0;
326 }
327 }
Chris Allegretta04d848e2000-11-05 17:54:41 +0000328 if (x > strlen(buf))
329 x--;
Chris Allegretta31925e42000-11-02 04:40:39 +0000330 nanoget_repaint(buf, inputbuf, x);
Chris Allegretta04d848e2000-11-05 17:54:41 +0000331 break;
332 case NANO_CONTROL_I:
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000333 if (allowtabs) {
334 tabbed++;
335 x += input_tab(inputbuf, (x - x_left), tabbed - 1);
336 nanoget_repaint(buf, inputbuf, x);
337 tabbed = 1;
338 }
Chris Allegretta04d848e2000-11-05 17:54:41 +0000339 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000340 case KEY_LEFT:
341 if (x > strlen(buf))
342 x--;
343 wmove(bottomwin, 0, x);
344 break;
345 case KEY_UP:
346 case KEY_DOWN:
347 break;
348
349 case 27:
350 switch (kbinput = wgetch(edit)) {
351 case 79:
352 switch (kbinput = wgetch(edit)) {
353 case 70:
354 x = x_left + strlen(inputbuf);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000355 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000356 break;
357 case 72:
358 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000359 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000360 break;
361 }
362 break;
363 case 91:
364 switch (kbinput = wgetch(edit)) {
365 case 'C':
366 if (x < xend)
367 x++;
368 wmove(bottomwin, 0, x);
369 break;
370 case 'D':
371 if (x > strlen(buf))
372 x--;
373 wmove(bottomwin, 0, x);
374 break;
375 case 49:
376 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000377 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000378 goto skip_126;
379 case 51:
380 if (strlen(inputbuf) > 0
381 && (x - x_left) != strlen(inputbuf)) {
382 memmove(inputbuf + (x - x_left),
383 inputbuf + (x - x_left) + 1,
384 strlen(inputbuf) - (x - x_left) - 1);
385 inputbuf[strlen(inputbuf) - 1] = 0;
386 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000387 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000388 goto skip_126;
389 case 52:
390 x = x_left + strlen(inputbuf);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000391 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000392 goto skip_126;
393 skip_126:
394 nodelay(edit, TRUE);
395 kbinput = wgetch(edit);
396 if (kbinput == 126 || kbinput == ERR)
397 kbinput = -1;
398 nodelay(edit, FALSE);
399 break;
400 }
401 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000402 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000403 break;
404
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000405 default:
406 if (kbinput < 32)
407 break;
Chris Allegretta31925e42000-11-02 04:40:39 +0000408
409 inputlen = strlen(inputbuf);
410 inputbuf = nrealloc(inputbuf, inputlen + 2);
411
412 memmove(&inputbuf[x - x_left + 1],
413 &inputbuf[x - x_left],
414 inputlen - (x - x_left) + 1);
415 inputbuf[x - x_left] = kbinput;
416
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000417 x++;
418
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000419 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000420#ifdef DEBUG
421 fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput);
422#endif
423 }
424 wrefresh(bottomwin);
425 }
426
Chris Allegretta31925e42000-11-02 04:40:39 +0000427 answer = mallocstrcpy(answer, inputbuf);
Chris Allegretta92d2bab2000-11-02 14:53:46 +0000428 free(inputbuf);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000429
Chris Allegretta105da332000-10-31 05:10:10 +0000430 /* Now that the text is editable instead of bracketed, we have to
431 check for answer == def, instead of answer == "" */
Chris Allegretta71844ba2000-11-03 14:23:00 +0000432 if (((ISSET(PICO_MSGS)) && !strcmp(answer, "")) ||
433 ((!ISSET(PICO_MSGS)) && !strcmp(answer, def)))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000434 return -2;
435 else
436 return 0;
437}
438
439void horizbar(WINDOW * win, int y)
440{
441 wattron(win, A_REVERSE);
442 mvwaddstr(win, 0, 0, hblank);
443 wattroff(win, A_REVERSE);
444}
445
446void titlebar(void)
447{
448 int namelen, space;
449
450 horizbar(topwin, 0);
451 wattron(topwin, A_REVERSE);
452 mvwaddstr(topwin, 0, 3, VERMSG);
453
454 space = COLS - strlen(VERMSG) - strlen(VERSION) - 21;
455
456 namelen = strlen(filename);
457
458 if (!strcmp(filename, ""))
459 mvwaddstr(topwin, 0, center_x - 6, _("New Buffer"));
460 else {
461 if (namelen > space) {
462 waddstr(topwin, _(" File: ..."));
463 waddstr(topwin, &filename[namelen - space]);
464 } else {
465 mvwaddstr(topwin, 0, center_x - (namelen / 2 + 1), "File: ");
466 waddstr(topwin, filename);
467 }
468 }
469 if (ISSET(MODIFIED))
470 mvwaddstr(topwin, 0, COLS - 10, _("Modified"));
471 wattroff(topwin, A_REVERSE);
472 wrefresh(topwin);
473 reset_cursor();
474}
475
476void onekey(char *keystroke, char *desc)
477{
478 char description[80];
479
Chris Allegrettae7034c62000-09-15 03:31:09 +0000480 snprintf(description, 12, " %-10s", desc);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000481 wattron(bottomwin, A_REVERSE);
482 waddstr(bottomwin, keystroke);
483 wattroff(bottomwin, A_REVERSE);
484 waddstr(bottomwin, description);
485}
486
487void clear_bottomwin(void)
488{
489 if (ISSET(NO_HELP))
490 return;
491
492 mvwaddstr(bottomwin, 1, 0, hblank);
493 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000494}
495
496void bottombars(shortcut s[], int slen)
497{
498 int i, j, k;
499 char keystr[10];
500
501 if (ISSET(NO_HELP))
502 return;
503
504 /* Determine how many extra spaces are needed to fill the bottom of the screen */
505 k = COLS / 6 - 13;
506
507 clear_bottomwin();
508 wmove(bottomwin, 1, 0);
509 for (i = 0; i <= slen - 1; i += 2) {
Robert Siemborski6af14312000-07-01 21:34:26 +0000510 snprintf(keystr, 10, "^%c", s[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000511 onekey(keystr, s[i].desc);
512
513 for (j = 0; j < k; j++)
514 waddch(bottomwin, ' ');
515 }
516
517 wmove(bottomwin, 2, 0);
518 for (i = 1; i <= slen - 1; i += 2) {
Robert Siemborski6af14312000-07-01 21:34:26 +0000519 snprintf(keystr, 10, "^%c", s[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000520 onekey(keystr, s[i].desc);
521
522 for (j = 0; j < k; j++)
523 waddch(bottomwin, ' ');
524 }
525
526 wrefresh(bottomwin);
527
528}
529
530/* If modified is not already set, set it and update titlebar */
531void set_modified(void)
532{
533 if (!ISSET(MODIFIED)) {
534 SET(MODIFIED);
535 titlebar();
536 wrefresh(topwin);
537 }
538}
539
Robert Siemborski9d584552000-07-08 00:41:29 +0000540/* And so start the display update routines */
541/* Given a column, this returns the "page" it is on */
542/* "page" in the case of the display columns, means which set of 80 */
543/* characters is viewable (ie: page 1 shows from 1 to COLS) */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000544inline int get_page_from_virtual(int virtual)
545{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000546 int page = 2;
547
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000548 if (virtual <= COLS - 2)
549 return 1;
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000550 virtual -= (COLS - 2);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000551
552 while (virtual > COLS - 2 - 7) {
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000553 virtual -= (COLS - 2 - 7);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000554 page++;
555 }
556
557 return page;
558}
559
Robert Siemborski9d584552000-07-08 00:41:29 +0000560/* The inverse of the above function */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000561inline int get_page_start_virtual(int page)
562{
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000563 int virtual;
564 virtual = --page * (COLS - 7);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000565 if (page)
566 virtual -= 2 * page - 1;
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000567 return virtual;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000568}
569
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000570inline int get_page_end_virtual(int page)
571{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000572 return get_page_start_virtual(page) + COLS - 1;
573}
574
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000575#ifndef NANO_SMALL
Robert Siemborski9d584552000-07-08 00:41:29 +0000576/* This takes care of the case where there is a mark that covers only */
577/* the current line. */
578
Chris Allegrettab275aac2000-07-08 01:22:33 +0000579/* It expects a line with no tab characers (ie: the type that edit_add */
Robert Siemborski9d584552000-07-08 00:41:29 +0000580/* deals with */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000581void add_marked_sameline(int begin, int end, filestruct * fileptr, int y,
582 int virt_cur_x, int this_page)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000583{
Robert Siemborski9d584552000-07-08 00:41:29 +0000584 /*
585 * The general idea is to break the line up into 3 sections: before
586 * the mark, the mark, and after the mark. We then paint each in
587 * turn (for those that are currently visible, of course
588 *
589 * 3 start points: 0 -> begin, begin->end, end->strlen(data)
590 * in data : pre sel post
591 */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000592 int this_page_start = get_page_start_virtual(this_page),
Robert Siemborski53875912000-06-16 04:25:30 +0000593 this_page_end = get_page_end_virtual(this_page);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000594
Robert Siemborskid8510b22000-06-06 23:04:06 +0000595 /* likewise, 3 data lengths */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000596 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 +0000597
598 /* now fix the start locations & lengths according to the cursor's
599 * position (ie: our page) */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000600 if (pre_data_len < this_page_start)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000601 pre_data_len = 0;
602 else
603 pre_data_len -= this_page_start;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000604
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000605 if (begin < this_page_start)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000606 begin = this_page_start;
607
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000608 if (end < this_page_start)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000609 end = this_page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000610
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000611 if (begin > this_page_end)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000612 begin = this_page_end;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000613
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000614 if (end > this_page_end)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000615 end = this_page_end;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000616
Robert Siemborski9d584552000-07-08 00:41:29 +0000617 /* Now calculate the lengths */
Robert Siemborskia9addc72000-06-17 06:06:35 +0000618 sel_data_len = end - begin;
619 post_data_len = this_page_end - end;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000620
Robert Siemborski9d584552000-07-08 00:41:29 +0000621 /* Paint this line! */
Robert Siemborski53875912000-06-16 04:25:30 +0000622 mvwaddnstr(edit, y, 0, &fileptr->data[this_page_start], pre_data_len);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000623 wattron(edit, A_REVERSE);
Robert Siemborskia9addc72000-06-17 06:06:35 +0000624 mvwaddnstr(edit, y, begin - this_page_start,
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000625 &fileptr->data[begin], sel_data_len);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000626 wattroff(edit, A_REVERSE);
Robert Siemborskia9addc72000-06-17 06:06:35 +0000627 mvwaddnstr(edit, y, end - this_page_start,
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000628 &fileptr->data[end], post_data_len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000629}
630#endif
631
Robert Siemborski9d584552000-07-08 00:41:29 +0000632/* edit_add takes care of the job of actually painting a line into the
633 * edit window.
634 *
635 * Called only from update_line. Expects a converted-to-not-have-tabs
Robert Siemborski53875912000-06-16 04:25:30 +0000636 * line */
637void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000638 int virt_mark_beginx, int this_page)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000639{
640#ifndef NANO_SMALL
Robert Siemborski9d584552000-07-08 00:41:29 +0000641 /* There are quite a few cases that could take place, we'll deal
642 * with them each in turn */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000643 if (ISSET(MARK_ISSET)
Robert Siemborski9d584552000-07-08 00:41:29 +0000644 && !((fileptr->lineno > mark_beginbuf->lineno
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000645 && fileptr->lineno > current->lineno)
646 || (fileptr->lineno < mark_beginbuf->lineno
647 && fileptr->lineno < current->lineno))) {
648 /* If we get here we are on a line that is atleast
649 * partially selected. The lineno checks above determined
650 * that */
651 if (fileptr != mark_beginbuf && fileptr != current) {
652 /* We are on a completely marked line, paint it all
653 * inverse */
654 wattron(edit, A_REVERSE);
655 mvwaddnstr(edit, yval, 0, fileptr->data, COLS);
656 wattroff(edit, A_REVERSE);
657 } else if (fileptr == mark_beginbuf && fileptr == current) {
658 /* Special case, we're still on the same line we started
659 * marking -- so we call our helper function */
660 if (virt_cur_x < virt_mark_beginx) {
661 /* To the right of us is marked */
662 add_marked_sameline(virt_cur_x, virt_mark_beginx,
663 fileptr, yval, virt_cur_x, this_page);
664 } else {
665 /* To the left of us is marked */
666 add_marked_sameline(virt_mark_beginx, virt_cur_x,
667 fileptr, yval, virt_cur_x, this_page);
668 }
669 } else if (fileptr == mark_beginbuf) {
670 /*
671 * we're updating the line that was first marked
672 * but we're not currently on it. So we want to
673 * figur out which half to invert based on our
674 * relative line numbers.
675 *
676 * i.e. If we're above the "beginbuf" line, we want to
677 * mark the left side. Otherwise we're below, so we
678 * mark the right
679 */
680 int target;
681
682 if (mark_beginbuf->lineno > current->lineno)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000683 wattron(edit, A_REVERSE);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000684
685 target =
686 (virt_mark_beginx <
687 COLS - 1) ? virt_mark_beginx : COLS - 1;
688
689 mvwaddnstr(edit, yval, 0, fileptr->data, target);
690
691 if (mark_beginbuf->lineno < current->lineno)
692 wattron(edit, A_REVERSE);
693 else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000694 wattroff(edit, A_REVERSE);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000695
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000696 target = (COLS - 1) - virt_mark_beginx;
697 if (target < 0)
698 target = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000699
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000700 mvwaddnstr(edit, yval, virt_mark_beginx,
701 &fileptr->data[virt_mark_beginx], target);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000702
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000703 if (mark_beginbuf->lineno < current->lineno)
704 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000705
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000706 } else if (fileptr == current) {
707 /* we're on the cursors line, but it's not the first
708 * one we marked. Similar to the previous logic. */
709 int this_page_start = get_page_start_virtual(this_page),
710 this_page_end = get_page_end_virtual(this_page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000711
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000712 if (mark_beginbuf->lineno < current->lineno)
713 wattron(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000714
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000715 if (virt_cur_x > COLS - 2) {
716 mvwaddnstr(edit, yval, 0,
717 &fileptr->data[this_page_start],
718 virt_cur_x - this_page_start);
719 } else {
720 mvwaddnstr(edit, yval, 0, fileptr->data, virt_cur_x);
721 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000722
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000723 if (mark_beginbuf->lineno > current->lineno)
724 wattron(edit, A_REVERSE);
725 else
726 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000727
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000728 if (virt_cur_x > COLS - 2)
729 mvwaddnstr(edit, yval, virt_cur_x - this_page_start,
730 &fileptr->data[virt_cur_x],
731 this_page_end - virt_cur_x);
732 else
733 mvwaddnstr(edit, yval, virt_cur_x,
734 &fileptr->data[virt_cur_x], COLS - virt_cur_x);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000735
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000736 if (mark_beginbuf->lineno > current->lineno)
737 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000738 }
739
740 } else
741#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000742 /* Just paint the string (no mark on this line) */
Robert Siemborskia9addc72000-06-17 06:06:35 +0000743 mvwaddnstr(edit, yval, 0, &fileptr->data[start],
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000744 get_page_end_virtual(this_page) - start);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000745}
746
747/*
Robert Siemborski9d584552000-07-08 00:41:29 +0000748 * Just update one line in the edit buffer. Basically a wrapper for
749 * edit_add
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000750 *
751 * index gives is a place in the string to update starting from.
752 * Likely args are current_x or 0.
753 */
754void update_line(filestruct * fileptr, int index)
755{
756 filestruct *filetmp;
Robert Siemborski53875912000-06-16 04:25:30 +0000757 int line = 0, col = 0;
758 int virt_cur_x = current_x, virt_mark_beginx = mark_beginx;
759 char *realdata, *tmp;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000760 int i, pos, len, page;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000761
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000762 if (!fileptr)
763 return;
Robert Siemborski53154a72000-06-18 00:11:03 +0000764
Robert Siemborski53875912000-06-16 04:25:30 +0000765 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000766 for (filetmp = edittop; filetmp != fileptr && filetmp != editbot;
767 filetmp = filetmp->next)
768 line++;
769
770 mvwaddstr(edit, line, 0, hblank);
771
Robert Siemborski53875912000-06-16 04:25:30 +0000772 /* Next, convert all the tabs to spaces so everything else is easy */
773 index = xpt(fileptr, index);
774
775 realdata = fileptr->data;
776 len = strlen(realdata);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000777 fileptr->data = nmalloc(xpt(fileptr, len) + 1);
Robert Siemborski53875912000-06-16 04:25:30 +0000778
779 pos = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000780 for (i = 0; i < len; i++) {
781 if (realdata[i] == '\t') {
Robert Siemborski53875912000-06-16 04:25:30 +0000782 do {
783 fileptr->data[pos++] = ' ';
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000784 if (i < current_x)
785 virt_cur_x++;
786 if (i < mark_beginx)
787 virt_mark_beginx++;
Chris Allegretta6d690a32000-08-03 22:51:21 +0000788 } while (pos % tabsize);
Robert Siemborski53875912000-06-16 04:25:30 +0000789 /* must decrement once to account for tab-is-one-character */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000790 if (i < current_x)
791 virt_cur_x--;
792 if (i < mark_beginx)
793 virt_mark_beginx--;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000794 } else if (realdata[i] >= 1 && realdata[i] <= 26) {
795 /* Treat control characters as ^letter */
Chris Allegretta6306a112000-09-02 07:55:41 +0000796 fileptr->data[pos++] = '^';
797 fileptr->data[pos++] = realdata[i] + 64;
Robert Siemborski53875912000-06-16 04:25:30 +0000798 } else {
799 fileptr->data[pos++] = realdata[i];
800 }
801 }
802
803 fileptr->data[pos] = '\0';
804
805 /* Now, Paint the line */
806 if (current == fileptr && index > COLS - 2) {
Robert Siemborskia9addc72000-06-17 06:06:35 +0000807 /* This handles when the current line is beyond COLS */
808 /* It requires figureing out what page we're at */
809 page = get_page_from_virtual(index);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000810 col = get_page_start_virtual(page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000811
Robert Siemborskia9addc72000-06-17 06:06:35 +0000812 edit_add(filetmp, line, col, virt_cur_x, virt_mark_beginx, page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000813 mvwaddch(edit, line, 0, '$');
814
Robert Siemborskid8510b22000-06-06 23:04:06 +0000815 if (strlenpt(fileptr->data) > get_page_end_virtual(page))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000816 mvwaddch(edit, line, COLS - 1, '$');
Robert Siemborskid8510b22000-06-06 23:04:06 +0000817 } else {
Robert Siemborskia9addc72000-06-17 06:06:35 +0000818 /* It's not the current line means that it's at x=0 and page=1 */
819 /* If it is the current line, then we're in the same boat */
820 edit_add(filetmp, line, 0, virt_cur_x, virt_mark_beginx, 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000821
Robert Siemborski53875912000-06-16 04:25:30 +0000822 if (strlenpt(&filetmp->data[col]) > COLS)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000823 mvwaddch(edit, line, COLS - 1, '$');
Robert Siemborskid8510b22000-06-06 23:04:06 +0000824 }
Robert Siemborski53875912000-06-16 04:25:30 +0000825
826 /* Clean up our mess */
827 tmp = fileptr->data;
828 fileptr->data = realdata;
829 free(tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000830}
831
832void center_cursor(void)
833{
834 current_y = editwinrows / 2;
835 wmove(edit, current_y, current_x);
836}
837
838/* Refresh the screen without changing the position of lines */
839void edit_refresh(void)
840{
Chris Allegrettaed022162000-08-03 16:54:11 +0000841 static int noloop = 0;
Chris Allegretta95b0b522000-07-28 02:58:06 +0000842 int lines = 0, i = 0, currentcheck = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000843 filestruct *temp, *hold = current;
844
845 if (current == NULL)
846 return;
847
848 temp = edittop;
849
850 while (lines <= editwinrows - 1 && lines <= totlines && temp != NULL) {
851 hold = temp;
852 update_line(temp, current_x);
Chris Allegretta95b0b522000-07-28 02:58:06 +0000853 if (temp == current)
854 currentcheck = 1;
855
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000856 temp = temp->next;
857 lines++;
858 }
Chris Allegrettaed022162000-08-03 16:54:11 +0000859 /* If noloop == 1, then we already did an edit_update without finishing
860 this function. So we don't run edit_update again */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000861 if (!currentcheck && !noloop) { /* Then current has run off the screen... */
Chris Allegrettada721be2000-07-31 01:26:42 +0000862 edit_update(current, CENTER);
Chris Allegrettaed022162000-08-03 16:54:11 +0000863 noloop = 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000864 } else if (noloop)
Chris Allegrettaed022162000-08-03 16:54:11 +0000865 noloop = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000866
867 if (lines <= editwinrows - 1)
868 while (lines <= editwinrows - 1) {
869 mvwaddstr(edit, lines, i, hblank);
870 lines++;
871 }
872 if (temp == NULL)
873 editbot = hold;
874 else
875 editbot = temp;
876}
877
878/*
Chris Allegrettaf1d33d32000-08-19 03:53:39 +0000879 * Same as above, but touch the window first so everything is redrawn.
880 */
881void edit_refresh_clearok(void)
882{
883 clearok(edit, TRUE);
884 edit_refresh();
885 clearok(edit, FALSE);
886}
887
888/*
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000889 * Nice generic routine to update the edit buffer given a pointer to the
890 * file struct =)
891 */
Chris Allegretta234a34d2000-07-29 04:33:38 +0000892void edit_update(filestruct * fileptr, int topmidbot)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000893{
Robert Siemborski29e9a762000-07-05 03:16:04 +0000894 int i = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000895 filestruct *temp;
896
897 if (fileptr == NULL)
898 return;
899
900 temp = fileptr;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000901 if (topmidbot == 2);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000902 else if (topmidbot == 0)
903 for (i = 0; i <= editwinrows - 1 && temp->prev != NULL; i++)
904 temp = temp->prev;
905 else
906 for (i = 0; i <= editwinrows / 2 && temp->prev != NULL; i++)
907 temp = temp->prev;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000908
Robert Siemborski29e9a762000-07-05 03:16:04 +0000909 edittop = temp;
910 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000911
912 edit_refresh();
913}
914
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000915/* This function updates current based on where current_y is, reset_cursor
916 does the opposite */
917void update_cursor(void)
918{
919 int i = 0;
920
921#ifdef DEBUG
922 fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
923 current_x);
924#endif
925
926 current = edittop;
927 while (i <= current_y - 1 && current->next != NULL) {
928 current = current->next;
929 i++;
930 }
931
932#ifdef DEBUG
933 fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
934#endif
935
936}
937
938/*
939 * Ask a question on the statusbar. Answer will be stored in answer
940 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
941 * otherwise, the valid shortcut key caught, Def is any editable text we
942 * want to put up by default.
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000943 *
944 * New arg tabs tells whether or not to allow tab completion.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000945 */
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000946int statusq(int tabs, shortcut s[], int slen, char *def, char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000947{
948 va_list ap;
949 char foo[133];
950 int ret;
951
952 bottombars(s, slen);
953
954 va_start(ap, msg);
955 vsnprintf(foo, 132, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000956 va_end(ap);
Chris Allegrettaa4d21622000-07-08 23:57:03 +0000957 strncat(foo, ": ", 132);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000958
959 wattron(bottomwin, A_REVERSE);
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000960 ret = nanogetstr(tabs, foo, def, s, slen, (strlen(foo) + 3));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000961 wattroff(bottomwin, A_REVERSE);
962
963 switch (ret) {
964
965 case NANO_FIRSTLINE_KEY:
966 do_first_line();
967 break;
968 case NANO_LASTLINE_KEY:
969 do_last_line();
970 break;
971 case NANO_CANCEL_KEY:
972 return -1;
973 default:
974 blank_statusbar_refresh();
975 }
976
977#ifdef DEBUG
978 fprintf(stderr, _("I got \"%s\"\n"), answer);
979#endif
980
981 return ret;
982}
983
984/*
985 * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0 for
986 * N, 2 for All (if all is non-zero when passed in) and -1 for abort (^C)
987 */
988int do_yesno(int all, int leavecursor, char *msg, ...)
989{
990 va_list ap;
991 char foo[133];
992 int kbinput, ok = -1;
993
994 /* Write the bottom of the screen */
995 clear_bottomwin();
996 wattron(bottomwin, A_REVERSE);
997 blank_statusbar_refresh();
998 wattroff(bottomwin, A_REVERSE);
999
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001000 /* Remove gettext call for keybindings until we clear the thing up */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001001 if (!ISSET(NO_HELP)) {
1002 wmove(bottomwin, 1, 0);
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001003 onekey(" Y", _("Yes"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001004 if (all)
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001005 onekey(" A", _("All"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001006 wmove(bottomwin, 2, 0);
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001007 onekey(" N", _("No"));
1008 onekey("^C", _("Cancel"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001009 }
1010 va_start(ap, msg);
1011 vsnprintf(foo, 132, msg, ap);
1012 va_end(ap);
1013 wattron(bottomwin, A_REVERSE);
1014 mvwaddstr(bottomwin, 0, 0, foo);
1015 wattroff(bottomwin, A_REVERSE);
1016 wrefresh(bottomwin);
1017
1018 if (leavecursor == 1)
1019 reset_cursor();
1020
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001021 while (ok == -1) {
1022 kbinput = wgetch(edit);
1023
1024 switch (kbinput) {
1025 case 'Y':
1026 case 'y':
1027 ok = 1;
1028 break;
1029 case 'N':
1030 case 'n':
1031 ok = 0;
1032 break;
1033 case 'A':
1034 case 'a':
1035 if (all)
1036 ok = 2;
1037 break;
1038 case NANO_CONTROL_C:
1039 ok = -2;
1040 break;
1041 }
1042 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001043
1044 /* Then blank the screen */
1045 blank_statusbar_refresh();
1046
1047 if (ok == -2)
1048 return -1;
1049 else
1050 return ok;
1051}
1052
1053void statusbar(char *msg, ...)
1054{
1055 va_list ap;
1056 char foo[133];
1057 int start_x = 0;
1058
1059 va_start(ap, msg);
1060 vsnprintf(foo, 132, msg, ap);
1061 va_end(ap);
1062
1063 start_x = center_x - strlen(foo) / 2 - 1;
1064
1065 /* Blank out line */
1066 blank_statusbar();
1067
1068 wmove(bottomwin, 0, start_x);
1069
1070 wattron(bottomwin, A_REVERSE);
1071
1072 waddstr(bottomwin, "[ ");
1073 waddstr(bottomwin, foo);
1074 waddstr(bottomwin, " ]");
1075 wattroff(bottomwin, A_REVERSE);
1076 wrefresh(bottomwin);
1077
1078 if (ISSET(CONSTUPDATE))
1079 statblank = 1;
1080 else
1081 statblank = 25;
1082}
1083
1084void display_main_list(void)
1085{
1086 bottombars(main_list, MAIN_VISIBLE);
1087}
1088
1089int total_refresh(void)
1090{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001091 clearok(edit, TRUE);
1092 clearok(topwin, TRUE);
1093 clearok(bottomwin, TRUE);
1094 wnoutrefresh(edit);
1095 wnoutrefresh(topwin);
1096 wnoutrefresh(bottomwin);
1097 doupdate();
1098 clearok(edit, FALSE);
1099 clearok(topwin, FALSE);
1100 clearok(bottomwin, FALSE);
Chris Allegrettaf1d33d32000-08-19 03:53:39 +00001101 edit_refresh();
Chris Allegretta2a42af12000-09-12 23:02:49 +00001102 titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001103 return 1;
1104}
1105
1106void previous_line(void)
1107{
1108 if (current_y > 0)
1109 current_y--;
1110}
1111
1112int do_cursorpos(void)
1113{
1114 filestruct *fileptr;
1115 float linepct, bytepct;
1116 int i, tot = 0;
1117
1118 if (current == NULL || fileage == NULL)
1119 return 0;
1120
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001121 for (fileptr = fileage; fileptr != current && fileptr != NULL;
1122 fileptr = fileptr->next)
1123 tot += strlen(fileptr->data) + 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001124
1125 if (fileptr == NULL)
1126 return -1;
1127
1128 i = tot + current_x;;
1129
1130 for (fileptr = current->next; fileptr != NULL; fileptr = fileptr->next)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001131 tot += strlen(fileptr->data) + 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001132
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001133 if (totlines > 0)
1134 linepct = 100 * current->lineno / totlines;
1135 else
1136 linepct = 0;
1137
1138 if (totsize > 0)
1139 bytepct = 100 * i / totsize;
1140 else
1141 bytepct = 0;
1142
1143#ifdef DEBUG
1144 fprintf(stderr, _("do_cursorpos: linepct = %f, bytepct = %f\n"),
1145 linepct, bytepct);
1146#endif
1147
1148 statusbar(_("line %d of %d (%.0f%%), character %d of %d (%.0f%%)"),
1149 current->lineno, totlines, linepct, i, totsize, bytepct);
1150 reset_cursor();
1151 return 1;
1152}
1153
1154/* Our broken, non-shortcut list compliant help function.
1155 But hey, it's better than nothing, and it's dynamic! */
1156int do_help(void)
1157{
1158#ifndef NANO_SMALL
1159 char *ptr = help_text, *end;
1160 int i, j, row = 0, page = 1, kbinput = 0, no_more = 0;
1161 int no_help_flag = 0;
1162
1163 blank_edit();
1164 curs_set(0);
1165 blank_statusbar();
1166
1167 if (ISSET(NO_HELP)) {
1168
1169 no_help_flag = 1;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001170 delwin(bottomwin);
1171 bottomwin = newwin(3, COLS, LINES - 3, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001172 keypad(bottomwin, TRUE);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001173
1174 editwinrows -= no_help();
1175 UNSET(NO_HELP);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001176 bottombars(help_list, HELP_LIST_LEN);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001177 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001178 bottombars(help_list, HELP_LIST_LEN);
1179
1180 do {
1181 ptr = help_text;
1182 switch (kbinput) {
1183 case NANO_NEXTPAGE_KEY:
1184 case NANO_NEXTPAGE_FKEY:
1185 case KEY_NPAGE:
1186 if (!no_more) {
1187 blank_edit();
1188 page++;
1189 }
1190 break;
1191 case NANO_PREVPAGE_KEY:
1192 case NANO_PREVPAGE_FKEY:
1193 case KEY_PPAGE:
1194 if (page > 1) {
1195 no_more = 0;
1196 blank_edit();
1197 page--;
1198 }
1199 break;
1200 }
1201
1202 /* Calculate where in the text we should be based on the page */
1203 for (i = 1; i < page; i++) {
1204 row = 0;
1205 j = 0;
Chris Allegretta44e73df2000-09-07 03:37:38 +00001206
1207 while (row < editwinrows - 2 && *ptr != '\0') {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001208 if (*ptr == '\n' || j == COLS - 5) {
1209 j = 0;
1210 row++;
1211 }
1212 ptr++;
1213 j++;
1214 }
1215 }
1216
Chris Allegretta44e73df2000-09-07 03:37:38 +00001217 if (i > 1) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001218
Chris Allegretta44e73df2000-09-07 03:37:38 +00001219 }
1220
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001221 i = 0;
1222 j = 0;
1223 while (i < editwinrows && *ptr != '\0') {
1224 end = ptr;
1225 while (*end != '\n' && *end != '\0' && j != COLS - 5) {
1226 end++;
1227 j++;
1228 }
1229 if (j == COLS - 5) {
1230
1231 /* Don't print half a word if we've run of of space */
1232 while (*end != ' ' && *end != '\0') {
1233 end--;
1234 j--;
1235 }
1236 }
1237 mvwaddnstr(edit, i, 0, ptr, j);
1238 j = 0;
1239 i++;
1240 if (*end == '\n')
1241 end++;
1242 ptr = end;
1243 }
1244 if (*ptr == '\0') {
1245 no_more = 1;
1246 continue;
1247 }
1248 } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001249 if (no_help_flag) {
1250 werase(bottomwin);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001251 wrefresh(bottomwin);
1252 delwin(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001253 SET(NO_HELP);
1254 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
1255 keypad(bottomwin, TRUE);
1256 editwinrows += no_help();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001257 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001258 display_main_list();
1259
1260 curs_set(1);
1261 edit_refresh();
1262#else
1263 nano_small_msg();
1264#endif
1265
1266 return 1;
1267}
1268
1269/* Dump the current file structure to stderr */
1270void dump_buffer(filestruct * inptr)
1271{
1272#ifdef DEBUG
1273 filestruct *fileptr;
1274
1275 if (inptr == fileage)
1276 fprintf(stderr, _("Dumping file buffer to stderr...\n"));
1277 else if (inptr == cutbuffer)
1278 fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
1279 else
1280 fprintf(stderr, _("Dumping a buffer to stderr...\n"));
1281
1282 fileptr = inptr;
1283 while (fileptr != NULL) {
1284 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1285 fflush(stderr);
1286 fileptr = fileptr->next;
1287 }
1288#endif /* DEBUG */
1289}
1290
1291void dump_buffer_reverse(filestruct * inptr)
1292{
1293#ifdef DEBUG
1294 filestruct *fileptr;
1295
1296 fileptr = filebot;
1297 while (fileptr != NULL) {
1298 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1299 fflush(stderr);
1300 fileptr = fileptr->prev;
1301 }
1302#endif /* DEBUG */
1303}
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001304
1305/* Fix editbot based on the assumption that edittop is correct */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001306void fix_editbot(void)
1307{
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001308 int i;
1309 editbot = edittop;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001310 for (i = 0; (i <= editwinrows - 1) && (editbot->next != NULL)
1311 && (editbot != filebot); i++, editbot = editbot->next);
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001312}