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

  1. From: guido@cwi.nl (Guido van Rossum)
  2. Newsgroups: alt.sources
  3. Subject: STDWIN 0.9.5, Part 07/19
  4. Message-ID: <3071@charon.cwi.nl>
  5. Date: 4 Mar 91 11:57:54 GMT
  6.  
  7. Archive-name: stdwin/part07
  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 7 (of 19)."
  16. # Contents:  Doc/vtrmdoc.ms Ports/mac/scroll.c Ports/x11/general.c
  17. #   Ports/x11/llevent.c
  18. # Wrapped by guido@voorn.cwi.nl on Mon Mar  4 12:37:26 1991
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'Doc/vtrmdoc.ms' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'Doc/vtrmdoc.ms'\"
  22. else
  23. echo shar: Extracting \"'Doc/vtrmdoc.ms'\" \(14015 characters\)
  24. sed "s/^X//" >'Doc/vtrmdoc.ms' <<'END_OF_FILE'
  25. X.TL
  26. X.if n .po 0
  27. X.if n .ll 72
  28. X.if n .nr LL 72n
  29. X.if t .po 3.5c \" For LaserWriter only
  30. XInterfacing to Keyboard and Screen with VTRM
  31. X.br
  32. X(Draft)
  33. X.AU
  34. XGuido van Rossum
  35. X.AB
  36. XSince both groups of `interns' at the ABC project will soon need to
  37. Xinterface their editors to a terminal, here is a description of the VTRM
  38. Xpackage, together with some hints on writing a simple displayer using
  39. Xthis package.  Footnotes are used to indicate portions of the interface
  40. Xthat may change in the future.
  41. X.AE
  42. X.SH
  43. X1. Introduction
  44. X.LP
  45. XThe VTRM package can significantly ease terminal-independent input and
  46. Xoutput for a screen-oriented program like a text editor, written in C.
  47. XThere are
  48. Xabout a dozen routines, with few and simple parameters, that allow
  49. Xoptimized output to almost any ASCII terminal designed in the Western
  50. Xhemisphere, and input of single characters without echoing.  Features
  51. Xinclude adaptation to any screen size, scrolling, and inverse video or a
  52. Xsimilar `stand-out' mode of displaying selected characters.  Screen
  53. Xrefreshes use available terminal features such as character insert or
  54. Xdelete to minimize the number of characters actually output to the
  55. Xterminal, thus obtaining reasonable performance even at low baud rates.
  56. X.PP
  57. XImplementations of the VTRM package are available for
  58. X.UX ,
  59. XMS-DOS and the Apple Macintosh, and the package can be ported to
  60. Xother similar micro-computers.  It is also possible to write an
  61. Xinterface to windowing systems like those found on Sun or Whitechapel
  62. Xworkstations.
  63. X.SH
  64. X2. Theory of operation
  65. X.LP
  66. XVTRM is a set of subroutines callable from a C program.  There is a
  67. Xcertain discipline required in calling these routines; there are
  68. Xan initialization call, several data manipulation and input calls, and a
  69. Xclean-up call.  The C program that is making the calls to VTRM is
  70. Xfurther referred to as `the application'.  In fact, on different
  71. Xsystems, different soubroutines are used; but they all conform to the
  72. Xsame interface, which is what is described in this document.
  73. X.PP
  74. XVTRM has a simple model for a terminal screen: there are YMAX lines,
  75. Xeach consisting XMAX characters.  YMAX and XMAX are not constants,
  76. Xbut remain constant during one particular program run.*
  77. X.FS
  78. X*This causes problems with resizable windows as currently available
  79. Xunder 4.3 BSD.  It is possible that future versions can adapt themselves
  80. Xto changing window sizes, but this will require adaptation of the
  81. Xprograms calling VTRM.
  82. X.FE
  83. X.PP
  84. XThe coordinate system used by VTRM is different from that normally used
  85. Xin geometry, but more convenient for referencing screen positions:
  86. Xwhereever a position on the screen is referenced, it has the form (Y, X)
  87. Xwhere Y is the line number and X is the column number.  The top line is
  88. Xline 0, the bottom line is YMAX\-1.  Likewise, the leftmost
  89. Xcolumn is column 0, the rightmost is XMAX\-1.  (Note how this is
  90. Xcompatible with array indexing practices in C.) **
  91. X.FS
  92. X** This will get us into trouble with bit-mapped displays, where often
  93. Xthe preferred character set or `font' has characters of different
  94. Xwidths, so that the number of characters displayable on a line is not a
  95. Xconstant.  This issue is ignored by VTRM; implementations on such
  96. Xsystems currently use a `fixed-width' font.
  97. X.FE
  98. X.PP
  99. XEach character position contains one character, which is in the ASCII
  100. Xrange SPACE to `~', i.e., SPACE and all printable characters.  Each
  101. Xcharacter can be displayed in one of two modes: normal or `stand-out',
  102. Xwhich is usually inverse video or underlined (this is a choice made by
  103. Xthe VTRM package).  `Empty' parts of the screen contain spaces in normal
  104. Xmode. ***
  105. X.FS
  106. X*** Eventually the character set allowed will have to be extended to all
  107. Xor most characters in the machine's standard character set that can be
  108. Xdisplayed.  There is a tendency for systems to extend the 7-bit ASCII
  109. Xcode to an 8-bit code, where the characters in the range 128-255 are
  110. Xused for special graphics, accented characters etc.  VTRM currently uses
  111. Xthe 8th bit to indicate stand-out mode; this will have to be changed in
  112. Xthe interface.  Applications are discouraged to use the 8th bit of
  113. Xcharacters as a `stand-out' flag except in the immediate interface with
  114. XVTRM.
  115. X.FE
  116. X.PP
  117. XVTRM is strongly line-oriented.  The application must offer data to VTRM
  118. Xin chunks of one or more lines, and scrolling operations can only be
  119. Xapplied to entire lines.  This is not likely to change in the near
  120. Xfuture.  VTRM does not necessarily send whole lines to the screen: only
  121. Xchanged parts of a line are actually transmitted.  VTRM recognizes most
  122. Xcases of insertion or deletion of small strings in a line, which can
  123. Xoften be handled with character insertions and/or deletions.
  124. X.PP
  125. XVTRM may buffer its output.  There is one routine which flushes the
  126. Xbuffer and moves the terminal's cursor to a given (Y, X) position;
  127. Xduring the screen update process the screen contents and cursor position
  128. Xmay temporarily be undefined.  Not all implementations actually buffer
  129. Xtheir output; micro-computer screen operations are often fast enough.
  130. XIn all cases, the cursor position is undefined during the screen update.
  131. X.PP
  132. XVTRM does not automatically clear the screen when first called; it
  133. Xallows an application to be written in such a manner that its output
  134. Xappears at the bottom of the screen and gradually scrolls upwards,
  135. Xmimicking the behaviour of older programs, if it so wishes.  On the
  136. Xother hand, it is trivial to clear the screen after the first call.
  137. X.PP
  138. XOn
  139. X.UX ,
  140. XVTRM sets the terminal in a special mode (formally: cbreak, no echo, no
  141. Xcr to nl mapping).  This makes it
  142. Xnecessary that an application takes measures to call the VTRM clean-up
  143. Xroutine whenever it exits.
  144. X.PP
  145. XOn
  146. X.UX ,
  147. XVTRM uses the `termcap' database to find out the terminal's
  148. Xcapabilities.  It requires that the <:TERM:> environment variable is
  149. Xset, and optionally acknowledges the <:TERMCAP:> variable.  Information
  150. Xon the proper use of these variables should be readily accessible to all
  151. Xusers of the application.
  152. X.SH
  153. X3. Description of the interface
  154. X.SH
  155. X3.1 Set-up and clean-up calls
  156. X.SH
  157. XTRMSTART
  158. X.LP
  159. X.DS
  160. X<:int trmstart(p_lines, p_columns, p_flags)
  161. Xint *p_lines, *p_columns;
  162. Xint *p_flags;:>
  163. X.DE
  164. XThis call must be made before any of the other calls are allowed.  The
  165. Xfunction result is 0 if initialization is successful, nonzero if an
  166. Xerror occurred.  In the latter case the applications should usually
  167. Xprint an error message and exit; the terminal state has not been
  168. Xaltered.  The meaning of the error codes is described in the appendix.
  169. X.PP
  170. XThe three arguments must be the addresses of three integer variables
  171. X(call as, e.g., <:trmstart(&lines, &columns, &flags):>).
  172. XIn <:*p_lines:> and <:*p_columns:>, YMAX and XMAX are returned.
  173. XIn <:*p_flags:>, some flag bits are returned, but these can usually be
  174. Xignored by the applications (some flag bits are defined but never used).
  175. X.SH
  176. XTRMEND
  177. X.LP
  178. X.DS
  179. X<:trmend();:>
  180. X.DE
  181. XThis function cleans up before the application exits.  If it is not
  182. Xcalled (when <:trmstart:> has been called), the application may leave
  183. Xthe terminal in a weird mode, from which it is hard to recover for the
  184. Xuser (on
  185. X.UX -systems non-
  186. Xother weird things may happen).
  187. X.PP
  188. XSo that it can be safely called from within an interrupt handler,
  189. X<:trmend:> may be called at any time, before or even during a call to
  190. X<:trmstart:>.  Calls at any other time than after a successful call
  191. Xto <:trmstart:> are ignored.  After a call to <:trmend:>, as before a
  192. Xcall to <:trmstart:>, calls to all other routines of VTRM are forbidden
  193. X(this is not enforced by all implementations \- but your program may
  194. Xcrash).
  195. X.PP
  196. XAn application may engage in a sequence of interactive sessions, each
  197. Xbracketed between calls to <:trmstart:> and <:trmend:>.  Outside these
  198. Xsessions, normal print-style output can safely be used, thusly:
  199. X.DS
  200. X<:trmstart(...);
  201. X\fIVTRM interaction 1\fP
  202. Xtrmend();
  203. Xprintf("Hello, world\\n"); /* Etc. */
  204. Xtrmstart(...);
  205. X\fIVTRM interaction 2\fP
  206. Xtrmend();
  207. X:><:...:>
  208. X.DE
  209. X.SH
  210. X3.2 Output calls
  211. X.SH
  212. XTRMPUTDATA
  213. X.LP
  214. X.DS
  215. X<:trmputdata(y0, y1, x, data)
  216. Xint y0, y1;
  217. Xint x;
  218. Xchar *data;:>
  219. X.DE
  220. XThe characters in `data' are placed on the screen, starting at line y0,
  221. Xposition x, and continuing up to the last position of line y1.  If data
  222. Xis shorter than this space, the remaining positions are filled with
  223. Xspaces; if tdata is too long, it is truncated.  The positions 0 through
  224. Xx\-1 on line y0 are left unchanged.
  225. X.PP
  226. XCharacters with their 8th bit on (or-ed with 0200 octal or 0x80 hex)
  227. Xare displayed in `stand-out' mode.
  228. X.PP
  229. XThe following is an easy way of clearing the screen:
  230. X.DS
  231. X<:trmputdata(0, YMAX-1, 0, "");:>
  232. X.DE
  233. X.SH
  234. XTRMSCROLLUP
  235. X.LP
  236. X.DS
  237. X<:trmscrollup(y0, y1, n)
  238. Xint y0, y1;
  239. Xint n;:>
  240. X.DE
  241. XScrolls the screen lines y0 to y1, inclusive, up by n lines.
  242. XIf n is negative, it scrolls down.  When scrolling up, the top n lines
  243. Xstarting at y0 disappear, the lines from y0+n to y1 move up n lines,
  244. Xand n blank lines are `shifted in' at and above line y1.  Scrolling down
  245. Xis similar.  If abs(n) > y1\-y0, lines y0 to y1 are blanked.
  246. X.SH
  247. XTRMSYNC
  248. X.LP
  249. X.DS
  250. X<:trmsync(y, x)
  251. Xint y, x;:>
  252. X.DE
  253. XCompletes any pending operations, flushes the output buffer, and moves
  254. Xthe cursor to position (y, x) on the screen.
  255. X.SH
  256. XTRMUNDEFINED
  257. X.LP
  258. X.DS
  259. X<:trmundefined();:>
  260. X.DE
  261. XTells VTRM to forget whatever it has remembered about the current screen
  262. Xcontents.  This is necessary before doing a complete screen refresh in
  263. Xresponse to a user command like control-L, since such a refresh is
  264. Xusually intended to correct the effect of transmission errors or other
  265. Xprocesses clobbering the screen.
  266. X.SH
  267. XTRMBELL
  268. X.LP
  269. X.DS
  270. X<:trmbell();:>
  271. X.DE
  272. XIssues an alarm to the user in a way most appropriate to the output
  273. Xdevice being used.  This may either be an audible bell or beep,
  274. Xor a `visible bell', meaning a flash of (part of) the screen.
  275. X.PP
  276. X(On
  277. X.UX ,
  278. Xa control-G is sent to the terminal, unless the termcap entry specifies
  279. Xthe `vb' property (visible bell).  On MS-DOS, the bell is sounded
  280. Xunconditionally.  On the Macintosh, `SysBeep' is called, which gives a
  281. Xbeep with a level determined by the volume control on the Control Panel,
  282. Xor flashes the menu bar if the volume is set to 0.)
  283. X.SH
  284. X3.3 Input calls
  285. X.SH
  286. XTRMINPUT
  287. X.LP
  288. X.DS
  289. X<:int trminput();:>
  290. X.DE
  291. XReturns the next input character typed at the keyboard, waiting if
  292. Xnecessary until one is typed.  When an error occurs, \-1 is returned;
  293. Xthis is usually permanent, so further input would be futile.  This could
  294. Xhappen, for example, when the user `hangs up'.
  295. X.SH
  296. XTRMAVAIL
  297. X.LP
  298. X.DS
  299. X<:int trmavail();:>
  300. X.DE
  301. XReturns 1 if an input character is immediately available for
  302. X<:trminput:>; 0 if no such character is available; and \-1 if the system
  303. Xcan't find out (this is not an error condition; it means that the system
  304. Xcannot do a `non-blocking read').
  305. X.SH
  306. XTRMSENSE
  307. X.LP
  308. X.DS
  309. X<:int trmsense(p_y, p_x)
  310. Xint *p_y, *p_x;:>
  311. X.DE
  312. XSenses the current cursor or mouse position, and returns its position,
  313. Xconverted to screen coordinates, in <:*p_y:> and <:*p_x:>.  If the
  314. Xterminal is not capable of sensing the cursor position, both values are
  315. Xset to \-1 and the functions returns 0; after a successful sense, the
  316. Xfunction returns 1.
  317. X.SH
  318. X3.4 Interrupt handling calls
  319. X.SH
  320. XTRMINTERRUPT
  321. X.LP
  322. X.DS
  323. X<:int trminterrupt();:>
  324. X.DE
  325. XChecks for keyboard-generated interrupt.  Returns 1 if one is found, 0
  326. Xif not.  This may set a signal handler for <:SIGINT:>, so it may
  327. Xinterfere with the application's signal handling.*  It may also flush
  328. Xtype-ahead and (unfortunately enough) discard output buffers.
  329. X.FS
  330. X* This is an experimental feature.  Use at own risk.  Check the source
  331. Xcode to see if its actually implemented, and how.
  332. X.FE
  333. X.SH
  334. XTRMSUSPEND
  335. X.LP
  336. X.DS
  337. X<:trmsuspend();:>
  338. X.DE
  339. XThis call does nothing except on Berkeley
  340. X.UX
  341. Xsupporting job control.  Because the terminal state and screen contents
  342. Xare not restored when a process is suspended or resumed, programs using
  343. XVTRM must be aware of suspension.  The character control-Z is received
  344. Xas a normal input character by <:trminput:>, because <:trmstart:> turns
  345. Xoff most special character processing.  When a control-Z is received,
  346. Xthe application should react as follows:
  347. X.DS
  348. X<:trmend();
  349. Xtrmsuspend();
  350. Xtrmstart(...);
  351. X\fIrepaint the screen\fR:>
  352. X.DE
  353. XThe <:trmsuspend:> call suspends the application and its `process group';
  354. Xthis includes any subprocesses, and possibly parent processes (if the
  355. Xapplication was run from a shell script or from another program, maybe
  356. Xusing a `shell escape').  It only returns when the process group is resumed
  357. Xagain (with the shell's `fg' command).
  358. X.SH
  359. X4. Examples
  360. X.LP
  361. XHere is a very small sample program:
  362. X.DS
  363. X<:main() {
  364. X    int lines, columns, flags;
  365. X    if (trmstart(&lines, &columns, &flags) != 0) exit(1);
  366. X    trmputdata(0, lines-1, 0, "Hello, \\327orld!");
  367. X    trmsync(1, 0);
  368. X    trmend();
  369. X    exit(0);
  370. X}:>
  371. X.DE
  372. XIt prints the text <:Hello, \fBW\fRorld!:> at the top of the screen,
  373. Xcleans the rest of the screen, and moves the cursor the the beginning of
  374. Xthe second line.  The `W' is displayed in stand-out mode.
  375. X.TL
  376. XAppendix \- <:\fBtrmstart:> error codes and flags
  377. X.sp 2
  378. X.LP
  379. XThe file "trm.h" can be included to get definitions for the flags and
  380. Xerror codes returned by <:trmstart:>.  It contains the following:
  381. X.sp 1
  382. X.nf
  383. X<:
  384. X.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
  385. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  386. X
  387. X/*
  388. X * Terminal capabilities.  These correspond to bits set by trmstart in its
  389. X * parameter flags parameter.
  390. X */
  391. X
  392. X#define HAS_STANDOUT    1    /* Terminal has inverse video or underline */
  393. X#define CAN_SCROLL    2    /* Terminal can insert/delete lines */
  394. X#define CAN_OPTIMISE    4    /* Terminal can insert/delete characters */
  395. X#define CAN_SENSE    8    /* Terminal can send cursor position */
  396. X
  397. X/*
  398. X * Error codes returned by trmstart.
  399. X */
  400. X
  401. X#define TE_OK        0    /* No errors */
  402. X#define TE_TWICE    1    /* Trmstart called again */
  403. X#define TE_NOTERM    2    /* $TERM not set or empty */
  404. X#define TE_BADTERM    3    /* $TERM not found in termcap database */
  405. X#define TE_DUMB        4    /* Terminal too dumb */
  406. X#define TE_NOTTY    5    /* Stdout not a tty device */
  407. X#define TE_NOMEM    6    /* Can't get enough memory */
  408. X#define TE_OTHER    7    /* This and higher are reserved errors */
  409. X:>
  410. X.fi
  411. END_OF_FILE
  412. if test 14015 -ne `wc -c <'Doc/vtrmdoc.ms'`; then
  413.     echo shar: \"'Doc/vtrmdoc.ms'\" unpacked with wrong size!
  414. fi
  415. # end of 'Doc/vtrmdoc.ms'
  416. fi
  417. if test -f 'Ports/mac/scroll.c' -a "${1}" != "-c" ; then 
  418.   echo shar: Will not clobber existing file \"'Ports/mac/scroll.c'\"
  419. else
  420. echo shar: Extracting \"'Ports/mac/scroll.c'\" \(13659 characters\)
  421. sed "s/^X//" >'Ports/mac/scroll.c' <<'END_OF_FILE'
  422. X/* MAC STDWIN -- SCROLLING. */
  423. X
  424. X/* All non-public functions here assume the current grafport is set */
  425. X
  426. X/* XXX The contents of this file should be organized more top-down */
  427. X
  428. X#include "macwin.h"
  429. X#ifdef MPW
  430. X#include <Events.h>
  431. X#endif
  432. X
  433. X/* I am using the fact here that the scroll bars of an inactive window
  434. X   are invisible:
  435. X   when a window's origin or its document size changes while it isn't the
  436. X   active window, its controls get their new values but aren't redrawn. */
  437. X
  438. X/* Key repeat constants in low memory (set by the Control Panel),
  439. X   in ticks (used here to control the continuous scrolling speed). */
  440. X
  441. X#define KeyThresh    (* (short*)0x18e)    /* Delay until repeat starts */
  442. X#define KeyRepThresh    (* (short*)0x190)    /* Repeat rate */
  443. X
  444. X#define JURJENBARPROC 48 /* CDEF id for Jurjen's proportional scrollbar */
  445. X
  446. XSTATIC void setscrollbarvalues _ARGS((WINDOW *win));
  447. XSTATIC void usescrollbarvalues _ARGS((WINDOW *win));
  448. XSTATIC void sizescrollbars _ARGS((WINDOW *win));
  449. XSTATIC void calcbar _ARGS((ControlHandle bar,
  450. X    int org, int size, int begin, int end));
  451. XSTATIC void setbar _ARGS((ControlHandle bar, int winsize, int val, int max));
  452. XSTATIC void deltabar _ARGS((ControlHandle bar, int delta));
  453. XSTATIC void showbar _ARGS((ControlHandle bar));
  454. XSTATIC void hidebar _ARGS((ControlHandle bar));
  455. XSTATIC void movebar _ARGS((ControlHandle bar,
  456. X    int left, int top, int right, int bottom));
  457. X
  458. Xvoid
  459. Xwsetorigin(win, orgh, orgv)
  460. X    WINDOW *win;
  461. X    int orgh, orgv;
  462. X{
  463. X    Rect r;
  464. X    
  465. X    /* XXX wsetorigin is currently the only routine that allows
  466. X       the application to show bits outside the document.
  467. X       Is even this desirable? */
  468. X    
  469. X    CLIPMIN(orgh, 0);
  470. X    CLIPMIN(orgv, 0);
  471. X    getwinrect(win, &r);
  472. X    orgh -= LSLOP;
  473. X    if (orgh != win->orgh || orgv != win->orgv) {
  474. X        SetPort(win->w);
  475. X        scrollby(win, &r, win->orgh - orgh, win->orgv - orgv);
  476. X        win->orgh= orgh;
  477. X        win->orgv= orgv;
  478. X        setscrollbarvalues(win);
  479. X    }
  480. X}
  481. X
  482. Xvoid
  483. Xwgetorigin(win, ph, pv)
  484. X    WINDOW *win;
  485. X    int *ph, *pv;
  486. X{
  487. X    *ph = win->orgh + LSLOP;
  488. X    *pv = win->orgv;
  489. X}
  490. X
  491. Xvoid
  492. Xwshow(win, left, top, right, bottom)
  493. X    WINDOW *win;
  494. X    int left, top, right, bottom;
  495. X{
  496. X    int orgh, orgv;
  497. X    int winwidth, winheight;
  498. X    int docwidth, docheight;
  499. X    
  500. X    /* Calls to wshow while the mouse is down are ignored,
  501. X       because they tend to mess up auto-scrolling.
  502. X       I presume it's harmless (even the right thing to do),
  503. X       since wshow is usually called to make sure the object
  504. X       being selected is visible, which isn't a problem while
  505. X       the user is busy pointing at it.
  506. X       The check must be here, not in wsetorigin, because
  507. X       the latter is used internally by the auto-scroll code! */
  508. X    if (_wm_down)
  509. X        return;
  510. X    
  511. X    /* The code below is generic for all versions of stdwin */
  512. X    
  513. X    wgetorigin(win, &orgh, &orgv);
  514. X    wgetwinsize(win, &winwidth, &winheight);
  515. X    wgetdocsize(win, &docwidth, &docheight);
  516. X    
  517. X    orgh = calcneworigin(orgh, left, right, winwidth, docwidth);
  518. X    orgv = calcneworigin(orgv, top, bottom, winheight, docheight);
  519. X    
  520. X    wsetorigin(win, orgh, orgv);
  521. X}
  522. X
  523. X/* Subroutine for wshow to calculate new origin in h or v direction */
  524. X
  525. Xstatic int
  526. Xcalcneworigin(org, low, high, winsize, docsize)
  527. X    int org, low, high, winsize, docsize;
  528. X{
  529. X    if (docsize <= 0)
  530. X        return org;
  531. X    
  532. X    /* Ignore requests to show bits outside doc */
  533. X    /* XXX Is this necessary? */
  534. X    CLIPMIN(low, 0);
  535. X    CLIPMAX(high, docsize);
  536. X    
  537. X    /* Ignore requests for empty range */
  538. X    /* XXX Is this what we want? */
  539. X    if (high <= low)
  540. X        return org;
  541. X    
  542. X    if (org <= low && high <= org + winsize)
  543. X        return org;
  544. X    
  545. X    if (high - low > winsize) {    /* Range too big for window */
  546. X        
  547. X        /* Don't scroll if at least 1/3 of the window is in range */
  548. X        /* XXX 1/3 is an arbitrary number! */
  549. X        if (low <= org + winsize*2/3 && high >= org + winsize/3)
  550. X            return org;
  551. X        
  552. X        /* Center the end of the range that's closest to the window */
  553. X        if (low - org >= org + winsize - high) {
  554. X            org = low - winsize/2;
  555. X            CLIPMIN(org, 0);
  556. X            return org;
  557. X        }
  558. X        else {
  559. X            org = high - winsize/2;
  560. X            CLIPMAX(org, docsize);
  561. X            CLIPMIN(org, 0);
  562. X            return org;
  563. X        }
  564. X    }
  565. X    
  566. X    /* The whole range will fit */
  567. X    
  568. X    /* See if it makes sense to scroll less than the window size */
  569. X    if (low < org) {
  570. X        if (org - low < winsize)
  571. X            return low;
  572. X    }
  573. X    else if (high > org + winsize) {
  574. X        if (high - (org + winsize) < winsize)
  575. X            return high - winsize;
  576. X    }
  577. X    
  578. X    /* Would have to scroll at least winsize -- center the range */
  579. X    org = (low + high - winsize) / 2;
  580. X    
  581. X    /* Make sure we stay within the document */
  582. X    CLIPMIN(org, 0);
  583. X    CLIPMAX(org, docsize);
  584. X    
  585. X    return org;
  586. X}
  587. X
  588. Xvoid
  589. Xwsetdocsize(win, docwidth, docheight)
  590. X    WINDOW *win;
  591. X    int docwidth, docheight;
  592. X{
  593. X    CLIPMIN(docwidth, 0);
  594. X    CLIPMIN(docheight, 0);
  595. X    if (docwidth == win->docwidth && docheight == win->docheight)
  596. X        return;
  597. X    win->docwidth= docwidth;
  598. X    win->docheight= docheight;
  599. X    SetPort(win->w);
  600. X    setscrollbarvalues(win);
  601. X    _wfixorigin(win);
  602. X    
  603. X    /* Make the zoomed window size the full document size,
  604. X       or the full screen size if the document is bigger. */
  605. X    
  606. X    if (((WindowPeek)(win->w))->dataHandle != NULL) {
  607. X        WStateData *data = (WStateData *)
  608. X            *((WindowPeek)(win->w))->dataHandle;
  609. X        if (data != NULL) {
  610. X            if (docwidth > 0) {
  611. X                CLIPMIN(docwidth, MIN_WIDTH);
  612. X                data->stdState.right =
  613. X                    data->stdState.left
  614. X                    + LSLOP + docwidth + RSLOP + BAR;
  615. X            }
  616. X            else
  617. X                data->stdState.right = 0x7fff;
  618. X            CLIPMAX(data->stdState.right,
  619. X                screen->portRect.right-3);
  620. X            if (docheight > 0) {
  621. X                CLIPMIN(docheight, MIN_HEIGHT);
  622. X                data->stdState.bottom =
  623. X                    data->stdState.top
  624. X                    + docheight + BAR;
  625. X            }
  626. X            else
  627. X                data->stdState.bottom = 0x7fff;
  628. X            CLIPMAX(data->stdState.bottom,
  629. X                screen->portRect.bottom-3);
  630. X        }
  631. X    }
  632. X}
  633. X
  634. Xvoid
  635. Xwgetdocsize(win, pwidth, pheight)
  636. X    WINDOW *win;
  637. X    int *pwidth, *pheight;
  638. X{
  639. X    *pwidth = win->docwidth;
  640. X    *pheight = win->docheight;
  641. X}
  642. X
  643. X/* Fix the window's origin after a document or window resize.
  644. X   (Also used from do_size() in event.c) */
  645. X
  646. X_wfixorigin(win)
  647. X    WINDOW *win;
  648. X{
  649. X    int orgh, orgv;
  650. X    int winwidth, winheight;
  651. X    int docwidth, docheight;
  652. X    wgetorigin(win, &orgh, &orgv);
  653. X    wgetwinsize(win, &winwidth, &winheight);
  654. X    wgetdocsize(win, &docwidth, &docheight);
  655. X    
  656. X    /* XXX Do we really want this?
  657. X       This means that in a text edit window, if you are focused
  658. X       at the bottom, every line deletion causes a scroll.
  659. X       Oh well, I suppose that text edit windows could fix
  660. X       their document size to include some blank lines at the
  661. X       end...
  662. X    */
  663. X    
  664. X    CLIPMAX(orgh, docwidth - winwidth);
  665. X    CLIPMIN(orgh, 0);
  666. X    CLIPMAX(orgv, docheight - winheight);
  667. X    CLIPMIN(orgv, 0);
  668. X    wsetorigin(win, orgh, orgv);
  669. X}
  670. X
  671. X/* do_scroll is called from event.c when a click in a scroll bar
  672. X   is detected */
  673. X
  674. XSTATIC pascal trackbar(ControlHandle bar, short pcode); /* Forward */
  675. X
  676. Xstatic WINDOW *scrollwin;    /* The window (needed by 'trackbar') */
  677. Xstatic int scrollstep;        /* By how much we scroll */
  678. Xstatic long deadline;        /* When the next step may happen */
  679. X
  680. Xvoid
  681. Xdo_scroll(pwhere, win, bar, pcode)
  682. X    Point *pwhere;
  683. X    WINDOW *win;
  684. X    ControlHandle bar;
  685. X    int pcode;
  686. X{
  687. X    int step, page;
  688. X    ProcPtr action;
  689. X    int width, height;
  690. X    
  691. X    wgetwinsize(win, &width, &height);
  692. X    
  693. X    if (bar == win->hbar) {
  694. X        step= width / 20;
  695. X        CLIPMIN(step, 1);
  696. X        page= width / 2;
  697. X    }
  698. X    else if (bar == win->vbar) {
  699. X        step= wlineheight(); /* Should use current win's */
  700. X        page= height - step;
  701. X    }
  702. X    else
  703. X        return;
  704. X    
  705. X    page= (page/step) * step; /* Round down to multiple of step */
  706. X    action= trackbar;
  707. X    scrollwin= win;
  708. X    
  709. X    switch (pcode) {
  710. X    case inUpButton:
  711. X        scrollstep= -step;
  712. X        break;
  713. X    case inDownButton:
  714. X        scrollstep= step;
  715. X        break;
  716. X    case inPageUp:
  717. X        scrollstep= -page;
  718. X        break;
  719. X    case inPageDown:
  720. X        scrollstep= page;
  721. X        break;
  722. X    default:
  723. X        action= NULL;
  724. X        break;
  725. X    }
  726. X    
  727. X    deadline= 0;
  728. X    if (TrackControl(bar, PASSPOINT *pwhere, action) == inThumb)
  729. X        usescrollbarvalues(win);
  730. X}
  731. X
  732. Xstatic pascal
  733. Xtrackbar(bar, pcode)
  734. X    ControlHandle bar;
  735. X    short pcode;
  736. X{
  737. X    long now= TickCount();
  738. X    if (now >= deadline && pcode != 0) {
  739. X        deltabar(bar, scrollstep);
  740. X        usescrollbarvalues(scrollwin);
  741. X        wupdate(scrollwin);
  742. X        if (deadline == 0 && KeyThresh > KeyRepThresh)
  743. X            deadline= now + KeyThresh;
  744. X            /* Longer delay first time */
  745. X        else
  746. X            deadline= now + KeyRepThresh;
  747. X    }
  748. X}
  749. X
  750. X/* Automatic scrolling when the mouse is pressed and moved outside
  751. X   the application panel. */
  752. X
  753. Xvoid
  754. Xautoscroll(win, h, v)
  755. X    WINDOW *win;
  756. X    int h, v; /* Mouse location in local coordinates */
  757. X{
  758. X    Rect r;
  759. X    int dh= 0, dv= 0;
  760. X    
  761. X    getwinrect(win, &r);
  762. X    if (h < r.left)
  763. X        dh= h - r.left;
  764. X    else if (h > r.right)
  765. X        dh= h - r.right;
  766. X    if (v < r.top)
  767. X        dv= v - r.top;
  768. X    else if (v > r.bottom)
  769. X        dv= v - r.bottom;
  770. X    if (dh != 0 || dv != 0) {
  771. X        /* NOTE: assuming current grafport is win->w */
  772. X        deltabar(win->hbar, dh);
  773. X        deltabar(win->vbar, dv);
  774. X        usescrollbarvalues(win);
  775. X    }
  776. X}
  777. X
  778. X/* Alternative scrolling: Option-click produces a 'hand' cursor
  779. X   and allows scrolling like in MacPaint.  Called from event.c. */
  780. X
  781. Xvoid
  782. Xdragscroll(win, h, v, constrained)
  783. X    WINDOW *win;
  784. X    int h, v;
  785. X    int constrained;
  786. X{
  787. X    int do_h= !constrained, do_v= !constrained;
  788. X    
  789. X    while (StillDown()) {
  790. X        Point mouse;
  791. X        SetPort(win->w);
  792. X        GetMouse(&mouse);
  793. X        if (constrained) {
  794. X            int ah= ABS(h - mouse.h);
  795. X            int av= ABS(v - mouse.v);
  796. X            if (ABS(ah - av) < 2)
  797. X                continue;
  798. X            if (ah > av)
  799. X                do_h= TRUE;
  800. X            else
  801. X                do_v= TRUE;
  802. X            constrained= FALSE;
  803. X        }
  804. X        if (do_h)
  805. X            deltabar(win->hbar, h - mouse.h);
  806. X        if (do_v)
  807. X            deltabar(win->vbar, v - mouse.v);
  808. X        usescrollbarvalues(win);
  809. X        wupdate(win);
  810. X        h= mouse.h;
  811. X        v= mouse.v;
  812. X    }
  813. X}
  814. X
  815. Xvoid
  816. Xmakescrollbars(win)
  817. X    WINDOW *win;
  818. X{
  819. X    Rect r;
  820. X    int id= scrollBarProc;
  821. X    
  822. X    /* The scroll bars are initially created at a dummy location,
  823. X       and then moved to their proper location.
  824. X       They are not displayed here;
  825. X       that's done only when an activate event arrives. */
  826. X    
  827. X#ifdef JURJENBARPROC
  828. X    /* If Jurjen's proportional scroll bar exists, use it.
  829. X       (For the vertical bar only -- it doesn't understand
  830. X       about horizontal bars...) */
  831. X    if (cdefexists(JURJENBARPROC))
  832. X        id= JURJENBARPROC;
  833. X#endif JURJENBARPROC
  834. X
  835. X    SetRect(&r, 0, 0, 1, 1); /* Dummy rectangle */
  836. X    win->hbar= NewControl(win->w,
  837. X        &r, "", false, 0, 0, 0, scrollBarProc, 0L);
  838. X    win->vbar= NewControl(win->w,
  839. X        &r, "", false, 0, 0, 0, id, 0L);
  840. X    sizescrollbars(win);
  841. X}
  842. X
  843. X#ifdef JURJENBARPROC
  844. Xstatic int
  845. Xcdefexists(id)
  846. X    int id;
  847. X{
  848. X    return GetResource('CDEF', id/16) != NULL;
  849. X}
  850. X#endif
  851. X
  852. Xvoid
  853. Xshowscrollbars(win)
  854. X    WINDOW *win;
  855. X{
  856. X    DrawGrowIcon(win->w);
  857. X    showbar(win->hbar);
  858. X    showbar(win->vbar);
  859. X}
  860. X
  861. Xvoid
  862. Xhidescrollbars(win)
  863. X    WINDOW *win;
  864. X{
  865. X    hidebar(win->hbar);
  866. X    hidebar(win->vbar);
  867. X}
  868. X
  869. Xvoid
  870. Xmovescrollbars(win)
  871. X    WINDOW *win;
  872. X{
  873. X    hidescrollbars(win);
  874. X    sizescrollbars(win);
  875. X    showscrollbars(win);
  876. X}
  877. X
  878. Xstatic void
  879. Xsizescrollbars(win)
  880. X    WINDOW *win;
  881. X{
  882. X    Rect r;
  883. X    
  884. X    /* This should be done while the scroll bars are invisible. */
  885. X    
  886. X    r= win->w->portRect;
  887. X    movebar(win->vbar, r.right - BAR, r.top - 1,
  888. X        r.right + 1, r.bottom - BAR + 1);
  889. X    movebar(win->hbar, r.left - 1, r.bottom - BAR,
  890. X        r.right - BAR + 1, r.bottom + 1);
  891. X    setscrollbarvalues(win);
  892. X}
  893. X
  894. Xstatic void
  895. Xsetscrollbarvalues(win)
  896. X    WINDOW *win;
  897. X{
  898. X    Rect r;
  899. X    
  900. X    getwinrect(win, &r);
  901. X    calcbar(win->hbar,
  902. X        win->orgh, win->docwidth, LSLOP, r.right - r.left - RSLOP);
  903. X    calcbar(win->vbar,
  904. X        win->orgv, win->docheight, 0, r.bottom - r.top);
  905. X    if (win == active) {
  906. X        /* XXX Should only draw those controls that have changed. */
  907. X        DrawControls(win->w);
  908. X        valid_border(win->w);
  909. X    }
  910. X}
  911. X
  912. X/*
  913. X * Calculate (and set!) the new value of a scroll bar.
  914. X * Parameters (all pertaining to either h or v): 
  915. X * org:     origin of window (win->orgh or win->orgv)
  916. X * size:    extent of document (win->docwidth or win->docheight)
  917. X * begin:    position of document origin if bar is at its beginning
  918. X * end:        position of document end if bar is at its end
  919. X * Situation sketch:
  920. X *                0    begin                          end  winwidth
  921. X *                +====+==============================+====+
  922. X *                     +--------------------------------------------------+
  923. X * +--------------------------------------------------+
  924. X * Window shown on top; min document position in the middle;
  925. X * max document position below.  Org is (begin of win) - (begin of doc).
  926. X */
  927. X
  928. Xstatic void
  929. Xcalcbar(bar, org, size, begin, end)
  930. X    ControlHandle bar;
  931. X    int org, size;
  932. X    int begin, end;
  933. X{
  934. X    int range;
  935. X    /* For the caller it's easier to remember to pass win->org{h,v};
  936. X       but for our calculations it's easier to have the sign reversed! */
  937. X    org= -org;
  938. X    CLIPMIN(begin, org);
  939. X    CLIPMIN(size, 0);
  940. X    CLIPMAX(end, org + size);
  941. X    range = size - (end - begin);
  942. X    CLIPMIN(range, 0);
  943. X    setbar(bar, end - begin, begin - org, range);
  944. X}
  945. X
  946. Xstatic void
  947. Xusescrollbarvalues(win)
  948. X    WINDOW *win;
  949. X{
  950. X    wsetorigin(win,
  951. X        GetCtlValue(win->hbar) - GetCtlMin(win->hbar),
  952. X        GetCtlValue(win->vbar) - GetCtlMin(win->vbar));
  953. X    /* Implies setscrollbarvalues! */
  954. X}
  955. X
  956. Xstatic void
  957. Xsetbar(bar, winsize, val, max)
  958. X    ControlHandle bar;
  959. X    int winsize, val, max;
  960. X{
  961. X    if (bar != NULL) {
  962. X        ControlPtr p= *bar;
  963. X        if (max < 0)
  964. X            max= 0;
  965. X        if (val > max)
  966. X            val= max;
  967. X        if (val < 0)
  968. X            val= 0;
  969. X        p->contrlMin= winsize;
  970. X        p->contrlValue= val + winsize;
  971. X        p->contrlMax= max + winsize;
  972. X        /* Must be drawn by DrawControls or ShowControl. */
  973. X    }
  974. X}
  975. X
  976. Xstatic void
  977. Xdeltabar(bar, delta)
  978. X    ControlHandle bar;
  979. X    int delta;
  980. X{
  981. X    int min= GetCtlMin(bar);
  982. X    int val= GetCtlValue(bar);
  983. X    int max= GetCtlMax(bar);
  984. X    int newval= val + delta;
  985. X    
  986. X    if (newval > max)
  987. X        newval= max;
  988. X    if (newval < min)
  989. X        newval= min;
  990. X    if (newval != val)
  991. X        SetCtlValue(bar, newval);
  992. X}
  993. X
  994. Xstatic void
  995. Xshowbar(bar)
  996. X    ControlHandle bar;
  997. X{
  998. X    if (bar != NULL)
  999. X        ShowControl(bar);
  1000. X}
  1001. X
  1002. Xstatic void
  1003. Xhidebar(bar)
  1004. X    ControlHandle bar;
  1005. X{
  1006. X    if (bar != NULL)
  1007. X        HideControl(bar);
  1008. X}
  1009. X
  1010. Xstatic void
  1011. Xmovebar(bar, left, top, right, bottom)
  1012. X    ControlHandle bar;
  1013. X    int left, top, right, bottom;
  1014. X{
  1015. X    if (bar != NULL) {
  1016. X        /* This works best while the scroll bar is invisible. */
  1017. X        MoveControl(bar, left, top);
  1018. X        SizeControl(bar, right-left, bottom-top);
  1019. X    }
  1020. X}
  1021. END_OF_FILE
  1022. if test 13659 -ne `wc -c <'Ports/mac/scroll.c'`; then
  1023.     echo shar: \"'Ports/mac/scroll.c'\" unpacked with wrong size!
  1024. fi
  1025. # end of 'Ports/mac/scroll.c'
  1026. fi
  1027. if test -f 'Ports/x11/general.c' -a "${1}" != "-c" ; then 
  1028.   echo shar: Will not clobber existing file \"'Ports/x11/general.c'\"
  1029. else
  1030. echo shar: Extracting \"'Ports/x11/general.c'\" \(13917 characters\)
  1031. sed "s/^X//" >'Ports/x11/general.c' <<'END_OF_FILE'
  1032. X/* X11 STDWIN -- General initializations, enquiries and defaults */
  1033. X
  1034. X#include "x11.h"
  1035. X
  1036. X
  1037. X/* Private globals */
  1038. X
  1039. XDisplay *_wd;            /* The Display (== connection) */
  1040. XScreen *_ws;            /* The screen */
  1041. XXFontStruct *_wf;        /* The font */
  1042. XXFontStruct *_wmf;        /* The menu font */
  1043. X#ifdef PIPEHACK
  1044. Xint _wpipe[2];            /* Pipe used by wungetevent from handler */
  1045. X#endif
  1046. X#ifdef AMOEBA
  1047. X#include <amoeba.h>
  1048. X#include <semaphore.h>
  1049. Xextern semaphore *_wsema;    /* From amtimer.c */
  1050. X#endif
  1051. Xchar *_wprogname = "stdwin";    /* Program name from argv[0] */
  1052. Xstatic char *_wdisplayname;    /* Display name */
  1053. X
  1054. X/* Interned atoms */
  1055. X
  1056. XAtom _wm_protocols;
  1057. XAtom _wm_delete_window;
  1058. XAtom _wm_take_focus;
  1059. X
  1060. X/* Globals used to communicate hints to wopen() */
  1061. X
  1062. Xchar *_whostname;
  1063. Xchar *_wm_command;
  1064. Xint _wm_command_len;
  1065. X
  1066. X/* Copy the arguments away to _wm_command, and get the host name */
  1067. X
  1068. Xstatic void
  1069. Xstoreargcargv(argc, argv)
  1070. X    int argc;
  1071. X    char **argv;
  1072. X{
  1073. X    int i;
  1074. X    char *bp;
  1075. X    char buf[256];
  1076. X    
  1077. X    /* Calculate length of buffer to allocate */
  1078. X    _wm_command_len= 0;
  1079. X    for (i= 0; i < argc; i++)
  1080. X        _wm_command_len += strlen(argv[i]) + 1;
  1081. X    if (_wm_command_len != 0) {
  1082. X        _wm_command= bp= malloc((unsigned)_wm_command_len);
  1083. X        for (i= 0; i < argc; i++) {
  1084. X            strcpy(bp, argv[i]);
  1085. X            bp += strlen(argv[i]) + 1;
  1086. X        }
  1087. X    }
  1088. X    
  1089. X    buf[0]= EOS;
  1090. X    gethostname(buf, sizeof buf);
  1091. X    buf[(sizeof buf)-1]= EOS;
  1092. X    _whostname= strdup(buf);
  1093. X}
  1094. X
  1095. X/* Function to get a default directly from a database */
  1096. X
  1097. Xstatic char *
  1098. Xgetoption(db, name, classname)
  1099. X    XrmDatabase db;
  1100. X    char *name;
  1101. X    char *classname;
  1102. X{
  1103. X    char namebuf[256], classnamebuf[256];
  1104. X    char *type;
  1105. X    XrmValue rmvalue;
  1106. X    
  1107. X    sprintf(namebuf, "%s.%s", _wprogname, name);
  1108. X    sprintf(classnamebuf, "Stdwin.%s", classname);
  1109. X    if (XrmGetResource(db, namebuf, classnamebuf, &type, &rmvalue))
  1110. X        return rmvalue.addr;
  1111. X    else
  1112. X        return NULL;
  1113. X}
  1114. X
  1115. X/* Command line options tables */
  1116. X
  1117. X/* NOTE: To prevent stdwin eating user options scanned with getopt(3),
  1118. X   single-letter options must never be acceptable as abbreviations.
  1119. X   When necessary, this is ensured by adding dummy options, e.g., "-g:"
  1120. X   because there is only one option starting with "-g" ("-geometry").
  1121. X   (The colon is used as second character because getopt() uses it as a
  1122. X   delimiter.)
  1123. X   Watch out: if you remove the last option starting with a certain
  1124. X   letter, also remove the dummy option!
  1125. X*/
  1126. X
  1127. X/* Table 1: command-line only options */
  1128. X
  1129. Xstatic XrmOptionDescRec options1[]= {
  1130. X  
  1131. X{"-debuglevel",        ".debugLevel",        XrmoptionSepArg, NULL},
  1132. X{"-display",        ".display",        XrmoptionSepArg, NULL},
  1133. X
  1134. X{"-n:",            NULL,            XrmoptionIsArg,  NULL},
  1135. X{"-name",        ".name",        XrmoptionSepArg, NULL},
  1136. X
  1137. X{"-s:",            NULL,            XrmoptionIsArg,  NULL},
  1138. X{"-synchronous",    ".synchronous",        XrmoptionNoArg,  "on"},
  1139. X
  1140. X};
  1141. X
  1142. X/* Table 2: options to be merged with resources */
  1143. X
  1144. Xstatic XrmOptionDescRec options2[]= {
  1145. X
  1146. X/* Command line options to override resources.
  1147. X   All the options named in "man X" are supported, except those to
  1148. X   do with borders (-bd, -bw) or national language choice (-xnl*). */
  1149. X
  1150. X{"-background",        ".background",        XrmoptionSepArg, NULL},
  1151. X{"-bg",            ".background",        XrmoptionSepArg, NULL},
  1152. X
  1153. X{"-font",        ".font",        XrmoptionSepArg, NULL},
  1154. X{"-fn",            ".font",        XrmoptionSepArg, NULL},
  1155. X{"-foreground",        ".foreground",        XrmoptionSepArg, NULL},
  1156. X{"-fg",            ".foreground",        XrmoptionSepArg, NULL},
  1157. X
  1158. X{"-g:",            NULL,            XrmoptionIsArg,  NULL},
  1159. X{"-geometry",        ".geometry",        XrmoptionSepArg, NULL},
  1160. X
  1161. X{"-iconic",        ".iconic",        XrmoptionNoArg,  "on"},
  1162. X{"-iconbitmap",        ".iconBitmap",        XrmoptionSepArg, NULL},
  1163. X{"-icongeometry",    ".iconGeometry",    XrmoptionSepArg, NULL},
  1164. X{"-iconmask",        ".iconMask",        XrmoptionSepArg, NULL},
  1165. X
  1166. X{"-menubackground",    ".menuBackground",    XrmoptionSepArg, NULL},
  1167. X{"-menufont",        ".menuFont",        XrmoptionSepArg, NULL},
  1168. X{"-menufn",        ".menuFont",        XrmoptionSepArg, NULL},
  1169. X{"-menuforeground",    ".menuForeground",    XrmoptionSepArg, NULL},
  1170. X
  1171. X{"-reversevideo",    ".reverse",        XrmoptionNoArg,  "on"},
  1172. X{"-rv",            ".reverse",        XrmoptionNoArg,  "on"},
  1173. X{"+rv",            ".reverse",        XrmoptionNoArg,  "off"},
  1174. X
  1175. X{"-s:",            NULL,            XrmoptionIsArg,  NULL},
  1176. X{"-selectionTimeout",    ".selectionTimeout",    XrmoptionSepArg, NULL},
  1177. X
  1178. X{"-t:",            NULL,            XrmoptionIsArg,  NULL},
  1179. X{"-title",        ".title",        XrmoptionSepArg, NULL},
  1180. X
  1181. X{"-x:",            NULL,            XrmoptionIsArg,  NULL},
  1182. X{"-xrm",        NULL,            XrmoptionResArg, NULL},
  1183. X
  1184. X/* Options that end option processing completely:
  1185. X   "-" means <stdin>, "--" is a getopt(3) convention
  1186. X   to force the end of the option list. */
  1187. X
  1188. X{"-",            NULL,            XrmoptionSkipLine, NULL},
  1189. X{"--",            NULL,            XrmoptionSkipLine, NULL},
  1190. X
  1191. X};
  1192. X
  1193. X#define NUM(options) (sizeof options / sizeof options[0])
  1194. X
  1195. X
  1196. X/* Initialization is split in two parts -- wargs(&argc, &argv) to process
  1197. X   the command line, winit() to open the connection.  The call
  1198. X   winitargs(&argc, &argv) calls wargs() and then winit().
  1199. X
  1200. X   Programs that call winit() without callin wargs() will always
  1201. X   appear to have the name "stdwin", and you can't pass X command
  1202. X   line arguments on their command line.  Defaults put in the server's
  1203. X   resource database for application name 'stdwin' will work, though.
  1204. X   You can also set the environment variable RESOURCE_NAME. */
  1205. X
  1206. X
  1207. Xstatic XrmDatabase db = NULL; /* Passed between wargs() and winit() */
  1208. Xstatic int wargs_called; /* Set when wargs is called */
  1209. X
  1210. X/* Part one of the initialization -- process command line arguments */
  1211. X
  1212. Xvoid
  1213. Xwargs(pargc, pargv)
  1214. X    int *pargc;
  1215. X    char ***pargv;
  1216. X{
  1217. X    char **argv= *pargv;
  1218. X    char *value;
  1219. X    
  1220. X    if (wargs_called)
  1221. X        _wfatal("wargs: called more than once");
  1222. X    wargs_called = 1;
  1223. X    
  1224. X    /* Get the program name (similar to basename(argv[0])) */
  1225. X    
  1226. X    if (*pargc > 0 && argv[0] != NULL && argv[0][0] != EOS) {
  1227. X        _wprogname= strrchr(argv[0], '/');
  1228. X        if (_wprogname != NULL && _wprogname[1] != EOS)
  1229. X            ++_wprogname;
  1230. X        else
  1231. X            _wprogname= argv[0];
  1232. X    }
  1233. X    
  1234. X    /* Save entire argument list for WM_COMMAND hint; plus hostname */
  1235. X    
  1236. X    storeargcargv(*pargc, argv);
  1237. X    
  1238. X    /* Get command-line-only X options */
  1239. X    
  1240. X    XrmParseCommand(&db, options1, NUM(options1),
  1241. X        _wprogname, pargc, *pargv);
  1242. X    
  1243. X    /* Get -debuglevel argument from temp database.
  1244. X       This is done first so calls to _wdebug will work. */
  1245. X    
  1246. X    if ((value= getoption(db, "debugLevel", "DebugLevel")) != NULL) {
  1247. X        _wtracelevel= _wdebuglevel= atoi(value);
  1248. X        setlinebuf(stderr);
  1249. X        _wwarning("wargs: -debuglevel %d", _wdebuglevel, value);
  1250. X    }
  1251. X    
  1252. X    /* Get -display argument from temp database */
  1253. X    
  1254. X    if ((_wdisplayname= getoption(db, "display", "Display")) != NULL)
  1255. X        _wdebug(1, "wargs: -display %s", _wdisplayname);
  1256. X    
  1257. X    /* Get -name argument from temp database.
  1258. X       This will override the command name used by _wgetdefault.
  1259. X       You can use this to pretend the command name is different,
  1260. X       so it gets its options from a different part of the defaults
  1261. X       database.  (Try -name xmh. :-)
  1262. X       If -name is not set, getenv("RESOURCE_NAME") will override
  1263. X       _wprogname (if non-empty). */
  1264. X    
  1265. X    if ((value= getoption(db, "name", "Name")) != NULL) {
  1266. X        _wdebug(1, "wargs: -name %s", value);
  1267. X        _wprogname= strdup(value);
  1268. X    }
  1269. X    else if ((value = getenv("RESOURCE_NAME")) != NULL && *value != '\0') {
  1270. X        _wdebug(1, "wargs: RESOURCE_NAME=%s", value);
  1271. X        _wprogname = strdup(value);
  1272. X    }
  1273. X    
  1274. X    /* Get the remaining command line options.
  1275. X       Option parsing is done in two phases so that if the user
  1276. X       specifies -name and -geometry, the geometry is stored under
  1277. X       the new name (else it won't be found by _wgetdefault later). */
  1278. X    
  1279. X    XrmParseCommand(&db, options2, NUM(options2),
  1280. X        _wprogname, pargc, *pargv);
  1281. X}
  1282. X
  1283. X
  1284. X/* Part two of the initialization -- open the display */
  1285. X
  1286. Xvoid
  1287. Xwinit()
  1288. X{
  1289. X    char *value;
  1290. X
  1291. X    /* Call wargs() with dummy arguments if not already called */
  1292. X
  1293. X    if (!wargs_called) {
  1294. X        static char* def_args[]= {"stdwin", (char*)NULL};
  1295. X        int argc= 1;
  1296. X        char **argv= def_args;
  1297. X        wargs(&argc, &argv);
  1298. X    }
  1299. X    
  1300. X    /* Open the display, die if we can't */
  1301. X    
  1302. X    _wd= XOpenDisplay(_wdisplayname);
  1303. X    if (_wd == NULL) {
  1304. X        _wfatal("winit: can't open display (%s)",
  1305. X            _wdisplayname ? _wdisplayname :
  1306. X            getenv("DISPLAY") ? getenv("DISPLAY") : "<none>");
  1307. X    }
  1308. X    
  1309. X#ifdef AMOEBA
  1310. X    /* Set the semaphore.  This must be done before doing anything
  1311. X       else with the connection. */
  1312. X    if (_wsema != NULL)
  1313. X        XamSetSema(_wd, _wsema);
  1314. X#endif
  1315. X    
  1316. X    /* Turn on synchronous mode if required.
  1317. X       This is not automatic when debuglevel is set,
  1318. X       since some bugs disappear in synchronous mode! */
  1319. X    
  1320. X    if (getoption(db, "synchronous", "Synchronous") != NULL)
  1321. X        XSynchronize(_wd, True);
  1322. X    
  1323. X    /* Call XGetDefault() once.  We don't use it to get our
  1324. X       defaults, since it doesn't let the caller specify the class
  1325. X       name for the resource requested, but the first call to it
  1326. X       also initializes the resources database from various sources
  1327. X       following conventions defined by the X toolkit, and that code
  1328. X       is too convoluted (and X11-version specific?) to bother to
  1329. X       repeat it here. */
  1330. X    
  1331. X    (void) XGetDefault(_wd, _wprogname, "unused");
  1332. X    
  1333. X    /* From now on, use _wgetdefault() exclusively to get defaults */
  1334. X    
  1335. X    /* Get the debug level again, this time from the user's
  1336. X       defaults database.  This value overrides only if larger. */
  1337. X    
  1338. X    value= _wgetdefault("debugLevel", "DebugLevel");
  1339. X    if (value != 0) {
  1340. X        int k= atoi(value);
  1341. X        if (k > _wdebuglevel) {
  1342. X            _wtracelevel= _wdebuglevel= k;
  1343. X            _wdebug(1, "winit: new debuglevel %d (%s)",
  1344. X                _wdebuglevel, value);
  1345. X            XSynchronize(_wd, True);
  1346. X        }
  1347. X    }
  1348. X    
  1349. X    /* Merge the command line options with the defaults database.
  1350. X       This must be done after the call to XGetDefault (above),
  1351. X       otherwise XGetDefault doesn't care to load the database.
  1352. X       I assume that the command line options get higher priority
  1353. X       than the user defaults in this way. */
  1354. X    
  1355. X    XrmMergeDatabases(db, &_wd->db);
  1356. X    db = NULL;
  1357. X    
  1358. X    /* Get the default screen (the only one we use) */
  1359. X    
  1360. X    _ws= DefaultScreenOfDisplay(_wd);
  1361. X    
  1362. X    _wdebug(1, "server does%s save-unders",
  1363. X        DoesSaveUnders(_ws) ? "" : "n't do");
  1364. X    
  1365. X    /* Intern some atoms (unconditionally) */
  1366. X    
  1367. X    _wm_protocols = XInternAtom(_wd, "WM_PROTOCOLS", False);
  1368. X    _wm_delete_window = XInternAtom(_wd, "WM_DELETE_WINDOW", False);
  1369. X    _wm_take_focus = XInternAtom(_wd, "WM_TAKE_FOCUS", False);
  1370. X    
  1371. X    /* Initialize font list */
  1372. X    
  1373. X    _winitfonts();
  1374. X    
  1375. X#ifdef PIPEHACK
  1376. X    /* Create the pipe used to communicate wungetevent calls
  1377. X       from a signal handler to wgetevent */
  1378. X    
  1379. X    if (pipe(_wpipe) != 0) {
  1380. X        _wwarning("winit: can't create pipe");
  1381. X        _wpipe[0]= _wpipe[1]= -1;
  1382. X    }
  1383. X#endif
  1384. X}
  1385. X
  1386. X
  1387. X/* Call both parts of the initialization together */
  1388. X
  1389. Xvoid
  1390. Xwinitargs(pargc, pargv)
  1391. X    int *pargc;
  1392. X    char ***pargv;
  1393. X{
  1394. X    wargs(pargc, pargv);
  1395. X    winit();
  1396. X}
  1397. X
  1398. X
  1399. X/* Return the name of the display, if known.  (X11 stdwin only.) */
  1400. X
  1401. Xchar *
  1402. Xwdisplayname()
  1403. X{
  1404. X    return _wdisplayname ? _wdisplayname : getenv("DISPLAY");
  1405. X}
  1406. X
  1407. X
  1408. X/* Clean up */
  1409. X
  1410. Xvoid
  1411. Xwdone()
  1412. X{
  1413. X    /* This may be called when we are not initialized */
  1414. X    if (_wd) {
  1415. X        _wkillwindows();
  1416. X        _wkillmenus();
  1417. X        XFlush(_wd); /* Show possibly queued visual effects */
  1418. X        XCloseDisplay(_wd);
  1419. X        _wd = NULL;
  1420. X    }
  1421. X}
  1422. X
  1423. X/* Flush server queue */
  1424. X
  1425. Xvoid
  1426. Xwflush()
  1427. X{
  1428. X    XFlush(_wd);
  1429. X}
  1430. X
  1431. X
  1432. X/* Get screen size */
  1433. X
  1434. Xvoid
  1435. Xwgetscrsize(pwidth, pheight)
  1436. X    int *pwidth, *pheight;
  1437. X{
  1438. X    *pwidth= WidthOfScreen(_ws);
  1439. X    *pheight= HeightOfScreen(_ws);
  1440. X}
  1441. X
  1442. X
  1443. X/* Get screen size in mm */
  1444. X
  1445. Xvoid
  1446. Xwgetscrmm(pwidth, pheight)
  1447. X    int *pwidth, *pheight;
  1448. X{
  1449. X    *pwidth= WidthMMOfScreen(_ws);
  1450. X    *pheight= HeightMMOfScreen(_ws);
  1451. X}
  1452. X
  1453. X/* Subroutine to invert a rectangle.
  1454. X   On a colour display, we invert all planes that have a different
  1455. X   value in the foreground and background pixels, thus swapping
  1456. X   fg anbd bg colors.
  1457. X   Since we can't get the fg and bg pixels from a GC without cheating
  1458. X   (i.e., risking future incompatibility), we depend on the fact
  1459. X   that the plane mask is *always* set to the XOR of the fg and bg colors.
  1460. X   If the bg color for the window is the same as the bg for the GC,
  1461. X   this means all draw operations need only be concerned with those planes.
  1462. X*/
  1463. X
  1464. X_winvert(d, gc, x, y, width, height)
  1465. X    Drawable d;
  1466. X    GC gc;
  1467. X    int x, y, width, height;
  1468. X{
  1469. X    XSetFunction(_wd, gc, GXinvert);
  1470. X    XFillRectangle(_wd, d, gc, x, y, width, height);
  1471. X    XSetFunction(_wd, gc, GXcopy);
  1472. X}
  1473. X
  1474. X/* Get a default (replaces XGetDefault calls) */
  1475. X
  1476. X#include <ctype.h>
  1477. X
  1478. Xchar *
  1479. X_wgetdefault(name, classname)
  1480. X    char *name;
  1481. X    char *classname;
  1482. X{
  1483. X    char namebuf[256], classnamebuf[256];
  1484. X    register char *p;
  1485. X    
  1486. X    p = getoption(_wd->db, name, classname);
  1487. X    if (p != NULL)
  1488. X        return p;
  1489. X    
  1490. X    /* XXX Compatibility hack.  Previous versions of STDWIN used
  1491. X       a different resource format, where the name would be
  1492. X       <progname>.stdwin.<resname> and the classname was defaulted
  1493. X       by XGetDefault to Program.Name (or some such).
  1494. X       The resource names were also all lowercase. */
  1495. X    sprintf(namebuf, "stdwin.%s", name);
  1496. X    sprintf(classnamebuf, "Stdwin.%s", classname);
  1497. X    for (p = namebuf; *p != '\0'; p++) {
  1498. X        if (isupper(*p))
  1499. X            *p = tolower(*p);
  1500. X    }
  1501. X    _wdebug(1, "_wgetdefault(%s, %s): no luck, trying %s, %s",
  1502. X        name, classname, namebuf, classnamebuf);
  1503. X    return getoption(_wd->db, namebuf, classnamebuf);
  1504. X}
  1505. X
  1506. X/* Get a Boolean default.  May be 'on' or 'off', 'true' or 'false',
  1507. X   '1' or '0'.  If not present, return the default value. */
  1508. X
  1509. Xint
  1510. X_wgetbool(name, classname, def)
  1511. X    char *name;
  1512. X    char *classname;
  1513. X    int def;
  1514. X{
  1515. X    register char *value;
  1516. X    static struct flags {
  1517. X        char *name;
  1518. X        int value;
  1519. X    };
  1520. X    static struct flags flags[] = {
  1521. X        {"on",        1},
  1522. X        {"true",    1},
  1523. X        {"yes",        1},
  1524. X        {"1",        1},
  1525. X        
  1526. X        {"off",        0},
  1527. X        {"false",    0},
  1528. X        {"no",        0},
  1529. X        {"0",        0},
  1530. X        
  1531. X        {NULL,        0}    /* Sentinel */
  1532. X    };
  1533. X    struct flags *fp, *hit;
  1534. X    
  1535. X    value = _wgetdefault(name, classname);
  1536. X    if (value == NULL)
  1537. X        return def;
  1538. X    hit = NULL;
  1539. X    for (fp = flags; fp->name != NULL; fp++) {
  1540. X        if (matchname(fp->name, value)) {
  1541. X            if (hit != NULL)
  1542. X                _wwarning(
  1543. X                    "ambiguous resource value for %s: %s",
  1544. X                    name, value);
  1545. X            hit = fp;
  1546. X        }
  1547. X    }
  1548. X    if (hit != NULL)
  1549. X        def = hit->value;
  1550. X    else
  1551. X        _wwarning("unknown resource value for %s: %s", name, value);
  1552. X    return def;
  1553. X}
  1554. X
  1555. Xstatic int
  1556. Xmatchname(fullname, shortname)
  1557. X    char *fullname;
  1558. X    char *shortname;
  1559. X{
  1560. X    register int c;
  1561. X    while ((c = *shortname++) != '\0') {
  1562. X        if (isupper(c))
  1563. X            c = tolower(c);
  1564. X        if (c != *fullname++)
  1565. X            return 0;
  1566. X    }
  1567. X    return 1;
  1568. X}
  1569. END_OF_FILE
  1570. if test 13917 -ne `wc -c <'Ports/x11/general.c'`; then
  1571.     echo shar: \"'Ports/x11/general.c'\" unpacked with wrong size!
  1572. fi
  1573. # end of 'Ports/x11/general.c'
  1574. fi
  1575. if test -f 'Ports/x11/llevent.c' -a "${1}" != "-c" ; then 
  1576.   echo shar: Will not clobber existing file \"'Ports/x11/llevent.c'\"
  1577. else
  1578. echo shar: Extracting \"'Ports/x11/llevent.c'\" \(8971 characters\)
  1579. sed "s/^X//" >'Ports/x11/llevent.c' <<'END_OF_FILE'
  1580. X/* X11 STDWIN -- Low-level event handling */
  1581. X
  1582. X#include "x11.h"
  1583. X#include "llevent.h"
  1584. X#include <X11/keysym.h>
  1585. X
  1586. X/* Double-click detection parameters */
  1587. X
  1588. X#define DCLICKTIME    500
  1589. X#define DCLICKDIST    5
  1590. X
  1591. X/* Events are handled in two phases.
  1592. X   There is low-level event handling which can be called at any time
  1593. X   and will only set various flags (global and in windows) indicating
  1594. X   changed circumstances.  This kind of event handling goes on even
  1595. X   while we are locked in a dialog box.
  1596. X   There is high-level event handling which passes the results of the
  1597. X   low-level handling to the application in request to a call to
  1598. X   'wgetevent'.
  1599. X   This file contains the low-level event handling. */
  1600. X
  1601. X
  1602. X/* Low-level event handler.
  1603. X   Data items set for use by higher-level event handler include:
  1604. X   
  1605. X   - the 'new active window' pointer
  1606. X   - the 'dirty' flags for all windows and subwindows
  1607. X   - the 'size changed' flags for all top-level windows
  1608. X   
  1609. X   These can be accumulated; the net effect of all such events is
  1610. X   correctly remembered.  The following data items are also set but need
  1611. X   to be checked after each call, since they are not queued:
  1612. X   
  1613. X   - the mouse button state
  1614. X   - the 'last-key-pressed' variable
  1615. X   
  1616. X   Mouse moves may be ignored, however.
  1617. X   The state change flags must be be reset by the higher-level event
  1618. X   handler after the changes have been noted. */
  1619. X
  1620. XWINDOW *_w_new_active;        /* New active window */
  1621. Xstruct button_state _w_bs;    /* Mouse button state */
  1622. XKeySym _w_keysym;        /* Keysym of last non-modifier key pressed */
  1623. Xint _w_state;            /* Modifiers in effect at key press */
  1624. X
  1625. Xbool _w_moved;            /* Set if button moved */
  1626. Xbool _w_bs_changed;        /* Set if button up/down state changed */
  1627. Xbool _w_dirty;            /* Set if any window needs a redraw */
  1628. Xbool _w_resized;        /* Set if any window resized */
  1629. Xbool _w_focused;        /* Set if between FocusIn and FocusOut */
  1630. XTime _w_lasttime = CurrentTime;    /* Last timestamp received in an event */
  1631. XWINDOW *_w_close_this;        /* Window to close (WM_DELETE_WINDOW) */
  1632. X
  1633. X_w_ll_event(e)
  1634. X    XEvent *e;
  1635. X{
  1636. X    WINDOW *win;
  1637. X    
  1638. X    _wdebug(6, "_w_ll_event: event type %ld", e->type);
  1639. X    
  1640. X    win = _whichwin(e->xkey.window);
  1641. X    if (win == NULL) {
  1642. X        _wdebug(6, "_w_ll_event: event not for any window -- ignore");
  1643. X        return;
  1644. X    }
  1645. X    
  1646. X    switch (e->type) {
  1647. X    
  1648. X    /* Keyboard */
  1649. X    
  1650. X    case KeyPress:
  1651. X        _w_lasttime = e->xkey.time;
  1652. X        activate(win);
  1653. X        ll_key(&e->xkey, win);
  1654. X        break;
  1655. X    
  1656. X    case MappingNotify:
  1657. X        XRefreshKeyboardMapping(&e->xmapping);
  1658. X        break;
  1659. X    
  1660. X    /* Buttons */
  1661. X    
  1662. X    case MotionNotify:
  1663. X#ifndef DONT_COMPRESS_MOTION /* XXX should be a resource option instead */
  1664. X        /* Compress motion events */
  1665. X        while (XPending(_wd) > 0) {
  1666. X            XEvent e2;
  1667. X            XPeekEvent(_wd, &e2);
  1668. X            if (e2.type == MotionNotify &&
  1669. X                e2.xmotion.window == e->xmotion.window &&
  1670. X                e2.xmotion.subwindow == e->xmotion.subwindow) {
  1671. X                /* replace current event with next one */
  1672. X                XNextEvent(_wd, e);
  1673. X            }
  1674. X            else
  1675. X                break;
  1676. X        }
  1677. X#endif
  1678. X        /* Fall through */
  1679. X    case ButtonPress:
  1680. X    case ButtonRelease:
  1681. X        _w_lasttime = e->xbutton.time;
  1682. X        ll_button(&e->xbutton, win);
  1683. X        break;
  1684. X    
  1685. X    /* Exposures */
  1686. X    
  1687. X    case GraphicsExpose:
  1688. X        _wdebug(3, "GraphicsExpose event:");
  1689. X    case Expose:
  1690. X        ll_expose(&e->xexpose, win);
  1691. X        break;
  1692. X    
  1693. X    /* Structure changes */
  1694. X    
  1695. X    case ConfigureNotify:
  1696. X        ll_configure(&e->xconfigure, win);
  1697. X        break;
  1698. X    
  1699. X    /* Input focus changes */
  1700. X    
  1701. X    case FocusIn:
  1702. X        _w_focused= TRUE;
  1703. X        activate(win);
  1704. X        break;
  1705. X    
  1706. X    case FocusOut:
  1707. X        _w_focused= FALSE;
  1708. X        deactivate(win);
  1709. X        break;
  1710. X    
  1711. X    case EnterNotify:
  1712. X        _w_lasttime = e->xcrossing.time;
  1713. X        if (!_w_focused && e->xcrossing.focus)
  1714. X            activate(win);
  1715. X        break;
  1716. X    
  1717. X    case LeaveNotify:
  1718. X        _w_lasttime = e->xcrossing.time;
  1719. X        if (!_w_focused && e->xcrossing.detail != NotifyInferior &&
  1720. X                e->xcrossing.focus)
  1721. X            deactivate(win);
  1722. X        break;
  1723. X    
  1724. X    /* ICCCM */
  1725. X    
  1726. X    case ClientMessage:
  1727. X        _wdebug(2,
  1728. X            "ClientMessage, type=%ld, send_event=%ld, format=%ld",
  1729. X            e->xclient.message_type,
  1730. X            e->xclient.send_event,
  1731. X            e->xclient.format);
  1732. X        if (e->xclient.message_type == _wm_protocols) {
  1733. X            _wdebug(2, "It's a WM_PROTOCOLS ClientMessage (%ld)",
  1734. X                e->xclient.data.l[0]);
  1735. X            _w_lasttime = e->xclient.data.l[1];
  1736. X        }
  1737. X        else {
  1738. X            _wdebug(1, "Unexpected ClientMessage ignored (%ld)",
  1739. X                e->xclient.message_type);
  1740. X            break;
  1741. X        }
  1742. X        if (e->xclient.data.l[0] == _wm_delete_window) {
  1743. X            _wdebug(1, "WM_DELETE_WINDOW");
  1744. X            _w_close_this = win;
  1745. X        }
  1746. X        else {
  1747. X            _wdebug(1,
  1748. X                "Unexpected WM_PROTOCOLS ClientMessage (%ld)",
  1749. X                e->xclient.data.l[0]);
  1750. X        }
  1751. X        break;
  1752. X    
  1753. X    case SelectionRequest:
  1754. X        _w_selectionreply(
  1755. X            e->xselectionrequest.owner,
  1756. X            e->xselectionrequest.requestor,
  1757. X            e->xselectionrequest.selection,
  1758. X            e->xselectionrequest.target,
  1759. X            e->xselectionrequest.property,
  1760. X            e->xselectionrequest.time);
  1761. X        break;
  1762. X    
  1763. X    case SelectionClear:
  1764. X        _w_selectionclear(e->xselectionclear.selection);
  1765. X        break;
  1766. X    
  1767. X    case MapNotify:
  1768. X        /* Ignore this */
  1769. X        break;
  1770. X    
  1771. X    default:
  1772. X        _wdebug(1, "unexpected event type %d", e->type);
  1773. X    
  1774. X    }
  1775. X}
  1776. X
  1777. Xstatic
  1778. Xactivate(win)
  1779. X    WINDOW *win;
  1780. X{
  1781. X    if (_w_new_active != win) {
  1782. X        if (_w_new_active != NULL)
  1783. X            deactivate(_w_new_active);
  1784. X        _w_new_active= win;
  1785. X        if (win != NULL)
  1786. X            XSetWindowBorder(_wd, win->wo.wid, win->fgo);
  1787. X    }
  1788. X}
  1789. X
  1790. Xstatic
  1791. Xdeactivate(win)
  1792. X    WINDOW *win;
  1793. X{
  1794. X    if (win == _w_new_active) {
  1795. X        _w_new_active= NULL;
  1796. X        if (win != NULL)
  1797. X            _w_setgrayborder(win);
  1798. X    }
  1799. X}
  1800. X
  1801. Xstatic
  1802. Xll_key(e, win)
  1803. X    XKeyEvent *e;
  1804. X    WINDOW *win;
  1805. X{
  1806. X    char sbuf[1];
  1807. X    
  1808. X    _wdebug(6, "keycode %d, state 0x%x", e->keycode, e->state);
  1809. X    if (XLookupString(e, sbuf, 1, &_w_keysym, (XComposeStatus*)NULL) > 0)
  1810. X        _w_keysym= sbuf[0];
  1811. X    else if (IsModifierKey(_w_keysym))
  1812. X        _w_keysym= 0;
  1813. X    _w_state= e->state;
  1814. X}
  1815. X
  1816. X/* Update button status, given a Button or Motion event.
  1817. X   THIS ASSUMES BUTTON AND MOTION EVENTS HAVE THE SAME LAY-OUT! */
  1818. X
  1819. Xstatic
  1820. Xll_button(e, win)
  1821. X    XButtonEvent *e;
  1822. X    WINDOW *win;
  1823. X{
  1824. X    Window w= e->window;
  1825. X    
  1826. X    /* This code is ugly.  I know. */
  1827. X    
  1828. X    if (!_w_bs.down) { /* New sequence */
  1829. X        if (e->type != ButtonPress) {
  1830. X            /* Button moved/release event while we've never
  1831. X               received a corresponding press event.
  1832. X               I suspect this is a server bug;
  1833. X               normally I never reach this code, but sometimes
  1834. X               it happens continually.  Why?... */
  1835. X            _wdebug(5,
  1836. X                "ll_button: spurious button move/release %d",
  1837. X                e->type);
  1838. X            return;
  1839. X        }
  1840. X        else {
  1841. X            bool isdclick= FALSE;
  1842. X            _w_bs.down= TRUE;
  1843. X            _w_bs_changed= TRUE;
  1844. X            if (_w_bs.button == e->button &&
  1845. X                    _w_bs.w == e->window) {
  1846. X                /* Multiple-click detection; must be done
  1847. X                   before setting new values */
  1848. X                if (e->time <= _w_bs.time + DCLICKTIME) {
  1849. X                    int dx= e->x - _w_bs.x;
  1850. X                    int dy= e->y - _w_bs.y;
  1851. X                    isdclick= (dx*dx + dy*dy <=
  1852. X                        DCLICKDIST*DCLICKDIST);
  1853. X                }
  1854. X            }
  1855. X            if (!isdclick)
  1856. X                _w_bs.clicks= 0;
  1857. X            ++_w_bs.clicks;
  1858. X            _w_bs.mask= e->state / Button1Mask; /* XXX */
  1859. X            _w_bs.button= e->button;
  1860. X            _w_bs.time= e->time;
  1861. X            _w_bs.win= win;
  1862. X            _w_bs.w= w;
  1863. X            for (_w_bs.isub= NSUBS; --_w_bs.isub >= 0; ) {
  1864. X                if (w == win->subw[_w_bs.isub].wid)
  1865. X                    break;
  1866. X            }
  1867. X            if (_w_bs.isub < 0) {
  1868. X                _wdebug(0, "ll_button: can't find subwin");
  1869. X                _w_bs.isub= 0;
  1870. X                return;
  1871. X            }
  1872. X            _w_bs.x= _w_bs.xdown= e->x;
  1873. X            _w_bs.y= _w_bs.ydown= e->y;
  1874. X        }
  1875. X    }
  1876. X    else { /* Continue existing sequence */
  1877. X        if (win == _w_bs.win && w != _w_bs.w) {
  1878. X            /* Maybe changed between mbar and mwin? */
  1879. X            if (_w_bs.isub == MBAR && w == win->mwin.wid) {
  1880. X                /* Change it -- because of XGrabPointer */
  1881. X                _wdebug(3, "MBAR grabbed button");
  1882. X                _w_bs.isub = MWIN;
  1883. X                _w_bs.w = w;
  1884. X            }
  1885. X        }
  1886. X        if (win != _w_bs.win || w != _w_bs.w) {
  1887. X            /* XXX This still happens -- why? */
  1888. X            _wdebug(0, "ll_button: inconsistent _w_bs");
  1889. X            _w_bs.down= FALSE;
  1890. X            _w_bs.mask= 0;
  1891. X            _w_bs_changed= TRUE;
  1892. X        }
  1893. X        else {
  1894. X            _w_bs.mask= e->state / Button1Mask; /* XXX */
  1895. X            _w_bs.x= e->x;
  1896. X            _w_bs.y= e->y;
  1897. X            _w_bs.time= e->time;
  1898. X            if (e->type == ButtonRelease &&
  1899. X                e->button == _w_bs.button) {
  1900. X                _w_bs.down= FALSE;
  1901. X                _w_bs_changed= TRUE;
  1902. X            }
  1903. X            else
  1904. X                _w_moved= TRUE;
  1905. X        }
  1906. X    }
  1907. X    _wdebug(5, "ll_button: xy=(%d, %d), down=%d, clicks=%d",
  1908. X        _w_bs.x, _w_bs.y, _w_bs.down, _w_bs.clicks);
  1909. X}
  1910. X
  1911. Xstatic
  1912. Xll_expose(e, win)
  1913. X    XExposeEvent *e;
  1914. X    WINDOW *win;
  1915. X{
  1916. X    Window w= e->window;
  1917. X    
  1918. X    _wdebug(3, "ll_expose called, count=%d, x=%d,y=%d,w=%d,h=%d",
  1919. X        e->count, e->x, e->y, e->width, e->height);
  1920. X    if (w == win->wa.wid)
  1921. X        wchange(win, e->x, e->y, e->x + e->width, e->y + e->height);
  1922. X    else if (w == win->mbar.wid)
  1923. X        win->mbar.dirty= TRUE;
  1924. X    else if (w == win->hbar.wid)
  1925. X        win->hbar.dirty= TRUE;
  1926. X    else if (w == win->vbar.wid)
  1927. X        win->vbar.dirty= TRUE;
  1928. X    else {
  1929. X        _wdebug(3, "ll_expose: uninteresting event");
  1930. X        return;
  1931. X    }
  1932. X    if (e->count == 0)
  1933. X        _w_dirty= TRUE;
  1934. X}
  1935. X
  1936. Xstatic
  1937. Xll_configure(e, win)
  1938. X    XConfigureEvent *e;
  1939. X    WINDOW *win;
  1940. X{
  1941. X    if (e->window != win->wo.wid) {
  1942. X        _wdebug(0, "ll_configure: not for wo.wid");
  1943. X        return;
  1944. X    }
  1945. X    win->wo.x= e->x + e->border_width;
  1946. X    win->wo.y= e->y + e->border_width;
  1947. X    win->wo.border= e->border_width;
  1948. X    if (win->wo.width != e->width || win->wo.height != e->height) {
  1949. X        /* Size changed */
  1950. X        win->wo.width= e->width;
  1951. X        win->wo.height= e->height;
  1952. X        _wmovesubwins(win);
  1953. X        win->resized= _w_resized= TRUE;
  1954. X    }
  1955. X}
  1956. END_OF_FILE
  1957. if test 8971 -ne `wc -c <'Ports/x11/llevent.c'`; then
  1958.     echo shar: \"'Ports/x11/llevent.c'\" unpacked with wrong size!
  1959. fi
  1960. # end of 'Ports/x11/llevent.c'
  1961. fi
  1962. echo shar: End of archive 7 \(of 19\).
  1963. cp /dev/null ark7isdone
  1964. MISSING=""
  1965. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1966.     if test ! -f ark${I}isdone ; then
  1967.     MISSING="${MISSING} ${I}"
  1968.     fi
  1969. done
  1970. if test "${MISSING}" = "" ; then
  1971.     echo You have unpacked all 19 archives.
  1972.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1973. else
  1974.     echo You still need to unpack the following archives:
  1975.     echo "        " ${MISSING}
  1976. fi
  1977. ##  End of shell archive.
  1978. exit 0
  1979.