1 /*---------------------------------------------------------------------------*
2 * N I N T E N D O C O N F I D E N T I A L P R O P R I E T A R Y
3 *---------------------------------------------------------------------------*
4 *
5 * Project: Dolphin OS - TextWindow primitives
6 * File: txwin.c
7 *
8 * Copyright 1999, 2000 Nintendo. All rights reserved.
9 *
10 * These coded instructions, statements, and computer programs contain
11 * proprietary information of Nintendo of America Inc. and/or Nintendo
12 * Company Ltd., and are protected by Federal copyright law. They may
13 * not be disclosed to third parties or copied or duplicated in any form,
14 * in whole or in part, without the prior written consent of Nintendo.
15 *
16 * $Log: DEMOWin.c,v $
17 * Revision 1.4 2008/07/10 03:04:49 yasuh-to
18 * Changed some variables to static
19 *
20 * Revision 1.3.38.1 2008/07/10 03:02:55 yasuh-to
21 * Changed some variables to be static.
22 *
23 * Revision 1.3 2006/05/21 15:02:09 ekwon
24 * Revised to accommodate MEM library usage if DEMO_USE_MEMLIB is #define'd before DEMOWIN.h is included.
25 *
26 * Also supports using MEM2 via #define of DEMOWIN_USE_MEM2. However, this has not been tested yet.
27 *
28 * Note that these changes are backwards compatible with older demos.
29 *
30 * Revision 1.2 2006/02/20 04:37:44 mitu
31 * Changed include path from dolphin/ to revolution/.
32 *
33 * Revision 1.1.1.1 2005/05/12 02:15:48 yasuh-to
34 * Ported from dolphin source tree
35 *
36
37 20 2002/08/26 10:03 Hashida
38 Deleted an unused variable.
39
40 19 2002/02/05 4:01p Eugene
41 Added pad data to window structure so that it may be exposed to the
42 calling application.
43
44 18 2001/07/27 11:49a Eugene
45 Failed to set window handles to NULL after freeing in
46 DEMOWinDestroy*Window() functions. Ooops, heee.
47
48 17 2001/05/21 12:14p Eugene
49 Modified default window color to accommodate gamma 1.0
50
51 16 2001/05/21 12:04p Eugene
52 Moved DEMOWIN.H to include/demo/demowin.h
53
54 15 2001/05/10 12:00a Eugene
55 Debounced MNU_SELECT and MNU_RIGHT inputs
56
57 14 2001/05/09 9:13p Eugene
58 Fixed consecutive SEPARATOR menu item bug.
59
60 13 2001/05/09 2:20p Eugene
61
62 12 2001/05/08 10:49p Eugene
63 1. Added Menu system.
64 2. Added List system.
65 3. No more special window types (log/state). Unified buffer system.
66 4. Windows are scrollable.
67 5. Menus support "child" menus recursively.
68 6. DEMO-lib friendly graphics for windows.
69 7. Window priority system. (using Z-buffer).
70 8. Window creation/destruction performed w/ separate API calls, to
71 facilitate handle reuse (and minimize mem allocation).
72 9. errrrmmm.....other stuff. repeat-mode pad inputs...
73
74 11 2001/05/08 4:05a Eugene
75
76 10 2001/05/08 2:18a Eugene
77
78 9 2001/05/08 2:05a Eugene
79
80 8 2001/05/07 11:54p Eugene
81
82 7 2001/05/07 11:27p Eugene
83
84 6 2001/05/07 11:12p Eugene
85
86 5 2001/05/07 10:02p Eugene
87
88 4 2001/05/07 1:28p Eugene
89
90 3 2001/05/06 11:28p Eugene
91
92 2 2001/05/06 11:07p Eugene
93
94 1 2001/05/06 8:29p Eugene
95 Simple text-windowing system. Not documented, not officially supported.
96 Include <dolphin/DEMOWin.h> to use the API. Does not impact old DEMO
97 library.
98
99 1 2000/12/04 7:28p Eugene
100 *
101 *
102 * $NoKeywords: $
103 *
104 *---------------------------------------------------------------------------*/
105
106
107 /*---------------------------------------------------------------------------*
108 * Includes
109 *---------------------------------------------------------------------------*/
110 #include <demo.h>
111 #include <stdlib.h>
112 #include <string.h>
113 #include <stddef.h>
114 #include <stdarg.h>
115
116 #include <revolution.h>
117
118 #include <demo/DEMOWin.h>
119
120
121
122 /*---------------------------------------------------------------------------*
123 * Local types
124 *---------------------------------------------------------------------------*/
125
126
127
128 /*---------------------------------------------------------------------------*
129 * Private module variables
130 *---------------------------------------------------------------------------*/
131
132 static DEMOWinInfo *__first_node;
133 static DEMOWinInfo *__last_node;
134 static DEMOWinInfo *__curr_node;
135
136 static GXRenderModeObj *__rmp;
137
138 #define __DEF_BKGND_R 0x1a
139 #define __DEF_BKGND_G 0x1f
140 #define __DEF_BKGND_B 0x21
141 #define __DEF_BKGND_A 0xff
142
143 #define __DEF_CAP_R 0x55
144 #define __DEF_CAP_G 0x1f
145 #define __DEF_CAP_B 0x1f
146 #define __DEF_CAP_A 0xff
147
148 #define __DEF_BORDER_R 0x45
149 #define __DEF_BORDER_G 0x25
150 #define __DEF_BORDER_B 0x25
151 #define __DEF_BORDER_A 0xff
152
153 static s32 fontShift = 0;
154
155 static u32 __DEMOWIN_PAD_repeat_threshold = DEMOWIN_PAD_REPEAT_THRESH_DEF;
156 static u32 __DEMOWIN_PAD_repeat_rate = DEMOWIN_PAD_REPEAT_RATE_DEF;
157
158
159 //
160 // hackery to use MEM library, and to specify MEM1 or MEM2
161 // based on whether or not DEMO_USE_MEMLIB and DEMOWIN_USE_MEM2 are #define'd
162 //
163
164 static BOOL __DEMOWin_use_memlib = FALSE;
165 static BOOL __DEMOWin_use_mem2 = FALSE;
166
167 static MEMAllocator *__DEMOWin_memallocator_ptr;
168
169
170 /*---------------------------------------------------------------------------*
171 * Private function prototypes
172 *---------------------------------------------------------------------------*/
173 static void __DEMOWin_add_node (DEMOWinInfo *handle);
174 static void __DEMOWin_delete_node (DEMOWinInfo *handle);
175 static void __DEMOWin_puts_n ( s16 x, s16 y, s16 z, u16 n, char* string );
176
177 static u16 __DEMOWinMenu_get_user_input (DEMOWinPadInfo *p);
178 static void __DEMOWinMenu_refesh_menu (DEMOWinInfo *w);
179 static void __DEMOWinList_refresh_list (DEMOWinInfo *w);
180
181 static void *__DEMOWin_alloc (u32 size);
182 static void __DEMOWin_free (void *ptr);
183
184 /*---------------------------------------------------------------------------*
185 * Name :
186 * Description :
187 * Arguments : None.
188 * Returns : None.
189 *---------------------------------------------------------------------------*/
__DEMOWin_alloc(u32 size)190 static void *__DEMOWin_alloc(u32 size)
191 {
192
193 void *ptr;
194
195 if (__DEMOWin_use_memlib)
196 {
197 ptr = MEMAllocFromAllocator(__DEMOWin_memallocator_ptr, size);
198 }
199 else
200 {
201 ptr = OSAlloc(size);
202 }
203
204 return(ptr);
205
206 } // End __DEMOWin_alloc()
207
208
209 /*---------------------------------------------------------------------------*
210 * Name :
211 * Description :
212 * Arguments : None.
213 * Returns : None.
214 *---------------------------------------------------------------------------*/
__DEMOWin_free(void * ptr)215 static void __DEMOWin_free(void *ptr)
216 {
217
218 if (__DEMOWin_use_memlib)
219 {
220 MEMFreeToAllocator(__DEMOWin_memallocator_ptr, ptr);
221 }
222 else
223 {
224 OSFree(ptr);
225 }
226
227 } // End __DEMOWin_free()
228
229 /*---------------------------------------------------------------------------*
230 * Name : DEMOWinInit()
231 *
232 * Description :
233 *
234 * Arguments : None.
235 *
236 * Returns : None.
237 *
238 *---------------------------------------------------------------------------*/
DEMOWinInit_Real(BOOL mem_lib_flag,BOOL mem2_flag)239 void DEMOWinInit_Real(BOOL mem_lib_flag, BOOL mem2_flag)
240 {
241
242 __DEMOWin_use_memlib = mem_lib_flag;
243 __DEMOWin_use_mem2 = mem2_flag;
244
245 if (__DEMOWin_use_memlib)
246 {
247 if (__DEMOWin_use_mem2)
248 {
249 __DEMOWin_memallocator_ptr = &DemoAllocator2;
250 }
251 else
252 {
253 __DEMOWin_memallocator_ptr = &DemoAllocator1;
254 }
255 }
256
257 // Initialize window list
258 __first_node = NULL;
259 __last_node = NULL;
260 __curr_node = NULL;
261
262 __rmp = DEMOGetRenderModeObj();
263
264 GXSetCopyClear( (GXColor){ 0x00, 0x00, 0x00, 0x00 }, GX_MAX_Z24 );
265
266 } // End winInit()
267
268 /*---------------------------------------------------------------------------*
269 * Name : DEMOWinCreateWindow()
270 *
271 * Description :
272 *
273 * Arguments : None.
274 *
275 * Returns : None.
276 *
277 *---------------------------------------------------------------------------*/
DEMOWinCreateWindow(s32 x1,s32 y1,s32 x2,s32 y2,char * caption,u16 scroll,void * func)278 DEMOWinInfo *DEMOWinCreateWindow(s32 x1, s32 y1, s32 x2, s32 y2, char *caption, u16 scroll, void *func)
279 {
280
281 DEMOWinInfo *handle;
282
283 ASSERTMSG((x1 < x2), "DEMOWIN: Illegal X coords for window\n");
284 ASSERTMSG((y1 < y2), "DEMOWIN: Illegal y coords for window\n");
285
286 // Allocate window structure
287 handle = (DEMOWinInfo *)__DEMOWin_alloc(sizeof(DEMOWinInfo));
288 ASSERTMSG(handle, "DEMOWIN: FAILED TO ALLOCATE WINDOW!\n");
289
290 handle->x1 = x1;
291 handle->y1 = y1;
292 handle->x2 = x2;
293 handle->y2 = y2;
294
295 handle->pixel_width = (u16)(x2 - x1 + 1);
296 handle->pixel_height = (u16)(y2 - y1 + 1);
297
298 handle->caption = caption;
299
300 handle->char_width = (u16)(((handle->pixel_width)/FONT_CHAR_WIDTH)-1); // Save a column for padding
301 handle->char_height = (u16)(((handle->pixel_height)/FONT_CHAR_HEIGHT)-2); // Save first line for caption, extra line for padding
302
303 handle->x_cal = (u16)((handle->pixel_width - (handle->char_width * FONT_CHAR_WIDTH) + 1) / 2);
304 handle->y_cal = (u16)(((handle->pixel_height - FONT_CHAR_HEIGHT) - (handle->char_height * FONT_CHAR_HEIGHT) + 1) / 2);
305
306 #ifdef DEMOWIN_DEBUG
307
308 OSReport("\n");
309 OSReport("======================================\n");
310 OSReport("WINDOW: '%s'\n", caption);
311 OSReport("======================================\n");
312 OSReport("x1: %4d\n", handle->x1);
313 OSReport("y1: %4d\n", handle->y1);
314 OSReport("x2: %4d\n", handle->x2);
315 OSReport("y2: %4d\n", handle->y2);
316 OSReport("pixel_width : %4d\n", handle->pixel_width);
317 OSReport("pixel_height: %4d\n", handle->pixel_height);
318 OSReport("char_width : %4d\n", handle->char_width);
319 OSReport("char_height : %4d\n", handle->char_height);
320 OSReport("x_cal : %4d\n", handle->x_cal);
321 OSReport("y_cal : %4d\n", handle->y_cal);
322
323 #endif
324
325 handle->num_scroll_lines = scroll;
326
327 handle->total_lines = (u16)(handle->char_height + handle->num_scroll_lines);
328
329 handle->curr_output_line = 0;
330 handle->curr_output_col = 0;
331 handle->curr_view_line = 0;
332
333 // User refresh function
334 handle->refresh = func;
335
336 // Clear flags
337 handle->flags = 0;
338
339 // Set priority
340 handle->priority = DEMOWIN_PRIORITY_FORE;
341
342
343 handle->buffer = (u8 *)__DEMOWin_alloc(sizeof(u8) * handle->total_lines * handle->char_width);
344 ASSERTMSG(handle->buffer, "DEMOWinCreateWindow(): Unable to allocation buffer!\n");
345
346 memset((void *)(handle->buffer), 0x20, sizeof(u8) * handle->total_lines * handle->char_width);
347
348
349 DEMOWinSetWindowColor(handle, DEMOWIN_COLOR_RESET, 0, 0, 0, 0);
350
351 // Turn off cursor;
352 handle->cursor_line = -1;
353
354 // Initialize parent to NULL
355 handle->parent = NULL;
356
357
358 // Do this last!
359 __DEMOWin_add_node(handle);
360
361 return(handle);
362
363
364 } // End DEMOWinCreateWindow()
365
366
367
368 /*---------------------------------------------------------------------------*
369 * Name : DEMOWinDestroyWindow()
370 *
371 * Description :
372 *
373 * Arguments : None.
374 *
375 * Returns : None.
376 *
377 *---------------------------------------------------------------------------*/
DEMOWinDestroyWindow(DEMOWinInfo * handle)378 void DEMOWinDestroyWindow(DEMOWinInfo *handle)
379 {
380 BOOL old;
381
382 ASSERTMSG(handle, "DEMOWinDestroyWindow(): NULL handle!\n");
383
384
385 old = OSDisableInterrupts();
386
387 __DEMOWin_delete_node(handle);
388
389 /*
390 for (i=0; i < handle->total_lines; i++)
391 {
392 __DEMOWin_free(handle->buffer[i]);
393 }
394 */
395 __DEMOWin_free(handle->buffer);
396
397 __DEMOWin_free(handle);
398
399 OSRestoreInterrupts(old);
400
401 } // End DEMOWinDestroyWindow()
402
403 /*---------------------------------------------------------------------------*
404 * Name : DEMOWinOpenWindow()
405 *
406 * Description :
407 *
408 * Arguments : None.
409 *
410 * Returns : None.
411 *
412 *---------------------------------------------------------------------------*/
DEMOWinOpenWindow(DEMOWinInfo * handle)413 void DEMOWinOpenWindow(DEMOWinInfo *handle)
414 {
415
416 ASSERTMSG(handle, "DEMOWinOpenWindow(): NULL handle!\n");
417 handle->flags |= DEMOWIN_FLAG_VISIBLE;
418 }
419
420 /*---------------------------------------------------------------------------*
421 * Name : DEMOWinCloseWindow()
422 *
423 * Description :
424 *
425 * Arguments : None.
426 *
427 * Returns : None.
428 *
429 *---------------------------------------------------------------------------*/
DEMOWinCloseWindow(DEMOWinInfo * handle)430 void DEMOWinCloseWindow(DEMOWinInfo *handle)
431 {
432 ASSERTMSG(handle, "DEMOWinCloseWindow(): NULL handle!\n");
433 handle->flags &= ~DEMOWIN_FLAG_VISIBLE;
434 }
435
436
437 /*---------------------------------------------------------------------------*
438 * Name : DEMOWinSetWindowColor()
439 *
440 * Description :
441 *
442 * Arguments : None.
443 *
444 * Returns : None.
445 *
446 *---------------------------------------------------------------------------*/
DEMOWinSetWindowColor(DEMOWinInfo * handle,u32 item,u8 r,u8 g,u8 b,u8 a)447 void DEMOWinSetWindowColor(DEMOWinInfo *handle, u32 item, u8 r, u8 g, u8 b, u8 a)
448 {
449
450 ASSERTMSG(handle, "DEMOWinSetWinColor(): NULL window handle\n");
451
452 switch (item)
453 {
454 case DEMOWIN_COLOR_CAPTION:
455 handle->cap.r = r;
456 handle->cap.g = g;
457 handle->cap.b = b;
458 handle->cap.a = a;
459 break;
460
461 case DEMOWIN_COLOR_BORDER:
462 handle->border.r = r;
463 handle->border.g = g;
464 handle->border.b = b;
465 handle->border.a = a;
466 break;
467
468 case DEMOWIN_COLOR_BKGND:
469 handle->bkgnd.r = r;
470 handle->bkgnd.g = g;
471 handle->bkgnd.b = b;
472 handle->bkgnd.a = a;
473 break;
474
475 case DEMOWIN_COLOR_RESET:
476 handle->bkgnd.r = __DEF_BKGND_R;
477 handle->bkgnd.g = __DEF_BKGND_G;
478 handle->bkgnd.b = __DEF_BKGND_B;
479 handle->bkgnd.a = __DEF_BKGND_A;
480
481 handle->cap.r = __DEF_CAP_R;
482 handle->cap.g = __DEF_CAP_G;
483 handle->cap.b = __DEF_CAP_B;
484 handle->cap.a = __DEF_CAP_A;
485
486 handle->border.r = __DEF_BORDER_R;
487 handle->border.g = __DEF_BORDER_G;
488 handle->border.b = __DEF_BORDER_B;
489 handle->border.a = __DEF_BORDER_A;
490 break;
491
492 default:
493 ASSERTMSG(0, "DEMOWinSetWinColor(): Unknown item\n");
494 break;
495 } // End switch
496
497 } // DEMOWinSetWinColor()
498
499
500 /*---------------------------------------------------------------------------*
501 * Name : DEMOWinLogPrintf()
502 *
503 * Description :
504 *
505 * Arguments : None.
506 *
507 * Returns : None.
508 *
509 *---------------------------------------------------------------------------*/
DEMOWinLogPrintf(DEMOWinInfo * handle,char * fmt,...)510 void DEMOWinLogPrintf(DEMOWinInfo *handle, char *fmt, ...)
511 {
512 va_list vlist;
513 char buffer[DEMOWIN_MAX_STRING_SIZE];
514 u16 len;
515 u16 i;
516 BOOL old;
517
518 u16 index = 0;
519
520 // get output string
521 va_start(vlist, fmt);
522 vsprintf(buffer, fmt, vlist);
523 va_end(vlist);
524
525
526 old = OSDisableInterrupts();
527
528
529 len = (u16)strlen(buffer);
530
531 for (i=0; i<len; i++)
532 {
533
534 if (buffer[i] == '\n')
535 {
536 // Advance current output line and view line
537 handle->curr_output_line = (u16)((handle->curr_output_line + 1) % handle->total_lines);
538 handle->curr_view_line = (u16)((handle->curr_view_line + 1) % handle->total_lines);
539 handle->curr_output_col = 0;
540
541 // Clobber new output line
542 index = (u16)(handle->curr_output_line * handle->char_width + handle->curr_output_col);
543 memset((void *)(&handle->buffer[index]), 0x20, sizeof(u8) * handle->char_width);
544
545 }
546 else
547 {
548 index = (u16)(handle->curr_output_line * handle->char_width + handle->curr_output_col);
549 handle->buffer[index] = (u8)buffer[i];
550 handle->curr_output_col++;
551 }
552
553 if (handle->curr_output_col >= handle->char_width)
554 {
555 handle->curr_output_col = 0;
556 handle->curr_output_line = (u16)((handle->curr_output_line + 1) % handle->total_lines);
557 handle->curr_view_line = (u16)((handle->curr_view_line + 1) % handle->total_lines);
558
559 // Clobber new output line
560 index = (u16)(handle->curr_output_line * handle->char_width + handle->curr_output_col);
561 memset((void *)(&handle->buffer[index]), 0x20, sizeof(u8) * handle->char_width);
562
563 }
564 }
565
566 OSRestoreInterrupts(old);
567
568 } // End DEMOWinLogPrintf()
569
570 /*---------------------------------------------------------------------------*
571 * Name : DEMOWinPrintfXY()
572 *
573 * Description :
574 *
575 * Arguments : None.
576 *
577 * Returns : None.
578 *
579 *---------------------------------------------------------------------------*/
DEMOWinPrintfXY(DEMOWinInfo * handle,u16 col,u16 row,char * fmt,...)580 void DEMOWinPrintfXY(DEMOWinInfo *handle, u16 col, u16 row, char *fmt, ...)
581 {
582
583 BOOL old;
584
585 va_list vlist;
586 char string[DEMOWIN_MAX_STRING_SIZE];
587
588 u16 buffer_row; // Map window row-coord to buffer space
589 u16 i;
590 u16 index;
591
592
593 // If row/col coords are outside of the window, then don't bother
594 if ((row >= handle->char_height) || (col >= handle->char_width))
595 {
596 return;
597 }
598
599 old = OSDisableInterrupts();
600
601 // get output string
602 va_start(vlist, fmt);
603 vsprintf(string, fmt, vlist);
604 va_end(vlist);
605
606 // Find top line of window in buffer
607 buffer_row = (u16)( ((handle->curr_view_line + handle->total_lines) - (handle->char_height-1)) % handle->total_lines);
608
609 // Now descend through buffer until we get the desired row
610 buffer_row = (u16)((buffer_row + row) % handle->total_lines);
611 // Truncate string to right screen edge
612 string[handle->char_width - col] = 0;
613
614 index = (u16)(buffer_row * handle->char_width + col);
615
616 for (i=0; i<strlen(string); i++)
617 {
618 handle->buffer[index+i] = (u8)string[i];
619 }
620
621 OSRestoreInterrupts(old);
622
623
624 } // End DEMOWinLogPrintf()
625
626 /*---------------------------------------------------------------------------*
627 * Name : DEMOWinScroll()
628 *
629 * Description : Scrolls ONE line up or down.
630 *
631 * Arguments : None.
632 *
633 * Returns : None.
634 *
635 *---------------------------------------------------------------------------*/
DEMOWinScrollWindow(DEMOWinInfo * handle,u32 dir)636 void DEMOWinScrollWindow(DEMOWinInfo *handle, u32 dir)
637 {
638
639 BOOL old;
640
641 u16 n;
642 u16 v_start;
643
644
645 ASSERTMSG(handle, "DEMOWinScrollWindow(): NULL handle!\n");
646 ASSERTMSG(handle->num_scroll_lines, "DEMOWinScrollWindow(): No scrollback buffer!\n");
647
648
649 switch(dir)
650 {
651 case DEMOWIN_SCROLL_UP:
652 old = OSDisableInterrupts();
653
654 n = (u16)(((handle->curr_view_line + handle->total_lines) - 1) % handle->total_lines);
655
656 v_start = (u16)(((n + handle->total_lines) - handle->char_height+1) % handle->total_lines);
657
658 if (v_start != handle->curr_output_line)
659 {
660 handle->curr_view_line = n;
661 }
662 OSRestoreInterrupts(old);
663 break;
664
665 case DEMOWIN_SCROLL_DOWN:
666 old = OSDisableInterrupts();
667 if (handle->curr_view_line != handle->curr_output_line)
668 {
669 handle->curr_view_line = (u16)((handle->curr_view_line + 1) % handle->total_lines);
670 }
671 OSRestoreInterrupts(old);
672 break;
673
674 case DEMOWIN_SCROLL_HOME:
675 old = OSDisableInterrupts();
676 handle->curr_view_line = handle->curr_output_line;
677 OSRestoreInterrupts(old);
678 break;
679
680 default:
681 ASSERTMSG(0, "DEMOWinScrollWindow(): Unknown token\n");
682 break;
683
684 } // End switch
685
686
687 } // End DEMOWinScrollWindow
688
689
690 /*---------------------------------------------------------------------------*
691 * Name : DEMOWinBringToFront()
692 *
693 * Description :
694 *
695 * Arguments : None.
696 *
697 * Returns : None.
698 *
699 *---------------------------------------------------------------------------*/
DEMOWinBringToFront(DEMOWinInfo * handle)700 void DEMOWinBringToFront(DEMOWinInfo *handle)
701 {
702 DEMOWinInfo *ptr;
703
704 ASSERTMSG(__first_node, "DEMOWinBringToFront(): Window list is empty!\n");
705 ASSERTMSG(handle, "DEMOWinBringToFront(): NULL handle!\n");
706
707 if (DEMOWIN_PRIORITY_FORE == handle->priority)
708 {
709 return;
710 }
711
712 // Send everyone else to the background
713 ptr = __first_node;
714 while (ptr)
715 {
716 ptr->priority = DEMOWIN_PRIORITY_BACK;
717 ptr = ptr->next;
718 }
719
720 // Bring our window to the front
721 handle->priority = DEMOWIN_PRIORITY_FORE;
722
723
724
725 } // End DEMOWinBringToFront()
726
727 /*---------------------------------------------------------------------------*
728 * Name : DEMOWinSendToBack()
729 *
730 * Description :
731 *
732 * Arguments : None.
733 *
734 * Returns : None.
735 *
736 *---------------------------------------------------------------------------*/
DEMOWinSendToBack(DEMOWinInfo * handle)737 void DEMOWinSendToBack(DEMOWinInfo *handle)
738 {
739
740 ASSERTMSG(handle, "DEMOWinSendToBack(): NULL handle!\n");
741 handle->priority = DEMOWIN_PRIORITY_BACK;
742
743 } // End DEMOWinSendToBack()
744
745
746 /*---------------------------------------------------------------------------*
747 * Name : DEMOWinClearRow()
748 *
749 * Description :
750 *
751 * Arguments : None.
752 *
753 * Returns : None.
754 *
755 *---------------------------------------------------------------------------*/
DEMOWinClearRow(DEMOWinInfo * handle,u16 row)756 void DEMOWinClearRow(DEMOWinInfo *handle, u16 row)
757 {
758
759 u16 buffer_row;
760 u16 index;
761 u16 i;
762 BOOL old;
763
764 ASSERTMSG(handle, "DEMOWinClearRow(): NULL handle!\n");
765
766
767 // Bail if the row is outside the window
768 if (row >= handle->char_height)
769 {
770 return;
771 }
772
773 old = OSDisableInterrupts();
774
775 // Find top line of window in buffer
776 buffer_row = (u16)( ((handle->curr_view_line + handle->total_lines) - (handle->char_height-1)) % handle->total_lines);
777
778 // Now descend through buffer until we get the desired row
779 buffer_row = (u16)((buffer_row + row) % handle->total_lines);
780
781 index = (u16)(buffer_row * handle->char_width);
782
783 for (i=0; i<handle->char_width; i++)
784 {
785 handle->buffer[index+i] = 0x20;
786 }
787
788 OSRestoreInterrupts(old);
789
790
791
792
793 } // End DEMOWinClearRow()
794
795 /*---------------------------------------------------------------------------*
796 * Name : DEMOWinClearWindow()
797 *
798 * Description :
799 *
800 * Arguments : None.
801 *
802 * Returns : None.
803 *
804 *---------------------------------------------------------------------------*/
DEMOWinClearWindow(DEMOWinInfo * handle)805 void DEMOWinClearWindow(DEMOWinInfo *handle)
806 {
807
808 u16 buffer_row;
809 u16 index;
810 u16 i;
811 BOOL old;
812
813 ASSERTMSG(handle, "DEMOWinClearWindow(): NULL handle!\n");
814
815
816 old = OSDisableInterrupts();
817
818 // Find top line of window in buffer
819 buffer_row = (u16)( ((handle->curr_view_line + handle->total_lines) - (handle->char_height-1)) % handle->total_lines);
820
821 for (i=0; i<handle->char_height; i++)
822 {
823 index = (u16)(buffer_row * handle->char_width);
824 memset((void *)(&handle->buffer[index]), 0x20, sizeof(u8) * handle->char_width);
825 buffer_row = (u16)((buffer_row + 1) % handle->total_lines);
826 }
827
828 OSRestoreInterrupts(old);
829
830 } // End DEMOWinClearWindow()
831
832
833 /*---------------------------------------------------------------------------*
834 * Name : DEMOWinClearBuffer()
835 *
836 * Description :
837 *
838 * Arguments : None.
839 *
840 * Returns : None.
841 *
842 *---------------------------------------------------------------------------*/
DEMOWinClearBuffer(DEMOWinInfo * handle)843 void DEMOWinClearBuffer(DEMOWinInfo *handle)
844 {
845 BOOL old;
846
847 ASSERTMSG(handle, "DEMOWinClearBuffer(): NULL handle!\n");
848
849 old = OSDisableInterrupts();
850
851 memset(handle->buffer, 0x20, sizeof(u8) * handle->total_lines * handle->char_width);
852
853
854 OSRestoreInterrupts(old);
855
856 } // End DEMOWinClearBuffer()
857
858
859
860
861
862
863
864 /*---------------------------------------------------------------------------*
865 * Name : DEMOWinRefresh()
866 *
867 * Description :
868 *
869 * Arguments : None.
870 *
871 * Returns : None.
872 *
873 *---------------------------------------------------------------------------*/
DEMOWinRefresh(void)874 void DEMOWinRefresh(void)
875 {
876
877 DEMOWinInfo *ptr;
878
879 u16 i;
880 u16 index;
881 u16 n;
882
883 u16 y;
884
885 BOOL old;
886
887 ASSERTMSG(__first_node, "DEMOWinRefresh(): Windowlist is empty!\n");
888
889 ptr = __first_node;
890
891 while(ptr)
892 {
893
894
895 if (ptr->flags & DEMOWIN_FLAG_VISIBLE)
896 {
897
898 // ------------------------------------------------------------
899 // DRAW WINDOWS FIRST - they are drawn without alpha/blending
900 // ------------------------------------------------------------
901
902 // Windows
903 GXSetZMode( GX_ENABLE, GX_LEQUAL, GX_ENABLE );
904 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
905
906 // Set vertex descriptor
907 GXClearVtxDesc();
908 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
909 GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
910
911 // Position has 3 elements (x,y,z), each of a float type
912 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
913 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
914
915 // Disable lighting
916 GXSetNumChans(1);
917 GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
918
919 // One tevstage that passes color
920 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
921 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
922 GXSetNumTexGens(0);
923 GXSetNumTevStages(1);
924
925 GXSetLineWidth( 6, GX_TO_ZERO );
926
927 // Window background
928 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
929 GXPosition3f32(ptr->x1, ptr->y1, (f32)(ptr->priority));
930 GXColor4u8( ptr->bkgnd.r, ptr->bkgnd.g, ptr->bkgnd.b, ptr->bkgnd.a );
931
932 GXPosition3f32(ptr->x2, ptr->y1, (f32)(ptr->priority));
933 GXColor4u8( ptr->bkgnd.r, ptr->bkgnd.g, ptr->bkgnd.b, ptr->bkgnd.a );
934
935 GXPosition3f32(ptr->x2, ptr->y2, (f32)(ptr->priority));
936 GXColor4u8( ptr->bkgnd.r, ptr->bkgnd.g, ptr->bkgnd.b, ptr->bkgnd.a );
937
938 GXPosition3f32(ptr->x1, ptr->y2, (f32)(ptr->priority));
939 GXColor4u8( ptr->bkgnd.r, ptr->bkgnd.g, ptr->bkgnd.b, ptr->bkgnd.a );
940 GXEnd();
941
942
943 // Caption
944 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR);
945 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
946 GXPosition3f32(ptr->x1, ptr->y1, (f32)(ptr->priority));
947 GXColor4u8( ptr->cap.r, ptr->cap.g, ptr->cap.b, 0xff );
948
949 GXPosition3f32(ptr->x2, ptr->y1, (f32)(ptr->priority));
950 GXColor4u8( 0, 0, 0, 64 );
951
952 GXPosition3f32(ptr->x2, ptr->y1+FONT_CHAR_HEIGHT+2, (f32)(ptr->priority));
953 GXColor4u8( 0, 0, 0, 64 );
954
955 GXPosition3f32(ptr->x1, ptr->y1+FONT_CHAR_HEIGHT+2, (f32)(ptr->priority));
956 GXColor4u8( ptr->cap.r, ptr->cap.g, ptr->cap.b, 0xff );
957 GXEnd();
958
959 // Border
960 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
961 {
962 u8 r1,g1,b1;
963 u8 r2,g2,b2;
964 u8 a;
965
966 r1 = (u8)((f32)(ptr->border.r)*1.3);
967 g1 = (u8)((f32)(ptr->border.g)*1.3);
968 b1 = (u8)((f32)(ptr->border.b)*1.3);
969
970 r2 = (u8)((f32)(ptr->border.r)*0.40);
971 g2 = (u8)((f32)(ptr->border.g)*0.40);
972 b2 = (u8)((f32)(ptr->border.b)*0.40);
973
974 a = 0x40;
975
976 GXSetLineWidth( 6, GX_TO_ZERO );
977 GXBegin(GX_LINESTRIP, GX_VTXFMT0, 7);
978 GXPosition3f32(ptr->x1, ptr->y1, (f32)(ptr->priority));
979 GXColor4u8(r1, g1, b1, a);
980
981 GXPosition3f32(ptr->x2, ptr->y1, (f32)(ptr->priority));
982 GXColor4u8(r1, g1, b1, a);
983
984 GXPosition3f32(ptr->x2, ptr->y1, (f32)(ptr->priority));
985 GXColor4u8(r2, g2, b2, a);
986
987 GXPosition3f32(ptr->x2, ptr->y2, (f32)(ptr->priority));
988 GXColor4u8(r2, g2, b2, a);
989
990 GXPosition3f32(ptr->x1, ptr->y2, (f32)(ptr->priority));
991 GXColor4u8(r2, g2, b2, a);
992
993 GXPosition3f32(ptr->x1, ptr->y2, (f32)(ptr->priority));
994 GXColor4u8(r1, g1, b1, a);
995
996 GXPosition3f32(ptr->x1, ptr->y1, (f32)(ptr->priority));
997 GXColor4u8(r1, g1, b1, a);
998 GXEnd();
999
1000 }
1001
1002 // Invoke user refresh callback
1003 if (ptr->refresh)
1004 {
1005 // Invoke refresh callback
1006 // User refresh should be invoked before application of caption/title and cursor highlighting, if any
1007 (*(ptr->refresh))(ptr);
1008 }
1009
1010 // ------------------------------------------------------------
1011 // Now slap on the text
1012 // ------------------------------------------------------------
1013 DEMOInitCaption(DM_FT_XLU, __rmp->fbWidth, __rmp->efbHeight);
1014 GXSetZMode( GX_ENABLE, GX_LEQUAL, GX_ENABLE );
1015
1016 old = OSDisableInterrupts();
1017
1018 n = ptr->curr_view_line;
1019
1020 y = (u16)(ptr->y2 - FONT_CHAR_HEIGHT - ptr->y_cal);
1021 n = (u16)(ptr->curr_view_line);
1022 index = (u16)(n * ptr->char_width);
1023
1024 for (i=0; i<ptr->char_height; i++)
1025 {
1026
1027 __DEMOWin_puts_n((s16)(ptr->x1+ptr->x_cal), (s16)y, (s16)ptr->priority, ptr->char_width, (char *)(&ptr->buffer[index]));
1028
1029 y = (u16)(y - FONT_CHAR_HEIGHT); // Decrement y-coord
1030 n = (u16)((((n + ptr->total_lines) - 1) % ptr->total_lines)); // Decrement current view line
1031 index = (u16)(n * ptr->char_width); // Recalc index
1032 }
1033
1034 DEMOPrintf((s16)(ptr->x1+2), (s16)ptr->y1, (s16)ptr->priority, "%s", ptr->caption);
1035
1036 // ------------------------------------------------------------
1037 // Now add highlighting, if any
1038 // ------------------------------------------------------------
1039 if (ptr->cursor_line >= 0)
1040 {
1041
1042 GXSetLineWidth( 6, GX_TO_ZERO );
1043
1044 GXSetZMode( GX_ENABLE, GX_LEQUAL, GX_ENABLE );
1045 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR);
1046
1047 // Set vertex descriptor
1048 GXClearVtxDesc();
1049 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
1050 GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
1051
1052 // Position has 3 elements (x,y,z), each of a float type
1053 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
1054 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
1055
1056 // Disable lighting
1057 GXSetNumChans(1);
1058 GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
1059
1060 // One tevstage that passes color
1061 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
1062 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
1063 GXSetNumTexGens(0);
1064 GXSetNumTevStages(1);
1065
1066
1067 GXSetLineWidth( 6, GX_TO_ZERO );
1068 {
1069 u8 r;
1070 u8 g;
1071 u8 b;
1072 u8 a;
1073 s32 curr_y;
1074
1075
1076 curr_y = ptr->y2 - FONT_CHAR_HEIGHT - ptr->y_cal;
1077 curr_y = curr_y - ( ((ptr->char_height-1)*FONT_CHAR_HEIGHT) - ((ptr->cursor_line)*FONT_CHAR_HEIGHT));
1078
1079 r = (u8)((f32)(ptr->bkgnd.r) * 1.9);
1080 g = (u8)((f32)(ptr->bkgnd.g) * 1.9);
1081 b = (u8)((f32)(ptr->bkgnd.b) * 1.9);
1082 a = 0x64;
1083
1084 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
1085 GXPosition3f32( (f32)(ptr->x1), (f32)(curr_y), (f32)(ptr->priority));
1086 GXColor4u8(r,g,b,a);
1087
1088 GXPosition3f32( (f32)(ptr->x2), (f32)(curr_y), (f32)(ptr->priority));
1089 GXColor4u8(r,g,b,a);
1090
1091 GXPosition3f32( (f32)(ptr->x2), (f32)(curr_y+FONT_CHAR_HEIGHT), (f32)(ptr->priority));
1092 GXColor4u8(r,g,b,a);
1093
1094 GXPosition3f32( (f32)(ptr->x1), (f32)(curr_y+FONT_CHAR_HEIGHT), (f32)(ptr->priority));
1095 GXColor4u8(r,g,b,a);
1096 GXEnd();
1097 }
1098 }
1099
1100 OSRestoreInterrupts(old);
1101
1102 } // If visible
1103
1104 ptr = ptr->next;
1105
1106 } // End while...
1107
1108
1109
1110 } // End DEMOWinRefresh()
1111
1112
1113
1114 /*---------------------------------------------------------------------------*
1115 * Name : __DEMOWinadd_node()
1116 *
1117 * Description :
1118 *
1119 * Arguments : None.
1120 *
1121 * Returns : None.
1122 *
1123 *---------------------------------------------------------------------------*/
__DEMOWin_add_node(DEMOWinInfo * handle)1124 static void __DEMOWin_add_node(DEMOWinInfo *handle)
1125 {
1126
1127 ASSERTMSG(handle, "__add_node(): you're adding a NULL node!\n");
1128
1129 if (NULL == __last_node)
1130 {
1131 // We're the first node!
1132 __first_node = __last_node = __curr_node = handle;
1133
1134 handle->next = NULL;
1135 handle->prev = NULL;
1136
1137 ASSERTMSG(__first_node, " > __first_node: NULL HANDLE!\n");
1138 }
1139 else
1140 {
1141
1142 __last_node->next = handle;
1143 handle->next = NULL;
1144 handle->prev = __last_node;
1145 __last_node = handle;
1146 }
1147
1148 handle->flags |= DEMOWIN_FLAG_ATTACHED;
1149
1150 } // add_node()
1151
1152
1153 /*---------------------------------------------------------------------------*
1154 * Name : __DEMOWin__delete_node()
1155 *
1156 * Description :
1157 *
1158 * Arguments : None.
1159 *
1160 * Returns : None.
1161 *
1162 *---------------------------------------------------------------------------*/
__DEMOWin_delete_node(DEMOWinInfo * handle)1163 static void __DEMOWin_delete_node(DEMOWinInfo *handle)
1164 {
1165
1166 ASSERTMSG(handle, "__delete_node(): you're deleting a NULL node!\n");
1167
1168
1169 // It's the first node
1170 if (__first_node == handle)
1171 {
1172 // Does a next node even exist?
1173 if (handle->next)
1174 {
1175 __first_node = (handle->next);
1176 (handle->next)->prev = NULL;
1177 }
1178 else
1179 {
1180 // Nope, it must have been the only node in the universe
1181 __first_node = __last_node = NULL;
1182 }
1183
1184 }
1185 else if (__last_node == handle)
1186 {
1187 // Does a previous node even exist?
1188 if (handle->prev)
1189 {
1190 // Yes
1191 __last_node = (handle->prev);
1192 (handle->prev)->next = NULL;
1193
1194 }
1195 else
1196 {
1197 // Nope, it was the only node in the universe
1198 __first_node = __last_node = NULL;
1199 }
1200
1201 }
1202 else
1203 {
1204 (handle->prev)->next = (handle->next);
1205 (handle->next)->prev = (handle->prev);
1206
1207 }
1208
1209 handle->flags = (handle->flags & (~DEMOWIN_FLAG_ATTACHED));
1210
1211
1212 } // add_node()
1213
1214
1215 /*---------------------------------------------------------------------------*
1216 * Name : __DEMOWin_puts_n()
1217 *
1218 * Description : Writes specified number of characters in string to screen
1219 *
1220 * Arguments :
1221 *
1222 * Returns :
1223 *
1224 *---------------------------------------------------------------------------*/
__DEMOWin_puts_n(s16 x,s16 y,s16 z,u16 n,char * string)1225 static void __DEMOWin_puts_n( s16 x, s16 y, s16 z, u16 n, char* string )
1226 {
1227 s32 s, t;
1228 s32 w, len, i;
1229
1230 // Set up vertex descriptors
1231 GXClearVtxDesc();
1232 GXSetVtxDesc( GX_VA_POS, GX_DIRECT );
1233 GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );
1234 GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0 );
1235 GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 1 );
1236
1237 len = n;
1238
1239 if ( len > 0 )
1240 {
1241 // Put a line
1242 GXBegin( GX_QUADS, GX_VTXFMT0, (u16)(len*4) );
1243 for ( i = 0; i < len; i ++ )
1244 {
1245 // Draw a letter
1246 w = string[i] - ' ';
1247 s = ( w % 8 ) * 16 + fontShift;
1248 t = ( w / 8 ) * 16 + fontShift;
1249 GXPosition3s16( (s16)(i*8+x ), (s16)(y ), z );
1250 GXTexCoord2s16( (s16)(s ), (s16)(t ) );
1251 GXPosition3s16( (s16)(i*8+x+8), (s16)(y ), z );
1252 GXTexCoord2s16( (s16)(s+16 ), (s16)(t ) );
1253 GXPosition3s16( (s16)(i*8+x+8), (s16)(y+8 ), z );
1254 GXTexCoord2s16( (s16)(s+16 ), (s16)(t+16) );
1255 GXPosition3s16( (s16)(i*8+x ), (s16)(y+8 ), z );
1256 GXTexCoord2s16( (s16)(s ), (s16)(t+16) );
1257 }
1258 GXEnd( );
1259 }
1260
1261 } // End __DEMOWinPutsN()
1262
1263
1264 //****************************************************************************
1265 // Menu Stuff
1266 //****************************************************************************
1267
1268 /*---------------------------------------------------------------------------*
1269 * Name : DEMOWinCreateMenuWindow()
1270 *
1271 * Description : Obvious
1272 *
1273 * Arguments : None.
1274 *
1275 * Returns : None.
1276 *
1277 *---------------------------------------------------------------------------*/
1278
DEMOWinCreateMenuWindow(DEMOWinMenuInfo * menu,u16 x,u16 y)1279 DEMOWinMenuInfo *DEMOWinCreateMenuWindow(DEMOWinMenuInfo *menu, u16 x, u16 y)
1280 {
1281
1282 DEMOWinMenuItem *ptr;
1283
1284 // Calculate max name/title string length
1285 // Calculate number of items in list
1286 ptr = menu->items;
1287
1288 menu->max_str_len = strlen(menu->title);
1289 menu->num_items = 0;
1290
1291 while (!(ptr->flags & DEMOWIN_ITM_TERMINATOR))
1292 {
1293 if (strlen(ptr->name) > menu->max_str_len)
1294 {
1295 menu->max_str_len = strlen(ptr->name);
1296 }
1297 (menu->num_items)++;
1298 ptr++;
1299 }
1300
1301 // Calculate actual number of items to display
1302 // It may be less than the max number specified by the user
1303 if (menu->num_items > menu->max_display_items)
1304 {
1305 menu->num_display_items = menu->max_display_items;
1306 }
1307 else
1308 {
1309 menu->num_display_items = menu->num_items;
1310 }
1311
1312 // Open window.
1313 // Note: This call will ASSERT if it fails to allocate a window
1314 menu->handle = DEMOWinCreateWindow((s16)x,
1315 (s16)y,
1316 (s16)(x + DEMOWIN_CALC_MENU_WIDTH_PIXELS(menu->max_str_len)),
1317 (s16)(y + DEMOWIN_CALC_MENU_HEIGHT_PIXELS(menu->num_display_items)),
1318 menu->title,
1319 0, // No scrollback lines! Menu function handles list scrolling
1320 __DEMOWinMenu_refesh_menu);
1321
1322
1323 // Parent of this window is the "menu" structure
1324 (menu->handle)->parent = menu;
1325
1326
1327
1328 if (menu->num_items)
1329 {
1330 return(menu);
1331 }
1332
1333 return(NULL);
1334
1335
1336 } // End DEMOWinCreateMenuWindow()
1337
1338
1339 /*---------------------------------------------------------------------------*
1340 * Name : DEMOWinDestroyMenuWindow()
1341 *
1342 * Description : Obvious
1343 *
1344 * Arguments : None.
1345 *
1346 * Returns : None.
1347 *
1348 *---------------------------------------------------------------------------*/
1349
DEMOWinDestroyMenuWindow(DEMOWinMenuInfo * menu)1350 void DEMOWinDestroyMenuWindow(DEMOWinMenuInfo *menu)
1351 {
1352
1353 if (menu->handle)
1354 {
1355 DEMOWinCloseWindow(menu->handle);
1356 DEMOWinDestroyWindow(menu->handle);
1357
1358 menu->handle = NULL;
1359 }
1360
1361 } // End DEMOWinDestroyMenuWindow()
1362
1363 /*---------------------------------------------------------------------------*
1364 * Name : DEMOWinMenuChild()
1365 *
1366 * Description : Obvious
1367 *
1368 * Arguments : None.
1369 *
1370 * Returns : None.
1371 *
1372 *---------------------------------------------------------------------------*/
1373
DEMOWinMenuChild(DEMOWinMenuInfo * menu,BOOL child_flag)1374 u32 DEMOWinMenuChild(DEMOWinMenuInfo *menu, BOOL child_flag)
1375 {
1376
1377 DEMOWinPadInfo *pad; // Pointer to pad data associated with this menu's window
1378 DEMOWinInfo *handle; // Pointer to window associated with this menu
1379
1380 u16 user_input; // User input from PAD
1381 BOOL exit_flag = FALSE;
1382 u32 result = 0;
1383
1384
1385
1386 // This is cheesy, but...
1387 handle = menu->handle;
1388 pad = &(menu->handle)->pad;
1389
1390
1391 // Display window, bring to foreground
1392 DEMOWinOpenWindow(handle);
1393 DEMOWinBringToFront(handle);
1394
1395
1396 // Initialize cursor and display-position state
1397 menu->curr_pos = 0;
1398 menu->display_pos = 0;
1399
1400 // Is there a callback for "open" event?
1401 if (menu->cb_open)
1402 {
1403 (*menu->cb_open)(menu, (u32)menu->curr_pos);
1404 }
1405
1406
1407 // Debounce
1408 DEMOWinPadInit(pad);
1409
1410 DEMOBeforeRender();
1411 DEMOWinRefresh();
1412 DEMODoneRender();
1413
1414 DEMOWinPadRead(pad);
1415
1416 DEMOBeforeRender();
1417 DEMOWinRefresh();
1418 DEMODoneRender();
1419
1420
1421 while(!exit_flag)
1422 {
1423
1424 user_input = __DEMOWinMenu_get_user_input(pad);
1425
1426 switch(user_input)
1427 {
1428 case DEMOWIN_MNU_UP:
1429
1430 menu->curr_pos = (u16)((menu->curr_pos - 1 + menu->num_items) % (menu->num_items));
1431 while( (menu->items[menu->curr_pos].flags & (DEMOWIN_ITM_DISABLED | DEMOWIN_ITM_SEPARATOR)) )
1432 {
1433 menu->curr_pos = (u16)((menu->curr_pos - 1 + menu->num_items) % (menu->num_items));
1434 }
1435 if (menu->cb_move)
1436 {
1437 (*(menu->cb_move))(menu, (u32)menu->curr_pos);
1438 }
1439
1440 break;
1441
1442 case DEMOWIN_MNU_DOWN:
1443 menu->curr_pos = (u16)((menu->curr_pos + 1) % (menu->num_items));
1444 while ((menu->items[menu->curr_pos].flags & (DEMOWIN_ITM_DISABLED | DEMOWIN_ITM_SEPARATOR)))
1445 {
1446 menu->curr_pos = (u16)((menu->curr_pos + 1) % (menu->num_items));
1447 }
1448 if (menu->cb_move)
1449 {
1450 (*(menu->cb_move))(menu, (u32)menu->curr_pos);
1451 }
1452
1453 break;
1454
1455 case DEMOWIN_MNU_LEFT:
1456 if (TRUE == child_flag)
1457 {
1458 // We are a child of another popup menu.
1459 exit_flag = TRUE;
1460 if (menu->cb_cancel)
1461 {
1462 (*(menu->cb_cancel))(menu, (u32)menu->curr_pos);
1463 }
1464
1465 }
1466 break;
1467
1468 case DEMOWIN_MNU_RIGHT:
1469 // Callback?
1470 if (menu->cb_move)
1471 {
1472 (*(menu->cb_move))(menu, (u32)menu->curr_pos);
1473 }
1474
1475
1476 // Ugh. Now, is there a link?
1477 if (menu->items[menu->curr_pos].link)
1478 {
1479 // Yes, there's a link. Is there an associated window handle?
1480 if ((menu->items[menu->curr_pos].link)->handle)
1481 {
1482 // Yup! So replace the window coordinates...
1483 ((menu->items[menu->curr_pos].link)->handle)->x1 = (u16)(handle->x1 + 20);
1484 ((menu->items[menu->curr_pos].link)->handle)->y1 = (u16)(handle->y1 + 20);
1485
1486 // ...and invoke the menu
1487 result = DEMOWinMenuChild(menu->items[menu->curr_pos].link, TRUE);
1488 if ((menu->items[menu->curr_pos].link)->flags & DEMOWIN_MNU_EOM)
1489 {
1490 exit_flag=TRUE;
1491 }
1492
1493 }
1494 else
1495 {
1496 // Nope. No window handle. So...create one!
1497 DEMOWinCreateMenuWindow(menu->items[menu->curr_pos].link, (u16)(handle->x1+20), (u16)(handle->y1+20));
1498 result = DEMOWinMenuChild(menu->items[menu->curr_pos].link, TRUE);
1499 if ((menu->items[menu->curr_pos].link)->flags & DEMOWIN_MNU_EOM)
1500 {
1501 exit_flag=TRUE;
1502 }
1503 DEMOWinDestroyMenuWindow(menu->items[menu->curr_pos].link);
1504
1505 }
1506 VIWaitForRetrace();
1507 DEMOWinPadRead(pad);
1508
1509 }
1510
1511 break;
1512
1513 case DEMOWIN_MNU_SELECT:
1514 if (menu->cb_select)
1515 {
1516 (*(menu->cb_select))(menu, (u32)menu->curr_pos);
1517 }
1518
1519 if (menu->items[menu->curr_pos].link)
1520 {
1521 // Yes, there's a link. Is there an associated window handle?
1522 if ((menu->items[menu->curr_pos].link)->handle)
1523 {
1524 // Yup! So replace the window coordinates...
1525 ((menu->items[menu->curr_pos].link)->handle)->x1 = (u16)(handle->x1 + 20);
1526 ((menu->items[menu->curr_pos].link)->handle)->y1 = (u16)(handle->y1 + 20);
1527
1528 // ...and invoke the menu
1529 result = DEMOWinMenuChild(menu->items[menu->curr_pos].link, TRUE);
1530 if ((menu->items[menu->curr_pos].link)->flags & DEMOWIN_MNU_EOM)
1531 {
1532 exit_flag=TRUE;
1533 }
1534
1535 }
1536 else
1537 {
1538 // Nope. No window handle. So...create one!
1539 DEMOWinCreateMenuWindow(menu->items[menu->curr_pos].link, (u16)(handle->x1+20), (u16)(handle->y1+20));
1540
1541 // ...and invoke the menu
1542 result = DEMOWinMenuChild(menu->items[menu->curr_pos].link, TRUE);
1543
1544
1545 // Now...should we kill the parent on this link?
1546 if ((menu->items[menu->curr_pos].link)->flags & DEMOWIN_MNU_EOM)
1547 {
1548 exit_flag=TRUE;
1549 }
1550 DEMOWinDestroyMenuWindow(menu->items[menu->curr_pos].link);
1551
1552
1553
1554 }
1555 VIWaitForRetrace();
1556 DEMOWinPadRead(pad);
1557
1558 }
1559 else
1560 {
1561 if (menu->items[menu->curr_pos].function)
1562 {
1563 (menu->items[menu->curr_pos].function)(menu, (u32)menu->curr_pos, &result);
1564 if (menu->items[menu->curr_pos].flags & DEMOWIN_ITM_EOF)
1565 {
1566 exit_flag = TRUE;
1567 }
1568 VIWaitForRetrace();
1569 DEMOWinPadRead(pad);
1570
1571 }
1572
1573 }
1574 break;
1575
1576 case DEMOWIN_MNU_CANCEL:
1577 if (menu->cb_cancel)
1578 {
1579 (*(menu->cb_cancel))(menu, (u32)menu->curr_pos);
1580 }
1581 exit_flag = TRUE;
1582 break;
1583
1584 }// End switch(parse_input)
1585
1586
1587 // Fix display pointer
1588 if (menu->curr_pos > (menu->display_pos+menu->num_display_items-1))
1589 {
1590 menu->display_pos = menu->curr_pos - menu->num_display_items + 1;
1591
1592 }
1593 else if (menu->curr_pos < menu->display_pos)
1594 {
1595 menu->display_pos = menu->curr_pos;
1596 }
1597
1598 // Calculate cursor position
1599 if (menu->display_pos > menu->curr_pos)
1600 {
1601 handle->cursor_line = (s16)(menu->display_pos - menu->curr_pos);
1602 }
1603 else
1604 {
1605 handle->cursor_line = (s16)(menu->curr_pos - menu->display_pos);
1606 }
1607
1608
1609 DEMOBeforeRender();
1610 DEMOWinRefresh();
1611 DEMODoneRender();
1612
1613
1614 } // While exit
1615
1616
1617 DEMOWinCloseWindow(handle);
1618
1619 DEMOBeforeRender();
1620 DEMOWinRefresh();
1621 DEMODoneRender();
1622
1623
1624 return(result);
1625
1626
1627 } // End DEMOWinMenuChild()
1628
1629 /*---------------------------------------------------------------------------*
1630 * Name : __DEMOWinMenu_display_menu()
1631 *
1632 * Description : Obvious
1633 *
1634 * Arguments : None.
1635 *
1636 * Returns : None.
1637 *
1638 *---------------------------------------------------------------------------*/
1639
__DEMOWinMenu_refesh_menu(DEMOWinInfo * w)1640 static void __DEMOWinMenu_refesh_menu(DEMOWinInfo *w)
1641 {
1642
1643 DEMOWinMenuInfo *m;
1644
1645 s32 i;
1646 s32 j;
1647 char check;
1648 char para_start;
1649 char para_end;
1650 char link;
1651
1652
1653 // Clear window contents
1654 DEMOWinClearWindow(w);
1655
1656 // Parent should be a Menu info structure
1657 m = (w->parent);
1658
1659 j = m->display_pos;
1660
1661 for (i=0; i<m->num_display_items; i++)
1662 {
1663 if (m->items[j].flags & DEMOWIN_ITM_SEPARATOR)
1664 {
1665
1666 if (strlen(m->items[(u16)j].name))
1667 {
1668 DEMOWinPrintfXY(w, 0, (u16)i, " %s ", m->items[(u16)j].name);
1669 }
1670
1671 }
1672 else
1673 {
1674
1675 check = (char)((m->items[j].flags & DEMOWIN_ITM_CHK_STATE) ? 'X' : ' ');
1676 para_start = (char)((m->items[j].flags & DEMOWIN_ITM_DISABLED) ? '(' : ' ');
1677 para_end = (char)((m->items[j].flags & DEMOWIN_ITM_DISABLED) ? ')' : ' ');
1678 link = (char)((NULL != m->items[j].link) ? '>' : ' ');
1679
1680 DEMOWinPrintfXY(w, 0, (u16)i, "%c %c%s%c %c", check, para_start, m->items[(u16)j].name, para_end, link);
1681 }
1682 j++;
1683 }
1684
1685
1686 } // End __DEMOWinMenu_display_menu()
1687
1688
1689 /*---------------------------------------------------------------------------*
1690 * Name : DEMOWinPadInit()
1691 *
1692 * Description : Obvious
1693 *
1694 * Arguments : None.
1695 *
1696 * Returns : None.
1697 *
1698 *---------------------------------------------------------------------------*/
1699
DEMOWinPadInit(DEMOWinPadInfo * p)1700 void DEMOWinPadInit(DEMOWinPadInfo *p)
1701 {
1702 u16 i;
1703
1704
1705 for (i=0; i<PAD_MAX_CONTROLLERS ;i++)
1706 {
1707 p->old_button[i] = 0;
1708 p->changed_button [i] = 0;
1709 p->repeat_button [i] = 0;
1710 p->repeat_ctr [i] = 0;
1711 }
1712 }
1713
1714 /*---------------------------------------------------------------------------*
1715 * Name : DEMOWinPadRead()
1716 *
1717 * Description : Obvious
1718 *
1719 * Arguments : None.
1720 *
1721 * Returns : None.
1722 *
1723 *---------------------------------------------------------------------------*/
DEMOWinPadRead(DEMOWinPadInfo * p)1724 void DEMOWinPadRead(DEMOWinPadInfo *p)
1725 {
1726
1727 PADStatus *pad;
1728
1729 u16 index;
1730
1731 u32 curr;
1732 u32 old;
1733
1734 u32 repeat;
1735
1736
1737 PADRead(p->pads);
1738
1739 for (index=0; index<PAD_MAX_CONTROLLERS; index++)
1740 {
1741
1742 old = p->old_button[index];
1743 pad = &(p->pads[index]);
1744
1745 curr = ( (pad->stickX > PAD_THRESHOLD)? DEMOWIN_STICK_R : 0 ) |
1746 ( (pad->stickX < -PAD_THRESHOLD)? DEMOWIN_STICK_L : 0 ) |
1747 ( (pad->stickY > PAD_THRESHOLD)? DEMOWIN_STICK_U : 0 ) |
1748 ( (pad->stickY < -PAD_THRESHOLD)? DEMOWIN_STICK_D : 0 ) |
1749 ( (pad->substickX > PAD_THRESHOLD)? DEMOWIN_SUBSTICK_R : 0 ) |
1750 ( (pad->substickX < -PAD_THRESHOLD)? DEMOWIN_SUBSTICK_L : 0 ) |
1751 ( (pad->substickY > PAD_THRESHOLD)? DEMOWIN_SUBSTICK_U : 0 ) |
1752 ( (pad->substickY < -PAD_THRESHOLD)? DEMOWIN_SUBSTICK_D : 0 ) |
1753 ( (pad->triggerLeft > TRIGGER_THRESHOLD)? DEMOWIN_TRIGGER_L : 0 ) |
1754 ( (pad->triggerRight > TRIGGER_THRESHOLD)? DEMOWIN_TRIGGER_R : 0 ) |
1755 (u32)pad->button;
1756
1757 p->changed_button[index] = (u32)((old ^ curr) & curr);
1758
1759 if (curr)
1760 {
1761 if (old == curr)
1762 {
1763 p->repeat_ctr[index]++;
1764 }
1765 else
1766 {
1767 p->repeat_ctr[index] = 1;
1768 }
1769 }
1770 else
1771 {
1772 p->repeat_ctr[index] = 0;
1773 }
1774
1775 repeat = p->repeat_ctr[index];
1776
1777 if (repeat == 1)
1778 {
1779 p->repeat_button[index] = curr;
1780 }
1781 else if (repeat > __DEMOWIN_PAD_repeat_threshold)
1782 {
1783 if ( ((repeat - __DEMOWIN_PAD_repeat_threshold) % __DEMOWIN_PAD_repeat_rate) == 0)
1784 {
1785 p->repeat_button[index] = curr;
1786 }
1787 else
1788 {
1789 p->repeat_button[index] = 0;
1790 }
1791 }
1792 else
1793 {
1794 p->repeat_button[index] = 0;
1795 }
1796 p->old_button[index] = curr;
1797 }
1798
1799 } // End DEMOWinPadRead()
1800
1801 /*---------------------------------------------------------------------------*
1802 * Name : __DEMOWinMenu_get_user_input()
1803 *
1804 * Description : Obvious
1805 *
1806 * Arguments : None.
1807 *
1808 * Returns : None.
1809 *
1810 *---------------------------------------------------------------------------*/
1811
__DEMOWinMenu_get_user_input(DEMOWinPadInfo * p)1812 static u16 __DEMOWinMenu_get_user_input(DEMOWinPadInfo *p)
1813 {
1814
1815 u16 user_input;
1816
1817 DEMOWinPadRead(p);
1818
1819 if (p->repeat_button[0] & (PAD_BUTTON_UP|DEMOWIN_STICK_U))
1820 {
1821 user_input = DEMOWIN_MNU_UP;
1822 }
1823 else if (p->repeat_button[0] & (PAD_BUTTON_DOWN|DEMOWIN_STICK_D))
1824 {
1825 user_input = DEMOWIN_MNU_DOWN;
1826 }
1827 else if (p->repeat_button[0] & (PAD_BUTTON_LEFT|DEMOWIN_STICK_L))
1828 {
1829 user_input = DEMOWIN_MNU_LEFT;
1830 }
1831 else if (p->repeat_button[0] & (PAD_BUTTON_RIGHT|DEMOWIN_STICK_R))
1832 {
1833 user_input = DEMOWIN_MNU_RIGHT;
1834 }
1835 else if (p->changed_button[0] & PAD_BUTTON_A) // No repeat!
1836 {
1837 user_input = DEMOWIN_MNU_SELECT;
1838 }
1839 else if (p->changed_button[0] & PAD_BUTTON_B) // No repeat!
1840 {
1841 user_input = DEMOWIN_MNU_CANCEL;
1842 }
1843 else
1844 {
1845 user_input = 0;
1846 }
1847
1848 /*
1849 if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_UP)
1850 {
1851 user_input = DEMOWIN_MNU_UP;
1852 }
1853 else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_DOWN)
1854 {
1855 user_input = DEMOWIN_MNU_DOWN;
1856 }
1857 else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_LEFT)
1858 {
1859 user_input = DEMOWIN_MNU_LEFT;
1860 }
1861 else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_RIGHT)
1862 {
1863 user_input = DEMOWIN_MNU_RIGHT;
1864 }
1865 else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_A)
1866 {
1867 user_input = DEMOWIN_MNU_SELECT;
1868 }
1869 else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_B)
1870 {
1871 user_input = DEMOWIN_MNU_CANCEL;
1872 }
1873 else
1874 {
1875 user_input = 0;
1876 }
1877
1878 *old_button = pads[0].button;
1879 */
1880
1881 return(user_input);
1882
1883 } // End __DEMOWinMenu_display_menu()
1884
1885
1886 /*---------------------------------------------------------------------------*
1887 * Name : DEMOWinSetRepeat()
1888 *
1889 * Description : Obvious
1890 *
1891 * Arguments : None.
1892 *
1893 * Returns : None.
1894 *
1895 *---------------------------------------------------------------------------*/
DEMOWinSetRepeat(u32 threshold,u32 rate)1896 void DEMOWinSetRepeat(u32 threshold, u32 rate)
1897 {
1898
1899 __DEMOWIN_PAD_repeat_rate = rate;
1900 __DEMOWIN_PAD_repeat_threshold = threshold;
1901
1902 } // End DEMOWinSetRepeat()
1903
1904 /*---------------------------------------------------------------------------*
1905 * Name : DEMOWinResetRepeat()
1906 *
1907 * Description : Obvious
1908 *
1909 * Arguments : None.
1910 *
1911 * Returns : None.
1912 *
1913 *---------------------------------------------------------------------------*/
1914
DEMOWinResetRepeat(void)1915 void DEMOWinResetRepeat(void)
1916 {
1917
1918 __DEMOWIN_PAD_repeat_threshold = DEMOWIN_PAD_REPEAT_THRESH_DEF;
1919 __DEMOWIN_PAD_repeat_rate = DEMOWIN_PAD_REPEAT_RATE_DEF;
1920
1921 } // End DEMOWinResetRepeat()
1922
1923
1924 /*---------------------------------------------------------------------------*
1925 * Name : DEMOWinCreateListWindow()
1926 *
1927 * Description : Obvious
1928 *
1929 * Arguments : None.
1930 *
1931 * Returns : None.
1932 *
1933 *---------------------------------------------------------------------------*/
1934
DEMOWinCreateListWindow(DEMOWinListInfo * list,u16 x,u16 y)1935 DEMOWinListInfo *DEMOWinCreateListWindow(DEMOWinListInfo *list, u16 x, u16 y)
1936 {
1937
1938 DEMOWinListItem *ptr;
1939
1940
1941 ASSERTMSG(list, "DEMOWinCreateListWindow(): List is NULL!\n");
1942
1943 // Calculate max name/title string length
1944 // Calculate number of items in list
1945 ptr = list->items;
1946
1947 list->max_str_len = strlen(list->title);
1948 list->num_items = 0;
1949
1950 while (!(ptr->flags & DEMOWIN_ITM_TERMINATOR))
1951 {
1952 if (strlen(ptr->name) > list->max_str_len)
1953 {
1954 list->max_str_len = strlen(ptr->name);
1955 }
1956 (list->num_items)++;
1957 ptr++;
1958 }
1959
1960 // Calculate actual number of items to display
1961 // It may be less than the max number specified by the user
1962 if (list->num_items > list->max_display_items)
1963 {
1964 list->num_display_items = list->max_display_items;
1965 }
1966 else
1967 {
1968 list->num_display_items = list->num_items;
1969 }
1970
1971 // Open window.
1972 // Note: This call will ASSERT if it fails to allocate a window
1973 list->handle = DEMOWinCreateWindow((s16)x,
1974 (s16)y,
1975 (s16)(x + DEMOWIN_CALC_MENU_WIDTH_PIXELS(list->max_str_len)),
1976 (s16)(y + DEMOWIN_CALC_MENU_HEIGHT_PIXELS(list->num_display_items)),
1977 list->title,
1978 0, // No scrollback lines! Menu function handles list scrolling
1979 __DEMOWinList_refresh_list); // No callback function
1980
1981
1982 // Set parent of this window to this list
1983 (list->handle)->parent = (void *)(list);
1984
1985
1986 if (list->num_items)
1987 {
1988 return(list);
1989 }
1990
1991 return(NULL);
1992
1993
1994 } // End DEMOWinCreateListWindow()
1995
1996 /*---------------------------------------------------------------------------*
1997 * Name : DEMOWinDestroyListWindow()
1998 *
1999 * Description : Obvious
2000 *
2001 * Arguments : None.
2002 *
2003 * Returns : None.
2004 *
2005 *---------------------------------------------------------------------------*/
2006
DEMOWinDestroyListWindow(DEMOWinListInfo * list)2007 void DEMOWinDestroyListWindow(DEMOWinListInfo *list)
2008 {
2009
2010 if (list->handle)
2011 {
2012 DEMOWinCloseWindow(list->handle);
2013 DEMOWinDestroyWindow(list->handle);
2014
2015 list->handle = NULL;
2016 }
2017
2018 } // End DEMOWinDestroyListWindow()
2019
2020
2021 /*---------------------------------------------------------------------------*
2022 * Name : __DEMOWinList_update_list()
2023 *
2024 * Description : Obvious
2025 *
2026 * Arguments : None.
2027 *
2028 * Returns : None.
2029 *
2030 *---------------------------------------------------------------------------*/
2031
__DEMOWinList_refresh_list(DEMOWinInfo * w)2032 static void __DEMOWinList_refresh_list(DEMOWinInfo *w)
2033 {
2034
2035
2036 DEMOWinListInfo *l;
2037
2038 s32 i;
2039 s32 j;
2040
2041 // The parent better the hell be a List info structure
2042 l = (w->parent);
2043
2044 // Just in case...
2045 l->curr_pos = l->curr_pos % l->num_items;
2046
2047 // Fix display pointer
2048 if (l->curr_pos > (l->display_pos+l->num_display_items-1))
2049 {
2050 l->display_pos = l->curr_pos - l->num_display_items + 1;
2051
2052 }
2053 else if (l->curr_pos < l->display_pos)
2054 {
2055 l->display_pos = l->curr_pos;
2056 }
2057
2058 if (l->cursor_state)
2059 {
2060 // Calculate cursor line
2061 if (l->display_pos > l->curr_pos)
2062 {
2063 w->cursor_line = (s16)(l->display_pos - l->curr_pos);
2064 }
2065 else
2066 {
2067 w->cursor_line = (s16)(l->curr_pos - l->display_pos);
2068 }
2069
2070 }// End cursor state check
2071 else
2072 {
2073 w->cursor_line = -1;
2074 }
2075
2076 // Display menu
2077 DEMOWinClearWindow(w);
2078
2079
2080 j = l->display_pos;
2081
2082 for (i=0; i<l->num_display_items; i++)
2083 {
2084 if (!(l->items[j].flags & DEMOWIN_ITM_SEPARATOR))
2085 {
2086 DEMOWinPrintfXY(w, 0, (u16)i, " %s ",l->items[(u16)j].name);
2087 }
2088 j++;
2089 }
2090
2091
2092 } // end __DEMOWinList_update_list()
2093
2094 /*---------------------------------------------------------------------------*
2095 * Name : DEMOWinListSetCursor()
2096 *
2097 * Description : Obvious
2098 *
2099 * Arguments : TRUE or FALSE.
2100 *
2101 * Returns : None.
2102 *
2103 *---------------------------------------------------------------------------*/
2104
DEMOWinListSetCursor(DEMOWinListInfo * list,BOOL x)2105 void DEMOWinListSetCursor(DEMOWinListInfo *list, BOOL x)
2106 {
2107
2108 list->cursor_state = x;
2109
2110 } // End DEMOWinListSetCursor()
2111
2112
2113 /*---------------------------------------------------------------------------*
2114 * Name : DEMOWinListScrollList()
2115 *
2116 * Description : Obvious
2117 *
2118 * Arguments : TRUE or FALSE.
2119 *
2120 * Returns : None.
2121 *
2122 *---------------------------------------------------------------------------*/
2123
DEMOWinListScrollList(DEMOWinListInfo * list,u32 dir)2124 s32 DEMOWinListScrollList(DEMOWinListInfo *list, u32 dir)
2125 {
2126
2127 ASSERTMSG(list, "DEMOWinListScrollList(): NULL handle!\n");
2128
2129 switch(dir)
2130 {
2131 case DEMOWIN_SCROLL_UP:
2132 if (list->display_pos)
2133 {
2134 // If it's zero, don't allow scroll
2135 list->display_pos = (u16)((list->display_pos - 1 + list->num_items) % (list->num_items));
2136 }
2137 break;
2138
2139 case DEMOWIN_SCROLL_DOWN:
2140 if (list->display_pos < (list->num_items - list->num_display_items))
2141 {
2142 // If display_pos is at the start of the last 'pageful' of items, then don't allow scroll
2143 list->display_pos = (u16)((list->display_pos + 1) % (list->num_items));
2144 }
2145 break;
2146
2147 case DEMOWIN_SCROLL_HOME:
2148 list->display_pos = 0;
2149 break;
2150
2151 default:
2152 ASSERTMSG(0, "DEMOWinListScrollList(): Invalid dimension!\n");
2153 break;
2154 }
2155
2156 // Fix up current_pos
2157
2158 if (list->curr_pos > (list->display_pos+list->num_display_items-1))
2159 {
2160 list->curr_pos = list->display_pos + list->num_display_items - 1;
2161 }
2162 else if (list->curr_pos < list->display_pos)
2163 {
2164 list->curr_pos = list->display_pos;
2165 }
2166
2167
2168 return(list->display_pos);
2169
2170 } // End DEMOWinListScrollList()
2171
2172
2173 /*---------------------------------------------------------------------------*
2174 * Name : DEMOWinListSetCursor()
2175 *
2176 * Description : Obvious
2177 *
2178 * Arguments : TRUE or FALSE.
2179 *
2180 * Returns : None.
2181 *
2182 *---------------------------------------------------------------------------*/
2183
DEMOWinListMoveCursor(DEMOWinListInfo * list,u32 dir)2184 s32 DEMOWinListMoveCursor(DEMOWinListInfo *list, u32 dir)
2185 {
2186
2187 ASSERTMSG(list, "DEMOWinListScrollList(): NULL handle!\n");
2188
2189 switch(dir)
2190 {
2191 case DEMOWIN_LIST_UP:
2192 list->curr_pos = (list->curr_pos + list->num_items - 1) % list->num_items;
2193 break;
2194
2195 case DEMOWIN_LIST_DOWN:
2196 list->curr_pos = (list->curr_pos + 1) % list->num_items;
2197 break;
2198
2199 default:
2200 ASSERTMSG(0, "DEMOWinListMoveCursor(): Invalid dimension!\n");
2201 break;
2202 }
2203
2204
2205 return(list->curr_pos);
2206
2207 } // End DEMOWinListMoveCursor()
2208
2209