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