1 /**
2 * Copyright (C) 2015 Aaron Ball <nullspoon@iohq.net>
3 *
4 * Noteless is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Noteless is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Noteless. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "common.h"
18
19 /**
20 * Determins the text editor that should be used. Checks the environmental
21 * variable EDITOR for this.
22 *
23 * @return char* Path to the editor binary to be used (stored in heap)
24 */
25 void get_user_editor(char* editor) {
26 if(getenv("EDITOR") != NULL) {
27 /* If the EDITOR variable is set, use that */
28 //int editor_len = strlen(getenv("EDITOR"));
29 // *editor = calloc(editor_len, sizeof(char));
30 strcpy(editor, getenv("EDITOR"));
31 } else {
32 strcpy(editor, "vi");
33 }
34 }
35
36
37 /**
38 * Converts an integer to its equivelant char array
39 *
40 * @param i The integer to be converted
41 * @param out Char array pointer to the output variable. Must be large enough
42 * to hold the output or unpredictable behavior may result.
43 *
44 * @return int The char count, not including the terminating null byte char
45 */
46 int itoc(int num, char* out) {
47 int count = 0;
48
49 int tmp_num = num;
50 // Get a char count. This is necessary becasue the numbers come out
51 // backwards. We need to start from the end and work back.
52 while(tmp_num > 0) {
53 //int n = tmp_num%10;
54 tmp_num /= 10;
55 count++;
56 }
57
58 int out_count = count;
59
60 // Set the last char as a null byte
61 out[count] = '\0';
62 count--;
63
64 while(count >= 0) {
65 int n = num%10;
66
67 // Add 48 to the int to get its char equivelant ascii index
68 out[count] = n + 48;
69
70 num /= 10;
71 count--;
72 }
73
74 return out_count;
75 }
76
77
78 /**
79 * Returns the current localtime in format YYYYMMDD.HHmmss. Useful for "random"
80 * non-conflicting filenames.
81 *
82 * @param date Output variable for the date string. The output variable must
83 * have space for the date to be stored, otherwise unexpected
84 * behavior may occur.
85 */
86 void get_current_date_time(char* date) {
87 time_t rawtime;
88 time(&rawtime);
89 struct tm* now = localtime(&rawtime);
90
91 // Date
92 // Year
93 int year = now->tm_year + 1900;
94 char c_year[5];
95 itoc(year, c_year);
96 strcpy(date, c_year);
97
98 // Month
99 int mon = now->tm_mon + 1;
100 char c_mon[3];
101 itoc(mon, c_mon);
102 if(mon < 10) { strcat(date, "0"); }
103 strcat(date, c_mon);
104
105 // Day
106 int day = now->tm_mday;
107 char c_day[3];
108 if(day < 10) { strcat(date, "0"); }
109 strcat(date, c_day);
110
111 // A delimiter to make it easier for humans to read.
112 strcat(date, ".");
113
114 // Time
115 // Hour
116 int hour = now->tm_hour;
117 char c_hour[3];
118 itoc(hour, c_hour);
119 if(hour < 10) { strcat(date, "0"); }
120 strcat(date, c_hour);
121
122 // Minute
123 int min = now->tm_min;
124 char c_min[3];
125 itoc(min, c_min);
126 if(min < 10) { strcat(date, "0"); }
127 strcat(date, c_min);
128
129 // Second
130 int sec = now->tm_sec;
131 char c_sec[3];
132 itoc(sec, c_sec);
133 if(sec < 10) { strcat(date, "0"); }
134 strcat(date, c_sec);
135 }
136
137
138 /**
139 * TODO: Write this function description
140 *
141 * @return int Extension char length
142 */
143 int get_extension(char* path, char* extension) {
144 int path_len = strlen(path);
145 // Start from the right and move left
146 for(int i = path_len; i > 0; i--) {
147 // Copy if an extension delimiter (a period) is found
148 if(path[i] == '.') {
149 int ext_len = path_len - i - 1;
150 strncpy(extension, &path[i+1], ext_len);
151 return ext_len;
152 }
153 }
154 return -1;
155 }
156
157
158 /**
159 * Yup, wrote my own.
160 * TODO: Make this work with escaped path delimiters
161 * TODO: Write this function description
162 *
163 * @return int Basename path length
164 */
165 int basename(char* path, char* out) {
166 int path_len = strlen(path);
167 // Start from the right and move left
168 for(int i = path_len; i > 0; i--) {
169 // Copy if an extension delimiter (a period) is found
170 if(path[i] == '/') {
171 strcpy(out, &path[i + 1]);
172 return i;
173 }
174 }
175 return -1;
176 }
177
178
179 /**
180 * Just a wrapper function to call the specified line search function for case
181 * insensitive or case sensitive matching.
182 *
183 * @param line Line to check for the search term
184 * @param term Search term to find in line
185 *
186 * @return int Search term found (1) or not (0)
187 */
188 int str_contains(char* line, char* term, int case_insensitive) {
189 if(case_insensitive == 1) {
190 return str_contains_case_insensitive(line, term);
191 } else {
192 return str_contains_case_sensitive(line, term);
193 }
194 }
195
196
197 /**
198 * Performs a case insensitive search in the given line for the specified term.
199 *
200 * Note that for the sake of efficiency, this function is fairly confusing
201 * (sorry). Learning how chars and ints relate in c will help tremendously
202 * to understand this function.
203 *
204 * @param str String to check for the search term
205 * @param term Search term to find in line
206 *
207 * @return int Search term found (1) or not (0)
208 */
209 int str_contains_case_insensitive(char* str, char* term) {
210 // String char index
211 int si = 0;
212 // Term char index
213 int ti = 0;
214 int term_len = strlen(term);
215
216 // Compare one char at a time
217 while(str[si] != '\0') {
218 // Current str char
219 char lc;
220 // Current term char
221 char tc;
222
223 // Welcome to the confusing part (see function description)
224
225 // Convert current term char to lowercase
226 if(term[ti] >= 97 && term[ti] <= 122) {
227 // Already lower case
228 tc = term[ti];
229 } else if(term[ti] >= 65 && term[ti] <= 90) {
230 // Uppercase. Add 32 to get lowercase equivelant.
231 tc = term[ti] + 32;
232 } else {
233 // Term char isn't a letter. Must be a symbol or something ELSE...
234 // Take it as it is.
235 tc = term[ti];
236 }
237
238 // Convert current str char to lowercase
239 if(str[si] >= 97 && str[si] <= 122) {
240 // Already lower case
241 lc = str[si];
242 } else if(str[si] >= 65 && str[si] <= 90) {
243 // Uppercase. Add 32 to get lowercase equivelant.
244 lc = str[si] + 32;
245 } else {
246 // Term char isn't a letter. Must be a symbol or something ELSE...
247 // Take it as it is.
248 lc = str[si];
249 }
250
251 // Compare the temp lowercase version of the current str and term chars
252 if(lc == tc) {
253 ti++;
254 } else {
255 ti = 0;
256 }
257
258 // Return if we've matched the entire search term
259 if(ti == term_len) { return 1; }
260
261 si++;
262 }
263 return 0;
264 }
265
266
267 /**
268 * Performs a case sensitive search in the given string for the specified term.
269 *
270 * @param str String to check for the search term
271 * @param term Search term to find in str
272 *
273 * @return int Search term found (1) or not (0)
274 */
275 int str_contains_case_sensitive(char* str, char* term) {
276 int s = 0;
277 int t = 0;
278 int term_len = strlen(term);
279
280 // Compare one char at a time
281 while(str[s] != '\0') {
282 if(t == term_len) {
283 return 1;
284 } else if(term[t] == str[s]) {
285 // Found a single char match. Increment to the next term char
286 t++;
287 } else {
288 // Reset the match counter if a partial or no match was made
289 t = 0;
290 }
291 s++;
292 }
293 return 0;
294 }
|