#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define WINTITLE "sorting..." #define FONTSIZE 80 #define FONTPATH "font/FreeSans.ttf" SDL_Color textcolor = { 255, 255, 255, 255 }; typedef struct displayer { SDL_Window *window; SDL_Renderer *renderer; SDL_Texture *background; TTF_Font *font; }displayer; void sdlcleanup(displayer *displayerer, char **images, DIR *dir, int count, int exitstatus){ closedir(dir); int i = 0; while(i < count){ free(images[i]); i++; } free(images); TTF_CloseFont(displayerer->font); SDL_DestroyTexture(displayerer->background); SDL_DestroyRenderer(displayerer->renderer); SDL_DestroyWindow(displayerer->window); TTF_Quit(); IMG_Quit(); SDL_Quit(); exit(exitstatus); } bool sdlinit(displayer *displayerer){ if (SDL_Init(SDL_INIT_EVERYTHING)){ fprintf(stderr, "failed to initialize SDL: %s\n", SDL_GetError()); return true; } int imginit = IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG); if ((imginit & (IMG_INIT_PNG | IMG_INIT_JPG)) != (IMG_INIT_PNG | IMG_INIT_JPG)){ fprintf(stderr, "failed to initialize SDL: %s\n", IMG_GetError()); return true; } if (TTF_Init()){ fprintf(stderr, "failed to initialize ttf: %s\n", TTF_GetError()); return true; } displayerer->font = TTF_OpenFont(FONTPATH, FONTSIZE); if(!displayerer->font) { fprintf(stderr, "failed to load font: %s\n", TTF_GetError()); return true; } displayerer->window = SDL_CreateWindow( WINTITLE,SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALWAYS_ON_TOP); if(!displayerer->window){ fprintf(stderr, "failed to create window: %s\n", SDL_GetError()); return true; } displayerer->renderer = SDL_CreateRenderer(displayerer->window, -1, 0); if(!displayerer->renderer){ fprintf(stderr, "failed to create renderer: %s\n", SDL_GetError()); return true; } return false; } bool loadimages(displayer *displayerer,char *who){ displayerer->background = IMG_LoadTexture(displayerer->renderer, who); if(!displayerer->background) { fprintf(stderr, "failed to load image: %s\n", IMG_GetError()); return true; } return false; } int main(int argc, char **argv){ struct displayer displayerer = { .window = NULL, .renderer = NULL, .background = NULL, .font = NULL, }; const char *path = (argc > 1) ? argv[1] : "."; char **images = malloc(16 * sizeof(char *)); DIR *dir = opendir(path); if(!dir){ fprintf(stderr, "%s: can't open dir %s", argv[0], argv[1]); return 1; } struct dirent *files; int count = 0; char buf[1024]; int capacity = 16; //tiny because i actally wanna realloc while ((files = readdir(dir)) != NULL) { char *ext = strrchr(files->d_name, '.'); if (ext == NULL) continue; if (strcasecmp(ext, ".png") != 0 && strcasecmp(ext, ".jpg") != 0 && strcasecmp(ext, ".jpeg") != 0) continue; if(count == capacity){ capacity *= 2; images = realloc(images, capacity * sizeof(char *)); if(images == NULL){ sdlcleanup(&displayerer, images, dir, count, EXIT_FAILURE); } } snprintf(buf, sizeof(buf), "%s/%s", path, files->d_name); //i hate how c does things images[count] = strdup(buf); count++; } if(count == 0){ printf("erm idk what you did here but you probably ran the program in a dir with no .pngs or .jpgs... hopefully you're not gonna segfault here"); sdlcleanup(&displayerer, images, dir, count, EXIT_FAILURE); } char saveddir[1024], otherdir[1024], deletedir[1024]; snprintf(saveddir, sizeof(saveddir), "%s/saved", path); snprintf(otherdir, sizeof(otherdir), "%s/other", path); snprintf(deletedir, sizeof(deletedir), "%s/delete", path); mkdir(saveddir, 0755); mkdir(otherdir, 0755); mkdir(deletedir, 0755); if(sdlinit(&displayerer)){ sdlcleanup(&displayerer, images, dir, count, EXIT_FAILURE); } int whichone = 1; //0 means nothing it doesn't load lol int typing = 0; int len; char textbuf[256]; loadimages(&displayerer, images[whichone]); while(true){ SDL_Event event; while(SDL_PollEvent(&event)){ switch(event.type){ default : break; case SDL_QUIT: sdlcleanup(&displayerer, images, dir, count, EXIT_SUCCESS); break; case SDL_TEXTINPUT: strcat(textbuf, event.text.text); break; case SDL_TEXTEDITING: strcpy(textbuf, event.edit.text); break; case SDL_KEYDOWN : switch(event.key.keysym.scancode){ default: break; case SDL_SCANCODE_BACKSPACE: len = strlen(textbuf); if (len > 0) { textbuf[len - 1] = '\0'; } break; case SDL_SCANCODE_ESCAPE: sdlcleanup(&displayerer, images, dir, count, EXIT_SUCCESS); break; case SDL_SCANCODE_W: if(!typing){ typing = 1; textbuf[0] = '\0'; SDL_StartTextInput(); } break; case SDL_SCANCODE_RETURN: if(typing){ typing = 0; SDL_StopTextInput(); char *ext = strrchr(images[whichone], '.'); char savedbuf[1024]; snprintf(savedbuf, sizeof(savedbuf), "%s/%s%s", saveddir, textbuf, ext ? ext : ""); rename(images[whichone], savedbuf); if(whichone + 1 < count){ whichone++; SDL_DestroyTexture(displayerer.background); loadimages(&displayerer, images[whichone]); } } break; case SDL_SCANCODE_Q: if(!typing){if(whichone + 1 < count){ whichone++; SDL_DestroyTexture(displayerer.background);} loadimages(&displayerer, images[whichone]); printf("loaded: %s\n", images[whichone]); }else { whichone = 0;} break; case SDL_SCANCODE_A: if(!typing){if(whichone > 1){ whichone--; SDL_DestroyTexture(displayerer.background); loadimages(&displayerer, images[whichone]); printf("loaded: %s\n", images[whichone]); } } break; case SDL_SCANCODE_S: if(!typing){ char otherbuf[1024]; snprintf(otherbuf, sizeof(otherbuf), "%s/%s", otherdir, strrchr(images[whichone], '/') + 1); rename(images[whichone], otherbuf); if(whichone + 1 < count){ whichone++; SDL_DestroyTexture(displayerer.background); loadimages(&displayerer, images[whichone]); } } break; case SDL_SCANCODE_D: if(!typing){ char otherbuf[1024]; snprintf(otherbuf, sizeof(otherbuf), "%s/%s", deletedir, strrchr(images[whichone], '/') + 1); rename(images[whichone], otherbuf); if(whichone + 1 < count){ whichone++; SDL_DestroyTexture(displayerer.background); loadimages(&displayerer, images[whichone]); } } break; } } } SDL_RenderClear(displayerer.renderer); //is it wise to calculate this each frame? no. will i optimize it? no //actually yeah because i can resize the window int imgw, imgh,winw, winh; SDL_QueryTexture(displayerer.background, NULL, NULL, &imgw, &imgh); SDL_GetRendererOutputSize(displayerer.renderer, &winw, &winh); float scalex = (float)winw / imgw; float scaley = (float)winh / imgh; float scale = (scalex < scaley) ? scalex : scaley; SDL_Rect dst = { .w = (int)(imgw * scale), .h = (int)(imgh * scale), }; dst.x = (winw - dst.w) / 2; dst.y = (winh - dst.h) / 2; //if i was smarter i'd wrap this in another function SDL_RenderCopy(displayerer.renderer, displayerer.background, NULL, &dst); SDL_Rect angle = { .w = (int)winw, .h = (int) 100, .y = (int)(winh)/2-50, .x = (int) 0, }; if(typing){ SDL_SetRenderDrawColor(displayerer.renderer, 0, 0, 0, 255); SDL_RenderFillRect(displayerer.renderer, &angle); SDL_Surface *surf = TTF_RenderText_Solid(displayerer.font, textbuf[0] ? textbuf : " ", textcolor); SDL_Texture *tex = SDL_CreateTextureFromSurface(displayerer.renderer, surf); int tw, th; SDL_QueryTexture(tex, NULL, NULL, &tw, &th); SDL_Rect textrect = { .x = winw/2 - tw/2, .y = winh/2 - th/2, .w = tw, .h = th, }; SDL_RenderCopy(displayerer.renderer, tex, NULL, &textrect); SDL_DestroyTexture(tex); } SDL_RenderPresent(displayerer.renderer); SDL_Delay(8); //about 120 fps, worthless since this is not really a game } sdlcleanup(&displayerer, images, dir, count, EXIT_SUCCESS); return 0; }