Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!wuarchive!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!caen!uwm.edu!ux1.cso.uiuc.edu!ux1.cso.uiuc.edu!uxh.cso.uiuc.edu!mead From: mead@uxh.cso.uiuc.edu Newsgroups: comp.lang.pascal Subject: How to "chain" in Turbo Pascal Message-ID: <13000015@uxh.cso.uiuc.edu> Date: 2 Sep 90 07:12:00 GMT Lines: 108 Nf-ID: #N:uxh.cso.uiuc.edu:13000015:000:3437 Nf-From: uxh.cso.uiuc.edu!mead Sep 2 02:12:00 1990 A while back, I asked if there was any way to "chain" from a Turbo Pascal (V5.5) program to another. I suggested stuffing the keyboard buffer, but didn't know how to do this. I have since learned, and for the people who tried to help me, as well as for the curious, here it is: The keyboard buffer is 16 words of memory from $0040:$001e to $003c. The buffer is a circular queue - the head pointer points to the head of the queue from $0040:$001a and the tail from $001b. (So all totaled, the buffer uses 17 words. As a warning, I've seen utilities that are supposed to increase the buffer area, I'm not sure whether this will work in these cases.) As a consequence of this, you may clear the buffer by setting the head and tail to $0040:$001e (the first position of the queue) instead of: WHILE KeyPressed DO ch := ReadKey; . Hopefully, this will be intuitive from the listing. I'm not sure which is more efficient, but I imagine that the direct method would be superior if you had to use it often. ====== program Demo_Chaining_Process; { Drives CHAIN } procedure Chain( s : string; { The string to be outputted } CRSwitch : boolean ); { Add a CR at the end? } { Places S into the keyboard buffer (thereby destroying any keystrokes that happen to be lying around) resulting in S being operated upon by DOS (provided that the program terminates without reading the keyboard buffer). Lifted from similar code in _Using Turbo Pascal_ by Michael Yester (p241) } const ASCIIEnter = 13; { ENTER's ASCII value } ExtEnter = 28; { ENTER's extended scan code } type KeyBufferType = array[ $1e..$3d ] of byte; { 16 words ... } var i, Len : byte; HeadPointer : byte absolute $0040:$001a; TailPointer : byte absolute $0040:$001c; KeyBuffer : ^KeyBufferType; begin KeyBuffer := Ptr( $0040,$001e ); { The buffer is contiguous with the } { head & tail pointers at $001a & } { $001c. } TailPointer := $1e; { The choice of subscripts makes } HeadPointer := $1e; { makes life easier. } Len := Length( s ); if CRSwitch then if Len > 14 then { ... then it's too long - we need room for the CR } Len := 14 else if Len > 15 then Len := 15; for i := 1 to Len do begin KeyBuffer^[ TailPointer ] := ord( s[i] ); inc(TailPointer,2); end; if CRSwitch then begin KeyBuffer^[ TailPointer ] := ASCIIEnter; KeyBuffer^[ TailPointer+1 ] := ExtEnter; inc( TailPointer,2 ); end; end; begin { Main } Chain( 'dir demochn.*',TRUE ); {Chain( 'demochn',TRUE );} { Try this :) } end. ============ I'm not sure how the queue works, but as you can see from the last assignments to the buffer (ASCIIEnter & ExtEnter), both the ASCII and the Extended Scan Codes need to be stuffed. Also, the buffer has 16 words of space, but strings greater than 15 bytes cause amusing results (well, not so amusing in the IDE). I guess that (as implied by my comments above) whenever the pointers point to the same word, that word isn't used. Hope this helps, -alan mead