From ca0cea5b5f65461397ab4cd30b97a46eadee9256 Mon Sep 17 00:00:00 2001 From: "nothings.org" Date: Sun, 15 Jul 2007 10:47:50 +0000 Subject: [PATCH] ctrl-c, nice filename sorting --- imv.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++----- notes.txt | 3 ++ 2 files changed, 136 insertions(+), 12 deletions(-) diff --git a/imv.c b/imv.c index d7b7512..6b1f3d2 100644 --- a/imv.c +++ b/imv.c @@ -547,6 +547,15 @@ int show_help=0; int downsample_cubic = 0; int upsample_cubic = TRUE; +int cur_loc = -1; // offset within the current list of files + +// information about files we have currently loaded +struct +{ + char *filename; + int lru; +} *fileinfo; + // declare with extra bytes so we can print the version number into it char helptext_center[140] = "imv(stb)\n" @@ -557,19 +566,16 @@ char helptext_center[140] = char helptext_left[] = "\n\n\n\n\n\n" - " ESC: exit\n" " ALT-ENTER: toggle size\n" " CTRL-PLUS: zoom in\n" "CTRL-MINUS: zoom out\n" "RIGHT, SPACE: next image\n" "LEFT, BACKSPACE: previous image\n" - " (CTRL-) O: open image\n" - " P: change preferences\n" + " O: open image\n" " B: toggle border\n" "SHIFT-B: toggle border but keep stripe\n" " CTRL-B: toggle white stripe in border\n" " L: toggle filename label\n" - "F1, H, ?: help" ; char helptext_right[] = @@ -580,6 +586,10 @@ char helptext_right[] = "double-click to toggle size\n" "mousewheel to zoom\n" "\n" + "F1, H, ?: help\n" + "ESC: exit\n" + "P: change preferences\n" + "CTRL-C: copy filename to clipboard\n" ; // draw the help text semi-prettily @@ -685,7 +695,13 @@ void display(HWND win, HDC hdc) SIZE size; RECT z; HFONT old = NULL; + char buffer[1024]; char *name = cur_filename ? cur_filename : "(none)"; + if (fileinfo) { + sprintf(buffer, "%s ( %d / %d )", name, cur_loc+1, stb_arr_len(fileinfo)); + name = buffer; + } + if (label_font) old = SelectObject(hdc, label_font); // get rect around label so we can draw it ourselves, because @@ -1079,14 +1095,6 @@ void toggle_display(void) // before they're flushed, it will still be valid char path_to_file[4096]; char *filename; // @TODO: gah, we have cur_filename AND filename. and filename is being set dumbly! -int cur_loc = -1; // offset within the current list of files - -// information about files we have currently loaded -struct -{ - char *filename; - int lru; -} *fileinfo; // stb_sdict is a string dictionary (strings as keys, void * as values) // dictionary mapping filenames (key) to cached images (ImageFile *) @@ -1105,6 +1113,102 @@ void free_fileinfo(void) fileinfo = NULL; } +//derived from michael herf's code: http://www.stereopsis.com/strcmp4humans.html + +// sorts like this: +// foo.jpg +// foo1.jpg +// foo2.jpg +// foo10.jpg +// foo_1.jpg +// food.jpg + +// use upper, not lower, to get better sorting versus '_' +__forceinline char tupper(char b) +{ + //if (b >= 'A' && b <= 'Z') return b - 'A' + 'a'; + if (b >= 'a' && b <= 'z') return b - 'a' + 'A'; + return b; +} + +__forceinline char isnum(char b) +{ + if (b >= '0' && b <= '9') return 1; + return 0; +} + +__forceinline int parsenum(char **a_p) +{ + char *a = *a_p; + int result = *a - '0'; + ++a; + + while (isnum(*a)) { + result *= 10; + result += *a - '0'; + ++a; + } + + *a_p = a-1; + return result; +} + +int StringCompare(char *a, char *b) +{ + char *orig_a = a, *orig_b = b; + + if (a == b) return 0; + + if (a == NULL) return -1; + if (b == NULL) return 1; + + while (*a && *b) { + + int a0, b0; // will contain either a number or a letter + + if (isnum(*a) && isnum(*b)) { + a0 = parsenum(&a); + b0 = parsenum(&b); + } else { + // if they are mixed number and character, use ASCII comparison + // order between them (number before character), not herf's + // approach (numbers after everything else). this produces the order: + // foo.jpg + // foo1.jpg + // food.jpg + // foo_.jpg + // which I think looks better than having foo_ before food (but + // I could be wrong, given how a blank space sorts) + + a0 = tupper(*a); + b0 = tupper(*b); + } + + if (a0 < b0) return -1; + if (a0 > b0) return 1; + + ++a; + ++b; + } + + if (*a) return 1; + if (*b) return -1; + + { + // if strings differ only by leading 0s, use case-insensitive ASCII sort + // (note, we should work this out more efficiently by noticing which one changes length first) + int z = stricmp(orig_a, orig_b); + if (z) return z; + // if identical case-insensitive, return ASCII sort + return strcmp(orig_a, orig_b); + } +} + +int StringCompareSort(const void *p, const void *q) +{ + return StringCompare(*(char **) p, *(char **) q); +} + char *open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp\0"; // build a filelist for the current directory @@ -1122,6 +1226,7 @@ void init_filelist(void) image_files = stb_readdir_files_mask(path_to_file, open_filter + 12); if (image_files == NULL) { error("Error: couldn't read directory."); exit(0); } + qsort(image_files, stb_arr_len(image_files), sizeof(*image_files), StringCompareSort); // given the array of filenames, build an equivalent fileinfo array stb_arr_setlen(fileinfo, stb_arr_len(image_files)); @@ -2068,6 +2173,21 @@ int WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (cur) frame(cur); break; + case 'C' | MY_CTRL: { + HGLOBAL hMem; + char buffer[1024], *t; + stb_fullpath(buffer, 1024, source_c->filename); + hMem = GlobalAlloc(GHND, strlen(buffer)+1); + t = GlobalLock(hMem); + strcpy(t, buffer); + GlobalUnlock(hMem); + OpenClipboard(win); + EmptyClipboard(); + SetClipboardData(CF_TEXT, hMem); + CloseClipboard(); + break; + } + #ifdef PERFTEST case 'D' | MY_CTRL: performance_test(); @@ -2342,6 +2462,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine if (pending_resize.size.w) { // there's a resize pending, so don't block if (!pending_resize.image) { + // @TODO: use a message instead! // resize isn't done, so sleep for a bit and try again Sleep(10); continue; diff --git a/notes.txt b/notes.txt index c0135f3..d7034d9 100644 --- a/notes.txt +++ b/notes.txt @@ -1,6 +1,9 @@ Version 0.94: Beta 5 * (bugfix: fix cacheing code to allow refreshing current image after flip etc.) * (feature: use 'f' to flip image vertically, in case FreeImage sucks) + * feature: sort filenames to sort numbers in human-friendly order + * feature: show index within sorted list + * feature: ctrl-C puts current image filename (with full path) in the clipboard * change: change the border control keys to 'b' instead of 'f' for next feature * feature: use FreeImage.dll if it's available * bugfix: fix bug in right or bottom cursor region due to internal cleanup