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

  1. From: guido@cwi.nl (Guido van Rossum)
  2. Newsgroups: alt.sources
  3. Subject: STDWIN 0.9.5, Part 08/19
  4. Message-ID: <3072@charon.cwi.nl>
  5. Date: 4 Mar 91 11:57:58 GMT
  6.  
  7. Archive-name: stdwin/part08
  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 8 (of 19)."
  16. # Contents:  Appls/dpv/dpvfonts.c Doc/seldoc.ms
  17. #   Packs/textedit/textlow.c Ports/mac/event.c Ports/mac/menu.h
  18. # Wrapped by guido@voorn.cwi.nl on Mon Mar  4 12:37:27 1991
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'Appls/dpv/dpvfonts.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'Appls/dpv/dpvfonts.c'\"
  22. else
  23. echo shar: Extracting \"'Appls/dpv/dpvfonts.c'\" \(12151 characters\)
  24. sed "s/^X//" >'Appls/dpv/dpvfonts.c' <<'END_OF_FILE'
  25. X/* dpv -- ditroff previewer.  Font translation. */
  26. X
  27. X#include "dpv.h"
  28. X#include "dpvmachine.h"
  29. X#include "dpvoutput.h"
  30. X
  31. X/* Font translation table, to map ditroff font names to font names
  32. X   STDWIN (really the underlying window system) understands.
  33. X   This information should really be read from a configuration file.
  34. X   For now, we know to map some ditroff names for Harris and PostScript
  35. X   fonts to more or less equivalent X11 and Mac fonts.
  36. X   (The X fonts used are to be found in the Andrew distribution).
  37. X   Because the current font scheme in STDWIN for X doesn't know about
  38. X   wsetsize and wsetbold c.s., the translation process is different
  39. X   for X than for the Macintosh. */
  40. X
  41. X#define NSIZES 10
  42. X
  43. X#define R    0
  44. X#define B    1
  45. X#define I    2
  46. X#define BI    3
  47. X
  48. Xstatic struct _translate {
  49. X    char *harname;
  50. X    char *xname;
  51. X    int style;
  52. X    int sizes[NSIZES+1];
  53. X} default_translate[]= {
  54. X#ifdef macintosh
  55. X    {"R",    "Times",    R},
  56. X    {"I",    "Times",    I},
  57. X    {"B",    "Times",    B},
  58. X    {"BI",    "Times",    BI},
  59. X    
  60. X    {"H",    "Helvetica",    R},
  61. X    {"HO",    "Helvetica",    I},
  62. X    {"HB",    "Helvetica",    B},
  63. X    {"HD",    "Helvetica",    BI},
  64. X    
  65. X    {"C",    "Courier",    R},
  66. X    {"CO",    "Courier",    I},
  67. X    {"CB",    "Courier",    B},
  68. X    {"CD",    "Courier",    BI},
  69. X    
  70. X    {"lp",    "Courier",    R},
  71. X    
  72. X    {"Vl",    "Helvetica",    R},
  73. X    {"vl",    "Helvetica",    R},
  74. X    {"V",    "Helvetica",    R},
  75. X    {"v",    "Helvetica",    R},
  76. X    
  77. X    /* Font used by funny character translation */
  78. X    
  79. X    {"Symbol", "Symbol",    R},
  80. X#else
  81. X#ifdef X11R2
  82. X    /* X11 Release 2, using fonts from Andrew */
  83. X    
  84. X    /* PostScript font names */
  85. X    
  86. X    {"R",    "times%d",    R, 8, 10, 12, 16, 22, 0},
  87. X    {"I",    "times%di",    R, 8, 10, 12, 16, 22, 0},
  88. X    {"B",    "times%db",    R, 8, 10, 12, 16, 22, 0},
  89. X    {"BI",    "times%dbi",    R, 8, 10, 12, 16, 22, 0},
  90. X    
  91. X    {"H",    "helvetica%d",    R, 8, 10, 12, 16, 22, 0},
  92. X    {"HO",    "helvetica%di",    R, 8, 10, 12, 16, 22, 0},
  93. X    {"HB",    "helvetica%db",    R, 8, 10, 12, 16, 22, 0},
  94. X    {"HD",    "helvetica%dbi",R, 8, 10, 12, 16, 22, 0},
  95. X    
  96. X    {"C",    "courier%df",    R, 8, 10, 12, 16, 22, 0},    
  97. X    {"CO",    "courier%dif",    R, 8, 10, 12, 16, 22, 0},
  98. X    {"CB",    "courier%dbf",    R, 8, 10, 12, 16, 22, 0},
  99. X    {"CD",    "courier%dbif", R, 8, 10, 12, 16, 22, 0},
  100. X    
  101. X    /* CWI Harris font names (also R, I, B, BI) */
  102. X    
  103. X    /* Vega light, Vega, Vega medium (Helvetica look-alike) */
  104. X    {"Vl",    "helvetica%d",    R, 8, 10, 12, 16, 22, 0},
  105. X    {"vl",    "helvetica%di",    R, 8, 10, 12, 16, 22, 0},
  106. X    {"V",    "helvetica%d",    R, 8, 10, 12, 16, 22, 0},
  107. X    {"v",    "helvetica%di",    R, 8, 10, 12, 16, 22, 0},
  108. X    {"Vm",    "helvetica%db",    R, 8, 10, 12, 16, 22, 0,},
  109. X    {"vm",    "helvetica%dbi",R, 8, 10, 12, 16, 22, 0,},
  110. X    
  111. X    /* Baskerville (see also small caps) */
  112. X    {"br",    "times%d",    R, 8, 10, 12, 16, 22, 0,},
  113. X    {"bi",    "times%di",    R, 8, 10, 12, 16, 22, 0,},
  114. X    {"bb",    "times%db",    R, 8, 10, 12, 16, 22, 0,},
  115. X    {"bI",    "times%dbi",    R, 8, 10, 12, 16, 22, 0,},
  116. X    
  117. X    /* Century Schoolbook */
  118. X    {"cr",    "times%d",    R, 8, 10, 12, 16, 22, 0,},
  119. X    {"ci",    "times%di",    R, 8, 10, 12, 16, 22, 0,},
  120. X    {"cb",    "times%db",    R, 8, 10, 12, 16, 22, 0,},
  121. X    {"cI",    "times%dbi",    R, 8, 10, 12, 16, 22, 0,},
  122. X    
  123. X    /* Laurel */
  124. X    {"lr",    "times%d",    R, 8, 10, 12, 16, 22, 0,},
  125. X    {"li",    "times%di",    R, 8, 10, 12, 16, 22, 0,},
  126. X    {"lb",    "times%db",    R, 8, 10, 12, 16, 22, 0,},
  127. X    {"lI",    "times%dbi",    R, 8, 10, 12, 16, 22, 0,},
  128. X    
  129. X    /* Funny fonts mapped to Helvetica, at least they differ from Times */
  130. X    {"G3",    "helvetica%d",    R, 8, 10, 12, 16, 22, 0,}, /* German no 3 */
  131. X    {"fs",    "helvetica%d",    R, 8, 10, 12, 16, 22, 0,}, /* French Script */
  132. X    {"RS",    "helvetica%di",    R, 8, 10, 12, 16, 22, 0,}, /* Rose Script */
  133. X    {"SO",    "helvetica%db",    R, 8, 10, 12, 16, 22, 0,}, /* Scitype Open */
  134. X    
  135. X    /* OCR-B (line printer font) */
  136. X    {"lp",    "courier%dbf",    R, 8, 10, 12, 0},
  137. X    
  138. X    /* Small caps fonts mapped to normal fonts */
  139. X    {"Rs",    "times%d",    R, 8, 10, 12, 16, 22, 0,}, /* Times */
  140. X    {"Bs",    "times%db",    R, 8, 10, 12, 16, 22, 0,}, /* Times bold */
  141. X    {"bs",    "times%d",    R, 8, 10, 12, 16, 22, 0,}, /* Baskerville */
  142. X    {"bS",    "times%db",    R, 8, 10, 12, 16, 22, 0,}, /* Baskerv. bold */
  143. X    
  144. X    /* Fonts used by funny character translation */
  145. X    
  146. X    {"symbol", "symbol%d",    R, 8, 10, 12, 16, 22, 0},
  147. X    {"symbola","symbola%d", R, 8, 10, 12, 16, 22, 0},
  148. X#else /* ! X11R3 */
  149. X    /* X11 Release 3 fonts */
  150. X    /* Also works for Release 4 */
  151. X    
  152. X    /* PostScript font names */
  153. X    
  154. X    {"R",    "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  155. X    {"I",    "-*-times-medium-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  156. X    {"B",    "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  157. X    {"BI",    "-*-times-bold-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  158. X    
  159. X    {"H",    "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  160. X    {"HO",    "-*-helvetica-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  161. X    {"HB",    "-*-helvetica-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  162. X    {"HD",    "-*-helvetica-bold-o-*--%d-*",R, 8, 10, 12, 14, 18, 24, 0},
  163. X    
  164. X    {"C",    "-*-courier-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},    
  165. X    {"CO",    "-*-courier-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  166. X    {"CB",    "-*-courier-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  167. X    {"CD",    "-*-courier-bold-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  168. X    
  169. X    /* CW is a common alias for C */
  170. X    {"CW",    "-*-courier-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},    
  171. X    
  172. X    /* CWI Harris font names (also R, I, B, BI) */
  173. X    
  174. X    /* Vega light, Vega, Vega medium (Helvetica look-alike) */
  175. X    {"Vl",    "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  176. X    {"vl",    "-*-helvetica-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  177. X    {"V",    "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  178. X    {"v",    "-*-helvetica-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  179. X    {"Vm",    "-*-helvetica-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  180. X    {"vm",    "-*-helvetica-bold-o-*--%d-*",R, 8, 10, 12, 14, 18, 24, 0,},
  181. X    
  182. X    /* Baskerville (see also small caps) */
  183. X    {"br",    "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  184. X    {"bi",    "-*-times-medium-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  185. X    {"bb",    "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  186. X    {"bI",    "-*-times-bold-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  187. X    
  188. X    /* Century Schoolbook */
  189. X    {"cr",    "-*-new century schoolbook-medium-r-*--%d-*",
  190. X    R, 8, 10, 12, 14, 18, 24, 0,},
  191. X    {"ci",    "-*-new century schoolbook-medium-i-*--%d-*",
  192. X    R, 8, 10, 12, 14, 18, 24, 0,},
  193. X    {"cb",    "-*-new century schoolbook-bold-r-*--%d-*",
  194. X    R, 8, 10, 12, 14, 18, 24, 0,},
  195. X    {"cI",    "-*-new century schoolbook-bold-i-*--%d-*",
  196. X    R, 8, 10, 12, 14, 18, 24, 0,},
  197. X    
  198. X    /* Laurel */
  199. X    {"lr",    "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  200. X    {"li",    "-*-times-medium-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  201. X    {"lb",    "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  202. X    {"lI",    "-*-times-bold-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  203. X    
  204. X    /* Funny fonts mapped to Helvetica, at least they differ from Times */
  205. X    {"G3",    "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  206. X    /* German no 3 */
  207. X    {"fs",    "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  208. X    /* French Script */
  209. X    {"RS",    "-*-helvetica-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  210. X    /* Rose Script */
  211. X    {"SO",    "-*-helvetica-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  212. X    /* Scitype Open */
  213. X    
  214. X    /* OCR-B (line printer font) */
  215. X    {"lp",    "-*-courier-bold-r-*--%d-*", R, 8, 10, 12, 0},
  216. X    
  217. X    /* Small caps fonts mapped to normal fonts */
  218. X    {"Rs",    "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  219. X    /* Times */
  220. X    {"Bs",    "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  221. X    /* Times bold */
  222. X    {"bs",    "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  223. X    /* Baskerville */
  224. X    {"bS",    "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,},
  225. X    /* Baskerville bold */
  226. X    
  227. X    /* Fonts used by funny character translation */
  228. X    
  229. X    {"r3symbol", "*-*-symbol-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0},
  230. X#endif /* ! X11R2 */
  231. X#endif /* ! macintosh */
  232. X    
  233. X    {NULL,    NULL}
  234. X};
  235. X
  236. Xstatic struct _translate *translate = default_translate;
  237. X
  238. X/* Tell STDWIN to use the desired font and size.
  239. X   Call at start of page and after each font or size change. */
  240. X
  241. Xusefont()
  242. X{
  243. X    char *fontname;
  244. X    
  245. X    if (showpage != ipage)
  246. X        return;
  247. X    
  248. X    fontname= fonts.name[font];
  249. X    if (fontname != NULL)
  250. X        fonthack(fontname);
  251. X    /* Else, font not loaded -- assume in initialization phase */
  252. X    baseline= wbaseline();
  253. X    lineheight= wlineheight();
  254. X    recheck();
  255. X}
  256. X
  257. Xfonthack(fontname)
  258. X    char *fontname;
  259. X{
  260. X    int i;
  261. X    int havesize;
  262. X    char *harname;
  263. X    char buf[256];
  264. X    struct _translate *t;
  265. X    
  266. X    for (t= translate; t->harname != NULL; ++t) {
  267. X        if (strcmp(t->harname, fontname) == 0)
  268. X            break;
  269. X    }
  270. X    if (t->harname == NULL) {
  271. X        fontwarning(fontname);
  272. X    }
  273. X    else {
  274. X#ifdef macintosh
  275. X        wsetfont(t->xname);
  276. X        wsetsize(size);
  277. X        wsetplain();
  278. X        switch (t->style) {
  279. X        case I: wsetitalic(); break;
  280. X        case B: wsetbold(); break;
  281. X        case BI: wsetbolditalic(); break;
  282. X        }
  283. X#else
  284. X        havesize= size;
  285. X        for (i= 0; ; ++i) {
  286. X            if (t->sizes[i] >= havesize || t->sizes[i+1] == 0) {
  287. X                havesize= t->sizes[i];
  288. X                break;
  289. X            }
  290. X        }
  291. X        sprintf(buf, t->xname, havesize);
  292. X        wsetfont(buf);
  293. X#endif
  294. X    }
  295. X}
  296. X
  297. X/* Issue a warning.
  298. X   Avoid warning many times in a row about the same font. */
  299. X
  300. Xfontwarning(fontname)
  301. X    char *fontname;
  302. X{
  303. X    static char lastwarning[200];
  304. X    char buf[256];
  305. X    
  306. X    if (strncmp(lastwarning, fontname, sizeof lastwarning) != 0) {
  307. X        strncpy(lastwarning, fontname, sizeof lastwarning);
  308. X        sprintf(buf, "mapping for font %s unknown", fontname);
  309. X        error(WARNING, buf);
  310. X    }
  311. X}
  312. X
  313. X/* Get a token */
  314. X
  315. Xstatic char *
  316. Xgettok(pp)
  317. X    char **pp;
  318. X{
  319. X    char *p = *pp;
  320. X    char *start;
  321. X    char c;
  322. X    
  323. X    while (isspace(c = *p++)) /* Skip to start of token */
  324. X        ;
  325. X    if (c == '\0' || c == '\n' || c == '#') {
  326. X        if (dbg > 2)
  327. X            if (c == '#')
  328. X                fprintf(stderr, "next token is comment\n");
  329. X            else if (c == '\n')
  330. X                fprintf(stderr, "next token is newline\n");
  331. X            else
  332. X                fprintf(stderr, "next token is EOS\n");
  333. X        return NULL; /* End of line of comment */
  334. X    }
  335. X    start = p-1; /* Remember start of token */
  336. X    while (!isspace(c = *p++) && c != '\0') /* Skip to end of token */
  337. X        ;
  338. X    if (c == '\0')
  339. X        p--;
  340. X    else
  341. X        p[-1] = '\0'; /* Zero-terminate token */
  342. X    *pp = p; /* Start point for next token */
  343. X    if (dbg > 2)
  344. X        fprintf(stderr, "next token: %s\n", start);
  345. X    return start;
  346. X}
  347. X
  348. Xstatic void
  349. Xaddtrans(pnt, pt, harname, xname, style, sizes)
  350. X    int *pnt;
  351. X    struct _translate **pt;
  352. X    char *harname;
  353. X    char *xname;
  354. X    int style;
  355. X    int sizes[];
  356. X{
  357. X    int i = (*pnt)++;
  358. X    struct _translate *t = *pt;
  359. X    
  360. X    if (i == 0)
  361. X        t = (struct _translate *) malloc(sizeof(struct _translate));
  362. X    else
  363. X        t = (struct _translate *)
  364. X            realloc((char *)t, sizeof(struct _translate) * *pnt);
  365. X    if (t == NULL)
  366. X        error(FATAL, "not enough memory for font translations");
  367. X    *pt = t;
  368. X    t += i;
  369. X    t->harname = strdup(harname);
  370. X    t->xname = strdup(xname);
  371. X    t->style = style;
  372. X    for (i = 0; i <= NSIZES; i++)
  373. X        t->sizes[i] = sizes[i];
  374. X}
  375. X
  376. X/* Read a file of alternative font translations. */
  377. X
  378. Xreadtrans(filename)
  379. X    char *filename;
  380. X{
  381. X    struct _translate *t;
  382. X    int nt;
  383. X    FILE *fp;
  384. X    int line;
  385. X    char buf[1000];
  386. X    char *p;
  387. X    char *harname;
  388. X    char *xname;
  389. X    char *sizetemp;
  390. X    int sizes[NSIZES+1];
  391. X    static int defsizes[NSIZES+1] = {8, 10, 12, 14, 18, 24, 0};
  392. X    int nsizes;
  393. X    
  394. X    fp = fopen(filename, "r");
  395. X    if (fp == NULL)
  396. X        error(FATAL, "can't find font translations file %s", filename);
  397. X    if (dbg > 0)
  398. X        fprintf(stderr, "reading translations from %s\n", filename);
  399. X    t = NULL;
  400. X    nt = 0;
  401. X    line = 0;
  402. X    while (fgets(buf, sizeof buf, fp) != NULL) {
  403. X        line++;
  404. X        if (dbg > 1)
  405. X            fprintf(stderr, "line %d: %s\n", line, buf);
  406. X        p = buf;
  407. X        harname = gettok(&p);
  408. X        if (harname == NULL)
  409. X            continue; /* Blank line or comment */
  410. X        xname = gettok(&p);
  411. X        if (xname == NULL) {
  412. X            error(WARNING, "%s(%d): incomplete line (only '%s')",
  413. X                        filename, line, harname);
  414. X            continue;
  415. X        }
  416. X        /* Style is always R */
  417. X        nsizes = 0;
  418. X        while (nsizes < NSIZES && (sizetemp = gettok(&p)) != NULL) {
  419. X            sizes[nsizes] = atoi(sizetemp);
  420. X            if (sizes[nsizes] <= 0 ||
  421. X                    nsizes > 0 &&
  422. X                    sizes[nsizes] <= sizes[nsizes-1]) {
  423. X                error(WARNING,
  424. X                    "%s(%d): bad or non-increasing size '%s'",
  425. X                    filename, line, sizetemp);
  426. X            }
  427. X            else
  428. X                nsizes++;
  429. X        }
  430. X        if (nsizes > 0)
  431. X            while (nsizes <= NSIZES)
  432. X                sizes[nsizes++] = 0;
  433. X        addtrans(&nt, &t, harname, xname, R,
  434. X            nsizes == 0 ? defsizes : sizes);
  435. X    }
  436. X    if (dbg > 0)
  437. X        fprintf(stderr, "done reading translations.\n");
  438. X    fclose(fp);
  439. X    if (nt == 0)
  440. X        error(FATAL, "%s: no valid font translations", filename);
  441. X    addtrans(&nt, &t, (char *)NULL, (char *)NULL, R, defsizes);
  442. X    translate = t;
  443. X}
  444. END_OF_FILE
  445. if test 12151 -ne `wc -c <'Appls/dpv/dpvfonts.c'`; then
  446.     echo shar: \"'Appls/dpv/dpvfonts.c'\" unpacked with wrong size!
  447. fi
  448. # end of 'Appls/dpv/dpvfonts.c'
  449. fi
  450. if test -f 'Doc/seldoc.ms' -a "${1}" != "-c" ; then 
  451.   echo shar: Will not clobber existing file \"'Doc/seldoc.ms'\"
  452. else
  453. echo shar: Extracting \"'Doc/seldoc.ms'\" \(12081 characters\)
  454. sed "s/^X//" >'Doc/seldoc.ms' <<'END_OF_FILE'
  455. X.\" To format, use (di)troff -ms; and make sure macros.ms is around!
  456. X.so macros.ms
  457. X.SH
  458. XUsing X11 Selections and Cut Buffers in STDWIN
  459. X.LP
  460. XThe C STDWIN interface has been extended to support the
  461. X.I selection
  462. Xmechanism used by X11.
  463. XSupport for the ring of 8 cut buffers is also provided.
  464. X.PP
  465. XThis document assumes you are familiar with STDWIN as a programmer and
  466. Xwith X11 as an end user (at least xterm experience and some idea of the
  467. Xclient-server model).
  468. X.NH
  469. XWhat are Selections?
  470. X.LP
  471. XX11 supports an arbitrary number of selections, but version 1.0 of the
  472. XICCCM (Inter-Client Communication Conventions Manual, by David Rosenthal)
  473. Xrequires only that clients support three selections called PRIMARY,
  474. XSECONDARY and CLIPBOARD.
  475. XI will further reference these in lower case.
  476. X.PP
  477. XThe
  478. X.I "primary selection"
  479. Xis the mechanism you normally use to transfer data interactively
  480. Xbetween clients (or within one client).
  481. XIn xterm and text-oriented toolkit clients, you make a primary
  482. Xselection by dragging with the left mouse button.
  483. XThe contents of the selection are highlighted using inverse video.
  484. XThe contents of the primary selection can be pasted into the same or
  485. Xanother (toolkit) client by pressing the middle mouse button.
  486. X.PP
  487. XConventions for use of the
  488. X.I "secondary selection"
  489. Xare less well-known.
  490. XIt is used as the second argument of operations with two arguments,
  491. Xsuch as swap or replace operations.
  492. XThere is no default support for it in the toolkit, but it is
  493. Xpossible to customize toolkit clients to use it.
  494. X.PP
  495. XThe
  496. X.I clipboard
  497. Xis intended to hold data that the user has deleted and wants to insert
  498. Xsomewhere later.
  499. XIt is supported by the standard X11 client
  500. X.I xclipboard ,
  501. Xwhich displays the current contents of the clipboard.
  502. XOther toolkit clients can be customized to use it.
  503. X.NH
  504. XSelections From the Client's Point of View
  505. X.LP
  506. XIt is important to realize that the contents of selections are
  507. Xtransferred between clients at the time they are pasted; selections are
  508. Xnot normally stored by the server.
  509. XAt any time, a selection is ``owned'' by at most one client, the
  510. X.I "selection owner" .
  511. XDifferent selections may be owned by different clients.
  512. XThe server keeps track of selection owners.
  513. XWhen a client wants to become owner of a particular selection, it tells
  514. Xthe server so, and the server will send the previous owner an event to
  515. Xtell it that it no longer owns the selection.
  516. X.PP
  517. XThe protocol to transfer the contents of a selection between clients is
  518. Xfairly involved.
  519. XSomewhat simplified, it works as follows:
  520. X.IP \(bu
  521. XA client requests the contents of a selection from the server.
  522. X.IP \(bu 2
  523. XThe server sends the owner an event asking ``please give me this
  524. Xselection.''
  525. X.IP \(bu 2
  526. XThe owner stores the contents of the selection as a
  527. X.I property\(dg
  528. X.FS
  529. X\(dg
  530. XA window
  531. X.I property
  532. Xis a named arbitrary piece of data associated with a window, stored by
  533. Xthe server.
  534. X.FE
  535. Xon the requestor's window, and sends an event back (via the server)
  536. Xtelling the requestor that the selection is stored.
  537. X.IP \(bu 2
  538. XThe requestor fetches the contents of the property, and deletes
  539. Xthe property.
  540. X.PP
  541. XVarious complications are possible:
  542. X.IP \(bu 2
  543. XRace conditions: a client may be slow to respond to a mouse click, and
  544. Xthe impatient user may have clicked again in another client's window.
  545. XWhen the first client finally decides it wants to become selection
  546. Xowner, the second client may already own it.
  547. X.IP \(bu
  548. XCrashes: a selection owner may crash before it has responded to a
  549. Xrequest for the selection's contents.
  550. X.IP \(bu
  551. XSpace limitations on the server.
  552. X.IP \(bu
  553. XNegotiations about the type of the selection: a string could be stored
  554. Xin simple ASCII or in a special format that retains font information,
  555. Xand in fact a selection may contain a picture or an arbitrarily
  556. Xcomplicated data structure that only a few clients know about.
  557. X.NH
  558. XThe STDWIN Interface to Selections
  559. X.LP
  560. XSTDWIN simplifies the concept of a selection somewhat and takes care of
  561. Xmost details of communicating with other clients.
  562. XIn STDWIN, selections are always ASCII strings and only the three
  563. Xstandard selections are supported.
  564. XThe strings are null-terminated but may also contain embedded null
  565. Xcharacters, so a length is always provided.
  566. X.PP
  567. XThe header
  568. X.cW <stdwin.h>
  569. Xdefines constants that identify the selections:
  570. X.cW WS_PRIMARY ,
  571. X.cW WS_SECONDARY ,
  572. Xand
  573. X.cW WS_CLIPBOARD .
  574. XThe application calls the function
  575. X.cW wsetselection()
  576. Xto become owner of a selection.
  577. XIt may later receive an event of type
  578. X.cW WE_LOST_SEL
  579. Xtelling it that it lost ownership again.
  580. XIt is also possible to voluntarily give up selection ownership by
  581. Xcalling
  582. X.cW wresetselection() .
  583. XTo access the contents of a selection, whether you own it or not, call
  584. Xthe function
  585. X.cW wgetselection() .
  586. XTransfer of selection contents to other clients is done automatically by
  587. X.cW wgetevent()
  588. Xand
  589. X.cW wpollevent() .
  590. XDetailed descriptions of the new functions follow:
  591. X.NH 2
  592. XFunction \*<wsetselection()\*>
  593. X.LP
  594. X.sC L
  595. Xbool wsetselection(win, sel, data, len)
  596. XWINDOW *win;
  597. Xint sel;
  598. Xchar *data;
  599. Xint len;
  600. X.eC
  601. X.LP
  602. XParameters:
  603. X.IP \*<win\*> 6n
  604. XSpecifies a window that will be associated with the selection.
  605. XThis has no other meaning that limiting the lifetime of the selection to
  606. Xthe lifetime of the window.
  607. XIt will not be reported in
  608. X.cW WE_LOST_SEL
  609. Xevents.
  610. X.IP \*<sel\*>
  611. XSpecifies which selection should be set.
  612. XIt should be one of the codes
  613. X.cW WS_PRIMARY ,
  614. X.cW WS_SECONDARY ,
  615. Xor
  616. X.cW WS_CLIPBOARD .
  617. X.IP \*<data\*>
  618. XSpecifies the data comprising the selection's contents.
  619. XThis need not be null-terminated.
  620. XIt is copied to a safe place by the function so it can be sent to
  621. Xother clients later.
  622. X.IP \*<len\*>
  623. XSpecifies the length of the data, not including a terminating null byte.
  624. X.LP
  625. XThis function attempts to acquirpe ownership of the specified selection.
  626. XThis may fail because of race conditions.
  627. XThe function returns nonzero if it succeeds.
  628. XIf it fails, the application should give the user visual feedback of the
  629. Xfailure,
  630. X.I e.g. ,
  631. Xby not inverting the selected text.
  632. X.NH 2
  633. XFunction \*<wresetselection()\*>
  634. X.LP
  635. X.sC L
  636. Xvoid wresetselection(sel)
  637. Xint sel;
  638. X.eC
  639. X.LP
  640. XParameters:
  641. X.IP \*<sel\*> 6n
  642. XSpecifies which selection should be reset.
  643. XIt should be one of the codes
  644. X.cW WS_PRIMARY ,
  645. X.cW WS_SECONDARY ,
  646. Xor
  647. X.cW WS_CLIPBOARD .
  648. X.LP
  649. XIf the application owns the specified selection, this function cancels
  650. Xownership.
  651. XNo
  652. X.cW WE_LOST_SEL
  653. Xevents are generated for the selection.
  654. X.NH 2
  655. XFunction \*<wgetselection()\*>
  656. X.LP
  657. X.sC L
  658. Xchar *wgetselection(sel, plen)
  659. Xint sel;
  660. Xint *plen;
  661. X.eC
  662. XParameters:
  663. X.IP \*<sel\*> 6n
  664. XSpecifies which selection should be retrieved.
  665. XIt should be one of the codes
  666. X.cW WS_PRIMARY ,
  667. X.cW WS_SECONDARY ,
  668. Xor
  669. X.cW WS_CLIPBOARD .
  670. X.IP \*<plen\*>
  671. XInto this parameter, the length of the data is returned, excluding the
  672. Xterminating null byte.
  673. X.LP
  674. XThis function retrieves the contents of the specified selection.
  675. XIf it succeeds, a pointer to its data is returned.
  676. XThe data is terminated by a null byte but may contain null bytes, so the
  677. Xlength is returned separately.
  678. XThe data pointer points to space internal to the STDWIN library.
  679. XIt remains valid until the next call involving selections.
  680. XIf the selection could not be retrieved somehow, a NULL pointer is
  681. Xreturned.
  682. XSelections longer that 32K may be truncated.
  683. XSince the transfer mechanism requires the use of a window, a NULL
  684. Xpointer is returned when the application currently has no windows open.
  685. X.NH 2
  686. XThe \*<WE_LOST_SEL\*> event type
  687. X.LP
  688. XA STDWIN application receives this event type when it owns a selection
  689. X(a call to
  690. X.cW wsetselection()
  691. Xhas succeeded) and another client has become the new owner.
  692. XThe
  693. X.cW window
  694. Xmember of the
  695. X.cW EVENT
  696. Xis set to
  697. X.cW NULL .
  698. XThe
  699. X.cW u.sel
  700. Xunion member is set to the code for the selection.
  701. XThis event is not generated when selection ownership is given up by
  702. Xcalling
  703. X.cW wresetselection()
  704. Xor by deleting its window.
  705. X.NH
  706. XThe STDWIN Interface to Cut Buffers
  707. X.LP
  708. XFor compatibility with old STDWIN or X11 clients and Andrew clients,
  709. Xan interface to the cut buffer interface is also provided.
  710. XThis is a ring of 8 buffers maintained at the server.
  711. XThe following functions are available:
  712. X.NH 2
  713. XFunction \*<wsetcutbuffer()\*>
  714. X.LP
  715. X.sC L
  716. Xvoid wsetcutbuffer(ibuffer, data, len)
  717. Xint ibuffer;
  718. Xchar *data;
  719. Xint len;
  720. X.eC
  721. X.LP
  722. XParameters:
  723. X.IP \*<ibuffer\*> 10n
  724. XSpecifies which buffer should be set, in the range [0 ... 7].
  725. X.IP \*<data\*>
  726. XSpecifies the data.
  727. XIt need not be null-terminated.
  728. X.IP \*<len\*>
  729. XSpecifies the length of the data, excluding a terminating null byte.
  730. X.LP
  731. XThis function sets the contents of the specified cut buffer to the given
  732. Xdata.
  733. XNo indication of success or failure is given.
  734. X.NH 2
  735. XFunction \*<wgetcutbuffer()\*>
  736. X.LP
  737. X.sC L
  738. Xchar *wgetcutbuffer(ibuffer, plen)
  739. Xint ibuffer;
  740. Xint *plen;
  741. X.eC
  742. X.LP
  743. XParameters:
  744. X.IP \*<ibuffer\*> 10n
  745. XSpecifies which buffer should be retrieved, in the range [0 ... 7].
  746. X.IP \*<plen\*>
  747. XReturns the length of the data, excluding the terminating null byte.
  748. X.LP
  749. XThis function returns the contents of the specified cut buffer,
  750. Xterminated by a null byte.
  751. XIf the cut buffer is not accessible, it returns
  752. X.cW NULL .
  753. X.NH 2
  754. XFunction \*<wrotatecutbuffers()\*>
  755. X.LP
  756. X.sC L
  757. Xvoid wrotatecutbuffers(n)
  758. Xint n;
  759. X.eC
  760. X.LP
  761. XParameters:
  762. X.IP \*<n\*> 4n
  763. XSpecifies the amount of rotation.
  764. XThis may be negative.
  765. X.LP
  766. XThe cut buffers are rotated as follows:
  767. Xbuffer n gets the contents of buffer 0, buffer n+1 (mod 8) gets the
  768. Xcontents of buffer 1, etc.
  769. X.NH 2
  770. XFunction \*<wsetclip()\*>
  771. X.LP
  772. X.sC L
  773. Xvoid wsetclip(data, len)
  774. Xchar *data;
  775. Xint len;
  776. X.eC
  777. XThis function is equivalent to
  778. X.sC
  779. Xwsetcutbuffer(0, data, len);
  780. Xwrotatecutbuffers(1);
  781. X.eC
  782. X.NH 2
  783. XFunction \*<wgetclip()\*>
  784. X.LP
  785. X.sC L
  786. Xchar *wgetclip()
  787. X.eC
  788. XThis function is equivalent to
  789. X.sC
  790. Xint len;
  791. Xreturn wgetcutbuffer(0, &len);
  792. X.eC
  793. X(It throws away the length.)
  794. X.NH
  795. XSuggested Usage
  796. X.LP
  797. XTo conform to X11 conventions, STDWIN applications should normally use
  798. Xthe primary selection, but use the cut buffers as a ``fall-back''
  799. Xmechanism.
  800. X.PP
  801. XWhen the user has selected some text, the application should transfer
  802. Xthe text to cut buffer 0 and rotate the buffers (the easiest way to do
  803. Xthis is to call
  804. X.cW wsetclip() ),
  805. Xand then call
  806. X.cW wsetselection()
  807. Xto set the primary selection to the text.
  808. XIf the latter call fails, the inverse video on the selected text should
  809. Xbe removed.
  810. XThe inverse video should also be removed when a
  811. X.cW WE_LOST_SEL
  812. Xevent is received.
  813. XIf there is a text insertion point associated with the selection, it
  814. Xshould be left at the position indicated by the last mouse click, or to
  815. Xthe beginning of the selected text.
  816. X.PP
  817. XWhen the user desires to paste some text, the applcation should first
  818. Xget the contents of the primary selection, and if this returns a NULL
  819. Xpointer, it should get the contents of cut buffer 0.
  820. XIf this returns a NULL pointer as well, the paste request should be
  821. Xrefused (with a beep, or something similar).
  822. X.PP
  823. XThe conventions for selecting and pasting text are:
  824. X.IP \(bu 2
  825. XDragging with the left (first) mouse button is used to make a selection.
  826. XDouble-clicking selects ``words.''
  827. X.IP \(bu
  828. XClicking with the middle mouse button requests a ``paste'' operation.
  829. XIt does not move the insert point to the position of the click.
  830. X.IP \(bu
  831. XClicking with the right mouse button extends the selection at the end
  832. Xclosest to the button click.
  833. X.NH
  834. XSelections and Macintosh STDWIN
  835. X.LP
  836. XThe Macintosh user interface standards prescribe only a single cut
  837. Xbuffer, called the Clipboard.
  838. XFor source compatibility with STDWIN applications developed for X11,
  839. Xdummy versions of the selection functions are provided:
  840. X.cW wsetselection()
  841. Xand
  842. X.cW wgetselection()
  843. Xalways fail, and
  844. X.cW wresetselection()
  845. Xis ignored.
  846. XVersions of the cut buffer functions are provided that identify cut
  847. Xbuffer 0 with the Macintosh Clipboard and ignore the other cut buffers.
  848. X.PP
  849. XThe net effect is that STDWIN applications written for X11 selections
  850. Xthat use the cut buffers as a fall-back mechanism will support the
  851. XMacintosh Clipboard, albeit with an X11-like interface.
  852. XMacintosh applications are encouraged to provide a standard Edit menu
  853. Xwith the operations Cut, Copy and Paste and the standard shortcuts for
  854. Xthem: Command-X, Command-C and Command-V.
  855. END_OF_FILE
  856. if test 12081 -ne `wc -c <'Doc/seldoc.ms'`; then
  857.     echo shar: \"'Doc/seldoc.ms'\" unpacked with wrong size!
  858. fi
  859. # end of 'Doc/seldoc.ms'
  860. fi
  861. if test -f 'Packs/textedit/textlow.c' -a "${1}" != "-c" ; then 
  862.   echo shar: Will not clobber existing file \"'Packs/textedit/textlow.c'\"
  863. else
  864. echo shar: Extracting \"'Packs/textedit/textlow.c'\" \(12558 characters\)
  865. sed "s/^X//" >'Packs/textedit/textlow.c' <<'END_OF_FILE'
  866. X/* Text Edit, low-level routines */
  867. X
  868. X/* CONVENTION:
  869. X    routines beginning with te... have a first parameter 'tp';
  870. X    routines beginning with z... don't, or are macros that
  871. X    implicitly use a variable or parameter 'tp'
  872. X*/
  873. X
  874. X#include "text.h"
  875. X
  876. X/* Variants on wtextwidth, wtextbreak, wdrawtext taking the gap in account.
  877. X   These have two buffer offsets as parameters instead of a text pointer
  878. X   and a length; tetextbreak also returns a buffer offset */
  879. X
  880. X/* These routines now also take tabs into account.
  881. X   They should now only be called with a line start for 'pos' ! */
  882. X
  883. Xint
  884. Xtetextwidth(tp, pos, end)
  885. X    register TEXTEDIT *tp;
  886. X    bufpos pos, end;
  887. X{
  888. X    char *p= tp->buf + pos;
  889. X    register char *e= tp->buf +
  890. X        (tp->gap >= pos && tp->gap < end ? tp->gap : end);
  891. X    int w= 0;
  892. X    register char *k;
  893. X    
  894. X    zcheckpos(pos);
  895. X    zcheckpos(end);
  896. X    zassert(pos <= end);
  897. X    
  898. X    /* This do loop is executed once or twice only! */
  899. X    do {
  900. X        for (k= p; k < e; ++k) {
  901. X            if (*k == '\t') {
  902. X                if (k > p)
  903. X                    w += wtextwidth(p, (int)(k-p));
  904. X                w= znexttab(w);
  905. X                p= k+1;
  906. X            }
  907. X        }
  908. X        if (k > p)
  909. X            w += wtextwidth(p, (int)(k-p));
  910. X        if (tp->gap >= pos) {
  911. X            p= tp->buf + zgapend;
  912. X            e= tp->buf + end;
  913. X        }
  914. X    } while (k < e);
  915. X    
  916. X    return w;
  917. X}
  918. X
  919. Xbufpos
  920. Xtetextbreak(tp, pos, end, width)
  921. X    register TEXTEDIT *tp;
  922. X    bufpos pos, end;
  923. X    int width;
  924. X{
  925. X    char *p= tp->buf + pos;
  926. X    register char *e= tp->buf +
  927. X        (tp->gap >= pos && tp->gap < end ? tp->gap : end);
  928. X    int w= 0;
  929. X    register char *k;
  930. X    
  931. X    zcheckpos(pos);
  932. X    zcheckpos(end);
  933. X    zassert(pos <= end);
  934. X    
  935. X    /* This do loop is executed once or twice only! */
  936. X    do {
  937. X        for (k= p; k < e; ++k) {
  938. X            if (*k == '\t') {
  939. X                if (k > p) {
  940. X                    int n= wtextbreak(p, (int)(k-p),
  941. X                        width-w);
  942. X                    if (n < k-p)
  943. X                        return p - tp->buf + n;
  944. X                    w += wtextwidth(p, (int)(k-p));
  945. X                }
  946. X                w= znexttab(w);
  947. X                if (w > width)
  948. X                    return k - tp->buf;
  949. X                p= k+1;
  950. X            }
  951. X        }
  952. X        if (k > p) {
  953. X            int n= wtextbreak(p, (int)(k-p), width-w);
  954. X            if (n < k-p)
  955. X                return p - tp->buf + n;
  956. X            w += wtextwidth(p, (int)(k-p));
  957. X        }
  958. X        if (tp->gap >= pos) {
  959. X            p= tp->buf + zgapend;
  960. X            e= tp->buf + end;
  961. X        }
  962. X    } while (k < e);
  963. X    
  964. X    return end;
  965. X}
  966. X
  967. Xhcoord
  968. Xtedrawtext(tp, h, v, pos, end)
  969. X    register TEXTEDIT *tp;
  970. X    int h, v;
  971. X    bufpos pos, end;
  972. X{
  973. X    char *p= tp->buf + pos;
  974. X    register char *e= tp->buf +
  975. X        (tp->gap >= pos && tp->gap < end ? tp->gap : end);
  976. X    int w= 0;
  977. X    register char *k;
  978. X    
  979. X    zcheckpos(pos);
  980. X    zcheckpos(end);
  981. X    zassert(pos <= end);
  982. X    
  983. X    /* This do loop is executed once or twice only! */
  984. X    do {
  985. X        for (k= p; k < e; ++k) {
  986. X            if (*k == '\t') {
  987. X                if (k > p)
  988. X                    wdrawtext(h+w, v, p, (int)(k-p));
  989. X                    w += wtextwidth(p, (int)(k-p));
  990. X                w= znexttab(w);
  991. X                p= k+1;
  992. X            }
  993. X        }
  994. X        if (k > p) {
  995. X            wdrawtext(h+w, v, p, (int)(k-p));
  996. X            w += wtextwidth(p, (int)(k-p));
  997. X        }
  998. X        if (tp->gap >= pos) {
  999. X            p= tp->buf + zgapend;
  1000. X            e= tp->buf + end;
  1001. X        }
  1002. X    } while (k < e);
  1003. X    
  1004. X    return h+w;
  1005. X}
  1006. X
  1007. X/* Safe memory allocation - these abort instead of returning NULL */
  1008. X
  1009. Xchar *
  1010. Xzmalloc(n)
  1011. X    int n;
  1012. X{
  1013. X    char *p= malloc((unsigned)n);
  1014. X    
  1015. X    if (p == NULL) {
  1016. X        dprintf("zmalloc(%d): out of mem", n);
  1017. X        exit(1);
  1018. X    }
  1019. X    return p;
  1020. X}
  1021. X
  1022. Xchar *
  1023. Xzrealloc(p, n)
  1024. X    char *p;
  1025. X    int n;
  1026. X{
  1027. X    char *q= realloc(p, (unsigned)n);
  1028. X    if (q == NULL) {
  1029. X        dprintf("zrealloc(0x%lx, %d): out of mem", (long)p, n);
  1030. X        exit(1);
  1031. X    }
  1032. X    return q;
  1033. X}
  1034. X
  1035. X/* Create/destroy a text-edit record */
  1036. X
  1037. XTEXTEDIT *
  1038. Xtealloc(win, left, top, width)
  1039. X    WINDOW *win;
  1040. X{
  1041. X    return tesetup(win, left, top, left+width, top, TRUE);
  1042. X}
  1043. X
  1044. XTEXTEDIT *
  1045. Xtecreate(win, left, top, right, bottom)
  1046. X    WINDOW *win;
  1047. X    int left, top, right, bottom;
  1048. X{
  1049. X    return tesetup(win, left, top, right, bottom, TRUE);
  1050. X}
  1051. X
  1052. X/*ARGSUSED*/
  1053. XTEXTEDIT *
  1054. Xtesetup(win, left, top, right, bottom, drawing)
  1055. X    WINDOW *win;
  1056. X    int left, top, right, bottom;
  1057. X    bool drawing;
  1058. X{
  1059. X    TEXTEDIT *tp= (TEXTEDIT*) zmalloc(sizeof(TEXTEDIT));
  1060. X    TEXTATTR saveattr;
  1061. X    
  1062. X    tp->win= win;
  1063. X    tp->left= left;
  1064. X    tp->top= top;
  1065. X    tp->right= right;
  1066. X    tp->width= right-left;
  1067. X    
  1068. X    wgettextattr(&saveattr);
  1069. X    if (win != NULL) {
  1070. X        wgetwintextattr(win, &tp->attr);
  1071. X        wsettextattr(&tp->attr);
  1072. X    }
  1073. X    else
  1074. X        tp->attr = saveattr;
  1075. X    tp->vspace= wlineheight();
  1076. X    tp->tabsize= 8*wcharwidth(' ');
  1077. X    if (win != NULL)
  1078. X        wsettextattr(&saveattr);
  1079. X    
  1080. X    tp->bottom= tp->top + tp->vspace;
  1081. X    
  1082. X    tp->foc= tp->foclen= 0;
  1083. X    
  1084. X    tp->buflen= 1;
  1085. X    tp->buf= zmalloc(tp->buflen);
  1086. X    
  1087. X    tp->gap= 0;
  1088. X    tp->gaplen= tp->buflen;
  1089. X    
  1090. X    tp->nlines= 1;
  1091. X    tp->nstart= STARTINCR;
  1092. X    tp->start= (bufpos*) zmalloc(tp->nstart*sizeof(bufpos));
  1093. X    tp->start[0]= tp->start[1]= tp->buflen;
  1094. X    
  1095. X    tp->aim= UNDEF;
  1096. X    tp->focprev= FALSE;
  1097. X    tp->hilite= FALSE;
  1098. X    tp->mdown= FALSE;
  1099. X    tp->drawing= tp->active= drawing;
  1100. X    tp->opt_valid= FALSE;
  1101. X    
  1102. X    if (tp->active)
  1103. X        tesetcaret(tp);
  1104. X    
  1105. X    zcheck();
  1106. X    
  1107. X    return tp;
  1108. X}
  1109. X
  1110. X
  1111. Xvoid
  1112. Xtedestroy(tp)
  1113. X    register TEXTEDIT *tp;
  1114. X{
  1115. X    wchange(tp->win, tp->left, tp->top, tp->right, tp->bottom);
  1116. X    tefree(tp);
  1117. X}
  1118. X
  1119. Xvoid
  1120. Xtefree(tp)
  1121. X    register TEXTEDIT *tp;
  1122. X{
  1123. X    if (tp->active) {
  1124. X        wnocaret(tp->win);
  1125. X        tehidefocus(tp);
  1126. X    }
  1127. X    if (tp->buf != NULL)
  1128. X        free(tp->buf);
  1129. X    if (tp->start != NULL)
  1130. X        free((char*)tp->start);
  1131. X    free((char*)tp);
  1132. X}
  1133. X
  1134. Xvoid
  1135. Xtesetactive(tp, active)
  1136. X    register TEXTEDIT *tp;
  1137. X    bool active;
  1138. X{
  1139. X    if (!tp->drawing || tp->active == active)
  1140. X        return;
  1141. X    tp->active = active;
  1142. X    if (active) {
  1143. X        tesetcaret(tp);
  1144. X    }
  1145. X    else {
  1146. X        wnocaret(tp->win);
  1147. X        tehidefocus(tp);
  1148. X    }
  1149. X}
  1150. X
  1151. X/* Show/hide the focus highlighting.
  1152. X   The boolean hilite is set when highlighting is visible.
  1153. X   teshowfocus ensures the highlighting is visible (if applicable);
  1154. X   tehidefocus ensures it is invisible.
  1155. X   teinvertfocus does the hard work (it is also called from zdraw) */
  1156. X
  1157. Xteshowfocus(tp)
  1158. X    register TEXTEDIT *tp;
  1159. X{
  1160. X    if (tp->active && !tp->hilite && tp->foclen > 0) {
  1161. X        wbegindrawing(tp->win);
  1162. X        teinvertfocus(tp);
  1163. X        wenddrawing(tp->win);
  1164. X        tp->hilite= TRUE;
  1165. X    }
  1166. X}
  1167. X
  1168. Xtehidefocus(tp)
  1169. X    register TEXTEDIT *tp;
  1170. X{
  1171. X    if (tp->hilite) {
  1172. X        wbegindrawing(tp->win);
  1173. X        teinvertfocus(tp);
  1174. X        wenddrawing(tp->win);
  1175. X        tp->hilite= FALSE;
  1176. X    }
  1177. X}
  1178. X
  1179. Xstatic
  1180. Xteinvertfocus(tp)
  1181. X    register TEXTEDIT *tp;
  1182. X{
  1183. X    teinvert(tp, tp->foc, zfocend);
  1184. X}
  1185. X
  1186. X/* Change to a new focus.
  1187. X   Sometimes this may keep the focus visible, sometimes not. */
  1188. X
  1189. Xtechangefocus(tp, f1, f2)
  1190. X    register TEXTEDIT *tp;
  1191. X    int f1, f2;
  1192. X{
  1193. X    if (tp->hilite) {
  1194. X        wbegindrawing(tp->win);
  1195. X        if (f1 == tp->foc)
  1196. X            teinvert(tp, zfocend, f2);
  1197. X        else if (f2 == zfocend)
  1198. X            teinvert(tp, f1, tp->foc);
  1199. X        else {
  1200. X            teinvert(tp, tp->foc, zfocend);
  1201. X            tp->hilite= FALSE;
  1202. X        }
  1203. X        wenddrawing(tp->win);
  1204. X    }
  1205. X    tp->foc= f1;
  1206. X    tp->foclen= f2-f1;
  1207. X}
  1208. X
  1209. X/* Low-level interface: invert the area between f1 and f2 */
  1210. X
  1211. Xstatic
  1212. Xteinvert(tp, f1, f2)
  1213. X    register TEXTEDIT *tp;
  1214. X    int f1, f2;
  1215. X{
  1216. X    coord h, v, hlast, vlast;
  1217. X    
  1218. X    if (f1 == f2)
  1219. X        return;
  1220. X    if (f2 < f1) {
  1221. X        int temp= f1;
  1222. X        f1= f2;
  1223. X        f2= temp;
  1224. X    }
  1225. X    
  1226. X    tewhichpoint(tp, f1, &h, &v);
  1227. X    tewhichpoint(tp, f2, &hlast, &vlast);
  1228. X    
  1229. X    if (v == vlast)
  1230. X        winvert(h, v, hlast, v + tp->vspace);
  1231. X    else {
  1232. X        winvert(h, v, tp->right, v + tp->vspace);
  1233. X        winvert(tp->left, v + tp->vspace, tp->right, vlast);
  1234. X        winvert(tp->left, vlast, hlast, vlast + tp->vspace);
  1235. X    }
  1236. X}
  1237. X
  1238. X/* Draw procedure */
  1239. X
  1240. Xvoid
  1241. Xtedraw(tp)
  1242. X    register TEXTEDIT *tp;
  1243. X{
  1244. X    tedrawnew(tp, tp->left, tp->top, tp->right, tp->bottom);
  1245. X}
  1246. X
  1247. X/*ARGSUSED*/
  1248. Xvoid
  1249. Xtedrawnew(tp, left, top, right, bottom)
  1250. X    register TEXTEDIT *tp;
  1251. X    coord left, top, right, bottom;
  1252. X{
  1253. X    lineno ifirst, ilast, i;
  1254. X    
  1255. X    /* Compute first, last line to be drawn */
  1256. X    ifirst= (top - tp->top)/tp->vspace;
  1257. X    if (ifirst < 0)
  1258. X        ifirst= 0;
  1259. X    ilast= (bottom - tp->top + tp->vspace - 1)/tp->vspace;
  1260. X    if (ilast > tp->nlines)
  1261. X        ilast= tp->nlines;
  1262. X    
  1263. X    /* Draw lines ifirst...ilast-1 */
  1264. X    for (i= ifirst; i < ilast; ++i) {
  1265. X        bufpos pos= tp->start[i];
  1266. X        bufpos end= tp->start[i+1];
  1267. X        if (end > pos && zcharbefore(end) == EOL)
  1268. X            zdecr(&end);
  1269. X        while (end > pos && zcharbefore(end) == ' ')
  1270. X            zdecr(&end);
  1271. X        (void) tedrawtext(tp, tp->left, tp->top + i*tp->vspace,
  1272. X            pos, end);
  1273. X    }
  1274. X    if (tp->hilite)
  1275. X        teinvertfocus(tp);
  1276. X}
  1277. X
  1278. X/* Move the gap to a new position */
  1279. X
  1280. Xtemovegapto(tp, newgap)
  1281. X    register TEXTEDIT *tp;
  1282. X    bufpos newgap;
  1283. X{
  1284. X    zcheck();
  1285. X    zassert(0<=newgap && newgap+tp->gaplen<=tp->buflen);
  1286. X    
  1287. X    if (newgap < tp->gap)
  1288. X        teshift(tp, tp->gaplen, newgap, tp->gap);
  1289. X    else if (newgap > tp->gap)
  1290. X        teshift(tp, -tp->gaplen, zgapend, newgap+tp->gaplen);
  1291. X    tp->gap= newgap;
  1292. X    
  1293. X    zcheck();
  1294. X}
  1295. X
  1296. X/* Extend the gap */
  1297. X
  1298. Xtegrowgapby(tp, add)
  1299. X    register TEXTEDIT *tp;
  1300. X    int add;
  1301. X{
  1302. X    zcheck();
  1303. X    zassert(add>=0);
  1304. X    
  1305. X    tp->buf= zrealloc(tp->buf, tp->buflen + add);
  1306. X    teshift(tp, add, zgapend, tp->buflen);
  1307. X    tp->gaplen += add;
  1308. X    if (tp->start[tp->nlines-1] == tp->buflen)
  1309. X        tp->start[tp->nlines-1]= tp->buflen+add;
  1310. X    tp->start[tp->nlines]= (tp->buflen += add);
  1311. X    
  1312. X    zcheck();
  1313. X}
  1314. X
  1315. X/* Shift buf[first..last-1] n bytes (positive right, negative left) */
  1316. X
  1317. Xstatic
  1318. Xteshift(tp, n, first, last)
  1319. X    register TEXTEDIT *tp;
  1320. X    int n;
  1321. X    bufpos first, last;
  1322. X{
  1323. X    teoffset(tp, n, first, last);
  1324. X    if (n < 0)
  1325. X        temovedown(tp, last-first, tp->buf+first, tp->buf+first+n);
  1326. X    else if (n > 0)
  1327. X        temoveup(tp, last-first, tp->buf+first, tp->buf+first+n);
  1328. X}
  1329. X
  1330. Xstatic
  1331. Xteoffset(tp, n, first, last)
  1332. X    register TEXTEDIT *tp;
  1333. X    int n;
  1334. X    int first, last;
  1335. X{
  1336. X    int i;
  1337. X    
  1338. X    zassert(0<=first&&first<=last&&last<=tp->buflen);
  1339. X    
  1340. X    i= 0;
  1341. X    while (tp->start[i] < first)
  1342. X        ++i;
  1343. X    while (tp->start[i] < last) {
  1344. X        tp->start[i] += n;
  1345. X        ++i;
  1346. X    }
  1347. X}
  1348. X
  1349. X/*ARGSUSED*/
  1350. Xstatic
  1351. Xtemoveup(tp, n, from, to)
  1352. X    TEXTEDIT *tp;
  1353. X    int n;
  1354. X    char *from, *to;
  1355. X{
  1356. X    zassert(from <= to);
  1357. X    
  1358. X    from += n, to += n;
  1359. X    while (--n >= 0)
  1360. X        *--to = *--from;
  1361. X}
  1362. X
  1363. X/*ARGSUSED*/
  1364. Xstatic
  1365. Xtemovedown(tp, n, from, to)
  1366. X    TEXTEDIT *tp;
  1367. X    int n;
  1368. X    char *from, *to;
  1369. X{
  1370. X    zassert(from >= to);
  1371. X    
  1372. X    while (--n >= 0)
  1373. X        *to++ = *from++;
  1374. X}
  1375. X
  1376. X/* Make all start entries pointing into the gap point to beyond it
  1377. X   TO DO: replace by a routine to delete the focus??? */
  1378. X
  1379. Xteemptygap(tp)
  1380. X    register TEXTEDIT *tp;
  1381. X{
  1382. X    lineno i;
  1383. X    
  1384. X    for (i= 0; tp->start[i] < tp->gap; ++i)
  1385. X        ;
  1386. X    for (; tp->start[i] < zgapend; ++i)
  1387. X        tp->start[i]= zgapend;
  1388. X}
  1389. X
  1390. X/* Set the caret at the new focus position,
  1391. X   or display the focus highlighting, if applicable.
  1392. X   Also call wshow() of the focus.
  1393. X   As a side effect, the optimization data is invalidated */
  1394. X
  1395. Xtesetcaret(tp)
  1396. X    register TEXTEDIT *tp;
  1397. X{
  1398. X    coord h, v, hlast, vlast;
  1399. X    
  1400. X    tp->opt_valid = FALSE;
  1401. X    if (!tp->active)
  1402. X        return;
  1403. X    
  1404. X    tewhichpoint(tp, tp->foc, &h, &v);
  1405. X    
  1406. X    if (tp->foclen == 0) {
  1407. X        wsetcaret(tp->win, h, v);
  1408. X        hlast= h;
  1409. X        vlast= v;
  1410. X    }
  1411. X    else {
  1412. X        tewhichpoint(tp, zfocend, &hlast, &vlast);
  1413. X        wnocaret(tp->win);
  1414. X        teshowfocus(tp);
  1415. X    }
  1416. X    wshow(tp->win, h, v, hlast, vlast + tp->vspace);
  1417. X}
  1418. X
  1419. X/* Coordinate transformations.
  1420. X   The following coordinate systems exist;
  1421. X   a position in the text can be expressed in any of these:
  1422. X   
  1423. X       A) offset in buffer with gap removed (used for focus)
  1424. X    B) offset in buffer (used for start[] array)
  1425. X    C) (line number, offset in line taking gap into account)
  1426. X    D) (h, v) on screen
  1427. X   
  1428. X   Conversions exist between successive pairs:
  1429. X   
  1430. X       A -> B: pos= zaddgap(foc)
  1431. X    B -> A: foc= zsubgap(pos)
  1432. X    
  1433. X    B -> C: line= zwhichline(pos, prev); offset= pos-start[line]
  1434. X    C -> B: pos= offset + start[line]
  1435. X    
  1436. X    C -> D: v= i*vspace; h= ztextwidth(start[i], start[i]+offset)
  1437. X    D -> C: i= v/wlh; offset= ztextround(i, h) - start[i]
  1438. X*/
  1439. X
  1440. X/* Find (h, v) corresponding to focus position */
  1441. X
  1442. Xtewhichpoint(tp, f, h_ret, v_ret)
  1443. X    TEXTEDIT *tp;
  1444. X    focpos f;
  1445. X    coord *h_ret, *v_ret;
  1446. X{
  1447. X    bufpos pos= zaddgap(f);
  1448. X    lineno i= tewhichline(tp, pos, f == tp->foc && tp->focprev);
  1449. X    hcoord h= tetextwidth(tp, tp->start[i], pos);
  1450. X    
  1451. X    *h_ret= h + tp->left;
  1452. X    *v_ret= i*tp->vspace + tp->top;
  1453. X}
  1454. X
  1455. X/* To which line does the given buffer position belong? */
  1456. X
  1457. Xlineno
  1458. Xtewhichline(tp, pos, prev)
  1459. X    register TEXTEDIT *tp;
  1460. X    bufpos pos;
  1461. X    bool prev; /* Cf. focprev */
  1462. X{
  1463. X    lineno i;
  1464. X    
  1465. X    for (i= 0; pos > tp->start[i+1]; ++i)
  1466. X        ;
  1467. X    if (pos == tp->start[i+1] && i+1 < tp->nlines) {
  1468. X        ++i;
  1469. X        if (prev && zcharbefore(tp->start[i]) != EOL)
  1470. X            --i;
  1471. X    }
  1472. X    
  1473. X    return i;
  1474. X}
  1475. X
  1476. X/* Convert point in window to buffer position,
  1477. X   possibly taking double-clicking into account.
  1478. X   If required, the line number is also returned. */
  1479. X
  1480. Xbufpos
  1481. Xtewhereis(tp, h, v, line_return)
  1482. X    register TEXTEDIT *tp;
  1483. X    coord h, v;
  1484. X    int *line_return;
  1485. X{
  1486. X    bufpos pos;
  1487. X    lineno i;
  1488. X    
  1489. X    i= (v - tp->top)/tp->vspace;
  1490. X    if (i >= tp->nlines) {
  1491. X        i= tp->nlines;
  1492. X        pos= tp->buflen;
  1493. X    }
  1494. X    else if (i < 0) {
  1495. X        i= 0;
  1496. X        pos= 0;
  1497. X    }
  1498. X    else
  1499. X        pos= tetextround(tp, i, h);
  1500. X    if (line_return != NULL)
  1501. X        *line_return= i;
  1502. X    return pos;
  1503. X}
  1504. X
  1505. X/* Find the buffer position nearest to the given h coordinate,
  1506. X   in the given line */
  1507. X
  1508. Xbufpos
  1509. Xtetextround(tp, i, h)
  1510. X    register TEXTEDIT *tp;
  1511. X    lineno i;
  1512. X    hcoord h;
  1513. X{
  1514. X    bufpos pos;
  1515. X    bufpos end= tp->start[i+1];
  1516. X    
  1517. X    h -= tp->left;
  1518. X    if (end > tp->start[i] && zcharbefore(end) == EOL)
  1519. X        zdecr(&end);
  1520. X    pos= tetextbreak(tp, tp->start[i], end, h);
  1521. X    
  1522. X    if (pos < end) {
  1523. X        if (h - tetextwidth(tp, tp->start[i], pos) >=
  1524. X            tetextwidth(tp, tp->start[i], znext(pos)) - h)
  1525. X            zincr(&pos);
  1526. X    }
  1527. X    
  1528. X    return pos;
  1529. X}
  1530. END_OF_FILE
  1531. if test 12558 -ne `wc -c <'Packs/textedit/textlow.c'`; then
  1532.     echo shar: \"'Packs/textedit/textlow.c'\" unpacked with wrong size!
  1533. fi
  1534. # end of 'Packs/textedit/textlow.c'
  1535. fi
  1536. if test -f 'Ports/mac/event.c' -a "${1}" != "-c" ; then 
  1537.   echo shar: Will not clobber existing file \"'Ports/mac/event.c'\"
  1538. else
  1539. echo shar: Extracting \"'Ports/mac/event.c'\" \(12997 characters\)
  1540. sed "s/^X//" >'Ports/mac/event.c' <<'END_OF_FILE'
  1541. X/* MAC STDWIN -- EVENT HANDLING. */
  1542. X
  1543. X#include "macwin.h"
  1544. X#ifdef MPW
  1545. X#include <Events.h>
  1546. X#include <Menus.h>
  1547. X#include <Desk.h>
  1548. X#include <ToolUtils.h>
  1549. X#endif
  1550. X#ifdef THINK_C
  1551. X#include <EventMgr.h>
  1552. X#endif
  1553. X
  1554. Xvoid (*_w_idle_proc)();    /* Function to call in idle loop */
  1555. X
  1556. XWINDOW *active= NULL;    /* The active window */
  1557. X            /* XXX should be a less obvious name */
  1558. Xbool _wm_down;        /* Set if mouse is down in content rect */
  1559. X
  1560. Xstatic EventRecord e;    /* Global, so it's accessible to all subroutines */
  1561. X            /* XXX the name is too short */
  1562. X
  1563. X/* Function prototypes */
  1564. X
  1565. XSTATIC void make_mouse_event _ARGS((EVENT *ep, Point *pwhere));
  1566. XSTATIC void do_idle _ARGS((EVENT *ep));
  1567. XSTATIC void do_update _ARGS((EVENT *ep));
  1568. XSTATIC void do_mouse_down _ARGS((EVENT *ep));
  1569. XSTATIC void do_mouse_up _ARGS((EVENT *ep));
  1570. XSTATIC void do_key _ARGS((EVENT *ep));
  1571. XSTATIC void do_activate _ARGS((EVENT *ep));
  1572. XSTATIC void do_disk _ARGS((EVENT *ep));
  1573. XSTATIC void activate _ARGS((WINDOW *win));
  1574. XSTATIC void deactivate _ARGS((void));
  1575. X
  1576. XSTATIC void do_click _ARGS((EVENT *ep, WindowPtr w));
  1577. XSTATIC void do_unclick _ARGS((EVENT *ep));
  1578. XSTATIC void do_drag _ARGS((WindowPtr w));
  1579. XSTATIC void do_grow _ARGS((EVENT *ep, WindowPtr w));
  1580. XSTATIC void do_goaway _ARGS((EVENT *ep, WindowPtr w));
  1581. XSTATIC void do_zoom _ARGS((EVENT *ep, WindowPtr w, int code));
  1582. XSTATIC void do_size _ARGS((EVENT *ep, WindowPtr w));
  1583. X
  1584. X# ifndef NO_STDIO
  1585. X/* Some applications (e.g., Python) want events passed to the stdio console.
  1586. X   They must call wsetstdio(1) before their first wgetevent() call. */
  1587. X
  1588. Xstatic int pass_to_stdio = 0;
  1589. X
  1590. Xvoid
  1591. Xwsetstdio(flag)
  1592. X    int flag;
  1593. X{
  1594. X    pass_to_stdio = flag;
  1595. X}
  1596. X#endif
  1597. X
  1598. Xstatic EVENT pushback= {WE_NULL};
  1599. X
  1600. Xvoid
  1601. Xwungetevent(ep)
  1602. X    EVENT *ep;
  1603. X{
  1604. X    pushback= *ep;
  1605. X}
  1606. X
  1607. Xstatic void
  1608. Xwwaitevent(ep, wait)
  1609. X    EVENT *ep;
  1610. X    bool wait;
  1611. X{
  1612. X    _wfreeclip();
  1613. X    if (pushback.type != WE_NULL) {
  1614. X        *ep= pushback;
  1615. X        pushback.type= WE_NULL;
  1616. X        return;
  1617. X    }
  1618. X    
  1619. X    if (_wmenuhilite) {
  1620. X        HiliteMenu(0);
  1621. X        _wmenuhilite= FALSE;
  1622. X    }
  1623. X    
  1624. X    if (active == NULL)
  1625. X        set_arrow();
  1626. X    
  1627. X    ep->type= WE_NULL;
  1628. X    ep->window= NULL;
  1629. X    
  1630. X    do {
  1631. X        if (!GetNextEvent(everyEvent, &e)) {
  1632. X            if (e.what == nullEvent) {
  1633. X                if (wait) do_idle(ep);
  1634. X                else return;
  1635. X            }
  1636. X        }
  1637. X        else {
  1638. X#ifndef NO_STDIO
  1639. X            /* Give THINK C stdio a chance to handle the event.
  1640. X               Unfortunately it also eats up clicks in
  1641. X               title bars, so, to save our Option-click feature,
  1642. X               we don't feed it those. */
  1643. X            if (pass_to_stdio &&
  1644. X                    !(e.what == mouseDown &&
  1645. X                      (e.modifiers & optionKey))) {
  1646. X                if (StdEvent(&e))
  1647. X                    continue;
  1648. X            }
  1649. X#endif
  1650. X            switch (e.what) {
  1651. X            case mouseDown:
  1652. X                do_mouse_down(ep);
  1653. X                break;
  1654. X            case mouseUp:
  1655. X                do_mouse_up(ep);
  1656. X                break;
  1657. X            case keyDown:
  1658. X            case autoKey:
  1659. X                do_key(ep);
  1660. X                break;
  1661. X            case updateEvt:
  1662. X                do_update(ep);
  1663. X                break;
  1664. X            case diskEvt:
  1665. X                do_disk(ep);
  1666. X                break;
  1667. X            case activateEvt:
  1668. X                do_activate(ep);
  1669. X                break;
  1670. X            }
  1671. X        }
  1672. X    } while (ep->type == WE_NULL);
  1673. X    
  1674. X    if (ep->window == NULL)
  1675. X        ep->window= whichwin(FrontWindow());
  1676. X    if (!_wm_down)
  1677. X        set_watch();
  1678. X}
  1679. X
  1680. Xint
  1681. Xwpollevent(ep)
  1682. X        EVENT *ep;
  1683. X{
  1684. X        ep->type = WE_NULL;
  1685. X        wwaitevent(ep, FALSE);
  1686. X        return ep->type != WE_NULL;
  1687. X}
  1688. X
  1689. Xvoid
  1690. Xwgetevent(ep)
  1691. X        EVENT *ep;
  1692. X{
  1693. X        wwaitevent(ep, TRUE);
  1694. X}
  1695. X
  1696. Xstatic void
  1697. Xdo_idle(ep)
  1698. X    EVENT *ep;
  1699. X{    
  1700. X    if (checktimer(ep))
  1701. X        return;
  1702. X    
  1703. X    if (_w_idle_proc != NULL)
  1704. X        (*_w_idle_proc)();
  1705. X    
  1706. X    /* The user idle proc may have called wungetevent: */
  1707. X    if (pushback.type != WE_NULL) {
  1708. X        *ep= pushback;
  1709. X        pushback.type= WE_NULL;
  1710. X        return;
  1711. X    }
  1712. X    
  1713. X    SystemTask();
  1714. X    
  1715. X    if (active != NULL) {
  1716. X        Point where;
  1717. X        Rect r;
  1718. X        
  1719. X        where= e.where;
  1720. X        SetPort(active->w);
  1721. X        GlobalToLocal(&where);
  1722. X        if (_wm_down) {
  1723. X            autoscroll(active, where.h, where.v);
  1724. X            make_mouse_event(ep, &where);
  1725. X            return;
  1726. X        }
  1727. X        getwinrect(active, &r);
  1728. X        if (PtInRect(PASSPOINT where, &r)) {
  1729. X            if (e.modifiers & optionKey)
  1730. X                set_hand();
  1731. X            else
  1732. X                set_applcursor();
  1733. X        }
  1734. X        else
  1735. X            set_arrow();
  1736. X        blinkcaret(active);
  1737. X    }
  1738. X}
  1739. X
  1740. Xstatic void
  1741. Xdo_update(ep)
  1742. X    EVENT *ep;
  1743. X{
  1744. X    WINDOW *win;
  1745. X    Rect r;
  1746. X    
  1747. X    win= whichwin((WindowPtr) e.message);
  1748. X    if (win == NULL) {
  1749. X        /* dprintf("update evt for alien window"); */
  1750. X        return;
  1751. X    }
  1752. X    _wupdate(win, &r);
  1753. X    if (win->drawproc == NULL && !EmptyRect(&r)) {
  1754. X        ep->type= WE_DRAW;
  1755. X        ep->window= win;
  1756. X        ep->u.area.left= r.left;
  1757. X        ep->u.area.top= r.top;
  1758. X        ep->u.area.right= r.right;
  1759. X        ep->u.area.bottom= r.bottom;
  1760. X    }
  1761. X}
  1762. X
  1763. Xstatic void
  1764. Xdo_mouse_down(ep)
  1765. X    EVENT *ep;
  1766. X{
  1767. X    WindowPtr w;
  1768. X    int code= FindWindow(PASSPOINT e.where, &w);
  1769. X    
  1770. X    /* XXX This doesn't look incredibly necessary:
  1771. X    if (active != NULL) {
  1772. X        SetPort(active->win);
  1773. X        rmcaret(active);
  1774. X    }
  1775. X    */
  1776. X    
  1777. X    if (code != inContent && code != inSysWindow)
  1778. X        set_arrow();
  1779. X    switch (code) {
  1780. X    case inMenuBar:
  1781. X        _wdo_menu(ep, MenuSelect(PASSPOINT e.where));    
  1782. X        break;
  1783. X    case inSysWindow:
  1784. X        SystemClick(&e, w);
  1785. X        break;
  1786. X    case inContent:
  1787. X        do_click(ep, w);
  1788. X        break;
  1789. X    case inDrag:
  1790. X        do_drag(w);
  1791. X        break;
  1792. X    case inGrow:
  1793. X        do_grow(ep, w);
  1794. X        break;
  1795. X    case inGoAway:
  1796. X        do_goaway(ep, w);
  1797. X        break;
  1798. X    case inZoomIn:
  1799. X    case inZoomOut:
  1800. X        do_zoom(ep, w, code);
  1801. X        break;
  1802. X    }
  1803. X}
  1804. X
  1805. Xstatic void
  1806. Xdo_mouse_up(ep)
  1807. X    EVENT *ep;
  1808. X{
  1809. X    do_unclick(ep);
  1810. X}
  1811. X
  1812. Xstatic void
  1813. Xdo_key(ep)
  1814. X    EVENT *ep;
  1815. X{
  1816. X    char c= e.message & charCodeMask;
  1817. X    
  1818. X    /* XXX shouldn't mess at all with non-stdwin windows */
  1819. X    
  1820. X    if (e.modifiers & cmdKey) {
  1821. X        if (c == '.') {
  1822. X            ep->type= WE_COMMAND;
  1823. X            ep->u.command= WC_CANCEL;
  1824. X        }
  1825. X        else
  1826. X            _wdo_menu(ep, MenuKey(c));
  1827. X    }
  1828. X    else {
  1829. X        ep->type= WE_COMMAND;
  1830. X        switch (c) {
  1831. X        
  1832. X        default:
  1833. X            ObscureCursor();
  1834. X            ep->type= WE_CHAR;
  1835. X            ep->u.character= c;
  1836. X            break;
  1837. X        
  1838. X        case LEFT_ARROW:
  1839. X        case RIGHT_ARROW:
  1840. X        case UP_ARROW:
  1841. X        case DOWN_ARROW:
  1842. X            ep->u.command= c-LEFT_ARROW + WC_LEFT;
  1843. X            break;
  1844. X        
  1845. X        case '\b':
  1846. X            ObscureCursor();
  1847. X            ep->u.command= WC_BACKSPACE;
  1848. X            break;
  1849. X        
  1850. X        case '\t':
  1851. X            ObscureCursor();
  1852. X            ep->u.command= WC_TAB;
  1853. X            break;
  1854. X        
  1855. X        case '\r':
  1856. X        case ENTER_KEY:
  1857. X            ep->u.command= WC_RETURN;
  1858. X            break;
  1859. X        
  1860. X        }
  1861. X    }
  1862. X}
  1863. X
  1864. Xstatic void
  1865. Xdo_disk(ep)
  1866. X    EVENT *ep;
  1867. X{
  1868. X    /* XXX Disk events not implemented -- who cares. */
  1869. X}
  1870. X
  1871. X/* XXX Need to be easier for cases where we seem to have missed events */
  1872. X
  1873. Xstatic void
  1874. Xdo_activate(ep)
  1875. X    EVENT *ep;
  1876. X{
  1877. X    WINDOW *win= whichwin((WindowPtr)e.message);
  1878. X    
  1879. X    if (win == NULL) {
  1880. X        /* dprintf("(de)activate evt for alien window"); */
  1881. X        return;
  1882. X    }
  1883. X    
  1884. X    if (e.modifiers & activeFlag) { /* Activation */
  1885. X        if (active != NULL) {
  1886. X            /* Perhaps reactivation after modal dialog */
  1887. X#ifdef NO_STDIO
  1888. X            /* But perhaps THINK C stdio is fooling us */
  1889. X            if (active == win)
  1890. X                return;
  1891. X            /* If we get here we've missed a
  1892. X               deactivate event... */
  1893. X            dprintf("activate without deactivate");
  1894. X#endif
  1895. X        }
  1896. X        activate(win);
  1897. X        ep->type= WE_ACTIVATE;
  1898. X        ep->window= active;
  1899. X    }
  1900. X    else { /* Deactivation */
  1901. X        if (win != active) {
  1902. X            /* Spurious deactivation event.
  1903. X               This always happens when we open
  1904. X               two or more windows without intervening
  1905. X               call to wgetevent().
  1906. X               Perhaps an conscious hack in the
  1907. X               ROM to "help" programs that believe
  1908. X               windows are created active? */
  1909. X            return;
  1910. X        }
  1911. X        ep->type= WE_DEACTIVATE;
  1912. X        ep->window= active;
  1913. X        deactivate();
  1914. X    }
  1915. X}
  1916. X
  1917. Xstatic void
  1918. Xdeactivate()
  1919. X{
  1920. X    SetPort(active->w);
  1921. X    rmcaret(active);
  1922. X    hidescrollbars(active);
  1923. X    rmlocalmenus(active);
  1924. X    DrawGrowIcon(active->w);
  1925. X    active= NULL;
  1926. X    set_arrow();
  1927. X}
  1928. X
  1929. Xstatic void
  1930. Xactivate(win)
  1931. X    WINDOW *win;
  1932. X{
  1933. X    if (active != NULL)
  1934. X        deactivate();
  1935. X    if (win != NULL) {
  1936. X        SetPort(win->w);
  1937. X        active= win;
  1938. X        showscrollbars(win);
  1939. X        addlocalmenus(active);
  1940. X        valid_border(win->w); /* Avoid flicker when window pops up */
  1941. X    }
  1942. X}
  1943. X
  1944. Xstatic void
  1945. Xdo_click(ep, w)
  1946. X    EVENT *ep;
  1947. X    WindowPtr w;
  1948. X{
  1949. X    WINDOW *win= whichwin(w);
  1950. X    Point where;
  1951. X    int pcode;
  1952. X    ControlHandle bar;
  1953. X    
  1954. X    if (win == NULL) {
  1955. X        /* dprintf("click in alien window"); */
  1956. X        return;
  1957. X    }
  1958. X    if (win != active) {
  1959. X        set_arrow();
  1960. X        if (e.modifiers & optionKey) {
  1961. X            /* Option-click sends a window behind. */
  1962. X            SendBehind(w, (WindowPtr) NULL);
  1963. X        }
  1964. X        else
  1965. X            SelectWindow(win->w);
  1966. X        return;
  1967. X        /* Let activate events do the rest. */
  1968. X    }
  1969. X    where= e.where;
  1970. X    SetPort(win->w);
  1971. X    GlobalToLocal(&where);
  1972. X    pcode= FindControl(PASSPOINT where, w, &bar);
  1973. X    if (pcode != 0) {
  1974. X        set_arrow();
  1975. X        do_scroll(&where, win, bar, pcode);
  1976. X    }
  1977. X    else {
  1978. X        Rect r;
  1979. X        
  1980. X        getwinrect(win, &r);
  1981. X        if (PtInRect(PASSPOINT where, &r)) {
  1982. X            if (e.modifiers & optionKey) {
  1983. X                set_hand();
  1984. X                dragscroll(win,
  1985. X                    where.h, where.v,
  1986. X                    e.modifiers & shiftKey);
  1987. X            }
  1988. X            else {
  1989. X                set_applcursor();
  1990. X                make_mouse_event(ep, &where);
  1991. X            }
  1992. X        }
  1993. X    }
  1994. X}
  1995. X
  1996. Xstatic void
  1997. Xdo_unclick(ep)
  1998. X    EVENT *ep;
  1999. X{
  2000. X    if (active != NULL) {
  2001. X        Point where;
  2002. X        
  2003. X        where= e.where;
  2004. X        SetPort(active->w);
  2005. X        GlobalToLocal(&where);
  2006. X        make_mouse_event(ep, &where);
  2007. X    }
  2008. X}
  2009. X
  2010. Xstatic void
  2011. Xdo_drag(w)
  2012. X    WindowPtr w;
  2013. X{
  2014. X    if (e.modifiers & optionKey) {
  2015. X        /* Nonstandard: option-click sends a window behind. */
  2016. X        SendBehind(w, (WindowPtr) NULL);
  2017. X    }
  2018. X    else {
  2019. X        Rect r;
  2020. X        
  2021. X        r= screen->portRect;
  2022. X        r.top += MENUBARHEIGHT;
  2023. X        InsetRect(&r, 4, 4);
  2024. X        DragWindow(w, PASSPOINT e.where, &r);
  2025. X    }
  2026. X}
  2027. X
  2028. Xstatic void
  2029. Xdo_grow(ep, w)
  2030. X    EVENT *ep;
  2031. X    WindowPtr w;
  2032. X{
  2033. X    Rect r;
  2034. X    long reply;
  2035. X    
  2036. X    /* XXX shouldn't mess at all with non-stdwin windows */
  2037. X    
  2038. X    /* Set minimal window size */
  2039. X    r.left= LSLOP + MIN_WIDTH + RSLOP + BAR;
  2040. X    r.top= MIN_HEIGHT + BAR;
  2041. X    
  2042. X    /* The max size is derived from the document size.
  2043. X       If there is no document size, it is unlimited.
  2044. X       (There is nothing wrong with windows larger than
  2045. X       the screen, really.) */
  2046. X    r.right = r.bottom = 0x7fff;
  2047. X    {
  2048. X        /* Max size restriction based on doc size, if specified */
  2049. X        WINDOW *win = whichwin(w);
  2050. X        int docwidth = win->docwidth;
  2051. X        int docheight = win->docheight;
  2052. X        if (win->docwidth > 0) {
  2053. X            CLIPMIN(docwidth, MIN_WIDTH);
  2054. X            r.right = LSLOP + docwidth + RSLOP + BAR + 1;
  2055. X        }
  2056. X        if (win->docheight > 0) {
  2057. X            CLIPMIN(docheight, MIN_HEIGHT);
  2058. X            r.bottom = docheight + BAR + 1;
  2059. X        }
  2060. X        /* For some reason 1 has to be added.  Sigh. */
  2061. X    }
  2062. X    
  2063. X    reply= GrowWindow(w, PASSPOINT e.where, &r);
  2064. X    if (reply != 0) {
  2065. X        SetPort(w);
  2066. X        inval_border(w);
  2067. X        SizeWindow(w, LoWord(reply), HiWord(reply), TRUE);
  2068. X        do_size(ep, w);
  2069. X    }
  2070. X}
  2071. X
  2072. Xstatic void
  2073. Xdo_goaway(ep, w)
  2074. X    EVENT *ep;
  2075. X    WindowPtr w;
  2076. X{
  2077. X    /* XXX shouldn't mess at all with non-stdwin windows */
  2078. X    
  2079. X    if (TrackGoAway(w, PASSPOINT e.where)) {
  2080. X        ep->type= WE_COMMAND;
  2081. X        ep->window= whichwin(w);
  2082. X        ep->u.command= WC_CLOSE;
  2083. X    }
  2084. X}
  2085. X
  2086. Xstatic void
  2087. Xdo_zoom(ep, w, code)
  2088. X    EVENT *ep;
  2089. X    WindowPtr w;
  2090. X    int code;
  2091. X{
  2092. X    /* XXX shouldn't mess at all with non-stdwin windows */
  2093. X    
  2094. X    /* This code will never be reached on a machine
  2095. X       with old (64K) ROMs, because FindWindow will
  2096. X       never return inZoomIn or inZoomOut.
  2097. X       Therefore, no check for new ROMs is necessary.
  2098. X       A warning in Inside Macintosh IV says that
  2099. X       it is necessary to make the zoomed window
  2100. X       the current GrafPort before calling ZoomWindow.
  2101. X       True enough, it fails spectacularly otherwise,
  2102. X       but still this looks like a bug to me - there
  2103. X       are no similar requirements for SizeWindow
  2104. X       or DragWindow. */
  2105. X    
  2106. X    SetPort(w);
  2107. X    if (TrackBox(w, PASSPOINT e.where, code)) {
  2108. X        inval_border(w);
  2109. X        ZoomWindow(w, code, TRUE);
  2110. X        do_size(ep, w);
  2111. X    }
  2112. X}
  2113. X
  2114. X/* do_size assumes w is already the current grafport */
  2115. X
  2116. Xstatic void
  2117. Xdo_size(ep, w)
  2118. X    EVENT *ep;
  2119. X    WindowPtr w;
  2120. X{
  2121. X    WINDOW *win= whichwin(w);
  2122. X    
  2123. X    if (win == NULL) {
  2124. X        /* dprintf("alien window resized"); */
  2125. X        return;
  2126. X    }
  2127. X    inval_border(w);
  2128. X    movescrollbars(win);
  2129. X    ep->type= WE_SIZE;
  2130. X    ep->window= win;
  2131. X    _wfixorigin(win);
  2132. X}
  2133. X
  2134. Xvoid
  2135. Xinval_border(w)
  2136. X    WindowPtr w;
  2137. X{
  2138. X    Rect r;
  2139. X    
  2140. X    r= w->portRect;
  2141. X    r.left= r.right - BAR;
  2142. X    InvalRect(&r);
  2143. X    r= w->portRect;
  2144. X    r.top= r.bottom - BAR;
  2145. X    InvalRect(&r);
  2146. X}
  2147. X
  2148. Xvoid
  2149. Xvalid_border(w)
  2150. X    WindowPtr w;
  2151. X{
  2152. X    Rect r;
  2153. X    
  2154. X    r= w->portRect;
  2155. X    r.left= r.right - BAR;
  2156. X    ValidRect(&r);
  2157. X    r= w->portRect;
  2158. X    r.top= r.bottom - BAR;
  2159. X    ValidRect(&r);
  2160. X}
  2161. X
  2162. X/* Variables needed in click and move detection. */
  2163. X
  2164. Xstatic int m_h, m_v;        /* Doc. coord. of last mouse evt. */
  2165. Xstatic long m_when;        /* TickCount of last mouse evt. */
  2166. Xstatic int m_clicks;        /* N-fold click stage */
  2167. Xstatic int m_button;        /* Which 'button';
  2168. X                   1=normal, 2=shift, 3=command. */
  2169. X
  2170. Xstatic void
  2171. Xmake_mouse_event(ep, pwhere)
  2172. X    EVENT *ep;
  2173. X    Point *pwhere;        /* Mouse pos. in local coord. */
  2174. X{
  2175. X    WINDOW *win= active;
  2176. X    int h= pwhere->h + win->orgh;
  2177. X    int v= pwhere->v + win->orgv;
  2178. X    int dh= h - m_h;
  2179. X    int dv= v - m_v;
  2180. X    
  2181. X    if (dh*dh + dv*dv > CLICK_DIST*CLICK_DIST)
  2182. X        m_clicks= 0;    /* Moved too much for a click */
  2183. X    
  2184. X    if (e.what == mouseDown) {
  2185. X        if (e.when > m_when + GetDblTime())
  2186. X            m_clicks= 1;
  2187. X        else
  2188. X            ++m_clicks;
  2189. X        ep->type= WE_MOUSE_DOWN;
  2190. X        _wm_down= TRUE;
  2191. X        /* XXX Should swap buttons 2 & 3 (also in textedit)
  2192. X           since X11 (e.g., xterm) uses button 3 for extend */
  2193. X        m_button= (e.modifiers & cmdKey) ? 3 :
  2194. X            (e.modifiers & shiftKey) ? 2 : 1;
  2195. X    }
  2196. X    else if (e.what == mouseUp) {
  2197. X        if (!_wm_down)
  2198. X            return;
  2199. X        ep->type= WE_MOUSE_UP;
  2200. X        _wm_down= FALSE;
  2201. X    }
  2202. X    else {
  2203. X        if (!_wm_down || m_clicks > 0 || (dh == 0 && dv == 0))
  2204. X            return;
  2205. X        ep->type= WE_MOUSE_MOVE;
  2206. X    }
  2207. X    ep->u.where.h= m_h= h;
  2208. X    ep->u.where.v= m_v= v;
  2209. X    ep->u.where.clicks= m_clicks;
  2210. X    ep->u.where.button= m_button;
  2211. X    ep->u.where.mask= (ep->type == WE_MOUSE_UP) ? 0 : 1;
  2212. X    ep->window= win;
  2213. X    m_when= e.when;
  2214. X}
  2215. X
  2216. X/* Reset the mouse state.
  2217. X   Called when a dialog is started. */
  2218. X
  2219. Xvoid
  2220. X_wresetmouse()
  2221. X{
  2222. X    _wm_down= FALSE;
  2223. X}
  2224. END_OF_FILE
  2225. if test 12997 -ne `wc -c <'Ports/mac/event.c'`; then
  2226.     echo shar: \"'Ports/mac/event.c'\" unpacked with wrong size!
  2227. fi
  2228. # end of 'Ports/mac/event.c'
  2229. fi
  2230. if test -f 'Ports/mac/menu.h' -a "${1}" != "-c" ; then 
  2231.   echo shar: Will not clobber existing file \"'Ports/mac/menu.h'\"
  2232. else
  2233. echo shar: Extracting \"'Ports/mac/menu.h'\" \(354 characters\)
  2234. sed "s/^X//" >'Ports/mac/menu.h' <<'END_OF_FILE'
  2235. X/* MAC STDWIN -- MENU DEFINITIONS. */
  2236. X
  2237. X/* Note -- struct menu isn't defined here.
  2238. X   MENU * is taken to be equivalent to MenuPtr, whenever appropriate.
  2239. X   I know this is a hack -- I'll fix it later. */
  2240. X
  2241. Xstruct menubar {
  2242. X    int nmenus;        /* Number of menus in the list */
  2243. X    MENU **menulist;    /* Pointer to list of MENU pointers */
  2244. X};
  2245. X
  2246. X#define APPLE_MENU 32000
  2247. END_OF_FILE
  2248. if test 354 -ne `wc -c <'Ports/mac/menu.h'`; then
  2249.     echo shar: \"'Ports/mac/menu.h'\" unpacked with wrong size!
  2250. fi
  2251. # end of 'Ports/mac/menu.h'
  2252. fi
  2253. echo shar: End of archive 8 \(of 19\).
  2254. cp /dev/null ark8isdone
  2255. MISSING=""
  2256. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  2257.     if test ! -f ark${I}isdone ; then
  2258.     MISSING="${MISSING} ${I}"
  2259.     fi
  2260. done
  2261. if test "${MISSING}" = "" ; then
  2262.     echo You have unpacked all 19 archives.
  2263.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2264. else
  2265.     echo You still need to unpack the following archives:
  2266.     echo "        " ${MISSING}
  2267. fi
  2268. ##  End of shell archive.
  2269. exit 0
  2270.