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 /* prevent initial current line to be a header and set it up */
38 buffer
->current
= buffer
->first
;
39 while (buffer
->current
->next
&& buffer
->current
->header
)
40 buffer
->current
= buffer
->current
->next
;
43 buffer
->empty
= malloc(sizeof(Line
));
44 buffer
->empty
->content
= buffer
->empty
->comment
= "";
45 buffer
->empty
->number
= buffer
->empty
->matches
= 0;
46 buffer
->empty
->prev
= buffer
->empty
->next
= buffer
->first
;
52 * Add a line to the end of the current buffer.
54 * This requires to create a new line with a link to the previous line
55 * and to NULL as the next line.
57 * The previous line's 'next' should be relinked to this new line.
59 * The header's last line have to point to this last line
62 add_line(Buffer
*buffer
, int number
, char *string
, char *separator
, Line
*prev
)
64 /* allocate new line */
65 Line
*line
= malloc(sizeof(Line
));
66 line
= parse_line(string
, separator
);
70 line
->number
= number
;
72 /* interlink with previous line if exists */
85 * Parse the line content to determine if it is a header and identify the
89 parse_line(char *s
, char *separator
)
91 Line
*line
= malloc(sizeof(Line
));
92 char *sep
= separator
? strstr(s
, separator
) : NULL
;
93 int pos
= sep
? (int) (sep
- s
) : (int) strlen(s
) - 1;
95 /* header is when separator is the first character of the line */
96 line
->header
= (sep
== s
);
98 /* strip trailing newline */
99 s
[strlen(s
) - 1] = '\0';
101 /* fill line->content */
102 line
->content
= malloc((pos
+ 1) * sizeof(char));
103 strncpy(line
->content
, s
, pos
);
105 /* fill line->comment */
107 line
->comment
= malloc((strlen(s
) - pos
) * sizeof(char));
108 strcpy(line
->comment
, s
+ pos
+ strlen(separator
));
113 /* strip trailing whitespaces from line->content */
114 for (pos
--; pos
> 0 && isspace(line
->content
[pos
]); pos
--)
115 line
->content
[pos
] = '\0';
117 /* strip leading whitespaces from line->comment */
118 for (pos
= 0; isspace(line
->comment
[pos
]); pos
++)
120 line
->comment
+= pos
;
126 * Set buffer->candidates to an array of lines that match and update
127 * buffer->matching to number of matching candidates.
130 filter_lines(Buffer
*buffer
, Opt
*opt
)
132 Line
* line
= buffer
->first
;
133 buffer
->matching
= 0;
136 line
->matches
= line_match_input(line
, buffer
->input
, opt
);
137 buffer
->matching
+= line
->matches
;
145 * Check if line matches and return TRUE or FALSE
148 line_match_input(Line
*line
, char *input
, Opt
*opt
)
150 return (opt
->complete
&& !strncmp(input
, line
->content
, strlen(input
)))
151 || strstr(line
->content
, input
)
158 * Seek the previous matching line, or NULL if none matches.
161 matching_prev(Line
*line
)
163 while ((line
= line
->prev
) && (!line
->matches
|| line
->header
))
170 * Seek the next matching line, or NULL if none matches.
173 matching_next(Line
*line
)
175 while ((line
= line
->next
) && (!line
->matches
|| line
->header
))