1 /*---------------------------------------------------------------------------*
2   Project:  WiiConnect24 API demos
3   File:     MsgViewerUpdate.c
4 
5   Copyright 2006 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: MsgViewerUpdate.c,v $
14   Revision 1.4  2008/05/01 08:50:26  hirose_kazuki
15   Added "Close library" mode.
16 
17   Revision 1.3  2008/04/28 11:20:23  hirose_kazuki
18   Updated framework.
19 
20   Revision 1.2  2007/02/02 02:20:46  torigoe_nobutaka
21   Added handling of messages without subject or body text.
22 
23   Revision 1.1  2006/09/27 08:58:21  torigoe_nobutaka
24   Renamed from update.c
25   Moved from nwc24demo/src.
26 
27   Revision 1.2  2006/09/27 07:31:45  torigoe_nobutaka
28   Improved performance.
29 
30   Revision 1.1  2006/08/28 08:51:50  torigoe_nobutaka
31   Initial check in.
32 
33 
34   $NoKeywords: $
35  *---------------------------------------------------------------------------*/
36 
37 #include <revolution.h>
38 #include <revolution/mem.h>
39 #include <revolution/nwc24.h>
40 #include <revolution/net.h>
41 #include <demo.h>
42 #include <stdio.h>
43 #include <string.h>
44 
45 #include "MsgViewerUpdate.h"
46 #include "MsgViewer.h"
47 
48 /*---------------------------------------------------------------------------*
49    Local functions
50  *---------------------------------------------------------------------------*/
51 static BOOL     GetMsgData          ( MsgData* msgData, NWC24MsgBoxId mBoxId, u32 msgId );
52 static void     ReceiveMessage      ( void );
53 static void     PostMessage         ( void );
54 static void     CreateMessage       ( NWC24MsgBoxId mBoxId );
55 static void     UpdateMenu          ( u32 input );
56 static void     UpdateRecvBox       ( u32 input );
57 static void     UpdateSendBox       ( u32 input );
58 static void     UpdateMsgContent    ( u32 input );
59 static void     UpdateDeleteMsg     ( u32 input );
60 static void     UpdateBeforeRecvMsg ( u32 input );
61 static void     UpdateBeforePostMsg ( u32 input );
62 static void     UpdateDoneRecvMsg   ( u32 input );
63 static void     UpdateDonePostMsg   ( u32 input );
64 static void     UpdateLibClosed     ( u32 input );
65 static void     UpdateWaitOpen      ( u32 input );
66 static void     UpdateErrorMsg      ( u32 input );
67 
68 /*---------------------------------------------------------------------------*
69   Name        : Render
70   Description : Updates scenes not being rendered.
71   Arguments   : input   - Input data from controller buttons (KPAD & PAD)
72   Returns     : None.
73  *---------------------------------------------------------------------------*/
Update(u32 input)74 void Update( u32 input )
75 {
76     switch ( g_state )
77     {
78         case MB_STATE_MENU:            UpdateMenu( input );          break;
79         case MB_STATE_RECV_BOX:        UpdateRecvBox( input );       break;
80         case MB_STATE_SEND_BOX:        UpdateSendBox( input );       break;
81         case MB_STATE_MSG_CONTENT:     UpdateMsgContent( input );    break;
82         case MB_STATE_DELETE_MSG:      UpdateDeleteMsg( input );     break;
83         case MB_STATE_BEFORE_RECV_MSG: UpdateBeforeRecvMsg( input ); break;
84         case MB_STATE_BEFORE_POST_MSG: UpdateBeforePostMsg( input ); break;
85         case MB_STATE_DONE_RECV_MSG:   UpdateDoneRecvMsg( input );   break;
86         case MB_STATE_DONE_POST_MSG:   UpdateDonePostMsg( input );   break;
87         case MB_STATE_LIB_CLOSED:      UpdateLibClosed( input );     break;
88         case MB_STATE_WAIT_OPEN:       UpdateWaitOpen( input );      break;
89         case MB_STATE_ERROR_CONT:      UpdateErrorMsg( input );      break;
90         case MB_STATE_ERROR_STOP:      break;
91     }
92     return;
93 }
94 
95 /*---------------------------------------------------------------------------*
96   Name        : GetMsgData
97   Description : Gets data from the specified message.
98   Arguments   : msgData - Pointer to the MsgData-type structure that stores the message data.
99 
100                 mBoxId  - Message box type.
101                 msgId   - Message ID.
102   Returns     : BOOL - TRUE if successful.
103  *---------------------------------------------------------------------------*/
104 #define THROW_ERROR(func, err) \
105 {                                               \
106     if ( err != NWC24_OK )                      \
107     {                                           \
108         OSReport("%s : error %d\n", func, err); \
109         goto errorHandling;                     \
110     }                                           \
111 }
112 
GetMsgData(MsgData * msgData,NWC24MsgBoxId mBoxId,u32 msgId)113 static BOOL GetMsgData( MsgData* msgData, NWC24MsgBoxId mBoxId, u32 msgId )
114 {
115     NWC24Err        err;
116     NWC24MsgObj     msgObj;
117     u32             subjectSize;
118     char*           subject;
119     u32             textSize;
120     char*           text;
121     NWC24Charset    charset;
122     NWC24Encoding   encoding;
123     MsgBoxType      mbType  = (mBoxId == NWC24_RECV_BOX) ? MB_TYPE_RECV : MB_TYPE_SEND;
124 
125     err = NWC24GetMsgObj( &msgObj, mBoxId, msgId );
126     if ( err == NWC24_ERR_HIDDEN )
127     {
128         return FALSE;
129     }
130     THROW_ERROR( "NWC24InitMsgObj()", err );
131 
132     /* Message type */
133     err = NWC24GetMsgType( &msgObj, &msgData->type );
134     THROW_ERROR( "NWC24GetMsgType()", err );
135 
136     /* Number of recipients */
137     err = NWC24GetMsgNumTo( &msgObj, &msgData->numTo );
138     THROW_ERROR( "NWC24GetMsgNumTo()", err );
139 
140     if ( MAX_NUM_TO < msgData->numTo )
141     {
142         msgData->numTo = MAX_NUM_TO;
143     }
144 
145     /* Subject Line */
146     err = NWC24GetMsgSubjectSize( &msgObj, &subjectSize );
147     THROW_ERROR( "NWC24GetMsgSubjectSize()", err );
148 
149     if ( subjectSize < 1 )
150     {
151         subjectSize = 1;
152     }
153     subject = MEMAllocFromAllocator( &DemoAllocator1, subjectSize );
154 
155     err = NWC24ReadMsgSubject( &msgObj, subject, subjectSize );
156     if ( err != NWC24_OK )
157     {
158         MEMFreeToAllocator( &DemoAllocator1, subject );
159         THROW_ERROR( "NWC24ReadMsgSubject()", err );
160     }
161 
162     if ( MAX_SUBJECT_SIZE < subjectSize )
163     {
164         subjectSize = MAX_SUBJECT_SIZE;
165     }
166     (void)memcpy( msgData->subject, subject, subjectSize );
167     msgData->subject[subjectSize] = '\0';
168 
169     MEMFreeToAllocator( &DemoAllocator1, subject );
170 
171     /* Text */
172     err = NWC24GetMsgTextSize( &msgObj, &textSize );
173     THROW_ERROR( "NWC24GetMsgTextSize()", err );
174 
175     if ( textSize < 1 )
176     {
177         textSize = 1;
178     }
179 
180     text = MEMAllocFromAllocator( &DemoAllocator1, textSize );
181 
182     err = NWC24ReadMsgText( &msgObj, text, textSize, &charset, &encoding );
183     if ( err != NWC24_OK )
184     {
185         MEMFreeToAllocator( &DemoAllocator1, text );
186         THROW_ERROR( "NWC24ReadMsgText()", err );
187     }
188 
189     if ( MAX_TEXT_SIZE < textSize )
190     {
191         textSize = MAX_TEXT_SIZE;
192     }
193 
194     (void)memcpy( msgData->text, text, textSize );
195     msgData->text[textSize] = '\0';
196 
197     MEMFreeToAllocator( &DemoAllocator1, text );
198 
199     /* Sender/recipient */
200     if ( msgData->type != NWC24_MSGTYPE_PUBLIC )
201     {
202         NWC24UserId     temp;
203         u32             i;
204 
205         err = NWC24GetMsgFromId( &msgObj, &temp );
206         THROW_ERROR( "NWC24GetMsgFromId()", err );
207 
208         (void)sprintf( msgData->from, "%016llu", temp );
209 
210         for ( i = 0; i < msgData->numTo; ++i )
211         {
212             err = NWC24ReadMsgToId( &msgObj, i, &temp );
213             THROW_ERROR( "NWC24ReadMsgToId()", err );
214 
215             (void)sprintf( msgData->to[i], "%016llu", temp );
216         }
217     }
218     else
219     {
220         u32         i;
221 
222         err = NWC24ReadMsgFromAddr( &msgObj, msgData->from, MAX_ADDR_SIZE );
223         THROW_ERROR( "NWC24ReadMsgFromAddr()", err );
224 
225         for ( i = 0; i < msgData->numTo; ++i )
226         {
227             err = NWC24ReadMsgToAddr( &msgObj, i, msgData->to[i], MAX_ADDR_SIZE );
228             THROW_ERROR( "NWC24ReadMsgToAddr()", err );
229         }
230     }
231 
232     return TRUE;
233 
234 errorHandling:
235     msgData->subject[0] = '\0';
236     msgData->text[0] = '\0';
237     msgData->from[0] = '\0';
238     msgData->numTo = 0;
239     return TRUE;
240 }
241 
242 #undef THROW_ERROR
243 
244 /*---------------------------------------------------------------------------*
245   Name        : ReceiveMessage
246   Description : Creates a Wii message and stores it in the Inbox.
247   Arguments   : None.
248   Returns     : None.
249  *---------------------------------------------------------------------------*/
ReceiveMessage(void)250 static void ReceiveMessage( void )
251 {
252     CreateMessage( NWC24_RECV_BOX );
253     ReleaseMsgIdList( NWC24_RECV_BOX );
254     GetMsgIdList( NWC24_RECV_BOX );
255     ReleaseListedSubjects( NWC24_RECV_BOX );
256     GetListedSubjects( NWC24_RECV_BOX );
257     return;
258 }
259 
260 /*---------------------------------------------------------------------------*
261   Name        : PostMessage
262   Description : Creates a Wii message and stores it in the Outbox.
263   Arguments   : None.
264   Returns     : None.
265  *---------------------------------------------------------------------------*/
PostMessage(void)266 static void PostMessage( void )
267 {
268     NWC24Err        err;
269 
270     err = NWC24Check(NWC24_USE_MESSAGES);
271     if ( err != NWC24_OK )
272     {
273         /* Cannot create a message to send */
274         g_errorCode = NWC24GetErrorCode();
275         g_state     = MB_STATE_ERROR_CONT;
276         return;
277     }
278 
279     CreateMessage( NWC24_SEND_BOX );
280     ReleaseMsgIdList( NWC24_SEND_BOX );
281     GetMsgIdList( NWC24_SEND_BOX );
282     ReleaseListedSubjects( NWC24_SEND_BOX );
283     GetListedSubjects( NWC24_SEND_BOX );
284     return;
285 }
286 
287 /*---------------------------------------------------------------------------*
288   Name        : CreateMessage
289   Description : Creates a Wii message and stores it in the specified message box.
290   Arguments   : None.
291   Returns     : None.
292  *---------------------------------------------------------------------------*/
CreateMessage(NWC24MsgBoxId mBoxId)293 static void CreateMessage( NWC24MsgBoxId mBoxId )
294 {
295     NWC24Err            err;
296     NWC24MsgObj         msgObj;
297 
298     const NWC24UserId   UID_TO          = 9999999999999999ULL;
299     const char*         STR_SUBJECT     = "TEST MESSAGE";
300     const char*         STR_BODY_TEXT   =
301     "Hello Wii Connect 24 World!!\x0d\x0a"
302     "This is a test mail.\x0d\x0a"
303     "Thank you.\x0d\x0a";
304 
305     err = NWC24InitMsgObj( &msgObj, NWC24_MSGTYPE_WII );
306     CheckError( "NWC24InitMsgObj()", err );
307 
308     if ( mBoxId == NWC24_SEND_BOX )
309     {
310         err = NWC24SetMsgToId( &msgObj, UID_TO );
311     }
312     else
313     {
314         // Set the local hardware as the recipient if the storage destination is the Inbox.
315         NWC24UserId     uidMy;
316         err = NWC24GetMyUserId( &uidMy );
317         CheckError( "NWC24GetMyUserId()", err );
318         err = NWC24SetMsgToId( &msgObj, uidMy );
319     }
320     CheckError( "NWC24SetMsgToId()", err );
321 
322     err = NWC24SetMsgSubject( &msgObj, STR_SUBJECT, (u32)strlen( STR_SUBJECT ) );
323     CheckError( "NWC24SetMsgSubject()", err );
324 
325     err = NWC24SetMsgText( &msgObj, (char*)STR_BODY_TEXT, (u32)strlen( STR_BODY_TEXT ),
326                            NWC24_US_ASCII, NWC24_ENC_7BIT );
327     CheckError( "NWC24SetMsgText()", err );
328 
329     err = NWC24CommitMsg( &msgObj );
330     CheckError( "NWC24CommitMsg()", err );
331 
332     return;
333 }
334 
335 /*---------------------------------------------------------------------------*
336   Name        : UpdateMenu
337   Description : This function is called each frame to perform updating other than rendering during menu selection.
338   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
339   Returns     : None.
340  *---------------------------------------------------------------------------*/
UpdateMenu(u32 input)341 static void UpdateMenu ( u32 input )
342 {
343     /* (A) button */
344     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
345     {
346         switch ( g_selectedMenu )
347         {
348             case MB_MENU_RECV_BOX:
349             {
350                 if ( g_numMsgs[MB_TYPE_RECV] != 0 )
351                 {
352                     g_state = MB_STATE_RECV_BOX;
353                 }
354                 break;
355             }
356 
357             case MB_MENU_SEND_BOX:
358             {
359                 if ( g_numMsgs[MB_TYPE_SEND] != 0 )
360                 {
361                     g_state = MB_STATE_SEND_BOX;
362                 }
363                 break;
364             }
365 
366             case MB_MENU_RECV_MSG:
367             {
368                 g_state = MB_STATE_BEFORE_RECV_MSG;
369                 break;
370             }
371 
372             case MB_MENU_POST_MSG:
373             {
374                 g_state = MB_STATE_BEFORE_POST_MSG;
375                 break;
376             }
377         }
378     }
379 
380     /* (up) button */
381     if ( input & (KPAD_BUTTON_UP|(PAD_BUTTON_UP<<16)) )
382     {
383         if ( 0 < g_selectedMenu )
384         {
385             --g_selectedMenu;
386             g_lineTopOfBodyText = 0;
387         }
388     }
389 
390     /* (down) button */
391     if ( input & (KPAD_BUTTON_DOWN|(PAD_BUTTON_DOWN<<16)) )
392     {
393         if (g_selectedMenu < NUM_MSG_BOX_MENUS - 1)
394         {
395             ++g_selectedMenu;
396             g_lineTopOfBodyText = 0;
397         }
398     }
399 
400     /* (B) button */
401     if ( input & (KPAD_BUTTON_B|(PAD_BUTTON_B<<16)) )
402     {
403         /* Close the library */
404         (void)CloseLib();
405     }
406 
407     return;
408 }
409 
410 /*---------------------------------------------------------------------------*
411   Name        : UpdateRecvBox
412   Description : This function is called each frame to perform updating other than rendering during inbox selection.
413   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
414   Returns     : None.
415  *---------------------------------------------------------------------------*/
UpdateRecvBox(u32 input)416 static void UpdateRecvBox( u32 input )
417 {
418 
419     /* (A) button */
420     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
421     {
422         if ( GetMsgData( &g_msgData, NWC24_RECV_BOX,
423                          g_idListBuf[MB_TYPE_RECV][g_idxSelectedId[MB_TYPE_RECV]] ) )
424         {
425             g_state = MB_STATE_MSG_CONTENT;
426         }
427         else
428         {
429             g_state = MB_STATE_RECV_BOX;
430         }
431     }
432 
433     /* (B) button */
434     if ( input & (KPAD_BUTTON_B|(PAD_BUTTON_B<<16)) )
435     {
436         g_state = MB_STATE_MENU;
437     }
438 
439     /* (up) button */
440     if ( input & (KPAD_BUTTON_UP|(PAD_BUTTON_UP<<16)) )
441     {
442         if ( 0 < g_idxSelectedId[MB_TYPE_RECV] )
443         {
444             if ( g_idxSelectedId[MB_TYPE_RECV] == g_idxIdTopOfList[MB_TYPE_RECV] )
445             {
446                 u32         msgId;
447                 char*       subjectBuf  = NULL;
448 
449                 --g_idxIdTopOfList[MB_TYPE_RECV];
450                 g_idxSubjectBufStart[MB_TYPE_RECV]
451                     = (u32)((g_idxSubjectBufStart[MB_TYPE_RECV] + LIST_BOX_ROWS - 1) % LIST_BOX_ROWS);
452 
453                 msgId = g_idListBuf[MB_TYPE_RECV][g_idxIdTopOfList[MB_TYPE_RECV]];
454                 subjectBuf = g_subjectBuf[MB_TYPE_RECV][g_idxSubjectBufStart[MB_TYPE_RECV]];
455 
456                 if ( subjectBuf )
457                 {
458                     MEMFreeToAllocator( &DemoAllocator1, subjectBuf );
459                     subjectBuf = NULL;
460                 }
461 
462                 subjectBuf = MEMAllocFromAllocator( &DemoAllocator1, LEN_SUBJECT_DISP );
463                 (void)NETMemSet( subjectBuf, 0, LEN_SUBJECT_DISP );
464                 (void)ReadSubject( subjectBuf, LEN_SUBJECT_DISP-1, NWC24_RECV_BOX, msgId );
465 
466                 g_subjectBuf[MB_TYPE_RECV][g_idxSubjectBufStart[MB_TYPE_RECV]] = subjectBuf;
467             }
468             --g_idxSelectedId[MB_TYPE_RECV];
469             g_lineTopOfBodyText = 0;
470         }
471     }
472 
473     /* (down) button */
474     if ( input & (KPAD_BUTTON_DOWN|(PAD_BUTTON_DOWN<<16)) )
475     {
476         if ( g_idxSelectedId[MB_TYPE_RECV] < g_numMsgs[MB_TYPE_RECV] - 1 )
477         {
478             u32     idxIdBottomOfList   = g_idxIdTopOfList[MB_TYPE_RECV] + LIST_BOX_ROWS - 1;
479 
480             if ( g_idxSelectedId[MB_TYPE_RECV] == idxIdBottomOfList )
481             {
482                 u32         msgId;
483                 char*       subjectBuf = NULL;
484                 u32         idxSubjectBufEnd;
485 
486                 ++g_idxIdTopOfList[MB_TYPE_RECV];
487                 ++idxIdBottomOfList;
488                 idxSubjectBufEnd = g_idxSubjectBufStart[MB_TYPE_RECV];
489                 g_idxSubjectBufStart[MB_TYPE_RECV]
490                     = (u32)((g_idxSubjectBufStart[MB_TYPE_RECV] + 1) % LIST_BOX_ROWS);
491 
492                 msgId = g_idListBuf[MB_TYPE_RECV][idxIdBottomOfList];
493                 subjectBuf = g_subjectBuf[MB_TYPE_RECV][idxSubjectBufEnd];
494 
495                 if ( subjectBuf )
496                 {
497                     MEMFreeToAllocator( &DemoAllocator1, subjectBuf );
498                     subjectBuf = NULL;
499                 }
500 
501                 subjectBuf = MEMAllocFromAllocator( &DemoAllocator1, LEN_SUBJECT_DISP );
502                 (void)NETMemSet( subjectBuf, 0, LEN_SUBJECT_DISP );
503                 (void)ReadSubject( subjectBuf, LEN_SUBJECT_DISP-1, NWC24_RECV_BOX, msgId );
504 
505                 g_subjectBuf[MB_TYPE_RECV][idxSubjectBufEnd] = subjectBuf;
506             }
507             ++g_idxSelectedId[MB_TYPE_RECV];
508             g_lineTopOfBodyText = 0;
509         }
510     }
511 
512     return;
513 }
514 
515 /*---------------------------------------------------------------------------*
516   Name        : UpdateSendBox
517   Description : This function is called each frame to perform updating other than rendering during outbox selection.
518   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
519   Returns     : None.
520  *---------------------------------------------------------------------------*/
UpdateSendBox(u32 input)521 static void UpdateSendBox( u32 input )
522 {
523     /* (A) button */
524     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
525     {
526         if ( GetMsgData( &g_msgData, NWC24_SEND_BOX,
527                          g_idListBuf[MB_TYPE_SEND][g_idxSelectedId[MB_TYPE_SEND]] ) )
528         {
529             g_state = MB_STATE_MSG_CONTENT;
530         }
531         else
532         {
533             g_state = MB_STATE_SEND_BOX;
534         }
535     }
536 
537     /* (B) button */
538     if ( input & (KPAD_BUTTON_B|(PAD_BUTTON_B<<16)) )
539     {
540         g_state = MB_STATE_MENU;
541     }
542 
543     /* (up) button */
544     if ( input & (KPAD_BUTTON_UP|(PAD_BUTTON_UP<<16)) )
545     {
546         if ( 0 < g_idxSelectedId[MB_TYPE_SEND] )
547         {
548             if ( g_idxSelectedId[MB_TYPE_SEND] == g_idxIdTopOfList[MB_TYPE_SEND] )
549             {
550                 u32         msgId;
551                 char*       subjectBuf  = NULL;
552 
553                 --g_idxIdTopOfList[MB_TYPE_SEND];
554                 g_idxSubjectBufStart[MB_TYPE_SEND]
555                     = (u32)((g_idxSubjectBufStart[MB_TYPE_SEND] + LIST_BOX_ROWS - 1) % LIST_BOX_ROWS);
556 
557                 msgId = g_idListBuf[MB_TYPE_SEND][g_idxIdTopOfList[MB_TYPE_SEND]];
558                 subjectBuf = g_subjectBuf[MB_TYPE_SEND][g_idxSubjectBufStart[MB_TYPE_SEND]];
559 
560                 if ( subjectBuf )
561                 {
562                     MEMFreeToAllocator( &DemoAllocator1, subjectBuf );
563                     subjectBuf = NULL;
564                 }
565 
566                 subjectBuf = MEMAllocFromAllocator( &DemoAllocator1, LEN_SUBJECT_DISP );
567                 (void)NETMemSet( subjectBuf, 0, LEN_SUBJECT_DISP );
568                 (void)ReadSubject( subjectBuf, LEN_SUBJECT_DISP-1, NWC24_SEND_BOX, msgId );
569 
570                 g_subjectBuf[MB_TYPE_SEND][g_idxSubjectBufStart[MB_TYPE_SEND]] = subjectBuf;
571             }
572             --g_idxSelectedId[MB_TYPE_SEND];
573             g_lineTopOfBodyText = 0;
574         }
575     }
576 
577     /* (down) button */
578     if ( input & (KPAD_BUTTON_DOWN|(PAD_BUTTON_DOWN<<16)) )
579     {
580         if ( g_idxSelectedId[MB_TYPE_SEND] < g_numMsgs[MB_TYPE_SEND] - 1 )
581         {
582             u32     idxIdBottomOfList   = g_idxIdTopOfList[MB_TYPE_SEND] + LIST_BOX_ROWS - 1;
583 
584             if ( g_idxSelectedId[MB_TYPE_SEND] == idxIdBottomOfList )
585             {
586                 u32         msgId;
587                 char*       subjectBuf          = NULL;
588                 u32         idxSubjectBufEnd;
589 
590                 ++g_idxIdTopOfList[MB_TYPE_SEND];
591                 ++idxIdBottomOfList;
592                 idxSubjectBufEnd = g_idxSubjectBufStart[MB_TYPE_SEND];
593                 g_idxSubjectBufStart[MB_TYPE_SEND]
594                     = (u32)((g_idxSubjectBufStart[MB_TYPE_SEND] + 1) % LIST_BOX_ROWS);
595 
596                 msgId = g_idListBuf[MB_TYPE_SEND][idxIdBottomOfList];
597                 subjectBuf = g_subjectBuf[MB_TYPE_SEND][idxSubjectBufEnd];
598 
599                 if ( subjectBuf )
600                 {
601                     MEMFreeToAllocator( &DemoAllocator1, subjectBuf );
602                     subjectBuf = NULL;
603                 }
604 
605                 subjectBuf = MEMAllocFromAllocator( &DemoAllocator1, LEN_SUBJECT_DISP );
606                 (void)NETMemSet( subjectBuf, 0, LEN_SUBJECT_DISP );
607                 (void)ReadSubject( subjectBuf, LEN_SUBJECT_DISP-1, NWC24_SEND_BOX, msgId );
608 
609                 g_subjectBuf[MB_TYPE_SEND][idxSubjectBufEnd] = subjectBuf;
610             }
611             ++g_idxSelectedId[MB_TYPE_SEND];
612             g_lineTopOfBodyText = 0;
613         }
614     }
615 
616     return;
617 }
618 
619 /*---------------------------------------------------------------------------*
620   Name        : UpdateMsgContent
621   Description : This function is called each frame to perform updating other than rendering during message selection.
622   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
623   Returns     : None.
624  *---------------------------------------------------------------------------*/
UpdateMsgContent(u32 input)625 static void UpdateMsgContent( u32 input )
626 {
627     /* (A) button */
628     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
629     {
630         g_state = MB_STATE_DELETE_MSG;
631     }
632 
633     /* (B) button */
634     if ( input & (KPAD_BUTTON_B|(PAD_BUTTON_B<<16)) )
635     {
636         g_state = (g_selectedMenu == MB_MENU_RECV_BOX) ? MB_STATE_RECV_BOX : MB_STATE_SEND_BOX;
637     }
638 
639     /* (up) button */
640     if ( input & (KPAD_BUTTON_UP|(PAD_BUTTON_UP<<16)) )
641     {
642         if ( 0 < g_lineTopOfBodyText )
643         {
644             --g_lineTopOfBodyText;
645         }
646     }
647 
648     /* (down) button */
649     if ( input & (KPAD_BUTTON_DOWN|(PAD_BUTTON_DOWN<<16)) )
650     {
651         if ( (s32)g_lineTopOfBodyText < (s32)(g_numLinesBodyText - TEXT_BOX_ROWS) )
652         {
653             ++g_lineTopOfBodyText;
654         }
655     }
656 
657     return;
658 }
659 
660 /*---------------------------------------------------------------------------*
661   Name        : UpdateDeleteMsg
662   Description : This function is called each frame to perform updating other than rendering when delete message is selected.
663   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
664   Returns     : None.
665  *---------------------------------------------------------------------------*/
UpdateDeleteMsg(u32 input)666 static void UpdateDeleteMsg( u32 input )
667 {
668     /* (A) button */
669     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
670     {
671         NWC24Err        err;
672         NWC24MsgBoxId   mBoxId  = (g_selectedMenu == MB_MENU_RECV_BOX) ? NWC24_RECV_BOX : NWC24_SEND_BOX;
673         MsgBoxType      mbType  = (g_selectedMenu == MB_MENU_RECV_BOX) ? MB_TYPE_RECV : MB_TYPE_SEND;
674 
675         err = NWC24DeleteMsg( mBoxId, g_idListBuf[mbType][ g_idxSelectedId[mbType] ] );
676         if ( err == NWC24_ERR_PROTECTED )
677         {
678             OSReport("Can't delete this message. (protected)\n");
679             g_state = MB_STATE_MSG_CONTENT;
680         }
681         else
682         {
683             CheckError( "NWC24DeleteMsg()", err );
684         }
685         ReleaseMsgIdList( mBoxId );
686         GetMsgIdList( mBoxId );
687 
688         if ( g_numMsgs[mbType] == 0 )
689         {
690             g_idxSelectedId[mbType] = 0;
691             g_state = MB_STATE_MENU;
692         }
693         else
694         {
695             if ( g_numMsgs[mbType] <= g_idxSelectedId[mbType] )
696             {
697                 g_idxSelectedId[mbType] = g_numMsgs[mbType] - 1;
698             }
699 
700             if ( g_idxIdTopOfList[mbType] != 0
701                  && g_numMsgs[mbType] - g_idxIdTopOfList[mbType] < LIST_BOX_ROWS )
702             {
703                 g_idxIdTopOfList[mbType] = g_numMsgs[mbType] - LIST_BOX_ROWS;
704             }
705 
706             g_state = (g_selectedMenu == MB_MENU_RECV_BOX) ? MB_STATE_RECV_BOX : MB_STATE_SEND_BOX;
707         }
708 
709         ReleaseListedSubjects( mBoxId );
710         GetListedSubjects( mBoxId );
711     }
712 
713     /* (B) button */
714     if ( input & (KPAD_BUTTON_B|(PAD_BUTTON_B<<16)) )
715     {
716         g_state = MB_STATE_MSG_CONTENT;
717     }
718 
719     return;
720 }
721 
722 /*---------------------------------------------------------------------------*
723   Name        : UpdateBeforeRecvMsg
724   Description : This function is called each frame to perform updating other than rendering when receive message is selected.
725   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
726   Returns     : None.
727  *---------------------------------------------------------------------------*/
UpdateBeforeRecvMsg(u32 input)728 static void UpdateBeforeRecvMsg( u32 input )
729 {
730     /* (A) button */
731     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
732     {
733         ReceiveMessage();
734         g_state = MB_STATE_DONE_RECV_MSG;
735     }
736 
737     /* (B) button */
738     if ( input & (KPAD_BUTTON_B|(PAD_BUTTON_B<<16)) )
739     {
740         g_state = MB_STATE_MENU;
741     }
742 
743     return;
744 }
745 
746 /*---------------------------------------------------------------------------*
747   Name        : UpdateBeforePostMsg
748   Description : This function is called each frame to perform updating other than rendering when send message is selected.
749   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
750   Returns     : None.
751  *---------------------------------------------------------------------------*/
UpdateBeforePostMsg(u32 input)752 static void UpdateBeforePostMsg( u32 input )
753 {
754     /* (A) button */
755     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
756     {
757         PostMessage();
758         g_state = MB_STATE_DONE_POST_MSG;
759     }
760 
761     /* (B) button */
762     if ( input & (KPAD_BUTTON_B|(PAD_BUTTON_B<<16)) )
763     {
764         g_state = MB_STATE_MENU;
765     }
766 
767     return;
768 }
769 
770 /*---------------------------------------------------------------------------*
771   Name        : UpdateDoneRecvMsg
772   Description : This function is called each frame to perform updating other than rendering after the message is received.
773   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
774   Returns     : None.
775  *---------------------------------------------------------------------------*/
UpdateDoneRecvMsg(u32 input)776 static void UpdateDoneRecvMsg( u32 input )
777 {
778     /* (A) button */
779     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
780     {
781         g_state = MB_STATE_MENU;
782     }
783 
784     return;
785 }
786 
787 /*---------------------------------------------------------------------------*
788   Name        : UpdateDonePostMsg
789   Description : This function is called each frame to perform updating other than rendering after the message is sent.
790   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
791   Returns     : None.
792  *---------------------------------------------------------------------------*/
UpdateDonePostMsg(u32 input)793 static void UpdateDonePostMsg( u32 input )
794 {
795     /* (A) button */
796     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
797     {
798         g_state = MB_STATE_MENU;
799     }
800 
801     return;
802 }
803 
804 /*---------------------------------------------------------------------------*
805   Name        : UpdateLibClosed
806   Description : This function is called each frame while closing the library to perform non-rendering updates.
807   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
808   Returns     : None.
809  *---------------------------------------------------------------------------*/
UpdateLibClosed(u32 input)810 static void UpdateLibClosed( u32 input )
811 {
812     /* (A) button */
813     if ( input & (KPAD_BUTTON_A|(PAD_BUTTON_A<<16)) )
814     {
815         g_state = MB_STATE_WAIT_OPEN;
816     }
817 
818     return;
819 }
820 
821 /*---------------------------------------------------------------------------*
822   Name        : UpdateWaitOpen
823   Description : This function is called each frame while waiting for the open state to perform non-rendering updates.
824   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
825   Returns     : None.
826  *---------------------------------------------------------------------------*/
UpdateWaitOpen(u32 input)827 static void UpdateWaitOpen( u32 input )
828 {
829     static u32 waitCount = 0;
830 
831     (void)input;
832 
833     if ( waitCount == 0 )
834     {
835         if ( OpenLib() )
836         {
837             /* Get the state after being reopened */
838             ReleaseMsgIdList( NWC24_RECV_BOX );
839             ReleaseMsgIdList( NWC24_SEND_BOX );
840             ReleaseListedSubjects( NWC24_RECV_BOX );
841             ReleaseListedSubjects( NWC24_SEND_BOX );
842             GetMsgIdList( NWC24_RECV_BOX );
843             GetMsgIdList( NWC24_SEND_BOX );
844             GetListedSubjects( NWC24_RECV_BOX );
845             GetListedSubjects( NWC24_SEND_BOX );
846             g_state = MB_STATE_MENU;
847 
848             return;
849         }
850     }
851 
852     /* processing to retry once per second */
853     ++waitCount;
854     waitCount %= 60;
855 
856     /* It is recommended to wait for approximately 10 to 20 seconds and then briefly display a message prompting the user to try again later.
857         */
858 
859     return;
860 }
861 
862 /*---------------------------------------------------------------------------*
863   Name        : UpdateErrorMsg
864   Description : This function is called each frame while displaying an error to perform non-rendering updates.
865   Arguments   : input   - Input data from controller buttons (KPAD and PAD)
866   Returns     : None.
867  *---------------------------------------------------------------------------*/
UpdateErrorMsg(u32 input)868 static void UpdateErrorMsg( u32 input )
869 {
870     /* (B) button */
871     if ( input & (KPAD_BUTTON_B|(PAD_BUTTON_B<<16)) )
872     {
873         g_state = MB_STATE_MENU;
874     }
875 
876     return;
877 }
878 
879 /*======== End of MsgViewerUpdate.c ========*/
880