/* ファイル名  Tex2Hex.c */

/* ヘッダファイルの取り込み */
#include <Pilot.h>
#include "Tex2Hex.h"

// -------------------------------------------------------------
// Constants
// -------------------------------------------------------------
/* アプリケーションを識別するためのID */
#define tex2HexDBCreator    'TxHx'   // 0x74586858 in hexadecimal

/* データベースの種別 */
#define tex2HexDBType  'Data'   // 0x64415441 in hexadecimal

// -------------------------------------------------------------
// Prototypes   プロトタイプ宣言
// -------------------------------------------------------------
static int  StartApplication (void);
static Boolean OpenDatabase (void);
static void  EventLoop (void);
static void  StopApplication(void);
static Boolean Tex2Hex (EventPtr event);
static void  Convert (void);
static void  ChangeBitmap (void);
 

// -------------------------------------------------------------
// Globals  グローバル変数宣言
// -------------------------------------------------------------
FieldPtr  FieldTextP;
FieldPtr  FieldHexP;
DmOpenRef  Tex2HexDB;
char   Tex2HexDBName[] = "Tex2HexDB";
char   Hex[60];
int    WhichBitmap;
 

// ==================================================================
// Pilot Main  メインルーチン
// =================================================================
DWord
PilotMain (Word cmd, Ptr cmdPBP, Word launchFlags)
{
  int error;

  /* 起動コードがノーマル起動であれば実行 */
  if (cmd == sysAppLaunchCmdNormalLaunch)
 {

   /* 起動時の処理                                     */
   /*   (データベースオープンと初期画面表示)  */
   error = StartApplication(); // Application start code
   if (error) return error;

   /* イベントループ処理                  */
   EventLoop();     // Event loop

   /* 終了時の処理                         */
   /*   (データベース終了処理など)    */
   StopApplication ();   // Application stop code
 }
  return 0;
}

// ==================================================================
// Start Application  起動時の処理
// =================================================================
static int
StartApplication(void)
{
  int error;

  /* データベースオープン. */
  error = OpenDatabase();
  if (error) return error;

  /* 初期画面の表示 */
  FrmGotoForm (resFormIDTex2Hex);
  return 0;
}

// ==================================================================
// Open our database
// =================================================================
static Boolean
OpenDatabase(void)
{
  UInt          index = 0;
  VoidHand      recH;
  Ptr           recP;
  char          nullstring = 0;

  Tex2HexDB = DmOpenDatabaseByTypeCreator (tex2HexDBType, tex2HexDBCreator,
    dmModeReadWrite);
  if (!Tex2HexDB)
 {
   if (DmCreateDatabase (0, Tex2HexDBName, tex2HexDBCreator,
     tex2HexDBType, false))
  return 1;

   Tex2HexDB = DmOpenDatabaseByTypeCreator (tex2HexDBType,
    tex2HexDBCreator, dmModeReadWrite);

   recH = DmNewRecord (Tex2HexDB, &index, 1);
   recP = MemHandleLock(recH);

   DmWrite (recP, 0, &nullstring, 1);
   MemPtrUnlock (recP);
   DmReleaseRecord (Tex2HexDB, index, true);
 }
  return 0;
}

// ==================================================================
// Event Loop  イベントループ処理
// =================================================================
static void
EventLoop(void)
{
  short  err;
  int  formID;
  FormPtr formP;
  EventType event;

  do
 {
   /* イベントを取得する */
   EvtGetEvent (&event, sysTicksPerSecond/2);

   /* システムイベントならイベント取得を継続 */
   if (SysHandleEvent (&event)) continue;
   /* メニューイベントならイベント取得を継続 */
   if (MenuHandleEvent ((void *)0, &event, &err)) continue;

   /* ロードイベントなら処理を実施 */
   if (event.eType == frmLoadEvent)
  {
    /* イベント変数から画面の識別子を取得 */
    formID = event.data.frmLoad.formID;
    formP = FrmInitForm (formID);
    FrmSetActiveForm (formP);

    switch (formID)
   {
   case resFormIDTex2Hex:
     FrmSetEventHandler (formP, (FormEventHandlerPtr) Tex2Hex);
     break;
   }
  }

   FrmDispatchEvent(&event);

  } while(event.eType != appStopEvent);
}
 

