Fix a bug (in revision 426) which made "Mode 3 - Unhook Syscalls" un-effectivei ...
[open-ps2-loader.git] / src / dia.c
blobf6b00e4c471e112e7fe91b3719ad523d231654d4
1 /*
2 Copyright 2009-2010 volca
3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
5 */
7 #include "include/usbld.h"
8 #include "include/dia.h"
9 #include "include/gui.h"
10 #include "include/lang.h"
11 #include "include/pad.h"
12 #include "include/renderman.h"
13 #include "include/fntsys.h"
14 #include "include/themes.h"
15 #include "include/util.h"
17 // UI spacing of the dialogues (pixels between consecutive items)
18 #define UI_SPACING_H 10
19 #define UI_SPACING_V 2
20 // spacer ui element width (simulates tab)
21 #define UI_SPACER_WIDTH 50
22 // minimal pixel width of spacer
23 #define UI_SPACER_MINIMAL 30
24 // length of breaking line in pixels
25 #define UI_BREAK_LEN 600
26 // scroll speed (delay in ms!) when in dialogs
27 #define DIA_SCROLL_SPEED 300
28 // scroll speed (delay in ms!) when setting int value
29 #define DIA_INT_SET_SPEED 100
31 static int screenWidth;
32 static int screenHeight;
34 // Utility stuff
35 #define KEYB_MODE 2
36 #define KEYB_WIDTH 12
37 #define KEYB_HEIGHT 4
38 #define KEYB_ITEMS (KEYB_WIDTH * KEYB_HEIGHT)
40 static void diaDrawBoundingBox(int x, int y, int w, int h, int focus) {
41 if (focus)
42 rmDrawRect(x - 5, y, w + 10, h + 10, gTheme->selTextColor & gColFocus);
43 else
44 rmDrawRect(x - 5, y, w + 10, h + 10, gTheme->textColor & gColFocus);
47 int diaShowKeyb(char* text, int maxLen) {
48 int i, j, len = strlen(text), selkeyb = 0, x, w;
49 int selchar = 0, selcommand = -1;
50 char c[2] = "\0\0";
51 char keyb0[KEYB_ITEMS] = {
52 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
53 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
54 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\\',
55 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '`', ':' };
57 char keyb1[KEYB_ITEMS] = {
58 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',
59 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}',
60 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '|',
61 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '~', '.' };
62 char *keyb = keyb0;
64 char *commands[KEYB_HEIGHT] = {_l(_STR_BACKSPACE), _l(_STR_SPACE), _l(_STR_ENTER), _l(_STR_MODE)};
65 GSTEXTURE *cmdicons[KEYB_HEIGHT];
66 cmdicons[0] = thmGetTexture(SQUARE_ICON);
67 cmdicons[1] = thmGetTexture(TRIANGLE_ICON);
68 cmdicons[2] = thmGetTexture(START_ICON);
69 cmdicons[3] = thmGetTexture(SELECT_ICON);
71 while(1) {
72 readPads();
74 rmStartFrame();
75 guiDrawBGPlasma();
76 rmDrawRect(0, 0, screenWidth, screenHeight, gColDarker);
78 //Text
79 fntRenderString(gTheme->fonts[0], 50, 120, ALIGN_NONE, 0, 0, text, gTheme->textColor);
81 // separating line for simpler orientation
82 rmDrawLine(25, 138, 615, 138, gColWhite);
83 rmDrawLine(25, 139, 615, 139, gColWhite);
85 for (j = 0; j < KEYB_HEIGHT; j++) {
86 for (i = 0; i < KEYB_WIDTH; i++) {
87 c[0] = keyb[i + j * KEYB_WIDTH];
89 x = 50 + i * 31;
90 w = fntRenderString(gTheme->fonts[0], x, 170 + 3 * UI_SPACING_H * j, ALIGN_NONE, 0, 0, c, gTheme->uiTextColor) - x;
91 if ((i + j * KEYB_WIDTH) == selchar)
92 diaDrawBoundingBox(x, 170 + 3 * UI_SPACING_H * j, w, UI_SPACING_H, 0);
96 // Commands
97 for (i = 0; i < KEYB_HEIGHT; i++) {
98 if (cmdicons[i])
99 rmDrawPixmap(cmdicons[i], 436, 170 + 3 * UI_SPACING_H * i, ALIGN_NONE, cmdicons[i]->Width, cmdicons[i]->Height, SCALING_RATIO, gDefaultCol);
101 x = 477;
102 w = fntRenderString(gTheme->fonts[0], x, 170 + 3 * UI_SPACING_H * i, ALIGN_NONE, 0, 0, commands[i], gTheme->uiTextColor) - x;
103 if (i == selcommand)
104 diaDrawBoundingBox(x, 170 + 3 * UI_SPACING_H * i, w, UI_SPACING_H, 0);
107 rmEndFrame();
109 if (getKey(KEY_LEFT)) {
110 if (selchar > -1) {
111 if (selchar % KEYB_WIDTH)
112 selchar--;
113 else {
114 selcommand = selchar / KEYB_WIDTH;
115 selchar = -1;
117 } else {
118 selchar = (selcommand + 1) * KEYB_WIDTH - 1;
119 selcommand = -1;
121 } else if (getKey(KEY_RIGHT)) {
122 if (selchar > -1) {
123 if ((selchar + 1) % KEYB_WIDTH)
124 selchar++;
125 else {
126 selcommand = selchar / KEYB_WIDTH;
127 selchar = -1;
129 } else {
130 selchar = selcommand * KEYB_WIDTH;
131 selcommand = -1;
133 } else if (getKey(KEY_UP)) {
134 if (selchar > -1)
135 selchar = (selchar + KEYB_ITEMS - KEYB_WIDTH) % KEYB_ITEMS;
136 else
137 selcommand = (selcommand + KEYB_HEIGHT - 1) % KEYB_HEIGHT;
138 } else if (getKey(KEY_DOWN)) {
139 if (selchar > -1)
140 selchar = (selchar + KEYB_WIDTH) % KEYB_ITEMS;
141 else
142 selcommand = (selcommand + 1) % KEYB_HEIGHT;
143 } else if (getKeyOn(KEY_CROSS)) {
144 if (len < (maxLen - 1) && selchar > -1) {
145 len++;
146 c[0] = keyb[selchar];
147 strcat(text,c);
148 } else if (selcommand == 0) {
149 if (len > 0) { // BACKSPACE
150 len--;
151 text[len] = 0;
153 } else if (selcommand == 1) {
154 if (len < (maxLen - 1)) { // SPACE
155 len++;
156 c[0] = ' ';
157 strcat(text,c);
159 } else if (selcommand == 2) {
160 return 1; //ENTER
161 } else if (selcommand == 3) {
162 selkeyb = (selkeyb + 1) % KEYB_MODE; // MODE
163 if (selkeyb == 0)
164 keyb = keyb0;
165 if (selkeyb == 1)
166 keyb = keyb1;
168 } else if (getKey(KEY_SQUARE)) {
169 if (len>0) { // BACKSPACE
170 len--;
171 text[len] = 0;
173 } else if (getKey(KEY_TRIANGLE)) {
174 if (len < (maxLen - 1) && selchar > -1) { // SPACE
175 len++;
176 c[0] = ' ';
177 strcat(text,c);
179 } else if (getKeyOn(KEY_START)) {
180 return 1; //ENTER
181 } else if (getKeyOn(KEY_SELECT)) {
182 selkeyb = (selkeyb + 1) % KEYB_MODE; // MODE
183 if (selkeyb == 0)
184 keyb = keyb0;
185 if (selkeyb == 1)
186 keyb = keyb1;
189 if (getKey(KEY_CIRCLE))
190 break;
193 return 0;
196 static int colPadSettings[16];
198 static int diaShowColSel(unsigned char *r, unsigned char *g, unsigned char *b) {
199 int selc = 0;
200 int ret = 0;
201 unsigned char col[3];
203 padStoreSettings(colPadSettings);
205 col[0] = *r; col[1] = *g; col[2] = *b;
206 setButtonDelay(KEY_LEFT, 1);
207 setButtonDelay(KEY_RIGHT, 1);
209 while(1) {
210 readPads();
212 rmStartFrame();
213 guiDrawBGPlasma();
214 rmDrawRect(0, 0, screenWidth, screenHeight, gColDarker);
216 // "Color selection"
217 fntRenderString(gTheme->fonts[0], 50, 50, ALIGN_NONE, 0, 0, _l(_STR_COLOR_SELECTION), GS_SETREG_RGBA(0x060, 0x060, 0x060, 0x060));
219 // 3 bars representing the colors...
220 size_t co;
221 int x, y;
223 for (co = 0; co < 3; ++co) {
224 unsigned char cc[3] = {0,0,0};
225 cc[co] = col[co];
227 x = 75;
228 y = 75 + co * 25;
230 u64 dcol = GS_SETREG_RGBA(cc[0], cc[1], cc[2], 0x80);
232 if (selc == co)
233 rmDrawRect(x, y, 200, 20, GS_SETREG_RGBA(0x060, 0x060, 0x060, 0x60));
234 else
235 rmDrawRect(x, y, 200, 20, GS_SETREG_RGBA(0x020, 0x020, 0x020, 0x60));
237 rmDrawRect(x + 2, y + 2, 190.0f*(cc[co]*100/255)/100, 16, dcol);
240 // target color itself
241 u64 dcol = GS_SETREG_RGBA(col[0],col[1],col[2], 0x80);
243 x = 300;
244 y = 75;
246 rmDrawRect(x, y, 70, 70, GS_SETREG_RGBA(0x060, 0x060, 0x060, 0x60));
247 rmDrawRect(x + 5, y + 5, 60, 60, dcol);
249 rmEndFrame();
251 if (getKey(KEY_LEFT)) {
252 if (col[selc] > 0)
253 col[selc]--;
254 } else if (getKey(KEY_RIGHT)) {
255 if (col[selc] < 255)
256 col[selc]++;
257 } else if (getKey(KEY_UP)) {
258 if (selc > 0)
259 selc--;
260 } else if (getKey(KEY_DOWN)) {
261 if (selc < 2)
262 selc++;
263 } else if (getKeyOn(KEY_CROSS)) {
264 *r = col[0];
265 *g = col[1];
266 *b = col[2];
267 ret = 1;
268 break;
269 } else if (getKeyOn(KEY_CIRCLE)) {
270 ret = 0;
271 break;
275 padRestoreSettings(colPadSettings);
276 return ret;
281 // ----------------------------------------------------------------------------
282 // --------------------------- Dialogue handling ------------------------------
283 // ----------------------------------------------------------------------------
284 static const char *diaGetLocalisedText(const char* def, int id) {
285 if (id >= 0)
286 return _l(id);
288 return def;
291 /// returns true if the item is controllable (e.g. a value can be changed on it)
292 static int diaIsControllable(struct UIItem *ui) {
293 return (ui->enabled && (ui->type >= UI_OK));
296 /// returns true if the given item should be preceded with nextline
297 static int diaShouldBreakLine(struct UIItem *ui) {
298 return (ui->type == UI_SPLITTER || ui->type == UI_OK || ui->type == UI_BREAK);
301 /// returns true if the given item should be superseded with nextline
302 static int diaShouldBreakLineAfter(struct UIItem *ui) {
303 return (ui->type == UI_SPLITTER);
306 static void diaDrawHint(int text_id) {
307 int x, y;
309 char* text = _l(text_id);
311 x = screenWidth - fntCalcDimensions(gTheme->fonts[0], text) - 10;
312 y = gTheme->usedHeight - 40;
314 // render hint on the lower side of the screen.
315 rmDrawRect(x, y, screenWidth - x, MENU_ITEM_HEIGHT + 10, gColDarker);
316 fntRenderString(gTheme->fonts[0], x + 5, y + 5, ALIGN_NONE, 0, 0, text, gTheme->textColor);
319 /// renders an ui item (either selected or not)
320 /// sets width and height of the render into the parameters
321 static void diaRenderItem(int x, int y, struct UIItem *item, int selected, int haveFocus, int *w, int *h) {
322 *h = UI_SPACING_H;
324 // all texts are rendered up from the given point!
325 u64 txtcol;
327 if (diaIsControllable(item))
328 txtcol = gTheme->uiTextColor;
329 else
330 txtcol = gTheme->textColor;
332 // let's see what do we have here?
333 switch (item->type) {
334 case UI_TERMINATOR:
335 return;
337 case UI_BUTTON:
338 case UI_LABEL: {
339 // width is text length in pixels...
340 const char *txt = diaGetLocalisedText(item->label.text, item->label.stringId);
341 if(txt && strlen(txt))
342 *w = fntRenderString(gTheme->fonts[0], x, y, ALIGN_NONE, 0, 0, txt, txtcol) - x;
343 else
344 *w = fntRenderString(gTheme->fonts[0], x, y, ALIGN_NONE, 0, 0, _l(_STR_NOT_SET), txtcol) - x;
346 break;
349 case UI_SPLITTER: {
350 // a line. Thanks to the font rendering, we need to shift up by one font line
351 *w = 0; // nothing to render at all
352 int ypos = y - UI_SPACING_V / 2; // gsFont->CharHeight +
354 // to ODD lines
355 ypos &= ~1;
357 // two lines for lesser eye strain :)
358 rmDrawLine(x, ypos , x + UI_BREAK_LEN, ypos , gColWhite);
359 rmDrawLine(x, ypos + 1, x + UI_BREAK_LEN, ypos + 1, gColWhite);
360 break;
363 case UI_BREAK:
364 *w = 0; // nothing to render at all
365 break;
367 case UI_SPACER: {
368 // next column divisible by spacer
369 *w = (UI_SPACER_WIDTH - x % UI_SPACER_WIDTH);
371 if (*w < UI_SPACER_MINIMAL) {
372 x += *w + UI_SPACER_MINIMAL;
373 *w += (UI_SPACER_WIDTH - x % UI_SPACER_WIDTH);
376 *h = 0;
377 break;
380 case UI_OK: {
381 const char *txt = _l(_STR_OK);
382 *w = fntRenderString(gTheme->fonts[0], x, y, ALIGN_NONE, 0, 0, txt, txtcol) - x;
383 break;
386 case UI_INT: {
387 char tmp[10];
389 snprintf(tmp, 10, "%d", item->intvalue.current);
390 *w = fntRenderString(gTheme->fonts[0], x, y, ALIGN_NONE, 0, 0, tmp, txtcol) - x;
391 break;
394 case UI_STRING: {
395 if(strlen(item->stringvalue.text))
396 *w = fntRenderString(gTheme->fonts[0], x, y, ALIGN_NONE, 0, 0, item->stringvalue.text, txtcol) - x;
397 else
398 *w = fntRenderString(gTheme->fonts[0], x, y, ALIGN_NONE, 0, 0, _l(_STR_NOT_SET), txtcol) - x;
399 break;
402 case UI_PASSWORD: {
403 char stars[32];
404 int i;
406 int len = min(strlen(item->stringvalue.text), 30);
407 for (i = 0; i < len; ++i)
408 stars[i] = '*';
410 stars[i] = '\0';
411 *w = fntRenderString(gTheme->fonts[0], x, y, ALIGN_NONE, 0, 0, stars, txtcol) - x;
412 break;
415 case UI_BOOL: {
416 const char *txtval = _l((item->intvalue.current) ? _STR_ON : _STR_OFF);
417 *w = fntRenderString(gTheme->fonts[0], x, y, ALIGN_NONE, 0, 0, txtval, txtcol) - x;
418 break;
421 case UI_ENUM: {
422 const char* tv = item->intvalue.enumvalues[item->intvalue.current];
424 if (!tv)
425 tv = _l(_STR_NO_ITEMS);
427 *w = fntRenderString(gTheme->fonts[0], x, y, ALIGN_NONE, 0, 0, tv, txtcol) - x;
428 break;
431 case UI_COLOUR: {
432 rmDrawRect(x, y + 3, 25, 17, txtcol);
433 u64 dcol = GS_SETREG_RGBA(item->colourvalue.r, item->colourvalue.g, item->colourvalue.b, 0x80);
434 rmDrawRect(x + 2, y + 5, 21, 13, dcol);
436 *w = 25;
437 *h = 17;
438 break;
442 if (selected)
443 diaDrawBoundingBox(x, y, *w, *h, haveFocus);
445 if (item->fixedWidth != 0) {
446 int newSize;
447 if (item->fixedWidth < 0)
448 newSize = item->fixedWidth * screenWidth / -100;
449 else
450 newSize = item->fixedWidth;
451 if (*w < newSize)
452 *w = newSize;
455 if (item->fixedHeight != 0) {
456 int newSize;
457 if (item->fixedHeight < 0)
458 newSize = item->fixedHeight * screenHeight / -100;
459 else
460 newSize = item->fixedHeight;
461 if (*h < newSize)
462 *h = newSize;
466 /// renders whole ui screen (for given dialog setup)
467 void diaRenderUI(struct UIItem *ui, short inMenu, struct UIItem *cur, int haveFocus) {
468 guiDrawBGPlasma();
470 int x0 = 20;
471 int y0 = 20;
473 // render all items
474 struct UIItem *rc = ui;
475 int x = x0, y = y0, hmax = 0;
477 while (rc->type != UI_TERMINATOR) {
478 int w = 0, h = 0;
480 if (diaShouldBreakLine(rc)) {
481 x = x0;
483 if (hmax > 0)
484 y += hmax + UI_SPACING_H;
486 hmax = 0;
489 diaRenderItem(x, y, rc, rc == cur, haveFocus, &w, &h);
491 if (w > 0)
492 x += w + UI_SPACING_V;
494 hmax = (h > hmax) ? h : hmax;
496 if (diaShouldBreakLineAfter(rc)) {
497 x = x0;
499 if (hmax > 0)
500 y += hmax + UI_SPACING_H;
502 hmax = 0;
505 rc++;
508 if ((cur != NULL) && (!haveFocus) && (cur->hintId != -1)) {
509 diaDrawHint(cur->hintId);
513 /// sets the ui item value to the default again
514 static void diaResetValue(struct UIItem *item) {
515 switch(item->type) {
516 case UI_INT:
517 case UI_BOOL:
518 item->intvalue.current = item->intvalue.def;
519 return;
520 case UI_STRING:
521 case UI_PASSWORD:
522 strncpy(item->stringvalue.text, item->stringvalue.def, 32);
523 return;
524 default:
525 return;
529 static int diaHandleInput(struct UIItem *item, int *modified) {
530 // circle loses focus, sets old values first
531 if (getKeyOn(KEY_CIRCLE)) {
532 diaResetValue(item);
533 return 0;
536 // cross loses focus without setting default
537 if (getKeyOn(KEY_CROSS)) {
538 *modified = 0;
539 return 0;
542 // UI item type dependant part:
543 if (item->type == UI_BOOL) {
544 // a trick. Set new value, lose focus
545 item->intvalue.current = !item->intvalue.current;
546 return 0;
547 } if (item->type == UI_INT) {
548 // to be sure
549 setButtonDelay(KEY_UP, DIA_INT_SET_SPEED);
550 setButtonDelay(KEY_DOWN, DIA_INT_SET_SPEED);
552 // up and down
553 if (getKey(KEY_UP) && (item->intvalue.current < item->intvalue.max))
554 item->intvalue.current++;
555 else if (getKey(KEY_DOWN) && (item->intvalue.current > item->intvalue.min))
556 item->intvalue.current--;
557 else
558 *modified = 0;
559 } else if ((item->type == UI_STRING) || (item->type == UI_PASSWORD)) {
560 char tmp[32];
561 strncpy(tmp, item->stringvalue.text, 32);
563 if (item->stringvalue.handler) {
564 if (item->stringvalue.handler(tmp, 32))
565 strncpy(item->stringvalue.text, tmp, 32);
566 } else {
567 if (diaShowKeyb(tmp, 32))
568 strncpy(item->stringvalue.text, tmp, 32);
571 return 0;
572 } else if (item->type == UI_ENUM) {
573 int cur = item->intvalue.current;
575 if (item->intvalue.enumvalues[cur] == NULL) {
576 if (cur > 0)
577 item->intvalue.current--;
578 else
579 return 0;
582 if (getKey(KEY_UP) && (item->intvalue.current > 0))
583 item->intvalue.current--;
584 else if (getKey(KEY_DOWN) && (item->intvalue.enumvalues[item->intvalue.current + 1] != NULL))
585 item->intvalue.current++;
586 else
587 *modified = 0;
588 } else if (item->type == UI_COLOUR) {
589 if (!diaShowColSel(&item->colourvalue.r, &item->colourvalue.g, &item->colourvalue.b))
590 *modified = 0;
592 return 0;
595 return 1;
598 static struct UIItem *diaGetFirstControl(struct UIItem *ui) {
599 struct UIItem *cur = ui;
601 while (!diaIsControllable(cur)) {
602 if (cur->type == UI_TERMINATOR)
603 return ui;
605 cur++;
608 return cur;
611 static struct UIItem *diaGetLastControl(struct UIItem *ui) {
612 struct UIItem *last = diaGetFirstControl(ui);
613 struct UIItem *cur = last;
615 while (cur->type != UI_TERMINATOR) {
616 cur++;
618 if (diaIsControllable(cur))
619 last = cur;
622 return last;
625 static struct UIItem *diaGetNextControl(struct UIItem *cur, struct UIItem* dflt) {
626 while (cur->type != UI_TERMINATOR) {
627 cur++;
629 if (diaIsControllable(cur))
630 return cur;
633 return dflt;
636 static struct UIItem *diaGetPrevControl(struct UIItem* cur, struct UIItem *ui) {
637 struct UIItem *newf = cur;
639 while (newf != ui) {
640 newf--;
642 if (diaIsControllable(newf))
643 return newf;
646 return cur;
649 /// finds first control on previous line...
650 static struct UIItem *diaGetPrevLine(struct UIItem* cur, struct UIItem *ui) {
651 struct UIItem *newf = cur;
653 int lb = 0;
654 int hadCtrl = 0; // had the scanned line any control?
656 while (newf != ui) {
657 newf--;
659 if ((lb > 0) && (diaIsControllable(newf)))
660 hadCtrl = 1;
662 if (diaShouldBreakLine(newf)) {// is this a line break?
663 if (hadCtrl || lb == 0) {
664 lb++;
665 hadCtrl = 0;
669 // twice the break? find first control
670 if (lb == 2)
671 return diaGetFirstControl(newf);
674 return cur;
677 static struct UIItem *diaGetNextLine(struct UIItem* cur, struct UIItem *ui) {
678 struct UIItem *newf = cur;
680 int lb = 0;
682 while (newf->type != UI_TERMINATOR) {
683 newf++;
685 if (diaShouldBreakLine(newf)) {// is this a line break?
686 lb++;
689 if (lb == 1)
690 return diaGetNextControl(newf, cur);
693 return cur;
696 static int diaPadSettings[16];
698 static void diaStoreScrollSpeed(void) {
699 padStoreSettings(diaPadSettings);
702 static void diaRestoreScrollSpeed(void) {
703 padRestoreSettings(diaPadSettings);
706 static struct UIItem* diaFindByID(struct UIItem* ui, int id) {
707 while (ui->type != UI_TERMINATOR) {
708 if (ui->id == id)
709 return ui;
711 ui++;
714 return NULL;
717 int diaExecuteDialog(struct UIItem *ui, int uiId, short inMenu, int (*updater)(int modified)) {
718 rmGetScreenExtents(&screenWidth, &screenHeight);
720 struct UIItem *cur = NULL;
721 if (uiId != -1)
722 cur = diaFindByID(ui, uiId);
724 if (!cur)
725 cur = diaGetFirstControl(ui);
727 // what? no controllable item? Exit!
728 if (cur == ui)
729 return -1;
731 int haveFocus = 0, modified;
733 diaStoreScrollSpeed();
735 // slower controls for dialogs
736 setButtonDelay(KEY_UP, DIA_SCROLL_SPEED);
737 setButtonDelay(KEY_DOWN, DIA_SCROLL_SPEED);
739 // okay, we have the first selectable item
740 // we can proceed with rendering etc. etc.
741 while (1) {
742 rmStartFrame();
743 diaRenderUI(ui, inMenu, cur, haveFocus);
744 rmEndFrame();
746 readPads();
748 if (haveFocus) {
749 modified = 1;
750 haveFocus = diaHandleInput(cur, &modified);
752 if (!haveFocus) {
753 setButtonDelay(KEY_UP, DIA_SCROLL_SPEED);
754 setButtonDelay(KEY_DOWN, DIA_SCROLL_SPEED);
756 } else {
757 modified = 0;
758 if (getKey(KEY_LEFT)) {
759 struct UIItem *newf = diaGetPrevControl(cur, ui);
761 if (newf == cur)
762 cur = diaGetLastControl(ui);
763 else
764 cur = newf;
767 if (getKey(KEY_RIGHT)) {
768 struct UIItem *newf = diaGetNextControl(cur, cur);
770 if (newf == cur)
771 cur = diaGetFirstControl(ui);
772 else
773 cur = newf;
776 if(getKey(KEY_UP)) {
777 // find
778 struct UIItem *newf = diaGetPrevLine(cur, ui);
780 if (newf == cur)
781 cur = diaGetLastControl(ui);
782 else
783 cur = newf;
786 if(getKey(KEY_DOWN)) {
787 // find
788 struct UIItem *newf = diaGetNextLine(cur, ui);
790 if (newf == cur)
791 cur = diaGetFirstControl(ui);
792 else
793 cur = newf;
796 // circle breaks focus or exits with false result
797 if (getKeyOn(KEY_CIRCLE)) {
798 diaRestoreScrollSpeed();
799 return 0;
802 // see what key events we have
803 if (getKeyOn(KEY_CROSS)) {
804 haveFocus = 1;
806 if (cur->type == UI_BUTTON) {
807 diaRestoreScrollSpeed();
808 return cur->id;
811 if (cur->type == UI_OK) {
812 diaRestoreScrollSpeed();
813 return 1;
818 if (updater) {
819 int updResult = updater(modified);
820 if (updResult)
821 return updResult;
826 void diaSetEnabled(struct UIItem* ui, int id, int enabled) {
827 struct UIItem *item = diaFindByID(ui, id);
829 if (!item)
830 return;
832 item->enabled = enabled;
835 int diaGetInt(struct UIItem* ui, int id, int *value) {
836 struct UIItem *item = diaFindByID(ui, id);
838 if (!item)
839 return 0;
841 if ((item->type == UI_INT) || (item->type == UI_BOOL) || (item->type == UI_ENUM)) {
842 *value = item->intvalue.current;
843 return 1;
846 return 0;
849 int diaSetInt(struct UIItem* ui, int id, int value) {
850 struct UIItem *item = diaFindByID(ui, id);
852 if (!item)
853 return 0;
855 if ((item->type == UI_INT) || (item->type == UI_BOOL) || (item->type == UI_ENUM)) {
856 item->intvalue.def = value;
857 item->intvalue.current = value;
858 return 1;
861 return 0;
864 int diaGetString(struct UIItem* ui, int id, char *value) {
865 struct UIItem *item = diaFindByID(ui, id);
867 if (!item)
868 return 0;
870 if ((item->type == UI_STRING) || (item->type == UI_PASSWORD)) {
871 strncpy(value, item->stringvalue.text, 32);
872 return 1;
875 return 0;
878 int diaSetString(struct UIItem* ui, int id, const char *text) {
879 struct UIItem *item = diaFindByID(ui, id);
881 if (!item)
882 return 0;
884 if ((item->type == UI_STRING) || (item->type == UI_PASSWORD)) {
885 strncpy(item->stringvalue.def, text, 32);
886 strncpy(item->stringvalue.text, text, 32);
887 return 1;
890 return 0;
893 int diaGetColor(struct UIItem* ui, int id, unsigned char *col) {
894 struct UIItem *item = diaFindByID(ui, id);
896 if (!item)
897 return 0;
899 if (item->type != UI_COLOUR)
900 return 0;
902 col[0] = item->colourvalue.r;
903 col[1] = item->colourvalue.g;
904 col[2] = item->colourvalue.b;
905 return 1;
908 int diaSetColor(struct UIItem* ui, int id, const unsigned char *col) {
909 struct UIItem *item = diaFindByID(ui, id);
911 if (!item)
912 return 0;
914 if (item->type != UI_COLOUR)
915 return 0;
917 item->colourvalue.r = col[0];
918 item->colourvalue.g = col[1];
919 item->colourvalue.b = col[2];
920 return 1;
923 int diaSetU64Color(struct UIItem* ui, int id, u64 col) {
924 struct UIItem *item = diaFindByID(ui, id);
926 if (!item)
927 return 0;
929 if (item->type != UI_COLOUR)
930 return 0;
932 item->colourvalue.r = col & 0xFF;
933 col >>= 8;
934 item->colourvalue.g = col & 0xFF;
935 col >>= 8;
936 item->colourvalue.b = col & 0xFF;
937 return 1;
940 int diaSetLabel(struct UIItem* ui, int id, const char *text) {
941 struct UIItem *item = diaFindByID(ui, id);
943 if (!item)
944 return 0;
946 if ((item->type == UI_LABEL) || (item->type == UI_BUTTON)) {
947 item->label.text = text;
948 return 1;
951 return 0;
954 int diaSetEnum(struct UIItem* ui, int id, const char **enumvals) {
955 struct UIItem *item = diaFindByID(ui, id);
957 if (!item)
958 return 0;
960 if (item->type != UI_ENUM)
961 return 0;
963 item->intvalue.enumvalues = enumvals;
964 return 1;