179 lines
3.9 KiB
C
179 lines
3.9 KiB
C
#include <windows.h>
|
|
|
|
#include <ctype.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "config/resource.h"
|
|
|
|
#include "util/array.h"
|
|
#include "util/log.h"
|
|
#include "util/str.h"
|
|
#include "util/winres.h"
|
|
|
|
struct usage {
|
|
uint16_t id;
|
|
char name[128];
|
|
};
|
|
|
|
struct usage_page {
|
|
uint16_t id;
|
|
struct array usages;
|
|
char wildcard[128];
|
|
};
|
|
|
|
static struct array usages;
|
|
|
|
static bool usages_begin_page(const char *line, struct usage_page *page);
|
|
static bool usages_read_usage(const char *line, struct usage_page *page);
|
|
|
|
void usages_init(HINSTANCE inst)
|
|
{
|
|
struct resource res;
|
|
struct usage_page *cur_page;
|
|
struct usage_page tmp_page;
|
|
char line[512];
|
|
size_t line_no;
|
|
size_t nchars;
|
|
|
|
resource_open(&res, inst, "USAGES", IDR_USAGES);
|
|
array_init(&usages);
|
|
|
|
cur_page = NULL;
|
|
line_no = 0;
|
|
|
|
while (resource_fgets(&res, line, sizeof(line))) {
|
|
line_no++;
|
|
|
|
nchars = strlen(line);
|
|
|
|
if (nchars == 0 || line[0] == '#' ||
|
|
strspn(line, " \t\r\n") == nchars) {
|
|
continue;
|
|
}
|
|
|
|
str_trim(line);
|
|
|
|
if (!isspace(line[0])) {
|
|
if (!usages_begin_page(line, &tmp_page)) {
|
|
log_fatal(
|
|
"IDR_USAGES:%u: Invalid usage page",
|
|
(unsigned int) line_no);
|
|
|
|
break;
|
|
}
|
|
|
|
cur_page = array_append(struct usage_page, &usages);
|
|
memcpy(cur_page, &tmp_page, sizeof(tmp_page));
|
|
} else {
|
|
if (cur_page == NULL) {
|
|
log_fatal(
|
|
"IDR_USAGES:%u: Usage before first page",
|
|
(unsigned int) line_no);
|
|
|
|
break;
|
|
}
|
|
|
|
if (!usages_read_usage(line, cur_page)) {
|
|
log_fatal(
|
|
"IDR_USAGES:%u: Invalid usage", (unsigned int) line_no);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool usages_begin_page(const char *line, struct usage_page *page)
|
|
{
|
|
int id;
|
|
|
|
if (sscanf(line, "%i", &id) != 1) {
|
|
return false;
|
|
}
|
|
|
|
page->id = (uint16_t) id;
|
|
array_init(&page->usages);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool usages_read_usage(const char *line, struct usage_page *page)
|
|
{
|
|
struct usage *usage;
|
|
int id;
|
|
int offset;
|
|
char c;
|
|
|
|
if (sscanf(line, " %c %n", &c, &offset) == 1 && c == '*') {
|
|
str_cpy(page->wildcard, sizeof(page->wildcard), &line[offset]);
|
|
page->wildcard[sizeof(page->wildcard) - 1] = '\0';
|
|
|
|
return true;
|
|
} else if (sscanf(line, " %i %n", &id, &offset) == 1) {
|
|
usage = array_append(struct usage, &page->usages);
|
|
|
|
usage->id = (uint16_t) id;
|
|
str_cpy(usage->name, sizeof(usage->name), &line[offset]);
|
|
usage->name[sizeof(usage->name) - 1] = '\0';
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void usages_get(char *chars, size_t nchars, uint32_t usage_id)
|
|
{
|
|
const struct usage_page *page;
|
|
const struct usage *usage;
|
|
uint16_t hi;
|
|
uint16_t lo;
|
|
size_t i;
|
|
size_t j;
|
|
|
|
hi = ((usage_id >> 16) & 0xFFFF);
|
|
lo = ((usage_id >> 0) & 0xFFFF);
|
|
|
|
for (i = 0; i < usages.nitems; i++) {
|
|
page = array_item(struct usage_page, &usages, i);
|
|
|
|
if (page->id != hi) {
|
|
continue;
|
|
}
|
|
|
|
for (j = 0; j < page->usages.nitems; j++) {
|
|
usage = array_item(struct usage, &page->usages, j);
|
|
|
|
if (usage->id == lo) {
|
|
str_cpy(chars, nchars, usage->name);
|
|
chars[nchars - 1] = '\0';
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (page->wildcard[0]) {
|
|
str_format(chars, nchars, page->wildcard, lo);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
str_format(chars, nchars, "%#08x", usage_id);
|
|
}
|
|
|
|
void usages_fini(void)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < usages.nitems; i++) {
|
|
array_fini(&array_item(struct usage_page, &usages, i)->usages);
|
|
}
|
|
|
|
array_fini(&usages);
|
|
}
|