intake.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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 "mouse.h"
  23. #include "beep.h"
  24. #include "intake.h"
  25. #include "graphics.h"
  26. #include "getkey.h"
  27. #include "cursor.h"
  28. #include "string.h"
  29. #include "window.h"
  30. #include "hexchar.h"
  31. // Global status of insert
  32. char insert_on=1;
  33. // (returns the key used to exit) String points to your memory for storing
  34. // the new string. The current "value" is used- clear the string before
  35. // calling intake if you need a blank string. Max_len is the maximum length
  36. // of the string. X, y, segment, and color are self-explanitory. Exit_type
  37. // determines when intake exits- 0 means exit only on Enter, 1 on Enter or
  38. // ESC, 2 on any non-display char except the editing keys. Filter_type is
  39. // bits to turn on filters- 1 changes all alpha to upper, 2 changes all
  40. // alpha to lower, 4 blocks all numbers, 8 blocks all alpha, 16 blocks
  41. // spaces, 32 blocks graphics, (ascii>126) 64 blocks punctuation that isn't
  42. // allowed in a filename/path/drive combo, 128 blocks punctuation that isn't
  43. // allowed in a filename only combo (use w/64), 256 blocks all punctuation.
  44. // (IE non-alphanumerics and spaces) The editing keys supported are as
  45. // follows- Keys to enter characters, Enter/ESC to exit, Home/End to move to
  46. // the front/back of the line, Insert to toggle insert/overwrite, Left/Right
  47. // to move within the line, Bkspace/Delete to delete as usual, and Alt-Bksp
  48. // to clear the entire line. No screen saving is performed. After this
  49. // function, the cursor is automatically off. If password is set, all
  50. // characters appear as x.
  51. //Password character
  52. #define PW_CHAR 42
  53. //Mouse support- Clicking inside string sends cursor there. Clicking
  54. //outside string returns a MOUSE_EVENT to caller without acknowledging
  55. //the event.
  56. //Returns a backspace if attempted at start of line. (and exit_type==2)
  57. //Returns a delete if attempted at end of line. (and exit_type==2)
  58. //If robo_intk is set, only 76 chars are shown and symbols are altered
  59. //on the far left/right if there is more to the left/right. Scrolling
  60. //of the line is supported. The current character (1 on) is shown at
  61. //x=32,y=0, in color 79, min. 3 chars.
  62. //Also, if robo_intk is set, then ANY line consisting of ONLY semicolons,
  63. //commas, and spaces is returned as a blank line (0 length)
  64. int intake(char far *string,int max_len,char x,char y,unsigned int segment,
  65. unsigned char color,char exit_type,int filter_type,char password,
  66. int *return_x_pos,char robo_intk,char far *macro) {
  67. int currx,key,curr_len,t1,ret;
  68. int macron=-1;
  69. static unsigned char ch_sel=219;
  70. if(macro!=NULL) macron=0;
  71. //Turn off auto acknowledge of mouse events
  72. auto_pop_mouse_events=0;
  73. //Activate cursor
  74. if(insert_on) cursor_underline();
  75. else cursor_solid();
  76. //Put cursor at the end of the string...
  77. currx=curr_len=str_len(string);
  78. //...unless return_x_pos says not to.
  79. if(return_x_pos)
  80. if(*return_x_pos<currx) currx=*return_x_pos;
  81. if(robo_intk&&(currx>75)) move_cursor(77,y);
  82. else move_cursor(x+currx,y);
  83. if(insert_on) cursor_underline();
  84. else cursor_solid();
  85. do {
  86. //Draw current string
  87. m_hide();
  88. if(password) fill_line(curr_len,x,y,(color<<8)+PW_CHAR,segment);
  89. else if(!robo_intk) write_string(string,x,y,color,segment,0);
  90. else {
  91. draw_char('',color,79,y,segment);
  92. if((curr_len<76)||(currx<76)) {
  93. draw_char('',color,0,y,segment);
  94. write_line(string,x,y,color,segment,0);
  95. if(curr_len<76)
  96. fill_line(76-curr_len,x+curr_len,y,(color<<8)+32,segment);
  97. else draw_char('¯',color,79,y,segment);
  98. }
  99. else {
  100. draw_char(' ',color,77,y,segment);
  101. write_line(&string[currx-75],x,y,color,segment,0);
  102. draw_char('®',color,0,y,segment);
  103. if(currx<curr_len) draw_char('¯',color,79,y,segment);
  104. }
  105. draw_char(' ',color,78,y,segment);
  106. }
  107. if(!robo_intk) fill_line(max_len+1-curr_len,x+curr_len,y,(color<<8)+32,segment);
  108. if(robo_intk) {
  109. write_number(currx+1,79,32,0,segment,3);
  110. write_number(curr_len,79,36,0,segment,3);
  111. }
  112. m_show();
  113. //Get key
  114. if(macron>=0) {
  115. key=macro[macron++];
  116. if(macro[macron]==0) macron=-1;
  117. if(key=='^') key=13;
  118. else goto text_place;
  119. }
  120. else key=getkey();
  121. //Process
  122. switch(key) {
  123. case MOUSE_EVENT:
  124. //In our string?
  125. t1=mouse_event.cx;
  126. if((mouse_event.cy==y)&&(t1>=x)&&(t1<=x+max_len)) {
  127. //Yep, reposition cursor and acknowledge event.
  128. currx=t1-x;
  129. if(currx>curr_len) currx=curr_len;
  130. acknowledge_mouse();
  131. break;
  132. }
  133. //Nope- exit or beep, depending upon exit_type.
  134. //(first, acknowledge event if exit_type is too low)
  135. if(exit_type<2) acknowledge_mouse();
  136. default:
  137. //Exit key or keycode.
  138. if(key<32) {
  139. keyer:
  140. //Exit?
  141. if(exit_type==2) {
  142. auto_pop_mouse_events=1;
  143. cursor_off();
  144. if(return_x_pos) *return_x_pos=currx;
  145. ret=key;
  146. goto rett;
  147. }
  148. else beep();
  149. break;
  150. }
  151. //Keycode.. Filter.
  152. if(filter_type&1) {
  153. if((key>='a')&&(key<='z')) key-=32;
  154. }
  155. if(filter_type&2) {
  156. if((key>='A')&&(key<='Z')) key+=32;
  157. }
  158. if(filter_type&4) {
  159. if((key>='0')&&(key<='9')) {
  160. beep();
  161. break;
  162. }
  163. }
  164. if(filter_type&8) {
  165. if((key>='a')&&(key<='z')) {
  166. beep();
  167. break;
  168. }
  169. if((key>='A')&&(key<='Z')) {
  170. beep();
  171. break;
  172. }
  173. }
  174. if(filter_type&16) {
  175. if(key==' ') {
  176. beep();
  177. break;
  178. }
  179. }
  180. if(filter_type&32) {
  181. if(key>126) {
  182. beep();
  183. break;
  184. }
  185. }
  186. if(filter_type&64) {
  187. if((key=='*')||(key=='[')||(key==']')||(key=='>')||
  188. (key=='<')||(key==',')||(key=='|')||(key=='?')||
  189. (key=='=')||(key==';')||(key=='\"')||(key=='/')) {
  190. beep();
  191. break;
  192. }
  193. }
  194. if(filter_type&128) {
  195. if((key==':')||(key=='\\')) {
  196. beep();
  197. break;
  198. }
  199. }
  200. if(filter_type&256) {
  201. if((key>' ')&&(key<'0')) {
  202. beep();
  203. break;
  204. }
  205. if((key>'9')&&(key<'A')) {
  206. beep();
  207. break;
  208. }
  209. if((key>'Z')&&(key<'a')) {
  210. beep();
  211. break;
  212. }
  213. if((key>'z')&&(key<127)) {
  214. beep();
  215. break;
  216. }
  217. }
  218. //Add key to string
  219. text_place:
  220. if(currx==max_len) {
  221. beep();
  222. break;//At end of str
  223. }
  224. if((insert_on)&&(curr_len==max_len)) {
  225. beep();
  226. break;//No room to insert
  227. }
  228. //Overwrite or insert?
  229. if((insert_on)||(currx==curr_len)) {
  230. //Insert- Move all ahead 1, increasing string length
  231. mem_mov(&string[currx+1],&string[currx],(++curr_len)-currx,1);
  232. }
  233. //Add character and move forward one
  234. string[currx++]=key;
  235. break;
  236. case -46:
  237. //Alt+C choose character
  238. if(filter_type) {
  239. beep();
  240. break;
  241. }
  242. ch_sel=key=char_selection(ch_sel,segment);
  243. if(key<32) break;
  244. goto text_place;
  245. case 27:
  246. //ESC
  247. if(exit_type>0) {
  248. cursor_off();
  249. auto_pop_mouse_events=1;
  250. if(return_x_pos) *return_x_pos=currx;
  251. ret=27;
  252. goto rett;
  253. }
  254. beep();
  255. break;
  256. case 13:
  257. //Enter
  258. cursor_off();
  259. auto_pop_mouse_events=1;
  260. if(return_x_pos) *return_x_pos=currx;
  261. ret=13;
  262. goto rett;
  263. case -71:
  264. //Home
  265. if(currx==0) goto keyer;
  266. currx=0;
  267. break;
  268. case -79:
  269. //End
  270. if(currx==curr_len) goto keyer;
  271. currx=curr_len;
  272. break;
  273. case -14:
  274. //Alt-Bkspace
  275. curr_len=currx=0;
  276. string[0]=0;
  277. break;
  278. case -75:
  279. //Left
  280. if(currx>0) currx--;
  281. break;
  282. case -77:
  283. //Right
  284. if(currx<curr_len) currx++;
  285. break;
  286. case -82:
  287. //Insert
  288. if(insert_on) cursor_solid();
  289. else cursor_underline();
  290. insert_on^=1;
  291. break;
  292. case 8:
  293. //Bkspace
  294. if(currx==0) {
  295. if(exit_type==2) {
  296. auto_pop_mouse_events=1;
  297. cursor_off();
  298. if(return_x_pos) *return_x_pos=currx;
  299. ret=8;
  300. goto rett;
  301. }
  302. beep();
  303. break;
  304. }
  305. //Move all back 1, decreasing string length
  306. mem_mov(&string[currx-1],&string[currx],(curr_len--)-currx+1,0);
  307. //Cursor back one
  308. currx--;
  309. case 0:
  310. break;
  311. case -83:
  312. //Delete
  313. if(currx==curr_len) {
  314. if(exit_type==2) {
  315. auto_pop_mouse_events=1;
  316. cursor_off();
  317. if(return_x_pos) *return_x_pos=currx;
  318. ret=-83;
  319. goto rett;
  320. }
  321. beep();
  322. break;
  323. }
  324. //Move all back 1, decreasing string length
  325. mem_mov(&string[currx],&string[currx+1],(curr_len--)-currx,0);
  326. break;
  327. }
  328. //Move cursor
  329. if(robo_intk&&(currx>75)) move_cursor(77,y);
  330. else move_cursor(x+currx,y);
  331. if(insert_on) cursor_underline();
  332. else cursor_solid();
  333. //Loop
  334. } while(1);
  335. rett:
  336. //Return ret. If robo_intk, verify that the string is valid
  337. if(robo_intk) {
  338. curr_len=str_len(string);
  339. if(curr_len) {
  340. for(t1=0;t1<curr_len;t1++)
  341. if((string[t1]!=';')&&(string[t1]!=',')&&(string[t1]!=' '))
  342. break;
  343. if(t1>=curr_len) {
  344. string[0]=0;//Become an empty string
  345. if(return_x_pos) *return_x_pos=0;
  346. }
  347. }
  348. }
  349. return ret;
  350. }