Programando para Palm OS usando Linux

Tutoriais ruins, dificuldade em se configurar um ambiente de desenvolvimento decente, códigos não compatíveis entre ferramentas diferentes… enfim, se você usa Linux e quer começar a criar aplicações para Palm OS, saiba que, até onde eu sei, o caminho não é muito fácil.
Por isso mesmo resolvi criar esse artigo. Espero que ele se torne um bom ponto de partida para você.
O que vamos desenvolver
Se você não sabe, antigamente, lá pelas alturas da era Mesozóica, a Palm produzia aparelhos equipados com processador Motorola68k (m68k, DragonBall, etc). Atualmente ela faz aparelhos equipados com processadores ARM. Se você é programador (e se não é: você está fazendo o que aqui? Vá aprender a programar “normalmente” antes de ler esse artigo!), deve estar com as palavras “incompatibilidade binária” na cabeça.
Bom, pra encurtar a história, a Palm botou no Palm OS um emulador/simulador/máquina virtual/enganador/interpretador de binários m68k. Sacou? Por isso as aplicações jurássicas ainda conseguem rodar em Palms novos.
E o que isso tem a ver conosco? Bom, tem a ver que eu vou mostrar, nesse artigo, como programar para m68k. Isso não é nenhum grande problema. Isso ainda é bem rápido, não se preocupe, e roda em qualquer Palm, desde os antigões até os mais novos.
Parte ruim: seria muito mais legal compilar direto para ARM.
Parte boa: você pode usar o POSE ou o xcopilot para emular o Palm. Isso facilita muito nossa vida!
Como se constrói um programa para Palm OS
Papel e caneta
Já de cara, você pega uma folha de papel e vai desenhando e escrevendo. Teu programa vai servir pra quê? Já não existe algum que faça o mesmo? Se existe, o dito cujo é GPL? Você vai distribuir? Se vai, sob que licença fará isso? Será necessário suporte a outras línguas?
Assim que responder essas perguntas, você já pode começar a desenhar as telas. Acredite, se você pular esse passo, terá o triplo de trabalho na hora de botar a mão na massa pra valer! Então, desenhe!
Resources
O primeiro passo, assim que você já sabe a cara do programa é desenhar a interface. “Desenhar” é modo de dizer. Não conheço nenhuma ferramenta gráfica que faça isso (não para Linux). Você escreverá a interface num editor de texto.
A relação entre interface e programação, nesse caso, é bem como a relação entre HTML e JavaScript, sabe? Primeiro você faz a “cara” da página, e depois bota funcionalidade.
Os arquivos com a interface, em geral, ganham o sufixo .rcp. Olha um exemplo, pra você ter uma idéia:
#include "interface.h" FORM ID id_MainForm AT (2 2 156 156) USABLE FRAME MODAL HELPID id_Help MENUID id_MainMenu BEGIN TITLE "Hello-World do Cléber" END MENU ID id_MainMenu BEGIN PULLDOWN "Opções" BEGIN MENUITEM "Sobre..." ID id_MenuItem_About "a" END END STRING ID id_Help "Hello world" ALERT ID id_About INFORMATION BEGIN TITLE "Sobre o Hello world" MESSAGE " Hello To the World " BUTTONS "Done" END
Olhando assim dá pra ver que é bem simples. É um arquivo cheio de BEGINs e ENDs e tal. Bem susse de sacar como é que se faz. No fim do artigo tem uns links com exemplos e explicações de cada tipo de resource (botões, caixas de texto, listas, etc).
pilrc
Esse é o cara que compila os arquivo de resources. Basicamente:
pilrc interface.rcp
Aí ele gera um monte de arquivinhos intermediários. Existe uma ferramenta chamada pilrcui, que mostra como ficou a interface.
Programação
Volte pro arquivo de resources e preste atenção em duas coisas: no include do início e nos nomes que começam com “id_”.
A programação para Palm OS é do tipo baseada em eventos. Aquele include é um arquivo cheio de defines, tipo:
#define id_About 1000 #define id_Help 1001 #define id_MainMenu 1002 #define id_MainForm 1003 #define AboutForm 1004 #define MainForm 1005 #define id_MenuItem_About 1006
Daí, lá no arquivo C, você fica tratando eventos e outras coisas pelo ID do resource. Os defines são, óbviamente, para facilitar tua vida, mas não são obrigatórios.
Bom, já que meu “hello world” é o exemplo, vou mandar o código para você ver:
#include <PalmOS.h>
#include "interface.h"
/***********************************************************************
*
* Internal Constants
*
***********************************************************************/
#define appFileCreator "HELO" // register your own at http://www.palmos.com/dev/creatorid/
#define appVersionNum 0x01
#define appPrefID 0x00
#define appPrefVersionNum 0x01
/***********************************************************************
*
* Internal Functions
*
***********************************************************************/
/***********************************************************************
* FUNCTION: MainFormDoCommand
* DESCRIPTION: This routine performs the menu command specified.
* PARAMETERS: command - menu item id
* RETURNED: nothing
***********************************************************************/
static Boolean MainFormDoCommand(UInt16 command)
{
Boolean handled = false;
FormType * pForm;
switch (command)
{
case id_MenuItem_About:
// pForm = FrmInitForm(id_About);
// FrmDoDialog(pForm); // Display the About Box.
// FrmDeleteForm(pForm);
FrmCustomAlert(id_About, NULL, NULL, NULL);
handled = true;
break;
}
return handled;
}
/***********************************************************************
*
* FUNCTION: MainFormHandleEvent
* DESCRIPTION: This routine is the event handler for the
* "MainForm" of this application.
* PARAMETERS: pEvent - a pointer to an EventType structure
* RETURNED: true if the event has handle and should not be passed
* to a higher level handler.
*
***********************************************************************/
static Boolean MainFormHandleEvent(EventType* pEvent)
{
FormType* pForm;
switch (pEvent->eType)
{
case menuEvent:
return MainFormDoCommand(pEvent->data.menu.itemID);
case frmOpenEvent:
pForm = FrmGetActiveForm();
FrmDrawForm(pForm);
return true;
}
return false;
}
/***********************************************************************
*
* FUNCTION: AppHandleEvent
* DESCRIPTION: This routine loads form resources and set the event
* handler for the form loaded.
* PARAMETERS: event - a pointer to an EventType structure
* RETURNED: true if the event has handle and should not be passed
* to a higher level handler.
*
***********************************************************************/
static Boolean AppHandleEvent(EventType* pEvent)
{
UInt16 formId;
FormType* pForm;
Boolean handled = false;
if (pEvent->eType == frmLoadEvent)
{
// Load the form resource.
formId = pEvent->data.frmLoad.formID;
pForm = FrmInitForm(formId);
FrmSetActiveForm(pForm);
// Set the event handler for the form. The handler of the currently
// active form is called by FrmHandleEvent each time is receives an
// event.
switch (formId)
{
case id_MainForm:
FrmSetEventHandler(pForm, MainFormHandleEvent);
break;
default:
break;
}
handled = true;
}
return handled;
}
/***********************************************************************
*
* FUNCTION: AppStart
* DESCRIPTION: Get the current application"s preferences.
* PARAMETERS: nothing
* RETURNED: Err value errNone if nothing went wrong
*
***********************************************************************/
static Err AppStart(void)
{
FrmGotoForm(id_MainForm);
return errNone;
}
/***********************************************************************
*
* FUNCTION: AppStop
* DESCRIPTION: Save the current state of the application.
* PARAMETERS: nothing
* RETURNED: nothing
*
***********************************************************************/
static void AppStop(void)
{
// Close all the open forms.
FrmCloseAllForms();
}
/***********************************************************************
*
* FUNCTION: AppEventLoop
* DESCRIPTION: This routine is the event loop for the application.
* PARAMETERS: nothing
* RETURNED: nothing
*
***********************************************************************/
static void AppEventLoop(void)
{
Err error;
EventType event;
do
{
EvtGetEvent(&event, evtWaitForever);
if (SysHandleEvent(&event))
continue;
if (MenuHandleEvent(0, &event, &error))
continue;
if (AppHandleEvent(&event))
continue;
FrmDispatchEvent(&event);
}
while (event.eType != appStopEvent);
}
/***********************************************************************
*
* FUNCTION: PilotMain
* DESCRIPTION: This is the main entry point for the application.
* PARAMETERS: cmd - word value specifying the launch code.
* cmdPB - pointer to a structure that is associated with the launch code.
* launchFlags - word value providing extra information about the launch.
* RETURNED: Result of launch
*
***********************************************************************/
UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
{
Err error = errNone;
switch (cmd)
{
case sysAppLaunchCmdNormalLaunch:
if ((error = AppStart()) == 0)
{
AppEventLoop();
AppStop();
}
break;
default:
break;
}
return error;
}
Leia todo o exemplo com atenção, só pra sacar como os eventos são tratados.
GCC
m68k-palmos-gcc hello.c
Isso gerará, simplesmente, o a.out. Atenção: esse não é o executável. Pare para pensar: o GCC gera um binário, mas não é tão esperto pra deixá-lo prontinho para rodar num sistema tão bizarro quanto o Palm OS. Vou mostrar o Makefile pra você ver:
All: pilrc interface.rcp m68k-palmos-gcc hello.c m68k-palmos-obj-res a.out build-prc hello.prc hello-world *.grc *.bin clean: rm *.bin rm *.grc rm a.out
POSE
Palm OS Emulator. Cara, não vou escrever aqui, agora, como fazer pra deixar ele redondo. Você é programador! Tenho certeza que vai se virar…
O POSE serve pra você testar tua aplicação. É muito bom, pois evita ter que ficar gravando/testanto/[reiniciando]/apagando/alterando/gravando/testando…
.
.
.
.
Puxa, ninguém nunca tinha dito isso assim, tão claro pra mim. Os tutoriais ensinam como configurar o ambiente para você programar, mas não dão esses macetes assim, em ordem e de forma concisa.
Macetes
Bibliotecas
Veja o hello.c novamente. Viu que eu só inclui uma biblioteca do Palm, mesmo (PalmOS.h)? Quando você correr atrás de exemplos, essa será uma das diferenças. Em geral, os arquivos C incluem um monte de coisas. Talvez funcione com os outros, mas comigo nunca dava certo… todos os programas que eu escrevi até agora (não foram muitos) eu escrevi desse jeito, sem incluir mais nada.
Se você vir alguém incluindo, por exemplo, o Pilot.h e mais coisas, e isso der pau, experimente trocar toda essa tralha pelo bom e velho “<PalmOS.h>”.
Tipos
Tem gente que usa coisas como Word, DWord, Ptr, etc. Pra mim nunca funcionou. Eu uso UInt32 (DWord/double word), UInt16 (Word) e MemPtr (no lugar de Ptr).
Links
Ambiente
Esses caras ensinam você a configurar tua máquina para começar a programar. Em breve vou criar meu próprio tutorial, ensinando a fazer isso no Slackware (do jeito que funcionou para mim).
http://www.shallowsky.com/linux/palmlinuxdev.html - Bem velho, meio estranho, mas bem escrito. Isso pode te ajudar.
http://www.elf.org/pilot/develop.html - não gostei muito.
http://www.isaac.cs.berkeley.edu/palmdevel/ - esse aqui é pra quem gosta de compilar coisas (cara, eu sou programador, mas compilar o GCC é um saco!).
Tutoriais como esse aqui
http://www.linuxjournal.com/article/3782
http://www.wirelessdevnet.com/channels/pda/training/palmdevelopment.html - não é voltado especialmente para Linux, mas pode ser útil.
http://www.ericgiguere.com/books/palm/palm-database-programming/chapter-3-gcc.html;jsessionid=A002A03E65C9497617F1C0EAE7D3370A - bom!
http://tangentsoft.net/palmfaq/articles/tutorial/ - bem legal pra uma segunda aplicação (depois do “hello world”)
Resources
http://www.mit.jyu.fi/mweber/teaching/docs/palmos/pilrc/doc/pilrc.htm - Manual do pilrc, com a definição e exemplos dos resources - ótimo.
http://64.233.169.104/search?q=cache:poz4aINtyPcJ:stuff.mit.edu/afs/sipb/project/pilot/doc/TutorialWin.pdf+palm+resource+%22gadget+id%22&hl=pt-PT&ct=clnk&cd=2&client=firefox-a#221 - é do CodeWarrior, solução proprietária para Windows e MacOS, mas tem a documentação de vários resources.
Programação
http://www.netmeister.org/palm/Example/PalmExample.html - Um programinha mais complexo. Bem bom.
http://www.access-company.com/developers/documents/docs/palmos/PalmOSReference/ReferenceTOC.html - referência oficial da API - obrigatório.
http://mobile.eric-poncet.com/palm/tutorial/ - excelente. Tem coisas para iniciantes, médios e avançados.
Bom, espero que isso tenha sido útil. Fique de olho, pois um dia eu vou escrever mais. Se você ler os links, tiver dúvidas, fuçar no Google e depois de um mês continuar com dúvidas, não exite em perguntar (só, por favor, tente se virar sozinho antes, ok? Esse é um bom hábito).
Leave a Reply
