diff options
Diffstat (limited to 'SrcShared/CGremlins.cpp')
-rw-r--r-- | SrcShared/CGremlins.cpp | 2336 |
1 files changed, 2336 insertions, 0 deletions
diff --git a/SrcShared/CGremlins.cpp b/SrcShared/CGremlins.cpp new file mode 100644 index 0000000..b40bd01 --- /dev/null +++ b/SrcShared/CGremlins.cpp @@ -0,0 +1,2336 @@ +/* -*- mode: C++; tab-width: 4 -*- */ +/* ===================================================================== *\ + Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries. + All rights reserved. + + This file is part of the Palm OS Emulator. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +\* ===================================================================== */ + +#include "EmCommon.h" + +#include <stdio.h> // needed for sprintf. +#include <stdlib.h> // needed for rand and srand +#include <string.h> // needed for strcpy and friends + + +#ifdef forSimulator + +#define PILOT_PRECOMPILED_HEADERS_OFF + +// Palm Includes +#include <BuildDefines.h> +#ifdef HAS_LOCAL_BUILD_DEFAULTS +#include "LocalBuildDefaults.h" +#endif +#include <PalmTypes.h> + +#include <Chars.h> +#include <DebugMgr.h> +#include <ErrorBase.h> +#include <FeatureMgr.h> +#include <Field.h> +#include <Form.h> +#include <TextMgr.h> +#include <PalmLocale.h> + +#include "CGremlinsStubs.h" +#include "CGremlins.h" +#include "Hardware.h" +#include <EmuStubs.h> + +#define NON_PORTABLE +#include "SystemPrv.h" +#include "DataPrv.h" +#include "SysEvtPrv.h" +#include <SystemPkt.h> + +#include "ShellCmd.h" + +#else // !forSimulator + +#include "EmBankRegs.h" // RegsBank +#include "EmEventPlayback.h" // RecordPenEvent, etc. +#include "EmMemory.h" // EmMemPut16, EmMemPut32 +#include "EmPalmStructs.h" // EmAliasPenBtnInfoType +#include "EmPatchState.h" // GetCurrentAppInfo +#include "EmSession.h" // gSession, ScheduleAutoSaveState +#include "ErrorHandling.h" // Errors::ThrowIfPalmError +#include "Hordes.h" // Hordes::IsOn, TurnOn +#include "Logging.h" +#include "PreferenceMgr.h" // Preference<GremlinInfo> +#include "ROMStubs.h" // FtrGet, TxtGetNextChar, TxtCharBounds, TxtByteAddr, FrmGetActiveForm... +#include "SessionFile.h" // SessionFile +#include "Strings.r.h" // kStr_ values +#include "EmLowMem.h" // EmLowMem_SetGlobal for setting battery level + + + +/////////////////////////////////////////////////////////////////////////////////// +// Private function declarations +// (actually just some operator override declarations we'll need) + +static EmStream& operator >> (EmStream&, DatabaseInfo&); +static EmStream& operator << (EmStream&, const DatabaseInfo&); + +static EmStream& operator >> (EmStream&, GremlinInfo&); +static EmStream& operator << (EmStream&, const GremlinInfo&); + + +/////////////////////////////////////////////////////////////////////////////////// +// Private globals + +static int gIntlMgrExists = -1; + + + + + +/////////////////////////////////////////////////////////////////////////////////// +// Private functions + +static Bool IntlMgrExists (void) +{ + if (gIntlMgrExists < 0) + { + // Note that we need to check by calling the feature manager rather than + // checking to see if the trap is implemented. sysTrapIntlDispatch is + // sysTrapPsrInit on 1.0 systems and sysUnused2 on intermediate systems. + // That means that the trap IS implemented, but just not the one we want. + + UInt32 data; + Err err = FtrGet (sysFtrCreator, sysFtrNumIntlMgr, &data); + + gIntlMgrExists = !err && (data & intlMgrExists) != 0; + } + + return gIntlMgrExists != 0; +} + +static UInt16 _TxtGetNextChar (const Char *inText, UInt32 inOffset, WChar *outChar) +{ + if (IntlMgrExists ()) + { + return TxtGetNextChar (inText, inOffset, outChar); + } + + if (outChar) + *outChar = (UInt8) inText[inOffset]; + + return sizeof (Char); +} + +static WChar _TxtCharBounds (const Char *inText, UInt32 inOffset, UInt32 *outStart, UInt32 *outEnd) +{ + if (IntlMgrExists ()) + { + return TxtCharBounds (inText, inOffset, outStart, outEnd); + } + + if (outStart) + *outStart = inOffset; + + if (outEnd) + *outEnd = inOffset + 1; + + return inText[inOffset]; +} + +static UInt8 _TxtByteAttr (UInt8 inByte) +{ + if (IntlMgrExists ()) + { + return TxtByteAttr (inByte); + } + + return byteAttrSingle; +} + +#define TxtGetNextChar _TxtGetNextChar +#define TxtCharBounds _TxtCharBounds +#define TxtByteAttr _TxtByteAttr + +#include "CGremlins.h" +#include "CGremlinsStubs.h" + +#define PRINTF if (!LogGremlins ()) ; else LogAppendMsg + + +// Use our own versions of rand() and srand() so that we generate the +// same numbers on both platforms. + +#undef RAND_MAX +#define RAND_MAX 0x7fff + +#define rand Gremlin_rand +#define srand Gremlin_srand + +unsigned long int gGremlinNext = 1; + +static int rand(void) +{ +// gGremlinNext = gGremlinNext * 1103515245 + 12345; // MSL numbers + + gGremlinNext = gGremlinNext * 214013L + 2531011L; // VC++ numbers + PRINTF ("--- gGremlinNext == 0x%08X", (long) gGremlinNext); + + return ((gGremlinNext >> 16) & 0x7FFF); +} + +static void srand(unsigned int seed) +{ + gGremlinNext = seed; +} + + +#endif + + +//#define randN(N) ((N) ? rand() / (RAND_MAX / (N)) : (0)) +#define randN(N) ((int) (((long) rand() * (N)) / ((long) RAND_MAX + 1))) +#define randPercent (randN(100)) + +#ifndef forSimulator +#undef randN +inline int randN (long N) +{ + int result = ((int) (((long) rand() * (N)) / ((long) RAND_MAX + 1))); + PRINTF ("--- randN(%ld) == 0x%08X", N, (long) result); + return result; +} +#endif + +#define PEN_MOVE_CHANCE 50 // 50% move pen else pen up +#define PEN_BIG_MOVE_CHANCE 5 // 5% move pen really far + +#define KEY_DOWN_EVENT_WITHOUT_FOCUS_CHANCE 10 +#define KEY_DOWN_EVENT_WITH_FOCUS_CHANCE 40 +#define PEN_DOWN_EVENT_CHANCE (70 + KEY_DOWN_EVENT_WITHOUT_FOCUS_CHANCE) +#define MENU_EVENT_CHANCE (PEN_DOWN_EVENT_CHANCE + 4) +#define FIND_EVENT_CHANCE (MENU_EVENT_CHANCE + 2) +#define KEYBOARD_EVENT_CHANCE (FIND_EVENT_CHANCE + 1) +#define LOW_BATTERY_EVENT_CHANCE (KEYBOARD_EVENT_CHANCE + 2) +#define APP_SWITCH_EVENT_CHANCE (LOW_BATTERY_EVENT_CHANCE + 4) +// #define POWER_OFF_CHANCE (APP_SWITCH_EVENT_CHANCE + 1) + +#define LAUNCHER_EVENT_CHANCE 0 // percent of APP_SWITCH_EVENT_CHANCE + + +#define commandKeyMask 0x0008 + + +#define TYPE_QUOTE_CHANCE 10 + +#define MAX_SEED_VALUE 1000 // Max. # of seed values allowed. +#define INITIAL_SEED 1 + +#define LETTER_PROB 60 + +// Chars less often than a letter +#define SYMBOL_PROB (LETTER_PROB / 10) +#define EXT_LTTR_PROB (LETTER_PROB / 3) +#define EXTENDED_PROB (LETTER_PROB / 5) +#define CONTROL_PROB (LETTER_PROB / 2) +#define MENU_PROB (LETTER_PROB / 10) +#define KBRD_PROB 1 // The formula results in 0 + // ((LETTER_PROB / 30) / 3) // three chars to activate keyboard +#define NXTFLD_PROB (LETTER_PROB / 10) +#define SEND_DATA_PROB (LETTER_PROB / 60) + +// Chars more often than a letter +#define SPACE_PROB (LETTER_PROB * 5) +#define TAB_PROB (LETTER_PROB * 2) +#define BACKSPACE_PROB (LETTER_PROB * 3) +#define RETURN_PROB ((LETTER_PROB * 10) * 1) // extra exercise + + +//Global variables +Gremlins* TheGremlinsP; // Pointer to the Gremlins class. +long IdleTimeCheck; // Tick count for the next idle query + +// Array of probabilities of a key being pressed for gremlin mode. +#define NUM_OF_KEYS 0x110 +static const int chanceForKey[NUM_OF_KEYS] = { + 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 - 0x07 + BACKSPACE_PROB, TAB_PROB, RETURN_PROB, CONTROL_PROB, CONTROL_PROB, 0, 0, 0, // 0x08 - 0x0F + 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 - 0x17 + 0, 0, 0, 0, CONTROL_PROB, CONTROL_PROB, CONTROL_PROB, CONTROL_PROB, // 0x18 - 0x1F + + // Symbols + SPACE_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x20 - 0x23 + SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x24 - 0x27 + SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x28 - 0x2B + SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x2C - 0x2F + SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x30 - 0x33 + SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x34 - 0x37 + SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x38 - 0x3B + SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x3C - 0x3F + + // Uppercase + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x40 - 0x43 + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x44 - 0x47 + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x48 - 0x4B + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x4C - 0x4F + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x50 - 0x53 + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x54 - 0x57 + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x58 - 0x5B + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x5C - 0x5F + + // Lowercase + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x60 - 0x63 + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x64 - 0x67 + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x68 - 0x6B + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x6C - 0x6F + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x70 - 0x73 + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x74 - 0x77 + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x78 - 0x8B + LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x7C - 0x7F + + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x80 - 0x83 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x84 - 0x87 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x88 - 0x8B + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x8C - 0x8F + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x90 - 0x93 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x94 - 0x97 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x98 - 0x9B + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x9C - 0x9F + + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xA0 - 0xA3 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xA4 - 0xA7 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xA8 - 0xAB + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xAC - 0xAF + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xB0 - 0xB3 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xB4 - 0xB7 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xB8 - 0xBB + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xBC - 0xBF + + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xC0 - 0xC3 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xC4 - 0xC7 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xC8 - 0xCB + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xCC - 0xCF + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xD0 - 0xD3 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xD4 - 0xD7 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xD8 - 0xDB + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xDC - 0xDF + + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xE0 - 0xE3 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xE4 - 0xE7 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xE8 - 0xEB + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xEC - 0xEF + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xF0 - 0xF3 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xF4 - 0xF7 + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xF8 - 0xFB + EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xFC - 0xFF + + // Virtual events + // DOLATER kwk - Why not generate keyboardAlphaChr (0x110) & keyboardNumericChr (0x111)? + 0, 0, 0, NXTFLD_PROB, 0, MENU_PROB, CONTROL_PROB, 0, // 0x100 - 0x107 + CONTROL_PROB, KBRD_PROB, CONTROL_PROB, 0, NXTFLD_PROB, 0, 0, 0, // 0x108 - 0x10f + +}; + +#define NUM_OF_QUOTES 18 + +// Shakespearean quotes used by Gremlins for English text +static const char * kAsciiQuotes[NUM_OF_QUOTES] = { + "Out out damn spot!", + + "Et tu, Brute?", + + "When in disgrace with fortune and mens' eyes " + "I all alone beweep my outcast state. " + "And trouble deaf heaven with my bootless cries and " + "look upon myself and curse my fate. " + "Wishing me like to one more rich in hope, " + "featured like him, like him with friends possest, " + "desiring this man's art and that man's scope, " + "with what I most enjoy contented least;" + "\n" + "Yet in these thoughts myself almost despising- " + "haply I think on thee: and then my state, " + "like to the lark at break of day arising " + "from sullen earth, sings hymns at Heaven's gate; " + "for thy sweet love rememb'red such wealth brings " + "that then I scorn to change my state with kings.", + + "I think my wife is honest, and think she is not; " + "I think that thou art just, and think thou art not.", + + "O that this too too sullied flesh would melt, thaw, " + "and resolve itself into a dew, " + "or that the Everlasting had not fixed " + "His canon 'gainst self-slaughter.", + + "Come, you spirits that tend on mortal thoughts, unsex me here, " + "and fill me from the crown to the toe top-full " + "of direst cruelty.", + + "I do not think but Desdemona's honest.", + + "That I did love the Moor to live with him", + + "What a piece of work is a man", + + "Fair is foul, and foul is fair.", + + "All hail, Macbeth, that shalt be King hereafter!", + + "What's Montague?", + + "To a nunnery, go, and quickly too.", + + "I'll have some proof.", + + "Now are we well resolved, and by God's help and yours, " + "the noble sinews of our power, France being ours, " + "we'll bend it to our awe or break it all to pieces.", + + "Tennis balls, my liege.", + + "De Sin: le col de Nick, le menton de Sin.", + + "But swords I smile at, weapons laugh to scorn, " + "brandished by man that's of a woman born." + +}; + +static const char * kShiftJISQuotes[NUM_OF_QUOTES] = { + "人は、かつて森の神を殺した", + + "もののけ姫", + + "人面と獣の身体、樹木の角を持つ森の神・シシ神を" + "人は何故殺さねばならなかったのか−" + "この時代、人間がふえ、多くの原生林が拓かれたとはいえ、" + "まだ人を寄せつけぬ太古の森があちこちに残っていた" + "\n" + "それぞれの森は、猪や山犬など" + "巨大で賢かった獣たちが必死になって守っていた" + "そして、聖域を侵す人間達を襲い" + "荒ぶる神々と恐れられていた" + "その獣達を従えていたのが、シシ神である" + "荒ぶる神々を最も激しく戦っていたのは" + "タタラ者と呼ばれる製鉄集団だった", + + "女の身でタタラ集団を率いるエボシ御前" + "彼女は己が信念で、森を切り拓いていた", + + "その配下で、御前を敬い慕う、ゴンザにおトキと甲六" + "シシ神をねらう正体不明の坊主・ジコ坊" + "北の地の果ての隠れ里に住む老巫女・ヒイさま" + "乙事主、ナゴの神、モロなど森を守る神獣たち", + + "それに森の精霊・コダマたち…少女サンは人間の" + "子でありながら山犬モロに育てられた「もののけ姫」", + + "だったサンは、森を侵す人間を激しく憎", + + "んでいたそして、人間と荒ぶる神々の最後", + + "の大決戦に巻き込まれる少年", + + "アシタカ彼は、死の呪いを", + + "かけられたがゆえに穢れを浄める方法を探しに、", + + "旅に出た少年だった", + + "少年と少女は惨劇の中で出会い、", + + "次第に心を通わせ", + + "てゆくふたりが憎悪と殺戮の果てに見いだした" + "希望とは何だったのか少年と少女の愛" + "を横糸にシシ神をめぐる人間と獣たち", + + "の戦いを縦糸に", + + "波瀾万丈の一大叙事詩が、展開されていく…", + + "原作・脚本 :宮崎 駿製 作 :氏家齊一郎・成田 豊製作総指揮 " + ":徳間康快プロデューサー:鈴木敏夫" +}; + +static const char * kBig5Quotes[NUM_OF_QUOTES] = { + "ヲケカ}ィイト、@ヲ^、]。Cァ@", + + "ェフヲロカウ。Gヲ]エソ", + + "セ荵L、@オfケレ、ロ、ァォ癸AャGアNッuィニチ・h。Aヲモュノ\"ウqニF\"" + "、ァサ。。Aシカヲケ、@ョム、]。CャG、鷭"コツ、hチ\"、ェ、ェ。C" + "ヲョム、、ゥメーOヲィニヲ、H。Hヲロ、Sカウ。G、オュキケミクLクL。A、@ィニオLヲィ。A", + + "ゥソゥタ、ホキ、鬩メヲウ、ァ、k、l。A、@、@イモヲメク・h。A" + "トアィ荐讀ィ」テム。Aャメ・Xゥァレ、ァ、W。Cヲァレーーナスャワ。A" + "クロ、」ュYゥシクネウヲォv。Hケキ\\ォhヲウセl。Aョャ、SオLッq、ァ、jオL・iヲpヲ、ァ" + "、鬢]。Iキヲケ。AォhヲロアアN、wゥケゥメソ爨ムョヲッェシw。AタAヲ醪K、ァ" + "ョノ。Aワョ・フナ茗ホ、ァ、鬘AュI、・Sアミィ|、ァョヲ。Aュtョv " + "\n" + "、ヘウWスヘ、ァシw。A・Hヲワ、オ、鬢@ァ゙オLヲィ。A・b・ヘシ罸ヒ、ァクo。Aスs " + "ュz、@カー。A・Hァi、ム、U、H。Gァレ、ァクoゥT、」ァK。AオMサモサユ、、" + "・サヲロセセヲウ、H。AクU、」・iヲ]ァレ、ァ、」ィv。Aヲロナ@、vオu " + "。A、@ィヨィマィ茗{キタ、]。Cチ、オ、鬢ァュTンワスエシ。A・ヒ_テキァノ。Aィ " + "ア皃iュキナS。Aカ・ャhョxェ癸A・逾シヲウァォァレ、ァテフテhオァセ・ェフ。Cチァレ " + "・シセヌ。A、UオァオL、蝪A、Sヲァォ・ホーイサyァィ・。Aシナコt・X、@ャqャGィニ" + "ィモ。A・逾iィマサモサユャLカヌ。Aスニ・iョョ・@、ァ・リ。Aッ}、HキTエe。A、」・ " + "ゥy・G。HャG、鷭"クォBァ\"、ェ、ェ。Cヲケヲ^、、、Z・ホ\"ケレ\"・ホ\"、ロ\"", + + "オ・ヲr。AャOエ」ソセ\\ェフイエ・リ。A・隨Oヲケョム・゚キN・サヲョ。CヲCヲャンゥx。GァA" + "ケDヲケョムアqヲヲモィモ。Hサ。ー_ョレ・ムチェッ " + "ュ。Aイモォォhイ`ヲウスィ。Cォンヲb、UアNヲケィモセェ`ゥ" + "ュィモ、kエE、キメ・ロクノ、ム、ァョノ。Aゥ、jッ、s", + + "オLス]アVスmヲィーェクg、Q、G、V。A、雕g、G、Q・|、Vケx・ロ、TクU、サ、d、ュヲハケs、@カ。CエEャモ" + "、・u・ホ、F、TクU、サ、d、ュヲハカ。A・uウ豕豕ム、F、@カ・シ・ホ。AォK" + "アヲbヲケ、sォCョGョp、U。C", + + "スヨェセヲケ・ロヲロクgキメ、ァォ癸AニFゥハ、wウq。Aヲ]ィ」_・ロ", + + "ュムアoクノ、ム。AソWヲロ、vオLァ、」ウ、Jソ。AケEヲロォ隕ロシロ", + + "。A、鬩]エdクケコFキ\\。C、@、鬘A・ソキカリ", + + "ア・、ァサレ。AォXィ」、@ケャ、@ケDサキサキヲモィモ。A", + + "・ヘアoーゥョ讀」、Z。Aツラッォュ~イァ。Aサ。サ。ッコッコィモヲワョp、U。Aァ、、_・ロ", + + "テ莢ェスヘァヨスラ。C・ャO", + + "サ。ィヌカウ、sテョッォ・P・ネ、ロ、ァィニ。Aォ皚Kサ。ィ", + + "ャケミ、、コaオリエIカQ。Cヲケ・ロ", + + "ナ・、F。A、」トア・エーハ、Z、゚。A、]キQュnィ、Hカ。・hィノ、@ィノウoコaオリエIカQ。Aヲ" + "ヲロォイハト。A、」アo、w。AォK、fヲR、Hィ・。AヲVィコケャケDサ。ケD。G、jョv。A" + "ァフ、lトェォ。A、」ッ爲」ツァ、F。CセAサD、Gヲスヘィコ、H・@カ。コaト」チcオリ。A", + + "、゚、チシ}、ァ。Cァフ、lス霖イハト", + + "。Aゥハォoオyウq。Aェpィ」、Gョv・PァホケDナ鬘AゥwォD、Zォ~。A・イ", + + "ヲウクノ、ムタル・@、ァァ。AァQェォタル、H、ァシw。CヲpサXオo、@ツIキO、゚。A" + "ト箜aァフ、lアo、Jャケミ。AヲbィコエIカQウ、、。AキナャXカmィス" +}; + +static const char * kGB2312Quotes[NUM_OF_QUOTES] = { + "エヒソェセオレメササリメイ。」ラ", + + "ユ゚ラヤヤニ」コメヤ", + + "タケメサキャテホサテヨョコ」ャケハスォユ賁ツメネ・」ャカス陦ーヘィチ鬘ア" + "ヨョヒオ」ャラォエヒメサハ鰓イ。」ケハヤサ。ーユ醋ソメ。アヤニヤニ。」" + "オォハ鰒ミヒシヌコホハツコホネヒ」ソラヤモヨヤニ」コスキ邉セツオツオ」ャメサハツボウノ」ャ", + + "コトシーオアネユヒモミヨョナョラモ」ャメサメサマクソシスマネ・」ャ" + "セニ菻ミヨケシハカ」ャスヤウモレホメヨョノマ。」コホホメフテフテミテシ」ャ" + "ウマイサネアヒネケホヤユ」ソハオタ「ヤモミモ爛ャサレモヨボメ贍ョエボソノネ郤ホヨョ" + "ネユメイ」。オアエヒ」ャヤラヤモスォメムヘヒタオフカラ豬ツ」ャスメツヨョ" + "ハア」ャ簑クハミキハヨョネユ」ャアウククミヨスフモヨョカ」ャクコハヲ" + "\n" + "モムケ賣クヨョオツ」ャメヤヨチスネユメサシシボウノ」ャーノチハオケヨョラ」ャア" + "ハメサシッ」ャメヤク賣マツネヒ」コホメヨョラケフイサテ筌ャネサケクヨミ" + "アセラヤタタモミネヒ」ャヘイサソノメホメヨョイサミ、」ャラヤサ、シコカフ" + "」ャメサイ「ハケニ蒹テメイ。」ヒ菴ネユヨョテゥエェナサ」ャペヤノエイ」ャニ" + "ウソマヲキ酊カ」ャスラチヘ・サィ」ャメ猥エモミキチホメヨョスサウアハトォユ゚。」ヒ萸メ" + "ホエムァ」ャマツアハボホト」ャモヨコホキチモテシルモエ衽ヤ」ャキムンウメサカホケハハツ" + "タエ」ャメ狒ノハケケクユムエォ」ャクエソノヤテハタヨョトソ」ャニニネヒウテニ」ャイサメ" + "メヒコ」ソケハヤサ。ーシヨモエ蝪アヤニヤニ。」エヒサリヨミキイモテ。ーテホ。アモテ。ーサテ。ア", + + "オネラヨ」ャハヌフ瞎ムヤトユ゚ムロトソ」ャメ猝ヌエヒハ鮹「メ箜セヨシ。」チミホサソエケル」コト" + "オタエヒハ魘モコホカタエ」ソヒオニクモノヒ菴サト" + "フニ」ャマクーエヤノモミネ、ホカ。」エヤレマツスォエヒタエタラ「テ" + "ヤュタエナョ豢ハマチカハッイケフヨョハア」ャモレエサトノス", + + "ボサムツチキウノク゚セュハョカユノ」ャキスセュカハョヒトユノヘ醋ッネヘチヌァホ蟆ルチ耡サソ鬘」豢サハ" + "ハマヨサモテチヒネヘチヌァホ蟆ルソ鬟ャヨサオ・オ・ハ」チヒメサソ鯰エモテ」ャア" + "ニヤレエヒノスヌ犹。キ袞ツ。」", + + "ヒュヨェエヒハッラヤセュチカヨョコ」ャチ鰔ヤメムヘィ」ャメシヨレハッ", + + "セ羞テイケフ」ャカタラヤシコボイトイサソーネム。」ャヒラヤヤケラヤフセ", + + "」ャネユメケアッコナイムタ「。」メサネユ」ャユオア犒", + + "オソヨョシハ」ャカシメサノョメサオタヤカヤカカタエ」ャ", + + "ノオテケヌクイサキイ」ャキ睨蠧メ」ャヒオヒオミヲミヲタエヨチキ袞ツ」ャラモレハッ", + + "ア゚ク゚フクソツロ。」マネハヌ", + + "ヒオミゥヤニノスホコ」ノマノミサテヨョハツ」ャコア耆オオス", + + "コウセヨミネルサェクサケ。」エヒハッ", + + "フチヒ」ャイサセエカッキイミト」ャメイマメェオスネヒシ菠・マメサマユ篳ルサェクサケ」ャオォ" + "ラヤゴエヨエタ」ャイサオテメム」ャア譱レヘツネヒムヤ」ャマトヌノョオタヒオオタ」コエハヲ」ャ" + "オワラモエタホ」ャイサトワシタチヒ。」ハハホナカホサフクトヌネヒハタシ菠ルメォキアサェ」ャ", + + "ミトヌミトスヨョ。」オワラモヨハヒ莇ヨエタ", + + "」ャミヤネエノヤヘィ」ャソシカハヲマノミホオタフ螢ャカィキヌキイニキ」ャアリ", + + "モミイケフシテハタヨョイト」ャタホシテネヒヨョオツ。」ネ酖ノキ「メサオ羔ネミト」ャ" + "ミッエオワラモオテネコウセ」ャヤレトヌクサケウ。ヨミ」ャホツネ睹鄲" +}; + +typedef struct +{ + UInt16 charEncoding; + const char** strings; +} QuotesInfoType; + +static const QuotesInfoType kQuotesInfo[] = +{ + { charEncodingPalmSJIS, kShiftJISQuotes }, + + // All of the possible Traditional Chinese encodings. + { charEncodingBig5, kBig5Quotes }, + { charEncodingBig5_HKSCS, kBig5Quotes }, + { charEncodingBig5Plus, kBig5Quotes }, + { charEncodingPalmBig5, kBig5Quotes }, + + // All of the possible Simplified Chinese encodings. + { charEncodingGB2312, kGB2312Quotes }, + { charEncodingGBK, kGB2312Quotes }, + { charEncodingPalmGB, kGB2312Quotes } +}; + +/*********************************************************************** + * + * FUNCTION: GetFocusObject + * + * DESCRIPTION: Return whether the current form has the focus. + * + * CALLED BY: here + * + * PARAMETERS: none + * + * RETURNED: TRUE if the form has a focus set and FALSE if not + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * roger 8/25/95 Initial Revision + * roger 11/27/95 Ignored not editable fields. + * + ***********************************************************************/ +static FieldPtr GetFocusObject() +{ + FormPtr frm; + UInt16 focusObj; + FieldPtr textFieldP; + + + // Pick a point within one of the current form's objects + frm = FrmGetActiveForm (); + + // The active window will not be the active form + // if a popup list of a menu is displayed. + if ((! frm) || (FrmGetWindowHandle (frm) != WinGetActiveWindow ()) || + ((focusObj = FrmGetFocus(frm)) == noFocus)) + { + if (!frm) + PRINTF ("--- GetFocusObject == NULL (FrmGetActiveForm () == NULL)"); + else if (FrmGetWindowHandle (frm) != WinGetActiveWindow ()) + PRINTF ("--- GetFocusObject == NULL (FrmGetWindowHandle () != WinGetActiveWindow ())"); + else + PRINTF ("--- GetFocusObject == NULL (FrmGetFocus () == noFocus)"); + + return NULL; + } + + // Get the field. If it's a table get it's field. + if (FrmGetObjectType(frm, focusObj) == frmTableObj) + { + textFieldP = TblGetCurrentField((TablePtr) FrmGetObjectPtr(frm, focusObj)); + if (textFieldP == NULL) + { + PRINTF ("--- GetFocusObject == NULL (TblGetCurrentField () == NULL)"); + return NULL; + } + } + else + { + textFieldP = (FieldPtr) FrmGetObjectPtr(frm, focusObj); + + if (textFieldP == NULL) + { + PRINTF ("--- GetFocusObject == NULL (FrmGetObjectPtr () == NULL)"); + } + } + + return textFieldP; +} + + +/*********************************************************************** + * + * FUNCTION: IsFocus + * + * DESCRIPTION: Return whether the current form has the focus. + * + * CALLED BY: EmGremlins.cp + * + * PARAMETERS: none + * + * RETURNED: TRUE if the form has a focus set and FALSE if not + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * roger 8/25/95 Initial Revision + * roger 11/27/95 Ignored not editable fields, broke out GetFocusObject + * + ***********************************************************************/ +static int IsFocus() +{ + FieldPtr textFieldP; + FieldAttrType attr; + + + + textFieldP = GetFocusObject(); + if (textFieldP == NULL) + { + PRINTF ("--- IsFocus == false (textFieldP == NULL)"); + return false; + } + + // Now make sure that the field is editable. + FldGetAttributes(textFieldP, &attr); + if (!attr.editable) + { + PRINTF ("--- IsFocus == false (!attr.editable 0x%04X)", (uint32) *(uint16*) &attr); + return false; + } + + PRINTF ("--- IsFocus == true"); + return true; +} + + +/*********************************************************************** + * + * FUNCTION: SpaceLeftInFocus + * + * DESCRIPTION: Return the number of characters which can be added to + * the object with the focus. + * + * CALLED BY: EmGremlins.cp + * + * PARAMETERS: none + * + * RETURNED: The number of characters which can be added to + * the object with the focus. + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * roger 11/27/95 Initial Revision + * + ***********************************************************************/ +static int SpaceLeftInFocus() +{ + FieldPtr textFieldP; + FieldAttrType attr; + + + + textFieldP = GetFocusObject(); + if (textFieldP == NULL) + return 0; + + // Now make sure that the field is editable. + FldGetAttributes(textFieldP, &attr); + if (!attr.editable) + return 0; + + + + return FldGetMaxChars(textFieldP) - FldGetTextLength(textFieldP); +} + + +/*********************************************************************** + * + * FUNCTION: FakeLocalMovement + * + * DESCRIPTION: Generate a random point within the vicinity of the last + * point. + * + * CALLED BY: EmGremlins.cp + * + * PARAMETERS: currentX - the new x-coordinate of a pen movement. + * currentY - the new y-coordinate of a pen movement. + * lastX - the last x-coordinate of a pen movement. + * lastY - the last y-coordinate of a pen movement. + * + * RETURNED: Nothing. + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 8/15/95 Initial Revision + * + ***********************************************************************/ +static void FakeLocalMovement(Int16* currentX, Int16* currentY, Int16 lastX, Int16 lastY) +{ + Int16 winWidth, winHeight; + + *currentX = lastX + (randN(FntLineHeight() * 2) - FntLineHeight()); + *currentY = lastY + (randN(FntLineHeight() * 2) - FntLineHeight()); // FntLineHeight + + // Note: This code was incorrectly using Hwr Display constants to determine screen size. + // The approved of method is to use the size of the current window, which may also be + // the screen, however, this may not be correct for what gremilns needs to do. + // Something needs to be done for now just to get it to work. BRM 6/30/99 + WinGetDisplayExtent(&winWidth, &winHeight); + + // Clip to screen bounds + // + // KAAR: In original Gremlins, the point was pinned to [-1...winWidth/Height]. + // That doesn't seem right, especially since -1 is used as a pen up indicator. + // So now I clip to [0...winWidth/Height). + + if (*currentX < 0) *currentX = 0; + if (*currentX >= winWidth) + *currentX = winWidth - 1; + + if (*currentY < 0) *currentY = 0; + if (*currentY >= winHeight) + *currentY = winHeight = 1; +} + + +/*********************************************************************** + * + * FUNCTION: RandomScreenXY + * + * DESCRIPTION: Generate a random point. + * + * CALLED BY: EmGremlins.cp + * + * PARAMETERS: x - the x-coordinate of a pen movement. + * y - the y-coordinate of a pen movement. + * + * RETURNED: Nothing. + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 8/15/95 Initial Revision + * + ***********************************************************************/ +static void RandomScreenXY(Int16* x, Int16* y) +{ +#ifdef __DEBUGGER_APPLICATION__ + + // Since the WinGetDisplayExtent() trap doesn't exist in all versions + // of the Palm OS, the debugger can't rely on it being around. So, + // for the debugger version of this build, we explicitely set the + // old screen width. + // + // DOLATER: Figure out a way to determine if the WinGetDisplayExtent() + // is around. If it is, then call it. Otherwise, revert to the + // old constants. + // + #define hwrDisplayWidth 160 + #define hwrDisplayHeight 160 + + *x = randN(hwrDisplayWidth); + *y = randN(hwrDisplayHeight); + +#else + + Int16 winWidth, winHeight; + + WinGetDisplayExtent(&winWidth, &winHeight); + + *x = randN(winWidth); + *y = randN(winHeight); + +#endif +} + + +/*********************************************************************** + * + * FUNCTION: RandomWindowXY + * + * DESCRIPTION: Generate a random point. + * + * CALLED BY: EmGremlins.cp + * + * PARAMETERS: x - the x-coordinate of a pen movement. + * y - the y-coordinate of a pen movement. + * + * RETURNED: Nothing. + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * Keith 11/11/99 Initial Revision + * + ***********************************************************************/ +static void RandomWindowXY(Int16* x, Int16* y) +{ + // Every so often tap anywhere on the screen (10%) + if ((randN(10) == 1) || (WinGetActiveWindow () == NULL)) + { + RandomScreenXY(x, y); + } + else + { + // We want to tap in the active window. However, WinGetWindowBounds + // works against the draw window, which is not necessarily the active + // window. Make it so. + + WinHandle oldDraw = WinSetDrawWindow (WinGetActiveWindow()); + + RectangleType bounds; + WinGetWindowBounds (&bounds); + + *x = bounds.topLeft.x + randN(bounds.extent.x); + *y = bounds.topLeft.y + randN(bounds.extent.y); + + WinSetDrawWindow (oldDraw); + } +} + + +/*********************************************************************** + * + * FUNCTION: FakeEventXY + * + * DESCRIPTION: Generate random (x,y) coordindates to produce an event. + * + * CALLED BY: EmGremlins.cp + * + * PARAMETERS: x - x-coordinate of a pen down. + * y - y-coordinate of a pen down. + * + * RETURNED: + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 08/15/95 Initial Revision + * kwk 07/17/98 10% of the time, generate tap in silkscreen btn. + * kwk 08/04/99 Cranked percentage down to 5%, since otherwise + * we're always just bringing up the keyboard or + * the Find form. + * + ***********************************************************************/ +static void FakeEventXY(Int16* x, Int16* y) +{ + FormPtr frm; + Int16 objIndex; + RectangleType bounds; + +#ifndef forSimulator + // Every so often tap anywhere on the screen (2%) + if (randN(100) < 2) + { + RandomScreenXY(x, y); + return; + } +#endif + + // Pick a point within one of the current form's objects + frm = FrmGetActiveForm (); + + // First see if we want to generate a tap in a silkscreen button. If not, then + // generate a point in the draw window if there no active form, or the active form + // is not the the active window.. The active window will not be the active form + // if a popup list of a menu is displayed. + // + // Also do this if there aren't any objects in the form. + + if (randN(20) == 1) { + UInt16 numButtons; + const PenBtnInfoType* buttonListP = EvtGetPenBtnList(&numButtons); + + const size_t size = EmAliasPenBtnInfoType<PAS>::GetSize (); + emuptr addr = ((emuptr) buttonListP) + randN(numButtons) * size; + + EmAliasPenBtnInfoType<PAS> button (addr); + RectangleType randButtonRect; + randButtonRect.topLeft.x = button.boundsR.topLeft.x; + randButtonRect.topLeft.y = button.boundsR.topLeft.y; + randButtonRect.extent.x = button.boundsR.extent.x; + randButtonRect.extent.y = button.boundsR.extent.y; + + *x = randButtonRect.topLeft.x + (randButtonRect.extent.x / 2); + *y = randButtonRect.topLeft.y + (randButtonRect.extent.y / 2); + } else if ((frm == NULL) || + (FrmGetWindowHandle (frm) != WinGetActiveWindow ())) + { + RandomWindowXY (x, y); + } + else + { + // Generate a point in an one of the form's objects that we expect + // can do something with the point (i.e. labels are ignored). + +#ifdef forSimulator + do + { + objIndex = randN(numObjects); + switch (FrmGetObjectType (frm, objIndex)) + { + case frmBitmapObj: + case frmLineObj: + case frmFrameObj: + case frmRectangleObj: + case frmLabelObj: + case frmTitleObj: + case frmPopupObj: + // do nothing for these + objIndex = -1; + break; + + default: + FrmGetObjectBounds (frm, objIndex, &bounds); + *x = bounds.topLeft.x + randN(bounds.extent.x); + *y = bounds.topLeft.y + randN(bounds.extent.y); + WinWindowToDisplayPt(x, y); + + if ( *x < -1 || *x > 1000 || + *y < -1 || *y > 1000) + ErrDisplay("Invalid point made"); + + break; + } // end switch + } while (objIndex == -1); // don't leave until we found a useful object + +#else + // Get the list of objects we can click on. + + vector<UInt16> okObjects; + ::CollectOKObjects (frm, okObjects); + + // If there are no such objects, just generate a random point. + + if (okObjects.size () == 0) + { + RandomWindowXY (x, y); + } + + // If there are such objects, pick one and click on it. + + else + { + objIndex = okObjects[randN(okObjects.size ())]; + + FrmGetObjectBounds (frm, objIndex, &bounds); + + Int16 winWidth, winHeight; + ::WinGetDisplayExtent(&winWidth, &winHeight); + + if (bounds.topLeft.x < 0) + bounds.topLeft.x = 0; + + if (bounds.topLeft.y < 0) + bounds.topLeft.y = 0; + + if (bounds.extent.x > winWidth - bounds.topLeft.x - 1) + bounds.extent.x = winWidth - bounds.topLeft.x - 1; + + if (bounds.extent.y > winHeight - bounds.topLeft.y - 1) + bounds.extent.y = winHeight - bounds.topLeft.y - 1; + + *x = bounds.topLeft.x + randN(bounds.extent.x); + *y = bounds.topLeft.y + randN(bounds.extent.y); + + WinWindowToDisplayPt(x, y); + } +#endif + } // end else +} + + +/************************************************************ + * + * FUNCTION: GremlinsSendEvent + * + * DESCRIPTION: Send a synthesized event to the device if it's + * idle. + * + * PARAMETERS: nothing + * + * RETURNS: nothing + * + * CALLED BY: the debugger's console object + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * art 11/2/95 Created. + * dia 8/26/98 Added try/catch block. + * + *************************************************************/ +#ifdef forSimulator + +void GremlinsSendEvent (void) +{ +// long tick; +// Boolean idle; +// LowMemType* lowMemP = (LowMemType*)PilotGlobalsP; +// SysEvtMgrGlobalsPtr sysEvtMgrGlobalsP; + + if (!TheGremlinsP->IsInitialized() || !StubGremlinsIsOn()) + return; + + ErrTry + { +#if EMULATION_LEVEL == EMULATION_WINDOWS + TheGremlinsP->GetFakeEvent(); +#else +// This makes it go faster, but it is much less careful (not as reproducable). +// The code was left here for future reference / fixing. + +// // If accessing remote device, low memory is at 0... +// #if MEMORY_TYPE == MEMORY_REMOTE +// lowMemP = (LowMemType*)0; +// #endif +// +// // Find out if the device is idle. +// tick = StubTimGetTicks(); +// if ((tick - IdleTimeCheck) >= 0) +// { +// sysEvtMgrGlobalsP = (SysEvtMgrGlobalsPtr)ShlDWord(&lowMemP->fixed.globals.sysEvtMgrGlobalsP); +// idle = ShlByte(&sysEvtMgrGlobalsP->idle); +// if (!idle) +// { +// IdleTimeCheck = tick + 12; // 10 times a second +// return; +// } +// else +// // Clear the idle bit so the the device will not send us another idle packet. +// // Send an event +// IdleTimeCheck = 0; +// + TheGremlinsP->GetFakeEvent(); +// } +#endif + } + ErrCatch (inErr) + { + if (inErr != -1) + { + char text[256]; + UInt32 step; + + // Print error & stop... + TheGremlinsP->Status (NULL, &step, NULL); + sprintf(text, "Error #%lx occurred while sending. Gremlins at %ld. Stopping.\n", inErr, step); + DbgMessage(text); + StubAppGremlinsOff(); + } + } + ErrEndCatch +} + +#endif + + +/************************************************************ + * + * FUNCTION: GremlinsProcessPacket + * + * DESCRIPTION: Send a synthesized event to the device if it's + * idle. + * + * PARAMETERS: bodyP - pointer to Gremlins packet from device. + * + * RETURNS: nothing + * + * CALLED BY: the debugger's console object + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * art 11/2/95 Created. + * dia 8/26/98 Added try/catch block. + * + *************************************************************/ +#ifdef forSimulator + +void GremlinsProcessPacket (void* bodyParamP) +{ + UInt8 flags; + SysPktGremlinsCmdType* bodyP = (SysPktGremlinsCmdType*)bodyParamP; + LowMemType* lowMemP = (LowMemType*)PilotGlobalsP; + SysEvtMgrGlobalsPtr sysEvtMgrGlobalsP; + + if (!TheGremlinsP->IsInitialized()) + return; + + ErrTry + { + // See which action code got sent us + if (bodyP->action == sysPktGremlinsIdle) { + + // If accessing remote device, low memory is at 0... + #if MEMORY_TYPE == MEMORY_REMOTE + lowMemP = (LowMemType*)0; + #endif + + // Clear the idle bit so the the device will not send us another idle packet. + // Send an event + TheGremlinsP->GetFakeEvent(); + + // Turn the idle bit back on. + sysEvtMgrGlobalsP = (SysEvtMgrGlobalsPtr)ShlDWord((void *)&lowMemP->fixed.globals.sysEvtMgrGlobalsP); + flags = ShlByte((void *)&sysEvtMgrGlobalsP->gremlinsFlags); + flags |= grmGremlinsIdle; + ShlWriteMem (&flags, (UInt32)&sysEvtMgrGlobalsP->gremlinsFlags, sizeof(UInt8)); + +// flags = ShlByte(&sysEvtMgrGlobalsP->gremlinsFlags); +// ErrFatalDisplayIf (!(flags & grmGremlinsIdle), "Invalid flags"); + } + + else + ErrDisplay("Invalid action code"); + } + ErrCatch (inErr) + { + if (inErr != -1) + { + char text[256]; + UInt32 step; + + // Print error & stop... + TheGremlinsP->Status (NULL, &step, NULL); + sprintf(text, "Error #%lx occurred while processing. Gremlins at %ld. Stopping.\n", inErr, step); + DbgMessage(text); + StubAppGremlinsOff(); + } + } + ErrEndCatch +} +#endif + + +// --------------------------------------------------------------------------- +// ・ operator >> (EmStream&, DatabaseInfo&) +// --------------------------------------------------------------------------- + +EmStream& operator >> (EmStream& inStream, DatabaseInfo& outInfo) +{ + inStream >> outInfo.creator; + inStream >> outInfo.type; + inStream >> outInfo.version; + + inStream >> outInfo.dbID; + inStream >> outInfo.cardNo; + inStream >> outInfo.modDate; + inStream >> outInfo.dbAttrs; + inStream >> outInfo.name; + + outInfo.dbName[0] = 0; + + return inStream; +} + + +// --------------------------------------------------------------------------- +// ・ operator << (EmStream&, const DatabaseInfo&) +// --------------------------------------------------------------------------- + +EmStream& operator << (EmStream& inStream, const DatabaseInfo& inInfo) +{ + LocalID dbID = 0; + UInt16 cardNo = 0; + UInt32 modDate = 0; + UInt16 dbAttrs = 0; + char name[dmDBNameLength] = {0}; + + inStream << inInfo.creator; + inStream << inInfo.type; + inStream << inInfo.version; + + // I have no idea why dummy values are written out for these fields. + // But it sure causes us problems later when we need to access them! + // See the code in Hordes::GetAppList that needs to patch up the missing + // information. + + inStream << dbID; + inStream << cardNo; + inStream << modDate; + inStream << dbAttrs; + inStream << name; + + return inStream; +} + + +// --------------------------------------------------------------------------- +// ・ operator >> (EmStream&, AppPreferences::GremlinInfo&) +// --------------------------------------------------------------------------- + +EmStream& operator >> (EmStream& inStream, GremlinInfo& outInfo) +{ + bool dummy; + + inStream >> outInfo.fNumber; + inStream >> outInfo.fSteps; + inStream >> outInfo.fAppList; + + inStream >> dummy; // forward compatibility: this field was + // fContinuePastWarnings + + inStream >> dummy; + inStream >> dummy; + + return inStream; +} + + +// --------------------------------------------------------------------------- +// ・ operator << (EmStream&, const AppPreferences::GremlinInfo&) +// --------------------------------------------------------------------------- + +EmStream& operator << (EmStream& inStream, const GremlinInfo& inInfo) +{ + bool dummy = false; + + inStream << inInfo.fNumber; + inStream << inInfo.fSteps; + inStream << inInfo.fAppList; + + inStream << dummy; // backward compatibility: this field was + // fContinuePastWarnings + + inStream << dummy; + inStream << dummy; + + return inStream; +} + + +/************************************************************ + * + * FUNCTION: Default Constructor + * + * DESCRIPTION: Finds the key probablilities sum. + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + * CALLED BY: main() of EmEmulatorApp.cp + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 08/01/95 Created. + * kwk 07/17/98 Moved key probability init into run-time + * section. + * + *************************************************************/ +Gremlins::Gremlins() +{ + keyProbabilitiesSum = 0; + inited = false; +#ifdef forSimulator + number = -1; +#else + number = ~0; +#endif +} + +/************************************************************ + * + * FUNCTION: Destructor + * + * DESCRIPTION: Any necessary deallocation or cleanup. + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + * CALLED BY: main() of EmEmulatorApp.cp + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 8/1/95 Created. + * + *************************************************************/ +Gremlins::~Gremlins() +{ +} + +/************************************************************ + * + * FUNCTION: IsInitialized + * + * DESCRIPTION: Returns whether or not Gremlins has be initialized. + * + * PARAMETERS: None. + * + * RETURNS: TRUE - has been initialized, FALSE - has not been initialized. + * + * CALLED BY: FindCommandStatus() in EmEmulatorApp.cp. + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 8/1/95 Created. + * + *************************************************************/ +Boolean Gremlins::IsInitialized() const +{ + return inited; +} + + +/************************************************************ + * + * FUNCTION: Initialize + * + * DESCRIPTION: Initialize the gremlins class. + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + * CALLED BY: ObeyCommand() in EmEmulatorApp.cp. + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 8/1/95 Created. + * + *************************************************************/ +void Gremlins::Initialize(UInt16 newNumber, UInt32 untilStep, UInt32 finalVal) +{ +#ifndef forSimulator + gIntlMgrExists = -1; + ::ResetCalibrationInfo(); + ::ResetClocks (); + EmLowMem_SetGlobal (hwrBatteryLevel, 255); + EmLowMem_SetGlobal (hwrBatteryPercent, 100); +#endif + + counter = 0; + until = untilStep; + finalUntil = finalVal; +#ifndef forSimulator + saveUntil = until; +#endif + catchUp = false; + needPenUp = false; + charsToType[0] = '\0'; + inited = true; +#ifdef forSimulator + // removed...test will always fail because newNumber is unsigned... +// if (newNumber == -1) +// newNumber = INITIAL_SEED; + //newNumber = clock() % MAX_SEED_VALUE + 1; +#endif + number = newNumber; + srand(number); + + IdleTimeCheck = 0; + + // Update menus (needed when init. called from console) + StubAppGremlinsOn (); +} + + + +/************************************************************ + * + * FUNCTION: Reset + * + * DESCRIPTION: Un-initialize the gremlins class. + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + *************************************************************/ +void Gremlins::Reset(void) +{ + inited = false; +} + + +/************************************************************ + * + * FUNCTION: New + * + * DESCRIPTION: Start new Gremlins + * + * PARAMETERS: GremlinInfo info + * + * RETURNS: Nothing. + * + *************************************************************/ +void +Gremlins::New (const GremlinInfo& info) +{ + if (LogGremlins ()) + { + string templ = Platform::GetString (kStr_GremlinStarted); + LogAppendMsg (templ.c_str (), (int) info.fNumber, info.fSteps); + } + + // If needed, switch to an "approved" application. + // This code roughly follows that in AppsViewSwitchApp in Launcher. + + if (info.fAppList.size () > 0) + { + // Switch to the first on the list. + + DatabaseInfo dbInfo = *(info.fAppList.begin ()); + + //--------------------------------------------------------------------- + // If this is an executable, call SysUIAppSwitch + //--------------------------------------------------------------------- + if (::IsExecutable (dbInfo.type, dbInfo.creator, dbInfo.dbAttrs)) + { + Err err = ::SysUIAppSwitch (dbInfo.cardNo, dbInfo.dbID, + sysAppLaunchCmdNormalLaunch, NULL); + Errors::ThrowIfPalmError (err); + } + + //--------------------------------------------------------------------- + // else, this must be a launchable data database. Find it's owner app + // and launch it with a pointer to the data database name. + //--------------------------------------------------------------------- + else + { + DmSearchStateType searchState; + UInt16 cardNo; + LocalID dbID; + Err err = ::DmGetNextDatabaseByTypeCreator (true, &searchState, + sysFileTApplication, dbInfo.creator, + true, &cardNo, &dbID); + Errors::ThrowIfPalmError (err); + + // Create the param block + emuptr cmdPBP = (emuptr) ::MemPtrNew (sizeof (SysAppLaunchCmdOpenDBType)); + Errors::ThrowIfNULL ((void*) cmdPBP); + + // Fill it in + ::MemPtrSetOwner ((MemPtr) cmdPBP, 0); + EmMemPut16 (cmdPBP + offsetof (SysAppLaunchCmdOpenDBType, cardNo), dbInfo.cardNo); + EmMemPut32 (cmdPBP + offsetof (SysAppLaunchCmdOpenDBType, dbID), dbInfo.dbID); + + // Switch now + err = ::SysUIAppSwitch (cardNo, dbID, sysAppLaunchCmdOpenDB, (MemPtr) cmdPBP); + Errors::ThrowIfPalmError (err); + } + } + + this->Initialize (info.fNumber, info.fSteps, info.fFinal); + + gremlinStartTime = Platform::GetMilliseconds (); + + // Make sure the app's awake. Normally, we post events on a patch to + // SysEvGroupWait. However, if the Palm device is already waiting, + // then that trap will never get called. By calling EvtWakeup now, + // we'll wake up the Palm device from its nap. + + Errors::ThrowIfPalmError (EvtWakeup ()); + + Hordes::TurnOn(true); + + if (info.fSaveFrequency != 0) + { + EmAssert (gSession); + gSession->ScheduleAutoSaveState (); + } +} + + + +/************************************************************ + * + * FUNCTION: Save + * + * DESCRIPTION: Saves Gremlin Info + * + * PARAMETERS: SessionFile to write to. + * + * RETURNS: Nothing. + * + *************************************************************/ +void +Gremlins::Save (SessionFile& f) +{ + gremlinStopTime = Platform::GetMilliseconds (); + + const long kCurrentVersion = 2; + + Chunk chunk; + EmStreamChunk s (chunk); + + Bool hordesIsOn = Hordes::IsOn (); + + s << kCurrentVersion; + + s << keyProbabilitiesSum; + s << lastPointY; + s << lastPointX; + s << lastPenDown; + s << number; + s << counter; + s << finalUntil; + s << saveUntil; + s << inited; + s << catchUp; + s << needPenUp; + s << charsToType; + + s << (hordesIsOn != false); + s << gremlinStartTime; + s << gremlinStopTime; + + s << gGremlinNext; + + GremlinInfo info; + + info.fAppList = gGremlinAppList; + info.fNumber = number; + info.fSaveFrequency = gGremlinSaveFrequency; + info.fSteps = until; + info.fFinal = finalUntil; + + s << info; + + f.WriteGremlinInfo (chunk); +} + + +/************************************************************ + * + * FUNCTION: Load + * + * DESCRIPTION: Loads Gremlin Info + * + * PARAMETERS: SessionFile to read from. + * + * RETURNS: TRUE if a Gremlin state have been loaded and it + * is ON. + * FALSE otherwise. + * + *************************************************************/ +Boolean +Gremlins::Load (SessionFile& f) +{ + Chunk chunk; + bool fHordesOn; + + if (f.ReadGremlinInfo (chunk)) + { + long version; + EmStreamChunk s (chunk); + + s >> version; + + if (version >= 1) + { + s >> keyProbabilitiesSum; + s >> lastPointY; + s >> lastPointX; + s >> lastPenDown; + s >> number; + s >> counter; + s >> finalUntil; + s >> saveUntil; + s >> inited; + s >> catchUp; + s >> needPenUp; + s >> charsToType; + + s >> fHordesOn; + + s >> gremlinStartTime; + s >> gremlinStopTime; + + s >> gGremlinNext; + + // sync until to finalUntil + + until = finalUntil; + + // Patch up the start and stop times. + + int32 delta = gremlinStopTime - gremlinStartTime; + gremlinStopTime = Platform::GetMilliseconds (); + gremlinStartTime = gremlinStopTime - delta; + + // Reset keyProbabilitiesSum to zero so that it gets + // recalculated. Writing it out to the session file + // was a bad idea. The value written out may not be + // appropriate for the version of Poser reading it in. + + keyProbabilitiesSum = 0; + } + + if (version >= 2) + { + GremlinInfo info; + + s >> info; + + Preference<GremlinInfo> pref (kPrefKeyGremlinInfo); + pref = info; + } + } + + return fHordesOn; +} + + +/************************************************************ + * + * FUNCTION: Status + * + * DESCRIPTION: Return the gremlin number and counter. + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + * CALLED BY: DoGremlins() in ShellCmdSys.cpp. + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * roger 8/4/95 Created. + * dia 9/1/98 Allows for NULL parameters. + * + *************************************************************/ +void Gremlins::Status(UInt16 *currentNumber, UInt32 *currentStep, + UInt32 *currentUntil) +{ + if (currentNumber) *currentNumber = number; + if (currentStep) *currentStep = counter; + if (currentUntil) *currentUntil = until; +} + + +/************************************************************ + * + * FUNCTION: SetSeed + * + * DESCRIPTION: Allows the user to set the seed to be used. + * + * PARAMETERS: newSeed - the new value of the seed. + * + * RETURNS: TRUE - seed value set to new seed, FALSE - value not set. + * + * CALLED BY: Uncalled. (to be called from Debug Console) + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 8/2/95 Created. + * + *************************************************************/ +Boolean Gremlins::SetSeed(UInt32 newSeed) +{ + if (newSeed > MAX_SEED_VALUE) + return false; + else + { + number = (UInt16) newSeed; + srand(number); + return true; + } +} + +/************************************************************ + * + * FUNCTION: SetUntil + * + * DESCRIPTION: Allows the user to set the until value to be used. + * + * PARAMETERS: newUntil - the new value of until. + * + * RETURNS: Nothing. + * + * CALLED BY: Hordes::Step + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 8/2/95 Created. + * + *************************************************************/ +void Gremlins::SetUntil(UInt32 newUntil) +{ + until = newUntil; +#ifndef forSimulator + saveUntil = until; +#endif +} + +/************************************************************ + * + * FUNCTION: RestoreFinalUntil + * + * DESCRIPTION: Restores the original max gremlins limit. + * + * CALLED BY: Hordes::Resume + * + *************************************************************/ + +void Gremlins::RestoreFinalUntil (void) +{ + until = finalUntil; +} + +/************************************************************ + * + * FUNCTION: Step + * + * DESCRIPTION: Allows Gremlins to go on step further then its + * set maximum. + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + * CALLED BY: ObeyCommand() in EmEmulatorApp.cp. + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * David 8/1/95 Created. + * + *************************************************************/ +void Gremlins::Step() +{ +#ifndef forSimulator + saveUntil = until; +#endif + until = counter + 1; +} + + + + +/************************************************************ + * + * FUNCTION: Resume + * + * DESCRIPTION: Resumes Gremlin + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + *************************************************************/ +void +Gremlins::Resume (void) +{ + gremlinStartTime = Platform::GetMilliseconds () - (gremlinStopTime - gremlinStartTime); + + // Make sure we're all on the same page... + ::ResetCalibrationInfo (); + + // Make sure the app's awake. Normally, we post events on a patch to + // SysEvGroupWait. However, if the Palm device is already waiting, + // then that trap will never get called. By calling EvtWakeup now, + // we'll wake up the Palm device from its nap. + + Errors::ThrowIfPalmError (EvtWakeup ()); +} + + + + +/************************************************************ + * + * FUNCTION: Stop + * + * DESCRIPTION: Stops Gremlin + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + *************************************************************/ +void +Gremlins::Stop (void) +{ + if (Hordes::IsOn()) + { + Hordes::TurnOn(false); + gremlinStopTime = Platform::GetMilliseconds (); + + unsigned short number; + unsigned long step; + unsigned long until; + this->Status (&number, &step, &until); + + if (LogGremlins ()) + { + string templ = Platform::GetString (kStr_GremlinEnded); + LogAppendMsg (templ.c_str (), + (int) number, step, until, (gremlinStopTime - gremlinStartTime)); + } + + LogDump (); + } +} + + +/************************************************************ + * + * FUNCTION: SendCharsToType + * + * DESCRIPTION: Send a char to the emulator if any are pending. + * + * PARAMETERS: None. + * + * RETURNS: true if a char was sent. + * + * CALLED BY: GetFakeEvent + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * roger 10/04/95 Created. + * kwk 07/28/98 Queue double-byte characters correctly. + * + *************************************************************/ +Boolean Gremlins::SendCharsToType() +{ + if (charsToType[0] != '\0') + { + WChar theChar; + UInt16 charSize = TxtGetNextChar(charsToType, 0, &theChar); + EmEventPlayback::RecordKeyEvent (theChar, 0, 0); + StubAppEnqueueKey(theChar, 0, 0); + PRINTF ("--- Gremlin #%ld Gremlins::SendCharsToType: key = %ld", (long) number, (long) theChar); + strcpy(&charsToType[0], &charsToType[charSize]); + return true; + } + + return false; +} + + +/************************************************************ + * + * FUNCTION: GetFakeEvent + * + * DESCRIPTION: Make a phony event for gremlin mode. + * + * PARAMETERS: None + * + * RETURNS: TRUE if a key or point was enqueued, FALSE otherwise. + * + * CALLED BY: TDEProcessMacEvents in EmEmulatorEvents.cp. + * + * REVISION HISTORY: + * 06/01/95 rsf Created by Roger Flores. + * 07/31/95 David Moved to emulator level. + * 08/28/98 kwk Removed usage of TxtCharIsVirtual macro. + * 07/03/99 kwk Set command bit for page up/page down keydown + * events, since these are virtual (to match Graffiti behavior). + * 06/04/01 kwk Add support for Big-5 char encoding (Trad. Chinese). + * + *************************************************************/ +Boolean Gremlins::GetFakeEvent() +{ + int chance; + int i; + int spaceLeft; + PointType pen; + const char *quote; + + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: Entering", (long) number); + + if (! inited) + { + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: not initialized; leaving", (long) number); + return false; + } + + // check to see if Gremlins has produced its max. # of "events." + if (counter > until) + { + StubAppGremlinsOff (); + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: End of Days; leaving", (long) number); + return false; + } + + // Added - during Gremlin runs, we found that the timeout + // could get set to 30 seconds and that a Gremlin may type + // characters for more than 30 seconds at a time. EvtEnqueueKey + // doesn't reset the event timer, so it was possible for the + // device to go to sleep, even when typing was occuring. + + ::EvtResetAutoOffTimer (); + + // check to see if the event loop needs time to catch up. + if (catchUp) + { + EmEventPlayback::RecordNullEvent (); + catchUp = false; + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: playing catchup; leaving", (long) number); + return false; + } +#ifdef forSimulator + counter++; +#endif + + // if no control object was entered, return a pen up. + if (needPenUp) + { + pen.x = -1; + pen.y = -1; + lastPointX = pen.x; + lastPointY = pen.y; + lastPenDown = false; + needPenUp = false; + EmEventPlayback::RecordPenEvent (pen); + StubAppEnqueuePt(&pen); + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted pen up; leaving", (long) number); + return true; + } + + // If we've queued up a quote string, and there are still characters to + // send, do so now. + + if (SendCharsToType()) + { + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: sent chars to type (1); leaving", (long) number); + return true; + } + + chance = randPercent; + + // Now fake an input + if ((chance < KEY_DOWN_EVENT_WITHOUT_FOCUS_CHANCE) + || (chance < KEY_DOWN_EVENT_WITH_FOCUS_CHANCE && IsFocus())) + { + if ((randPercent < TYPE_QUOTE_CHANCE) && IsFocus()) + { + const char** quoteArray = kAsciiQuotes; + + // 80% of the time we'll use text that's appropriate for the device's + // character encoding. The other 20%, we'll use 7-bit ASCII. + if (randN(10) < 8) + { + UInt32 encoding; + if (FtrGet(sysFtrCreator, sysFtrNumEncoding, &encoding) != errNone) + { + encoding = charEncodingPalmLatin; + } + + for (UInt16 i = 0; i < sizeof(kQuotesInfo) / sizeof(QuotesInfoType); i++) + { + if (kQuotesInfo[i].charEncoding == encoding) + { + quoteArray = kQuotesInfo[i].strings; + break; + } + } + } + + quote = quoteArray[randN(NUM_OF_QUOTES)]; + strcat(charsToType, quote); + + // The full field functionality doesn't need to be tested much + // If charsToType is more than the space remaining in the current + // field, then for each char past the full point give 1/3 chance to + // stop at that char. + spaceLeft = SpaceLeftInFocus(); + if (strlen(charsToType) > (size_t) spaceLeft) { + UInt32 charStart, charEnd; + TxtCharBounds(charsToType, spaceLeft, &charStart, &charEnd); + i = charStart; + while (charsToType[i] != '\0') { + if (randPercent < 33) { + charsToType[i] = '\0'; + break; + } else { + i += TxtNextCharSize(charsToType, i); + } + } + } + + Bool result = SendCharsToType (); + + if (!result) + EmEventPlayback::RecordNullEvent (); + + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: sent chars to type (2); leaving", (long) number); + return result; + } + else + { + if (keyProbabilitiesSum == 0) { + for (Int16 i = 0; i < NUM_OF_KEYS; i++) { + if ((i > 0x00FF) + || ((TxtByteAttr(i) & byteAttrSingle) != 0)) { + keyProbabilitiesSum += chanceForKey[i]; + } + } + } + + chance = randN(keyProbabilitiesSum); + + // Skip chars which cannot be single-byte, since we don't want to + // generate bogus high-byte values. + + for (i = 0; i < NUM_OF_KEYS; i++) { + if ((i < 0x0100) + && ((TxtByteAttr(i) & byteAttrSingle) == 0)) { + continue; + } else if (chance < chanceForKey[i]) { + break; + } else { + chance -= chanceForKey[i]; + } + } + + // There's a fractional chance for a greater number to be generated. If + // so we do nothing. + if (i >= NUM_OF_KEYS) + return false; + + if ((i > 255) || (i == chrPageUp) || (i == chrPageDown)) + { + EmEventPlayback::RecordKeyEvent (i, 0, commandKeyMask); + StubAppEnqueueKey(i, 0, commandKeyMask); + } + else + { + EmEventPlayback::RecordKeyEvent (i, 0, 0); + StubAppEnqueueKey(i, 0, 0); + } + + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = %ld; leaving", (long) number, i); + return true; + } + } + + else if (chance < PEN_DOWN_EVENT_CHANCE) + { + needPenUp = true; + + FakeEventXY(&pen.x, &pen.y); + + lastPointX = pen.x; + lastPointY = pen.y; + lastPenDown = true; + EmEventPlayback::RecordPenEvent (pen); + StubAppEnqueuePt(&pen); + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted pen event = (%ld, %ld), leaving", + (long) number, (long) pen.x, (long) pen.y); + + // Draw a test pixel on the overlay + StubViewDrawPixel(pen.x, pen.y); + return true; + } + + + else if (chance < MENU_EVENT_CHANCE) + { + EmEventPlayback::RecordKeyEvent (vchrMenu, vchrMenu, commandKeyMask); + StubAppEnqueueKey(vchrMenu, vchrMenu, commandKeyMask); + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrMenu, leaving", (long) number); + return true; + } + + + else if (chance < FIND_EVENT_CHANCE) + { + EmEventPlayback::RecordKeyEvent (vchrFind, vchrFind, commandKeyMask); + StubAppEnqueueKey(vchrFind, vchrFind, commandKeyMask); + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrFind, leaving", (long) number); + return true; + } + + + else if (chance < KEYBOARD_EVENT_CHANCE) + { + EmEventPlayback::RecordKeyEvent (vchrKeyboard, vchrKeyboard, commandKeyMask); + StubAppEnqueueKey(vchrKeyboard, vchrKeyboard, commandKeyMask); + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrKeyboard, leaving", (long) number); + return true; + } + + + else if (chance < LOW_BATTERY_EVENT_CHANCE) + { + EmEventPlayback::RecordKeyEvent (vchrLowBattery, vchrLowBattery, commandKeyMask); + StubAppEnqueueKey(vchrLowBattery, vchrLowBattery, commandKeyMask); + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrLowBattery, leaving", (long) number); + return true; + } + + + else if (chance < APP_SWITCH_EVENT_CHANCE) + { + // Modify the standard APP_SWITCH_EVENT_CHANCE by another factor + // of 5%. Without it, we enter this code way too often, and + // Gremlins slows down a LOT! (Like, by a factor of 2.3). + + if (randPercent < 5) + { + DatabaseInfoList appList = Hordes::GetAppList (); + + if (appList.size () > 0) + { + // Switch to a random app on the list. + + DatabaseInfo& dbInfo = appList [randN (appList.size ())]; + + //--------------------------------------------------------------------- + // If this is an executable, call SysUIAppSwitch + //--------------------------------------------------------------------- + if (::IsExecutable (dbInfo.type, dbInfo.creator, dbInfo.dbAttrs)) + { + EmuAppInfo currentApp = EmPatchState::GetCurrentAppInfo (); + + EmEventPlayback::RecordSwitchEvent (dbInfo.cardNo, dbInfo.dbID, + currentApp.fCardNo, currentApp.fDBID); + + Err err = ::SysUIAppSwitch (dbInfo.cardNo, dbInfo.dbID, + sysAppLaunchCmdNormalLaunch, NULL); + Errors::ThrowIfPalmError (err); + + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: switched to app %s, leaving", + (long) number, dbInfo.name); + + return true; + } + + //--------------------------------------------------------------------- + // else, say we tried and call it quits by falling through + //--------------------------------------------------------------------- + + } + } + } + +/* + else if (chance < POWER_OFF_CHANCE) + { + EmEventPlayback::RecordKeyEvent (vchrAutoOff, vchrAutoOff, commandKeyMask); + StubAppEnqueueKey(vchrAutoOff, vchrAutoOff, commandKeyMask); + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrAutoOff, leaving", (long) number); + return true; + } +*/ + PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: exiting with no event.", + (long) number); + + // If nothing happened fall out to generate a nilEvent + + EmEventPlayback::RecordNullEvent (); + return false; +} + + +/************************************************************ + * + * FUNCTION: GetPenMovement + * + * DESCRIPTION: Make a phony pen movement. + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + * CALLED BY: + * + * REVISION HISTORY: + * Name Date Description + * ---- ---- ----------- + * Roger 6/1/95 Created. + * David 7/31/95 Moved to emulator level. + * + *************************************************************/ +void Gremlins::GetPenMovement() +{ + // This function is not called anywhere that I can see. And since it + // calls FakeLocalMovement, which calls WinGetDisplayExtent, which + // doesn't exist in PalmDebugger, out it goes... + +#ifndef __DEBUGGER_APPLICATION__ + PointType pen; + + + // check to see if Gremlins has produced its max. # of "events." +/* if (counter > until) + { + testMode &= ~gremlinsOn; + theApp->UpdateMenus(); + } +*/ +#ifdef forSimulator + counter++; +#endif + + needPenUp = false; + if (randPercent < PEN_MOVE_CHANCE) + { + if (lastPenDown) + { + // move a small distance from the last pen position + if (randPercent < PEN_BIG_MOVE_CHANCE) + { + RandomScreenXY(&pen.x, &pen.y); + } + else + { + FakeLocalMovement(&pen.x, &pen.y, lastPointX, lastPointY); + } + } + else + { + // start the pen anywhere! + RandomScreenXY(&pen.x, &pen.y); + } + StubViewDrawLine(pen.x, pen.y, lastPointX, lastPointY); + } + else + { + lastPenDown = false; + pen.x = -1; + pen.y = -1; + catchUp = true; + } + lastPointX = pen.x; + lastPointY = pen.y; + EmEventPlayback::RecordPenEvent (pen); + StubAppEnqueuePt(&pen); +#endif + + PRINTF ("--- Gremlin #%ld Gremlins::GetPenMovement: pen = (%ld, %ld)", + (long) number, (long) pen.x, (long) pen.y); +} + + +/************************************************************ + * + * FUNCTION: BumpCounter + * + * DESCRIPTION: Bumps Gremlin event counter + * + * PARAMETERS: None. + * + * RETURNS: Nothing. + * + *************************************************************/ +void Gremlins::BumpCounter() +{ + PRINTF ("--- Gremlin #%ld: bumping counter", (long) number); + ++counter; +} |