This is the open source Pawn interpreter ported to mbed. See here: http://www.compuphase.com/pawn/pawn.htm and here: http://code.google.com/p/pawnscript/
amxcons.c
00001 /* Console output module (terminal I/O) for the Pawn AMX 00002 * 00003 * Since some of these routines go further than those of standard C, they 00004 * cannot always be implemented with portable C functions. In other words, 00005 * these routines must be ported to other environments. 00006 * 00007 * Copyright (c) ITB CompuPhase, 1997-2011 00008 * 00009 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 00010 * use this file except in compliance with the License. You may obtain a copy 00011 * of the License at 00012 * 00013 * http://www.apache.org/licenses/LICENSE-2.0 00014 * 00015 * Unless required by applicable law or agreed to in writing, software 00016 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00017 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 00018 * License for the specific language governing permissions and limitations 00019 * under the License. 00020 * 00021 * Version: $Id: amxcons.c 4523 2011-06-21 15:03:47Z thiadmer $ 00022 */ 00023 00024 #if defined _UNICODE || defined __UNICODE__ || defined UNICODE 00025 # if !defined UNICODE /* for Windows */ 00026 # define UNICODE 00027 # endif 00028 # if !defined _UNICODE /* for C library */ 00029 # define _UNICODE 00030 # endif 00031 #endif 00032 00033 #include <limits.h> 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <string.h> 00037 #include <assert.h> 00038 #if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined __MSDOS__ 00039 #define HAVE_CONIO 00040 #include <conio.h> 00041 #include <malloc.h> 00042 #endif 00043 #if defined USE_CURSES || defined HAVE_CURSES_H 00044 #include <curses.h> 00045 #if !defined CURSES 00046 #define CURSES 1 00047 #endif 00048 #endif 00049 #include "osdefs.h" 00050 #if defined __ECOS__ 00051 /* eCos puts include files in cyg/package_name */ 00052 #include <cyg/hal/hal_if.h> 00053 #include <cyg/infra/diag.h> 00054 #include <cyg/hal/hal_diag.h> 00055 #include <cyg/pawn/amx.h> 00056 #else 00057 #include "amx.h" 00058 #endif 00059 #if defined __WIN32__ || defined _WIN32 || defined WIN32 00060 #include <windows.h> 00061 #endif 00062 00063 #if defined _UNICODE 00064 # include <tchar.h> 00065 #elif !defined __T 00066 typedef char TCHAR; 00067 # define __T(string) string 00068 # define _fgetts fgets 00069 # define _puttchar putchar 00070 # define _stprintf sprintf 00071 # define _tcschr strchr 00072 # define _tcscpy strcpy 00073 # define _tcsdup strdup 00074 # define _tcslen strlen 00075 # define _tprintf printf 00076 #endif 00077 #include "amxcons.h" 00078 00079 #if defined AMX_TERMINAL 00080 #define EOL_CHAR '\r' 00081 #endif 00082 #if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined __MSDOS__ 00083 #define EOL_CHAR '\r' 00084 #endif 00085 #if !defined EOL_CHAR 00086 /* if not a "known" operating system, assume Linux/Unix */ 00087 #define EOL_CHAR '\n' 00088 #endif 00089 00090 #if !defined AMX_STRING_LIB 00091 00092 #if defined AMX_TERMINAL 00093 /* required functions are implemented elsewhere */ 00094 int amx_putstr(const TCHAR *); 00095 int amx_putchar(int); 00096 int amx_fflush(void); 00097 int amx_getch(void); 00098 TCHAR *amx_gets(TCHAR *,int); 00099 int amx_termctl(int,int); 00100 void amx_clrscr(void); 00101 void amx_clreol(void); 00102 int amx_gotoxy(int x,int y); 00103 void amx_wherexy(int *x,int *y); 00104 unsigned int amx_setattr(int foregr,int backgr,int highlight); 00105 void amx_console(int columns, int lines, int flags); 00106 void amx_viewsize(int *width,int *height); 00107 int amx_kbhit(void); 00108 #elif defined CURSES && CURSES != 0 00109 /* Use the "curses" library to implement the console */ 00110 static WINDOW *curseswin; 00111 #define amx_putstr(s) printw("%s",(s)) 00112 #define amx_putchar(c) addch(c) 00113 #define amx_fflush() refresh() 00114 #define amx_getch() getch() 00115 #define amx_gets(s,n) getnstr((s),(n)) 00116 #define amx_clrscr() clear() 00117 #define amx_clreol() clrtoeol() 00118 #define amx_gotoxy(x,y) move((y)-1,(x)-1) 00119 #define amx_console(c,l,f) ((void)(c),(void)(l),(void)(f)) 00120 unsigned int amx_setattr(int foregr,int backgr,int highlight) 00121 { 00122 int attribs=A_NORMAL; 00123 if (highlight>0) 00124 attribs=(attribs & ~A_NORMAL) | A_STANDOUT; 00125 attrset(attribs); 00126 //??? in future, also handle colours 00127 } 00128 void CreateConsole(void); 00129 int amx_kbhit(void) 00130 { 00131 int result; 00132 CreateConsole(); 00133 nodelay(curseswin,TRUE); /* enter non-blocking state */ 00134 result=getch(); /* read key (if any) */ 00135 nodelay(curseswin,FALSE); /* leave non-blocking state */ 00136 if (result!=ERR) 00137 ungetch(result); /* a key is waiting, push it back */ 00138 return (result==ERR) ? 0 : 1; 00139 } 00140 int amx_termctl(int code,int value) 00141 { 00142 switch (code) { 00143 case 0: /* query terminal support */ 00144 return 1; 00145 /* case 1: */ /* switch auto-wrap on/off (not supported in curses!) */ 00146 /* case 2: */ /* create/switch to another console */ 00147 case 3: /* set emphasized font */ 00148 if (value) 00149 attron(A_BOLD); 00150 else 00151 attroff(A_BOLD); 00152 return 1; 00153 /* case 4: */ /* query whether a terminal is "open" */ 00154 default: 00155 return 0; 00156 } /* switch */ 00157 } 00158 void amx_wherexy(int *x,int *y) 00159 { 00160 int row,col; 00161 getyx(curseswin,row,col); 00162 if (x!=NULL) 00163 *x=col+1; 00164 if (y!=NULL) 00165 *y=row+1; 00166 } 00167 void amx_viewsize(int *width,int *height) 00168 { 00169 int row,col; 00170 getmaxyx(curseswin,row,col); 00171 if (width!=NULL) 00172 *width=col; 00173 if (height!=NULL) 00174 *height=row; 00175 } 00176 #elif defined VT100 || defined __LINUX__ || defined ANSITERM || defined __ECOS__ 00177 /* ANSI/VT100 terminal, or shell emulating "xterm" */ 00178 #if defined __ECOS__ 00179 #define AMXCONSOLE_NOIDLE 00180 #endif 00181 00182 #if CYGPKG_PAWN_AMXCONSOLE_DIAG==1 00183 /* eCos has basically two ways to make simple exchanges with a terminal: 00184 * - with the diag_*() functions (no input provided!) 00185 * - with f*() functions (fprintf(),fputs(), etc). 00186 */ 00187 #define amx_fflush() 00188 00189 static int amx_putstr(TCHAR *s) 00190 { 00191 diag_write_string(s); 00192 return 1; 00193 } 00194 static int amx_putchar(TCHAR c) 00195 { 00196 diag_write_char(c); 00197 return c; 00198 } 00199 static char amx_getch(void) 00200 { 00201 char c=-1; 00202 HAL_DIAG_READ_CHAR(c); 00203 return c; 00204 } 00205 #else 00206 00207 #define amx_putstr(s) fputs((s),stdout) 00208 #define amx_putchar(c) putchar(c) 00209 #define amx_fflush() fflush(stdout) 00210 #define amx_getch() getch() 00211 #define amx_gets(s,n) fgets(s,n,stdin) 00212 #define amx_kbhit() kbhit() 00213 #endif 00214 00215 int amx_termctl(int code,int value) 00216 { 00217 switch (code) { 00218 case 0: /* query terminal support */ 00219 return 1; 00220 00221 case 1: /* switch "auto-wrap" on or off */ 00222 if (value) 00223 amx_putstr("\033[?7h"); /* enable "auto-wrap" */ 00224 else 00225 amx_putstr("\033[?7l"); /* disable "auto-wrap" */ 00226 return 1; 00227 00228 #if 0 00229 /* next to swapping buffers, more information should be saved and swapped, 00230 * such as the cursor position and the current terminal attributes 00231 */ 00232 case 2: /* swap console buffers */ 00233 amx_fflush(); 00234 if (value==1) { 00235 amx_putstr("\033[?47h"); 00236 } else { 00237 amx_putstr("\033[?47l"); 00238 } /* if */ 00239 amx_fflush(); 00240 return 1; 00241 #endif 00242 00243 case 3: /* set bold/highlighted font */ 00244 return 0; 00245 00246 default: 00247 return 0; 00248 } /* switch */ 00249 } 00250 void amx_clrscr(void) 00251 { 00252 amx_putstr("\033[2J"); 00253 amx_fflush(); /* pump through the terminal codes */ 00254 } 00255 void amx_clreol(void) 00256 { 00257 amx_putstr("\033[K"); 00258 amx_fflush(); /* pump through the terminal codes */ 00259 } 00260 int amx_gotoxy(int x,int y) 00261 { 00262 char str[30]; 00263 _stprintf(str,"\033[%d;%dH",y,x); 00264 amx_putstr(str); 00265 amx_fflush(); /* pump through the terminal codes */ 00266 return 1; 00267 } 00268 void amx_wherexy(int *x,int *y) 00269 { 00270 int val,i; 00271 char str[10]; 00272 00273 assert(x!=NULL && y!=NULL); 00274 amx_putstr("\033[6n"); 00275 amx_fflush(); 00276 while (amx_getch()!='\033') 00277 /* nothing */; 00278 val=amx_getch(); 00279 assert(val=='['); 00280 for (i=0; i<8 && (val=amx_getch())!=';'; i++) 00281 str[i]=(char)val; 00282 str[i]='\0'; 00283 if (y!=NULL) 00284 *y=atoi(str); 00285 for (i=0; i<8 && (val=amx_getch())!='R'; i++) 00286 str[i]=(char)val; 00287 str[i]='\0'; 00288 if (x!=NULL) 00289 *x=atoi(str); 00290 #if defined ANSITERM 00291 val=amx_getch(); 00292 assert(val=='\r'); /* ANSI driver adds CR to the end of the command */ 00293 #endif 00294 } 00295 unsigned int amx_setattr(int foregr,int backgr,int highlight) 00296 { 00297 static short current=(0 << 8) | 7; 00298 short prev = current; 00299 char str[30]; 00300 00301 if (foregr>=0) { 00302 _stprintf(str,"\x1b[%dm",foregr+30); 00303 amx_putstr(str); 00304 current=(current & 0xff00) | (foregr & 0x0f); 00305 } /* if */ 00306 if (backgr>=0) { 00307 _stprintf(str,"\x1b[%dm",backgr+40); 00308 amx_putstr(str); 00309 current=(current & 0x00ff) | ((backgr & 0x0f) << 8); 00310 } /* if */ 00311 if (highlight>=0) { 00312 _stprintf(str,"\x1b[%dm",highlight); 00313 amx_putstr(str); 00314 current=(current & 0x7fff) | ((highlight & 0x01) << 15); 00315 } /* if */ 00316 return prev; 00317 } 00318 void amx_console(int columns, int lines, int flags) 00319 { 00320 char str[30]; 00321 00322 (void)flags; 00323 /* There is no ANSI code (or VT100/VT220) to set the size of the console 00324 * (indeed, the terminal was that of the alphanumeric display). In xterm (a 00325 * terminal emulator) we can set the terminal size though, and most 00326 * terminals that in use today are in fact emulators. 00327 * Putty understands this code too, by many others do not. 00328 */ 00329 sprintf(str,"\033[8;%d;%dt",lines,columns); 00330 amx_putstr(str); 00331 amx_fflush(); 00332 } 00333 void amx_viewsize(int *width,int *height) 00334 { 00335 /* a trick to get the size of the terminal is to position the cursor far 00336 * away and then read it back 00337 */ 00338 amx_gotoxy(999,999); 00339 amx_wherexy(width,height); 00340 } 00341 #elif defined __WIN32__ || defined _WIN32 || defined WIN32 00342 /* Win32 console */ 00343 #define amx_putstr(s) _tprintf("%s",(s)) 00344 #define amx_putchar(c) _puttchar(c) 00345 #define amx_fflush() fflush(stdout) 00346 #define amx_getch() getch() 00347 #define amx_gets(s,n) _fgetts(s,n,stdin) 00348 #define amx_kbhit() kbhit() 00349 00350 int amx_termctl(int code,int value) 00351 { 00352 switch (code) { 00353 case 0: /* query terminal support */ 00354 return 1; 00355 00356 case 1: { /* switch auto-wrap on/off */ 00357 /* only works in Windows 2000/XP */ 00358 HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE); 00359 DWORD Flags=ENABLE_PROCESSED_OUTPUT; 00360 if (value) 00361 Flags |= ENABLE_WRAP_AT_EOL_OUTPUT; 00362 SetConsoleMode(hConsole,Flags); 00363 return 1; 00364 } /* case */ 00365 00366 /* case 2: */ /* create/switch to another console */ 00367 /* case 3: */ /* set emphasized font */ 00368 /* case 4: */ /* query whether a terminal is "open" */ 00369 default: 00370 return 0; 00371 } /* switch */ 00372 } 00373 void amx_clrscr(void) 00374 { 00375 COORD coordScreen={0,0}; 00376 DWORD cCharsWritten; 00377 CONSOLE_SCREEN_BUFFER_INFO csbi; 00378 DWORD dwConSize; 00379 HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE); 00380 00381 amx_fflush(); /* make sure the I/O buffer is empty */ 00382 GetConsoleScreenBufferInfo(hConsole,&csbi); 00383 dwConSize=csbi.dwSize.X*csbi.dwSize.Y; 00384 FillConsoleOutputCharacter(hConsole,' ',dwConSize,coordScreen,&cCharsWritten); 00385 FillConsoleOutputAttribute(hConsole,csbi.wAttributes,dwConSize,coordScreen, &cCharsWritten); 00386 SetConsoleCursorPosition(hConsole,coordScreen); 00387 } 00388 void amx_clreol(void) 00389 { 00390 DWORD cCharsWritten; 00391 CONSOLE_SCREEN_BUFFER_INFO csbi; 00392 DWORD dwConSize; 00393 HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE); 00394 00395 amx_fflush(); /* make sure all output is written */ 00396 GetConsoleScreenBufferInfo(hConsole,&csbi); 00397 dwConSize=csbi.dwSize.X - csbi.dwCursorPosition.X; 00398 FillConsoleOutputCharacter(hConsole,' ',dwConSize,csbi.dwCursorPosition,&cCharsWritten); 00399 FillConsoleOutputAttribute(hConsole,csbi.wAttributes,dwConSize,csbi.dwCursorPosition,&cCharsWritten); 00400 } 00401 int amx_gotoxy(int x,int y) 00402 { 00403 COORD point; 00404 CONSOLE_SCREEN_BUFFER_INFO csbi; 00405 HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE); 00406 00407 GetConsoleScreenBufferInfo(hConsole, &csbi); 00408 if (x<=0 || x>csbi.dwSize.X || y<=0 || y>csbi.dwSize.Y) 00409 return 0; 00410 amx_fflush(); /* make sure all output is written */ 00411 point.X=(short)(x-1); 00412 point.Y=(short)(y-1); 00413 SetConsoleCursorPosition(hConsole,point); 00414 return 1; 00415 } 00416 void amx_wherexy(int *x,int *y) 00417 { 00418 CONSOLE_SCREEN_BUFFER_INFO csbi; 00419 amx_fflush(); /* make sure all output is written */ 00420 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); 00421 if (x!=NULL) 00422 *x=csbi.dwCursorPosition.X+1; 00423 if (y!=NULL) 00424 *y=csbi.dwCursorPosition.Y+1; 00425 } 00426 unsigned int amx_setattr(int foregr,int backgr,int highlight) 00427 { 00428 static int ansi_colours[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 00429 CONSOLE_SCREEN_BUFFER_INFO csbi; 00430 int f,b,h,prev; 00431 HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE); 00432 00433 amx_fflush(); /* make sure all output is written */ 00434 GetConsoleScreenBufferInfo(hConsole,&csbi); 00435 f=csbi.wAttributes & 0x07; 00436 b=(csbi.wAttributes >> 4) & 0x0f; 00437 h=(csbi.wAttributes & 0x08) ? 1 : 0; 00438 prev=(b << 8) | f | (h << 15); 00439 if (foregr>=0 && foregr<8) 00440 f=ansi_colours[foregr]; 00441 if (backgr>=0 && backgr<8) 00442 b=ansi_colours[backgr]; 00443 if (highlight>=0) 00444 h=highlight!=0; 00445 SetConsoleTextAttribute(hConsole, (WORD)((b << 4) | f | (h << 3))); 00446 return prev; 00447 } 00448 void amx_console(int columns, int lines, int flags) 00449 { 00450 SMALL_RECT rect; 00451 COORD dwSize; 00452 (void)flags; 00453 dwSize.X=(short)columns; 00454 dwSize.Y=(short)lines; 00455 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),dwSize); 00456 rect.Left=0; 00457 rect.Top=0; 00458 rect.Right=(short)(columns-1); 00459 rect.Bottom=(short)(lines-1); 00460 SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE),TRUE,&rect); 00461 } 00462 void amx_viewsize(int *width,int *height) 00463 { 00464 CONSOLE_SCREEN_BUFFER_INFO csbi; 00465 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&csbi); 00466 if (width!=NULL) 00467 *width=(int)csbi.dwSize.X; 00468 if (height!=NULL) 00469 *height=(int)(csbi.srWindow.Bottom-csbi.srWindow.Top+1); 00470 } 00471 #else 00472 /* assume a streaming terminal; limited features (no colour, no cursor 00473 * control) 00474 */ 00475 #define amx_putstr(s) printf("%s",(s)) 00476 #define amx_putchar(c) putchar(c) 00477 #define amx_fflush() fflush(stdout) 00478 #define amx_gets(s,n) fgets(s,n,stdin) 00479 #define amx_clrscr() (void)(0) 00480 #define amx_clreol() (void)(0) 00481 #define amx_gotoxy(x,y) ((void)(x),(void)(y),(0)) 00482 #define amx_wherexy(x,y) (*(x)=*(y)=0) 00483 #define amx_setattr(c,b,h) ((void)(c),(void)(b),(void)(h),(0)) 00484 #define amx_termctl(c,v) ((void)(c),(void)(v),(0)) 00485 #define amx_console(c,l,f) ((void)(c),(void)(l),(void)(f)) 00486 #define amx_viewsize (*(x)=80,*(y)=25) 00487 #if defined HAVE_CONIO 00488 #define amx_getch() getch() 00489 #define amx_kbhit() kbhit() 00490 #else 00491 #define amx_getch() getchar() 00492 #define amx_kbhit() (0) 00493 #endif 00494 #endif 00495 00496 #if !defined AMX_TERMINAL && (defined __WIN32__ || defined _WIN32 || defined WIN32) 00497 void CreateConsole(void) 00498 { static int createdconsole=0; 00499 if (!createdconsole) { 00500 AllocConsole(); 00501 createdconsole=1; 00502 } /* if */ 00503 } 00504 #elif defined CURSES && CURSES != 0 00505 // The Mac OS X build variant uses curses. 00506 void CreateConsole(void) 00507 { static int createdconsole=0; 00508 if (!createdconsole) { 00509 curseswin=initscr(); 00510 cbreak(); 00511 noecho(); 00512 nonl(); 00513 scrollok(curseswin,TRUE); 00514 intrflush(curseswin,FALSE); 00515 keypad(curseswin,TRUE); 00516 createdconsole=1; 00517 } /* if */ 00518 } 00519 #else 00520 #define CreateConsole() 00521 #endif 00522 00523 static int cons_putstr(void *dest,const TCHAR *str) 00524 { 00525 (void)dest; 00526 return amx_putstr(str); 00527 } 00528 00529 static int cons_putchar(void *dest,TCHAR ch) 00530 { 00531 (void)dest; 00532 return amx_putchar(ch); 00533 } 00534 00535 #endif /* AMX_STRING_LIB */ 00536 00537 enum { 00538 SV_DECIMAL, 00539 SV_HEX 00540 }; 00541 00542 static TCHAR *reverse(TCHAR *string,int stop) 00543 { 00544 int start=0; 00545 TCHAR temp; 00546 00547 /* swap the string */ 00548 stop--; /* avoid swapping the '\0' byte to the first position */ 00549 while (stop - start > 0) { 00550 temp = string[start]; 00551 string[start] = string[stop]; 00552 string[stop] = temp; 00553 start++; 00554 stop--; 00555 } /* while */ 00556 return string; 00557 } 00558 00559 /* Converts an integral value to a string, with optional padding with spaces or 00560 * zeros. 00561 * The "format" must be decimal or hexadecimal 00562 * The number is right-aligned in the field with the size of the absolute value 00563 * of the "width" parameter. 00564 * If the width value is positive, the string is padded with spaces; if it is 00565 * negative, it is padded with zeros. 00566 */ 00567 static TCHAR *amx_strval(TCHAR buffer[], long value, int format, int width) 00568 { 00569 int start, stop; 00570 TCHAR temp; 00571 00572 start = stop = 0; 00573 if (format == SV_DECIMAL) { 00574 if (value < 0) { 00575 buffer[0] = __T('-'); 00576 start = stop = 1; 00577 value = -value; 00578 } /* if */ 00579 do { 00580 buffer[stop++] = (TCHAR)((value % 10) + __T('0')); 00581 value /= 10; 00582 } while (value > 0); 00583 } else { 00584 /* hexadecimal */ 00585 unsigned long v = (unsigned long)value; /* copy to unsigned value for shifting */ 00586 do { 00587 buffer[stop] = (TCHAR)((v & 0x0f) + __T('0')); 00588 if (buffer[stop] > __T('9')) 00589 buffer[stop] += (TCHAR)(__T('A') - __T('0') - 10); 00590 v >>= 4; 00591 stop++; 00592 } while (v != 0); 00593 } /* if */ 00594 00595 /* pad to given width */ 00596 if (width < 0) { 00597 temp = __T('0'); 00598 width = -width; 00599 } else { 00600 temp = __T(' '); 00601 } /* if */ 00602 while (stop < width) 00603 buffer[stop++] = temp; 00604 00605 buffer[stop] = __T('\0'); 00606 00607 /* swap the string, and we are done */ 00608 reverse(buffer+start,stop-start); 00609 return buffer; 00610 } 00611 00612 #if defined FIXEDPOINT 00613 #define FIXEDMULT 1000 00614 #define FIXEDDIGITS 3 00615 00616 static TCHAR *formatfixed(TCHAR *string,cell value,TCHAR align,int width,TCHAR decpoint,int digits,TCHAR filler) 00617 { 00618 int i, len; 00619 cell ipart,v; 00620 TCHAR vsign=__T('\0'); 00621 00622 /* make the value positive (but keep the sign) */ 00623 if (value<0) { 00624 value=-value; 00625 vsign=__T('-'); 00626 } /* if */ 00627 00628 /* "prepare" the value so that when it is truncated to the requested 00629 * number of digits, the result is rounded towards the dropped digits 00630 */ 00631 assert(digits<INT_MAX); 00632 v=FIXEDMULT/2; 00633 for (i=0; i<digits; i++) 00634 v/=10; 00635 value+=v; 00636 00637 /* get the integer part and remove it from the value */ 00638 ipart=value/FIXEDMULT; 00639 value-=FIXEDMULT*ipart; 00640 assert(ipart>=0); 00641 assert(value>=0); 00642 00643 /* truncate the fractional part to the requested number of digits */ 00644 for (i=FIXEDDIGITS; i>digits; i--) 00645 value/=10; 00646 00647 string[0]=__T('\0'); 00648 00649 /* add sign */ 00650 i=_tcslen(string); 00651 string[i]=vsign; 00652 string[i+1]=__T('\0'); 00653 00654 /* add integer part */ 00655 amx_strval(string+_tcslen(string),(long)ipart,SV_DECIMAL,0); 00656 00657 /* add fractional part */ 00658 if (digits>0) { 00659 i=_tcslen(string); 00660 string[i]=decpoint; 00661 amx_strval(string+i+1,(long)value,SV_DECIMAL,-digits); 00662 } /* if */ 00663 00664 len=_tcslen(string); 00665 if (len<width) { 00666 /* pad to the requested width */ 00667 for (i=len; i<width; i++) 00668 string[i]=filler; 00669 string[i]=__T('\0'); 00670 /* optionally move the padding to the beginning of the string, using the handwaving algorithm */ 00671 if (align!=__T('-')) { 00672 assert(i==(int)_tcslen(string)); 00673 assert(i>=len); 00674 reverse(string,len); 00675 reverse(string+len,i-len); 00676 reverse(string,i); 00677 } /* if */ 00678 } /* if */ 00679 00680 return string; 00681 } 00682 #endif 00683 00684 00685 static int dochar(AMX *amx,TCHAR ch,cell param,TCHAR sign,TCHAR decpoint,int width,int digits,TCHAR filler, 00686 int (*f_putstr)(void*,const TCHAR *),int (*f_putchar)(void*,TCHAR),void *user) 00687 { 00688 cell *cptr; 00689 TCHAR buffer[40]; 00690 #if defined FLOATPOINT 00691 TCHAR formatstring[40]; 00692 #endif 00693 00694 #if !defined FIXEDPOINT && !defined FLOATPOINT 00695 (void)decpoint; 00696 #endif 00697 assert(f_putstr!=NULL); 00698 assert(f_putchar!=NULL); 00699 00700 switch (ch) { 00701 case __T('c'): 00702 cptr=amx_Address(amx,param); 00703 width--; /* single character itself has a with of 1 */ 00704 if (sign!=__T('-')) 00705 while (width-->0) 00706 f_putchar(user,filler); 00707 f_putchar(user,(TCHAR)*cptr); 00708 while (width-->0) 00709 f_putchar(user,filler); 00710 return 1; 00711 00712 case __T('d'): { 00713 cell value; 00714 int length=1; 00715 cptr=amx_Address(amx,param); 00716 value=*cptr; 00717 if (value<0 || sign==__T('+')) 00718 length++; 00719 if (value<0) 00720 value=-value; 00721 while (value>=10) { 00722 length++; 00723 value/=10; 00724 } /* while */ 00725 width-=length; 00726 if (sign!=__T('-')) 00727 while (width-->0) 00728 f_putchar(user,filler); 00729 amx_strval(buffer,*cptr,SV_DECIMAL,0); 00730 if (sign==__T('+') && *cptr>=0) 00731 f_putchar(user,sign); 00732 f_putstr(user,buffer); 00733 while (width-->0) 00734 f_putchar(user,filler); 00735 return 1; 00736 } /* case */ 00737 00738 #if defined FLOATPOINT 00739 case __T('f'): /* 32-bit floating point number */ 00740 case __T('r'): /* if floating point is enabled, %r == %f */ 00741 /* build a format string */ 00742 if (digits==INT_MAX) 00743 digits=5; 00744 else if (digits>25) 00745 digits=25; 00746 _tcscpy(formatstring,__T("%")); 00747 if (sign!=__T('\0')) 00748 _stprintf(formatstring+_tcslen(formatstring),__T("%c"),sign); 00749 if (width>0) 00750 _stprintf(formatstring+_tcslen(formatstring),__T("%d"),width); 00751 _stprintf(formatstring+_tcslen(formatstring),__T(".%df"),digits); 00752 cptr=amx_Address(amx,param); 00753 #if PAWN_CELL_SIZE == 64 00754 _stprintf(buffer,formatstring,*(double*)cptr); 00755 #else 00756 _stprintf(buffer,formatstring,*(float*)cptr); 00757 #endif 00758 if (decpoint==__T(',')) { 00759 TCHAR *ptr=_tcschr(buffer,__T('.')); 00760 if (ptr!=NULL) 00761 *ptr=__T(','); 00762 } /* if */ 00763 f_putstr(user,buffer); 00764 return 1; 00765 #endif 00766 00767 #if defined FIXEDPOINT 00768 #define FIXEDMULT 1000 00769 case __T('q'): /* 32-bit fixed point number */ 00770 #if !defined FLOATPOINT 00771 case __T('r'): /* if fixed point is enabled, and floating point is not, %r == %q */ 00772 #endif 00773 cptr=amx_Address(amx,param); 00774 /* format the number */ 00775 if (digits==INT_MAX) 00776 digits=3; 00777 else if (digits>25) 00778 digits=25; 00779 formatfixed(buffer,*cptr,sign,width,decpoint,digits,filler); 00780 assert(_tcslen(buffer)<sizeof buffer); 00781 f_putstr(user,buffer); 00782 return 1; 00783 #endif 00784 00785 #if !defined FLOATPOINT && !defined FIXEDPOINT 00786 case __T('f'): 00787 case __T('q'): 00788 case __T('r'): 00789 f_putstr(user,__T("(no rational number support)")); 00790 return 0; /* flag this as an error */ 00791 #endif 00792 00793 case __T('s'): { 00794 AMX_FMTINFO info; 00795 memset(&info,0,sizeof info); 00796 info.length=digits; 00797 info.f_putstr=f_putstr; 00798 info.f_putchar=f_putchar; 00799 info.user=user; 00800 cptr=amx_Address(amx,param); 00801 amx_printstring(amx,cptr,&info); 00802 return 1; 00803 } /* case */ 00804 00805 case __T('x'): { 00806 ucell value; 00807 int length=1; 00808 cptr=amx_Address(amx,param); 00809 value=*(ucell*)cptr; 00810 while (value>=0x10) { 00811 length++; 00812 value>>=4; 00813 } /* while */ 00814 width-=length; 00815 if (sign!=__T('-')) 00816 while (width-->0) 00817 f_putchar(user,filler); 00818 amx_strval(buffer,(long)*cptr,SV_HEX,0); 00819 f_putstr(user,buffer); 00820 while (width-->0) 00821 f_putchar(user,filler); 00822 return 1; 00823 } /* case */ 00824 00825 } /* switch */ 00826 /* error in the string format, try to repair */ 00827 f_putchar(user,ch); 00828 return 0; 00829 } 00830 00831 enum { 00832 FMT_NONE, /* not in format state; accept '%' */ 00833 FMT_START, /* found '%', accept '+', '-' (START), '0' (filler; START), digit (WIDTH), '.' (DECIM), or '%' or format letter (done) */ 00834 FMT_WIDTH, /* found digit after '%' or sign, accept digit (WIDTH), '.' (DECIM) or format letter (done) */ 00835 FMT_DECIM, /* found digit after '.', accept accept digit (DECIM) or format letter (done) */ 00836 }; 00837 00838 static int formatstate(TCHAR c,int *state,TCHAR *sign,TCHAR *decpoint,int *width,int *digits,TCHAR *filler) 00839 { 00840 assert(state!=NULL && sign!=NULL && decpoint!=NULL && width!=NULL && digits!=NULL && filler!=NULL); 00841 switch (*state) { 00842 case FMT_NONE: 00843 if (c==__T('%')) { 00844 *state=FMT_START; 00845 *sign=__T('\0'); 00846 *decpoint=__T('.'); 00847 *width=0; 00848 *digits=INT_MAX; 00849 *filler=__T(' '); 00850 } else { 00851 return -1; /* print a single character */ 00852 } /* if */ 00853 break; 00854 case FMT_START: 00855 if (c==__T('+') || c==__T('-')) { 00856 *sign=c; 00857 } else if (c==__T('0')) { 00858 *filler=c; 00859 } else if (c>=__T('1') && c<=__T('9')) { 00860 *width=(int)(c-__T('0')); 00861 *state=FMT_WIDTH; 00862 } else if (c==__T('.') || c==__T(',')) { 00863 *decpoint=c; 00864 *digits=0; 00865 *state=FMT_DECIM; 00866 } else if (c==__T('%')) { 00867 *state=FMT_NONE; 00868 return -1; /* print literal '%' */ 00869 } else { 00870 return 1; /* print formatted character */ 00871 } /* if */ 00872 break; 00873 case FMT_WIDTH: 00874 if (c>=__T('0') && c<=__T('9')) { 00875 *width=*width*10+(int)(c-__T('0')); 00876 } else if (c==__T('.') || c==__T(',')) { 00877 *decpoint=c; 00878 *digits=0; 00879 *state=FMT_DECIM; 00880 } else { 00881 return 1; /* print formatted character */ 00882 } /* if */ 00883 break; 00884 case FMT_DECIM: 00885 if (c>=__T('0') && c<=__T('9')) { 00886 *digits=*digits*10+(int)(c-__T('0')); 00887 } else { 00888 return 1; /* print formatted character */ 00889 } /* if */ 00890 break; 00891 } /* switch */ 00892 00893 return 0; 00894 } 00895 00896 int amx_printstring(AMX *amx,cell *cstr,AMX_FMTINFO *info) 00897 { 00898 int i,paramidx=0; 00899 int fmtstate=FMT_NONE,width,digits; 00900 TCHAR sign,decpoint,filler; 00901 int (*f_putstr)(void*,const TCHAR *); 00902 int (*f_putchar)(void*,TCHAR); 00903 void *user; 00904 int skip,length; 00905 00906 if (info!=NULL) { 00907 f_putstr=info->f_putstr; 00908 f_putchar=info->f_putchar; 00909 user=info->user; 00910 skip=info->skip; 00911 length=info->length; 00912 } else { 00913 f_putstr=NULL; 00914 f_putchar=NULL; 00915 user=NULL; 00916 skip=0; 00917 length=INT_MAX; 00918 } /* if */ 00919 #if !defined AMX_STRING_LIB 00920 if (f_putstr==NULL) 00921 f_putstr=cons_putstr; 00922 if (f_putchar==NULL) 00923 f_putchar=cons_putchar; 00924 #else 00925 assert(f_putstr!=NULL && f_putchar!=NULL); 00926 #endif 00927 00928 /* if no placeholders appear, we can use a quicker routine */ 00929 if (info==NULL || info->params==NULL) { 00930 00931 TCHAR cache[100]; 00932 int idx=0; 00933 00934 if ((ucell)*cstr>UNPACKEDMAX) { 00935 int j=sizeof(cell)-sizeof(char); 00936 char c; 00937 /* the string is packed */ 00938 i=0; 00939 for ( ; ; ) { 00940 c=(char)((ucell)cstr[i] >> 8*j); 00941 if (c==0) 00942 break; 00943 if (skip>0) { 00944 skip--; /* skip a number of characters */ 00945 } else { 00946 if (length--<=0) 00947 break; /* print up to a certain length */ 00948 assert(idx<sizeof cache); 00949 cache[idx++]=c; 00950 if (idx==sizeof cache - 1) { 00951 cache[idx]=__T('\0'); 00952 f_putstr(user,cache); 00953 idx=0; 00954 } /* if */ 00955 } /* if */ 00956 if (j==0) 00957 i++; 00958 j=(j+sizeof(cell)-sizeof(char)) % sizeof(cell); 00959 } /* for */ 00960 } else { 00961 /* unpacked string */ 00962 for (i=0; cstr[i]!=0; i++) { 00963 if (skip-->0) 00964 continue; 00965 assert(idx<sizeof cache); 00966 cache[idx++]=(TCHAR)cstr[i]; 00967 if (idx==sizeof cache - 1) { 00968 cache[idx]=__T('\0'); 00969 f_putstr(user,cache); 00970 idx=0; 00971 } /* if */ 00972 } /* for */ 00973 } /* if */ 00974 if (idx>0) { 00975 cache[idx]=__T('\0'); 00976 f_putstr(user,cache); 00977 } /* if */ 00978 00979 } else { 00980 00981 /* check whether this is a packed string */ 00982 if ((ucell)*cstr>UNPACKEDMAX) { 00983 int j=sizeof(cell)-sizeof(char); 00984 char c; 00985 /* the string is packed */ 00986 i=0; 00987 for ( ; ; ) { 00988 c=(char)((ucell)cstr[i] >> 8*j); 00989 if (c==0) 00990 break; 00991 switch (formatstate(c,&fmtstate,&sign,&decpoint,&width,&digits,&filler)) { 00992 case -1: 00993 f_putchar(user,c); 00994 break; 00995 case 0: 00996 break; 00997 case 1: 00998 assert(info!=NULL && info->params!=NULL); 00999 if (paramidx>=info->numparams) /* insufficient parameters passed */ 01000 amx_RaiseError(amx, AMX_ERR_NATIVE); 01001 else 01002 paramidx+=dochar(amx,c,info->params[paramidx],sign,decpoint,width,digits,filler, 01003 f_putstr,f_putchar,user); 01004 fmtstate=FMT_NONE; 01005 break; 01006 default: 01007 assert(0); 01008 } /* switch */ 01009 if (j==0) 01010 i++; 01011 j=(j+sizeof(cell)-sizeof(char)) % sizeof(cell); 01012 } /* for */ 01013 } else { 01014 /* the string is unpacked */ 01015 for (i=0; cstr[i]!=0; i++) { 01016 switch (formatstate((TCHAR)cstr[i],&fmtstate,&sign,&decpoint,&width,&digits,&filler)) { 01017 case -1: 01018 f_putchar(user,(TCHAR)cstr[i]); 01019 break; 01020 case 0: 01021 break; 01022 case 1: 01023 assert(info!=NULL && info->params!=NULL); 01024 if (paramidx>=info->numparams) /* insufficient parameters passed */ 01025 amx_RaiseError(amx, AMX_ERR_NATIVE); 01026 else 01027 paramidx+=dochar(amx,(TCHAR)cstr[i],info->params[paramidx],sign,decpoint,width,digits,filler, 01028 f_putstr,f_putchar,user); 01029 fmtstate=FMT_NONE; 01030 break; 01031 default: 01032 assert(0); 01033 } /* switch */ 01034 } /* for */ 01035 } /* if */ 01036 01037 } /* if (info==NULL || info->params==NULL) */ 01038 01039 return paramidx; 01040 } 01041 01042 #if !defined AMX_STRING_LIB 01043 01044 #if defined AMX_ALTPRINT 01045 /* print(const string[], start=0, end=cellmax) */ 01046 static cell AMX_NATIVE_CALL n_print(AMX *amx,const cell *params) 01047 { 01048 cell *cstr; 01049 AMX_FMTINFO info; 01050 01051 memset(&info,0,sizeof info); 01052 info.skip= ((size_t)params[0]>=2*sizeof(cell)) ? (int)params[2] : 0; 01053 info.length= ((size_t)params[0]>=3*sizeof(cell)) ? (int)(params[3]-info.skip) : INT_MAX; 01054 01055 CreateConsole(); 01056 cstr=amx_Address(amx,params[1]); 01057 amx_printstring(amx,cstr,&info); 01058 amx_fflush(); 01059 return 0; 01060 } 01061 #else 01062 /* print(const string[], foreground=-1, background=-1, highlight=-1) */ 01063 static cell AMX_NATIVE_CALL n_print(AMX *amx,const cell *params) 01064 { 01065 cell *cstr; 01066 int oldcolours; 01067 01068 CreateConsole(); 01069 01070 /* set the new colours */ 01071 oldcolours=amx_setattr((int)params[2],(int)params[3],(int)params[4]); 01072 01073 cstr=amx_Address(amx,params[1]); 01074 amx_printstring(amx,cstr,NULL); 01075 01076 /* reset the colours */ 01077 (void)amx_setattr(oldcolours & 0xff,(oldcolours >> 8) & 0x7f,(oldcolours >> 15) & 0x01); 01078 amx_fflush(); 01079 return 0; 01080 } 01081 #endif 01082 01083 static cell AMX_NATIVE_CALL n_printf(AMX *amx,const cell *params) 01084 { 01085 cell *cstr; 01086 AMX_FMTINFO info; 01087 01088 memset(&info,0,sizeof info); 01089 info.params=params+2; 01090 info.numparams=(int)(params[0]/sizeof(cell))-1; 01091 info.skip=0; 01092 info.length=INT_MAX; 01093 01094 CreateConsole(); 01095 cstr=amx_Address(amx,params[1]); 01096 amx_printstring(amx,cstr,&info); 01097 amx_fflush(); 01098 return 0; 01099 } 01100 01101 /* getchar(bool:echo=true) */ 01102 static cell AMX_NATIVE_CALL n_getchar(AMX *amx,const cell *params) 01103 { 01104 int c; 01105 01106 (void)amx; 01107 CreateConsole(); 01108 c=amx_getch(); 01109 if (params[1]) { 01110 #if defined(SUPPRESS_ECHO) 01111 /* For Mac OS X, non-Curses, don't echo the character */ 01112 #else 01113 amx_putchar((TCHAR)c); 01114 amx_fflush(); 01115 #endif 01116 } /* if */ 01117 return c; 01118 } 01119 01120 /* getstring(string[], size=sizeof string, bool:pack=false) */ 01121 static cell AMX_NATIVE_CALL n_getstring(AMX *amx,const cell *params) 01122 { 01123 int c,chars,max; 01124 cell *cptr; 01125 01126 (void)amx; 01127 CreateConsole(); 01128 chars=0; 01129 max=(int)params[2]; 01130 if (max>0) { 01131 #if __STDC_VERSION__ >= 199901L 01132 TCHAR str[max]; /* use C99 feature if available */ 01133 #else 01134 TCHAR *str=(TCHAR *)alloca(max*sizeof(TCHAR)); 01135 if (str==NULL) 01136 return chars; 01137 #endif 01138 01139 c=amx_getch(); 01140 while (c!=EOF && c!=EOL_CHAR && chars<max-1) { 01141 str[chars++]=(TCHAR)c; 01142 #if defined(SUPPRESS_ECHO) 01143 /* For Mac OS X, non-Curses, don't echo the character */ 01144 #else 01145 amx_putchar((TCHAR)c); 01146 amx_fflush(); 01147 #endif 01148 if (chars<max-1) 01149 c=amx_getch(); 01150 } /* while */ 01151 01152 if (c==EOL_CHAR) 01153 amx_putchar('\n'); 01154 assert(chars<max); 01155 str[chars]='\0'; 01156 01157 cptr=amx_Address(amx,params[1]); 01158 amx_SetString(cptr,(char*)str,(int)params[3],sizeof(TCHAR)>1,max); 01159 01160 } /* if */ 01161 return chars; 01162 } 01163 01164 static void acceptchar(int c,int *num) 01165 { 01166 switch (c) { 01167 case '\b': 01168 amx_putchar('\b'); 01169 *num-=1; 01170 #if defined amx_putchar && (defined __BORLANDC__ || defined __WATCOMC__) 01171 /* the backspace key does not erase the 01172 * character, so do this explicitly */ 01173 amx_putchar(' '); /* erase */ 01174 amx_putchar('\b'); /* go back */ 01175 #endif 01176 break; 01177 case EOL_CHAR: 01178 amx_putchar('\n'); 01179 *num+=1; 01180 break; 01181 default: 01182 #if defined(SUPPRESS_ECHO) 01183 /* For Mac OS X, non-Curses, don't echo the character */ 01184 #else 01185 amx_putchar((TCHAR)c); 01186 #endif 01187 *num+=1; 01188 } /* switch */ 01189 amx_fflush(); 01190 } 01191 01192 static int inlist(AMX *amx,int c,const cell *params,int num) 01193 { 01194 int i, key; 01195 01196 (void)amx; 01197 for (i=0; i<num; i++) { 01198 if (i==0) { 01199 /* first key is passed by value, others are passed by reference */ 01200 key = (int)params[i]; 01201 } else { 01202 cell *cptr; 01203 cptr=amx_Address(amx,params[i]); 01204 key=(int)*cptr; 01205 } /* if */ 01206 if (c==key || c==-key) 01207 return key; 01208 } /* for */ 01209 return 0; 01210 } 01211 01212 static cell AMX_NATIVE_CALL n_getvalue(AMX *amx,const cell *params) 01213 { 01214 cell value; 01215 int base,sign,c,d; 01216 int chars,n; 01217 01218 CreateConsole(); 01219 base=(int)params[1]; 01220 if (base<2 || base>36) 01221 return 0; 01222 01223 chars=0; 01224 value=0; 01225 sign=1; /* to avoid a compiler warning (Microsoft Visual C/C++ 6.0) */ 01226 01227 c=amx_getch(); 01228 while (c!=EOF) { 01229 /* check for sign (if any) */ 01230 if (chars==0) { 01231 if (c=='-') { 01232 sign=-1; 01233 acceptchar(c,&chars); 01234 c=amx_getch(); 01235 } else { 01236 sign=1; 01237 } /* if */ 01238 } /* if */ 01239 01240 /* check end of input */ 01241 #if EOL_CHAR!='\r' 01242 if (c==EOL_CHAR && inlist(amx,'\r',params+2,(int)params[0]/sizeof(cell)-1)!=0) 01243 c='\r'; 01244 #endif 01245 if ((chars>1 || chars>0 && sign>0) 01246 && (n=inlist(amx,c,params+2,(int)params[0]/sizeof(cell)-1))!=0) 01247 { 01248 if (n>0) 01249 acceptchar(c,&chars); 01250 break; 01251 } /* if */ 01252 #if EOL_CHAR!='\r' 01253 if (c=='\r') 01254 c=EOL_CHAR; 01255 #endif 01256 01257 /* get value */ 01258 d=base; /* by default, do not accept the character */ 01259 if (c>='0' && c<='9') { 01260 d=c-'0'; 01261 } else if (c>='a' && c<='z') { 01262 d=c-'a'+10; 01263 } else if (c>='A' && c<='Z') { 01264 d=c-'A'+10; 01265 } else if (c=='\b') { 01266 if (chars>0) { 01267 value/=base; 01268 acceptchar(c,&chars); 01269 } /* if */ 01270 } /* if */ 01271 if (d<base) { 01272 acceptchar(c,&chars); 01273 value=value*base + d; 01274 } /* if */ 01275 c=amx_getch(); 01276 } /* while */ 01277 return sign*value; 01278 } 01279 01280 static cell AMX_NATIVE_CALL n_clrscr(AMX *amx,const cell *params) 01281 { 01282 (void)amx; 01283 (void)params; 01284 CreateConsole(); 01285 amx_clrscr(); 01286 return 0; 01287 } 01288 01289 static cell AMX_NATIVE_CALL n_clreol(AMX *amx,const cell *params) 01290 { 01291 (void)amx; 01292 (void)params; 01293 CreateConsole(); 01294 amx_clreol(); 01295 return 0; 01296 } 01297 01298 static cell AMX_NATIVE_CALL n_gotoxy(AMX *amx,const cell *params) 01299 { 01300 (void)amx; 01301 CreateConsole(); 01302 return amx_gotoxy((int)params[1],(int)params[2]); 01303 } 01304 01305 static cell AMX_NATIVE_CALL n_wherexy(AMX *amx,const cell *params) 01306 { 01307 cell *px,*py; 01308 int x,y; 01309 01310 (void)amx; 01311 CreateConsole(); 01312 amx_wherexy(&x,&y); 01313 px=amx_Address(amx,params[1]); 01314 py=amx_Address(amx,params[2]); 01315 *px=x; 01316 *py=y; 01317 return 0; 01318 } 01319 01320 static cell AMX_NATIVE_CALL n_setattr(AMX *amx,const cell *params) 01321 { 01322 (void)amx; 01323 CreateConsole(); 01324 (void)amx_setattr((int)params[1],(int)params[2],(int)params[3]); 01325 return 0; 01326 } 01327 01328 static cell AMX_NATIVE_CALL n_consctrl(AMX *amx,const cell *params) 01329 { 01330 (void)amx; 01331 CreateConsole(); 01332 (void)amx_termctl((int)params[1],(int)params[2]); 01333 return 0; 01334 } 01335 01336 static cell AMX_NATIVE_CALL n_console(AMX *amx,const cell *params) 01337 { 01338 (void)amx; 01339 CreateConsole(); 01340 amx_console((int)params[1],(int)params[2],(int)params[3]); 01341 return 0; 01342 } 01343 01344 01345 #if !defined AMXCONSOLE_NOIDLE 01346 static AMX_IDLE PrevIdle = NULL; 01347 static int idxKeyPressed = -1; 01348 01349 static int AMXAPI amx_ConsoleIdle(AMX *amx, int AMXAPI Exec(AMX *, cell *, int)) 01350 { 01351 int err=0, key; 01352 01353 assert(idxKeyPressed >= 0); 01354 01355 if (PrevIdle != NULL) 01356 PrevIdle(amx, Exec); 01357 01358 if (amx_kbhit()) { 01359 key = amx_getch(); 01360 amx_Push(amx, key); 01361 err = Exec(amx, NULL, idxKeyPressed); 01362 while (err == AMX_ERR_SLEEP) 01363 err = Exec(amx, NULL, AMX_EXEC_CONT); 01364 } /* if */ 01365 01366 return err; 01367 } 01368 #endif 01369 01370 #if defined __cplusplus 01371 extern "C" 01372 #endif 01373 const AMX_NATIVE_INFO console_Natives[] = { 01374 // { "getchar", n_getchar }, 01375 // { "getstring", n_getstring }, 01376 // { "getvalue", n_getvalue }, 01377 { "print", n_print }, 01378 { "printf", n_printf }, 01379 // { "clrscr", n_clrscr }, 01380 // { "clreol", n_clreol }, 01381 // { "gotoxy", n_gotoxy }, 01382 // { "wherexy", n_wherexy }, 01383 // { "setattr", n_setattr }, 01384 // { "console", n_console }, 01385 // { "consctrl", n_consctrl }, 01386 { NULL, NULL } /* terminator */ 01387 }; 01388 01389 int AMXEXPORT AMXAPI amx_ConsoleInit(AMX *amx) 01390 { 01391 #if !defined AMXCONSOLE_NOIDLE 01392 /* see whether there is an @keypressed() function */ 01393 if (amx_FindPublic(amx, "@keypressed", &idxKeyPressed) == AMX_ERR_NONE) { 01394 if (amx_GetUserData(amx, AMX_USERTAG('I','d','l','e'), (void**)&PrevIdle) != AMX_ERR_NONE) 01395 PrevIdle = NULL; 01396 amx_SetUserData(amx, AMX_USERTAG('I','d','l','e'), (void*)amx_ConsoleIdle); 01397 } /* if */ 01398 #endif 01399 01400 return amx_Register(amx, console_Natives, -1); 01401 } 01402 01403 int AMXEXPORT AMXAPI amx_ConsoleCleanup(AMX *amx) 01404 { 01405 (void)amx; 01406 #if !defined AMXCONSOLE_NOIDLE 01407 PrevIdle = NULL; 01408 #endif 01409 return AMX_ERR_NONE; 01410 } 01411 01412 #endif /* AMX_STRING_LIB */
Generated on Sat Jul 16 2022 16:09:35 by 1.7.2