blob: 69478c6cd06b416dca1faa2948392c008de3e338 [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{
224 blank_statusbar();
Chris Allegretta31925e42000-11-02 04:40:39 +0000225 if (x <= COLS) {
226 mvwaddstr(bottomwin, 0, 0, buf);
227 waddnstr(bottomwin, inputbuf, COLS - strlen(buf));
228
229 } else if (x > COLS && x <= COLS * 2)
230 mvwaddnstr(bottomwin, 0, 0, &inputbuf[COLS - strlen(buf)], COLS);
231 else
232 mvwaddnstr(bottomwin, 0, 0, &inputbuf[COLS * (x / COLS) -
233 strlen(buf)], COLS);
234
235 wmove(bottomwin, 0, (x % COLS));
236
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000237}
238
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000239/* Get the input from the kb, this should only be called from statusq */
240int nanogetstr(char *buf, char *def, shortcut s[], int slen, int start_x)
241{
242 int kbinput = 0, j = 0, x = 0, xend;
Chris Allegretta31925e42000-11-02 04:40:39 +0000243 int x_left = 0, inputlen;
244 char *inputbuf;
245
246 inputbuf = nmalloc(strlen(def) + 1);
247 inputbuf[0] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000248
249 x_left = strlen(buf);
250 x = strlen(def) + x_left;
251
252 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +0000253 if (strlen(def) > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000254 strcpy(inputbuf, def);
Chris Allegretta31925e42000-11-02 04:40:39 +0000255
256 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000257
258 while ((kbinput = wgetch(bottomwin)) != 13) {
259 for (j = 0; j <= slen - 1; j++) {
260 if (kbinput == s[j].val) {
Chris Allegrettaf5deac32000-11-02 05:10:26 +0000261 answer = mallocstrcpy(answer, "");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000262 return s[j].val;
263 }
264 }
265 xend = strlen(buf) + strlen(inputbuf);
266
267 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000268 /* Stuff we want to equate with <enter>, ASCII 13 */
269 case 343:
Chris Allegrettaf9b6c9b2000-10-18 19:35:59 +0000270 ungetch(13); /* Enter on iris-ansi $TERM, sometimes */
271 break;
272
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000273 case KEY_HOME:
274 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000275 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000276 break;
277 case KEY_END:
278 x = x_left + strlen(inputbuf);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000279 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000280 break;
281 case KEY_RIGHT:
282
283 if (x < xend)
284 x++;
285 wmove(bottomwin, 0, x);
286 break;
287 case NANO_CONTROL_D:
288 if (strlen(inputbuf) > 0 && (x - x_left) != strlen(inputbuf)) {
289 memmove(inputbuf + (x - x_left),
290 inputbuf + (x - x_left) + 1,
291 strlen(inputbuf) - (x - x_left) - 1);
292 inputbuf[strlen(inputbuf) - 1] = 0;
293 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000294 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000295 break;
296 case NANO_CONTROL_K:
297 case NANO_CONTROL_U:
298 *inputbuf = 0;
299 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000300 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000301 break;
302 case KEY_BACKSPACE:
303 case KEY_DC:
304 case 127:
305 case NANO_CONTROL_H:
306 if (strlen(inputbuf) > 0) {
307 if (x == (x_left + strlen(inputbuf)))
308 inputbuf[strlen(inputbuf) - 1] = 0;
309 else if (x - x_left) {
310 memmove(inputbuf + (x - x_left) - 1,
311 inputbuf + (x - x_left),
312 strlen(inputbuf) - (x - x_left));
313 inputbuf[strlen(inputbuf) - 1] = 0;
314 }
315 }
Chris Allegretta31925e42000-11-02 04:40:39 +0000316 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000317 case KEY_LEFT:
318 if (x > strlen(buf))
319 x--;
320 wmove(bottomwin, 0, x);
321 break;
322 case KEY_UP:
323 case KEY_DOWN:
324 break;
325
326 case 27:
327 switch (kbinput = wgetch(edit)) {
328 case 79:
329 switch (kbinput = wgetch(edit)) {
330 case 70:
331 x = x_left + strlen(inputbuf);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000332 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000333 break;
334 case 72:
335 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000336 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000337 break;
338 }
339 break;
340 case 91:
341 switch (kbinput = wgetch(edit)) {
342 case 'C':
343 if (x < xend)
344 x++;
345 wmove(bottomwin, 0, x);
346 break;
347 case 'D':
348 if (x > strlen(buf))
349 x--;
350 wmove(bottomwin, 0, x);
351 break;
352 case 49:
353 x = x_left;
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000354 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000355 goto skip_126;
356 case 51:
357 if (strlen(inputbuf) > 0
358 && (x - x_left) != strlen(inputbuf)) {
359 memmove(inputbuf + (x - x_left),
360 inputbuf + (x - x_left) + 1,
361 strlen(inputbuf) - (x - x_left) - 1);
362 inputbuf[strlen(inputbuf) - 1] = 0;
363 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000364 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000365 goto skip_126;
366 case 52:
367 x = x_left + strlen(inputbuf);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000368 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000369 goto skip_126;
370 skip_126:
371 nodelay(edit, TRUE);
372 kbinput = wgetch(edit);
373 if (kbinput == 126 || kbinput == ERR)
374 kbinput = -1;
375 nodelay(edit, FALSE);
376 break;
377 }
378 }
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000379 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000380 break;
381
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000382 default:
383 if (kbinput < 32)
384 break;
Chris Allegretta31925e42000-11-02 04:40:39 +0000385
386 inputlen = strlen(inputbuf);
387 inputbuf = nrealloc(inputbuf, inputlen + 2);
388
389 memmove(&inputbuf[x - x_left + 1],
390 &inputbuf[x - x_left],
391 inputlen - (x - x_left) + 1);
392 inputbuf[x - x_left] = kbinput;
393
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000394 x++;
395
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000396 nanoget_repaint(buf, inputbuf, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000397#ifdef DEBUG
398 fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput);
399#endif
400 }
401 wrefresh(bottomwin);
402 }
403
Chris Allegretta31925e42000-11-02 04:40:39 +0000404 answer = mallocstrcpy(answer, inputbuf);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000405
Chris Allegretta105da332000-10-31 05:10:10 +0000406 /* Now that the text is editable instead of bracketed, we have to
407 check for answer == def, instead of answer == "" */
Chris Allegretta105da332000-10-31 05:10:10 +0000408 if (!strcmp(answer, def))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000409 return -2;
410 else
411 return 0;
412}
413
414void horizbar(WINDOW * win, int y)
415{
416 wattron(win, A_REVERSE);
417 mvwaddstr(win, 0, 0, hblank);
418 wattroff(win, A_REVERSE);
419}
420
421void titlebar(void)
422{
423 int namelen, space;
424
425 horizbar(topwin, 0);
426 wattron(topwin, A_REVERSE);
427 mvwaddstr(topwin, 0, 3, VERMSG);
428
429 space = COLS - strlen(VERMSG) - strlen(VERSION) - 21;
430
431 namelen = strlen(filename);
432
433 if (!strcmp(filename, ""))
434 mvwaddstr(topwin, 0, center_x - 6, _("New Buffer"));
435 else {
436 if (namelen > space) {
437 waddstr(topwin, _(" File: ..."));
438 waddstr(topwin, &filename[namelen - space]);
439 } else {
440 mvwaddstr(topwin, 0, center_x - (namelen / 2 + 1), "File: ");
441 waddstr(topwin, filename);
442 }
443 }
444 if (ISSET(MODIFIED))
445 mvwaddstr(topwin, 0, COLS - 10, _("Modified"));
446 wattroff(topwin, A_REVERSE);
447 wrefresh(topwin);
448 reset_cursor();
449}
450
451void onekey(char *keystroke, char *desc)
452{
453 char description[80];
454
Chris Allegrettae7034c62000-09-15 03:31:09 +0000455 snprintf(description, 12, " %-10s", desc);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000456 wattron(bottomwin, A_REVERSE);
457 waddstr(bottomwin, keystroke);
458 wattroff(bottomwin, A_REVERSE);
459 waddstr(bottomwin, description);
460}
461
462void clear_bottomwin(void)
463{
464 if (ISSET(NO_HELP))
465 return;
466
467 mvwaddstr(bottomwin, 1, 0, hblank);
468 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000469}
470
471void bottombars(shortcut s[], int slen)
472{
473 int i, j, k;
474 char keystr[10];
475
476 if (ISSET(NO_HELP))
477 return;
478
479 /* Determine how many extra spaces are needed to fill the bottom of the screen */
480 k = COLS / 6 - 13;
481
482 clear_bottomwin();
483 wmove(bottomwin, 1, 0);
484 for (i = 0; i <= slen - 1; i += 2) {
Robert Siemborski6af14312000-07-01 21:34:26 +0000485 snprintf(keystr, 10, "^%c", s[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000486 onekey(keystr, s[i].desc);
487
488 for (j = 0; j < k; j++)
489 waddch(bottomwin, ' ');
490 }
491
492 wmove(bottomwin, 2, 0);
493 for (i = 1; i <= slen - 1; i += 2) {
Robert Siemborski6af14312000-07-01 21:34:26 +0000494 snprintf(keystr, 10, "^%c", s[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000495 onekey(keystr, s[i].desc);
496
497 for (j = 0; j < k; j++)
498 waddch(bottomwin, ' ');
499 }
500
501 wrefresh(bottomwin);
502
503}
504
505/* If modified is not already set, set it and update titlebar */
506void set_modified(void)
507{
508 if (!ISSET(MODIFIED)) {
509 SET(MODIFIED);
510 titlebar();
511 wrefresh(topwin);
512 }
513}
514
Robert Siemborski9d584552000-07-08 00:41:29 +0000515/* And so start the display update routines */
516/* Given a column, this returns the "page" it is on */
517/* "page" in the case of the display columns, means which set of 80 */
518/* characters is viewable (ie: page 1 shows from 1 to COLS) */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000519inline int get_page_from_virtual(int virtual)
520{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000521 int page = 2;
522
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000523 if (virtual <= COLS - 2)
524 return 1;
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000525 virtual -= (COLS - 2);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000526
527 while (virtual > COLS - 2 - 7) {
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000528 virtual -= (COLS - 2 - 7);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000529 page++;
530 }
531
532 return page;
533}
534
Robert Siemborski9d584552000-07-08 00:41:29 +0000535/* The inverse of the above function */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000536inline int get_page_start_virtual(int page)
537{
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000538 int virtual;
539 virtual = --page * (COLS - 7);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000540 if (page)
541 virtual -= 2 * page - 1;
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000542 return virtual;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000543}
544
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000545inline int get_page_end_virtual(int page)
546{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000547 return get_page_start_virtual(page) + COLS - 1;
548}
549
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000550#ifndef NANO_SMALL
Robert Siemborski9d584552000-07-08 00:41:29 +0000551/* This takes care of the case where there is a mark that covers only */
552/* the current line. */
553
Chris Allegrettab275aac2000-07-08 01:22:33 +0000554/* It expects a line with no tab characers (ie: the type that edit_add */
Robert Siemborski9d584552000-07-08 00:41:29 +0000555/* deals with */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000556void add_marked_sameline(int begin, int end, filestruct * fileptr, int y,
557 int virt_cur_x, int this_page)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000558{
Robert Siemborski9d584552000-07-08 00:41:29 +0000559 /*
560 * The general idea is to break the line up into 3 sections: before
561 * the mark, the mark, and after the mark. We then paint each in
562 * turn (for those that are currently visible, of course
563 *
564 * 3 start points: 0 -> begin, begin->end, end->strlen(data)
565 * in data : pre sel post
566 */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000567 int this_page_start = get_page_start_virtual(this_page),
Robert Siemborski53875912000-06-16 04:25:30 +0000568 this_page_end = get_page_end_virtual(this_page);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000569
Robert Siemborskid8510b22000-06-06 23:04:06 +0000570 /* likewise, 3 data lengths */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000571 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 +0000572
573 /* now fix the start locations & lengths according to the cursor's
574 * position (ie: our page) */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000575 if (pre_data_len < this_page_start)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000576 pre_data_len = 0;
577 else
578 pre_data_len -= this_page_start;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000579
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000580 if (begin < this_page_start)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000581 begin = this_page_start;
582
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000583 if (end < this_page_start)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000584 end = this_page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000585
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000586 if (begin > this_page_end)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000587 begin = this_page_end;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000588
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000589 if (end > this_page_end)
Robert Siemborskia9addc72000-06-17 06:06:35 +0000590 end = this_page_end;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000591
Robert Siemborski9d584552000-07-08 00:41:29 +0000592 /* Now calculate the lengths */
Robert Siemborskia9addc72000-06-17 06:06:35 +0000593 sel_data_len = end - begin;
594 post_data_len = this_page_end - end;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000595
Robert Siemborski9d584552000-07-08 00:41:29 +0000596 /* Paint this line! */
Robert Siemborski53875912000-06-16 04:25:30 +0000597 mvwaddnstr(edit, y, 0, &fileptr->data[this_page_start], pre_data_len);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000598 wattron(edit, A_REVERSE);
Robert Siemborskia9addc72000-06-17 06:06:35 +0000599 mvwaddnstr(edit, y, begin - this_page_start,
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000600 &fileptr->data[begin], sel_data_len);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000601 wattroff(edit, A_REVERSE);
Robert Siemborskia9addc72000-06-17 06:06:35 +0000602 mvwaddnstr(edit, y, end - this_page_start,
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000603 &fileptr->data[end], post_data_len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000604}
605#endif
606
Robert Siemborski9d584552000-07-08 00:41:29 +0000607/* edit_add takes care of the job of actually painting a line into the
608 * edit window.
609 *
610 * Called only from update_line. Expects a converted-to-not-have-tabs
Robert Siemborski53875912000-06-16 04:25:30 +0000611 * line */
612void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000613 int virt_mark_beginx, int this_page)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000614{
615#ifndef NANO_SMALL
Robert Siemborski9d584552000-07-08 00:41:29 +0000616 /* There are quite a few cases that could take place, we'll deal
617 * with them each in turn */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000618 if (ISSET(MARK_ISSET)
Robert Siemborski9d584552000-07-08 00:41:29 +0000619 && !((fileptr->lineno > mark_beginbuf->lineno
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000620 && fileptr->lineno > current->lineno)
621 || (fileptr->lineno < mark_beginbuf->lineno
622 && fileptr->lineno < current->lineno))) {
623 /* If we get here we are on a line that is atleast
624 * partially selected. The lineno checks above determined
625 * that */
626 if (fileptr != mark_beginbuf && fileptr != current) {
627 /* We are on a completely marked line, paint it all
628 * inverse */
629 wattron(edit, A_REVERSE);
630 mvwaddnstr(edit, yval, 0, fileptr->data, COLS);
631 wattroff(edit, A_REVERSE);
632 } else if (fileptr == mark_beginbuf && fileptr == current) {
633 /* Special case, we're still on the same line we started
634 * marking -- so we call our helper function */
635 if (virt_cur_x < virt_mark_beginx) {
636 /* To the right of us is marked */
637 add_marked_sameline(virt_cur_x, virt_mark_beginx,
638 fileptr, yval, virt_cur_x, this_page);
639 } else {
640 /* To the left of us is marked */
641 add_marked_sameline(virt_mark_beginx, virt_cur_x,
642 fileptr, yval, virt_cur_x, this_page);
643 }
644 } else if (fileptr == mark_beginbuf) {
645 /*
646 * we're updating the line that was first marked
647 * but we're not currently on it. So we want to
648 * figur out which half to invert based on our
649 * relative line numbers.
650 *
651 * i.e. If we're above the "beginbuf" line, we want to
652 * mark the left side. Otherwise we're below, so we
653 * mark the right
654 */
655 int target;
656
657 if (mark_beginbuf->lineno > current->lineno)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000658 wattron(edit, A_REVERSE);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000659
660 target =
661 (virt_mark_beginx <
662 COLS - 1) ? virt_mark_beginx : COLS - 1;
663
664 mvwaddnstr(edit, yval, 0, fileptr->data, target);
665
666 if (mark_beginbuf->lineno < current->lineno)
667 wattron(edit, A_REVERSE);
668 else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000669 wattroff(edit, A_REVERSE);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000670
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000671 target = (COLS - 1) - virt_mark_beginx;
672 if (target < 0)
673 target = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000674
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000675 mvwaddnstr(edit, yval, virt_mark_beginx,
676 &fileptr->data[virt_mark_beginx], target);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000677
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000678 if (mark_beginbuf->lineno < current->lineno)
679 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000680
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000681 } else if (fileptr == current) {
682 /* we're on the cursors line, but it's not the first
683 * one we marked. Similar to the previous logic. */
684 int this_page_start = get_page_start_virtual(this_page),
685 this_page_end = get_page_end_virtual(this_page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000686
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000687 if (mark_beginbuf->lineno < current->lineno)
688 wattron(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000689
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000690 if (virt_cur_x > COLS - 2) {
691 mvwaddnstr(edit, yval, 0,
692 &fileptr->data[this_page_start],
693 virt_cur_x - this_page_start);
694 } else {
695 mvwaddnstr(edit, yval, 0, fileptr->data, virt_cur_x);
696 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000697
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000698 if (mark_beginbuf->lineno > current->lineno)
699 wattron(edit, A_REVERSE);
700 else
701 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000702
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000703 if (virt_cur_x > COLS - 2)
704 mvwaddnstr(edit, yval, virt_cur_x - this_page_start,
705 &fileptr->data[virt_cur_x],
706 this_page_end - virt_cur_x);
707 else
708 mvwaddnstr(edit, yval, virt_cur_x,
709 &fileptr->data[virt_cur_x], COLS - virt_cur_x);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000710
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000711 if (mark_beginbuf->lineno > current->lineno)
712 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000713 }
714
715 } else
716#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000717 /* Just paint the string (no mark on this line) */
Robert Siemborskia9addc72000-06-17 06:06:35 +0000718 mvwaddnstr(edit, yval, 0, &fileptr->data[start],
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000719 get_page_end_virtual(this_page) - start);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000720}
721
722/*
Robert Siemborski9d584552000-07-08 00:41:29 +0000723 * Just update one line in the edit buffer. Basically a wrapper for
724 * edit_add
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000725 *
726 * index gives is a place in the string to update starting from.
727 * Likely args are current_x or 0.
728 */
729void update_line(filestruct * fileptr, int index)
730{
731 filestruct *filetmp;
Robert Siemborski53875912000-06-16 04:25:30 +0000732 int line = 0, col = 0;
733 int virt_cur_x = current_x, virt_mark_beginx = mark_beginx;
734 char *realdata, *tmp;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000735 int i, pos, len, page;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000736
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000737 if (!fileptr)
738 return;
Robert Siemborski53154a72000-06-18 00:11:03 +0000739
Robert Siemborski53875912000-06-16 04:25:30 +0000740 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000741 for (filetmp = edittop; filetmp != fileptr && filetmp != editbot;
742 filetmp = filetmp->next)
743 line++;
744
745 mvwaddstr(edit, line, 0, hblank);
746
Robert Siemborski53875912000-06-16 04:25:30 +0000747 /* Next, convert all the tabs to spaces so everything else is easy */
748 index = xpt(fileptr, index);
749
750 realdata = fileptr->data;
751 len = strlen(realdata);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000752 fileptr->data = nmalloc(xpt(fileptr, len) + 1);
Robert Siemborski53875912000-06-16 04:25:30 +0000753
754 pos = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000755 for (i = 0; i < len; i++) {
756 if (realdata[i] == '\t') {
Robert Siemborski53875912000-06-16 04:25:30 +0000757 do {
758 fileptr->data[pos++] = ' ';
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000759 if (i < current_x)
760 virt_cur_x++;
761 if (i < mark_beginx)
762 virt_mark_beginx++;
Chris Allegretta6d690a32000-08-03 22:51:21 +0000763 } while (pos % tabsize);
Robert Siemborski53875912000-06-16 04:25:30 +0000764 /* must decrement once to account for tab-is-one-character */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000765 if (i < current_x)
766 virt_cur_x--;
767 if (i < mark_beginx)
768 virt_mark_beginx--;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000769 } else if (realdata[i] >= 1 && realdata[i] <= 26) {
770 /* Treat control characters as ^letter */
Chris Allegretta6306a112000-09-02 07:55:41 +0000771 fileptr->data[pos++] = '^';
772 fileptr->data[pos++] = realdata[i] + 64;
Robert Siemborski53875912000-06-16 04:25:30 +0000773 } else {
774 fileptr->data[pos++] = realdata[i];
775 }
776 }
777
778 fileptr->data[pos] = '\0';
779
780 /* Now, Paint the line */
781 if (current == fileptr && index > COLS - 2) {
Robert Siemborskia9addc72000-06-17 06:06:35 +0000782 /* This handles when the current line is beyond COLS */
783 /* It requires figureing out what page we're at */
784 page = get_page_from_virtual(index);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000785 col = get_page_start_virtual(page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000786
Robert Siemborskia9addc72000-06-17 06:06:35 +0000787 edit_add(filetmp, line, col, virt_cur_x, virt_mark_beginx, page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000788 mvwaddch(edit, line, 0, '$');
789
Robert Siemborskid8510b22000-06-06 23:04:06 +0000790 if (strlenpt(fileptr->data) > get_page_end_virtual(page))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000791 mvwaddch(edit, line, COLS - 1, '$');
Robert Siemborskid8510b22000-06-06 23:04:06 +0000792 } else {
Robert Siemborskia9addc72000-06-17 06:06:35 +0000793 /* It's not the current line means that it's at x=0 and page=1 */
794 /* If it is the current line, then we're in the same boat */
795 edit_add(filetmp, line, 0, virt_cur_x, virt_mark_beginx, 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000796
Robert Siemborski53875912000-06-16 04:25:30 +0000797 if (strlenpt(&filetmp->data[col]) > COLS)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000798 mvwaddch(edit, line, COLS - 1, '$');
Robert Siemborskid8510b22000-06-06 23:04:06 +0000799 }
Robert Siemborski53875912000-06-16 04:25:30 +0000800
801 /* Clean up our mess */
802 tmp = fileptr->data;
803 fileptr->data = realdata;
804 free(tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000805}
806
807void center_cursor(void)
808{
809 current_y = editwinrows / 2;
810 wmove(edit, current_y, current_x);
811}
812
813/* Refresh the screen without changing the position of lines */
814void edit_refresh(void)
815{
Chris Allegrettaed022162000-08-03 16:54:11 +0000816 static int noloop = 0;
Chris Allegretta95b0b522000-07-28 02:58:06 +0000817 int lines = 0, i = 0, currentcheck = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000818 filestruct *temp, *hold = current;
819
820 if (current == NULL)
821 return;
822
823 temp = edittop;
824
825 while (lines <= editwinrows - 1 && lines <= totlines && temp != NULL) {
826 hold = temp;
827 update_line(temp, current_x);
Chris Allegretta95b0b522000-07-28 02:58:06 +0000828 if (temp == current)
829 currentcheck = 1;
830
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000831 temp = temp->next;
832 lines++;
833 }
Chris Allegrettaed022162000-08-03 16:54:11 +0000834 /* If noloop == 1, then we already did an edit_update without finishing
835 this function. So we don't run edit_update again */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000836 if (!currentcheck && !noloop) { /* Then current has run off the screen... */
Chris Allegrettada721be2000-07-31 01:26:42 +0000837 edit_update(current, CENTER);
Chris Allegrettaed022162000-08-03 16:54:11 +0000838 noloop = 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000839 } else if (noloop)
Chris Allegrettaed022162000-08-03 16:54:11 +0000840 noloop = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000841
842 if (lines <= editwinrows - 1)
843 while (lines <= editwinrows - 1) {
844 mvwaddstr(edit, lines, i, hblank);
845 lines++;
846 }
847 if (temp == NULL)
848 editbot = hold;
849 else
850 editbot = temp;
851}
852
853/*
Chris Allegrettaf1d33d32000-08-19 03:53:39 +0000854 * Same as above, but touch the window first so everything is redrawn.
855 */
856void edit_refresh_clearok(void)
857{
858 clearok(edit, TRUE);
859 edit_refresh();
860 clearok(edit, FALSE);
861}
862
863/*
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000864 * Nice generic routine to update the edit buffer given a pointer to the
865 * file struct =)
866 */
Chris Allegretta234a34d2000-07-29 04:33:38 +0000867void edit_update(filestruct * fileptr, int topmidbot)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000868{
Robert Siemborski29e9a762000-07-05 03:16:04 +0000869 int i = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000870 filestruct *temp;
871
872 if (fileptr == NULL)
873 return;
874
875 temp = fileptr;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000876 if (topmidbot == 2);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000877 else if (topmidbot == 0)
878 for (i = 0; i <= editwinrows - 1 && temp->prev != NULL; i++)
879 temp = temp->prev;
880 else
881 for (i = 0; i <= editwinrows / 2 && temp->prev != NULL; i++)
882 temp = temp->prev;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000883
Robert Siemborski29e9a762000-07-05 03:16:04 +0000884 edittop = temp;
885 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000886
887 edit_refresh();
888}
889
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000890/* This function updates current based on where current_y is, reset_cursor
891 does the opposite */
892void update_cursor(void)
893{
894 int i = 0;
895
896#ifdef DEBUG
897 fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
898 current_x);
899#endif
900
901 current = edittop;
902 while (i <= current_y - 1 && current->next != NULL) {
903 current = current->next;
904 i++;
905 }
906
907#ifdef DEBUG
908 fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
909#endif
910
911}
912
913/*
914 * Ask a question on the statusbar. Answer will be stored in answer
915 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
916 * otherwise, the valid shortcut key caught, Def is any editable text we
917 * want to put up by default.
918 */
919int statusq(shortcut s[], int slen, char *def, char *msg, ...)
920{
921 va_list ap;
922 char foo[133];
923 int ret;
924
925 bottombars(s, slen);
926
927 va_start(ap, msg);
928 vsnprintf(foo, 132, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000929 va_end(ap);
Chris Allegrettaa4d21622000-07-08 23:57:03 +0000930 strncat(foo, ": ", 132);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000931
932 wattron(bottomwin, A_REVERSE);
933 ret = nanogetstr(foo, def, s, slen, (strlen(foo) + 3));
934 wattroff(bottomwin, A_REVERSE);
935
936 switch (ret) {
937
938 case NANO_FIRSTLINE_KEY:
939 do_first_line();
940 break;
941 case NANO_LASTLINE_KEY:
942 do_last_line();
943 break;
944 case NANO_CANCEL_KEY:
945 return -1;
946 default:
947 blank_statusbar_refresh();
948 }
949
950#ifdef DEBUG
951 fprintf(stderr, _("I got \"%s\"\n"), answer);
952#endif
953
954 return ret;
955}
956
957/*
958 * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0 for
959 * N, 2 for All (if all is non-zero when passed in) and -1 for abort (^C)
960 */
961int do_yesno(int all, int leavecursor, char *msg, ...)
962{
963 va_list ap;
964 char foo[133];
965 int kbinput, ok = -1;
966
967 /* Write the bottom of the screen */
968 clear_bottomwin();
969 wattron(bottomwin, A_REVERSE);
970 blank_statusbar_refresh();
971 wattroff(bottomwin, A_REVERSE);
972
Jordi Mallach0b0fc492000-06-23 01:00:13 +0000973 /* Remove gettext call for keybindings until we clear the thing up */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000974 if (!ISSET(NO_HELP)) {
975 wmove(bottomwin, 1, 0);
Jordi Mallach0b0fc492000-06-23 01:00:13 +0000976 onekey(" Y", _("Yes"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000977 if (all)
Jordi Mallach0b0fc492000-06-23 01:00:13 +0000978 onekey(" A", _("All"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000979 wmove(bottomwin, 2, 0);
Jordi Mallach0b0fc492000-06-23 01:00:13 +0000980 onekey(" N", _("No"));
981 onekey("^C", _("Cancel"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000982 }
983 va_start(ap, msg);
984 vsnprintf(foo, 132, msg, ap);
985 va_end(ap);
986 wattron(bottomwin, A_REVERSE);
987 mvwaddstr(bottomwin, 0, 0, foo);
988 wattroff(bottomwin, A_REVERSE);
989 wrefresh(bottomwin);
990
991 if (leavecursor == 1)
992 reset_cursor();
993
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000994 while (ok == -1) {
995 kbinput = wgetch(edit);
996
997 switch (kbinput) {
998 case 'Y':
999 case 'y':
1000 ok = 1;
1001 break;
1002 case 'N':
1003 case 'n':
1004 ok = 0;
1005 break;
1006 case 'A':
1007 case 'a':
1008 if (all)
1009 ok = 2;
1010 break;
1011 case NANO_CONTROL_C:
1012 ok = -2;
1013 break;
1014 }
1015 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001016
1017 /* Then blank the screen */
1018 blank_statusbar_refresh();
1019
1020 if (ok == -2)
1021 return -1;
1022 else
1023 return ok;
1024}
1025
1026void statusbar(char *msg, ...)
1027{
1028 va_list ap;
1029 char foo[133];
1030 int start_x = 0;
1031
1032 va_start(ap, msg);
1033 vsnprintf(foo, 132, msg, ap);
1034 va_end(ap);
1035
1036 start_x = center_x - strlen(foo) / 2 - 1;
1037
1038 /* Blank out line */
1039 blank_statusbar();
1040
1041 wmove(bottomwin, 0, start_x);
1042
1043 wattron(bottomwin, A_REVERSE);
1044
1045 waddstr(bottomwin, "[ ");
1046 waddstr(bottomwin, foo);
1047 waddstr(bottomwin, " ]");
1048 wattroff(bottomwin, A_REVERSE);
1049 wrefresh(bottomwin);
1050
1051 if (ISSET(CONSTUPDATE))
1052 statblank = 1;
1053 else
1054 statblank = 25;
1055}
1056
1057void display_main_list(void)
1058{
1059 bottombars(main_list, MAIN_VISIBLE);
1060}
1061
1062int total_refresh(void)
1063{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001064 clearok(edit, TRUE);
1065 clearok(topwin, TRUE);
1066 clearok(bottomwin, TRUE);
1067 wnoutrefresh(edit);
1068 wnoutrefresh(topwin);
1069 wnoutrefresh(bottomwin);
1070 doupdate();
1071 clearok(edit, FALSE);
1072 clearok(topwin, FALSE);
1073 clearok(bottomwin, FALSE);
Chris Allegrettaf1d33d32000-08-19 03:53:39 +00001074 edit_refresh();
Chris Allegretta2a42af12000-09-12 23:02:49 +00001075 titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001076 return 1;
1077}
1078
1079void previous_line(void)
1080{
1081 if (current_y > 0)
1082 current_y--;
1083}
1084
1085int do_cursorpos(void)
1086{
1087 filestruct *fileptr;
1088 float linepct, bytepct;
1089 int i, tot = 0;
1090
1091 if (current == NULL || fileage == NULL)
1092 return 0;
1093
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001094 for (fileptr = fileage; fileptr != current && fileptr != NULL;
1095 fileptr = fileptr->next)
1096 tot += strlen(fileptr->data) + 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001097
1098 if (fileptr == NULL)
1099 return -1;
1100
1101 i = tot + current_x;;
1102
1103 for (fileptr = current->next; fileptr != NULL; fileptr = fileptr->next)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001104 tot += strlen(fileptr->data) + 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001105
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001106 if (totlines > 0)
1107 linepct = 100 * current->lineno / totlines;
1108 else
1109 linepct = 0;
1110
1111 if (totsize > 0)
1112 bytepct = 100 * i / totsize;
1113 else
1114 bytepct = 0;
1115
1116#ifdef DEBUG
1117 fprintf(stderr, _("do_cursorpos: linepct = %f, bytepct = %f\n"),
1118 linepct, bytepct);
1119#endif
1120
1121 statusbar(_("line %d of %d (%.0f%%), character %d of %d (%.0f%%)"),
1122 current->lineno, totlines, linepct, i, totsize, bytepct);
1123 reset_cursor();
1124 return 1;
1125}
1126
1127/* Our broken, non-shortcut list compliant help function.
1128 But hey, it's better than nothing, and it's dynamic! */
1129int do_help(void)
1130{
1131#ifndef NANO_SMALL
1132 char *ptr = help_text, *end;
1133 int i, j, row = 0, page = 1, kbinput = 0, no_more = 0;
1134 int no_help_flag = 0;
1135
1136 blank_edit();
1137 curs_set(0);
1138 blank_statusbar();
1139
1140 if (ISSET(NO_HELP)) {
1141
1142 no_help_flag = 1;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001143 delwin(bottomwin);
1144 bottomwin = newwin(3, COLS, LINES - 3, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001145 keypad(bottomwin, TRUE);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001146
1147 editwinrows -= no_help();
1148 UNSET(NO_HELP);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001149 bottombars(help_list, HELP_LIST_LEN);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001150 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001151 bottombars(help_list, HELP_LIST_LEN);
1152
1153 do {
1154 ptr = help_text;
1155 switch (kbinput) {
1156 case NANO_NEXTPAGE_KEY:
1157 case NANO_NEXTPAGE_FKEY:
1158 case KEY_NPAGE:
1159 if (!no_more) {
1160 blank_edit();
1161 page++;
1162 }
1163 break;
1164 case NANO_PREVPAGE_KEY:
1165 case NANO_PREVPAGE_FKEY:
1166 case KEY_PPAGE:
1167 if (page > 1) {
1168 no_more = 0;
1169 blank_edit();
1170 page--;
1171 }
1172 break;
1173 }
1174
1175 /* Calculate where in the text we should be based on the page */
1176 for (i = 1; i < page; i++) {
1177 row = 0;
1178 j = 0;
Chris Allegretta44e73df2000-09-07 03:37:38 +00001179
1180 while (row < editwinrows - 2 && *ptr != '\0') {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001181 if (*ptr == '\n' || j == COLS - 5) {
1182 j = 0;
1183 row++;
1184 }
1185 ptr++;
1186 j++;
1187 }
1188 }
1189
Chris Allegretta44e73df2000-09-07 03:37:38 +00001190 if (i > 1) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001191
Chris Allegretta44e73df2000-09-07 03:37:38 +00001192 }
1193
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001194 i = 0;
1195 j = 0;
1196 while (i < editwinrows && *ptr != '\0') {
1197 end = ptr;
1198 while (*end != '\n' && *end != '\0' && j != COLS - 5) {
1199 end++;
1200 j++;
1201 }
1202 if (j == COLS - 5) {
1203
1204 /* Don't print half a word if we've run of of space */
1205 while (*end != ' ' && *end != '\0') {
1206 end--;
1207 j--;
1208 }
1209 }
1210 mvwaddnstr(edit, i, 0, ptr, j);
1211 j = 0;
1212 i++;
1213 if (*end == '\n')
1214 end++;
1215 ptr = end;
1216 }
1217 if (*ptr == '\0') {
1218 no_more = 1;
1219 continue;
1220 }
1221 } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001222 if (no_help_flag) {
1223 werase(bottomwin);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001224 wrefresh(bottomwin);
1225 delwin(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001226 SET(NO_HELP);
1227 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
1228 keypad(bottomwin, TRUE);
1229 editwinrows += no_help();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001230 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001231 display_main_list();
1232
1233 curs_set(1);
1234 edit_refresh();
1235#else
1236 nano_small_msg();
1237#endif
1238
1239 return 1;
1240}
1241
1242/* Dump the current file structure to stderr */
1243void dump_buffer(filestruct * inptr)
1244{
1245#ifdef DEBUG
1246 filestruct *fileptr;
1247
1248 if (inptr == fileage)
1249 fprintf(stderr, _("Dumping file buffer to stderr...\n"));
1250 else if (inptr == cutbuffer)
1251 fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
1252 else
1253 fprintf(stderr, _("Dumping a buffer to stderr...\n"));
1254
1255 fileptr = inptr;
1256 while (fileptr != NULL) {
1257 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1258 fflush(stderr);
1259 fileptr = fileptr->next;
1260 }
1261#endif /* DEBUG */
1262}
1263
1264void dump_buffer_reverse(filestruct * inptr)
1265{
1266#ifdef DEBUG
1267 filestruct *fileptr;
1268
1269 fileptr = filebot;
1270 while (fileptr != NULL) {
1271 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1272 fflush(stderr);
1273 fileptr = fileptr->prev;
1274 }
1275#endif /* DEBUG */
1276}
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001277
1278/* Fix editbot based on the assumption that edittop is correct */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001279void fix_editbot(void)
1280{
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001281 int i;
1282 editbot = edittop;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001283 for (i = 0; (i <= editwinrows - 1) && (editbot->next != NULL)
1284 && (editbot != filebot); i++, editbot = editbot->next);
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001285}