stringverbs.c

Go to the documentation of this file.
00001 
00002 /*  $Id: stringverbs.c 1327 2006-04-24 01:03:36Z sethdill $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "memory.h"
00032 #include "strings.h"
00033 #include "ops.h"
00034 #include "resources.h"
00035 #include "lang.h"
00036 #include "langinternal.h"
00037 #include "langhtml.h"
00038 #include "langsystem7.h"
00039 #include "tablestructure.h"
00040 #include "kernelverbs.h"
00041 #include "kernelverbdefs.h"
00042 #include "timedate.h"
00043 #include "oplist.h"
00044 #include "tableverbs.h"
00045 
00046 #include "md5.h" //6.1b11 AR
00047 
00048 
00049 /*Latin to Mac conversion table: 7.0b28 PBS*/
00050 /* moved to stringverbs.c: 2004-10-28 aradke */
00051 
00052 static unsigned char latintomactable [] = {
00053 
00054     0, 1, 2, 3,
00055     4, 5, 6, 7,
00056     8, 9, 10, 11,
00057     12, 13, 14, 15,
00058     16, 17, 18, 19,
00059     20, 21, 22, 23,
00060     24, 25, 26, 27,
00061     28, 29, 30, 31,
00062     32, 33, 34, 35,
00063     36, 37, 38, 39,
00064     40, 41, 42, 43,
00065     44, 45, 46, 47,
00066     48, 49, 50, 51,
00067     52, 53, 54, 55,
00068     56, 57, 58, 59,
00069     60, 61, 62, 63,
00070     64, 65, 66, 67,
00071     68, 69, 70, 71,
00072     72, 73, 74, 75,
00073     76, 77, 78, 79,
00074     80, 81, 82, 83,
00075     84, 85, 86, 87,
00076     88, 89, 90, 91,
00077     92, 93, 94, 95,
00078     96, 97, 98, 99,
00079     100, 101, 102, 103,
00080     104, 105, 106, 107,
00081     108, 109, 110, 111,
00082     112, 113, 114, 115,
00083     116, 117, 118, 119,
00084     120, 121, 122, 123,
00085     124, 125, 126, 127,
00086     165, 170, 173, 176,
00087     179, 183, 186, 189,
00088     195, 197, 201, 209,
00089     212, 217, 218, 182,
00090     198, 206, 226, 227,
00091     228, 240, 246, 247,
00092     249, 250, 251, 253,
00093     254, 255, 245, 196,
00094     202, 193, 162, 163,
00095     219, 180, 207, 164,
00096     172, 169, 187, 199,
00097     194, 208, 168, 248,
00098     161, 177, 211, 210,
00099     171, 181, 166, 225,
00100     252, 213, 188, 200,
00101     185, 184, 178, 192,
00102     203, 231, 229, 204,
00103     128, 129, 174, 130,
00104     233, 131, 230, 232,
00105     237, 234, 235, 236,
00106     220, 132, 241, 238,
00107     239, 205, 133, 215,
00108     175, 244, 242, 243,
00109     134, 160, 222, 167,
00110     136, 135, 137, 139,
00111     138, 140, 190, 141,
00112     143, 142, 144, 145,
00113     147, 146, 148, 149,
00114     221, 150, 152, 151,
00115     153, 155, 154, 214,
00116     191, 157, 156, 158,
00117     159, 224, 223, 216
00118     };
00119 
00120 /*Mac to Latin conversion table: 7.0b35 PBS*/
00121 /* moved to stringverbs.c: 2004-10-28 aradke */
00122 
00123 static unsigned char mactolatintable [] = {
00124 
00125     0, 1, 2, 3,
00126     4, 5, 6, 7,
00127     8, 9, 10, 11,
00128     12, 13, 14, 15,
00129     16, 17, 18, 19,
00130     20, 21, 22, 23,
00131     24, 25, 26, 27,
00132     28, 29, 30, 31,
00133     32, 33, 34, 35,
00134     36, 37, 38, 39,
00135     40, 41, 42, 43,
00136     44, 45, 46, 47,
00137     48, 49, 50, 51,
00138     52, 53, 54, 55,
00139     56, 57, 58, 59,
00140     60, 61, 62, 63,
00141     64, 65, 66, 67,
00142     68, 69, 70, 71,
00143     72, 73, 74, 75,
00144     76, 77, 78, 79,
00145     80, 81, 82, 83,
00146     84, 85, 86, 87,
00147     88, 89, 90, 91,
00148     92, 93, 94, 95,
00149     96, 97, 98, 99,
00150     100, 101, 102, 103,
00151     104, 105, 106, 107,
00152     108, 109, 110, 111,
00153     112, 113, 114, 115,
00154     116, 117, 118, 119,
00155     120, 121, 122, 123,
00156     124, 125, 126, 127,
00157     196, 197, 199, 201,
00158     209, 214, 220, 225,
00159     224, 226, 228, 227,
00160     229, 231, 233, 232,
00161     234, 235, 237, 236,
00162     238, 239, 241, 243,
00163     242, 244, 246, 245,
00164     250, 249, 251, 252,
00165     221, 176, 162, 163,
00166     167, 128, 182, 223,
00167     174, 169, 129, 180,
00168     168, 130, 198, 216,
00169     131, 177, 190, 132,
00170     165, 181, 143, 133,
00171     189, 188, 134, 170,
00172     186, 135, 230, 248,
00173     191, 161, 172, 136,
00174     159, 137, 144, 171,
00175     187, 138, 160, 192,
00176     195, 213, 145, 166,
00177     173, 139, 179, 178,
00178     140, 185, 247, 215,
00179     255, 141, 142, 164,
00180     208, 240, 222, 254,
00181     253, 183, 146, 147,
00182     148, 194, 202, 193,
00183     203, 200, 205, 206,
00184     207, 204, 211, 212,
00185     149, 210, 218, 219,
00186     217, 158, 150, 151,
00187     175, 152, 153, 154,
00188     184, 155, 156, 157
00189     };
00190 
00191 
00192 #define stringerrorlist 263
00193 #define notimplementederror 1
00194 
00195 
00196 typedef enum tystringtoken { /*verbs that are processed by string.c*/
00197     
00198     deletefunc,
00199     
00200     insertfunc,
00201     
00202     popleadingfunc,
00203     
00204     poptrailingfunc,
00205     
00206     trimwhitespacefunc,
00207     
00208     popsuffixfunc,
00209     
00210     hassuffixfunc,
00211     
00212     midfunc,
00213     
00214     nthcharfunc,
00215     
00216     nthfieldfunc,
00217     
00218     countfieldsfunc,
00219     
00220     setwordcharfunc,
00221     
00222     getwordcharfunc,
00223     
00224     firstwordfunc,
00225     
00226     lastwordfunc,
00227     
00228     nthwordfunc,
00229     
00230     countwordsfunc,
00231     
00232     commentdeletefunc,
00233     
00234     firstsentencefunc,
00235     
00236     patternmatchfunc,
00237     
00238     hexfunc,
00239     
00240     timestringfunc,
00241     
00242     datestringfunc,
00243     
00244     uppercasefunc,
00245     
00246     lowercasefunc,
00247     
00248     filledstringfunc,
00249     
00250     addcommasfunc,
00251     
00252     replacefunc,
00253     
00254     replaceallfunc,
00255     
00256     lengthfunc,
00257     
00258     isalphafunc,
00259     
00260     isnumericfunc,
00261     
00262     ispunctuationfunc,
00263     
00264     processmacrosfunc,
00265     
00266     urldecodefunc,
00267     
00268     urlencodefunc,
00269     
00270     parseargsfunc,
00271     
00272     iso8859encodefunc,
00273 
00274     getgifheightwidthfunc,
00275 
00276     getjpegheightwidthfunc,
00277 
00278     wrapfunc,
00279 
00280     davenetmassagerfunc,
00281     
00282     parseaddressfunc,
00283     
00284     dropnonalphasfunc,
00285     
00286     padwithzerosfunc,
00287     
00288     ellipsizefunc,
00289     
00290     innercasefunc,
00291     
00292     urlsplitfunc,
00293 
00294     hashmd5func,
00295     
00296     latintomacfunc,
00297     
00298     mactolatinfunc, /*7.0b35 PBS*/
00299 
00300     utf16toansifunc, /*7.0b41 PBS*/
00301 
00302     utf8toansifunc, /*7.0b41 PBS*/
00303 
00304     ansitoutf8func, /*7.0b41 PBS*/
00305 
00306     ansitoutf16func, /*7.0b42 PBS*/
00307     
00308     multiplereplaceallfunc, /*7.1b17 PBS*/
00309 
00310     macromantoutf8func, // 2006-02-25 creedon
00311     
00312     utf8tomacromanfunc, // 2006-02-25 creedon
00313     
00314     convertcharsetfunc, /* 2006-04-14 smd */
00315     
00316     ischarsetavailablefunc, /* 2006-04-23 smd */
00317 
00318     ctstringverbs
00319     } tystringtoken;
00320 
00321 
00322 char chword = ' '; /*used when getting first word, last word, etc from a string*/
00323 
00324 
00325 
00326 long countleadingchars (Handle htext, byte ch) {
00327     
00328     long len = gethandlesize (htext);
00329     long i;
00330     
00331     for (i = 0; i < len; i++) {
00332         
00333         if ((*(byte **) htext) [i] != ch)
00334             return (i);
00335         } /*for*/
00336     
00337     return (len);
00338     } /*countleadingchars*/
00339 
00340 
00341 void handlepopleadingchars (Handle htext, byte ch) {
00342 
00343     pullfromhandle (htext, 0, countleadingchars (htext, ch), nil);
00344 
00345     } /*handlepopleadingchars*/
00346 
00347 
00348 void handlepoptrailingchars (Handle htext, byte ch) {
00349 
00350     long i;
00351     long len = gethandlesize (htext);
00352 
00353     if (len <= 0)
00354         return;
00355 
00356     for (i = len - 1; i >= 0; i--)
00357         if ((*(byte **) htext) [i] != ch)
00358             break;
00359     
00360     sethandlesize (htext, i + 1); /*shrinking, can't fail*/
00361     } /*handlepoptrailingchars*/
00362 
00363 
00364 static void handletrimwhitespace (Handle htext) {
00365 
00366     long len = gethandlesize (htext);
00367     long ixbegin, ixend;
00368     
00369     if (len <= 0)
00370         return;
00371     
00372     for (ixbegin = 0; ixbegin < len; ixbegin++)     
00373         if ((*htext) [ixbegin] != ' '
00374                 && (*htext) [ixbegin] != '\t'
00375                 && (*htext) [ixbegin] != '\r'
00376                 && (*htext) [ixbegin] != '\n')
00377             break;
00378 
00379     for (ixend = len - 1; ixend >= 0; ixend--)
00380         if ((*htext) [ixend] != ' '
00381                 && (*htext) [ixend] != '\t'
00382                 && (*htext) [ixend] != '\r'
00383                 && (*htext) [ixend] != '\n')
00384             break;
00385 
00386     if (ixend < ixbegin)
00387         sethandlesize (htext, 0);
00388     else {
00389         sethandlesize (htext, ixend + 1); /*shrinking, can't fail*/
00390         pullfromhandle (htext, 0, ixbegin, nil);
00391         }
00392 
00393     return;
00394     } /*handletrimwhitespace*/
00395 
00396 
00397 static void handlepopsuffix (Handle h, byte ch) {
00398     
00399     long ix, len = gethandlesize (h);
00400     
00401     if (len <= 0)
00402         return;
00403     
00404     for (ix = len - 1; ix >= 0; ix--)
00405         if ((byte)((*h) [ix]) == ch) {
00406         
00407             sethandlesize (h, ix);
00408             
00409             return;
00410             }
00411     
00412     return;
00413     } /*handlepopsuffix*/
00414 
00415 
00416 static boolean handlehassuffix (Handle hsuffix, Handle h) {
00417     
00418     return (searchhandle (h, hsuffix, gethandlesize (h) - gethandlesize (hsuffix), longinfinity) >= 0);
00419     } /*handlehassuffix*/
00420 
00421 
00422 static boolean ellipsizehandle (Handle h, long maxlen) {
00423     
00424     long len = gethandlesize (h);
00425     long ix;
00426     
00427     if (len <= maxlen)
00428         return (true);
00429     
00430     if (maxlen < 3)
00431         maxlen = 3;
00432 
00433     if (!sethandlesize (h, maxlen))
00434         return (false);
00435     
00436     for (ix = 1; ix <= 3; ix++)
00437         (*h) [maxlen - ix] = '.';
00438     
00439     return (true);
00440     } /*handleellipsize*/
00441 
00442 
00443 static void fillstring (ptrvoid pfill, long ctfill, bigstring bsfill) {
00444     
00445     /*
00446     do a mass memory fill, like memset, but of a repeated string --
00447     copy ctfill bsfills at pfill.
00448     */
00449     
00450     ptrbyte p = pfill;
00451     long ct = ctfill;
00452     short len = stringlength (bsfill);
00453     ptrbyte s = bsfill + 1;
00454     
00455     while (--ct >= 0) {
00456         
00457         moveleft (s, p, len);
00458         
00459         p += len;
00460         }
00461     } /*fillstring*/
00462 
00463 
00464 static boolean wordwraphandle (Handle htext) {
00465     
00466     /*
00467     DW 12/3/94: rewrote the routine. it's now a two-pass thing.
00468     
00469     5.0.2b8 dmb: handle cr-lf line endings. lf-only line ending are not handled.
00470     */
00471     
00472     unsigned long handlesize = gethandlesize (htext);
00473     unsigned long ix = 0;
00474     char ch, chnext, chprev = ' ';
00475     boolean fllinestart = true;
00476         
00477     for (ix = 0; ix < handlesize; ++ix) { /*pass 1 -- remove leading white space on each line*/
00478     
00479         if (ix >= handlesize)
00480             break;
00481         
00482         ch = (*htext) [ix];
00483         
00484         if (fllinestart && ((ch == ' ') || (ch == chtab) || (ch == chlinefeed))) {
00485             
00486             moveleft (&(*htext) [ix + 1], &(*htext) [ix], handlesize - ix);
00487         
00488             handlesize--;
00489             
00490             ix--;
00491             
00492             continue;
00493             }
00494             
00495         if (ch == chreturn /*|| ch == chlinefeed*/) {
00496             
00497             fllinestart = true;
00498             
00499             continue;
00500             }
00501         
00502         fllinestart = false; 
00503         } /*while*/
00504     
00505     for (ix = 0; ix < handlesize; chprev = ch, ++ix) { /*pass 2 -- strip out the extraneous hard returns*/
00506         
00507         ch = (*htext) [ix];
00508         
00509         if (ch != chreturn) 
00510             continue;
00511         
00512         if (ix == (handlesize - 1)) { /*last char is a return*/
00513             
00514             /*sethandlesize (htext, handlesize - 1);*/ /*disabled -- the text might not be the whole message*/
00515             
00516             break; /*finished processing the text*/
00517             }
00518         
00519         chnext = (*htext) [ix + 1];
00520         
00521     //  if (chnext == chlinefeed) {
00522     //      
00523     //      if (ix == (handlesize - 2)) /*last chars are cr-lf*/
00524     //      break;
00525     //      
00526     //      chnext = (*htext) [ix + 2];
00527     //      }
00528         
00529         if ((chnext == chreturn) || (chprev == chreturn)) /*leave double or triple returns alone*/
00530             continue;
00531         
00532         if ((chnext != ' ') && (chprev != ' ')) {
00533             
00534             (*htext) [ix] = ' '; /*replace it with a space*/
00535             
00536             continue;
00537             }
00538             
00539         moveleft (&(*htext) [ix + 1], &(*htext) [ix], handlesize - ix);
00540         
00541         handlesize--;
00542         } /*while*/
00543         
00544     sethandlesize (htext, handlesize);
00545         
00546     return (true);
00547     } /*wordwraphandle*/
00548                     
00549                 
00550 static boolean daveNetMassager (short indentlen, short maxlinelen, Handle h, Handle *hmassaged) {
00551     
00552     unsigned long handlesize = gethandlesize (h);
00553     unsigned long ixhandle = 0;
00554     short linelen, wordlen;
00555     bigstring indent, dashes, word, cr, space;
00556     Handle hnew;
00557     short i;
00558     
00559     if (!newemptyhandle (&hnew))
00560         return (false);
00561         
00562     filledstring (' ', indentlen, indent);
00563     
00564     setstringlength (dashes, 0);
00565     
00566     setstringlength (word, 0);
00567     
00568     setstringwithchar (chreturn, cr);
00569     
00570     setstringwithchar (' ', space);
00571     
00572     for (i = 1; i <= 16; i++)
00573         pushstring (BIGSTRING ("\x04" " ---"), dashes);
00574     
00575     if (!pushtexthandle (indent, hnew))
00576         goto error;
00577         
00578     linelen = indentlen;
00579     
00580     while (true) {
00581     
00582         if (ixhandle >= handlesize)
00583             break;
00584         
00585         if ((*h) [ixhandle] == chreturn) {
00586             
00587             if (equalstrings (word, BIGSTRING ("\x03" "---"))) {
00588                 
00589                 if (!pushtexthandle (dashes, hnew))
00590                     goto error;
00591                 
00592                 setstringlength (word, 0);
00593                 }
00594             
00595             if (!pushtexthandle (cr, hnew))
00596                 goto error;
00597                 
00598             if (!pushtexthandle (indent, hnew))
00599                 goto error;
00600                 
00601             linelen = indentlen;
00602                 
00603             ixhandle++;
00604             }
00605         else { /*first char is not a return*/
00606             
00607             while (true) { /*skip over leading blanks*/
00608                 
00609                 if ((*h) [ixhandle] != ' ')
00610                     break;
00611                     
00612                 ixhandle++;
00613                 
00614                 if (ixhandle >= handlesize)
00615                     goto exit;
00616                 } /*while*/
00617             
00618             setstringlength (word, 0);
00619             
00620             while (true) { /*pop off the first word*/
00621                 
00622                 char ch = (*h) [ixhandle];
00623                 
00624                 if ((ch == ' ') || (ch == chreturn)) 
00625                     break;
00626                 
00627                 pushchar (ch, word);
00628                 
00629                 ixhandle++;
00630                 
00631                 if (ixhandle >= handlesize)
00632                     break;
00633                 } /*while*/
00634                 
00635             while (true) { /*skip over leading blanks*/
00636                 
00637                 if (ixhandle >= handlesize)
00638                     break;
00639                 
00640                 if ((*h) [ixhandle] != ' ')
00641                     break;
00642                     
00643                 ixhandle++;
00644                 } /*while*/
00645             
00646             wordlen = stringlength (word);
00647             
00648             if ((linelen + wordlen) > maxlinelen) {
00649                 
00650                 if (!pushtexthandle (cr, hnew))
00651                     goto error;
00652                     
00653                 if (!pushtexthandle (indent, hnew))
00654                     goto error;
00655                     
00656                 if (!pushtexthandle (word, hnew))
00657                     goto error;
00658                     
00659                 if (!pushtexthandle (space, hnew))
00660                     goto error;
00661                     
00662                 linelen = indentlen + wordlen;
00663                 }
00664             else {
00665                 if (!pushtexthandle (word, hnew))
00666                     goto error;
00667                     
00668                 if (!pushtexthandle (space, hnew))
00669                     goto error;
00670                     
00671                 linelen += wordlen;
00672                 }
00673             }
00674         } /*while*/
00675     
00676     exit:
00677     
00678     *hmassaged = hnew;
00679     
00680     return (true);
00681     
00682     error:
00683     
00684     disposehandle (hnew);
00685     
00686     *hmassaged = nil;
00687     
00688     return (false);
00689     } /*daveNetMassager*/
00690     
00691 
00692 
00693 static boolean getpositivelongvalue (hdltreenode hparam1, short pnum, long *x) {
00694     
00695     if (!getlongvalue (hparam1, pnum, x))
00696         return (false);
00697     
00698     if (*x < 0) {
00699         
00700         langerror (numbernotpositiveerror);
00701         
00702         return (false);
00703         }
00704     
00705     return (true);
00706     } /*getpositivelongvalue*/
00707 
00708 
00709 static boolean stringreplaceverb (hdltreenode hparam1, tyvaluerecord *vreturned, boolean flreplaceall) {
00710     
00711     /*
00712     6.1d7 AR: Now handles unicase searching.
00713 
00714     6.1b11 AR: Use getoptionalparamvalue.
00715     */
00716 
00717     Handle h = nil;
00718     Handle hfind;
00719     Handle hreplace;
00720     tyvaluerecord vcase;
00721     short ctconsumed = 3;
00722     short ctpositional = 3;
00723     
00724     if (!getexempttextvalue (hparam1, 1, &h))
00725         return (false);
00726 
00727     if (!getreadonlytextvalue (hparam1, 2, &hfind))
00728         goto exit;
00729     
00730     if (!getreadonlytextvalue (hparam1, 3, &hreplace))
00731         goto exit;
00732     
00733     setbooleanvalue (true, &vcase);
00734 
00735     flnextparamislast = true;
00736 
00737     if (!getoptionalparamvalue (hparam1, &ctconsumed, &ctpositional, BIGSTRING ("\x0f""flCaseSensitive"), &vcase)) 
00738         goto exit;
00739 
00740     if (!textfindreplace (hfind, hreplace, h, flreplaceall, !(boolean)vcase.data.flvalue))
00741         goto exit;
00742     
00743     return (setheapvalue (h, stringvaluetype, vreturned));
00744 
00745 exit:
00746 
00747     disposehandle (h);
00748 
00749     return (false);
00750     } /*stringreplaceverb*/
00751 
00752 
00753 static boolean commentdeleteverb (hdltreenode hp1, tyvaluerecord *v) {
00754     
00755     /*
00756     5.018 dmb: skip over :// for URLs
00757 
00758     5.0.1 dmb: need to skip on more char to handle file:///
00759     */
00760 
00761     Handle x;
00762     
00763     flnextparamislast = true;
00764     
00765     if (!getexempttextvalue (hp1, 1, &x))
00766         return (false);
00767     
00768     if (!textcommentdelete (x)) {
00769         
00770         disposehandle (x);
00771         
00772         return (false);
00773         }
00774     
00775     return (setheapvalue (x, stringvaluetype, v));
00776     } /*commentdeleteverb*/
00777 
00778 boolean parseaddress (Handle htext, tyvaluerecord *v); /*called from langhtml.c*/
00779 
00780 boolean parseaddress (Handle htext, tyvaluerecord *v) {
00781     
00782     /*
00783     5.0.2b8 dmb: new verb
00784     
00785     6.1d4 AR: report proper error message if langcompiletext fails.
00786     */
00787     
00788     hdltreenode hmodule;
00789     hdllistrecord hlist = nil;
00790     boolean fl;
00791     unsigned short savelines;
00792     unsigned short savechars;
00793         
00794     savelines = ctscanlines;
00795     
00796     savechars = ctscanchars;
00797     
00798     disablelangerror ();
00799     
00800     fl = langcompiletext (htext, false, &hmodule); /*always disposes htext*/
00801     
00802     enablelangerror ();
00803     
00804     ctscanlines = savelines;
00805     
00806     ctscanchars = savechars;
00807 
00808     if (!fl) {
00809         
00810         langerror (parseaddresserror); /*Can't parse the address because of a syntax error.*/
00811         
00812         return (false);
00813         }
00814 
00815     fl = opnewlist (&hlist, false);
00816     
00817     disablelangerror ();
00818     
00819     fl = fl && langbuildnamelist ((**hmodule).param1, hlist);
00820     
00821     enablelangerror ();
00822     
00823     langdisposetree (hmodule);
00824     
00825     if (!fl) {
00826             
00827         opdisposelist (hlist);
00828         
00829         langerror (parseaddresserror); /*Can't parse the address because it's not a valid address.*/
00830         
00831         return (false);
00832         }
00833     
00834     return (setheapvalue ((Handle) hlist, listvaluetype, v));
00835     } /*parseaddressverb*/
00836 
00837 
00838 static boolean parseaddressverb (hdltreenode hp1, tyvaluerecord *v) {
00839         
00840     Handle htext;
00841     
00842     flnextparamislast = true;
00843     
00844     if (!getexempttextvalue (hp1, 1, &htext))
00845         return (false);
00846         
00847     return (parseaddress (htext, v));
00848     } /*parseaddressverb*/
00849 
00850 
00851 static boolean dropnonalphasverb (hdltreenode hp1, tyvaluerecord *v) {
00852     
00853     /*
00854     5.0.2b14 dmb: sucked into kernel
00855     
00856     5.1.4 dmb: gets moved into new streamdropnonalphas
00857     */
00858     
00859     Handle x;
00860     handlestream s;
00861     
00862     flnextparamislast = true;
00863     
00864     if (!getexempttextvalue (hp1, 1, &x))
00865         return (false);
00866     
00867     openhandlestream (x, &s);
00868     
00869     streamdropnonalphas (&s);
00870     
00871     closehandlestream (&s);
00872     
00873     return (setheapvalue (x, stringvaluetype, v));
00874     } /*dropnonalphasverb*/
00875 
00876 
00877 static boolean padwithzerosverb (hdltreenode hp1, tyvaluerecord *v) {
00878     
00879     /*
00880     6.2a8 AR: Rewritten to remove 256 char limit (which would sometimes crash Frontier)
00881     */
00882 
00883     Handle h;
00884     long paddedlength, currentlength, delta;
00885 
00886     if (!getexempttextvalue (hp1, 1, &h))
00887         return (false);
00888 
00889     currentlength = gethandlesize (h);
00890 
00891     flnextparamislast = true;
00892 
00893     if (!getlongvalue (hp1, 2, &paddedlength))
00894         goto error;
00895 
00896     delta = paddedlength - currentlength;
00897 
00898     if (delta > 0) {
00899 
00900         if (!sethandlesize (h, paddedlength))
00901             goto error;
00902 
00903         moveright (*h, *h + delta, currentlength);
00904 
00905         memset (*h, '0', delta);
00906         }
00907 
00908     return (setheapvalue (h, stringvaluetype, v));
00909 
00910 error:
00911 
00912     disposehandle (h);
00913 
00914     return (false);
00915     } /*padwithzerosverb*/
00916 
00917 
00918 static boolean stringmultiplereplace (Handle h, hdlhashtable ht, boolean flunicase, bigstring bsstartstring, bigstring bsendstring) {
00919     
00920     /*
00921     7.0b58 PBS: front end for string.replaceAll -- do a replace all for
00922     each item in a table.
00923     */
00924     
00925     hdlhashnode hn;
00926     tyvaluerecord v;
00927     bigstring hashkey;
00928     boolean flstartstring = false, flendstring = false;
00929 
00930     if (stringlength (bsstartstring) > 0)
00931         flstartstring = true;
00932 
00933     if (stringlength (bsendstring) > 0)
00934         flendstring = true;
00935 
00936     for (hn = (**ht).hfirstsort; hn != nil; hn = (**hn).sortedlink) {
00937         
00938         v = ((**hn).val);
00939         
00940         if (copyvaluerecord (v, &v) && coercevalue (&v, stringvaluetype)) {
00941             
00942             Handle hfind;
00943             
00944             gethashkey (hn, hashkey);
00945             
00946             if (!newtexthandle (hashkey, &hfind))
00947                 return (false);
00948             
00949             if (flstartstring) {
00950                 if (!inserttextinhandle (hfind, 0, bsstartstring)) {
00951                     disposehandle (hfind);
00952                     return (false);
00953                     } /*if*/
00954             } /*if*/
00955 
00956             if (flendstring) {
00957                 if (!inserttextinhandle (hfind, gethandlesize (hfind), bsendstring)) {
00958                     disposehandle (hfind);
00959                     return (false);
00960                     } /*if*/
00961                 } /*if*/
00962 
00963             if (!textfindreplace (hfind, v.data.stringvalue, h, true, flunicase)) {
00964                 disposehandle (hfind);
00965                 return (false);
00966                 } /*if*/
00967             
00968             disposehandle (hfind);
00969 
00970             disposevaluerecord (v, false); // don't let tmp stack accumulate
00971             } /*if*/            
00972         } /*for*/
00973     
00974     return (true);
00975     } /*stringmultiplereplace*/
00976 
00977 
00978 static boolean stringmultiplereplaceallverb (hdltreenode hp, tyvaluerecord *v) {
00979     
00980     /*
00981     7.0b58 PBS: do multiple replace-alls from a table. Used by localization
00982     support in Manila and mainResponder.
00983     
00984     2002-10-30 AR: actually get optional parameters by name rather than by position
00985     */
00986     
00987     Handle h;
00988     hdlhashtable ht;
00989     boolean flcasesensitive = true;
00990     bigstring bsstartstring, bsendstring;
00991     short ctconsumed = 0;
00992     short ctpositional;
00993     tyvaluerecord vcasesensitive, vstartchars, vendchars;
00994 
00995     if (!getexempttextvalue (hp, ++ctconsumed, &h))
00996         return (false);
00997 
00998     if (!gettablevalue (hp, ++ctconsumed, &ht)) {
00999         disposehandle (h);
01000         return (false);
01001         } /*if*/    
01002     
01003     ctpositional = ctconsumed;
01004     
01005     /* get optional flCaseSensitive param */
01006     
01007     setbooleanvalue (true, &vcasesensitive);
01008     
01009     if (!getoptionalparamvalue (hp, &ctconsumed, &ctpositional, (BIGSTRING ("\x0f" "flCaseSensitive")), &vcasesensitive))
01010         return (false);
01011     
01012     flcasesensitive = vcasesensitive.data.flvalue;
01013     
01014     /* get optional startCharacters param */
01015     
01016     initvalue (&vstartchars, stringvaluetype);
01017     
01018     if (!getoptionalparamvalue (hp, &ctconsumed, &ctpositional, (BIGSTRING ("\x0f" "startCharacters")), &vstartchars))
01019         return (false);
01020     
01021     pullstringvalue (&vstartchars, bsstartstring);
01022     
01023     /* get optional endCharacters param */
01024     
01025     flnextparamislast = true;
01026     
01027     initvalue (&vendchars, stringvaluetype);
01028     
01029     if (!getoptionalparamvalue (hp, &ctconsumed, &ctpositional, (BIGSTRING ("\x0d" "endCharacters")), &vendchars))
01030         return (false);
01031     
01032     pullstringvalue (&vendchars, bsendstring);
01033 
01034     /* now do the replacement */
01035             
01036     stringmultiplereplace (h, ht, !flcasesensitive, bsstartstring, bsendstring);
01037     
01038     return (setheapvalue (h, stringvaluetype, v));  
01039     } /*stringmultiplereplaceallverb*/
01040 
01041 
01042 static void grabnthfield (Handle htext, long fieldnum, byte chdelim, Handle *hfield, boolean flstrict) {
01043     
01044     /* 12/5/2004 smd: optimization - now takes hfield parameter, a pointer to the 
01045     handle for the extracted field */
01046     
01047     long ixword, lenword;
01048     
01049     if (!textnthword ((ptrbyte) *htext, gethandlesize (htext), fieldnum, chdelim, flstrict, &ixword, &lenword))
01050         lenword = 0;
01051     
01052     if (!loadfromhandletohandle (htext, &ixword, lenword, false, hfield))
01053         newemptyhandle (hfield);
01054     
01055     } /*grabnthfield*/
01056 
01057 
01058 #ifdef MACVERSION
01059 
01060 static void macuppertext (byte *p, long ct) {
01061     
01062     /*
01063     5.1.1 dmb: we use UpperText for handle international chars, but the 
01064     length is a short...
01065     */
01066     //Code change by Timothy Paustian Monday, June 19, 2000 3:09:12 PM
01067     //Updated to new routine.
01068     //UppercaseText(p, ct, smSystemScript); 
01069     
01070     /*7.0b28 PBS: restore the loop. This way we don't
01071     have a >32K bug.*/
01072 
01073     while (ct > infinity) {
01074         
01075         #if TARGET_API_MAC_CARBON == 1
01076         
01077             UppercaseText ((Ptr) p, infinity, smSystemScript);  
01078         
01079         #else
01080         
01081             UpperText ((Ptr) p, infinity);
01082         
01083         #endif
01084         
01085         p += infinity;
01086         
01087         ct -= infinity;
01088         }
01089     
01090     #if TARGET_API_MAC_CARBON == 1
01091     
01092         UppercaseText ((Ptr) p, ct, smSystemScript);    
01093     
01094     #else
01095     
01096         UpperText ((Ptr) p, ct);
01097     
01098     #endif
01099         
01100     } /*macuppertext*/
01101 
01102 
01103 static void maclowertext (byte *p, long ct) {
01104     
01105     /*
01106     5.1.1 dmb: we use LowerText for handle international chars, but the 
01107     length is a short...
01108     */
01109     //Code change by Timothy Paustian Monday, June 19, 2000 3:09:28 PM
01110     //Changed to Opaque call for Carbon
01111 //  LowercaseText(p, ct, smSystemScript);
01112 
01113     /*7.0b28 PBS: restore the loop. This way we don't
01114     have a >32K bug.*/
01115     
01116     while (ct > infinity) {
01117         
01118         #if TARGET_API_MAC_CARBON == 1
01119 
01120             LowercaseText ((Ptr) p, infinity, smSystemScript);
01121     
01122         #else
01123         
01124             LowerText ((Ptr) p, infinity);
01125         
01126         #endif
01127         
01128         p += infinity;
01129         
01130         ct -= infinity;
01131         }
01132     
01133     #if TARGET_API_MAC_CARBON == 1
01134 
01135         LowercaseText ((Ptr) p, ct, smSystemScript);
01136 
01137     #else
01138     
01139         LowerText ((Ptr) p, ct);
01140     
01141     #endif
01142     } /*maclowertext*/
01143 
01144 #endif
01145 
01146 
01147 static void innercasehandle (Handle h) {
01148     
01149     long ix, len;
01150     byte ch;
01151 
01152     lockhandle (h);
01153 
01154 #if MACVERSION
01155     maclowertext ((byte *) (*h), gethandlesize (h));
01156 #else
01157     lowertext ((ptrbyte) *h, gethandlesize (h));
01158 #endif
01159     
01160     unlockhandle (h);
01161 
01162     handlepopleadingchars (h, ' ');
01163 
01164     handlepoptrailingchars (h, ' ');
01165     
01166     len = gethandlesize (h);
01167     
01168     if (len <= 0)
01169         return;
01170 
01171     lockhandle (h);
01172 
01173     for (ix = len - 1; ix >= 0; ix--)
01174         if ((*h) [ix] == ' ') {
01175             
01176             moveleft (*h + ix + 1, *h + ix, len - ix);
01177             
01178             ch = toupper ((*h) [ix]);
01179             
01180             (*h) [ix] = ch;
01181             
01182             len--;
01183             }
01184 
01185     unlockhandle (h);
01186     
01187     sethandlesize (h, len);
01188 
01189     return;
01190     } /*innercasehandle*/
01191 
01192 
01193 static boolean urlsplit (Handle h, tyvaluerecord *vreturn) {
01194     
01195     /*
01196     6.1d5 AR: Assume a valid complete URL, split it into three parts, return as a list.
01197     */
01198     
01199     Handle htemp;
01200     hdllistrecord hlist = nil;
01201     long ix = 0, ct = 0;
01202     long len = gethandlesize (h);
01203     
01204     if (len <= 0)
01205         goto urlerror;
01206     
01207     for (ct = 0; ct < len; ct++)
01208         if ((*h) [ct] == ':')
01209             break;
01210     
01211     if (ct >= len)
01212         goto urlerror;
01213     
01214     while (++ct < len)
01215         if ((*h) [ct] != '/')
01216             break;
01217     
01218     if (ct >= len)
01219         goto urlerror;
01220     
01221     if (!opnewlist (&hlist, false))
01222         goto exit;
01223         
01224     if (!loadfromhandletohandle (h, &ix, ct, false, &htemp)
01225             || !langpushlisttext (hlist, htemp))
01226         goto exit;
01227 
01228     for (ct = ix; ct < len; ct++)
01229         if ((*h) [ct] == '/')
01230             break;
01231 
01232     if (ct >= len)
01233         goto urlerror;
01234 
01235     if (!loadfromhandletohandle (h, &ix, ct - ix, false, &htemp)
01236             || !langpushlisttext (hlist, htemp))
01237         goto exit;
01238     
01239     ix++;
01240     
01241     if (ix == len) {
01242         if (!newemptyhandle (&htemp))
01243             goto exit;
01244         }
01245     else
01246         if (!loadfromhandletohandle (h, &ix, len - ix, false, &htemp))
01247             goto exit;
01248     
01249     if (!langpushlisttext (hlist, htemp))
01250         goto exit;
01251 
01252     assert (ix == len); /*make sure we got the whole thing*/
01253 
01254     return (setheapvalue ((Handle) hlist, listvaluetype, vreturn));
01255 
01256 urlerror:
01257     langerror (urlspliterror);
01258 
01259 exit:   
01260     opdisposelist (hlist);
01261     
01262     return (false);
01263     } /*urlsplit*/
01264 
01265 
01266 void latintomac (Handle h) {
01267     
01268     /*
01269     7.0b28 PBS: convert text from Latin to Mac character sets.
01270     */
01271     
01272     long ix = 0;
01273     long lentext = gethandlesize (h);
01274     
01275     while (true) {
01276     
01277         unsigned char ch = (*h) [ix];
01278         unsigned char chreplace;
01279         
01280         if (ch > 127) {
01281         
01282             chreplace = latintomactable [ch];
01283         
01284             (*h) [ix] = chreplace;
01285             } /*if*/
01286             
01287         ix++;
01288         
01289         if (ix >= lentext)
01290             break;
01291         } /*while*/
01292     } /*latintomac*/
01293 
01294 
01295 void mactolatin (Handle h) {
01296     
01297     /*
01298     7.0b35 PBS: convert text from Mac to Latin character sets.
01299     */
01300     
01301     long ix = 0;
01302     long lentext = gethandlesize (h);
01303     
01304     while (true) {
01305     
01306         unsigned char ch = (*h) [ix];
01307         unsigned char chreplace;
01308         
01309         if (ch > 127) {
01310         
01311             chreplace = mactolatintable [ch];
01312         
01313             (*h) [ix] = chreplace;
01314             } /*if*/
01315             
01316         ix++;
01317         
01318         if (ix >= lentext)
01319             break;
01320         } /*while*/
01321     } /*latintomac*/
01322 
01323 
01324 static boolean isCharsetAvailableVerb( hdltreenode hp1, tyvaluerecord *v )
01325 {
01326     bigstring bscharset;
01327     
01328     flnextparamislast = true;
01329     
01330     if ( !getstringvalue( hp1, 1, bscharset ) ) /* IANA names can't be longer than 40 ASCII characters, so this is safe */
01331         return (false);
01332     
01333     (*v).data.flvalue = isTextEncodingAvailable( bscharset );
01334     
01335     return (true);
01336 }
01337 
01338 
01339 static boolean stringfunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
01340     
01341     /*
01342     bridges string.c with the language.  the name of the verb is bs, its first parameter
01343     is hparam1, and we return a value in vreturned.
01344     
01345     we use a limited number of support routines from lang.c to get parameters and
01346     to return values. 
01347     
01348     return false only if the error is serious enough to halt the running of the script
01349     that called us, otherwise error values are returned through the valuerecord, which
01350     is available to the script.
01351     
01352     if we return false, we try to provide a descriptive error message in the 
01353     returned string bserror.
01354     
01355     8/15/91: most string verbs now deal with any length text.  for efficiency, 
01356     many call getstringcopy, which returns a copy of a string handle.  
01357     to ease error handling, these parameters are retrieved last, even 
01358     though they're often the first parameter.
01359     
01360     10/13/91 dmb: set return value to false by default, so on error it's always false
01361     
01362     10/30/91 dmb: if nthword is out of range, return the empty string
01363     
01364     2/14/92 dmb: replaced getstringcopy calls with getexempttextvalue, which is new 
01365     and does the job better.  also, recoded string.mid so that existing handle is 
01366     reused instead of creating a new one.
01367     
01368     3/9/92 dmb: use Script manager for upper/lower casing; added countfields, nthfield; 
01369     added nthchar (to kernel)
01370     
01371     6/3/92 dmb: firstwordfunc now uses (nthword, 1) to match nthwordfunc
01372     
01373     9/11/92 dmb: added insertfuc (used to be just glue)
01374     
01375     3/3/92 dmb: lock handle when calling Upper/LowerText
01376 
01377     5.0a12 dmb: handle // comments
01378     
01379     5.0.2b17 dmb: use new getreadonlytextvalue where appropriate
01380     
01381     5.1.1 dmb: remove 32K limit in string.upper/lower [Mac]
01382     
01383     6.1d4 AR: added popTrailing, trimWhiteSpace, popSuffix, ellipsize, innerCaseName
01384     
01385     6.1d5 AR: added urlSplit, hasSuffix.
01386     string.dateString and string.timeString now optionally accept a date parameter.
01387     
01388     12/4/2004 smd: optimization - midfunc (ie string.mid) now uses a readonly handle for
01389     the input string, and copies only the results to the output string, for performance
01390     
01391     12/5/2004 smd: optimization - deletefunc now uses a readonly handle for the input
01392     string, creates a new handle sized precisely for the output string, and copies 
01393     two parts from the input to the output (substrings before and after the deleted chars)
01394     
01395     2006-02-25 creedon: added macRomanToUtf8 and utf8ToMacRoman
01396     */
01397     
01398     hdltreenode hp1 = hparam1;
01399     tyvaluerecord *v = vreturned;
01400     short errornum = 0;
01401     bigstring bs; //utility
01402     
01403     setbooleanvalue (false, v); /*by default, string functions return false*/
01404     
01405     switch (token) {
01406         
01407         case setwordcharfunc:
01408             flnextparamislast = true;
01409             
01410             if (!getcharvalue (hp1, 1, &chword))
01411                 return (false);
01412             
01413             (*v).data.flvalue = true;
01414             
01415             return (true);
01416             
01417         case getwordcharfunc:
01418             if (!langcheckparamcount (hp1, 0)) /*no parameters expected*/
01419                 return (false);
01420             
01421             return (setcharvalue (chword, v));
01422     
01423         case deletefunc: {
01424             /* 12/5/2004 smd: optimized */
01425             
01426             Handle x;
01427             Handle hstring;
01428             long ctdelete;
01429             long ixdelete;
01430             long lenbefore;
01431             long ixbefore;
01432             long ixafter;
01433             long lenafter;
01434             long hlen;
01435             
01436             if (!getpositivelongvalue (hp1, 2, &ixdelete))
01437                 return (false);
01438             
01439             flnextparamislast = true;
01440             
01441             if (!getpositivelongvalue (hp1, 3, &ctdelete))
01442                 return (false);
01443             
01444             if (!getreadonlytextvalue (hp1, 1, &hstring))
01445                 return (false);
01446             
01447             hlen = gethandlesize (hstring);
01448             
01449             if (ixdelete > 0)
01450                 --ixdelete; /*convert to zero-base*/
01451             
01452             lenbefore = ixdelete;
01453             
01454             ctdelete = min (ctdelete, hlen - ixdelete); /* in case ctdelete is too big */
01455             
01456             ixafter = ixdelete + ctdelete;
01457             
01458             lenafter = hlen - ixafter;
01459             
01460             if (!newhandle (lenbefore + lenafter, &x))
01461                 return (false);
01462             
01463             ixbefore = 0;
01464             if (lenbefore > 0)
01465                 if (!loadfromhandle (hstring, &ixbefore, lenbefore, *x))
01466                     return (false);
01467             
01468             ixbefore += ctdelete;
01469             if (lenafter > 0)
01470                 if (!loadfromhandle (hstring, &ixbefore, lenafter, &((*x) [lenbefore]) ))
01471                     return (false);
01472             
01473             return (setheapvalue (x, stringvaluetype, v));
01474             }
01475         
01476         case insertfunc: {
01477             Handle hsource;
01478             Handle hdest;
01479             long ixinsert;
01480             boolean fl;
01481             
01482             if (!getreadonlytextvalue (hp1, 1, &hsource)) 
01483                 return (false);
01484             
01485             flnextparamislast = true;
01486             
01487             if (!getpositivelongvalue (hp1, 3, &ixinsert))
01488                 return (false);
01489             
01490             if (!getexempttextvalue (hp1, 2, &hdest)) /*get last to simplify error handing*/
01491                 return (false);
01492             
01493             if (ixinsert > 0) /*convert to zero-base*/
01494                 --ixinsert;
01495             
01496             ixinsert = min (ixinsert, gethandlesize (hdest));
01497             
01498             lockhandle (hsource);
01499             
01500             fl = insertinhandle (hdest, ixinsert, *hsource, gethandlesize (hsource));
01501             
01502             unlockhandle (hsource);
01503             
01504             if (!fl) {
01505                 
01506                 disposehandle (hdest);
01507                 
01508                 return (false);
01509                 }
01510             
01511             return (setheapvalue (hdest, stringvaluetype, v));
01512             }
01513         
01514         case popleadingfunc: {
01515             Handle x;
01516             char ch;
01517             
01518             flnextparamislast = true;
01519             
01520             if (!getcharvalue (hp1, 2, &ch))
01521                 return (false);
01522             
01523             if (!getexempttextvalue (hp1, 1, &x))
01524                 return (false);
01525             
01526             handlepopleadingchars (x, ch);
01527             
01528             return (setheapvalue (x, stringvaluetype, v));
01529             }
01530 
01531         case poptrailingfunc: {
01532             Handle x;
01533             char ch;
01534             
01535             flnextparamislast = true;
01536             
01537             if (!getcharvalue (hp1, 2, &ch))
01538                 return (false);
01539             
01540             if (!getexempttextvalue (hp1, 1, &x))
01541                 return (false);
01542             
01543             handlepoptrailingchars (x, ch);
01544             
01545             return (setheapvalue (x, stringvaluetype, v));
01546             }
01547 
01548         case trimwhitespacefunc: {
01549             Handle x;
01550             
01551             flnextparamislast = true;
01552             
01553             if (!getexempttextvalue (hp1, 1, &x))
01554                 return (false);
01555             
01556             handletrimwhitespace (x);
01557             
01558             return (setheapvalue (x, stringvaluetype, v));
01559             }
01560         
01561         case popsuffixfunc: {
01562             Handle x;
01563             char ch = '.';
01564 
01565             if (langgetparamcount (hp1) > 1) {
01566                 
01567                 flnextparamislast = true;
01568                 
01569                 if (!getcharvalue (hp1, 2, &ch))
01570                     return (false);
01571                 }
01572                         
01573             if (!getexempttextvalue (hp1, 1, &x)) /*get last to simplify error handling*/
01574                 return (false);
01575             
01576             handlepopsuffix (x, ch);
01577             
01578             return (setheapvalue (x, stringvaluetype, v));
01579             }
01580 
01581         case hassuffixfunc: {
01582             Handle h, hsuffix;
01583             
01584             if (!getreadonlytextvalue (hp1, 1, &hsuffix))
01585                 return (false);
01586             
01587             flnextparamislast = true;
01588             
01589             if (!getreadonlytextvalue (hp1, 2, &h))
01590                 return (false);
01591             
01592             return (setbooleanvalue (handlehassuffix (hsuffix, h), v));
01593             }
01594         
01595         case midfunc: {
01596             
01597             /* 12/4/2004 smd: optimized */
01598             
01599             Handle hstring;
01600             Handle x;
01601             long ix;
01602             long newlen;
01603             
01604             
01605             if (!getpositivelongvalue (hp1, 2, &ix))
01606                 return (false);
01607             
01608             flnextparamislast = true;
01609             
01610             if (!getlongvalue (hp1, 3, &newlen)) 
01611                 return (false);
01612             
01613             if (!getreadonlytextvalue (hp1, 1, &hstring)) /*get last to simplify error handling*/
01614                 return (false);
01615             
01616             if (ix > 0)
01617                 --ix; /*convert to zero-base*/
01618             
01619             newlen = min (newlen, gethandlesize (hstring) - ix);
01620             
01621             
01622             if (newlen > 0) {
01623                 if (!newhandle (newlen, &x))
01624                     return (false);
01625                 if (!loadfromhandle (hstring, &ix, newlen, *x))
01626                     return (false);
01627                 }
01628             else if (!newemptyhandle (&x))
01629                 return (false);
01630             
01631             return (setheapvalue (x, stringvaluetype, v));
01632             }
01633         
01634         case nthcharfunc: {
01635             Handle htext;
01636             byte ch;
01637             long charnum;
01638             
01639             if (!getreadonlytextvalue (hp1, 1, &htext)) 
01640                 return (false);
01641             
01642             flnextparamislast = true;
01643             
01644             if (!getpositivelongvalue (hp1, 2, &charnum))
01645                 return (false);
01646             
01647             if (charnum == 0 || charnum > gethandlesize (htext))
01648                 return (setstringvalue (zerostring, v));
01649             
01650             ch = *((byte *) *htext + charnum - 1);
01651             
01652             return (setcharvalue (ch, v));
01653             }
01654         
01655         case nthfieldfunc: {
01656             Handle htext;
01657             Handle x;
01658             char chdelim;
01659             long fieldnum;
01660             
01661             /*
01662             if (!gettextvalue (hp1, 1, &htext)) 
01663                 return (false);
01664             */
01665             
01666             if (!getcharvalue (hp1, 2, &chdelim)) {
01667                 return (false);
01668                 } /*if*/
01669             
01670             flnextparamislast = true;
01671             
01672             if (!getpositivelongvalue (hp1, 3, &fieldnum)) {
01673                 return (false);
01674                 } /*if*/            
01675 
01676             if (!getreadonlytextvalue (hp1, 1, &htext)) /*get last to simplify error handing*/
01677                 return (false);
01678 
01679             grabnthfield (htext, fieldnum, chdelim, &x, true);
01680             
01681             return (setheapvalue (x, stringvaluetype, v));
01682             }
01683         
01684         case countfieldsfunc: {
01685             Handle htext;
01686             char chdelim;
01687             long ctfields;
01688             
01689             if (!getreadonlytextvalue (hp1, 1, &htext)) 
01690                 return (false);
01691             
01692             flnextparamislast = true;
01693             
01694             if (!getcharvalue (hp1, 2, &chdelim))
01695                 return (false);
01696             
01697             ctfields = textcountwords ((ptrbyte) *htext, gethandlesize (htext), chdelim, true);
01698             
01699             setlongvalue (ctfields, v);
01700             
01701             return (true);
01702             }
01703         
01704         case firstwordfunc: {
01705             Handle htext;
01706             Handle x;
01707             
01708             flnextparamislast = true;
01709             
01710             if (!getreadonlytextvalue (hp1, 1, &htext)) /*get last to simplify error handing*/
01711                 return (false);
01712             
01713             grabnthfield (htext, 1, chword, &x, false);
01714             
01715             return (setheapvalue (x, stringvaluetype, v));
01716             }
01717         
01718         case lastwordfunc: {
01719             Handle htext;
01720             
01721             flnextparamislast = true;
01722             
01723             if (!getreadonlytextvalue (hp1, 1, &htext)) 
01724                 return (false);
01725             
01726             textlastword ((ptrbyte) *htext, gethandlesize (htext), chword, bs);
01727             
01728             return (setstringvalue (bs, v));
01729             }
01730     
01731         case nthwordfunc: {
01732             Handle htext;
01733             Handle x;
01734             long wordnum;
01735             
01736             flnextparamislast = true;
01737             
01738             if (!getpositivelongvalue (hp1, 2, &wordnum))
01739                 return (false);
01740             
01741             if (!getreadonlytextvalue (hp1, 1, &htext)) /*get last to simplify error handing*/
01742                 return (false);
01743             
01744             grabnthfield (htext, wordnum, chword, &x, false);
01745             
01746             return (setheapvalue (x, stringvaluetype, v));
01747             }
01748         
01749         case countwordsfunc: {
01750             Handle htext;
01751             long ctwords;
01752             
01753             flnextparamislast = true;
01754             
01755             if (!getreadonlytextvalue (hp1, 1, &htext)) 
01756                 return (false);
01757             
01758             ctwords = textcountwords ((ptrbyte) *htext, gethandlesize (htext), chword, false);
01759             
01760             setlongvalue (ctwords, v);
01761             
01762             return (true);
01763             }
01764         
01765         case commentdeletefunc:
01766             return (commentdeleteverb (hp1, v));
01767         
01768         case firstsentencefunc:
01769             flnextparamislast = true;
01770             
01771             if (!getstringvalue (hp1, 1, bs)) 
01772                 return (false);
01773             
01774             firstsentence (bs);
01775             
01776             return (setstringvalue (bs, v));
01777         
01778         case uppercasefunc: {
01779             Handle x;
01780             
01781             flnextparamislast = true;
01782             
01783             if (!getexempttextvalue (hp1, 1, &x))
01784                 return (false);
01785             
01786             lockhandle (x);
01787             
01788         #if MACVERSION
01789             macuppertext ((byte *) (*x), gethandlesize (x));
01790         #else
01791             uppertext ((ptrbyte) *x, gethandlesize (x));
01792         #endif
01793             
01794             unlockhandle (x);
01795             
01796             return (setheapvalue (x, stringvaluetype, v));
01797             }
01798         
01799         case lowercasefunc: {
01800             Handle x;
01801             
01802             flnextparamislast = true;
01803             
01804             if (!getexempttextvalue (hp1, 1, &x))
01805                 return (false);
01806             
01807             /*
01808             */
01809             
01810             lockhandle (x);
01811         
01812         #if MACVERSION
01813             maclowertext ((byte *) (*x), gethandlesize (x));
01814         #else
01815             lowertext ((ptrbyte) *x, gethandlesize (x));
01816         #endif
01817             
01818             unlockhandle (x);
01819             
01820             return (setheapvalue (x, stringvaluetype, v));
01821             }
01822         
01823         case filledstringfunc: {
01824             long ctfill;
01825             Handle x;
01826             
01827             if (!getstringvalue (hp1, 1, bs))
01828                 return (false);
01829             
01830             flnextparamislast = true;
01831             
01832             if (!getpositivelongvalue (hp1, 2, &ctfill))
01833                 return (false);
01834             
01835             ctfill = min (ctfill, longinfinity / stringlength (bs));
01836             
01837             if (!newhandle (ctfill * stringlength (bs), &x))
01838                 return (false);
01839             
01840             fillstring (*x, ctfill, bs);
01841             
01842             return (setheapvalue (x, stringvaluetype, v));
01843             }
01844         
01845         case patternmatchfunc: {
01846             Handle hsearch, hpattern;
01847             long ixmatch;
01848             short ctconsumed = 2;
01849             short ctpositional = 2;
01850             tyvaluerecord vixstart;
01851             
01852             if (!getreadonlytextvalue (hp1, 1, &hpattern))
01853                 return (false);
01854             
01855             if (!getreadonlytextvalue (hp1, 2, &hsearch))
01856                 return (false);
01857             
01858             flnextparamislast = true;
01859             
01860             setlongvalue (1, &vixstart);
01861             
01862             /* 2004-12-27 smd: added optional ix parameter */
01863             if (!getoptionalparamvalue (hp1, &ctconsumed, &ctpositional, BIGSTRING ("\x02""ix"), &vixstart))
01864                 return (false);
01865             
01866             if (vixstart.data.longvalue > 0) /*switch to 0-index*/
01867                 --vixstart.data.longvalue;
01868             
01869             ixmatch = searchhandle (hsearch, hpattern, vixstart.data.longvalue, longinfinity);
01870             
01871             setlongvalue (ixmatch + 1, v);
01872             
01873             return (true);
01874             }
01875         
01876         case hexfunc: {
01877             long n;
01878             
01879             flnextparamislast = true;
01880             
01881             if (!getlongvalue (hp1, 1, &n))
01882                 return (false);
01883             
01884             numbertohexstring (n, bs);
01885             
01886             return (setstringvalue (bs, v));
01887             }
01888         
01889         case timestringfunc: {
01890             unsigned long dt = timenow ();
01891             
01892             /*
01893             if (!langcheckparamcount (hp1, 0))
01894                 return (false);
01895             */
01896             
01897             if (langgetparamcount (hp1) > 0) {
01898                 
01899                 flnextparamislast = true;
01900                 
01901                 if (!getdatevalue (hp1, 1, &dt))
01902                     return (false);
01903                 }
01904             
01905             timetotimestring (dt, bs, true);
01906             
01907             return (setstringvalue (bs, v));
01908             }
01909         
01910         case datestringfunc: {
01911             unsigned long dt = timenow ();
01912             
01913             /*
01914             if (!langcheckparamcount (hp1, 0))
01915                 return (false);
01916             */
01917             
01918             if (langgetparamcount (hp1) > 0) {
01919                 
01920                 flnextparamislast = true;
01921                 
01922                 if (!getdatevalue (hp1, 1, &dt))
01923                     return (false);
01924                 }
01925             
01926             timetodatestring (dt, bs, true);
01927             
01928             return (setstringvalue (bs, v));
01929             }
01930         
01931         case addcommasfunc:
01932             flnextparamislast = true;
01933             
01934             if (!getstringvalue (hp1, 1, bs))
01935                 return (false);
01936             
01937             stringaddcommas (bs);
01938             
01939             return (setstringvalue (bs, v));
01940         
01941         case replacefunc:
01942             return (stringreplaceverb (hp1, v, false));
01943         
01944         case replaceallfunc:
01945             return (stringreplaceverb (hp1, v, true));
01946         
01947         case lengthfunc: {
01948             Handle htext;
01949             
01950             flnextparamislast = true;
01951             
01952             if (!getreadonlytextvalue (hp1, 1, &htext)) 
01953                 return (false);
01954             
01955             return (setlongvalue (gethandlesize (htext), v));
01956             }
01957         
01958         case isalphafunc: {
01959             char ch;
01960     
01961             flnextparamislast = true;
01962             
01963             if (!getcharvalue (hp1, 1, &ch))
01964                 return (false);
01965             
01966             (*v).data.flvalue = isalpha ((unsigned char)ch) != 0;
01967             
01968             return (true);
01969             }
01970             
01971         case isnumericfunc: {
01972             char ch;
01973     
01974             flnextparamislast = true;
01975             
01976             if (!getcharvalue (hp1, 1, &ch))
01977                 return (false);
01978             
01979             (*v).data.flvalue = isdigit ((unsigned char)ch) != 0;
01980             
01981             return (true);
01982             }
01983             
01984         case ispunctuationfunc: {
01985             char ch;
01986     
01987             flnextparamislast = true;
01988             
01989             if (!getcharvalue (hp1, 1, &ch))
01990                 return (false);
01991             
01992             (*v).data.flvalue = ispunct ((unsigned char)ch) != 0;
01993             
01994             return (true);
01995             }
01996         
01997         case processmacrosfunc:
01998             return (processhtmlmacrosverb (hparam1, v));
01999         
02000         case urldecodefunc:
02001             return (urldecodeverb (hparam1, v));
02002         
02003         case urlencodefunc:
02004             return (urlencodeverb (hparam1, v));
02005         
02006         case parseargsfunc:
02007             return (parseargsverb (hparam1, v));
02008         
02009         case iso8859encodefunc:
02010             return (iso8859encodeverb (hparam1, v));
02011 
02012         case getgifheightwidthfunc:
02013             return (getgifheightwidthverb (hparam1, v));
02014 
02015         case getjpegheightwidthfunc:
02016             return (getjpegheightwidthverb (hparam1, v));
02017 
02018         case wrapfunc: {
02019             Handle htext;
02020             boolean result;
02021             
02022             flnextparamislast = true;
02023             
02024             if (!getexempttextvalue (hp1, 1, &htext)) 
02025                 return (false);
02026             
02027             result = wordwraphandle (htext);
02028             
02029             result = result && setheapvalue (htext, stringvaluetype, v);
02030 
02031             return (result);
02032             }
02033 
02034         case davenetmassagerfunc: {
02035             Handle htext, hnew;
02036             boolean result;
02037             short indentlen, maxlinelen; 
02038             
02039             if (!getintvalue (hp1, 1, &indentlen))
02040                 return (false);
02041 
02042             if (!getintvalue (hp1, 2, &maxlinelen))
02043                 return (false);
02044 
02045             flnextparamislast = true;
02046             
02047             if (!getreadonlytextvalue (hp1, 3, &htext)) 
02048                 return (false);
02049             
02050             result = daveNetMassager (indentlen, maxlinelen, htext, &hnew);
02051             
02052             result = result && setheapvalue (hnew, stringvaluetype, v);
02053             
02054             return (result);
02055             }
02056         
02057         case parseaddressfunc:
02058             return (parseaddressverb (hparam1, v));
02059         
02060         case dropnonalphasfunc:
02061             return (dropnonalphasverb (hparam1, v));
02062         
02063         case padwithzerosfunc:
02064             return (padwithzerosverb (hparam1, v));
02065         
02066         case ellipsizefunc: {
02067             Handle htext;
02068             long maxlen = 35;
02069             
02070             flnextparamislast = true;
02071                 
02072             if (!getpositivelongvalue (hparam1, 2, &maxlen))
02073                 return (false);
02074 
02075             if (!getexempttextvalue (hparam1, 1, &htext))
02076                 return (false);
02077 
02078             if (!ellipsizehandle (htext, maxlen)) {
02079             
02080                 disposehandle (htext);
02081                 
02082                 return (false);
02083                 }
02084 
02085             return (setheapvalue (htext, stringvaluetype, v));
02086             }
02087 
02088         case innercasefunc: {
02089             Handle x;
02090             
02091             flnextparamislast = true;
02092             
02093             if (!getexempttextvalue (hp1, 1, &x))
02094                 return (false);
02095             
02096             innercasehandle (x);
02097                         
02098             return (setheapvalue (x, stringvaluetype, v));
02099             }
02100         
02101         case urlsplitfunc: {
02102             Handle x;
02103             
02104             flnextparamislast = true;
02105             
02106             if (!getreadonlytextvalue (hp1, 1, &x))
02107                 return (false);
02108                         
02109             return (urlsplit (x, v));
02110             }
02111 
02112         case hashmd5func: {
02113             Handle x;
02114             MD5_CTX hashcontext; /* MD5 context. */
02115             unsigned char checksum[16];
02116             short ctconsumed = 1;
02117             short ctpositional = 1;
02118             tyvaluerecord vtranslate;
02119         
02120             if (!getreadonlytextvalue (hp1, 1, &x))
02121                 return (false);
02122 
02123             setbooleanvalue (true, &vtranslate);
02124 
02125             flnextparamislast = true;
02126 
02127             if (!getoptionalparamvalue (hp1, &ctconsumed, &ctpositional, BIGSTRING ("\x0b""flTranslate"), &vtranslate)) 
02128                 return (false);
02129 
02130 /*          if (langgetparamcount (hparam1) > 1) {
02131 
02132                 flnextparamislast = true;
02133         
02134                 if (!getbooleanvalue (hparam1, 2, &flTranslate))
02135                     return (false);
02136                 }
02137 */
02138             lockhandle (x);
02139     
02140             MD5Init (&hashcontext);
02141             
02142             MD5Update (&hashcontext, (unsigned char *)(*x), gethandlesize (x));
02143             
02144             MD5Final (checksum, &hashcontext);
02145             
02146             unlockhandle (x);
02147 
02148             if (vtranslate.data.flvalue) { /*return a hex string*/
02149                 bigstring lbs;
02150                 unsigned char enc[] = "0123456789abcdef";
02151                 long ix;
02152                 Handle h;
02153 
02154                 for(ix = 0; ix < 16; ix++) {
02155                     setstringcharacter (lbs, 2*ix, enc[(int)((checksum[ix])/16)]);
02156                     setstringcharacter (lbs, 2*ix+1, enc[(int)((checksum[ix])%16)]);
02157                     }/*for*/
02158 
02159                 setstringlength (lbs, 32);
02160 
02161                 if (!newtexthandle (lbs, &h))
02162                     return (false);
02163 
02164                 return (setheapvalue (h, stringvaluetype, v));
02165                 }
02166 
02167             else { /*return a binary of unknown type*/
02168                 Handle h;
02169 
02170                 if (!newfilledhandle (checksum, 16, &h))
02171                     return (false);
02172 
02173                 return (setbinaryvalue (h, typeunknown, v));
02174                 }
02175             
02176             return (true);
02177             }
02178             
02179         case latintomacfunc: { /*7.0b28 PBS: convert from Latin to Mac character sets*/
02180         
02181             Handle h;
02182             
02183             flnextparamislast = true;
02184             
02185             if (!getexempttextvalue (hp1, 1, &h))
02186                 return (false);
02187                 
02188             latintomac (h);
02189 
02190             return (setheapvalue (h, stringvaluetype, v));
02191             }
02192         
02193         case mactolatinfunc: { /*7.0b35 PBS: convert from Mac to Latin character sets*/
02194         
02195             Handle h;
02196             
02197             flnextparamislast = true;
02198             
02199             if (!getexempttextvalue (hp1, 1, &h))
02200                 return (false);
02201                 
02202             mactolatin (h);
02203 
02204             return (setheapvalue (h, stringvaluetype, v));
02205             }
02206 
02207         case utf16toansifunc: { /*7.0b41: convert from UTF-16 to ANSI*/
02208 
02209             Handle h, hresult;
02210 
02211             flnextparamislast = true;
02212 
02213             if (!getexempttextvalue (hp1, 1, &h))
02214                 return (false);
02215 
02216             newemptyhandle (&hresult);
02217 
02218             if (!utf16toansi (h, hresult))
02219                 return (false);
02220 
02221             disposehandle(h); // kw 2005-07-23 --- memleak
02222 
02223             return (setheapvalue (hresult, stringvaluetype, v));
02224             }
02225 
02226         case utf8toansifunc: { /*7.0b41: convert from UTF-8 to ANSI*/
02227 
02228             Handle h, hresult;
02229 
02230             flnextparamislast = true;
02231 
02232             if (!getexempttextvalue (hp1, 1, &h))
02233                 return (false);
02234 
02235             newemptyhandle (&hresult);
02236 
02237             if (!utf8toansi (h, hresult))
02238                 return (false);
02239 
02240             disposehandle(h); // kw 2005-07-23 --- memleak
02241 
02242             return (setheapvalue (hresult, stringvaluetype, v));
02243             }
02244 
02245         case ansitoutf8func: { /*7.0b41: convert from ANSI to UTF-8*/
02246 
02247             Handle h, hresult;
02248 
02249             flnextparamislast = true;
02250 
02251             if (!getexempttextvalue (hp1, 1, &h))
02252                 return (false);
02253 
02254             newemptyhandle (&hresult);
02255 
02256             if (!ansitoutf8 (h, hresult))
02257                 return (false);
02258 
02259             disposehandle(h); // kw 2005-07-23 --- memleak
02260 
02261             return (setheapvalue (hresult, stringvaluetype, v));
02262             }
02263 
02264         case ansitoutf16func: { /*7.0b41: convert from ANSI to UTF-16*/
02265 
02266             Handle h, hresult;
02267 
02268             flnextparamislast = true;
02269 
02270             if (!getexempttextvalue (hp1, 1, &h))
02271                 return (false);
02272 
02273             newemptyhandle (&hresult);
02274 
02275             if (!ansitoutf16 (h, hresult))
02276                 return (false);
02277 
02278             disposehandle (h); // kw 2005-07-23 --- memleak
02279 
02280             return (setheapvalue (hresult, stringvaluetype, v));
02281             }
02282 
02283         case multiplereplaceallfunc: { /*7.0b58: multiple string.replaceAlls*/
02284             
02285             return (stringmultiplereplaceallverb (hp1, v));
02286             }
02287             
02288         case macromantoutf8func: { /* 2006-02-25 creedon: convert mac roman character set to utf-8 */
02289 
02290             Handle h, hresult;
02291 
02292             flnextparamislast = true;
02293 
02294             if (!getreadonlytextvalue (hp1, 1, &h))
02295                 goto error;
02296 
02297             newemptyhandle (&hresult);
02298 
02299             if (!macromantoutf8 (h, hresult))
02300                 goto error;
02301 
02302             return (setheapvalue (hresult, stringvaluetype, v));
02303             }
02304 
02305         case utf8tomacromanfunc: { /* 2006-02-25 creedon: convert utf-8 character set to mac roman */
02306 
02307             Handle h, hresult;
02308 
02309             flnextparamislast = true;
02310 
02311             if (!getreadonlytextvalue (hp1, 1, &h))
02312                 goto error;
02313 
02314             newemptyhandle (&hresult);
02315 
02316             if (!utf8tomacroman (h, hresult))
02317                 goto error;
02318 
02319             return (setheapvalue (hresult, stringvaluetype, v));
02320             }
02321         
02322         case convertcharsetfunc:  /* 2006-04-13 smd: convert any character set to any other character set, if the os supports it */
02323         {
02324             Handle h, hresult;
02325             bigstring charsetIn, charsetOut;
02326             
02327             /*
02328                 the "internet names" of character sets are 40 ASCII chars or less,
02329                 so this is a safe way to get the params
02330             */
02331             if ( !getstringvalue( hp1, 1, charsetIn ) )
02332                 goto error;
02333             
02334             if ( !getstringvalue( hp1, 2, charsetOut ) )
02335                 goto error;
02336             
02337             flnextparamislast = true;
02338             
02339             if ( !getreadonlytextvalue( hp1, 3, &h ) )
02340                 goto error;
02341             
02342             newemptyhandle( &hresult );
02343             
02344             if ( !convertCharset( h, hresult, charsetIn, charsetOut ) )
02345                 goto error;
02346             
02347             return ( setheapvalue( hresult, stringvaluetype, v ) );
02348         }
02349         
02350         case ischarsetavailablefunc:  /* 2006-04-23 smd: determine if a character set is available, based on an internet-friendly (IANA) name */
02351         {
02352             return isCharsetAvailableVerb( hparam1, v );
02353         }
02354         
02355         default:
02356             errornum = notimplementederror;
02357             
02358             goto error;
02359         } /*switch*/
02360     
02361     error:
02362     
02363     if (errornum != 0) /*get error string*/
02364         getstringlist (stringerrorlist, errornum, bserror);
02365     
02366     return (false);
02367     } /*stringfunctionvalue*/
02368 
02369 
02370 boolean stringinitverbs (void) {
02371     
02372     /*
02373     if you just changed or added some definitions in stringinitbuiltins, call
02374     stringinstallbuiltins here.  rebuild, run the program, come back and change
02375     it to stringloadbuiltins, rebuild and go on...
02376     
02377     12/18/90 dmb: no longer save hash tables in program file, so we just 
02378     initialize the builtins directly.
02379     
02380     2.1b5 dmb: verb initialization is now resource-based
02381     */
02382     
02383     return (loadfunctionprocessor (idstringverbs, &stringfunctionvalue));
02384     } /*stringinitverbs*/
02385 

Generated on Wed May 31 18:20:02 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6