⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sugarmemoedit.c

📁 Palm上著名的背单词软件的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
#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 + -