The problem with whole-word-only searching seems to be a function of the TURESearch class which is in the JEDI JCL library. Alongside that class, though, is another unicode implementation of TSearchEngine, named TUTBMSearch (for Unicode Tuned Boyer-Moore). Switching to this class seems to have completely solved the problem.
Now that FindAll
is basically working (the only caveats are also applicable to FindNext
, and are external to FindAll
itself), I found it straightforward to implement the GoToSearchHit
routine. The list of KWIC items found in FindAll can now be double-clicked, to jump directly to one of the items, highlighted.
Before getting back into the difficulties of Replace, I decided to get my head back into the code by tackling the relatively simpler FindAll functionality, which involves retrieving and storing a KWIC-style display for the user, who can then double-click on individual hits to view them in the GUI. Got this working fairly well, although one bug remains: the WholeWordOnly setting doesn't seem to be passed through, or if it is passed through, it doesn't seem to be honoured by the FindNext function. This needs to be fixed. I should also test the MatchCase parameter.
Fixed the menu bug reported by DP, and also ported the fixes (XSLT, CSS and JS) into the version of the code which is used on the Mariage site. The Mariage code is very similar, except that it uses camelBack notation, in order to match the rest of its code; this raises the issue of whether I should camelBack the IMT code (by which I mean the XHTML, XSLT, JS and CSS used in the Web View).
DP reported a bug in the Web View output that affects pages with huge annotation lists. The annotation menu appears to have a scrollbar, but in fact it doesn't scroll, so you can't get down to the bottom elements in the list; and because it's position: fixed
, even though the page itself scrolls to accommodate it, you can't get down to the bottom of the list because the menu doesn't move with the page. The sample page is here.
There's a JavaScript function called Initialize() that does a lot of the positioning and sizing work. It contains this line:
document.getElementById('AnnMenu').style.overflow = 'scroll';
which should make the scrolling work, but I suspect the height of the container element is being extended too far, and the container doesn't have a scrollbar. I see a line commented out, just before that:
// L.style.maxHeight = ImgHeight + 'px';
That would set the max height of the menu container, which might achieve the desired effect, but if I've commented it out, it's probably because of some unwanted side-effect (probably with IE, which doesn't support CSS max-height).
Testing the IMT under Wine on my EEE PC at home reveal some problems due to the low screen res (800 x 480) of the EEE PC. Since I'm planning to present the project on the EEE PC in June, I need to work on these, and it makes sense to fix them anyway, because they may affect other users working under Wine.
The core problem is that the annotation category window shows up sized to the desktop height (which is 480px less the taskbar height). When this happens, the bottom two controls (OK and Cancel buttons) are chopped off, although oddly the status bar, which is below them, remains. Even though the window manager (IceWM in this case) is set up to allow windows to be bigger than the desktop, when you resize this window to try to get back the controls, you just get a black area with redraw failure artifacts.
There are various possible reasons for this, and these are my approaches to them:
- The form style of that particular window is unusual; it's fsStayOnTop, ensuring that it appears above the main window at all times. That could be screwing up IceWM or Wine, so I've added an option to hold down the Shift key while starting the app, which should set it back to fsNormal for testing purposes.
- The original window size was nearly 600 pixels, meaning that the window would have to be aggressively resized in order to fit on the screen. This might well happen before my own code for restoring the form state (including window size) kicks in, so the problem may occur before my code even tries to resize the window. To avoid this, I've reduced the original window height considerably, putting it well under 480px. I should be able to test starting the app with no previous window size settings (having deleted them from the user profile), and see if that successfully avoids the aggressive resizing, and if so, whether it solves the problem.
- There may be some constraint somewhere in the code which is interacting with the aggressive resizing done by the window manager. I've searched for this, but all I can find are MinHeight settings on two of the panels, one at 100px and one at 200px; these combined do not prevent the window from sizing to 480px, so I don't thinkt that's the problem.
I'll test these changes and see if they have any effect.
On the surface, Replace is just Find + changing the selected text, but of course it's not that simple; the change puts the textbox data out of sync with the back-end document, so there needs to be a save before the next operation is invoked.
This actually applies to some extent with Find alone; if there's dirty data, I guess changes might be lost with the right combination of actions. I think it makes sense, therefore, to check for dirty data before every Find or Replace operation; or perhaps to save a Replace change back to the document automatically. If the latter, we risk confusion, as the user may assume that, since they haven't pressed OK in the edit box, the data isn't saved. If the former, then we risk annoying the user with popups. One final option is that, if an item is already visible, we search in the live text of that item (ie the text in the GUI) rather than the back-end document. This would be the most intuitive approach from the user's point of view, but perhaps the most programmatically fragile because of the need to search and display hits in two distinct ways, depending on whether an item is live in the GUI or not.
This needs some careful thought.
Implemented a simple tracking system so that the main form knows which of the three document forms in the app last received focus, and the Find now works because it knows where to start from.
All three bugs in the previous posting are now fixed. The Find functionality appears to be working pretty well, with the exception of one new bug which has emerged:
When a search hit is found in an annotation title, it often seems to stick on that ann title and not move on when Find is pressed again; it's as if if fails to get the next container correctly, and searches again within the same container. The reason for this is that the code which determines where the cursor is currently located (GetCursorLocation
), which is called to find out where to start searching from, cannot yet tell where the focus last was; it can't just ask which form has focus, because obviously what has the focus is the Search form itself, which has invoked the Find action. Therefore, currently, it just checks to see which windows are visible, and if the teiHeader window is visible, it assumes that one had the focus. Of course, if searching has been done, that's not necessarily the case; it may just have been left open. But if so, it always starts the search from that container, working forward, and therefore always finds the same hit if the hit is in an annotation title.
Currently working on a solution.
Found and fixed the bug in the code which checks to see whether a search has looped right around, so now searching stops after traversing the whole document. Then I looked at the search code itself, and found the bug which prevented searches from working. Now searching works, and repeated searches take you through the whole document. These are the remaining bugs with Find:
- Anything that finds a hit in a Category ID causes an endless loop. This is probably just a typo that keeps sending the thing back to the same container.
- Although hits in annotation titles, annotation text, and category explanations are all correctly highlighted, when a hit is found in the teiHeader, the selection is off by one (shifted forward one character). This might be caused by trimming taking place in some place but not in another.
- There's no default action that happens when you press Return in the find/replace dialog box. It should probably be Find, which is non-destructive.
These don't look like showstoppers.