home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / unix / uw_shar.sit / uw-42-part1.shar next >
Text File  |  1989-09-14  |  57KB  |  2,121 lines

  1. #       ARPANET/MILNET: jdb@mordor.s1.gov
  2. #
  3. #       UUCP:           {lll-crg,decwrl,caip}!mordor!jdb
  4. #
  5. #       U.S. Mail:      John Bruner
  6. #                       Lawrence Livermore National Laboratory
  7. #                       P.O. Box 5503, L-276
  8. #                       Livermore, CA  94550
  9. #
  10. #These are comments.  You can remove everything above the next
  11. #blank line if you wish.
  12. : This is a shar archive.  Extract with sh, not csh.
  13. if test ! -d misc; then
  14.     echo mkdir misc
  15.     mkdir misc
  16. fi
  17. if test ! -d utility; then
  18.     echo mkdir utility
  19.     mkdir utility
  20. fi
  21. echo x - README
  22. sed -e 's/^X//' > README << '!EOF!README!'
  23. X                UW Version 4.2
  24. X                31 January 1988
  25. X
  26. XThis is version 4.2 of UW, a multiple-window interface to UNIX for
  27. Xthe Macintosh computer.  The distribution for UW consists of two
  28. Xbinary files for the Macintosh (in BinHex 4.0 format) and a number
  29. Xof source files for the (BSD) UNIX server.
  30. X
  31. XThe distribution includes the following directories:
  32. X
  33. X    h    - all UW include files
  34. X    server    - source code for the UW server
  35. X    lib    - source code for the UW programmer's library
  36. X    utility    - source code for miscellaneous utility programs
  37. X    doc    - [nt]roff documentation (-ms and -man formats)
  38. X    hqx    - Macintosh binary files
  39. X    misc    - other things of possible interest
  40. X
  41. XThe two Macintosh files are "uw.hqx", which is the executable binary
  42. Xand "uw.doc.hqx", which is a MacWrite-format document describing the
  43. XMacintosh user interface.
  44. X
  45. XUW was developed alternately on a Sun 3 and 4.3BSD VAX.  It also
  46. Xhas been tested (more briefly) on a Sun 2 (release 2.0), Integrated
  47. XSolutions VME 68020 (release 3.05), and a Pyramid. It depends quite a
  48. Xbit upon BSD-specific features such as interprocess communication and
  49. Xwill not run without modification on a System V UNIX system.
  50. X
  51. XThis distribution, like the version 3.4 distribution, includes
  52. Xmake files for both 4.2BSD and 4.3BSD.  The choice of make files
  53. Xand other configuration options is determined by the top-level
  54. X"Makefile".  Comments in that file describe the configuration options.
  55. X
  56. XA "make install" in the top-level directory will compile and install
  57. Xall of the (UNIX) pieces of the UW distribution.  As distributed,
  58. Xthis will create a link between the directory name "/usr/include/uw"
  59. Xand the "h" subdirectory and will create a "/usr/local/bin/libuw.a"
  60. Xlibrary file.  These two steps allow application program to use
  61. X    #include <uw/uwlib.h>
  62. Xand
  63. X    cc -o xyzzy xyzzy.o -luw
  64. Xfor greater convenience in creating programs that use the UW library.
  65. X
  66. XIf you do not have the "getopt" library routine, you will find the
  67. Xsource in "misc/getopt.c"  This source code was publicly distributed by
  68. XAT&T and is also available in the "mod.sources" archive.  You should
  69. Xcompile it and install it in your machine's "/lib/libc.a"  (Note that
  70. Xsince it uses "strchr", you should compile it on a BSD system with the
  71. Xcommand "cc -O -c getopt.c -Dstrchr=index".)  [Sorry, I can't find a
  72. Xmanual page which I can (legally) include.]  If you can't change
  73. X"libc.a", then you should add it to the makefiles in the "server"
  74. Xand "lib" directories.
  75. X
  76. XVersion 4.2 is primarily a maintenance release.  Because of constraints
  77. Xon the author's time, few things have changed since version 4.1.  Some
  78. Xof the differences are:
  79. X
  80. X    1)    UW v4.2 is compatible with Multifinder.  It understands background
  81. X    events, so it can receive input and update windows even when
  82. X    another application's window is active.
  83. X
  84. X    2)    Some problems relating to keyboard mapping have been fixed.
  85. X    UW recognizes the Control and ESC keys.  The mapping for the
  86. X    numeric keypad still seems to be incomplete.  The author is
  87. X    hampered by the fact that his development machine still has
  88. X    its original 512K Mac keyboard.  (He dislikes the Mac+ and
  89. X    SE keyboards.)
  90. X
  91. X    3)    A new window type -- plot -- has been defined.  This type of
  92. X    window can only be created by the host.  It interprets output
  93. X    in UNIX v7 plot(5) format.
  94. X
  95. X    4)    Windows may use 7, 9, 10, or 12 point fixed-width fonts.
  96. X    UW includes non-Apple-copyrighted Mishawaka fonts for these sizes.
  97. X
  98. XUW is not public domain.  It is copyrighted.  However, permission to
  99. Xcopy UW is given provided that the copies are not sold and that the
  100. Xcopyright notices are retained.
  101. X
  102. XComments about UW can be sent to the author (me) at the following
  103. Xaddresses:
  104. X
  105. X    ARPANET/MILNET:    jdb@mordor.s1.gov
  106. X
  107. X    UUCP:        {lll-crg,decwrl,caip}!mordor!jdb
  108. X
  109. X    U.S. Mail:    John Bruner
  110. X            Lawrence Livermore National Laboratory
  111. X            P.O. Box 5503, L-276
  112. X            Livermore, CA  94550
  113. X
  114. XI try to answer all mail, but sometimes am unable to do so for reasons
  115. Xbeyond my control (e.g. incomplete or incorrect return addresses,
  116. Xfinicky mailers).
  117. !EOF!README!
  118. echo x - Makefile
  119. sed -e 's/^X//' > Makefile << '!EOF!Makefile!'
  120. X#! /bin/make -f
  121. X#
  122. X#    Makefile for UW version 4.2
  123. X#
  124. X# Specify VERSION 4.3 for 4.3BSD, 4.2 for 4.2BSD (including Sun 3.x)
  125. X#
  126. X# DEFINES is a list of the site-dependent compile-time options:
  127. X#     -DUTMP        attempt to update "/etc/utmp" (who) file
  128. X#     -DV7TTYS    V7-format "/etc/ttys" (pre-4.3BSD)
  129. X#    -DSETOWN_BUG    fcntl(fd, F_SETOWN, pgrp) is broken (pre-4.3BSD)
  130. X#    -Dvoid=int    kludge around broken C compilers
  131. X#
  132. X# UTMP specifies that UW should attempt to update the "/etc/utmp" file.
  133. X# On some (foolish) systems this file is world-writeable.  Other
  134. X# installations may wish AFTER CAREFUL EXAMINATION OF THE ISSUES to
  135. X# install the UW server with group write access to the utmp file.
  136. X#
  137. X# V7TTYS should be used for V7-derived systems that do not have 4.3BSD's
  138. X# "/etc/ttys" file.  This includes 4.2BSD and Sun UNIX.  There is no
  139. X# support for USG's "/etc/inittab".
  140. X#
  141. X# SETOWN_BUG should be defined if the fcntl(fd, F_SETOWN, pgrp) system
  142. X# call is broken (as it is in 4.2BSD and Sun 3.0 UNIX).  On those
  143. X# machines the third argument must be negative to specify a process ID
  144. X# and positive to specify a process group.
  145. X#
  146. X# Some C compilers do not understand pointers to void functions.  The
  147. X# common kludge around this problem is to substitute "int" for "void"
  148. X# everywhere.  "lint" doesn't like this, but the program will compile
  149. X# into working code.
  150. X#
  151. XBINDIR    =    /usr/local/bin
  152. XINCDIR    =    /usr/include/uw
  153. XLIBDIR    =    /usr/local/lib
  154. XVERSION    =    4.3
  155. X
  156. XDEFINES    =    -DUTMP
  157. X
  158. XMKFILES    =    server/Makefile lib/Makefile utility/Makefile hqx/Makefile
  159. X
  160. Xall:    DEFINES $(MKFILES)
  161. X    cd server; make
  162. X    cd lib; make
  163. X    cd utility; make
  164. X    cd hqx; make
  165. X
  166. Xdepend:
  167. X    cd server; make depend
  168. X    cd lib; make depend
  169. X    cd utility; make depend
  170. X
  171. Xinstall:    all
  172. X    ln -s `pwd`/h $(INCDIR)
  173. X    install -s server/uw $(BINDIR)/uw
  174. X    install -s utility/uwtool $(BINDIR)/uwtool
  175. X    install -s utility/uwtitle $(BINDIR)/uwtitle
  176. X    install -s utility/uwterm $(BINDIR)/uwterm
  177. X    install -s utility/uwplot $(BINDIR)/uwplot
  178. X    cp lib/libuw.a $(LIBDIR); ranlib $(LIBDIR)/libuw.a
  179. X
  180. Xclean:
  181. X    cd server; make clean
  182. X    cd lib; make clean
  183. X    cd utility; make clean
  184. X
  185. XDEFINES:    Makefile
  186. X    echo "" $(DEFINES) > DEFINES
  187. X
  188. Xserver/Makefile:    Makefile server/Makefile_$(VERSION)
  189. X    cd server; cp Makefile_$(VERSION) Makefile; make depend
  190. X
  191. Xlib/Makefile:    Makefile lib/Makefile_$(VERSION)
  192. X    cd lib; cp Makefile_$(VERSION) Makefile; make depend
  193. X
  194. Xutility/Makefile:    Makefile utility/Makefile_$(VERSION)
  195. X    cd utility; cp Makefile_$(VERSION) Makefile; make depend
  196. !EOF!Makefile!
  197. echo x - utility/Makefile_4.2
  198. sed -e 's/^X//' > utility/Makefile_4.2 << '!EOF!utility/Makefile_4.2!'
  199. X#! /bin/make -f
  200. X#
  201. X#    uw utility makefile (4.2BSD)
  202. X#
  203. X#    INCDIR should be set to the directory containing header files.
  204. X#
  205. X#    LIBUW should be set to the name of the library file (or, if it is
  206. X#    installed in a system directory, "-luw").
  207. X#
  208. X#    Note: in order for "uwterm" to work on remote machines it is
  209. X#    necessary for it to be installed in a directly where "rsh"
  210. X#    will find it.  The #defined symbol UWTERM in the source can
  211. X#    be set to the desired absolute pathname, if necessary.
  212. X#
  213. X
  214. XINCDIR    =    ../h
  215. X
  216. XLIBUW    =    ../lib/libuw.a
  217. X
  218. XUWTOOL_OBJS =    uwtool.o
  219. XUWTITLE_OBJS =    uwtitle.o
  220. XUWTERM_OBJS =    uwterm.o
  221. XUWPLOT_OBJS =    uwplot.o
  222. X
  223. XOBJECTS    =    $(UWTOOL_OBJS) $(UWTITLE_OBJS) $(UWTERM_OBJS) $(UWPLOT_OBJS)
  224. X
  225. XSOURCES    =    `echo $(OBJECTS) | sed -e 's/\\.o/\\.c/g'`
  226. X
  227. XDEFINES    =    `cat ../DEFINES`
  228. X
  229. XCFLAGS    =    -O -I$(INCDIR) $(DEFINES)
  230. XLFLAGS    =
  231. X
  232. Xall:        uwtool uwtitle uwterm uwplot
  233. X
  234. Xuwtool:        $(UWTOOL_OBJS)
  235. X    $(CC) -o $@ $(LFLAGS) $(UWTOOL_OBJS) $(LIBUW)
  236. X
  237. Xuwtitle:    $(UWTITLE_OBJS)
  238. X    $(CC) -o $@ $(LFLAGS) $(UWTITLE_OBJS) $(LIBUW)
  239. X
  240. Xuwterm:        $(UWTERM_OBJS)
  241. X    $(CC) -o $@ $(LFLAGS) $(UWTERM_OBJS) $(LIBUW)
  242. X
  243. Xuwplot:        $(UWPLOT_OBJS)
  244. X    $(CC) -o $@ $(LFLAGS) $(UWPLOT_OBJS) $(LIBUW)
  245. X
  246. Xlint:
  247. X    for src in $(SOURCES); \
  248. X    do echo $$src:; lint -hubx -I$(INCDIR) $(DEFINES) $$src; done
  249. X
  250. Xtags:
  251. X    ctags $(SOURCES)
  252. X
  253. Xdepend: 
  254. X    grep '^#include' $(SOURCES) | \
  255. X    sed -e '/</d' \
  256. X        -e 's/:[^"]*"\([^"]*\)".*/: ..\/h\/\1/' \
  257. X        -e 's,^../[a-zA-Z0-9]*/\([^\.]*\)\.[cs],\1.o \1.L,' | \
  258. X    awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
  259. X        else { if (length(rec $$3) > 78) { print rec; rec = $$0; } \
  260. X               else rec = rec " " $$3 } } \
  261. X          END { print rec } ' > makedep
  262. X    echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
  263. X    echo '$$r makedep' >>eddep
  264. X    echo 'w' >>eddep
  265. X    cp Makefile Makefile.bak
  266. X    ex - Makefile < eddep
  267. X    rm eddep makedep
  268. X
  269. Xclean:
  270. X    -rm -f *.o
  271. X
  272. X# DO NOT DELETE THIS LINE (or the following blank line) -- make depend uses it
  273. X
  274. !EOF!utility/Makefile_4.2!
  275. echo x - utility/Makefile_4.3
  276. sed -e 's/^X//' > utility/Makefile_4.3 << '!EOF!utility/Makefile_4.3!'
  277. X#! /bin/make -f
  278. X#
  279. X#    uw utility makefile (4.3BSD)
  280. X#
  281. X#    INCDIR should be set to the directory containing header files.
  282. X#
  283. X#    LIBUW should be set to the name of the library file (or, if it is
  284. X#    installed in a system directory, "-luw").
  285. X#
  286. X#    Note: in order for "uwterm" to work on remote machines it is
  287. X#    necessary for it to be installed in a directly where "rsh"
  288. X#    will find it.  The #defined symbol UWTERM in the source can
  289. X#    be set to the desired absolute pathname, if necessary.
  290. X#
  291. X
  292. XINCDIR    =    ../h
  293. X
  294. XLIBUW    =    ../lib/libuw.a
  295. X
  296. XUWTOOL_OBJS =    uwtool.o
  297. XUWTITLE_OBJS =    uwtitle.o
  298. XUWTERM_OBJS =    uwterm.o
  299. XUWPLOT_OBJS =    uwplot.o
  300. X
  301. XOBJECTS    =    $(UWTOOL_OBJS) $(UWTITLE_OBJS) $(UWTERM_OBJS) $(UWPLOT_OBJS)
  302. X
  303. XSOURCES    =    `echo $(OBJECTS) | sed -e 's/\\.o/\\.c/g'`
  304. X
  305. XDEFINES    =    `cat ../DEFINES`
  306. X
  307. XCFLAGS    =    -O -I$(INCDIR) $(DEFINES)
  308. XLFLAGS    =
  309. X
  310. Xall:        uwtool uwtitle uwterm uwplot
  311. X
  312. Xuwtool:        $(UWTOOL_OBJS)
  313. X    $(CC) -o $@ $(LFLAGS) $(UWTOOL_OBJS) $(LIBUW)
  314. X
  315. Xuwtitle:    $(UWTITLE_OBJS)
  316. X    $(CC) -o $@ $(LFLAGS) $(UWTITLE_OBJS) $(LIBUW)
  317. X
  318. Xuwterm:        $(UWTERM_OBJS)
  319. X    $(CC) -o $@ $(LFLAGS) $(UWTERM_OBJS) $(LIBUW)
  320. X
  321. Xuwplot:        $(UWPLOT_OBJS)
  322. X    $(CC) -o $@ $(LFLAGS) $(UWPLOT_OBJS) $(LIBUW)
  323. X
  324. Xlint:
  325. X    for src in $(SOURCES); \
  326. X    do echo $$src:; lint -hubx -I$(INCDIR) $(DEFINES) $$src; done
  327. X
  328. Xtags:
  329. X    ctags $(SOURCES)
  330. X
  331. Xdepend: 
  332. X    $(CC) -M -I$(INCDIR) $(DEFINES) $(SOURCES) | \
  333. X    sed -e ':loop' \
  334. X        -e 's/\.\.\/[^ /]*\/\.\./../' \
  335. X        -e 't loop' | \
  336. X    awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
  337. X        else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
  338. X               else rec = rec " " $$2 } } \
  339. X          END { print rec } ' >> makedep
  340. X    echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
  341. X    echo '$$r makedep' >>eddep
  342. X    echo 'w' >>eddep
  343. X    cp Makefile Makefile.bak
  344. X    ex - Makefile < eddep
  345. X    rm eddep makedep
  346. X
  347. Xclean:
  348. X    -rm -f *.o
  349. X
  350. X# DO NOT DELETE THIS LINE (or the following blank line) -- make depend uses it
  351. X
  352. !EOF!utility/Makefile_4.3!
  353. echo x - utility/uwplot.c
  354. sed -e 's/^X//' > utility/uwplot.c << '!EOF!utility/uwplot.c!'
  355. X/*
  356. X *    uwplot
  357. X *
  358. X * Copyright 1986 by John D. Bruner.  All rights reserved.  Permission to
  359. X * copy this program is given provided that the copy is not sold and that
  360. X * this copyright notice is included.
  361. X */
  362. X
  363. X#include <sys/types.h>
  364. X#include <sys/socket.h>
  365. X#include <netinet/in.h>
  366. X#include <sys/signal.h>
  367. X#include <sys/errno.h>
  368. X#include <ctype.h>
  369. X#include <stdio.h>
  370. X
  371. X#include "uwlib.h"
  372. X
  373. Xchar *argv0;
  374. XUWIN uwin;
  375. X
  376. Xmain(argc, argv)
  377. Xchar **argv;
  378. X{
  379. X    register int c, len;
  380. X    register char *cp;
  381. X    register char *title;
  382. X    register struct sockaddr_in *sin;
  383. X    auto struct sockaddr_in sa;
  384. X    auto char buf[4096];
  385. X    extern char *optarg;
  386. X    extern int errno;
  387. X    extern onintr();
  388. X
  389. X    /*
  390. X     * Options which are recognized directly are:
  391. X     *
  392. X     *    -ninet    connect to server at address "inet"
  393. X     *    -ttitle    label window with "title" (default is argv[0])
  394. X     */
  395. X    argv0 = argv[0];
  396. X    sin = (struct sockaddr_in *)0;
  397. X    title = argv0;
  398. X    while ((c = getopt(argc, argv, "n:t:")) != EOF) {
  399. X        switch (c) {
  400. X        case 'n':
  401. X            sa.sin_family = AF_INET;
  402. X            sa.sin_addr.s_addr = 0;
  403. X            sa.sin_port = 0;
  404. X            bzero(sa.sin_zero, sizeof sa.sin_zero);
  405. X            for (cp=optarg; isxdigit(c = *cp); cp++) {
  406. X                /* Pyramid compiler botch */
  407. X                /* sa.sin_addr.s_addr *= 16; */
  408. X                sa.sin_addr.s_addr <<= 4;
  409. X                if (isdigit(c))
  410. X                    sa.sin_addr.s_addr += c - '0';
  411. X                else if (islower(c))
  412. X                    sa.sin_addr.s_addr += c-'a' + 10;
  413. X                else
  414. X                    sa.sin_addr.s_addr += c-'A' + 10;
  415. X            }
  416. X            if (c == '.')
  417. X                for (cp++; isdigit(c = *cp); cp++)
  418. X                    sa.sin_port = sa.sin_port*10 + c-'0';
  419. X            if (sa.sin_addr.s_addr == 0 || sa.sin_port == 0) {
  420. X                fprintf(stderr,
  421. X                    "%s: bad Internet address: %s\n",
  422. X                    argv0, optarg);
  423. X                return(1);
  424. X            }
  425. X            sa.sin_addr.s_addr = htonl(sa.sin_addr.s_addr);
  426. X            sa.sin_port = htons(sa.sin_port);
  427. X            sin = &sa;
  428. X            break;
  429. X        case 't':
  430. X            title = optarg;
  431. X            break;
  432. X        }
  433. X    }
  434. X
  435. X    /*
  436. X     * Catch hangup, interrupt, quit, and termination signals.  Kill
  437. X     * the window if one of these is received.
  438. X     */
  439. X    (void)signal(SIGHUP, onintr);
  440. X    (void)signal(SIGINT, onintr);
  441. X    (void)signal(SIGQUIT, onintr);
  442. X    (void)signal(SIGTERM, onintr);
  443. X
  444. X    /*
  445. X     * Create a new plot window, title it, and make it visible.
  446. X     */
  447. X    if ((uwin = uw_new(UWT_PLOT, sin)) == (UWIN)0) {
  448. X        uw_perror(argv[0], uwerrno, errno);
  449. X        return(1);
  450. X    }
  451. X    (void)uw_stitle(uwin, title);
  452. X    (void)uw_svis(uwin, 1);
  453. X
  454. X    /*
  455. X     * Copy the standard input to the plot window.
  456. X     */
  457. X    while ((len = read(0, buf, sizeof buf)) > 0 ||
  458. X        (len < 0 && errno == EINTR)) {
  459. X        if (len > 0)
  460. X            (void)write(UW_DATAFD(uwin), buf, len);
  461. X    }
  462. X
  463. X    /*
  464. X     * This is something of a hack.  We don't expect to be able to
  465. X     * read anything from the window.  The read will hang until the
  466. X     * window is killed.
  467. X     */
  468. X    while ((len = read(UW_DATAFD(uwin), buf, sizeof buf)) > 0 ||
  469. X        len < 0 && errno == EINTR)
  470. X        ;
  471. X    return(0);
  472. X}
  473. X
  474. Xonintr()
  475. X{
  476. X    uw_kill(uwin);
  477. X    exit(0);
  478. X}
  479. !EOF!utility/uwplot.c!
  480. echo x - utility/uwterm.c
  481. sed -e 's/^X//' > utility/uwterm.c << '!EOF!utility/uwterm.c!'
  482. X/*
  483. X *    uwterm
  484. X *
  485. X * Copyright 1986 by John D. Bruner.  All rights reserved.  Permission to
  486. X * copy this program is given provided that the copy is not sold and that
  487. X * this copyright notice is included.
  488. X */
  489. X#include <sys/types.h>
  490. X#include <sys/file.h>
  491. X#include <sys/ioctl.h>
  492. X#include <sys/socket.h>
  493. X#include <sys/time.h>
  494. X#include <sys/resource.h>
  495. X#include <sys/wait.h>
  496. X#include <netinet/in.h>
  497. X#include <signal.h>
  498. X#include <strings.h>
  499. X#include <ctype.h>
  500. X#include <errno.h>
  501. X#include <stdio.h>
  502. X
  503. X#include "openpty.h"
  504. X#include "uwlib.h"
  505. X
  506. X#ifndef UWTERM
  507. X#define    UWTERM    "uwterm"
  508. X#endif
  509. X
  510. X#define    CTL(c)        ((c)&037)
  511. X
  512. X#ifndef FD_SET
  513. X/* 4.2 retrofit: better definitions for these are in 4.3BSD's <sys/types.h> */
  514. X#define    FD_SET(n,p)    ((p)->fds_bits[0] |= (1 << (n)))
  515. X#define    FD_CLR(n,p)    ((p)->fds_bits[0] &= ~(1 << (n)))
  516. X#define    FD_ISSET(n,p)    ((p)->fds_bits[0] & (1 << (n)))
  517. X#define    FD_ZERO(p)    ((p)->fds_bits[0] = 0)
  518. X#define    FD_SETSIZE    (NBBY*sizeof(long))
  519. X#endif
  520. X
  521. Xextern int optind;
  522. Xextern char *optarg;
  523. Xextern char *getenv();
  524. Xextern char *malloc();
  525. Xextern deadkid();
  526. Xextern int errno;
  527. X
  528. X#ifndef htons
  529. X/* These should have been defined in <netinet/in.h>, but weren't (in 4.2BSD) */
  530. Xextern unsigned short htons(), ntohs();
  531. Xextern unsigned long htonl(), ntohl();
  532. X#endif
  533. X
  534. Xchar *argv0;
  535. X
  536. Xmain(argc, argv)
  537. Xint argc;
  538. Xchar **argv;
  539. X{
  540. X    register char *cp;
  541. X    register int c;
  542. X    int wflag;
  543. X    uwtype_t wtype;
  544. X    char *term, *title, *server, *login;
  545. X    struct sockaddr_in sa, *sin;
  546. X    char hostname[32];
  547. X
  548. X    /*
  549. X     * If called with no arguments, create a new window using the
  550. X     * current shell according to the SHELL environment variable
  551. X     * (or "/bin/sh" if that doesn't exist).
  552. X     *
  553. X     * Options which are recognized directly are:
  554. X     *
  555. X     *    -ninet    connect to server at address "inet"
  556. X     *    -wtype    create window with emulation "type"
  557. X     *    -ttitle    label window with "title"
  558. X     *    -llogin    use login name "login" on remote machine
  559. X     *
  560. X     * If no explicit title is specified, the command name is used.
  561. X     */
  562. X    argv0 = argv[0];
  563. X    sin = (struct sockaddr_in *)0;
  564. X    server = (char *)0;
  565. X    login = (char *)0;
  566. X    title = (char *)0;
  567. X    wflag = 0;
  568. X    term = (char *)0;
  569. X    while ((c = getopt(argc, argv, "l:n:t:w:")) != EOF) {
  570. X        switch (c) {
  571. X        case 'l':
  572. X            if (optarg[0] == '\0') {
  573. X                fprintf(stderr,
  574. X                    "%s: \"-l\" requires user name\n", argv0);
  575. X            } else
  576. X                login = optarg;
  577. X            break;
  578. X        case 'n':
  579. X            server = optarg;
  580. X            sa.sin_family = AF_INET;
  581. X            sa.sin_addr.s_addr = 0;
  582. X            sa.sin_port = 0;
  583. X            bzero(sa.sin_zero, sizeof sa.sin_zero);
  584. X            for (cp=optarg; isxdigit(c = *cp); cp++) {
  585. X                /* Pyramid compiler botch */
  586. X                /* sa.sin_addr.s_addr *= 16; */
  587. X                sa.sin_addr.s_addr <<= 4;
  588. X                if (isdigit(c))
  589. X                    sa.sin_addr.s_addr += c - '0';
  590. X                else if (islower(c))
  591. X                    sa.sin_addr.s_addr += c-'a' + 10;
  592. X                else
  593. X                    sa.sin_addr.s_addr += c-'A' + 10;
  594. X            }
  595. X            if (c == '.')
  596. X                for (cp++; isdigit(c = *cp); cp++)
  597. X                    sa.sin_port = sa.sin_port*10 + c-'0';
  598. X            if (sa.sin_addr.s_addr == 0 || sa.sin_port == 0) {
  599. X                fprintf(stderr,
  600. X                    "%s: bad Internet address: %s\n",
  601. X                    argv0, optarg);
  602. X                return(1);
  603. X            }
  604. X            sa.sin_addr.s_addr = htonl(sa.sin_addr.s_addr);
  605. X            sa.sin_port = htons(sa.sin_port);
  606. X            sin = &sa;
  607. X            break;
  608. X        case 'w':
  609. X            wflag++;
  610. X            term = optarg;
  611. X            wtype = uw_ttype(optarg);
  612. X            break;
  613. X        case 't':
  614. X            title = optarg;
  615. X            break;
  616. X        }
  617. X    }
  618. X
  619. X    gethostname(hostname, sizeof hostname);
  620. X    if (title == (char *)0) {
  621. X        /*
  622. X         * If there was no "-t" argument, then "title" will still
  623. X         * be NULL.  In this case we use the host name.
  624. X         */
  625. X        if (optind == argc)
  626. X            title = hostname;
  627. X        else
  628. X            title = argv[optind];
  629. X    }
  630. X    
  631. X    if (!term) {
  632. X        /*
  633. X         * If there was no "-w" argument, fetch the window
  634. X         * type from the environment.  If that fails, use
  635. X         * a default.
  636. X         */
  637. X        if ((term=getenv("TERM")) != (char *)0)
  638. X            wtype = uw_ttype(term);
  639. X        else
  640. X            wtype = UWT_ADM31;
  641. X    }
  642. X
  643. X    if (optind == argc-1) {
  644. X        /*
  645. X         * The remaining argument is the host name.  Fork an "rsh"
  646. X         * to execute this on the remote machine.
  647. X         */
  648. X        return(doremote(argv[optind], server, title, term, login));
  649. X    } else if (optind == argc) {
  650. X        /*
  651. X         * There are no other arguments.  Set up the connection
  652. X         * to this machine.
  653. X         */
  654. X        return(dolocal(sin, title, wtype, term));
  655. X    } else {
  656. X        fprintf(stderr,
  657. X            "Usage: \"%s [-ttitle] [-wtype] [-naddr] [-llogin] host\"\n",
  658. X            argv0);
  659. X        return(1);
  660. X    }
  661. X}
  662. X
  663. Xdoremote(host, server, title, term, login)
  664. Xchar *host;
  665. Xchar *server;
  666. Xchar *title;
  667. Xchar *term;
  668. Xchar *login;
  669. X{
  670. X    register int fd, i, pid;
  671. X    register char *cp;
  672. X    char *av[16];
  673. X
  674. X    /*
  675. X     * Invoke a remote "uwterm" via "rsh".
  676. X     */
  677. X    i = 0;
  678. X    av[i++] = "rsh";
  679. X    av[i++] = host;
  680. X    av[i++] = "-n";
  681. X    if (login != NULL) {
  682. X        av[i++] = "-l";
  683. X        av[i++] = login;
  684. X    }
  685. X    av[i++] = UWTERM;
  686. X    if (server == (char *)0) {
  687. X        if ((server = getenv("UW_INET")) == (char *)0) {
  688. X            fprintf(stderr,"%s: Can't find window server\n",argv0);
  689. X            return(1);
  690. X        }
  691. X    }
  692. X    if ((cp = malloc(3+strlen(server))) == (char *)0) {
  693. X        fprintf(stderr, "%s: out of memory\n", argv0);
  694. X        return(1);
  695. X    }
  696. X    (void)strcat(strcpy(cp, "-n"), server);
  697. X    av[i++] = cp;
  698. X
  699. X    if (title != (char *)0) {
  700. X        if ((cp = malloc(3+strlen(title))) == (char *)0) {
  701. X            fprintf(stderr, "%s: out of memory\n", argv0);
  702. X            return(1);
  703. X        }
  704. X        (void)strcat(strcpy(cp, "-t"), title);
  705. X        av[i++] = cp;
  706. X    }
  707. X
  708. X    if (term != (char *)0) {
  709. X        if ((cp = malloc(3+strlen(term))) == (char *)0) {
  710. X            fprintf(stderr, "%s: out of memory\n", argv0);
  711. X            return(1);
  712. X        }
  713. X        (void)strcat(strcpy(cp, "-w"), term);
  714. X        av[i++] = cp;
  715. X    }
  716. X
  717. X    av[i] = (char *)0;
  718. X
  719. X    for (fd=getdtablesize()-1; fd > 2; fd--)
  720. X        (void)fcntl(fd, F_SETFD, 1);
  721. X    (void)execvp(av[0], av);
  722. X    (void)execv("/usr/ucb/rsh", av);    /* last-ditch try */
  723. X    perror(av[0]);
  724. X    return(1);
  725. X}
  726. X
  727. X            
  728. Xdolocal(sin, title, wtype, term)
  729. Xstruct sockaddr_in *sin;
  730. Xchar *title;
  731. Xuwtype_t wtype;
  732. Xchar *term;
  733. X{
  734. X    register UWIN uwin;
  735. X    register int fd;
  736. X    register int s;
  737. X    struct ptydesc pt;
  738. X
  739. X    /*
  740. X     * Create and initialize a pseudo-terminal.
  741. X     */
  742. X    if (openpty(&pt) < 0) {
  743. X        fprintf(stderr, "No pseudo-terminals are available\n");
  744. X        return(1);
  745. X    }
  746. X    ttyinit(pt.pt_tfd);
  747. X
  748. X
  749. X    /*
  750. X     * Make fd's 0 and 1 be "/dev/null".  We'd like to force a known
  751. X     * definition for fd 2 at this point, but we may need it for
  752. X     * uw_perror() if uw_new() fails.
  753. X     */
  754. X    if ((fd = open("/dev/null", O_RDWR)) >= 0) {    /* should be zero */
  755. X        if (fd != 0 && pt.pt_tfd != 0 && pt.pt_pfd != 0)
  756. X            dup2(fd, 0);
  757. X        if (fd != 1 && pt.pt_tfd != 1 && pt.pt_pfd != 1)
  758. X            dup2(fd, 1);
  759. X        if (fd > 2)
  760. X            (void)close(fd);
  761. X    }
  762. X
  763. X    /*
  764. X     * Create and title the window.  Make it visible.
  765. X     */
  766. X    if ((uwin = uw_new(wtype, sin)) == (UWIN)0) {
  767. X        uw_perror(argv0, uwerrno, errno);
  768. X        return(1);
  769. X    }
  770. X    (void)uw_stitle(uwin, title);
  771. X    (void)uw_svis(uwin, 1);
  772. X
  773. X    /*
  774. X     * We no longer have use for fd 2, so make it "/dev/null" (the
  775. X     * same as fd 0.
  776. X     */
  777. X    (void)dup2(0, 2);
  778. X
  779. X    /*
  780. X     * Adjust the environment to contain the correct values of TERM,
  781. X     * UW_ID, and UW_INET.  These will be inherited by the child
  782. X     * we will create next.
  783. X     */
  784. X    adjenv(term, sin, UW_ID(uwin));
  785. X
  786. X    /*
  787. X     * Create a process to execute the command connected to the pty.
  788. X     */
  789. X    runcmd(pt.pt_tfd, pt.pt_tname);
  790. X
  791. X    /*
  792. X     * Ignore signals that might cause us trouble.  We do NOT ignore
  793. X     * SIGTSTP so that the user can move us from the foreground into
  794. X     * the background if desired.
  795. X     */
  796. X    signal(SIGINT, SIG_IGN);
  797. X    signal(SIGQUIT, SIG_IGN);
  798. X    signal(SIGCHLD, deadkid);
  799. X
  800. X#if defined(TIOCSWINSZ) || defined(TIOCSSIZE)
  801. X    /*
  802. X     * Install an option handling routine to catch window size
  803. X     * changes from the Mac and make the appropriate changes to
  804. X     * the pseudo-terminal.
  805. X     */
  806. X    setresize(uwin, pt.pt_pfd);
  807. X#endif
  808. X
  809. X    /*
  810. X     * Close the slave side of the pty.  Copy data between the pty
  811. X     * and the window.  The return value from copy() is the exit
  812. X     * status.
  813. X     */
  814. X    (void)close(pt.pt_tfd);
  815. X    s = copy(pt.pt_pfd, UW_DATAFD(uwin));
  816. X    uw_kill(uwin);
  817. X    return(s);
  818. X}
  819. X
  820. Xttyinit(ptyfd)
  821. Xregister int ptyfd;
  822. X{
  823. X    register int ttyfd;
  824. X    struct sgttyb sg;
  825. X    struct tchars tc;
  826. X    struct ltchars ltc;
  827. X    int ldisc;
  828. X    int lmode;
  829. X
  830. X    /*
  831. X     * Initialize the modes of the terminal whose file descriptor
  832. X     * is "ptyfd" to the same modes as the current terminal.  If there
  833. X     * isn't a "current terminal" handy, then use hardcoded defaults.
  834. X     */
  835. X    for (ttyfd=0; ttyfd < 3 && ioctl(ttyfd, TIOCGETD, &ldisc) < 0; ttyfd++)
  836. X        ;
  837. X    if (ttyfd < 3) {
  838. X        (void)ioctl(ttyfd, TIOCGETP, &sg);
  839. X        (void)ioctl(ttyfd, TIOCGETC, &tc);
  840. X        (void)ioctl(ttyfd, TIOCGLTC, <c);
  841. X        (void)ioctl(ttyfd, TIOCLGET, &lmode);
  842. X    } else {
  843. X        ldisc = NTTYDISC;
  844. X
  845. X        sg.sg_ispeed = sg.sg_ospeed = 13; /* doesn't really matter */
  846. X        sg.sg_erase = 0177;    /* ugh */
  847. X        sg.sg_kill = CTL('u');    /* ugh */
  848. X        sg.sg_flags = ECHO|CRMOD|ANYP;
  849. X
  850. X        tc.t_intrc = CTL('c');    /* yuck, should be 0177 */
  851. X        tc.t_quitc = CTL('\\');
  852. X        tc.t_startc = CTL('q');
  853. X        tc.t_stopc = CTL('s');
  854. X        tc.t_eofc = CTL('d');
  855. X        tc.t_brkc = -1;
  856. X
  857. X        ltc.t_suspc = CTL('z');
  858. X        ltc.t_dsuspc = CTL('y');
  859. X        ltc.t_rprntc = CTL('r');
  860. X        ltc.t_flushc = CTL('o');
  861. X        ltc.t_werasc = CTL('w');
  862. X        ltc.t_lnextc = CTL('v');
  863. X
  864. X        lmode = LCRTBS|LCRTERA|LCRTKIL|LCTLECH;
  865. X    }
  866. X    (void)ioctl(ptyfd, TIOCSETD, &ldisc);
  867. X    (void)ioctl(ptyfd, TIOCSETP, &sg);
  868. X    (void)ioctl(ptyfd, TIOCSETC, &tc);
  869. X    (void)ioctl(ptyfd, TIOCSLTC, <c);
  870. X    (void)ioctl(ptyfd, TIOCLSET, &lmode);
  871. X}
  872. X
  873. Xadjenv(term, sin, wid)
  874. Xchar *term;
  875. Xstruct sockaddr_in *sin;
  876. Xuwid_t wid;
  877. X{
  878. X    char *env[4];
  879. X    static char ttype[sizeof "TERM=" + 16];
  880. X    static char inet[sizeof INET_ENV + 16];
  881. X    static char idstr[sizeof "UW_ID=" + 20];
  882. X
  883. X    /*
  884. X     * Redefine the environment variable UW_ID.  Redefine UW_INET
  885. X     * if "sin" is non-NULL.  Redefine TERM.
  886. X     */
  887. X    (void)sprintf(ttype, "TERM=%.15s", term);
  888. X    env[0] = ttype;
  889. X    
  890. X    (void)sprintf(idstr, "UW_ID=%ld", wid);
  891. X    env[1] = idstr;
  892. X
  893. X    if (sin != NULL) {
  894. X        (void)sprintf(inet, "%s=%08lx.%d", INET_ENV,
  895. X            ntohl(sin->sin_addr.s_addr), ntohs(sin->sin_port));
  896. X        env[2] = inet;
  897. X        env[3] = (char *)0;
  898. X    }  else
  899. X        env[2] = (char *)0;
  900. X    env_set(env);
  901. X}
  902. X
  903. Xruncmd(fd, tname)
  904. Xint fd;
  905. Xchar *tname;
  906. X{
  907. X    register int pid;
  908. X    register char *shell;
  909. X
  910. X    /*
  911. X     * Figure out the name of the user's shell.  If unknown,
  912. X     * use a default.
  913. X     */
  914. X    if ((shell = getenv("SHELL")) == (char *)0)
  915. X        shell = "/bin/sh";
  916. X
  917. X    /*
  918. X     * Fork a new process and attach "fd" to fd's 0, 1, and 2 of
  919. X     * that new process.  Disassociate the current controlling
  920. X     * terminal and attach the new one (whose name is "tname").
  921. X     */
  922. X    while ((pid = fork()) < 0)
  923. X        sleep(5);
  924. X    if (pid == 0) {
  925. X        if (fd != 0)
  926. X            dup2(fd, 0);
  927. X        if (fd != 1)
  928. X            dup2(fd, 1);
  929. X        if (fd != 2)
  930. X            dup2(fd, 2);
  931. X        if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
  932. X            (void)ioctl(fd, TIOCNOTTY, (char *)0);
  933. X            (void)close(fd);
  934. X        } else
  935. X            setpgrp(0, 0);
  936. X        (void)open(tname, O_RDWR);
  937. X        for (fd=getdtablesize()-1; fd > 2; fd--)
  938. X            (void)fcntl(fd, F_SETFD, 1);
  939. X        execlp(shell, "-", (char *)0);
  940. X        execl(shell, "-", (char *)0);
  941. X        _exit(1);
  942. X    }
  943. X}
  944. X
  945. Xcopy(fd1, fd2)
  946. Xint fd1, fd2;
  947. X{
  948. X    struct fdinfo {
  949. X        int    fi_fd;        /* associated file descriptor */
  950. X        int    fi_size;    /* amount of data in buffer */
  951. X        char    *fi_ptr;    /* pointer to data in fi_buf */
  952. X        char    fi_buf[1024];
  953. X    };
  954. X    register struct fdinfo *fi, *fo;
  955. X    register int n, nfds, len;
  956. X    struct fdinfo fdinfo[2];
  957. X    struct fd_set rdmask[2], wtmask[2], exmask[2];
  958. X    struct timeval tv;
  959. X
  960. X    /*
  961. X     * Copy data between file descriptors fd1 and fd2.  Return when an
  962. X     * EOF is read or an I/O error (other than an interrupted system
  963. X     * call or non-blocking I/O message) is encountered.
  964. X     */
  965. X    FD_ZERO(&rdmask[1]);
  966. X    FD_ZERO(&wtmask[1]);
  967. X    FD_ZERO(&exmask[1]);
  968. X
  969. X    fdinfo[0].fi_fd = fd1;
  970. X    fdinfo[0].fi_size = 0;
  971. X    fdinfo[1].fi_fd = fd2;
  972. X    fdinfo[1].fi_size = 0;
  973. X
  974. X    FD_SET(fd1, &rdmask[1]);
  975. X    FD_SET(fd2, &rdmask[1]);
  976. X
  977. X    (void)fcntl(fd1, F_SETFL, FNDELAY);
  978. X    (void)fcntl(fd2, F_SETFL, FNDELAY);
  979. X
  980. X    nfds = ((fd1 > fd2) ? fd1 : fd2) + 1;
  981. X
  982. X    while (1) {
  983. X        rdmask[0] = rdmask[1];
  984. X        wtmask[0] = wtmask[1];
  985. X        exmask[0] = exmask[1];
  986. X        errno = 0;
  987. X        if (fdinfo[0].fi_size != 0 || fdinfo[1].fi_size != 0) {
  988. X            /*
  989. X             * Select does not work correctly for writes on
  990. X             * some machines, so we must fake it.  If a write
  991. X             * is pending, we time out after 1/50 second and
  992. X             * pretend that select told us that writes could
  993. X             * now be performed.  The code below will do the
  994. X             * correct thing if the write would still block.
  995. X             */
  996. X            tv.tv_sec = 0;
  997. X            tv.tv_usec = 1000000 / 50;
  998. X            n = select(nfds, rdmask, wtmask, exmask, &tv);
  999. X            wtmask[0] = wtmask[1];
  1000. X        } else
  1001. X            n = select(nfds, rdmask, wtmask, exmask, (struct timeval *)0);
  1002. X        if (n < 0 && errno == EINTR) {
  1003. X            continue;
  1004. X        } else if (n <= 0) {
  1005. X            perror("select");
  1006. X            return(1);
  1007. X        }
  1008. X        for (fi=fdinfo; fi < fdinfo+2; fi++) {
  1009. X            fo = fdinfo + !(fi - fdinfo);
  1010. X            if (FD_ISSET(fi->fi_fd, rdmask)) {
  1011. X                /* data available for reading */
  1012. X                len = read(fi->fi_fd, fi->fi_buf,
  1013. X                    sizeof fi->fi_buf);
  1014. X                if (len > 0) {
  1015. X                    fi->fi_size = len;
  1016. X                    fi->fi_ptr = fi->fi_buf;
  1017. X                    FD_CLR(fi->fi_fd, &rdmask[1]);
  1018. X                    FD_SET(fo->fi_fd, &wtmask[1]);
  1019. X                    FD_SET(fo->fi_fd, &wtmask[0]);
  1020. X                } else if (len == 0) {
  1021. X                    /* EOF, exit */
  1022. X                    return(0);
  1023. X                } else if (errno != EWOULDBLOCK &&
  1024. X                    errno != EINTR) {
  1025. X                    /* error, exit */
  1026. X                    return(1);
  1027. X                }
  1028. X            }
  1029. X            if (FD_ISSET(fo->fi_fd, wtmask)) {
  1030. X                /* data ready for writing */
  1031. X                errno = 0;
  1032. X                len = write(fo->fi_fd, fi->fi_ptr, fi->fi_size);
  1033. X                if (len > 0) {
  1034. X                    fi->fi_ptr += len;
  1035. X                    fi->fi_size -= len;
  1036. X                    if (fi->fi_size == 0) {
  1037. X                        FD_SET(fi->fi_fd, &rdmask[1]);
  1038. X                        FD_CLR(fo->fi_fd, &wtmask[1]);
  1039. X                    }
  1040. X                } else if (errno != EWOULDBLOCK &&
  1041. X                    errno != EINTR) {
  1042. X                    /* error, exit */
  1043. X                    return(1);
  1044. X                }
  1045. X            }
  1046. X        }
  1047. X    }
  1048. X}
  1049. X
  1050. Xdeadkid()
  1051. X{
  1052. X    register int pid;
  1053. X
  1054. X    /*
  1055. X     * Collect dead children.  Don't bother with their exit status
  1056. X     * or resource usage.
  1057. X     */
  1058. X    while ((pid = wait3((union wait *)0, WNOHANG, (struct rusage *)0)) > 0)
  1059. X        ;
  1060. X}
  1061. X
  1062. X#if defined(TIOCSWINSZ) || defined(TIOCSSIZE)
  1063. Xstatic int ptyfd;
  1064. X
  1065. X#ifdef TIOCSWINSZ
  1066. Xstatic struct winsize winsz;
  1067. X
  1068. Xvoid
  1069. Xdoresize(uwin, optnum, optcmd, uwoptval)
  1070. XUWIN uwin;
  1071. Xuwopt_t optnum;
  1072. Xuwoptcmd_t optcmd;
  1073. Xunion uwoptval *uwoptval;
  1074. X{
  1075. X    uwtype_t wtype;
  1076. X
  1077. X    /*
  1078. X     * 4.3BSD-style window resizing
  1079. X     */
  1080. X    if (uw_gtype(uwin, &wtype) < 0)
  1081. X        wtype = UWT_ADM31;    /* probably wrong to do this here */
  1082. X    if (optcmd == UWOC_SET) {
  1083. X        switch (optnum) {
  1084. X        case UWOP_WSIZE:
  1085. X            winsz.ws_ypixel = uwoptval->uwov_point.v;
  1086. X            winsz.ws_xpixel = uwoptval->uwov_point.h;
  1087. X            break;
  1088. X        case UWOP_TSIZE:
  1089. X            if (wtype <= UWT_ANSI) {
  1090. X                winsz.ws_row = uwoptval->uwov_point.v;
  1091. X                winsz.ws_col = uwoptval->uwov_point.h;
  1092. X            }
  1093. X            break;
  1094. X        }
  1095. X        if (wtype <= UWT_ANSI &&
  1096. X            (optnum == UWOP_WSIZE || optnum == UWOP_TSIZE))
  1097. X            (void)ioctl(ptyfd, TIOCSWINSZ, &winsz);
  1098. X    }
  1099. X}
  1100. X
  1101. Xsetresize(uwin, fd)
  1102. XUWIN uwin;
  1103. Xint fd;
  1104. X{
  1105. X    struct uwpoint pt;
  1106. X    uwtype_t wtype;
  1107. X
  1108. X    /*
  1109. X     * Set up the option-handling routine "doresize".
  1110. X     */
  1111. X    ptyfd = fd;
  1112. X    uw_optfn(uwin, UWOP_TSIZE, doresize);
  1113. X    uw_optfn(uwin, UWOP_WSIZE, doresize);
  1114. X    winsz.ws_row = 24;    /* default to standard terminal size */
  1115. X    winsz.ws_col = 80;
  1116. X    if (uw_gwsize(uwin, &pt) == 0) {
  1117. X        winsz.ws_ypixel = pt.uwp_v;
  1118. X        winsz.ws_xpixel = pt.uwp_h;
  1119. X    } else {
  1120. X        /* make up something plausible */
  1121. X        winsz.ws_ypixel = 8 * winsz.ws_row;
  1122. X        winsz.ws_xpixel = 8 * winsz.ws_col;
  1123. X    }
  1124. X
  1125. X    if (uw_gtype(uwin, &wtype) == 0 && wtype <= UWT_ANSI)
  1126. X        (void)uw_optcmd(uwin, UWOP_TSIZE, UWOC_DO, (union uwoptval *)0);
  1127. X}
  1128. X
  1129. X#else
  1130. X#ifdef TIOCSSIZE
  1131. Xvoid
  1132. Xdoresize(uwin, optnum, optcmd, uwoptval)
  1133. XUWIN uwin;
  1134. Xuwopt_t optnum;
  1135. Xuwoptcmd_t optcmd;
  1136. Xunion uwoptval *uwoptval;
  1137. X{
  1138. X    struct ttysize ts;
  1139. X    uwtype_t wtype;
  1140. X
  1141. X    /*
  1142. X     * Sun-style window resizing
  1143. X     */
  1144. X    if (uw_gtype(uwin, &wtype) < 0)
  1145. X        wtype = UWT_ADM31;    /* probably wrong to do this here */
  1146. X    if (wtype <= UWT_ANSI && optnum == UWOP_TSIZE && optcmd == UWOC_SET) {
  1147. X        ts.ts_lines = uwoptval->uwov_point.v;
  1148. X        ts.ts_cols = uwoptval->uwov_point.h;
  1149. X        (void)ioctl(ptyfd, TIOCSSIZE, &ts);
  1150. X    }
  1151. X}
  1152. X
  1153. Xsetresize(uwin, fd)
  1154. XUWIN uwin;
  1155. Xint fd;
  1156. X{
  1157. X    uwtype_t wtype;
  1158. X
  1159. X    /*
  1160. X     * Set up the option-handling routine "doresize".
  1161. X     */
  1162. X    ptyfd = fd;
  1163. X    uw_optfn(uwin, UWOP_TSIZE, doresize);
  1164. X
  1165. X    if (uw_gtype(uwin, &wtype) == 0 && wtype <= UWT_ANSI)
  1166. X        (void)uw_optcmd(uwin, UWOP_TSIZE, UWOC_DO, (union uwoptval *)0);
  1167. X}
  1168. X#endif
  1169. X#endif
  1170. X#endif
  1171. !EOF!utility/uwterm.c!
  1172. echo x - utility/uwtitle.c
  1173. sed -e 's/^X//' > utility/uwtitle.c << '!EOF!utility/uwtitle.c!'
  1174. X/*
  1175. X *    uwtitle
  1176. X *
  1177. X * Copyright 1986 by John D. Bruner.  All rights reserved.  Permission to
  1178. X * copy this program is given provided that the copy is not sold and that
  1179. X * this copyright notice is included.
  1180. X */
  1181. X#include <strings.h>
  1182. X#include <stdio.h>
  1183. X
  1184. X#include "uwlib.h"
  1185. X
  1186. Xextern char *optarg;
  1187. Xextern int optind;
  1188. Xextern int errno;
  1189. X
  1190. Xextern char *getenv();
  1191. Xextern long atol();
  1192. X
  1193. Xmain(argc, argv)
  1194. Xint argc;
  1195. Xchar **argv;
  1196. X{
  1197. X    register int c;
  1198. X    register char *cp, *cq, **av;
  1199. X    register uwid_t uwid;
  1200. X    char *argv0;
  1201. X    char *cqlimit;
  1202. X    union uwoptval uwoptval;
  1203. X
  1204. X    /*
  1205. X     * If called with no arguments, print a syntax message.  Otherwise,
  1206. X     * set the title of the current window to argv[1..argc-1].  The
  1207. X     * window ID is obtained from the environment or the "-i" argument.
  1208. X     */
  1209. X    argv0 = argv[0];
  1210. X    uwid = 0;
  1211. X    while ((c = getopt(argc, argv, "i:")) != EOF) {
  1212. X        switch (c) {
  1213. X        case 'i':
  1214. X            if ((uwid = atol(optarg)) == 0) {
  1215. X                fprintf(stderr,
  1216. X                    "%s: malformed \"-i\" argument\n", argv0);
  1217. X                return(1);
  1218. X            }
  1219. X            break;
  1220. X        }
  1221. X    }
  1222. X    if (optind >= argc) {
  1223. X        fprintf(stderr, "Syntax: \"%s [-iID] title ...\"\n", *argv);
  1224. X        return(1);
  1225. X    }
  1226. X
  1227. X    if (uwid == 0) {
  1228. X        if ((cp = getenv("UW_ID")) == NULL) {
  1229. X            fprintf(stderr,
  1230. X                "%s: can't determine window ID\n", argv0);
  1231. X            return(1);
  1232. X        }
  1233. X
  1234. X        if ((uwid = (uwid_t)atol(cp)) == 0) {
  1235. X            fprintf(stderr,
  1236. X                "%s: garbaged window ID in environment: %s",
  1237. X                argv0, cp);
  1238. X            return(1);
  1239. X        }
  1240. X    }
  1241. X
  1242. X    /*
  1243. X     * Copy the argv list into "uwoptval" and change the title.
  1244. X     */
  1245. X    av = argv + optind - 1;
  1246. X    cq = uwoptval.uwov_string;
  1247. X    cqlimit = uwoptval.uwov_string + sizeof uwoptval.uwov_string;
  1248. X    while ((cp = *++av) != NULL && cq < cqlimit) {
  1249. X        while (cq < cqlimit && (*cq++ = *cp++) != '\0')
  1250. X            ;
  1251. X        cq[-1] = ' ';
  1252. X    }
  1253. X    cq[-1] = '\0';
  1254. X
  1255. X    if (uw_rsetopt(uwid, UWOP_TITLE, &uwoptval) < 0) {
  1256. X        uw_perror("uw_rsetopt", uwerrno, errno);
  1257. X        return(1);
  1258. X    } else
  1259. X        return(0);
  1260. X}
  1261. !EOF!utility/uwtitle.c!
  1262. echo x - utility/uwtool.c
  1263. sed -e 's/^X//' > utility/uwtool.c << '!EOF!utility/uwtool.c!'
  1264. X/*
  1265. X *    uwtool
  1266. X *
  1267. X * Copyright 1986 by John D. Bruner.  All rights reserved.  Permission to
  1268. X * copy this program is given provided that the copy is not sold and that
  1269. X * this copyright notice is included.
  1270. X */
  1271. X#include <strings.h>
  1272. X#include <stdio.h>
  1273. X
  1274. X#include "uwlib.h"
  1275. X
  1276. Xmain(argc, argv)
  1277. Xint argc;
  1278. Xchar **argv;
  1279. X{
  1280. X    register uwid_t uwid;
  1281. X    register char *fname, *term;
  1282. X    register int c;
  1283. X    register uwtype_t wtype;
  1284. X    char *argv0;
  1285. X    char *av[2];
  1286. X    int vflag;
  1287. X    int wflag;
  1288. X    char *title;
  1289. X    union uwoptval uwoptval;
  1290. X    extern int errno;
  1291. X    extern int optind;
  1292. X    extern char *optarg;
  1293. X    extern char *getenv();
  1294. X
  1295. X    /*
  1296. X     * If called with no arguments, create a new window using the
  1297. X     * current shell according to the SHELL environment variable
  1298. X     * (or "/bin/sh" if that doesn't exist).  If called with
  1299. X     * arguments, argv[optind] through argv[argc-1] are the arguments
  1300. X     * to the command.
  1301. X     *
  1302. X     * Options which are recognized directly are:
  1303. X     *
  1304. X     *    -v    (verbose) print new window ID on stdout
  1305. X     *    -wtype    create window with emulation "type"
  1306. X     *    -ttitle    label window with "title"
  1307. X     *
  1308. X     * If no explicit title is specified, the command name is used.
  1309. X     */
  1310. X    argv0 = argv[0];
  1311. X    wflag = 0;
  1312. X    vflag = 0;
  1313. X    title = (char *)0;
  1314. X    while ((c = getopt(argc, argv, "vw:t:")) != EOF) {
  1315. X        switch (c) {
  1316. X        case 'v':
  1317. X            vflag++;
  1318. X            break;
  1319. X        case 'w':
  1320. X            wflag++;
  1321. X            wtype = uw_ttype(optarg);
  1322. X            break;
  1323. X        case 't':
  1324. X            title = optarg;
  1325. X            break;
  1326. X        }
  1327. X    }
  1328. X            
  1329. X    if (optind < argc) {
  1330. X        /*
  1331. X         * Adjust the "argv" pointer according to the number of
  1332. X         * arguments we've processed.
  1333. X         */
  1334. X        argv += optind;
  1335. X        fname = *argv;
  1336. X    } else {
  1337. X        /*
  1338. X         * No (non-option) arguments -- use SHELL
  1339. X         */
  1340. X        if ((fname = getenv("SHELL")) == (char *)0)
  1341. X            fname = "/bin/sh";
  1342. X        av[0] = fname;
  1343. X        av[1] = (char *)0;
  1344. X        argv = av;
  1345. X    }
  1346. X
  1347. X    if (title == (char *)0) {
  1348. X        /*
  1349. X         * If there was no "-t" argument, then "title" will still
  1350. X         * be NULL.  In this case we use the command name as
  1351. X         * the title.
  1352. X         */
  1353. X        title = fname;
  1354. X    }
  1355. X    
  1356. X    if (!wflag) {
  1357. X        /*
  1358. X         * If there was no "-w" argument, fetch the window
  1359. X         * type from the environment.  If that fails, use
  1360. X         * a default.
  1361. X         */
  1362. X        if ((term=getenv("TERM")) != (char *)0)
  1363. X            wtype = uw_ttype(term);
  1364. X        else
  1365. X            wtype = UWT_ADM31;
  1366. X    }
  1367. X    
  1368. X    if ((uwid = uw_cmd(wtype, fname, argv)) > 0) {
  1369. X        (void)strncpy(uwoptval.uwov_string, title,
  1370. X            sizeof uwoptval.uwov_string);
  1371. X        (void)uw_rsetopt(uwid, UWOP_TITLE, &uwoptval);
  1372. X        if (vflag)
  1373. X            printf("%d\n", uwid);
  1374. X        return(0);
  1375. X    } else {
  1376. X        if (uwerrno != UWE_NXSERV)
  1377. X            uw_perror(fname, uwerrno, errno);
  1378. X        else
  1379. X            uw_perror(argv0, uwerrno, errno);
  1380. X        return(1);
  1381. X    }
  1382. X}
  1383. !EOF!utility/uwtool.c!
  1384. echo x - misc/README
  1385. sed -e 's/^X//' > misc/README << '!EOF!misc/README!'
  1386. XThis directory contains three items that may be of interest:
  1387. X
  1388. X
  1389. X    getopt.c    The AT&T version of the getopt() library
  1390. X            routine (for command-line processing).  This
  1391. X            version, to the best of my knowledge, was
  1392. X            placed into the public domain by AT&T.
  1393. X
  1394. X    
  1395. X    macmouse.ml    A package for use with Gosling's EMACS
  1396. X            which intreprets encoded mouse-down and
  1397. X            mouse-up events within windows to perform
  1398. X            various operations.
  1399. X
  1400. X            Author: Chris Kent (kent@decwrl.dec.com)
  1401. X
  1402. X
  1403. X    macmouse.el    A similar macro package for GNU EMACS.
  1404. X
  1405. X            Author: Gregory Lauer (glauer@bbn.arpa)
  1406. X
  1407. X
  1408. XThe two EMACS macro packages were developed for a previous version of
  1409. XUW (version 2.10).  Since I (John Bruner) am not an EMACS user, I do
  1410. Xnot know how well they will work with UW v4.2.
  1411. !EOF!misc/README!
  1412. echo x - misc/getopt.c
  1413. sed -e 's/^X//' > misc/getopt.c << '!EOF!misc/getopt.c!'
  1414. X/*LINTLIBRARY*/
  1415. X#define NULL    0
  1416. X#define EOF    (-1)
  1417. X#define ERR(s, c)    if(opterr){\
  1418. X    extern int strlen(), write();\
  1419. X    char errbuf[2];\
  1420. X    errbuf[0] = c; errbuf[1] = '\n';\
  1421. X    (void) write(2, argv[0], (unsigned)strlen(argv[0]));\
  1422. X    (void) write(2, s, (unsigned)strlen(s));\
  1423. X    (void) write(2, errbuf, 2);}
  1424. X
  1425. Xextern int strcmp();
  1426. Xextern char *strchr();
  1427. X
  1428. Xint    opterr = 1;
  1429. Xint    optind = 1;
  1430. Xint    optopt;
  1431. Xchar    *optarg;
  1432. X
  1433. Xint
  1434. Xgetopt(argc, argv, opts)
  1435. Xint    argc;
  1436. Xchar    **argv, *opts;
  1437. X{
  1438. X    static int sp = 1;
  1439. X    register int c;
  1440. X    register char *cp;
  1441. X
  1442. X    if(sp == 1)
  1443. X        if(optind >= argc ||
  1444. X           argv[optind][0] != '-' || argv[optind][1] == '\0')
  1445. X            return(EOF);
  1446. X        else if(strcmp(argv[optind], "--") == NULL) {
  1447. X            optind++;
  1448. X            return(EOF);
  1449. X        }
  1450. X    optopt = c = argv[optind][sp];
  1451. X    if(c == ':' || (cp=strchr(opts, c)) == NULL) {
  1452. X        ERR(": illegal option -- ", c);
  1453. X        if(argv[optind][++sp] == '\0') {
  1454. X            optind++;
  1455. X            sp = 1;
  1456. X        }
  1457. X        return('?');
  1458. X    }
  1459. X    if(*++cp == ':') {
  1460. X        if(argv[optind][sp+1] != '\0')
  1461. X            optarg = &argv[optind++][sp+1];
  1462. X        else if(++optind >= argc) {
  1463. X            ERR(": option requires an argument -- ", c);
  1464. X            sp = 1;
  1465. X            return('?');
  1466. X        } else
  1467. X            optarg = argv[optind++];
  1468. X        sp = 1;
  1469. X    } else {
  1470. X        if(argv[optind][++sp] == '\0') {
  1471. X            sp = 1;
  1472. X            optind++;
  1473. X        }
  1474. X        optarg = NULL;
  1475. X    }
  1476. X    return(c);
  1477. X}
  1478. !EOF!misc/getopt.c!
  1479. echo x - misc/macmouse.el
  1480. sed -e 's/^X//' > misc/macmouse.el << '!EOF!misc/macmouse.el!'
  1481. X;;;  macmouse.el (Version: 2.0)
  1482. X
  1483. X;;;  Copyright (C) Gregory S. Lauer (glauer@bbn), 1985. 
  1484. X;;;    Please send suggestions and corrections to the above address.
  1485. X;;;
  1486. X;;;  This file contains macmouse, a GNU Emacs mouse package for UW.
  1487. X
  1488. X
  1489. X;;
  1490. X;; GNU Emacs is distributed in the hope that it will be useful,
  1491. X;; but without any warranty.  No author or distributor
  1492. X;; accepts responsibility to anyone for the consequences of using it
  1493. X;; or for whether it serves any particular purpose or works at all,
  1494. X;; unless he says so in writing.
  1495. X
  1496. X;; Everyone is granted permission to copy, modify and redistribute
  1497. X;; GNU Emacs, but only under the conditions described in the
  1498. X;; document "GNU Emacs copying permission notice".   An exact copy
  1499. X;; of the document is supposed to have been given to you along with
  1500. X;; GNU Emacs so that you can know how you may redistribute it all.
  1501. X;; It should be in a file named COPYING.  Among other things, the
  1502. X;; copyright notice and this notice must be preserved on all copies.
  1503. X
  1504. X
  1505. X;;;  Original version for Gosling emacs by Chris Kent, Purdue University 1985.
  1506. X;;;  Modified by Gregory Lauer, BBN, Novemeber 1985.
  1507. X;
  1508. X;
  1509. X;
  1510. X; Macmouse provides the following features:
  1511. X;  Up or down mouse button in a window selects that window
  1512. X;
  1513. X;  A scroll bar/thumbing area for each window with the following features:
  1514. X;       the mode lines are horizontal scroll bars
  1515. X;           (running from rightmost column to under leftmost column)
  1516. X;       the unused right window bar and the dividing lines between
  1517. X;           windows are vertical scroll bars
  1518. X;           (running from top of window THRU modeline
  1519. X;   for vertical scroll bars:
  1520. X;     click at line 1 does previous page
  1521. X;    click at last line does next page
  1522. X;     click anywhere else "thumbs" to the relative portion of the buffer.
  1523. X;     shift-click at line 1 scrolls one line down
  1524. X;     shift-click at last line scrolls one line up
  1525. X;     shift-click elsewhere moves line to top of window
  1526. X;     option-shift-click elsewhere moves line to bottom of window
  1527. X;   for horizontal scroll bars:
  1528. X;       click at column 1 does scroll right one window width
  1529. X;       click at last column does scroll left one window width
  1530. X;       click anywhere else moves to that "percent" of the buffer width
  1531. X;       shift-click at column 1 scrolls one column right
  1532. X;       shift-click at last column scrolls one column left
  1533. X;       shift-click elsewhere moves column to right of window
  1534. X;       option-shift-click elsewhere moves column to left of window
  1535. X;
  1536. X; There is also basic positioning and kill-buffer support:
  1537. X;     click in a buffer moves dot there and selects that buffer
  1538. X;     drag copies the dragged region to the kill buffer
  1539. X;     shift-drag deletes the dragged region to the kill buffer
  1540. X;
  1541. X;   It is possible to use the scrolling and thumbing area to make the region
  1542. X;   larger than a single screen; just click, scroll, release. Make sure
  1543. X;   that the last scroll is just a down event; the up must be in the buffer.
  1544. X;   The last mouse position is remembered for each different buffer (not
  1545. X;   window), and thus you can start a drag in one buffer, select another,
  1546. X;   go back to the first buffer, etc.
  1547. X;
  1548. X;     option-click yanks from the kill buffer
  1549. X;     option-shift-click similarly yanks from a named buffer.
  1550. X; 
  1551. X
  1552. X(defconst mouse-max-x 95 "Maximum UW column returned on mouse click")
  1553. X(defconst mouse-max-y 95 "Maximum UW row returned on mouse click")
  1554. X
  1555. X(make-variable-buffer-local 'mouse-last-x) ; x of last event
  1556. X(set-default 'mouse-last-x 0)
  1557. X
  1558. X(make-variable-buffer-local 'mouse-last-y) ; y of last event
  1559. X(set-default 'mouse-last-y 0)
  1560. X
  1561. X(make-variable-buffer-local 'mouse-last-b) ; buttons at last event
  1562. X(set-default 'mouse-last-b 0)
  1563. X
  1564. X(make-variable-buffer-local 'mouse-last-dot) ; dot after last event
  1565. X(set-default 'mouse-last-dot 0)
  1566. X
  1567. X(make-variable-buffer-local 'scrolling-p)
  1568. X(set-default 'scrolling-p nil)
  1569. X
  1570. X(defun move-mac-cursor ()
  1571. X  (interactive)
  1572. X  (let (savest b x y up down lock shift option command)
  1573. X    (setq savest stack-trace-on-error)
  1574. X    (setq stack-trace-on-error nil)
  1575. X                    ; decode everything
  1576. X    (setq y (- (read-char) 32))
  1577. X    (setq x (- (read-char) 32))
  1578. X    (setq b (- (read-char) 32))
  1579. X    (setq command (< 0 (logand b 1)))    ; command key
  1580. X    (setq shift (< 0 (logand b 2)))    ; shift
  1581. X    (setq lock (< 0 (logand b 4)))    ; caps-lock
  1582. X    (setq option (< 0 (logand b 8)))    ; option
  1583. X    (setq down (< 0 (logand b 16)))    ; mouse down
  1584. X    (setq up (< 0 (logand b 32)))    ; mouse up
  1585. X    (condition-case ()
  1586. X    (progn
  1587. X      (select-window-containing-x-and-y x y) ; side-effect sets scrolling-p
  1588. X      (if scrolling-p
  1589. X          (mouse-scroll-region b x y)
  1590. X        (progn
  1591. X          (move-to-window-x-y x y)    ; move cursor to mouse-dot always
  1592. X          (if down (setq mouse-last-dot (dot)))
  1593. X          (mouse-edit-action))))
  1594. X      (error (message "Click not in selectable window")
  1595. X         (sit-for 1)
  1596. X         (message "")))
  1597. X    (setq stack-trace-on-error savest)
  1598. X    (if down
  1599. X    (progn 
  1600. X      (setq mouse-last-x x)
  1601. X      (setq mouse-last-y y)
  1602. X      (setq mouse-last-b b))
  1603. X      (progn 
  1604. X    (setq mouse-last-x 0)
  1605. X    (setq mouse-last-y 0)
  1606. X    (setq mouse-last-b 0)))))
  1607. X
  1608. X(defun mouse-edit-action ()
  1609. X                                ;marking and editing actions on buttons:
  1610. X                ;   if no movement, nothing.
  1611. X                ;   if movement, save mouse-last-dot,
  1612. X                ;      and edit.
  1613. X                ; editing (on upstrokes):
  1614. X                ;   unmodified, copy to kill buffer.
  1615. X                ;   SHIFTed, delete (cut) to kill buffer.
  1616. X                ; 
  1617. X                ; option-click yanks from kill buffer; 
  1618. X                ; shift-option-click from named buffer.
  1619. X  (let ((fun (get 'mouse-function b)))
  1620. X    (if fun (apply fun nil))))
  1621. X
  1622. X
  1623. X    ; individual button bindings
  1624. X    ; generally will only need up mouse button: mouse-last-dot
  1625. X    ; is saved automatically on down mouse button
  1626. X
  1627. X; only need to define functions for keys that get used
  1628. X
  1629. X(put 'mouse-function 32            ; up
  1630. X     '(lambda ()
  1631. X         (if (and (not (mouse-click-p))
  1632. X         (not scrolling-p))
  1633. X        (copy-region-as-kill (dot) mouse-last-dot))))
  1634. X
  1635. X(put 'mouse-function 34            ; up/shift
  1636. X     '(lambda ()
  1637. X         (if (and (not (mouse-click-p))
  1638. X         (not scrolling-p))
  1639. X           (kill-region (dot) mouse-last-dot))))
  1640. X
  1641. X(put 'mouse-function 40            ; up/option
  1642. X     '(lambda ()
  1643. X         (if (mouse-click-p)
  1644. X        (progn
  1645. X          (yank)
  1646. X          (exchange-dot-and-mark)))))
  1647. X
  1648. X(put 'mouse-function 42
  1649. X     '(lambda ()        ; up/option/shift
  1650. X    (if (mouse-click-p)
  1651. X        (insert-buffer (read-buffer "Insert contents of buffer: ")))))
  1652. X
  1653. X(defun mouse-click-p ()
  1654. X  (= (dot) mouse-last-dot))
  1655. X
  1656. X(defun set-window-boundaries ()
  1657. X  (let ((edges (window-edges)))
  1658. X    (setq xl (1+ (car edges)))
  1659. X    (setq yt (1+ (car (cdr edges))))
  1660. X    (let ((temp (car (cdr (cdr edges)))))
  1661. X      (setq xr (if (= (screen-width) temp) mouse-max-x temp)))
  1662. X    (let ((temp (car (cdr (cdr (cdr edges))))))
  1663. X      (setq yb (if (= (screen-height) temp) mouse-max-y temp )))))
  1664. X
  1665. X(defun select-window-containing-x-and-y (x y)
  1666. X  (let ((starting-window (selected-window)))
  1667. X    (set-window-boundaries)
  1668. X    (while (not (point-in-window x y))
  1669. X      (other-window 1)
  1670. X      (if (eq (selected-window) starting-window)
  1671. X      (error nil)
  1672. X    (set-window-boundaries)))
  1673. X    (if (or (= x xr) (= y yb))
  1674. X    (setq scrolling-p t)
  1675. X      (setq scrolling-p nil))))
  1676. X
  1677. X(defun point-in-window (x y)
  1678. X  (and (<= xl x)(<= x xr)(<= yt y)(<= y yb)))
  1679. X
  1680. X(defun move-to-window-x-y (x y)
  1681. X  (move-to-window-line (- y yt))
  1682. X  (move-to-window-column (- x xl)))
  1683. X
  1684. X(defun move-to-window-column (x)
  1685. X  (move-to-column (+ (max 0 (- (window-hscroll) 1)) x)))
  1686. X
  1687. X(defun mouse-scroll-region (b x y)
  1688. X  (if down
  1689. X      (if shift
  1690. X      (do-lines b x y)
  1691. X    (do-pages b x y)))
  1692. X  (if (and up
  1693. X       (or (/= x mouse-last-x)
  1694. X           (/= y mouse-last-y)))
  1695. X      (if shift
  1696. X      (do-lines b x y)
  1697. X    (do-pages b x y))))
  1698. X
  1699. X(defun do-lines (b x y)            ; fine control over lines
  1700. X  (if (= x xr)
  1701. X      (cond ((= y yt)(scroll-down 1))
  1702. X        ((= y yb)(scroll-up 1))
  1703. X        (t (if option
  1704. X           (scroll-down (- yb y 1))
  1705. X         (scroll-up (- y yt))))))
  1706. X  (if (and (= y yb) (/= x xr))
  1707. X      (cond ((<= x xl)(scroll-right 1))
  1708. X        ((>= x (1- xr))(scroll-left 1))
  1709. X        (t (if option
  1710. X           (move-column-right x)
  1711. X         (move-column-left x))))))
  1712. X
  1713. X(defun move-column-left (x)        ;need to mess about a bit because
  1714. X  (scroll-left                ;first scroll left of 1 just writes
  1715. X   (if (= (window-hscroll) 0)        ;a column of $s in column 1
  1716. X       (- x xl)
  1717. X     (- x xl 1))))
  1718. X
  1719. X(defun move-column-right (x)
  1720. X  (scroll-right (- xr x 2)))
  1721. X
  1722. X
  1723. X(defun do-pages (b x y)            ; large motions via pages and thumbing
  1724. X  (if (= x xr)
  1725. X      (cond ((= y yt)(scroll-down nil))
  1726. X        ((= y yb)(scroll-up nil))
  1727. X        (t (goto-percent (/ (* (- y yt 1) 100)
  1728. X                (- yb yt 2))))))
  1729. X  (if (and (= y yb)(/= x xr))
  1730. X      (cond ((<= x xl)(scroll-right (- (window-width)
  1731. X                       next-screen-context-lines)))
  1732. X        ((>= x (1- xr))(scroll-left (- (window-width)
  1733. X                       next-screen-context-lines)))
  1734. X        (t (goto-horizontal-percent (/ (* (- x xl 1) 100)
  1735. X                       (- xr xl 2)))))))
  1736. X
  1737. X(defun goto-percent (p)
  1738. X  (goto-char (/ (* (- (dot-max) (dot-min)) p) 100)))
  1739. X
  1740. X(defun goto-horizontal-percent (p)    ;try to put this percent of columns
  1741. X  (let ((window-offset (window-hscroll));in the center column of the window
  1742. X    delta)                ;unless that would move the first or
  1743. X    (setq delta                ;last column past the window edge
  1744. X      (- window-offset
  1745. X         (min (max 0 (- (/ (* (screen-width) p) 100)
  1746. X                (/ (- xr xl) 2)))
  1747. X          (- (screen-width) (- xr xl)))))
  1748. X    (scroll-right delta)))
  1749. X
  1750. X    
  1751. X(global-set-key "\em" 'move-mac-cursor)
  1752. !EOF!misc/macmouse.el!
  1753. echo x - misc/macmouse.ml
  1754. sed -e 's/^X//' > misc/macmouse.ml << '!EOF!misc/macmouse.ml!'
  1755. X; $Header: /c/cak/lib/mlisp/RCS/macmouse.ml,v 1.5 85/11/05 14:01:44 cak Rel $
  1756. X; 
  1757. X; Macintosh mouse routines for use with John Bruner's uw program.
  1758. X;     Chris Kent, Purdue University Fri Oct 25 1985
  1759. X;     Copyright 1985 by Christopher A. Kent. All rights reserved.
  1760. X;     Permission to copy is given provided that the copy is not
  1761. X;     sold and this copyright notice is included.
  1762. X; 
  1763. X; Provides a scroll bar/thumbing area in the unused scroll bar with the
  1764. X; following features:
  1765. X;     click at line 1 does previous page
  1766. X;    click at line 24 does next page
  1767. X;     click anywhere else "thumbs" to the relative portion of the buffer.
  1768. X;     shift-click at line 1 scrolls one line down
  1769. X;     shift-click at line 24 scrolls one line up
  1770. X;     shift-click elsewhere moves line to top of window
  1771. X;     option-shift-click elsewhere moves line to bottom of window
  1772. X; 
  1773. X; There is also basic positioning and kill-buffer support:
  1774. X;     click in a buffer moves dot there
  1775. X;     drag copies the dragged region to the kill buffer (mark is left
  1776. X;         at the beginning of the region.)
  1777. X;     shift-drag deletes the dragged region to the kill buffer
  1778. X;   it is possible to use the scrolling and thumbing area to make the region
  1779. X;   larger than a single screen; just click, scroll, release. Make sure
  1780. X;   that the last scroll is just a down event; the up must be in the buffer.
  1781. X;
  1782. X;     option-click yanks from the kill buffer, doesn't affect mark.
  1783. X;     option-shift-click similarly yanks from a named buffer.
  1784. X; 
  1785. X
  1786. X(declare-global
  1787. X    #mouse-last-x        ; x of last event
  1788. X    #mouse-last-y        ; y of last event
  1789. X    #mouse-last-b        ; buttons at last event
  1790. X    #mouse-last-dot        ; dot after last event
  1791. X    #mouse-last-action        ; whether last was scroll (1) or edit (2)
  1792. X)
  1793. X
  1794. X(defun
  1795. X    (move-mac-cursor savest b x y up down lock shift option command saveb
  1796. X    (setq savest stack-trace-on-error)
  1797. X    (setq stack-trace-on-error 0)
  1798. X    ; decode everything
  1799. X    (setq y (- (get-tty-character) 32))
  1800. X    (setq x (- (get-tty-character) 32))
  1801. X    (setq b (- (get-tty-character) 32))
  1802. X    (setq saveb b)
  1803. X    (setq command (% b 2))(setq b (/ b 2))    ; command key
  1804. X    (setq shift (% b 2))(setq b (/ b 2))    ; shift 
  1805. X    (setq lock (% b 2))(setq b (/ b 2))    ; caps-lock
  1806. X    (setq option (% b 2))(setq b (/ b 2))    ; option
  1807. X    (setq down (% b 2))(setq b (/ b 2))    ; mouse down
  1808. X    (setq up (% b 2))
  1809. X    
  1810. X    (if (= x 81)        ; right margin -- move-dot-to-x-y is wrong
  1811. X        (progn 
  1812. X           (#mouse-scroll-region)
  1813. X           (setq #mouse-last-action 1))
  1814. X        (if (error-occurred 
  1815. X            (if (= #mouse-last-action 2)    ; not if just scrolled
  1816. X            (setq #mouse-last-dot (dot)))
  1817. X            (move-dot-to-x-y x y)
  1818. X            (backward-character)(forward-character)
  1819. X            (#mouse-edit-action)
  1820. X            (setq #mouse-last-action 2)
  1821. X        )
  1822. X        (progn 
  1823. X               (#mouse-scroll-region b x y)
  1824. X               (setq #mouse-last-action 1))
  1825. X        ))
  1826. X    (setq stack-trace-on-error savest)
  1827. X    (if (= down 1)
  1828. X        (progn 
  1829. X           (setq #mouse-last-x x)
  1830. X           (setq #mouse-last-y y)
  1831. X           (setq #mouse-last-b saveb))
  1832. X        (progn 
  1833. X           (setq #mouse-last-x 0)
  1834. X           (setq #mouse-last-y 0)
  1835. X           (setq #mouse-last-b 0)))
  1836. X    )
  1837. X    
  1838. X    (#mouse-edit-action        ; marking and editing actions on buttons:
  1839. X                ;   if no movement, nothing.
  1840. X                ;   if movement, put  mark at #mouse-last-dot,
  1841. X                ;      leave dot here,and edit.
  1842. X                ; editing (on upstrokes):
  1843. X                ;   unmodified, copy to kill buffer.
  1844. X                ;   SHIFTed, delete (cut) to kill buffer.
  1845. X                ; 
  1846. X                ; option-click yanks from kill buffer; 
  1847. X                ; shift-option-click from named buffer.
  1848. X    (if (= saveb 16)
  1849. X        (#mouse-d))
  1850. X    (if (= saveb 17)
  1851. X        (#mouse-dc))
  1852. X    (if (= saveb 18)
  1853. X        (#mouse-ds))
  1854. X    (if (= saveb 19)
  1855. X        (#mouse-dsc))
  1856. X    (if (= saveb 20)
  1857. X        (#mouse-dl))
  1858. X    (if (= saveb 21)
  1859. X        (#mouse-dlc))
  1860. X    (if (= saveb 22)
  1861. X        (#mouse-dls))
  1862. X    (if (= saveb 23)
  1863. X        (#mouse-dlsc))
  1864. X    (if (= saveb 24)
  1865. X        (#mouse-do))
  1866. X    (if (= saveb 25)
  1867. X        (#mouse-doc))
  1868. X    (if (= saveb 26)
  1869. X        (#mouse-dos))
  1870. X    (if (= saveb 27)
  1871. X        (#mouse-dosc))
  1872. X    (if (= saveb 28)
  1873. X        (#mouse-dol))
  1874. X    (if (= saveb 29)
  1875. X        (#mouse-dolc))
  1876. X    (if (= saveb 30)
  1877. X        (#mouse-dols))
  1878. X    (if (= saveb 31)
  1879. X        (#mouse-dolsc))
  1880. X    (if (= saveb 32)
  1881. X        (#mouse-u))
  1882. X    (if (= saveb 33)
  1883. X        (#mouse-uc))
  1884. X    (if (= saveb 34)
  1885. X        (#mouse-us))
  1886. X    (if (= saveb 35)
  1887. X        (#mouse-usc))
  1888. X    (if (= saveb 36)
  1889. X        (#mouse-ul))
  1890. X    (if (= saveb 37)
  1891. X        (#mouse-ulc))
  1892. X    (if (= saveb 38)
  1893. X        (#mouse-uls))
  1894. X    (if (= saveb 39)
  1895. X        (#mouse-ulsc))
  1896. X    (if (= saveb 40)
  1897. X        (#mouse-uo))
  1898. X    (if (= saveb 41)
  1899. X        (#mouse-uoc))
  1900. X    (if (= saveb 42)
  1901. X        (#mouse-uos))
  1902. X    (if (= saveb 43)
  1903. X        (#mouse-uosc))
  1904. X    (if (= saveb 44)
  1905. X        (#mouse-uol))
  1906. X    (if (= saveb 45)
  1907. X        (#mouse-uolc))
  1908. X    (if (= saveb 46)
  1909. X        (#mouse-uols))
  1910. X    (if (= saveb 47)
  1911. X        (#mouse-uolsc))
  1912. X    )
  1913. X
  1914. X    ; individual button bindings
  1915. X
  1916. X    (#mouse-u            ; up
  1917. X         (if (! (#mouse-click-p))
  1918. X        (progn 
  1919. X           (#mouse-set-region)
  1920. X           (Copy-region-to-kill-buffer)
  1921. X        ))
  1922. X    )
  1923. X
  1924. X    (#mouse-uc            ; up/command
  1925. X    )
  1926. X
  1927. X    (#mouse-us            ; up/shift
  1928. X         (if (! (#mouse-click-p))
  1929. X        (progn 
  1930. X           (#mouse-set-region)
  1931. X           (delete-to-killbuffer)
  1932. X        ))
  1933. X    )
  1934. X
  1935. X    (#mouse-usc            ; up/shift/command
  1936. X    )
  1937. X
  1938. X    (#mouse-ul            ; up/lock
  1939. X    )
  1940. X
  1941. X    (#mouse-ulc            ; up/lock/command
  1942. X    )
  1943. X
  1944. X    (#mouse-uls            ; up/lock/shift
  1945. X    )
  1946. X
  1947. X    (#mouse-ulsc        ; up/lock/shift/command
  1948. X    )
  1949. X
  1950. X    (#mouse-uo            ; up/option
  1951. X         (if (#mouse-click-p)
  1952. X        (yank-from-killbuffer)
  1953. X    )
  1954. X    )
  1955. X
  1956. X    (#mouse-uoc            ; up/option/command
  1957. X    )
  1958. X
  1959. X    (#mouse-uos            ; up/option/shift
  1960. X    (if (#mouse-click-p)    ; click
  1961. X        (yank-buffer (get-tty-buffer "Insert contents of buffer: "))
  1962. X    )
  1963. X    )
  1964. X
  1965. X    (#mouse-uosc        ; up/option/shift
  1966. X    )
  1967. X
  1968. X    (#mouse-uol            ; up/option/lock
  1969. X    )
  1970. X
  1971. X    (#mouse-uolc        ; up/option/lock
  1972. X    )
  1973. X
  1974. X    (#mouse-uols        ; up/option/lock/shift
  1975. X    )
  1976. X
  1977. X    (#mouse-uolsc        ; up/option/lock/shift/command
  1978. X    )
  1979. X    
  1980. X    (#mouse-d            ; down
  1981. X    )
  1982. X
  1983. X    (#mouse-dc            ; down/command
  1984. X    )
  1985. X
  1986. X    (#mouse-ds            ; down/shift
  1987. X    )
  1988. X
  1989. X    (#mouse-dsc            ; down/shift/command
  1990. X    )
  1991. X
  1992. X    (#mouse-dl            ; down/lock
  1993. X    )
  1994. X
  1995. X    (#mouse-dlc            ; down/lock/command
  1996. X    )
  1997. X
  1998. X    (#mouse-dls            ; down/lock/shift
  1999. X    )
  2000. X
  2001. X    (#mouse-dlsc        ; down/lock/shift/command
  2002. X    )
  2003. X
  2004. X    (#mouse-do            ; down/option
  2005. X    )
  2006. X
  2007. X    (#mouse-doc            ; down/option/command
  2008. X    )
  2009. X
  2010. X    (#mouse-dos            ; down/option/shift
  2011. X    )
  2012. X
  2013. X    (#mouse-dosc        ; down/option/shift
  2014. X    )
  2015. X
  2016. X    (#mouse-dol            ; down/option/lock
  2017. X    )
  2018. X
  2019. X    (#mouse-dolc        ; down/option/lock
  2020. X    )
  2021. X
  2022. X    (#mouse-dols        ; down/option/lock/shift
  2023. X    )
  2024. X
  2025. X    (#mouse-dolsc        ; down/option/lock/shift/command
  2026. X    )
  2027. X
  2028. X    (#mouse-set-region        ; set the region to be from last dot to dot.
  2029. X    (set-mark)
  2030. X    (goto-character #mouse-last-dot)
  2031. X    (exchange-dot-and-mark)
  2032. X    )
  2033. X
  2034. X    (#mouse-click-p clickp
  2035. X         (if (= (dot) #mouse-last-dot)
  2036. X        (setq clickp 1)
  2037. X        (setq clickp 0)
  2038. X    ))
  2039. X    
  2040. X    (#mouse-scroll-region     ; out of range actions:
  2041. X                ;    left margin -- hard to generate, ignored
  2042. X                ;    right margin -- simulate scroll bar
  2043. X                ;      line 1 -- previous page
  2044. X                ;      line 24/25 -- next page
  2045. X                ;      other lines -- thumbing
  2046. X                ;    top margin -- previous page
  2047. X                ;    bottom margin -- next page
  2048. X                ; 
  2049. X                ; if shifted, deal with lines. 
  2050. X                ;    line 1 scrolls one line down
  2051. X                ;    line 24/25 scrolls one line up
  2052. X                ;    else line to top;  with option to bottom.
  2053. X                ;
  2054. X                ; if up stroke is in same place as down
  2055. X                ; stroke, don't do anything, so clicks in
  2056. X                ; the scroll region don't do the action
  2057. X                ; twice.
  2058. X    (if (= down 1)
  2059. X        (if (= shift 1)
  2060. X        (do-lines)
  2061. X        (do-pages))
  2062. X    )
  2063. X    (if (& (= up 1)
  2064. X           (| (!= x #mouse-last-x) (!= y #mouse-last-y)))
  2065. X        (if (= shift 1)
  2066. X        (do-lines)
  2067. X        (do-pages)
  2068. X        )
  2069. X    )
  2070. X    (#mouse-set-region)
  2071. X    )
  2072. X
  2073. X    (do-pages            ; large motions via pages and thumbing
  2074. X    (if (| (= y 0) (= y 1) (= y 24) (= y 25))
  2075. X        (progn 
  2076. X           (if (| (= y 0) (= y 1))
  2077. X               (previous-page)
  2078. X               (Next-Page)
  2079. X           ))
  2080. X        (if (= x 81)
  2081. X        (goto-percent (/ (* y 100) 25))
  2082. X        )
  2083. X    ))
  2084. X
  2085. X    (do-lines            ; fine control over lines
  2086. X    (if (= x 81)
  2087. X        (if (| (= y 1) (= y 24) (= y 25))
  2088. X        (if (| (= y 0) (= y 1))
  2089. X            (scroll-one-line-down)
  2090. X            (scroll-one-line-up)
  2091. X        )
  2092. X        (progn
  2093. X              (move-dot-to-x-y 1 y)
  2094. X              (if (= option 0)
  2095. X              (line-to-top-of-window)
  2096. X              (line-to-bottom-of-window))
  2097. X        )
  2098. X        )
  2099. X    )
  2100. X    )
  2101. X
  2102. X    (line-to-bottom-of-window nlines i
  2103. X    (line-to-top-of-window)
  2104. X    (setq i 0)
  2105. X    (setq nlines (- (window-height) 1))
  2106. X    (while (< i nlines)
  2107. X           (scroll-one-line-down)
  2108. X           (setq i (+ i 1))
  2109. X    )
  2110. X    )
  2111. X
  2112. X    (goto-percent
  2113. X       (goto-character (/ (* (buffer-size) (arg 1)) 100))
  2114. X   )
  2115. X)
  2116. X    
  2117. X(bind-to-key "move-mac-cursor" "\em")
  2118. !EOF!misc/macmouse.ml!
  2119. exit 0
  2120. : end of shell archive
  2121.