Working on headers: a separator at the beginning
[iomenu.git] / buffer.c
blob32d5c01685721c6c361ffd909092cc931e6b5362
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
6 #include "main.h"
7 #include "util.h"
8 #include "buffer.h"
12 * Fill the buffer apropriately with the lines and headers.
14 Buffer *
15 fill_buffer(char *separator)
17 /* fill buffer with string */
18 char string[LINE_SIZE];
19 Line *last = malloc(sizeof(Line));
20 Buffer *buffer = malloc(sizeof(Buffer));
21 FILE *fp = stdin;
23 if (!fp) {
24 die("Can not open file for reading.");
27 /* empty line in case no line come from stdin */
28 last->content = last->comment = "";
29 buffer->first = buffer->current = buffer->last = last;
31 /* read the file into a doubly linked list of lines */
32 while (fgets(string, LINE_SIZE, fp)) {
33 buffer->total++;
34 last = add_line(buffer, buffer->total, string, separator, last);
37 /* set the buffer stats */
38 buffer->current = buffer->first;
40 /* empty line */
41 buffer->empty = malloc(sizeof(Line));
42 buffer->empty->content = buffer->empty->comment = "";
43 buffer->empty->number = buffer->empty->matches = 0;
44 buffer->empty->prev = buffer->empty->next = buffer->first;
46 return buffer;
50 * Add a line to the end of the current buffer.
52 * This requires to create a new line with a link to the previous line
53 * and to NULL as the next line.
55 * The previous line's 'next' should be relinked to this new line.
57 * The header's last line have to point to this last line
59 Line *
60 add_line(Buffer *buffer, int number, char *string, char *separator, Line *prev)
62 /* allocate new line */
63 Line *line = malloc(sizeof(Line));
64 line = parse_line(string, separator);
65 line->next = NULL;
66 line->prev = NULL;
67 buffer->last = line;
68 line->number = number;
70 /* interlink with previous line if exists */
71 if (number == 1) {
72 buffer->first = line;
73 } else {
74 prev->next = line;
75 line->prev = prev;
78 return line;
83 * Parse the line content to determine if it is a header and identify the
84 * separator if any.
86 Line *
87 parse_line(char *s, char *separator)
89 Line *line = malloc(sizeof(Line));
90 char *sep = separator ? strstr(s, separator) : NULL;
91 int pos = sep ? (int) (sep - s) : (int) strlen(s) - 1;
93 /* header is when separator is the first character of the line */
94 line->header = sep == s;
96 /* strip trailing newline */
97 s[strlen(s) - 1] = '\0';
99 /* fill line->content */
100 line->content = malloc((pos + 1) * sizeof(char));
101 strncpy(line->content, s, pos);
103 /* fill line->comment */
104 if (sep) {
105 line->comment = malloc((strlen(s) - pos) * sizeof(char));
106 strcpy(line->comment, s + pos + strlen(separator));
107 } else {
108 line->comment = "";
111 /* strip trailing whitespaces from line->content */
112 for (pos--; pos > 0 && isspace(line->content[pos]); pos--)
113 line->content[pos] = '\0';
115 /* strip leading whitespaces from line->comment */
116 for (pos = 0; isspace(line->comment[pos]); pos++)
118 line->comment += pos;
120 return line;
124 * Set buffer->candidates to an array of lines that match and update
125 * buffer->matching to number of matching candidates.
127 void
128 filter_lines(Buffer *buffer, Opt *opt)
130 Line * line = buffer->first;
131 buffer->matching = 0;
133 while (line) {
134 line->matches = line_match_input(line, buffer->input, opt);
135 buffer->matching += line->matches;
137 line = line->next;
143 * Check if line matches and return TRUE or FALSE
146 line_match_input(Line *line, char *input, Opt *opt)
148 if (opt->complete_mode) {
149 if (!strncmp(input, line->content, strlen(input))) {
150 return TRUE;
152 } else {
153 if (strstr(line->content, input)) {
154 return TRUE;
158 return FALSE;
163 * Seek the previous matching line, or NULL if none matches.
165 Line *
166 matching_prev(Line *line)
168 while ((line = line->prev) && !line->matches)
170 return line;
175 * Seek the next matching line, or NULL if none matches.
177 Line *
178 matching_next(Line *line)
180 while ((line = line->next) && !line->matches)
182 return line;