home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume16 / psterm / part02 < prev    next >
Text File  |  1988-11-01  |  59KB  |  2,364 lines

  1. Subject:  v16i049:  Terminal emulator for NeWS window system, Part02/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: hoptoad!gnu (John Gilmore)
  7. Posting-number: Volume 16, Issue 49
  8. Archive-name: psterm/part02
  9.  
  10.  
  11. : psterm part 2 of 4
  12. : To unbundle, sh this file
  13. echo sampl.pstermrc
  14. cat >sampl.pstermrc <<'@@@ Fin de sampl.pstermrc'
  15. %
  16. % @(#)$Header: sampl.pstermrc,v 2.0 88/09/16 00:19:10 eric Release $
  17. % to use this file, just copy it to ~/.pstermrc
  18.  
  19. % see the beginning of /usr/NeWS/lib/psterm.ps for more
  20. % customizable things
  21.  
  22. PSTermDict begin
  23.  
  24. /DefaultTerminalFont /Courier-Bold def
  25.  
  26. /NoTopBorder {            % use psterm -ui NoTopBorder
  27.     /UserWindowCustom {
  28.         /BorderTop 3 def
  29.         /PaintFrameControls nullproc def
  30.         /PaintFrameLabel nullproc def
  31.         /PaintFocus nullproc def
  32.     } def
  33. } def
  34.  
  35. /NoIconLabel {            % use psterm -ui NoIconLabel
  36.     /UserWindowCustom {
  37.         /MyIconLabel () store
  38.         /IconFont OnePointFont def
  39.     } def
  40. } def
  41.  
  42. % this is just a combination of NoTopBorder and NoIconLabel
  43. /BareBones {            % use psterm -ui BareBones
  44.     /UserWindowCustom {
  45.         /BorderTop 3 def
  46.         /PaintFrameControls nullproc def
  47.         /PaintFrameLabel nullproc def
  48.         /PaintFocus nullproc def
  49.         /MyIconLabel () store
  50.         /IconFont OnePointFont def
  51.     } def
  52. } def
  53.  
  54. end
  55. @@@ Fin de sampl.pstermrc
  56. echo sampl.user.ps
  57. cat >sampl.user.ps <<'@@@ Fin de sampl.user.ps'
  58. %
  59. % @(#)$Header: sampl.user.ps,v 2.1 88/10/04 05:59:50 gnu Release $
  60. % to use this file, copy it to ~/user.ps
  61. %
  62.  
  63. % these guys switch on and off some of the parts of the file...
  64. /narrowborders true def        % give all windows nice skinny borders
  65. /startclock false def        % start a clock up for me
  66. /startconsole false def        % start a console window for me
  67. /changefocus false def        % make the focus paint around the borders
  68. /newstretch true def        % twiddle with the shape of the stretch box
  69. /initialrootimage null def    % put the name of a picture here if you want
  70.  
  71. /NetSecurityWanted false store    % stop annoying ``security violation'' popups
  72.  
  73.  %%%% Redirect stderr for process that have been 'forkunix'ed
  74.    %% This is done so that error message from forked processed can be seen.
  75.    %% Note:  only available under A/UX, hence the errored...
  76. {(/dev/console) setforkunixstderr} errored pop
  77.  
  78.  %%%% Set up LiteMenus so that submenus are stroked (outlined) and
  79.    %% things you can select are inverted.
  80. {
  81.     /OrigPaintBox /PaintBox load def
  82.     /DiffPaintBox { % value => -
  83.         dup null ne {
  84.         dup % save a copy for the getmenuaction
  85.         MenuItems exch get begin X Y W H end rectpath
  86.         5 setrasteropcode 
  87.         getmenuaction type /dicttype eq {stroke} {fill} ifelse
  88.         } {pop} ifelse
  89.     } def
  90.     /PaintBox /DiffPaintBox load def
  91. } LitePullRightMenu send
  92.  
  93. DefaultMenu begin
  94.     /StrokeSelection    true    def
  95.     /Shadow            4    def
  96.     /ShadowColor        0 0 0 rgbcolor def
  97. end
  98.  
  99. narrowborders {
  100. DefaultWindow begin
  101.     /FrameFont    /Times-Roman findfont 12 scalefont def
  102.     /ZoomSteps    0    def
  103.     /BorderLeft    3    def
  104.     /BorderRight    3    def
  105.     /BorderBottom    3    def
  106.     /BorderTop    16    def
  107.     /stroketop?    true    def
  108.     changefocus {
  109.     /PaintFocus {
  110.         gsave
  111.         FrameCanvas setcanvas
  112.         KeyFocus? {KeyFocusColor} {FrameFillColor} ifelse setcolor
  113.         stroketop? {
  114.             BorderLeft FrameHeight BorderTop sub 2 add moveto
  115.             FrameWidth BorderRight sub
  116.             FrameHeight BorderTop sub 2 add lineto
  117.         } {
  118.             BorderLeft 2 div  FrameHeight BorderTop sub moveto
  119.             BorderLeft 2 div  BorderBottom 2 div lineto
  120.             FrameWidth BorderRight 2 div sub
  121.             BorderBottom 2 div lineto
  122.             FrameWidth BorderRight 2 div sub
  123.             FrameHeight BorderTop sub lineto
  124.         } ifelse
  125.         stroke
  126.         grestore
  127.     } def
  128.     /PaintFrameControls nullproc def
  129.     } if
  130. end
  131. } if
  132.  
  133. newstretch {
  134. DefaultWindow begin
  135.     /MoveFrameControls { % - => - ([Re]set frame control shapes)
  136.     gsave
  137.     CloseControl setcanvas
  138.     0 FrameHeight BorderTop sub BorderTop ControlSize sub 2 div add
  139.     movecanvas
  140.  
  141.     StretchControl setcanvas
  142.     FrameWidth ControlSize sub 0 movecanvas
  143.     grestore
  144.     } def
  145.  
  146.     /CreateFrameControls { % - => - (Create frame control canvases/items)
  147.     gsave
  148.     FrameCanvas setcanvas
  149.         /CloseControl FrameCanvas newcanvas dup begin
  150.         /Mapped true def
  151.         /EventsConsumed /AllEvents def
  152.     end def
  153.         /StretchControl FrameCanvas newcanvas dup begin
  154.         /Mapped true def
  155.         /EventsConsumed /AllEvents def
  156.     end def
  157.     0 0 ControlSize dup BorderTop le exch BorderLeft le or
  158.         {ControlSize ControlSize} {BorderTop BorderTop} ifelse
  159.     rectpath CloseControl reshapecanvas
  160.     ControlSize BorderRight gt ControlSize BorderBottom gt and {
  161.         newpath
  162.         0                0        moveto
  163.         0                BorderBottom    lineto
  164.         ControlSize BorderRight sub    BorderBottom    lineto
  165.         ControlSize BorderRight sub    ControlSize    lineto
  166.         ControlSize            ControlSize    lineto
  167.         ControlSize            0        lineto
  168.         closepath
  169.     } {
  170.         0 0 ControlSize ControlSize rectpath
  171.     } ifelse
  172.     StretchControl reshapecanvas
  173.     grestore
  174.     } def
  175. end
  176. } if
  177.  
  178. /davincipicturemenu [
  179.     (angel)
  180.     (ermine)
  181.     (lady)
  182.     (man)
  183.     (mona-face)
  184.     (mona-hands)
  185.     (mona-smile)
  186. %    (mona-hires)
  187.     (mona)
  188.     (stjerome)
  189.     (virgin)
  190.     (virgino)
  191. ] [{currentkey setrootpicture}] /new DefaultMenu send def
  192. /japanesepicturemenu [
  193.     (cherries)
  194.     (fuji)
  195.     (geese)
  196.     (puppet)
  197.     (snow)
  198.     (stormy)
  199.     (washing)
  200. %    (wash-hires)
  201.     (writing)
  202. ] [{currentkey setrootpicture}] /new DefaultMenu send def
  203. /sunpicturemenu [
  204.     (founders)
  205.     (sun3110)
  206.     (sun3160c)
  207.     (sun3160m)
  208.     (sun3260h)
  209.     (sun350)
  210.     (sun352)
  211.     (sun352w)
  212.     (sunballs)
  213.     (suncase)
  214.     (sungame)
  215.     (sunnet)
  216.     (sunnfs)
  217.     (sunprism)
  218. ] [{currentkey setrootpicture}] /new DefaultMenu send def
  219. /travelpicturemenu [
  220.     (bryce)
  221.     (harem)
  222.     (joshua)
  223.     (lascruces)
  224.     (new_york)
  225.     (pagosa)
  226.     (saturn)
  227.     (fullmoon)
  228.     (shroom)
  229.     (taj-detail)
  230.     (taj)
  231.     (vla)
  232.     (zion)
  233. ] [{currentkey setrootpicture}] /new DefaultMenu send def
  234.  
  235. /picturerootmenu [
  236.         (Da Vinci =>)    davincipicturemenu
  237.         (Japanese =>)    japanesepicturemenu
  238. %        (Sun =>)        sunpicturemenu
  239.         (Travel =>)        travelpicturemenu
  240. ] /new DefaultMenu send def
  241.  
  242. systemdict begin
  243. /setrootpicture {
  244.     gsave
  245.         framebuffer /Retained true put
  246.         (NEWSHOME) getenv (/images/) append
  247.         exch append (.im8) append readcanvas
  248.         systemdict begin
  249.             /RootImageCanvas exch def
  250.             /PaintRoot {
  251.                 gsave
  252.                 framebuffer setcanvas
  253.                 clippath pathbbox scale pop pop
  254.                 RootImageCanvas imagecanvas
  255.             } def
  256.         end
  257.         PaintRoot
  258.     grestore
  259. } def
  260. end
  261.  
  262. /roots [
  263.     (random)    { systemdict begin
  264.                 /DefaultRootGrayOrColor
  265.                  {random random random hsbcolor} def
  266.                 framebuffer /Retained false put
  267.             PaintRoot end }
  268.     (normal)    { systemdict begin
  269.                 /DefaultRootGrayOrColor {.5 .5 .5 hsbcolor} def
  270.                 framebuffer /Retained false put
  271.                 PaintRoot end }
  272. %    (wedge)        { (pscode/wl.root.ps) run PaintRoot }
  273.     (dull)        { systemdict begin
  274.                  /PaintRoot systemdict /DullPaintRoot get def
  275.                 PaintRoot /RootImageCanvas null def end }
  276.     (pictures...)    picturerootmenu
  277. ] /new DefaultMenu send def
  278.  
  279. /term (psterm -ls -t psterm -li 66 -co 132) def        % I like big windows
  280.  
  281. /loginmenu [
  282.     (local)        { term forkunix }
  283. % change rsh below to remsh under A/UX
  284.     (hoptoad)    { (rsh hoptoad ) term append forkunix }
  285.     (polliwog)    { (rsh polliwog ) term append forkunix }
  286.     (pondscum)    { (rsh pondscum ) term append forkunix }
  287.     (console)    {
  288.          (psterm -C -t sun -sl 512 -il Console -fl Console) forkunix }
  289. ] /new DefaultMenu send def
  290.  
  291. 0 (Roots =>) roots /insertitem rootmenu send
  292. 0 (Login =>) loginmenu /insertitem rootmenu send
  293.  
  294. systemdict begin
  295.     /DefaultRootGrayOrColor {.5 .5 .5 hsbcolor} def
  296.     systemdict /DullPaintRoot known not {
  297.         /DullPaintRoot systemdict /PaintRoot get def } if
  298.     initialrootimage null ne {
  299.         initialrootimage setrootpicture } { PaintRoot } ifelse
  300. end
  301.  
  302. startclock {
  303.     (/usr/NeWS/demo/roundclock -s) forkunix pause
  304. } if
  305.  
  306. startconsole {
  307.     (psterm -C -t sun -sl 512 -il Console -fl Console) forkunix pause
  308. } if
  309.  
  310. /dragframe? false store    % false means continuously repaint
  311.  
  312. % /xhair /xhair_m framebuffer setstandardcursor
  313. @@@ Fin de sampl.user.ps
  314. echo psterm.tcap
  315. cat >psterm.tcap <<'@@@ Fin de psterm.tcap'
  316. #
  317. #    Grasshopper Group NeWS Termcaps 1.8  -HD  88/08/23
  318. #    @(#)$Header: psterm.tcap,v 2.1 88/09/23 19:12:35 hugh Release $
  319. #
  320. # nterm is a fancy vt220 terminal emulator for the NeWS window system
  321. nt|nterm:\
  322.     :cr=^M:do=^J:nl=^J:bl=^G:le=^H:ho=\E[H:\
  323.     :co#80:li#65:cl=\E[H\E[2J:bs:am:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
  324.     :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
  325.     :md=\E[1m:mr=\E[7m:me=\E[m:\
  326.     :ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:kb=^H:\
  327.     :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sf=\n:sr=\EM:\
  328.     :al=\E[L:dl=\E[M:dc=\E[P:\
  329.     :MT:ks=\E[?1h\E=:ke=\E[?1l\E>:\
  330.     :is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:\
  331.     :rs=\E[r\E<\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:xn:\
  332.     :AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:\
  333.     :ti=\E[2J\E[?47h:te=\E[?47l:im=\E[4h:ei=\E[4l:\
  334.     :ts=\E[?E\E[?%i%dT:fs=\E[?F:es:ds=\E[?E:
  335. nt|nterms|nterm terminal emulator (small)(NeWS window system):\
  336.     :co#80:li#24:tc=nterm:
  337. #
  338. # Termcap for NeWS's psterm from Eric Messick & Hugh Daniel
  339. p1|psterm-96x48:\
  340.     :co#96:li#48:tc=psterm-basic:
  341. p1|psterm-90x28:\
  342.     :co#90:li#28:tc=psterm-basic:
  343. p1|psterm-80x24:\
  344.     :co#80:li#24:tc=psterm-basic:
  345. p1|psterm|psterm-basic|psterm-80x34:\
  346.     :am:bs:al=\EA:cd=\EB:ce=\EC:cl=^L:cm=\E%d;%d;:cs=\EE%d;%d;:\
  347.     :dc=\EF:dl=\EK:do=\EP:ei=\ENi:el=\ENl:fs=\ENl:\
  348.     :ho=\ER:hs:im=\EOi:is=\EN*:km:\
  349.     :kd=\E[B:ku=\E[A:kr=\E[C:kl=\E[D:\
  350.     :mb=\EOb:md=\EOd:\
  351.     :me=\EN*:mr=\EOr:nd=\EV:pt:rc=\034:rs=\EN*:sc=\035:\
  352.     :se=\ENo:sf=\EW:sl=\EOl:so=\EOo:sr=\EX:te=\ENt:\
  353.     :ti=\EOt:ts=\EOl:ue=\ENu:\
  354.     :le=\ET:ll=\EU:ul:up=\EY:us=\EOu:vb=\EZ:\
  355.     :co#80:li#34:
  356. #  This is a faster termcap for psterm, Warning: if you use this termcap
  357. #  some control characters you type will do strange things to the screen.
  358. p1|psterm-fast:\
  359.     :am:bs:al=^A:cd=^B:ce=^C:cl=^L:cm=^D%d;%d;:cs=^E%d;%d;:\
  360.     :dc=^F:dl=^K:do=^P:ei=^Ni:el=^Nl:fs=^Nl:\
  361.     :ho=^R:hs:im=^Oi:is=^N*:km:\
  362.     :kd=\E[B:ku=\E[A:kr=\E[C:kl=\E[D:\
  363.     :mb=^Ob:md=^Od:\
  364.     :me=^N*:mr=^Or:nd=^V:pt:rc=\034:rs=^N*:sc=\035:\
  365.     :se=^No:sf=^W:sl=^Ol:so=^Oo:sr=^X:te=^Nt:\
  366.     :ti=^Ot:ts=^Ol:ue=^Nu:\
  367.     :le=^T:ll=^U:ul:up=^Y:us=^Ou:vb=^Z:\
  368.     :co#80:li#34:
  369. ####  End of stuff added by Grasshopper Group
  370. @@@ Fin de psterm.tcap
  371. echo psterm.tinfo
  372. cat >psterm.tinfo <<'@@@ Fin de psterm.tinfo'
  373. #
  374. #    Grasshopper Group NeWS Termcaps 1.9  -HD  88/9/03
  375. #    @(#)$Header: psterm.tinfo,v 2.2 88/10/05 17:36:11 eric Release $
  376. #
  377. # nterm is a fancy vt220 terminal emulator for the NeWS window system
  378. nterm,
  379.     am,    xenl,    eslok,
  380.     cols#80,    lines#65,
  381.     bel=^G,    cr=\r,    clear=\E[H\E[2J,
  382.     el=\E[K,    ed=\E[J,    cup=\E[%i%p1%d;%p2%dH,
  383.     cud1=\n,    home=\E[H,    cub1=\b,
  384.     cuf1=\E[C,    cuu1=\E[A,    dch1=\E[P,
  385.     dl1=\E[M,    dsl=\E[?E,    bold=\E[1m,
  386.     smcup=\E[2J\E[?47h,    smir=\E[4h,    rev=\E[7m,
  387.     smso=\E[7m,    smul=\E[4m,    sgr0=\E[m,
  388.     rmcup=\E[?47l,    rmir=\E[4l,    rmso=\E[m,
  389.     rmul=\E[m,    fsl=\E[?F,    is1=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l,
  390.     il1=\E[L,    kbs=\b,    kcud1=\E[B,
  391.     kf1=\EOP,    kf2=\EOQ,    kf3=\EOR,
  392.     kf4=\EOS,    kcub1=\E[D,    kcuf1=\E[C,
  393.     kcuu1=\E[A,    rmkx=\E[?1l\E>,    smkx=\E[?1h\E=,
  394.     nel=\r\n,    dch=\E[%p1%dP,    dl=\E[%p1%dM,
  395.     ich=\E[%p1%d@,    il=\E[%p1%dL,    rs1=\E[r\E<\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l,
  396.     ind=\n,    ri=\EM,    ht=\t,
  397.     tsl=\E[?E\E[?%i%p1%dT,
  398. # Small nterm terminal emulator termcap
  399. nterms|small nterm,
  400.     cols#80,    lines#24,
  401.     bel=^G,    cr=\r,    cud1=\n,
  402.     cub1=\b,    kbs=\b,    kcud1=\n,
  403.     kcub1=\b,    nel=\r\n,    ind=\n,
  404.     use=nterm,
  405. #
  406. # Termcap for NeWS's psterm from Eric Messick & Hugh Daniel
  407. psterm-96x48,
  408.     cols#96,    lines#48,
  409.     bel=^G,    cr=\r,    cud1=\n,
  410.     cub1=\b,    kbs=\b,    kcud1=\n,
  411.     kcub1=\b,    nel=\r\n,    ind=\n,
  412.     use=psterm-basic,
  413. psterm-90x28,
  414.     cols#90,    lines#28,
  415.     bel=^G,    cr=\r,    cud1=\n,
  416.     cub1=\b,    kbs=\b,    kcud1=\n,
  417.     kcub1=\b,    nel=\r\n,    ind=\n,
  418.     use=psterm-basic,
  419. psterm-80x24,
  420.     cols#80,    lines#24,
  421.     bel=^G,    cr=\r,    cud1=\n,
  422.     cub1=\b,    kbs=\b,    kcud1=\n,
  423.     kcub1=\b,    nel=\r\n,    ind=\n,
  424.     use=psterm-basic,
  425. psterm|psterm-basic|psterm-80x34,
  426.     am,    km,    hs,    ul,
  427.     cols#80,    lines#34,
  428.     bel=^G,    cr=\r,    csr=\EE%p1%d;%p2%d;,
  429.     clear=\f,    el=\EC,    ed=\EB,
  430.     cup=\E%p1%d;%p2%d;,    cud1=\EP,    home=\ER,
  431.     cub1=\ET,    cuf1=\EV,    ll=\EU,
  432.     cuu1=\EY,    dch1=\EF,    dl1=\EK,
  433.     blink=\EOb,    bold=\EOd,    smcup=\EOt,
  434.     smir=\EOi,    rev=\EOr,    smso=\EOo,
  435.     smul=\EOu,    sgr0=\EN*,    rmcup=\ENt,
  436.     rmir=\ENi,    rmso=\ENo,    rmul=\ENu,
  437.     flash=\EZ,    fsl=\ENl,    is1=\EN*,
  438.     il1=\EA,    kbs=\b,    kcud1=\E[B,
  439.     kcub1=\E[D,    kcuf1=\E[C,    kcuu1=\E[A,
  440.     nel=\r\n,    rs1=\EN*,    rc=^\,
  441.     sc=^],    ind=\EW,    ri=\EX,
  442.     ht=\t,    tsl=\EOl,
  443. #  This is a faster termcap for psterm, Warning: if you use this termcap
  444. #  some control characters you type will do strange things to the screen
  445. #  on systems that echo typed control characters to the users terminal.
  446. psterm-fast,
  447.     am,    km,    hs,    ul,
  448.     cols#80,    lines#34,
  449.     bel=^G,    cr=\r,    csr=^E%p1%d;%p2%d;,
  450.     clear=\f,    el=^C,    ed=^B,
  451.     cup=^D%p1%d;%p2%d;,    cud1=^P,    home=^R,
  452.     cub1=^T,    cuf1=^V,    ll=^U,
  453.     cuu1=^Y,    dch1=^F,    dl1=^K,
  454.     blink=^Ob,    bold=^Od,    smcup=^Ot,
  455.     smir=^Oi,    rev=^Or,    smso=^Oo,
  456.     smul=^Ou,    sgr0=^N*,    rmcup=^Nt,
  457.     rmir=^Ni,    rmso=^No,    rmul=^Nu,
  458.     flash=^Z,    fsl=^Nl,    is1=^N*,
  459.     il1=^A,    kbs=\b,    kcud1=\E[B,
  460.     kcub1=\E[D,    kcuf1=\E[C,    kcuu1=\E[A,
  461.     nel=\r\n,    rs1=^N*,    rc=^\,
  462.     sc=^],    ind=^W,    ri=^X,
  463.     ht=\t,    tsl=^Ol,
  464. ####  End of stuff added by Grasshopper Group
  465. @@@ Fin de psterm.tinfo
  466. echo slave.c
  467. cat >slave.c <<'@@@ Fin de slave.c'
  468. /*
  469.  * This file is a product of Sun Microsystems, Inc. and is provided for
  470.  * unrestricted use provided that this legend is included on all tape
  471.  * media and as a part of the software program in whole or part.
  472.  * Users may copy, modify or distribute this file at will.
  473.  * 
  474.  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  475.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  476.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  477.  * 
  478.  * This file is provided with no support and without any obligation on the
  479.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  480.  * modification or enhancement.
  481.  * 
  482.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  483.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
  484.  * OR ANY PART THEREOF.
  485.  * 
  486.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  487.  * or profits or other special, indirect and consequential damages, even
  488.  * if Sun has been advised of the possibility of such damages.
  489.  * 
  490.  * Sun Microsystems, Inc.
  491.  * 2550 Garcia Avenue
  492.  * Mountain View, California  94043
  493.  *
  494.  * Modifications to the original Sun Microsystems, Inc. source code
  495.  * made by the Grasshopper Group are in the Public Domain.
  496.  *
  497.  * Extensions to this file by Eric Messick of the Grasshopper Group.
  498.  *
  499.  * Grasshopper Group
  500.  * 212 Clayton St
  501.  * San Francisco, CA 94117
  502.  *
  503.  */
  504.  
  505. #ifndef lint
  506. static char sccsid[] = "@(#)slave.c 9.6 88/01/19 Copyright 1985 Sun Micro";
  507. static    char RCSid[] = "@(#)$Header: slave.c,v 2.1 88/10/04 04:22:54 eric Release $";
  508. #endif
  509.  
  510.  
  511. /*
  512.  * Copyright (c) 1985 by Sun Microsystems, Inc. 
  513.  */
  514.  
  515. /*-
  516.     slave.c
  517.  
  518.     slave.c, Tue Apr  1 09:17:08 1986
  519.  
  520.         David Rosenthal,
  521.         Sun Microsystems
  522.  */
  523.  
  524. #include <stdio.h>
  525. #include <errno.h>
  526. #include <sys/types.h>
  527. #ifdef REF
  528. #include <ref/config.h>
  529. #endif
  530.  
  531. extern void exit();
  532. extern unsigned sleep();
  533. extern void perror();
  534.  
  535. #ifndef HAVE_VFORK
  536. #define    vfork()    fork()
  537. #endif
  538.  
  539. int    Mfd, Sfd;
  540. /* XXX - there should be a library routine to get a pty */
  541. char    ptcname[] = "/dev/ptyXX";
  542. char    ptsname[] = "/dev/ttyXX";
  543. int    pgrp;
  544. extern    int errno;
  545. extern    int BackGround;
  546.  
  547. FILE       *
  548. spawn_slave(name, args)
  549.     char *name, **args;
  550. {
  551.     FILE *Master;
  552.     int i, pid, uid, gid;
  553.     unsigned delay = 2 ;
  554. #define    MAXDELAY    120
  555.     char *gp, *tp;
  556.  
  557.     GetTTYDefaults();
  558. #ifdef SYSVREF
  559. /* Micom-Interlan software installs some non-streams based pty's on 'p' */
  560. #ifdef INTERLANTCP
  561.     for (gp = "qrst"; *gp; gp++)
  562. #else
  563.     for (gp = "pqrst"; *gp; gp++)
  564. #endif
  565. #else
  566.     for (gp = "pqrst"; *gp; gp++)
  567. #endif
  568.     for (tp = "0123456789abcdef"; *tp; tp++) {
  569.         ptcname[sizeof ("/dev/pty")-1] = *gp;
  570.         ptcname[sizeof ("/dev/ptyX")-1] = *tp;
  571.         if ((Mfd = open(ptcname, 2)) < 0)
  572.         continue;
  573.         ptsname[sizeof ("/dev/pty")-1] = *gp;
  574.         ptsname[sizeof ("/dev/ptyX")-1] = *tp;
  575.         if ((Sfd = open(ptsname, 2)) >= 0)
  576.         goto done;
  577.         close(Mfd);
  578.     }
  579. done:
  580.     if (Mfd < 0 || Sfd < 0)
  581.     return (NULL);
  582.     uid = getuid(), gid = getgid();
  583.     (void) chown(ptsname, uid, gid);        /* set tty ownership */
  584.     (void) chmod(ptsname, 0622);        /* set tty protection */
  585.     /*
  586.      * Establish tty state.
  587.      */
  588.     SetTTYState(Sfd);
  589.     /*
  590.      * If we're to operate in the background, fork
  591.      * to return control to the shell and disassociate
  592.      * ourselves from the tty.  The caller closes
  593.      * file descriptors so that, for example, rsh
  594.      * will not be kept around.
  595.      */
  596.     if (BackGround) {
  597.     if (fork())
  598.         exit(0);
  599.     (void) setpgrp(0, getpid());
  600.     DisAssociateTTY();
  601.     } else
  602.     AssociateTTY();
  603.     Master = fdopen(Mfd, "r+");
  604.     while ((pid = vfork()) < 0 && errno == EAGAIN) {
  605.     sleep(delay);
  606.     if ((delay <<= 1) > MAXDELAY) {
  607.         close (Mfd); close (Sfd);
  608.         return (NULL);
  609.     }
  610.     }
  611.     if (pid == 0) {
  612.     /*
  613.      * Setup controlling tty.
  614.      */
  615.     for (i = 0; i < 3; i++)
  616.         (void) dup2(Sfd, i);
  617.     addut(uid, ptsname);
  618.     for (i = getdtablesize(); i > 2; i--)
  619.         (void) close(i);
  620.     SetupControllingTTY(ptsname);
  621.     (void) setuid(uid), (void) setgid(gid);
  622.     execvp(name, args);
  623.     perror(name);
  624.     exit(errno);
  625.     }
  626.     pgrp = pid;
  627.     close(Sfd);
  628.     return (Master);
  629. }
  630.  
  631. CleanupPty()
  632. {
  633.  
  634.     rmut();
  635.     (void) chown(ptsname, 0, 0);        /* revoke ownership */
  636.     (void) chmod(ptsname, 0666);        /* revoke protection */
  637. }
  638. @@@ Fin de slave.c
  639. echo io.c
  640. cat >io.c <<'@@@ Fin de io.c'
  641. /*
  642.  * This file is a product of Sun Microsystems, Inc. and is provided for
  643.  * unrestricted use provided that this legend is included on all tape
  644.  * media and as a part of the software program in whole or part.
  645.  * Users may copy, modify or distribute this file at will.
  646.  * 
  647.  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  648.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  649.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  650.  * 
  651.  * This file is provided with no support and without any obligation on the
  652.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  653.  * modification or enhancement.
  654.  * 
  655.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  656.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
  657.  * OR ANY PART THEREOF.
  658.  * 
  659.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  660.  * or profits or other special, indirect and consequential damages, even
  661.  * if Sun has been advised of the possibility of such damages.
  662.  * 
  663.  * Sun Microsystems, Inc.
  664.  * 2550 Garcia Avenue
  665.  * Mountain View, California  94043
  666.  *
  667.  * Modifications to the original Sun Microsystems, Inc. source code
  668.  * made by the Grasshopper Group are in the Public Domain.
  669.  *
  670.  * Extensions to this file by Eric Messick of the Grasshopper Group.
  671.  *
  672.  * Grasshopper Group
  673.  * 212 Clayton St
  674.  * San Francisco, CA 94117
  675.  *
  676.  */
  677.  
  678. #ifndef lint
  679. static char sccsid[] = "@(#)io.c 9.7 88/01/19 Copyright 1985 Sun Micro";
  680. static    char RCSid[] = "@(#)$Header: io.c,v 2.1 88/10/04 04:22:45 eric Release $";
  681. #endif
  682.  
  683.  
  684. /*
  685.  * Copyright (c) 1985 by Sun Microsystems, Inc. 
  686.  */
  687. #ifdef REF
  688. #include <sys/types.h>
  689. #include <ref/config.h>
  690. #endif
  691.  
  692. #ifndef HAVE_SELECT
  693. #ifdef INTERLANTCP
  694. #include <interlan/il_errno.h>
  695. #endif
  696. #include <stropts.h>
  697. #include <poll.h>
  698. #endif
  699. #include <stdio.h>
  700. #include <psio.h>
  701. #include <errno.h>
  702. #include <fcntl.h>
  703. #include <sys/time.h>
  704.  
  705. extern void perror();
  706.  
  707. #define    MAX(a,b)    ((a)>(b)?(a):(b))
  708. #define    KBDBUFSIZE    4096
  709. #define    PTYBUFSIZE    8192
  710.  
  711. static    char kbdbuf[KBDBUFSIZE], *kbdfront, *kbdback, *kbdend;
  712. static    char ptybuf[PTYBUFSIZE];    /* buffer for reading from pty slave */
  713. static    int wfproto;            /* prototype for write select mask */
  714. extern    int Mfd;
  715. extern    int errno;
  716. extern    PSFILE *PostScript;
  717. extern    int PageMode;
  718. extern    int PageFull;
  719. extern    int fontisfixedwidth;
  720. extern    int FastPaint;
  721. extern    int DoScrolling;
  722.  
  723. static    int pty_out();
  724. static    int kbd_input();
  725.  
  726. /*
  727.  * Input dispatcher: take data from postscript
  728.  * program and pty, dispatching each to the
  729.  * appropriate handler.
  730.  */
  731. terminal(cfd, kfd)
  732. {
  733.     register int n;
  734. #ifdef HAVE_SELECT
  735.     int rf, wf;
  736.     int max;
  737. #else    /* !HAVE_SELECT */
  738. #define PTY 0
  739. #define KEYBOARD 1
  740. #define POSTSCRIPT 2
  741. #define NFDS 3
  742.     struct pollfd rwf[NFDS];
  743.     int i;
  744. #endif    /* !HAVE_SELECT */
  745.     int keyboard, pty, postscript, ndeferred;
  746.     char *deferred;
  747.  
  748.     PageFull = 0;            /* not inhibiting scrolling */
  749.     ndeferred = 0;            /* no deferred output */
  750.     keyboard = 1<<kfd;
  751.     pty = 1<<cfd;
  752.     postscript = 1<<psio_fileno(PostScript);
  753. #ifdef HAVE_FNDELAY
  754.     (void) fcntl(cfd, F_SETFL, fcntl(cfd, F_GETFL, 0)|FNDELAY);
  755.     (void) fcntl(kfd, F_SETFL, fcntl(kfd, F_GETFL, 0)|FNDELAY);
  756. #else
  757.     (void) fcntl(cfd, F_SETFL, fcntl(cfd, F_GETFL, 0)|O_NDELAY);
  758.     (void) fcntl(kfd, F_SETFL, fcntl(kfd, F_GETFL, 0)|O_NDELAY);
  759. #endif
  760. #ifdef HAVE_SELECT
  761.     max = MAX(kfd, cfd) + 1;
  762. #endif
  763.     kbdend = kbdbuf + KBDBUFSIZE; 
  764.     kbdfront = kbdback = kbdbuf;
  765.     wfproto = 0;
  766.     for (;;) {
  767.     /*
  768.      * Don't poll for input to be sent to the display
  769.      * if we have a full screen, or we are blocked already
  770.      * trying to transmit to the server.
  771.      */
  772. #ifdef HAVE_SELECT
  773.     rf = (PageFull || (wfproto & postscript)) ? 0 : pty;
  774.     wf = wfproto;
  775.     if (kbdfront != kbdend)        /* space to read from kbd */
  776.         rf |= keyboard;
  777.     if (select(max, &rf, &wf, (int *)NULL, (struct timeval *)NULL) < 0) {
  778.         if (errno == EINTR)
  779.         continue;
  780.         perror("select");
  781.         break;
  782.     }
  783. #else
  784.     rwf[PTY].fd = -1;
  785.     rwf[PTY].events = 0;
  786.     rwf[KEYBOARD].fd = -1;
  787.     rwf[KEYBOARD].events = 0;
  788.     rwf[POSTSCRIPT].fd = -1;
  789.     rwf[POSTSCRIPT].events = 0;
  790.  
  791.     if (!(PageFull || (wfproto & postscript))) {
  792.         rwf[PTY].fd = cfd;
  793.         rwf[PTY].events |= POLLIN;
  794.     }
  795.  
  796.     if (wfproto & pty) {
  797.         rwf[PTY].fd = cfd;
  798.         rwf[PTY].events |= POLLOUT;
  799.     }
  800.     if (wfproto & postscript) {
  801.         rwf[POSTSCRIPT].fd = psio_fileno(PostScript);
  802.         rwf[POSTSCRIPT].events |= POLLOUT;
  803.     }
  804.  
  805.     if (kbdfront != kbdend) {        /* space to read from kbd */
  806.         rwf[KEYBOARD].fd = kfd;
  807.         rwf[KEYBOARD].events |= POLLIN;
  808.     }
  809.     if (poll(rwf, NFDS, -1) < 0) {
  810.         if (errno == EINTR)
  811.         continue;
  812.         perror("poll");
  813. break_here:
  814.         break;
  815.     }
  816.  
  817.     /* check to see if any connections were hung up */
  818.     if (rwf[KEYBOARD].revents & POLLHUP || rwf[PTY].revents & POLLHUP
  819.                     || rwf[POSTSCRIPT].revents & POLLHUP)
  820.         break;
  821.  
  822.     /*  look for exceptional conditions on fd's */
  823.     for (i = 0; i < NFDS; i++) {
  824.         if (rwf[i].revents & (POLLERR | POLLNVAL)) {
  825.             fprintf(stderr, "Error on an fd in poll ");
  826.             fprintf(stderr, "[POLLERR | POLLNVAL]\n");
  827.             goto break_here;    /* should be break, but C has */
  828.                         /* no multi-level break */
  829.         }
  830.     }
  831. #endif
  832.     /*
  833.      * Flush PostScript descriptor.
  834.      */
  835. #ifdef HAVE_SELECT
  836.     if (wf & postscript && (psio_flush(PostScript) == 0))
  837. #else
  838.     if (rwf[POSTSCRIPT].revents & POLLOUT && (psio_flush(PostScript) == 0))
  839. #endif
  840.         wfproto &= ~postscript;
  841.     /*
  842.      * Try to flush pty, if clogged, before reading from keyboard.
  843.      */
  844. #ifdef HAVE_SELECT
  845.     if (wf & pty)
  846. #else
  847.     if (rwf[PTY].revents & POLLOUT)
  848. #endif
  849.     {
  850.         wfproto &= ~pty;
  851.         pty_out();
  852.     }
  853.     /*
  854.      * Take keyboard input.
  855.      */
  856. #ifdef HAVE_SELECT
  857.     if (rf & keyboard)
  858. #else
  859.     if (rwf[KEYBOARD].revents & POLLIN)
  860. #endif
  861.     {
  862.         errno = 0;
  863.         n = read(kfd, kbdfront, (unsigned)(kbdend-kbdfront));
  864.         if (n <= 0) {
  865.         if (errno != EWOULDBLOCK) {
  866. #ifdef HAVE_SELECT    /* Connection Reset is checked above in SYSVREF */
  867.             if (n < 0 && errno != ECONNRESET)
  868. #endif
  869.                 perror("keyboard");
  870.             break;
  871.         }
  872.         } else if (n > 0)
  873.         kbd_input(n);
  874.     }
  875.     /*
  876.      * If pty_out or kbd_input changed
  877.      * PageFull, loop to inhibit output.
  878.      */
  879.     if (PageFull)            /* loop if inhibiting output */
  880.         continue;
  881.     /*
  882.      * If screen output was blocked due to previous PageFull condition,
  883.      * resume it.  Note that this may leave us back in PageFull mode,
  884.      * and interrupted tcap ops may still need the chars in ptybuf.
  885.      */
  886. #ifdef lint
  887.     deferred = (char *)0 ;
  888. #endif
  889.     if (ndeferred) {
  890.         n = tc_display((u_char *)deferred, ndeferred);
  891.         if (n > 0)
  892.         deferred += (ndeferred - n);
  893.         ndeferred = n;
  894.         tc_refresh(0);
  895.         if (PageFull)        /* if PageFull, can't touch ptybuf */
  896.         continue;
  897.     }
  898.     /*
  899.      * Finally, take pty stuff and send it to the display
  900.      * except when we're already flush with output.
  901.      */
  902. #ifdef HAVE_SELECT
  903.     if ((wfproto & postscript) == 0 && rf & pty)
  904. #else
  905.     if ((wfproto & postscript) == 0 && rwf[PTY].revents & POLLIN)
  906. #endif
  907.     {
  908.         errno = 0;
  909.         n = read(cfd, ptybuf, PTYBUFSIZE);
  910. #ifdef HAVE_SELECT
  911.         if (n < 0) {
  912.         if (errno != EIO) {
  913. /* BEGIN SUN BUG WORKAROUND */
  914.             if (errno == EWOULDBLOCK)
  915.                 continue;
  916. /* END SUN BUG WORKAROUND */
  917.             perror("pty");
  918.         }
  919.         break;
  920.         }
  921. #else
  922.         if (n == 0)
  923.         continue;
  924.         if (n < 0) {
  925.         if (errno == EAGAIN)
  926.             continue;
  927.         perror("pty");
  928.         break;
  929.         }
  930. #endif
  931.         ndeferred = tc_display((u_char *)ptybuf, n);
  932.         if (ndeferred)
  933.         deferred = ptybuf + (n - ndeferred);
  934.         tc_refresh(0);
  935.     }
  936. #ifdef notdef
  937. if (wfproto & postscript) fprintf(stderr, "blocked\n");
  938. #endif
  939.     }
  940. }
  941.  
  942. /*
  943.  * Flush PostScript destined for window.
  944.  * If all data was not written, then mark
  945.  * the select mask to find out when data
  946.  * has been flushed to the network.
  947.  */
  948. FlushPostScript()
  949. {
  950.  
  951.     if (!(psio_flush(PostScript) == 0))
  952.     wfproto |= 1<<psio_fileno(PostScript);
  953. }
  954.  
  955. /*
  956.  * Flush output to pty.
  957.  */
  958. static
  959. pty_out()
  960. {
  961.     register int cc;
  962.  
  963.     if ((cc = kbdfront - kbdback) > 0) {
  964.         if (PageMode) {
  965.         if (PageFull) {
  966.             switch (*kbdback) {
  967.             case '\r':
  968.             --cc, kbdback++;
  969.             scrollreset(1);
  970.             break;
  971.             case ' ':
  972.             --cc, kbdback++;
  973.             /* fall thru... */
  974.             default:
  975.             scrollreset(0);
  976.             break;
  977.             }
  978.             if (cc < 1) {
  979.             kbdfront = kbdback = kbdbuf;
  980.             return;
  981.             }
  982.         } else
  983.             scrollreset(0);
  984.         }
  985.         cc = write(Mfd, kbdback, (unsigned)cc);
  986.         if (cc < 0) {
  987.         if (errno != EWOULDBLOCK)
  988.             perror("master pty");
  989.         } else
  990.         kbdback += cc;
  991.     }
  992.     if (kbdfront != kbdback)
  993.         wfproto |= 1<<Mfd;        /* must explicity reenable */
  994.     else
  995.         kbdfront = kbdback = kbdbuf;
  996. }
  997.  
  998. #define EVENT_ESCAPE        0200    /* introduce event packet */
  999.  
  1000. #define EVENT_REPAIR        'a'    /* window resized or damaged */
  1001. #define    EVENT_BEGINSEL        'b'    /* set selection start */
  1002. #define    EVENT_EXTSEL        'c'    /* drag end of current selection */
  1003. #define    EVENT_ENDSEL        'd'    /* complete selection */
  1004. #define EVENT_TOGGLEAM        'e'    /* toggle auto-margins */
  1005. #define EVENT_TOGGLEPM        'f'    /* toggle page mode */
  1006. #define EVENT_ROWCOL        'g'    /* new row/col size selected */
  1007. #define    EVENT_FONTFIXED        'h'    /* just switched to a fixed width font */
  1008. #define EVENT_FONTVAR        'i'    /* just switched to a variable width font */
  1009. #define    EVENT_RECTSEL        'j'    /* set rect selection start */
  1010. #define EVENT_EXTRECT        'k'    /* extend rect selection */
  1011. #define EVENT_SCROLL        'l'    /* scrollbar movement report */
  1012. #define EVENT_SAVESIZE        'm'    /* change number of lines saved */
  1013. #define EVENT_ENDREFRESH    'n'    /* postscript side has completed refresh */
  1014. #define EVENT_FASTPAINT        'o'    /* set or clear fastpaint */
  1015. #define EVENT_DOSCROLL        'p'    /* set or clear use of scrolling */
  1016.  
  1017. /*
  1018.  * Handle keyboard input + postscript events.
  1019.  */
  1020. static
  1021. kbd_input(n)
  1022. register int n;
  1023. {
  1024.     register unsigned char *p, *d;
  1025.     register n2;
  1026.     extern int RefreshSuppressed;
  1027.     int    col, row, rank, dorefresh = 0, doresize = 0, rect = 0 ;
  1028.  
  1029. #define NEXTVAL        while (n-- > 0 && *p++ != '\n') ;
  1030.  
  1031.     for (p = (unsigned char *)kbdfront, n2 = 0, d = p; n > 0;) {
  1032.         if (*p == EVENT_ESCAPE) {
  1033.             p++ ;
  1034.             if (--n > 0) {
  1035.                 n-- ;
  1036.                 switch (*p++) {
  1037.                 case EVENT_TOGGLEAM:
  1038.                     toggleautomargins();
  1039.                     break;
  1040.                 case EVENT_TOGGLEPM:
  1041.                     togglepagemode();
  1042.                     if (PageFull) {
  1043.                         /* resume output if blocked */
  1044.                         scrollreset(0);
  1045.                         dorefresh++;
  1046.                         }
  1047.                     break;
  1048.                 case EVENT_REPAIR:
  1049.                     RefreshSuppressed = 0 ;
  1050.                     doresize++ ;
  1051.                     break;
  1052.                 case EVENT_RECTSEL:
  1053.                     rect = 1 ;    /* fall through... */
  1054.                 case EVENT_BEGINSEL:
  1055.                     /* col row rank size mode preview */
  1056.                     if (n>0) { col = atoi((char *)p); NEXTVAL; }
  1057.                     if (n>0) { row = atoi((char *)p); NEXTVAL; }
  1058.                     if (n>0) {
  1059.                         rank = atoi((char *)p); NEXTVAL;
  1060.                         tc_deselect(rank);
  1061.                         tc_extend_selection(col, row,
  1062.                                 rank, rect);
  1063.                         dorefresh++;
  1064.                         rect = 0 ;
  1065.                         }
  1066.                     break;
  1067.                 case EVENT_EXTRECT:
  1068.                     rect = 1 ;    /* fall through... */
  1069.                 case EVENT_EXTSEL:
  1070.                     /* col row rank size mode preview */
  1071.                     if (n>0) { col = atoi((char *)p); NEXTVAL; }
  1072.                     if (n>0) { row = atoi((char *)p); NEXTVAL; }
  1073.                     if (n>0) {
  1074.                         rank = atoi((char *)p); NEXTVAL;
  1075.                         tc_extend_selection(col, row,
  1076.                                 rank, rect);
  1077.                         dorefresh++;
  1078.                         rect = 0 ;
  1079.                         }
  1080.                     break;
  1081.                 case EVENT_ENDSEL:
  1082.                     /* col row rank size mode preview */
  1083.                     if (n>0) { col = atoi((char *)p); NEXTVAL; }
  1084.                     if (n>0) { row = atoi((char *)p); NEXTVAL; }
  1085.                     if (n>0) {
  1086.                         rank = atoi((char *)p); NEXTVAL;
  1087.                         tc_extend_selection(col, row,
  1088.                                 rank, rect);
  1089.                         tc_report_selection(rank);
  1090.                         dorefresh++;
  1091.                         }
  1092.                     break;
  1093.                 case EVENT_ESCAPE:
  1094.                     *d++ = EVENT_ESCAPE ;
  1095.                     n2++ ;
  1096.                     break;
  1097.                 case EVENT_ROWCOL:
  1098.                     if (n>0) { col = atoi((char *)p); NEXTVAL; }
  1099.                     if (n>0) {
  1100.                         row = atoi((char *)p); NEXTVAL;
  1101.                         change_rowcol(row, col);
  1102.                         }
  1103.                     break;
  1104.                 case EVENT_FONTFIXED:
  1105.                     fontisfixedwidth = 1 ;
  1106.                     break;
  1107.                 case EVENT_FONTVAR:
  1108.                     fontisfixedwidth = 0 ;
  1109.                     break;
  1110.                 case EVENT_SCROLL:
  1111.                     if (n>0) {
  1112.                         row = atoi((char *)p); NEXTVAL;
  1113.                         scroll_to(row);
  1114.                         dorefresh++;
  1115.                         }
  1116.                     break;
  1117.                 case EVENT_SAVESIZE:
  1118.                     if (n>0) {
  1119.                         row = atoi((char *)p); NEXTVAL;
  1120.                         set_scroll_save(row);
  1121.                         dorefresh++;
  1122.                         }
  1123.                     break;
  1124.                 case EVENT_ENDREFRESH:
  1125.                     end_refresh();
  1126.                     dorefresh++;
  1127.                     break;
  1128.                 case EVENT_FASTPAINT:
  1129.                     if (n>0) {
  1130.                         FastPaint = atoi((char *)p); NEXTVAL;
  1131.                         }
  1132.                     break;
  1133.                 case EVENT_DOSCROLL:
  1134.                     if (n>0) {
  1135.                         DoScrolling = atoi((char *)p); NEXTVAL;
  1136.                         }
  1137.                     break;
  1138.                     }
  1139.                 }
  1140.             }
  1141.         else    {
  1142.             *d++ = *p++ ;
  1143.             n-- ;
  1144.             n2++ ;
  1145.             }
  1146.         }
  1147.     if (doresize)
  1148.         do_display_resize();
  1149.     if (n2 > 0)
  1150.         kbdfront += n2;
  1151.     if (kbdfront != kbdback) {
  1152.         tc_deselect(1);
  1153.         pty_out();
  1154.         }
  1155.     if (dorefresh)
  1156.         tc_refresh(0);
  1157. }
  1158. @@@ Fin de io.c
  1159. echo main.c
  1160. cat >main.c <<'@@@ Fin de main.c'
  1161. /*
  1162.  * This file is a product of Sun Microsystems, Inc. and is provided for
  1163.  * unrestricted use provided that this legend is included on all tape
  1164.  * media and as a part of the software program in whole or part.
  1165.  * Users may copy, modify or distribute this file at will.
  1166.  * 
  1167.  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1168.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1169.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1170.  * 
  1171.  * This file is provided with no support and without any obligation on the
  1172.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1173.  * modification or enhancement.
  1174.  * 
  1175.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1176.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
  1177.  * OR ANY PART THEREOF.
  1178.  * 
  1179.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1180.  * or profits or other special, indirect and consequential damages, even
  1181.  * if Sun has been advised of the possibility of such damages.
  1182.  * 
  1183.  * Sun Microsystems, Inc.
  1184.  * 2550 Garcia Avenue
  1185.  * Mountain View, California  94043
  1186.  *
  1187.  * Modifications to the original Sun Microsystems, Inc. source code
  1188.  * made by the Grasshopper Group are in the Public Domain.
  1189.  *
  1190.  * Extensions to this file by Eric Messick of the Grasshopper Group.
  1191.  *
  1192.  * Grasshopper Group
  1193.  * 212 Clayton St
  1194.  * San Francisco, CA 94117
  1195.  *
  1196.  */
  1197.  
  1198. #ifndef lint
  1199. static    char sccsid[] = "@(#)main.c 9.7 88/01/19 Copyright 1985 Sun Micro";
  1200. static    char RCSid[] = "@(#)$Header: main.c,v 2.2 88/10/04 04:22:48 eric Release $";
  1201. #endif
  1202.  
  1203. /*
  1204.  * Copyright (c) 1985 by Sun Microsystems, Inc.
  1205.  */
  1206.  
  1207.  
  1208. #include <stdio.h>
  1209. #include <psio.h>
  1210. #include <signal.h>
  1211. #include <pwd.h>
  1212. #include <fcntl.h>
  1213. #include <sys/param.h>
  1214. #include <sys/ioctl.h>
  1215. #ifdef SYSVREF
  1216. #ifdef INTERLANTCP
  1217. #include <interlan/il_types.h>
  1218. #include <interlan/socket.h>
  1219. #include <interlan/in.h>
  1220. #include <interlan/netdb.h>
  1221. #else
  1222. #include <sys/types.h>
  1223. #endif
  1224. #else
  1225. #ifdef REF
  1226. #include <sys/types.h>
  1227. #endif
  1228. #include <sys/socket.h>
  1229. #include <netinet/in.h>
  1230. #include <netdb.h>
  1231. #endif
  1232.  
  1233. #ifdef REF
  1234. #include <ref/config.h>
  1235. #endif
  1236.  
  1237. #ifdef SYSVREF
  1238. #define    SIGCHLD    SIGCLD
  1239. #else
  1240. #include <sys/wait.h>
  1241. #endif
  1242.  
  1243. extern void exit();
  1244. extern void perror();
  1245. extern char *strcpy();
  1246. #ifndef bcopy
  1247. extern void bcopy();
  1248. #endif
  1249. extern void endpwent();
  1250. extern void free();
  1251. extern char *strcat();
  1252.  
  1253. extern    PSFILE *Connect_To_Server();
  1254.  
  1255. int    console;
  1256. static    int KillChild();
  1257. static    int ReapChild();
  1258. static    char *term = NULL;
  1259. static    int seed = 0;
  1260. static    int Persist;
  1261. static    int loginshell = 0;
  1262. static    int tflag = 0;
  1263. static    char *framelabel = NULL;
  1264. static    char *iconlabel = NULL;
  1265. static    char *userinit = "" ;
  1266. static    char *font = "" ;
  1267. static    int xorg = -1;
  1268. static    int yorg = -1;
  1269. static    int iconx = -1;
  1270. static    int icony = -1;
  1271. static    int reload = 0;
  1272. static    int starticonic = 0 ;
  1273. static    int save_lines = 0 ;
  1274. int    fontsize = -1;
  1275. int    BackGround = 1;
  1276. int    PageMode = 0;            /* "pause on end of page" mode */
  1277. int    userCharsPerLine = -1;
  1278. int    userLinesPerScreen = -1;
  1279.  
  1280. main(argc,argv)
  1281.     int    argc;
  1282.     char **argv;
  1283. {
  1284.     char *s_name, **s_args, *argv0 = argv[0];
  1285.     FILE *Client;
  1286.     PSFILE *Keyboard;
  1287.     extern char *getenv();
  1288.     extern PSFILE *tc_init_screen();
  1289.     extern FILE *spawn_slave();
  1290.  
  1291.     BackGround = isatty(0) ;
  1292.  
  1293.     for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
  1294.     if (strcmp(argv[0], "-bg") == 0 || strcmp(argv[0], "-ga") == 0) {
  1295.         BackGround++;        /* put ourself in the background */
  1296.         continue;
  1297.     }
  1298.     if (strcmp(argv[0], "-C") == 0) {
  1299.         console++;
  1300.         continue;
  1301.     }
  1302.     if (strcmp(argv[0], "-co") == 0) {
  1303.         if (--argc > 0)
  1304.         userCharsPerLine = atoi(*++argv);
  1305.         continue;
  1306.     }
  1307.     if (strcmp(argv[0], "-F") == 0) {
  1308.         if (--argc > 0) {
  1309.         font = *++argv;
  1310.         }
  1311.         continue;
  1312.     }
  1313.     if (strcmp(argv[0], "-f") == 0) {
  1314.         continue;
  1315.     }
  1316.     if (strcmp(argv[0], "-fg") == 0) {
  1317.         BackGround = 0 ;        /* don't put ourself in the background */
  1318.         continue;
  1319.     }
  1320.     if (strcmp(argv[0], "-fl") == 0) {
  1321.         if (--argc > 0)
  1322.         framelabel = *++argv;
  1323.         continue;
  1324.     }
  1325.     if (strcmp(argv[0], "-fs") == 0) {
  1326.         if (--argc > 0)
  1327.         fontsize = atoi(*++argv);
  1328.         continue;
  1329.     }
  1330.     if (strcmp(argv[0], "-ic") == 0) {
  1331.         starticonic++;
  1332.         continue;
  1333.     }
  1334.     if (strcmp(argv[0], "-il") == 0) {
  1335.         if (--argc > 0)
  1336.         iconlabel = *++argv;
  1337.         continue;
  1338.     }
  1339.     if (strcmp(argv[0], "-ixy") == 0) {
  1340.         if (--argc > 0)
  1341.         iconx = atoi(*++argv);
  1342.         if (--argc > 0)
  1343.         iconx = atoi(*++argv);
  1344.         if (iconx >= 0 && icony >= 0)
  1345.         continue;
  1346.     }
  1347.     if (strcmp(argv[0], "-li") == 0) {
  1348.         if (--argc > 0)
  1349.         userLinesPerScreen = atoi(*++argv);
  1350.         continue;
  1351.     }
  1352.     if (strcmp(argv[0], "-ls") == 0) {
  1353.         loginshell++;
  1354.         continue;
  1355.     }
  1356.     if (strcmp(argv[0], "-pm") == 0 || strcmp(argv[0], "-ps") == 0) {
  1357.         PageMode++;            /* enable page mode */
  1358.         continue;
  1359.     }
  1360.     if (strcmp(argv[0], "-r") == 0) {
  1361.         reload++;
  1362.         continue;
  1363.     }
  1364.     if (strcmp(argv[0], "-s") == 0) {
  1365.         if (--argc > 0)
  1366.         seed = atoi(*++argv);
  1367.         continue;
  1368.     }
  1369.     if (strcmp(argv[0], "-sl") == 0) {
  1370.         if (--argc > 0)
  1371.         save_lines = atoi(*++argv);
  1372.         continue;
  1373.     }
  1374.     if (strcmp(argv[0], "-t") == 0) {
  1375.         if (--argc > 0) {
  1376.         term = *++argv;
  1377.         tflag++;
  1378.         }
  1379.         continue;
  1380.     }
  1381.     if (strcmp(argv[0], "-ui") == 0) {
  1382.         if (--argc > 0) {
  1383.         userinit = *++argv;
  1384.         }
  1385.         continue;
  1386.     }
  1387.     if (strcmp(argv[0], "-w") == 0) {
  1388.         Persist++;
  1389.         continue;
  1390.     }
  1391.     if (strcmp(argv[0], "-xy") == 0) {
  1392.         if (--argc > 0)
  1393.         xorg = atoi(*++argv);
  1394.         if (--argc > 0)
  1395.         yorg = atoi(*++argv);
  1396.         if (xorg >= 0 && yorg >= 0)
  1397.         continue;
  1398.     }
  1399.     fprintf(stderr, "Usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s\n", argv0,
  1400.         "[-bg] [-C] [-co columns] [-F font] [-f] [-fg] [-fl framelabel]",
  1401.         "[-fs fontsize] [-ic] [-il iconlabel] [-ixy x y] [-li lines]",
  1402.         "[-ls] [-pm] [-r] [-sl savelines] [-t termtype] [-ui userinit] [-w]",
  1403.         "[-xy x y] [command]");
  1404.     (void) Connect_To_Server();
  1405.     Fatal("psterm:  error in arguments", (char *)NULL);
  1406.     }
  1407.     if (loginshell) {
  1408.     char *s, *p, *malloc();
  1409. #ifndef SYSVREF
  1410.     char *rindex(), *index();
  1411. #else
  1412. #define index(s, c)        (char *)strchr(s, c)
  1413. #endif
  1414.     struct passwd *pw, *getpwuid();
  1415.     static char *loginargv[4];
  1416.  
  1417.     s_name = "/bin/sh";        /* default shell name */
  1418.     s_args = loginargv;
  1419.  
  1420.     s_args[0] = "-sh";
  1421.     s_args[1] = 0;
  1422.     if (pw = getpwuid(getuid())) {
  1423.         if (pw->pw_dir)
  1424.         set_environment_var("HOME", pw->pw_dir);
  1425.         if (pw->pw_name) {
  1426.         set_environment_var("LOGNAME", pw->pw_name);
  1427.             set_environment_var("USER", pw->pw_name);
  1428.         }
  1429.         if (pw->pw_shell) {
  1430.         if (s = rindex(pw->pw_shell,'/')) {
  1431.             p = malloc ((unsigned)strlen(s)+4);
  1432.             if (p) {
  1433.             sprintf(p, "-%s", s+1);
  1434.             s_args[0] = p;
  1435.             }
  1436.             p = malloc((unsigned)strlen(pw->pw_shell)+4);
  1437.             if (p) {
  1438.             s_name = p;
  1439.             strcpy(s_name, pw->pw_shell);
  1440.             }
  1441.             set_environment_var("SHELL",pw->pw_shell);
  1442.         }
  1443.         }
  1444.         endpwent();
  1445.     }
  1446.     if (argc > 0) {
  1447.         int i, count = 0;
  1448.         /*
  1449.          * This goofy business in case someone wants to run complex
  1450.          * shell commands after login-shell initialization...
  1451.          */
  1452.         for (i=0; i<argc; i++) {
  1453.         count += strlen(argv[i]);
  1454.         }
  1455.         if (s_args[2] = malloc((unsigned)count+argc+4)) {
  1456.         s_args[2][0] = 0;
  1457.         for (i=0; i<argc; i++) {
  1458.             if (i)
  1459.             strcat(s_args[2], " ");
  1460.             strcat(s_args[2], argv[i]);
  1461.         }
  1462.         s_args[0]++;
  1463.         s_args[1] = "-c";
  1464.         s_args[3] = 0;
  1465.         }
  1466.     }
  1467.     /*
  1468.      * if $NEWSSERVER isn't defined and stdin is a socket, chances
  1469.      * are we're being invoked with rsh, so figure out where the
  1470.      * rsh command came from and use that for NEWSSERVER.
  1471.      */
  1472.     if (getenv("NEWSSERVER")==0) {
  1473.         struct hostent *hp;
  1474.         struct sockaddr_in remote;
  1475.         int n = sizeof remote;
  1476.         if (getpeername(0, (struct sockaddr *)&remote, &n) == 0) {
  1477.         if (remote.sin_family == AF_INET) {
  1478.             char srv[128];
  1479.             sprintf(srv, "%lu.%d;",
  1480.                 ntohl(remote.sin_addr.s_addr), 2000);
  1481.             hp = gethostbyaddr((char*) &remote.sin_addr,
  1482.                        sizeof (remote.sin_addr),
  1483.                        remote.sin_family);
  1484.             if (hp)
  1485.             strcat(srv,hp->h_name);
  1486.             set_environment_var("NEWSSERVER", srv);
  1487.         }
  1488.         }
  1489.     }
  1490.     if (framelabel == NULL) {
  1491.         static char labelbuf[128];
  1492.         gethostname(labelbuf, sizeof labelbuf);
  1493.         if ((p = index(labelbuf, '.')) != NULL)
  1494.         *p = 0;
  1495.         if (argc > 0) {
  1496.         strcat(labelbuf, " ");
  1497.         strcat (labelbuf, argv[0]);
  1498.         }        
  1499.         framelabel = labelbuf;
  1500.     }
  1501.     if (iconlabel == NULL)
  1502.         iconlabel = framelabel;
  1503.     } else if (argc > 0) {
  1504.     s_name = *argv;
  1505.     s_args = argv;
  1506.     } else {
  1507. #ifndef SYSVREF
  1508.     static char *def_argv[] = { "csh", NULL};
  1509. #else
  1510.     static char *def_argv[] = { "-sh", NULL};
  1511. #endif
  1512.  
  1513.     s_args = def_argv;
  1514.     if ((s_name = getenv("SHELL")) == NULL) {
  1515. #ifndef SYSVREF
  1516.         s_name = *def_argv;
  1517.         s_args[0] = s_name;
  1518. #else
  1519.         s_name = "sh";
  1520. #endif
  1521.     }
  1522.     else {
  1523.         s_args[0] = s_name;
  1524.     }
  1525.     }
  1526.     if ( !tflag || term == NULL) {
  1527. #ifdef RandomBehaviour
  1528.     /* Choose one at random - should scan termcap? */
  1529.     static char * def_term[] = {
  1530.         "ansi", "h19", "wyse",
  1531.     };
  1532.  
  1533.     if (seed == 0)
  1534.         seed = getpid();
  1535.     srand(seed);
  1536.     term = def_term[(rand()>>4)%((sizeof def_term)/(sizeof def_term[0]))];
  1537. #else
  1538.     term = "psterm";
  1539. #endif
  1540.     }
  1541.     if (BackGround) {
  1542.     int i;
  1543.     /*
  1544.      * Close any extraneous files.
  1545.      */
  1546.     for (i = getdtablesize(); i > 2; i--)
  1547.         close(i);
  1548.     }
  1549.     if (xorg < 0)
  1550.     xorg = 0;
  1551.     if (yorg < 0)
  1552.     yorg = 0;
  1553.     Keyboard =
  1554.     tc_init_screen(term, xorg, yorg, fontsize, framelabel, iconlabel,
  1555.             reload, userinit, font, starticonic, iconx, icony, save_lines);
  1556.     if (Keyboard == NULL) {
  1557.     char *foo;
  1558.     foo = getenv("NEWSSERVER");
  1559.     if (foo)
  1560.         Fatal("Can't connect to NeWS server at: %s", foo);
  1561.     else
  1562.         Fatal("Can't connect to NeWS server; did you set NEWSSERVER?",
  1563.           (char *)NULL);
  1564.     }
  1565.  
  1566.     tc_initmodemenu();
  1567.     set_environment_var("TERM", term);
  1568.     if ((Client = spawn_slave(s_name, s_args)) == NULL)
  1569.     Fatal("Cannot spawn %s", s_name);
  1570.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  1571.     signal(SIGINT, KillChild);
  1572.     if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  1573.     signal(SIGQUIT, KillChild);
  1574.     signal(SIGHUP, KillChild);
  1575.     signal(SIGTERM, KillChild);
  1576.     signal(SIGCHLD, ReapChild);
  1577.     terminal(fileno(Client), psio_fileno(Keyboard));
  1578.     Exit(0);
  1579.     /*NOTREACHED*/
  1580. }
  1581.  
  1582. Fatal(fmt, a1)
  1583. char *fmt, *a1;
  1584. {
  1585.     extern int ConnectionEstablished;
  1586.     char buf[1024];
  1587.  
  1588.     if (ConnectionEstablished) {
  1589.         sprintf(buf, fmt, a1);
  1590.         PostScriptErrorMessage(buf);
  1591.         }
  1592.     else    {
  1593.         fprintf(stderr, "psterm: ");
  1594.         fprintf(stderr, fmt, a1);
  1595.         fprintf(stderr, ".\n");
  1596.         }
  1597.     Exit(1);
  1598. }
  1599.  
  1600. Exit(status)
  1601. {
  1602.  
  1603.     CleanupPty();
  1604.     exit(status);
  1605. }
  1606.  
  1607. static
  1608. KillChild(sig)
  1609. {
  1610.     extern int pgrp;
  1611.  
  1612.     if (pgrp != 0)
  1613.     killpg(pgrp, sig);
  1614.     CleanupPty();
  1615.     signal(sig, SIG_DFL);
  1616.     kill(0, sig);
  1617. }
  1618.  
  1619. static
  1620. ReapChild()
  1621. {
  1622. #ifdef HAVE_WAIT3
  1623.     union wait status;
  1624.     int pid = wait3(&status, WNOHANG, 0);
  1625. #else    /* !HAVE_WAIT3 */
  1626.     int status, pid = wait(&status);
  1627.     signal(SIGCHLD, ReapChild);
  1628. #endif
  1629.  
  1630.     if (pid < 0)
  1631.     perror("fruitless wait3");
  1632.     else if (Persist == 0)
  1633.     Exit(0);
  1634. }
  1635.  
  1636. set_environment_var(name, value)
  1637. char       *name, *value; {
  1638.     register    len;
  1639.     register char **ap;
  1640.     register char **new;
  1641.     register char *buf;
  1642.     static      alloced = 0;
  1643.     extern char **environ;
  1644.  
  1645.     len = strlen(name);
  1646.     buf = (char *) malloc((unsigned)(len + strlen(value) + 2));
  1647.     if (buf==NULL) return;
  1648.     sprintf(buf, "%s=%s", name, value);
  1649.     for (ap = environ; *ap; ap++)
  1650.     if (strncmp(*ap, buf, len+1) == 0) {
  1651.         *ap = buf;
  1652.         return;
  1653.     }
  1654.     len = ap - environ;
  1655.     new = (char **) malloc((unsigned)((len + 2) * sizeof(char *)));
  1656.     if (new==NULL) return;
  1657.     bcopy((char *)environ, (char *)new, len * sizeof(char *));
  1658.     new[len] = buf;
  1659.     new[len + 1] = 0;
  1660.     if (alloced)
  1661.     free((char *)environ);
  1662.     alloced = 1 ;
  1663.     environ = new;
  1664. }
  1665.  
  1666. unsetenv(name)
  1667. char *name;
  1668. {
  1669.     register    len;
  1670.     register char **ap;
  1671.     register char **new;
  1672.     extern char **environ;
  1673.  
  1674.     len = strlen(name);
  1675.     for (new = ap = environ;  (*new = *ap) != NULL;  ap++) {
  1676.         if (strncmp(*ap, name, len) == 0  &&  (*ap)[len] == '=') {
  1677.             /* Memory leak bug: we cannot free(*ap) here, because we don't know
  1678.              * whether *ap was created with putenv(). */
  1679.             }
  1680.         else    new++;
  1681.         }
  1682. }
  1683. @@@ Fin de main.c
  1684. echo display.c
  1685. cat >display.c <<'@@@ Fin de display.c'
  1686. /*
  1687.  * This file is a product of Sun Microsystems, Inc. and is provided for
  1688.  * unrestricted use provided that this legend is included on all tape
  1689.  * media and as a part of the software program in whole or part.
  1690.  * Users may copy, modify or distribute this file at will.
  1691.  * 
  1692.  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1693.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1694.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1695.  * 
  1696.  * This file is provided with no support and without any obligation on the
  1697.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1698.  * modification or enhancement.
  1699.  * 
  1700.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1701.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
  1702.  * OR ANY PART THEREOF.
  1703.  * 
  1704.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1705.  * or profits or other special, indirect and consequential damages, even
  1706.  * if Sun has been advised of the possibility of such damages.
  1707.  * 
  1708.  * Sun Microsystems, Inc.
  1709.  * 2550 Garcia Avenue
  1710.  * Mountain View, California  94043
  1711.  *
  1712.  * Modifications to the original Sun Microsystems, Inc. source code
  1713.  * made by the Grasshopper Group are in the Public Domain.
  1714.  *
  1715.  * Extensions to this file by Eric Messick of the Grasshopper Group.
  1716.  *
  1717.  * Grasshopper Group
  1718.  * 212 Clayton St
  1719.  * San Francisco, CA 94117
  1720.  *
  1721.  */
  1722.  
  1723. #ifndef lint
  1724. static char sccsid[] = "@(#)display.c 9.5 88/01/19 Copyright 1985 Sun Micro";
  1725. static char RCSid[] =
  1726.     "@(#)$Header: display.c,v 2.2 88/10/04 05:11:23 eric Release $";
  1727. #endif
  1728.  
  1729. /*
  1730.  * Copyright (c) 1985 by Sun Microsystems, Inc. 
  1731.  */
  1732.  
  1733. /*-
  1734.     display.c
  1735.  
  1736.     display.c, Wed Mar 26 15:56:31 1986
  1737.  
  1738.         David Rosenthal,
  1739.         Sun Microsystems
  1740.  */
  1741.  
  1742. #ifdef    notdef
  1743. #define Diagnose
  1744. #endif
  1745. /*
  1746.  * Screen display module 
  1747.  *
  1748.  * The external interface of this module is the routine tc_refresh(), and the
  1749.  * initialization routine tc_init_screen(). 
  1750.  */
  1751.  
  1752. #include    <sys/types.h>
  1753. #ifdef REF
  1754. #include    <ref/config.h>
  1755. #endif
  1756. #include    <sys/ioctl.h>
  1757. #include    <sys/signal.h>
  1758. #include    <sys/file.h>
  1759. #include    "screen.h"
  1760. #include    "tcap.h"
  1761.  
  1762. extern void free();
  1763. #ifndef bzero
  1764. extern void bzero();
  1765. #endif
  1766. #ifndef bcopy
  1767. extern void bcopy();
  1768. #endif
  1769. extern void perror();
  1770.  
  1771. #define CHARS_PER_LINE        80
  1772. #define LINES_PER_SCREEN    24
  1773.  
  1774. #define TypicalWidth        80
  1775.  
  1776. #define min(x, y) (((x)<(y))?(x):(y))
  1777.  
  1778. int     CharsPerLine = CHARS_PER_LINE;
  1779. int     LinesPerScreen = LINES_PER_SCREEN;
  1780. struct pair Dot = {0, 0};
  1781.  
  1782. int fontisfixedwidth = 1 ;
  1783.  
  1784. int ConnectionEstablished = 0 ;
  1785.  
  1786. static Repairing;
  1787. static struct pair ScreenDot = {0, 0};
  1788. static char *CursorChar = " ";
  1789. static u_char CursorProp = 0 ;
  1790. extern int PageFull;
  1791.  
  1792. int RefreshSuppressed = 1;
  1793.  
  1794. int TotalScrollLength = 0 ;
  1795. int ScrollLength = 0 ;
  1796. int ScrollY = 0 ;
  1797. int ScrollLinesSaved = 0 ;
  1798. int userScrollLength = 0 ;
  1799. int FastPaint = 1 ;
  1800. int DoScrolling = 1 ;
  1801.  
  1802. struct line **scroll_area;
  1803.  
  1804. char *
  1805. Malloc(size)
  1806. int size;
  1807. {
  1808.     extern char *malloc();
  1809.     char *ret;
  1810.  
  1811.     if ((ret=malloc((unsigned)size))==NULL)
  1812.         Fatal("Out of Memory", (char *)NULL);
  1813.     return ret;
  1814. }
  1815.  
  1816. static
  1817. RemoveCursor()
  1818. {
  1819.     if ((ScreenDot.x >= 0) && (! (CursorProp & ReverseVideoLook)))
  1820.         CursorDown(ScreenDot.x, ScreenDot.y, CursorChar, 1);
  1821.     ScreenDot.x = -1;
  1822. }
  1823.  
  1824. static
  1825. PlaceCursor(x, y)
  1826. {
  1827.     register struct line *l;
  1828.  
  1829.     if (x >= CharsPerLine) x = CharsPerLine - 1;
  1830.     if (x < 0) x = 0;
  1831.  
  1832.     if (y >= LinesPerScreen) y = LinesPerScreen - 1;
  1833.     if (y < 0) y = 0;
  1834.  
  1835.     ScreenDot.x = x ;
  1836.     ScreenDot.y = y + ScrollLength - LinesPerScreen - ScrollY ;
  1837.  
  1838.     l = screen[y];
  1839.     CursorChar = l->body + x ;
  1840.     CursorProp = l->prop[x] ;
  1841.  
  1842.     if (ScreenDot.y >= LinesPerScreen) {
  1843.     ScreenDot.x = -1 ;
  1844.     return;
  1845.     }
  1846.  
  1847.     if (!PageFull)            /* hide cursor if output blocked */
  1848.     CursorUp(ScreenDot.x, ScreenDot.y, CursorChar, 1);
  1849. }
  1850.  
  1851. set_scroll_save(length)
  1852. int length;
  1853. {
  1854.     int i, j, delta;
  1855.     struct line *line, **new_lines;
  1856.     char *body;
  1857.     u_char *prop;
  1858.  
  1859.     tc_deselect(0);        /* do this before we move the lines around */
  1860.     userScrollLength = length ;
  1861.     if (!RefreshSuppressed)
  1862.         ToggleScrollBar(length);
  1863.     if (length < LinesPerScreen) length = LinesPerScreen ;
  1864.     if (length > TotalScrollLength) {
  1865.         new_lines = (struct line **) Malloc(2 * length *
  1866.                         sizeof(struct line *)) ;
  1867.         for (i=length-ScrollLength, j=0; j<ScrollLength; j++, i++) {
  1868.             new_lines[i] = lines[j] ;
  1869.             }
  1870.         TotalScrollLength = length ;
  1871.         if (scroll_area) free((char *)scroll_area);
  1872.         scroll_area = lines = new_lines ;
  1873.         }
  1874.     else    {
  1875.         delta = ScrollLength - length ;
  1876.         if (delta>0) {
  1877.             for (i=0; i<length; i++) {
  1878.                 if (lines[i]) {
  1879.                     if (lines[i]->body)
  1880.                         free(lines[i]->body);
  1881.                     if (lines[i]->prop)
  1882.                         free((char *)lines[i]->prop);
  1883.                     free((char *)lines[i]);
  1884.                     }
  1885.                 lines[i] = lines[i+delta] ;
  1886.                 lines[i+delta] = NULL ;
  1887.                 }
  1888.             }
  1889.         else    for (i=ScrollLength-1; i>=0; i--)
  1890.                 lines[i-delta] = lines[i] ;
  1891.         }
  1892.     for (i=0; i<length-ScrollLength; i++) {
  1893.         line = (struct line *) Malloc(sizeof(struct line));
  1894.         line->body = Malloc(TypicalWidth) ;
  1895.         for (j=0; j<TypicalWidth; j++)
  1896.             line->body[j] = ' ' ;
  1897.         line->prop = (u_char *)Malloc(TypicalWidth) ;
  1898.         bzero((char *)line->prop, TypicalWidth);
  1899.         line->buffer_length = TypicalWidth ;
  1900.         line->length = 0 ;
  1901.         line->changeposition = 0 ;
  1902.         line->end_of_changes = 0 ;
  1903.         line->usedtobe = -1 ;
  1904.         line->flags = 0 ;
  1905.         lines[i] = line ;
  1906.         }
  1907.     ScrollY += length - ScrollLength ;
  1908.     ScrollLength = length ;
  1909.     if (ScrollY < 0) ScrollY = 0 ;
  1910.     if (ScrollY > ScrollLength - LinesPerScreen)
  1911.         ScrollY = ScrollLength - LinesPerScreen ;
  1912.     for (i=ScrollLength-LinesPerScreen; i < ScrollLength; i++) {
  1913.         if (lines[i]->buffer_length <= CharsPerLine) {
  1914.             body = Malloc(CharsPerLine+1);
  1915.             prop = (u_char *) Malloc(CharsPerLine+1);
  1916.             length = lines[i]->length ;
  1917.             if (lines[i]->buffer_length > 0) {
  1918.                 bcopy(lines[i]->body, body, length);
  1919.                 bcopy((char *)lines[i]->prop, (char *)prop, length);
  1920.                 free(lines[i]->body);
  1921.                 free((char *)lines[i]->prop);
  1922.                 }
  1923.             bzero((char *)&prop[length], CharsPerLine - length + 1);
  1924.             for (; length <= CharsPerLine; length++)
  1925.                 body[length] = ' ' ;
  1926.             lines[i]->body = body ;
  1927.             lines[i]->prop = prop ;
  1928.             lines[i]->buffer_length = CharsPerLine + 1 ;
  1929.             }
  1930.         }
  1931. /*    if (ScrollLinesSaved > ScrollLength) */
  1932.         ScrollLinesSaved = ScrollLength ;
  1933.     if (ScrollLinesSaved < LinesPerScreen)
  1934.         ScrollLinesSaved = LinesPerScreen ;
  1935.     screen = &lines[ScrollLength - LinesPerScreen] ;
  1936. }
  1937.  
  1938. scroll_to_bottom()
  1939. {
  1940.     scroll_to(ScrollLinesSaved - LinesPerScreen);
  1941. }
  1942.  
  1943. scroll_to(scrolly)
  1944. int scrolly;
  1945. {
  1946.     int i, lesser, greater;
  1947.  
  1948.     scrolly += ScrollLength - ScrollLinesSaved ;
  1949.     if (scrolly < 0) scrolly = 0 ;
  1950.     if (scrolly > ScrollLength - LinesPerScreen)
  1951.         scrolly = ScrollLength - LinesPerScreen ;
  1952.     if (scrolly != ScrollY) {
  1953.         if (scrolly < ScrollY) {
  1954.             lesser = scrolly;
  1955.             greater = ScrollY;
  1956.             }
  1957.         else    {
  1958.             lesser = ScrollY;
  1959.             greater = scrolly;
  1960.             }
  1961.         for (i=lesser; i<greater; i++)
  1962.             if (lines[i])
  1963.                 lines[i]->usedtobe = -1 ;
  1964.         for (i=lesser+LinesPerScreen; i<greater+LinesPerScreen; i++)
  1965.             if (lines[i])
  1966.                 lines[i]->usedtobe = -1 ;
  1967.         }
  1968.     ScrollY = scrolly ;
  1969. }
  1970.  
  1971. ScrollSaveLine(line)
  1972. struct line *line;
  1973. {
  1974.     int i;
  1975.     struct line *new;
  1976.  
  1977.     if (ScrollLength <= LinesPerScreen)
  1978.         return;
  1979.     if (ScrollLinesSaved < ScrollLength)
  1980.         ScrollLinesSaved++;
  1981.     for (i=ScrollLength; i>ScrollLength-LinesPerScreen; i--)
  1982.         lines[i] = lines[i-1] ;
  1983.     new = lines[i] = lines[0] ;
  1984.     if (new->buffer_length < line->length + 1) {
  1985.         free(new->body);
  1986.         free((char *)new->prop);
  1987.         new->body = Malloc((int)line->length + 1);
  1988.         new->prop = (u_char *) Malloc((int)line->length + 1);
  1989.         new->buffer_length = line->length + 1 ;
  1990.         }
  1991.     bcopy(line->body, new->body, (int)line->length+1);
  1992.     bcopy((char *)line->prop, (char *)new->prop, (int)line->length+1);
  1993.     new->length = line->length ;
  1994.     new->changeposition = 0 ;
  1995.     new->end_of_changes = CharsPerLine + 1 ;
  1996.     new->usedtobe = line->usedtobe ;
  1997.     new->flags = line->flags ;
  1998.     lines++ ;
  1999.     if (&lines[ScrollLength] >= &scroll_area[TotalScrollLength * 2]) {
  2000.         bcopy((char *)lines, (char *)scroll_area,
  2001.             sizeof(struct line **)*ScrollLength);
  2002.         lines = scroll_area ;
  2003.         }
  2004.     screen = &lines[ScrollLength - LinesPerScreen] ;
  2005. }
  2006.     
  2007. /* --------------- External Routines Below ------------------- */
  2008.  
  2009. do_display_resize() {
  2010.     register i;
  2011. /*    tc_refresh(0);*/
  2012.     BeginRepair();
  2013.     Repairing++;
  2014.     ReInitialize();
  2015.     for (i = 0; i<LinesPerScreen; i++) {
  2016.     lines[i+ScrollY]->changeposition = 0;
  2017.     lines[i+ScrollY]->end_of_changes = CharsPerLine ;
  2018.     }
  2019.     tc_refresh(0);
  2020.     tc_refresh_selection();
  2021.     psio_flush(PostScript);
  2022. }
  2023.  
  2024. PSFILE *
  2025. Connect_To_Server()
  2026. {
  2027.     extern PSFILE *ps_open_PostScript();
  2028.     PSFILE *f;
  2029.  
  2030.     if ((f = ps_open_PostScript()) == NULL) {
  2031.         return (NULL);
  2032.         }
  2033.     ConnectionEstablished = 1 ;
  2034.     return f;
  2035. }
  2036.  
  2037. PSFILE       *
  2038. tc_init_screen(term, xorg, yorg, font_size, framelabel, iconlabel, reload,
  2039.         userinit, font, starticonic, iconx, icony, savelines)
  2040. char *term;
  2041. int xorg, yorg, font_size;
  2042. char *framelabel, *iconlabel;
  2043. int reload;
  2044. char *userinit, *font;
  2045. int starticonic, iconx, icony, savelines;
  2046. {
  2047.     PSFILE       *f;
  2048.     char        frametitle[100];
  2049.     char        host[100];
  2050.  
  2051.     f = Connect_To_Server();
  2052.     if (f==NULL) return NULL;
  2053.  
  2054.     PSDefs(reload);
  2055.     psio_flush(PostScript);
  2056.  
  2057.     if (framelabel == NULL) {
  2058.         static char te[] = " terminal emulator";
  2059.         sprintf(frametitle, "%.*s%s",
  2060.         sizeof(frametitle)-sizeof(te)-strlen(term), term, te);
  2061.         framelabel = frametitle;
  2062.         }
  2063.     if (iconlabel == NULL) {
  2064.         gethostname(host, sizeof (host));
  2065.         host[sizeof(host)-1] = '\0';
  2066.          iconlabel = host;
  2067.         }
  2068.     if (tc_initialize(term))
  2069.         Fatal("%s: Unknown terminal type or bad termcap description",
  2070.             term);
  2071.     set_scroll_save(savelines);
  2072.     scroll_to_bottom();
  2073.     tc_init_selection();
  2074.     PSInitCode(userinit);
  2075.     CreateWindow(xorg, yorg, font_size, CharsPerLine, LinesPerScreen,
  2076.         framelabel, iconlabel, font, starticonic, iconx, icony);
  2077.     ToggleScrollBar(savelines);
  2078.     StartInput();
  2079.     /* XXX - set up PostScript process for i/p etc. */
  2080.     psio_flush(PostScript);
  2081.     return (f);
  2082. }
  2083.  
  2084. PostScriptErrorMessage(s)
  2085. char *s;
  2086. {
  2087.     PopMsg(s);
  2088.     psio_flush(PostScript);
  2089. }
  2090.  
  2091. #define Finished_Dammage    1
  2092. #define Finished_NoDammage    2
  2093. #define Painting_Dammage    3
  2094. #define Painting_NoDammage    4
  2095.  
  2096. static int RefreshState = Finished_Dammage ;
  2097.  
  2098. end_refresh()
  2099. {
  2100.     switch (RefreshState) {
  2101.     case Painting_Dammage:
  2102.         RefreshState = Finished_Dammage ;
  2103.         break;
  2104.     case Painting_NoDammage:
  2105.         RefreshState = Finished_NoDammage ;
  2106.         break;
  2107.     case Finished_Dammage:
  2108.         RefreshState = Finished_Dammage ;
  2109.         break;
  2110.     case Finished_NoDammage:
  2111.         RefreshState = Finished_NoDammage ;
  2112.         break;
  2113.         }
  2114. }
  2115.  
  2116. /*ARGSUSED*/
  2117. tc_refresh(full)
  2118.     int full;
  2119. {
  2120.     register struct line *l;
  2121.     register int i, pos, c;
  2122.     register u_char *cp;
  2123.     register struct line **sp;
  2124.     int delta, curdelta, len;
  2125.     int linesscrolledforward, linesscrolledreverse;
  2126.     int paintfromtop;
  2127.     int x, y;
  2128.     static int CursorLine = 0 ;
  2129.     static int CursorCol = 0 ;
  2130.     static int oldlinessaved = 0 ;
  2131.     static int oldlinesperscreen = 0 ;
  2132.     static int oldscrolly = 0 ;
  2133.     u_char *tp, *ep, hit[MaxLinesPerScreen];
  2134.  
  2135.     if (RefreshSuppressed) return;
  2136.     switch (RefreshState) {
  2137.     case Painting_Dammage:
  2138.         if (FastPaint) return ;
  2139.         break;
  2140.     case Painting_NoDammage:
  2141.         RefreshState = Painting_Dammage ;
  2142.         if (FastPaint) return ;
  2143.         break;
  2144.     case Finished_Dammage:
  2145.         RefreshState = Painting_NoDammage ;
  2146.         break;
  2147.     case Finished_NoDammage:
  2148.         RefreshState = Finished_Dammage ;
  2149.         return;
  2150.         }
  2151.     if (ScrollY != oldscrolly) tc_take_down_selection();
  2152.     bzero((char *)hit, LinesPerScreen);
  2153.     linesscrolledforward = linesscrolledreverse = 0 ;
  2154.     if (!fontisfixedwidth) {
  2155.     y = Dot.y + ScrollLength - LinesPerScreen - ScrollY ;
  2156.     if (y >= 0 && y < LinesPerScreen)
  2157.         hit[y] = 1 ;
  2158.     y = CursorLine + ScrollLength - LinesPerScreen - ScrollY ;
  2159.     if (y >= 0 && y < LinesPerScreen)
  2160.         hit[y] = 1 ;
  2161.     }
  2162.     else RemoveCursor();
  2163.     /*
  2164.      * Figure out which lines have moved and by
  2165.      * how much.  Accumulate delta line movements
  2166.      * and copy lines to perform scrolling.
  2167.      */
  2168.     curdelta = 0;
  2169.         /* positive delta means lines are travelling in this direction
  2170.          *             |  |
  2171.          *             |  |
  2172.          *            \    /
  2173.          *             \  /
  2174.          *              \/
  2175.          */
  2176.     sp = &lines[ScrollY];
  2177.     for (i = 0; i < LinesPerScreen; i++) {
  2178.     l = *sp++;
  2179.     pos = l->usedtobe ;    /* this line just moved from position pos */
  2180.     delta = i - pos ;    /* it moved this far in getting here */
  2181.     if (pos >= LinesPerScreen || pos < 0 || hit[pos] || (delta && !DoScrolling)) {
  2182.         delta = 0 ;        /* this line has been scribbled on,
  2183.                      *   so it stays put */
  2184.         l->changeposition = 0 ;    /* but has been dammaged */
  2185.         l->end_of_changes = CharsPerLine ;
  2186.         }
  2187.     l->usedtobe = i;
  2188. #ifdef lint
  2189.     c = 0 ;
  2190. #endif
  2191.     /*
  2192.      * If the delta changes, we need to start a new
  2193.      * run of lines to copy.  If there was a previous
  2194.      * run, then copy those first.
  2195.      */
  2196.     if (delta != curdelta) {
  2197.         if (curdelta != 0) {
  2198.         for (pos = c; pos < i; pos++)
  2199.             hit[pos] = 1 ;
  2200.         if (curdelta > 0)
  2201.             linesscrolledreverse += i - c ;
  2202.         else    linesscrolledforward += i - c ;
  2203.         CopyLines(c - curdelta, curdelta, CharsPerLine, i - c);
  2204.         }
  2205.         curdelta = delta;        /* delta for current run */
  2206.         c = i;            /* starting line of run */
  2207.     }
  2208.     }
  2209.     /*
  2210.      * Catch any trailing run needing to be copied.
  2211.      */
  2212.     if (curdelta != 0) {
  2213.     if (curdelta > 0)
  2214.         linesscrolledreverse += i - c ;
  2215.     else    linesscrolledforward += i - c ;
  2216.     CopyLines(c - curdelta, curdelta, CharsPerLine, i - c);
  2217.     }
  2218. #ifdef lint
  2219.     paintfromtop = linesscrolledreverse > linesscrolledforward ;
  2220. #endif
  2221.     paintfromtop = 1 ;
  2222.  
  2223.     /*
  2224.      * Finally, perform any erasures
  2225.      * and/or text painting required.
  2226.      */
  2227.     if (paintfromtop)
  2228.         sp = &lines[ScrollY] ;
  2229.     else    sp = &lines[ScrollY + LinesPerScreen - 1];
  2230.     for (i = 0; i < LinesPerScreen; (paintfromtop ? sp++ : sp--), i++) {
  2231.         l = *sp;
  2232.         pos = l->changeposition;
  2233.         if (pos<min(l->end_of_changes+MaxCharsPerLine, l->length)+1) {
  2234.             if (!fontisfixedwidth)
  2235.                 pos = 0 ;
  2236.             x = pos ;
  2237.             y = l->usedtobe ;
  2238.             MoveTo(x, y);
  2239.             if (l->buffer_length == 0) {
  2240.                 PaintNor(" ", 1);
  2241.                 continue;
  2242.                 }
  2243.             ep = &l->prop[l->length+1];
  2244.             for (cp = &l->prop[pos]; cp < ep; pos += len) {
  2245.                 /*
  2246.                  * Calculate longest sub-string of
  2247.                  * changed text with identical properties.
  2248.                  */
  2249.                 tp = cp;
  2250.                 if (!fontisfixedwidth &&
  2251.                         y == Dot.y + ScrollLength -
  2252.                         LinesPerScreen - ScrollY) {
  2253.                     c = *cp++ ;
  2254.                     if (x++==Dot.x)
  2255.                         c ^= ReverseVideoLook ;
  2256.                     for (; c==*cp && cp<ep && x!=Dot.x;
  2257.                             cp++, x++)
  2258.                         ;
  2259.                     }
  2260.                 else    {
  2261.                     for (c = *cp++; c==*cp && cp<ep; cp++)
  2262.                         ;
  2263.                     }
  2264.                 len = cp - tp;
  2265.                 /*
  2266.                  * Paint sub-string according to properties.
  2267.                  */
  2268.                 if (c & UnderlineLook) {
  2269.                     if (c & ReverseVideoLook)
  2270.                         PaintUnderRev(&l->body[pos],
  2271.                             len);
  2272.                     else
  2273.                         PaintUnderNor(&l->body[pos],
  2274.                             len);
  2275.                     }
  2276.                 else    {
  2277.                     if (c & ReverseVideoLook)
  2278.                         PaintRev(&l->body[pos], len);
  2279.                     else
  2280.                         PaintNor(&l->body[pos], len);
  2281.                     }
  2282.                 }
  2283.             l->changeposition = CharsPerLine + 1 ;
  2284.             l->end_of_changes = 0 ;
  2285.             }
  2286.         }
  2287.  
  2288.     if (fontisfixedwidth) PlaceCursor(Dot.x, Dot.y);
  2289.     CursorLine = Dot.y ;
  2290.     CursorCol = Dot.x ;
  2291. #ifdef lint
  2292.     CursorLine = CursorCol ;
  2293. #endif
  2294.     if (Repairing) {
  2295.     EndRepair();
  2296.     Repairing = 0;
  2297.     }
  2298.     if (oldlinessaved != ScrollLinesSaved ||
  2299.         oldlinesperscreen != LinesPerScreen) {
  2300.     SetScrollBarValue(ScrollLinesSaved,
  2301.         ScrollY + ScrollLinesSaved - ScrollLength);
  2302.     oldlinessaved = ScrollLinesSaved ;
  2303.     oldlinesperscreen = LinesPerScreen ;
  2304.     }
  2305.     if (ScrollY != oldscrolly) tc_refresh_selection();
  2306.     oldscrolly = ScrollY ;
  2307.     EndRefresh();
  2308.     FlushPostScript();
  2309. }
  2310.  
  2311. change_rowcol(row, col)
  2312. int row, col;
  2313. {
  2314.     extern int Mfd;        /* Master pty fd */
  2315.     int pgroup;
  2316.  
  2317.     if (row >= MaxLinesPerScreen) row = MaxLinesPerScreen - 1 ;
  2318.     if (col >= MaxCharsPerLine) col = MaxCharsPerLine - 1 ;
  2319.     if (row != LinesPerScreen || col != CharsPerLine) {
  2320. #ifdef sun
  2321.  
  2322. #ifdef TIOCSSIZE
  2323.         struct ttysize ts;
  2324.  
  2325.         ts.ts_lines = row;
  2326.         ts.ts_cols = col;
  2327.         ioctl(Mfd, TIOCSSIZE, &ts);
  2328. #endif TIOCSSIZE
  2329.  
  2330. #else sun
  2331.  
  2332. #ifdef TIOCSWINSZ
  2333.         struct winsize ws;
  2334.  
  2335.         ws.ws_row = row;
  2336.         ws.ws_col = col;
  2337.         ws.ws_xpixel = row; /* don't know */
  2338.         ws.ws_ypixel = col; /* don't know */
  2339.         ioctl(Mfd, TIOCSWINSZ, &ws);
  2340. #endif TIOCSWINSZ
  2341.  
  2342. #endif sun
  2343.  
  2344.         ScrollY += LinesPerScreen - row ;
  2345.         resetscreensize(row, col);
  2346.  
  2347. #ifdef sun
  2348.         if (ioctl(Mfd, TIOCGPGRP, &pgroup)<0)
  2349.             perror("ioctl TIOCGPGRP");
  2350.         else if (killpg(pgroup, SIGWINCH)<0)
  2351.             perror("kill SIGWINCH");
  2352. #endif sun
  2353.         }
  2354.     for (row=0; row<ScrollLength; row++)
  2355.         if (lines[row])
  2356.             lines[row]->usedtobe = -1 ;
  2357.     /* allocate full length lines for whole screen */
  2358.     set_scroll_save(userScrollLength);
  2359.     scroll_to(ScrollY - ScrollLength + ScrollLinesSaved);
  2360. }
  2361. @@@ Fin de display.c
  2362. exit 0
  2363.  
  2364.