OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / sys / amiga / winstr.c
1 /* NetHack 3.6  winstr.c        $NHDT-Date: 1432512795 2015/05/25 00:13:15 $  $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */
2 /* Copyright (c) Gregg Wonderly, Naperville, Illinois,  1991,1992,1993. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "NH:sys/amiga/windefs.h"
6 #include "NH:sys/amiga/winext.h"
7 #include "NH:sys/amiga/winproto.h"
8
9 /* Put a string into the indicated window using the indicated attribute */
10
11 void
12 amii_putstr(window, attr, str)
13 winid window;
14 int attr;
15 const char *str;
16 {
17     int fudge;
18     int len;
19     struct Window *w;
20     register struct amii_WinDesc *cw;
21     char *ob;
22     int i, j, n0, bottom, totalvis, wheight;
23     static int wrapping = 0;
24
25     /* Always try to avoid a panic when there is no window */
26     if (window == WIN_ERR) {
27         window = WIN_BASE;
28         if (window == WIN_ERR)
29             window = WIN_BASE = amii_create_nhwindow(NHW_BASE);
30     }
31
32     if (window == WIN_ERR || (cw = amii_wins[window]) == NULL) {
33         iflags.window_inited = 0;
34         panic(winpanicstr, window, "putstr");
35     }
36
37     w = cw->win;
38
39     if (!str)
40         return;
41     amiIDisplay->lastwin = window; /* do we care??? */
42
43     /* NHW_MENU windows are not opened immediately, so check if we
44      * have the window pointer yet
45      */
46
47     if (w) {
48         /* Set the drawing mode and pen colors */
49         SetDrMd(w->RPort, JAM2);
50         amii_sethipens(w, cw->type, attr);
51     } else if (cw->type != NHW_MENU && cw->type != NHW_TEXT) {
52         panic("NULL window pointer in putstr 2: %d", window);
53     }
54
55     /* Okay now do the work for each type */
56
57     switch (cw->type) {
58     case NHW_MESSAGE:
59         if (WINVERS_AMIV)
60             fudge = 2;
61         else {
62             /* 8 for --more--, 1 for preceeding sp, 1 for putstr pad */
63             fudge = 10;
64         }
65
66         /* There is a one pixel border at the borders, so subtract two */
67         bottom = amii_msgborder(w);
68
69         wheight = (w->Height - w->BorderTop - w->BorderBottom - 3)
70                   / w->RPort->TxHeight;
71
72         if (scrollmsg || wheight > 1)
73             fudge = 0;
74
75         amii_scrollmsg(w, cw);
76
77         while (isspace(*str))
78             str++;
79         strncpy(toplines, str, TBUFSZ);
80         toplines[TBUFSZ - 1] = 0;
81
82         /* For initial message to be visible, we need to explicitly position
83          * the
84          * cursor.  This flag, cw->curx == -1 is set elsewhere to force the
85          * cursor to be repositioned to the "bottom".
86          */
87         if (cw->curx == -1) {
88             amii_curs(WIN_MESSAGE, 1, bottom);
89             cw->curx = 0;
90         }
91
92         /* If used all of history lines, move them down */
93         if (cw->maxrow >= iflags.msg_history) {
94             if (cw->data[0])
95                 free(cw->data[0]);
96             memcpy(cw->data, &cw->data[1],
97                    (iflags.msg_history - 1) * sizeof(char *));
98             cw->data[iflags.msg_history - 1] =
99                 (char *) alloc(strlen(toplines) + 5);
100             strcpy(cw->data[i = iflags.msg_history - 1] + SOFF
101                        + (scrollmsg != 0),
102                    toplines);
103         } else {
104             /* Otherwise, allocate a new one and copy the line in */
105             cw->data[cw->maxrow] = (char *) alloc(strlen(toplines) + 5);
106             strcpy(cw->data[i = cw->maxrow++] + SOFF + (scrollmsg != 0),
107                    toplines);
108         }
109         cw->data[i][SEL_ITEM] = 1;
110         cw->data[i][VATTR] = attr + 1;
111
112         if (scrollmsg) {
113             cw->curx = 0;
114             cw->data[i][2] = (cw->wflags & FLMSG_FIRST) ? '>' : ' ';
115         }
116
117         str = cw->data[i] + SOFF;
118         if (cw->curx + strlen(str) >= (cw->cols - fudge)) {
119             int i;
120             char *ostr = (char *) str;
121             char *p;
122
123             while (cw->curx + strlen(str) >= (cw->cols - fudge)) {
124                 for (p = ((char *) &str[cw->cols - 1 - cw->curx]) - fudge;
125                      !isspace(*p) && p > str;)
126                     --p;
127                 if (p < str)
128                     p = (char *) str;
129
130                 if (p == str) {
131                     /*    p = (char *)&str[ cw->cols ]; */
132                     outmore(cw);
133                     continue;
134                 }
135
136                 i = (long) p - (long) str;
137                 outsubstr(cw, (char *) str, i, fudge);
138                 cw->curx += i;
139
140                 while (isspace(*p))
141                     p++;
142                 str = p;
143
144 #if 0
145                 if( str != ostr ) {
146                     outsubstr( cw, "+", 1, fudge );
147                     cw->curx+=2;
148                 }
149 #endif
150                 if (*str)
151                     amii_scrollmsg(w, cw);
152                 amii_cl_end(cw, cw->curx);
153             }
154
155             if (*str) {
156                 if (str != ostr) {
157                     outsubstr(cw, "+", 1, fudge);
158                     cw->curx += 2;
159                 }
160                 while (isspace(*str))
161                     ++str;
162                 outsubstr(cw, (char *) str, i = strlen((char *) str), fudge);
163                 cw->curx += i;
164                 amii_cl_end(cw, cw->curx);
165             }
166         } else {
167             outsubstr(cw, (char *) str, i = strlen((char *) str), fudge);
168             cw->curx += i;
169             amii_cl_end(cw, cw->curx);
170         }
171         cw->wflags &= ~FLMSG_FIRST;
172         len = 0;
173         if (scrollmsg) {
174             totalvis = CountLines(window);
175             SetPropInfo(w, &MsgScroll,
176                         (w->Height - w->BorderTop - w->BorderBottom)
177                             / w->RPort->TxHeight,
178                         totalvis, totalvis);
179         }
180         i = strlen(toplines + SOFF);
181         cw->maxcol = max(cw->maxcol, i);
182         cw->vwy = cw->maxrow;
183         break;
184
185     case NHW_STATUS:
186         if (cw->data[cw->cury] == NULL)
187             panic("NULL pointer for status window");
188         ob = &cw->data[cw->cury][j = cw->curx];
189         if (context.botlx)
190             *ob = 0;
191
192         /* Display when beam at top to avoid flicker... */
193         WaitTOF();
194         Text(w->RPort, (char *) str, strlen((char *) str));
195         if (cw->cols > strlen(str))
196             TextSpaces(w->RPort, cw->cols - strlen(str));
197
198         (void) strncpy(cw->data[cw->cury], str, cw->cols);
199         cw->data[cw->cury][cw->cols - 1] = '\0'; /* null terminate */
200         cw->cury = (cw->cury + 1) % 2;
201         cw->curx = 0;
202         break;
203
204     case NHW_MAP:
205     case NHW_BASE:
206         if (cw->type == NHW_BASE && wrapping) {
207             amii_curs(window, cw->curx + 1, cw->cury);
208             TextSpaces(w->RPort, cw->cols);
209             if (cw->cury < cw->rows) {
210                 amii_curs(window, cw->curx + 1, cw->cury + 1);
211                 TextSpaces(w->RPort, cw->cols);
212                 cw->cury--;
213             }
214         }
215         amii_curs(window, cw->curx + 1, cw->cury);
216         Text(w->RPort, (char *) str, strlen((char *) str));
217         cw->curx = 0;
218         /* CR-LF is automatic in these windows */
219         cw->cury++;
220         if (cw->type == NHW_BASE && cw->cury >= cw->rows) {
221             cw->cury = 0;
222             wrapping = 1;
223         }
224         break;
225
226     case NHW_MENU:
227     case NHW_TEXT:
228
229         /* always grows one at a time, but alloc 12 at a time */
230
231         if (cw->cury >= cw->rows || !cw->data) {
232             char **tmp;
233
234             /* Allocate 12 more rows */
235             cw->rows += 12;
236             tmp = (char **) alloc(sizeof(char *) * cw->rows);
237
238             /* Copy the old lines */
239             for (i = 0; i < cw->cury; i++)
240                 tmp[i] = cw->data[i];
241
242             if (cw->data) {
243                 free(cw->data);
244                 cw->data = NULL;
245             }
246
247             cw->data = tmp;
248
249             /* Null out the unused entries. */
250             for (i = cw->cury; i < cw->rows; i++)
251                 cw->data[i] = 0;
252         }
253
254         if (!cw->data)
255             panic("no data storage");
256
257         /* Shouldn't need to do this, but... */
258
259         if (cw->data && cw->data[cw->cury]) {
260             free(cw->data[cw->cury]);
261             cw->data[cw->cury] = NULL;
262         }
263
264         n0 = strlen(str) + 1;
265         cw->data[cw->cury] = (char *) alloc(n0 + SOFF);
266
267         /* avoid nuls, for convenience */
268         cw->data[cw->cury][VATTR] = attr + 1;
269         cw->data[cw->cury][SEL_ITEM] = 0;
270         Strcpy(cw->data[cw->cury] + SOFF, str);
271
272         if (n0 > cw->maxcol)
273             cw->maxcol = n0;
274         if (++cw->cury > cw->maxrow)
275             cw->maxrow = cw->cury;
276         break;
277
278     default:
279         panic("Invalid or unset window type in putstr()");
280     }
281 }
282
283 void
284 amii_scrollmsg(w, cw)
285 register struct Window *w;
286 register struct amii_WinDesc *cw;
287 {
288     int bottom, wheight;
289
290     bottom = amii_msgborder(w);
291
292     wheight =
293         (w->Height - w->BorderTop - w->BorderBottom - 3) / w->RPort->TxHeight;
294
295     if (scrollmsg) {
296         if (++cw->disprows > wheight) {
297             outmore(cw);
298             cw->disprows = 1; /* count this line... */
299         } else {
300             ScrollRaster(w->RPort, 0, w->RPort->TxHeight, w->BorderLeft,
301                          w->BorderTop + 1, w->Width - w->BorderRight - 1,
302                          w->Height - w->BorderBottom - 1);
303         }
304         amii_curs(WIN_MESSAGE, 1, bottom);
305     }
306 }
307
308 int
309 amii_msgborder(w)
310 struct Window *w;
311 {
312     register int bottom;
313
314     /* There is a one pixel border at the borders, so subtract two */
315     bottom = w->Height - w->BorderTop - w->BorderBottom - 2;
316     bottom /= w->RPort->TxHeight;
317     if (bottom > 0)
318         --bottom;
319     return (bottom);
320 }
321
322 void
323 outmore(cw)
324 register struct amii_WinDesc *cw;
325 {
326     struct Window *w = cw->win;
327
328     if ((cw->wflags & FLMAP_SKIP) == 0) {
329         if (scrollmsg) {
330             int bottom;
331
332             bottom = amii_msgborder(w);
333
334             ScrollRaster(w->RPort, 0, w->RPort->TxHeight, w->BorderLeft,
335                          w->BorderTop + 1, w->Width - w->BorderRight - 1,
336                          w->Height - w->BorderBottom - 1);
337             amii_curs(WIN_MESSAGE, 1, bottom); /* -1 for inner border */
338             Text(w->RPort, "--more--", 8);
339         } else
340             Text(w->RPort, " --more--", 9);
341
342         /* Make sure there are no events in the queue */
343         flushIDCMP(HackPort);
344
345         /* Allow mouse clicks to clear --more-- */
346         WindowGetchar();
347         if (lastevent.type == WEKEY && lastevent.un.key == '\33')
348             cw->wflags |= FLMAP_SKIP;
349     }
350     if (!scrollmsg) {
351         amii_curs(WIN_MESSAGE, 1, 0);
352         amii_cl_end(cw, cw->curx);
353     }
354 }
355
356 void
357 outsubstr(cw, str, len, fudge)
358 register struct amii_WinDesc *cw;
359 char *str;
360 int len;
361 int fudge;
362 {
363     struct Window *w = cw->win;
364
365     if (cw->curx) {
366         /* Check if this string and --more-- fit, if not,
367          * then put out --more-- and wait for a key.
368          */
369         if ((len + fudge) + cw->curx >= cw->cols) {
370             if (!scrollmsg)
371                 outmore(cw);
372         } else {
373             /* Otherwise, move and put out a blank separator */
374             Text(w->RPort, spaces, 1);
375             cw->curx += 1;
376         }
377     }
378
379     Text(w->RPort, str, len);
380 }
381
382 /* Put a graphics character onto the screen */
383
384 void
385 amii_putsym(st, i, y, c)
386 winid st;
387 int i, y;
388 CHAR_P c;
389 {
390     amii_curs(st, i, y);
391     Text(amii_wins[st]->win->RPort, &c, 1);
392 }
393
394 /* Add to the last line in the message window */
395
396 void
397 amii_addtopl(s)
398 const char *s;
399 {
400     register struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE];
401
402     while (*s) {
403         if (cw->curx == cw->cols - 1)
404             amii_putstr(WIN_MESSAGE, 0, "");
405         amii_putsym(WIN_MESSAGE, cw->curx + 1, amii_msgborder(cw->win), *s++);
406         cw->curx++;
407     }
408 }
409
410 void
411 TextSpaces(rp, nr)
412 struct RastPort *rp;
413 int nr;
414 {
415     if (nr < 1)
416         return;
417
418     while (nr > sizeof(spaces) - 1) {
419         Text(rp, spaces, (long) sizeof(spaces) - 1);
420         nr -= sizeof(spaces) - 1;
421     }
422     if (nr > 0)
423         Text(rp, spaces, (long) nr);
424 }
425
426 void
427 amii_remember_topl()
428 {
429     /* ignore for now.  I think this will be done automatically by
430      * the code writing to the message window, but I could be wrong.
431      */
432 }
433
434 int
435 amii_doprev_message()
436 {
437     struct amii_WinDesc *cw;
438     struct Window *w;
439     char *str;
440
441     if (WIN_MESSAGE == WIN_ERR || (cw = amii_wins[WIN_MESSAGE]) == NULL
442         || (w = cw->win) == NULL) {
443         panic(winpanicstr, WIN_MESSAGE, "doprev_message");
444     }
445
446     /* When an interlaced/tall screen is in use, the scroll bar will be there
447      */
448     /* Or in some other cases as well */
449     if (scrollmsg) {
450         struct Gadget *gd;
451         struct PropInfo *pip;
452         int hidden, topidx, i, total, wheight;
453
454         for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
455             gd = gd->NextGadget;
456
457         if (gd) {
458             pip = (struct PropInfo *) gd->SpecialInfo;
459             wheight = (w->Height - w->BorderTop - w->BorderBottom - 2)
460                       / w->RPort->TxHeight;
461             hidden = max(cw->maxrow - wheight, 0);
462             topidx = (((ULONG) hidden * pip->VertPot) + (MAXPOT / 2)) >> 16;
463             for (total = i = 0; i < cw->maxrow; ++i) {
464                 if (cw->data[i][1] != 0)
465                     ++total;
466             }
467
468             i = 0;
469             topidx -= wheight / 4 + 1;
470             if (topidx < 0)
471                 topidx = 0;
472             SetPropInfo(w, &MsgScroll, wheight, total, topidx);
473             DisplayData(WIN_MESSAGE, topidx);
474         }
475         return (0);
476     }
477
478     if (--cw->vwy < 0) {
479         cw->maxcol = 0;
480         DisplayBeep(NULL);
481         str = "\0\0No more history saved...";
482     } else
483         str = cw->data[cw->vwy];
484
485     amii_cl_end(cw, 0);
486     amii_curs(WIN_MESSAGE, 1, 0);
487     amii_setdrawpens(amii_wins[WIN_MESSAGE]->win, NHW_MESSAGE);
488     Text(w->RPort, str + SOFF, strlen(str + SOFF));
489     cw->curx = cw->cols + 1;
490
491     return (0);
492 }