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