blob: 4cc14d8c80dcc8523903d3c5a64c9187746a3925 [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
Robert Siemborski53875912000-06-16 04:25:30 +0000116 fprintf(stderr, _("actual_x_from_start for xplus=%d returned %d\n"), xplus, i);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000117#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 Siemborski53875912000-06-16 04:25:30 +0000553/* Called only from edit_add, and therefore expects a
554 * converted-to-only-spaces line */
Robert Siemborskid8510b22000-06-06 23:04:06 +0000555/* begin, end: beginning and end of mark in data
556 * fileptr: the data
557 * y: the line on screen */
Robert Siemborski53875912000-06-16 04:25:30 +0000558void add_marked_sameline(int begin, int end, filestruct *fileptr, int y, int virt_cur_x)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000559{
Robert Siemborski53875912000-06-16 04:25:30 +0000560 int this_page = get_page_from_virtual(virt_cur_x),
Robert Siemborskid8510b22000-06-06 23:04:06 +0000561 this_page_start = get_page_start_virtual(this_page),
Robert Siemborski53875912000-06-16 04:25:30 +0000562 this_page_end = get_page_end_virtual(this_page);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000563
564 /* 3 start points: 0 -> begin, begin->end, end->strlen(data) */
565 /* in data : pre sel post */
Robert Siemborski53875912000-06-16 04:25:30 +0000566 int virtual_sel_start = begin,
Robert Siemborskid8510b22000-06-06 23:04:06 +0000567 sel_start = 0,
Robert Siemborski53875912000-06-16 04:25:30 +0000568 virtual_post_start = end,
Robert Siemborskid8510b22000-06-06 23:04:06 +0000569 post_start = 0;
570
571 /* likewise, 3 data lengths */
572 int pre_data_len = begin,
573 sel_data_len = end - begin,
574 post_data_len = 0;
575
576 /* now fix the start locations & lengths according to the cursor's
577 * position (ie: our page) */
Robert Siemborski53875912000-06-16 04:25:30 +0000578 if(pre_data_len < this_page_start) pre_data_len = 0;
579 else pre_data_len -= this_page_start;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000580
581 if(virtual_sel_start < this_page_start) {
Robert Siemborski53875912000-06-16 04:25:30 +0000582 begin = virtual_sel_start = this_page_start;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000583 }
584 if(virtual_post_start < this_page_start) {
Robert Siemborski53875912000-06-16 04:25:30 +0000585 end = virtual_post_start = this_page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000586 }
587
Robert Siemborskid8510b22000-06-06 23:04:06 +0000588 /* we don't care about end, because it will just get cropped
589 * due to length */
590 if(virtual_sel_start > this_page_end)
591 virtual_sel_start = this_page_end;
592 if(virtual_post_start > this_page_end)
593 virtual_post_start = this_page_end;
594
Robert Siemborski53875912000-06-16 04:25:30 +0000595 sel_data_len = virtual_post_start - virtual_sel_start;
596 post_data_len = this_page_end - virtual_post_start;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000597
598 sel_start = virtual_sel_start - this_page_start;
599 post_start = virtual_post_start - this_page_start;
600
Robert Siemborski53875912000-06-16 04:25:30 +0000601 mvwaddnstr(edit, y, 0, &fileptr->data[this_page_start], pre_data_len);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000602 wattron(edit, A_REVERSE);
603 mvwaddnstr(edit, y, sel_start, &fileptr->data[begin], sel_data_len);
604 wattroff(edit, A_REVERSE);
605 mvwaddnstr(edit, y, post_start, &fileptr->data[end], post_data_len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000606}
607#endif
608
Robert Siemborski53875912000-06-16 04:25:30 +0000609/* Called only from update_line. Expects a converted-to-not-have-tabs
610 * line */
611void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
612 int virt_mark_beginx)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000613{
614#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000615 if (ISSET(MARK_ISSET)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000616 if ((fileptr->lineno > mark_beginbuf->lineno
617 && fileptr->lineno > current->lineno)
618 || (fileptr->lineno < mark_beginbuf->lineno
619 && fileptr->lineno < current->lineno)) {
620
621 /* We're on a normal, unselected line */
Robert Siemborski53875912000-06-16 04:25:30 +0000622 mvwaddnstr(edit, yval, 0, fileptr->data, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000623 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000624 /* We're on selected text */
625 if (fileptr != mark_beginbuf && fileptr != current) {
626 wattron(edit, A_REVERSE);
Robert Siemborski53875912000-06-16 04:25:30 +0000627 mvwaddnstr(edit, yval, 0, fileptr->data, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000628 wattroff(edit, A_REVERSE);
629 }
Robert Siemborski53875912000-06-16 04:25:30 +0000630
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000631 /* Special case, we're still on the same line we started marking */
632 else if (fileptr == mark_beginbuf && fileptr == current) {
Robert Siemborski53875912000-06-16 04:25:30 +0000633 if (virt_cur_x < virt_mark_beginx)
634 add_marked_sameline(virt_cur_x, virt_mark_beginx,
635 fileptr, yval, virt_cur_x);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000636 else
Robert Siemborski53875912000-06-16 04:25:30 +0000637 add_marked_sameline(virt_mark_beginx, virt_cur_x,
638 fileptr, yval, virt_cur_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000639
640 } else if (fileptr == mark_beginbuf) {
Robert Siemborskid8510b22000-06-06 23:04:06 +0000641 int target;
642
Robert Siemborski53875912000-06-16 04:25:30 +0000643 /* we're updating the line that was first marked */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000644 if (mark_beginbuf->lineno > current->lineno)
645 wattron(edit, A_REVERSE);
646
Robert Siemborski53875912000-06-16 04:25:30 +0000647 target = (virt_mark_beginx < COLS - 1) ? virt_mark_beginx : COLS - 1;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000648
Robert Siemborski53875912000-06-16 04:25:30 +0000649 mvwaddnstr(edit, yval, 0, fileptr->data, target);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000650
651 if (mark_beginbuf->lineno < current->lineno)
652 wattron(edit, A_REVERSE);
653 else
654 wattroff(edit, A_REVERSE);
655
Robert Siemborski53875912000-06-16 04:25:30 +0000656 target = (COLS - 1) - virt_mark_beginx;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000657 if(target < 0) target = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000658
Robert Siemborski53875912000-06-16 04:25:30 +0000659 mvwaddnstr(edit, yval, virt_mark_beginx,
660 &fileptr->data[virt_mark_beginx],
661 target);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000662
663 if (mark_beginbuf->lineno < current->lineno)
664 wattroff(edit, A_REVERSE);
665
666 } else if (fileptr == current) {
Robert Siemborskid8510b22000-06-06 23:04:06 +0000667 /* we're on the cursors line, but it's not the first
668 * one we marked... */
Robert Siemborski53875912000-06-16 04:25:30 +0000669 int this_page = get_page_from_virtual(virt_cur_x),
Robert Siemborskid8510b22000-06-06 23:04:06 +0000670 this_page_start = get_page_start_virtual(this_page),
671 this_page_end = get_page_end_virtual(this_page);
672
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000673 if (mark_beginbuf->lineno < current->lineno)
674 wattron(edit, A_REVERSE);
675
Robert Siemborski53875912000-06-16 04:25:30 +0000676 if (virt_cur_x > COLS - 2) {
677 mvwaddnstr(edit, yval, 0, &fileptr->data[this_page_start],
678 virt_cur_x - this_page_start);
679 } else {
680 mvwaddnstr(edit, yval, 0, fileptr->data, virt_cur_x);
681 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000682
683 if (mark_beginbuf->lineno > current->lineno)
684 wattron(edit, A_REVERSE);
685 else
686 wattroff(edit, A_REVERSE);
687
Robert Siemborski53875912000-06-16 04:25:30 +0000688 if (virt_cur_x > COLS - 2) {
689 mvwaddnstr(edit, yval, virt_cur_x - this_page_start,
690 &fileptr->data[virt_cur_x],
691 this_page_end - virt_cur_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000692 } else
Robert Siemborski53875912000-06-16 04:25:30 +0000693 mvwaddnstr(edit, yval, virt_cur_x,
694 &fileptr->data[virt_cur_x],
695 COLS - virt_cur_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000696
697 if (mark_beginbuf->lineno > current->lineno)
698 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000699 }
700 }
701
702 } else
703#endif
Robert Siemborski53875912000-06-16 04:25:30 +0000704 mvwaddnstr(edit, yval, 0, &fileptr->data[start], COLS - start);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000705}
706
707/*
708 * Just update one line in the edit buffer
709 *
710 * index gives is a place in the string to update starting from.
711 * Likely args are current_x or 0.
712 */
713void update_line(filestruct * fileptr, int index)
714{
715 filestruct *filetmp;
Robert Siemborski53875912000-06-16 04:25:30 +0000716 int line = 0, col = 0;
717 int virt_cur_x = current_x, virt_mark_beginx = mark_beginx;
718 char *realdata, *tmp;
719 int i,pos,len;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000720
Robert Siemborski53875912000-06-16 04:25:30 +0000721 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000722 for (filetmp = edittop; filetmp != fileptr && filetmp != editbot;
723 filetmp = filetmp->next)
724 line++;
725
726 mvwaddstr(edit, line, 0, hblank);
Robert Siemborski53875912000-06-16 04:25:30 +0000727 if(!fileptr) return;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000728
Robert Siemborski53875912000-06-16 04:25:30 +0000729 /* Next, convert all the tabs to spaces so everything else is easy */
730 index = xpt(fileptr, index);
731
732 realdata = fileptr->data;
733 len = strlen(realdata);
734 fileptr->data = nmalloc(xpt(fileptr,len) + 1);
735
736 pos = 0;
737 for(i=0;i<len;i++) {
738 if(realdata[i] == '\t') {
739 do {
740 fileptr->data[pos++] = ' ';
741 if(i < current_x) virt_cur_x++;
742 if(i < mark_beginx) virt_mark_beginx++;
743 } while(pos % 8);
744 /* must decrement once to account for tab-is-one-character */
745 if(i < current_x) virt_cur_x--;
746 if(i < mark_beginx) virt_mark_beginx--;
747 } else {
748 fileptr->data[pos++] = realdata[i];
749 }
750 }
751
752 fileptr->data[pos] = '\0';
753
754 /* Now, Paint the line */
755 if (current == fileptr && index > COLS - 2) {
756 int page = get_page_from_virtual(index);
Robert Siemborskid8510b22000-06-06 23:04:06 +0000757 col = get_page_start_virtual(page);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000758
Robert Siemborski53875912000-06-16 04:25:30 +0000759 edit_add(filetmp, line, col, virt_cur_x, virt_mark_beginx);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000760 mvwaddch(edit, line, 0, '$');
761
Robert Siemborskid8510b22000-06-06 23:04:06 +0000762 if (strlenpt(fileptr->data) > get_page_end_virtual(page))
763 mvwaddch(edit, line, COLS - 1, '$');
764 } else {
Robert Siemborski53875912000-06-16 04:25:30 +0000765 edit_add(filetmp, line, 0, virt_cur_x, virt_mark_beginx);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000766
Robert Siemborski53875912000-06-16 04:25:30 +0000767 if (strlenpt(&filetmp->data[col]) > COLS)
Robert Siemborskid8510b22000-06-06 23:04:06 +0000768 mvwaddch(edit, line, COLS - 1, '$');
769 }
Robert Siemborski53875912000-06-16 04:25:30 +0000770
771 /* Clean up our mess */
772 tmp = fileptr->data;
773 fileptr->data = realdata;
774 free(tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000775}
776
777void center_cursor(void)
778{
779 current_y = editwinrows / 2;
780 wmove(edit, current_y, current_x);
781}
782
783/* Refresh the screen without changing the position of lines */
784void edit_refresh(void)
785{
786 int lines = 0, i = 0;
787 filestruct *temp, *hold = current;
788
789 if (current == NULL)
790 return;
791
792 temp = edittop;
793
794 while (lines <= editwinrows - 1 && lines <= totlines && temp != NULL) {
795 hold = temp;
796 update_line(temp, current_x);
797 temp = temp->next;
798 lines++;
799 }
800
801 if (lines <= editwinrows - 1)
802 while (lines <= editwinrows - 1) {
803 mvwaddstr(edit, lines, i, hblank);
804 lines++;
805 }
806 if (temp == NULL)
807 editbot = hold;
808 else
809 editbot = temp;
810}
811
812/*
813 * Nice generic routine to update the edit buffer given a pointer to the
814 * file struct =)
815 */
816void edit_update(filestruct * fileptr)
817{
818
819 int lines = 0, i = 0;
820 filestruct *temp;
821
822 if (fileptr == NULL)
823 return;
824
825 temp = fileptr;
826 while (i <= editwinrows / 2 && temp->prev != NULL) {
827 i++;
828 temp = temp->prev;
829 }
830 edittop = temp;
831
832 while (lines <= editwinrows - 1 && lines <= totlines && temp != NULL
833 && temp != filebot) {
834 temp = temp->next;
835 lines++;
836 }
837 editbot = temp;
838
839 edit_refresh();
840}
841
842/* Now we want to update the screen using this struct as the top of the edit buffer */
843void edit_update_top(filestruct * fileptr)
844{
845 int i;
846 filestruct *temp = fileptr;
847
848 if (fileptr->next == NULL || fileptr == NULL)
849 return;
850
851 i = 0;
852 while (i <= editwinrows / 2 && temp->next != NULL) {
853 i++;
854 temp = temp->next;
855 }
856 edit_update(temp);
857}
858
859/* And also for the bottom... */
860void edit_update_bot(filestruct * fileptr)
861{
862 int i;
863 filestruct *temp = fileptr;
864
865 i = 0;
866 while (i <= editwinrows / 2 - 1 && temp->prev != NULL) {
867 i++;
868 temp = temp->prev;
869 }
870 edit_update(temp);
871}
872
873/* This function updates current based on where current_y is, reset_cursor
874 does the opposite */
875void update_cursor(void)
876{
877 int i = 0;
878
879#ifdef DEBUG
880 fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
881 current_x);
882#endif
883
884 current = edittop;
885 while (i <= current_y - 1 && current->next != NULL) {
886 current = current->next;
887 i++;
888 }
889
890#ifdef DEBUG
891 fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
892#endif
893
894}
895
896/*
897 * Ask a question on the statusbar. Answer will be stored in answer
898 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
899 * otherwise, the valid shortcut key caught, Def is any editable text we
900 * want to put up by default.
901 */
902int statusq(shortcut s[], int slen, char *def, char *msg, ...)
903{
904 va_list ap;
905 char foo[133];
906 int ret;
907
908 bottombars(s, slen);
909
910 va_start(ap, msg);
911 vsnprintf(foo, 132, msg, ap);
912 strncat(foo, ": ", 132);
913 va_end(ap);
914
915 wattron(bottomwin, A_REVERSE);
916 ret = nanogetstr(foo, def, s, slen, (strlen(foo) + 3));
917 wattroff(bottomwin, A_REVERSE);
918
919 switch (ret) {
920
921 case NANO_FIRSTLINE_KEY:
922 do_first_line();
923 break;
924 case NANO_LASTLINE_KEY:
925 do_last_line();
926 break;
927 case NANO_CANCEL_KEY:
928 return -1;
929 default:
930 blank_statusbar_refresh();
931 }
932
933#ifdef DEBUG
934 fprintf(stderr, _("I got \"%s\"\n"), answer);
935#endif
936
937 return ret;
938}
939
940/*
941 * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0 for
942 * N, 2 for All (if all is non-zero when passed in) and -1 for abort (^C)
943 */
944int do_yesno(int all, int leavecursor, char *msg, ...)
945{
946 va_list ap;
947 char foo[133];
948 int kbinput, ok = -1;
949
950 /* Write the bottom of the screen */
951 clear_bottomwin();
952 wattron(bottomwin, A_REVERSE);
953 blank_statusbar_refresh();
954 wattroff(bottomwin, A_REVERSE);
955
956 if (!ISSET(NO_HELP)) {
957 wmove(bottomwin, 1, 0);
958 onekey(_(" Y"), _("Yes"));
959 if (all)
960 onekey(_(" A"), _("All"));
961 wmove(bottomwin, 2, 0);
962 onekey(_(" N"), _("No"));
963 onekey(_("^C"), _("Cancel"));
964 }
965 va_start(ap, msg);
966 vsnprintf(foo, 132, msg, ap);
967 va_end(ap);
968 wattron(bottomwin, A_REVERSE);
969 mvwaddstr(bottomwin, 0, 0, foo);
970 wattroff(bottomwin, A_REVERSE);
971 wrefresh(bottomwin);
972
973 if (leavecursor == 1)
974 reset_cursor();
975
976 raw();
977
978 while (ok == -1) {
979 kbinput = wgetch(edit);
980
981 switch (kbinput) {
982 case 'Y':
983 case 'y':
984 ok = 1;
985 break;
986 case 'N':
987 case 'n':
988 ok = 0;
989 break;
990 case 'A':
991 case 'a':
992 if (all)
993 ok = 2;
994 break;
995 case NANO_CONTROL_C:
996 ok = -2;
997 break;
998 }
999 }
1000 noraw();
1001 cbreak();
1002
1003 /* Then blank the screen */
1004 blank_statusbar_refresh();
1005
1006 if (ok == -2)
1007 return -1;
1008 else
1009 return ok;
1010}
1011
1012void statusbar(char *msg, ...)
1013{
1014 va_list ap;
1015 char foo[133];
1016 int start_x = 0;
1017
1018 va_start(ap, msg);
1019 vsnprintf(foo, 132, msg, ap);
1020 va_end(ap);
1021
1022 start_x = center_x - strlen(foo) / 2 - 1;
1023
1024 /* Blank out line */
1025 blank_statusbar();
1026
1027 wmove(bottomwin, 0, start_x);
1028
1029 wattron(bottomwin, A_REVERSE);
1030
1031 waddstr(bottomwin, "[ ");
1032 waddstr(bottomwin, foo);
1033 waddstr(bottomwin, " ]");
1034 wattroff(bottomwin, A_REVERSE);
1035 wrefresh(bottomwin);
1036
1037 if (ISSET(CONSTUPDATE))
1038 statblank = 1;
1039 else
1040 statblank = 25;
1041}
1042
1043void display_main_list(void)
1044{
1045 bottombars(main_list, MAIN_VISIBLE);
1046}
1047
1048int total_refresh(void)
1049{
1050 display_main_list();
1051 clearok(edit, TRUE);
1052 clearok(topwin, TRUE);
1053 clearok(bottomwin, TRUE);
1054 wnoutrefresh(edit);
1055 wnoutrefresh(topwin);
1056 wnoutrefresh(bottomwin);
1057 doupdate();
1058 clearok(edit, FALSE);
1059 clearok(topwin, FALSE);
1060 clearok(bottomwin, FALSE);
1061
1062 return 1;
1063}
1064
1065void previous_line(void)
1066{
1067 if (current_y > 0)
1068 current_y--;
1069}
1070
1071int do_cursorpos(void)
1072{
1073 filestruct *fileptr;
1074 float linepct, bytepct;
1075 int i, tot = 0;
1076
1077 if (current == NULL || fileage == NULL)
1078 return 0;
1079
1080 for (fileptr = fileage; fileptr != current && fileptr != NULL; fileptr = fileptr->next)
1081 tot += strlen(fileptr->data) + 1;
1082
1083 if (fileptr == NULL)
1084 return -1;
1085
1086 i = tot + current_x;;
1087
1088 for (fileptr = current->next; fileptr != NULL; fileptr = fileptr->next)
1089 tot += strlen(fileptr->data) + 1;
1090
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001091 if (totlines > 0)
1092 linepct = 100 * current->lineno / totlines;
1093 else
1094 linepct = 0;
1095
1096 if (totsize > 0)
1097 bytepct = 100 * i / totsize;
1098 else
1099 bytepct = 0;
1100
1101#ifdef DEBUG
1102 fprintf(stderr, _("do_cursorpos: linepct = %f, bytepct = %f\n"),
1103 linepct, bytepct);
1104#endif
1105
1106 statusbar(_("line %d of %d (%.0f%%), character %d of %d (%.0f%%)"),
1107 current->lineno, totlines, linepct, i, totsize, bytepct);
1108 reset_cursor();
1109 return 1;
1110}
1111
1112/* Our broken, non-shortcut list compliant help function.
1113 But hey, it's better than nothing, and it's dynamic! */
1114int do_help(void)
1115{
1116#ifndef NANO_SMALL
1117 char *ptr = help_text, *end;
1118 int i, j, row = 0, page = 1, kbinput = 0, no_more = 0;
1119 int no_help_flag = 0;
1120
1121 blank_edit();
1122 curs_set(0);
1123 blank_statusbar();
1124
1125 if (ISSET(NO_HELP)) {
1126
1127 no_help_flag = 1;
1128 delwin (bottomwin);
1129 bottomwin = newwin(3, COLS, LINES - 3, 0);
1130 keypad(bottomwin, TRUE);
1131
1132 editwinrows -= no_help ();
1133 UNSET(NO_HELP);
1134 bottombars(help_list, HELP_LIST_LEN);
1135 }
1136 else
1137 bottombars(help_list, HELP_LIST_LEN);
1138
1139 do {
1140 ptr = help_text;
1141 switch (kbinput) {
1142 case NANO_NEXTPAGE_KEY:
1143 case NANO_NEXTPAGE_FKEY:
1144 case KEY_NPAGE:
1145 if (!no_more) {
1146 blank_edit();
1147 page++;
1148 }
1149 break;
1150 case NANO_PREVPAGE_KEY:
1151 case NANO_PREVPAGE_FKEY:
1152 case KEY_PPAGE:
1153 if (page > 1) {
1154 no_more = 0;
1155 blank_edit();
1156 page--;
1157 }
1158 break;
1159 }
1160
1161 /* Calculate where in the text we should be based on the page */
1162 for (i = 1; i < page; i++) {
1163 row = 0;
1164 j = 0;
1165 while (row < editwinrows && *ptr != '\0') {
1166 if (*ptr == '\n' || j == COLS - 5) {
1167 j = 0;
1168 row++;
1169 }
1170 ptr++;
1171 j++;
1172 }
1173 }
1174
1175 i = 0;
1176 j = 0;
1177 while (i < editwinrows && *ptr != '\0') {
1178 end = ptr;
1179 while (*end != '\n' && *end != '\0' && j != COLS - 5) {
1180 end++;
1181 j++;
1182 }
1183 if (j == COLS - 5) {
1184
1185 /* Don't print half a word if we've run of of space */
1186 while (*end != ' ' && *end != '\0') {
1187 end--;
1188 j--;
1189 }
1190 }
1191 mvwaddnstr(edit, i, 0, ptr, j);
1192 j = 0;
1193 i++;
1194 if (*end == '\n')
1195 end++;
1196 ptr = end;
1197 }
1198 if (*ptr == '\0') {
1199 no_more = 1;
1200 continue;
1201 }
1202 } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY);
1203
1204 if (no_help_flag) {
1205 werase(bottomwin);
1206 wrefresh(bottomwin);
1207 delwin (bottomwin);
1208 SET(NO_HELP);
1209 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
1210 keypad(bottomwin, TRUE);
1211 editwinrows += no_help();
1212 }
1213 else
1214 display_main_list();
1215
1216 curs_set(1);
1217 edit_refresh();
1218#else
1219 nano_small_msg();
1220#endif
1221
1222 return 1;
1223}
1224
1225/* Dump the current file structure to stderr */
1226void dump_buffer(filestruct * inptr)
1227{
1228#ifdef DEBUG
1229 filestruct *fileptr;
1230
1231 if (inptr == fileage)
1232 fprintf(stderr, _("Dumping file buffer to stderr...\n"));
1233 else if (inptr == cutbuffer)
1234 fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
1235 else
1236 fprintf(stderr, _("Dumping a buffer to stderr...\n"));
1237
1238 fileptr = inptr;
1239 while (fileptr != NULL) {
1240 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1241 fflush(stderr);
1242 fileptr = fileptr->next;
1243 }
1244#endif /* DEBUG */
1245}
1246
1247void dump_buffer_reverse(filestruct * inptr)
1248{
1249#ifdef DEBUG
1250 filestruct *fileptr;
1251
1252 fileptr = filebot;
1253 while (fileptr != NULL) {
1254 fprintf(stderr, "(%ld) %s\n", fileptr->lineno, fileptr->data);
1255 fflush(stderr);
1256 fileptr = fileptr->prev;
1257 }
1258#endif /* DEBUG */
1259}