bskendig@phoenix.Princeton.EDU (Brian Kendig) (07/31/89)
A while ago, I made a thorough search for a command-line interface for a Macintosh. The only one I found did not quite suit my needs, so I decided to take the most logical route and create my own. Here's my problem: I want to be able to open a simple window into which the user can type commands. When he types a character, it is displayed; when he types delete, a character is erased; when he types return or enter, the entire command is parsed by the program. Simple enough, right? When I use TextEdit for the text window, the user is able to go back into the stuff already displayed and edit it. I don't want this. Besides, I can't trap for the return or enter keys easily, and even when I do, I don't know how to go back to the beginning of the line and retrieve the whole thing. A simpler way would be to ignore TextEdit. I can listen for characters and echo them to the screen when I get them, and when I get a return or enter, I can parse the line. Scrolling is a tad difficult and unwieldy, but that can be overcome. The problem here is that when the user types delete, the delete appears as a *character* on the screen - one of those little white rectangles. So, how do I do this? I want to have an IBM-style interface (hold your cries; there's a method to my madness) in a window. There's got to be an easy way! Help! -- | Brian S. Kendig | I feel more like I | bskendig | | Computer Engineering | did when I got here | @phoenix.Princeton.EDU | | Princeton University | than I do now. | @PUCC.BITNET | | Systems Engineering, NASA Space Station Freedom / General Electric WP3 |
levin@bbn.com (Joel B Levin) (07/31/89)
In article <9674@phoenix.Princeton.EDU> bskendig@phoenix.Princeton.EDU (Brian Kendig) writes: |A simpler way would be to ignore TextEdit. I can listen for characters and |echo them to the screen when I get them, and when I get a return or enter, I |can parse the line. Scrolling is a tad difficult and unwieldy, but that can |be overcome. The problem here is that when the user types delete, the delete |appears as a *character* on the screen - one of those little white rectangles. So don't just echo the characters, look at them. If you get a delete, don't echo it, erase the previous character. If you get a word-delete character (whatever you choose), don't echo it, erase the previous word, etc. terminal interfaces have been doing this for years! | |So, how do I do this? I want to have an IBM-style interface (hold your cries; |there's a method to my madness) in a window. There's got to be an easy way! I'll leave the flames to others, I sense them coming... /JBL = UUCP: levin@bbn.com (new) or {backbone}!bbn!levin (old) INTERNET: levin@bbn.com POTS: (617) 873-3463 "The night was"
bskendig@phoenix.Princeton.EDU (Brian Kendig) (08/01/89)
In article <43528@bbn.COM> levin@BBN.COM (Joel B Levin) writes: >In article <9674@phoenix.Princeton.EDU> bskendig@phoenix.Princeton.EDU (Brian Kendig) writes: >|A simpler way would be to ignore TextEdit. I can listen for characters and >|echo them to the screen when I get them, and when I get a return or enter, I >|can parse the line. Scrolling is a tad difficult and unwieldy, but that can >|be overcome. The problem here is that when the user types delete, the delete >|appears as a *character* on the screen - one of those little white rectangles. > >So don't just echo the characters, look at them. If you get a delete, >don't echo it, erase the previous character. If you get a word-delete >character (whatever you choose), don't echo it, erase the previous >word, etc. terminal interfaces have been doing this for years! Sounds simple enough, doesn't it? But: how do I erase the previous character? If I send a 'delete' to the window, it appears as a gremlin (the 'technical' name for those little white rectangles). Methinks I'd have to do some pretty snappy QuickDraw manipulations to manually erase the graphic shape of the last character I sent to the screen; think for a moment about the sheer number of calculations involved in such a move and you'll see why I don't care to try it. If I could figure out how to erase the last character I sent to the screen (and ones before that, then, if the user types delete more than once), I would be a happy puppy. (Then, what about a flashing cursor...? Ugh.) Barring that, if that ain't possible, I'd have to mess with TextEdit somehow. How? I don't know. I'd have to disable moving the cursor with mouse clicks, at the very least. TE would take care of the delete key. If I could trap for a carriage return (and I think I know how to), how can I get back into the TE record and extract all the text between this CR and the last one? I know this stuff is possible. The terminal program I'm using is doing it (well, kind of) right now. >| ... I want to have an IBM-style interface (hold your cries; >|there's a method to my madness) in a window. There's got to be an easy way! > >I'll leave the flames to others, I sense them coming... Actually, the reason I want to do this is to attract the attention of those poor souls who think that COMPLEXITY=POWER. They think that if they have to learn how to type all sorts of convoluted commands, they can do more than pointing-and-clicking could ever get them. With a little work, I could easily (?!) get this thing to recognize commands from Unix, MS-D*S, CP/M... you name it. Ain't resources great? Besides, I'd use this interface myself. Typing "cd HD:Applications:Word proc: MacWrite files" is *much* faster than digging through four cluttered windows and looking for specific folder icons. (Well, maybe not *much* faster... but you get the general idea.) Hm. Imagine what people would think of HyperCard if you were to run it on an IBM text-only system! > /JBL >UUCP: levin@bbn.com (new) or {backbone}!bbn!levin (old) >INTERNET: levin@bbn.com POTS: (617) 873-3463 -- | Brian S. Kendig | I feel more like I | bskendig | | Computer Engineering | did when I got here | @phoenix.Princeton.EDU | | Princeton University | than I do now. | @PUCC.BITNET | | Systems Engineering, NASA Space Station Freedom / General Electric WP3 |
al@inebriae.UUCP (Al Evans) (08/01/89)
In article <9674@phoenix.Princeton.EDU> bskendig@phoenix.Princeton.EDU (Brian Kendig) writes: >Here's my problem: I want to be able to open a simple window into which the >user can type commands. When he types a character, it is displayed; when he >types delete, a character is erased; when he types return or enter, the >entire command is parsed by the program. Simple enough, right? > >When I use TextEdit for the text window, the user is able to go back into the >stuff already displayed and edit it. I don't want this. Besides, I can't >trap for the return or enter keys easily, and even when I do, I don't know >how to go back to the beginning of the line and retrieve the whole thing. Maybe I'm not understanding correctly, but this actually looks to me like the best way to do what you want. You simply check for the return/enter keys before posting them to TEKey. You should be able to get the last line typed from calculations based on nLines and lineStarts in the TERec. In fact, by adding calculations based on selStart and selEnd, it should be fairly easy to allow the user to select and execute previously-entered text. In my opinion, this would be the best way to handle it. >A simpler way would be to ignore TextEdit. I can listen for characters and >echo them to the screen when I get them, and when I get a return or enter, I >can parse the line. Scrolling is a tad difficult and unwieldy, but that can >be overcome. The problem here is that when the user types delete, the delete >appears as a *character* on the screen - one of those little white rectangles. This is a bit more unwieldy, but still fairly easy. Basically, you allocate a buffer to hold the keystrokes (24X80 or whatever) and write a routine to draw this buffer on the screen (surely you don't intend to disallow DAs, etc.!) for updates. You'll probably want to provide a separate (faster) routine for drawing single characters as they're typed. But you've gotta CASE on the characters -- when the user types delete, YOU've got to move the pointer one back in the buffer, do an EraseRect on the character just deleted, etc. For scrolling, just make the buffer bigger. Is this beginning to sound like you're reinventing TextEdit? You are. Don't do this unless you absolutely HAVE to. [long story about EBCDIC term emulator and blink attributes omitted, much to the collective relief of the audience] --Al Evans-- -- Al Evans {tndev,texbell,ssbn}!inebriae!al al@inebriae.WLK.COM
tim@hoptoad.uucp (Tim Maroney) (08/01/89)
In article <9674@phoenix.Princeton.EDU> bskendig@phoenix.Princeton.EDU (Brian Kendig) writes: >Here's my problem: I want to be able to open a simple window into which the >user can type commands. When he types a character, it is displayed; when he >types delete, a character is erased; when he types return or enter, the >entire command is parsed by the program. Simple enough, right? (Too bad no women will be using the software, eh?) Simple, yes, but it seems like you want something so simple that it violates users' expectations of the Mac user interface. >When I use TextEdit for the text window, the user is able to go back into the >stuff already displayed and edit it. I don't want this. Why? If you're going to be displaying text, I assure you that you *do* want users to be able to copy and paste it at least. If you don't want them to be able to change it, then that's easy enough -- don't allow any typing while there's a selection anywhere but at the end of the text, and don't pass on Cut or Clear commands. However, this is an inferior solution -- it implies that users can't use the normal text editing mechanisms on the Macintosh to edit their command lines. That's a mess. I recommend that you re-examine this assumption that editing the command text is bad. It works quite well in the MPW Shell, after all. >Besides, I can't >trap for the return or enter keys easily, and even when I do, I don't know >how to go back to the beginning of the line and retrieve the whole thing. Why? You are getting event records with the character codes stored in them in a not very subtle fashion. What prevents you from checking for them? Getting the text line is admittedly a bit harder, but the line starts array stored in the text edit record is not hard to use either. Just look in the last line start entry, add the offset to the start of the text area (a handle to which is stored in the text edit record) and extract the line there to the end of the record. >A simpler way would be to ignore TextEdit. I can listen for characters and >echo them to the screen when I get them, and when I get a return or enter, I >can parse the line. How is getting a return or enter here any different from if you are calling TextEdit to handle characters? You're dealing in the same commodity, key down event records. >Scrolling is a tad difficult and unwieldy, but that can >be overcome. The problem here is that when the user types delete, the delete >appears as a *character* on the screen - one of those little white rectangles. Yes, of course, if you call Quickdraw with that character code, you get whatever the Font Manager says is the appearance of that character. If you want to do editing, then you'll have to do your own using other Quickdraw calls, specifically, MoveTo (to backspace over the previous character) and EraseRect (to get rid of the image of the previous character). You will also have to draw your own flashing caret using MoveTo and LineTo calls. And your own selection handling, with all the mouse tracking and InvertRect calls and so forth. If you don't do all this, you haven't really written a Mac program. >So, how do I do this? I want to have an IBM-style interface (hold your cries; >there's a method to my madness) in a window. There's got to be an easy way! The easy way is to use TextEdit. That puts an effective length limitation on the size of your text, but you can cope with a screenful. But I have to question whether there really is a method to this. I feel that your comments are rife in assumptions that conflict with the basic goals of the Mac interface, and which seem to show that you don't have a lot of Mac experience yet. Most of us went through this stage; a horrible example is the MacNosy interface. You will likely find that after you assimilate more of the basic Mac concpets, you will decide that your decision to provide a command line interface was not a very good one. It may be that you do have some reason, but you haven't shared it with us. Nonetheless, because of your Mac inexperience, I am inclined to think that your design decisions have a great deal to do with a mental model that speaks well to the tty-interface problem and very badly to the Mac-interface problem. -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com "The pride of the peacock is the glory of God. The lust of the goat is the bounty of God. The wrath of the lion is the wisdom of God. The nakedness of woman is the work of God." - Blake, "The Marriage of Heaven and Hell"
guido@piring.cwi.nl (Guido van Rossum) (08/01/89)
Well, it seems like you want to write your own textedit-like package, only less fancy, and with some features that textedit doesn't have (or maybe it does, only it's hidden somewhere in the documentation). You could begin by splitting the design in two parts (this is what textedit also does, basically): a data structure to remember the text to be displayed (maybe only the still editable part would be enough, although then you couldn't reconstruct stuff that got temporarily hidden under a desk accessory or some similar thing from outer space, not to mention MultiFinder), and code to display it on the screen, by drawing all characters using quickdraw operations. Editing the buffer is easy: keep a counter of how many characters there are, etc. Conceptually, after each edit operation (append/erase character), you could erase the screen and redraw everything -- if only your code were fast enough to avoid flickering. What you do in practice is keep some extra data around to avoid unnecessary redrawing. The start and ending position of each character in the editable part of the buffer should be sufficient, really. Actually, you can compute this on the fly as well -- quickdraw has some nifty calls to calculate the width of a character. Of course, restricting yourself to a fixed-width font such as monaco would make things a lot easier. Etc., etc.; if you think a bit more about it you'll see it's entirely doable, but you may decide not to implement it as it could be a lot of work (although also a lot of fun). -- Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam guido@cwi.nl or mcvax!guido or guido%cwi.nl@uunet.uu.net "You're so *digital*, girl!" -- Neneh Cherry
jakob@nada.kth.se (Jakob Cederlund) (08/01/89)
In my opinion you should do it just like the MPW Shell does it: Return key does nothing except splitting the text line. ___ Enter ^ key executes the selection. If nothing is selected it executes the line with the caret on. If several lines are selected, they are executed in order. Using this method you do not have need for any special treatment of rubout, users going back in the text etc. BTW MPW Shell uses a not too bad script language, take a look at it. /Jakob Cederlund jakob@nada.kth.se Computer Science Dept. Royal Institute of Technology, Stockholm, Sweden
svc@well.UUCP (Leonard Rosenthol) (08/02/89)
In article <9674@phoenix.Princeton.EDU>, bskendig@phoenix.Princeton.EDU (Brian Kendig) writes: > A while ago, I made a thorough search for a command-line interface for a > Macintosh. The only one I found did not quite suit my needs, so I decided > to take the most logical route and create my own. > > Here's my problem: I want to be able to open a simple window into which the > user can type commands. When he types a character, it is displayed; when he > types delete, a character is erased; when he types return or enter, the > entire command is parsed by the program. Simple enough, right? > > When I use TextEdit for the text window, the user is able to go back into the > stuff already displayed and edit it. I don't want this. Besides, I can't > trap for the return or enter keys easily, and even when I do, I don't know > how to go back to the beginning of the line and retrieve the whole thing. > Just because the default interaction of TE does what you describe above does NOT mean that it HAS to. Since all events go through your application (or whatever) BEFORE TE gets them, you can do all sorts of preprocessing to decide whether TE should get them at as is, modified, or not at all. For example, to prevent editing of previous text, you can check the selection point/rect (TE^^.selStart, TE^^.selEnd) and if it is not on the last line of the text (current entry line, I am assuming one line at a time) (you can get lines using the TE^^.lineStarts array) then don't process keydowns, edit commands, etc. As to trapping the return/enter keys you get the keyDown first, and simply check to see what the key is and if CR or Enter than get the last line using the lineStarts array and TE^^.length and parse it, etc. If you need some example code for using the lineStarts array I can dig some up and post it. > A simpler way would be to ignore TextEdit. I can listen for characters and > echo them to the screen when I get them, and when I get a return or enter, I > can parse the line. Scrolling is a tad difficult and unwieldy, but that can > be overcome. The problem here is that when the user types delete, the delete > appears as a *character* on the screen - one of those little white rectangles. > As mentioned above, TE will work just fine. If, however, you want to write your own then you will need to do certain things to emulate TE. For example, you site one of the best examples, the handling of backspace. The backspace character is a character in teh font just like any other, and as such you really do want to call DrawChar on it. What you want to do is to back the 'cursor' up one character (probably erasing it as well), just like TE does. the other major problem would be handling of scrolling, storage, etc. I think your tiem would be best spent working with my above suggestions to use TE rathe than reinventing the wheel for this 'simple' taks. -- +--------------------------------------------------+ Leonard Rosenthol | GEnie : MACgician Lazerware, inc. | MacNet: MACgician UUCP: svc@well.UUCP | ALink : D0025