change string indexing to avoid invalid indexes

I felt it was strange that using invalid indexes was fairly routine in our string code and API. Some functions returned them, and some functions practically expected them as input. There were `i+1` and `i-1`s sprinkled here and there, to be fixed up eventually by a call to `thisind`. I don't think this is a good practice, and we should just use valid indexes. The only exception is the special index `nextind(s, endof(s))`, which identifies the empty space at the end of the string (for example when searching for the empty string).

The clearest example is in the commit message; `search("∀ x", "∀", 1)` gave `1:3`. Using `last(r)` of that range could result in an invalid index error. Now it gives `1:1`, a range of character indexes that is inclusive like all other index ranges. This can of course still be passed to `getindex`, which then no longer needs to call `thisind`.

Another way to look at this is that some functions tolerated invalid string indexes, and others gave errors, which is a bit confusing. It also made the behavior of `isvalid`, `nextind`, and `prevind` more ambiguous, since some indexes were completely invalid due to being out of bounds, while others were "less" invalid.

This also makes `next` and `nextind` more consistent: they give the same value when called on `endof(s)`.