📄 addredit.c
字号:
/******************************************************************************
*
* Copyright (c) 1995-2003 PalmSource, Inc. All rights reserved.
*
* File: AddrEdit.c
*
* Release: Palm OS 5 SDK (68K) R3.
*
* Description:
* This is the Address Book application's edit form module.
*
*****************************************************************************/
#include <TraceMgr.h>
#include <TextMgr.h>
#include <ErrorMgr.h>
#include <StringMgr.h>
#include <AboutBox.h>
#include <Category.h>
#include <Graffiti.h>
#include <Menu.h>
#include <UIResources.h>
#include <PalmUtils.h>
#include "AddrEdit.h"
#include "AddrDialList.h"
#include "Address.h"
#include "AddressAutoFill.h"
#include "AddressRsc.h"
#include "AddrDefines.h"
#include "AddrTools.h"
#include "AddrDetails.h"
#include "AddrNote.h"
#include "AddressTransfer.h"
/***********************************************************************
*
* Defines
*
***********************************************************************/
#define addrEditLabelFont stdFont
#define addrEditBlankFont stdFont
#define noFieldIndex 0xff
// Address edit table's rows and columns
#define editLabelColumn 0
#define editDataColumn 1
#define spaceBeforeDesc 2
#define editLastFieldIndex 17
#define isPhoneField(f) (f >= firstPhoneField && f <= lastPhoneField)
#define editInvalidRow ((UInt16) 0xFFFF)
#define kAutoFillConstantID 1800
#define kDontUseAutoFill 0
#define ADDR_FOCUS_FIX
/***********************************************************************
*
* Global variables
*
***********************************************************************/
static UInt16 CurrentFieldIndex;
// global to remember the row of the last tapped tel label
static UInt16 CurrentTableRow;
// The following structure maps row in the edit table to fields in the
// address record. This controls the order in which fields are edited.
// Valid after PrvEditInit.
static const AddressFields* FieldMap;
static MemHandle FieldMapH;
// Valid after PrvEditInit
static Char * EditPhoneListChoices[numPhoneLabels];
// Global flag that indicates whether auto-fill should be active
// 0 == do not use autofill; 1 == use autofill
static UInt32 UseAutoFill = 0;
/***********************************************************************
*
* Internal Functions
*
***********************************************************************/
static void PrvEditInit( FormPtr frmP, Boolean leaveDataLocked );
static void PrvEditInitTableRow( FormType* frmP, TablePtr table, UInt16 row, UInt16 fieldIndex, Int16 rowHeight, FontID fontID, AddrDBRecordPtr record, AddrAppInfoPtr appInfoPtr );
static Boolean PrvEditHandleSelectField (Int16 row, Int16 column);
static void PrvEditRestoreEditState( FormType* frmP );
static void PrvEditSetGraffitiMode (FieldPtr fld, UInt16 currentField);
static Err PrvEditGetRecordField (void * table, Int16 row, Int16 /*column*/, Boolean editing, MemHandle * textH, Int16 * textOffset, Int16 * textAllocSize, FieldPtr fld);
static Boolean PrvEditSaveRecordField (void * table, Int16 row, Int16 /*column*/);
static UInt16 PrvEditSaveRecord ();
static void PrvEditSelectCategory (void);
static void PrvEditUpdateScrollers (FormPtr frmP, UInt16 bottomFieldIndex, Boolean lastItemClipped);
static UInt16 PrvEditGetFieldHeight (TablePtr table, UInt16 fieldIndex, Int16 columnWidth, Int16 maxHeight, AddrDBRecordPtr record, FontID * fontIdP);
static void PrvEditDrawBusinessCardIndicator (FormPtr formP);
static void PrvEditResizeDescription (EventType * event);
static void PrvEditScroll (WinDirectionType direction);
static void PrvEditNextField (WinDirectionType direction);
static void PrvEditUpdateCustomFieldLabels( FormType* frmP);
static void PrvEditUpdateDisplay( UInt16 updateCode );
static Boolean PrvEditDoCommand (UInt16 command);
static Boolean PrvEditAutoFill (EventPtr event);
static void PrvEditDialCurrent( void );
#ifdef ADDR_FOCUS_FIX
static void PrvEditLoadTable( FormType* frmP, Boolean doFocusFix );
#else
static void PrvEditLoadTable( FormType* frmP );
#endif
/***********************************************************************
*
* FUNCTION: EditHandleEvent
*
* DESCRIPTION: This routine is the event handler for the "Edit View"
* of the Address Book 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:
* Name Date Description
* ---- ---- -----------
* art 06/05/95 Created by Art Lamb.
* kwk 07/29/99 Unlock FieldMap in frmCloseEvent block.
* jmp 09/17/99 Use NewNoteView instead of NoteView.
* fpa 10/23/00 Fixed bug #27480 - Font Style: The default font
* setting did not get refresh in the Address Edit
* View when entering text in the last name field
* after you entered the first name and tap done
* 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.
*
***********************************************************************/
Boolean EditHandleEvent (EventType * event)
{
FormType* frmP;
TablePtr tableP;
Boolean handled = false;
Int16 row;
UInt32 numLibs;
switch (event->eType)
{
case frmOpenEvent:
{
UInt16 tableIndex;
FieldPtr fldP;
TraceOutput(TL(appErrorClass, "EditHandleEvent() - frmOpenEvent"));
frmP = FrmGetActiveForm ();
#ifdef ADDR_FOCUS_FIX
CurrentFieldIndex = EditRowIDWhichHadFocus;
#else /* not ADDR_FOCUS_FIX */
#endif /* not ADDR_FOCUS_FIX */
PrvEditInit (frmP, true);
tableIndex = FrmGetObjectIndex(frmP, EditTable);
tableP = FrmGetObjectPtr (frmP, tableIndex);
// Make sure the field which will get the focus is visible
while (!TblFindRowID (tableP, EditRowIDWhichHadFocus, &row))
{
TopVisibleFieldIndex = EditRowIDWhichHadFocus;
CurrentFieldIndex = EditRowIDWhichHadFocus;
#ifdef ADDR_FOCUS_FIX
PrvEditLoadTable(frmP, true);
#else /* not ifdef ADDR_FOCUS_FIX */
PrvEditLoadTable(frmP);
#endif /* not ifdef ADDR_FOCUS_FIX */
}
FrmDrawForm (frmP);
PrvEditDrawBusinessCardIndicator (frmP);
// Now set the focus.
FrmSetFocus(frmP, tableIndex);
TblGrabFocus (tableP, row, editDataColumn);
fldP = TblGetCurrentField(tableP);
FldGrabFocus (fldP);
// If NumCharsToHilite is not 0, then we know that we are displaying
// a duplicated message for the first time and we must hilite the last
// NumCharsToHilite of the field (first name) to indicate the modification
// to that duplicated field.
if (NumCharsToHilite > 0)
{
EditFieldPosition = FldGetTextLength (fldP);
// Now hilite the chars added.
FldSetSelection (fldP, EditFieldPosition - NumCharsToHilite, EditFieldPosition);
NumCharsToHilite = 0;
}
FldSetInsPtPosition (fldP, EditFieldPosition);
PriorAddressFormID = FrmGetFormId (frmP);
// Simulate a tap in last name field in order to fix bug #27480
PrvEditHandleSelectField(EditRowIDWhichHadFocus - TopVisibleFieldIndex, 1);
handled = true;
break;
}
case frmCloseEvent:
{
AddrAppInfoPtr appInfoPtr;
TraceOutput(TL(appErrorClass, "EditHandleEvent() - frmCloseEvent"));
// Check if the record is empty and should be deleted. This cannot
// be done earlier because if the record is deleted there is nothing
// to display in the table.
PrvEditSaveRecord ();
// We need to unlock the block containing the phone labels.
appInfoPtr = (AddrAppInfoPtr) AddrDBAppInfoGetPtr(AddrDB);
MemPtrUnlock(appInfoPtr); // Call to AddrAppInfoGetPtr did a lock
MemPtrUnlock(appInfoPtr); // Unlock lock in PrvEditInit
// We need to unlock the FieldMap resource, which was also locked
// in PrvEditInit.
MemHandleUnlock(FieldMapH);
DmReleaseResource(FieldMapH);
FieldMap = 0;
break;
}
case tblEnterEvent:
// if a phone label is tapped: store current
if (isPhoneField(FieldMap[TblGetRowID(event->data.tblEnter.pTable, event->data.tblEnter.row)]))
{
CurrentTableRow = event->data.tblEnter.row;
}
break;
case winExitEvent:
case tblExitEvent:
TraceOutput(TL(appErrorClass, "EditHandleEvent() - winExitEvent (%us)", CurrentFieldIndex));
// if we exits a window and a phone label was tapped: redraw the associated row
// to replace the semicolon character
if (CurrentTableRow != editInvalidRow)
{
tableP = ToolsGetFrmObjectPtr(FrmGetActiveForm(), EditTable);
TblMarkRowInvalid(tableP, CurrentTableRow);
TblRedrawTable(tableP);
CurrentTableRow = editInvalidRow;
}
break;
case tblSelectEvent:
TraceOutput(TL(appErrorClass, "EditHandleEvent() - tblSelectEvent"));
// Select the field if it's different than the one selected before. This means the selection
// is on a different row or the selection is a phone label.
if (CurrentFieldIndex != TblGetRowID (event->data.tblSelect.pTable, event->data.tblSelect.row) ||
(event->data.tblSelect.column == editLabelColumn && isPhoneField(FieldMap[
TblGetRowID(event->data.tblSelect.pTable, event->data.tblSelect.row)])))
PrvEditHandleSelectField (event->data.tblSelect.row, event->data.tblSelect.column);
CurrentTableRow = editInvalidRow;
break;
case ctlSelectEvent:
TraceOutput(TL(appErrorClass, "EditHandleEvent() - ctlSelectEvent - controlID = %hu", event->data.ctlSelect.controlID));
switch (event->data.ctlSelect.controlID)
{
case EditCategoryTrigger:
PrvEditSelectCategory ();
PrvEditRestoreEditState(FrmGetActiveForm()); // DOLATER: Can cause problems when no field is editable
handled = true;
break;
case EditDoneButton:
FrmGotoForm (ListView);
handled = true;
break;
case EditDetailsButton:
FrmPopupForm (DetailsDialog);
handled = true;
break;
case EditNoteButton:
if (NoteViewCreate())
{
RecordNeededAfterEditView = true;
FrmGotoForm (NewNoteView);
}
handled = true;
break;
default:
break;
}
break;
case ctlRepeatEvent:
switch (event->data.ctlRepeat.controlID)
{
case EditUpButton:
PrvEditScroll (winUp);
// leave unhandled so the buttons can repeat
break;
case EditDownButton:
PrvEditScroll (winDown);
// leave unhandled so the buttons can repeat
break;
default:
break;
}
break;
case menuEvent:
return PrvEditDoCommand (event->data.menu.itemID);
case menuCmdBarOpenEvent:
{
FieldType* fldP;
UInt16 startPos, endPos;
fldP = TblGetCurrentField(ToolsGetObjectPtr(EditTable));
if (fldP)
FldGetSelection(fldP, &startPos, &endPos);
if ((fldP) && (startPos == endPos)) // there's no highlighted text
{
// Call directly the Field event handler so that edit buttons are added if applicable
FldHandleEvent(fldP, event);
MenuCmdBarAddButton(menuCmdBarOnRight, BarDeleteBitmap, menuCmdBarResultMenuItem, EditRecordDeleteRecordCmd, 0);
MenuCmdBarAddButton(menuCmdBarOnLeft, BarBeamBitmap, menuCmdBarResultMenuItem, EditRecordBeamRecordCmd, 0);
// Prevent the field package to add edit buttons again
event->data.menuCmdBarOpen.preventFieldButtons = true;
}
else if (fldP == NULL) // there is no active text field (none have cursor visible)
{
MenuCmdBarAddButton(menuCmdBarOnLeft, BarDeleteBitmap, menuCmdBarResultMenuItem, EditRecordDeleteRecordCmd, 0);
MenuCmdBarAddButton(menuCmdBarOnLeft, BarBeamBitmap, menuCmdBarResultMenuItem, EditRecordBeamRecordCmd, 0);
// Prevent the field package to add edit buttons again
event->data.menuCmdBarOpen.preventFieldButtons = true;
}
else
{
// When there is a selection range of text (ie startPos != endPos)
// fall through to the field code to add the appropriate cut, copy,
// paste, and undo selections to the command bar.
event->data.menuCmdBarOpen.preventFieldButtons = false;
}
// don't set handled to true; this event must fall through to the system.
break;
}
case menuOpenEvent:
if(!ToolsIsDialerPresent())
MenuHideItem(EditRecordDialCmd);
if (ExgGetRegisteredApplications(NULL, &numLibs, NULL, NULL, exgRegSchemeID, exgSendScheme) || !numLibs)
MenuHideItem(EditRecordSendRecordCmd);
else
MenuShowItem(EditRecordSendRecordCmd);
// don't set handled = true
break;
case fldHeightChangedEvent:
TraceOutput(TL(appErrorClass, "EditHandleEvent() - fldHeightChangedEvent"));
PrvEditResizeDescription (event);
handled = true;
break;
case keyDownEvent:
if (TxtCharIsHardKey(event->data.keyDown.modifiers, event->data.keyDown.chr))
{
TblReleaseFocus(ToolsGetObjectPtr(EditTable));
TopVisibleRecord = 0; // Same as when app switched to
CurrentFieldIndex = noFieldIndex;
FrmGotoForm (ListView);
return (true);
}
else if (EvtKeydownIsVirtual(event))
{
switch (event->data.keyDown.chr)
{
case vchrPageUp:
PrvEditScroll (winUp);
handled = true;
break;
case vchrPageDown:
PrvEditScroll (winDown);
handled = true;
break;
case vchrNextField:
PrvEditNextField (winDown);
handled = true;
break;
case vchrPrevField:
PrvEditNextField (winUp);
handled = true;
break;
case vchrSendData:
// Make sure the field being edited is saved
frmP = FrmGetActiveForm ();
tableP = ToolsGetFrmObjectPtr(frmP, EditTable);
TblReleaseFocus(tableP);
MenuEraseStatus (0);
TransferSendRecord(AddrDB, CurrentRecord, exgBeamPrefix, NoDataToBeamAlert);
handled = true;
break;
default:
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -