Performance improvement
[iomenu.git] / draw.c
blob081df48b2402d9e627ac159163ce8f9ed9777673
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <sys/ioctl.h>
6 #include "main.h"
9 /*
10 * Print a line to stderr.
12 void
13 draw_line(Line *line, int current, int cols, Opt *opt)
15 size_t i;
16 int n = 0;
17 char *content = expand_tabs(line->content);
18 char *comment = expand_tabs(line->comment);
20 /* clear the line */
21 fputs("\033[K", stderr);
23 if (!line->header) {
24 fputs(current ? "\033[1;31m>" : " ", stderr);
25 n++;
28 if (opt->line_numbers) {
29 fprintf(stderr, current
30 ? "\033[1;37m%7d\033[0m "
31 : "\033[1;30m%7d\033[0m ",
32 line->number);
33 n += 8;
34 } else {
35 fputc(' ', stderr);
36 n++;
39 /* highlight current line */
40 if (current)
41 fputs("\033[1;33m", stderr);
43 /* print content without overflowing terminal width */
44 for (i = 0; i < strlen(content) && n < cols; n++, i++)
45 fputc(content[i], stderr);
47 /* shift without overflowing terminal width */
48 if (!line->header && line->comment[0] != '\0') {
49 /* MAX with '1' as \033[0C still move 1 to the right */
50 fprintf(stderr, "\033[%dC", MAX(40 - n, 1));
51 n += MAX(40 - n, 1);
54 /* comments in grey */
55 fputs("\033[1;30m", stderr);
57 /* print comment without overflowing terminal width */
58 for (i = 0; i < strlen(comment) && n < cols; n++, i++)
59 fputc(comment[i], stderr);
61 fputs("\033[0m\n", stderr);
63 free(content);
64 free(comment);
69 * Print all the lines from an array of pointer to lines.
71 * The total number oflines printed shall not excess 'count'.
73 void
74 draw_lines(Buffer *buffer, int count, int cols, Opt *opt)
76 Line *line = buffer->current;
77 int i = 0;
78 int j = 0;
80 /* seek back from current line to the first line to print */
81 while (line && i < count - OFFSET) {
82 i = line->matches ? i + 1 : i;
83 line = line->prev;
85 line = line ? line : buffer->first;
87 /* print up to count lines that match the input */
88 while (line && j < count) {
89 if (line->matches) {
90 draw_line(line, line == buffer->current, cols, opt);
91 j++;
94 line = line->next;
97 /* continue up to the end of the screen clearing it */
98 for (; j < count; j++)
99 fputs("\r\033[K\n", stderr);
104 * Update the screen interface and print all candidates.
106 * This also has to clear the previous lines.
108 void
109 draw_screen(Buffer *buffer, int tty_fd, Opt *opt)
111 struct winsize w;
112 int count;
114 ioctl(tty_fd, TIOCGWINSZ, &w);
115 count = MIN(opt->lines, w.ws_row - 2);
117 fputs("\n", stderr);
118 draw_lines(buffer, count, w.ws_col, opt);
120 /* go up to the prompt position and update it */
121 fprintf(stderr, "\033[%dA", count + 1);
122 draw_prompt(buffer, w.ws_col, opt);
126 void
127 draw_clear(int lines)
129 int i;
131 for (i = 0; i < lines + 1; i++)
132 fputs("\r\033[K\n", stderr);
133 fprintf(stderr, "\033[%dA", lines + 1);
138 * Print the prompt, before the input, with the number of candidates that
139 * match.
141 void
142 draw_prompt(Buffer *buffer, int cols, Opt *opt)
144 size_t i;
145 int matching = buffer->matching;
146 int total = buffer->total;
147 char *input = expand_tabs(buffer->input);
148 char *suggest = expand_tabs(buffer->current->content);
150 /* for the '/' separator between the numbers */
151 cols--;
153 /* number of digits */
154 for (i = matching; i; i /= 10, cols--);
155 for (i = total; i; i /= 10, cols--);
157 /* 0 also has one digit*/
158 cols -= !matching ? 1 : 0;
160 /* actual prompt */
161 fprintf(stderr, "\r%s\033[K> ", opt->prompt);
162 cols -= 2 + strlen(opt->prompt);
164 /* input without overflowing terminal width */
165 for (i = 0; i < strlen(input) && cols > 0; cols--, i++)
166 fputc(input[i], stderr);
168 /* save the cursor position at the end of the input */
169 fputs("\033[s", stderr);
171 /* grey */
172 fputs("\033[1;30m", stderr);
174 /* go to the end of the line */
175 fprintf(stderr, "\033[%dC", cols);
177 /* total match and line count at the end of the line */
178 fprintf(stderr, "%d/%d", matching, total);
180 /* restore cursor position at the end of the input */
181 fputs("\033[0m\033[u", stderr);
183 free(input);
184 free(suggest);