mtsedit/src/search.c

192 lines
6.7 KiB
C

/*
* mtsedit/search.c
*
* Copyright (C) 2019 bzt (bztsrc@gitlab)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* @brief Search Block window
*
*/
#include "main.h"
int numresults, *results = NULL, line, overblk = -1, searchscr = 0;
int searchlen = 0, searchpos = 0;
char search[256] = { 0 }, cur[2] = {0, 0};
/**
* Redraw the Search Block window
*/
void search_redraw()
{
int i;
SDL_Rect rect;
rect.x = 36; rect.y = 0; rect.w = screen->w - 36; rect.h = screen->h - font->height;
SDL_FillRect(screen, &rect, theme[THEME_BG]);
strmaxw = screen->w - 5;
sdlprint((screen->w - 47 - strlen(lang[ADDBLOCKS]) * (font->width+1)) / 2 + 47, 4, THEME_INPUT, THEME_BG, lang[ADDBLOCKS]);
rect.y = 12 + font->height;
sdlprint(42, rect.y, THEME_FG, THEME_BG, lang[SEARCH]);
rect.x = 160; rect.w = screen->w - 165; rect.h = font->height + 2;
SDL_FillRect(screen, &rect, theme[THEME_INPBG]);
strmaxw = screen->w - 5;
sdlprint(161,rect.y + 1, THEME_INPUT, THEME_INPBG, search);
cur[0] = search[searchpos] ? search[searchpos] : ' ';
sdlprint(161 + searchpos * (font->width+1), rect.y + 1, THEME_INPBG, THEME_INPUT, cur);
rect.x = 42; rect.y = 20 + 2*font->height; rect.w = rect.h = 32;
if(line != (screen->w - 47) / 32) {
line = (screen->w - 47) / 32;
searchscr = 0;
}
for(i = searchscr * line; i < numresults && rect.y + 32 < (int)(screen->h - font->height); i++, rect.x += 32) {
if(rect.x + 32 > screen->w - 5) { rect.x = 42; rect.y += 32; }
if(rect.y + 32 > (int)(screen->h - font->height)) rect.h = screen->h - font->height - rect.y;
blk->pixels = results[i] > 0 && results[i] < numblocks && blocks[results[i]].img ? blocks[results[i]].img :
(uint8_t*)icons->pixels + 32 * icons->pitch;
SDL_FillRect(screen, &rect, theme[i == overblk ? THEME_INACT : THEME_BG]);
SDL_BlitSurface(blk, NULL, screen, &rect);
}
}
/**
* Search Block window scrolling event handler
*/
void search_scroll(SDL_Event *event)
{
int i = numresults / line;
searchscr -= event->wheel.y;
if(searchscr < 0) searchscr = 0;
if(searchscr + 1 >= i) searchscr = i - 1;
}
/**
* Add a block to the palette
*/
void search_addblock(int blk)
{
int i, j, b;
if(blk != -1 && blk < numresults) {
b = results[blk];
if(!b) return;
for(j = 1; j < 15 && palette[j] != b; j++);
for(i = j; i > 1; i--) palette[i] = palette[i - 1];
palette[1] = b;
activeblock = 1;
}
}
/**
* Search Block window mouse down event handler
*/
void search_mousedown(_unused SDL_Event *event)
{
if(overblk != -1 && overblk < numresults) {
search_addblock(overblk);
status = overblk < 0 || overblk >= numresults || results[overblk] < 0 || results[overblk] >= numblocks ? NULL :
blocks[results[overblk]].name;
sdlredraw();
}
}
/**
* Search Block mouse over event handler
*/
void search_mouseover(SDL_Event *event)
{
int i, j = -1;
if(event->motion.x >= 42 && event->motion.x < screen->w - 5) {
if(event->motion.y >= (int)(20 + 2*font->height) && event->motion.y < (int)(screen->h - font->height)) {
i = ((event->motion.x - 42) / 32);
j = (((event->motion.y - (20 + 2*font->height)) / 32 + searchscr) * line) + (i < line ? i : line);
if(j >= numresults || !results[j]) j = -1;
}
}
if(j != overblk) {
overblk = j;
status = j < 0 || j >= numresults || results[j] < 0 || results[j] >= numblocks ? NULL : blocks[results[j]].name;
sdlredraw();
}
}
/**
* Search Block window keypress event handler
*/
void search_key(SDL_Event *event)
{
int i, j, l;
switch(event->type) {
case SDL_TEXTINPUT:
j = strlen(event->text.text);
if(!ctrl && searchlen + j < (int)(sizeof(search))) {
for(i = searchlen - 1; i >= searchpos; i--) search[i + j] = search[i];
memcpy(search + searchpos, &event->text.text, j);
searchpos += j;
searchlen += j;
search[searchlen] = 0;
}
break;
case SDL_KEYUP:
switch (event->key.keysym.sym) {
case SDLK_BACKSPACE:
if(searchpos) {
searchpos--;
for(i = searchpos; i < searchlen + 1; i++) search[i] = search[i+1];
searchlen--;
}
break;
case SDLK_DELETE:
if(searchpos < searchlen) {
for(i = searchpos; i < searchlen + 1; i++) search[i] = search[i+1];
searchlen--;
}
break;
case SDLK_UP: searchpos = 0; break;
case SDLK_DOWN: searchpos = searchlen; break;
case SDLK_LEFT: if(searchpos) searchpos--; break;
case SDLK_RIGHT: if(searchpos < searchlen) searchpos++; break;
case SDLK_TAB:
case SDLK_RETURN: sdldo(-1); break;
}
if(ctrl && event->key.keysym.sym >= SDLK_1 && event->key.keysym.sym <= SDLK_9)
search_addblock(event->key.keysym.sym - SDLK_1);
break;
}
if(!searchlen) {
numresults = numblocks - 1;
for(i = 0; (int)i < numresults; i++) results[i] = i + 1;
} else {
for(numresults = 0, i = 1; i < numblocks; i++) {
l = strlen(blocks[i].name) - searchlen;
for(j = 0; j < l + 1; j++)
if(!strncasecmp(blocks[i].name + j, search, searchlen)) {
results[numresults++] = i;
break;
}
}
}
}