/* * Handles the word list form. */ #include #include "flipMain.h" #include "flipFlip.h" #include "flipEdit.h" #include "flipAbout.h" #include "palmUtil.h" #include "flipList.h" #include "resdefs.h" #define word1Column 0 #define word2Column 1 #define knownColumn 2 static Boolean ListEventStealer(EventPtr event); static Boolean ListEventHandler(EventPtr event); static void WordListInit(void); struct FormInfo ListFormInfo = { EventStealer:ListEventStealer, EventHandler:ListEventHandler, InitForm:WordListInit, DeinitForm:NULL, UpdateForm:NULL, }; /* * Global variables */ /* The first visible word in the word list. */ static UInt16 topVisibleWord = 0; /* * WordListForm stuff */ /* Get the number of rows on one page. */ static UInt16 GetRowsPerPage(TablePtr table) { UInt16 rows; UInt16 rowsInTable; UInt16 tableHeight; RectangleType r; Int16 rowHeight; rowsInTable = TblGetNumberOfRows(table); TblGetBounds(table, &r); tableHeight = r.extent.y; rowHeight = TblGetRowHeight(table, 0); rows = tableHeight / rowHeight; return (rows <= rowsInTable) ? rows : rowsInTable; } static void WordListUpdateScrollBar(void) { UInt16 numOfRecords; UInt16 rowsPerPage; UInt16 scrollMax; numOfRecords = GetNumWords(wordDB); rowsPerPage = GetRowsPerPage(GetObjectPtr(WordListTable)); scrollMax = (numOfRecords > rowsPerPage) ? (numOfRecords - rowsPerPage) : 0; SclSetScrollBar(GetObjectPtr(WordListScrollBar), topVisibleWord, 0, scrollMax, rowsPerPage); } static void WordListUpdateTable(void) { TablePtr table; table = GetObjectPtr(WordListTable); TblMarkTableInvalid(table); TblRedrawTable(table); } static void WordListScrollTo(UInt16 newTopVisibleWord) { TablePtr table; UInt16 rowsPerPage; Int16 delta; WinDirectionType dir; Coord dist; RectangleType r; UInt16 i; if (newTopVisibleWord != topVisibleWord) { table = GetObjectPtr(WordListTable); rowsPerPage = GetRowsPerPage(table); delta = newTopVisibleWord - topVisibleWord; i = (delta < 0) ? -delta : delta; if (i >= rowsPerPage) { TblMarkTableInvalid(table); } else { dir = (delta < 0) ? winDown : winUp; dist = i * TblGetRowHeight(table, 0); TblGetBounds(table, &r); WinScrollRectangle(&r, dir, dist, &r); while (i--) TblMarkRowInvalid(table, (delta < 0) ? i : rowsPerPage - 1 - i); } topVisibleWord = newTopVisibleWord; TblRedrawTable(table); } } static void WordListScroll(Int16 lines) { Int16 newTopVisibleWord; UInt16 numOfRecords; UInt16 rowsPerPage; numOfRecords = GetNumWords(wordDB); rowsPerPage = GetRowsPerPage(GetObjectPtr(WordListTable)); newTopVisibleWord = topVisibleWord + lines; if (newTopVisibleWord < 0 || numOfRecords < rowsPerPage) { newTopVisibleWord = 0; } else if (newTopVisibleWord + rowsPerPage > numOfRecords) { newTopVisibleWord = numOfRecords - rowsPerPage; } WordListScrollTo((UInt16)newTopVisibleWord); } static void WordListDrawWord(void *table, Int16 row, Int16 column, RectanglePtr bounds) { UInt16 recordIndex; MemHandle recordH; PackedWord *recordP; char *word; Int16 x, y; recordIndex = topVisibleWord + row; recordH = DmQueryRecord(wordDB, recordIndex); ErrFatalDisplayIf(!recordH, "No such record"); recordP = MemHandleLock(recordH); word = GetWordPtr(recordP, column == word2Column); x = bounds->topLeft.x + 1; y = bounds->topLeft.y; WorkingWinDrawTruncChars(word, StrLen(word), x, y, bounds->extent.x); TblSetItemInt(table, row, knownColumn, recordP->known); MemHandleUnlock(recordH); } static void DictListDraw(Int16 itemNum, RectanglePtr bounds, Char **data) { FlipDBInfo info; Err err; err = FlipGetDatabase(itemNum, &info); ErrNonFatalDisplayIf(err, "Error getting database info."); if (err) return; WinDrawChars(info.name, StrLen(info.name), bounds->topLeft.x, bounds->topLeft.y); } static void DictListInit(UInt16 listID) { UInt16 dbs; Err err; ListPtr list; UInt16 sel; FlipDBInfo openDBInfo; list = GetObjectPtr(listID); err = FlipNumDatabases(&dbs); ErrNonFatalDisplayIf(err, "Error getting number of databases."); if (err) return; LstSetListChoices(list, NULL, dbs); err = FlipGetOpenDatabase(wordDB, &openDBInfo); ErrNonFatalDisplayIf(err, "Error getting info about open database."); if (!err) { err = FlipGetDatabaseIndex(&sel, &openDBInfo); ErrNonFatalDisplayIf(err, "Error getting index of open database."); if (!err) LstSetSelection(list, sel); } LstSetDrawFunction(list, DictListDraw); } static void WordListUpdate(void) { TablePtr table; UInt16 numOfRecords; UInt16 rowsPerPage; UInt16 rowsInTable; UInt16 row; table = GetObjectPtr(WordListTable); /* set up word list selection list */ CtlSetLabel(GetObjectPtr(WordListPopupTrigger), wordDBInfo.name); DictListInit(WordListPopupList); /* make visible rows with words usable */ numOfRecords = GetNumWords(wordDB); rowsPerPage = GetRowsPerPage(table); rowsInTable = TblGetNumberOfRows(table); for (row = 0; row < rowsInTable; row++) TblSetRowUsable(table, row, row < rowsPerPage && row < numOfRecords); // FIXME: should we remember this from last time the form was open? topVisibleWord = 0; WordListUpdateScrollBar(); } static void ChangeWordList(UInt16 index) { TablePtr table; table = GetObjectPtr(WordListTable); SwitchDB(&wordDB, &wordDBInfo, index); WordListUpdate(); TblMarkTableInvalid(table); TblRedrawTable(table); } static void WordListInit(void) { TablePtr table; UInt16 rowsInTable; UInt16 row; table = GetObjectPtr(WordListTable); TblHasScrollBar(table, true); rowsInTable = TblGetNumberOfRows(table); for (row = 0; row < rowsInTable; row++) { TblSetItemStyle(table, row, word1Column, customTableItem); TblSetItemStyle(table, row, word2Column, customTableItem); TblSetItemStyle(table, row, knownColumn, checkboxTableItem); //TblSetRowSelectable (table, row, false); } TblSetColumnUsable(table, word1Column, true); TblSetColumnUsable(table, word2Column, true); TblSetColumnUsable(table, knownColumn, true); TblSetCustomDrawProcedure(table, word1Column, WordListDrawWord); TblSetCustomDrawProcedure(table, word2Column, WordListDrawWord); WordListUpdate(); } /* Intercept hard button events to do scrolling with * arrow buttons. */ static Boolean ListEventStealer(EventPtr event) { UInt16 scrollRows; if ((event->eType == keyDownEvent)) { scrollRows = GetRowsPerPage(GetObjectPtr(WordListTable)); /* Down key. */ if (event->data.keyDown.chr == vchrPageDown) { WordListScroll(scrollRows); WordListUpdateScrollBar(); return true; /* Up key. */ } else if (event->data.keyDown.chr == vchrPageUp) { WordListScroll(-scrollRows); WordListUpdateScrollBar(); return true; } } return false; } /* Handles select events for table items. */ static Boolean ListHandleTableSelectEvent(EventPtr event) { TablePtr table; UInt16 col; UInt16 row; UInt16 recordIndex; UInt8 known; table = event->data.tblSelect.pTable; col = event->data.tblSelect.column; row = event->data.tblSelect.row; recordIndex = topVisibleWord + row; switch (col) { case word1Column: FlipWord(recordIndex, false); return true; case word2Column: FlipWord(recordIndex, true); return true; case knownColumn: known = TblGetItemInt(table, row, knownColumn); SetKnown(wordDB, recordIndex, known); return true; } return false; } /* Main event handler for the list form. */ static Boolean ListEventHandler(EventPtr event) { switch (event->eType) { case ctlSelectEvent: switch (event->data.ctlSelect.controlID) { case WordListNewButton: AddAndEditWord(); return true; case WordListFlipButton: FlipWord(0, false); return true; } return false; case tblSelectEvent: if (ListHandleTableSelectEvent(event)) return true; return false; case sclRepeatEvent: WordListScrollTo(event->data.sclRepeat.newValue); return false; case menuEvent: switch (event->data.menu.itemID) { case MenuAllUnknown: SetAllKnown(wordDB, 0); WordListUpdateTable(); return true; case MenuScramble: UtilScrambleDB(wordDB); WordListUpdateTable(); return true; } return false; case popSelectEvent: if (event->data.popSelect.listID == WordListPopupList) { ChangeWordList(event->data.popSelect.selection); return true; } return false; default: return false; } }