Oh man, this thread is so painful to read. It's almost enough to make me want to document this stuff. :) Although actually, some of it is documented on the Scamper swiki page (or, some page nearby to it. I don't have Internet access to check the exact location right now.)
For new, let me correct a few mistakes.
Close tags are *not* required. If they were then lists wouldn't work, because people hardly ever put in the </li>'s. In fact, Scamper copes not only with omitted close tags, but with lots of erroneous HTML, as well. This is why it uses a hand-written parser instead of a much more elegant SGML parser. (A nice thing about XML is a social one: it's so verbose and obscure that nobody wants to write it by hand, and so it's socially acceptible for parser's to just dump even slightly erroneous input on the floor.)
The mayContain: idea is crucial for both of these, and the parsing problem people saw is surely because one or more of the various HtmlTable class's has an incorrect mayContain: method. It's worth spending a few minutes getting these #mayContain: methods to something reasonable, instead of just returning true all the time -- it helps with making reasonable parses of bad HTML, and it helps when processing the HTML after it's parsed, because you know, e.g., that TABLE's only contain TR's.
Finally, Scamper *does* use content-type. If it's not working for some php script, it's because the script specifies the wrong content-type.
Okay, those little bits aside, here is a skeleton design for adding tables. I'll leave out the details of building the table morph itself -- frankly, I don't even know exactly how! :)
The core idea is to make outputStream be a stack, ie "outputStreams" instead of "outputStream". Add an #outputStream method that returns the top element of outputStreams, update all users of the outputStream ivar to use the #outputStream method, and then add some methods like:
#startNewOutputStream #endCurrentOutputStream
(Here would be a good time to run regression tests. Ah well, too bad there aren't any.)
Now, to format a table, add a addToFormatter: method to HtmlTable like this:
addToFormatter: formatter | tm | tm := "insert your code to make a table morph". self subEntities do: [ :rowEntity | tm startNewRow. rowEntity subEntities do: [ :cell | formatter startNewOutputStream. cell addToFormatter: formatter. tm addCell: formatter formattedText. formatted endCurrentOutputStream ] ]. formatter addMorph: tm
Note, critically, that #formattedText should return the text of the *current* output stream, not of of the whole document. This will probably happen automatically, but be aware of this as you read the above code.
And that's it. Now you just have to figure out how to make TableMorph's at all!
By the way, here are two other tricks people will be interested in, once you start playing with tables.
First, you can get tables to resize horizontally by adding some sort of widthProportion instance variable to TextAnchor (TextAnchor is the subclass of TextAttribute that Text uses to deal with embedded morphs). Then, TextAnchor>>emphasizeScanner can resize the morph before doing its normal thing, if this instance variable has been set. Bolot and I put together something like this once upon a time, but it got lost. I leave figuring out the width of a CharacterScanner as an excercise for those who have a lot of time.
Second, you can add a TextAlignment attribute that allows centered text, but this is a tad more work. You must make all uses of "textStyle alignment" in CharacterScaner+subclasses use the "alignment" instance variable, instead. The rest is really easy: add an #allignment: method in TextAlignment that sets the alignment, and make TextAlignment>>emphasizeScanner: set the alignment on the supplied formatter.
Cheers! Like Je77, I'm really excited to see people playing with this -- tables would make Scamper much nicer to use!
By the way, frames aren't too far away, once we have tables -- one could use the same table morph that tables use, but with some sort of "DownloadingHtmlMorph" in the cells. DownloadingHtmlMorph will look like DownloadingImageMorph, except that it downloads and displays HTML instead of images.
My apologies for not reading any of the specific table packages people have posted. The above fixes all of the problems people have mentioned having, though, and so unless everyone is burned out now I'll wait until someone has a more complete solution.
Lex Spoon
Well, know I tracked down the culpit of the problem and that was me... I had changed the mayContain in HtmlTableDataItem to mayContain: anEntity ^ true.