libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmText.c 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmLinkedHeap.h"
  9. #include "cmText.h"
  10. #include "cmFloatTypes.h"
  11. #include "cmVectOps.h"
  12. typedef struct cmTextSys_str
  13. {
  14. cmErr_t err;
  15. cmLHeapH_t lhH;
  16. cmChar_t* buf;
  17. } cmTextSys_t;
  18. cmTextSysH_t cmTextSysNullHandle = cmSTATIC_NULL_HANDLE;
  19. cmTextSysH_t _cmTextSysGlobalH = cmSTATIC_NULL_HANDLE;
  20. cmTextSys_t* _cmTextSysHandleToPtr( cmTextSysH_t h )
  21. {
  22. cmTextSys_t* p = (cmTextSys_t*)h.h;
  23. assert(p != NULL);
  24. return p;
  25. }
  26. cmTxRC_t _cmTextSysFinalize( cmTextSys_t* p )
  27. {
  28. cmTxRC_t rc = kOkTxRC;
  29. if( cmLHeapIsValid(p->lhH) )
  30. cmLHeapDestroy(&p->lhH);
  31. cmMemFree(p->buf);
  32. cmMemFree(p);
  33. return rc;
  34. }
  35. cmTxRC_t cmTextSysInitialize( cmCtx_t* ctx, cmTextSysH_t* hp )
  36. {
  37. cmTxRC_t rc;
  38. if((rc = cmTextSysFinalize(hp)) != kOkTxRC )
  39. return rc;
  40. cmTextSys_t* p = cmMemAllocZ(cmTextSys_t,1);
  41. cmErrSetup(&p->err,&ctx->rpt,"Text System");
  42. if( cmLHeapIsValid( p->lhH = cmLHeapCreate( 8192, ctx )) == false )
  43. {
  44. rc = cmErrMsg(&p->err,kLHeapFailTxRC,"Linked Heap create failed.");
  45. goto errLabel;
  46. }
  47. hp->h = p;
  48. errLabel:
  49. return rc;
  50. }
  51. cmTxRC_t cmTextSysFinalize( cmTextSysH_t* hp )
  52. {
  53. cmTxRC_t rc = kOkTxRC;
  54. if( hp == NULL || cmTextSysIsValid(*hp)==false )
  55. return kOkTxRC;
  56. cmTextSys_t* p = _cmTextSysHandleToPtr(*hp);
  57. if((rc = _cmTextSysFinalize(p)) == kOkTxRC )
  58. {
  59. hp->h = NULL;
  60. }
  61. return rc;
  62. }
  63. bool cmTextSysIsValid( cmTextSysH_t h )
  64. { return h.h != NULL; }
  65. cmChar_t* _cmTextSysVPrintf( cmTextSysH_t h, cmLHeapH_t lhH, bool staticFl, const cmChar_t* fmt, va_list vl )
  66. {
  67. va_list vl1;
  68. va_copy(vl1,vl);
  69. cmTextSys_t* p = cmLHeapIsValid(lhH) ? NULL : _cmTextSysHandleToPtr(h);
  70. unsigned n = vsnprintf(NULL,0,fmt,vl);
  71. cmChar_t* s = NULL;
  72. if( staticFl )
  73. s = p->buf = cmMemResize(cmChar_t,p->buf,n+1);
  74. else
  75. s = cmLhAllocZ(cmLHeapIsValid(lhH) ? lhH : p->lhH,cmChar_t,n+1);
  76. unsigned m = vsnprintf(s,n+1,fmt,vl1);
  77. assert(m==n);
  78. s[n] = 0;
  79. return s;
  80. }
  81. cmChar_t* cmTextSysVPrintfH( cmLHeapH_t lhH, const cmChar_t* fmt, va_list vl )
  82. { return _cmTextSysVPrintf( cmTextSysNullHandle, lhH, false, fmt, vl ); }
  83. cmChar_t* cmTextSysPrintfH( cmLHeapH_t lhH, const cmChar_t* fmt, ... )
  84. {
  85. va_list vl;
  86. va_start( vl, fmt );
  87. cmChar_t* s = cmTextSysVPrintfH(lhH,fmt,vl);
  88. va_end(vl);
  89. return s;
  90. }
  91. cmChar_t* cmTextSysVPrintfS( cmTextSysH_t h, const cmChar_t* fmt, va_list vl )
  92. { return _cmTextSysVPrintf(h,cmLHeapNullHandle,true,fmt,vl); }
  93. cmChar_t* cmTextSysPrintfS( cmTextSysH_t h, const cmChar_t* fmt, ... )
  94. {
  95. va_list vl;
  96. va_start(vl,fmt);
  97. cmChar_t* s = cmTextSysVPrintfS(h,fmt,vl);
  98. va_end(vl);
  99. return s;
  100. }
  101. cmChar_t* cmTextSysVPrintf( cmTextSysH_t h, const cmChar_t* fmt, va_list vl )
  102. { return _cmTextSysVPrintf(h,cmLHeapNullHandle,false,fmt,vl); }
  103. cmChar_t* cmTextSysPrintf( cmTextSysH_t h, const cmChar_t* fmt, ... )
  104. {
  105. va_list vl;
  106. va_start(vl,fmt);
  107. cmChar_t* s = cmTextSysVPrintf(h,fmt,vl);
  108. va_end(vl);
  109. return s;
  110. }
  111. void cmTextSysFreeStr( cmTextSysH_t h, const cmChar_t* s )
  112. {
  113. cmTextSys_t* p = _cmTextSysHandleToPtr(h);
  114. cmLhFree(p->lhH,(cmChar_t*)s);
  115. }
  116. //
  117. // Global interface
  118. //
  119. cmTxRC_t cmTsInitialize( cmCtx_t* ctx )
  120. { return cmTextSysInitialize(ctx,&_cmTextSysGlobalH); }
  121. cmTxRC_t cmTsFinalize()
  122. { return cmTextSysFinalize(&_cmTextSysGlobalH); }
  123. bool cmTsIsValid()
  124. { return cmTextSysIsValid(_cmTextSysGlobalH); }
  125. cmChar_t* cmTsVPrintfS( const cmChar_t* fmt, va_list vl )
  126. { return cmTextSysVPrintfS(_cmTextSysGlobalH,fmt,vl); }
  127. cmChar_t* cmTsPrintfS( const cmChar_t* fmt, ... )
  128. {
  129. va_list vl;
  130. va_start(vl,fmt);
  131. cmChar_t* s = cmTsVPrintfS(fmt,vl);
  132. va_end(vl);
  133. return s;
  134. }
  135. cmChar_t* cmTsVPrintfH( cmLHeapH_t h, const cmChar_t* fmt, va_list vl )
  136. { return cmTextSysVPrintfH(h,fmt,vl); }
  137. cmChar_t* cmTsPrintfH( cmLHeapH_t h, const cmChar_t* fmt, ... )
  138. {
  139. va_list vl;
  140. va_start(vl,fmt);
  141. cmChar_t* s = cmTsVPrintfH(h,fmt,vl);
  142. va_end(vl);
  143. return s;
  144. }
  145. cmChar_t* cmTsVPrintf( const cmChar_t* fmt, va_list vl )
  146. { return cmTextSysVPrintf(_cmTextSysGlobalH,fmt,vl); }
  147. cmChar_t* cmTsPrintf( const cmChar_t* fmt, ... )
  148. {
  149. va_list vl;
  150. va_start(vl,fmt);
  151. cmChar_t* s = cmTsVPrintf(fmt,vl);
  152. va_end(vl);
  153. return s;
  154. }
  155. void cmTsFreeStr( const cmChar_t* s )
  156. { cmTextSysFreeStr(_cmTextSysGlobalH,s); }
  157. cmChar_t* cmTsVPrintfP( cmChar_t* s, const cmChar_t* fmt, va_list vl )
  158. {
  159. va_list vl1;
  160. va_copy(vl1,vl);
  161. int n = vsnprintf(NULL,0,fmt,vl);
  162. assert(n != -1);
  163. s = cmMemResize(cmChar_t,s,n+1);
  164. unsigned m = vsnprintf(s,n+1,fmt,vl1);
  165. assert(m==n);
  166. s[n] = 0;
  167. return s;
  168. }
  169. cmChar_t* cmTsPrintfP( cmChar_t* s, const cmChar_t* fmt, ... )
  170. {
  171. va_list vl;
  172. va_start(vl,fmt);
  173. s = cmTsVPrintfP(s,fmt,vl);
  174. va_end(vl);
  175. return s;
  176. }
  177. void _cmTxError( cmErr_t* err, cmTxRC_t rc, const char* fmt, ... )
  178. {
  179. va_list vl;
  180. va_start(vl,fmt);
  181. cmErrVMsg(err,rc,fmt,vl);
  182. va_end(vl);
  183. }
  184. cmTxRC_t _cmTxRptError( cmErr_t* err, const char* msg, const char* inputText )
  185. {
  186. if( err == NULL )
  187. return kOkTxRC;
  188. if( inputText == NULL )
  189. {
  190. _cmTxError(err,kNullTxRC,"Text to %s conversion failed due to NULL input text.");
  191. return kNullTxRC;
  192. }
  193. if( errno != 0 )
  194. {
  195. _cmTxError(err,kCvtErrTxRC,"Text to %s conversion failed on input '%s'.",msg,inputText);
  196. return kCvtErrTxRC;
  197. }
  198. return kOkTxRC;
  199. }
  200. cmTxRC_t cmTextToInt(const char* text, int* vp, cmErr_t* err )
  201. {
  202. assert( vp != NULL );
  203. cmTxRC_t rc = kOkTxRC;
  204. int en = errno;
  205. errno = 0;
  206. *vp = text==NULL ? 0 : strtol(text,NULL,0);
  207. rc = _cmTxRptError(err,"integer",text);
  208. errno = en;
  209. return rc;
  210. }
  211. cmTxRC_t cmTextToUInt( const char* text, unsigned* vp, cmErr_t* err )
  212. {
  213. assert( vp != NULL );
  214. cmTxRC_t rc = kOkTxRC;
  215. int en = errno;
  216. errno = 0;
  217. *vp = text==NULL ? 0 : (unsigned)strtol(text,NULL,0);
  218. rc = _cmTxRptError(err,"unsigned integer",text);
  219. errno = en;
  220. return rc;
  221. }
  222. cmTxRC_t cmTextToFloat( const char* text, float* vp, cmErr_t* err )
  223. {
  224. assert( vp != NULL );
  225. cmTxRC_t rc = kOkTxRC;
  226. int en = errno;
  227. errno = 0;
  228. *vp = text==NULL ? 0 : (float)strtod(text,NULL);
  229. rc = _cmTxRptError(err,"float",text);
  230. errno = en;
  231. return rc;
  232. }
  233. cmTxRC_t cmTextToDouble( const char* text, double* vp, cmErr_t* err )
  234. {
  235. assert( vp != NULL );
  236. cmTxRC_t rc = kOkTxRC;
  237. int en = errno;
  238. errno = 0;
  239. *vp = text==NULL ? 0 : strtod(text,NULL);
  240. rc = _cmTxRptError(err,"double",text);
  241. errno = en;
  242. return rc;
  243. }
  244. cmTxRC_t cmTextToBool( const char* text, bool* vp, cmErr_t* err )
  245. {
  246. assert( vp != NULL );
  247. cmTxRC_t rc = kOkTxRC;
  248. if( strcasecmp(text,"true") == 0 || strcasecmp(text,"0") == 0 )
  249. *vp = true;
  250. else
  251. if( strcasecmp(text,"false") == 0 || strcasecmp(text,"1") == 0 )
  252. *vp = false;
  253. else
  254. rc = _cmTxRptError(err,"bool",text);
  255. return rc;
  256. }
  257. cmChar_t* cmTextNextNonWhiteOrEos( cmChar_t* s )
  258. {
  259. assert( s != NULL );
  260. while( (*s) && isspace(*s) )
  261. ++s;
  262. return s;
  263. }
  264. const cmChar_t* cmTextNextNonWhiteOrEosC( const cmChar_t* s )
  265. { return cmTextNextNonWhiteOrEos((cmChar_t*)s); }
  266. cmChar_t* cmTextNextNonWhite( cmChar_t* s )
  267. { //return (*(s=cmTextNextNonWhiteOrEos(s))) == 0 ? NULL : s;
  268. s=cmTextNextNonWhiteOrEos(s);
  269. if( *s == 0 )
  270. return NULL;
  271. return s;
  272. }
  273. const cmChar_t* cmTextNextNonWhiteC( const cmChar_t* s )
  274. { return cmTextNextNonWhite((cmChar_t*)s); }
  275. cmChar_t* cmTextPrevNonWhiteOrBos( cmChar_t* s0, const cmChar_t* s1 )
  276. {
  277. assert( s0!=NULL && s1!=NULL && s0 <= s1 );
  278. for(; s0 < s1; --s1 )
  279. if( !isspace(*s1) )
  280. break;
  281. return (cmChar_t*)s1;
  282. }
  283. const cmChar_t* cmTextPrevNonWhiteOrBosC( const cmChar_t* s0, const cmChar_t* s1 )
  284. { return cmTextPrevNonWhiteOrBos((cmChar_t*)s0,s1); }
  285. cmChar_t* cmTextPrevNonWhite( cmChar_t* s0, const cmChar_t* s1 )
  286. {
  287. cmChar_t* s2;
  288. if((s2 = cmTextPrevNonWhiteOrBos(s0,s1)) == s0 )
  289. return NULL;
  290. return s2;
  291. }
  292. const cmChar_t* cmTextPrevNonWhiteC( const cmChar_t* s0, const cmChar_t* s1 )
  293. { return cmTextPrevNonWhite((cmChar_t*)s0,s1); }
  294. cmChar_t* cmTextNextWhiteOrEos( cmChar_t* s )
  295. {
  296. assert( s!=NULL);
  297. while(*s && !isspace(*s) )
  298. ++s;
  299. return s;
  300. }
  301. const cmChar_t* cmTextNextWhiteOrEosC( const cmChar_t* s )
  302. { return cmTextNextWhiteOrEos((cmChar_t*)s); }
  303. cmChar_t* cmTextNextWhite( cmChar_t* s )
  304. { return (*(s=cmTextNextWhiteOrEos(s)))!=0 ? s : NULL; }
  305. const cmChar_t* cmTextNextWhiteC( const cmChar_t* s )
  306. { return cmTextNextWhite((cmChar_t*)s); }
  307. cmChar_t* cmTextPrevWhiteOrBos( cmChar_t* s0, const cmChar_t* s1 )
  308. {
  309. assert( s0!=NULL && s1!=NULL && s0 <= s1 );
  310. while( s1>s0 && !isspace(*s1) )
  311. --s1;
  312. return (cmChar_t*)s1;
  313. }
  314. const cmChar_t* cmTextPrevWhiteOrBosC( const cmChar_t* s0, const cmChar_t* s1 )
  315. { return cmTextPrevWhiteOrBos((cmChar_t*)s0,s1); }
  316. cmChar_t* cmTextPrevWhite( cmChar_t* s0, const cmChar_t* s1 )
  317. {
  318. cmChar_t* s2;
  319. if((s2 = cmTextPrevWhiteOrBos(s0,s1)) == s0 )
  320. return NULL;
  321. return s2;
  322. }
  323. const cmChar_t* cmTextPrevWhiteC( const cmChar_t* s0, const cmChar_t* s1 )
  324. { return cmTextPrevWhite((cmChar_t*)s0,s1); }
  325. cmChar_t* cmTextBegOfLine( cmChar_t* s0, const cmChar_t* s1 )
  326. {
  327. assert( s1!=NULL && s0!=NULL && s1 >= s0 );
  328. if( s0 == s1 )
  329. return s0;
  330. --s1;
  331. while( s1>s0 && *s1 != '\n' )
  332. --s1;
  333. if( *s1 == '\n' )
  334. ++s1;
  335. return (cmChar_t*)s1;
  336. }
  337. const cmChar_t* cmTextBegOfLineC( const cmChar_t* s0, const cmChar_t* s1 )
  338. { return cmTextBegOfLine((cmChar_t*)s0,s1); }
  339. cmChar_t* cmTextEndOfLine( cmChar_t* s )
  340. {
  341. assert( s!=NULL);
  342. while( *s!=0 && *s != '\n' )
  343. ++s;
  344. return s;
  345. }
  346. const cmChar_t* cmTextEndOfLineC( const cmChar_t* s )
  347. { return cmTextEndOfLine((cmChar_t*)s); }
  348. cmChar_t* cmTextLastNonWhiteChar( const cmChar_t* s )
  349. {
  350. unsigned n;
  351. if(s==NULL || (n = strlen(s)) == 0 )
  352. return NULL;
  353. cmChar_t* s0 = (cmChar_t*)s + n-1;
  354. for(; s0>=s; --s0)
  355. if( !isspace(*s0) )
  356. return s0;
  357. return NULL;
  358. }
  359. const cmChar_t* cmTextLastNonWhiteCharC( const cmChar_t* s )
  360. { return cmTextLastNonWhiteChar(s); }
  361. void cmTextShrinkS( cmChar_t* s, const cmChar_t* t, unsigned tn )
  362. { cmVOC_Shrink(s,strlen(s)+1,t,tn); }
  363. void cmTextShrinkSN(cmChar_t* s, unsigned sn, const cmChar_t* t, unsigned tn )
  364. { cmVOC_Shrink(s,sn,t,tn); }
  365. void cmTextClip( cmChar_t* s, unsigned n )
  366. {
  367. if( n == 0 || s == NULL || strlen(s)==0 )
  368. return;
  369. if( n >= strlen(s) )
  370. {
  371. s[0]=0;
  372. return;
  373. }
  374. s[ strlen(s)-n ] = 0;
  375. }
  376. cmChar_t* cmTextExpandS( cmChar_t* s, const cmChar_t* t, unsigned tn )
  377. { return cmVOC_Expand(s,strlen(s)+1,t,tn); }
  378. cmChar_t* cmTextReplaceSN( cmChar_t* s, const cmChar_t* t, unsigned tn, const cmChar_t* u, unsigned un )
  379. {
  380. unsigned n = strlen(s)+1;
  381. return cmVOC_Replace(s,&n,t,tn,u,un);
  382. }
  383. cmChar_t* cmTextReplaceS( cmChar_t* s, const cmChar_t* t, unsigned tn, const cmChar_t* u )
  384. { return cmTextReplaceSN(s,t,tn,u,u==NULL ? 0 : strlen(u)); }
  385. cmChar_t* _cmTextReplace( cmChar_t* s, const cmChar_t* t, const cmChar_t* u, unsigned n )
  386. {
  387. // we will go into an endless loop if 't' is contained in 'u' and n > 1.
  388. assert( s!= NULL && t!=NULL && u!=NULL && (n==1 || strstr(u,t) == NULL) );
  389. int tn = strlen(t);
  390. cmChar_t* c = NULL;
  391. unsigned i = 0;
  392. while( (c = strstr(s,t)) != NULL )
  393. {
  394. s = cmTextReplaceS(s,c,tn,u);
  395. assert(s!=NULL);
  396. ++i;
  397. if( n!=cmInvalidCnt && i>=n)
  398. break;
  399. };
  400. return s;
  401. }
  402. cmChar_t* cmTextReplaceAll( cmChar_t* s, const cmChar_t* t, const cmChar_t* u )
  403. { return _cmTextReplace(s,t,u,cmInvalidCnt); }
  404. cmChar_t* cmTextReplaceFirst( cmChar_t* s, const cmChar_t* t, const cmChar_t* u )
  405. { return _cmTextReplace(s,t,u,1); }
  406. cmChar_t* cmTextInsertSN( cmChar_t* s, const cmChar_t* t, const cmChar_t* u, unsigned un )
  407. {
  408. unsigned n = strlen(s)+1;
  409. return cmVOC_Replace(s,&n,t,0,u,un);
  410. }
  411. cmChar_t* cmTextInsertS( cmChar_t* s, const cmChar_t* t, const cmChar_t* u )
  412. { return cmTextInsertSN(s,t,u,u==NULL?0:strlen(u)); }
  413. cmChar_t* cmTextAppend( cmChar_t* s, unsigned* sn, const cmChar_t* u, unsigned un )
  414. { return cmVOC_Replace(s,sn,s+(*sn),0,u,un); }
  415. cmChar_t* cmTextAppendSN( cmChar_t* s, const cmChar_t* u, unsigned un )
  416. {
  417. unsigned sn = s==NULL ? 0 : strlen(s);
  418. if( un > 0 )
  419. {
  420. s = cmTextAppend(s,&sn,u,un+1);
  421. s[sn-1] = 0;
  422. }
  423. return s;
  424. }
  425. // append u[un] to s[] and append terminating zero.
  426. cmChar_t* cmTextAppendSNZ( cmChar_t* s, const cmChar_t* u, unsigned un )
  427. {
  428. unsigned sn = s==NULL ? 0 : strlen(s)+1;
  429. cmChar_t z = 0;
  430. s = cmTextAppend(s,&sn,u,un);
  431. return cmTextAppend(s,&sn,&z,1);
  432. }
  433. // both s[] and u[] are strz's
  434. cmChar_t* cmTextAppendSS( cmChar_t* s, const cmChar_t* u )
  435. { return cmTextAppendSN(s,u,strlen(u)); }
  436. cmChar_t* cmTextAppendChar( cmChar_t* s, cmChar_t c, unsigned n )
  437. {
  438. if( n <= 0 )
  439. return s;
  440. cmChar_t t[ n+1 ];
  441. memset(t,' ',n);
  442. t[n] = 0;
  443. return cmTextAppendSS(s,t);
  444. }
  445. bool cmTextIsEmpty( const cmChar_t* s )
  446. {
  447. if( s!=NULL )
  448. for(; *s; ++s )
  449. if( !isspace(*s) )
  450. return false;
  451. return true;
  452. }
  453. bool cmTextIsNotEmpty( const cmChar_t* s )
  454. { return !cmTextIsEmpty(s); }
  455. cmChar_t* cmTextLine( cmChar_t* s, unsigned line )
  456. {
  457. assert( line>0);
  458. unsigned i;
  459. // count down to the code line containing the tag reference
  460. for(i=0; i<line-1; ++i)
  461. {
  462. s = strchr(s,'\n');
  463. if( s == NULL )
  464. return NULL;
  465. ++s;
  466. }
  467. return s+1;
  468. }
  469. const cmChar_t* cmTextLineC( const cmChar_t* s, unsigned line )
  470. { return cmTextLine((cmChar_t*)s,line); }
  471. cmChar_t* cmTextRemoveConsecutiveSpaces( cmChar_t* s )
  472. {
  473. if( s==NULL || strlen(s) < 2 )
  474. return s;
  475. int i=1;
  476. while( s[i] )
  477. {
  478. if( isspace(s[i-1]) && isspace(s[i]) )
  479. cmTextShrinkS(s, s+i, 1 );
  480. else
  481. ++i;
  482. }
  483. return s;
  484. }
  485. cmChar_t* cmTextColumize( cmChar_t* s, unsigned colCnt )
  486. {
  487. if( s==NULL || strlen(s) < colCnt )
  488. return s;
  489. int i = 0;
  490. int c = 0;
  491. cmChar_t* c0 = NULL;
  492. for(; s[i]; ++i)
  493. {
  494. // remove any existing newlines
  495. if( s[i] == '\n' )
  496. s[i] = ' ';
  497. // track the last space (which is a potential wrap point).
  498. if( isspace(s[i]) )
  499. c0 = s+i;
  500. if( c < colCnt )
  501. ++c;
  502. else
  503. {
  504. // if there is no previous wrap point ...
  505. if( c0 == NULL )
  506. {
  507. // ... then insert one
  508. s = cmTextInsertS(s,s+i,"\n");
  509. }
  510. else
  511. {
  512. // replace the wrap point with a '\n'
  513. *c0 = '\n';
  514. }
  515. c = 0;
  516. c0 = NULL;
  517. }
  518. }
  519. return s;
  520. }
  521. cmChar_t* _cmTextPrefixRows( cmChar_t* s, const cmChar_t* t )
  522. {
  523. if( s==NULL || t==NULL || strlen(t)==0 )
  524. return s;
  525. int i;
  526. for(i=0; s[i]; ++i)
  527. if( i==0 || s[i]=='\n')
  528. {
  529. cmChar_t* u = s + (i==0 ? 0 : i+1);
  530. s = cmTextInsertS(s,u,t);
  531. }
  532. return s;
  533. }
  534. cmChar_t* cmTextIndentRows( cmChar_t* s, unsigned indent )
  535. {
  536. if( s==NULL || indent==0 )
  537. return s;
  538. cmChar_t* t = cmMemAllocZ( cmChar_t, indent+1 );
  539. cmVOC_Fill(t,indent,' ');
  540. t[indent] = 0;
  541. s = _cmTextPrefixRows(s,t);
  542. cmMemFree(t);
  543. return s;
  544. }
  545. cmChar_t* cmTextPrefixRows( cmChar_t* s, const cmChar_t* t )
  546. { return _cmTextPrefixRows(s,t); }
  547. cmChar_t* cmTextTrimRows( cmChar_t* s )
  548. {
  549. bool fl = true;
  550. int i = 0;
  551. while( s[i] )
  552. {
  553. if( s[i] == '\n' )
  554. {
  555. fl = true;
  556. ++i;
  557. }
  558. else
  559. {
  560. if( isspace(s[i]) && fl )
  561. cmTextShrinkS(s, s+i, 1 );
  562. else
  563. {
  564. fl = false;
  565. ++i;
  566. }
  567. }
  568. }
  569. return s;
  570. }
  571. cmChar_t* cmTextEatLeadingSpace( cmChar_t* s )
  572. {
  573. if( s == NULL )
  574. return s;
  575. while( *s )
  576. {
  577. if( !isspace(*s) )
  578. break;
  579. cmTextShrinkS(s,s,1);
  580. }
  581. return s;
  582. }