<commit_before>#ifdef _WIN32
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#endif

#include "gl-app.h"

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

#define ICON_PC 0x1f4bb
#define ICON_HOME 0x1f3e0
#define ICON_FOLDER 0x1f4c1
#define ICON_DOCUMENT 0x1f4c4
#define ICON_DISK 0x1f4be
#define ICON_PIN 0x1f4cc

#ifndef PATH_MAX
#define PATH_MAX 2048
#endif

struct entry
{
	int is_dir;
	char name[FILENAME_MAX];
};

static struct
{
	int (*filter)(const char *fn);
	struct input input_dir;
	struct input input_file;
	struct list list_dir;
	char curdir[PATH_MAX];
	int count;
	struct entry files[512];
	int selected;
} fc;

static int cmp_entry(const void *av, const void *bv)
{
	const struct entry *a = av;
	const struct entry *b = bv;
	/* "." first */
	if (a->name[0] == '.' && a->name[1] == 0) return -1;
	if (b->name[0] == '.' && b->name[1] == 0) return 1;
	/* ".." second */
	if (a->name[0] == '.' && a->name[1] == '.' && a->name[2] == 0) return -1;
	if (b->name[0] == '.' && b->name[1] == '.' && b->name[2] == 0) return 1;
	/* directories before files */
	if (a->is_dir && !b->is_dir) return -1;
	if (b->is_dir && !a->is_dir) return 1;
	/* then alphabetically */
	return strcmp(a->name, b->name);
}

#ifdef _WIN32

#include <strsafe.h>
#include <shlobj.h>

const char *realpath(const char *path, char buf[PATH_MAX])
{
	wchar_t wpath[PATH_MAX];
	wchar_t wbuf[PATH_MAX];
	int i;
	MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, PATH_MAX);
	GetFullPathNameW(wpath, PATH_MAX, wbuf, NULL);
	WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, PATH_MAX, NULL, NULL);
	for (i=0; buf[i]; ++i)
		if (buf[i] == '\\')
			buf[i] = '/';
	return buf;
}

static void load_dir(const char *path)
{
	WIN32_FIND_DATA ffd;
	HANDLE dir;
	wchar_t wpath[PATH_MAX];
	char buf[PATH_MAX];
	int i;

	realpath(path, fc.curdir);
	if (!fz_is_directory(ctx, path))
		return;

	ui_input_init(&fc.input_dir, fc.curdir);

	fc.selected = -1;
	fc.count = 0;

	MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, PATH_MAX);
	for (i=0; wpath[i]; ++i)
		if (wpath[i] == '/')
			wpath[i] = '\\';
	StringCchCat(wpath, PATH_MAX, TEXT("/*"));
	dir = FindFirstFileW(wpath, &ffd);
	if (dir)
	{
		do
		{
			WideCharToMultiByte(CP_UTF8, 0, ffd.cFileName, -1, buf, PATH_MAX, NULL, NULL);
			if (ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
				continue;
			fc.files[fc.count].is_dir = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
			if (fc.files[fc.count].is_dir || !fc.filter || fc.filter(buf))
			{
				fz_strlcpy(fc.files[fc.count].name, buf, FILENAME_MAX);
				++fc.count;
			}
		}
		while (FindNextFile(dir, &ffd));
		FindClose(dir);
	}

	qsort(fc.files, fc.count, sizeof fc.files[0], cmp_entry);
}

static void list_drives(void)
{<commit_msg>mingw: Use wcscat_s() instead of StringCchCat()<commit_after>#ifdef _WIN32
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#endif

#include "gl-app.h"

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

#define ICON_PC 0x1f4bb
#define ICON_HOME 0x1f3e0
#define ICON_FOLDER 0x1f4c1
#define ICON_DOCUMENT 0x1f4c4
#define ICON_DISK 0x1f4be
#define ICON_PIN 0x1f4cc

#ifndef PATH_MAX
#define PATH_MAX 2048
#endif

struct entry
{
	int is_dir;
	char name[FILENAME_MAX];
};

static struct
{
	int (*filter)(const char *fn);
	struct input input_dir;
	struct input input_file;
	struct list list_dir;
	char curdir[PATH_MAX];
	int count;
	struct entry files[512];
	int selected;
} fc;

static int cmp_entry(const void *av, const void *bv)
{
	const struct entry *a = av;
	const struct entry *b = bv;
	/* "." first */
	if (a->name[0] == '.' && a->name[1] == 0) return -1;
	if (b->name[0] == '.' && b->name[1] == 0) return 1;
	/* ".." second */
	if (a->name[0] == '.' && a->name[1] == '.' && a->name[2] == 0) return -1;
	if (b->name[0] == '.' && b->name[1] == '.' && b->name[2] == 0) return 1;
	/* directories before files */
	if (a->is_dir && !b->is_dir) return -1;
	if (b->is_dir && !a->is_dir) return 1;
	/* then alphabetically */
	return strcmp(a->name, b->name);
}

#ifdef _WIN32

#ifdef __MINGW32__
typedef int errno_t;
__attribute__ ((dllimport)) errno_t wcscat_s (wchar_t *, size_t, const wchar_t *);
#endif
#include <shlobj.h>

const char *realpath(const char *path, char buf[PATH_MAX])
{
	wchar_t wpath[PATH_MAX];
	wchar_t wbuf[PATH_MAX];
	int i;
	MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, PATH_MAX);
	GetFullPathNameW(wpath, PATH_MAX, wbuf, NULL);
	WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, PATH_MAX, NULL, NULL);
	for (i=0; buf[i]; ++i)
		if (buf[i] == '\\')
			buf[i] = '/';
	return buf;
}

static void load_dir(const char *path)
{
	WIN32_FIND_DATA ffd;
	HANDLE dir;
	wchar_t wpath[PATH_MAX];
	char buf[PATH_MAX];
	int i;

	realpath(path, fc.curdir);
	if (!fz_is_directory(ctx, path))
		return;

	ui_input_init(&fc.input_dir, fc.curdir);

	fc.selected = -1;
	fc.count = 0;

	MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, PATH_MAX);
	for (i=0; wpath[i]; ++i)
		if (wpath[i] == '/')
			wpath[i] = '\\';
	wcscat_s(wpath, PATH_MAX, TEXT("/*"));
	dir = FindFirstFileW(wpath, &ffd);
	if (dir)
	{
		do
		{
			WideCharToMultiByte(CP_UTF8, 0, ffd.cFileName, -1, buf, PATH_MAX, NULL, NULL);
			if (ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
				continue;
			fc.files[fc.count].is_dir = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
			if (fc.files[fc.count].is_dir || !fc.filter || fc.filter(buf))
			{
				fz_strlcpy(fc.files[fc.count].name, buf, FILENAME_MAX);
				++fc.count;
			}
		}
		while (FindNextFile(dir, &ffd));
		FindClose(dir);
	}

	qsort(fc.files, fc.count, sizeof fc.files[0], cmp_entry);
}

static void list_drives(void)
{
{'fraction_non_alphanumeric': 0.17738242029240797, 'fraction_numerical': 0.02536550995243967, 'mean_word_length': 4.194876486733761, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3060696', 'n_tokens_mistral': 2683, 'n_tokens_neox': 2503, 'n_words': 561}