home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2967 < 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 06/19
  4. Message-ID: <3070@charon.cwi.nl>
  5. Date: 4 Mar 91 11:57:50 GMT
  6.  
  7. Archive-name: stdwin/part06
  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 6 (of 19)."
  16. # Contents:  Appls/dpv/dpvoutput.c Doc/ABOUT Packs/textedit/textedit.c
  17. #   Ports/x11/dialog.c
  18. # Wrapped by guido@voorn.cwi.nl on Mon Mar  4 12:37:25 1991
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'Appls/dpv/dpvoutput.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'Appls/dpv/dpvoutput.c'\"
  22. else
  23. echo shar: Extracting \"'Appls/dpv/dpvoutput.c'\" \(5954 characters\)
  24. sed "s/^X//" >'Appls/dpv/dpvoutput.c' <<'END_OF_FILE'
  25. X/* dpv -- ditroff previewer.  Output functions. */
  26. X
  27. X#include "dpv.h"
  28. X#include "dpvmachine.h"
  29. X#include "dpvoutput.h"
  30. X
  31. XWINDOW    *win;            /* output window */
  32. X
  33. X/* Scale factors (must be longs to avoid overflow) */
  34. X
  35. Xlong    hscale, hdiv;        /* Horizontal scaling factors */
  36. Xlong    vscale, vdiv;        /* Vertical scaling factors */
  37. X
  38. Xint paperwidth, paperheight;    /* Paper dimenmsions */
  39. X
  40. X/* Variables used to make put1(c) as fast as possible */
  41. X
  42. Xint    topdraw, botdraw;    /* Top, bottom of rect to redraw */
  43. Xint    baseline;        /* Caches wbaseline() */
  44. Xint    lineheight;        /* Caches wlineheight() */
  45. Xint    doit;            /* Set if output makes sense */
  46. Xint    vwindow;        /* Caches VWINDOW - baseline */
  47. X
  48. Xextern void    drawproc();    /* Draw procedore, in dpvcontrol.c */
  49. X
  50. X/* Create the window */
  51. X
  52. Xinitoutput(filename)
  53. X    char *filename;
  54. X{
  55. X    int winwidth, winheight;
  56. X    int hmargin, vmargin;
  57. X    
  58. X    setscale();
  59. X    wsetdefwinsize(paperwidth, paperheight);
  60. X    win= wopen(filename, drawproc);
  61. X    wsetdocsize(win, paperwidth, paperheight);
  62. X    wsetwincursor(win, wfetchcursor("arrow"));
  63. X    
  64. X    /* Center the window in the document */
  65. X    wgetwinsize(win, &winwidth, &winheight);
  66. X    hmargin = (paperwidth - winwidth) / 2;
  67. X    if (hmargin < 0)
  68. X        hmargin = 0;
  69. X    vmargin = (paperheight - winheight) / 2;
  70. X    if (vmargin < 0)
  71. X        vmargin = 0;
  72. X    wshow(win, hmargin, vmargin,
  73. X                paperwidth - hmargin, paperheight - hmargin);
  74. X}
  75. X
  76. X/* Compute scale factors from screen dimensions and device resolution.
  77. X   Call before outputting anything, but after input device resolution
  78. X   is known. */
  79. X
  80. Xstatic
  81. Xsetscale()
  82. X{
  83. X    int scrwidth, scrheight, mmwidth, mmheight;
  84. X    int hdpi, vdpi;
  85. X    
  86. X    wgetscrsize(&scrwidth, &scrheight);
  87. X    wgetscrmm(&mmwidth, &mmheight);
  88. X    hdpi = scrwidth * 254L / 10 / mmwidth;
  89. X    vdpi = scrheight * 254L / 10 / mmwidth;
  90. X    if (dbg) {
  91. X        printf("screen %dx%d pixels, %dx%d mm.\n",
  92. X            scrwidth, scrheight, mmwidth, mmheight);
  93. X        printf("dots per inch %dx%d\n", hdpi, vdpi);
  94. X    }
  95. X    /* Adjust mm sizes to 75x75 dpi if a resolution less than 75 dpi
  96. X       is reported (some servers lie!) */
  97. X    if (hdpi < 75) {
  98. X        fprintf(stderr,
  99. X            "Adjusting horizontal resolution to 75 dpi\n");
  100. X        mmwidth = scrwidth * 254L / 750;
  101. X    }
  102. X    if (vdpi < 75) {
  103. X        fprintf(stderr,
  104. X            "dpv: Adjusting vertical resolution to 75 dpi\n");
  105. X        mmheight = scrheight * 254L / 750;
  106. X    }
  107. X    /* Dots/mm == scrwidth/mmwidth, etc.; there are 25.4 mm/inch */
  108. X    hscale= 254L * scrwidth / 10;
  109. X    hdiv= mmwidth * res;
  110. X    vscale= 254L * scrheight / 10;
  111. X    vdiv= mmheight * res;
  112. X    /* Set desired width & height of paper */
  113. X    paperwidth= 210 * scrwidth / mmwidth;
  114. X    paperheight= 297 * scrheight / mmheight;
  115. X    if (dbg) {
  116. X        printf("hscale=%d, hdiv=%d, vscale=%d, vdiv=%d\n",
  117. X            hscale, hdiv, vscale, vdiv);
  118. X        printf("paper %dx%d\n", paperwidth, paperheight);
  119. X    }
  120. X}
  121. X
  122. X/* Force a redraw event for the entire window.
  123. X   Used after a new page is made current. */
  124. X
  125. Xchangeall()
  126. X{
  127. X    wchange(win, 0, 0, paperwidth, paperheight);
  128. X}
  129. X
  130. X/* Recompute doit & vwindow.
  131. X   Call after each font change and each vertical move.
  132. X   Assumes topdraw and botdraw are set by drawproc(),
  133. X   and lineheight and baseline are set by usefont(). */
  134. X
  135. Xrecheck()
  136. X{
  137. X    if (ipage != showpage)
  138. X        doit= FALSE;
  139. X    else {
  140. X        vwindow= VWINDOW - baseline;
  141. X        doit= vwindow < botdraw && vwindow+lineheight > topdraw;
  142. X    }
  143. X}
  144. X
  145. X/* Output a funny character, called in response to 'Cxx' input.
  146. X   Don't rely on 'doit'; the character might be in a different font,
  147. X   invalidating the clipping computations in recheck(). */
  148. X
  149. Xput1s(s)
  150. X    char *s;
  151. X{
  152. X    if (ipage == showpage)
  153. X        drawfunny(s);
  154. X}
  155. X
  156. X/* Line drawing functions.
  157. X   There really do some of the work that belongs in dpvmachine.c,
  158. X   and even dpvparse.c. */
  159. X
  160. Xdrawline(dh, dv)
  161. X    int dh, dv;
  162. X{
  163. X    if (ipage == showpage)
  164. X        wdrawline(HWINDOW, VWINDOW, HWIN(hpos+dh), VWIN(vpos+dv));
  165. X    hpos += dh;
  166. X    vpos += dv;
  167. X}
  168. X
  169. Xdrawcirc(diameter)
  170. X    int diameter;
  171. X{
  172. X    if (ipage == showpage)
  173. X        wdrawcircle(HWIN(hpos+diameter/2), VWINDOW,
  174. X            (int)(diameter/2*hscale/hdiv));
  175. X    /* I assume hpos, vpos remain unchanged here */
  176. X}
  177. X
  178. Xdrawellip(haxis, vaxis)
  179. X    int haxis, vaxis;
  180. X{
  181. X    if (ipage == showpage) {
  182. X        wdrawelarc(HWIN(hpos+haxis/2), VWIN(vpos),
  183. X            (int) (haxis*hscale/hdiv/2),
  184. X            (int) (vaxis*vscale/vdiv/2),
  185. X            0, 360);
  186. X    }
  187. X}
  188. X
  189. X#define PI 3.1415726
  190. X
  191. Xdrawarc(n, m, n1, m1)
  192. X/*    current position is start of arc
  193. X *    n,m is position of center relative to current
  194. X *    n1,m1 is intersection point of tangents at start- and endpoints
  195. X *    of the arc
  196. X */
  197. X{
  198. X    double rad, angle1, angle2, sqrt(), atan2(), c;
  199. X    int iang1, iang2;
  200. X    
  201. X    c = 180.0/PI;
  202. X    rad = sqrt((double)((n*n)+(m*m)));
  203. X    angle1 = c*atan2((double)m,(double)-n);
  204. X    angle2 = -2 * (angle1 + c * atan2((double)(m1-m),(double)(n1-n)));
  205. X    iang1 = (int) (angle1 + 0.5);
  206. X    iang2 = (int) (angle2 + 0.5);
  207. X    while (iang1 < 0) iang1 += 360;
  208. X    while (iang2 < 0) iang2 += 360;
  209. X    while (iang1 >= 360) iang1 -= 360;
  210. X    while (iang2 >= 360) iang2 -= 360;
  211. X    /* params for wdrawelarc are
  212. X     *    x,y for center,
  213. X     *    horizontal and vertical radii (different for ellipses)
  214. X     *    start angle in degrees and number of degrees to draw.
  215. X     *    angles measured anticlockwise from positive x-axis
  216. X     */
  217. X    if (ipage == showpage)
  218. X        wdrawelarc(HWIN(hpos+n), VWIN(vpos+m),
  219. X            (int)(rad*hscale/hdiv), (int)(rad*vscale/vdiv),
  220. X            iang1, iang2);
  221. X}
  222. X
  223. Xdrawwig(buf, fp, flag)
  224. X    char *buf;
  225. X    FILE *fp;
  226. X{
  227. X    int dh, dv, x = hpos, y = vpos;
  228. X
  229. X    while (getint(&buf, &dh) && getint(&buf, &dv))
  230. X        if (ipage == showpage) {
  231. X            /* HIRO: should always do this (for side effects)? */
  232. X            drawline(x + dh/4 - hpos, y + dv/4 - vpos);
  233. X            drawline(dh / 2, dv / 2);
  234. X            x += dh;
  235. X            y += dv;
  236. X        }
  237. X    drawline(dh / 4, dv / 4);
  238. X    if (index(buf, EOL) == NULL) {
  239. X        int c;
  240. X        /* HIRO: don't know how to do handle this */
  241. X        error(WARNING, "rest of very long wiggly line ignored");
  242. X        do {
  243. X            c = getc(fp);
  244. X        } while (c != EOL && c != EOF);
  245. X    }
  246. X}
  247. X
  248. Xstatic bool
  249. Xgetint(pbuf, px)
  250. X    char **pbuf;
  251. X    int *px;
  252. X{
  253. X    char *buf= *pbuf;
  254. X    while (*buf != EOS && isspace(*buf))
  255. X        ++buf;
  256. X    if (*buf == EOS || *buf != '-' && !isdigit(*buf))
  257. X        return FALSE;
  258. X    *px= atoi(buf);
  259. X    while (*buf != EOS && !isspace(*buf))
  260. X        ++buf;
  261. X    *pbuf= buf;
  262. X    return TRUE;
  263. X}
  264. END_OF_FILE
  265. if test 5954 -ne `wc -c <'Appls/dpv/dpvoutput.c'`; then
  266.     echo shar: \"'Appls/dpv/dpvoutput.c'\" unpacked with wrong size!
  267. fi
  268. # end of 'Appls/dpv/dpvoutput.c'
  269. fi
  270. if test -f 'Doc/ABOUT' -a "${1}" != "-c" ; then 
  271.   echo shar: Will not clobber existing file \"'Doc/ABOUT'\"
  272. else
  273. echo shar: Extracting \"'Doc/ABOUT'\" \(15823 characters\)
  274. sed "s/^X//" >'Doc/ABOUT' <<'END_OF_FILE'
  275. X[Last modified on Sat Apr 15 20:19:00 MET DST 1989 by guido]
  276. X
  277. X
  278. X0. Copyright Notice
  279. X
  280. XSTDWIN is copyrighted: Copyright (c) 1988, 1989 by Stichting Mathematisch
  281. XCentrum, Amsterdam, The Netherlands.  STDWIN is available for
  282. Xnoncommercial use only, free of charge, and with no guarantees.  It can
  283. Xbe freely used and distributed provided these restrictions are honoured.
  284. X
  285. X
  286. X1. Target systems
  287. X
  288. XSTDWIN is aimed at C programs.  It consists of a few header files (of
  289. Xwhich only one is visible to the user) and a library.  In most cases
  290. Xsome system-provided libraries must also be used in the linking phase.
  291. X
  292. XCurrently, full STDWIN is available for the following environments:
  293. X
  294. X(Note that in all cases the code is in beta test state; there may be
  295. Xbugs, functionality may change slightly in the future and new
  296. Xfunctionality may be added, but the basic framework isn't going to
  297. Xchange much.)
  298. X
  299. X*       X version 11, release 3 (should still work with release 2)
  300. X*       Apple Macintosh, using either THINK C (3.01) or MPW C (2.02)
  301. X*       Atari ST, using Mark Williams C (2.1)
  302. X
  303. XYou may volunteer to create a version for your favourite system, or to
  304. Xport it to your favourite C compiler for one of the mentioned micros.
  305. X(The micro versions are rather compiler-dependent, due to the many
  306. Xdifferences between compilers and especially libraries.  Expect
  307. Xdifficulties if you have another compiler or version than the ones
  308. Xmentioned.  Especially the Atari version is flakey.)
  309. X
  310. XA subset, emulating most of STDWIN's functionality on an alphanumeric
  311. Xdisplay (excluding line drawing, but including multiple (non-overlapping)
  312. Xwindows, menus, text editing etc.) is available for:
  313. X
  314. X*       Any decent Unix that has termcap (tested with 4.{2,3} BSD)
  315. X*       MS-DOS, using the Microsoft C compiler (4.0)
  316. X
  317. XSorry, there are no versions yet for SunTools, SunView, NeWS, X10,
  318. XMS-Windows, Presentation Manager or the Amiga.  A hacker might be able
  319. Xto turn the Atari ST version into a general GEM version.  The code is
  320. Xremarkably portable to different processor types and various Unix
  321. Xflavors, as long as they are derived from 4.xBSD.
  322. X
  323. X
  324. X2. Getting the full scoop
  325. X
  326. XI have written a paper about STDWIN which has been published as a
  327. XCWI report (Guido van Rossum: STDWIN -- A Standard Window System
  328. XInterface.  Centre for Mathematics and Computer Science, report
  329. XCS-R8817.  Amsterdam, 1988).
  330. X
  331. XYou can also get a source version for any or all of the above-mentioned
  332. Xsystems.  This is essentially a directory dump of my working version,
  333. Xuntil I have the time or get some help to prepare a real distribution.
  334. XIt is available through anonymous ftp access from uunet.uu.net.
  335. XThe directory is amiga-sources/stdwin (thanks to the moderator, Peter
  336. Xda Silva) get the file README.txt for further instructions.  A version
  337. Xof this file is in ABOUT.txt.  (The version on gatekeeper no longer
  338. Xexists, although it may be revived in the near future).
  339. X
  340. XDistribution to to non-ftp-users is solely by electronic mail.  Be
  341. Xprepared to receive up to half a megabyte (in 32K pieces in "shar"
  342. Xformat).  If you're interested, write to guido@cwi.nl.
  343. X
  344. X
  345. X3. Basic functionality
  346. X
  347. XSTDWIN allows multiple "full-function" windows, roughly in Macintosh
  348. Xstyle (title bar, grow box, close box, scroll bars).  The appearance of
  349. Xwindows is determined by the default of the underlying window manager,
  350. Xand so are other limitations (e.g., overlapping, maximum size, etc.).
  351. XWindows are dynamically created and destroyed by the application, never
  352. Xdirectly by the user or the window manager.
  353. X
  354. XSTDWIN uses a coordinate system derived from the display's coordinate
  355. Xsystem: (0, 0) is top left, with X pointing right and Y pointing down
  356. X(these are actually called h and v).  Pixel size is that of the display.
  357. XThere are enquiry functions to ask for the display size in pixels and in
  358. Xmillimeters.
  359. X
  360. XThe application is responsible for redrawing the window contents when it
  361. Xis exposed.  This is done by associating a "draw procedure" with each
  362. Xwindow, which knows how to draw the entire window's contents.  It gets
  363. Xpassed a pointer to the window and the coordinates of the rectangle that
  364. Xneeds to be redrawn, so it can (although it needn't) restrict itself to
  365. Xthat area.  STDWIN guarantees that a window's redraw procedure is only
  366. Xcalled while the application is waiting for an input event (most
  367. Ximplementations simply turn exposure events into calls to the draw
  368. Xprocedure).
  369. X
  370. XIf the application wants to change part of the graphics it is
  371. Xdisplaying, this is usually done in a two-phase process: first, STDWIN
  372. Xis told that a particular area of the screen must be changed; later,
  373. Xwhen the application starts waiting for input events again, the draw
  374. Xprocedure is called to update the indicated area (and any other area
  375. Xthat was exposed or damaged in some way).
  376. X
  377. XThe application defines the width and height of the area it wants to
  378. Xdraw; this needn't bear any relation to the window or screen size.  This
  379. Xarea is called the "document" although you may also think of it as a
  380. Xvirtual window.  The actual window generally displays a sub-area of the
  381. Xdocument; the window's scroll bars indicate the position of the window
  382. Xwith respect to the document.  The application always uses the
  383. Xcoordinates of its document; STDWIN performs the translation to window
  384. Xor screen coordinates are required by the window manager, and ensures
  385. Xclipping of all output to the window.
  386. X
  387. XSTDWIN is event-based.  An application is expected to have a main loop
  388. Xcontaining a "get event" call followed by a switch on the event type.
  389. XThere is no event mask; an application can simply ignore events it isn't
  390. Xinterested in.  The most important event types are:
  391. X
  392. XACTIVATE:       A window becomes active (keyboard attached and/or topmost)
  393. X
  394. XCHAR:           ASCII character key pressed (except BS, TAB, CR)
  395. X
  396. XCOMMAND:        special key or function (CLOSE, TAB, RETURN, BS, CANCEL,
  397. X                arrow keys etc.)
  398. X
  399. XMOUSE:          MOUSE DOWN, MOUSE MOVE (only while down), MOUSE UP;
  400. X                fields in the event record indicate the h, v position,
  401. X                the number of the button, and the "click number" if the
  402. X                event is potentially part of a multiple-click sequence
  403. X
  404. XMENU:           menu id and item number of a menu selection
  405. X
  406. XSIZE:           user has resized the window
  407. X
  408. XTIMER:          the window's timer went off; each window has one
  409. X                programmable timer which can be set to go off at N/10
  410. X                seconds in the future.  When the timer goes off a TIMER
  411. X                event is returned.
  412. X
  413. XNormally, STDWIN draws text in a single font.  The actual font used
  414. Xdepends on the underlying window manager (and can sometimes be
  415. Xinfluenced by the application programmer and/or the end user in a
  416. Xsystem-dependent manner).  The font may be proportionally spaced, and
  417. Xthere are enquiry functions to find out the dimensions of characters and
  418. Xstrings.  There are also functions to change the font name and point
  419. Xsize dynamically; but these work different in different systems,
  420. Xespecially the allowed font names differ drastically.  This feature is
  421. Xused with some success in the ditroff previewer that is supplied as a
  422. Xdemo.
  423. X
  424. XThere are functions to draw text and simple lines, rectangles and
  425. Xcircles, and ways to erase, shade or invert rectangular areas.  There is
  426. Xno way (yet) to do general bitblt operations, or to influence the pen
  427. Xshape.
  428. X
  429. X
  430. X4. Higher level functionality
  431. X
  432. XSTDWIN provides a blinking vertical bar which can be used to indicate
  433. Xthe text insertion point, so the application needn't use TIMER events to
  434. Xdo the blinking.
  435. X
  436. XSTDWIN provides Macintosh-style menus.  Each window has its own set of
  437. Xmenus, although by default all menus apply to all windows.  A reasonably
  438. Xnumber of menus per window is allowed, each with a reasonable number of
  439. X(textual) menu items.  Menus can be changed dynamically.  Items can be
  440. Xenabled or disabled, and a 'tick mark' can be placed in front of an
  441. Xitem.  Each menu item may have a shortcut character, which, when typed
  442. Xin combination with some system-defined meta key (e.g., ALT or an ESC-
  443. Xprefix) selects the menu item (if enabled).  Menu selection is done
  444. Xcompletely "underwater"; all the application notices are MENU events.
  445. X
  446. XSTDWIN has a few simple routines to display Mac-style "dialog boxes",
  447. Xe.g., to show an error message, or to ask a yes/no question or to ask
  448. Xfor a string to be typed.  There is also a predefined function to ask
  449. Xfor a file name, which may allow the user to browse the file system in
  450. Xsome implementations.
  451. X
  452. XSTDWIN comes with a package built on top of the basic functionality, to
  453. Xedit arbitrary blocks of text (cf. Macintosh TEXTEDIT).  In the future,
  454. Xmore packages will be provided, e.g., a package to provide a simple file
  455. Xeditor (available now!), a package to display a scrolling list of items,
  456. Xa package to define a list of arbitrary labeled "buttons", and a package
  457. Xto simplify the binding of menus to functions somewhat, and a VT100
  458. Xemulator (available now!).
  459. X
  460. X
  461. X5. Function definitions
  462. X
  463. XHere follows a slightly edited listing of the <stdwin.h> header file,
  464. Xwhich more or less documents all available functions and data
  465. Xstructures.  Note that the argument lists are given here as ANSI C
  466. Xprototypes (untested).
  467. X
  468. X#define bool int
  469. X
  470. Xvoid winit();
  471. Xvoid wdone();
  472. X
  473. Xvoid wsetdefwinsize(int width, int height);
  474. Xvoid wsetdefwinpos(int h, int v);
  475. X
  476. X#define MENU struct menu
  477. X
  478. X/* The contents of a text attributes struct are disclosed here because
  479. X   the interface allows the programmer to declare objects of this type.
  480. X   (I'm not so sure anymore that this is the right thing to do!) */
  481. X
  482. Xstruct textattr {
  483. X        short font;
  484. X        unsigned char size;
  485. X        unsigned char style;
  486. X};
  487. X
  488. X#define TEXTATTR struct textattr
  489. X
  490. X#ifndef WINDOW
  491. X
  492. Xstruct window {
  493. X        short tag;
  494. X};
  495. X
  496. X#define WINDOW struct window
  497. X
  498. X#endif
  499. X
  500. XWINDOW *wopen(char *title, void drawproc();
  501. Xvoid wclose(WINDOW *win);
  502. X#define wgettag(win) ((win)->tag)
  503. X#define wsettag(win, newtag) ((win)->tag= newtag)
  504. Xvoid wsetactive(WINDOW *win);
  505. XWINDOW *wgetactive();
  506. Xvoid wgetwinsize(WINDOW *win, int *width, int *height);
  507. Xvoid wsetdocsize(WINDOW *win, int width, int height);
  508. Xvoid wsettitle(WINDOW *win, char *title);
  509. X
  510. Xvoid wsetorigin(WINDOW *win, int h, int v);
  511. Xvoid wshow(WINDOW *win, int left, int top, int right, int bottom);
  512. Xvoid wchange(WINDOW *win, int left, int top, int right, int bottom);
  513. Xvoid wscroll(WINDOW *win, int left, int top, int right, int bottom,
  514. X        int dh, int dv);
  515. X
  516. Xvoid wfleep();
  517. Xvoid wmessage(char *str);
  518. Xvoid wperror(char *name);
  519. Xbool waskstr(char *prompt, char *buf, int buflen);
  520. Xint waskync(char *question, int dflt);
  521. Xbool waskfile(char *prompt, char *buf, int buflen, bool new);
  522. X
  523. Xvoid wsetcaret(WINDOW *win, int h, int v);
  524. Xvoid wnocaret(WINDOW *win);
  525. X
  526. Xvoid wsettimer(WINDOW *win, int deciseconds);
  527. X
  528. XMENU *wmenucreate(int id, char *title);
  529. Xvoid wmenudelete(MENU *mp);
  530. Xint wmenuadditem(MENU *mp, char *text, char shortcut);
  531. Xvoid wmenusetitem(MENU *mp, int i, char *text);
  532. Xvoid wmenusetdeflocal(bool local);
  533. Xvoid wmenuattach(WINDOW *win, MENU *mp);
  534. Xvoid wmenudetach(WINDOW *win, MENU *mp);
  535. X
  536. X/* EVENT STRUCT DEFINITION */
  537. X
  538. Xstruct event {
  539. X        int type;
  540. X        WINDOW *window;
  541. X        union {
  542. X        /* case WE_CHAR: */
  543. X                int character;
  544. X        /* case WE_COMMAND: */
  545. X                int command;
  546. X        /* case WE_MENU: */
  547. X                struct { int id; int item; } m;
  548. X        /* case WE_DRAW: */
  549. X                struct { int left, top, right, bottom; } area;
  550. X        /* case WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP: */
  551. X                struct {
  552. X                        int v;
  553. X                        int h;
  554. X                        int clicks;
  555. X                        int button;
  556. X                        int mask;
  557. X                } where;
  558. X        } u;
  559. X};
  560. X
  561. X#define EVENT struct event
  562. X
  563. X/* Event types */
  564. X
  565. X#define WE_NULL         0       /* (Used internally) */
  566. X#define WE_ACTIVATE     1       /* Window became active */
  567. X#define WE_CHAR         2       /* Character typed at keyboard */
  568. X#define WE_COMMAND      3       /* Special command, function key etc. */
  569. X#define WE_MOUSE_DOWN   4       /* Mouse button pressed */
  570. X#define WE_MOUSE_MOVE   5       /* Mouse moved with button down */
  571. X#define WE_MOUSE_UP     6       /* Mouse button released */
  572. X#define WE_MENU         7       /* Menu item selected */
  573. X#define WE_SIZE         8       /* Window size changed */
  574. X#define WE_MOVE         9       /* (Reserved) */
  575. X#define WE_DRAW         10      /* Request to redraw part of window */
  576. X#define WE_TIMER        11      /* Window's timer went off */
  577. X#define WE_DEACTIVATE   12      /* Window became inactive */
  578. X
  579. X/* Command codes for WE_COMMAND.
  580. X   Special ways of entering these are usually available,
  581. X   such as clicking icons, standard menu items or special keys.
  582. X   Some ASCII keys are also passed back as commands since they
  583. X   more often than not need special processing. */
  584. X
  585. X#define WC_CLOSE        1       /* Should become a separate event! */
  586. X/* The following four are arrow keys */
  587. X#define WC_LEFT         2
  588. X#define WC_RIGHT        3
  589. X#define WC_UP           4
  590. X#define WC_DOWN         5
  591. X/* ASCII keys */
  592. X#define WC_CANCEL       6
  593. X#define WC_BACKSPACE    7
  594. X#define WC_TAB          8
  595. X#define WC_RETURN       9
  596. X
  597. Xvoid wgetevent(EVENT *ep);
  598. Xvoid wungetevent(EVENT *ep);
  599. Xvoid wupdate(WINDOW *win);
  600. Xvoid wbegindrawing(WINDOW *win);
  601. Xvoid wenddrawing(WINDOW *win);
  602. Xvoid wflush();
  603. X
  604. Xvoid wdrawline(int h1, int v1, int h2, int v2);
  605. Xvoid wxorline(int h1, int v1, int h2, int v2);
  606. Xvoid wdrawcircle(int h, int v, int radius);
  607. Xvoid wdrawelarc(int h, int v, int radh, int radv, int angle1, int angle2);
  608. Xvoid wdrawbox(int left, int top, int right, int bottom);
  609. Xvoid werase(int left, int top, int right, int bottom);
  610. Xvoid wpaint(int left, int top, int right, int bottom);
  611. Xvoid winvert(int left, int top, int right, int bottom);
  612. Xvoid wshade(int left, int top, int right, int bottom, int percent);
  613. X
  614. Xint wdrawtext(int h, int v, char *str, int len);
  615. Xint wdrawchar(int h, int v, char c);
  616. Xint wlineheight();
  617. Xint wtextwidth(char *str, int len);
  618. Xint wcharwidth(char c);
  619. Xint wtextbreak(char *str, int len, int width);
  620. X
  621. Xvoid wgettextattr(TEXTATTR *attr);
  622. Xvoid wsettextattr(TEXTATTR *attr);
  623. Xvoid wgetwintextattr(WINDOW *win, TEXTATTR *attr);
  624. Xvoid wsetwintextattr(WINDOW *win, TEXTATTR *attr);
  625. X
  626. Xvoid wsetplain();
  627. Xvoid wsethilite();
  628. Xvoid wsetinverse();
  629. Xvoid wsetitalic();
  630. Xvoid wsetbold();
  631. Xvoid wsetbolditalic();
  632. Xvoid wsetunderline();
  633. X
  634. X/* TEXTEDIT PACKAGE DEFINITIONS */
  635. X
  636. X#define TEXTEDIT struct _textedit
  637. X
  638. XTEXTEDIT *tealloc(WINDOW *win, int left, int top, int width);
  639. XTEXTEDIT *tecreate(WINDOW *win,
  640. X        int left, int top, int right, int bottom);
  641. Xvoid tefree(TEXTEDIT *tp);
  642. Xvoid tedestroy(TEXTEDIT *tp);
  643. X
  644. Xvoid tedraw(TEXTEDIT *tp);
  645. Xvoid tedrawnew(TEXTEDIT *tp, int left, int top, int right, int bottom);
  646. Xvoid temove(TEXTEDIT *tp, int left, int top, int width);
  647. Xvoid temovenew(TEXTEDIT *tp,
  648. X        int left, int top, int right, int bottom);
  649. X
  650. Xvoid tesetfocus(TEXTEDIT *tp, int foc1, int foc2);
  651. Xvoid tereplace(TEXTEDIT *tp, char *str);
  652. Xvoid tesetbuf(TEXTEDIT *tp, char *buf, int buflen);
  653. X
  654. Xvoid tearrow(TEXTEDIT *tp, int code);
  655. Xvoid tebackspace(TEXTEDIT *tp);
  656. Xbool teclicknew(TEXTEDIT *tp, int h, int v, bool extend);
  657. Xbool tedoubleclick(TEXTEDIT *tp, int h, int v);
  658. Xbool teevent(TEXTEDIT *tp, EVENT *ep);
  659. X
  660. X#define teclick(tp, h, v) teclicknew(tp, h, v, FALSE)
  661. X#define teclickextend(tp, h, v) teclicknew(tp, h, v, TRUE)
  662. X
  663. Xchar *tegettext(TEXTEDIT *tp);
  664. Xint tegetlen(TEXTEDIT *tp);
  665. Xint tegetnlines(TEXTEDIT *tp);
  666. Xint tegetfoc1(TEXTEDIT *tp);
  667. Xint tegetfoc2(TEXTEDIT *tp);
  668. Xint tegetleft(TEXTEDIT *tp);
  669. Xint tegettop(TEXTEDIT *tp);
  670. Xint tegetright(TEXTEDIT *tp);
  671. Xint tegetbottom(TEXTEDIT *tp);
  672. X
  673. X/* Text paragraph drawing functions: */
  674. X
  675. Xint wdrawpar(int h, int v, char *text, int width);
  676. X        /* Returns new v coord. */
  677. Xint wparheight(char *text, int width);
  678. X        /* Returns height */
  679. END_OF_FILE
  680. if test 15823 -ne `wc -c <'Doc/ABOUT'`; then
  681.     echo shar: \"'Doc/ABOUT'\" unpacked with wrong size!
  682. fi
  683. # end of 'Doc/ABOUT'
  684. fi
  685. if test -f 'Packs/textedit/textedit.c' -a "${1}" != "-c" ; then 
  686.   echo shar: Will not clobber existing file \"'Packs/textedit/textedit.c'\"
  687. else
  688. echo shar: Extracting \"'Packs/textedit/textedit.c'\" \(14543 characters\)
  689. sed "s/^X//" >'Packs/textedit/textedit.c' <<'END_OF_FILE'
  690. X/* Text Edit, high level routines */
  691. X
  692. X#include "text.h"
  693. X
  694. Xvoid
  695. Xtereplace(tp, str)
  696. X    TEXTEDIT *tp;
  697. X    char *str;
  698. X{
  699. X    int len= strlen(str);
  700. X    
  701. X    if (len == 1 && teoptinschar(tp, (int) str[0]))
  702. X        return;
  703. X    
  704. X    teinsert(tp, str, len);
  705. X}
  706. X
  707. Xstatic
  708. Xteinschar(tp, c)
  709. X    TEXTEDIT *tp;
  710. X    int c;
  711. X{
  712. X    char cbuf[2];
  713. X    
  714. X    if (teoptinschar(tp, c))
  715. X        return;
  716. X    
  717. X    cbuf[0]= c;
  718. X    cbuf[1]= EOS;
  719. X    teinsert(tp, cbuf, 1);
  720. X}
  721. X
  722. X/* Optimization for the common case insert char.
  723. X   Assumes text measurement is additive. */
  724. X
  725. Xstatic
  726. Xtesetoptdata(tp)
  727. X    TEXTEDIT *tp;
  728. X{
  729. X    lineno i;
  730. X    bufpos k, pos, end;
  731. X    
  732. X    zcheck();
  733. X    zassert(tp->foclen == 0);
  734. X    
  735. X    pos= zaddgap(tp->foc);
  736. X    tp->opt_i= i= tewhichline(tp, pos, FALSE);
  737. X    tp->opt_h= tp->left + tetextwidth(tp, tp->start[i], pos);
  738. X    tp->opt_v= tp->top + i*tp->vspace;
  739. X    end= tp->start[i+1];
  740. X    if (end > pos && zcharbefore(end) == EOL)
  741. X        zdecr(&end);
  742. X    while (end > pos && zcharbefore(end) == ' ')
  743. X        zdecr(&end);
  744. X    for (k= pos; k < end; zincr(&k)) {
  745. X        if (zcharat(k) == '\t')
  746. X            break;
  747. X    }
  748. X    if (k < end) {
  749. X        tp->opt_end=
  750. X            tp->left + tetextwidth(tp, tp->start[i], znext(k));
  751. X        tp->opt_avail= tp->opt_end -
  752. X            (tp->left + tetextwidth(tp, tp->start[i], k));
  753. X    }
  754. X    else {
  755. X        tp->opt_end= tp->right;
  756. X        tp->opt_avail= tp->width - tetextwidth(tp, tp->start[i], end);
  757. X    }
  758. X    if (tp->start[i] > 0 && zcharbefore(tp->start[i]) != EOL) {
  759. X        tp->opt_in_first_word= TRUE;
  760. X        for (k= tp->start[i]; k < pos; zincr(&k)) {
  761. X            if (isspace(zcharat(k))) {
  762. X                tp->opt_in_first_word= FALSE;
  763. X                break;
  764. X            }
  765. X        }
  766. X    }
  767. X    else
  768. X        tp->opt_in_first_word= FALSE;
  769. X    tp->opt_valid= TRUE;
  770. X}
  771. X
  772. Xstatic bool
  773. Xteoptinschar(tp, c)
  774. X    TEXTEDIT *tp;
  775. X    int c;
  776. X{
  777. X    int w;
  778. X    
  779. X    if (tp->foclen != 0 || c == EOL || c == '\t' || tp->focprev)
  780. X        return FALSE;
  781. X    if (!tp->opt_valid)
  782. X        tesetoptdata(tp);
  783. X    if (c == ' ' && tp->opt_in_first_word)
  784. X        return FALSE;
  785. X    w= wcharwidth(c);
  786. X    if (w >= tp->opt_avail)
  787. X        return FALSE;
  788. X    
  789. X    temovegapto(tp, tp->foc);
  790. X    if (tp->gaplen < 1)
  791. X        tegrowgapby(tp, 1+RESERVE);
  792. X    if (tp->start[tp->opt_i] == zgapend)
  793. X        tp->start[tp->opt_i]= tp->gap;
  794. X    ++tp->gap;
  795. X    --tp->gaplen;
  796. X    tp->buf[tp->foc]= c;
  797. X    ++tp->foc;
  798. X    
  799. X    tp->opt_avail -= w;
  800. X    if (tp->active)
  801. X        wnocaret(tp->win);
  802. X    wscroll(tp->win,
  803. X        tp->opt_h, tp->opt_v,
  804. X        tp->opt_end, tp->opt_v + tp->vspace,
  805. X        w, 0);
  806. X    wbegindrawing(tp->win);
  807. X    wdrawchar(tp->opt_h, tp->opt_v, c);
  808. X    wenddrawing(tp->win);
  809. X    tp->opt_h += w;
  810. X    if (tp->active) {
  811. X        wsetcaret(tp->win, tp->opt_h, tp->opt_v);
  812. X        wshow(tp->win,
  813. X            tp->opt_h, tp->opt_v,
  814. X            tp->opt_h, tp->opt_v + tp->vspace);
  815. X    }
  816. X    tp->aim= tp->opt_h;
  817. X    
  818. X    return TRUE;
  819. X}
  820. X
  821. Xstatic
  822. Xteinsert(tp, str, len)
  823. X    TEXTEDIT *tp;
  824. X    char *str;
  825. X    int len;
  826. X{
  827. X    focpos oldfoc= tp->foc;
  828. X    
  829. X    tehidefocus(tp);
  830. X    temovegapto(tp, zfocend);
  831. X    tp->gap= tp->foc;
  832. X    tp->gaplen += tp->foclen;
  833. X    teemptygap(tp);
  834. X    tp->foclen= 0;
  835. X    if (tp->gaplen < len)
  836. X        tegrowgapby(tp, len-tp->gaplen+RESERVE);
  837. X    strncpy(tp->buf+tp->gap, str, len);
  838. X    tp->gap += len;
  839. X    tp->gaplen -= len;
  840. X    tp->foc += len;
  841. X    terecompute(tp, zaddgap(oldfoc), zaddgap(tp->foc));
  842. X}
  843. X
  844. Xstatic int lasteol;    /* Optimization trick for teendofline */
  845. X
  846. Xstatic
  847. Xterecompute(tp, first, last)
  848. X    TEXTEDIT *tp;
  849. X    int first, last;
  850. X{
  851. X    lineno i;
  852. X    lineno chfirst, chlast; /* Area to pass to wchange */
  853. X    lineno shift= 0; /* Lines to shift down (negative: up) */
  854. X    vcoord newbottom;
  855. X    
  856. X    tp->start[0]= zaddgap(0);
  857. X    
  858. X    i= 2;
  859. X    while (i <= tp->nlines && tp->start[i] < first)
  860. X        ++i;
  861. X    i -= 2;
  862. X    chfirst= tp->nlines;
  863. X    chlast= i;
  864. X    lasteol= -1;
  865. X    
  866. X    /* TO DO: scroll up/down if inserting/deleting lines */
  867. X    
  868. X    for (;; ++i) {
  869. X        bufpos end= teendofline(tp, tp->start[i]);
  870. X        bool unchanged= (i < tp->nlines && end == tp->start[i+1]);
  871. X        if (!unchanged)
  872. X            shift += tesetstart(tp, i+1, end, last);
  873. X        if (!(unchanged && end < first)) {
  874. X            if (i < chfirst)
  875. X                chfirst= i;
  876. X            chlast= i+1;
  877. X        }
  878. X        if (end >= tp->buflen) {
  879. X            if (end > tp->start[i] && zcharbefore(end) == EOL)
  880. X                continue;
  881. X            else
  882. X                break;
  883. X        }
  884. X        if (unchanged && end > last) {
  885. X            i= tp->nlines-1;
  886. X            break;
  887. X        }
  888. X    }
  889. X    
  890. X    zassert(tp->nlines > i);
  891. X    
  892. X    if (tp->drawing) {
  893. X        if (shift != 0) {
  894. X            lineno k= chlast;
  895. X            if (shift > 0)
  896. X                k -= shift;
  897. X            wscroll(tp->win,
  898. X                tp->left, tp->top + k*tp->vspace,
  899. X                tp->right, tp->top + tp->nlines*tp->vspace,
  900. X                0, shift*tp->vspace);
  901. X        }
  902. X        
  903. X        wchange(tp->win,
  904. X            tp->left, tp->top + chfirst*tp->vspace,
  905. X            tp->right, tp->top + chlast*tp->vspace);
  906. X    }
  907. X    
  908. X    tp->nlines= i+1;
  909. X    newbottom= tp->top + tp->vspace*tp->nlines;
  910. X    if (newbottom < tp->bottom)
  911. X        wchange(tp->win,
  912. X            tp->left, newbottom, tp->right, tp->bottom);
  913. X    tp->bottom= newbottom;
  914. X    tp->aim= UNDEF;
  915. X    tp->focprev= FALSE;
  916. X    if (tp->drawing)
  917. X        tesetcaret(tp);
  918. X    
  919. X    zcheck();
  920. X}
  921. X
  922. Xstatic int
  923. Xtesetstart(tp, i, pos, last)
  924. X    register TEXTEDIT *tp;
  925. X    register lineno i;
  926. X    bufpos pos, last;
  927. X{
  928. X    if (i > tp->nlines) {
  929. X        tp->nlines= i;
  930. X        if (tp->nlines >= tp->nstart) {
  931. X            tp->nstart= tp->nlines + STARTINCR;
  932. X            tp->start= (bufpos*)zrealloc((char*)tp->start,
  933. X                tp->nstart*sizeof(int));
  934. X        }
  935. X        tp->start[i]= pos;
  936. X        return 0;
  937. X    }
  938. X    else {
  939. X        lineno shift= 0;
  940. X        lineno k;
  941. X        for (k= i; k < tp->nlines; ++k) {
  942. X            if (tp->start[k] > pos)
  943. X                break;
  944. X        }
  945. X        shift= k-1 - i;
  946. X        /* start[k] should really be start[i+1] */
  947. X        if (shift < 0 && tp->start[k] >= last) { /* Insert one */
  948. X            ++tp->nlines;
  949. X            if (tp->nlines >= tp->nstart) {
  950. X                tp->nstart= tp->nlines + STARTINCR;
  951. X                tp->start= (int*)zrealloc((char*)tp->start,
  952. X                    tp->nstart*sizeof(int));
  953. X            }
  954. X            for (k= tp->nlines; k > i; --k)
  955. X                tp->start[k]= tp->start[k-1];
  956. X        }
  957. X        else if (shift > 0 && pos >= last) { /* Delete some */
  958. X            for (; k <= tp->nlines; ++k)
  959. X                tp->start[k-shift]= tp->start[k];
  960. X            tp->nlines -= shift;
  961. X            if (tp->nlines < tp->nstart - STARTINCR) {
  962. X                tp->nstart= tp->nlines+1;
  963. X                tp->start= (int*)zrealloc((char*)tp->start,
  964. X                    tp->nstart*sizeof(int));
  965. X            }
  966. X        }
  967. X        else
  968. X            shift= 0; /* Don't shift (yet) */
  969. X        tp->start[i]= pos;
  970. X        return -shift;
  971. X    }
  972. X}
  973. X
  974. Xstatic int
  975. Xteendofline(tp, pos)
  976. X    TEXTEDIT *tp;
  977. X    bufpos pos;
  978. X{
  979. X    bufpos end= tp->buflen;
  980. X    bufpos k;
  981. X    
  982. X    /* Find first EOL if any */
  983. X    if (lasteol >= pos)
  984. X        k= lasteol;
  985. X    else {
  986. X        for (k= pos; k < end && zcharat(k) != EOL; zincr(&k))
  987. X            ;
  988. X        lasteol= k;
  989. X    }
  990. X    
  991. X    end= tetextbreak(tp, pos, k, tp->width);
  992. X    
  993. X    /* Extend with any spaces immediately following end */
  994. X    for (; end < tp->buflen && zcharat(end) == ' '; zincr(&end))
  995. X        ;
  996. X    
  997. X    if (end < tp->buflen) {
  998. X        /* Extend with immediately following EOL */
  999. X        if (zcharat(end) == EOL)
  1000. X            zincr(&end);
  1001. X        else {
  1002. X            /* Search back for space before last word */
  1003. X            for (k= end; zdecr(&k) >= pos && !isspace(zcharat(k)); )
  1004. X                ;
  1005. X            
  1006. X            if (k >= pos)
  1007. X                end= znext(k);
  1008. X        }
  1009. X    }
  1010. X
  1011. X    /* Each line must be at least one character long,
  1012. X       otherwise a very narrow text-edit box would cause
  1013. X       the size calculation to last forever */
  1014. X    if (end == pos && end < tp->buflen)
  1015. X        zincr(&end);
  1016. X    
  1017. X    return end;
  1018. X}
  1019. X
  1020. Xbool
  1021. Xteevent(tp, e)
  1022. X    TEXTEDIT *tp;
  1023. X    EVENT *e;
  1024. X{
  1025. X    if (e->window != tp->win)
  1026. X        return FALSE;
  1027. X    
  1028. X    switch (e->type) {
  1029. X    
  1030. X    case WE_CHAR:
  1031. X        teinschar(tp, e->u.character);
  1032. X        break;
  1033. X    
  1034. X    case WE_COMMAND:
  1035. X        switch (e->u.command) {
  1036. X        case WC_BACKSPACE:
  1037. X            tebackspace(tp);
  1038. X            break;
  1039. X        case WC_RETURN:
  1040. X            teinschar(tp, EOL);
  1041. X            break;
  1042. X        case WC_TAB:
  1043. X            teinschar(tp, '\t');
  1044. X            break;
  1045. X        case WC_LEFT:
  1046. X        case WC_RIGHT:
  1047. X        case WC_UP:
  1048. X        case WC_DOWN:
  1049. X            tearrow(tp, e->u.command);
  1050. X            break;
  1051. X        default:
  1052. X            return FALSE;
  1053. X        }
  1054. X        break;
  1055. X    
  1056. X    case WE_MOUSE_DOWN:
  1057. X        {
  1058. X            int h= e->u.where.h, v= e->u.where.v;
  1059. X            if (h >= tp->left && h <= tp->right &&
  1060. X                    v >= tp->top && v <= tp->bottom)
  1061. X                teclicknew(tp, h, v,
  1062. X                    e->u.where.button == 2,
  1063. X                    e->u.where.clicks > 1);
  1064. X            else
  1065. X                return FALSE;
  1066. X        }
  1067. X        break;
  1068. X    
  1069. X    case WE_MOUSE_MOVE:
  1070. X    case WE_MOUSE_UP:
  1071. X        if (!tp->mdown)
  1072. X            return FALSE;
  1073. X        teclicknew(tp, e->u.where.h, e->u.where.v, TRUE, tp->dclick);
  1074. X        if (e->type == WE_MOUSE_UP)
  1075. X            tp->mdown= FALSE;
  1076. X        break;
  1077. X    
  1078. X    case WE_DRAW:
  1079. X        wbegindrawing(tp->win);
  1080. X        tedrawnew(tp, e->u.area.left, e->u.area.top,
  1081. X                e->u.area.right, e->u.area.bottom);
  1082. X        wenddrawing(tp->win);
  1083. X        break;
  1084. X    
  1085. X    default:
  1086. X        return FALSE;
  1087. X    
  1088. X    }
  1089. X    
  1090. X    /* If broke out of switch: */
  1091. X    return TRUE;
  1092. X}
  1093. X
  1094. Xvoid
  1095. Xtearrow(tp, code)
  1096. X    TEXTEDIT *tp;
  1097. X    int code;
  1098. X{
  1099. X    lineno i;
  1100. X    bufpos pos;
  1101. X    
  1102. X    tehidefocus(tp);
  1103. X    
  1104. X    switch (code) {
  1105. X    
  1106. X    case WC_LEFT:
  1107. X        if (tp->foclen != 0)
  1108. X            tp->foclen= 0;
  1109. X        else {
  1110. X            if (tp->foc > 0)
  1111. X                --tp->foc;
  1112. X            else
  1113. X                wfleep();
  1114. X        }
  1115. X        tp->aim= UNDEF;
  1116. X        tp->focprev= FALSE;
  1117. X        break;
  1118. X    
  1119. X    case WC_RIGHT:
  1120. X        if (tp->foclen != 0) {
  1121. X            tp->foc += tp->foclen;
  1122. X            tp->foclen= 0;
  1123. X        }
  1124. X        else {
  1125. X            if (tp->foc < tp->buflen-tp->gaplen)
  1126. X                ++tp->foc;
  1127. X            else
  1128. X                wfleep();
  1129. X        }
  1130. X        tp->aim= UNDEF;
  1131. X        tp->focprev= FALSE;
  1132. X        break;
  1133. X    
  1134. X    /* TO DO: merge the following two cases */
  1135. X    
  1136. X    case WC_UP:
  1137. X        if (tp->foclen > 0)
  1138. X            tp->foclen= 0;
  1139. X        else {
  1140. X            pos= zaddgap(tp->foc);
  1141. X            i= tewhichline(tp, pos, (bool) tp->focprev);
  1142. X            if (i <= 0)
  1143. X                wfleep();
  1144. X            else {
  1145. X                if (tp->aim == UNDEF)
  1146. X                    tp->aim= tp->left + tetextwidth(tp,
  1147. X                        tp->start[i], pos);
  1148. X                --i;
  1149. X                pos= tetextround(tp, i, tp->aim);
  1150. X                tp->foc= zsubgap(pos);
  1151. X                tp->focprev= (pos == tp->start[i+1]);
  1152. X            }
  1153. X        }
  1154. X        break;
  1155. X    
  1156. X    case WC_DOWN:
  1157. X        if (tp->foclen > 0) {
  1158. X            tp->foc += tp->foclen;
  1159. X            tp->foclen= 0;
  1160. X        }
  1161. X        else {
  1162. X            pos= zaddgap(tp->foc);
  1163. X            i= tewhichline(tp, pos, (bool) tp->focprev);
  1164. X            if (i+1 >= tp->nlines)
  1165. X                wfleep();
  1166. X            else {
  1167. X                if (tp->aim == UNDEF)
  1168. X                    tp->aim= tp->left + tetextwidth(tp,
  1169. X                        tp->start[i], pos);
  1170. X                ++i;
  1171. X                pos= tetextround(tp, i, tp->aim);
  1172. X                tp->foc= zsubgap(pos);
  1173. X                tp->focprev= (pos == tp->start[i+1]);
  1174. X            }
  1175. X        }
  1176. X        break;
  1177. X    
  1178. X    default:
  1179. X        dprintf("tearrow: bad code %d", code);
  1180. X        break;
  1181. X        
  1182. X    }
  1183. X    tesetcaret(tp);
  1184. X}
  1185. X
  1186. Xvoid
  1187. Xtebackspace(tp)
  1188. X    TEXTEDIT *tp;
  1189. X{
  1190. X    if (tp->foclen == 0) {
  1191. X        if (tp->foc == 0) {
  1192. X            wfleep();
  1193. X            return;
  1194. X        }
  1195. X        --tp->foc;
  1196. X        tp->foclen= 1;
  1197. X    }
  1198. X    teinsert(tp, "", 0);
  1199. X}
  1200. X
  1201. Xbool
  1202. Xteclicknew(tp, h, v, extend, dclick)
  1203. X    TEXTEDIT *tp;
  1204. X    coord h, v;
  1205. X    bool extend, dclick;
  1206. X{
  1207. X    lineno i;
  1208. X    bufpos pos;
  1209. X    focpos f;
  1210. X    
  1211. X    tp->dclick= dclick;
  1212. X    pos= tewhereis(tp, h, v, &i);
  1213. X    f= zsubgap(pos);
  1214. X    if (extend) {
  1215. X        if (!tp->mdown) {
  1216. X            tp->mdown= TRUE;
  1217. X            if (f - tp->foc < tp->foc + tp->foclen - f)
  1218. X                tp->anchor= tp->foc + tp->foclen;
  1219. X            else
  1220. X                tp->anchor= tp->foc;
  1221. X            tp->anchor2= tp->anchor;
  1222. X        }
  1223. X        if (f >= tp->anchor) {
  1224. X            if (dclick)
  1225. X                f= tewordend(tp, f);
  1226. X            techangefocus(tp, tp->anchor, f);
  1227. X        }
  1228. X        else {
  1229. X            if (dclick)
  1230. X                f= tewordbegin(tp, f);
  1231. X            techangefocus(tp, f, tp->anchor2);
  1232. X        }
  1233. X    }
  1234. X    else {
  1235. X        tp->mdown= TRUE;
  1236. X        tp->anchor= tp->anchor2= f;
  1237. X        if (dclick) {
  1238. X            tp->anchor= tewordbegin(tp, tp->anchor);
  1239. X            tp->anchor2= tewordend(tp, f);
  1240. X        }
  1241. X        techangefocus(tp, tp->anchor, tp->anchor2);
  1242. X    }
  1243. X    tp->aim= UNDEF;
  1244. X    tp->focprev= (tp->foclen == 0 && pos == tp->start[i+1]);
  1245. X    tesetcaret(tp);
  1246. X    return TRUE;
  1247. X}
  1248. X
  1249. X/* Return f, 'rounded down' to a word begin */
  1250. X
  1251. Xstatic int
  1252. Xtewordbegin(tp, f)
  1253. X    TEXTEDIT *tp;
  1254. X    int f;
  1255. X{
  1256. X    f= zaddgap(f);
  1257. X    for (;;) {
  1258. X        if (f == 0 || isspace(zcharbefore(f)))
  1259. X            break;
  1260. X        zdecr(&f);
  1261. X    }
  1262. X    return zsubgap(f);
  1263. X}
  1264. X
  1265. X/* Ditto to word end */
  1266. X
  1267. Xstatic int
  1268. Xtewordend(tp, f)
  1269. X    TEXTEDIT *tp;
  1270. X    int f;
  1271. X{
  1272. X    f= zaddgap(f);
  1273. X    for (;;) {
  1274. X        if (f >= tp->buflen || isspace(zcharat(f)))
  1275. X            break;
  1276. X        zincr(&f);
  1277. X    }
  1278. X    return zsubgap(f);
  1279. X}
  1280. X
  1281. Xint
  1282. Xtegetleft(tp)
  1283. X    TEXTEDIT *tp;
  1284. X{
  1285. X    return tp->left;
  1286. X}
  1287. X
  1288. Xint
  1289. Xtegettop(tp)
  1290. X    TEXTEDIT *tp;
  1291. X{
  1292. X    return tp->top;
  1293. X}
  1294. X
  1295. Xint
  1296. Xtegetright(tp)
  1297. X    TEXTEDIT *tp;
  1298. X{
  1299. X    return tp->right;
  1300. X}
  1301. X
  1302. Xint
  1303. Xtegetbottom(tp)
  1304. X    TEXTEDIT *tp;
  1305. X{
  1306. X    return tp->bottom;
  1307. X}
  1308. X
  1309. Xvoid
  1310. Xtemove(tp, left, top, width)
  1311. X    TEXTEDIT *tp;
  1312. X    coord left, top, width;
  1313. X{
  1314. X    temovenew(tp, left, top, left+width, top + tp->nlines*tp->vspace);
  1315. X}
  1316. X
  1317. X/*ARGSUSED*/
  1318. Xvoid
  1319. Xtemovenew(tp, left, top, right, bottom)
  1320. X    TEXTEDIT *tp;
  1321. X    int left, top, right, bottom;
  1322. X{
  1323. X    int oldheight= tp->bottom - tp->top;
  1324. X    tp->left= left;
  1325. X    tp->top= top;
  1326. X    tp->right= right;
  1327. X    tp->bottom= tp->top + oldheight;
  1328. X    if (right - left != tp->width) {
  1329. X        tp->width= right - left;
  1330. X        tp->nlines= 0; /* Experimental! */
  1331. X        terecompute(tp, 0, tp->buflen);
  1332. X    }
  1333. X}
  1334. X
  1335. Xvoid
  1336. Xtesetfocus(tp, foc1, foc2)
  1337. X    TEXTEDIT *tp;
  1338. X    focpos foc1, foc2;
  1339. X{
  1340. X    if (foc1 > tp->buflen - tp->gaplen)
  1341. X        foc1= tp->buflen - tp->gaplen;
  1342. X    if (foc2 > tp->buflen - tp->gaplen)
  1343. X        foc2= tp->buflen - tp->gaplen;
  1344. X    if (foc1 < 0)
  1345. X        foc1= 0;
  1346. X    if (foc2 < foc1)
  1347. X        foc2= foc1;
  1348. X    techangefocus(tp, foc1, foc2);
  1349. X    tp->aim= UNDEF;
  1350. X    tp->focprev= FALSE;
  1351. X    tesetcaret(tp);
  1352. X}
  1353. X
  1354. Xint
  1355. Xtegetfoc1(tp)
  1356. X    TEXTEDIT *tp;
  1357. X{
  1358. X    return tp->foc;
  1359. X}
  1360. X
  1361. Xint
  1362. Xtegetfoc2(tp)
  1363. X    TEXTEDIT *tp;
  1364. X{
  1365. X    return tp->foc + tp->foclen;
  1366. X}
  1367. X
  1368. Xint
  1369. Xtegetnlines(tp)
  1370. X    TEXTEDIT *tp;
  1371. X{
  1372. X    return tp->nlines;
  1373. X}
  1374. X
  1375. Xchar *
  1376. Xtegettext(tp)
  1377. X    TEXTEDIT *tp;
  1378. X{
  1379. X    temovegapto(tp, tp->buflen - tp->gaplen);
  1380. X    if (tp->gaplen < 1)
  1381. X        tegrowgapby(tp, 1+RESERVE);
  1382. X    tp->buf[tp->gap]= EOS;
  1383. X    return tp->buf;
  1384. X}
  1385. X
  1386. Xint
  1387. Xtegetlen(tp)
  1388. X    TEXTEDIT *tp;
  1389. X{
  1390. X    return tp->buflen - tp->gaplen;
  1391. X}
  1392. X
  1393. Xvoid
  1394. Xtesetbuf(tp, buf, buflen)
  1395. X    TEXTEDIT *tp;
  1396. X    char *buf;
  1397. X    int buflen;
  1398. X{
  1399. X    bool drawing= tp->drawing;
  1400. X    
  1401. X    if (buf == NULL || buflen < 0)
  1402. X        return;
  1403. X    if (drawing)
  1404. X        wchange(tp->win, tp->left, tp->top, tp->right, tp->bottom);
  1405. X    free(tp->buf);
  1406. X    tp->buf= buf;
  1407. X    tp->buflen= buflen;
  1408. X    tp->foc= tp->foclen= tp->gap= tp->gaplen= 0;
  1409. X    tp->drawing= FALSE;
  1410. X    terecompute(tp, 0, tp->buflen);
  1411. X    if (drawing) {
  1412. X        tp->drawing= TRUE;
  1413. X        wchange(tp->win, tp->left, tp->top, tp->right, tp->bottom);
  1414. X    }
  1415. X}
  1416. X
  1417. X
  1418. X/* The following paragraph-drawing routines are experimental.
  1419. X   They cannibalize on the existing text-edit code,
  1420. X   which makes it trivial to ensure the lay-out is the same,
  1421. X   but causes overhead to initialize a text-edit struct.
  1422. X   The flag 'drawing' has been added to the textedit struct,
  1423. X   which suppresses calls to tesetcaret, wchange and wscroll
  1424. X   from tesetup and terecompute.
  1425. X   It doesn't suppress actual drawing, which only occurs when
  1426. X   tedraw is called.
  1427. X   Note -- this could be optimized, but it is infrequently,
  1428. X   so I don't care until I get complaints. */
  1429. X
  1430. X/* Draw a paragraph of text, exactly like tedraw would draw it.
  1431. X   Parameters are the top left corner, the width, the text and its length.
  1432. X   Return value is the v coordinate of the bottom line.
  1433. X   An empty string is drawn as one blank line. */
  1434. X
  1435. Xint
  1436. Xwdrawpar(left, top, text, width)
  1437. X    int left, top;
  1438. X    char *text;
  1439. X    int width;
  1440. X{
  1441. X    return _wdrawpar(left, top, text, width, TRUE);
  1442. X}
  1443. X
  1444. X/* Measure the height of a paragraph of text, when drawn with wdrawpar. */
  1445. X
  1446. Xint
  1447. Xwparheight(text, width)
  1448. X    char *text;
  1449. X    int width;
  1450. X{
  1451. X    return _wdrawpar(0, 0, text, width, FALSE);
  1452. X}
  1453. X
  1454. X/* Routine to do the dirty work for the above two.
  1455. X   Size calculations are implemented by going through the normal
  1456. X   routine but suppressing the actual drawing. */
  1457. X
  1458. Xstatic int
  1459. X_wdrawpar(left, top, text, width, draw)
  1460. X    int left, top;
  1461. X    char *text;
  1462. X    int width;
  1463. X    bool draw;
  1464. X{
  1465. X    TEXTEDIT *tp= tesetup((WINDOW*)NULL, left, top, left+width, top, FALSE);
  1466. X    int v;
  1467. X    
  1468. X    tesetbuf(tp, text, strlen(text));
  1469. X    if (draw)
  1470. X        tedraw(tp);
  1471. X    v= tegetbottom(tp);
  1472. X    tp->buf= NULL;
  1473. X    tefree(tp);
  1474. X    return v;
  1475. X}
  1476. END_OF_FILE
  1477. if test 14543 -ne `wc -c <'Packs/textedit/textedit.c'`; then
  1478.     echo shar: \"'Packs/textedit/textedit.c'\" unpacked with wrong size!
  1479. fi
  1480. # end of 'Packs/textedit/textedit.c'
  1481. fi
  1482. if test -f 'Ports/x11/dialog.c' -a "${1}" != "-c" ; then 
  1483.   echo shar: Will not clobber existing file \"'Ports/x11/dialog.c'\"
  1484. else
  1485. echo shar: Extracting \"'Ports/x11/dialog.c'\" \(14224 characters\)
  1486. sed "s/^X//" >'Ports/x11/dialog.c' <<'END_OF_FILE'
  1487. X/* X11 STDWIN -- Dialog boxes */
  1488. X
  1489. X#include "x11.h"
  1490. X#include "llevent.h"
  1491. X
  1492. X/* The kinds of dialogs we know */
  1493. X
  1494. X#define MESSAGEKIND    0
  1495. X#define ASKYNCKIND    1
  1496. X#define ASKSTRKIND    2
  1497. X
  1498. X/* Display a message and wait until acknowledged */
  1499. X
  1500. Xvoid
  1501. Xwmessage(prompt)
  1502. X    char *prompt;
  1503. X{
  1504. X    (void) dialog(prompt, (char*)NULL, 0, MESSAGEKIND, 0);
  1505. X}
  1506. X
  1507. X/* Ask a yes/no question.
  1508. X   Return value: yes ==> 1, no ==> 0, cancel (^C) ==> -1.
  1509. X   Only the first non-blank character of the string typed is checked.
  1510. X   The 'def' parameter is returned when an empty string is typed. */
  1511. X
  1512. Xint
  1513. Xwaskync(prompt, def)
  1514. X    char *prompt;
  1515. X    int def;
  1516. X{
  1517. X    return dialog(prompt, (char*)NULL, 0, ASKYNCKIND, def);
  1518. X}
  1519. X
  1520. X/* Ask for a string. */
  1521. X
  1522. Xbool
  1523. Xwaskstr(prompt, buf, len)
  1524. X    char *prompt;
  1525. X    char *buf;
  1526. X    int len;
  1527. X{
  1528. X    return dialog(prompt, buf, len, ASKSTRKIND, TRUE);
  1529. X}
  1530. X
  1531. X/* Definition for the current dialog box */
  1532. X
  1533. Xstatic struct windata box;    /* Window descriptor for the dialog box */
  1534. Xstatic unsigned long fg, bg;    /* Foreground, background pixel values */
  1535. Xstatic GC b_gc;            /* Corresponding Graphics Context */
  1536. X
  1537. X/* Definition for a command "button" or text item in a dialog box */
  1538. X
  1539. Xstruct button {
  1540. X    char type;        /* Button, label or text */
  1541. X    char *text;        /* The button label */
  1542. X    int ret;        /* Value to return when chosen */
  1543. X    struct windata wd;    /* Window description */
  1544. X    tbool down;        /* Button is pressed */
  1545. X    tbool inside;        /* Mouse inside button */
  1546. X    tbool hilite;        /* Button is hilited */
  1547. X    tbool def;        /* Set if default button */
  1548. X};
  1549. X
  1550. X/* Constants used in button definition 'type' field above */
  1551. X
  1552. X#define LABEL    'l'
  1553. X#define TEXT    't'
  1554. X#define BUTTON    'b'
  1555. X
  1556. Xstatic int nbuttons;        /* number of buttons and items */
  1557. Xstatic struct button *buttonlist; /* Definition list */
  1558. X
  1559. X/* Constants guiding button dimensions */
  1560. X
  1561. Xstatic int charwidth, textheight;
  1562. Xstatic int promptwidth;
  1563. Xstatic int buttonwidth;
  1564. X
  1565. X/* Dialog routine.
  1566. X   Create the window and subwindows, then engage in interaction.
  1567. X   Return the proper return value for waskync or waskstr.
  1568. X*/
  1569. X
  1570. X/* Dimension of buttons:
  1571. X   vertically:
  1572. X       - 1 pixel white space around text,
  1573. X       - 1 pixel wide border,
  1574. X       - q pixel white space around border
  1575. X   horizontally:
  1576. X       - 1 space character around text
  1577. X       - 1 pixel wide border
  1578. X       - 1 pixel white space around border
  1579. X   The prompt and reply are placed as buttons but their
  1580. X   border is white.
  1581. X   For a message, the OK button is to the right of the text,
  1582. X   separated from the prompt by two extra space characters.
  1583. X*/
  1584. X
  1585. Xstatic int
  1586. Xdialog(prompt, buf, len, kind, def)
  1587. X    char *prompt;        /* Prompt string */
  1588. X    char *buf;        /* Reply buffer, or NULL if unused */
  1589. X    int len;        /* Size of reply buffer */
  1590. X    int kind;        /* Dialog kind */
  1591. X    int def;        /* Default return value */
  1592. X{
  1593. X    WINDOW *act;
  1594. X    XFontStruct *save_wf= _wf;
  1595. X    int ret;
  1596. X    int textlen= 60;
  1597. X    
  1598. X    _wf= _wmf; /* So we can use wtextwidth() etc. */
  1599. X    
  1600. X    /* Compute various useful dimensions */
  1601. X    charwidth= wcharwidth(' ');
  1602. X    textheight= wlineheight();
  1603. X    promptwidth= wtextwidth(prompt, -1);
  1604. X    if (kind == MESSAGEKIND)
  1605. X        buttonwidth= wtextwidth("OK", 2);
  1606. X    else
  1607. X        buttonwidth= wtextwidth("Cancel", 6);
  1608. X    
  1609. X    /* Compute the outer box dimensions */
  1610. X    switch (kind) {
  1611. X    case MESSAGEKIND:
  1612. X        box.width= promptwidth + buttonwidth + 6*charwidth + 8;
  1613. X        box.height= textheight + 6;
  1614. X        break;
  1615. X    case ASKYNCKIND:
  1616. X        box.width= promptwidth + 2*charwidth + 4;
  1617. X        CLIPMIN(box.width, 3*(buttonwidth + 2*charwidth + 4));
  1618. X        box.height= 2 * (textheight + 6);
  1619. X        break;
  1620. X    default:
  1621. X        _wdebug(0, "dialog: bad kind");
  1622. X        kind= ASKSTRKIND;
  1623. X        /* Fall through */
  1624. X    case ASKSTRKIND:
  1625. X        box.width= promptwidth + 2*charwidth + 4;
  1626. X        CLIPMAX(textlen, len);
  1627. X        CLIPMIN(box.width, textlen*charwidth);
  1628. X        CLIPMIN(box.width, 2*(buttonwidth + 2*charwidth + 4));
  1629. X        box.height= 3 * (textheight + 6);
  1630. X        break;
  1631. X    }
  1632. X    CLIPMAX(box.width, WidthOfScreen(_ws));
  1633. X    CLIPMAX(box.height, HeightOfScreen(_ws));
  1634. X    
  1635. X    /* Compute the box position:
  1636. X       above a window if possible,
  1637. X       on the screen if necessary. */
  1638. X    
  1639. X    /* XXX Default placement could use an option resource */
  1640. X    
  1641. X    act= _w_get_last_active();
  1642. X    if (act != NULL) {
  1643. X        Window child_dummy;
  1644. X        if (!XTranslateCoordinates(_wd, act->wi.wid,
  1645. X            RootWindowOfScreen(_ws),
  1646. X#ifdef CENTERED
  1647. X            (act->wi.width - box.width) / 2,
  1648. X            (act->wi.height - box.height) / 2,
  1649. X#else
  1650. X            0,
  1651. X            0,
  1652. X#endif
  1653. X            &box.x, &box.y, &child_dummy))
  1654. X            act= NULL; /* Couldn't do it -- center on screen */
  1655. X    }
  1656. X    if (act == NULL) {
  1657. X        /* No window to cover */
  1658. X#ifdef CENTERED
  1659. X        /* center the box in the screen */
  1660. X        box.x= (WidthOfScreen(_ws) - box.width) / 2;
  1661. X        box.y= (HeightOfScreen(_ws) - box.height) / 2;
  1662. X#else
  1663. X        /* use top left screen corner */
  1664. X        box.x= box.y = 2*IBORDER + 1;
  1665. X        /* well, 1 pixel from the corner, to fool twm */
  1666. X#endif
  1667. X    }
  1668. X    
  1669. X    /* Clip the box to the screen */
  1670. X    
  1671. X    CLIPMAX(box.x, WidthOfScreen(_ws) - box.width);
  1672. X    CLIPMAX(box.y, HeightOfScreen(_ws) - box.height);
  1673. X    CLIPMIN(box.x, 0);
  1674. X    CLIPMIN(box.y, 0);
  1675. X    _wdebug(1, "dialog box: x=%d y=%d w=%d h=%d",
  1676. X        box.x, box.y, box.width, box.height);
  1677. X    
  1678. X    /* Create the box window and its GC */
  1679. X    
  1680. X    fg= _wgetpixel("menuForeground", "Foreground",
  1681. X                        BlackPixelOfScreen(_ws));
  1682. X    bg= _wgetpixel("menuBackground", "Background",
  1683. X                        WhitePixelOfScreen(_ws));
  1684. X    box.border= 2*IBORDER;
  1685. X    (void) _wcreate(&box, RootWindowOfScreen(_ws), 0, FALSE, fg, bg);
  1686. X    _wsaveunder(&box, True);
  1687. X    XSelectInput(_wd, box.wid,
  1688. X        ExposureMask|KeyPressMask|StructureNotifyMask);
  1689. X    b_gc= _wgcreate(box.wid, _wf->fid, fg, bg);
  1690. X    
  1691. X    /* Keep window managers happy:
  1692. X       a name for WM's that insist on displaying a window title;
  1693. X       class hints;
  1694. X       WM hints;
  1695. X       size hints to avoid interactive window placement;
  1696. X       and "transient hints" to link it to an existing window. 
  1697. X       The latter two only if the dialog box belongs to a window. */
  1698. X    
  1699. X    /* XXX This code could be unified with similar code in windows.c */
  1700. X    
  1701. X    /* The name is taken from _wprogname, to make it clear what
  1702. X       application a dialog belongs to (especially if there is
  1703. X       no window for it yet). */
  1704. X    
  1705. X    XStoreName(_wd, box.wid, _wprogname);
  1706. X    
  1707. X    /* Set class hints */
  1708. X    {
  1709. X        XClassHint classhint;
  1710. X        classhint.res_name= _wprogname;
  1711. X        classhint.res_class= "StdwinDialog";
  1712. X        XSetClassHint(_wd, box.wid, &classhint);
  1713. X    }
  1714. X    
  1715. X    /* Set WM hints */
  1716. X    {
  1717. X        XWMHints wmhints;
  1718. X        wmhints.flags = InputHint | StateHint;
  1719. X        wmhints.input = 1;
  1720. X        wmhints.initial_state = NormalState;
  1721. X        XSetWMHints(_wd, box.wid, &wmhints);
  1722. X    }
  1723. X    
  1724. X    if (act != NULL) {
  1725. X        XSizeHints sizehints;
  1726. X        
  1727. X        /* Pretend the user specified the size and position,
  1728. X           in an attempt to avoid window manager interference */
  1729. X        sizehints.x= box.x - box.border;
  1730. X        sizehints.y= box.y - box.border;
  1731. X        sizehints.width= box.width;
  1732. X        sizehints.height= box.height;
  1733. X        sizehints.flags= USPosition|USSize;
  1734. X        XSetNormalHints(_wd, box.wid, &sizehints);
  1735. X        
  1736. X        XSetTransientForHint(_wd, box.wid, act->wo.wid);
  1737. X    }
  1738. X    
  1739. X    /* Create the prompt label */
  1740. X    
  1741. X    addbutton(LABEL, prompt, def, FALSE,
  1742. X        2,
  1743. X        2,
  1744. X        promptwidth + 2*charwidth,
  1745. X        textheight + 2);
  1746. X    
  1747. X    /* Create the command buttons and text field (for ASKSTRKIND).
  1748. X       Note that our x, y convention differs from XCreateWindow:
  1749. X       we don't include the border width. */
  1750. X    
  1751. X    switch (kind) {
  1752. X    case MESSAGEKIND:
  1753. X        addbutton(BUTTON, "OK", def, FALSE,
  1754. X            box.width - buttonwidth - 2*charwidth - 2, 2,
  1755. X            buttonwidth + 2*charwidth,
  1756. X            textheight + 2);
  1757. X        break;
  1758. X    case ASKYNCKIND:
  1759. X        addbutton(BUTTON, "Yes", 1, def==1,
  1760. X            2,
  1761. X            box.height - textheight - 4,
  1762. X            buttonwidth + 2*charwidth,
  1763. X            textheight + 2);
  1764. X        addbutton(BUTTON, "No", 0, def==0,
  1765. X            buttonwidth + 2*charwidth + 6,
  1766. X            box.height - textheight - 4,
  1767. X            buttonwidth + 2*charwidth,
  1768. X            textheight + 2);
  1769. X        addbutton(BUTTON, "Cancel", -1, def==-1,
  1770. X            box.width - buttonwidth - 2*charwidth - 2,
  1771. X            box.height - textheight - 4,
  1772. X            buttonwidth + 2*charwidth,
  1773. X            textheight + 2);
  1774. X        break;
  1775. X    case ASKSTRKIND:
  1776. X        addbutton(BUTTON, "OK", 1, FALSE,
  1777. X            2,
  1778. X            box.height - textheight - 4,
  1779. X            buttonwidth + 2*charwidth,
  1780. X            textheight + 2);
  1781. X        addbutton(BUTTON, "Cancel", 0, FALSE,
  1782. X            box.width - buttonwidth - 2*charwidth - 2,
  1783. X            box.height - textheight - 4,
  1784. X            buttonwidth + 2*charwidth,
  1785. X            textheight + 2);
  1786. X        addbutton(TEXT, buf, def, FALSE,
  1787. X            2,
  1788. X            textheight + 8,
  1789. X            box.width - 4,
  1790. X            textheight + 2);
  1791. X        break;
  1792. X    }
  1793. X    
  1794. X    /* Finish the work.
  1795. X       Map the window, process events, extract text,
  1796. X       destroy everything, return value. */
  1797. X    
  1798. X    XMapRaised(_wd, box.wid);
  1799. X    
  1800. X    ret=dialogeventloop(def);
  1801. X    if (kind == ASKSTRKIND && ret < 0)
  1802. X        ret= 0;
  1803. X    
  1804. X    if (ret > 0 && len > 0)
  1805. X        gettext(buf, len);
  1806. X    
  1807. X    XFreeGC(_wd, b_gc);
  1808. X    killbuttons();
  1809. X    XDestroyWindow(_wd, box.wid);
  1810. X    XFlush(_wd);
  1811. X    
  1812. X    _wf= save_wf;
  1813. X    
  1814. X    return ret;
  1815. X}
  1816. X
  1817. X/* Add a command button */
  1818. X
  1819. Xstatic
  1820. Xaddbutton(type, text, ret, def, x, y, width, height)
  1821. X    int type;
  1822. X    char *text;
  1823. X    int ret;
  1824. X    bool def;
  1825. X    int x, y, width, height;
  1826. X{
  1827. X    struct button b;
  1828. X    int cursor= (type == BUTTON) ? XC_arrow : 0;
  1829. X    
  1830. X    b.type= type;
  1831. X    b.text= strdup(text);
  1832. X    b.ret= ret;
  1833. X    b.def= def;
  1834. X    
  1835. X    b.wd.x= x;
  1836. X    b.wd.y= y;
  1837. X    b.wd.width= width;
  1838. X    b.wd.height= height;
  1839. X    
  1840. X    if (type == LABEL)
  1841. X        b.wd.border= 0;
  1842. X    else
  1843. X        b.wd.border= IBORDER;
  1844. X    (void) _wcreate(&b.wd, box.wid, cursor, TRUE, fg, bg);
  1845. X    XSelectInput(_wd, b.wd.wid,
  1846. X        type == BUTTON ?
  1847. X            ExposureMask|ButtonPressMask|ButtonReleaseMask|
  1848. X            EnterWindowMask|LeaveWindowMask
  1849. X        :    ExposureMask);
  1850. X    
  1851. X    b.down= 0;
  1852. X    b.inside= FALSE;
  1853. X    b.hilite= type == TEXT && text[0] != EOS;
  1854. X    
  1855. X    L_APPEND(nbuttons, buttonlist, struct button, b);
  1856. X}
  1857. X
  1858. X/* Dialog event processing loop.
  1859. X   Return number of button selected, -1 for Return, -2 for ^C. */
  1860. X
  1861. Xstatic struct button *whichbutton(); /* Forward */
  1862. X
  1863. Xstatic int
  1864. Xdialogeventloop(def)
  1865. X    int def;
  1866. X{
  1867. X    for (;;) {
  1868. X        XEvent e;
  1869. X        struct button *bp;
  1870. X        int c;
  1871. X        
  1872. X        XNextEvent(_wd, &e);
  1873. X        _wdebug(3, "dlog2: evt type %d", e.type);
  1874. X        bp= whichbutton(e.xbutton.window);
  1875. X        if (bp != NULL) {
  1876. X            if (buttonevent(bp, &e)) {
  1877. X                return bp->ret;
  1878. X            }
  1879. X        }
  1880. X        else if (e.xbutton.window == box.wid || e.type == KeyPress) {
  1881. X            switch (e.type) {
  1882. X            
  1883. X            case KeyPress:
  1884. X                switch (c= charcode(&e.xkey)) {
  1885. X                case EOS:
  1886. X                    break;
  1887. X                case '\003': /* ^C, interrupt */
  1888. X                    return -1;
  1889. X                    /* Fall through */
  1890. X                case '\n':
  1891. X                case '\r':
  1892. X                    return def;
  1893. X                default:
  1894. X                    if (!addchar(c))
  1895. X                        XBell(_wd, 0);
  1896. X                    break;
  1897. X                }
  1898. X                break;
  1899. X            
  1900. X            case MapNotify:
  1901. X                /* Could set the input focus if another
  1902. X                   of our windows has it */
  1903. X                break;
  1904. X            
  1905. X            default:
  1906. X                _wdebug(3, "dialog: box ev %d", e.type);
  1907. X                if (e.type == ButtonPress)
  1908. X                    XBell(_wd, 0);
  1909. X                break;
  1910. X            
  1911. X            }
  1912. X        }
  1913. X        else {
  1914. X            switch (e.type) {
  1915. X            case ButtonPress:
  1916. X            case KeyPress:
  1917. X                _wdebug(3, "dialog: alien press %d", e.type);
  1918. X                XBell(_wd, 0);
  1919. X                break;
  1920. X            case ButtonRelease:
  1921. X            case MotionNotify:
  1922. X                _wdebug(3, "dialog: alien move %d", e.type);
  1923. X                break;
  1924. X            default:
  1925. X                _wdebug(3, "dialog: alien llev %d", e.type);
  1926. X                _w_ll_event(&e);
  1927. X                break;
  1928. X            }
  1929. X        }
  1930. X    }
  1931. X}
  1932. X
  1933. X/* Find out which button a given Window ID belongs to (if any) */
  1934. X
  1935. Xstatic struct button *
  1936. Xwhichbutton(w)
  1937. X    Window w;
  1938. X{
  1939. X    int i;
  1940. X    
  1941. X    for (i= nbuttons; --i >= 0; ) {
  1942. X        if (w == buttonlist[i].wd.wid)
  1943. X            return &buttonlist[i];
  1944. X    }
  1945. X    return NULL;
  1946. X}
  1947. X
  1948. X/* Return the character code corresponding to a key event.
  1949. X   Returns EOS if no ASCII character. */
  1950. X
  1951. Xstatic int
  1952. Xcharcode(kep)
  1953. X    XKeyEvent *kep;
  1954. X{
  1955. X    KeySym keysym;
  1956. X    char strbuf[10];
  1957. X    
  1958. X    if (XLookupString(kep, strbuf, sizeof strbuf,
  1959. X        &keysym, (XComposeStatus*)NULL) <= 0)
  1960. X        return EOS;
  1961. X    else
  1962. X        return strbuf[0];
  1963. X}
  1964. X
  1965. X/* Append a character to the text item.
  1966. X   Here it is that we assume that the text item is last.
  1967. X   Unfortunately we can't use textedit (yet) to support all
  1968. X   desirable functionality, but we do support backspace
  1969. X   and overwriting the entire text. */
  1970. X
  1971. Xstatic bool
  1972. Xaddchar(c)
  1973. X    int c;
  1974. X{
  1975. X    struct button *bp= &buttonlist[nbuttons - 1];
  1976. X    int i;
  1977. X    
  1978. X    if (bp->type != TEXT || bp->text == NULL)
  1979. X        return FALSE;
  1980. X    i= strlen(bp->text);
  1981. X    if (c == '\b' || c == '\177' /*DEL*/ ) {
  1982. X        if (i > 0) {
  1983. X            bp->text[i-1]= EOS;
  1984. X            bp->hilite= FALSE;
  1985. X        }
  1986. X    }
  1987. X    else {
  1988. X        if (bp->hilite) {
  1989. X            i= 0;
  1990. X            bp->hilite= FALSE;
  1991. X        }
  1992. X        bp->text= realloc(bp->text, (unsigned)(i+2));
  1993. X        if (bp->text != NULL) {
  1994. X            bp->text[i]= c;
  1995. X            bp->text[i+1]= EOS;
  1996. X        }
  1997. X    }
  1998. X    drawbutton(bp);
  1999. X    return TRUE;
  2000. X}
  2001. X
  2002. X/* Process an event directed to a given button.
  2003. X   This also updates the highlighting. */
  2004. X
  2005. Xstatic bool
  2006. Xbuttonevent(bp, xep)
  2007. X    struct button *bp;
  2008. X    XEvent *xep;
  2009. X{
  2010. X    bool hit= FALSE;
  2011. X    
  2012. X    switch (xep->type) {
  2013. X    
  2014. X    case Expose:
  2015. X        drawbutton(bp);
  2016. X        return FALSE;
  2017. X    
  2018. X    case ButtonPress:
  2019. X        if (bp->down == 0)
  2020. X            bp->down= xep->xbutton.button;
  2021. X        break;
  2022. X    
  2023. X    case ButtonRelease:
  2024. X        if (bp->down == xep->xbutton.button) {
  2025. X            hit= bp->inside;
  2026. X            bp->down= 0;
  2027. X        }
  2028. X        break;
  2029. X    
  2030. X    case EnterNotify:
  2031. X        bp->inside= TRUE;
  2032. X        break;
  2033. X    
  2034. X    case LeaveNotify:
  2035. X        bp->inside= FALSE;
  2036. X        break;
  2037. X    
  2038. X    default:
  2039. X        return FALSE;
  2040. X    
  2041. X    }
  2042. X    hilitebutton(bp, bp->down > 0 && bp->inside);
  2043. X    return hit;
  2044. X}
  2045. X
  2046. X/* Draw procedure to draw a command button or text item */
  2047. X
  2048. Xstatic
  2049. Xdrawbutton(bp)
  2050. X    struct button *bp;
  2051. X{
  2052. X    char *text= bp->text == NULL ? "" : bp->text;
  2053. X    int len= strlen(text);
  2054. X    int width= XTextWidth(_wmf, text, len);
  2055. X    int x= (bp->type == BUTTON) ? (bp->wd.width - width) / 2 : charwidth;
  2056. X    int y= (bp->wd.height + _wmf->ascent - _wmf->descent) / 2;
  2057. X    
  2058. X    XClearWindow(_wd, bp->wd.wid);
  2059. X    XDrawString(_wd, bp->wd.wid, b_gc, x, y, text, len);
  2060. X    /* Indicate the default button with an underline */
  2061. X    if (bp->def) {
  2062. X        unsigned long ulpos, ulthick;
  2063. X        if (!XGetFontProperty(_wmf, XA_UNDERLINE_POSITION, &ulpos))
  2064. X            ulpos= _wmf->descent/2;
  2065. X        if (!XGetFontProperty(_wmf, XA_UNDERLINE_THICKNESS,&ulthick)) {
  2066. X            ulthick= _wmf->descent/3;
  2067. X            CLIPMIN(ulthick, 1);
  2068. X        }
  2069. X        _winvert(bp->wd.wid, b_gc,
  2070. X            x, (int)(y + ulpos), width, (int)ulthick);
  2071. X    }
  2072. X    if (bp->hilite)
  2073. X        _winvert(bp->wd.wid, b_gc,
  2074. X            0, 0, bp->wd.width, bp->wd.height);
  2075. X}
  2076. X
  2077. X/* Highlight or unhighlight a command button */
  2078. X
  2079. Xstatic
  2080. Xhilitebutton(bp, hilite)
  2081. X    struct button *bp;
  2082. X    bool hilite;
  2083. X{
  2084. X    if (bp->hilite != hilite) {
  2085. X        _winvert(bp->wd.wid, b_gc,
  2086. X            0, 0, bp->wd.width, bp->wd.height);
  2087. X        bp->hilite= hilite;
  2088. X    }
  2089. X}
  2090. X
  2091. X/* Extract the text from the text item */
  2092. X
  2093. Xstatic
  2094. Xgettext(buf, len)
  2095. X    char *buf;
  2096. X    int len;
  2097. X{
  2098. X    struct button *bp= &buttonlist[nbuttons - 1];
  2099. X    
  2100. X    if (bp->type != TEXT || bp->text == NULL)
  2101. X        return;
  2102. X    strncpy(buf, bp->text, len-1);
  2103. X    buf[len-1]= EOS;
  2104. X}
  2105. X
  2106. X/* Destroy all buttons and associated data structures */
  2107. X
  2108. Xstatic
  2109. Xkillbuttons()
  2110. X{
  2111. X    int i;
  2112. X    for (i= 0; i < nbuttons; ++i)
  2113. X        free(buttonlist[i].text);
  2114. X    L_SETSIZE(nbuttons, buttonlist, struct button, 0);
  2115. X}
  2116. END_OF_FILE
  2117. if test 14224 -ne `wc -c <'Ports/x11/dialog.c'`; then
  2118.     echo shar: \"'Ports/x11/dialog.c'\" unpacked with wrong size!
  2119. fi
  2120. # end of 'Ports/x11/dialog.c'
  2121. fi
  2122. echo shar: End of archive 6 \(of 19\).
  2123. cp /dev/null ark6isdone
  2124. MISSING=""
  2125. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  2126.     if test ! -f ark${I}isdone ; then
  2127.     MISSING="${MISSING} ${I}"
  2128.     fi
  2129. done
  2130. if test "${MISSING}" = "" ; then
  2131.     echo You have unpacked all 19 archives.
  2132.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2133. else
  2134.     echo You still need to unpack the following archives:
  2135.     echo "        " ${MISSING}
  2136. fi
  2137. ##  End of shell archive.
  2138. exit 0
  2139.