palm-os-sdk/handera-105/examples/ExampleI/Src/MemoMain.c
Tavisco 1c2f65cd40 Renamed handera-sdk-105 to handera-105
Its obviously a SDK, no need to repeat it :P
2023-11-16 22:06:58 -03:00

4995 lines
139 KiB
C

/******************************************************************************
*
* Copyright (c) 1995-2000 Palm, Inc. or its subsidiaries.
* All rights reserved.
*
* File: MemoMain.c
*
* Release: Palm OS SDK 4.0 (63220)
*
* Description:
* This is the Memo application's main module. This module
* starts the application, dispatches events, and stops
* the application.
*
* History:
* Feb 21, 1995 Created by Art Lamb
*
*****************************************************************************/
#include <TextMgr.h>
#include <PrivateRecords.h>
#include <Menu.h>
#include <TxtGlue.h>
#include <SystemResources.h>
#include <Preferences.h>
#include <Category.h>
#include <ErrorMgr.h>
#include <NotifyMgr.h>
#include <UIResources.h>
#include <FeatureMgr.h>
#include <StringMgr.h>
#include <UIColor.h>
#include <Find.h>
#include <SysEvtMgr.h>
#include <FontSelect.h>
#include <Graffiti.h>
#include <PhoneLookup.h>
#include <AboutBox.h>
#include <SoundMgr.h>
#include <TraceMgr.h>
#include <GraffitiShift.h>
#include <PalmUtils.h>
#include "MemoDB.h"
#include "MemoRsc.h"
#include "MemoMain.h"
/* TRG */
#include "Vga.h"
/* end TRG */
/***********************************************************************
*
* Internal Constants
*
***********************************************************************/
#define memoVersionNum 3
#define memoPrefsVersionNum 3
#define memoPrefID 0x00
#define newMemoSize 64
#define noRecordSelected 0xffff
#define noRecordSelectedID -1
// Update codes, used to determine how the to do list view should
// be redrawn.
#define updateRedrawAll 0x00
#define updateCategoryChanged 0x01
#define updateDisplayOptsChanged 0x02
#define updateFontChanged 0x04
//The listViewIndexStringSize is the size of the character array
//that holds the string representation of the index that is displayed to
//the left of the memo title in the list view. The string can have a
//range of 1 - 99,999 with the current value.
#define listViewIndexStringSize 7
/***********************************************************************
*
* Internal Structures
*
***********************************************************************/
typedef struct {
UInt16 topVisibleRecord;
UInt16 currentRecord;
UInt16 currentView;
UInt16 currentCategory;
FontID v20editFont;
UInt8 reserved1;
UInt16 editScrollPosition;
Boolean showAllCategories;
UInt8 reserved2;
UInt32 currentRecordID;
Boolean saveBackup;
// Version 2 preferences
FontID v20listFont;
// Version 3 preferences
FontID editFont;
FontID listFont;
} MemoPreferenceType;
typedef struct {
DmOpenRef db;
Char * categoryName;
UInt16 categoryIndex;
} AcceptBeamType;
/***********************************************************************
*
* Global variables
*
***********************************************************************/
static DmOpenRef MemoDB;
static char CategoryName [dmCategoryLength];
static UInt16 MemosInCategory;
static privateRecordViewEnum PrivateRecordVisualStatus;
static MenuBarPtr CurrentMenu;
/* TRG */
static Boolean vgaExists = false; // larger screen support
static Int16 selectedItem = -1; // one hand operation
/* end TRG */
// The following global variable are saved to a state file.
static UInt16 TopVisibleRecord = 0;
static UInt16 CurrentRecord = noRecordSelected;
static UInt16 CurrentView = ListView;
static UInt16 CurrentCategory = dmAllCategories;
static Boolean ShowAllCategories = true;
static FontID ListFont = stdFont;
static FontID EditFont = stdFont;
static UInt16 EditScrollPosition = 0;
static Boolean SaveBackup = true;
static Boolean InPhoneLookup = false;
static UInt16 TopRowPositionInCategory;
/***********************************************************************
*
* Internal Functions
*
***********************************************************************/
static Boolean EditViewDeleteRecord (void);
static void MemoLoadPrefs(UInt32* currentRecordID);
static void MemoSavePrefs(UInt16 scrollPosition);
static void ListViewDisplayMask (RectanglePtr bounds);
static Boolean ListViewUpdateDisplay (UInt16 updateCode);
static void RegisterLocaleChangingNotification(void);
/* TRG */
static void ListViewResizeForm(FormPtr frmP, Boolean draw);
static void EditViewResizeForm(FormPtr frmP, Boolean draw);
static void ListViewSelectTableItem (Boolean selected, TablePtr table, Int16 row, Int16 column, RectangleType *r);
/* end TRG */
/***********************************************************************
*
* FUNCTION: SetDBBackupBit
*
* DESCRIPTION: This routine sets the backup bit on the given database.
* This is to aid syncs with non Palm software.
* If no DB is given, open the app's default database and set
* the backup bit on it.
*
* PARAMETERS: dbP - the database to set backup bit,
* can be NULL to indicate app's default database
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* grant 4/1/99 Initial Revision
*
***********************************************************************/
void SetDBBackupBit(DmOpenRef dbP)
{
DmOpenRef localDBP;
LocalID dbID;
UInt16 cardNo;
UInt16 attributes;
// Open database if necessary. If it doesn't exist, simply exit (don't create it).
if (dbP == NULL)
{
localDBP = DmOpenDatabaseByTypeCreator (memoDBType, sysFileCMemo, dmModeReadWrite);
if (localDBP == NULL) return;
}
else
{
localDBP = dbP;
}
// now set the backup bit on localDBP
DmOpenDatabaseInfo(localDBP, &dbID, NULL, NULL, &cardNo, NULL);
DmDatabaseInfo(cardNo, dbID, NULL, &attributes, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
attributes |= dmHdrAttrBackup;
DmSetDatabaseInfo(cardNo, dbID, NULL, &attributes, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
// close database if necessary
if (dbP == NULL)
{
DmCloseDatabase(localDBP);
}
}
/***********************************************************************
*
* FUNCTION: CreateDefaultDatabase
*
* DESCRIPTION: This routine creates the default database from the
* saved image in a resource in the application.
*
* PARAMETERS: none
*
* RETURNED: 0 - if no error
* otherwise appropriate error value
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* vivek 8/17/00 Initial Revision
*
***********************************************************************/
static Err CreateDefaultDatabase(void)
{
MemHandle resH;
DmOpenRef dbP;
Err error = errNone;
// Attempt to get our default data image and create our
// database.
resH = DmGet1Resource(sysResTDefaultDB, sysResIDDefaultDB);
if (resH)
{
error = DmCreateDatabaseFromImage(MemHandleLock(resH));
if (!error)
{
MemHandleUnlock(resH);
DmReleaseResource(resH);
// Set the bakcup bit on the newly created DB.
SetDBBackupBit(NULL);
}
}
// If there is no default data, or we had a problem creating it,
// then attempt to create an empty database.
if (!resH || error)
{
error = MemoGetDatabase (&dbP, dmModeReadWrite);
if (!error)
DmCloseDatabase(dbP);
}
return error;
}
/* TRG */
/***********************************************************************
*
* FUNCTION: ToolsVgaModeSupported
*
* DESCRIPTION:
*
* PARAMETERS:
*
* RETURNED:
*
* REVISION HISTORY:
*
***********************************************************************/
static Boolean ToolsVgaModeSupported(void)
{
VgaScreenModeType mode;
VgaRotateModeType rotate;
if (vgaExists)
{
VgaGetScreenMode(&mode, &rotate);
return (mode == screenMode1To1);
}
return false;
}
/* end TRG */
/***********************************************************************
*
* FUNCTION: StartApplication
*
* DESCRIPTION: This routine opens the application's database, loads the
* saved-state information and initializes global variables.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
* grant 4/6/99 Moved code to set backup bit into SetDBBackupBit
* jmp 10/2/99 Call new MemoGetDataBase() to create database
* if it doesn't already exist.
*
***********************************************************************/
static UInt16 StartApplication (void)
{
Err err = 0;
UInt16 attr;
UInt16 mode;
UInt32 uniqueID;
UInt32 currentRecordID = 0;
Boolean recordFound = false;
UInt32 vgaVersion;
/* TRG */
if (_TRGVGAFeaturePresent(&vgaVersion))
{
VgaRotateModeType rotate;
vgaExists = true;
VgaGetScreenMode(NULL, &rotate);
VgaSetScreenMode(screenMode1To1, rotate);
}
else
vgaExists = false;
/* end TRG */
// Determime if secert record should be shown.
PrivateRecordVisualStatus = (privateRecordViewEnum)PrefGetPreference (prefShowPrivateRecords);
if (PrivateRecordVisualStatus == hidePrivateRecords)
{
mode = dmModeReadWrite;
}
else
{
mode = dmModeReadWrite | dmModeShowSecret;
}
// Find the application's data file. If it doesn't exist, create it.
err = MemoGetDatabase (&MemoDB, mode);
if (err)
return err;
// Read the preferences.
MemoLoadPrefs(&currentRecordID);
// The file may have been synchronized since the last time we used it,
// check that the current record and the currrent category still
// exist. Also, if secret records are being hidden, check if the
// the current record is marked secret.
CategoryGetName (MemoDB, CurrentCategory, CategoryName);
if (*CategoryName == 0)
{
CurrentCategory = dmAllCategories;
ShowAllCategories = true;
}
if ( DmQueryRecord (MemoDB, CurrentRecord) != 0)
{
DmRecordInfo (MemoDB, CurrentRecord, &attr, &uniqueID, NULL);
recordFound = (uniqueID == currentRecordID) &&
((PrivateRecordVisualStatus == showPrivateRecords) ||
(!(attr & dmRecAttrSecret)));
}
if (! recordFound)
{
TopVisibleRecord = 0;
CurrentRecord = noRecordSelected;
CurrentView = ListView;
EditScrollPosition = 0;
}
if (ShowAllCategories)
MemosInCategory = DmNumRecordsInCategory (MemoDB, dmAllCategories);
else
MemosInCategory = DmNumRecordsInCategory (MemoDB, CurrentCategory);
return (err);
}
/***********************************************************************
*
* FUNCTION: StopApplication
*
* DESCRIPTION: This routine closes the application's database
* and saves the current state of the application.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
*
***********************************************************************/
static void StopApplication (void)
{
UInt16 scrollPosition = 0;
FormPtr frm;
FieldPtr fld;
// If we are in the "edit view", get the current scroll position.
if ((CurrentView == EditView) && (CurrentRecord != noRecordSelected))
{
frm = FrmGetFormPtr (EditView);
fld = FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, EditMemoField));
scrollPosition = FldGetScrollPosition (fld);
}
// Close all open forms, this will force any unsaved data to
// be written to the database.
FrmCloseAllForms ();
// Write the preferences / saved-state information.
MemoSavePrefs(scrollPosition);
// Close the application's data file.
DmCloseDatabase (MemoDB);
}
/***********************************************************************
*
* FUNCTION: SyncNotification
*
* DESCRIPTION: This routine is an entry point of the memo application.
* It is called when the application's database is
* synchronized. This routine will resort the database.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 10/17/96 Initial Revision
* jmp 10/02/99 Changed call to DmOpenDatabaseByTypeCreator() to
* MemoGetDatabase().
*
***********************************************************************/
static void SyncNotification (void)
{
DmOpenRef dbP;
Err err;
// Find the application's data file.
err = MemoGetDatabase(&dbP, dmModeReadWrite);
if (err)
return;
// Resort the database.
MemoSort (dbP);
DmCloseDatabase (dbP);
}
/***********************************************************************
*
* FUNCTION: RegisterLocaleChangingNotification
*
* DESCRIPTION: Register for NotifyMgr notifications for locale chagning.
* DOLATER : This function and the one above can be rolled into one.
*
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* vivek 8/01/00 Initial Revision
*
***********************************************************************/
void RegisterLocaleChangingNotification(void)
{
UInt16 cardNo;
LocalID dbID;
Err err;
err = SysCurAppDatabase(&cardNo, &dbID);
ErrNonFatalDisplayIf(err != errNone, "can't get app db info");
if(err == errNone)
{
err = SysNotifyRegister(cardNo, dbID, sysNotifyLocaleChangedEvent,
NULL, sysNotifyNormalPriority, NULL);
#if EMULATION_LEVEL == EMULATION_NONE
ErrNonFatalDisplayIf((err != errNone) && (err != sysNotifyErrDuplicateEntry), "can't register");
#endif
}
return;
}
/***********************************************************************
*
* FUNCTION: RegisterData
*
* DESCRIPTION: Register with the Exchange Manager to receive .txt and
* text/plain.
*
* PARAMETERS: none
*
* RETURNED: nothing
*
* HISTORY:
* 7/28/00 dje Initial Revision.
*
***********************************************************************/
static void RegisterData(void)
{
MemHandle resH;
void *desc;
resH = DmGetResource(strRsc, ExgDescriptionStr);
desc = MemHandleLock(resH);
ExgRegisterDatatype(sysFileCMemo, exgRegExtensionID, memoExtension, desc, 0);
ExgRegisterDatatype(sysFileCMemo, exgRegTypeID, memoMIMEType, desc, 0);
MemHandleUnlock(resH);
DmReleaseResource(resH);
}
/***********************************************************************
*
* FUNCTION: MemoLoadPrefs
*
* DESCRIPTION: Load the preferences and do any fixups needed for backwards
* and forwards compatibility
*
* PARAMETERS: currentRecordID <- returned record id from preferences.
*
* RETURNED: nothing
*
* HISTORY:
* 01/13/98 BGT Initial Revision.
* 08/04/99 kwk Cleaned up setting EditFont/ListFont from prefs.
*
***********************************************************************/
void MemoLoadPrefs(UInt32* currentRecordID)
{
MemoPreferenceType prefs;
UInt16 prefsSize;
Int16 prefsVersion;
Boolean needFontInfo = false;
// Read the preferences / saved-state information.
prefsSize = sizeof (MemoPreferenceType);
prefsVersion = PrefGetAppPreferences (sysFileCMemo, memoPrefID, &prefs, &prefsSize, true);
if (prefsVersion > memoPrefsVersionNum) {
prefsVersion = noPreferenceFound;
}
if (prefsVersion > noPreferenceFound)
{
// Try to carry forward the version 2 preferences for the font
if (prefsVersion < 2)
{
// No font data in original prefs
needFontInfo = true;
}
else if (prefsVersion == 2)
{
prefs.editFont = prefs.v20editFont;
prefs.listFont = prefs.v20listFont;
// Use the 'better' large font if we've got it, since version 2
// prefs would have been created on an older version of the OS
// which didn't have the largeBoldFont available.
if (prefs.editFont == largeFont)
prefs.editFont = largeBoldFont;
if (prefs.listFont == largeFont)
prefs.listFont = largeBoldFont;
}
TopVisibleRecord = prefs.topVisibleRecord;
CurrentRecord = prefs.currentRecord;
CurrentView = prefs.currentView;
CurrentCategory = prefs.currentCategory;
EditScrollPosition = prefs.editScrollPosition;
ShowAllCategories = prefs.showAllCategories;
SaveBackup = prefs.saveBackup;
*currentRecordID = prefs.currentRecordID;
}
else
{
needFontInfo = true;
}
// If the prefs didn't supply us with font info, we'll need to get it ourselves.
if (needFontInfo)
{
UInt32 defaultFont;
FtrGet(sysFtrCreator, sysFtrDefaultFont, &defaultFont);
/* TRG */
/* the default font feature is for 160x160 apps,
we need to convert to Vga font. */
if (vgaExists)
defaultFont = VgaBaseToVgaFont(defaultFont);
/* end TRG */
EditFont = (FontID)defaultFont;
ListFont = (FontID)defaultFont;
}
else
{
EditFont = prefs.editFont;
ListFont = prefs.listFont;
}
// The first time this app starts register to handle .txt and text/plain.
if (prefsVersion != memoPrefsVersionNum)
RegisterData();
}
/***********************************************************************
*
* FUNCTION: MemoSavePrefs
*
* DESCRIPTION: Save the preferences and do any fixups needed for backwards
* and forwards compatibility
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* BGT 1/13/98 Initial Revision
*
***********************************************************************/
void MemoSavePrefs(UInt16 scrollPosition)
{
MemoPreferenceType prefs;
UInt32 uniqueID;
// Write the preferences / saved-state information.
prefs.topVisibleRecord = TopVisibleRecord;
prefs.currentRecord = CurrentRecord;
prefs.currentView = CurrentView;
prefs.currentCategory = CurrentCategory;
prefs.showAllCategories = ShowAllCategories;
prefs.editScrollPosition = scrollPosition;
prefs.saveBackup = SaveBackup;
prefs.editFont = EditFont;
prefs.listFont = ListFont;
prefs.v20editFont = stdFont;
prefs.v20listFont = stdFont;
// Clear reserved fields so prefs don't look "different" just from stack garbage!
prefs.reserved1 = 0;
prefs.reserved2 = 0;
// Get the current record's unique id and save it with the state
// information.
if ( DmQueryRecord (MemoDB, CurrentRecord) != 0)
{
DmRecordInfo (MemoDB, CurrentRecord, NULL, &uniqueID, NULL);
prefs.currentRecordID = uniqueID;
}
else
prefs.currentRecordID = noRecordSelectedID;
// Write the state information.
PrefSetAppPreferences (sysFileCMemo, memoPrefID, memoPrefsVersionNum, &prefs,
sizeof (MemoPreferenceType), true);
}
/***********************************************************************
*
* FUNCTION: GetObjectPtr
*
* DESCRIPTION: This routine returns a pointer to an object in the current
* form.
*
* PARAMETERS: formId - id of the form to display
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
*
***********************************************************************/
static void * GetObjectPtr (UInt16 objectID)
{
FormPtr frm;
frm = FrmGetActiveForm ();
return (FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, objectID)));
}
/***********************************************************************
*
* FUNCTION: GetFocusObjectPtr
*
* DESCRIPTION: This routine returns a pointer to the field object, in
* the current form, that has the focus.
*
* PARAMETERS: nothing
*
* RETURNED: pointer to a field object or NULL of there is no fucus
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
*
***********************************************************************/
static FieldPtr GetFocusObjectPtr (void)
{
FormPtr frm;
UInt16 focus;
frm = FrmGetActiveForm ();
focus = FrmGetFocus (frm);
if (focus == noFocus)
return (NULL);
return (FrmGetObjectPtr (frm, focus));
}
/***********************************************************************
*
* FUNCTION: SeekRecord
*
* DESCRIPTION: Given the index of a 'to do' record, this routine scans
* forwards or backwards for displayable 'to do' records.
*
* PARAMETERS: indexP - pointer to the index of a record to start from;
* the index of the record sought is returned in
* this parameter.
*
* offset - number of records to skip:
* 0 - mean seek from the current record to the
* next display record, if the current record is
* a displayable record, its index is retuned.
* 1 - mean seek foreward, skipping one displayable
* record
* -1 - menas seek backwards, skipping one
* displayable record
*
*
* RETURNED: false is return if a displayable record was not found.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/5/95 Initial Revision
*
***********************************************************************/
static Boolean SeekRecord (UInt16 * indexP, Int16 offset, Int16 direction)
{
DmSeekRecordInCategory (MemoDB, indexP, offset, direction, CurrentCategory);
if (DmGetLastErr()) return (false);
return (true);
}
/***********************************************************************
*
* FUNCTION: ChangeCategory
*
* DESCRIPTION: This routine updates the global varibles that keep track
* of category information.
*
* PARAMETERS: category - new category (index)
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 3/10/95 Initial Revision
*
***********************************************************************/
static void ChangeCategory (UInt16 category)
{
if (ShowAllCategories)
MemosInCategory = DmNumRecordsInCategory (MemoDB, dmAllCategories);
else
MemosInCategory = DmNumRecordsInCategory (MemoDB, category);
CurrentCategory = category;
TopVisibleRecord = 0;
/* TRG */
selectedItem = -1;
/* end TRG */
}
/***********************************************************************
*
* FUNCTION: DrawMemoTitle
*
* DESCRIPTION: This routine draws the title of the specified memo.
*
* PARAMETERS: memo - pointer to a memo
* x - draw position
* y - draw position
* width - maximum width to draw.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 04/18/95 Initial Revision
* roger 07/27/95 Combined both cases
* kwk 05/15/99 Use Int'l code for truncation of title.
*
***********************************************************************/
static void DrawMemoTitle (Char * memo, Int16 x, Int16 y, Int16 width)
{
Char * ptr = StrChr (memo, linefeedChr);
UInt16 titleLen = (ptr == NULL ? StrLen (memo) : (UInt16) (ptr - memo));
if (FntWidthToOffset (memo, titleLen, width, NULL, NULL) == titleLen)
{
WinDrawChars (memo, titleLen, x, y);
}
else
{
Int16 titleWidth;
titleLen = FntWidthToOffset (memo, titleLen, width - FntCharWidth (chrEllipsis), NULL, &titleWidth);
WinDrawChars (memo, titleLen, x, y);
WinDrawChar (chrEllipsis, x + titleWidth, y);
}
}
/***********************************************************************
*
* FUNCTION: ReplaceTwoColors
*
* DESCRIPTION: This routine does a selection or deselection effect by
* replacing foreground and background colors with a new pair
* of colors. In order to reverse the process, you must pass
* the colors in the opposite order, so that the current
* and new colors are known to this routine. This routine
* correctly handling the cases when two or more of these
* four colors are the same, but it requires that the
* affected area of the screen contains neither of the
* given NEW colors, unless these colors are the same as
* one of the old colors.
*
* PARAMETERS: rP - pointer to a rectangle to 'invert'
* cornerDiam - corner diameter
* oldForeground - UI color currently used for foreground
* oldBackground - UI color currently used for background
* newForeground - UI color that you want for foreground
* newBackground - UI color that you want for background
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* peter 05/19/00 Initial Revision
*
***********************************************************************/
static void ReplaceTwoColors (const RectangleType *rP, UInt16 cornerDiam,
UIColorTableEntries oldForeground, UIColorTableEntries oldBackground,
UIColorTableEntries newForeground, UIColorTableEntries newBackground)
{
UInt8 oldForegroundIndex = UIColorGetTableEntryIndex(oldForeground);
UInt8 oldBackgroundIndex = UIColorGetTableEntryIndex(oldBackground);
UInt8 newForegroundIndex = UIColorGetTableEntryIndex(newForeground);
UInt8 newBackgroundIndex = UIColorGetTableEntryIndex(newBackground);
WinPushDrawState();
WinSetDrawMode(winSwap);
WinSetPatternType (blackPattern);
if (newBackgroundIndex == oldForegroundIndex)
if (newForegroundIndex == oldBackgroundIndex)
{
// Handle the case when foreground and background colors change places,
// such as on black and white systems, with a single swap.
WinSetBackColor(oldBackgroundIndex);
WinSetForeColor(oldForegroundIndex);
WinPaintRectangle(rP, cornerDiam);
}
else
{
// Handle the case when the old foreground and the new background
// are the same, using two swaps.
WinSetBackColor(oldForegroundIndex);
WinSetForeColor(oldBackgroundIndex);
WinPaintRectangle(rP, cornerDiam);
WinSetBackColor(oldBackgroundIndex);
WinSetForeColor(newForegroundIndex);
WinPaintRectangle(rP, cornerDiam);
}
else if (oldBackgroundIndex == newForegroundIndex)
{
// Handle the case when the old background and the new foreground
// are the same, using two swaps.
WinSetBackColor(newForegroundIndex);
WinSetForeColor(oldForegroundIndex);
WinPaintRectangle(rP, cornerDiam);
WinSetBackColor(newBackgroundIndex);
WinSetForeColor(oldForegroundIndex);
WinPaintRectangle(rP, cornerDiam);
}
else
{
// Handle the case when no two colors are the same, as is typically the case
// on color systems, using two swaps.
WinSetBackColor(oldBackgroundIndex);
WinSetForeColor(newBackgroundIndex);
WinPaintRectangle(rP, cornerDiam);
WinSetBackColor(oldForegroundIndex);
WinSetForeColor(newForegroundIndex);
WinPaintRectangle(rP, cornerDiam);
}
WinPopDrawState();
}
/***********************************************************************
*
* FUNCTION: Search
*
* DESCRIPTION: This routine searchs the memo database for records
* containing the string passed.
*
* PARAMETERS: findParams - text search parameter block
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 04/18/95 Initial Revision
* roger 07/26/95 converted to modern search mechanism
* kwk 05/15/99 Use TxtFindString, save match length in custom param.
* jmp 10/01/99 Changed call to DmOpenDatabaseByTypeCreator() to
* MemoGetDatabase().
* jmp 10/21/99 Previous change caused bug #22965, but previous code
* caused yet another problem. Fixed #22965 by using
* everyone else's way: Call DmGetNextDatabaseByTypeCreator()
* first, then call DmOpenDatabase() if all is well.
*
***********************************************************************/
static void Search (FindParamsPtr findParams)
{
UInt16 pos;
Char * header;
UInt16 recordNum;
MemHandle recordH;
MemHandle headerStringH;
RectangleType r;
Boolean done;
Boolean match;
DmOpenRef dbP;
DmSearchStateType searchState;
Err err;
UInt16 cardNo = 0;
LocalID dbID;
MemoDBRecordPtr memoRecP;
UInt32 longPos;
UInt16 matchLength;
// Find the application's data file.
err = DmGetNextDatabaseByTypeCreator (true, &searchState, memoDBType,
sysFileCMemo, true, &cardNo, &dbID);
if (err)
{
findParams->more = false;
return;
}
// Open the Memo database.
dbP = DmOpenDatabase(cardNo, dbID, findParams->dbAccesMode);
if (!dbP)
{
findParams->more = false;
return;
}
// Display the heading line.
headerStringH = DmGetResource(strRsc, FindMemoHeaderStr);
header = MemHandleLock(headerStringH);
done = FindDrawHeader(findParams, header);
MemHandleUnlock(headerStringH);
DmReleaseResource(headerStringH);
if (done)
goto Exit;
// Search the memos for the "find" string.
recordNum = findParams->recordNum;
while (true)
{
// Because applications can take a long time to finish a find when
// the result may be on the screen or for other reasons, users like
// to be able to stop the find. Stop the find if an event is pending.
// This stops if the user does something with the device. Because
// this call slows winDown the search we perform it every so many
// records instead of every record. The response time should still
// be Int16 without introducing much extra work to the search.
// Note that in the implementation below, if the next 16th record is
// secret the check doesn't happen. Generally this shouldn't be a
// problem since if most of the records are secret then the search
// won't take long anyways!
if ((recordNum & 0x000f) == 0 && // every 16th record
EvtSysEventAvail(true))
{
// Stop the search process.
findParams->more = true;
break;
}
recordH = DmQueryNextInCategory (dbP, &recordNum, dmAllCategories);
// Have we run out of records?
if (! recordH)
{
findParams->more = false;
break;
}
memoRecP = MemHandleLock (recordH);
// Search for the string passed, if it's found display the title
// of the memo.
match = TxtFindString (&(memoRecP->note), findParams->strToFind, &longPos, &matchLength);
pos = longPos;
if (match)
{
// Add the match to the find paramter block, if there is no room to
// display the match the following function will return true.
done = FindSaveMatch (findParams, recordNum, pos, 0, matchLength, cardNo, dbID);
if (!done)
{
// Get the bounds of the region where we will draw the results.
FindGetLineBounds (findParams, &r);
// Display the title of the description.
DrawMemoTitle (&(memoRecP->note), r.topLeft.x+1, r.topLeft.y,
r.extent.x-2);
findParams->lineNumber++;
}
}
MemHandleUnlock(recordH);
if (done) break;
recordNum++;
}
Exit:
DmCloseDatabase (dbP);
}
/***********************************************************************
*
* FUNCTION: GoToItem
*
* DESCRIPTION: This routine is an entry point of the memo application.
* It is generally called as the result of hitting a
* "Go to" button in the text search dialog. The record
* identifies by the parameter block passed will be display,
* with the character range specified highlighted.
*
* PARAMETERS: goToParams - parameter block that identifies the record to
* display.
* launchingApp - true if the application is being launched.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 06/06/95 Initial Revision
* roger 07/26/95 converted to modern search mechanism
* kwk 05/15/99 Use saved match length in matchCustom field, so
* that it works with Japanese.
*
***********************************************************************/
static void GoToItem (GoToParamsPtr goToParams, Boolean launchingApp)
{
UInt16 recordNum;
UInt16 attr;
UInt32 uniqueID;
EventType event;
recordNum = goToParams->recordNum;
if (!DmQueryRecord(MemoDB, recordNum))
{
// Record isn't accessible. This can happen when receiving a beam while in the
// Memo New form. This prevents a fatal alert, but doesn't fix the off-by-one
// error. (See DOLATER in sysAppLaunchCmdExgReceiveData case.)
if (!SeekRecord(&recordNum, 0, dmSeekBackward))
if (!SeekRecord(&recordNum, 0, dmSeekForward))
{
FrmAlert(secGotoInvalidRecordAlert);
FrmGotoForm(ListView);
return;
}
}
DmRecordInfo(MemoDB, recordNum, &attr, &uniqueID, NULL);
if ((attr & dmRecAttrSecret) && PrivateRecordVisualStatus == maskPrivateRecords)
{
FrmAlert(secGotoInvalidRecordAlert);
FrmGotoForm(ListView);
return;
}
// Make the item the first item displayed.
TopVisibleRecord = recordNum;
// Change the current category if necessary.
if (CurrentCategory != dmAllCategories)
{
ChangeCategory (attr & dmRecAttrCategoryMask);
}
// If the application is already running, close all open forms. This
// may cause in the database record to be reordered, so we'll find the
// records index by its unique id.
if (! launchingApp)
{
FrmCloseAllForms ();
DmFindRecordByID (MemoDB, uniqueID, &recordNum);
}
// Send an event to goto a form and select the matching text.
MemSet (&event, sizeof(EventType), 0);
event.eType = frmLoadEvent;
event.data.frmLoad.formID = EditView;
EvtAddEventToQueue (&event);
event.eType = frmGotoEvent;
event.data.frmGoto.recordNum = recordNum;
event.data.frmGoto.matchPos = goToParams->matchPos;
event.data.frmGoto.matchLen = goToParams->matchCustom;
event.data.frmGoto.matchFieldNum = goToParams->matchFieldNum;
event.data.frmGoto.formID = EditView;
EvtAddEventToQueue (&event);
CurrentView = EditView;
}
/***********************************************************************
*
* FUNCTION: CreateRecord
*
* DESCRIPTION: This routine creates a new memo record.
*
* PARAMETERS: none
*
* RETURNED: true if the record was sucessfully created.
*
* HISTORY:
* 10/03/95 art Created by Art Lamb.
* 10/11/95 kcr Set initial graffiti upshift.
* 09/25/99 kwk No longer take initial character parameter.
* 10/29/99 jmp Eliminate compiler's "has no side-effect" warning.
*
***********************************************************************/
static Boolean CreateRecord (void)
{
MemPtr p;
Char zero = 0;
UInt32 offset = 0;
UInt16 attr = dmUnfiledCategory;
UInt16 index;
MemHandle memoRec;
// Add a new record at the end of the database.
index = DmNumRecords (MemoDB);
memoRec = DmNewRecord (MemoDB, &index, newMemoSize);
// If the allocate failed, display a warning.
if (! memoRec)
{
FrmAlert (DeviceFullAlert);
return (false);
}
p = MemHandleLock (memoRec);
// Null terminate the new memo string.
DmWrite (p, offset, &zero, sizeof(Char));
MemPtrUnlock (p);
// Set the category of the new record to the current category.
DmRecordInfo (MemoDB, index, &attr, NULL, NULL);
attr &= ~dmRecAttrCategoryMask;
if (CurrentCategory != dmAllCategories)
attr |= CurrentCategory;
DmSetRecordInfo (MemoDB, index, &attr, NULL);
CurrentRecord = index;
MemosInCategory++;
DmReleaseRecord (MemoDB, index, true);
// Set the graffiti state for an initial upshift of the
// first character of a new memo.
//GrfSetState (false, false, true);
return (true);
}
/***********************************************************************
*
* FUNCTION: DeleteRecord
*
* DESCRIPTION: This routine deletes the specified memo
*
* PARAMETERS: index - index of record to delete
*
* RETURNED: true if the record was sucessfully deleted.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 9/30/95 Initial Revision
*
***********************************************************************/
static Boolean DeleteRecord (UInt16 index)
{
UInt16 ctlIndex;
UInt16 buttonHit;
FormPtr alert;
Boolean saveBackup;
// Display an alert to confirm the delete operation.
alert = FrmInitForm (DeleteMemoDialog);
/* TRG */
if (vgaExists)
{
VgaScreenModeType mode;
VgaRotateModeType rotation;
VgaGetScreenMode(&mode, &rotation);
if((mode == screenMode1To1) && ((rotation == rotateModeNone) || (rotation == rotateMode180)))
VgaFormModify(alert, vgaFormModify160To240);
}
/* end TRG */
ctlIndex = FrmGetObjectIndex (alert, DeleteMemoSaveBackup);
FrmSetControlValue (alert, ctlIndex, SaveBackup);
buttonHit = FrmDoDialog (alert);
saveBackup = FrmGetControlValue (alert, ctlIndex);;
FrmDeleteForm (alert);
if (buttonHit != DeleteMemoOk)
return (false);
SaveBackup = saveBackup;
// Delete or archive the record.
if (SaveBackup)
DmArchiveRecord (MemoDB, index);
else
DmDeleteRecord (MemoDB, index);
DmMoveRecord (MemoDB, index, DmNumRecords (MemoDB));
return (true);
}
/***********************************************************************
*
* FUNCTION: SelectFont
*
* DESCRIPTION: This routine handles selection of a font in the List
* View.
*
* PARAMETERS: currFontID - id of current font
*
* RETURNED: id of new font
*
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 9/10/97 Initial Revision
*
***********************************************************************/
static FontID SelectFont (FontID currFontID)
{
UInt16 formID;
FontID fontID;
formID = (FrmGetFormId (FrmGetActiveForm ()));
// Call the OS font selector to get the id of a font.
fontID = FontSelect (currFontID);
/* TRG */
if (vgaExists && (formID == ListView))
{
FormPtr frm;
frm = FrmGetActiveForm();
VgaTableUseBaseFont(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, ListTable)),
!VgaIsVgaFont(fontID));
}
/* end TRG */
if (fontID != currFontID)
FrmUpdateForm (formID, updateFontChanged);
return (fontID);
}
/* TRG */
// utility functions to move and resize form objects for the virtual silk screen
static void PrvMoveObject(FormPtr frmP, UInt16 objIndex, Coord x_diff, Coord y_diff, Boolean draw)
{
Coord old_x, old_y;
if(draw)
FrmHideObject(frmP, objIndex);
FrmGetObjectPosition(frmP, objIndex, &old_x, &old_y);
FrmSetObjectPosition(frmP, objIndex, old_x + x_diff, old_y + y_diff);
if(draw)
FrmShowObject(frmP, objIndex);
}
static void PrvResizeObject(FormPtr frmP, UInt16 objIndex, Coord x_diff, Coord y_diff, Boolean draw)
{
RectangleType r;
if(draw)
FrmHideObject(frmP, objIndex);
FrmGetObjectBounds(frmP, objIndex, &r);
r.extent.x += x_diff;
r.extent.y += y_diff;
FrmSetObjectBounds(frmP, objIndex, &r);
if(draw)
FrmShowObject(frmP, objIndex);
}
static UInt16 PrvFrmGetGSI(FormPtr frmP)
{
UInt16 retval = -1;
UInt16 i, num;
num = FrmGetNumberOfObjects(frmP);
for (i=0;i<num;i++)
{
if (FrmGetObjectType(frmP, i)==frmGraffitiStateObj)
{
retval = i;
break;
}
}
return retval;
}
static void PrvVgaAdjustModalForm(FormPtr frmP)
{
VgaScreenModeType mode;
VgaRotateModeType rotation;
RectangleType r, frmBounds;
WinPtr saveWindow;
if (vgaExists)
{
VgaFormModify(frmP, vgaFormModify160To240);
//Adjust Position
VgaGetScreenMode(&mode, &rotation);
if((mode == screenMode1To1) && ((rotation == rotateMode90) || (rotation == rotateMode270)))
{
FrmGetFormBounds(frmP, &frmBounds);
saveWindow = WinSetDrawWindow(FrmGetWindowHandle(frmP));
WinGetDrawWindowBounds(&r);
WinSetDrawWindow(saveWindow);
r.topLeft.y = 160 - ((frmBounds.topLeft.y + frmBounds.extent.y) - r.topLeft.y);
WinSetWindowBounds(FrmGetWindowHandle(frmP), &r);
}
}
}
/* end TRG */
#pragma mark ----
/***********************************************************************
*
* FUNCTION: PreferencesApply
*
* DESCRIPTION: This routine applies the changes made in the Preferences
* Dialog
*
* PARAMETERS: nothing
*
* RETURNED: update code
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 7/18/95 Initial Revision
*
***********************************************************************/
static UInt16 PreferencesApply (void)
{
UInt8 sortOrder;
UInt16 updateCode = 0;
// Update the sort order. Reset the To Do list to the top.
sortOrder = LstGetSelection (GetObjectPtr (PreferencesSortByList));
if (MemoGetSortOrder (MemoDB) != sortOrder)
{
if (sortOrder == soAlphabetic)
{
if (FrmAlert (alphabeticSortAlert) == alphabeticSortNo)
return (0);
}
MemoChangeSortOrder (MemoDB, sortOrder);
updateCode = updateDisplayOptsChanged;
}
return (updateCode);
}
/***********************************************************************
*
* FUNCTION: PreferencesInit
*
* DESCRIPTION: This routine initializes the Preferences Dialog.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 7/18/95 Initial Revision
*
***********************************************************************/
static void PreferencesInit (void)
{
UInt16 sortOrder;
Char * label;
ListPtr lst;
ControlPtr ctl;
/* TRG */
PrvVgaAdjustModalForm(FrmGetActiveForm());
/* end TRG */
// Set the trigger and popup list that indicates the sort order.
sortOrder = MemoGetSortOrder (MemoDB);
lst = GetObjectPtr (PreferencesSortByList);
label = LstGetSelectionText (lst, sortOrder);
ctl = GetObjectPtr (PreferencesSortByTrigger);
CtlSetLabel (ctl, label);
LstSetSelection (lst, sortOrder);
}
/***********************************************************************
*
* FUNCTION: PreferencesHandleEvent
*
* DESCRIPTION: This routine is the event handler for the "Preferences
* Dialog Box" of the Memo application.
*
* PARAMETERS: event - a pointer to an EventType structure
*
* RETURNED: true if the event was handled and should not be passed
* to a higher level handler.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 7/18/95 Initial Revision
*
***********************************************************************/
static Boolean PreferencesHandleEvent (EventType * event)
{
UInt16 updateCode;
Boolean handled = false;
FormPtr frm;
if (event->eType == ctlSelectEvent)
{
switch (event->data.ctlSelect.controlID)
{
case PreferencesOkButton:
updateCode = PreferencesApply ();
FrmReturnToForm (ListView);
if (updateCode)
FrmUpdateForm (ListView, updateCode);
handled = true;
break;
case PreferencesCancelButton:
FrmReturnToForm (ListView);
handled = true;
break;
}
}
else if (event->eType == frmOpenEvent)
{
frm = FrmGetActiveForm ();
PreferencesInit ();
FrmDrawForm (frm);
handled = true;
}
return (handled);
}
#pragma mark ----
/***********************************************************************
*
* FUNCTION: DetailsSelectCategory
*
* DESCRIPTION: This routine handles selection, creation and deletion of
* categories form the Details Dialog.
*
* PARAMETERS: nothing
*
* RETURNED: index of the selected category.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 03/10/95 Initial Revision
* gap 08/13/99 Update to use new constant categoryDefaultEditCategoryString.
*
***********************************************************************/
static UInt16 DetailsSelectCategory (UInt16* category)
{
Char* name;
Boolean categoryEdited;
name = (Char *)CtlGetLabel (GetObjectPtr (DetailsCategoryTrigger));
categoryEdited = CategorySelect (MemoDB, FrmGetActiveForm (),
DetailsCategoryTrigger, DetailsCategoryList,
false, category, name, 1, categoryDefaultEditCategoryString);
return (categoryEdited);
}
/***********************************************************************
*
* FUNCTION: DetailsApply
*
* DESCRIPTION: This routine applies the changes made in the Details Dialog.
*
* PARAMETERS: category - new catagory
*
* RETURNED: code which indicates how the memo was changed, this
* code is sent as the update code, in the frmUpdate event.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 3/10/95 Initial Revision
* kcr 10/9/95 added 'private records' alert.
*
***********************************************************************/
static UInt16 DetailsApply (UInt16 category, Boolean categoryEdited)
{
UInt16 attr;
UInt16 updateCode = 0;
Boolean dirty = false;
Boolean secret;
// Get the category and secret attribute of the current record.
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
// Get the current setting of the secret checkbox.
secret = (CtlGetValue (GetObjectPtr (DetailsSecretCheckbox)) != 0);
// Has the secret attribute was been changed?
if (((attr & dmRecAttrSecret) == dmRecAttrSecret) != secret)
{
if (secret)
{
attr |= dmRecAttrSecret;
if (PrivateRecordVisualStatus == showPrivateRecords)
FrmAlert (privateRecordInfoAlert);
}
else
attr &= ~dmRecAttrSecret;
dirty = true;
}
// Has the category been changed?
if (CurrentCategory != category)
{
attr &= ~dmRecAttrCategoryMask;
attr |= category;
dirty = true;
updateCode = updateCategoryChanged;
}
// If the current category was deleted, renamed, or merged with
// another category, then the list view needs to be redrawn.
if (categoryEdited)
{
CurrentCategory = category;
updateCode |= updateCategoryChanged;
}
if (dirty)
{
attr |= dmRecAttrDirty;
DmSetRecordInfo (MemoDB, CurrentRecord, &attr, NULL);
}
return (updateCode);
}
/***********************************************************************
*
* FUNCTION: DetailsInit
*
* DESCRIPTION: This routine initializes the Details Dialog.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 3/10/95 Initial Revision
*
***********************************************************************/
static void DetailsInit (void)
{
UInt16 attr;
UInt16 category;
Char* name;
Boolean secret;
ControlPtr ctl;
/* TRG */
PrvVgaAdjustModalForm(FrmGetActiveForm());
/* end TRG */
// Get the category and secret attribute of the current record.
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
category = attr & dmRecAttrCategoryMask;
secret = attr & dmRecAttrSecret;
// If the record is marked secret, turn on the secret checkbox.
ctl = GetObjectPtr (DetailsSecretCheckbox);
if (secret)
CtlSetValue (ctl, true);
else
CtlSetValue (ctl, false);
// Set the label of the category trigger.
ctl = GetObjectPtr (DetailsCategoryTrigger);
name = (Char *)CtlGetLabel (ctl);
CategoryGetName (MemoDB, category, name);
CategorySetTriggerLabel (ctl, name);
}
/***********************************************************************
*
* FUNCTION: DetailsHandleEvent
*
* DESCRIPTION: This routine is the event handler for the "Details
* Dialog Box".
*
* 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.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
*
***********************************************************************/
static Boolean DetailsHandleEvent (EventType * event)
{
static UInt16 category;
static Boolean categoryEdited;
UInt16 updateCode;
FormPtr frm;
Boolean handled = false;
if (event->eType == ctlSelectEvent)
{
switch (event->data.ctlSelect.controlID)
{
case DetailsOkButton:
updateCode = DetailsApply (category, categoryEdited);
FrmReturnToForm (EditView);
if (updateCode)
FrmUpdateForm (EditView, updateCode);
handled = true;
break;
case DetailsCancelButton:
if (categoryEdited)
FrmUpdateForm (EditView, updateCategoryChanged);
FrmReturnToForm (EditView);
handled = true;
break;
case DetailsDeleteButton:
if ( EditViewDeleteRecord ())
{
frm = FrmGetActiveForm();
FrmEraseForm (frm);
FrmDeleteForm (frm);
FrmCloseAllForms ();
FrmGotoForm (ListView);
}
handled = true;
break;
case DetailsCategoryTrigger:
categoryEdited = DetailsSelectCategory (&category) || categoryEdited;
handled = true;
break;
}
}
else if (event->eType == frmOpenEvent)
{
frm = FrmGetActiveForm ();
DetailsInit ();
FrmDrawForm (frm);
category = CurrentCategory;
categoryEdited = false;
handled = true;
}
return (handled);
}
#pragma mark ----
/***********************************************************************
*
* FUNCTION: EditViewSetTitle
*
* DESCRIPTION: This routine formats and sets the title of the Edit View.
* If the Edit View is visible, the new title is drawn.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* HISTORY:
* 02/21/95 art Created by Art Labm.
* 08/31/00 kwk Re-wrote to use TxtParamString, versus hard-coding
* order of elements using '#' in template string.
* 11/22/00 FPa Added DmReleaseResource()
* 11/28/00 CS Use FrmSetTitle instead of FrmCopyTitle and leave it
* allocated until EditViewExit. This removes the
* dependency that the form title in the resource has to
* be wide enough to accomodate the longest possible title.
* 11/30/00 FPa Fixed bug #46014
*
***********************************************************************/
static void EditViewSetTitle (void)
{
MemHandle titleTemplateH;
Char * titleTemplateP;
Char * title;
Char * oldTitle;
Char posStr[maxStrIToALen + 1];
Char totalStr[maxStrIToALen + 1];
UInt16 pos;
FormType* formP;
formP = FrmGetFormPtr(EditView);
// If there's an old title, we must free it; nevertheless FrmSetTitle() uses the old title -> we need to free it *after* having called FrmSetTitle()
oldTitle = (Char*)FrmGetTitle(formP);
// Format as strings, the memo's postion within its category, and
// the total number of memos in the category.
pos = DmPositionInCategory( MemoDB,CurrentRecord, ShowAllCategories ? dmAllCategories : CurrentCategory);
StrIToA(posStr, pos+1);
StrIToA(totalStr, MemosInCategory);
titleTemplateH = DmGetResource(strRsc, EditTitleString);
titleTemplateP = MemHandleLock(titleTemplateH);
title = TxtParamString(titleTemplateP, posStr, totalStr, NULL, NULL); // title needs to be freed
FrmSetTitle(formP, title);
if (oldTitle != 0)
MemPtrFree(oldTitle);
MemHandleUnlock(titleTemplateH);
DmReleaseResource(titleTemplateH);
}
/***********************************************************************
*
* FUNCTION: EditViewSelectCategory
*
* DESCRIPTION: This routine recategorizes a memo in the "Edit View".
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* The following global variables are modified:
* CurrentCategory
* CategoryName
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 10/03/95 Initial Revision
* grant 86/29/99 Adjust MemosInCategory when the record is private
* gap 08/13/99 Update to use new constant categoryDefaultEditCategoryString.
*
***********************************************************************/
static void EditViewSelectCategory (void)
{
UInt16 attr;
FormPtr frm;
UInt16 category;
Boolean categorySelected;
Boolean categoryEdited;
// Get the current category.
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
category = attr & dmRecAttrCategoryMask;
// Process the category popup list.
frm = FrmGetActiveForm();
categoryEdited = CategorySelect (MemoDB, frm, EditCategoryTrigger,
EditCategoryList, false, &category, CategoryName, 1, categoryDefaultEditCategoryString);
categorySelected = category != (attr & dmRecAttrCategoryMask);
// If a different category was selected, set the category field
// in the new record.
if (categorySelected)
{
// Change the category of the record.
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
attr &= ~dmRecAttrCategoryMask;
attr |= category | dmRecAttrDirty;
DmSetRecordInfo (MemoDB, CurrentRecord, &attr, NULL);
}
// If the current category was changed or the name of the category
// was edited, draw the title.
if (categoryEdited || categorySelected)
{
ChangeCategory (category);
// If the record is secret and secret records are hidden, then the record isn't
// accounted for by MemosInCategory. Adjust it, and EditViewSaveRecord will
// adjust when done with the record.
if ((PrivateRecordVisualStatus == hidePrivateRecords) && (attr & dmRecAttrSecret))
MemosInCategory++;
EditViewSetTitle ();
}
}
/***********************************************************************
*
* FUNCTION: EditViewUpdateScrollBar
*
* DESCRIPTION: This routine update the scroll bar.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 07/01/96 Initial Revision
* gap 11/02/96 Fix case where field and scroll bars get out of sync
*
***********************************************************************/
static void EditViewUpdateScrollBar ()
{
UInt16 scrollPos;
UInt16 textHeight;
UInt16 fieldHeight;
Int16 maxValue;
FieldPtr fld;
ScrollBarPtr bar;
fld = GetObjectPtr (EditMemoField);
bar = GetObjectPtr (EditMemoScrollBar);
FldGetScrollValues (fld, &scrollPos, &textHeight, &fieldHeight);
if (textHeight > fieldHeight)
{
// On occasion, such as after deleting a multi-line selection of text,
// the display might be the last few lines of a field followed by some
// blank lines. To keep the current position in place and allow the user
// to "gracefully" scroll out of the blank area, the number of blank lines
// visible needs to be added to max value. Otherwise the scroll position
// may be greater than maxValue, get pinned to maxvalue in SclSetScrollBar
// resulting in the scroll bar and the display being out of sync.
maxValue = (textHeight - fieldHeight) + FldGetNumberOfBlankLines (fld);
}
else if (scrollPos)
maxValue = scrollPos;
else
maxValue = 0;
SclSetScrollBar (bar, scrollPos, 0, maxValue, fieldHeight-1);
}
/***********************************************************************
*
* FUNCTION: EditViewLoadRecord
*
* DESCRIPTION: This routine loads a memo record into the Edit View form.
*
* PARAMETERS: frm - pointer to the Edit View form
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
* roger 6/24/99 Fixup MemosInCategory when the record is private
* peter 4/25/00 Add support for un-masking just the selected record.
*
***********************************************************************/
static void EditViewLoadRecord (FormPtr frm)
{
UInt16 attr;
FieldPtr fld;
ControlPtr ctl;
MemHandle memoRec;
Boolean capsLock, numLock, autoShifted;
UInt16 tempShift;
if ((GrfGetState(&capsLock, &numLock, &tempShift, &autoShifted) == 0)
&& (autoShifted))
{
GrfSetState(capsLock, numLock, false);
}
// Get a pointer to the memo field.
fld = FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, EditMemoField));
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
// Get the current record.
memoRec = DmGetRecord (MemoDB, CurrentRecord);
ErrFatalDisplayIf ((! memoRec), "Bad record");
// Set the font used by the memo field.
FldSetFont (fld, EditFont);
FldSetTextHandle (fld, memoRec);
FldSetScrollPosition (fld, EditScrollPosition);
// Set the global variable that keeps track of the current category
// to the category of the current record.
CurrentCategory = attr & dmRecAttrCategoryMask;
// If the record is secret and secret records are hidden, then the record isn't
// accounted for by MemosInCategory. Adjust it, and EditViewSaveRecord will
// adjust when done with the record.
if ((PrivateRecordVisualStatus == hidePrivateRecords) && (attr & dmRecAttrSecret))
MemosInCategory++;
// Set the view's title
EditViewSetTitle ();
// Set the label that contains the note's category.
ctl = GetObjectPtr (EditCategoryTrigger);
CategoryGetName (MemoDB, CurrentCategory, CategoryName);
CategorySetTriggerLabel (ctl, CategoryName);
EditViewUpdateScrollBar ();
}
/***********************************************************************
*
* FUNCTION: EditViewSaveRecord
*
* DESCRIPTION: This routine save a memo record to the memo database or
* deletes it if it's empty.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
* kcr 11/16/95 use DmReleaseRecord to set dirty attribute
* jmp 9/29/99 Use FrmGetFormPtr() & FrmGetObjectIndex() instead of
* GetObjectPtr() because GetObjectPtr() calls FrmGetActiveForm(),
* and FrmGetActiveForm() may return a form that isn't the one we
* want when other forms are up when we are called.
* Fixes bug #22418.
*
***********************************************************************/
static void EditViewSaveRecord (void)
{
UInt16 attr;
Char * ptr;
Boolean empty;
Boolean dirty;
FieldPtr fld;
FormPtr frm;
// Find out if the field has been modified or if it's empty.
frm = FrmGetFormPtr (EditView);
fld = FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, EditMemoField));
ptr = FldGetTextPtr (fld);
dirty = FldDirty (fld);
empty = (*ptr == 0);
FldReleaseFocus (fld);
// Release any free space in the memo field.
FldCompactText (fld);
// Clear the handle value in the field, otherwise the handle
// will be free when the form is disposed of.
FldSetTextHandle (fld, 0);
// If there's data in an existing record, mark it dirty if
// necessary and release it.
if (! empty)
{
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
if (PrivateRecordVisualStatus == hidePrivateRecords && (attr & dmRecAttrSecret))
MemosInCategory--;
DmReleaseRecord (MemoDB, CurrentRecord, dirty);
// Move the current record to the correct sort position.
if (dirty)
MemoSortRecord (MemoDB, &CurrentRecord);
}
// If the record is empty, delete it.
else
{
if (dirty)
{
DmDeleteRecord (MemoDB, CurrentRecord);
DmMoveRecord (MemoDB, CurrentRecord, DmNumRecords (MemoDB));
}
else
DmRemoveRecord (MemoDB, CurrentRecord);
CurrentRecord = noRecordSelected;
MemosInCategory--;
}
ErrNonFatalDisplayIf(MemosInCategory > DmNumRecords(MemoDB), "invalid MemosInCategory");
}
/***********************************************************************
*
* FUNCTION: EditViewChangeFont
*
* DESCRIPTION: This routine redisplay the memo in the font specified.
* It is called when one of the font push-buttons is presed.
*
* PARAMETERS: controlID - id to button pressed.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
* kcr 10/20/95 handles two-button font change mechanism
*
***********************************************************************/
static void EditViewChangeFont (void)
{
FontID fontID;
FieldPtr fld;
// Call the OS font selector to get the id of a font.
fontID = FontSelect (EditFont);
if (fontID != EditFont)
{
EditFont = fontID;
// FldSetFont will redraw the field if it is visible.
fld = GetObjectPtr (EditMemoField);
FldSetFont (fld, fontID);
}
EditViewUpdateScrollBar ();
}
/***********************************************************************
*
* FUNCTION: EditViewDeleteRecord
*
* DESCRIPTION: This routine deletes a memo record..
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
*
***********************************************************************/
static Boolean EditViewDeleteRecord (void)
{
FormPtr frm;
FieldPtr fld;
Char * ptr;
UInt16 ctlIndex;
UInt16 buttonHit;
FormPtr alert;
Boolean empty;
Boolean saveBackup;
frm = FrmGetFormPtr (EditView);
fld = FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, EditMemoField));
// Find out if the field is empty.
ptr = FldGetTextPtr (fld);
empty = (*ptr == 0);
// Display an alert to confirm the operation.
if (!empty)
{
alert = FrmInitForm (DeleteMemoDialog);
/* TRG */
PrvVgaAdjustModalForm(alert);
/* end TRG */
ctlIndex = FrmGetObjectIndex (alert, DeleteMemoSaveBackup);
FrmSetControlValue (alert, ctlIndex, SaveBackup);
buttonHit = FrmDoDialog (alert);
saveBackup = FrmGetControlValue (alert, ctlIndex);;
FrmDeleteForm (alert);
if (buttonHit == DeleteMemoCancel)
return (false);
SaveBackup = saveBackup;
}
// Clear the handle value in the field, otherwise the handle
// will be free when the form is disposed of.
FldSetTextHandle (fld, 0);
// Delete or archive the record.
if (empty && (! FldDirty (fld)))
{
DmRemoveRecord (MemoDB, CurrentRecord);
}
else
{
if (SaveBackup)
DmArchiveRecord (MemoDB, CurrentRecord);
else
DmDeleteRecord (MemoDB, CurrentRecord);
DmMoveRecord (MemoDB, CurrentRecord, DmNumRecords (MemoDB));
}
MemosInCategory--;
CurrentRecord = noRecordSelected;
ErrNonFatalDisplayIf(MemosInCategory > DmNumRecords(MemoDB), "invalid MemosInCategory");
return (true);
}
/***********************************************************************
*
* FUNCTION: EditViewDoCommand
*
* DESCRIPTION: This routine performs the menu command specified.
*
* PARAMETERS: command - menu item id
*
* RETURNED: True if we handled the command.
*
* HISTORY:
* 03/29/95 art Created by Art Lamb.
* 11/07/95 kcr converted to common about box
* 08/21/99 kwk Deleted page top/bottom commands.
* 11/04/99 jmp To prevent other sublaunch issues, remind ourselves
* that we've sublaunched already into PhoneNumberLookup().
*
***********************************************************************/
static Boolean EditViewDoCommand (UInt16 command)
{
FieldPtr fld;
FormPtr frm;
Boolean handled = true;
switch (command)
{
case NewMemoCmd:
EditViewSaveRecord ();
CreateRecord ();
EditScrollPosition = 0;
if (CurrentRecord != noRecordSelected)
{
EditViewLoadRecord (FrmGetActiveForm ());
fld = GetFocusObjectPtr ();
if (fld) FldGrabFocus (fld);
}
else
FrmGotoForm (ListView);
break;
case DeleteMemoCmd:
if (EditViewDeleteRecord ())
FrmGotoForm (ListView);
break;
case BeamMemoCmd:
case SendMemoCmd:
fld = GetObjectPtr (EditMemoField);
if (FldGetTextLength(fld) > 0)
{
EditViewSaveRecord();
MemoSendRecord(MemoDB, CurrentRecord, (command == BeamMemoCmd ? exgBeamPrefix : exgSendPrefix));
// Redisplay the record. If the IR loopback mechanism sends the
// record to this app the goto action code closes all forms and
// send a frmGotoEvent. Load the record again only if the form
// still exits.
frm = FrmGetActiveForm ();
if (frm)
EditViewLoadRecord (frm);
}
else
FrmAlert(NoDataToBeamAlert);
break;
/*
case BeamCategoryCmd:
case SendCategoryCmd:
fld = GetObjectPtr (EditMemoField);
if (FldGetTextLength(fld) > 0)
{
FldCompactText (fld);
MemoSendCategory(MemoDB, CurrentCategory, (command == BeamCategoryCmd ? exgBeamPrefix : exgSendPrefix), (command == BeamCategoryCmd ? NoDataToBeamAlert : NoDataToSendAlert));
}
else
FrmAlert(NoDataToBeamAlert);
break;
*/
case EditOptionsFontsCmd:
EditViewChangeFont ();
break;
case EditOptionPhoneLookupCmd:
fld = GetObjectPtr (EditMemoField);
if (fld)
{
InPhoneLookup = true;
PhoneNumberLookup (fld);
InPhoneLookup = false;
}
break;
case EditOptionsAboutCmd:
AbtShowAbout (sysFileCMemo);
break;
default:
handled = false;
}
return (handled);
}
/***********************************************************************
*
* FUNCTION: EditViewScroll
*
* DESCRIPTION: This routine scrolls the memo edit view a page or a
* line at a time.
*
* PARAMETERS: linesToScroll - the number of lines to scroll,
* positive for winDown,
* negative for winUp
* updateScrollbar - force a scrollbar update?
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 7/1/96 Initial Revision
* grant 2/4/99 Use EditViewUpdateScrollBar()
*
***********************************************************************/
static void EditViewScroll (Int16 linesToScroll, Boolean updateScrollbar)
{
UInt16 blankLines;
FieldPtr fld;
fld = GetObjectPtr (EditMemoField);
blankLines = FldGetNumberOfBlankLines (fld);
if (linesToScroll < 0)
FldScrollField (fld, -linesToScroll, winUp);
else if (linesToScroll > 0)
FldScrollField (fld, linesToScroll, winDown);
// If there were blank lines visible at the end of the field
// then we need to update the scroll bar.
if (blankLines || updateScrollbar)
{
ErrNonFatalDisplayIf(blankLines && linesToScroll > 0, "blank lines when scrolling winDown");
EditViewUpdateScrollBar();
}
}
/***********************************************************************
*
* FUNCTION: EditViewPageScroll
*
* DESCRIPTION: This routine scrolls the message a page winUp or winDown.
* When the top of a memo is visible, scrolling up will
* display the display the botton of the previous memo.
* If the bottom of a memo is visible, scrolling down will
* display the top of the next memo.
*
* PARAMETERS: direction winUp or winDown
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 7/1/96 Initial Revision
* grant 2/4/99 Use EditViewScroll() to do actual scrolling.
*
***********************************************************************/
static void EditViewPageScroll (WinDirectionType direction)
{
Int16 seekDirection;
UInt16 category;
UInt16 recordNum;
UInt32 uniqueID;
UInt16 linesToScroll;
FieldPtr fld;
UInt16 attr;
fld = GetObjectPtr (EditMemoField);
if (FldScrollable (fld, direction))
{
linesToScroll = FldGetVisibleLines (fld) - 1;
if (direction == winUp)
linesToScroll = -linesToScroll;
EditViewScroll(linesToScroll, true);
return;
}
// Move to the next or previous memo.
if (direction == winUp)
{
seekDirection = dmSeekBackward;
EditScrollPosition = maxFieldTextLen;
}
else
{
seekDirection = dmSeekForward;
EditScrollPosition = 0;
}
if (ShowAllCategories)
category = dmAllCategories;
else
category = CurrentCategory;
recordNum = CurrentRecord;
//while to skip masked records. Even if the body never executes, we'll have done a DmSeekRecordInCategory
while (!DmSeekRecordInCategory (MemoDB, &recordNum, 1, seekDirection, category) &&
!DmRecordInfo (MemoDB, recordNum, &attr, NULL, NULL) &&
((attr & dmRecAttrSecret) && PrivateRecordVisualStatus == maskPrivateRecords))
{
}
if (recordNum == CurrentRecord) return;
// Don't show first/last record if it's private and we're masking.
if (!DmRecordInfo (MemoDB, recordNum, &attr, NULL, NULL) &&
((attr & dmRecAttrSecret) && PrivateRecordVisualStatus == maskPrivateRecords))
return;
SndPlaySystemSound (sndInfo);
// Saving the current record may cause it to move if the records are
// sorted alphabeticly.
DmRecordInfo (MemoDB, recordNum, NULL, &uniqueID, NULL);
EditViewSaveRecord ();
DmFindRecordByID (MemoDB, uniqueID, &CurrentRecord);
EditViewLoadRecord (FrmGetActiveForm ());
FldGrabFocus (fld);
}
/***********************************************************************
*
* FUNCTION: EditViewExit
*
* DESCRIPTION: This routine is call when the Edit View is exited. It
* releases any memory allocated for the Edit View.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 3/17/95 Initial Revision
*
***********************************************************************/
static void EditViewExit (void)
{
FormPtr frm;
void * title;
// Free the title string.
frm = FrmGetActiveForm ();
title = (void *)FrmGetTitle (frm);
if (title)
{
MemPtrFree(title);
}
}
/***********************************************************************
*
* FUNCTION: EditViewInit
*
* DESCRIPTION: This routine initials the Edit View form.
*
* PARAMETERS: frm - pointer to the Edit View form.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 3/31/95 Initial Revision
* art 7/1/96 Set field hasScrollBar attribute
* FPa 11/30/96 Set title to 0
*
***********************************************************************/
static void EditViewInit (FormPtr frm)
{
FieldPtr fld;
FieldAttrType attr;
// Have the field send event to maintain the scroll bar.
fld = GetObjectPtr (EditMemoField);
FldGetAttributes (fld, &attr);
attr.hasScrollBar = true;
FldSetAttributes (fld, &attr);
FrmSetTitle(frm, 0); // To avoid a crash into EditViewSetTitle when trying to free the old title
EditViewLoadRecord (frm);
CurrentView = EditView;
}
/***********************************************************************
*
* FUNCTION: EditViewUpdateDisplay
*
* DESCRIPTION: This routine update the display of the edit view
*
* PARAMETERS: updateCode - a code that indicated what changes have been
* made to the view.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 10/3/95 Initial Revision
*
***********************************************************************/
static Boolean EditViewUpdateDisplay (UInt16 updateCode)
{
UInt16 attr;
UInt16 category;
if (updateCode == updateCategoryChanged)
{
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
category = attr & dmRecAttrCategoryMask;
ChangeCategory (category);
// If we are editing a secret record and secret records are hidden
// then increment the record count so that the correct record count
// is shown.
if (PrivateRecordVisualStatus == hidePrivateRecords && (attr & dmRecAttrSecret))
MemosInCategory++;
// Set the title of the edit view.
EditViewSetTitle ();
// Set the label of the category trigger.
CategoryGetName (MemoDB, CurrentCategory, CategoryName);
CategorySetTriggerLabel (GetObjectPtr (EditCategoryTrigger),
CategoryName);
return (true);
}
return (false);
}
/***********************************************************************
*
* FUNCTION: EditViewHandleEvent
*
* DESCRIPTION: This routine is the event handler for the "Edit View"
* of the Memo application.
*
* PARAMETERS: event - a pointer to an EventType structure
*
* RETURNED: true if the event has handled and should not be passed
* to a higher level handler.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 02/21/95 Initial Revision.
* kwk 10/04/98 Explicitly disable Graffiti auto-shift if we get
* a printable key-down event.
* kwk 11/21/98 Handle cmd keys in separate code block, so TxtCharIsPrint
* doesn't get called w/virtual key codes.
* gap 10/27/00 change the command bar initialization to allow field
* code to add cut, copy, paste, & undo commands as
* appropriate rather than adding a fixed set of selections.
* CS 11/28/00 Call EditViewExit in response to frmCloseEvent.
*
***********************************************************************/
static Boolean EditViewHandleEvent (EventType * event)
{
FormPtr frm;
Boolean handled = false;
FieldPtr fldP;
UInt32 numLibs;
if (event->eType == keyDownEvent)
{
if (TxtCharIsHardKey(event->data.keyDown.modifiers, event->data.keyDown.chr))
{
EditViewSaveRecord ();
FrmGotoForm (ListView);
handled = true;
}
else if (EvtKeydownIsVirtual(event))
{
if (event->data.keyDown.chr == vchrPageUp)
{
EditViewPageScroll (winUp);
handled = true;
}
else if (event->data.keyDown.chr == vchrPageDown)
{
EditViewPageScroll (winDown);
handled = true;
}
// Send data key presed?
else if (event->data.keyDown.chr == vchrSendData)
{
if (FldGetTextLength(GetObjectPtr (EditMemoField)) > 0)
{
EditViewSaveRecord();
MemoSendRecord(MemoDB, CurrentRecord, exgBeamPrefix);
// Redisplay the record. If the IR loopback mechanism sends the
// record to this app the goto action code closes all forms and
// send a frmGotoEvent. Load the record again only if the form
// still exits.
frm = FrmGetActiveForm ();
if (frm)
EditViewLoadRecord (frm);
}
else
FrmAlert(NoDataToBeamAlert);
handled = true;
}
/* TRG */
else if ((event->data.keyDown.chr == chrEscape) ||
(event->data.keyDown.chr == chrCarriageReturn))
{
EditViewSaveRecord ();
FrmGotoForm (ListView);
handled = true;
}
/* end TRG */
}
// If we get a printable character, then we can assume that any Graffiti
// auto-shifting is finished, so it's safe to turn it off. This solves the
// problem of a re-queued keydown event (e.g. when in list view & writing
// a character -> generate a new memo) not turning off the temp shift state
// because it wasn't created by Graffiti.
// DOLATER kwk - figure out if this is the best way to handle auto-shift
// problem with creation of memo from list view (input method coordination).
// Better would be for the field code to turn off auto-shift when it handles
// insertion or a keydown event.
// LFe: This is done now by the field.
/*
else if (TxtCharIsPrint(event->data.keyDown.chr))
{
Boolean capsLock, numLock, autoShifted;
UInt16 tempShift;
if ((GrfGetState(&capsLock, &numLock, &tempShift, &autoShifted) == 0)
&& (autoShifted))
{
GrfSetState(capsLock, numLock, false);
}
}
*/
}
else if (event->eType == ctlSelectEvent)
{
switch (event->data.ctlSelect.controlID)
{
case EditCategoryTrigger:
EditViewSelectCategory ();
handled = true;
break;
case EditDoneButton:
EditViewSaveRecord ();
FrmGotoForm (ListView);
handled = true;
break;
case EditDetailsButton:
FrmPopupForm (DetailsDialog);
handled = true;
break;
}
}
else if (event->eType == menuOpenEvent)
{
if (ExgGetRegisteredApplications(NULL, &numLibs, NULL, NULL, exgRegSchemeID, exgSendScheme) || !numLibs)
MenuHideItem(SendMemoCmd);
else
MenuShowItem(SendMemoCmd);
// don't set handled = true
}
else if (event->eType == menuEvent)
{
handled = EditViewDoCommand (event->data.menu.itemID);
}
// Add the buttons that we want available on the command bar, based on the current context
else if (event->eType == menuCmdBarOpenEvent)
{
UInt16 startPos, endPos;
FieldType* fldP;
fldP = GetObjectPtr (EditMemoField);
FldGetSelection(fldP, &startPos, &endPos);
if (startPos == endPos) // there's no highlighted text
{
// Call directly Field event handler so that System Edit buttons are added
FldHandleEvent(fldP, event);
// Beam on the left
MenuCmdBarAddButton(menuCmdBarOnLeft, BarBeamBitmap, menuCmdBarResultMenuItem, BeamMemoCmd, 0);
// Delete on the Right
MenuCmdBarAddButton(menuCmdBarOnRight, BarDeleteBitmap, menuCmdBarResultMenuItem, DeleteMemoCmd, 0);
// Prevent the field package to automatically add cut, copy, paste, and undo buttons as applicable
// since it was done previously
event->data.menuCmdBarOpen.preventFieldButtons = true;
}
// don't set handled to true; this event must fall through to the system.
}
else if (event->eType == frmOpenEvent)
{
frm = FrmGetActiveForm ();
/* TRG */
if (vgaExists)
VgaFormModify(frm, vgaFormModify160To240);
EditViewResizeForm(frm, false);
/* end TRG */
EditViewInit (frm);
FrmDrawForm (frm);
FrmSetFocus (frm, FrmGetObjectIndex (frm, EditMemoField));
handled = true;
}
else if (event->eType == frmGotoEvent)
{
frm = FrmGetActiveForm ();
/* TRG */
if (vgaExists)
VgaFormModify(frm, vgaFormModify160To240);
EditViewResizeForm(frm, false);
/* end TRG */
CurrentRecord = event->data.frmGoto.recordNum;
EditViewInit (frm);
fldP = GetObjectPtr (EditMemoField);
FldSetScrollPosition(fldP, event->data.frmGoto.matchPos);
FldSetSelection(fldP, event->data.frmGoto.matchPos,
event->data.frmGoto.matchPos + event->data.frmGoto.matchLen);
EditViewUpdateScrollBar ();
FrmDrawForm (frm);
FrmSetFocus (frm, FrmGetObjectIndex (frm, EditMemoField));
handled = true;
}
else if (event->eType == frmUpdateEvent)
{
handled = EditViewUpdateDisplay (event->data.frmUpdate.updateCode);
}
else if (event->eType == fldChangedEvent)
{
frm = FrmGetActiveForm ();
EditViewUpdateScrollBar ();
handled = true;
}
else if (event->eType == frmCloseEvent)
{
FormPtr frm;
frm = FrmGetFormPtr (EditView);
if ( FldGetTextHandle (FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, EditMemoField))))
EditViewSaveRecord (); // This deletes empty memos.
EditViewExit();
}
else if (event->eType == sclRepeatEvent)
{
EditViewScroll (event->data.sclRepeat.newValue -
event->data.sclRepeat.value, false);
}
/* TRG */
else if (event->eType == displayExtentChangedEvent)
{
EditViewResizeForm(FrmGetActiveForm(), true);
handled = true;
}
/* end TRG */
return (handled);
}
/* TRG */
/***********************************************************************
*
* FUNCTION: EditViewResizeForm
*
* DESCRIPTION: This routine resizes the y extent of the form for
* virtual silk support.
*
* PARAMETERS: frmP - pointer to EditView form
* draw - if we can draw to the form at this time or not.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* DanF 3/04/01 Initial Revision
*
***********************************************************************/
static void EditViewResizeForm(FormPtr frmP, Boolean draw)
{
Coord x, y;
Coord xDiff, yDiff;
RectangleType r;
FieldPtr fldP;
UInt16 tmpPos, tmpStart, tmpEnd;
UInt16 objIdx;
// this will get the new extent
WinGetDisplayExtent(&x, &y);
// this will get the old extent
FrmGetFormBounds(frmP, &r);
xDiff = x - (r.topLeft.x + r.extent.x);
yDiff = y - (r.topLeft.y + r.extent.y);
if ((xDiff == 0) && (yDiff == 0))
return;
// resize form
r.extent.x += xDiff;
r.extent.y += yDiff;
WinSetWindowBounds(FrmGetWindowHandle(frmP), &r);
// resize field (save and restore insertion state around it)
if (draw)
{
fldP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, EditMemoField));
FldGetSelection(fldP, &tmpStart, &tmpEnd);
if (InsPtEnabled() || (tmpStart != tmpEnd))
tmpPos = FldGetInsPtPosition(fldP);
else
tmpPos = -1;
}
//Adjust Table
PrvResizeObject(frmP, FrmGetObjectIndex(frmP, EditMemoField), xDiff, yDiff, draw);
// Adjust scrollbar
PrvMoveObject(frmP, FrmGetObjectIndex(frmP, EditMemoScrollBar), xDiff, 0, false);
PrvResizeObject(frmP, FrmGetObjectIndex(frmP, EditMemoScrollBar), 0, yDiff, draw);
if(xDiff != 0)
{
PrvMoveObject(frmP, FrmGetObjectIndex(frmP, EditCategoryTrigger), xDiff, 0, draw); //do not double draw
PrvMoveObject(frmP, FrmGetObjectIndex(frmP, EditCategoryList), xDiff, 0, draw); //do not double draw
}
// move done button
PrvMoveObject(frmP, FrmGetObjectIndex(frmP, EditDoneButton), 0, yDiff, draw);
// move details button
PrvMoveObject(frmP, FrmGetObjectIndex(frmP, EditDetailsButton), 0, yDiff, draw);
// Adjust GSI
objIdx = PrvFrmGetGSI(frmP);
PrvMoveObject(frmP, objIdx, xDiff, yDiff, draw);
// You need to set the GSI's location as well as it's location on the form
// for everything to work properly.
FrmGetObjectPosition(frmP, objIdx, &x, &y);
GsiSetLocation(x + xDiff, y+yDiff);
if (draw)
{
if (tmpPos != -1)
{
// restore the selection, this will make sure the cursor is still visible
fldP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, EditMemoField));
FldSetInsPtPosition(fldP, tmpPos);
FldSendChangeNotification(fldP);
FldSetSelection(fldP, tmpStart, tmpEnd);
}
FrmDrawForm(frmP);
}
}
/* end TRG */
#pragma mark ----
/***********************************************************************
*
* FUNCTION: ListViewDoCommand
*
* DESCRIPTION: This routine performs the menu command specified.
*
* PARAMETERS: command - menu item id
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 3/29/95 Initial Revision
* kcr 11/7/95 converted to common about box
* jmp 10/02/99 Changed call to DmOpenDatabaseByTypeCreator() to
* MemoGetDatabase().
* jmp 03/19/00 Fixed bug #23669: Adjust the number of memos currently
* available so that scrollbar will be updated correctly
* after a change in security level.
*
***********************************************************************/
static void ListViewDoCommand (UInt16 command)
{
Boolean wasHiding;
UInt32 currentRecordID;
UInt16 mode;
switch (command)
{
case ListOptionsFontsCmd:
ListFont = SelectFont(ListFont);
break;
case ListRecordBeamCategoryCmd:
MemoSendCategory(MemoDB, CurrentCategory, exgBeamPrefix, NoDataToBeamAlert);
break;
case ListRecordSendCategoryCmd:
MemoSendCategory(MemoDB, CurrentCategory, exgSendPrefix, NoDataToSendAlert);
break;
case ListOptionsSecurityCmd:
wasHiding = (PrivateRecordVisualStatus == hidePrivateRecords);
PrivateRecordVisualStatus = SecSelectViewStatus();
if (wasHiding ^ (PrivateRecordVisualStatus == hidePrivateRecords)) //xor on two logical values - mode to open DB has changed
{
// Close the application's data file.
MemoSavePrefs(0);
DmCloseDatabase(MemoDB);
mode = (PrivateRecordVisualStatus == hidePrivateRecords) ?
dmModeReadWrite : (dmModeReadWrite | dmModeShowSecret);
MemoGetDatabase(&MemoDB, mode);
ErrFatalDisplayIf(!MemoDB,"Can't reopen DB");
// Read the preferences.
MemoLoadPrefs(&currentRecordID);
// Adjust the number of memos currently available so the scrollbar will be updated correctly.
if (ShowAllCategories)
MemosInCategory = DmNumRecordsInCategory(MemoDB, dmAllCategories);
else
MemosInCategory = DmNumRecordsInCategory(MemoDB, CurrentCategory);
}
//For safety, simply reset the currentRecord
CurrentRecord = noRecordSelected;
ListViewUpdateDisplay(updateDisplayOptsChanged);
break;
case ListOptionsPreferencesCmd:
FrmPopupForm (PreferencesDialog);
break;
case ListOptionsAboutCmd:
MenuEraseStatus(CurrentMenu);
AbtShowAbout(sysFileCMemo);
break;
}
}
/***********************************************************************
*
* FUNCTION: ListViewNumberOfRows
*
* DESCRIPTION: This routine return the maximun number of visible rows,
* with the current list view font setting.
*
* PARAMETERS: table - List View table
*
* RETURNED: maximun number of displayable rows
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 8/28/97 Initial Revision
*
***********************************************************************/
static UInt16 ListViewNumberOfRows (TablePtr table)
{
UInt16 rows;
UInt16 rowsInTable;
UInt16 tableHeight;
FontID currFont;
RectangleType r;
rowsInTable = TblGetNumberOfRows (table);
TblGetBounds (table, &r);
tableHeight = r.extent.y;
currFont = FntSetFont (ListFont);
rows = tableHeight / FntLineHeight ();
FntSetFont (currFont);
if (rows <= rowsInTable)
return (rows);
else
return (rowsInTable);
}
/***********************************************************************
*
* FUNCTION: ListViewDrawRecord
*
* DESCRIPTION: This routine draws the title memo record in the list
* view. This routine is called by the table routine,
* TblDrawTable, each time a line of the table needs to
* be drawn.
*
* PARAMETERS: table - pointer to the memo list table (TablePtr)
* row - row of the table to draw
* column - column of the table to draw
* bounds - bound to the draw region
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
* ADH 7/21/99 Increased the size of the posStr character array
* to allow for display of five digit numbers.
* Previously only four digit numbers could be
* displayed.
* ryw 1/11/01 use global TopRowPositionInCategory to determine numbering
*
***********************************************************************/
static void ListViewDrawRecord (void * table, Int16 row, Int16 UNUSED_PARAM(column),
RectanglePtr bounds)
{
UInt16 len;
UInt16 category;
UInt16 recordNum;
MemHandle memoH;
Int16 x, y;
Char * memoP;
UInt16 pos;
// this string should handle up to "99999." but does not have to be 0 terminated when the . is added
char posStr[6];
UInt16 attr;
RectangleType maskRectangle;
// Get the record number that corresponds to the table item to draw.
// The record number is stored in the "intValue" field of the item.
recordNum = TblGetRowID (table, row);
DmRecordInfo (MemoDB, recordNum, &attr, NULL, NULL);
// If the record is private and we are to hide private records, then get out of here.
// This should be taken care of by the calling function, but we will go ahead and
// take care of it here also.
if ((attr & dmRecAttrSecret) && PrivateRecordVisualStatus == hidePrivateRecords)
{
return;
}
x = bounds->topLeft.x + 1;
y = bounds->topLeft.y;
FntSetFont (ListFont);
// Format the memo's postion, within its category, an draw it.
if (ShowAllCategories)
category = dmAllCategories;
else
category = CurrentCategory;
//pos = DmPositionInCategory (MemoDB, recordNum, category);
pos = TopRowPositionInCategory + row;
StrIToA (posStr, pos+1);
len = StrLen(posStr);
// Warning if more than 99999 record (5 chars)
ErrNonFatalDisplayIf(len > sizeof(posStr) - 1, "Too many records");
posStr[len++] = '.';
// This string does not need 0 termination for up to the end of the function. So the size is ok
if (len < 3) x += FntCharWidth ('1');
WinDrawChars (posStr, len, x, y);
x += FntCharsWidth (posStr, len) + 4;
// If we are here then we either we either mask the memo out or display the
// memo title.
if (((attr & dmRecAttrSecret) && PrivateRecordVisualStatus == maskPrivateRecords))
{
MemMove (&maskRectangle, bounds, sizeof (RectangleType));
maskRectangle.topLeft.x = x;
maskRectangle.extent.x = bounds->extent.x - x;
//If next row is masked, thicken rect so as to keep boundary at 1 pixel.
/* // THIS CODE REMOVED because people didn't like combining the masks together.
if (TblGetLastUsableRow(table) > row)
{
DmRecordInfo (MemoDB, TblGetRowID (table, row+1), &attr, NULL, NULL);
if (attr & dmRecAttrSecret)
maskRectangle.extent.y++;
}
*/
ListViewDisplayMask (&maskRectangle);
}
else
{
// Display the memo's title, the title is the first line of the memo.
memoH = DmQueryRecord(MemoDB, recordNum);
memoP = MemHandleLock(memoH);
DrawMemoTitle (memoP, x, y, bounds->extent.x - x);
MemHandleUnlock(memoH);
}
}
/***********************************************************************
*
* FUNCTION: ListViewDisplayMask
*
* DESCRIPTION: Draws the masked display for the record.
*
* PARAMETERS: bounds (Input): The bounds of the table item to display.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* css 06/21/99 Initial Revision
*
***********************************************************************/
static void ListViewDisplayMask (RectanglePtr bounds)
{
RectangleType tempRect;
CustomPatternType origPattern;
MemHandle bitmapH;
BitmapType * bitmapP;
CustomPatternType pattern = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
MemMove (&tempRect, bounds, sizeof (RectangleType));
// Make sure it fits nicely into the display.
tempRect.topLeft.y++;
tempRect.extent.y --;
/* TRG */
if (vgaExists && VgaIsVgaFont(ListFont))
tempRect.extent.x -= SecLockWidth + ((SecLockWidth+1)>>1) + 1;
else
tempRect.extent.x -= SecLockWidth + 1;
/* end TRG */
WinGetPattern(&origPattern);
WinSetPattern (&pattern);
WinFillRectangle (&tempRect, 0);
WinSetPattern(&origPattern);
//draw lock icon
//draw lock icon
/* TRG */
if (vgaExists && VgaIsVgaFont(ListFont))
bitmapH = DmGetResource (bitmapRsc, SecLockBitmap+0x1000);
else
bitmapH = DmGetResource (bitmapRsc, SecLockBitmap);
/* end TRG */
if (bitmapH)
{
bitmapP = MemHandleLock (bitmapH);
WinDrawBitmap (bitmapP, tempRect.topLeft.x + tempRect.extent.x + 1,
tempRect.topLeft.y + ((tempRect.extent.y - SecLockHeight) / 2));
MemPtrUnlock (bitmapP);
}
}
/***********************************************************************
*
* FUNCTION: ListViewUpdateScrollers
*
* DESCRIPTION: This routine draws or erases the list view scroll arrow
* buttons.
*
* PARAMETERS: frm - pointer to the to do list form
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 5/1/95 Initial Revision
*
***********************************************************************/
static void ListViewUpdateScrollers (FormPtr UNUSED_PARAM(frm))
{
UInt16 pos;
Int16 rows;
UInt16 maxValue;
rows = ListViewNumberOfRows (GetObjectPtr(ListTable));
if (MemosInCategory > rows)
{
pos = DmPositionInCategory (MemoDB, TopVisibleRecord, CurrentCategory);
maxValue = MemosInCategory - rows;
}
else
{
pos = 0;
maxValue = 0;
}
SclSetScrollBar (GetObjectPtr (ListScrollBar), pos, 0, maxValue, rows);
}
/***********************************************************************
*
* FUNCTION: ListViewLoadTable
*
* DESCRIPTION: This routine loads memo database records into
* the list view form.
*
* PARAMETERS: recordNum index of the first record to display.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/16/95 Initial Revision
* grant 1/29/99 Set the heights of unused rows
* ryw 1/11/01 update global TopRowPositionInCategory on table load
*
***********************************************************************/
static void ListViewLoadTable (FormPtr frm)
{
UInt16 row;
UInt16 recordNum;
UInt16 lineHeight;
UInt16 dataHeight;
UInt16 tableHeight;
UInt16 numRows;
UInt32 uniqueID;
FontID currFont;
TablePtr table;
MemHandle recordH;
RectangleType r;
table = GetObjectPtr (ListTable);
TblGetBounds (table, &r);
tableHeight = r.extent.y;
currFont = FntSetFont (ListFont);
lineHeight = FntLineHeight ();
FntSetFont (currFont);
dataHeight = 0;
recordNum = TopVisibleRecord;
// For each row in the table, store the record number in the table item
// that will dispaly the record.
numRows = TblGetNumberOfRows (table);
for (row = 0; row < numRows; row++)
{
// Get the next record in the currunt category.
recordH = DmQueryNextInCategory (MemoDB, &recordNum, CurrentCategory);
if(row == 0)
{
// store the position of the first row so we can use TopRowPositionInCategory+row
// when drawing
TopRowPositionInCategory = recordH ? DmPositionInCategory(MemoDB, recordNum, CurrentCategory) : 0;
}
// If the record was found, store the record number in the table item,
// otherwise set the table row unusable.
if (recordH && (tableHeight >= dataHeight + lineHeight))
{
TblSetRowID (table, row, recordNum);
TblSetItemStyle (table, row, 0, customTableItem);
TblSetItemFont (table, row, 0, ListFont);
TblSetRowHeight (table, row, lineHeight);
DmRecordInfo (MemoDB, recordNum, NULL, &uniqueID, NULL);
if ((TblGetRowData (table, row) != uniqueID) ||
( ! TblRowUsable (table, row)))
{
TblSetRowUsable (table, row, true);
// Store the unique id of the record in the row.
TblSetRowData (table, row, uniqueID);
// Mark the row invalid so that it will draw when we call the
// draw routine.
TblMarkRowInvalid (table, row);
}
if (row+1 < numRows) recordNum++;
dataHeight += lineHeight;
}
else
{
// Set the row height - when scrolling winDown, the heights of the last rows of
// the table are used to determine how far to scroll. As rows are deleted
// from the top of the table, formerly unused rows scroll into view, and the
// height is used before the next call to ListViewLoadTable (which would set
// the height correctly).
TblSetRowHeight (table, row, lineHeight);
TblSetRowUsable (table, row, false);
}
}
// Update the scroll arrows.
ListViewUpdateScrollers (frm);
}
/***********************************************************************
*
* FUNCTION: ListViewLoadRecords
*
* DESCRIPTION: This routine loads memo database records into
* the list view form.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/16/95 Initial Revision
*
***********************************************************************/
static void ListViewLoadRecords (FormPtr frm)
{
TablePtr table;
UInt16 recordNum;
UInt16 rowsInTable;
if (ShowAllCategories)
CurrentCategory = dmAllCategories;
table = FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, ListTable));
rowsInTable = ListViewNumberOfRows (table);
// Is the current record before the first visible record?
if (CurrentRecord != noRecordSelected)
{
if (TopVisibleRecord > CurrentRecord)
TopVisibleRecord = CurrentRecord;
// Is the current record after the last visible record?
else
{
recordNum = TopVisibleRecord;
DmSeekRecordInCategory (MemoDB, &recordNum, rowsInTable-1,
dmSeekForward, CurrentCategory);
if (recordNum < CurrentRecord)
TopVisibleRecord = CurrentRecord;
}
}
// Make sure we show a full display of records.
if (MemosInCategory)
{
recordNum = dmMaxRecordIndex;
DmSeekRecordInCategory (MemoDB, &recordNum, (rowsInTable-1),
dmSeekBackward, CurrentCategory);
TopVisibleRecord = min (TopVisibleRecord, recordNum);
}
else
TopVisibleRecord = 0;
ListViewLoadTable (frm);
// Set the callback routine that will draw the records.
TblSetCustomDrawProcedure (table, 0, ListViewDrawRecord);
TblSetColumnUsable (table, 0, true);
}
/***********************************************************************
*
* FUNCTION: ListViewSelectCategory
*
* DESCRIPTION: This routine handles selection, creation and deletion of
* categories form the Details Dialog.
*
* PARAMETERS: nothing
*
* RETURNED: The index of the new category.
*
* The following global variables are modified:
* CurrentCategory
* ShowAllCategories
* CategoryName
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 03/10/95 Initial Revision
* gap 08/13/99 Update to use new constant categoryDefaultEditCategoryString.
*
***********************************************************************/
static UInt16 ListViewSelectCategory (void)
{
FormPtr frm;
TablePtr table;
UInt16 category;
Boolean categoryEdited;
// Process the category popup list.
category = CurrentCategory;
frm = FrmGetActiveForm();
categoryEdited = CategorySelect (MemoDB, frm, ListCategoryTrigger,
ListCategoryList, true, &category, CategoryName, 1, categoryDefaultEditCategoryString);
if (category == dmAllCategories)
ShowAllCategories = true;
else
ShowAllCategories = false;
if (categoryEdited || (category != CurrentCategory))
{
ChangeCategory (category);
// Display the new category.
ListViewLoadRecords (frm);
table = GetObjectPtr (ListTable);
TblEraseTable (table);
TblDrawTable (table);
}
return (category);
}
/***********************************************************************
*
* FUNCTION: ListViewNextCategory
*
* DESCRIPTION: This routine display the next category, if the last
* catagory isn't being displayed
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* The following global variables are modified:
* CurrentCategory
* ShowAllCategories
* CategoryName
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 9/15/95 Initial Revision
*
***********************************************************************/
static void ListViewNextCategory (void)
{
UInt16 category;
FormPtr frm;
TablePtr table;
ControlPtr ctl;
category = CategoryGetNext (MemoDB, CurrentCategory);
if (category != CurrentCategory)
{
if (category == dmAllCategories)
ShowAllCategories = true;
else
ShowAllCategories = false;
ChangeCategory (category);
// Set the label of the category trigger.
ctl = GetObjectPtr (ListCategoryTrigger);
CategoryGetName (MemoDB, CurrentCategory, CategoryName);
CategorySetTriggerLabel (ctl, CategoryName);
// Display the new category.
TopVisibleRecord = 0;
frm = FrmGetActiveForm ();
ListViewLoadTable (frm);
table = GetObjectPtr (ListTable);
TblEraseTable (table);
TblDrawTable (table);
}
}
/***********************************************************************
*
* FUNCTION: ListViewPageScroll
*
* DESCRIPTION: This routine scrolls the list of of memo titles
* in the direction specified.
*
* PARAMETERS: direction - winUp or dowm
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
* roger 7/27/95 Copied fixed code from Address Book
*
***********************************************************************/
static void ListViewPageScroll (WinDirectionType direction)
{
TablePtr table;
Int16 rowsInTable;
UInt16 newTopVisibleRecord;
table = GetObjectPtr (ListTable);
rowsInTable = ListViewNumberOfRows (table);
newTopVisibleRecord = TopVisibleRecord;
CurrentRecord = noRecordSelected;
// Scroll the table winDown a page (less one row).
if (direction == winDown)
{
// Try going forward one page
if (!SeekRecord (&newTopVisibleRecord, rowsInTable - 1, dmSeekForward))
{
// Try going backwards one page from the last record
newTopVisibleRecord = dmMaxRecordIndex;
if (!SeekRecord (&newTopVisibleRecord, rowsInTable - 1, dmSeekBackward))
{
// Not enough records to fill one page. Start with the first record
newTopVisibleRecord = 0;
SeekRecord (&newTopVisibleRecord, 0, dmSeekForward);
}
}
}
// Scroll up a page (less one row).
else
{
if (!SeekRecord (&newTopVisibleRecord, rowsInTable - 1, dmSeekBackward))
{
// Not enough records to fill one page. Start with the first record
newTopVisibleRecord = 0;
SeekRecord (&newTopVisibleRecord, 0, dmSeekForward);
}
}
// Avoid redraw if no change
if (TopVisibleRecord != newTopVisibleRecord)
{
/* TRG */
selectedItem = -1;
/* end TRG */
TopVisibleRecord = newTopVisibleRecord;
ListViewLoadRecords (FrmGetActiveForm ());
TblRedrawTable(table);
}
}
/***********************************************************************
*
* FUNCTION: ListViewScroll
*
* DESCRIPTION: This routine scrolls the list of of memo titles
* in the direction specified.
*
* PARAMETERS: direction - winUp or dowm
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
* roger 7/27/95 Copied fixed code from Address Book
*
***********************************************************************/
static void ListViewScroll (Int16 linesToScroll)
{
Int16 i;
UInt16 rows;
UInt16 lastRow;
UInt16 scrollAmount;
UInt16 newTopVisibleRecord;
TablePtr table;
RectangleType scrollR;
RectangleType vacated;
WinDirectionType direction;
table = GetObjectPtr (ListTable);
CurrentRecord = noRecordSelected;
// Find the new top visible record
newTopVisibleRecord = TopVisibleRecord;
// Scroll down.
if (linesToScroll > 0)
SeekRecord (&newTopVisibleRecord, linesToScroll, dmSeekForward);
// Scroll up.
else if (linesToScroll < 0)
SeekRecord (&newTopVisibleRecord, -linesToScroll, dmSeekBackward);
ErrFatalDisplayIf (TopVisibleRecord == newTopVisibleRecord,
"Invalid scroll value");
TopVisibleRecord = newTopVisibleRecord;
// Move the bits that will remain visible.
rows = ListViewNumberOfRows (table);
if (((linesToScroll > 0) && (linesToScroll < rows)) ||
((linesToScroll < 0) && (-linesToScroll < rows)))
{
scrollAmount = 0;
if (linesToScroll > 0)
{
lastRow = TblGetLastUsableRow (table) - 1;
for (i = 0; i < linesToScroll; i++)
{
scrollAmount += TblGetRowHeight (table, lastRow);
TblRemoveRow (table, 0);
}
direction = winUp;
}
else
{
for (i = 0; i < -linesToScroll; i++)
{
scrollAmount += TblGetRowHeight (table, 0);
TblInsertRow (table, 0);
}
direction = winDown;
}
TblGetBounds (table, &scrollR);
WinScrollRectangle (&scrollR, direction, scrollAmount, &vacated);
WinEraseRectangle (&vacated, 0);
}
ListViewLoadTable (FrmGetActiveForm ());
TblRedrawTable(table);
/* TRG */
if (selectedItem != -1)
ListViewSelectTableItem(true, table, selectedItem, 0, &vacated);
/* end TRG */
}
/***********************************************************************
*
* FUNCTION: ListViewInit
*
* DESCRIPTION: This routine initializes the "List View" of the
* Memo application.
*
* PARAMETERS: event - a pointer to an EventType structure
*
* RETURNED: nothing.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
*
***********************************************************************/
static void ListViewInit (FormPtr frm)
{
ControlPtr ctl;
/* TRG */
selectedItem = -1;
/* end TRG */
ListViewLoadRecords (frm);
// Set the label of the category trigger.
ctl = GetObjectPtr (ListCategoryTrigger);
CategoryGetName (MemoDB, CurrentCategory, CategoryName);
CategorySetTriggerLabel (ctl, CategoryName);
CurrentView = ListView;
}
/***********************************************************************
*
* FUNCTION: ListViewInvertMoveIndicator
*
* DESCRIPTION: If draw is true, then save the area behind the rectangle,
* then draw the indicator there. If draw is false, then restore
* the screen bits.
*
*
* PARAMETERS: itemR - bounds of the move indicator
* savedBits - if draw is true, then restore this window of bits at
* itemR.
* draw - draw or erase the move indicator.
*
* RETURNED: WinHandle - handle to a saved window of screen bits, if the move
* indicator is visible. Otherwise, the value is 0.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 1/29/96 Initial Revision
*
***********************************************************************/
static WinHandle ListViewInvertMoveIndicator (RectanglePtr itemR, WinHandle savedBits,
Boolean draw)
{
UInt16 i;
UInt16 err;
WinHandle winH = 0;
RectangleType indictatorR;
CustomPatternType pattern;
CustomPatternType savedPattern;
indictatorR.topLeft.x = itemR->topLeft.x;
indictatorR.topLeft.y = itemR->topLeft.y + itemR->extent.y - 2;
indictatorR.extent.x = itemR->extent.x;
indictatorR.extent.y = 2;
if (draw)
{
WinGetPattern (&savedPattern);
for (i = 0; i < sizeof (CustomPatternType) / sizeof (*pattern); i++)
pattern[i]= 0xAA55;
WinSetPattern (&pattern);
winH = WinSaveBits (&indictatorR, &err);
WinFillRectangle (&indictatorR, 0);
WinSetPattern (&savedPattern);
}
else
{
WinRestoreBits (savedBits, indictatorR.topLeft.x, indictatorR.topLeft.y);
}
return (winH);
}
/***********************************************************************
*
* FUNCTION: ListViewSelectTableItem
*
* DESCRIPTION: This routine either selects or unselects the specified
* table item.
*
* PARAMETERS: selected - specifies whether an item should be selected or
* unselected
* table - pointer to a table object
* row - row of the item (zero based)
* column - column of the item (zero based)
* rP - pointer to a structure that will hold the bound
* of the item
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* jmp 10/29/99 Initial Revision
* jmp 11/12/99 While a table item is "on the move," having it be selected
* can cause the Table code grief. So, instead of using
* the TblSelectItem()/TblUnhighlightSelect() calls, we now
* manually select/unselect the table's row. Before color,
* only WinInvertRectangle() was called, so this is now in line
* again with the way things used to work. Sigh.
*
***********************************************************************/
static void ListViewSelectTableItem (Boolean selected, TablePtr table, Int16 row, Int16 column, RectangleType *r)
{
// Get the item's rectangle.
//
TblGetItemBounds (table, row, column, r);
// Set up the drawing state the way we want it.
//
WinPushDrawState();
WinSetBackColor(UIColorGetTableEntryIndex(UIFieldBackground));
WinSetForeColor(UIColorGetTableEntryIndex(UIObjectForeground));
WinSetTextColor(UIColorGetTableEntryIndex(UIObjectForeground));
// Erase and (re)draw the item.
//
WinEraseRectangle(r, 0);
ListViewDrawRecord(table, row, column, r);
// If selected, make it look that way.
//
if (selected)
ReplaceTwoColors (r, 0,
UIObjectForeground, UIFieldBackground,
UIObjectSelectedForeground, UIObjectSelectedFill);
// Restore the previous drawing state.
//
WinPopDrawState();
}
/***********************************************************************
*
* FUNCTION: ListViewSelectMemo
*
* DESCRIPTION: This routine tracks a Memo item for either selection
* to go to EditView, or movement in the ListView.
*
*
* PARAMETERS: event
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 1/29/96 Initial Revision
* jmp 10/29/99 Replaced WinInvertRectangle() calls with calls to
* ListViewSelectTableItem() to eliminate general
* color inversion problem.
* peter 4/25/00 Add support for un-masking just the selected record.
* gap 06/06/00 Correct what appears to be a copy/paste error. When
* row < 0, the row was properly incremented but the
* y value of the move indicator was decremented causing the
* tracking line to draw up across the title area of the form.
*
***********************************************************************/
static void ListViewSelectMemo (EventType * event)
{
Int16 sortOrder;
Int16 row;
Int16 selectedRow;
Int16 column;
UInt16 recordNum;
Int16 selectedRecord;
Coord x, y;
Boolean penDown = true;
Boolean moving = false;
Boolean selected = true;
TablePtr table;
WinHandle savedBits;
RectangleType r;
UInt16 attr;
sortOrder = MemoGetSortOrder (MemoDB);
row = event->data.tblSelect.row;
column = event->data.tblSelect.column;
table = event->data.tblSelect.pTable;
// Highlight the item the pen when winDown on.
selectedRecord = TblGetRowID (table, row);
ListViewSelectTableItem (selected, table, row, column, &r);
// Trace the pen until it move enough to constitute a move operation or until
// the pen it released.
while (true)
{
PenGetPoint (&x, &y, &penDown);
if (! penDown) break;
if (! moving)
{
if (sortOrder != soAlphabetic)
{
// Is the pen still within the bounds of the item it went winDown on,
// if not draw the move indicator.
if (! RctPtInRectangle (x, y, &r))
{
moving = true;
TblGetItemBounds (table, row, column, &r);
savedBits = ListViewInvertMoveIndicator (&r, 0, true);
}
}
else
selected = RctPtInRectangle (x, y, &r);
}
else if (! RctPtInRectangle (x, y, &r))
{
// Above the first item ?
if (row < 0)
{
if (y >= r.topLeft.y)
{
row++;
ListViewInvertMoveIndicator (&r, savedBits, false);
r.topLeft.y += r.extent.y;
savedBits = ListViewInvertMoveIndicator (&r, 0, true);
}
}
// Move winUp.
else if (y < r.topLeft.y)
{
recordNum = TblGetRowID (table, row);
if (SeekRecord (&recordNum, 1, dmSeekBackward))
{
ListViewInvertMoveIndicator (&r, savedBits, false);
if (row)
row--;
else
{
ListViewScroll (-1);
if (TblFindRowID (table, selectedRecord, &selectedRow))
ListViewSelectTableItem (selected, table, selectedRow, column, &r);
}
TblGetItemBounds (table, row, column, &r);
savedBits = ListViewInvertMoveIndicator (&r, 0, true);
}
else if (row == 0)
{
row--;
ListViewInvertMoveIndicator (&r, savedBits, false);
r.topLeft.y -= r.extent.y;
savedBits = ListViewInvertMoveIndicator (&r, 0, true);
}
}
// Move winDown
else
{
recordNum = TblGetRowID (table, row);
if (SeekRecord (&recordNum, 1, dmSeekForward))
{
ListViewInvertMoveIndicator (&r, savedBits, false);
if (row < TblGetLastUsableRow (table))
row++;
else
{
ListViewScroll (1);
if (TblFindRowID (table, selectedRecord, &selectedRow))
ListViewSelectTableItem (selected, table, selectedRow, column, &r);
}
TblGetItemBounds (table, row, column, &r);
savedBits = ListViewInvertMoveIndicator (&r, 0, true);
}
}
}
}
// Turn off the move indicator, if it is on.
if (moving)
{
savedBits = ListViewInvertMoveIndicator (&r, savedBits, false);
}
// If the highlighted item is visible, unhighlight it.
if (TblFindRowID (table, selectedRecord, &selectedRow))
ListViewSelectTableItem (false, table, selectedRow, column, &r);
if (moving)
{
if (row >= 0)
{
recordNum = TblGetRowID (table, row);
if (selectedRecord == recordNum)
return;
recordNum++;
}
else
{
recordNum = TblGetRowID (table, 0);;
}
DmMoveRecord (MemoDB, selectedRecord, recordNum);
/* Was
if (selectedRecord < TopVisibleRecord)
TopVisibleRecord--;
CurrentRecord = recordNum;
ListViewLoadTable (FrmGetActiveForm());
*/
ListViewLoadRecords (FrmGetActiveForm());
TblRedrawTable (table);
}
// If we didn't move the item then it's been selected for editing, go to the
// edit view.
else if (sortOrder != soAlphabetic || selected)
{
CurrentRecord = TblGetRowID (event->data.tblSelect.pTable,
event->data.tblSelect.row);
EditScrollPosition = 0;
// Get the category and secret attribute of the current record.
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
// If this is a "private" record, then determine what is to be shown.
if (attr & dmRecAttrSecret)
{
switch (PrivateRecordVisualStatus)
{
case showPrivateRecords:
FrmGotoForm (EditView);
break;
case maskPrivateRecords:
if (SecVerifyPW (showPrivateRecords) == true)
{
// We only want to unmask this one record, so restore the preference.
PrefSetPreference (prefShowPrivateRecords, maskPrivateRecords);
FrmGotoForm (EditView);
}
break;
// This case should never be executed!!!!!!!
case hidePrivateRecords:
default:
break;
}
}
else
{
FrmGotoForm (EditView);
}
}
}
/***********************************************************************
*
* FUNCTION: ListViewUpdateDisplay
*
* DESCRIPTION: This routine update the display of the list view
*
* PARAMETERS: updateCode - a code that indicated what changes have been
* made to the view.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 7/19/95 Initial Revision
*
***********************************************************************/
static Boolean ListViewUpdateDisplay (UInt16 updateCode)
{
TablePtr table;
if (updateCode & (updateDisplayOptsChanged | updateFontChanged))
{
if (updateCode & updateDisplayOptsChanged)
TopVisibleRecord = 0;
ListViewLoadRecords (FrmGetActiveForm());
table = GetObjectPtr (ListTable);
TblEraseTable (table);
TblDrawTable (table);
return (true);
}
return (false);
}
/***********************************************************************
*
* FUNCTION: ListViewHandleEvent
*
* DESCRIPTION: This routine is the event handler for the "List View"
* of the Memo application.
*
* PARAMETERS: event - a pointer to an EventType structure
*
* RETURNED: true if the event was handled and should not be passed
* to a higher level handler.
*
* HISTORY:
* 02/21/95 art Created by Art Lamb.
* 11/22/98 kwk Handle command keys in separate code block so that
* TxtCharIsPrint doesn't get called w/virtual chars.
* 09/25/99 kwk Use TxtGlueUpperChar to capitalize initial char for
* memo that's autocreated by writing a printable char.
*
***********************************************************************/
static Boolean ListViewHandleEvent (EventPtr event)
{
FormPtr frm;
Boolean handled = false;
UInt16 attr;
UInt32 numLibs;
if (event->eType == keyDownEvent)
{
// Memo button pressed?
if (TxtCharIsHardKey(event->data.keyDown.modifiers, event->data.keyDown.chr))
{
if (!(event->data.keyDown.modifiers & poweredOnKeyMask))
ListViewNextCategory ();
handled = true;
}
else if (EvtKeydownIsVirtual(event))
{
// Scroll up key presed?
if (event->data.keyDown.chr == vchrPageUp)
{
ListViewPageScroll (winUp);
handled = true;
}
// Scroll down key presed?
else if (event->data.keyDown.chr == vchrPageDown)
{
ListViewPageScroll (winDown);
handled = true;
}
// Send Data key presed?
else if (event->data.keyDown.chr == vchrSendData)
{
ListViewDoCommand(ListRecordSendCategoryCmd);
handled = true;
}
/* TRG */
else if (event->data.keyDown.chr == chrCarriageReturn)
{
if (selectedItem != -1)
{
CurrentRecord = TblGetRowID (GetObjectPtr(ListTable), selectedItem);
EditScrollPosition = 0;
// Get the category and secret attribute of the current record.
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
selectedItem = -1;
// If this is a "private" record, then determine what is to be shown.
if (attr & dmRecAttrSecret)
{
switch (PrivateRecordVisualStatus)
{
case showPrivateRecords:
FrmGotoForm (EditView);
break;
case maskPrivateRecords:
if (SecVerifyPW (showPrivateRecords) == true)
{
PrivateRecordVisualStatus = showPrivateRecords;
FrmGotoForm (EditView);
}
break;
// This case should never be executed!!!!!!!
case hidePrivateRecords:
default:
break;
}
}
else
{
FrmGotoForm (EditView);
}
}
handled = true;
}
else if (event->data.keyDown.chr == vchrNextField)
{
TablePtr tblP;
RectangleType r;
Int16 pos;
if (DmNumRecordsInCategory(MemoDB, CurrentCategory) == 0)
return true;
tblP = (TablePtr)GetObjectPtr(ListTable);
if (selectedItem == TblGetLastUsableRow(tblP))
{
ListViewSelectTableItem(false, tblP, selectedItem, 0, &r);
pos = DmPositionInCategory (MemoDB, TopVisibleRecord, CurrentCategory);
if ((TblGetLastUsableRow(tblP) + pos+1) < MemosInCategory)
ListViewScroll(1);
}
else if (selectedItem > TblGetLastUsableRow(tblP)) // can happen with silk/font changes
selectedItem = TblGetLastUsableRow(tblP);
else if (selectedItem != -1)
ListViewSelectTableItem(false, tblP, selectedItem, 0, &r);
if (selectedItem < TblGetLastUsableRow(tblP))
selectedItem++;
if (selectedItem != -1)
{
ListViewSelectTableItem(true, tblP, selectedItem, 0, &r);
handled = true;
}
}
else if (event->data.keyDown.chr == vchrPrevField)
{
TablePtr tblP;
RectangleType r;
Int16 pos;
if (DmNumRecordsInCategory(MemoDB, CurrentCategory) == 0)
return true;
tblP = (TablePtr)GetObjectPtr(ListTable);
if (selectedItem == 0)
{
ListViewSelectTableItem(false, tblP, selectedItem, 0, &r);
pos = DmPositionInCategory (MemoDB, TopVisibleRecord, CurrentCategory);
if (pos != 0)
ListViewScroll(-1);
}
else if (selectedItem > TblGetLastUsableRow(tblP)) // can happen with silk/font changes
selectedItem = -1;
else if (selectedItem != -1)
ListViewSelectTableItem(false, tblP, selectedItem, 0, &r);
if ((selectedItem == -1) && (MemosInCategory > 0))
selectedItem = 0;
if (selectedItem > 0)
selectedItem--;
if (selectedItem != -1)
{
ListViewSelectTableItem(true, tblP, selectedItem, 0, &r);
handled = true;
}
}
}
/* end TRG */
// If printable character, create a new record.
else if (TxtCharIsPrint (event->data.keyDown.chr))
{
if (CreateRecord ())
{
FrmGotoForm (EditView);
event->data.keyDown.chr = TxtGlueUpperChar(event->data.keyDown.chr);
EvtAddEventToQueue (event);
}
handled = true;
}
}
else if (event->eType == ctlSelectEvent)
{
switch (event->data.ctlSelect.controlID)
{
case ListNewButton:
if (CreateRecord ())
FrmGotoForm (EditView);
handled = true;
break;
case ListCategoryTrigger:
ListViewSelectCategory ();
handled = true;
break;
}
}
else if (event->eType == tblEnterEvent)
{
ListViewSelectMemo (event);
handled = true;
}
else if (event->eType == tblSelectEvent)
{
// An item in the list of memos was selected, display it.
CurrentRecord = TblGetRowID (event->data.tblSelect.pTable,
event->data.tblSelect.row);
EditScrollPosition = 0;
// Get the category and secret attribute of the current record.
DmRecordInfo (MemoDB, CurrentRecord, &attr, NULL, NULL);
// If this is a "private" record, then determine what is to be shown.
if (attr & dmRecAttrSecret)
{
switch (PrivateRecordVisualStatus)
{
case showPrivateRecords:
FrmGotoForm (EditView);
break;
case maskPrivateRecords:
// FrmGotoForm (); TODO XXXX
break;
// This case should never be executed!!!!!!!
case hidePrivateRecords:
default:
break;
}
}
else
{
FrmGotoForm (EditView);
}
handled = true;
}
else if (event->eType == menuOpenEvent)
{
if (ExgGetRegisteredApplications(NULL, &numLibs, NULL, NULL, exgRegSchemeID, exgSendScheme) || !numLibs)
MenuHideItem(ListRecordSendCategoryCmd);
else
MenuShowItem(ListRecordSendCategoryCmd);
// don't set handled = true
}
else if (event->eType == menuEvent)
{
ListViewDoCommand (event->data.menu.itemID);
return (true);
}
else if (event->eType == frmOpenEvent)
{
frm = FrmGetActiveForm ();
/* TRG */
if (vgaExists)
{
VgaFormModify(frm, vgaFormModify160To240);
VgaTableUseBaseFont(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, ListTable)),
!VgaIsVgaFont(ListFont));
}
ListViewResizeForm(frm, false);
/* end TRG */
ListViewInit (frm);
FrmDrawForm (frm);
handled = true;
}
else if (event->eType == menuCmdBarOpenEvent)
{
MenuCmdBarAddButton(menuCmdBarOnLeft, BarSecureBitmap, menuCmdBarResultMenuItem, ListOptionsSecurityCmd, 0);
// tell the field package to not add buttons automatically; we've done it all ourselves.
event->data.menuCmdBarOpen.preventFieldButtons = true;
// don't set handled to true; this event must fall through to the system.
}
else if (event->eType == frmUpdateEvent)
{
handled = ListViewUpdateDisplay (event->data.frmUpdate.updateCode);
}
else if (event->eType == sclRepeatEvent)
{
ListViewScroll (event->data.sclRepeat.newValue -
event->data.sclRepeat.value);
}
/* TRG */
else if (event->eType == displayExtentChangedEvent)
{
ListViewResizeForm(FrmGetActiveForm(), true);
handled = true;
}
/* end TRG */
return (handled);
}
/* TRG */
/***********************************************************************
*
* FUNCTION: ListViewResizeForm
*
* DESCRIPTION: This routine resizes the y extent of the form for
* virtual silk support.
*
* PARAMETERS: frmP - pointer to ListView form
* draw - if we can draw to the form at this time or not.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* DanF 3/04/01 Initial Revision
*
***********************************************************************/
static void ListViewResizeForm(FormPtr frmP, Boolean draw)
{
Coord x, y;
Coord xDiff, yDiff;
RectangleType r, tableR;
TablePtr tblP;
// this will get the new extent
WinGetDisplayExtent(&x, &y);
// this will get the old extent
FrmGetFormBounds(frmP, &r);
xDiff = x - (r.topLeft.x + r.extent.x);
yDiff = y - (r.topLeft.y + r.extent.y);
if ((xDiff==0) && (yDiff == 0))
return;
// resize form
r.extent.x += xDiff;
r.extent.y += yDiff;
if ((xDiff > 0) || (yDiff > 0)) // only resize here if growing
WinSetWindowBounds(FrmGetWindowHandle(frmP), &r);
// adjust table
//PrvResizeObject(frmP, FrmGetObjectIndex(frmP, ListTable), xDiff, yDiff, draw);
tblP = GetObjectPtr(ListTable);
TblGetBounds(tblP, &tableR);
tableR.extent.x += xDiff;
tableR.extent.y += yDiff;
TblSetBounds(tblP, &tableR);
if(draw && (yDiff < 0))
{
tableR.topLeft.y = (tableR.topLeft.y + tableR.extent.y);
tableR.extent.y = -yDiff;
WinEraseRectangle (&tableR, 0);
}
//Only one column so do it here.
if(xDiff != 0)
{
x = TblGetColumnWidth (FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, ListTable)), 0);
TblSetColumnWidth (FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, ListTable)), 0, x + xDiff);
}
// adjust scrollbar
PrvMoveObject(frmP, FrmGetObjectIndex(frmP, ListScrollBar), xDiff, 0, false); //do not double draw
PrvResizeObject(frmP, FrmGetObjectIndex(frmP, ListScrollBar), 0, yDiff, draw);
if(xDiff != 0)
{
PrvMoveObject(frmP, FrmGetObjectIndex(frmP, ListCategoryTrigger), xDiff, 0, draw); //do not double draw
PrvMoveObject(frmP, FrmGetObjectIndex(frmP, ListCategoryList), xDiff, 0, draw); //do not double draw
}
// move new button
PrvMoveObject(frmP, FrmGetObjectIndex(frmP, ListNewButton), 0, yDiff, draw);
// don't resize form until here if shrinking so we can erase our old controls
WinSetWindowBounds(FrmGetWindowHandle(frmP), &r);
if (draw)
{
// ListViewLoadRecords() can scroll the table. We need to make sure
// we are still selecting the same item after we are all done, so save
// the current state.
if (selectedItem != -1)
selectedItem += TopVisibleRecord;
ListViewLoadRecords(frmP);
FrmDrawForm(frmP);
if (selectedItem != -1)
{
selectedItem -= TopVisibleRecord;
tblP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, ListTable));
if (selectedItem > TblGetLastUsableRow(tblP))
{
ListViewScroll(selectedItem - TblGetLastUsableRow(tblP));
selectedItem -= selectedItem - TblGetLastUsableRow(tblP);
}
ListViewSelectTableItem(true, tblP, selectedItem, 0, &r);
}
}
}
/* end TRG */
#pragma mark ----
/***********************************************************************
*
* FUNCTION: CustomAcceptBeamDialog
*
* DESCRIPTION: This routine uses uses a new exchange manager function to
* Ask the user if they want to accept the data as well as set
* the category to put the data in. By default all data will go
* to the unfiled category, but the user can select another one.
* We store the selected category index in the appData field of
* the exchange socket so we have it at the when we get the receive
* data launch code later.
*
* PARAMETERS: dbP - open database that holds category information
* askInfoP - structure passed on exchange ask launchcode
*
* RETURNED: Error if any
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* bhall 9/7/99 Initial Revision
* gavin 11/9/99 Rewritten to use new ExgDoDialog function
*
***********************************************************************/
static Err CustomAcceptBeamDialog(DmOpenRef dbP, ExgAskParamPtr askInfoP)
{
ExgDialogInfoType exgInfo;
Err err;
Boolean result;
// set default category to unfiled
exgInfo.categoryIndex = dmUnfiledCategory;
// Store the database ref into a gadget for use by the event handler
exgInfo.db = dbP;
// Let the exchange manager run the dialog for us
result = ExgDoDialog(askInfoP->socketP, &exgInfo, &err);
if (!err && result) {
// pretend as if user hit OK, we'll now accept the data
askInfoP->result = exgAskOk;
// Stuff the category index into the appData field
askInfoP->socketP->appData = exgInfo.categoryIndex;
} else {
// pretend as if user hit cancel, we won't accept the data
askInfoP->result = exgAskCancel;
}
return err;
}
/***********************************************************************
*
* FUNCTION: ApplicationHandleEvent
*
* DESCRIPTION: This routine loads form resources and sets the event
* handler for the form loaded.
*
* PARAMETERS: event - a pointer to an EventType structure
*
* RETURNED: true if the event was handled and should not be passed
* to a higher level handler.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 9/11/95 Initial Revision
*
***********************************************************************/
static Boolean ApplicationHandleEvent (EventType * event)
{
UInt16 formID;
FormPtr frm;
if (event->eType == frmLoadEvent)
{
// Load the form resource.
formID = event->data.frmLoad.formID;
frm = FrmInitForm (formID);
FrmSetActiveForm (frm);
// Set the event handler for the form. The handler of the currently
// active form is called by FrmHandleEvent each time it receives an
// event.
switch (formID)
{
case ListView:
FrmSetEventHandler (frm, ListViewHandleEvent);
break;
case EditView:
FrmSetEventHandler (frm, EditViewHandleEvent);
break;
case DetailsDialog:
FrmSetEventHandler (frm, DetailsHandleEvent);
break;
case PreferencesDialog:
FrmSetEventHandler (frm, PreferencesHandleEvent);
break;
}
return (true);
}
return (false);
}
/***********************************************************************
*
* FUNCTION: EventLoop
*
* DESCRIPTION: This routine is the event loop for the Memo
* aplication.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
*
***********************************************************************/
static void EventLoop (void)
{
UInt16 error;
EventType event;
do
{
EvtGetEvent (&event, evtWaitForever);
if (! SysHandleEvent (&event))
if (! MenuHandleEvent (CurrentMenu, &event, &error))
if (! ApplicationHandleEvent (&event))
FrmDispatchEvent (&event);
}
while (event.eType != appStopEvent);
}
/***********************************************************************
*
* FUNCTION: PilotMain
*
* DESCRIPTION: This is the main entry point for the Memo
* application.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
* art 1/3098 Removed sysAppLaunchCmdSaveData logic
* grant 6/25/99 In sysAppLaunchCmdInitDatabase, set the backup bit on the DB.
* In sysAppLaunchCmdExgReceiveData, update MemosInCategory.
* jmp 10/02/99 Made the support for the sysAppLaunchCmdExgReceiveData
* sysAppLaunchCmdExgAskUser launch codes more like their
* counterparts in Address, Databook, and ToDo.
* jmp 10/18/99 If the default "demo" database image doesn't exist, then
* create an empty database instead.
* jmp 11/04/99 Eliminate extraneous FrmSaveAllForms() call from sysAppLaunchCmdExgAskUser
* since it was already being done in sysAppLaunchCmdExgReceiveData if
* the user affirmed sysAppLaunchCmdExgAskUser. Also, in sysAppLaunchCmdExgReceiveData
* prevent call FrmSaveAllForms() if we're being call back through
* PhoneNumberLookup() as the two tasks are incompatible with each other.
*
***********************************************************************/
UInt32 PilotMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
{
UInt16 error;
DmOpenRef dbP;
if (cmd == sysAppLaunchCmdNormalLaunch)
{
error = StartApplication ();
if (error)
return (error);
FrmGotoForm (CurrentView);
EventLoop ();
StopApplication ();
}
else if (cmd == sysAppLaunchCmdFind)
{
Search ((FindParamsPtr)cmdPBP);
}
// This action code might be sent to the app when it's already running
// if the use hits the Find soft key next to the Graffiti area.
else if (cmd == sysAppLaunchCmdGoTo)
{
if (launchFlags & sysAppLaunchFlagNewGlobals)
{
error = StartApplication ();
if (error) return (error);
GoToItem ((GoToParamsPtr) cmdPBP, true);
EventLoop ();
StopApplication ();
}
else
GoToItem ((GoToParamsPtr) cmdPBP, false);
}
// Launch code sent to running app before sysAppLaunchCmdFind
// or other action codes that will cause data searches or manipulation.
// We don't need to respond to this launch code because memos are
// edited in place.
// else if (cmd == sysAppLaunchCmdSaveData)
// {
// FrmSaveAllForms ();
// }
// This launch code is sent after the system is reset. We use this time
// to create our default database. If there is no default database image,
// then we create an empty database.
else if (cmd == sysAppLaunchCmdSystemReset)
{
if (((SysAppLaunchCmdSystemResetType*)cmdPBP)->createDefaultDB)
{
error = CreateDefaultDatabase();
// Register to receive .txt and text/plain on hard reset.
RegisterData();
}
RegisterLocaleChangingNotification();
}
else if (cmd == sysAppLaunchCmdSyncNotify)
{
SyncNotification ();
}
else if (cmd == sysAppLaunchCmdExgAskUser)
{
// if our app is not active, we need to open the database
// the subcall flag is used here since this call can be made without launching the app
if (!(launchFlags & sysAppLaunchFlagSubCall))
{
error = MemoGetDatabase (&dbP, dmModeReadWrite);
}
else
dbP = MemoDB;
if (dbP != NULL)
{
CustomAcceptBeamDialog (dbP, (ExgAskParamPtr) cmdPBP);
if (!(launchFlags & sysAppLaunchFlagSubCall))
error = DmCloseDatabase(dbP);
}
}
// Present the user with ui to perform a lookup and return a string
// with information from the selected record.
else if (cmd == sysAppLaunchCmdExgReceiveData)
{
UInt16 numReceived = 0;
UInt32 currentUID;
// if our app is not active, we need to open the database
// the subcall flag is used here since this call can be made without launching the app
if (!(launchFlags & sysAppLaunchFlagSubCall))
error = MemoGetDatabase (&dbP, dmModeReadWrite);
else
{
dbP = MemoDB;
// We don't delete the current record if it's empty because the user
// could cancel the beam receive.
// MemoReceiveData() calls MemoSort(), which may change the index of
// the current record. So we remember its UID here, and refresh our
// copy of its index afterwards.
if (CurrentRecord != noRecordSelected)
DmRecordInfo(dbP, CurrentRecord, NULL, &currentUID, NULL);
}
if (dbP != NULL)
{
error = MemoReceiveData(dbP, (ExgSocketPtr) cmdPBP, &numReceived);
// We may have just added some memos to the current category.
// If the app is currently running, update MemosInCategory to reflect this.
if (launchFlags & sysAppLaunchFlagSubCall)
{
MemosInCategory += numReceived;
if (CurrentRecord != noRecordSelected)
{
if (DmFindRecordByID(dbP, currentUID, &CurrentRecord) != 0)
CurrentRecord = noRecordSelected; // Can't happen, but...
// DOLATER dje -
// To fix the off-by-one error, we can decrement exgSocketP->goToParams.recordNum
// if it's after the current empty record in order to compensate for the
// current empty record getting deleted when we exit before the goto launch.
}
}
else
DmCloseDatabase(dbP);
}
else
error = exgErrAppError; // DOLATER dje - use a new error code - "try again after switching apps"
// If we can't open our database, return the error since it wasn't passed to ExgDisconnect
return error;
}
else if(cmd == sysAppLaunchCmdExgPreview)
{
MemoTransferPreview((ExgPreviewInfoType *)cmdPBP);
}
// This action code is sent by the DesktopLink server when it create
// a new database. We will initializes the new database.
else if (cmd == sysAppLaunchCmdInitDatabase)
{
MemoAppInfoInit (((SysAppLaunchCmdInitDatabaseType*)cmdPBP)->dbP);
// Set the backup bit. This is to aid syncs with non Palm software.
SetDBBackupBit(((SysAppLaunchCmdInitDatabaseType*)cmdPBP)->dbP);
}
else if (cmd == sysAppLaunchCmdNotify)
{
if (((SysNotifyParamType*)cmdPBP)->notifyType == sysNotifyLocaleChangedEvent)
{
DmSearchStateType searchState;
LocalID dbID;
UInt16 cardNo;
// Since the locale has changed, delete the existing database
// and re-create it for the new locale
error = DmGetNextDatabaseByTypeCreator (true, &searchState, memoDBType,
sysFileCMemo, true, &cardNo, &dbID);
if (!error)
DmDeleteDatabase(cardNo, dbID);
error = CreateDefaultDatabase();
}
}
return (errNone);
}