scrdisp.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /* $Id$
  2. * MegaZeux
  3. *
  4. * Copyright (C) 1996 Greg Janson
  5. * Copyright (C) 1998 Matthew D. Williams - dbwilli@scsn.net
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. /* Scroll display code */
  22. #include <string.h>
  23. #include <stdio.h>
  24. #include <ctype.h>
  25. #include "event.h"
  26. #include "data.h"
  27. #include "scrdisp.h"
  28. #include "window.h"
  29. #include "graphics.h"
  30. #include "error.h"
  31. #include "intake.h"
  32. #include "world.h"
  33. #include "robot.h"
  34. // Also used to display scrolls. Use a type of 0 for Show Scroll, 1 for Show
  35. // Sign, 2 for Edit Scroll.
  36. void scroll_edit(World *mzx_world, Scroll *scroll, char type)
  37. {
  38. // Important status vars (insert kept in intake.cpp)
  39. unsigned int pos = 1, old_pos; // Where IN scroll?
  40. int currx = 0; // X position in line
  41. int key; // Key returned by intake()
  42. int t1, t2, t3;
  43. char *where; // Where scroll is
  44. char line[80]; // For editing
  45. int scroll_base_color = mzx_world->scroll_base_color;
  46. int fade_status = get_fade_status();
  47. // Draw screen
  48. save_screen();
  49. if(fade_status)
  50. {
  51. clear_screen(32, 7);
  52. insta_fadein();
  53. }
  54. scroll_edging(mzx_world, type);
  55. // Loop
  56. where = scroll->mesg;
  57. do
  58. {
  59. // Display scroll
  60. scroll_frame(mzx_world, scroll, pos);
  61. update_screen();
  62. if(type == 2)
  63. {
  64. // Figure length
  65. for(t1 = 0; t1 < 80; t1++)
  66. {
  67. if(where[pos + t1] == '\n')
  68. break;
  69. }
  70. // t1 == length
  71. // Edit line
  72. where[pos + t1] = 0;
  73. strcpy(line, where + pos);
  74. where[pos + t1] = '\n';
  75. key = intake(line, 64, 8, 12, scroll_base_color, 2, 0, 0, &currx);
  76. // Modify scroll to hold new line (give errors here)
  77. t2 = strlen(line); // Get length of NEW line
  78. // Resize and move
  79. t3 = scroll->mesg_size;
  80. reallocate_scroll(scroll, t3 + t2 - t1);
  81. where = scroll->mesg;
  82. // Now move.
  83. memmove(where + pos + t2, where + pos + t1, t3 - pos - t1);
  84. // Copy in new line
  85. strcpy(where + pos, line);
  86. where[pos + t2] = '\n';
  87. }
  88. else
  89. {
  90. update_event_status_delay();
  91. key = get_key(keycode_SDL);
  92. }
  93. old_pos = pos;
  94. if(get_mouse_press() || (key == -1))
  95. {
  96. int mouse_x, mouse_y;
  97. get_mouse_position(&mouse_x, &mouse_y);
  98. if((mouse_y >= 6) && (mouse_y <= 18) && (mouse_x >= 8) &&
  99. (mouse_x <= 71))
  100. {
  101. t1 = mouse_y - 12;
  102. if(t1)
  103. {
  104. if(t1 < 0)
  105. goto pgdn;
  106. else
  107. goto pgup;
  108. }
  109. }
  110. key = SDLK_ESCAPE;
  111. }
  112. switch(key)
  113. {
  114. case SDLK_UP: // Up
  115. up_a_line:
  116. // Go back a line (if possible)
  117. if(where[pos - 1] == 1) break; // Can't.
  118. pos--;
  119. // Go to start of this line.
  120. do
  121. {
  122. pos--;
  123. } while((where[pos] != '\n') && (where[pos] != 1));
  124. pos++;
  125. // Done.
  126. break;
  127. case SDLK_DOWN://Down
  128. down_a_line:
  129. // Go forward a line (if possible)
  130. while(where[pos] != '\n')
  131. pos++;
  132. // At end of current. Is there a next line?
  133. pos++;
  134. if(where[pos] == 0)
  135. {
  136. // Nope.
  137. pos = old_pos;
  138. break;
  139. }
  140. // Yep. Done.
  141. break;
  142. case SDLK_RETURN: // Enter
  143. if(type < 2)
  144. {
  145. key = SDLK_ESCAPE;
  146. }
  147. else
  148. {
  149. // Add in new line below. Need only add one byte.
  150. t3 = scroll->mesg_size;
  151. reallocate_scroll(scroll, t3 + 1);
  152. where = scroll->mesg;
  153. // Move all at pos + currx up a space
  154. memmove(where + pos + currx + 1, where + pos + currx, t3 - pos - currx);
  155. // Insert a \n
  156. where[pos + currx] = '\n';
  157. // Change pos and currx
  158. pos = pos + currx + 1;
  159. currx = 0;
  160. scroll->num_lines++;
  161. }
  162. break;
  163. case SDLK_BACKSPACE: // Backspace
  164. if(type < 2) break;
  165. // We are at the start of the current line and we are trying to
  166. // append it to the end of the previous line. First, remember
  167. // the size of the current line is in t2. Now we go back a line,
  168. // if there is one.
  169. if(where[pos - 1] == 1) break; // Nope.
  170. pos--;
  171. // Go to start of this line, COUNTING CHARACTERS.
  172. t1 = 0;
  173. do
  174. {
  175. pos--;
  176. t1++;
  177. } while((where[pos] != '\n') && (where[pos] != 1));
  178. // pos is at one before the start of this line. WHO CARES!? :)
  179. // Now we have to see if the size, t2, is over 64 characters.
  180. // t2 + t1 is currently one too many so check for >65 for error.
  181. if((t2 + t1) > 65)
  182. {
  183. pos = old_pos;
  184. break; // Too long. Reset position.
  185. }
  186. // OKAY! Just copy backwards over the \n in the middle to
  187. // append...
  188. t3 = scroll->mesg_size;
  189. memmove(where + old_pos - 1, where + old_pos, t3 - old_pos);
  190. // ...and reallocate to one space less!
  191. reallocate_scroll(scroll, t3 - 1);
  192. where = scroll->mesg;
  193. // pos is one before this start. Fix to the start of this new
  194. // line. Set currx to the length of the old line this was.
  195. pos++;
  196. currx = t1 - 1;
  197. scroll->num_lines--;
  198. // Done.
  199. break;
  200. case SDLK_PAGEDOWN: // Pagedown (by 6 lines)
  201. for(t1 = 6; t1 > 0; t1--)
  202. {
  203. pgdn:
  204. // Go forward a line (if possible)
  205. old_pos = pos;
  206. while(where[pos] != '\n') pos++;
  207. // At end of current. Is there a next line?
  208. pos++;
  209. if(where[pos] == 0)
  210. {
  211. // Nope.
  212. pos = old_pos;
  213. break;
  214. }
  215. // Yep. Done.
  216. }
  217. break;
  218. case SDLK_PAGEUP: // Pageup (by 6 lines)
  219. for(t1 = -6; t1 < 0; t1++)
  220. {
  221. pgup:
  222. // Go back a line (if possible)
  223. if(where[pos - 1] == 1) break; // Can't.
  224. pos--;
  225. // Go to start of this line.
  226. do
  227. {
  228. pos--;
  229. } while((where[pos] != '\n') && (where[pos] != 1));
  230. pos++;
  231. // Done.
  232. }
  233. break;
  234. case SDLK_HOME: // Home
  235. // FIXME - This is so dirty. Please replace it.
  236. t1 = -30000;
  237. goto pgup;
  238. case SDLK_END: // End
  239. // FIXME - See above.
  240. t1 = 30000;
  241. goto pgdn;
  242. default:
  243. case SDLK_ESCAPE:
  244. case 0:
  245. break;
  246. }
  247. // Continue?
  248. } while(key != SDLK_ESCAPE);
  249. // Restore screen and exit
  250. restore_screen();
  251. if(fade_status)
  252. insta_fadeout();
  253. }
  254. void scroll_frame(World *mzx_world, Scroll *scroll, unsigned int pos)
  255. {
  256. // Displays one frame of a scroll. The scroll edging, arrows, and title
  257. // must already be shown. Simply prints each line. POS is the position
  258. // of the scroll's line in the text. This is of the center line.
  259. int t1;
  260. unsigned int old_pos = pos;
  261. char *where;
  262. int scroll_base_color = mzx_world->scroll_base_color;
  263. where = scroll->mesg;
  264. // Display center line
  265. fill_line(64, 8, 12, 32, scroll_base_color);
  266. write_line(where + pos, 8, 12, scroll_base_color, 1);
  267. // Display lines above center line
  268. for(t1 = 11; t1 >= 6; t1--)
  269. {
  270. fill_line(64, 8, t1, 32, scroll_base_color);
  271. // Go backward to previous line
  272. if(where[pos] != 1)
  273. {
  274. pos--;
  275. if(where[pos] == '\n')
  276. {
  277. do
  278. {
  279. pos--;
  280. } while((where[pos] != '\n') && (where[pos] != 1));
  281. // At start of prev. line -1. Display.
  282. pos++;
  283. write_line(where + pos, 8, t1, scroll_base_color, 1);
  284. }
  285. }
  286. // Next line...
  287. }
  288. // Display lines below center line
  289. pos = old_pos;
  290. for(t1 = 13; t1 <= 18; t1++)
  291. {
  292. fill_line(64, 8, t1, 32, scroll_base_color);
  293. if(where[pos] == 0) continue;
  294. // Go forward to next line
  295. while(where[pos] != '\n') pos++;
  296. // At end of current. If next is a 0, don't show nuthin'.
  297. pos++;
  298. if(where[pos])
  299. write_line(where + pos, 8, t1, scroll_base_color, 1);
  300. // Next line...
  301. }
  302. }
  303. char scr_nm_strs[5][12] =
  304. { " Scroll ", " Sign ", "Edit Scroll", " Help ", "" };
  305. void scroll_edging(World *mzx_world, char type)
  306. {
  307. int scroll_base_color = mzx_world->scroll_base_color;
  308. int scroll_corner_color = mzx_world->scroll_corner_color;
  309. int scroll_pointer_color = mzx_world->scroll_pointer_color;
  310. int scroll_title_color = mzx_world->scroll_title_color;
  311. // Displays the edging box of scrolls. Type=0 for Scroll, 1 for Sign, 2
  312. // for Edit Scroll, 3 for Help, 4 for Robot (w/o title)
  313. // Doesn't save the screen.
  314. // Box for the title
  315. draw_window_box(5, 3, 74, 5, scroll_base_color & 0xF0, scroll_base_color,
  316. scroll_corner_color, 1, 1);
  317. // Main box
  318. draw_window_box(5, 5, 74, 19, scroll_base_color, scroll_base_color & 0xF0,
  319. scroll_corner_color, 1, 1); /* Text on 6 - 18 */
  320. // Shows keys in a box at the bottom
  321. if(type == 3)
  322. {
  323. draw_window_box(5, 19, 74, 22, scroll_base_color & 0xF0,
  324. scroll_base_color, scroll_corner_color, 1, 1);
  325. }
  326. else
  327. {
  328. draw_window_box(5, 19, 74, 21, scroll_base_color & 0xF0,
  329. scroll_base_color, scroll_corner_color, 1, 1);
  330. }
  331. // Fix chars on edging
  332. draw_char(217, scroll_base_color, 74, 5);
  333. draw_char(217, scroll_base_color & 0xF0, 74, 19);
  334. // Add arrows
  335. draw_char(16, scroll_pointer_color, 6, 12);
  336. draw_char(17, scroll_pointer_color, 73, 12);
  337. // Write title
  338. write_string(scr_nm_strs[type], 34, 4, scroll_title_color, 0);
  339. // Write key reminders
  340. if(type == 2)
  341. {
  342. write_string(": Move cursor Alt+C: Character Esc: Done editing",
  343. 13, 20, scroll_corner_color, 0);
  344. }
  345. else
  346. if(type < 2)
  347. {
  348. write_string(": Scroll text Esc/Enter: End reading",
  349. 21, 20, scroll_corner_color, 0);
  350. }
  351. else
  352. if(type == 3)
  353. {
  354. write_string(":Scroll text Esc:Exit help Enter:Select Alt+P:Print",
  355. 13, 20, scroll_corner_color, 0);
  356. write_string("F1:Help on Help Alt+F1:Table of Contents",
  357. 20, 21, scroll_corner_color, 0);
  358. }
  359. else
  360. {
  361. write_string(":Scroll text Esc:Exit Enter:Select", 21, 20,
  362. scroll_corner_color, 0);
  363. }
  364. update_screen();
  365. }
  366. void help_display(World *mzx_world, char *help, unsigned int offs,
  367. char *file, char *label)
  368. {
  369. // Display a help file
  370. unsigned int pos = offs, old_pos, next_pos; // Where
  371. int key, fad = get_fade_status();
  372. int t1, t2;
  373. char mclick;
  374. // allow_help = 0;
  375. // Draw screen
  376. save_screen();
  377. if(fad)
  378. {
  379. clear_screen(32, 7);
  380. insta_fadein();
  381. }
  382. scroll_edging(mzx_world, 3);
  383. // Loop
  384. file[0] = label[0] = 0;
  385. do
  386. {
  387. // Display scroll
  388. help_frame(mzx_world, help, pos);
  389. mclick = 0;
  390. update_screen();
  391. update_event_status_delay();
  392. if(get_mouse_press())
  393. {
  394. int mouse_x, mouse_y;
  395. get_mouse_position(&mouse_x, &mouse_y);
  396. // Move to line clicked on if mouse is in scroll, else exit
  397. if((mouse_y >= 6)&&(mouse_y <= 18)&&
  398. (mouse_x >= 8) && (mouse_x <= 71))
  399. {
  400. mclick=1;
  401. t1 = mouse_y - 12;
  402. if(t1 == 0)
  403. goto option;
  404. //t1<0 = PGUP t1 lines
  405. //t1>0 = PGDN t1 lines
  406. if(t1 < 0)
  407. goto pgup;
  408. goto pgdn;
  409. }
  410. key = SDLK_ESCAPE;
  411. }
  412. key = get_key(keycode_SDL);
  413. old_pos = pos;
  414. switch(key)
  415. {
  416. case SDLK_F1: // F1
  417. if(get_key_status(keycode_SDL, SDLK_LALT) ||
  418. get_key_status(keycode_SDL, SDLK_RALT))
  419. {
  420. // Jump to label 072 in MAIN.HLP
  421. strcpy(file,"MAIN.HLP");
  422. strcpy(label,"072");
  423. }
  424. else
  425. {
  426. // Jump to label 000 in HELPONHE.HLP
  427. strcpy(file, "HELPONHE.HLP");
  428. strcpy(label, "000");
  429. }
  430. goto ex;
  431. case SDLK_UP: // Up
  432. up_a_line:
  433. // Go back a line (if possible)
  434. if(help[pos - 1] == 1) break; // Can't.
  435. pos--;
  436. // Go to start of this line.
  437. do
  438. {
  439. pos--;
  440. } while((help[pos] != '\n') && (help[pos] != 1));
  441. pos++;
  442. // Done.
  443. break;
  444. case SDLK_DOWN: // Down
  445. down_a_line:
  446. // Go forward a line (if possible)
  447. while(help[pos] != '\n') pos++;
  448. // At end of current. Is there a next line?
  449. pos++;
  450. if(help[pos] == 0)
  451. {
  452. // Nope.
  453. pos = old_pos;
  454. break;
  455. }
  456. // Yep. Done.
  457. break;
  458. case SDLK_RETURN://Enter
  459. option:
  460. // Option?
  461. if((help[pos] == 255) && ((help[pos + 1] == '>') ||
  462. (help[pos + 1] == '<')))
  463. {
  464. // Yep!
  465. pos++;
  466. if(help[pos] == '<')
  467. {
  468. // Get file and label and exit
  469. t1 = 0;
  470. pos++;
  471. do
  472. {
  473. pos++;
  474. file[t1] = help[pos];
  475. t1++;
  476. } while(help[pos] != ':');
  477. file[t1 - 1] = 0;
  478. strcpy(label, help + pos + 1);
  479. goto ex;
  480. }
  481. // Get label and jump
  482. strcpy(label, help + pos + 2);
  483. // Search backwards for a 1
  484. do
  485. {
  486. pos--;
  487. } while(help[pos] != 1);
  488. // Search for label OR a \n followed by a \0
  489. do
  490. {
  491. pos++;
  492. if(help[pos] == 255)
  493. if(help[pos + 1] == ':')
  494. if(!strcmp(help + pos + 3, label))
  495. // pos is correct!
  496. goto labdone;
  497. if(help[pos] == '\n')
  498. if(help[pos + 1] == 0) break;
  499. } while(1);
  500. }
  501. // If there WAS an option, any existing label was found.
  502. labdone:
  503. break;
  504. case SDLK_PAGEDOWN://Pagedown (by 6 lines)
  505. for(t1 = 6; t1 > 0; t1--)
  506. {
  507. pgdn:
  508. // Go forward a line (if possible)
  509. old_pos = pos;
  510. while(help[pos] != '\n') pos++;
  511. // At end of current. Is there a next line?
  512. pos++;
  513. if(help[pos] == 0)
  514. {
  515. // Nope.
  516. pos = old_pos;
  517. break;
  518. }
  519. // Yep. Done.
  520. }
  521. if(mclick) goto option;
  522. break;
  523. case SDLK_PAGEUP: // Pageup (by 6 lines)
  524. for(t1 = -6; t1 < 0; t1++)
  525. {
  526. pgup:
  527. // Go back a line (if possible)
  528. if(help[pos - 1] == 1) break; // Can't.
  529. pos--;
  530. // Go to start of this line.
  531. do
  532. {
  533. pos--;
  534. } while((help[pos] != '\n') && (help[pos] != 1));
  535. pos++;
  536. // Done.
  537. }
  538. if(mclick) goto option;
  539. break;
  540. case SDLK_HOME: // Home
  541. // FIXME - :(
  542. t1 = -30000;
  543. goto pgup;
  544. case SDLK_END: // End
  545. t1 = 30000;
  546. goto pgdn;
  547. default:
  548. break;
  549. }
  550. //Continue?
  551. } while(key != SDLK_ESCAPE);
  552. // Restore screen and exit
  553. ex:
  554. if(fad) insta_fadeout();
  555. restore_screen();
  556. // allow_help = 1;
  557. }
  558. void help_frame(World *mzx_world, char *help, unsigned int pos)
  559. {
  560. // Displays one frame of the help. Simply prints each line. POS is the
  561. // position of the center line.
  562. int t1, t2;
  563. int first = 12;
  564. int scroll_base_color = mzx_world->scroll_base_color;
  565. int scroll_arrow_color = mzx_world->scroll_arrow_color;
  566. unsigned int next_pos;
  567. // Work backwards to line
  568. do
  569. {
  570. if(help[pos - 1] == 1) break; // Can't.
  571. pos--;
  572. // Go to start of this line.
  573. do
  574. {
  575. pos--;
  576. } while((help[pos] != '\n') && (help[pos] != 1));
  577. pos++;
  578. //Back a line!
  579. first--;
  580. } while(first > 6);
  581. //First holds first line pos (6-12) to draw
  582. if(first > 6)
  583. {
  584. for(t1 = 6; t1 < first; t1++)
  585. fill_line(64, 8, t1, 32, scroll_base_color);
  586. }
  587. // Display from First to either 18 or end of help
  588. for(t1 = first; t1 < 19; t1++)
  589. {
  590. // Fill...
  591. fill_line(64, 8, t1, 32, scroll_base_color);
  592. // Find NEXT line NOW - Actually get end of this one.
  593. next_pos = pos;
  594. while(help[next_pos] != '\n') next_pos++;
  595. // Temp. make a 0
  596. help[next_pos] = 0;
  597. // Write- What TYPE is it?
  598. if(help[pos] != 255) //Normal
  599. color_string(help + pos, 8, t1, scroll_base_color);
  600. else
  601. {
  602. pos++;
  603. switch(help[pos])
  604. {
  605. case '$':
  606. // Centered. :)
  607. pos++;
  608. t2 = strlencolor(help + pos);
  609. color_string(help + pos, 40 - (t2 >> 1), t1, scroll_base_color);
  610. break;
  611. case '>':
  612. case '<':
  613. // Option- Jump to AFTER dest. label/fill
  614. pos += help[pos + 1] + 3;
  615. // Now show, two spaces over
  616. color_string(help + pos, 10, t1, scroll_base_color);
  617. // Add arrow
  618. draw_char('', scroll_arrow_color, 8, t1);
  619. break;
  620. case ':':
  621. // Label- Jump to mesg and show
  622. pos += help[pos + 1] + 3;
  623. color_string(help + pos, 8, t1, scroll_base_color);
  624. break;
  625. }
  626. }
  627. // Now fix EOS to be a \n
  628. help[next_pos] = '\n';
  629. // Next line...
  630. next_pos++;
  631. pos = next_pos;
  632. if(help[pos] == 0) break;
  633. }
  634. if(t1 < 19)
  635. {
  636. for(t1 += 1; t1 < 19; t1++)
  637. fill_line(64, 8, t1, 32, scroll_base_color);
  638. }
  639. update_screen();
  640. }
  641. int strlencolor(char *str)
  642. {
  643. int len = 0;
  644. char cur_char = *str;\
  645. while(cur_char != 0)
  646. {
  647. switch(cur_char)
  648. {
  649. // Color character
  650. case '@':
  651. case '~':
  652. {
  653. str++;
  654. cur_char = *str;
  655. // If 0, stop right there
  656. if(!cur_char)
  657. return len;
  658. // If the next isn't hex, count as one
  659. if(!isxdigit(cur_char))
  660. {
  661. len++;
  662. }
  663. break;
  664. }
  665. default:
  666. {
  667. len++;
  668. }
  669. }
  670. str++;
  671. cur_char = *str;
  672. }
  673. return len;
  674. }