intake.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  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. // Code to the intake function, which inputs text with friendliness.
  22. #include <string.h>
  23. #include "event.h"
  24. #include "intake.h"
  25. #include "graphics.h"
  26. #include "window.h"
  27. #include "hexchar.h"
  28. // Global status of insert
  29. char insert_on = 1;
  30. // (returns the key used to exit) String points to your memory for storing
  31. // the new string. The current "value" is used- clear the string before
  32. // calling intake if you need a blank string. Max_len is the maximum length
  33. // of the string. X, y, segment, and color are self-explanitory. Exit_type
  34. // determines when intake exits- 0 means exit only on Enter, 1 on Enter or
  35. // ESC, 2 on any non-display char except the editing keys. Filter_type is
  36. // bits to turn on filters- 1 changes all alpha to upper, 2 changes all
  37. // alpha to lower, 4 blocks all numbers, 8 blocks all alpha, 16 blocks
  38. // spaces, 32 blocks graphics, (ascii>126) 64 blocks punctuation that isn't
  39. // allowed in a filename/path/drive combo, 128 blocks punctuation that isn't
  40. // allowed in a filename only combo (use w/64), 256 blocks all punctuation.
  41. // (IE non-alphanumerics and spaces) The editing keys supported are as
  42. // follows- Keys to enter characters, Enter/ESC to exit, Home/End to move to
  43. // the front/back of the line, Insert to toggle insert/overwrite, Left/Right
  44. // to move within the line, Bkspace/Delete to delete as usual, and Alt-Bksp
  45. // to clear the entire line. No screen saving is performed. After this
  46. // function, the cursor is automatically off. If password is set, all
  47. // characters appear as x.
  48. // Password character
  49. #define PW_CHAR 42
  50. // Mouse support- Clicking inside string sends cursor there. Clicking
  51. // outside string returns a MOUSE_EVENT to caller without acknowledging
  52. // the event.
  53. // Returns a backspace if attempted at start of line. (and exit_type==2)
  54. // Returns a delete if attempted at end of line. (and exit_type==2)
  55. // If robo_intk is set, only 76 chars are shown and symbols are altered
  56. // on the left/right if there is more to the left/right. Scrolling
  57. // of the line is supported. The current character (1 on) is shown at
  58. // x = 32, y = 0, in color 79, min. 3 chars.
  59. // Also, if robo_intk is set, then ANY line consisting of ONLY semicolons,
  60. // commas, and spaces is returned as a blank line (0 length)
  61. int intake(char *string, int max_len, char x, char y,
  62. unsigned char color, char exit_type, int filter_type,
  63. char password, int *return_x_pos, char robo_intk, char *macro)
  64. {
  65. int currx, key, curr_len, t1, ret;
  66. int macro_position = -1;
  67. int done = 0, place;
  68. char cur_char = 0;
  69. char temp_char;
  70. int in_macro;
  71. static unsigned char ch_sel = 219;
  72. if(macro != NULL)
  73. macro_position = 0;
  74. // Activate cursor
  75. if(insert_on)
  76. cursor_underline();
  77. else
  78. cursor_solid();
  79. // Put cursor at the end of the string...
  80. currx = curr_len = strlen(string);
  81. // ...unless return_x_pos says not to.
  82. if((return_x_pos) && (*return_x_pos < currx))
  83. currx = *return_x_pos;
  84. if(robo_intk && (currx > 75))
  85. move_cursor(77, y);
  86. else
  87. move_cursor(x + currx, y);
  88. if(insert_on)
  89. cursor_underline();
  90. else
  91. cursor_solid();
  92. do
  93. {
  94. // Draw current string
  95. if(password)
  96. {
  97. fill_line(curr_len, x, y, PW_CHAR, color);
  98. }
  99. else
  100. if(!robo_intk)
  101. {
  102. write_string(string, x, y, color, 0);
  103. }
  104. else
  105. {
  106. draw_char('', color, 79, y);
  107. if((curr_len < 76) || (currx < 76))
  108. {
  109. draw_char('', color, 0, y);
  110. if(curr_len < 76)
  111. {
  112. write_line(string, x, y, color, 0);
  113. fill_line(76 - curr_len, x + curr_len, y, 32, color);
  114. }
  115. else
  116. {
  117. temp_char = string[76];
  118. string[76] = 0;
  119. write_line(string, x, y, color, 0);
  120. string[76] = temp_char;
  121. draw_char('¯', color, 79, y);
  122. }
  123. }
  124. else
  125. {
  126. draw_char(' ', color, 77, y);
  127. if(strlen(string + currx - 75) > 78)
  128. {
  129. temp_char = string[currx + 1];
  130. string[currx + 1] = 0;
  131. write_line(string + currx - 75, x, y, color, 0);
  132. string[currx + 1] = temp_char;
  133. }
  134. else
  135. {
  136. write_line(string + currx - 75, x, y, color, 0);
  137. }
  138. draw_char('®', color, 0, y);
  139. if(currx < curr_len)
  140. draw_char('¯', color, 79, y);
  141. }
  142. draw_char(' ', color, 78, y);
  143. }
  144. if(!robo_intk)
  145. {
  146. fill_line(max_len + 1 - curr_len, x + curr_len, y, 32, color);
  147. }
  148. else
  149. {
  150. write_number(currx + 1, 79, 37, 0, 3);
  151. write_number(curr_len + 1, 79, 41, 0, 3);
  152. }
  153. in_macro = 0;
  154. // Get key
  155. if(macro_position != -1)
  156. {
  157. key = macro[macro_position];
  158. cur_char = key;
  159. macro_position++;
  160. if(macro[macro_position] == 0)
  161. macro_position = -1;
  162. if(key == '^')
  163. key = SDLK_RETURN;
  164. }
  165. else
  166. {
  167. update_screen();
  168. update_event_status_delay();
  169. key = get_key(keycode_SDL);
  170. place = 0;
  171. cur_char = get_key(keycode_unicode);
  172. }
  173. if(get_mouse_press())
  174. {
  175. int mouse_x, mouse_y;
  176. get_mouse_position(&mouse_x, &mouse_y);
  177. if((mouse_y == y) && (mouse_x >= x) && (mouse_x <= (x + max_len)))
  178. {
  179. // Yep, reposition cursor.
  180. currx = mouse_x - x;
  181. if(currx > curr_len)
  182. currx = curr_len;
  183. }
  184. else
  185. {
  186. key = -1;
  187. done = 1;
  188. }
  189. }
  190. // Handle key cases
  191. switch(key)
  192. {
  193. case SDLK_ESCAPE:
  194. {
  195. // ESC
  196. if(exit_type > 0)
  197. {
  198. done = 1;
  199. }
  200. break;
  201. }
  202. case SDLK_KP_ENTER:
  203. case SDLK_RETURN:
  204. {
  205. // Enter
  206. done = 1;
  207. break;
  208. }
  209. case SDLK_HOME:
  210. {
  211. if(get_alt_status(keycode_SDL) && robo_intk)
  212. {
  213. done = 1;
  214. }
  215. else
  216. {
  217. // Home
  218. currx = 0;
  219. }
  220. break;
  221. }
  222. case SDLK_END:
  223. {
  224. if(get_alt_status(keycode_SDL) && robo_intk)
  225. {
  226. done = 1;
  227. }
  228. else
  229. {
  230. // End
  231. currx = curr_len;
  232. }
  233. break;
  234. }
  235. case SDLK_LEFT:
  236. {
  237. if(get_ctrl_status(keycode_SDL))
  238. {
  239. // Find nearest space to the left
  240. if(currx)
  241. {
  242. char *current_position = string + currx;
  243. do
  244. {
  245. current_position--;
  246. currx--;
  247. } while(currx && (*current_position != ' '));
  248. }
  249. }
  250. else
  251. {
  252. // Left
  253. if(currx > 0)
  254. currx--;
  255. }
  256. break;
  257. }
  258. case SDLK_RIGHT:
  259. {
  260. if(get_ctrl_status(keycode_SDL))
  261. {
  262. // Find nearest space to the right
  263. if(currx < curr_len)
  264. {
  265. char *current_position = string + currx;
  266. char current_char;
  267. do
  268. {
  269. current_position++;
  270. currx++;
  271. current_char = *current_position;
  272. } while(current_char && (current_char != ' '));
  273. }
  274. }
  275. else
  276. {
  277. // Right
  278. if(currx < curr_len)
  279. currx++;
  280. }
  281. break;
  282. }
  283. case SDLK_F1:
  284. case SDLK_F2:
  285. case SDLK_F3:
  286. case SDLK_F4:
  287. case SDLK_F5:
  288. case SDLK_F6:
  289. case SDLK_F7:
  290. case SDLK_F8:
  291. case SDLK_F9:
  292. case SDLK_F10:
  293. case SDLK_F11:
  294. case SDLK_F12:
  295. case SDLK_UP:
  296. case SDLK_DOWN:
  297. case SDLK_TAB:
  298. case SDLK_PAGEUP:
  299. case SDLK_PAGEDOWN:
  300. {
  301. done = 1;
  302. break;
  303. }
  304. case SDLK_INSERT:
  305. {
  306. if(get_alt_status(keycode_SDL) && robo_intk)
  307. {
  308. done = 1;
  309. }
  310. else
  311. {
  312. // Insert
  313. if(insert_on)
  314. cursor_solid();
  315. else
  316. cursor_underline();
  317. insert_on ^= 1;
  318. }
  319. break;
  320. }
  321. case SDLK_BACKSPACE:
  322. {
  323. // Backspace, at 0 it might exit
  324. if(get_alt_status(keycode_SDL))
  325. {
  326. // Alt-backspace, erase input
  327. curr_len = currx = 0;
  328. string[0] = 0;
  329. }
  330. else
  331. if(currx == 0)
  332. {
  333. if(exit_type == 2)
  334. {
  335. done = 1;
  336. }
  337. }
  338. else
  339. {
  340. // Move all back 1, decreasing string length
  341. memmove(string + currx - 1, string + currx, curr_len - currx + 1);
  342. curr_len--;
  343. // Cursor back one
  344. currx--;
  345. }
  346. break;
  347. }
  348. case SDLK_DELETE:
  349. {
  350. // Delete, at the end might exit
  351. if(currx == curr_len)
  352. {
  353. if(exit_type == 2)
  354. done = 1;
  355. }
  356. else
  357. {
  358. if(curr_len)
  359. {
  360. // Move all back 1, decreasing string length
  361. memmove(string + currx, string + currx + 1, curr_len - currx);
  362. curr_len--;
  363. }
  364. }
  365. break;
  366. }
  367. case SDLK_c:
  368. {
  369. if(get_ctrl_status(keycode_SDL) && robo_intk)
  370. {
  371. done = 1;
  372. }
  373. else
  374. if(get_alt_status(keycode_SDL) && !filter_type)
  375. {
  376. // If alt - C is pressed, choose character
  377. int new_char = char_selection(cur_char);
  378. if(new_char >= 32)
  379. {
  380. cur_char = new_char;
  381. place = 1;
  382. }
  383. else
  384. {
  385. place = 0;
  386. }
  387. }
  388. else
  389. {
  390. place = 1;
  391. }
  392. break;
  393. }
  394. case SDLK_t:
  395. {
  396. if(get_alt_status(keycode_SDL))
  397. {
  398. done = 1;
  399. }
  400. else
  401. {
  402. place = 1;
  403. }
  404. break;
  405. }
  406. case SDLK_l:
  407. case SDLK_g:
  408. case SDLK_d:
  409. {
  410. if(get_ctrl_status(keycode_SDL) && robo_intk)
  411. {
  412. done = 1;
  413. }
  414. else
  415. {
  416. place = 1;
  417. }
  418. break;
  419. }
  420. case SDLK_i:
  421. {
  422. if((get_ctrl_status(keycode_SDL) ||
  423. get_alt_status(keycode_SDL)) && robo_intk)
  424. {
  425. done = 1;
  426. }
  427. else
  428. {
  429. place = 1;
  430. }
  431. break;
  432. }
  433. case SDLK_u:
  434. case SDLK_o:
  435. case SDLK_x:
  436. case SDLK_b:
  437. case SDLK_s:
  438. case SDLK_e:
  439. case SDLK_v:
  440. case SDLK_p:
  441. {
  442. if(get_alt_status(keycode_SDL) && robo_intk)
  443. {
  444. done = 1;
  445. }
  446. else
  447. {
  448. place = 1;
  449. }
  450. break;
  451. }
  452. case SDLK_LSHIFT:
  453. case SDLK_RSHIFT:
  454. case 0:
  455. {
  456. place = 0;
  457. break;
  458. }
  459. default:
  460. {
  461. // Place the char
  462. place = 1;
  463. break;
  464. }
  465. }
  466. if(place)
  467. {
  468. if((cur_char < 32) && (exit_type == 2))
  469. {
  470. done = 1;
  471. key = cur_char;
  472. }
  473. else
  474. // Keycode.. Filter.
  475. if(filter_type & 1)
  476. {
  477. if((cur_char >= 'a') && (cur_char <= 'z'))
  478. cur_char -= 32;
  479. }
  480. if(filter_type & 2)
  481. {
  482. if((cur_char >= 'A') && (cur_char <= 'Z'))
  483. cur_char += 32;
  484. }
  485. // Block numbers
  486. if((filter_type & 4) && ((cur_char >= '0') && (cur_char <= '9')))
  487. {
  488. place = 0;
  489. }
  490. // Block alpha
  491. if((filter_type & 8) &&
  492. (((cur_char >= 'a') && (cur_char <= 'z')) ||
  493. ((cur_char >= 'A') && (cur_char <= 'Z'))))
  494. {
  495. place = 0;
  496. }
  497. // Block spaces
  498. if((filter_type & 16) && (cur_char == ' '))
  499. {
  500. place = 0;
  501. }
  502. // Block high-ASCII
  503. if((filter_type & 32) && (cur_char > 126))
  504. {
  505. place = 0;
  506. }
  507. // Block these chars
  508. if((filter_type & 64) &&
  509. ((cur_char == '*') || (cur_char == '[') ||
  510. (cur_char == ']') || (cur_char == '>') ||
  511. (cur_char == '<') || (cur_char == ',') ||
  512. (cur_char == '|') || (cur_char == '?') ||
  513. (cur_char == '=') || (cur_char == ';') ||
  514. (cur_char == '\"') || (cur_char =='/')))
  515. {
  516. place = 0;
  517. }
  518. // Block these chars
  519. if((filter_type & 128) &&
  520. ((cur_char == ':') || (cur_char == '\\')))
  521. {
  522. place = 0;
  523. }
  524. // Block these chars
  525. if((filter_type & 256) &&
  526. (((cur_char > ' ') && (cur_char < '0')) ||
  527. ((cur_char > '9') && (cur_char < 'A')) ||
  528. ((cur_char > 'Z') && (cur_char < 'a')) ||
  529. ((cur_char > 'z') && (cur_char < 127))))
  530. {
  531. place = 0;
  532. }
  533. // Now, can it still be placed?
  534. if(place && (curr_len != max_len) && (!done) && cur_char)
  535. {
  536. // Overwrite or insert?
  537. if((insert_on) || (currx == curr_len))
  538. {
  539. // Insert- Move all ahead 1, increasing string length
  540. curr_len++;
  541. memmove(string + currx + 1, string + currx, curr_len - currx);
  542. }
  543. // Add character and move forward one
  544. string[currx++] = cur_char;
  545. }
  546. }
  547. // Move cursor
  548. if(robo_intk && (currx > 75))
  549. move_cursor(77, y);
  550. else
  551. move_cursor(x + currx, y);
  552. if(insert_on)
  553. cursor_underline();
  554. else
  555. cursor_solid();
  556. // Loop
  557. } while(!done);
  558. cursor_off();
  559. if(return_x_pos)
  560. *return_x_pos = currx;
  561. // Return ret. If robo_intk, verify that the string is valid
  562. if(robo_intk)
  563. {
  564. curr_len = strlen(string);
  565. if(curr_len)
  566. {
  567. for(t1 = 0; t1 < curr_len; t1++)
  568. {
  569. if((string[t1] != ';') && (string[t1] != ',') &&
  570. (string[t1] != ' '))
  571. break;
  572. }
  573. if(t1 >= curr_len)
  574. {
  575. string[0] = 0; // Become an empty string
  576. if(return_x_pos)
  577. *return_x_pos = 0;
  578. }
  579. }
  580. }
  581. return key;
  582. }