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