magicpoint-1.10a.tar.gz (MirPorts)
[alioth/magicpoint.git] / plist.c
1 /*
2  * Copyright (C) 1997 and 1998 WIDE Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. Neither the name of the project nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 /*
29  * $Id: plist.c,v 1.23 2003/05/19 07:29:45 nishida Exp $
30  */
31
32 #include "mgp.h"
33
34 #define PL_X_MARGIN     10
35
36 static Window pl_titlewin = None;
37 static Window pg_win = None;
38 static Pixmap pg_tmp;
39 static int pg_lastpage = -1;
40 static struct ctrl *pg_lastcp = NULL;
41
42 static int draw_kstring __P((Drawable, char *, int, int));
43
44 /*
45  * Display Page List at the bottom of the window
46  */
47
48 void
49 pl_on(state)
50         struct render_state *state;
51 {
52         XSetWindowAttributes wattr;
53         int i, ny, pl_x;
54         u_int pl_nx, pl_ny, pl_y;
55
56         if (pl_titlewin || !plfs)
57                 return;
58
59         /* number of pages in x-axis */
60         pl_nx = (window_width - 2 * PL_X_MARGIN) / pl_fw / 3;
61         /* number of pages in y-axis */
62         pl_ny = maxpage / pl_nx + 1;
63         /* page list coordinate */
64         pl_x = PL_X_MARGIN;
65         /* keep 5 for timebar*/ 
66         pl_y = window_height - (pl_ny + 1) * pl_fh - (t_fin ? 5 : 0);
67         pl_titlewin = XCreateSimpleWindow(display, window,
68                 0, pl_y - pl_fh, window_width, pl_fh, 0,
69                 BlackPixel(display, 0), back_color[caching]);
70         XSelectInput(display, pl_titlewin, StructureNotifyMask);
71
72         for (i = 1; i <= maxpage; i++) {
73                 ny = (i - 1) / pl_nx;
74                 plwin[i] = XCreateSimpleWindow(display, window,
75                         pl_x + 3 * ((i - 1) % pl_nx) * pl_fw,
76                         pl_y + pl_fh * ny,
77                         3 * pl_fw, pl_fh, 0,
78                         BlackPixel(display, 0), WhitePixel(display, 0));
79                 wattr.do_not_propagate_mask =
80                         ButtonPressMask|ButtonReleaseMask;
81                 XChangeWindowAttributes(display, plwin[i],
82                         CWDontPropagate, &wattr);
83                 XSelectInput(display, plwin[i],
84                         ButtonPressMask|EnterWindowMask|
85                         LeaveWindowMask|StructureNotifyMask);
86         }
87
88         XMapSubwindows(display, window);
89         for (i = 1; i <= maxpage; i++)
90                 pl_pdraw(state, i, gc_pl);
91 }
92
93 /*
94  * Turn off the page list
95  */
96 void
97 pl_off(state)
98         struct render_state *state;
99 {
100         int i;
101
102         if (!pl_titlewin)
103                 return;
104         XUnmapSubwindows(display, window);
105         XDestroyWindow(display, pl_titlewin);
106         pl_titlewin = None;
107         for (i = 1; i <= maxpage; i++) {
108                 XDestroyWindow(display, plwin[i]);
109                 plwin[i] = None;
110         }
111         XMapSubwindows(display, window);
112         XFlush(display);
113 }
114
115 /*
116  * Draw page numbers in each small window
117  * Enbold the current page
118  */
119 void
120 pl_pdraw(state, i, gc)
121         struct render_state *state;
122         int i;
123         GC gc;
124 {
125         char buf[10];
126
127         if (!pl_titlewin)
128                 return;
129
130         sprintf(buf, "%02d", i % 100);
131         XDrawImageString(display, plwin[i], gc, (int)(pl_fw / 2),
132                 (int)(pl_fh / 1.2), buf, 2);
133         if (i == state->page)
134                 XDrawString(display, plwin[i], gc, (int)(pl_fw / 2) + 1,
135                         (int)(pl_fh / 1.2), buf, 2);
136 }
137
138 /*
139  * Show the title of the page when the mouse enters a window.
140  * Turn it off if the page number is zero.
141  */
142 void
143 pl_title(page)
144         u_int page;
145 {
146         char buf[BUFSIZ];
147
148         if (!pl_titlewin)
149                 return;
150
151         XClearArea(display, pl_titlewin, 0, 0, window_width, pl_fh, 0);
152         if (page == 0)
153                 return;
154         sprintf(buf, "page %d: %s", page, page_title(page));
155         XSetForeground(display, gc_pta, ctrl_color[caching]);
156         XSetForeground(display, gc_ptk, ctrl_color[caching]);
157         XSetBackground(display, gc_pta, back_color[caching]);
158         XSetBackground(display, gc_ptk, back_color[caching]);
159         draw_kstring(pl_titlewin, buf,
160                 PL_X_MARGIN, pl_fh - plfs->max_bounds.descent);
161 }
162
163 /*
164  * Returns a pointer to title of specified page.
165  */
166 char *
167 page_title(page)
168         int page;
169 {
170         int l;
171         char *p;
172         struct ctrl *cp;
173
174         p = "";
175         for (l = 0; l <= page_attribute[page].pg_linenum; l++) {
176                 cp = page_control[page][l];
177                 while (cp && cp->ct_op != CTL_TEXT)
178                         cp = cp->ct_next;
179                 if (!cp)
180                         continue;
181                 if (cp->ctc_value && *cp->ctc_value) {
182                         p = cp->ctc_value;
183                         break;
184                 }
185         }
186
187         while (*p && isspace(*p))
188                 p++;
189
190         return p;
191 }
192
193 void
194 pg_on()
195 {
196         if (pg_win)
197                 return;
198
199         /* 5 for timebar*/ 
200         pg_win = XCreateSimpleWindow(display, window,
201                 0, window_height - pl_fh - (t_fin ? 5 : 0),
202                 window_width, pl_fh, 0,
203                 BlackPixel(display, screen), back_color[caching]);
204         XSelectInput(display, pg_win, StructureNotifyMask);
205         XMapSubwindows(display, window);
206
207         pg_tmp = XCreatePixmap(display, pg_win, window_width, pl_fh, depth);
208
209         pg_lastpage = -1;
210         pg_lastcp = NULL;
211 }
212
213 void
214 pg_clean()
215 {
216         XClearArea(display, pg_win, 0, 0, window_width, pl_fh, 0);
217         pg_lastpage = -1;
218         pg_lastcp = NULL;
219 }
220
221 void
222 pg_draw(state)
223         struct render_state *state;
224 {
225         char buf[BUFSIZ], *p;
226         int n;
227         u_int page;
228         int showlast;
229
230         if (!pg_mode || !pg_win || !plfs)
231                 return;
232
233         page = state->page;
234 #if 0
235         if (page == pg_lastpage && state->cp == pg_lastcp)
236                 return;
237 #endif
238         if (page == pg_lastpage)
239                 return;
240
241         if (!state->cp) {
242                 pg_clean();
243                 return;
244         }
245
246         showlast = (state->cp->ct_op == CTL_PAUSE && state->cp->cti_value);
247         XSetForeground(display, gc_pta, ctrl_color[caching]);
248         XSetForeground(display, gc_ptk, ctrl_color[caching]);
249         XSetBackground(display, gc_pta, back_color[caching]);
250         XSetBackground(display, gc_ptk, back_color[caching]);
251
252         pg_clean();
253         if (page > 1) {
254                 sprintf(buf, "\033$B\"+\033(B %s",
255                         page_title(page - 1));
256                 draw_kstring(pg_win, buf,
257                         PL_X_MARGIN, pl_fh - plfs->max_bounds.descent);
258         }
259         if (page < maxpage) {
260                 sprintf(buf, "%s\033$B\"*\033(B",
261                         page_title(page + 1));
262                 for (p = buf; *p; p++)
263                         if (*p == '\n')
264                                 *p = ' ';
265                 n = draw_kstring(pg_tmp, buf, 0, pl_fh);
266                 sprintf(buf, "%s\033$B\"*\033(B",
267                         page_title(page + 1));
268                 for (p = buf; *p; p++)
269                         if (*p == '\n')
270                                 *p = ' ';
271                 draw_kstring(pg_win, buf, window_width - 10 - n,
272                         pl_fh - plfs->max_bounds.descent);
273         }
274         if (showlast == 0) {
275                 sprintf(buf, "-- %d/%d --", page, maxpage);
276                 n = draw_kstring(pg_tmp, buf, 0, pl_fh);
277                 /*
278                  * The contents of buf is not destroyed by draw_kstring
279                  * as it doesnot include Kanji sequence.
280                  */
281                 draw_kstring(pg_win, buf, window_width / 2 - n / 2,
282                         pl_fh - plfs->max_bounds.descent);
283         }
284
285         pg_lastpage = state->page;
286         pg_lastcp = state->cp;
287 }
288
289 void
290 pg_off()
291 {
292         if (!pg_win)
293                 return;
294         XUnmapSubwindows(display, window);
295         XFreePixmap(display, pg_tmp);
296         XDestroyWindow(display, pg_win);
297         XMapSubwindows(display, window);
298         XFlush(display);
299         pg_win = None;
300         pg_lastpage = -1;
301         pg_lastcp = NULL;
302 }
303
304 static int
305 draw_kstring(d, buf, x, y)
306         Drawable d;
307         char *buf;
308         int x, y;
309 {
310         char *p;
311         int x0 = x;
312
313         p = buf + strlen(buf) - 1;
314         if (*p == '\n')
315                 *p = '\0';
316         for (p = buf; *p; p++) {
317                 if (strncmp(p, "\033$@", 3) == 0 ||
318                     strncmp(p, "\033$B", 3) == 0) {
319                         *p = '\0'; p += 3;
320                         /* draw 8bit char */
321                         XDrawImageString(display, d, gc_pta, x, y,
322                                 buf, strlen(buf));
323                         x += XTextWidth(plfs, buf, strlen(buf));
324                         buf = p--;
325                 } else if (strncmp(p, "\033(B", 3) == 0 ||
326                            strncmp(p, "\033(J", 3) == 0) {
327                         *p = '\0'; p += 3;
328                         /* draw 16bit char */
329                         XDrawImageString16(display, d, gc_ptk, x, y,
330                                 (XChar2b *)buf, strlen(buf)/2);
331                         x += XTextWidth16(plkfs, (XChar2b *)buf, strlen(buf)/2);
332                         buf = p--;
333                 }
334         }
335         /* draw 8bit char */
336         if (*buf != '\0') {     /* Assumed ASCII at the end of string */
337                 XDrawImageString(display, d, gc_pta, x, y, buf, strlen(buf));
338                 x += XTextWidth(plfs, buf, strlen(buf));
339         }
340         return x - x0;
341 }