10 * Fill the buffer apropriately with the lines and headers.
13 fill_buffer(char *separator
)
15 /* fill buffer with string */
16 char string
[LINE_SIZE
];
17 Line
*last
= malloc(sizeof(Line
));
18 Buffer
*buffer
= malloc(sizeof(Buffer
));
22 die("Can not open file for reading.");
24 /* empty line in case no line come from stdin */
25 last
->content
= last
->comment
= "";
26 buffer
->first
= buffer
->current
= buffer
->last
= last
;
28 /* read the file into a doubly linked list of lines */
29 while (fgets(string
, LINE_SIZE
, fp
)) {
31 last
= add_line(buffer
, buffer
->total
, string
, separator
, last
);
34 /* prevent initial current line to be a header and set it up */
35 buffer
->current
= buffer
->first
;
36 while (buffer
->current
->next
&& buffer
->current
->header
)
37 buffer
->current
= buffer
->current
->next
;
57 * Free every struct in the buffer, recursing the doubly linked list, then free
61 free_buffer(Buffer
*buffer
)
63 while (buffer
->first
) {
64 free_line(buffer
->first
);
65 buffer
->first
= buffer
->first
->next
;
73 * Add a line to the end of the current buffer.
75 * This requires to create a new line with a link to the previous line
76 * and to NULL as the next line.
78 * The previous line's 'next' should be relinked to this new line.
80 * The header's last line have to point to this last line
83 add_line(Buffer
*buffer
, int number
, char *string
, char *separator
, Line
*prev
)
85 /* allocate new line */
86 Line
*line
= malloc(sizeof(Line
));
87 line
= parse_line(string
, separator
);
91 line
->number
= number
;
93 /* interlink with previous line if exists */
106 * Parse the line content to determine if it is a header and identify the
110 parse_line(char *s
, char *separator
)
112 Line
*line
= malloc(sizeof(Line
));
113 char *sep
= separator
? strstr(s
, separator
) : NULL
;
114 int pos
= sep
? (int) (sep
- s
) : (int) strlen(s
) - 1;
116 /* header is when separator is the first character of the line */
117 line
->header
= (sep
== s
);
119 /* strip trailing newline */
120 s
[strlen(s
) - 1] = '\0';
122 /* fill line->content */
123 line
->content
= malloc((pos
+ 1) * sizeof(char));
124 strncpy(line
->content
, s
, pos
);
126 /* fill line->comment */
128 line
->comment
= malloc((strlen(s
) - pos
) * sizeof(char));
129 strcpy(line
->comment
, s
+ pos
+ strlen(separator
));
134 /* strip trailing whitespaces from line->content */
135 for (pos
--; pos
> 0 && isspace(line
->content
[pos
]); pos
--)
136 line
->content
[pos
] = '\0';
138 /* strip leading whitespaces from line->comment */
139 for (pos
= 0; isspace(line
->comment
[pos
]); pos
++);
140 line
->comment
+= pos
;
146 * Set buffer->candidates to an array of lines that match and update
147 * buffer->matching to number of matching candidates.
150 filter_lines(Buffer
*buffer
, Opt
*opt
)
152 Line
* line
= buffer
->first
;
153 buffer
->matching
= 0;
156 line
->matches
= line_match_input(line
, buffer
->input
, opt
);
157 buffer
->matching
+= line
->matches
;
165 * Check if line matches and return TRUE or FALSE
168 line_match_input(Line
*line
, char *input
, Opt
*opt
)
170 return (opt
->complete
&& !strncmp(input
, line
->content
, strlen(input
)))
171 || strstr(line
->content
, input
)
178 * Seek the previous matching line, or NULL if none matches.
181 matching_prev(Line
*line
)
183 while ((line
= line
->prev
) && (!line
->matches
|| line
->header
));
189 * Seek the next matching line, or NULL if none matches.
192 matching_next(Line
*line
)
194 while ((line
= line
->next
) && (!line
->matches
|| line
->header
));