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

📄 listform.c

📁 keyring是一种用于保护PALM中关键信息的系统
💻 C
字号:
/* -*- c-file-style: "java"; -*- * * $Header: /cvsroot/gnukeyring/keyring/listform.c,v 1.51 2006/01/13 14:09:04 hoenicke Exp $ *  * Keyring -- store passwords securely on a handheld * Copyright (C) 1999, 2000, 2001 Martin Pool <mbp@users.sourceforge.net> * Copyright (C) 2001-2005 Jochen Hoenicke <hoenicke@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "includes.h"// =====================================================================// List form/* * TODO: Show category headings in the list. */static TablePtr f_Table;static ScrollBarPtr f_ScrollBar;static FieldPtr f_LookUp;static FormPtr f_ListForm;/* Number of table rows that could possibly fit on the screen.  Some * of them might not be actually in use if there's less than a screen * of records. */static UInt16 f_ScreenRows;/* Number of records available to be shown in the table, after taking * into account categories and reserved records. */static UInt16 f_NumListed;/* Index of the first displayed row of the table.  Zero shows top of table, * etc. */UInt16 f_FirstIdx;/* Index of the selected row in the table */static UInt16 f_SelectedIdx;/* Record index of the first displayed record */static UInt16 f_FirstIndex;/* Should we scroll in the table with the rocker buttons */static Boolean rockerNavTable;static GUI_SECTION Int16 ListForm_RecordIdx(Int16 row){    Int16       idx = f_FirstIndex;    Err         err;    /* FIXME: We need to skip the first few reserved records, but that     * depends on the category: if it is zero (if that's their     * category) or all, then we must increase the itemNum; otherwise     * not.     *     * Also, we need to selectively reduce the number of records in     * the list by that amount, and also compensate when mapping list position     * to record idx.     *     * Is there no "hidden" bit we can set to avoid all this?     */    err = DmSeekRecordInCategory(gKeyDB, &idx, row, 				 dmSeekForward, gPrefs.category);    return err == errNone ? idx : -1;}static GUI_SECTION void ListForm_DrawCell(TablePtr UNUSED(table),                              Int16 row, Int16 UNUSED(col),                               RectanglePtr bounds){    /* This could be faster if we remembered the current position and     * stepped forward to the next.     */    MemHandle   rec = 0;    FieldHeaderType *recPtr = 0;    Char const  *scrStr;    UInt16      len;    Int16       idx;    static Char altBuf[maxStrIToALen + 1];    /* Clear current cell content.  This is needed by PalmOS 3.3 and below */    WinEraseRectangle(bounds, 0);    idx = ListForm_RecordIdx(row);     if (idx == -1) 	/* We reached the end of the table; return immediately. */	return;    rec = DmQueryRecord(gKeyDB, idx);    if (!rec) {        scrStr = "<no-record>";	len = StrLen(scrStr);	goto draw;    }        recPtr = MemHandleLock(rec);     len    = recPtr->len;    scrStr = (Char *) (recPtr + 1);    if (!len) {        /* If there is no name, use the record index instead.  */        altBuf[0] = '#';        StrIToA(altBuf + 1, idx);        scrStr = altBuf;	len = StrLen(scrStr);    } draw:    WinGlueDrawTruncChars(scrStr, len, 			  bounds->topLeft.x, bounds->topLeft.y, 			  bounds->extent.x);        if (recPtr)        MemHandleUnlock(rec);}static GUI_SECTION void ListForm_DrawLockBitmap(void) {    MemHandle bmpH;    BitmapPtr bmpP;    Boolean locked;    locked = !Snib_RetrieveKey(NULL);    bmpH = (MemHandle) DmGetResource        (bitmapRsc, locked ? LockBitmap : UnlockBitmap);    ErrFatalDisplayIf(!bmpH, "Missing bitmap");    bmpP = MemHandleLock((MemHandle)bmpH);    WinDrawBitmap(bmpP, 150, 1);    MemPtrUnlock(bmpP);    DmReleaseResource((MemHandle) bmpH);}/* * Update the table control, after querying the database to see how * many rows can be displayed. */static GUI_SECTION void ListForm_UpdateTable(void){    UInt16 row;    f_NumListed = DmNumRecordsInCategory(gKeyDB, gPrefs.category);    /* Mark all rows upto f_NumListed as usable.     */    for (row = 0; row < f_ScreenRows; row++) {	TblSetRowUsable(f_Table, row, row < f_NumListed);    }}static GUI_SECTION void ListForm_UpdateScrollBar(void){    /*     * Connect the scrollbar to the list.  The list cannot change     * while this form is displayed: insertion, deletion, and renaming     * all happen from inside the key details form.  Therefore, we     * don't have to update the size of the scroll bar.     */    UInt16 max;    max = f_NumListed <= f_ScreenRows ? 0 :f_NumListed - f_ScreenRows;    if (f_FirstIdx > max)	f_FirstIdx = max;    SclSetScrollBar(f_ScrollBar, f_FirstIdx, 0, max, f_ScreenRows);    f_FirstIndex = 0;    DmSeekRecordInCategory(gKeyDB, &f_FirstIndex, f_FirstIdx, 			   dmSeekForward, gPrefs.category);}static GUI_SECTION void ListForm_UpdateCategory(void){    Category_UpdateName(f_ListForm, gPrefs.category);}static GUI_SECTION void ListForm_UpdateSelection(void){    if (f_SelectedIdx >= f_FirstIdx	&& f_SelectedIdx < f_FirstIdx + f_ScreenRows)	TblSelectItem(f_Table, f_SelectedIdx - f_FirstIdx, 0);    else	TblUnhighlightSelection(f_Table);}static GUI_SECTION void ListForm_Update(void){    ListForm_UpdateTable();    ListForm_UpdateCategory();    ListForm_UpdateScrollBar();        FrmDrawForm(f_ListForm);    ListForm_UpdateSelection();    ListForm_DrawLockBitmap();}static GUI_SECTION void ListForm_InitTable(void){    UInt16 row;    /* Get the total number of rows allocated.  */    f_ScreenRows = TblGetNumberOfRows(f_Table);    /* Mark all rows as custom     */    for (row = 0; row < f_ScreenRows; row++) {	TblSetItemStyle(f_Table, row, 0, customTableItem);    }    TblSetColumnUsable(f_Table, 0, true);        TblSetCustomDrawProcedure(f_Table, 0,                              (TableDrawItemFuncPtr) ListForm_DrawCell);    TblHasScrollBar(f_Table, true);}static GUI_SECTION void ListForm_FormOpen(void){    f_ListForm = FrmGetActiveForm();    f_Table = UI_GetObjectByID(f_ListForm, KeyTable);    f_ScrollBar = UI_GetObjectByID(f_ListForm, KeyTableScrollBar);    f_LookUp = UI_GetObjectByID(f_ListForm, LookUpFld);    f_SelectedIdx = kNoRecord;    ListForm_InitTable();    ListForm_Update();    FrmSetFocus(f_ListForm, FrmGetObjectIndex(f_ListForm, LookUpFld));    rockerNavTable = false; }static GUI_SECTION Boolean ListForm_SelectIndex(UInt16 listIdx){    UInt16      idx;    Err         err;    /* Map from a position within this category to an overall     * record index. */    idx = 0;    err = DmSeekRecordInCategory(gKeyDB, &idx, listIdx,				 dmSeekForward, gPrefs.category);    ErrFatalDisplayIf(err, __FUNCTION__ ": selected item doesn't exist");    KeyEdit_GotoRecord(idx);    return false;}static GUI_SECTION void ListForm_NewKey(void){     KeyEdit_GotoRecord(kNoRecord);}/* * Scroll to the record.  Update table and scrollbar. * * It can't be less than zero of course, but also we don't allow * whitespace at the bottom if there are enough rows to fill the * display.  However we leave the display as close as possible to * where the user put it last.   */static GUI_SECTION void ListForm_Scroll(UInt16 newPos){    UInt16 oldPos = f_FirstIdx;    f_FirstIdx = newPos;    ListForm_UpdateScrollBar();    if (f_FirstIdx != oldPos) {	TblUnhighlightSelection(f_Table);	TblMarkTableInvalid(f_Table);	TblRedrawTable(f_Table);	ListForm_UpdateSelection();    }}static GUI_SECTION void ListForm_LookUpItem(Char *item){    UInt16 idx, itemLen, matchLen;    UInt16 catpos;    MemHandle rec;    FieldHeaderType *fldHeader;    Int16 compare;    if (!item || !(itemLen = StrLen(item))) {	f_SelectedIdx = kNoRecord;	ListForm_UpdateSelection();	return;    }    idx = 0;    for (;;) {	rec = DmQueryNextInCategory(gKeyDB, &idx, gPrefs.category);	if (!rec) {	    /* scroll to the end */	    ListForm_Scroll(f_NumListed);	    break;	}	fldHeader = MemHandleLock(rec); 	if (fldHeader) {	    compare = TxtGlueCaselessCompare((Char *) (fldHeader + 1), 					     fldHeader->len, NULL,					     item, itemLen, &matchLen);	    MemHandleUnlock(rec);	    if (compare >= 0) {		catpos = DmPositionInCategory(gKeyDB, idx, gPrefs.category);		if (matchLen == itemLen)		    f_SelectedIdx = catpos;		else		    f_SelectedIdx = kNoRecord;		ListForm_Scroll(catpos);		ListForm_UpdateSelection();		break;	    }	}	idx++;    }}    static GUI_SECTION void ListForm_CategoryTrigger(void){    if (Category_Selected(&gPrefs.category, true)) {        ListForm_Update();	ListForm_LookUpItem(FldGetTextPtr(f_LookUp));    }}GUI_SECTION Boolean ListForm_HandleEvent(EventPtr event){    UInt16        tableIndex;     f_ListForm = FrmGetActiveForm();    tableIndex = FrmGetObjectIndex (f_ListForm, KeyTable);        switch (event->eType) {    case ctlSelectEvent:        switch (event->data.ctlSelect.controlID) {        case LockBtn:            Snib_Eradicate();            break;        case NewKeyBtn:            ListForm_NewKey();            return true;        case CategoryTrigger:            ListForm_CategoryTrigger();            return true;        }        break;    case frmOpenEvent:        ListForm_FormOpen();        return true;    case frmUpdateEvent:        ListForm_Update();        return true;    case menuEvent:        if (Common_HandleMenuEvent(event)) {	    /* We may have left the form.  Update the lock bitmap	     * on return.	     */	    ListForm_DrawLockBitmap();	    return true;	}        break;    case sclRepeatEvent:        ListForm_Scroll(event->data.sclRepeat.newValue);        break;    case tblSelectEvent:	if (event->data.tblSelect.tableID != KeyTable)	    break;	f_SelectedIdx = f_FirstIdx + event->data.tblSelect.row;	ListForm_UpdateSelection();        return ListForm_SelectIndex(f_SelectedIdx);    case keyDownEvent:	if (TxtCharIsHardKey(event->data.keyDown.modifiers, 			     event->data.keyDown.chr)) {	    /* Select next category if hard key was pressed */	    gPrefs.category = CategoryGetNext (gKeyDB, gPrefs.category);	    ListForm_Update();	    ListForm_LookUpItem(FldGetTextPtr(f_LookUp));	    return true;	} else if (IsFiveWayNavEvent(event)) {	    /* Handle 5-way Nav Rocker Buttons.	     * If rockerNavTable is "true" then we are currently	     * navigating the lines of the table.	     */	    if (NavSelectPressed(event)) {		if (rockerNavTable) {		    /* view the item that we have highlighted */		    if (f_SelectedIdx != kNoRecord)			return ListForm_SelectIndex(f_SelectedIdx);		} else if (FrmGetFocus(f_ListForm) == 			   FrmGetObjectIndex(f_ListForm, LookUpFld)) {		    /* If we are clicking the centerRocker in the		     * LookUpFld, then navigate the table.		     */		    rockerNavTable = true;		    if ((f_SelectedIdx == kNoRecord) && (f_NumListed > 0)) {			f_SelectedIdx = f_FirstIdx;		    }		    ListForm_UpdateSelection();                        		    return true;		}		/* We did not process the event, let the system process it.		 */	    } else if (NavDirectionPressed(event, Up)		       || NavDirectionPressed(event, Down)) {		/* If rockerNavTable is set, scroll up and down the		 * table with the rocker keys, otherwise, follow the		 * focus specified in the fnav resource.		 */		if (rockerNavTable && f_SelectedIdx != kNoRecord) {		    /* navigating the rows of the table		     * move up/down one.		     */		    int newIdx = f_SelectedIdx;		    if (NavDirectionPressed(event, Up))			newIdx--;		    else			newIdx++;		    if (newIdx >= 0 && (unsigned) newIdx < f_NumListed) {			f_SelectedIdx = newIdx;			/* Scroll the list so that the selected index is 			 * visible.			 */			if (f_SelectedIdx < f_FirstIdx)			    ListForm_Scroll(f_SelectedIdx);			else if (f_SelectedIdx >= f_FirstIdx + f_ScreenRows)			    ListForm_Scroll(f_SelectedIdx - f_ScreenRows + 1);			ListForm_UpdateSelection();		    }		} else {		    /* Use rockerUp/Down as a pageUp/Down buttons */		    if (NavDirectionPressed(event, Up))			ListForm_Scroll(f_FirstIdx > f_ScreenRows ?					f_FirstIdx - f_ScreenRows : 0);		    else			ListForm_Scroll(f_FirstIdx + f_ScreenRows);		}		/* return here so no other rockerUp events can be processed. */		return true;	    } else if (NavDirectionPressed(event, Left)		       || NavDirectionPressed(event, Right)) {				if (rockerNavTable) {		    /* if navigating the table, turn off table nav on		     * rockerLeft/Right.		     */		    rockerNavTable = false;		    f_SelectedIdx = kNoRecord;		    ListForm_UpdateSelection();		}		/* Let the system handle event */	    }	} else {	    switch (event->data.keyDown.chr) {	    case pageUpChr:		ListForm_Scroll(f_FirstIdx > f_ScreenRows ? 				f_FirstIdx - f_ScreenRows : 0);		return true;	    case pageDownChr:		ListForm_Scroll(f_FirstIdx + f_ScreenRows);		return true;	    case chrLineFeed:		if (f_SelectedIdx != kNoRecord)		    return ListForm_SelectIndex(f_SelectedIdx);		break;	    default:		if (FldHandleEvent (f_LookUp, event)) {		    ListForm_LookUpItem(FldGetTextPtr(f_LookUp));		    rockerNavTable = true;		    return true;		}		break;	    }	}    case fldChangedEvent:	ListForm_LookUpItem(FldGetTextPtr(f_LookUp));	return true;    default:    }    return false;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -