TweetFollow Us on Twitter

Terminal Emulation
Volume Number:2
Issue Number:3
Column Tag:Threaded Code: Neon

Scrap Support for Terminal Emulation

By Jörg Langowski, EMBL, c/o I.L.L., Grenoble, Cedex, France, MacTutor Editorial Board

"NQSD" terminal emulator

First, lets continue and finish the example from last month's NEON column by adding (finally!) the scrap support (You may remember that I promised to write something about scrap handling some time ago).

Actually, I have reworked the example somewhat. Neon supports a rudimentary form of multitasking which makes event handling a lot simpler, so I added that; then, of course, I promised to add support for serial I/O so that we would end up with a not-quite-so-dumb terminal program (not quite, since we will be able to do cutting/pasting and therefore capture text files). The 'finished' example (to be expanded and improved by you) is shown in Listing 1.

Scrap handling in NEON (and other Forths, for that matter)

Let's first look at the way the scrap can be passed around between applications. I will limit myself to text scrap only, since that's what our example is using.

The crucial point here is that the 'scrap' that TextEdit uses is internal to the TextEdit routines, so that it will not automatically become part of the clipboard after a TECut is executed. If you don't believe this, start up last month's example and open the Note Pad desk accessory. Cut or Copy some text from the TE window (using the TEmenu), click the notepad and then try to paste it (using ctrl-V, since the Edit menu has been lost). Nothing happens. Also, if you cut text from the notepad and try to paste it into the TEwindow, that won't work either.

This proves what you might have known already, namely that the desk scrap (contained in the Clipboard) does not have anything to do with the TE scrap, and that we need a set of routines that transfer text between those two kinds of scrap.

Refer to the listing. The magic numbers that we need are system globals, the length of the TE scrap at $AB0 and its handle at $AB4. The length of the desk scrap is maintained in $960.

Two routines transfer the scrap from TE to desk and vice versa. put.tescrap, as you might have guessed, takes the TE scrap and puts it into the clipboard. It uses the toolbox trap putscrap, which is a function that returns a 32-bit result code (0 if ok) and is called with the stack set up as follows:

- 0 for the return code

- a 32-bit integer giving the length of the data that goes into the scrap

- the resource type, 'TEXT' or 'PICT'

- a pointer to the beginning of the data.

We first check whether there is any text edit scrap available at all, and if it is, zero the desk scrap (=: clear the clipboard). Then the parameters for putscrap are set up, converting absolute addresses to NEON-relative (-base) and dereferencing handles where necessary. After exiting, the clipboard will contain a copy of the text edit scrap. The resource type constant 'TEXT'is contained in txtype, which is defined in FrontEnd.

get.tescrap does the opposite: if desk scrap is available, it will transfer it into the TE scrap by calling getscrap with the parameters:

- 0 to hold the return result (the total length in bytes)

- the handle to the TE scrap

- the resource type 'TEXT'

- the value variable theOffset, also defined in FrontEnd.

We assume that there is only TEXT type scrap in the clipboard, so theOffset (which tells you where in the clipboard the desired type of resource starts) won't interest us. After the call, the TE scrap will contain whatever TEXT scrap was in the clipboard.

put.tescrap and get.tescrap will now have to be built into the code that defines our editing window. put.tescrap is installed into the window's activate action vector. No vector is provided in NEON to handle deactivate events, therefore we redefine the disable: method for that window so that it includes get.tescrap.

You might now want to install just these changes into last month's example, then run the program and open the note pad. Now cutting text out of the note pad (using ctrl-X), clicking the edit window and pasting it there (using the TEmenu) should give the correct results. The opposite transfer should work, too.

In order to install the serial I/O support and simplify the whole application somewhat, we'll use the multitasking that is provided in the NEON source files. Let me first say some words about how multitasking can be achieved under NEON.

Multi-tasking the NEON way

The NEON system supports a simple form of 'concurrency' (contained in the file Tasks that is part of the NEON system). Tasks redefines the null event vector NULL-EVT in such a way that it sequentially executes a set of words that are contained in the Ordered-Col list tasklist (This feature is not described in the first release of the manual). To use the multitasking support simply type // tasks .

A new task is added to the tasklist by putting its cfa on the stack and calling addtask, it is removed again from the list by calling killtask with the task's cfa on the stack. So instead of redefining the event handler to include a call to TEIdle and cursor adjustment (as we did last time), we can simply define

: idle.text 
  idle: mytext adjust.cursor ;

and then put the cfa of this word into the task list by saying

'c idle.text addtask

This will make the caret blink and give the cursor the correct shape while the main event loop can be kept in the simple form given in the NEON manual

begin key makeint key: mytext again

where the makeint comes in because TEkey expects a 16-bit integer on the stack.

What is done here is not true multi-tasking, of course. Each word that is put into the task list is executed all the way to its end before the next 'task' becomes active. True multi-tasking would include some means to leave a word before it is finished, saving the task's parameters so that it may be resumed where it was left.

One way multi-tasking can be done, for example, is to issue interrupts at regular intervals (by some real-time clock or, in the Mac, through the vertical retrace), and on each interrupt switch tasks. At this point one would save a copy of the task's register status in an area local to that task and proceed to the next one. Another possibility is that the task itself calls the scheduler to switch to the next task at certain strategic points - like when a character is being output to the screen.

The way VBL tasks are handled in the Mac is an example of the first method [see also the article by Bob Denny in MacTutor V1#9]. The problem on the Mac is that the time allocated for a VBL task cannot be too long. All tasks within the VBL task queue must complete before the next vertical blanking interrupt comes in (which is 16.67 msec). Here again, there is no possibility to leave a task in the middle of execution and jump to another one.

An example for the other method (the task itself calls the scheduler, which activates the next task) is the way desk accessories are handled, because here you will call SystemTask from within your application each time you think the desk accessories should get something to eat. However, the DA's Control routine will have to execute all the way until it is finished - no interruption possible -, so in this case we have a master task (the application) which calls slave tasks (the desk accessories).

A full implementation of the second method of task scheduling has been achieved in a new Forth system - Mach1 - which has been advertised in this journal and which I am going to review in the next article. This system - under Forth - is almost as close as you can get to true multitasking on the Macintosh; watch for some new exciting information next month.

For the time being, we will have to stick to the constraints of the NEON multitasker, which means that words installed into the tasklist have to be short in execution because they will have to finish before the next task gets its turn. The idling routine is fast enough so that you don't notice any annoying delay.

Serial port handling

Another task that we will put into tasklist is a routine that will watch for characters to come in through the serial port and put them into the TE record wherever the insertion point is. Then we may - optionally - send the keystrokes not directly into the TE record, but to the serial output port and convert our editing example into a terminal emulator.

The listing shows how to do it. Serial port handling is contained in the NEON source file drvr and serial, so these will have to be loaded first. We define modin and modout for the serial input and output ports and initialize them to 8 data bits, 2 stop bits, no parity and 300 baud. (Yes, unfortunately this program will handle only 300 baud, because no handshake has been added yet. You may use it at any speed, but have to watch for characters getting lost.)

The init: , config: and baud: methods will set the configuration word of the port object, but not actually reconfigure the serial port itself. This is done by reset:, which may be used only after sending an open: to the port (otherwise -> bomb).

We implement the input and output handlers to work asynchronously, using the methods readNW: and writeNW: provided by the system. These routines need the pointer to a completion routine as a parameter. The completion routines are defined using the NEON word :proc (note that you may never execute a :proc directly, but may only pass it as a parameter to a toolbox routine).

A :proc should be short, and therefore the routines only set flags that indicate that something has been received in the buffer or that the port is ready to transmit another character.

getone and typeone are the words that are used to read and write the serial port. getone does absolutely nothing as long as no character has been received; otherwise, it inserts this character into the TE record at the insertion point and starts the next asynchronous read. typeone will wait until the output port is ready to send data and then initiate an asynchronous write.

The background serial read is installed into the task list by

'c getone addtask

and when a character is typed out using typeone, the echo will be inserted into the TE record at the right position (assuming that the modem port is connected to some other system that supports full duplex communication).

I have provided two routines that let you change between typing text into the TE record locally and doing full duplex communication. Another menu -localmenu- is provided to switch between these two modes. The revised menu text is printed in listing 2.

This terminal emulator is now ready to capture text files through the serial port and transferring them through the clipboard to other applications.

Coming up: the review of the multi-tasking Forth system Mach1; a revision of the decompiler that can be used on NEON words and objects; and more.

Listing 1: Text Edit in NEON with scrap handling and serial support
\ application template example 
\ added scrap handling and some serial support
\ (c) J. Langowski 1986 for MacTutor V2#3
 
( te scrap to  desk scrap copy, uses definitions from frontEnd ) 
 hex    AB0 constant tescrap.len                                
          AB4 constant tescrap.handle
          960 constant scrap.len
decimal
                             
: put.tescrap  ( copy te scrap to desk scrap )  
     tescrap.len -base w@  ( scrap available? ) 
     if  0 call zeroscrap drop
         0 tescrap.len -base w@  txtype 
         tescrap.handle -base @ >ptr +base  
         call putscrap drop
     then   
;            

: get.tescrap  ( copy desk scrap to te scrap )       
     scrap.len -base @  0> 
     if   0 tescrap.handle -base @ txtype abs: theOffset 
            call getscrap 
            tescrap.len -base W! 
     then   
;    

\ revised version of class editwindow.
\ some of the previously defined words 
\ are needed in this class 

:class editwindow <super ctlwind
    TErecord text
    var TEscrollbar
    int position

    :M teinit: new:    text ;M
    :M settext: settext: text ;M
    :M terec:  addr:   text ;M
    :M key:    key:    text ;M 
    :M idle:   idle:   text ;M

    :M act:    act:    text ;M
\ deactivate has to be handled explicitly by disable: 
\ for correct scrap handling
    :M deact:  deact:  text ;M
    :M disable: deact: text  put.tescrap  
         disable: super ;M
 
    :M click:  click:  text ;M
    :M cut:    cut:    text ;M
    :M copy:   copy:   text ;M
    :M paste:  paste:  text ;M
    :M getcont: getrect: self swap 15 - swap ;M

\ draw: redraws window, recalculates text boundaries
    :M draw: getvrect: self calc.scroll.length
       16 swap size: [ obj: TEscrollbar ]
             moveto: [ obj: TEscrollbar ] draw: super 
       getcont: self setdest: text  
       getcont: self setview: text
       recalc: text  
       0 get: [ obj: TEscrollbar ] -1 * scroll: text
       getrect: self put: temprect 
       abs: temprect call invalrect
       (abs) call beginupdate  update: text 
       (abs) call endupdate 
    ;M
    
    :M release: release: text dispose: TEscrollbar ;M
    :M setcr:  setcr:  text ;M
    :M showscr: show: [ obj: TEscrollbar ] ;M
    :M classinit: heap> Vscroll put: TEscrollbar ;M
    :M initscroll: getvrect: self calc.scroll.length 
         addr: self  new: [ obj: TEscrollbar ] 
    ;M
    :M scroll: 
         dup +: position 0 swap -1 * scroll: text 
    ;M
    :M adjust: get: [ obj: TEscrollbar ] 
         get: position - scroll: self 
    ;M
    :M getscr: obj: TEscrollbar ;M
;class  

\ now setup serial support for window
     port modin    port modout
    0 0   init: modin    0 1   init: modout
    300 baud: modin   1 8 0 config: modin
\ the next line isn't really necessary, 
\ since the control routines work on both ports
\ simultaneously, anyway...
    300 baud: modout 1 8 0 config: modout

open: modin        open: modout
reset: modin       reset: modout

0 value rxfull   0 value txempty
0 variable serbuf

:proc inputdone     1 -> rxfull     ;proc
:proc outputdone   1 -> txempty ;proc

\ define main editing window
editwindow mytext

\ routines for background tasks
: adjust.cursor 
    word0 where: themouse pack 
    getcont: mytext put: temprect 
    abs: temprect call ptinrect word0 
    if ibeamcurs else call initcursor then 
;

: idle.text 
    idle: mytext adjust.cursor ;

\ serial i/o for TE record
: getone 
    rxfull if
            0 -> rxfull
            serbuf c@ dup 10 = 
                if drop 0 then  \ remove linefeeds
            makeint key: mytext
            'c inputdone serbuf 1 readNW: modin
            drop  \ get rid of fcode
           then
;

: typeone
    txempty if 
             serbuf c!
             'c outputdone serbuf 1 writeNW: modout
             drop \ junk fcode
            then
;


\ action words, changed w/multitasking support
: myact get.tescrap act: mytext ;
: ciao 
    'c getone killtask
    'c idle.text killtask 
    select: fwind set: fwind 
    release: mytext put.tescrap quit 
;
: mycont where: fevent g->l false makeint 
  click: mytext ;
: initwind <[ 4 ]> 'cfas ciao myact null mycont 
  actions: mytext 
;

: inup get: [ getscr: mytext ]  10 - 
  put: [ getscr: mytext ] adjust: mytext ;
: indn get: [ getscr: mytext ]  10 + 
  put: [ getscr: mytext ] adjust: mytext ;
: pgup get: [ getscr: mytext ] 100 - 
  put: [ getscr: mytext ] adjust: mytext ;
: pgdn get: [ getscr: mytext ] 100 + 
  put: [ getscr: mytext ] adjust: mytext ;
: thmb adjust: mytext ;
: initctl <[ 5 ]> 'cfas inup indn pgup pgdn thmb 
           actions: [ getscr: mytext ] ;

\ menu handlers
\ Edit menu
: cut cut: mytext ;
: copy copy: mytext ;
: paste paste: mytext ;

\ local/line switch
1 value linesw
: local  0 -> linesw ;
: online 1 -> linesw ;

: start.edit 
    begin key linesw 
    if typeone else makeint key: mytext then 
    again 
;

2 menu localmenu  
3 menu TEmenu 
1 menu filmen

rect edw  rect edest  rect eview
50 50 400 250 put: edw
5 5 380 240 put: edest  get: edest put: eview

: main  " TEmenu.txt" getmtxt 
    edw " Test Edit Window" docwind true true 
    new: mytext  initwind  
    call teinit 
    0 abs: edest abs: eview  teinit: mytext
    32 32 500 300 true setgrow: mytext
    10 10 500 300 true setdrag: mytext
    0 setcr: mytext  initscroll: mytext  initctl
" Text Edit Window, example MacTutor V2#3 (c) 1985 J. Langowski"
            settext: mytext
    0 2000 putrange: [ getscr: mytext ]
    select: mytext  set: mytext  
    'c idle.text addtask
    1 -> rxfull   1 -> txempty
    'c getone addtask
    start.edit 
;
Listing 2: Menu Text file for example
APPLEMEN  1
  "$14" 
    "About Neon™..." about
    "(___________"  null
    "RES"  DRVR   \  get desk acc
    "\\\"  
FILMEN  256
  "File"
     "Quit"   bye
     "\\\"
TEMENU 261
  "TEMenu"
     "Cut/X" cut
     "Copy/C" copy
     "Paste/V" paste
     "\\\"
LOCALMENU 262
    "Terminal"
        "Local" local
        "Line" online
        "\\\"
xxx
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

WhatsApp 0.2.8000 - Desktop client for W...
WhatsApp is the desktop client for WhatsApp Messenger, a cross-platform mobile messaging app which allows you to exchange messages without having to pay for SMS. WhatsApp Messenger is available for... Read more
TunnelBear 3.5.1 - Subscription-based pr...
TunnelBear is a subscription-based virtual private network (VPN) service and companion app, enabling you to browse the internet privately and securely. Features Browse privately - Secure your data... Read more
Typinator 7.4 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
Monosnap 3.4.9 - Versatile screenshot ut...
Monosnap lets you capture screenshots, share files, and record video and .gifs! Features Capture Capture full screen, just part of the screen, or a selected window Make your crop area pixel... Read more
Fantastical 2.4.5 - Create calendar even...
Fantastical 2 is the Mac calendar you'll actually enjoy using. Creating an event with Fantastical is quick, easy, and fun: Open Fantastical with a single click or keystroke Type in your event... Read more
TunnelBear 3.5.1 - Subscription-based pr...
TunnelBear is a subscription-based virtual private network (VPN) service and companion app, enabling you to browse the internet privately and securely. Features Browse privately - Secure your data... Read more
Typinator 7.4 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
Fantastical 2.4.5 - Create calendar even...
Fantastical 2 is the Mac calendar you'll actually enjoy using. Creating an event with Fantastical is quick, easy, and fun: Open Fantastical with a single click or keystroke Type in your event... Read more
Monosnap 3.4.9 - Versatile screenshot ut...
Monosnap lets you capture screenshots, share files, and record video and .gifs! Features Capture Capture full screen, just part of the screen, or a selected window Make your crop area pixel... Read more
Skim 1.4.32 - PDF reader and note-taker...
Skim is a PDF reader and note-taker for OS X. It is designed to help you read and annotate scientific papers in PDF, but is also great for viewing any PDF file. Skim includes many features and has a... Read more

Latest Forum Discussions

See All

Everything about Hero Academy 2 - The co...
It's fair to say we've spent a good deal of time on Hero Academy 2. So much so, that we think we're probably in a really good place to give you some advice about how to get the most out of the game. And in this guide, that's exactly what you're... | Read more »
Everything about Hero Academy 2: Part 3...
In the third part of our Hero Academy 2 guide we're going to take a look at the different modes you can play in the game. We'll explain what you need to do in each of them, and tell you why it's important that you do. [Read more] | Read more »
Everything about Hero Academy 2: Part 2...
In this second part of our guide to Hero Academy 2, we're going to have a look at the different card types that you're going to be using in the game. We'll split them up into different sections too, to make sure you're getting the most information... | Read more »
Everything about Hero Academy 2: Part 1...
So you've started playing Hero Academy 2, and you're feeling a little bit lost. Don't worry, we've got your back. So we've come up with a series of guides that are going to help you get to grips with everything that's going on in the game. [Read... | Read more »
What mobile gaming can learn from the Ni...
While Nintendo might not have had things all its own way since it began developing for mobile, one thing it has got right is the release of the Switch. After the disappointment of the WiiU, which I still can't really explain, the Switch felt a... | Read more »
Programmer of Sonic The Hedgehog launche...
Japanese programmer Yuji Naka is best known for leading the team that created the original Sonic The Hedgehog. He’s moved on from the speedy blue hero since then, launching his own company based in Tokyo – Prope Games. Legend of Coin is the... | Read more »
Why doesn't mobile gaming have its...
The Overwatch League is a pretty big deal. It's an attempt to really push eSports into the mainstream, by turning them into, well, regular sports. But slightly less sweaty. It's a lavish affair with teams from all around the world, and more... | Read more »
Give Webzen’s new billiard game PoolTime...
Best known for producing hugely popular MMO titles, South Korean publisher Webzen is now taking aim at a different genre altogether. PoolTime is a realistic eight ball pool simulator, allowing you to compete in real-time matches against players... | Read more »
Let Them Come Guide - How to survive aga...
Let Them Come is all about making it as far as possible against overwhelming odds. Check out some of these tips to help you last a little longer in your unwinnable fight: [Read more] | Read more »
All the best games on sale for iPhone an...
Happy last day of the week. I hope you've been having a good one. I have. I saw ten doggos today. So because I'm in a good mood, I thought I'd round up all of the best games that are currently on sale on the App Store. [Read more] | Read more »

Price Scanner via MacPrices.net

Apple now offering Certified Refurbished 2017...
Apple has Certified Refurbished 9.7″ WiFi iPads available for $50-$80 off the cost of new models. An Apple one-year warranty is included with each iPad, and shipping is free: – 9″ 32GB WiFi iPad: $... Read more
10″ iPad Pros on sale for $50-$75 off MSRP, n...
B&H Photo has 10″ and #Apple #iPad Pros on sale for up to $75 off MSRP. Shipping is free, and B&H charges sales tax in NY & NJ only. Note that some sale prices are restricted to certain... Read more
Apple refurbished Mac minis available startin...
Apple has restocked Certified Refurbished Mac minis starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: – 1.4GHz Mac mini: $419 $80 off MSRP – 2.6GHz Mac... Read more
Amazon offers Silver 13″ Apple MacBook Pros f...
Amazon has new Silver 2017 13″ #Apple #MacBook Pros on sale today for up to $150 off MSRP, each including free shipping: – 13″ 2.3GHz/128GB Silver MacBook Pro (MPXR2LL/A): $1199.99 $100 off MSRP – 13... Read more
Sale: 12″ 1.3GHz MacBooks on sale for $1499,...
B&H Photo has Space Gray and Rose Gold 12″ 1.3GHz #Apple MacBooks on sale for $100 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 12″ 1.3GHz Space... Read more
Apple offers Certified Refurbished 2017 iMacs...
Apple has a full line of Certified Refurbished iMacs available for up to $350 off original MSRP. Apple’s one-year warranty is standard, and shipping is free. The following models are available: – 27... Read more
13″ MacBook Airs on sale for $120-$100 off MS...
B&H Photo has 2017 13″ 128GB MacBook Airs on sale for $120 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $... Read more
15″ Touch Bar MacBook Pros on sale for up to...
Adorama has Space Gray 15″ MacBook Pros on sale for $200 off MSRP. Shipping is free, and Adorama charges sales tax in NJ and NY only: – 15″ 2.8GHz MacBook Pro Space Gray (MPTR2LL/A): $2199, $200 off... Read more
21″ 3.4GHz 4K iMac on sale for $1399, $100 of...
Adorama has the 21″ 3.4GHz 4K #Apple #iMac on sale today for $1399. Their price is $100 off MSRP. Shipping is free, and Adorama charges sales tax in NJ and NY only: – 21″ 3.4GHz 4K iMac (MNE02LL/A... Read more
B&H offering 13″ Apple MacBook Pros for u...
B&H Photo has 13″ MacBook Pros on sale for up to $75-$120 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 13-inch 2.3GHz/128GB Space Gray MacBook Pro (... Read more

Jobs Board

Commerce Engineer, *Apple* Media Products -...
# Commerce Engineer, Apple Media Products Job Number: 113161479 Santa Clara Valley, California, United States Posted: 01-Nov-2017 Weekly Hours: 40.00 **Job Summary** Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Site Reliability Engineer, *Apple* Pay - Ap...
# Site Reliability Engineer, Apple Pay Job Number: 113356036 Santa Clara Valley, California, United States Posted: 12-Jan-2018 Weekly Hours: 40.00 **Job Summary** Read more
UI Tools and Automation Engineer, *Apple* M...
# UI Tools and Automation Engineer, Apple Media Products Job Number: 86351939 Santa Clara Valley, California, United States Posted: 11-Jan-2018 Weekly Hours: 40.00 Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.