📄 sugarmemoedit.c
字号:
#include <PalmOS.h>
#include <PalmUtils.h>
#include "SugarMemo.h"
#include "SugarMemoRsc.h"
#include "SugarMemoDB.h"
#include "SugarMemoBrowse.h"
#include "SugarMemoEdit.h"
#include "SugarMemoTools.h"
#define labelColumnWidth 15
#define LabelLength 10
//typedef char EditLabel[LabelLength];
#define noFieldIndex 0xff
#define labelColumn 0
#define dataColumn 1
#define spaceAfterColumn 2
#define FirstFieldIndex 0
#define MaxFieldIndex 3
#define ColumnsInVowelTable 6
#define ColumnsInConsonantTable 2
//global
Char EditCategoryName[dmCategoryLength];
UInt16 TopVisibleFieldIndex =0;
UInt16 EditRowIDWhichHadFocus =0;
UInt16 EditFieldPosition = 0;
UInt16 StudyListIndex;
extern TabSelected tabCurrentSelected;
extern Boolean SeekNextRecord(UInt16 * indexP, Int16 direction);
//internal
static UInt16 CurrentFieldIndex = 0;
const WordFields FieldMap[4] = {WordFieldQuestion,
WordFieldPhonetic,
WordFieldAnswer,
WordFieldNote3};
EditLabel fieldLabel[WordFieldsCount] = {"Q",
"P",
"A",
"WordNet",
"MerriamW",
"Dict1",
"Dict2",
"Dict3",
"Note1",
"Note2",
"N"};
//internal functions
static void EditInit( FormPtr frmP, Boolean leaveDataLocked );
static void EditFormLoadControls();
static void EditFormLoadCategory();
static void EditFormLoadTable(FormType* frmP);
static void EditInitTableRow( FormType* frmP, TablePtr table, UInt16 row, UInt16 fieldIndex,
Int16 rowHeight, WordRecordType* record);
static UInt16 EditGetFieldHeight (TablePtr table, UInt16 fieldIndex, Int16 columnWidth, Int16 maxHeight,
WordRecordType* record);
static Err EditGetRecordField (void * table, Int16 row, Int16 column, Boolean editing,
MemHandle * textH, Int16 * textOffset, Int16 * textAllocSize, FieldPtr fld);
static Boolean EditSaveRecordField (void * table, Int16 row, Int16 column);
static UInt16 EditFormSaveRecord ();
static void EditDrawRecordField (void * table, Int16 row, Int16 column, RectanglePtr bounds);
static void EditUpdateScrollers (FormPtr frmP, UInt16 bottomFieldIndex, Boolean lastItemClipped);
static void EditFormScroll (WinDirectionType direction);
static void EditFormResizeField (EventType * event);
static UInt16 EditCategorySelection (void);
static void FieldSelection(Int16 row);
static void EditFormNextWord(Boolean next);
static void EditUpdateHorizonScrollers();
//event handler
Boolean EditFormHandleEvent(EventType * event){
FormType* frmP = FrmGetActiveForm();
Boolean handled = false;
TableType* tableP = GetObjectPtr(EditEditTable);
FieldType * field;
ControlType * ctl = GetObjectPtr(EditLearnPushButton);
switch (event->eType){
case frmOpenEvent:
frmP = FrmGetActiveForm ();
EditInit (frmP, false);
FrmDrawForm (frmP);
handled = true;
break;
case frmUpdateEvent:
FrmDrawForm(frmP);
handled = true;
break;
case fldHeightChangedEvent:
EditFormResizeField(event);
handled = true;
break;
case tblSelectEvent:
FieldSelection(event->data.tblSelect.row);
break;
case ctlSelectEvent:
switch (event->data.ctlSelect.controlID){
case EditCategoryPopTrigger:
EditCategorySelection();
handled = true;
break;
case EditDoneButton:
switch(HeaderRecordIndex){
case HeaderIndexCounts:
VisibleRows = 0;
FrmGotoForm(BrowseForm);
break;
case LearningRecordIndex:
case TestingRecordIndex:
FrmGotoForm(Learn2Form);
break;
}
handled = true;
break;
case EditDeleteButton:
FrmSetFocus(frmP, noFocus);
WordDBDeleteRecord(false);
VisibleRows = 0;
FrmGotoForm(BrowseForm);
handled = true;
break;
case EditLearnPushButton:
if (CtlGetValue(ctl) == 0) SetQueue(CurrentDB, CurrentRecord, RawQueue);
else SetQueue(CurrentDB, CurrentRecord, LearningQueue);
//do not set handled, let system update display
break;
default:
break;
}
break;
case ctlRepeatEvent:
switch (event->data.ctlRepeat.controlID)
{
case EditScrollUpRepeating:
EditFormScroll (winUp);
// leave unhandled so the buttons can repeat
break;
case EditScrollDownRepeating:
EditFormScroll (winDown);
// leave unhandled so the buttons can repeat
break;
case EditPrevRepeating:
EditFormNextWord(false);
break;
case EditNextRepeating:
EditFormNextWord(true);
break;
default:
break;
}
break;
case keyDownEvent:
if (EvtKeydownIsVirtual(event))
{
switch (event->data.keyDown.chr)
{
case vchrPageUp:
if (TblGetLastUsableRow(tableP) == 0){
field = TblGetCurrentField(tableP);
if (field != NULL){
if (FldScrollable(field, winUp)){
EvtEnqueueKey(chrUpArrow, 0, 0);
FldScrollField(field, 1, winUp);
handled = true;
break;
}
}
}
EditFormScroll (winUp);
handled = true;
break;
case vchrPageDown:
if (TblGetLastUsableRow(tableP) == 0){
field = TblGetCurrentField(tableP);
if (field != NULL){
if (FldScrollable(field, winDown)){
EvtEnqueueKey(chrDownArrow, 0, 0);
FldScrollField(field, 1, winDown);
handled = true;
break;
}
}
}
EditFormScroll (winDown);
handled = true;
break;
}
}
break;
default:
break;
}
return handled;
}
void EditFormLoadControls(){
ControlType * ctl;
HeaderQueue queue;
//Initialize controls
if (HeaderRecordIndex == HeaderIndexCounts){
ShowObject(EditDeleteButton);
ShowObject(EditPrevRepeating);
ShowObject(EditNextRepeating);
if (tabCurrentSelected == StudyListTab)
HideObject(EditLearnPushButton);
else {
queue = GetQueue(CurrentDB, CurrentRecord);
if (queue == RawQueue || queue == LearningQueue){
ctl = GetObjectPtr(EditLearnPushButton);
if (queue == RawQueue) CtlSetValue(ctl, 0);
else CtlSetValue(ctl, 1);
ShowObject(EditLearnPushButton);
}
else
HideObject(EditLearnPushButton);
}
}
else {
HideObject(EditDeleteButton);
HideObject(EditLearnPushButton);
HideObject(EditPrevRepeating);
HideObject(EditNextRepeating);
}
}
void EditFormLoadCategory(){
UInt16 attr;
UInt16 category;
ControlType* ctl;
// Set the label of the category trigger.
DmRecordInfo (CurrentDB, CurrentRecord, &attr, NULL, NULL);
category = attr & dmRecAttrCategoryMask;
ctl = GetObjectPtr(EditCategoryPopTrigger);
CategoryGetName (CurrentDB, category, EditCategoryName);
CategorySetTriggerLabel (ctl, EditCategoryName);
CtlDrawControl(ctl);
}
//This routine initialize edit form
void EditInit( FormPtr frmP, Boolean leaveDataLocked ){
UInt16 row;
UInt16 rowsInTable;
UInt16 dataColumnWidth;
TablePtr table;
RectangleType bounds;
EditFormLoadControls();
EditFormLoadCategory();
if (HeaderRecordIndex == HeaderIndexCounts) EditUpdateHorizonScrollers();
// Initialize the edit table.
table = GetObjectPtr(EditEditTable);
rowsInTable = TblGetNumberOfRows (table);
for (row = 0; row < rowsInTable; row++)
{
// This sets the data column
TblSetItemStyle (table, row, labelColumn, labelTableItem);
TblSetRowUsable (table, row, false);
}
TblSetColumnUsable (table, labelColumn, true);
TblSetColumnUsable (table, dataColumn, true);
TblSetColumnSpacing (table, labelColumn, spaceAfterColumn);
// Set the callback routines
TblSetLoadDataProcedure (table, dataColumn, EditGetRecordField);
TblSetSaveDataProcedure (table, dataColumn, EditSaveRecordField);
TblSetCustomDrawProcedure (table, dataColumn, EditDrawRecordField);
// Set the column widths so that the label column contents fit exactly.
TblGetBounds (table, &bounds);
dataColumnWidth = bounds.extent.x - spaceAfterColumn - labelColumnWidth;
TblSetColumnWidth(table, labelColumn, labelColumnWidth);
TblSetColumnWidth(table, dataColumn, dataColumnWidth);
EditFormLoadTable(frmP);
}
Err EditGetRecordField (void * table, Int16 row, Int16 column,
Boolean editing, MemHandle * textH, Int16 * textOffset, Int16 * textAllocSize, FieldPtr fld){
UInt16 fieldNum;
UInt16 fieldIndex;
Char * recordP;
Char * fieldP;
MemHandle recordH, fieldH;
UInt16 fieldSize;
WordRecordType record;
//FieldType * field;
FldSetMaxChars(fld, 1024);
// Get the field number that corresponds to the table item.
// The field number is stored as the row id.
fieldIndex = TblGetRowID (table, row);
fieldNum = FieldMap[fieldIndex];
GetWordRecord (CurrentDB, CurrentRecord, &record, &recordH);
if (editing)
{
if (record.field[fieldNum])
{
fieldSize = StrLen(record.field[fieldNum]) + 1;
fieldH = MemHandleNew(fieldSize); // Handle freeing done into PrvEditSaveRecordField() by calling FldFreeMemory() function
fieldP = MemHandleLock(fieldH);
MemMove(fieldP, record.field[fieldNum], fieldSize);
*textAllocSize = fieldSize;
MemHandleUnlock(fieldH);
}
else
{
fieldH = 0;
*textAllocSize = 0;
}
MemHandleUnlock (recordH);
*textOffset = 0; // only one string
*textH = fieldH;
return (0);
}
else
{
// Calculate the offset from the start of the record.
recordP = MemHandleLock (recordH); // record now locked twice
if (record.field[fieldNum])
{
*textOffset = record.field[fieldNum] - recordP;
*textAllocSize = StrLen (record.field[fieldNum]) + 1; // one for null terminator
}
else
{
do
{
fieldNum++;
} while (fieldNum < WordFieldsCount && record.field[fieldNum] == NULL);
if (fieldNum < WordFieldsCount)
*textOffset = record.field[fieldNum] - recordP;
else
// Place the new field at the end of the text.
*textOffset = MemHandleSize(recordH);
*textAllocSize = 0; // one for null terminator
}
MemHandleUnlock (recordH); // unlock the second lock
}
MemHandleUnlock (recordH); // unlock the AddrGetRecord lock
*textH = recordH;
return (0);
}
Boolean EditSaveRecordField (void * table, Int16 row, Int16 column){
UInt16 fieldNum;
UInt16 fieldIndex;
FieldPtr fld;
WordRecordType record;
MemHandle recordH;
MemHandle textH;
Char * textP;
WordFieldFlags bit;
Err err;
Boolean redraw = false;
UInt16 numOfRows;
Int16 newSize;
fld = TblGetCurrentField (table);
textH = FldGetTextHandle(fld);
// Get the field number that corresponds to the table item to save.
fieldIndex = TblGetRowID (table, row);
fieldNum = FieldMap[fieldIndex];
// Save the field last edited.
EditRowIDWhichHadFocus = fieldIndex;
// Save the cursor position of the field last edited.
// Check if the top of the text is scroll off the top of the
// field, if it is then redraw the field.
if (FldGetScrollPosition (fld))
{
FldSetScrollPosition (fld, 0);
EditFieldPosition = 0;
}
else
EditFieldPosition = FldGetInsPtPosition (fld);
// Make sure there any selection is removed since we will free
// the text memory before the callee can remove the selection.
FldSetSelection (fld, 0, 0);
if (FldDirty (fld))
{
// Since the field is dirty, mark the record as dirty
ToolsDirtyRecord (CurrentRecord);
// Get a pointer to the text of the field.
if (textH == 0)
textP = NULL;
else
{
textP = MemHandleLock(textH);
if (textP[0] == '\0')
textP = NULL;
}
GetWordRecord (CurrentDB, CurrentRecord, &record, &recordH);
record.field[fieldNum] = textP;
bit.allBits = (UInt32)1 << fieldNum;
err = ChangeWordRecord(CurrentDB, &CurrentRecord, &record, bit);
// The new field has been copied into the new record. Unlock it.
if (textP)
MemPtrUnlock(textP);
// The change was not made (probably storage out of memory)
if (err)
{
// Because the storage is full the text in the text field differs
// from the text in the record. PrvEditGetFieldHeight uses
// the text in the field (because it's being edited).
// Make the text in the field the same as the text in the record.
// Resizing should always be possible.
MemHandleUnlock(recordH); // Get original text
GetWordRecord(CurrentDB, CurrentRecord, &record, &recordH);
if (record.field[fieldNum] == NULL)
newSize = 1;
else
newSize = StrLen(record.field[fieldNum]) + 1;
// Have the field stop using the chunk to unlock it. Otherwise the resize can't
// move the chunk if more space is needed and no adjacent free space exists.
FldSetTextHandle (fld, 0);
if (!MemHandleResize(textH, newSize))
{
textP = MemHandleLock(textH);
if (newSize > 1)
StrCopy(textP, record.field[fieldNum]);
else
textP[0] = '\0';
MemPtrUnlock(textP);
}
else
{
ErrNonFatalDisplay("Resize failed.");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -