// aptassist.c
// Lee Wilmot 2008
// Public Domain, Share and Prosper (And Give Credit)
// See also: aptassist.html
#include "resident.h"
#include "share.h"
#include <Libraries/PalmOSGlue/CtlGlue.h>
#include <Libraries/PalmOSGlue/FrmGlue.h>
#include <Standalone.h>
STANDALONE_CODE_RESOURCE_ID(1000);
void handleRotate( actionType action ) ;
void actionOrientation( UInt16 desired );
void flashBoxNum( const char *text, Int32 num, Int32 ms );
Boolean resourceToBuffer( char **buffer, char *name, UInt16 resID );
void mySwitchToPinlet( actionType action, actionType actionMode );
void handleFormObject( actionType action, UInt16 resourceID, Int16 amountOrAction );
void showResourceIDs( actionType action );
void simHardButton( actionType action, UInt32 numberOfTimes );
void actionKhromaTheme( char *themeName ) ;
void setColours( RGBColorType* c, UInt16 count );
void DAMain( void )
{
actionType action = fget( FtrAptAssistAction );
UInt32 actionArg = fget( FtrAptAssistArg );
if ( isHardSimAction( action ) )
simHardButton( action, actionArg );
else if (
( action >= actionTypePinModeFirst ) &&
( action <= actionTypePinModeLast )
)
mySwitchToPinlet( NULL, action );
else if (
( action >= actionTypeFirstPinAction ) &&
( action <= actionTypeLastPinAction )
)
mySwitchToPinlet( action, 0 );
else if(
(
( action >= actionCatFieldFirst ) &&
( action <= actionCatFieldLast )
) ||
( action == actionTypeSimControl ) ||
( action == actionTypeSimControlEnable ) ||
( action == actionTypeSimControlDisable )
)
handleFormObject( action, actionArg, 0 );
else if ( action == actionTypeSimScrollUp )
handleFormObject( action, actionArg, -10 );
else if ( action == actionTypeSimScrollDown )
handleFormObject( action, actionArg, +10 );
else if (
( action >= actionTypeShowListFirst ) &&
( action < ( actionTypeShowListFirst + 4 ) )
)
showResourceIDs( action );
else if (
( action == actionTypeRotateLeft ) ||
( action == actionTypeRotateRight )
)
handleRotate( action );
else if (
( action >= actionTypeRotateSetUser ) &&
( action <= actionTypeRotateLast )
)
actionOrientation( action - actionTypeRotateSetUser );
// undocumented, not Apt actions
else if ( action == assistActionSetKhromaTheme )
actionKhromaTheme( (char *) actionArg );
else
flashBox( "AptAssist: unknown action, old version ? ", 1500 );
}
void mySwitchToPinlet( actionType action, actionType modeAction )
{
if ( getPINVersion() > 0 ) {
UInt16 refNum;
const char pinIDs[3][10] = {
pinClassic,
pinTriCell,
pinStdKeyboard
};
// Shouldn't we do a find first ? Is it one of those that always needs a load ?
if ( SysLibLoad( sysFileTLibrary, 'pinM', &refNum ) == errNone ) {
if ( PinLibOpen( refNum ) == errNone ) {
const char *currID = PinGetCurrentPinletID( refNum );
UInt16 currMode = PinGetInputMode( refNum );
UInt16 modeToSet;
const char *idToSet;
if ( modeAction == 0 )
modeToSet = currMode;
else
modeToSet = modeAction - actionTypePinModeFirst;
if ( action == NULL )
idToSet = currID;
else
idToSet = pinIDs[action - actionTypeFirstPinAction];
// Detection of current mode doesn't always work...
PinSwitchToPinlet( refNum, idToSet, modeToSet );
PinSetInputMode( refNum, modeToSet );
PinLibClose( refNum );
}
SysLibRemove( refNum );
}
}
}
void handleFormObject( actionType action, UInt16 resourceID, Int16 amountOrAction )
{
FormPtr formP = FrmGetActiveForm();
UInt16 objIndex = frmInvalidObjectId;
FormObjectKind reqKind;
if ( ! formP )
return;
switch ( action ) {
case actionTypeSimControl:
case actionTypeSimControlEnable:
case actionTypeSimControlDisable:
reqKind = frmControlObj;
// flashBox( "gadg", 1000 );
// reqKind = frmGadgetObj;
break;
case actionTypeSimScrollUp:
case actionTypeSimScrollDown:
reqKind = frmScrollBarObj;
break;
default:
reqKind = frmFieldObj;
break;
}
// None specified, get one with focus
if ( resourceID == 0 ) {
UInt32 focusIndex = FrmGetFocus( formP );
if ( focusIndex != noFocus ) {
FormObjectKind kind = FrmGetObjectType( formP, focusIndex );
if ( kind == reqKind )
resourceID = FrmGetObjectId( formP, focusIndex );
}
}
// Not of right type: try first in form
if ( resourceID == 0 ) {
UInt16 noObjects = FrmGetNumberOfObjects( formP );
UInt16 objectNo;
for ( objectNo = 0; objectNo < noObjects; objectNo++ ) {
if ( FrmGetObjectType( formP, objectNo ) == reqKind ) {
objIndex = objectNo;
resourceID = FrmGetObjectId( formP, objIndex );
break;
}
}
if ( objIndex == frmInvalidObjectId ) {
errFlash( "no object found");
return;
}
}
else
objIndex = FrmGetObjectIndex( formP, resourceID );
if ( objIndex == frmInvalidObjectId )
flashBoxNum( "AptAssist: ignore bad obj ID: ", resourceID, 800 );
else {
FormObjectKind kind = FrmGetObjectType( formP, objIndex );
void *ptr = FrmGetObjectPtr ( formP, objIndex );
if ( kind != reqKind )
flashBoxNum( "AptAssist: ID wrong resource: ", resourceID, 800 );
else if ( reqKind == frmControlObj ) {
ControlPtr controlP= (ControlPtr) ptr;
ControlStyleType style = CtlGlueGetControlStyle( controlP );
switch ( style ) {
case pushButtonCtl:
case checkboxCtl:
{
Int16 val = CtlGetValue ( controlP );
switch ( action ) {
case actionTypeSimControl:
val = 1 - val;
break;
case actionTypeSimControlEnable:
val = 1;
break;
case actionTypeSimControlDisable:
val = 0;
break;
default:
break;
}
if ( CtlGetValue( controlP ) != val ) {
CtlSetValue( controlP, val );
CtlHitControl( controlP );
CtlDrawControl( controlP );
}
}
break;
case popupTriggerCtl:
case selectorTriggerCtl:
case buttonCtl:
case repeatingButtonCtl:
if ( action == actionTypeSimControl )
CtlHitControl( controlP );
break;
default:
break;
}
}
else if ( reqKind == frmFieldObj ) {
FieldPtr fldP= (FieldPtr) FrmGetObjectPtr ( formP, objIndex );
switch ( action ) {
// Next version
case actionTypeFieldToggleEditable:
case actionTypeFieldToggleUnderlined:
{
FieldAttrType attrib;
FldGetAttributes( fldP, &attrib );
if ( action == actionTypeFieldToggleEditable ) {
attrib.editable = ! ( attrib.editable );
}
else
attrib.underlined = ! ( attrib.underlined );
FldSetAttributes( fldP, &attrib );
}
case actionTypeFieldExit:
FldReleaseFocus( fldP );
break;
case actionTypeFieldEnter:
FldGrabFocus( fldP );
FldDrawField( fldP );
case actionTypeFieldEnd:
FldSetInsertionPoint( fldP, FldGetTextLength( fldP ) );
break;
case actionTypeFieldStart:
FldSetInsertionPoint( fldP, 0 );
break;
case actionTypeFieldCopy:
FldCopy( fldP );
break;
case actionTypeFieldCut:
FldCut( fldP );
break;
case actionTypeFieldPaste:
FldPaste( fldP );
break;
case actionTypeFieldUndo:
FldUndo( fldP );
break;
case actionTypeFieldSelectAll:
FldSetSelection( fldP, 0, FldGetTextLength( fldP ) );
break;
default:
break;
}
}
/* else if ( reqKind == frmGadgetObj ) {
EventType ev = initEvent( frmGadgetEnterEvent );
RectangleType bounds;
FrmGetObjectBounds( FrmGetActiveForm(), objIndex, &bounds );
ev.data.gadgetEnter.gadgetID = resourceID;
ev.data.gadgetEnter.gadgetP = ( struct FormGadgetType * ) ptr;
ev.screenX = bounds.topLeft.x + 73;
ev.screenY = bounds.topLeft.y + 183;
ev.tapCount = 1;
ev.penDown = true;
// enter->
// flashBox( "add", 1000 );
// if ( resourceID != 1001 )
// flashBox( "bad no", 1000 );
EvtAddEventToQueue( &ev );
}*/
else if ( reqKind == frmScrollBarObj ) {
ScrollBarType *scrollP = (ScrollBarType *) ptr;
Int16 value, min, max, pageSize;
EventType ev = initEvent( sclEnterEvent );
Int16 newValue;
SclGetScrollBar ( scrollP, &value, &min, &max, &pageSize );
if ( amountOrAction > 0 )
newValue = value + ( pageSize / 2 );
else
newValue = value - ( pageSize / 2 );
if ( newValue < min )
newValue = min;
if ( newValue > max )
newValue = max;
ev.data.sclEnter.scrollBarID = resourceID;
ev.data.sclEnter.pScrollBar = scrollP;
EvtAddEventToQueue( &ev );
ev =initEvent( sclRepeatEvent );
ev.data.sclRepeat.scrollBarID = resourceID;
ev.data.sclRepeat.pScrollBar = scrollP;
ev.data.sclRepeat.value = value;
ev.data.sclRepeat.newValue = newValue;
ev.data.sclRepeat.time = TimGetTicks();
EvtAddEventToQueue( &ev );
ev = initEvent( sclExitEvent );
ev.data.sclExit.scrollBarID = resourceID;
ev.data.sclExit.pScrollBar = scrollP;
ev.data.sclExit.value = newValue;
ev.data.sclExit.newValue = newValue;
EvtAddEventToQueue( &ev );
SclSetScrollBar( scrollP, newValue, min, max, pageSize );
}
}
}
void showResourceIDs( actionType type )
{
FormPtr oldFormP = FrmGetActiveForm();
Char *selNames[MAX_NO_LISTIDS];
UInt16 ids[MAX_NO_LISTIDS];
UInt32 noSelections = 0;
if ( oldFormP ) {
if ( type == actionTypeShowFormList ) {
ids[0] = FrmGetActiveFormID();
if ( resourceToBuffer( &selNames[0], (char *) FrmGetTitle( oldFormP ) , ids[0] ) ) {
noSelections++;
}
}
else if ( type == actionTypeShowMenuList ) {
UInt16 barID = FrmGlueGetMenuBarID ( oldFormP );
if ( barID != 0 ) {
MenuBarType *barP = MenuInit ( barID );
if ( barP != NULL ) {
UInt16 pno;
for ( pno = 0; pno < barP->numMenus; pno++ ) {
UInt16 itemno;
MenuPullDownPtr pulldownP = (MenuPullDownPtr) barP->menus+pno;
if ( pulldownP != NULL ) {
for ( itemno = 0; itemno < pulldownP->numItems; itemno++ ) {
MenuItemType *itemP = (MenuItemType *) pulldownP->items+itemno;
if( *(itemP->itemStr) != MenuSeparatorChar ) {
if ( resourceToBuffer( &selNames[noSelections], itemP->itemStr, itemP->id ) ) {
ids[noSelections] = itemP->id;
noSelections++;
if ( noSelections == MAX_NO_LISTIDS )
break;
}
}
}
}
if ( noSelections == MAX_NO_LISTIDS )
break;
}
MenuDispose( barP );
}
}
}
else {
UInt16 noObjects = FrmGetNumberOfObjects( oldFormP );
UInt16 objectNo;
for ( objectNo = 0; objectNo < noObjects; objectNo++ ) {
FormObjectKind kind = FrmGetObjectType( oldFormP, objectNo );
UInt8 controlPrefixIndex = 99;
char controlPrefixes[7][9] = {
"<ckbox>",
"<popup>",
"<select>",
"<button>",
"<scroll>",
"<graph>",
"<field>"
};
char *labelP = NULL;
switch ( type ) {
case actionTypeShowControlList:
{
switch ( kind ) {
case frmControlObj:
{
ControlPtr controlP = (ControlPtr) FrmGetObjectPtr( oldFormP, objectNo ) ;
if ( controlP != NULL ) {
switch ( CtlGlueGetControlStyle( controlP ) ) {
case checkboxCtl:
controlPrefixIndex = 0;
break;
case popupTriggerCtl:
controlPrefixIndex = 1;
break;
case selectorTriggerCtl:
controlPrefixIndex = 2;
break;
case buttonCtl:
case pushButtonCtl:
case repeatingButtonCtl:
controlPrefixIndex = 3;
break;
default:
break;
}
}
break;
}
case frmScrollBarObj:
controlPrefixIndex = 4;
default:
break;
}
if (
( controlPrefixIndex != 99 ) &&
( kind == frmControlObj )
) {
ControlPtr controlP= (ControlPtr) FrmGetObjectPtr( oldFormP, objectNo ) ;
if ( controlP != NULL ) {
if ( CtlGlueIsGraphical( controlP ) )
controlPrefixIndex = 5;
else
labelP = (char *) CtlGetLabel( controlP );
}
}
break;
}
case actionTypeShowFieldList:
if ( kind == frmFieldObj ) {
labelP = FldGetTextPtr( FrmGetObjectPtr( oldFormP, objectNo ) );
controlPrefixIndex = 6;
}
break;
default:
break;
}
if ( controlPrefixIndex != 99 ) {
UInt16 resourceID = FrmGetObjectId( oldFormP, objectNo );
// If we don't have a label for it, use the prefix
if (
( labelP == NULL ) ||
( StrLen( labelP ) == 0 )
)
labelP = controlPrefixes[controlPrefixIndex];
if ( resourceToBuffer( &selNames[noSelections], labelP, resourceID ) ) {
ids[noSelections] = resourceID;
noSelections++;
if ( noSelections == MAX_NO_LISTIDS )
break;
}
}
}
}
}
if ( noSelections == 0 )
flashBox( "Apt: none found", 1000 );
else {
ListType *listP;
UInt32 selNo;
Int16 chosen = noSelections;
FontID oldFont = FntSetFont( stdFont );
FormPtr newFormP;
newFormP = makeFormList( noSelections, &listP);
if ( newFormP != NULL ) {
if ( listP != NULL ) {
chosen = setupList( newFormP, listP, selNames, noSelections );
}
swapForm( newFormP, oldFormP );
FntSetFont( oldFont );
}
fsetFlag( FtrAptAssistResult, ( chosen >= 0 ) && ( chosen < noSelections ), ids[chosen] );
for ( selNo = 0; selNo < noSelections; selNo++ )
MemPtrFree( selNames[selNo] );
}
}
// Better free *buffer when you're finished guy
//
Boolean resourceToBuffer( char **buffer, char *name, UInt16 resID )
{
if ( resID > 99999 )
return false;
else {
char numBuff[6];
IDToString( resID, numBuff );
if (
( name != NULL ) &&
( StrLen( name ) > 0 )
) {
*buffer = MemPtrNew( sizeof( char ) * ( StrLen( name ) + 2 + StrLen( numBuff ) + 1 ) );
// Leave space for ': ID'
StrCopy( *buffer, name );
StrCat( *buffer, ": " );
}
else {
*buffer = MemPtrNew( StrLen( numBuff ) + 1 );
(*buffer)[0] = '\0';
}
StrCat( *buffer, numBuff );
}
return true;
}
void simHardButton( actionType action, UInt32 numberOfTimes )
{
UInt32 i;
WChar navChars[5] = { vchrRockerLeft, vchrRockerRight, vchrRockerUp, vchrRockerDown, vchrRockerCenter };
WChar hardChars[5] = { vchrHard1, vchrHard2, vchrHard3, vchrHard4, vchrHardPower };
WChar treoChars[5] = { hsChrSide, vchrHard5, vchrHard6, vchrHard7, vchrHard8 };
WChar key;
if (
( action >= actionCatSimHardFirst ) &&
( action <= actionCatSimHardLast )
)
key = hardChars[action - actionCatSimHardFirst];
else if (
( action >= actionCatSimTreoFirst ) &&
( action <= actionCatSimTreoLast )
)
key = treoChars[action - actionCatSimTreoFirst];
else
key = navChars[action - actionCatSimNavFirst];
for ( i = 0; i < numberOfTimes; i++ ) {
// EvtEnqueueKey ( hsChrModifierKey, 0, commandKeyMask );
EvtEnqueueKey ( key, 0, commandKeyMask );
}
}
void handleRotate( actionType action )
{
if ( getPINVersion() >= pinAPIVersion1_1 ) {
UInt16 newOrient = SysGetOrientation();
if ( action == actionTypeRotateRight ) {
if ( newOrient == sysOrientationReverseLandscape )
newOrient = sysOrientationPortrait;
else
newOrient++;
}
else {
if ( newOrient <= sysOrientationPortrait )
newOrient = sysOrientationReverseLandscape;
else
newOrient--;
}
actionOrientation( newOrient );
}
}
void actionOrientation( UInt16 desired )
{
if ( getPINVersion() >= pinAPIVersion1_1 ) {
if ( SysGetOrientation() != desired )
SysSetOrientation( desired );
}
}
// Thanks to Alex Pruss
//
void actionKhromaTheme( char *themeName )
{
DmOpenRef ref = DmOpenDatabaseByTypeCreator( KhromaDBType, KhromaDBCreator, dmModeReadOnly );
if ( ref != NULL ) {
UInt16 i;
UInt16 numRecords = DmNumRecords( ref );
Boolean stopFlag = false;
for ( i = 0 ; i < numRecords ; i++ ) {
MemHandle h = DmQueryRecord( ref, i );
if ( h != NULL && 32 + sizeof( RGBColorType ) <= MemHandleSize( h ) ) {
void* p = MemHandleLock( h );
if ( ! StrCompare( p, themeName ) ) {
setColours( ( RGBColorType* )( ( UInt8* )p + 32 ),
( MemHandleSize( h ) - 32 ) / sizeof( RGBColorType ) );
stopFlag = true;
}
MemHandleUnlock( h );
}
if ( stopFlag )
break;
}
DmCloseDatabase( ref );
if ( ! stopFlag ) {
errFlash( "theme not found" );
// errFlash( themeName ); could be corrupt
}
}
else
errFlash( "no KhromaDB" );
}
// Thanks to Alex Pruss
//
void setColours( RGBColorType* c, UInt16 count )
{
UInt16 i;
for ( i = 0 ; i < count ; i++ )
UIColorSetTableEntry( i, c + i );
}
void flashBoxNum( const char *text, Int32 num, Int32 ms )
{
char numBuff[20];
char buff[100];
StrIToA( numBuff, num );
StrCopy( buff, text );
StrCat( buff, ": " );
StrCat( buff, numBuff );
flashBox( buff, ms );
}