Advertisement
Y_Less

YSI_format.own

Mar 23rd, 2012
308
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 25.32 KB | None | 0 0
  1. /*----------------------------------------------------------------------------*-
  2.                     ==============================
  3.                     Y Sever Includes - Format Core
  4.                     ==============================
  5. Description:
  6.     Based on the AMXMODX format function, used in SA:MP, modified by me for 0.2
  7.     Extends the Text core and is required by the Message2Format functions.
  8. Legal:
  9.     Based on format() by the AMXModX team.  Original header:
  10.         //Adapted from Quake3's vsprintf
  11.         // thanks to cybermind for linking me to this :)
  12.         //I made the following changes:
  13.         // - Fixed spacing to be AMX Mod X standard
  14.         // - Added 'n' support, no buffer overflows
  15.         // - Templatized input/output buffers
  16.  
  17.     Copyright (C) 2007 Alex "Y_Less" Cole
  18.  
  19.     This program is free software; you can redistribute it and/or
  20.     modify it under the terms of the GNU General Public License
  21.     as published by the Free Software Foundation; either version 2
  22.     of the License, or (at your option) any later version.
  23.  
  24.     This program is distributed in the hope that it will be useful,
  25.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.     GNU General Public License for more details.
  28.  
  29.     You should have received a copy of the GNU General Public License
  30.     along with this program; if not, write to the Free Software
  31.     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  32.     MA 02110-1301, USA.
  33. Version:
  34.     0.1.2
  35. Changelog:
  36.     27/12/07:
  37.         Rewrote text draw support for better optimisation.
  38.     26/12/07:
  39.         Added text draw support.
  40.     20/10/07:
  41.         Changed AddNum code for faster defaults.
  42.         Added %u for unsigned variable base.
  43.         Added %t for signed variable base.
  44.         Added formatex and printfex.
  45.     17/10/07:
  46.         Altered AddNum code for optional signage of numbers.
  47.     19/06/07:
  48.         Added support for blank INI strings to ignore text.
  49.     13/06/07:
  50.         Added better error handling.
  51.     07/06/07:
  52.         Added %% support.
  53.         Added protection against insufficient parameters.
  54.     30/04/07:
  55.         Added postfix (suffix) option (%p).
  56.     26/04/07:
  57.         Added * width and prec options.
  58.     15/04/07:
  59.         Added %o - Octal radix.
  60.         Made Format_AddNum more generic.
  61.     14/04/07:
  62.         Updated header documentation with more than changelog.
  63.         Added %n - Command from INI name.
  64.     31/03/07:
  65.         First version.
  66. Functions:
  67.     Public:
  68.         -
  69.     Core:
  70.         formatex - New format with additional identifiers.
  71.         printfex - New printf with additional identifiers.
  72.     Stock:
  73.         Format_SendFormattedText - Sends a formatted message to a player.
  74.     Static:
  75.         Format_AddNum - Adds a number to the output string.
  76.         Format_AddFloat - Adds a float to the output string.
  77.         Format_AddString - Adds a string to the output string.
  78.         Format_AddCommand - Adds a command to the output string.
  79.         Format_IsDigit - Checks a character is a number.
  80.         Format_AddSuffix = Add a suffix for a number.
  81.     Inline:
  82.         Format_AddBin - Base 2 wrapper for Format_AddNum.
  83.         Format_AddInt- Base 10 wrapper for Format_AddNum.
  84.         Format_AddHex - Base 16 wrapper for Format_AddNum.
  85.         Format_AddOct - Base 8 wrapper for Format_AddNum.
  86.     API:
  87.         -
  88. Callbacks:
  89.     -
  90. Definitions:
  91.     FORMAT_LADJUST - Flag for padding left instead of right.
  92.     FORMAT_ZEROPAD - Flag for padding with 0's instead of spaces.
  93.     FORMAT_COMMAND - Adler32 of "Command" for properties.
  94. Enums:
  95.     -
  96. Macros:
  97.     -
  98. Variables:
  99.     Global:
  100.         -
  101.     Static:
  102.         -
  103. Commands:
  104.     -
  105. Compile options:
  106.     -
  107. Operators:
  108.     -
  109. -*----------------------------------------------------------------------------*/
  110.  
  111. #define FORMAT_LADJUST 1
  112. #define FORMAT_ZEROPAD 2
  113. #define FORMAT_COMMAND 179176128
  114.  
  115. /*----------------------------------------------------------------------------*-
  116. Function:
  117.     Format_AddBin
  118. Params:
  119.     output[] - The string to write the data to.
  120.     &maxlen - The maximum number of characters to write.
  121.     val - The number to write.
  122.     width - The minimum length of string to write.
  123.     flags - FORMAT_LADJUST - pad left, FORMAT_ZEROPAD - pad with 0's.
  124. Return:
  125.     Format_AddNum
  126. Notes:
  127.     Wrapper for Format_AddNum in base 2.  See Format_AddNum.
  128. -*----------------------------------------------------------------------------*/
  129.  
  130. #define Format_AddBin(%1,%2,%3,%4,%5) Format_AddNum((%1), (%2), (%3), (%4), (%5), 0b10, false)
  131.  
  132. /*----------------------------------------------------------------------------*-
  133. Function:
  134.     Format_AddInt
  135. Params:
  136.     output[] - The string to write the data to.
  137.     &maxlen - The maximum number of characters to write.
  138.     val - The number to write.
  139.     width - The minimum length of string to write.
  140.     flags - FORMAT_LADJUST - pad left, FORMAT_ZEROPAD - pad with 0's.
  141. Return:
  142.     Format_AddNum
  143. Notes:
  144.     Wrapper for Format_AddNum in base 10.  See Format_AddNum.
  145. -*----------------------------------------------------------------------------*/
  146.  
  147. #define Format_AddInt(%1,%2,%3,%4,%5) Format_AddNum((%1), (%2), (%3), (%4), (%5),   10, true)
  148.  
  149. /*----------------------------------------------------------------------------*-
  150. Function:
  151.     Format_AddBin
  152. Params:
  153.     output[] - The string to write the data to.
  154.     &maxlen - The maximum number of characters to write.
  155.     val - The number to write.
  156.     width - The minimum length of string to write.
  157.     flags - FORMAT_LADJUST - pad left, FORMAT_ZEROPAD - pad with 0's.
  158. Return:
  159.     Format_AddNum
  160. Notes:
  161.     Wrapper for Format_AddNum in base 16.  See Format_AddNum.
  162. -*----------------------------------------------------------------------------*/
  163.  
  164. #define Format_AddHex(%1,%2,%3,%4,%5) Format_AddNum((%1), (%2), (%3), (%4), (%5), 0x10, false)
  165.  
  166. /*----------------------------------------------------------------------------*-
  167. Function:
  168.     Format_AddOct
  169. Params:
  170.     output[] - The string to write the data to.
  171.     &maxlen - The maximum number of characters to write.
  172.     val - The number to write.
  173.     width - The minimum length of string to write.
  174.     flags - FORMAT_LADJUST - pad left, FORMAT_ZEROPAD - pad with 0's.
  175. Return:
  176.     Format_AddNum
  177. Notes:
  178.     Wrapper for Format_AddNum in base 8.  See Format_AddNum.
  179. -*----------------------------------------------------------------------------*/
  180.  
  181. #define Format_AddOct(%1,%2,%3,%4,%5) Format_AddNum((%1), (%2), (%3), (%4), (%5),   8, false)
  182.  
  183. /*----------------------------------------------------------------------------*-
  184. Function:
  185.     Format_AddNum
  186. Params:
  187.     output[] - The string to write the data to.
  188.     &maxlen - The maximum number of characters to write.
  189.     val - The number to write.
  190.     width - The minimum length of string to write.
  191.     flags - FORMAT_LADJUST - pad left, FORMAT_ZEROPAD - pad with 0's.
  192.     base - The base to display the number in.
  193.     sign - Wether or not sign should be shown.
  194. Return:
  195.     Length of the string added.
  196. Notes:
  197.     Adds a number to the output string according to the passed parameters. The
  198.     original had separate, almost identical functions for each base, this
  199.     combines them all into one.
  200. -*----------------------------------------------------------------------------*/
  201.  
  202. static Format_AddNum(output[], &maxlen, val, width, flags, base, sign)
  203. {
  204.     new
  205.         text[33],
  206.         digits,
  207.         pos;
  208.     if (sign)
  209.     {
  210.         new
  211.             signedVal = val,
  212.             num;
  213.         if (val < 0) val = -val;
  214.         do
  215.         {
  216.             num = '0' + (val % base);
  217.             if (num > '9') num += 7;
  218.             text[digits++] = num;
  219.             val /= base;
  220.         }
  221.         while (val);
  222.         if (signedVal & 0x80000000)
  223.         {
  224.             if (flags & FORMAT_ZEROPAD) output[pos++] = '-';
  225.             else text[digits++] = '-';
  226.         }
  227.     }
  228.     else
  229.     {
  230.         switch (base)
  231.         {
  232.             case 2:
  233.             {
  234.                 do
  235.                 {
  236.                     text[digits++] = '0' + (val & 1);
  237.                     val >>>= 1;
  238.                 }
  239.                 while (val);
  240.             }
  241.             case 8:
  242.             {
  243.                 do
  244.                 {
  245.                     text[digits++] = '0' + (val & 7);
  246.                     val >>>= 3;
  247.                 }
  248.                 while (val);
  249.             }
  250.             case 16:
  251.             {
  252.                 new
  253.                     num;
  254.                 do
  255.                 {
  256.                     num = '0' + (val & 15);
  257.                     if (num > '9') num += 7;
  258.                     text[digits++] = num;
  259.                     val >>>= 4;
  260.                 }
  261.                 while (val);
  262.             }
  263.             default:
  264.             {
  265.                 new
  266.                     num;
  267.                 do
  268.                 {
  269.                     if (val & 0x80000000)
  270.                     {
  271.                         num = '0' + ((((((val >>> 1) % base) << 1) % base) + (val & 1)) % base);
  272.                         if (num > '9') num += 7;
  273.                         text[digits++] = num;
  274.                         val = (val >>> 1) / (base >>> 1);
  275.                     }
  276.                     else
  277.                     {
  278.                         num = '0' + (val % base);
  279.                         if (num > '9') num += 7;
  280.                         text[digits++] = num;
  281.                         val /= base;
  282.                     }
  283.                 }
  284.                 while (val);
  285.             }
  286.         }
  287.     }
  288.     if(!(flags & FORMAT_LADJUST))
  289.     {
  290.         while (digits < width && maxlen)
  291.         {
  292.             output[pos++] = (flags & FORMAT_ZEROPAD) ? '0' : ' ';
  293.             width--;
  294.             maxlen--;
  295.         }
  296.     }
  297.     while (digits-- && maxlen)
  298.     {
  299.         output[pos++] = text[digits];
  300.         width--;
  301.         maxlen--;
  302.     }
  303.     if (flags & FORMAT_LADJUST)
  304.     {
  305.         while (width-- && maxlen)
  306.         {
  307.             output[pos++] = (flags & FORMAT_ZEROPAD) ? '0' : ' ';
  308.             maxlen--;
  309.         }
  310.     }
  311.     return pos;
  312. }
  313.  
  314. /*----------------------------------------------------------------------------*-
  315. Function:
  316.     Format_AddFloat
  317. Params:
  318.     output[] - String to add to.
  319.     &maxlen - Length of string remaining.
  320.     Float:fval - value to add.
  321.     width - Minimum length.
  322.     prec - Number of DP.
  323. Return:
  324.     Length of the string added.
  325. Notes:
  326.     -
  327. -*----------------------------------------------------------------------------*/
  328.  
  329. static Format_AddFloat(output[], &maxlen, Float:fval, width, prec)
  330. {
  331.     new
  332.         text[32],
  333.         digits,
  334.         pos,
  335.         Float:signedVal = fval,
  336.         val;
  337.     if (fval < 0) fval = -fval;
  338.     digits = 0;
  339.     val = floatround(fval, floatround_floor);
  340.     do
  341.     {
  342.         text[digits++] = '0' + val % 10;
  343.         val /= 10;
  344.     }
  345.     while (val);
  346.     if (signedVal < 0.0) text[digits++] = '-';
  347.     while (digits < width && maxlen)
  348.     {
  349.         output[pos++] = ' ';
  350.         width--;
  351.         maxlen--;
  352.     }
  353.  
  354.     while (digits-- && maxlen)
  355.     {
  356.         output[pos++] = text[digits];
  357.         maxlen--;
  358.     }
  359.     if (prec < 0) prec = 6;
  360.     digits = 0;
  361.     while (digits < prec)
  362.     {
  363.         fval = (fval - val) * 10.0;
  364.         val = floatround(fval, floatround_floor);
  365.         text[digits++] = '0' + val % 10;
  366.     }
  367.  
  368.     if (digits > 0 && maxlen)
  369.     {
  370.         output[pos++] = '.';
  371.         maxlen--;
  372.         for (prec = 0; maxlen && prec < digits; prec++)
  373.         {
  374.             output[pos++] = text[prec];
  375.             maxlen--;
  376.         }
  377.     }
  378.     return pos;
  379. }
  380.  
  381. /*----------------------------------------------------------------------------*-
  382. Function:
  383.     Format_AddString
  384. Params:
  385.     output[] - String to add to.
  386.     &maxlen - Length of string remaining.
  387.     string[] - String to add.
  388.     width - Minimum length.
  389.     prec - Maximum length.
  390. Return:
  391.     Length of the string added.
  392. Notes:
  393.     -
  394. -*----------------------------------------------------------------------------*/
  395.  
  396. static Format_AddString(output[], &maxlen, string[], width, prec)
  397. {
  398.     new
  399.         size,
  400.         pos,
  401.         pos2;
  402.     if (!string[0])
  403.     {
  404.         prec = -1;
  405.     }
  406.     if (prec >= 0)
  407.     {
  408.         for (size = 0; size < prec; size++)
  409.         {
  410.             if (string[size] == '\0') break;
  411.         }
  412.     }
  413.     else
  414.     {
  415.         while (string[size]) size++;
  416.     }
  417.     if (size > maxlen) size = maxlen;
  418.     maxlen -= size;
  419.     width -= size;
  420.     while (size--)
  421.     {
  422.         output[pos++] = string[pos2++];
  423.     }
  424.     while (width-- > 0 && maxlen)
  425.     {
  426.         output[pos++] = ' ';
  427.         maxlen--;
  428.     }
  429.     return pos;
  430. }
  431.  
  432. /*----------------------------------------------------------------------------*-
  433. Function:
  434.     Format_AddCommand
  435. Params:
  436.     output[] - String to add to.
  437.     &maxlen - Length of string remaining.
  438.     str[] - Function name to find.
  439.     width - Minimum length.
  440.     prec - Maximum length.
  441. Return:
  442.     Length of the string added.
  443. Notes:
  444.     -
  445. -*----------------------------------------------------------------------------*/
  446.  
  447. static Format_AddCommand(output[], &maxlen, str[], width, prec)
  448. {
  449.     new
  450.         size,
  451.         pos,
  452.         pos2,
  453.         string[MAX_STRING] = "FAIL";
  454.     if (str[0] && CallRemoteFunction("Command_Name", "s", str))
  455.     {
  456.         getproperty(0, "", FORMAT_COMMAND, string);
  457.         strunpack(string, string);
  458.     }
  459.     if (!string[0])
  460.     {
  461.         prec = -1;
  462.     }
  463.     if (prec >= 0)
  464.     {
  465.         for (size = 0; size < prec; size++)
  466.         {
  467.             if (string[size] == '\0') break;
  468.         }
  469.     }
  470.     else
  471.     {
  472.         while (string[size]) size++;
  473.     }
  474.     if (size > maxlen) size = maxlen;
  475.     maxlen -= size;
  476.     width -= size;
  477.     while (size--)
  478.     {
  479.         output[pos++] = string[pos2++];
  480.     }
  481.     while (width-- > 0 && maxlen)
  482.     {
  483.         output[pos++] = ' ';
  484.         maxlen--;
  485.     }
  486.     return pos;
  487. }
  488.  
  489. /*----------------------------------------------------------------------------*-
  490. Function:
  491.     Format_AddSuffix
  492. Params:
  493.     output[] - String to add to.
  494.     &maxlen - Length of string remaining.
  495.     number - Number to add suffix of.
  496. Return:
  497.     -
  498. Notes:
  499.     Adds the ordinal suffix of a given number.  Does not support multiple
  500.     languages atm.
  501. -*----------------------------------------------------------------------------*/
  502.  
  503. static Format_AddSuffix(output[], &maxlen, number)
  504. {
  505.     if (number < 0) number = 0 - number;
  506.     new
  507.         suffix[3],
  508.         pos,
  509.         digits,
  510.         len;
  511.     if (number > 3 && number <= 20) suffix = "th";
  512.     else switch (number % 10)
  513.     {
  514.         case 1: suffix = "st";
  515.         case 2: suffix = "nd";
  516.         case 3: suffix = "rd";
  517.         default: suffix = "th";
  518.     }
  519.     len = strlen(suffix);
  520.     while (digits < len && maxlen)
  521.     {
  522.         output[pos++] = suffix[digits++];
  523.         maxlen--;
  524.     }
  525.     return pos;
  526. }
  527.  
  528. /*----------------------------------------------------------------------------*-
  529. Function:
  530.     Format_IsDigit
  531. Params:
  532.     n - The digit to test.
  533. Return:
  534.     bool: Is n a digit?
  535. Notes:
  536.     -
  537. -*----------------------------------------------------------------------------*/
  538.  
  539. static bool:Format_IsDigit(n)
  540. {
  541.     return (n <= '9' && n >= '0');
  542. }
  543.  
  544. /*----------------------------------------------------------------------------*-
  545. Function:
  546.     Format_SendFormattedText
  547. Params:
  548.     playerid - The player to send it to or INVALID_PLAYER_ID for all players.
  549.     identifier[] - The string identifier of the text to output.
  550.     ...
  551. Return:
  552.     -
  553. Notes:
  554.     This is a rewritten version of the SA:MP format function (taken from the
  555.     HL AMXMODX mod).  It is based on the 0.2 version including %b, %h and %x.
  556.     The code is an almost direct port with minor fixes and changes due to the
  557.     use of more generalised template code used in the original.
  558.    
  559.     This function is also designed to be as efficient as possible with
  560.     multiple languages, ensuring each one is parsed only once if required then
  561.     saved for later users of the same language.
  562.    
  563.     If playerid is INVALID_PLAYER_ID the function will loop through all
  564.     players and format the message for them in their own language where
  565.     available, otherwise it will format it for the required playerid and send
  566.     it.
  567.    
  568.     This is also streamlined by only aquiring string parameters once and saving
  569.     them for later use, unless more than 8 are used in which case the last
  570.     array slot is used as a buffer, but this should rarely be the case.
  571. -*----------------------------------------------------------------------------*/
  572.  
  573. stock Format_SendFormattedText(Bit:players[], identifier[], {Float,_}:...)
  574. {
  575.     DBGP2("Format_SendFormattedText call");
  576.     new
  577.         messageid = Text_FindTextPointers(identifier),
  578.         numa = numargs(),
  579.         output[MAX_LANGUAGES][MAX_STRING],
  580.         style = Text_GetTextStyle(messageid),
  581.         colour,
  582.         Text:td[MAX_LANGUAGES] = {Text:INVALID_TEXT_DRAW, ...};
  583.     if (style < 0)
  584.     {
  585.         colour = _:TD_GetID(Text_GetTextColour(messageid));
  586.         if (colour == _:MAX_TEXT_DRAW_STYLES) return;
  587.     }
  588.     else if (style)
  589.     {
  590.         colour = Text_GetTextTime(messageid);
  591.     }
  592.     else
  593.     {
  594.         colour = Text_GetTextColour(messageid);
  595.     }
  596.     DBGP3("Format_SendFormattedText start loop");
  597.     foreach (Player, playerid)
  598.     {
  599.         if (!Bit_Get(players, playerid)) continue;
  600.         new
  601.             Language:playerLanguage = Text_GetPlayerLanguage(playerid);
  602.         if (output[playerLanguage][0]) goto display;
  603.         new
  604.             pos,
  605.             p,
  606.             arg = 2,
  607.             tempString[MAX_STRING],
  608.             ch,
  609.             llen = MAX_STRING,
  610.             stringCount;
  611.         tempString = Text_GetTextFromIndex(messageid, playerLanguage, identifier);
  612.         while (TRUE)
  613.         {
  614.             while (llen-- && (ch = tempString[pos++]) != '\0' && ch != '%') output[playerLanguage][p++] = ch;
  615.             if (ch == '\0' || llen <= 0) goto done;
  616.             new
  617.                 argStrings[8][MAX_STRING],
  618.                 flags,
  619.                 width,
  620.                 prec = -1,
  621.                 stringPos,
  622.                 n;
  623.             rflag:
  624.             ch = tempString[pos++];
  625.             if (arg >= numa) continue;
  626.             reswitch:
  627.             switch (ch)
  628.             {
  629.                 case '-':
  630.                 {
  631.                     flags |= FORMAT_LADJUST;
  632.                     goto rflag;
  633.                 }
  634.                 case '.':
  635.                 {
  636.                     if ((ch = tempString[pos]) == '*')
  637.                     {
  638.                         pos++;
  639.                         prec = getarg(arg++);
  640.                         goto rflag;
  641.                     }
  642.                     else
  643.                     {
  644.                         n = 0;
  645.                         while (Format_IsDigit((ch = tempString[pos++]))) n = 10 * n + (ch - '0');
  646.                         prec = n < 0 ? -1 : n;
  647.                         goto reswitch;
  648.                     }
  649.                 }
  650.                 case '0':
  651.                 {
  652.                     flags |= FORMAT_ZEROPAD;
  653.                     goto rflag;
  654.                 }
  655.                 case '1', '2', '3', '4', '5', '6', '7', '8', '9':
  656.                 {
  657.                     do
  658.                     {
  659.                         n = 10 * n + (ch - '0');
  660.                     }
  661.                     while (Format_IsDigit((ch = tempString[pos++])));
  662.                     width = n;
  663.                     goto reswitch;
  664.                 }
  665.                 case '*':
  666.                 {
  667.                     width = getarg(arg++);
  668.                     goto rflag;
  669.                 }
  670.                 case 'b':
  671.                 {
  672.                     p += Format_AddBin(output[playerLanguage][p], llen, getarg(arg++), width, flags);
  673.                 }
  674.                 case 'c':
  675.                 {
  676.                     output[playerLanguage][p++] = getarg(arg++);
  677.                     if (!llen--) goto done;
  678.                 }
  679.                 case 'd', 'i':
  680.                 {
  681.                     p += Format_AddInt(output[playerLanguage][p], llen, getarg(arg++), width, flags);
  682.                 }
  683.                 case 'f':
  684.                 {
  685.                     p += Format_AddFloat(output[playerLanguage][p], llen, Float:getarg(arg++), width, prec);
  686.                 }
  687.                 case 's':
  688.                 {
  689.                     if (stringCount < pos)
  690.                     {
  691.                         for (new k = 0; k < MAX_STRING; k++)
  692.                         {
  693.                             if (!(argStrings[stringPos][k] = getarg(arg, k))) break;
  694.                         }
  695.                     }
  696.                     p += Format_AddString(output[playerLanguage][p], llen, argStrings[stringPos], width, prec);
  697.                     stringPos++;
  698.                     arg++;
  699.                     stringCount = pos;
  700.                     if (stringPos == sizeof (argStrings))
  701.                     {
  702.                         stringCount--;
  703.                         stringPos--;
  704.                     }
  705.                 }
  706.                 case 'h', 'x':
  707.                 {
  708.                     p += Format_AddHex(output[playerLanguage][p], llen, getarg(arg++), width, flags);
  709.                 }
  710.                 case 'o':
  711.                 {
  712.                     p += Format_AddOct(output[playerLanguage][p], llen, getarg(arg++), width, flags);
  713.                 }
  714.                 case 'n':
  715.                 {
  716.                     if (stringCount < pos)
  717.                     {
  718.                         for (new k = 0; k < MAX_STRING; k++)
  719.                         {
  720.                             if (!(argStrings[stringPos][k] = getarg(arg, k))) break;
  721.                         }
  722.                     }
  723.                     p += Format_AddCommand(output[playerLanguage][p], llen, argStrings[stringPos], width, prec);
  724.                     stringPos++;
  725.                     arg++;
  726.                     stringCount = pos;
  727.                     if (stringPos == sizeof (argStrings))
  728.                     {
  729.                         stringCount--;
  730.                         stringPos--;
  731.                     }
  732.                 }
  733.                 case 'p':
  734.                 {
  735.                     p += Format_AddSuffix(output[playerLanguage][p], llen, getarg(arg++));
  736.                 }
  737.                 case 'u':
  738.                 {
  739.                     if (prec < 0) prec = 10;
  740.                     p += Format_AddNum(output[playerLanguage][p], llen, getarg(arg++), width, flags, prec, false);
  741.                 }
  742.                 case 't':
  743.                 {
  744.                     if (prec < 0) prec = 10;
  745.                     p += Format_AddNum(output[playerLanguage][p], llen, getarg(arg++), width, flags, prec, true);
  746.                 }
  747.                 case '\0', '%':
  748.                 {
  749.                     output[playerLanguage][p++] = '%';
  750.                     if (!llen--) goto done;
  751.                 }
  752.                 default:
  753.                 {
  754.                     output[playerLanguage][p++] = ch;
  755.                     if (!llen--) goto done;
  756.                 }
  757.             }
  758.         }
  759.         done:
  760.         output[playerLanguage][p] = '\0';
  761.         if (!output[playerLanguage][0]) continue;
  762.         display:
  763.         if (style < 0)
  764.         {
  765.             if (td[playerLanguage] == Text:INVALID_TEXT_DRAW)
  766.             {
  767.                 td[playerLanguage] = TD_Display(output[playerLanguage], Style:colour);
  768.             }
  769.             TD_ShowForPlayer(playerid, td[playerLanguage]);
  770.             TD_Garbage(td[playerLanguage]);
  771.         }
  772.         else if (style)
  773.         {
  774.             GameTextForPlayer(playerid, output[playerLanguage], colour, style);
  775.         }
  776.         else
  777.         {
  778.             SendClientMessage(playerid, colour, output[playerLanguage]);
  779.         }
  780.     }
  781.     DBGP3("Format_SendFormattedText end loop");
  782. }
  783.  
  784. /*----------------------------------------------------------------------------*-
  785. Function:
  786.     formatex
  787. Params:
  788.     output[] - The output target.
  789.     len - Length of the output.
  790.     const format[] - The format string.
  791.     ...
  792. Return:
  793.     -
  794. Notes:
  795.     Rewrite of format to support additional identifiers.
  796. -*----------------------------------------------------------------------------*/
  797.  
  798. stock formatex(output[], len, const format[], {Float,_}:...)
  799. {
  800.     new
  801.         numa = numargs(),
  802.         pos,
  803.         p,
  804.         n,
  805.         arg = 3,
  806.         ch,
  807.         argStrings[MAX_STRING];
  808.     while (TRUE)
  809.     {
  810.         while (len-- && (ch = format[pos++]) != '\0' && ch != '%') output[p++] = ch;
  811.         if (ch == '\0' || len <= 0) break;
  812.         new
  813.             flags,
  814.             width,
  815.             prec = -1;
  816.         rflag:
  817.         ch = format[pos++];
  818.         if (arg >= numa) continue;
  819.         reswitch:
  820.         switch (ch)
  821.         {
  822.             case '-':
  823.             {
  824.                 flags |= FORMAT_LADJUST;
  825.                 goto rflag;
  826.             }
  827.             case '.':
  828.             {
  829.                 if ((ch = format[pos]) == '*')
  830.                 {
  831.                     pos++;
  832.                     prec = getarg(arg++);
  833.                     goto rflag;
  834.                 }
  835.                 else
  836.                 {
  837.                     n = 0;
  838.                     while (Format_IsDigit((ch = format[pos++]))) n = 10 * n + (ch - '0');
  839.                     prec = n < 0 ? -1 : n;
  840.                     goto reswitch;
  841.                 }
  842.             }
  843.             case '0':
  844.             {
  845.                 flags |= FORMAT_ZEROPAD;
  846.                 goto rflag;
  847.             }
  848.             case '1', '2', '3', '4', '5', '6', '7', '8', '9':
  849.             {
  850.                 do
  851.                 {
  852.                     n = 10 * n + (ch - '0');
  853.                 }
  854.                 while (Format_IsDigit((ch = format[pos++])));
  855.                 width = n;
  856.                 goto reswitch;
  857.             }
  858.             case '*':
  859.             {
  860.                 width = getarg(arg++);
  861.                 goto rflag;
  862.             }
  863.             case 'b':
  864.             {
  865.                 p += Format_AddBin(output[p], len, getarg(arg++), width, flags);
  866.             }
  867.             case 'c':
  868.             {
  869.                 output[p++] = getarg(arg++);
  870.                 if (!len--) break;
  871.             }
  872.             case 'd', 'i':
  873.             {
  874.                 p += Format_AddInt(output[p], len, getarg(arg++), width, flags);
  875.             }
  876.             case 'f':
  877.             {
  878.                 p += Format_AddFloat(output[p], len, Float:getarg(arg++), width, prec);
  879.             }
  880.             case 's':
  881.             {
  882.                 for (new k = 0; k < MAX_STRING; k++)
  883.                 {
  884.                     if (!(argStrings[k] = getarg(arg, k))) break;
  885.                 }
  886.                 p += Format_AddString(output[p], len, argStrings, width, prec);
  887.                 arg++;
  888.             }
  889.             case 'h', 'x':
  890.             {
  891.                 p += Format_AddHex(output[p], len, getarg(arg++), width, flags);
  892.             }
  893.             case 'o':
  894.             {
  895.                 p += Format_AddOct(output[p], len, getarg(arg++), width, flags);
  896.             }
  897.             case 'n':
  898.             {
  899.                 for (new k = 0; k < MAX_STRING; k++)
  900.                 {
  901.                     if (!(argStrings[k] = getarg(arg, k))) break;
  902.                 }
  903.                 p += Format_AddCommand(output[p], len, argStrings, width, prec);
  904.                 arg++;
  905.             }
  906.             case 'p':
  907.             {
  908.                 p += Format_AddSuffix(output[p], len, getarg(arg++));
  909.             }
  910.             case 'u':
  911.             {
  912.                 if (prec < 0) prec = 10;
  913.                 p += Format_AddNum(output[p], len, getarg(arg++), width, flags, prec, false);
  914.             }
  915.             case 't':
  916.             {
  917.                 if (prec < 0) prec = 10;
  918.                 p += Format_AddNum(output[p], len, getarg(arg++), width, flags, prec, true);
  919.             }
  920.             case '\0', '%':
  921.             {
  922.                 output[p++] = '%';
  923.                 if (!len--) break;
  924.             }
  925.             default:
  926.             {
  927.                 output[p++] = ch;
  928.                 if (!len--) break;
  929.             }
  930.         }
  931.     }
  932.     output[p - (len ? 0 : 1)] = '\0';
  933. }
  934.  
  935. /*----------------------------------------------------------------------------*-
  936. Function:
  937.     printfex
  938. Params:
  939.     const format[] - The format string.
  940.     ...
  941. Return:
  942.     -
  943. Notes:
  944.     Rewrite of printf to support additional identifiers.
  945. -*----------------------------------------------------------------------------*/
  946.  
  947. stock printfex(const format[], {Float,_}:...)
  948. {
  949.     new
  950.         numa = numargs(),
  951.         pos,
  952.         p,
  953.         n,
  954.         arg = 1,
  955.         ch,
  956.         argStrings[MAX_STRING],
  957.         output[MAX_STRING],
  958.         len = MAX_STRING;
  959.     while (TRUE)
  960.     {
  961.         while (len-- && (ch = format[pos++]) != '\0' && ch != '%') output[p++] = ch;
  962.         if (ch == '\0' || len <= 0) break;
  963.         new
  964.             flags,
  965.             width,
  966.             prec = -1;
  967.         rflag:
  968.         ch = format[pos++];
  969.         if (arg >= numa) continue;
  970.         reswitch:
  971.         switch (ch)
  972.         {
  973.             case '-':
  974.             {
  975.                 flags |= FORMAT_LADJUST;
  976.                 goto rflag;
  977.             }
  978.             case '.':
  979.             {
  980.                 if ((ch = format[pos]) == '*')
  981.                 {
  982.                     pos++;
  983.                     prec = getarg(arg++);
  984.                     goto rflag;
  985.                 }
  986.                 else
  987.                 {
  988.                     n = 0;
  989.                     while (Format_IsDigit((ch = format[pos++]))) n = 10 * n + (ch - '0');
  990.                     prec = n < 0 ? -1 : n;
  991.                     goto reswitch;
  992.                 }
  993.             }
  994.             case '0':
  995.             {
  996.                 flags |= FORMAT_ZEROPAD;
  997.                 goto rflag;
  998.             }
  999.             case '1', '2', '3', '4', '5', '6', '7', '8', '9':
  1000.             {
  1001.                 do
  1002.                 {
  1003.                     n = 10 * n + (ch - '0');
  1004.                 }
  1005.                 while (Format_IsDigit((ch = format[pos++])));
  1006.                 width = n;
  1007.                 goto reswitch;
  1008.             }
  1009.             case '*':
  1010.             {
  1011.                 width = getarg(arg++);
  1012.                 goto rflag;
  1013.             }
  1014.             case 'b':
  1015.             {
  1016.                 p += Format_AddBin(output[p], len, getarg(arg++), width, flags);
  1017.             }
  1018.             case 'c':
  1019.             {
  1020.                 output[p++] = getarg(arg++);
  1021.                 if (!len--) break;
  1022.             }
  1023.             case 'd', 'i':
  1024.             {
  1025.                 p += Format_AddInt(output[p], len, getarg(arg++), width, flags);
  1026.             }
  1027.             case 'f':
  1028.             {
  1029.                 p += Format_AddFloat(output[p], len, Float:getarg(arg++), width, prec);
  1030.             }
  1031.             case 's':
  1032.             {
  1033.                 for (new k = 0; k < MAX_STRING; k++)
  1034.                 {
  1035.                     if (!(argStrings[k] = getarg(arg, k))) break;
  1036.                 }
  1037.                 p += Format_AddString(output[p], len, argStrings, width, prec);
  1038.                 arg++;
  1039.             }
  1040.             case 'h', 'x':
  1041.             {
  1042.                 p += Format_AddHex(output[p], len, getarg(arg++), width, flags);
  1043.             }
  1044.             case 'o':
  1045.             {
  1046.                 p += Format_AddOct(output[p], len, getarg(arg++), width, flags);
  1047.             }
  1048.             case 'n':
  1049.             {
  1050.                 for (new k = 0; k < MAX_STRING; k++)
  1051.                 {
  1052.                     if (!(argStrings[k] = getarg(arg, k))) break;
  1053.                 }
  1054.                 p += Format_AddCommand(output[p], len, argStrings, width, prec);
  1055.                 arg++;
  1056.             }
  1057.             case 'p':
  1058.             {
  1059.                 p += Format_AddSuffix(output[p], len, getarg(arg++));
  1060.             }
  1061.             case 'u':
  1062.             {
  1063.                 if (prec < 0) prec = 10;
  1064.                 p += Format_AddNum(output[p], len, getarg(arg++), width, flags, prec, false);
  1065.             }
  1066.             case 't':
  1067.             {
  1068.                 if (prec < 0) prec = 10;
  1069.                 p += Format_AddNum(output[p], len, getarg(arg++), width, flags, prec, true);
  1070.             }
  1071.             case '\0', '%':
  1072.             {
  1073.                 output[p++] = '%';
  1074.                 if (!len--) break;
  1075.             }
  1076.             default:
  1077.             {
  1078.                 output[p++] = ch;
  1079.                 if (!len--) break;
  1080.             }
  1081.         }
  1082.     }
  1083.     output[p - (len ? 0 : 1)] = '\0';
  1084.     print(output);
  1085. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement