/*
 Main.c
 From Palm Programming: the Developer's Guide
 by Neil Rhodes and Julie McKeehan
 

*/

#include <Pilot.h>    // all the system toolbox headers
#include <SysEvtMgr.h>   // P14. Needed for search for EvtSysEventAvail
#include <FeatureMgr.h>   // P4. Needed to get the ROM version
#include "SendMailRsc.h"  // application resource defines
#include "SendMail.h"
#ifdef __GNUC__
#include "callback.h"
#endif
 
 
 

#define version20 0x02000000 // P4. PalmOS 2.0 version number
 

static Boolean StartApplication(void)
{
 return false;
}
 

static Err RomVersionCompatible (DWord requiredVersion, Word launchFlags)
{
 DWord romVersion;
 

 // See if we're on in minimum required version of the ROM or later.
 // The system records the version number in a feature.  A feature is a
 // piece of information which can be looked up by a creator and feature
 // number.
 FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
 if (romVersion < requiredVersion)
  {
  // If the user launched the app from the launcher, explain
  // why the app shouldn't run.  If the app was contacted for something
  // else, like it was asked to find a string by the system find, then
  // don't bother the user with a warning dialog.  These flags tell how
  // the app was launched to decided if a warning should be displayed.
  if ((launchFlags & (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) ==
   (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp))
   {
   FrmAlert (RomIncompatibleAlert);

   // Pilot 1.0 will continuously relaunch this app unless we switch to
   // another safe one.  The sysFileCDefaultApp is considered "safe".
   if (romVersion < 0x02000000)
    {
    Err err;

    AppLaunchWithCommand(sysFileCDefaultApp, sysAppLaunchCmdNormalLaunch, NULL);
    }
   }

  return (sysErrRomIncompatible);
  }

 return 0;
}

static void StopApplication(void)
{
}
 

// どうもこの関数は使われていないようだ
static void MainViewInit(void)
{
 FormPtr   frm;

 // Get a pointer to the main form.
 frm = FrmGetActiveForm();

 // Draw the form.
 FrmDrawForm(frm);
}

#include <NetMgr.h>
extern Word AppNetRefnum;
Err errno;     // needed for Berkely socket interfaces

static void MyErrorFunc(char *error, char *additional)
{
 FrmCustomAlert(ErrorAlert, error, additional ? additional : "", NULL);
}

static void MyStatusFunc(char *status)
{
 FrmCustomAlert(StatusAlert, status, NULL, NULL);
}

// returns (locked) text in a field object
static char *GetLockedPtr(Word objectID)
{
 FormPtr frm = FrmGetActiveForm();
 FieldPtr fld = FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, objectID));
 Handle h = FldGetTextHandle(fld);

 if (h)
  return MemHandleLock(h);
 else
  return 0;
}

static Boolean MainViewHandleEvent(EventPtr event)
{
#ifdef __GNUC__
 CALLBACK_PROLOGUE
#endif
 Boolean  handled = false;

 switch (event->eType)
  {
    // ボタンを押された後、離したとき発生するイベント
    case ctlSelectEvent:  // A control button was pressed and released.
     // 押されたボタンが送信ボタンのとき
     if (event->data.ctlEnter.controlID == SendmailMainSendButton)
     {
    if (SysLibFind( "Net.lib", &AppNetRefnum) == 0) {
     Word interfaceError;
     Err error;
     // 画面入力文字を取得する
     char *smtpServer = GetLockedPtr(SendmailMainSmtpHostField);
     char *to = GetLockedPtr(SendmailMainToField);
     char *from = GetLockedPtr(SendmailMainFromField);
     char *subject = GetLockedPtr(SendmailMainSubjectField);
     char *body = GetLockedPtr(SendmailMainBodyField);

     if (!smtpServer)  // 文字(Smtp)が入力されていないとき
      MyErrorFunc("Missing smtpServer", NULL);
     else if (!to)     // 文字(To)が入力されていないとき
      MyErrorFunc("Missing to", NULL);
     else if (!from)    // 文字(From)が入力されていないとき
      MyErrorFunc("Missing from", NULL);
     else if (!body)    // 文字(body)が入力されていないとき
      MyErrorFunc("Missing body", NULL);
     else  {
     // ネットワークをオープンする
      error = NetLibOpen(AppNetRefnum, &interfaceError);
      if (interfaceError != 0) {
       MyErrorFunc("NetLibOpen: interface error", NULL);
       NetLibClose(AppNetRefnum, true);
   // ネットワークオープンに成功あるいは既にオープンされているとき
      } else if (error == 0 || error == netErrAlreadyOpen) {
         // sendmail()を呼んでメールを送信する
         if (sendmail(smtpServer, from, to,
          subject, body, MyStatusFunc, MyErrorFunc))
          MyStatusFunc("Completed successfully");
       // ネットワークをクローズする
       NetLibClose(AppNetRefnum, false);
        } else
         MyErrorFunc("netLibOpen error", NULL);
       }
       if (smtpServer)
        MemPtrUnlock(smtpServer);
       if (to)
        MemPtrUnlock(to);
       if (from)
        MemPtrUnlock(from);
       if (subject)
        MemPtrUnlock(subject);
       if (body)
        MemPtrUnlock(body);
     }
   else
    MyErrorFunc("Can't SysLibFind", NULL);
   }
   handled = true;
   break;
  //
  case frmOpenEvent:
   FrmDrawForm(FrmGetActiveForm());
   handled = true;
  }
#ifdef __GNUC__
 CALLBACK_EPILOGUE
#endif
 return(handled);
}
 

static Boolean ApplicationHandleEvent(EventPtr event)
{
 FormPtr frm;
 Int  formId;
 Boolean handled = false;

 if (event->eType == frmLoadEvent)
  {
  // Load the form resource specified in the event then activate the form.
  formId = event->data.frmLoad.formID;
  frm = FrmInitForm(formId);
  FrmSetActiveForm(frm);

  switch (formId)
   {
   case SendmailMainForm:
    FrmSetEventHandler(frm, MainViewHandleEvent);
    break;

   }
  handled = true;
  }

 return handled;
}
 

static void EventLoop(void)
{
 EventType event;
 Word   error;

 do
  {
  EvtGetEvent(&event, evtWaitForever);
  // システムにてイベント処理しないとき
  if (! SysHandleEvent(&event))
   // メニュー処理しないとき
   if (! MenuHandleEvent(0, &event, &error))
    // アプリ(自分)にイベント処理しないとき
    if (! ApplicationHandleEvent(&event))
     // イベントを適切なフォームに送る
     FrmDispatchEvent(&event);
  }
 // アプリストップイベントが来るまでループを続ける
 while (event.eType != appStopEvent);
}
 

DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
{
 Word error;
 // ROMのバージョンが2.0以上であることを確認する
 error = RomVersionCompatible (version20, launchFlags);
 if (error)
  return error;

 if (cmd == sysAppLaunchCmdNormalLaunch)
  {
  if (!StartApplication())
   {
   // 画面を表示する
   FrmGotoForm(SendmailMainForm);
   // イベントループを実行する
   EventLoop();

   StopApplication();
   }
  }
 return 0;
}