|
Packit Service |
a9274b |
#include <stdlib.h>
|
|
Packit Service |
a9274b |
#include <string.h>
|
|
Packit Service |
a9274b |
#include "mixer_clickable.h"
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
extern int screen_cols;
|
|
Packit Service |
a9274b |
extern int screen_lines;
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
static struct clickable_rect *clickable_rects = NULL;
|
|
Packit Service |
a9274b |
static unsigned int clickable_rects_count = 0;
|
|
Packit Service |
a9274b |
static unsigned int last_rect = 0;
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
/* Using 0 instead of -1 for marking free rectangles allows us to use
|
|
Packit Service |
a9274b |
* memset for `freeing` all rectangles at once.
|
|
Packit Service |
a9274b |
* Zero is actually a valid coordinate in ncurses, but since we don't have
|
|
Packit Service |
a9274b |
* any clickables in the top line this is fine. */
|
|
Packit Service |
a9274b |
#define FREE_MARKER 0
|
|
Packit Service |
a9274b |
#define RECT_IS_FREE(RECT) ((RECT).y1 == FREE_MARKER)
|
|
Packit Service |
a9274b |
#define RECT_FREE(RECT) ((RECT).y1 = FREE_MARKER)
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
void clickable_set(int y1, int x1, int y2, int x2, command_enum command, int arg1) {
|
|
Packit Service |
a9274b |
struct clickable_rect* tmp;
|
|
Packit Service |
a9274b |
unsigned int i;
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
for (i = last_rect; i < clickable_rects_count; ++i) {
|
|
Packit Service |
a9274b |
if (RECT_IS_FREE(clickable_rects[i])) {
|
|
Packit Service |
a9274b |
last_rect = i;
|
|
Packit Service |
a9274b |
goto SET_CLICKABLE_DATA;
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
for (i = 0; i < last_rect; ++i) {
|
|
Packit Service |
a9274b |
if (RECT_IS_FREE(clickable_rects[i])) {
|
|
Packit Service |
a9274b |
last_rect = i;
|
|
Packit Service |
a9274b |
goto SET_CLICKABLE_DATA;
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
last_rect = clickable_rects_count;
|
|
Packit Service |
a9274b |
tmp = realloc(clickable_rects, (clickable_rects_count + 8) * sizeof(*clickable_rects));
|
|
Packit Service |
a9274b |
if (!tmp) {
|
|
Packit Service |
a9274b |
free(clickable_rects);
|
|
Packit Service |
a9274b |
clickable_rects = NULL;
|
|
Packit Service |
a9274b |
clickable_rects_count = 0;
|
|
Packit Service |
a9274b |
last_rect = 0;
|
|
Packit Service |
a9274b |
return;
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
clickable_rects = tmp;
|
|
Packit Service |
a9274b |
#if FREE_MARKER == 0
|
|
Packit Service |
a9274b |
memset(clickable_rects + clickable_rects_count, 0, 8 * sizeof(*clickable_rects));
|
|
Packit Service |
a9274b |
#else
|
|
Packit Service |
a9274b |
for (i = clickable_rects_count; i < clickable_rects_count + 8; ++i)
|
|
Packit Service |
a9274b |
RECT_FREE(clickable_rects[i]);
|
|
Packit Service |
a9274b |
#endif
|
|
Packit Service |
a9274b |
clickable_rects_count += 8;
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
SET_CLICKABLE_DATA:
|
|
Packit Service |
a9274b |
clickable_rects[last_rect] = (struct clickable_rect) {
|
|
Packit Service |
a9274b |
.y1 = y1,
|
|
Packit Service |
a9274b |
.x1 = x1,
|
|
Packit Service |
a9274b |
.x2 = x2,
|
|
Packit Service |
a9274b |
.y2 = y2,
|
|
Packit Service |
a9274b |
.command = command,
|
|
Packit Service |
a9274b |
.arg1 = arg1
|
|
Packit Service |
a9274b |
};
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
void clickable_set_relative(WINDOW *win, int y1, int x1, int y2, int x2, command_enum command, int arg1) {
|
|
Packit Service |
a9274b |
int y, x;
|
|
Packit Service |
a9274b |
getyx(win, y, x);
|
|
Packit Service |
a9274b |
y1 = y + y1;
|
|
Packit Service |
a9274b |
x1 = x + x1;
|
|
Packit Service |
a9274b |
y2 = y + y2;
|
|
Packit Service |
a9274b |
x2 = x + x2;
|
|
Packit Service |
a9274b |
clickable_set(y1, x1, y2, x2, command, arg1);
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
void clickable_clear(int y1, int x1, int y2, int x2) {
|
|
Packit Service |
a9274b |
#define IS_IN_RECT(Y, X) (Y >= y1 && Y <= y2 && X >= x1 && X <= x2)
|
|
Packit Service |
a9274b |
unsigned int i;
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
if (x1 == 0 && x2 == -1 && y2 == -1) {
|
|
Packit Service |
a9274b |
if (y1 == 0) {
|
|
Packit Service |
a9274b |
// Optimize case: clear all
|
|
Packit Service |
a9274b |
#if FREE_MARKER == 0
|
|
Packit Service |
a9274b |
if (clickable_rects)
|
|
Packit Service |
a9274b |
memset(clickable_rects, 0,
|
|
Packit Service |
a9274b |
clickable_rects_count * sizeof(*clickable_rects));
|
|
Packit Service |
a9274b |
#else
|
|
Packit Service |
a9274b |
for (i = 0; i < clickable_rects_count; ++i)
|
|
Packit Service |
a9274b |
RECT_FREE(clickable_rects[i]);
|
|
Packit Service |
a9274b |
#endif
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
else {
|
|
Packit Service |
a9274b |
// Optimize case: clear all lines beyond y1
|
|
Packit Service |
a9274b |
for (i = 0; i < clickable_rects_count; ++i) {
|
|
Packit Service |
a9274b |
if (clickable_rects[i].y2 >= y1)
|
|
Packit Service |
a9274b |
RECT_FREE(clickable_rects[i]);
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
return;
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
if (y2 < 0)
|
|
Packit Service |
a9274b |
y2 = screen_lines + y2 + 1;
|
|
Packit Service |
a9274b |
if (x2 < 0)
|
|
Packit Service |
a9274b |
x2 = screen_cols + x2 + 1;
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
for (i = 0; i < clickable_rects_count; ++i) {
|
|
Packit Service |
a9274b |
if (!RECT_IS_FREE(clickable_rects[i]) && (
|
|
Packit Service |
a9274b |
IS_IN_RECT(clickable_rects[i].y1, clickable_rects[i].x1) ||
|
|
Packit Service |
a9274b |
IS_IN_RECT(clickable_rects[i].y2, clickable_rects[i].x2)
|
|
Packit Service |
a9274b |
))
|
|
Packit Service |
a9274b |
{
|
|
Packit Service |
a9274b |
RECT_FREE(clickable_rects[i]);
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
struct clickable_rect* clickable_find(int y, int x) {
|
|
Packit Service |
a9274b |
unsigned int i;
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
for (i = 0; i < clickable_rects_count; ++i) {
|
|
Packit Service |
a9274b |
if (
|
|
Packit Service |
a9274b |
!RECT_IS_FREE(clickable_rects[i]) &&
|
|
Packit Service |
a9274b |
y >= clickable_rects[i].y1 &&
|
|
Packit Service |
a9274b |
x >= clickable_rects[i].x1 &&
|
|
Packit Service |
a9274b |
y <= clickable_rects[i].y2 &&
|
|
Packit Service |
a9274b |
x <= clickable_rects[i].x2
|
|
Packit Service |
a9274b |
)
|
|
Packit Service |
a9274b |
{
|
|
Packit Service |
a9274b |
return &clickable_rects[i];
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
}
|
|
Packit Service |
a9274b |
|
|
Packit Service |
a9274b |
return NULL;
|
|
Packit Service |
a9274b |
}
|