// ==================================================================
// Stop Application   終了時の処理
// =================================================================
static void
StopApplication (void)
{
  FldSetTextHandle (FieldTextP, NULL);
  DmReleaseRecord (Tex2HexDB, 0, true);
  DmCloseDatabase (Tex2HexDB);
}

// ==================================================================
// Form Event Handler
// =================================================================
static Boolean
Tex2Hex (EventPtr event)
{
  FormPtr   formP;
  int       handled = 0;

  switch (event->eType)
 {
 case frmOpenEvent:
   formP = FrmGetActiveForm();

   FieldTextP = FrmGetObjectPtr (formP,
    FrmGetObjectIndex (formP, resFieldIDText));
   FldSetTextHandle (FieldTextP, (Handle) DmQueryRecord (Tex2HexDB, 0));
   FieldHexP = FrmGetObjectPtr (formP,
    FrmGetObjectIndex (formP, resFieldIDHex));
 
   FrmDrawForm(formP);
   handled = 1;
   break;
 
 case ctlSelectEvent:  // A control button was pressed and released.
   if (event->data.ctlEnter.controlID == resButtonIDConvert)
  {
    Convert();
    handled = 1;
  }
   break;

 case menuEvent:
   switch (event->data.menu.itemID)
  {
  case resMenuItemConvert:
    Convert();
    break;
  case resMenuItemAbout:
    FrmAlert(resAlertIDAbout);
    break;
  case resMenuItemCopy:
    FldCopy (FieldTextP);   // user has to select (highllight) the text to copy
    break;
  case resMenuItemPaste:
    FldPaste (FieldTextP);
    break;
  }
   handled = 1;
   break;

 case nilEvent:
   ChangeBitmap();
   handled = 1;
   break;

 default:
   break;
 }
  return handled;
}

// ==================================================================
// Convert  キャラクタコードを16進数に変換する
// =================================================================
static void
Convert(void)
{
  char  textChar;
  int  textPos;
  int  lowNibble, hiNibble;
  char  hexChar;
  int  textLength;
  CharPtr textP;

  textP = FldGetTextPtr (FieldTextP);
  textLength = FldGetTextLength (FieldTextP);
  if (textLength)
 {
   for (textPos = 0; textPos < textLength; textPos ++)
   {
  textChar = textP [textPos];
  lowNibble = textChar % 16;
  hiNibble = textChar / 16;

  if (hiNibble < 10) hexChar = 48 + hiNibble;
    else hexChar = 55 + hiNibble;

  Hex [textPos * 3] = hexChar;

  if (lowNibble < 10) hexChar = 48 + lowNibble;
    else hexChar = 55 + lowNibble;

  Hex [textPos * 3 + 1] = hexChar;
  Hex [textPos * 3 + 2] = 45;
   }
   Hex [textPos * 3 - 1] = 0;
   FldSetTextPtr (FieldHexP, Hex);
   FldRecalculateField (FieldHexP, true);

   FrmDrawForm (FrmGetActiveForm());
 }
  else
 {
   FrmAlert (resAlertIDErrNullStr);
 }
}

// ==================================================================
// ChangeBitmap    ビットマップ画像2枚を交互に表示する
// =================================================================
static void
ChangeBitmap(void)
{
  VoidHand   bitmapH;
  BitmapPtr   bitmapP;
 
  WhichBitmap = (WhichBitmap + 1) % 2;

  if (WhichBitmap == 0)
 bitmapH = DmGet1Resource('Tbmp', resBitmapIDText);

  else
 bitmapH = DmGet1Resource('Tbmp', resBitmapIDHex);

  if (!bitmapH) return;

  bitmapP = MemHandleLock (bitmapH);
  WinDrawBitmap (bitmapP, 20, 120);
  MemHandleUnlock (bitmapH);
}