PageRenderTime 25ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/tags/rxvt-2-7-1/src/graphics.c

#
C | 547 lines | 398 code | 67 blank | 82 comment | 122 complexity | 17116652f9914d685d295047c227136d MD5 | raw file
  1. /*--------------------------------*-C-*---------------------------------*
  2. * File: graphics.c
  3. *----------------------------------------------------------------------*
  4. * $Id: graphics.c 674 1999-09-25 15:53:45Z mason $
  5. *
  6. * All portions of code are copyright by their respective author/s.
  7. * Copyright (C) 1994 Rob Nation <nation@rocket.sanders.lockheed.com>
  8. * - original version
  9. * Copyright (C) 1997 Raul Garcia Garcia <rgg@tid.es>
  10. * Copyright (C) 1997,1998 mj olesen <olesen@me.queensu.ca>
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. *----------------------------------------------------------------------*/
  26. #include "../config.h" /* NECESSARY */
  27. #ifdef RXVT_GRAPHICS
  28. #include "rxvt.h" /* NECESSARY */
  29. typedef struct grwin_t {
  30. Window win;
  31. int x, y;
  32. unsigned int w, h;
  33. short screen;
  34. grcmd_t *graphics;
  35. struct grwin_t *prev, *next;
  36. } grwin_t;
  37. #include "graphics.intpro" /* PROTOS for internal routines */
  38. #include <X11/cursorfont.h>
  39. /* commands:
  40. * 'C' = Clear
  41. * 'F' = Fill
  42. * 'G' = Geometry
  43. * 'L' = Line
  44. * 'P' = Points
  45. * 'T' = Text
  46. * 'W' = Window
  47. */
  48. #ifndef GRX_SCALE
  49. # define GRX_SCALE 10000
  50. #endif
  51. static int graphics_up = 0;
  52. static grwin_t *gr_root = NULL;
  53. /*----------------------------------------------------------------------*
  54. * local functions
  55. */
  56. /* ARGSUSED */
  57. /* INTPROTO */
  58. void
  59. Gr_NewWindow(int nargs, int args[])
  60. {
  61. int x, y;
  62. unsigned int w, h;
  63. Window win;
  64. grwin_t *grwin;
  65. Cursor cursor;
  66. if (nargs != 4) {
  67. print_error("NewWindow: 4 args needed, got %d\n", nargs);
  68. return;
  69. }
  70. x = args[0] * TermWin.width / GRX_SCALE + BORDERWIDTH;
  71. y = args[1] * TermWin.height / GRX_SCALE + BORDERWIDTH;
  72. w = args[2] * TermWin.width / GRX_SCALE;
  73. h = args[3] * TermWin.height / GRX_SCALE;
  74. win = XCreateSimpleWindow(Xdisplay, TermWin.vt,
  75. x, y, w, h,
  76. 0,
  77. PixColors[Color_fg],
  78. PixColors[Color_bg]);
  79. cursor = XCreateFontCursor(Xdisplay, XC_crosshair);
  80. XDefineCursor(Xdisplay, win, cursor);
  81. XMapWindow(Xdisplay, win);
  82. XSelectInput(Xdisplay, win, ExposureMask);
  83. grwin = (grwin_t *) MALLOC(sizeof(grwin_t));
  84. grwin->win = win;
  85. grwin->x = x;
  86. grwin->y = y;
  87. grwin->w = w;
  88. grwin->h = h;
  89. grwin->screen = 0;
  90. grwin->prev = NULL;
  91. grwin->next = gr_root;
  92. if (grwin->next)
  93. grwin->next->prev = grwin;
  94. gr_root = grwin;
  95. grwin->graphics = NULL;
  96. graphics_up++;
  97. tt_printf("\033W%ld\n", (long)grwin->win);
  98. }
  99. /* ARGSUSED */
  100. /* INTPROTO */
  101. void
  102. Gr_ClearWindow(grwin_t *grwin)
  103. {
  104. grcmd_t *cmd, *next;
  105. for (cmd = grwin->graphics; cmd != NULL; cmd = next) {
  106. next = cmd->next;
  107. free(cmd->coords);
  108. if (cmd->text != NULL)
  109. free(cmd->text);
  110. free(cmd);
  111. }
  112. grwin->graphics = NULL;
  113. XClearWindow(Xdisplay, grwin->win);
  114. }
  115. /*
  116. * arg [0] = x
  117. * arg [1] = y
  118. * arg [2] = alignment
  119. * arg [3] = strlen (text)
  120. */
  121. /* ARGSUSED */
  122. /* INTPROTO */
  123. void
  124. Gr_Text(grwin_t *grwin, grcmd_t *data)
  125. {
  126. int x, y, align;
  127. if (data->ncoords < 4 || data->text == NULL || *(data->text) == '\0')
  128. return;
  129. x = data->coords[0] * grwin->w / GRX_SCALE;
  130. y = data->coords[1] * grwin->h / GRX_SCALE;
  131. align = data->coords[2];
  132. if (align & RIGHT_TEXT)
  133. x -= XTextWidth(TermWin.font, data->text, data->coords[3]);
  134. else if (align & HCENTER_TEXT)
  135. x -= (XTextWidth(TermWin.font, data->text, data->coords[3]) >> 1);
  136. if (align & TOP_TEXT)
  137. y += TermWin.font->ascent;
  138. else if (align & BOTTOM_TEXT)
  139. y -= TermWin.font->descent;
  140. if (align & VCENTER_TEXT)
  141. y -= TermWin.font->descent
  142. + ((TermWin.font->ascent + TermWin.font->descent) >> 1);
  143. if (align & VCAPS_CENTER_TEXT)
  144. y += (TermWin.font->ascent >> 1);
  145. XPMClearArea(Xdisplay, grwin->win, x, y, Width2Pixel(data->coords[3]),
  146. Height2Pixel(1), 0);
  147. XDrawString(Xdisplay, grwin->win, TermWin.gc, x, y,
  148. data->text, data->coords[3]);
  149. }
  150. /* ARGSUSED */
  151. /* INTPROTO */
  152. void
  153. Gr_Geometry(grwin_t *grwin, grcmd_t *data)
  154. {
  155. if (grwin)
  156. tt_printf("\033G%ld %d %d %u %u %d %d %ld %ld %d\n",
  157. (long)grwin->win,
  158. grwin->x, grwin->y, grwin->w, grwin->h,
  159. TermWin.fwidth,
  160. TermWin.fheight,
  161. (long)GRX_SCALE * TermWin.fwidth / grwin->w,
  162. (long)GRX_SCALE * TermWin.fheight / grwin->h,
  163. Xdepth);
  164. else /* rxvt terminal window size */
  165. tt_printf("\033G0 0 0 %d %d %d %d %ld %ld %d\n",
  166. TermWin.width - 2 * BORDERWIDTH,
  167. TermWin.height - 2 * BORDERWIDTH,
  168. TermWin.fwidth,
  169. TermWin.fheight,
  170. (long)GRX_SCALE * TermWin.fwidth
  171. / (TermWin.width - 2 * BORDERWIDTH),
  172. (long)GRX_SCALE * TermWin.fheight
  173. / (TermWin.height - 2 * BORDERWIDTH),
  174. Xdepth);
  175. }
  176. /* ARGSUSED */
  177. /* INTPROTO */
  178. void
  179. Gr_DestroyWindow(grwin_t *grwin)
  180. {
  181. grcmd_t *cmd, *next;
  182. if (grwin == NULL)
  183. return;
  184. for (cmd = grwin->graphics; cmd; cmd = next) {
  185. next = cmd->next;
  186. free(cmd->coords);
  187. if (cmd->text != NULL)
  188. free(cmd->text);
  189. free(cmd);
  190. }
  191. XDestroyWindow(Xdisplay, grwin->win);
  192. if (grwin->next != NULL)
  193. grwin->next->prev = grwin->prev;
  194. if (grwin->prev != NULL)
  195. grwin->prev->next = grwin->next;
  196. else
  197. gr_root = grwin->next;
  198. free(grwin);
  199. graphics_up--;
  200. }
  201. /* ARGSUSED */
  202. /* INTPROTO */
  203. void
  204. Gr_Dispatch(grwin_t *grwin, grcmd_t *data)
  205. {
  206. int i, n;
  207. union {
  208. XPoint pt[NGRX_PTS / 2];
  209. XRectangle rect[NGRX_PTS / 4];
  210. } xdata;
  211. if (data->color != Color_fg) {
  212. XGCValues gcv;
  213. gcv.foreground = PixColors[data->color];
  214. XChangeGC(Xdisplay, TermWin.gc, GCForeground, &gcv);
  215. }
  216. if (grwin)
  217. switch (data->cmd) {
  218. case 'L':
  219. if (data->ncoords > 3) {
  220. for (n = i = 0; i < data->ncoords; i += 2, n++) {
  221. xdata.pt[n].x = data->coords[i] * grwin->w / GRX_SCALE;
  222. xdata.pt[n].y = data->coords[i + 1] * grwin->h / GRX_SCALE;
  223. }
  224. XDrawLines(Xdisplay,
  225. grwin->win, TermWin.gc, xdata.pt, n, CoordModeOrigin);
  226. }
  227. break;
  228. case 'P':
  229. if (data->ncoords > 3) {
  230. for (n = i = 0; i < data->ncoords; i += 2, n++) {
  231. xdata.pt[n].x = data->coords[i] * grwin->w / GRX_SCALE;
  232. xdata.pt[n].y = data->coords[i + 1] * grwin->h / GRX_SCALE;
  233. }
  234. XDrawPoints(Xdisplay,
  235. grwin->win, TermWin.gc, xdata.pt, n, CoordModeOrigin);
  236. }
  237. break;
  238. case 'F':
  239. if (data->ncoords > 0) {
  240. for (n = i = 0; i < data->ncoords; i += 4, n++) {
  241. xdata.rect[n].x = data->coords[i] * grwin->w / GRX_SCALE;
  242. xdata.rect[n].y = data->coords[i + 1] * grwin->h
  243. / GRX_SCALE;
  244. xdata.rect[n].width = ((data->coords[i + 2]
  245. - data->coords[i] + 1) *
  246. grwin->w / GRX_SCALE);
  247. xdata.rect[n].height = ((data->coords[i + 3]
  248. - data->coords[i + 1] + 1) *
  249. grwin->h / GRX_SCALE);
  250. XPMClearArea(Xdisplay, grwin->win,
  251. xdata.rect[n].x, xdata.rect[n].y,
  252. xdata.rect[n].width, xdata.rect[n].height,
  253. 0);
  254. }
  255. XFillRectangles(Xdisplay, grwin->win, TermWin.gc, xdata.rect,
  256. n);
  257. }
  258. break;
  259. case 'T':
  260. Gr_Text(grwin, data);
  261. break;
  262. case 'C':
  263. Gr_ClearWindow(grwin);
  264. break;
  265. }
  266. if (data->color != Color_fg) {
  267. XGCValues gcv;
  268. gcv.foreground = PixColors[Color_fg];
  269. XChangeGC(Xdisplay, TermWin.gc, GCForeground, &gcv);
  270. }
  271. }
  272. /* ARGSUSED */
  273. /* INTPROTO */
  274. void
  275. Gr_Redraw(grwin_t *grwin)
  276. {
  277. grcmd_t *cmd;
  278. for (cmd = grwin->graphics; cmd != NULL; cmd = cmd->next)
  279. Gr_Dispatch(grwin, cmd);
  280. }
  281. /*----------------------------------------------------------------------*
  282. * end of static functions
  283. */
  284. /* ARGSUSED */
  285. /* EXTPROTO */
  286. void
  287. Gr_ButtonReport(int but, int x, int y)
  288. {
  289. grwin_t *grwin;
  290. for (grwin = gr_root; grwin != NULL; grwin = grwin->next)
  291. if ((x > grwin->x)
  292. && (y > grwin->y)
  293. && (x < grwin->x + grwin->w)
  294. && (y < grwin->y + grwin->h))
  295. break;
  296. if (grwin == NULL)
  297. return;
  298. x = GRX_SCALE * (x - grwin->x) / grwin->w;
  299. y = GRX_SCALE * (y - grwin->y) / grwin->h;
  300. tt_printf("\033%c%ld;%d;%d;\n", but, (long)grwin->win, x, y);
  301. }
  302. /* ARGSUSED */
  303. /* EXTPROTO */
  304. void
  305. Gr_do_graphics(int cmd, int nargs, int args[], unsigned char *text)
  306. {
  307. static Window last_id = None;
  308. long win_id;
  309. grwin_t *grwin;
  310. grcmd_t *newcmd, *oldcmd;
  311. int i;
  312. if (cmd == 'W') {
  313. Gr_NewWindow(nargs, args);
  314. return;
  315. }
  316. win_id = (nargs > 0) ? (Window) args[0] : None;
  317. if ((cmd == 'G') && (win_id == None)) {
  318. Gr_Geometry(NULL, NULL);
  319. return;
  320. }
  321. if ((win_id == None) && (last_id != None))
  322. win_id = last_id;
  323. if (win_id == None)
  324. return;
  325. grwin = gr_root;
  326. while ((grwin != NULL) && (grwin->win != win_id))
  327. grwin = grwin->next;
  328. if (grwin == NULL)
  329. return;
  330. if (cmd == 'G') {
  331. Gr_Geometry(grwin, NULL);
  332. return;
  333. }
  334. nargs--;
  335. args++; /* skip over window id */
  336. /* record this new command */
  337. newcmd = (grcmd_t *) MALLOC(sizeof(grcmd_t));
  338. newcmd->ncoords = nargs;
  339. newcmd->coords = (int *)MALLOC((newcmd->ncoords * sizeof(int)));
  340. newcmd->next = NULL;
  341. newcmd->cmd = cmd;
  342. newcmd->color = scr_get_fgcolor();
  343. newcmd->text = text;
  344. for (i = 0; i < newcmd->ncoords; i++)
  345. newcmd->coords[i] = args[i];
  346. /*
  347. * If newcmd == fill, and rectangle is full window, drop all prior
  348. * commands.
  349. */
  350. if ((newcmd->cmd == 'F') && (grwin) && (grwin->graphics)) {
  351. for (i = 0; i < newcmd->ncoords; i += 4) {
  352. if ((newcmd->coords[i] == 0)
  353. && (newcmd->coords[i + 1] == 0)
  354. && (newcmd->coords[i + 2] == GRX_SCALE)
  355. && (newcmd->coords[i + 3] == GRX_SCALE)) {
  356. /* drop previous commands */
  357. oldcmd = grwin->graphics;
  358. while (oldcmd->next != NULL) {
  359. grcmd_t *tmp = oldcmd;
  360. oldcmd = oldcmd->next;
  361. free(tmp);
  362. }
  363. grwin->graphics = NULL;
  364. }
  365. }
  366. }
  367. /* insert new command into command list */
  368. oldcmd = grwin->graphics;
  369. if (oldcmd == NULL)
  370. grwin->graphics = newcmd;
  371. else {
  372. while (oldcmd->next != NULL)
  373. oldcmd = oldcmd->next;
  374. oldcmd->next = newcmd;
  375. }
  376. Gr_Dispatch(grwin, newcmd);
  377. }
  378. /* ARGSUSED */
  379. /* EXTPROTO */
  380. void
  381. Gr_scroll(int count)
  382. {
  383. static short prev_start = 0;
  384. grwin_t *grwin, *next;
  385. if ((count == 0) && (prev_start == TermWin.view_start))
  386. return;
  387. prev_start = TermWin.view_start;
  388. for (grwin = gr_root; grwin != NULL; grwin = next) {
  389. next = grwin->next;
  390. grwin->y -= (count * TermWin.fheight);
  391. if ((grwin->y + grwin->h) < -(TermWin.saveLines * TermWin.fheight))
  392. Gr_DestroyWindow(grwin);
  393. else
  394. XMoveWindow(Xdisplay, grwin->win,
  395. grwin->x,
  396. grwin->y + (TermWin.view_start * TermWin.fheight));
  397. }
  398. }
  399. /* EXTPROTO */
  400. void
  401. Gr_ClearScreen(void)
  402. {
  403. grwin_t *grwin, *next;
  404. for (grwin = gr_root; grwin != NULL; grwin = next) {
  405. next = grwin->next;
  406. if ((grwin->screen == 0) && (grwin->y + grwin->h > 0)) {
  407. if (grwin->y >= 0)
  408. Gr_DestroyWindow(grwin);
  409. else
  410. XResizeWindow(Xdisplay, grwin->win,
  411. grwin->w, -grwin->y);
  412. }
  413. }
  414. }
  415. /* EXTPROTO */
  416. void
  417. Gr_ChangeScreen(void)
  418. {
  419. grwin_t *grwin, *next;
  420. for (grwin = gr_root; grwin != NULL; grwin = next) {
  421. next = grwin->next;
  422. if (grwin->y + grwin->h > 0) {
  423. if (grwin->screen == 1) {
  424. XMapWindow(Xdisplay, grwin->win);
  425. grwin->screen = 0;
  426. } else {
  427. XUnmapWindow(Xdisplay, grwin->win);
  428. grwin->screen = 1;
  429. }
  430. }
  431. }
  432. }
  433. /* ARGSUSED */
  434. /* EXTPROTO */
  435. void
  436. Gr_expose(Window win)
  437. {
  438. grwin_t *grwin;
  439. for (grwin = gr_root; grwin != NULL; grwin = grwin->next) {
  440. if (grwin->win == win) {
  441. Gr_Redraw(grwin);
  442. break;
  443. }
  444. }
  445. }
  446. /* ARGSUSED */
  447. /* EXTPROTO */
  448. void
  449. Gr_Resize(int w, int h)
  450. {
  451. grwin_t *grwin;
  452. for (grwin = gr_root; grwin != NULL; grwin = grwin->next) {
  453. if (TermWin.height != h) {
  454. grwin->y += (TermWin.height - h);
  455. XMoveWindow(Xdisplay, grwin->win,
  456. grwin->x,
  457. grwin->y + (TermWin.view_start * TermWin.fheight));
  458. }
  459. Gr_Redraw(grwin);
  460. }
  461. }
  462. /* EXTPROTO */
  463. void
  464. Gr_reset(void)
  465. {
  466. grwin_t *grwin, *next;
  467. for (grwin = gr_root; grwin != NULL; grwin = next) {
  468. next = grwin->next;
  469. Gr_DestroyWindow(grwin);
  470. }
  471. graphics_up = 0;
  472. }
  473. /* EXTPROTO */
  474. int
  475. Gr_Displayed(void)
  476. {
  477. return graphics_up;
  478. }
  479. #endif
  480. /*----------------------- end-of-file (C source) -----------------------*/