#include "pistachio.h" #define TEXTBOX_LEN 400#define ERROR_MSG_LEN 400 #define SCREEN 0 bool render_glyphs(Glyph *renders, Screen_Info *dimensions, Settings *config) { bool oblique = config->results_font.oblique; bool bold = config->results_font.bold; u32 color = config->back_color; for (int i = 0; i < 8; i++) { if (i == 4) color = config->selected_color; config->results_font.oblique = oblique ^ (i & 1); config->results_font.bold = bold ^ ((i >> 1) & 1); if (!render_font( dimensions, &config->results_font, color, &renders[i * N_CHARS] )) return false; } if (!render_font( dimensions, &config->search_font, config->back_color, &renders[BAR_OFFSET] )) return false; return render_font( dimensions, &config->error_font, config->back_color, &renders[ERR_OFFSET] );} char *parse_command(char *textbox, Settings *config, char *error, int error_len) { int len = strlen(textbox); int second = find_next_word(textbox, 0, len); bool is_command = second || (textbox[0] != '/' && textbox[0] != '~'); bool daemonize = true; if (is_command) { int name_len = second ? second - 1 : len; char name[name_len + 1]; memcpy(name, textbox, name_len); name[name_len] = 0; char *msg; if (!find_program(name, &msg)) { bool is_exe = false; char *path = get_desugared_path(textbox, name_len); FILE *f = fopen(path, "rb"); if (f) { char magic[4]; fread(magic, 1, 4, f); is_exe = ((magic[0] == 0x7f && magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') || (magic[0] == '#' && magic[1] == '!' && magic[2] == '/')); } if (!is_exe) { snprintf(error, error_len, "%s\"%s\"", msg, path); return NULL; } } if (name_len == 4 && (!memcmp(name, "sudo", 4) || !memcmp(name, "doas", 4))) { // kind of risky! // FIXME: pass in textbox size so that this can be done safely textbox[len] = '"'; textbox[len+1] = 0; memmove(&textbox[4], textbox, len+1); textbox[0] = '-'; textbox[1] = 'e'; textbox[2] = ' '; textbox[3] = '"'; prepend_word(config->terminal_program.command, textbox); } } else { struct stat s; char *path = get_desugared_path(textbox, len); if (stat(path, &s) != 0) { snprintf(error, error_len, "file/folder not found: %s", textbox); return NULL; } // If this is a folder if ((s.st_mode & S_IFMT) == S_IFDIR) { prepend_word(config->folder_program.command, textbox); daemonize = config->folder_program.daemonize; } // Else if it's a file else if ((s.st_mode & S_IFMT) == S_IFREG) { Program *prog = config->programs; while (prog) { bool found = false; char *ext = prog->extensions; int ext_len = 0; for (int i = 0; i < prog->n_extensions; i++, ext += ext_len + 1) { ext_len = strlen(ext); if (!strcmp(&textbox[len - ext_len], ext)) { found = true; break; } } if (found) break; prog = prog->next; } if (!prog) { bool is_exe = false; if ((s.st_mode & S_IXUSR) && (s.st_mode & S_IRUSR)) { char magic[4]; FILE *f = fopen(path, "rb"); fread(magic, 1, 4, f); fclose(f); is_exe = ((magic[0] == 0x7f && magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') || (magic[0] == '#' && magic[1] == '!' && magic[2] == '/')); } if (!is_exe) { prog = &config->default_program; } } if (prog) { prepend_word(prog->command, textbox); daemonize = prog->daemonize; } } } if (daemonize) { len = strlen(textbox); if (textbox[len-1] != '&' && len < TEXTBOX_LEN-3) strcpy(&textbox[len], " &"); else textbox[len-1] = 0; } return textbox;} int main(int argc, char **argv) { defer_arena_destruction(); init_directory_arena(); Settings *config = load_config(); struct stat s = {0}; if (stat(config->font_path, &s) != 0 || (s.st_mode & S_IFREG) == 0) { fprintf(stderr, "Could not find font (absolute path \"%s\" does not specify a file)\n", config->font_path); return 2; } Screen_Info dimensions; if (!open_display(SCREEN, &dimensions)) { fprintf(stderr, "Failed to access the display\n"); return 3; } if (config->window_w > 1.0) config->window_w /= (float)dimensions.w; if (config->window_h > 1.0) config->window_h /= (float)dimensions.h; if (!open_font(config->font_path)) return 4; Glyph *renders = malloc(N_RENDERS * sizeof(Glyph)); render_glyphs(renders, &dimensions, config); close_font(); char textbox[TEXTBOX_LEN] = {0}; char error_buf[ERROR_MSG_LEN] = {0}; char *error_msg = NULL; char *command = NULL; while (!command) { int res = run_gui(config, &dimensions, renders, textbox, TEXTBOX_LEN, error_msg); if (res == STATUS_EXIT) break; command = parse_command(textbox, config, error_buf, ERROR_MSG_LEN); error_msg = &error_buf[0]; } close_display(); free(renders); if (command) system(command); return 0;}