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