#include "parser.h"
#include "utils.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
bool foundName = false;
bool foundKey = false;
bool foundExec = false;
bool isDesktopEntry = false;
void parse_name(char *line, Program *program) {
if (foundName) return;
if (strncmp(line, "Name[", 5) == 0) {
char *locale = line + 5;
char *end = strchr(locale, ']');
if (!end) return;
*end = '\0';
if (strncmp(locale, getenv("LANG"), 2) != 0) return;
if (!isdup(end + 2)) {
strncpy(program->name, end + 2, MAX_NAME_LEN - 1);
program->name[strcspn(program->name, "\n")] = '\0';
}
add_to_dup(end + 2);
foundName = true;
} else {
if (!isdup(line + 5)) {
strncpy(program->name, line + 5, MAX_NAME_LEN - 1);
program->name[strcspn(program->name, "\n")] = '\0';
}
add_to_dup(line + 5);
foundName = true;
}
}
void parse_keywords(char *line, Program *program) {
if (foundKey) return;
size_t len = strnlen(line + 9, MAX_NAME_LEN - 1);
strncpy(program->keys, line + 9, len);
program->keys[len] = '\0';
program->keys[strcspn(program->keys, "\n")] = '\0';
foundKey = true;
}
void parse_exec(char *line, Program *program) {
if (foundExec) return;
size_t len = strnlen(line + 5, MAX_NAME_LEN - 1);
strncpy(program->exec, line + 5, len);
program->exec[strcspn(program->exec, "\n")] = '\0';
char *p = program->exec;
while ((p = strpbrk(p, "%")) != NULL) {
*p = '\0';
size_t rspace = MAX_NAME_LEN - strlen(program->exec) - 1;
if (rspace > 0) {
strncat(program->exec, p + 2, rspace);
}
}
foundExec = true;
}
void parse_term(char *line, Program *program) {
size_t len = strnlen(line + 9, MAX_NAME_LEN - 1);
strncpy(program->term, line + 9, len);
program->term[strcspn(program->term, "\n")] = '\0';
char *p = program->term;
while ((p = strpbrk(p, "%")) != NULL) {
*p = '\0';
size_t rspace = MAX_NAME_LEN - strlen(program->term) - 1;
if (rspace > 0) {
strncat(program->term, p + 2, rspace);
}
}
}
void parse_desktop_file(const char *filepath) {
FILE *file = fopen(filepath, "r");
if (!file) return;
char line[MAX_NAME_LEN * 2];
Program program = {0};
while (fgets(line, sizeof(line), file)) {
if (strncmp(line, "Name=", 5) == 0 || strncmp(line, "Name[", 5) == 0) {
parse_name(line, &program);
} else if (strncmp(line, "Keywords=", 9) == 0) {
parse_keywords(line, &program);
} else if (strncmp(line, "Exec=", 5) == 0) {
parse_exec(line, &program);
} else if (strncmp(line, "Terminal=", 9) == 0) {
parse_term(line, &program);
}
}
fclose(file);
if (program.name[0] && program.exec[0]) {
programs[programcount++] = program;
}
}
void scan_desktop_files(const char *directory) {
DIR *dir = opendir(directory);
if (!dir) return;
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strcasestr(entry->d_name, ".desktop")) {
size_t filepath_len = strlen(directory) + strlen(entry->d_name) + 2;
char *filepath = malloc(filepath_len);
if (!filepath) {
closedir(dir);
return;
}
snprintf(filepath, filepath_len, "%s/%s", directory, entry->d_name);
if (isdis(filepath)) parse_desktop_file(filepath);
isDesktopEntry = false;
foundName = false;
foundKey = false;
foundExec = false;
free(filepath);
}
}
closedir(dir);
}