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