12 * Fill the buffer apropriately with the lines and headers.
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
));
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
)) {
34 last
= add_line(buffer
, buffer
->total
, string
, separator
, last
);
37 /* set the buffer stats */
38 buffer
->current
= buffer
->first
;
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
;
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
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
);
68 line
->number
= number
;
70 /* interlink with previous line if exists */
83 * Parse the line content to determine if it is a header and identify the
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 */
105 line
->comment
= malloc((strlen(s
) - pos
) * sizeof(char));
106 strcpy(line
->comment
, s
+ pos
+ strlen(separator
));
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
;
124 * Set buffer->candidates to an array of lines that match and update
125 * buffer->matching to number of matching candidates.
128 filter_lines(Buffer
*buffer
, Opt
*opt
)
130 Line
* line
= buffer
->first
;
131 buffer
->matching
= 0;
134 line
->matches
= line_match_input(line
, buffer
->input
, opt
);
135 buffer
->matching
+= line
->matches
;
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
))) {
153 if (strstr(line
->content
, input
)) {
163 * Seek the previous matching line, or NULL if none matches.
166 matching_prev(Line
*line
)
168 while ((line
= line
->prev
) && !line
->matches
)
175 * Seek the next matching line, or NULL if none matches.
178 matching_next(Line
*line
)
180 while ((line
= line
->next
) && !line
->matches
)