home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2971 < prev    next >
Encoding:
Internet Message Format  |  1991-03-05  |  54.2 KB

  1. From: guido@cwi.nl (Guido van Rossum)
  2. Newsgroups: alt.sources
  3. Subject: STDWIN 0.9.5, Part 10/19
  4. Message-ID: <3074@charon.cwi.nl>
  5. Date: 4 Mar 91 11:58:05 GMT
  6.  
  7. Archive-name: stdwin/part10
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 10 (of 19)."
  16. # Contents:  Appls/dpv/choose.c Conf/README Doc/man/editwin.man
  17. #   Packs/vt/vtselect.c Ports/alfa/draw.c Ports/x11/selection.c
  18. # Wrapped by guido@voorn.cwi.nl on Mon Mar  4 12:37:28 1991
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'Appls/dpv/choose.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'Appls/dpv/choose.c'\"
  22. else
  23. echo shar: Extracting \"'Appls/dpv/choose.c'\" \(8842 characters\)
  24. sed "s/^X//" >'Appls/dpv/choose.c' <<'END_OF_FILE'
  25. X/* Application to choose ditroff special character names
  26. X   for glyphs in a given font.
  27. X   Usage: choose [-f  glyphfont] [-s size] [-c columns]
  28. X   Mac defaults: -f Symbol -s 24 -c 8
  29. X   X defaults: -f '*-symbol-*--24-*' -c 8
  30. X
  31. X   TO DO:
  32. X       - start with font choosing dialog on Mac
  33. X    - more object-like file interface (pretend we're editing
  34. X      a table object)
  35. X    - more syntax checking on input
  36. X    - check for duplicate names?
  37. X*/
  38. X
  39. X#define CHARWIDTHBUG        /* wcharwidth(i) == 0 for all i >= 128 */
  40. X
  41. X#include <stdwin.h>
  42. X#include <tools.h>
  43. X
  44. X/* Number of possible characters per font -- limited by char = 8 bit */
  45. X#define NGLYPHS 256
  46. X
  47. X/* Table of names for each char -- 3rd is terminating zero */
  48. Xchar namelist[NGLYPHS][3];
  49. X
  50. X/* Random global variables */
  51. Xchar *progname= "choose";    /* Program name for error messages */
  52. XWINDOW *win;            /* Where it all happens */
  53. Xint selected= -1;        /* Glyph currently selected, -1 if none */
  54. Xbool changed;            /* Set if any changes made */
  55. Xchar *filename;            /* Namelist file name */
  56. X
  57. X/* Variables controlling the window lay-out */
  58. Xchar *glyphfont, *namefont;    /* Fonts used for ditto */
  59. Xint glyphsize, namesize;    /* Point sizes used for glyph and name */
  60. Xint firstglyph, lastglyph;    /* First and last glyphs */
  61. Xint ncols, nrows;        /* Matrix dimensions */
  62. Xint colwidth, rowheight;    /* Cell dimensions */
  63. X
  64. X/* Parse the command line */
  65. X
  66. Xparse(argc, argv)
  67. X    int argc;
  68. X    char **argv;
  69. X{
  70. X    if (argc > 0 && argv[0] != NULL && argv[0][0] != EOS) {
  71. X        progname= rindex(argv[0], '/');
  72. X        if (progname == NULL)
  73. X            progname= argv[0];
  74. X        else
  75. X            progname++;
  76. X    }
  77. X    
  78. X    for (;;) {
  79. X        int c= getopt(argc, argv, "c:f:s:");
  80. X        if (c == EOF)
  81. X            break;
  82. X        switch (c) {
  83. X        case 'c':
  84. X            ncols= atoi(optarg);
  85. X            break;
  86. X        case 'f':
  87. X            glyphfont= optarg;
  88. X            break;
  89. X        case 's':
  90. X            glyphsize= atoi(optarg);
  91. X            break;
  92. X        default:
  93. X            usage();
  94. X            /*NOTREACHED*/
  95. X        }
  96. X    }
  97. X    
  98. X    if (optind < argc)
  99. X        filename= argv[optind++];
  100. X    
  101. X    if (optind < argc)
  102. X        usage();
  103. X}
  104. X
  105. X/* Print usage message and exit */
  106. X
  107. Xusage()
  108. X{
  109. X    wdone();
  110. X    fprintf(stderr, "usage: %s [-c columns] [-f font] [-s size]\n",
  111. X        progname);
  112. X    exit(2);
  113. X}
  114. X
  115. X/* Initialize the control variables */
  116. X
  117. Xsetup()
  118. X{
  119. X    /* Fill in defaults */
  120. X    if (ncols <= 0)
  121. X        ncols= 8;
  122. X    if (glyphfont == NULL || *glyphfont == EOS) {
  123. X#ifdef macintosh
  124. X        glyphfont= "Symbol";
  125. X#else
  126. X#ifdef X11R2
  127. X        glyphfont= "symbol22";
  128. X#else
  129. X        glyphfont= "*-symbol-*--24-*";
  130. X#endif
  131. X#endif
  132. X    }
  133. X    
  134. X    if (glyphsize <= 0)
  135. X        glyphsize= 24;
  136. X    if (namefont == NULL || *namefont == EOS) {
  137. X#ifdef machintosh
  138. X        namefont= "Courier";
  139. X#else
  140. X#ifdef X11R2
  141. X        namefont= "courier12f";
  142. X#else
  143. X        namefont= "*-courier-*--12-*";
  144. X#endif
  145. X#endif
  146. X    }
  147. X    if (namesize <= 0)
  148. X        namesize= 10;
  149. X    
  150. X    /* Find first and last existing character */
  151. X    firstglyph= 0;
  152. X    lastglyph= NGLYPHS-1;
  153. X    wsetfont(glyphfont);
  154. X    wsetsize(glyphsize);
  155. X    while (firstglyph < lastglyph && wcharwidth(firstglyph) == 0)
  156. X        ++firstglyph;
  157. X    firstglyph= (firstglyph/ncols) * ncols;
  158. X#ifndef CHARWIDTHBUG
  159. X    while (lastglyph > firstglyph && wcharwidth(lastglyph) == 0)
  160. X        --lastglyph;
  161. X    lastglyph= (lastglyph/ncols + 1) * ncols - 1;
  162. X#endif
  163. X    
  164. X    /* Compute remaining variables */
  165. X    nrows= (lastglyph - firstglyph + ncols) / ncols;
  166. X    colwidth= 2*wcharwidth('M');
  167. X    rowheight= wlineheight();
  168. X    wsetfont(namefont);
  169. X    wsetsize(namesize);
  170. X    rowheight += 4 + wlineheight();
  171. X    {
  172. X        int cw= wtextwidth("MM  MM", -1) + 4;
  173. X        if (colwidth < cw)
  174. X            colwidth= cw;
  175. X    }
  176. X}
  177. X
  178. X/* Draw procedure */
  179. X
  180. Xvoid
  181. Xdrawproc(win, left, top, right, bottom)
  182. X    WINDOW *win;
  183. X    int left, top, right, bottom;
  184. X{
  185. X    int i;
  186. X    
  187. X    /* Draw vertical grid lines */
  188. X    for (i= 1; i < ncols; ++i)
  189. X        wdrawline(i*colwidth-1, 0, i*colwidth-1, nrows*rowheight);
  190. X    
  191. X    /* Draw horizontal grid lines */
  192. X    for (i= 1; i < nrows; ++i)
  193. X        wdrawline(0, i*rowheight-1, ncols*colwidth, i*rowheight-1);
  194. X    
  195. X    /* Draw glyph cells */
  196. X    for (i= firstglyph; i <= lastglyph; ++i) {
  197. X        int h, v, h2, v2;
  198. X        int glyphwidth;
  199. X        cellbounds(i, &h, &v, &h2, &v2);
  200. X        if (v >= bottom)
  201. X            break;
  202. X        if (!intersects(h, v, h2, v2, left, top, right, bottom))
  203. X            continue;
  204. X        wsetfont(glyphfont);
  205. X        wsetsize(glyphsize);
  206. X        glyphwidth= wcharwidth(i);
  207. X#ifndef CHARWIDTHBUG
  208. X        if (glyphwidth == 0)
  209. X            continue;
  210. X#endif
  211. X        wdrawchar(h + (colwidth-glyphwidth) / 2, v+2, i);
  212. X        wsetfont(namefont);
  213. X        wsetsize(namesize);
  214. X        {
  215. X            char buf[10];
  216. X            sprintf(buf, "%02X", i);
  217. X            wdrawtext(h+2, v2 - 2 - wlineheight(), buf, -1);
  218. X        }
  219. X        if (namelist[i][0] != EOS) {
  220. X            int namewidth;
  221. X            namewidth= wtextwidth(namelist[i], -1);
  222. X            wdrawtext(h + colwidth - namewidth - 2,
  223. X                v2 - 2 - wlineheight(),
  224. X                namelist[i], -1);
  225. X        }
  226. X        if (i == selected)
  227. X            winvert(h+1, v+1, h2-2, v2-2);
  228. X    }
  229. X}
  230. X    
  231. X/* Main program */
  232. X
  233. Xmain(argc, argv)
  234. X    int argc;
  235. X    char **argv;
  236. X{
  237. X    winitargs(&argc, &argv);
  238. X    parse(argc, argv);
  239. X    setup();
  240. X    readnamelist();
  241. X    wsetdefwinsize(colwidth*ncols, 0);
  242. X    win= wopen(glyphfont, drawproc);
  243. X    if (win == NULL) {
  244. X        wdone();
  245. X        fprintf(stderr, "%s: can't create window\n", progname);
  246. X    }
  247. X    wsetdocsize(win, colwidth*ncols, rowheight*nrows);
  248. X    eventloop();
  249. X    /*NOTREACHED*/
  250. X}
  251. X
  252. X/* Event loop.  Never returns. */
  253. X
  254. Xeventloop() {
  255. X    for (;;) {
  256. X        EVENT e;
  257. X        wgetevent(&e);
  258. X        switch (e.type) {
  259. X        
  260. X        case WE_MOUSE_DOWN:
  261. X        case WE_MOUSE_MOVE:
  262. X        case WE_MOUSE_UP:
  263. X            do_select(&e);
  264. X            break;
  265. X        
  266. X        case WE_CHAR:
  267. X            do_char(e.u.character);
  268. X            break;
  269. X        
  270. X        case WE_COMMAND:
  271. X            switch (e.u.command) {
  272. X            case WC_CLOSE:
  273. X            case WC_CANCEL:
  274. X        close_it:
  275. X                if (changed) {
  276. X                    int ok;
  277. X                    ok= waskync("Save changes?", 1);
  278. X                    if (ok > 0) {
  279. X                        if (!writenamelist())
  280. X                            ok= -1;
  281. X                    }
  282. X                    if (ok < 0)
  283. X                        continue;
  284. X                }
  285. X                wclose(win);
  286. X                wdone();
  287. X                exit(0);
  288. X                /*NOTREACHED*/
  289. X            case WC_BACKSPACE:
  290. X                do_char('\b');
  291. X                break;
  292. X            }
  293. X            break;
  294. X        
  295. X        case WE_CLOSE:
  296. X            goto close_it;
  297. X
  298. X        }
  299. X    }
  300. X    /*NOTREACHED*/
  301. X}
  302. X
  303. X/* Handle mouse events */
  304. X
  305. Xdo_select(ep)
  306. X    EVENT *ep;
  307. X{
  308. X    int left, top, right, bottom;
  309. X    int col= ep->u.where.h / colwidth;
  310. X    int row= ep->u.where.v / rowheight;
  311. X    int i= firstglyph + col + ncols*row;
  312. X    wsetfont(glyphfont);
  313. X    wsetsize(glyphsize);
  314. X    if (ep->u.where.h < 0 || ep->u.where.v < 0 ||
  315. X        col >= ncols || row >= nrows ||
  316. X        i < firstglyph || i > lastglyph ||
  317. X        wcharwidth(i) == 0)
  318. X        i= -1;
  319. X    if (i != selected) {
  320. X        wbegindrawing(win);
  321. X        if (selected >= 0) {
  322. X            cellbounds(selected, &left, &top, &right, &bottom);
  323. X            winvert(left+1, top+1, right-2, bottom-2);
  324. X        }
  325. X        selected= i;
  326. X        if (selected >= 0) {
  327. X            cellbounds(selected, &left, &top, &right, &bottom);
  328. X            winvert(left+1, top+1, right-2, bottom-2);
  329. X        }
  330. X        wenddrawing(win);
  331. X    }
  332. X    /* Must do this here because wshow may have no effect
  333. X       while the mouse is down. */
  334. X    if (selected >= 0) {
  335. X        cellbounds(selected, &left, &top, &right, &bottom);
  336. X        wshow(win, left, top, right, bottom);
  337. X    }
  338. X        
  339. X}
  340. X
  341. X/* Handle character events and backspace */
  342. X
  343. Xdo_char(c)
  344. X    int c;
  345. X{
  346. X    int n;
  347. X    int left, top, right, bottom;
  348. X    if (selected < 0) {
  349. X        wfleep();
  350. X        return;
  351. X    }
  352. X    if (c == '\b') {
  353. X        n= 0;
  354. X    }
  355. X    else {
  356. X        n= strlen(namelist[selected]) % 2;
  357. X        namelist[selected][n++]= c;
  358. X    }
  359. X    namelist[selected][n]= EOS;
  360. X    wsetfont(namefont);
  361. X    wsetsize(namesize);
  362. X    cellbounds(selected, &left, &top, &right, &bottom);
  363. X    wshow(win, left, top, right, bottom);
  364. X    wchange(win,
  365. X        right - 3*wcharwidth('m'), bottom - 2 - wlineheight(),
  366. X        right-2, bottom-2);
  367. X    changed= TRUE;
  368. X}
  369. X
  370. X/* Subroutine to find a glyph's cell */
  371. X
  372. Xcellbounds(i, pleft, ptop, pright, pbottom)
  373. X    int i;
  374. X    int *pleft, *ptop, *pright, *pbottom;
  375. X{
  376. X    int row= (i - firstglyph) / ncols;
  377. X    int col= (i - firstglyph) % ncols;
  378. X    *pleft= col*colwidth;
  379. X    *pright= *pleft + colwidth;
  380. X    *ptop= row * rowheight;
  381. X    *pbottom= *ptop + rowheight;
  382. X}
  383. X
  384. X/* Predicate for rectangle intersection */
  385. X
  386. Xbool
  387. Xintersects(l1, t1, r1, b1, l2, t2, r2, b2)
  388. X{
  389. X    if (l1 >= r2 || r1 <= l2)
  390. X        return FALSE;
  391. X    if (t1 >= b2 || b1 <= t2)
  392. X        return FALSE;
  393. X    return TRUE;
  394. X}
  395. X
  396. X/* Read the namelist */
  397. X
  398. Xbool
  399. Xreadnamelist()
  400. X{
  401. X    FILE *fp;
  402. X    char buf[256];
  403. X    if (filename == NULL) {
  404. X        buf[0]= EOS;
  405. X        if (!waskfile("Read file:", buf, sizeof buf, FALSE))
  406. X            return FALSE;
  407. X        filename= strdup(buf);
  408. X    }
  409. X    fp= fopen(filename, "r");
  410. X    if (fp == NULL) {
  411. X        char buf[256];
  412. X        sprintf(buf, "Can't read file %s", filename);
  413. X        wmessage(buf);
  414. X        return FALSE;
  415. X    }
  416. X    while (fgets(buf, sizeof buf, fp) != NULL) {
  417. X        int glyph;
  418. X        char name[256];
  419. X        if (sscanf(buf, "%s - 0x%x", name, &glyph) == 2 ||
  420. X            sscanf(buf, "%s 0x%x", name, &glyph) == 2) {
  421. X            if (glyph >= 0 && glyph < NGLYPHS)
  422. X                strncpy(namelist[glyph], name, 2);
  423. X        }
  424. X    }
  425. X    fclose(fp);
  426. X}
  427. X
  428. X/* Write the namelist */
  429. X
  430. Xbool
  431. Xwritenamelist()
  432. X{
  433. X    char name[256];
  434. X    FILE *fp;
  435. X    int i;
  436. X    if (filename == NULL)
  437. X        name[0]= EOS;
  438. X    else
  439. X        strcpy(name, filename);
  440. X    if (!waskfile("Write to file:", name, sizeof name, TRUE))
  441. X        return FALSE;
  442. X    filename= strdup(name);
  443. X    fp= fopen(filename, "w");
  444. X    if (fp == NULL) {
  445. X        sprintf(name, "Can't create file %s", filename);
  446. X        wmessage(name);
  447. X        filename= NULL;
  448. X        return FALSE;
  449. X    }
  450. X    for (i= 0; i < NGLYPHS; ++i) {
  451. X        if (namelist[i][0] != EOS)
  452. X            fprintf(fp, "%-2s - 0x%02X\n", namelist[i], i);
  453. X    }
  454. X    fclose(fp);
  455. X    changed= FALSE;
  456. X    return TRUE;
  457. X}
  458. END_OF_FILE
  459. if test 8842 -ne `wc -c <'Appls/dpv/choose.c'`; then
  460.     echo shar: \"'Appls/dpv/choose.c'\" unpacked with wrong size!
  461. fi
  462. # end of 'Appls/dpv/choose.c'
  463. fi
  464. if test -f 'Conf/README' -a "${1}" != "-c" ; then 
  465.   echo shar: Will not clobber existing file \"'Conf/README'\"
  466. else
  467. echo shar: Extracting \"'Conf/README'\" \(5259 characters\)
  468. sed "s/^X//" >'Conf/README' <<'END_OF_FILE'
  469. XConf subdirectory
  470. X-----------------
  471. X
  472. XThis directory contains tools (scrips) and data (Makefile fragments)
  473. Xused to build various ports of stdwin and applications that use it on
  474. Xvarious UNIX-based platforms.
  475. X
  476. XAn explanation of some of the terms used may be in order:
  477. X
  478. XA "port" of stdwin consists of code that implements the portable stdwin
  479. Xinterface on top of a particular lower-level interface, e.g., there is a
  480. Xport for X11, called "x11", and a port for ASCII terminals using the
  481. Xtermcap library, called "alfa"; there are also ports to the Macintosh
  482. Xand the Atari ST, etc.  Ports can share code; in particular, some
  483. Xlibrary packages built on top of stdwin (like "textedit") are used with
  484. Xall ports, and some low-level routines (like "strdup") are used by all
  485. Xports.  Ports are structured as libraries that must be linked with
  486. Xapplications.
  487. X
  488. XA "platform" is a combination of operating system and machine
  489. Xarchitecture on which you might want to use stdwin.  The x11 and alfa
  490. Xports work on many platforms, and most of those platforms support both
  491. Xports.  The current set-up identifies platforms with architectures;
  492. Xwhile several operating systems are used on multiple architectures
  493. X(e.g., SunOS on sun3 and sun4 architectures), few architectures offer a
  494. Xchoice of operating system.  (If this simplification becomes a real
  495. Xproblem, we'll simply change the maning of architecture identifiers into
  496. Xplatform identifiers, so we might have platforms "ultvax" and "bsdvax"
  497. Xfor a VAX under Ultrix and a VAX under BSD, respectively.)
  498. X
  499. XA "component" is either a port library, a package library, or an
  500. Xapplication program.  Components are the smallest units that have
  501. XMakefiles.  There is one set of sources for a particular component, used
  502. Xon all platforms.  Package and application components are also used with
  503. Xdifferent ports, again using the same set of sources.
  504. X
  505. XObjects live in a different part of the stdwin tree than sources.  This
  506. Xsubtree is rooted at the Build subdirectory of the tree.  We certainly
  507. Xneed a subtree per port, since two or more ports can co-exist on most
  508. Xplatforms; but we also need a subtree per platform, since, through the
  509. Xwonders of NFS, a single file system containing the stdwin tree may be
  510. Xmounted on totally different systems.  Hence, the Build subtree has two
  511. Xlevels of subdirectories before we are getting to business, one per
  512. Xarchitecture (really per platform), one per port.  The scripts have a
  513. Xfew provisions to create build trees in nonstandard places if you need
  514. Xmore freedom.
  515. X
  516. XThe subtree structure under Build is as follows:
  517. X
  518. XBuild/<arch>/            subtree for a particular architecture
  519. X                or platform (<arch> can be sun3, sun4,
  520. X                vax etc.)
  521. X
  522. XBuild/<arch>/<port>/        subtree for a particular port
  523. X                (<port> can be alfa or x11)
  524. X
  525. XBuild/<arch>/<port>/lib/    the main library component for the port
  526. X                is built here
  527. X
  528. XBuild/<arch>/<port>/lib/lib.a    library file to link with applications
  529. X
  530. XBuild/<arch>/<port>/<pack>/
  531. XBuild/<arch>/<port>/<appl>/    each application or package library
  532. X                component is built in its own
  533. X                subdirectory
  534. X
  535. XThe Makefiles are all generated automatically by scripts that live in
  536. Xthe Conf subdirectory.  They are created from four sources:
  537. X
  538. Xa)    The concatenation of Makefile fragments that contain definitions
  539. X    specific to:
  540. X        - the port
  541. X        - the architecture (or platform)
  542. X        - the operating system
  543. X    These fragments live in the Conf subdirectory.  Fragments for
  544. X    all supported ports, and platforms are provided, as well as
  545. X    templates that can be used to create new fragments.  These serve
  546. X    as documentation for the fragments as well.
  547. X
  548. Xb)    A Makefile fragment specific to the component being built.
  549. X    It defines which sources are needed and how they must be
  550. X    combined.  The sources can come form any number of directories
  551. X    besides the component's main source directory.  The object names
  552. X    are derived from the source names.  There are two methods of
  553. X    combining objects right now: libraries are created with "ar"
  554. X    (and optionally "ranlib"), applications are created by linking
  555. X    all objects together.  These Makefile fragments live in the main
  556. X    source directory of the component (library or application) being
  557. X    built.  The actual rules for building and creating the objects
  558. X    are not contained in the fragments; rather, a bit of "bootstrap
  559. X    magic" is used.
  560. X
  561. Xc)    The bootstrap magic consists of a Make rule in the
  562. X    component-specific fragment.  This rule calls a program
  563. X    "putprogmf" or "putlibmf" (depending on the component type) with
  564. X    the list of source files used; the output is concatenated with
  565. X    the Makefile fragments listed previously to produce a Makefile
  566. X    that can build the component on the given platform using the
  567. X    given port library (in case of an application).
  568. X
  569. Xd)    Full dependencies are added to the Makefile later.  Each
  570. X    Makefile contains a rule "depend" which updates the Makefile
  571. X    (in place!) with the current dependencies.  This should be run
  572. X    once after the Makefile is built, and later when the dependency
  573. X    structure of the sources is changed.  The dependencies are not
  574. X    added when the Makefile is created initially, since the script
  575. X    that computes dependencies *must* run on the platform where the
  576. X    component is actually being built, while the Makefile can be
  577. X    created (through NFS) from another platform.
  578. END_OF_FILE
  579. if test 5259 -ne `wc -c <'Conf/README'`; then
  580.     echo shar: \"'Conf/README'\" unpacked with wrong size!
  581. fi
  582. # end of 'Conf/README'
  583. fi
  584. if test -f 'Doc/man/editwin.man' -a "${1}" != "-c" ; then 
  585.   echo shar: Will not clobber existing file \"'Doc/man/editwin.man'\"
  586. else
  587. echo shar: Extracting \"'Doc/man/editwin.man'\" \(8791 characters\)
  588. sed "s/^X//" >'Doc/man/editwin.man' <<'END_OF_FILE'
  589. X.TH EDITWIN 3
  590. X.SH NAME
  591. XEditwin \- editing windows package for STDWIN
  592. X.SH SYNOPSIS
  593. X.nf
  594. X.ft C
  595. X#include "stdwin.h"
  596. X#include "editwin.h"
  597. X
  598. Xtypedef struct editwin {
  599. X    WINDOW *win;
  600. X    TEXTEDIT *tp;
  601. X    char *filename;
  602. X    char saved;
  603. X} EDITWIN;
  604. X
  605. XEDITWIN *ewcreate(char *filename);
  606. XEDITWIN *ewnew();
  607. XEDITWIN *ewopen();
  608. X
  609. Xbool ewsave(EDITWIN *ew);
  610. Xbool ewsaveas(EDITWIN *ew);
  611. Xbool ewsavecopy(EDITWIN *ew);
  612. Xbool ewsaveall();
  613. Xbool ewrevert(EDITWIN *ew);
  614. Xbool ewclose(EDITWIN *ew);
  615. Xbool ewcloseall();
  616. X
  617. Xbool ewwritefile(EDITWIN *ew, char *filename);
  618. Xbool ewreadfile(EDITWIN *ew, char *filename);
  619. X
  620. Xbool ewevent(EDITWIN *ew, EVENT *e, int *closed_return);
  621. Xvoid ewreplace(EDITWIN *ew, char *str);
  622. Xvoid ewundo(EDITWIN *ew); /* Not implemented */
  623. Xvoid ewcopy(EDITWIN *ew);
  624. Xvoid ewpaste(EDITWIN *ew);
  625. X
  626. XEDITWIN *ewfind(WINDOW *win);
  627. Xint ewcount();
  628. X.ft 1
  629. X.fi
  630. X.SH DESCRIPTION
  631. X.I Editwin
  632. Xis a package built on top of the
  633. X.I textedit
  634. Xpackage, to ease the construction of views on text files etc.
  635. XMany calls exist to make it extremely simple to respond to standard
  636. Xmenus of
  637. X.B File
  638. Xoperations (New, Open..., Save, etc.) and
  639. X.B Edit
  640. Xoperations (Cut, Copy, Paste).
  641. X.PP
  642. XBelow are descriptions of the individual functions.
  643. XNote that when a reference is made to a window's contents, the entire
  644. Xcontents of the edit buffer belonging to the window is meant, not just
  645. Xthe part of it visible in the window.
  646. X.IP ewcreate
  647. XIf
  648. X.I filename
  649. Xis a nil pointer, this call creates an ``Untitled'' edit window.
  650. XOtherwise, the specified file must exist, and an edit window showing
  651. Xits contents is created.
  652. XIn both cases, the window's `saved' flag is set initially.
  653. XA pointer to a newly allocated EDITWIN struct is returned.
  654. XIf something went wrong (e.g., insufficient memory, or an unreadable
  655. Xfile was specified), a nil pointer is returned.
  656. X.IP ewnew
  657. XThis function can be called in response to the selection of the
  658. X.B New
  659. Xmenu item.
  660. XIt is equivalent to a call to
  661. X.I ewcreate((char*)0).
  662. X.IP ewopen
  663. XCall this function for the
  664. X.B Open...
  665. Xmenu item.
  666. XIt asks the user for an existing file name (using
  667. X.IR waskfile ),
  668. Xand then calls
  669. X.I ewcreate
  670. Xwith that file name as parameter.
  671. XIt returns nil if the dialog was cancelled or
  672. X.I ewcreate
  673. Xreturns nil.
  674. X.IP ewsave
  675. XCall this function for the
  676. X.B Save
  677. Xmenu item.
  678. XIf the window's contents were modified since they were last read or
  679. Xsaved, the function attempts to save the window to its file.
  680. XIf the window was still ``Untitled'', the user is first asked to specify
  681. Xa file name.
  682. XThe function returns true (nonzero) if the contents were actually saved,
  683. Xor didn't need saving.
  684. X.IP ewsaveas
  685. XCall this function for the
  686. X.B Save As...
  687. Xmenu item.
  688. XIt asks the user for a new file name to save the window's contents, and
  689. Xif the saving succeeds, sets this to be the file name to which future
  690. Xsave operations are directed.
  691. X.IP ewsavecopy
  692. XCall this function for the
  693. X.B Save a Copy...
  694. Xmenu item.
  695. XLike
  696. X.IR ewsaveas ,
  697. Xthis function asks file a new file name and saves the window's contents
  698. Xto that file; but it does not change the file name used for future save
  699. Xoperations.
  700. X.IP ewsaveall
  701. XCalls
  702. X.I ewsave
  703. Xfor all windows.
  704. XIf any call returns false (zero),
  705. X.I ewsaveall
  706. Xskips further calls and returns false.
  707. X.IP ewrevert
  708. XCall this function for the
  709. X.B Revert...
  710. Xmenu item.
  711. XIt attempts to undo any changes since the window was last read or
  712. Xsaved, by re-reading the corresponding file.
  713. XIf this is at all possible, the user is asked to confirm the operation
  714. Xfirst (since it may destroy valuable changes).
  715. XThe function returns true if the file was actually read back, or if the
  716. Xwindow was unchanged with respect to the file.
  717. X.IP ewclose
  718. XCloses the window.
  719. XIf the window was changed since it was last read or saved, the user is
  720. Xfirst asked whether it should be saved, and if the answer is Yes,
  721. X.I ewsave
  722. Xis called.
  723. XCancelling the dialog will prevent closing the window.
  724. XReturns true if the window was actually closed.
  725. X.IP ewcloseall
  726. XCalls
  727. X.I ewclose
  728. Xfor all windows.
  729. XIf any call returns false,
  730. X.I ewcloseall
  731. Xskips further calls and returns false.
  732. X.IP ewwritefile
  733. XWrites the contents of the edit window to the specified file.
  734. XReturns true if the operation succeeded.
  735. XThis does
  736. X.I not
  737. Xset the `saved' flag for the window (because it is used internally be
  738. X.IR ewsavecopy ).
  739. X.IP ewreadfile
  740. XReads the contents of the given file into the edit window, discarding
  741. Xits previous contents.
  742. XReturns true if the operation succeeded.
  743. XThis
  744. X.I does
  745. Xset the `saved' flag for the window.
  746. X.IP ewevent
  747. XCall this function in response to
  748. X.I any
  749. Xevent returned by
  750. X.I wgetevent.
  751. XIf the event is a non-menu event applicable to the specified window, it
  752. Xis handled and the function returns true;
  753. Xotherwise nothing is done and the function returns false.
  754. X(Menu events cannot be handled this way because the editwin package
  755. Xdoesn't create its own menus, and thus cannot know the menu IDs or the
  756. Xnumbers of the menu items.)
  757. XIf the first parameter is a nil pointer, the event is checked against
  758. Xany edit window; otherwise, only events applying to the given window are
  759. Xhandled.
  760. XThe third parameter must be a pointer to an integer variable, which is
  761. Xcleared normally when an event was handled, but set to true when a
  762. Xwindow was closed as a consequence of the event (it is unchanged when
  763. Xthe event was nbot handled at all).
  764. XIn the latter case, the caller should check whether any windows are
  765. Xstill open (see
  766. X.IR ewcount ),
  767. Xand if this is not the case, it should either exit or open a new window.
  768. XThis function clears a window's `saved' flag whenever its contents are
  769. Xmodified by the event's handling.
  770. X.IP ewreplace
  771. XReplaces the current text selection in the window by the given
  772. X(null-terminated) string.
  773. XThis will insert text if the text selection was an insert point.
  774. X.IP ewundo
  775. XReserved for future extension of the package with an Undo facility.
  776. X.IP ewcopy
  777. XCall this function for the
  778. X.B Copy
  779. Xmenu item.
  780. XIt retrieves the contents of the window's text selection, if non-null,
  781. Xand copies it in into the clipboard through a call to
  782. X.I wsetclip.
  783. XIt beeps if the text selection is empty.
  784. X(To implement the
  785. X.B Cut
  786. Xmenu item, call
  787. X.I ewcopy
  788. Xfollowed by
  789. X.IR "ewreplace(ew, ``'')" .)
  790. X.IP ewpaste
  791. XCall this function for the
  792. X.B Paste
  793. Xmenu item.
  794. XIt retrieves the contents of the clipboard, if non-null,
  795. Xand pastes it into the window through a call to
  796. X.I ewreplace.
  797. XIt beeps (and does not change the window's contents) if the clipboard is
  798. Xempty.
  799. X.IP ewfind
  800. XReturns a pointer to the EDITWIN struct containing the given WINDOW
  801. Xpointer; returns nil if none exists.
  802. X.IP ewcount
  803. XReturns the number of open edit windows.
  804. X.SH EXAMPLE
  805. XThe following program is a trivial but almost usable single-file text
  806. Xeditor.
  807. XUsage is ``program [file]''.
  808. X.nf
  809. X.ft C
  810. X
  811. X#include "stdwin.h"
  812. X#include "editwin.h"
  813. X
  814. Xmain(argc, argv) int argc; char **argv; {
  815. X    EDITWIN *ew;
  816. X    winitnew(&argc, &argv);
  817. X    if (argc <= 1) ewnew();
  818. X    else           ewcreate(argv[1]);
  819. X    for (;;) {
  820. X        EVENT e;
  821. X        int closed;
  822. X        wgetevent(&e);
  823. X        if (ewevent(ew, &e, &b) && closed) break;
  824. X    }
  825. X    wdone();
  826. X    exit(0);
  827. X}
  828. X.ft 1
  829. X.fi
  830. X.SH HINTS
  831. XThe members of the EDITWIN data structure are explicitly intended to be
  832. Xaccessible to the caller.
  833. XFunctionality which is not provided directly but which is available for
  834. Xplain windows or for textedit data structures can be implemented by
  835. Xapplying it to the
  836. X.I win
  837. Xor
  838. X.I tp
  839. Xmembers.
  840. XNote that the
  841. X.I filename
  842. Xmember, when non-nil, points to memory allocated with
  843. X.IR malloc (3).
  844. X.PP
  845. XChanges to the window's contents should preferably be made with
  846. X.I ewreplace,
  847. Xsince it manages the `saved' flag.
  848. X.PP
  849. XTo control the text attributes used in an EDITWIN window, you can set
  850. Xthem globally before creating the window.
  851. X.SH DIAGNOSTICS
  852. X.I Ewcreate, ewnew
  853. Xand
  854. X.I ewopen
  855. Xreturn nil when the user cancelled the operation or when they could not
  856. Xget all the necessary memory.
  857. XThe save, revert, close and read/write family of functions return FALSE
  858. Xif the operation was canceled by the user or if the file I/O failed.
  859. X.I Ewevent
  860. Xreturns TRUE when it has processed the event.
  861. X.PP
  862. X.I Ewcreate
  863. Xand
  864. X.I ewopen
  865. Xwarn the user if a file is larger than about 30K; the textedit package
  866. Xwas not designed to operate on big files, and may be intolerably slow.
  867. X.SH SEE ALSO
  868. XSTDWIN documentation
  869. X.br
  870. Xtextedit(3)
  871. X.SH AUTHOR
  872. XGuido van Rossum
  873. X.SH BUGS
  874. X.I Editwin
  875. Xinherits some bugs from the
  876. X.I textedit
  877. Xpackage.
  878. X.br
  879. XThe package doesn't detect the situation where the user opens the same
  880. Xfile twice, edits both copies, and saves them, thus losing the
  881. Xchanges to the copy saved first.
  882. X.br
  883. XIf the height of the document gets over 32K scan lines, you are
  884. Xin trouble: most window systems limit coordinates to short integers.
  885. X.br
  886. XMissing functionality:
  887. Xa way to specify an alternate title for an untitled window;
  888. Xa way to create a non-file window, which isn't saved when closed.
  889. X(These should be easy to add, given the simplicity of the source.)
  890. END_OF_FILE
  891. if test 8791 -ne `wc -c <'Doc/man/editwin.man'`; then
  892.     echo shar: \"'Doc/man/editwin.man'\" unpacked with wrong size!
  893. fi
  894. # end of 'Doc/man/editwin.man'
  895. fi
  896. if test -f 'Packs/vt/vtselect.c' -a "${1}" != "-c" ; then 
  897.   echo shar: Will not clobber existing file \"'Packs/vt/vtselect.c'\"
  898. else
  899. echo shar: Extracting \"'Packs/vt/vtselect.c'\" \(9625 characters\)
  900. sed "s/^X//" >'Packs/vt/vtselect.c' <<'END_OF_FILE'
  901. X/* Copy and paste operations for VT.
  902. X   The selections here are not rectangles,
  903. X   like in most other vt-stuff */
  904. X
  905. X/* XXX This must be redesigned.
  906. X   In the new design, the event loop is in the caller and we remember
  907. X   the state somehow in the vt structure.
  908. X   This is necessary to make it independent of aterm (special semantics
  909. X   of WE_EXTERN events) and to support extending the selection with the
  910. X   third button.
  911. X*/
  912. X
  913. X#include "vtimpl.h"
  914. X
  915. X
  916. Xextern int extra_downs; /* For aterm */
  917. X
  918. X
  919. X/* Data structure used by coord_sort */
  920. X
  921. Xstruct coord {        /* A coordinate */
  922. X    int c, r;    /* Column and row */
  923. X};
  924. X
  925. X/*
  926. X *    Bubblesort an array of coordinates.
  927. X */
  928. Xstatic void
  929. Xcoord_sort(coord, n)
  930. X    struct coord coord[];
  931. X    int n;
  932. X{
  933. X    int i, j, big;
  934. X    /* Bubble */
  935. X    for (j = n; --j > 0; ) {
  936. X    /* Find biggest in 0..j */
  937. X    for (big = i = 0; ++i <= j; ) { /* Compare big and i */
  938. X        if (coord[big].r < coord[i].r ||
  939. X        (coord[big].r == coord[i].r && coord[big].c < coord[i].c))
  940. X        big = i; /* Found a bigger one */
  941. X    }
  942. X    if (big != j) {
  943. X        struct coord swap;
  944. X        swap = coord[big]; coord[big] = coord[j]; coord[j] = swap;
  945. X    }
  946. X    }
  947. X}
  948. X
  949. X/*
  950. X *    Delete double occurences in a sorted
  951. X *    array of coordinates (Both of them!)
  952. X */
  953. Xstatic int
  954. Xno_double(coord, n)
  955. X    struct coord coord[];
  956. X    int n;
  957. X{
  958. X    int i, j;
  959. X    for (i = j = 0; i < n; ) {
  960. X    if (i < n - 1 && coord[i].r == coord[i + 1].r
  961. X    && coord[i].c == coord[i + 1].c) {
  962. X        i += 2; /* Skip both */
  963. X    }
  964. X    else {
  965. X        if (i != j) coord[j] = coord[i]; /* Copy */
  966. X        ++i; ++j;
  967. X    }
  968. X    }
  969. X    return j; /* Return # array elements */
  970. X}
  971. X
  972. X/*
  973. X *    Set the selection of a vt, update state variables
  974. X */
  975. Xstatic void
  976. Xset_selection(vt, row1, col1, row2, col2)
  977. X    VT *vt;
  978. X    int row1, col1, row2, col2;
  979. X{
  980. X    /* Screen coordinates of begins/ends of selection */
  981. X    struct coord coord[4];
  982. X    int n_coord, i;
  983. X
  984. X    /* Above last remembered line; repair */
  985. X    if (row1 < -vt->topterm) {
  986. X        row1 = -vt->topterm;
  987. X        col1 = 0;
  988. X    }
  989. X
  990. X    /* Initialise array */
  991. X    coord[0].r = vt->sel_row1;
  992. X    coord[0].c = vt->sel_col1;
  993. X    coord[1].r = vt->sel_row2;
  994. X    coord[1].c = vt->sel_col2;
  995. X    coord[2].r = row1;
  996. X    coord[2].c = col1;
  997. X    coord[3].r = row2;
  998. X    coord[3].c = col2;
  999. X
  1000. X    /* Sort, optimise */
  1001. X    coord_sort(coord, 4);
  1002. X    n_coord = no_double(coord, 4);
  1003. X
  1004. X    /* Blit */
  1005. X    if (n_coord > 0) {
  1006. X    VTBEGINDRAWING(vt);
  1007. X    for (i = 0; i < n_coord; i += 2)
  1008. X        vtinvert(vt, coord[i].r, coord[i].c, coord[i+1].r, coord[i+1].c);
  1009. X    VTENDDRAWING(vt);
  1010. X    }
  1011. X
  1012. X    /* Save state */
  1013. X    vt->sel_row1 = row1;
  1014. X    vt->sel_col1 = col1;
  1015. X    vt->sel_row2 = row2;
  1016. X    vt->sel_col2 = col2;
  1017. X} /* set_selection */
  1018. X
  1019. X
  1020. X/* Pass the selection to STDWIN.
  1021. X   Always set cut buffer 0, also try primary selection.
  1022. X   Return success/failure of the latter. */
  1023. X
  1024. Xstatic int
  1025. Xpass_selection(vt, data, len)
  1026. X    VT *vt;
  1027. X    char *data;
  1028. X    int len;
  1029. X{
  1030. X    wsetcutbuffer(0, data, len);
  1031. X    return wsetselection(vt->win, WS_PRIMARY, data, len);
  1032. X}
  1033. X
  1034. X
  1035. X/* Interface to STDWIN selection and cut buffer: save the copied text.
  1036. X   Returns success/failure */
  1037. X
  1038. Xstatic int
  1039. Xextract_selection(vt, row1, col1, row2, col2)
  1040. X    VT *vt;
  1041. X{
  1042. X    /* Swap if needed to make sure (row1, col1) <= (row2, col2) */
  1043. X    if (row1 > row2 || row1 == row2 && col1 > col2) {
  1044. X    register int scratch;
  1045. X    scratch = row1; row1 = row2; row2 = scratch;
  1046. X    scratch = col1; col1 = col2; col2 = scratch;
  1047. X    }
  1048. X
  1049. X    /* Make sure (0, 0) <= (row1, col1) and (row2, col2) <= (vt->rows, 0) */
  1050. X    if (row1 < 0) { row1 = 0; col1 = 0; }
  1051. X    if (row2 > vt->rows) { row2 = vt->rows; col2 = 0; }
  1052. X
  1053. X    /* Now, if (row1, col1) >= (row2, col2), the selection is empty */
  1054. X    if (row1 > row2 || row1 == row2 && col1 >= col2) {
  1055. X    wresetselection(WS_PRIMARY); /* Clear any previous selection */
  1056. X    return 1;
  1057. X    }
  1058. X
  1059. X    /* Check for simple case -- everything on one line */
  1060. X    if (row1 == row2 && col2 <= vt->llen[row2])
  1061. X    return pass_selection(vt, vt->data[row1] + col1, col2 - col1);
  1062. X
  1063. X    /* Harder case: more lines, or one line + end-of-line */
  1064. X
  1065. X    {
  1066. X    char *str, *p;
  1067. X    int ok;
  1068. X
  1069. X    /* Get (more than) enough memory, fail if can't get it */
  1070. X    p = str = malloc((row2 - row1 + 1) * (vt->cols + 1));
  1071. X    if (p == NULL) return 0; /* Fail */
  1072. X
  1073. X    /* Copy first line, add a newline */
  1074. X    if (col1 < vt->llen[row1]) {
  1075. X        strncpy(p, vt->data[row1] + col1, vt->llen[row1] - col1);
  1076. X        p += vt->llen[row1] - col1;
  1077. X    }
  1078. X    *p++ = '\n';
  1079. X
  1080. X    /* Copy intermediate lines, adding newlines */
  1081. X    while (++row1 < row2) {
  1082. X        strncpy(p, vt->data[row1], vt->llen[row1]);
  1083. X        p += vt->llen[row1];
  1084. X        *p++ = '\n';
  1085. X    }
  1086. X
  1087. X    /* Copy last line -- if this is not the first as well, nor too far */
  1088. X    if (row1 == row2 && row2 < vt->rows) {
  1089. X        if (col2 <= vt->llen[row2]) {
  1090. X        strncpy(p, vt->data[row2], col2);
  1091. X        p += col2;
  1092. X        }
  1093. X        else {
  1094. X        /* Beyond last char, copy a \n as well */
  1095. X        strncpy(p, vt->data[row2], vt->llen[row2]);
  1096. X        p += vt->llen[row2];
  1097. X        *p++ = '\n';
  1098. X        }
  1099. X    }
  1100. X
  1101. X    /* Pass the string to STDWIN, free it, and return success */
  1102. X    ok = pass_selection(vt, str, (int) (p - str));
  1103. X    free(str);
  1104. X    return ok;
  1105. X    }
  1106. X}
  1107. X
  1108. X
  1109. X/* Symbolic values for the modes we can be in while selecting: */
  1110. X
  1111. X#define SEL_CHARS    0    /* Selecting chars */
  1112. X#define SEL_WORDS    1    /* Selecting words */
  1113. X#define SEL_LINES    2    /* Selecting lines */
  1114. X#define SEL_KINDS    3    /* How many modes we know */
  1115. X
  1116. X/* Macros to distinguish between various "brands" of characters.
  1117. X   A "word" is a sequence of characters of the same brand */
  1118. X
  1119. X#define BRAND_LETTER    0
  1120. X#define BRAND_SPACE    1
  1121. X#define BRAND_PUNCT    2
  1122. X
  1123. X/* Determine the brand of a character */
  1124. X
  1125. Xstatic int
  1126. Xbrand(ch)
  1127. X    int ch;
  1128. X{
  1129. X    return (('a' <= ch && ch <= 'z') ||
  1130. X     ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9') ||
  1131. X     (ch == '_') ? BRAND_LETTER :
  1132. X     (ch == ' ' || ch == '\t') ? BRAND_SPACE : BRAND_PUNCT);
  1133. X}
  1134. X
  1135. X
  1136. X/* Called by the mainloop upon a mouse-down. Exits when the mouse is
  1137. X   up again; any other intermediate events terminates the selection.
  1138. X   Returns whether the selection succeeded */
  1139. X
  1140. Xint
  1141. Xvtselect(vt, e)
  1142. X    VT *vt;
  1143. X    EVENT *e;
  1144. X{
  1145. X    int first_row, first_col; /* Coords save at mouse-down */
  1146. X    int was_lazy; /* Zapped because vtsetcursor is lazy as well */
  1147. X    int csr_row, csr_col; /* Cursor saved at mouse-down */
  1148. X    int button_down = 1; /* That's the reason we're called after all */
  1149. X    int sel_mode = SEL_CHARS; /* This one is not yet handled */
  1150. X    int timer_pending = 0;
  1151. X    int success = 1; /* We are optimists */
  1152. X
  1153. X    /* Save cursor position */
  1154. X    was_lazy = vt->lazy; vt->lazy = 0;
  1155. X    csr_row = vt->cur_row;
  1156. X    csr_col = vt->cur_col;
  1157. X
  1158. X    /* Init */
  1159. X    first_row = e->u.where.v / vt->cheight;
  1160. X    first_col = (e->u.where.h + vt->cwidth/2) / vt->cwidth;
  1161. X    if (first_col > vt->llen[first_row]) {
  1162. X    /* Clicked beyond eoln; use first char on next line instead */
  1163. X    ++first_row;
  1164. X    first_col = 0;
  1165. X    }
  1166. X
  1167. X    vtsetcursor(vt, first_row, first_col);
  1168. X
  1169. X    do {
  1170. X    int row, col; /* Current mouse position */
  1171. X
  1172. X    wgetevent(e);
  1173. X    switch (e->type) {
  1174. X    case WE_MOUSE_UP:
  1175. X        button_down = 0;
  1176. X        wsettimer(vt->win, 2);
  1177. X        timer_pending = 1;
  1178. X        break;
  1179. X    case WE_MOUSE_MOVE:
  1180. X        break;
  1181. X    case WE_MOUSE_DOWN:
  1182. X        if (e->u.where.button != 1) {
  1183. X        /* E.g. paste-button; stop selection */
  1184. X        timer_pending = button_down = 0;
  1185. X        wungetevent(e);
  1186. X        break;
  1187. X        }
  1188. X        button_down = 1;
  1189. X        sel_mode = (sel_mode + 1) % SEL_KINDS;
  1190. X        break;
  1191. X    case WE_EXTERN:    /* Got output from child - save */
  1192. X        ++extra_downs;
  1193. X        continue;    /* Get next event */
  1194. X    case WE_TIMER:
  1195. X        timer_pending = 0;
  1196. X        break;
  1197. X    default:
  1198. X        wungetevent(e);
  1199. X        success = 0;
  1200. X        goto reset;
  1201. X    }
  1202. X
  1203. X    /*
  1204. X     * We only get here when we want
  1205. X     * to draw the current selection;
  1206. X     * Compute new coords
  1207. X     */
  1208. X
  1209. X    row = e->u.where.v / vt->cheight;
  1210. X    col = (e->u.where.h + vt->cwidth/2) / vt->cwidth;
  1211. X    vtsetcursor(vt, row, col);
  1212. X
  1213. X#if 0    /* To do: Make sure everything in the neighbourhood can be seen: */
  1214. X    /* This does not work; it's far too fast */
  1215. X    if (vt->rows > 3 && vt->cols > 3)
  1216. X        wshow(vt->win,
  1217. X        e->u.where.h - vt->cwidth, e->u.where.v - vt->cheight,
  1218. X        e->u.where.h + vt->cwidth, e->u.where.v + vt->cheight);
  1219. X#endif
  1220. X
  1221. X    switch (sel_mode) {
  1222. X    int rs, cs;
  1223. X    case SEL_CHARS:
  1224. X    case SEL_WORDS:
  1225. X        /* Clip row and col */
  1226. X        if (row > vt->rows) row = vt->rows;
  1227. X        else if (row < 0) row = 0;
  1228. X        if (col > vt->cols) col = vt->cols;
  1229. X        else if (col < 0) col = 0;
  1230. X        rs = first_row;
  1231. X        cs = first_col;
  1232. X        if (sel_mode == SEL_CHARS) {
  1233. X        /* Select including the eoln when beyond last char */
  1234. X        if (vt->llen[row] < col) col = vt->cols;
  1235. X        } else {
  1236. X        /* Sort coordinates */
  1237. X        if (rs > row || (rs == row && cs > col)) {
  1238. X            register tmp;
  1239. X            tmp = row; row = rs; rs = tmp;
  1240. X            tmp = col; col = cs; cs = tmp;
  1241. X        }
  1242. X        /* Expand */
  1243. X        while (cs > 0 &&
  1244. X            brand(vt->data[rs][cs]) == brand(vt->data[rs][cs - 1]))
  1245. X            --cs;
  1246. X        if (col >= vt->llen[row]) col = vt->cols;
  1247. X        else while (++col < vt->llen[row] &&
  1248. X            brand(vt->data[row][col - 1]) == brand(vt->data[row][col]))
  1249. X            ;
  1250. X        }
  1251. X        /* Update screen */
  1252. X        set_selection(vt, rs, cs, row, col);
  1253. X        break;
  1254. X    case SEL_LINES:
  1255. X        if (++row > vt->rows) row = vt->rows;
  1256. X        set_selection(vt,
  1257. X        first_row >= row ? first_row + 1 : first_row, 0, row, 0);
  1258. X        break;
  1259. X    }
  1260. X
  1261. X    } while (button_down || timer_pending);
  1262. X
  1263. X    /* Now pass the selection to STDWIN */
  1264. X    if (!extract_selection(vt,
  1265. X            vt->sel_row1, vt->sel_col1, vt->sel_row2, vt->sel_col2))
  1266. X        wfleep(); /* Give the user some indication that it failed */
  1267. X
  1268. Xreset:
  1269. X    /* Invert back to normal:    */
  1270. X    set_selection(vt, 0, 0, 0, 0);
  1271. X    vtsetcursor(vt, csr_row, csr_col);
  1272. X    vt->lazy = was_lazy;
  1273. X    return success;
  1274. X}
  1275. X
  1276. X
  1277. X/* Extend the selection */
  1278. X
  1279. Xint
  1280. Xvtextendselection(vt, ep)
  1281. X    VT *vt;
  1282. X    EVENT *ep;
  1283. X{
  1284. X    /* XXX not yet implemented */
  1285. X    wfleep();
  1286. X    return 0;
  1287. X}
  1288. END_OF_FILE
  1289. if test 9625 -ne `wc -c <'Packs/vt/vtselect.c'`; then
  1290.     echo shar: \"'Packs/vt/vtselect.c'\" unpacked with wrong size!
  1291. fi
  1292. # end of 'Packs/vt/vtselect.c'
  1293. fi
  1294. if test -f 'Ports/alfa/draw.c' -a "${1}" != "-c" ; then 
  1295.   echo shar: Will not clobber existing file \"'Ports/alfa/draw.c'\"
  1296. else
  1297. echo shar: Extracting \"'Ports/alfa/draw.c'\" \(8748 characters\)
  1298. sed "s/^X//" >'Ports/alfa/draw.c' <<'END_OF_FILE'
  1299. X/* ALFA STDWIN -- DRAWING. */
  1300. X
  1301. X#include "alfa.h"
  1302. X
  1303. Xstatic char *textline[MAXLINES];
  1304. Xstatic short textlen[MAXLINES];
  1305. Xstatic char texttouched[MAXLINES];
  1306. X
  1307. Xstatic TEXTATTR draw_saveattr;
  1308. Xstatic WINDOW *draw_win;
  1309. X
  1310. X/* Cause a redraw of part of a window. */
  1311. X
  1312. X/*ARGSUSED*/
  1313. Xvoid
  1314. Xwchange(win, left, top, right, bottom)
  1315. X    WINDOW *win;
  1316. X    int left, top;
  1317. X    int right, bottom;
  1318. X{
  1319. X    int id= win - winlist;
  1320. X    int i;
  1321. X    
  1322. X    if (id < 0 || id >= MAXWINDOWS || !win->open)
  1323. X        return;
  1324. X    top -= win->offset;
  1325. X    bottom -= win->offset;
  1326. X    if (top < win->top)
  1327. X        top= win->top;
  1328. X    if (bottom > win->bottom)
  1329. X        bottom= win->bottom;
  1330. X    for (i= top; i < bottom; ++i)
  1331. X        uptodate[i]= FALSE;
  1332. X    _wnewtitle(win);
  1333. X}
  1334. X
  1335. X/* (Try to) make sure a particular part of a window is visible,
  1336. X   by scrolling in distant parts if necessary. */
  1337. X
  1338. Xvoid scrollupdate();
  1339. X
  1340. X/*ARGSUSED*/
  1341. Xvoid
  1342. Xwshow(win, left, top, right, bottom)
  1343. X    WINDOW *win;
  1344. X    int left, top;
  1345. X    int right, bottom;
  1346. X{
  1347. X    int id= win - winlist;
  1348. X    int offset;
  1349. X    int extra;
  1350. X    int dv;
  1351. X    
  1352. X    if (id < 0 || id >= MAXWINDOWS || !win->open)
  1353. X        return;
  1354. X    extra= ( (win->bottom - win->top) - (bottom - top) ) / 2;
  1355. X    if (extra < 0)
  1356. X        extra= 0;
  1357. X    offset= win->offset;
  1358. X    if (bottom > win->bottom + offset)
  1359. X        offset= bottom - win->bottom + extra;
  1360. X    if (top < win->top + offset)
  1361. X        offset= top - win->top - extra;
  1362. X    if (win->top + offset < 0)
  1363. X        offset= -win->top;
  1364. X    dv= offset - win->offset;
  1365. X    if (dv == 0)
  1366. X        return;
  1367. X    win->offset= offset;
  1368. X    /* Now we'll use top, bottom to indicate the changed part. */
  1369. X    top= win->top;
  1370. X    bottom= win->bottom;
  1371. X    scrollupdate(top, bottom, dv);
  1372. X    trmscrollup(top, bottom-1, dv);
  1373. X}
  1374. X
  1375. X/* Similar, but by giving an explicit new origin */
  1376. X
  1377. X/*ARGSUSED*/
  1378. Xvoid
  1379. Xwsetorigin(win, h, v)
  1380. X    WINDOW *win;
  1381. X    int h, v;
  1382. X{
  1383. X    int id= win - winlist;
  1384. X    int top, bottom;
  1385. X    int dv;
  1386. X
  1387. X    if (id < 0 || id >= MAXWINDOWS || !win->open)
  1388. X        return;
  1389. X    dv = (v - win->top) - win->offset;
  1390. X    if (dv == 0)
  1391. X        return;
  1392. X    win->offset += dv;
  1393. X    top = win->top;
  1394. X    bottom = win->bottom;
  1395. X    scrollupdate(top, bottom, dv);
  1396. X    trmscrollup(top, bottom-1, dv);
  1397. X}
  1398. X
  1399. X/* Scroll the update bits */
  1400. X
  1401. X/*ARGSUSED*/
  1402. Xvoid
  1403. Xscrollupdate(top, bottom, dv)
  1404. X    int top, bottom;
  1405. X    int dv;
  1406. X{
  1407. X    int i;
  1408. X
  1409. X#ifndef EUROGEMODDER
  1410. X    for (i= top; i < bottom; ++i)
  1411. X        uptodate[i] = FALSE;
  1412. X#else
  1413. X    char *p;
  1414. X
  1415. X    if(dv==0)
  1416. X        return;
  1417. X    if(dv > 0) {
  1418. X        for (i= top; i < bottom; ++i) {
  1419. X            if (uptodate[i+dv]) {
  1420. X                p=textline[i];
  1421. X                textline[i]=textline[i+dv];
  1422. X                textlen[i]=textlen[i+dv];
  1423. X                uptodate[i]= TRUE;
  1424. X                textline[i+dv]= p;
  1425. X                /*needed? textlen[i+dv]= 0; */
  1426. X                uptodate[i+dv]= FALSE;
  1427. X            } else {
  1428. X                uptodate[i]= FALSE;
  1429. X            }
  1430. X        }
  1431. X    } else {
  1432. X        for (i= bottom-1; i >= top; --i) {
  1433. X            if (uptodate[i+dv]) {
  1434. X                p=textline[i];
  1435. X                textline[i]=textline[i+dv];
  1436. X                textlen[i]=textlen[i+dv];
  1437. X                uptodate[i]= TRUE;
  1438. X                textline[i+dv]= p;
  1439. X                /*needed? textlen[i+dv]= 0; */
  1440. X                uptodate[i+dv]= FALSE;
  1441. X            } else {
  1442. X                uptodate[i]= FALSE;
  1443. X            }
  1444. X        }
  1445. X    }
  1446. X#endif
  1447. X}
  1448. X
  1449. X/* Set the caret (cursor) position. */
  1450. X
  1451. Xvoid
  1452. Xwsetcaret(win, h, v)
  1453. X    WINDOW *win;
  1454. X    int h, v;
  1455. X{
  1456. X    win->curh= h;
  1457. X    win->curv= v;
  1458. X    /* wshow(win, h, v, h+1, v+1); */
  1459. X    /* Shouldn't call wshow here -- it's not always desirable! */
  1460. X}
  1461. X
  1462. X/* Remove the caret altogether. */
  1463. X
  1464. Xvoid
  1465. Xwnocaret(win)
  1466. X    WINDOW *win;
  1467. X{
  1468. X    win->curh= win->curv= -1;
  1469. X}
  1470. X
  1471. X/* Cause a redraw of the window 's title bar. */
  1472. X
  1473. Xvoid
  1474. X_wnewtitle(win)
  1475. X    WINDOW *win;
  1476. X{
  1477. X    if (win->top > 0)
  1478. X        uptodate[win->top-1]= FALSE;
  1479. X}
  1480. X
  1481. X/* Compute the smallest rectangle that needs an update.
  1482. X   As a side effect, uptodate is set to TRUE for the affected lines,
  1483. X   and the lines are cleared and set to touched
  1484. X   (but no actual output is performed).
  1485. X   Return FALSE if the rectangle is empty. */
  1486. X
  1487. Xbool
  1488. Xwgetchange(win, pleft, ptop, pright, pbottom)
  1489. X    WINDOW *win;
  1490. X    int *pleft, *ptop, *pright, *pbottom;
  1491. X{
  1492. X    int top= win->bottom;
  1493. X    int bottom= win->top;
  1494. X    int i;
  1495. X    
  1496. X    for (i= win->top; i < win->bottom; ++i) {
  1497. X        if (!uptodate[i]) {
  1498. X            texttouched[i]= TRUE;
  1499. X            textlen[i]= 0;
  1500. X            uptodate[i]= TRUE;
  1501. X            if (top > i)
  1502. X                top= i;
  1503. X            bottom= i+1;
  1504. X        }
  1505. X    }
  1506. X    if (top > bottom) {
  1507. X        *pleft= *pright= *ptop= *pbottom= 0;
  1508. X        return FALSE;
  1509. X    }
  1510. X    else {
  1511. X        *pleft= 0;
  1512. X        *pright= columns;
  1513. X        *ptop= top + win->offset;
  1514. X        *pbottom= bottom + win->offset;
  1515. X        return TRUE;
  1516. X    }
  1517. X}
  1518. X
  1519. Xvoid
  1520. Xwupdate(win)
  1521. X    WINDOW *win;
  1522. X{
  1523. X    int left, top, right, bottom;
  1524. X    
  1525. X    wgetchange(win, &left, &top, &right, &bottom);
  1526. X    
  1527. X    wbegindrawing(win);
  1528. X    
  1529. X    if (win->drawproc != NULL)
  1530. X        (*win->drawproc)(win, 0, top, columns, bottom);
  1531. X    
  1532. X    wenddrawing(win);
  1533. X}
  1534. X
  1535. Xvoid
  1536. Xwbegindrawing(win)
  1537. X    WINDOW *win;
  1538. X{
  1539. X    int i;
  1540. X    
  1541. X    if (draw_win != NULL)
  1542. X        wenddrawing(draw_win); /* Finish previous job */
  1543. X    
  1544. X    /* Auto-initialization of the textline array.
  1545. X       The other arrays needn't be initialized,
  1546. X       since they are preset to zero. */
  1547. X    for (i= win->top; i < win->bottom; ++i) {
  1548. X        if (textline[i] == NULL)
  1549. X            textline[i]= malloc((unsigned) (columns+1));
  1550. X            /*uptodate[i]= FALSE;*/
  1551. X    }
  1552. X    
  1553. X    draw_saveattr= wattr;
  1554. X    wattr= win->attr;
  1555. X    draw_win= win;
  1556. X}
  1557. X
  1558. Xvoid
  1559. Xwenddrawing(win)
  1560. X    WINDOW *win;
  1561. X{
  1562. X    int i;
  1563. X    
  1564. X    if (draw_win != win) {
  1565. X        return; /* Bad call */
  1566. X    }
  1567. X    
  1568. X    for (i= win->top; i < win->bottom; ++i) {
  1569. X        if (texttouched[i]) {
  1570. X            texttouched[i]= FALSE;
  1571. X            textline[i][textlen[i]]= EOS;
  1572. X            trmputdata(i, i, 0, textline[i]);
  1573. X        }
  1574. X    }
  1575. X    
  1576. X    wattr= draw_saveattr;
  1577. X    draw_win= NULL;
  1578. X}
  1579. X
  1580. Xvoid
  1581. Xwdrawtitle(win)
  1582. X    WINDOW *win;
  1583. X{
  1584. X    int titline= win->top - 1;
  1585. X    char buf[256];
  1586. X    char *title= win->title == NULL ? "" : win->title;
  1587. X    int tlen= strlen(title);
  1588. X    int space= columns-tlen;
  1589. X    int mask= (win == front) ? 0200 : 0;
  1590. X    int k;
  1591. X    
  1592. X    for (k= 0; k < space/2 - 1; ++k)
  1593. X        buf[k]= '-'|mask;
  1594. X    buf[k++]= ' '|mask;
  1595. X    while (k < columns && *title != EOS)
  1596. X        buf[k++]= *title++|mask;
  1597. X    if (k < columns)
  1598. X        buf[k++]= ' '|mask;
  1599. X    while (k < columns)
  1600. X        buf[k++]= '-'|mask;
  1601. X    buf[k]= EOS;
  1602. X    trmputdata(titline, titline, 0, buf);
  1603. X    uptodate[titline]= TRUE;
  1604. X}
  1605. X
  1606. Xvoid
  1607. Xwdrawtext(h, v, str, len)
  1608. X    int h, v;
  1609. X    char *str;
  1610. X    int len;
  1611. X{
  1612. X    int k;
  1613. X    int mask= (wattr.style == 0) ? 0 : 0200;
  1614. X    char *text;
  1615. X    WINDOW *win= draw_win;
  1616. X    
  1617. X    if (len < 0)
  1618. X        len= strlen(str);
  1619. X    v -= win->offset;
  1620. X    if (v < win->top || v >= win->bottom || h >= columns || len == 0)
  1621. X        return;
  1622. X    text= textline[v];
  1623. X    k= textlen[v];
  1624. X    while (k < h)
  1625. X        text[k++]= ' ';
  1626. X    while (len > 0) {
  1627. X#define APPC(c) \
  1628. X    if (h >= 0) text[h]= (c) | mask; if (++h >= columns) break
  1629. X        unsigned char c= *str++;
  1630. X        --len;
  1631. X        if (c < ' ') {
  1632. X            APPC('^');
  1633. X            APPC(c | '@');
  1634. X        }
  1635. X        else  if (c < 0177) {
  1636. X            APPC(c);
  1637. X        }
  1638. X        else if (c < 0200) {
  1639. X            APPC('^');
  1640. X            APPC('?');
  1641. X        }
  1642. X        else {
  1643. X            APPC('\\');
  1644. X            APPC('0' | ((c>>6) & 07));
  1645. X            APPC('0' | ((c>>3) & 07));
  1646. X            APPC('0' | (c & 07));
  1647. X        }
  1648. X#undef APPC
  1649. X    }
  1650. X    if (h > textlen[v])
  1651. X        textlen[v]= h;
  1652. X    texttouched[v]= TRUE;
  1653. X}
  1654. X
  1655. Xvoid
  1656. Xwdrawchar(h, v, c)
  1657. X    int h, v;
  1658. X    int c;
  1659. X{
  1660. X    char cbuf[2];
  1661. X    cbuf[0]= c;
  1662. X    cbuf[1]= EOS;
  1663. X    wdrawtext(h, v, cbuf, 1);
  1664. X}
  1665. X
  1666. Xvoid
  1667. Xwgetwintextattr(win, attr)
  1668. X    WINDOW *win;
  1669. X    TEXTATTR *attr;
  1670. X{
  1671. X    *attr= win->attr;
  1672. X}
  1673. X
  1674. Xvoid
  1675. Xwsetwintextattr(win, attr)
  1676. X    WINDOW *win;
  1677. X    TEXTATTR *attr;
  1678. X{
  1679. X    win->attr= *attr;
  1680. X}
  1681. X
  1682. X/* Non-text drawing dummy functions: */
  1683. X
  1684. X/*ARGSUSED*/
  1685. Xvoid
  1686. Xwdrawline(h1, v1, h2, v2)
  1687. X    int h1, v1, h2, v2;
  1688. X{
  1689. X}
  1690. X
  1691. X/*ARGSUSED*/
  1692. Xvoid
  1693. Xwxorline(h1, v1, h2, v2)
  1694. X    int h1, v1, h2, v2;
  1695. X{
  1696. X}
  1697. X
  1698. X/*ARGSUSED*/
  1699. Xvoid
  1700. Xwdrawcircle(h, v, radius)
  1701. X    int h, v;
  1702. X    int radius;
  1703. X{
  1704. X}
  1705. X
  1706. X/*ARGSUSED*/
  1707. Xvoid
  1708. Xwdrawelarc(h, v, radh, radv, ang1, ang2)
  1709. X    int h, v;
  1710. X    int radh, radv;
  1711. X    int ang1, ang2;
  1712. X{
  1713. X}
  1714. X
  1715. X/*ARGSUSED*/
  1716. Xvoid
  1717. Xwdrawbox(left, top, right, bottom)
  1718. X    int left, top, right, bottom;
  1719. X{
  1720. X}
  1721. X
  1722. X/*ARGSUSED*/
  1723. Xvoid
  1724. Xwpaint(left, top, right, bottom)
  1725. X    int left, top, right, bottom;
  1726. X{
  1727. X}
  1728. X
  1729. X/*ARGSUSED*/
  1730. Xvoid
  1731. Xwshade(left, top, right, bottom, percentage)
  1732. X    int left, top, right, bottom;
  1733. X    int percentage;
  1734. X{
  1735. X}
  1736. X
  1737. X/*ARGSUSED*/
  1738. Xvoid
  1739. Xwinvert(left, top, right, bottom)
  1740. X    int left, top, right, bottom;
  1741. X{
  1742. X    WINDOW *win= draw_win;
  1743. X    int v;
  1744. X    
  1745. X    if (left < 0)
  1746. X        left= 0;
  1747. X    if (right >= columns)
  1748. X        right= columns;
  1749. X    if (left >= right)
  1750. X        return;
  1751. X    top -= win->offset;
  1752. X    bottom -= win->offset;
  1753. X    if (top < win->top)
  1754. X        top= win->top;
  1755. X    if (bottom > win->bottom)
  1756. X        bottom= win->bottom;
  1757. X    for (v= top; v < bottom; ++v) {
  1758. X        int k= textlen[v];
  1759. X        char *text= textline[v];
  1760. X        if (k < right) {
  1761. X            do {
  1762. X                text[k++]= ' ';
  1763. X            } while (k < right);
  1764. X            textlen[v]= k;
  1765. X        }
  1766. X        for (k= left; k < right; ++k)
  1767. X            text[k] ^= 0200;
  1768. X        texttouched[v]= TRUE;
  1769. X    }
  1770. X}
  1771. X
  1772. X/*ARGSUSED*/
  1773. Xvoid
  1774. Xwerase(left, top, right, bottom)
  1775. X    int left, top, right, bottom;
  1776. X{
  1777. X    WINDOW *win= draw_win;
  1778. X    int v;
  1779. X    
  1780. X    if (left < 0)
  1781. X        left= 0;
  1782. X    if (right >= columns)
  1783. X        right= columns;
  1784. X    if (left >= right)
  1785. X        return;
  1786. X    top -= win->offset;
  1787. X    bottom -= win->offset;
  1788. X    if (top < win->top)
  1789. X        top= win->top;
  1790. X    if (bottom > win->bottom)
  1791. X        bottom= win->bottom;
  1792. X    for (v= top; v < bottom; ++v) {
  1793. X        int k= textlen[v];
  1794. X        char *text= textline[v];
  1795. X        if (k > right)
  1796. X            k= right;
  1797. X        while (--k >= left)
  1798. X            text[k]= ' ';
  1799. X        texttouched[v]= TRUE;
  1800. X    }
  1801. X}
  1802. X
  1803. X/*ARGSUSED*/
  1804. Xvoid
  1805. Xwcliprect(left, top, right, bottom)
  1806. X    int left, top, right, bottom;
  1807. X{
  1808. X    /* XXX not implemented */
  1809. X}
  1810. X
  1811. X/*ARGSUSED*/
  1812. Xvoid
  1813. Xwnoclip()
  1814. X{
  1815. X    /* XXX not implemented */
  1816. X}
  1817. END_OF_FILE
  1818. if test 8748 -ne `wc -c <'Ports/alfa/draw.c'`; then
  1819.     echo shar: \"'Ports/alfa/draw.c'\" unpacked with wrong size!
  1820. fi
  1821. # end of 'Ports/alfa/draw.c'
  1822. fi
  1823. if test -f 'Ports/x11/selection.c' -a "${1}" != "-c" ; then 
  1824.   echo shar: Will not clobber existing file \"'Ports/x11/selection.c'\"
  1825. else
  1826. echo shar: Extracting \"'Ports/x11/selection.c'\" \(8353 characters\)
  1827. sed "s/^X//" >'Ports/x11/selection.c' <<'END_OF_FILE'
  1828. X/* Selection Interface, a la ICCCM */
  1829. X
  1830. X
  1831. X/*
  1832. X    Features:
  1833. X    
  1834. X    - supports CLIPBOARD, PRIMARY and SECONDARY selections
  1835. X    - only supports STRING as selection type
  1836. X    - XXX no required funny targets TARGETS, MULTIPLE, TIMESTAMP
  1837. X    - no side effect targets DELETE, INSERT_*
  1838. X    - no INCR targets (XXX should accept these when receiving?)
  1839. X    - XXX truncates large selections to 32 K
  1840. X    - fixed timeout 1 second or 10 requests
  1841. X    
  1842. X    XXX To do:
  1843. X    
  1844. X    - delete selection data when we delete its window
  1845. X    - report the selection's window in WE_LOST_SEL events
  1846. X*/
  1847. X
  1848. X
  1849. X#include "x11.h"
  1850. X#include "llevent.h" /* For _w_lasttime; */
  1851. X
  1852. X
  1853. X#ifndef AMOEBA
  1854. X
  1855. X/* Provide default definitions for FD_ZERO and FD_SET */
  1856. X
  1857. X#ifndef FD_ZERO
  1858. X#define FD_ZERO(p)    bzero((char *)(p), sizeof(*(p)))
  1859. X#endif
  1860. X
  1861. X#ifndef NFDBITS
  1862. X#define NFDBITS        (sizeof(long)*8)    /* Assume 8 bits/byte */
  1863. X#endif
  1864. X
  1865. X#ifndef FD_SET
  1866. X#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  1867. X#endif
  1868. X
  1869. X#endif /* AMOEBA */
  1870. X
  1871. X
  1872. X/* Data structure describing what we know about each selection */
  1873. X
  1874. Xstruct seldescr {
  1875. X    Atom atom;
  1876. X    char *data;
  1877. X    int len;
  1878. X    Time time;
  1879. X    int lost;
  1880. X};
  1881. X
  1882. Xstatic struct seldescr seldata[] = {
  1883. X    {None,        NULL,    0,    CurrentTime,    0},    /* CLIPBOARD */
  1884. X    {XA_PRIMARY,    NULL,    0,    CurrentTime,    0},
  1885. X    {XA_SECONDARY,    NULL,    0,    CurrentTime,    0},
  1886. X};
  1887. X
  1888. X#define NSEL ( sizeof(seldata) / sizeof(seldata[0]) )
  1889. X
  1890. Xstatic void
  1891. Xinitseldata()
  1892. X{
  1893. X    /* The CLIPBOARD atom is not predefined, so intern it here... */
  1894. X    if (seldata[0].atom == None)
  1895. X        seldata[0].atom = XInternAtom(_wd, "CLIPBOARD", False);
  1896. X}
  1897. X
  1898. X
  1899. X/* Attempt to acquire selection ownership.  Return nonzero if success. */
  1900. X
  1901. Xint
  1902. Xwsetselection(win, sel, data, len)
  1903. X    WINDOW *win;
  1904. X    int sel; /* WS_CLIPBOARD, WS_PRIMARY or WS_SECONDARY */
  1905. X    char *data;
  1906. X    int len;
  1907. X{
  1908. X    Window owner;
  1909. X    initseldata();
  1910. X    if (sel < 0 || sel >= NSEL) {
  1911. X        _wwarning("wsetselection: invalid selection number %d", sel);
  1912. X        return 0;
  1913. X    }
  1914. X    seldata[sel].lost = 0;
  1915. X    XSetSelectionOwner(_wd, seldata[sel].atom, win->wo.wid, _w_lasttime);
  1916. X    owner = XGetSelectionOwner(_wd, seldata[sel].atom);
  1917. X    if (owner != win->wo.wid)
  1918. X        return 0; /* Didn't get it */
  1919. X    /* Squirrel away the data value for other clients */
  1920. X    seldata[sel].len = 0;
  1921. X    seldata[sel].time = CurrentTime;
  1922. X    if (seldata[sel].data != NULL)
  1923. X        free(seldata[sel].data);
  1924. X    seldata[sel].data = malloc(len+1);
  1925. X    if (seldata[sel].data == NULL) {
  1926. X        _wwarning("wsetselection: no mem for data (%d bytes)", len);
  1927. X        return 0;
  1928. X    }
  1929. X    memcpy(seldata[sel].data, data, len);
  1930. X    seldata[sel].data[len] = '\0';
  1931. X                /* Trailing NULL byte for wgetselection */
  1932. X    seldata[sel].len = len;
  1933. X    seldata[sel].time = _w_lasttime;
  1934. X    return 1;
  1935. X}
  1936. X
  1937. X
  1938. X/* Give up selection ownership */
  1939. X
  1940. Xvoid
  1941. Xwresetselection(sel)
  1942. X    int sel;
  1943. X{
  1944. X    if (sel < 0 || sel >= NSEL) {
  1945. X        _wwarning("wresetselection: invalid selection number %d", sel);
  1946. X        return;
  1947. X    }
  1948. X    seldata[sel].lost = 0;
  1949. X    if (seldata[sel].data != NULL) {
  1950. X        XSetSelectionOwner(_wd, seldata[sel].atom, None,
  1951. X                            seldata[sel].time);
  1952. X        free(seldata[sel].data);
  1953. X        seldata[sel].data = NULL;
  1954. X        seldata[sel].len = 0;
  1955. X        seldata[sel].len = CurrentTime;
  1956. X    }
  1957. X}
  1958. X
  1959. X
  1960. X/* Attempt to get the value of a selection */
  1961. X
  1962. Xchar *
  1963. Xwgetselection(sel, len_return)
  1964. X    int sel;
  1965. X    int *len_return;
  1966. X{
  1967. X    static char *prop;
  1968. X    WINDOW *win;
  1969. X    XEvent e;
  1970. X    int i;
  1971. X    
  1972. X    initseldata();
  1973. X    
  1974. X    /* Free data retrieved last time */
  1975. X    if (prop != NULL) {
  1976. X        XFree(prop);
  1977. X        prop = NULL;
  1978. X    }
  1979. X    
  1980. X    /* Check selection code */
  1981. X    if (sel < 0 || sel >= NSEL) {
  1982. X        _wwarning("wgetselection: invalid selection number %d", sel);
  1983. X        return NULL;
  1984. X    }
  1985. X    
  1986. X    /* We may own this selection ourself... */
  1987. X    if (seldata[sel].data != NULL) {
  1988. X        _wdebug(2, "wgetselection: we have it");
  1989. X        *len_return = seldata[sel].len;
  1990. X        return seldata[sel].data;
  1991. X    }
  1992. X    
  1993. X    /* Have to ask some other client (the selection owner) */
  1994. X    win = _w_get_last_active();
  1995. X    if (win == NULL) {
  1996. X        _wwarning("wgetselection: no window");
  1997. X        return NULL;
  1998. X    }
  1999. X    
  2000. X    /* Tell the server to ask the selection owner */
  2001. X    XConvertSelection(_wd,
  2002. X        seldata[sel].atom,    /* selection */
  2003. X        XA_STRING,        /* target */
  2004. X        XA_STRING,        /* property (why not?) */
  2005. X        win->wo.wid,        /* window */
  2006. X        _w_lasttime);        /* time */
  2007. X    
  2008. X    /* Now wait for a SelectionNotify event -- 10 times */
  2009. X    _wdebug(2, "waiting for SelectionNotify");
  2010. X    for (i = 0; i < 10; i++) {
  2011. X        e.xselection.property = None;
  2012. X        if (XCheckTypedWindowEvent(_wd, win->wo.wid,
  2013. X                        SelectionNotify, &e)) {
  2014. X            _wdebug(2, "got a SelectionNotify");
  2015. X            break;
  2016. X        }
  2017. X        else {
  2018. X#ifdef AMOEBA
  2019. X            /* XXX For now, just sleep a bit -- there is a
  2020. X               routine to do this, though */
  2021. X            millisleep(100);
  2022. X#else /* !AMOEBA */
  2023. X            /* Use select */
  2024. X            /* SGI/SYSV interface */
  2025. X            fd_set readfds;
  2026. X            struct timeval timeout;
  2027. X            int nfound;
  2028. X            FD_ZERO(&readfds);
  2029. X            FD_SET(_wd->fd, &readfds);
  2030. X            timeout.tv_sec = 0;
  2031. X            timeout.tv_usec = 100000;
  2032. X            nfound = select(_wd->fd+1, &readfds,
  2033. X                (fd_set *)NULL, (fd_set *)NULL, &timeout);
  2034. X            if (nfound < 0)
  2035. X                _wwarning("select failed, errno %d", errno);
  2036. X            else
  2037. X                _wdebug(3, "select: nfound=%d\n", nfound);
  2038. X#endif /* !AMOEBA */
  2039. X        }
  2040. X    }
  2041. X    
  2042. X    if (e.xselection.property != None) {
  2043. X        /* Got a reply, now fetch the property */
  2044. X        int status;
  2045. X        Atom actual_type;
  2046. X        int actual_format;
  2047. X        unsigned long nitems;
  2048. X        unsigned long bytes_after;
  2049. X        status = XGetWindowProperty(_wd,
  2050. X            win->wo.wid,
  2051. X            e.xselection.property,
  2052. X            0L,
  2053. X            8192L, /* Times sizeof(long) is 32K ! */
  2054. X            True,
  2055. X            AnyPropertyType,
  2056. X            &actual_type,
  2057. X            &actual_format,
  2058. X            &nitems,
  2059. X            &bytes_after,
  2060. X            (unsigned char **)&prop);
  2061. X        if (status != Success) {
  2062. X            _wdebug(1, "XGetWindowProperty failed (%d)", status);
  2063. X            return NULL;
  2064. X        }
  2065. X        if (bytes_after != 0) {
  2066. X            _wwarning("truncated %d property bytes", bytes_after);
  2067. X            /* XXX should fetch the rest as well */
  2068. X            XDeleteProperty(_wd, win->wo.wid,
  2069. X                        e.xselection.property);
  2070. X        }
  2071. X        if (actual_type != XA_STRING) {
  2072. X            _wdebug(1, "bad property type: 0x%lx", actual_type);
  2073. X            if (prop != NULL) {
  2074. X                XFree(prop);
  2075. X                prop = NULL;
  2076. X            }
  2077. X            return NULL;
  2078. X        }
  2079. X        *len_return = nitems * (actual_format/8);
  2080. X        _wdebug(2, "got a selection, %d bytes", *len_return);
  2081. X        return prop;
  2082. X        /* Will be freed next time this function is called */
  2083. X    }
  2084. X    
  2085. X    _wdebug(1, "SelectionNotify with property=None");
  2086. X    return NULL;
  2087. X}
  2088. X
  2089. X
  2090. X/* Handle a SelectionClear event -- called from llevent.c */
  2091. X
  2092. Xvoid
  2093. X_w_selectionclear(selection)
  2094. X    Atom selection;
  2095. X{
  2096. X    int sel;
  2097. X    
  2098. X    _wdebug(2, "clearing a selection");
  2099. X    initseldata();
  2100. X    
  2101. X    for (sel = 0; sel < NSEL; sel++) {
  2102. X        if (seldata[sel].atom == selection) {
  2103. X            wresetselection(sel);
  2104. X            seldata[sel].lost = 1;
  2105. X            break;
  2106. X        }
  2107. X    }
  2108. X}
  2109. X
  2110. X
  2111. X/* Generate a WE_LOST_SEL event if one is pending -- called from event.c */
  2112. X
  2113. Xint
  2114. X_w_lostselection(ep)
  2115. X    EVENT *ep;
  2116. X{
  2117. X    int sel;
  2118. X    
  2119. X    for (sel = 0; sel < NSEL; sel++) {
  2120. X        if (seldata[sel].lost) {
  2121. X            seldata[sel].lost = 0;
  2122. X            ep->type = WE_LOST_SEL;
  2123. X            /* XXX Should we report the window?
  2124. X               This is not easily available. */
  2125. X            ep->window = NULL;
  2126. X            ep->u.sel = sel;
  2127. X            return 1;
  2128. X        }
  2129. X    }
  2130. X    return 0;
  2131. X}
  2132. X
  2133. X
  2134. X/* Reply to a SelectionRequest event -- called from llevent.c */
  2135. X
  2136. Xvoid
  2137. X_w_selectionreply(owner, requestor, selection, target, property, time)
  2138. X    Window owner;
  2139. X    Window requestor;
  2140. X    Atom selection;
  2141. X    Atom target;
  2142. X    Atom property;
  2143. X    Time time;
  2144. X{
  2145. X    XSelectionEvent e;
  2146. X    int sel;
  2147. X    
  2148. X    _wdebug(2, "replying to selection request");
  2149. X    initseldata();
  2150. X    
  2151. X    /* Fill in the reply event */
  2152. X    e.type = SelectionNotify;
  2153. X    e.requestor = requestor;
  2154. X    e.selection = selection;
  2155. X    e.target = target;
  2156. X    e.property = None; /* Replaced by property type if OK */
  2157. X    e.time = time;
  2158. X    
  2159. X    if (property == None)
  2160. X        property = target; /* Obsolete client */
  2161. X    
  2162. X    for (sel = 0; sel < NSEL; sel++) {
  2163. X        if (seldata[sel].atom == selection) {
  2164. X            /* It's this selection */
  2165. X            if (seldata[sel].data != NULL &&
  2166. X                (time == CurrentTime ||
  2167. X                seldata[sel].time == CurrentTime ||
  2168. X                ((long)time - (long)seldata[sel].time) >= 0)) {
  2169. X                
  2170. X                /* And we have it.  Store it as a property
  2171. X                   on the requestor window.  The requestor
  2172. X                   will eventually delete it (says ICCCM). */
  2173. X                
  2174. X                /* XXX Always convert to STRING, OK? */
  2175. X                XChangeProperty(_wd,
  2176. X                    requestor,
  2177. X                    property,
  2178. X                    XA_STRING,
  2179. X                    8,
  2180. X                    PropModeReplace,
  2181. X                    (unsigned char *)seldata[sel].data,
  2182. X                    seldata[sel].len);
  2183. X                /* Tell requestor we stored the property */
  2184. X                e.property = property;
  2185. X            }
  2186. X            else {
  2187. X                /* But we don't have it or the time is wrong */
  2188. X                _wdebug(1, "stale selection request");
  2189. X            }
  2190. X            break;
  2191. X        }
  2192. X    }
  2193. X    
  2194. X    if (!XSendEvent(_wd, requestor, False, 0L, (XEvent*)&e))
  2195. X        _wdebug(1, "XSendEvent failed");
  2196. X}
  2197. END_OF_FILE
  2198. if test 8353 -ne `wc -c <'Ports/x11/selection.c'`; then
  2199.     echo shar: \"'Ports/x11/selection.c'\" unpacked with wrong size!
  2200. fi
  2201. # end of 'Ports/x11/selection.c'
  2202. fi
  2203. echo shar: End of archive 10 \(of 19\).
  2204. cp /dev/null ark10isdone
  2205. MISSING=""
  2206. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  2207.     if test ! -f ark${I}isdone ; then
  2208.     MISSING="${MISSING} ${I}"
  2209.     fi
  2210. done
  2211. if test "${MISSING}" = "" ; then
  2212.     echo You have unpacked all 19 archives.
  2213.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2214. else
  2215.     echo You still need to unpack the following archives:
  2216.     echo "        " ${MISSING}
  2217. fi
  2218. ##  End of shell archive.
  2219. exit 0
  2220.