blob: 96a1e0e15f47fd670fc361e690e8d7ed9d34c7d7 [file] [log] [blame]
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001/**************************************************************************
2 * winio.c *
3 * *
4 * Copyright (C) 1999 Chris Allegretta *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 1, or (at your option) *
8 * any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
18 * *
19 **************************************************************************/
20
21#include <stdarg.h>
22#include <string.h>
23#include "config.h"
24#include "proto.h"
25#include "nano.h"
26
27#ifndef NANO_SMALL
28#include <libintl.h>
29#define _(string) gettext(string)
30#else
31#define _(string) (string)
32#endif
33
34static int statblank = 0; /* Number of keystrokes left after
35 we call statubar() before we
36 actually blank the statusbar */
Robert Siemborskid8510b22000-06-06 23:04:06 +000037
38/* Local Function Prototypes for only winio.c */
39inline int get_page_from_virtual(int virtual);
40inline int get_page_start_virtual(int page);
41inline int get_page_end_virtual(int page);
42
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000043/* Window I/O */
44
45int do_first_line(void)
46{
47 current = fileage;
48 placewewant = 0;
49 current_x = 0;
50 edit_update(current);
51 return 1;
52}
53
54int do_last_line(void)
55{
56 current = filebot;
57 placewewant = 0;
58 current_x = 0;
59 edit_update(current);
60 return 1;
61}
62
63/* Like xplustabs, but for a specifc index of a speficific filestruct */
64int xpt(filestruct * fileptr, int index)
65{
66 int i, tabs = 0;
67
68 if (fileptr == NULL || fileptr->data == NULL)
69 return 0;
70
71 for (i = 0; i < index && fileptr->data[i] != 0; i++) {
72 tabs++;
73
74 if (fileptr->data[i] == NANO_CONTROL_I) {
75 if (tabs % 8 == 0);
76 else
77 tabs += 8 - (tabs % 8);
78 } else if (fileptr->data[i] & 0x80)
79 /* Make 8 bit chars only 1 collumn! */
80 ;
81 else if (fileptr->data[i] < 32)
82 tabs++;
83 }
84
85 return tabs;
86}
87
88
89/* Return the actual place on the screen of current->data[current_x], which
90 should always be > current_x */
91int xplustabs(void)
92{
93 return xpt(current, current_x);
94}
95
96
Robert Siemborskid8510b22000-06-06 23:04:06 +000097/* Return what current_x should be, given xplustabs() for the line,
98 * given a start position in the filestruct's data */
99int actual_x_from_start(filestruct * fileptr, int xplus, int start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000100{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000101 int i, tot = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000102
103 if (fileptr == NULL || fileptr->data == NULL)
104 return 0;
105
Robert Siemborskid8510b22000-06-06 23:04:06 +0000106 for (i = start; tot <= xplus && fileptr->data[i] != 0; i++,tot++)
107 if (fileptr->data[i] == NANO_CONTROL_I) {
108 if (tot % 8 == 0) tot++;
109 else tot += 8 - (tot % 8);
110 } else if (fileptr->data[i] & 0x80)
111 tot++; /* Make 8 bit chars only 1 column (again) */
112 else if (fileptr->data[i] < 32)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000113 tot += 2;
114
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000115#ifdef DEBUG
116 fprintf(stderr, _("actual_x for xplus=%d returned %d\n"), xplus, i);
117#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +0000118 return i - start;
119}
120
121/* Opposite of xplustabs */
122inline int actual_x(filestruct * fileptr, int xplus)
123{
124 return actual_x_from_start(fileptr, xplus, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000125}
126
127/* a strlen with tabs factored in, similar to xplustabs() */
128int strlenpt(char *buf)
129{
130 int i, tabs = 0;
131
132 if (buf == NULL)
133 return 0;
134
135 for (i = 0; buf[i] != 0; i++) {
136 tabs++;
137
138 if (buf[i] == NANO_CONTROL_I) {
139 if (tabs % 8 == 0);
140 else
141 tabs += 8 - (tabs % 8);
142 } else if (buf[i] & 0x80)
143 /* Make 8 bit chars only 1 collumn! */
144 ;
145 else if (buf[i] < 32)
146 tabs++;
147 }
148
149 return tabs;
150}
151
152
153/* resets current_y based on the position of current and puts the cursor at
154 (current_y, current_x) */
155void reset_cursor(void)
156{
157 filestruct *ptr = edittop;
158 int x;
159
160 current_y = 0;
161
162 while (ptr != current && ptr != editbot && ptr->next != NULL) {
163 ptr = ptr->next;
164 current_y++;
165 }
166
167 x = xplustabs();
168 if (x <= COLS - 2)
Robert Siemborskid8510b22000-06-06 23:04:06 +0000169 wmove(edit, current_y, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000170 else
Robert Siemborskid8510b22000-06-06 23:04:06 +0000171 wmove(edit, current_y, x -
Robert Siemborski7a1da872000-06-07 04:31:48 +0000172 get_page_start_virtual(get_page_from_virtual(x)));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000173
174}
175
176void blank_bottombars(void)
177{
178 int i = no_help()? 3 : 1;
179
180 for (; i <= 2; i++)
181 mvwaddstr(bottomwin, i, 0, hblank);
182
183}
184
185void blank_edit(void)
186{
187 int i;
188 for (i = 0; i <= editwinrows - 1; i++)
189 mvwaddstr(edit, i, 0, hblank);
190 wrefresh(edit);
191}
192
193
194void blank_statusbar(void)
195{
196 mvwaddstr(bottomwin, 0, 0, hblank);
197}
198
199void blank_statusbar_refresh(void)
200{
201 blank_statusbar();
202 wrefresh(bottomwin);
203}
204
205void check_statblank(void)
206{
207
208 if (statblank > 1)
209 statblank--;
210 else if (statblank == 1 && !ISSET(CONSTUPDATE)) {
211 statblank--;
212 blank_statusbar_refresh();
213 }
214}
215
216/* Get the input from the kb, this should only be called from statusq */
217int nanogetstr(char *buf, char *def, shortcut s[], int slen, int start_x)
218{
219 int kbinput = 0, j = 0, x = 0, xend;
220 int x_left = 0;
221 char inputstr[132], inputbuf[132] = "";
222
223 blank_statusbar();
224 mvwaddstr(bottomwin, 0, 0, buf);
225 if (strlen(def) > 0)
226 waddstr(bottomwin, def);
227 wrefresh(bottomwin);
228
229 x_left = strlen(buf);
230 x = strlen(def) + x_left;
231
232 /* Get the input! */
233 if (strlen(def) > 0) {
234 strcpy(answer, def);
235 strcpy(inputbuf, def);
236 }
237 /* Go into raw mode so we can actually get ^C, for example */
238 raw();
239
240 while ((kbinput = wgetch(bottomwin)) != 13) {
241 for (j = 0; j <= slen - 1; j++) {
242 if (kbinput == s[j].val) {
243 noraw();
244 cbreak();
245 strcpy(answer, "");
246 return s[j].val;
247 }
248 }
249 xend = strlen(buf) + strlen(inputbuf);
250
251 switch (kbinput) {
252 case KEY_HOME:
253 x = x_left;
254 blank_statusbar();
255 mvwaddstr(bottomwin, 0, 0, buf);
256 waddstr(bottomwin, inputbuf);
257 wmove(bottomwin, 0, x);
258 break;
259 case KEY_END:
260 x = x_left + strlen(inputbuf);
261 blank_statusbar();
262 mvwaddstr(bottomwin, 0, 0, buf);
263 waddstr(bottomwin, inputbuf);
264 wmove(bottomwin, 0, x);
265 break;
266 case KEY_RIGHT:
267
268 if (x < xend)
269 x++;
270 wmove(bottomwin, 0, x);
271 break;
272 case NANO_CONTROL_D:
273 if (strlen(inputbuf) > 0 && (x - x_left) != strlen(inputbuf)) {
274 memmove(inputbuf + (x - x_left),
275 inputbuf + (x - x_left) + 1,
276 strlen(inputbuf) - (x - x_left) - 1);
277 inputbuf[strlen(inputbuf) - 1] = 0;
278 }
279 blank_statusbar();
280 mvwaddstr(bottomwin, 0, 0, buf);
281 waddstr(bottomwin, inputbuf);
282 wmove(bottomwin, 0, x);
283 break;
284 case NANO_CONTROL_K:
285 case NANO_CONTROL_U:
286 *inputbuf = 0;
287 x = x_left;
288 blank_statusbar();
289 mvwaddstr(bottomwin, 0, 0, buf);
290 waddstr(bottomwin, inputbuf);
291 wmove(bottomwin, 0, x);
292 break;
293 case KEY_BACKSPACE:
294 case KEY_DC:
295 case 127:
296 case NANO_CONTROL_H:
297 if (strlen(inputbuf) > 0) {
298 if (x == (x_left + strlen(inputbuf)))
299 inputbuf[strlen(inputbuf) - 1] = 0;
300 else if (x - x_left) {
301 memmove(inputbuf + (x - x_left) - 1,
302 inputbuf + (x - x_left),
303 strlen(inputbuf) - (x - x_left));
304 inputbuf[strlen(inputbuf) - 1] = 0;
305 }
306 }
307 blank_statusbar();
308 mvwaddstr(bottomwin, 0, 0, buf);
309 waddstr(bottomwin, inputbuf);
310 case KEY_LEFT:
311 if (x > strlen(buf))
312 x--;
313 wmove(bottomwin, 0, x);
314 break;
315 case KEY_UP:
316 case KEY_DOWN:
317 break;
318
319 case 27:
320 switch (kbinput = wgetch(edit)) {
321 case 79:
322 switch (kbinput = wgetch(edit)) {
323 case 70:
324 x = x_left + strlen(inputbuf);
325 blank_statusbar();
326 mvwaddstr(bottomwin, 0, 0, buf);
327 waddstr(bottomwin, inputbuf);
328 wmove(bottomwin, 0, x);
329 break;
330 case 72:
331 x = x_left;
332 blank_statusbar();
333 mvwaddstr(bottomwin, 0, 0, buf);
334 waddstr(bottomwin, inputbuf);
335 wmove(bottomwin, 0, x);
336 break;
337 }
338 break;
339 case 91:
340 switch (kbinput = wgetch(edit)) {
341 case 'C':
342 if (x < xend)
343 x++;
344 wmove(bottomwin, 0, x);
345 break;
346 case 'D':
347 if (x > strlen(buf))
348 x--;
349 wmove(bottomwin, 0, x);
350 break;
351 case 49:
352 x = x_left;
353 blank_statusbar();
354 mvwaddstr(bottomwin, 0, 0, buf);
355 waddstr(bottomwin, inputbuf);
356 wmove(bottomwin, 0, x);
357 goto skip_126;
358 case 51:
359 if (strlen(inputbuf) > 0
360 && (x - x_left) != strlen(inputbuf)) {
361 memmove(inputbuf + (x - x_left),
362 inputbuf + (x - x_left) + 1,
363 strlen(inputbuf) - (x - x_left) - 1);
364 inputbuf[strlen(inputbuf) - 1] = 0;
365 }
366 blank_statusbar();
367 mvwaddstr(bottomwin, 0, 0, buf);
368 waddstr(bottomwin, inputbuf);
369 wmove(bottomwin, 0, x);
370 goto skip_126;
371 case 52:
372 x = x_left + strlen(inputbuf);
373 blank_statusbar();
374 mvwaddstr(bottomwin, 0, 0, buf);
375 waddstr(bottomwin, inputbuf);
376 wmove(bottomwin, 0, x);
377 goto skip_126;
378 skip_126:
379 nodelay(edit, TRUE);
380 kbinput = wgetch(edit);
381 if (kbinput == 126 || kbinput == ERR)
382 kbinput = -1;
383 nodelay(edit, FALSE);
384 break;
385 }
386 }
387 blank_statusbar();
388 mvwaddstr(bottomwin, 0, 0, buf);
389 waddstr(bottomwin, inputbuf);
390 wmove(bottomwin, 0, x);
391 break;
392
393
394 default:
395 if (kbinput < 32)
396 break;
397 strcpy(inputstr, inputbuf);
398 inputstr[x - strlen(buf)] = kbinput;
399 strcpy(&inputstr[x - strlen(buf) + 1],
400 &inputbuf[x - strlen(buf)]);
401 strcpy(inputbuf, inputstr);
402 x++;
403
404 mvwaddstr(bottomwin, 0, 0, buf);
405 waddstr(bottomwin, inputbuf);
406 wmove(bottomwin, 0, x);
407
408#ifdef DEBUG
409 fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput);
410#endif
411 }
412 wrefresh(bottomwin);
413 }
414
415 strncpy(answer, inputbuf, 132);
416
417 noraw();
418 cbreak();
419 if (!strcmp(answer, ""))
420 return -2;
421 else
422 return 0;
423}
424
425void horizbar(WINDOW * win, int y)
426{
427 wattron(win, A_REVERSE);
428 mvwaddstr(win, 0, 0, hblank);
429 wattroff(win, A_REVERSE);
430}
431
432void titlebar(void)
433{
434 int namelen, space;
435
436 horizbar(topwin, 0);
437 wattron(topwin, A_REVERSE);
438 mvwaddstr(topwin, 0, 3, VERMSG);
439
440 space = COLS - strlen(VERMSG) - strlen(VERSION) - 21;
441
442 namelen = strlen(filename);
443
444 if (!strcmp(filename, ""))
445 mvwaddstr(topwin, 0, center_x - 6, _("New Buffer"));
446 else {
447 if (namelen > space) {
448 waddstr(topwin, _(" File: ..."));
449 waddstr(topwin, &filename[namelen - space]);
450 } else {
451 mvwaddstr(topwin, 0, center_x - (namelen / 2 + 1), "File: ");
452 waddstr(topwin, filename);
453 }
454 }
455 if (ISSET(MODIFIED))
456 mvwaddstr(topwin, 0, COLS - 10, _("Modified"));
457 wattroff(topwin, A_REVERSE);
458 wrefresh(topwin);
459 reset_cursor();
460}
461
462void onekey(char *keystroke, char *desc)
463{
464 char description[80];
465
466 snprintf(description, 12, " %-11s", desc);
467 wattron(bottomwin, A_REVERSE);
468 waddstr(bottomwin, keystroke);
469 wattroff(bottomwin, A_REVERSE);
470 waddstr(bottomwin, description);
471}
472
473void clear_bottomwin(void)
474{
475 if (ISSET(NO_HELP))
476 return;
477
478 mvwaddstr(bottomwin, 1, 0, hblank);
479 mvwaddstr(bottomwin, 2, 0, hblank);
480 wrefresh(bottomwin);
481}
482
483void bottombars(shortcut s[], int slen)
484{
485 int i, j, k;
486 char keystr[10];
487
488 if (ISSET(NO_HELP))
489 return;
490
491 /* Determine how many extra spaces are needed to fill the bottom of the screen */
492 k = COLS / 6 - 13;
493
494 clear_bottomwin();
495 wmove(bottomwin, 1, 0);
496 for (i = 0; i <= slen - 1; i += 2) {
497 sprintf(keystr, "^%c", s[i].val + 64);
498 onekey(keystr, s[i].desc);
499
500 for (j = 0; j < k; j++)
501 waddch(bottomwin, ' ');
502 }
503
504 wmove(bottomwin, 2, 0);
505 for (i = 1; i <= slen - 1; i += 2) {
506 sprintf(keystr, "^%c", s[i].val + 64);
507 onekey(keystr, s[i].desc);
508
509 for (j = 0; j < k; j++)
510 waddch(bottomwin, ' ');
511 }
512
513 wrefresh(bottomwin);
514
515}
516
517/* If modified is not already set, set it and update titlebar */
518void set_modified(void)
519{
520 if (!ISSET(MODIFIED)) {
521 SET(MODIFIED);
522 titlebar();
523 wrefresh(topwin);
524 }
525}
526
Robert Siemborskid8510b22000-06-06 23:04:06 +0000527inline int get_page_from_virtual(int virtual) {
528 int page = 2;
529
530 if(virtual <= COLS - 2) return 1;
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000531 virtual -= (COLS - 2);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000532
533 while (virtual > COLS - 2 - 7) {
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000534 virtual -= (COLS - 2 - 7);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000535 page++;
536 }
537
538 return page;
539}
540
541inline int get_page_start_virtual(int page) {
Robert Siemborskie8c6fd02000-06-07 04:40:09 +0000542 int virtual;
543 virtual = --page * (COLS - 7);
544 if(page) virtual -= 2 * page - 1;
545 return virtual;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000546}
547
548inline int get_page_end_virtual(int page) {
549 return get_page_start_virtual(page) + COLS - 1;
550}
551
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000552#ifndef NANO_SMALL
Robert Siemborskid8510b22000-06-06 23:04:06 +0000553/* begin, end: beginning and end of mark in data
554 * fileptr: the data
555 * y: the line on screen */
556void add_marked_sameline(int begin, int end, filestruct *fileptr, int y)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000557{
Robert Siemborskid8510b22000-06-06 23:04:06 +0000558 /* where we are on the line */
559 int virtual_col = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000560
Robert Siemborskid8510b22000-06-06 23:04:06 +0000561 /* actual_col is beginning of the line in the data */
562 int this_page = get_page_from_virtual(virtual_col),
563 this_page_start = get_page_start_virtual(this_page),
564 this_page_end = get_page_end_virtual(this_page),
565 actual_col = actual_x(fileptr, this_page_start);
566
567 /* 3 start points: 0 -> begin, begin->end, end->strlen(data) */
568 /* in data : pre sel post */
569 int virtual_sel_start = xpt(fileptr, begin),
570 sel_start = 0,
571 virtual_post_start = xpt(fileptr, end),
572 post_start = 0;
573
574 /* likewise, 3 data lengths */
575 int pre_data_len = begin,
576 sel_data_len = end - begin,
577 post_data_len = 0;
578
579 /* now fix the start locations & lengths according to the cursor's
580 * position (ie: our page) */
581 if(xpt(fileptr,pre_data_len) < this_page_start) pre_data_len = 0;
582 else pre_data_len -= actual_col;
583
584 if(virtual_sel_start < this_page_start) {
585 begin = actual_col;
586 virtual_sel_start = this_page_start;
587 }
588 if(virtual_post_start < this_page_start) {
589 end = actual_col;
590 virtual_post_start = this_page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000591 }
592
Robert Siemborskid8510b22000-06-06 23:04:06 +0000593 /* we don't care about end, because it will just get cropped
594 * due to length */
595 if(virtual_sel_start > this_page_end)
596 virtual_sel_start = this_page_end;
597 if(virtual_post_start > this_page_end)
598 virtual_post_start = this_page_end;
599
600 sel_data_len = actual_x(fileptr, virtual_post_start) -
601 actual_x(fileptr, virtual_sel_start);
602
603 post_data_len = actual_x(fileptr, this_page_end) -
604 actual_x(fileptr, virtual_post_start);
605
606 sel_start = virtual_sel_start - this_page_start;
607 post_start = virtual_post_start - this_page_start;
608
609 mvwaddnstr(edit, y, 0, &fileptr->data[actual_col], pre_data_len);
610 wattron(edit, A_REVERSE);
611 mvwaddnstr(edit, y, sel_start, &fileptr->data[begin], sel_data_len);
612 wattroff(edit, A_REVERSE);
613 mvwaddnstr(edit, y, post_start, &fileptr->data[end], post_data_len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000614}
615#endif
616
Robert Siemborski7a1da872000-06-07 04:31:48 +0000617/* we used to have xval. turns out it should always be zero */
618void edit_add(filestruct * fileptr, int yval, int start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000619{
620#ifndef NANO_SMALL
621 int col;
622
623 if (ISSET(MARK_ISSET)) {
Robert Siemborskid8510b22000-06-06 23:04:06 +0000624 /* Our horribly ugly marker code */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000625 if ((fileptr->lineno > mark_beginbuf->lineno
626 && fileptr->lineno > current->lineno)
627 || (fileptr->lineno < mark_beginbuf->lineno
628 && fileptr->lineno < current->lineno)) {
629
630 /* We're on a normal, unselected line */
Robert Siemborskid8510b22000-06-06 23:04:06 +0000631 mvwaddnstr(edit, yval, 0, fileptr->data,
632 actual_x(fileptr, COLS));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000633 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000634 /* We're on selected text */
635 if (fileptr != mark_beginbuf && fileptr != current) {
636 wattron(edit, A_REVERSE);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000637 mvwaddnstr(edit, yval, 0, fileptr->data, actual_x(fileptr,COLS));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000638 wattroff(edit, A_REVERSE);
639 }
640 /* Special case, we're still on the same line we started marking */
641 else if (fileptr == mark_beginbuf && fileptr == current) {
Robert Siemborskid8510b22000-06-06 23:04:06 +0000642 if (current_x < mark_beginx)
643 add_marked_sameline(current_x, mark_beginx, fileptr, yval);
644 else
645 add_marked_sameline(mark_beginx, current_x, fileptr, yval);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000646
647 } else if (fileptr == mark_beginbuf) {
Robert Siemborskid8510b22000-06-06 23:04:06 +0000648 int target;
649
650 /* we're at the line that was first marked */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000651 if (mark_beginbuf->lineno > current->lineno)
652 wattron(edit, A_REVERSE);
653
Robert Siemborskid8510b22000-06-06 23:04:06 +0000654 target = (xpt(fileptr,mark_beginx) < COLS - 1) ? mark_beginx : COLS - 1;
655
656 mvwaddnstr(edit, yval, 0, fileptr->data,
657 actual_x(fileptr, target));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000658
659 if (mark_beginbuf->lineno < current->lineno)
660 wattron(edit, A_REVERSE);
661 else
662 wattroff(edit, A_REVERSE);
663
Robert Siemborskid8510b22000-06-06 23:04:06 +0000664 target = (COLS - 1) - xpt(fileptr,mark_beginx);
665 if(target < 0) target = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000666
Robert Siemborskid8510b22000-06-06 23:04:06 +0000667 mvwaddnstr(edit, yval, xpt(fileptr,mark_beginx),
668 &fileptr->data[mark_beginx],
669 actual_x_from_start(fileptr, target, mark_beginx));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000670
671 if (mark_beginbuf->lineno < current->lineno)
672 wattroff(edit, A_REVERSE);
673
674 } else if (fileptr == current) {
Robert Siemborskid8510b22000-06-06 23:04:06 +0000675 /* we're on the cursors line, but it's not the first
676 * one we marked... */
677 int this_page = get_page_from_virtual(xplustabs()),
678 this_page_start = get_page_start_virtual(this_page),
679 this_page_end = get_page_end_virtual(this_page);
680
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000681 if (mark_beginbuf->lineno < current->lineno)
682 wattron(edit, A_REVERSE);
683
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000684 if (xplustabs() > COLS - 2) {
Robert Siemborskid8510b22000-06-06 23:04:06 +0000685 col = actual_x(current, this_page_start);
686 mvwaddnstr(edit, yval, 0, &fileptr->data[col],
687 current_x - col);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000688 } else
689 mvwaddnstr(edit, yval, 0, fileptr->data, current_x);
690
691 if (mark_beginbuf->lineno > current->lineno)
692 wattron(edit, A_REVERSE);
693 else
694 wattroff(edit, A_REVERSE);
695
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000696 if (xplustabs() > COLS - 2) {
Robert Siemborskid8510b22000-06-06 23:04:06 +0000697 mvwaddnstr(edit, yval, xplustabs() - this_page_start,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000698 &fileptr->data[current_x],
Robert Siemborskid8510b22000-06-06 23:04:06 +0000699 actual_x(current,this_page_end) - current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000700 } else
701 mvwaddnstr(edit, yval, xplustabs(),
702 &fileptr->data[current_x],
Robert Siemborskid8510b22000-06-06 23:04:06 +0000703 actual_x_from_start(fileptr,
704 COLS - xpt(fileptr,current_x), current_x));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000705
706 if (mark_beginbuf->lineno > current->lineno)
707 wattroff(edit, A_REVERSE);
708
709 }
710 }
711
712 } else
713#endif
Robert Siemborski7a1da872000-06-07 04:31:48 +0000714 mvwaddnstr(edit, yval, 0, &fileptr->data[start],
715 actual_x_from_start(fileptr,COLS,start));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000716
717}
718
719/*
720 * Just update one line in the edit buffer
721 *
722 * index gives is a place in the string to update starting from.
723 * Likely args are current_x or 0.
724 */
Robert Siemborskid8510b22000-06-06 23:04:06 +0000725
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000726void update_line(filestruct * fileptr, int index)
727{
728 filestruct *filetmp;
729 int line = 0, col = 0, actual_col = 0, x;
730
731 for (filetmp = edittop; filetmp != fileptr && filetmp != editbot;
732 filetmp = filetmp->next)
733 line++;
734
735 mvwaddstr(edit, line, 0, hblank);
736
737 if (current == fileptr && (x = xpt(current, index)) > COLS - 2) {
Robert Siemborskid8510b22000-06-06 23:04:06 +0000738 int page = get_page_from_virtual(x);
739 col = get_page_start_virtual(page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000740 actual_col = actual_x(filetmp, col);
741
Robert Siemborski7a1da872000-06-07 04:31:48 +0000742 edit_add(filetmp, line, actual_col);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000743 mvwaddch(edit, line, 0, '$');
744
Robert Siemborskid8510b22000-06-06 23:04:06 +0000745 if (strlenpt(fileptr->data) > get_page_end_virtual(page))
746 mvwaddch(edit, line, COLS - 1, '$');
747 } else {
Robert Siemborski7a1da872000-06-07 04:31:48 +0000748 edit_add(filetmp, line, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000749
Robert Siemborskid8510b22000-06-06 23:04:06 +0000750 if (strlenpt(&filetmp->data[actual_col]) > COLS)
751 mvwaddch(edit, line, COLS - 1, '$');
752 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000753}
754
755void center_cursor(void)
756{
757 current_y = editwinrows / 2;
758 wmove(edit, current_y, current_x);
759}
760
761/* Refresh the screen without changing the position of lines */
762void edit_refresh(void)
763{
764 int lines = 0, i = 0;
765 filestruct *temp, *hold = current;
766
767 if (current == NULL)
768 return;
769
770 temp = edittop;
771
772 while (lines <= editwinrows - 1 && lines <= totlines && temp != NULL) {
773 hold = temp;
774 update_line(temp, current_x);
775 temp = temp->next;
776 lines++;
777 }
778
779 if (lines <= editwinrows - 1)
780 while (lines <= editwinrows - 1) {
781 mvwaddstr(edit, lines, i, hblank);
782 lines++;
783 }
784 if (temp == NULL)
785 editbot = hold;
786 else
787 editbot = temp;
788}
789
790/*
791 * Nice generic routine to update the edit buffer given a pointer to the
792 * file struct =)
793 */
794void edit_update(filestruct * fileptr)
795{
796
797 int lines = 0, i = 0;
798 filestruct *temp;
799
800 if (fileptr == NULL)
801 return;
802
803 temp = fileptr;
804 while (i <= editwinrows / 2 && temp->prev != NULL) {
805 i++;
806 temp = temp->prev;
807 }
808 edittop = temp;
809
810 while (lines <= editwinrows - 1 && lines <= totlines && temp != NULL
811 && temp != filebot) {
812 temp = temp->next;
813 lines++;
814 }
815 editbot = temp;
816
817 edit_refresh();
818}
819
820/* Now we want to update the screen using this struct as the top of the edit buffer */
821void edit_update_top(filestruct * fileptr)
822{
823 int i;
824 filestruct *temp = fileptr;
825
826 if (fileptr->next == NULL || fileptr == NULL)
827 return;
828
829 i = 0;
830 while (i <= editwinrows / 2 && temp->next != NULL) {
831 i++;
832 temp = temp->next;
833 }
834 edit_update(temp);
835}
836
837/* And also for the bottom... */
838void edit_update_bot(filestruct * fileptr)
839{
840 int i;
841 filestruct *temp = fileptr;
842
843 i = 0;
844 while (i <= editwinrows / 2 - 1 && temp->prev != NULL) {
845 i++;
846 temp = temp->prev;
847 }
848 edit_update(temp);
849}
850
851/* This function updates current based on where current_y is, reset_cursor
852 does the opposite */
853void update_cursor(void)
854{
855 int i = 0;
856
857#ifdef DEBUG
858 fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
859 current_x);
860#endif
861
862 current = edittop;
863 while (i <= current_y - 1 && current->next != NULL) {
864 current = current->next;
865 i++;
866 }
867
868#ifdef DEBUG
869 fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
870#endif
871
872}
873
874/*
875 * Ask a question on the statusbar. Answer will be stored in answer
876 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
877 * otherwise, the valid shortcut key caught, Def is any editable text we
878 * want to put up by default.
879 */
880int statusq(shortcut s[], int slen, char *def, char *msg, ...)
881{
882 va_list ap;
883 char foo[133];
884 int ret;
885
886 bottombars(s, slen);
887
888 va_start(ap, msg);
889 vsnprintf(foo, 132, msg, ap);
890 strncat(foo, ": ", 132);
891 va_end(ap);
892
893 wattron(bottomwin, A_REVERSE);
894 ret = nanogetstr(foo, def, s, slen, (strlen(foo) + 3));
895 wattroff(bottomwin, A_REVERSE);
896
897 switch (ret) {
898
899 case NANO_FIRSTLINE_KEY:
900 do_first_line();
901 break;
902 case NANO_LASTLINE_KEY:
903 do_last_line();
904 break;
905 case NANO_CANCEL_KEY:
906 return -1;
907 default:
908 blank_statusbar_refresh();
909 }
910
911#ifdef DEBUG
912 fprintf(stderr, _("I got \"%s\"\n"), answer);
913#endif
914
915 return ret;
916}
917
918/*
919 * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0 for
920 * N, 2 for All (if all is non-zero when passed in) and -1 for abort (^C)
921 */
922int do_yesno(int all, int leavecursor, char *msg, ...)
923{
924 va_list ap;
925 char foo[133];
926 int kbinput, ok = -1;
927
928 /* Write the bottom of the screen */
929 clear_bottomwin();
930 wattron(bottomwin, A_REVERSE);
931 blank_statusbar_refresh();
932 wattroff(bottomwin, A_REVERSE);
933
934 if (!ISSET(NO_HELP)) {
935 wmove(bottomwin, 1, 0);
936 onekey(_(" Y"), _("Yes"));
937 if (all)
938 onekey(_(" A"), _("All"));
939 wmove(bottomwin, 2, 0);
940 onekey(_(" N"), _("No"));
941 onekey(_("^C"), _("Cancel"));
942 }
943 va_start(ap, msg);
944 vsnprintf(foo, 132, msg, ap);
945 va_end(ap);
946 wattron(bottomwin, A_REVERSE);
947 mvwaddstr(bottomwin, 0, 0, foo);
948 wattroff(bottomwin, A_REVERSE);
949 wrefresh(bottomwin);
950
951 if (leavecursor == 1)
952 reset_cursor();
953
954 raw();
955
956 while (ok == -1) {
957 kbinput = wgetch(edit);
958
959 switch (kbinput) {
960 case 'Y':
961 case 'y':
962 ok = 1;
963 break;
964 case 'N':
965 case 'n':
966 ok = 0;
967 break;
968 case 'A':
969 case 'a':
970 if (all)
971 ok = 2;
972 break;
973 case NANO_CONTROL_C:
974 ok = -2;
975 break;
976 }
977 }
978 noraw();
979 cbreak();
980
981 /* Then blank the screen */
982 blank_statusbar_refresh();
983
984 if (ok == -2)
985 return -1;
986 else
987 return ok;
988}
989
990void statusbar(char *msg, ...)
991{
992 va_list ap;
993 char foo[133];
994 int start_x = 0;
995
996 va_start(ap, msg);
997 vsnprintf(foo, 132, msg, ap);
998 va_end(ap);
999
1000 start_x = center_x - strlen(foo) / 2 - 1;
1001
1002 /* Blank out line */
1003 blank_statusbar();
1004
1005 wmove(bottomwin, 0, start_x);
1006
1007 wattron(bottomwin, A_REVERSE);
1008
1009 waddstr(bottomwin, "[ ");
1010 waddstr(bottomwin, foo);
1011 waddstr(bottomwin, " ]");
1012 wattroff(bottomwin, A_REVERSE);
1013 wrefresh(bottomwin);
1014
1015 if (ISSET(CONSTUPDATE))
1016 statblank = 1;
1017 else
1018 statblank = 25;
1019}
1020
1021void display_main_list(void)
1022{
1023 bottombars(main_list, MAIN_VISIBLE);
1024}
1025
1026int total_refresh(void)
1027{
1028 display_main_list();
1029 clearok(edit, TRUE);
1030 clearok(topwin, TRUE);
1031 clearok(bottomwin, TRUE);
1032 wnoutrefresh(edit);
1033 wnoutrefresh(topwin);
1034 wnoutrefresh(bottomwin);
1035 doupdate();
1036 clearok(edit, FALSE);
1037 clearok(topwin, FALSE);
1038 clearok(bottomwin, FALSE);
1039
1040 return 1;
1041}
1042
1043void previous_line(void)
1044{
1045 if (current_y > 0)
1046 current_y--;
1047}
1048
1049int do_cursorpos(void)
1050{
1051 filestruct *fileptr;
1052 float linepct, bytepct;
1053 int i, tot = 0;
1054
1055 if (current == NULL || fileage == NULL)
1056 return 0;
1057
1058 for (fileptr = fileage; fileptr != current && fileptr != NULL; fileptr = fileptr->next)
1059 tot += strlen(fileptr->data) + 1;
1060
1061 if (fileptr == NULL)
1062 return -1;
1063
1064 i = tot + current_x;;
1065
1066 for (fileptr = current->next; fileptr != NULL; fileptr = fileptr->next)
1067 tot += strlen(fileptr->data) + 1;
1068
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001069 if (totlines > 0)
1070 linepct = 100 * current->lineno / totlines;
1071 else
1072 linepct = 0;
1073
1074 if (totsize > 0)
1075 bytepct = 100 * i / totsize;
1076 else
1077 bytepct = 0;
1078
1079#ifdef DEBUG
1080 fprintf(stderr, _("do_cursorpos: linepct = %f, bytepct = %f\n"),
1081 linepct, bytepct);
1082#endif
1083
1084 statusbar(_("line %d of %d (%.0f%%), character %d of %d (%.0f%%)"),
1085 current->lineno, totlines, linepct, i, totsize, bytepct);
1086 reset_cursor();
1087 return 1;
1088}
1089
1090/* Our broken, non-shortcut list compliant help function.
1091 But hey, it's better than nothing, and it's dynamic! */
1092int do_help(void)
1093{
1094#ifndef NANO_SMALL
1095 char *ptr = help_text, *end;
1096 int i, j, row = 0, page = 1, kbinput = 0, no_more = 0;
1097 int no_help_flag = 0;
1098
1099 blank_edit();
1100 curs_set(0);
1101 blank_statusbar();
1102
1103 if (ISSET(NO_HELP)) {
1104
1105 no_help_flag = 1;
1106 delwin (bottomwin);
1107 bottomwin = newwin(3, COLS, LINES - 3, 0);
1108 keypad(bottomwin, TRUE);
1109
1110 editwinrows -= no_help ();
1111 UNSET(NO_HELP);
1112 bottombars(help_list, HELP_LIST_LEN);
1113 }
1114 else
1115 bottombars(help_list, HELP_LIST_LEN);
1116
1117 do {
1118 ptr = help_text;
1119 switch (kbinput) {
1120 case NANO_NEXTPAGE_KEY:
1121 case NANO_NEXTPAGE_FKEY:
1122 case KEY_NPAGE:
1123 if (!no_more) {
1124 blank_edit();
1125 page++;
1126 }
1127 break;
1128 case NANO_PREVPAGE_KEY:
1129 case NANO_PREVPAGE_FKEY:
1130 case KEY_PPAGE:
1131 if (page > 1) {
1132 no_more = 0;
1133 blank_edit();
1134 page--;
1135 }
1136 break;
1137 }
1138
1139 /* Calculate where in the text we should be based on the page */
1140 for (i = 1; i < page; i++) {
1141 row = 0;
1142 j = 0;
1143 while (row < editwinrows && *ptr != '\0') {
1144 if (*ptr == '\n' || j == COLS - 5) {
1145 j = 0;
1146 row++;
1147 }
1148 ptr++;
1149 j++;
1150 }
1151 }
1152
1153 i = 0;
1154 j = 0;
1155 while (i < editwinrows && *ptr != '\0') {
1156 end = ptr;
1157 while (*end != '\n' && *end != '\0' && j != COLS - 5) {
1158 end++;
1159 j++;
1160 }
1161 if (j == COLS - 5) {
1162
1163 /* Don't print half a word if we've run of of space */
1164 while (*end != ' ' && *end != '\0') {
1165 end--;
1166 j--;
1167 }
1168 }
1169 mvwaddnstr(edit, i, 0, ptr, j);
1170 j = 0;
1171 i++;
1172 if (*end == '\n')
1173 end++;
1174 ptr = end;
1175 }
1176 if (*ptr == '\0') {
1177 no_more = 1;
1178 continue;
1179 }
1180 } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY);
1181
1182 if (no_help_flag) {
1183 werase(bottomwin);
1184 wrefresh(bottomwin);
1185 delwin (bottomwin);
1186 SET(NO_HELP);
1187 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
1188 keypad(bottomwin, TRUE);
1189 editwinrows += no_help();
1190 }
1191 else
1192 display_main_list();
1193
1194 curs_set(1);
1195 edit_refresh();
1196#else
1197 nano_small_msg();
1198#endif
1199
1200 return 1;
1201}
1202
1203/* Dump the current file structure to stderr */
1204void dump_buffer(filestruct * inptr)
1205{
1206#ifdef DEBUG
1207 filestruct *fileptr;
1208
1209 if (inptr == fileage)
1210 fprintf(stderr, _("Dumping file buffer to stderr...\n"));
1211 else if (inptr == cutbuffer)
1212 fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
1213 else
1214 fprintf(stderr, _("Dumping a buffer to stderr...\n"));
1215
1216 fileptr = inptr;
1217 while (fileptr != NULL) {
1218 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1219 fflush(stderr);
1220 fileptr = fileptr->next;
1221 }
1222#endif /* DEBUG */
1223}
1224
1225void dump_buffer_reverse(filestruct * inptr)
1226{
1227#ifdef DEBUG
1228 filestruct *fileptr;
1229
1230 fileptr = filebot;
1231 while (fileptr != NULL) {
1232 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1233 fflush(stderr);
1234 fileptr = fileptr->prev;
1235 }
1236#endif /* DEBUG */
1237}