1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #ifdef HAVE_CONFIG_H
30 #include "../config.h"
31 #endif
32
33 #include "shift.h"
34 #include "textBuf.h"
35 #include "text.h"
36 #include "nedit.h"
37 #include "window.h"
38 #include "../util/nedit_malloc.h"
39
40 #include <string.h>
41 #include <limits.h>
42 #include <ctype.h>
43 #include <locale.h>
44 #include <wctype.h>
45 #include <wchar.h>
46 #include <sys/param.h>
47
48 #include <Xm/Xm.h>
49
50 #ifdef HAVE_DEBUG_H
51 #include "../debug.h"
52 #endif
53
54
55 static void shiftRect(WindowInfo *window,
int direction,
int byTab,
56 int selStart,
int selEnd,
int rectStart,
int rectEnd);
57 static void changeCase(WindowInfo *window,
int makeUpper);
58 static char *shiftLineRight(
char *line,
int lineLen,
int tabsAllowed,
59 int tabDist,
int nChars);
60 static char *shiftLineLeft(
char *line,
int lineLen,
int tabDist,
int nChars);
61 static int findLeftMargin(
char *text,
int length,
int tabDist);
62 static char *fillParagraphs(
char *text,
int rightMargin,
int tabDist,
63 int useTabs,
char nullSubsChar,
int *filledLen,
int alignWithFirst);
64 static char *fillParagraph(
char *text,
int leftMargin,
int firstLineIndent,
65 int rightMargin,
int tabDist,
int allowTabs,
char nullSubsChar,
66 int *filledLen);
67 static char *makeIndentString(
int indent,
int tabDist,
int allowTabs,
int *nChars);
68 static int atTabStop(
int pos,
int tabDist);
69 static int nextTab(
int pos,
int tabDist);
70 static int countLines(
const char *text);
71 static int findParagraphStart(textBuffer *buf,
int startPos);
72 static int findParagraphEnd(textBuffer *buf,
int startPos);
73
74
75
76
77
78
79 void ShiftSelection(WindowInfo *window,
int direction,
int byTab)
80 {
81 int selStart, selEnd, isRect, rectStart, rectEnd;
82 int shiftedLen, newEndPos, cursorPos, origLength, emTabDist, shiftDist;
83 char *text, *shiftedText;
84 textBuffer *buf = window->buffer;
85
86
87 if (!BufGetSelectionPos(buf, &selStart, &selEnd, &isRect,
88 &rectStart, &rectEnd)) {
89 cursorPos = TextGetCursorPos(window->lastFocus);
90 selStart = BufStartOfLine(buf, cursorPos);
91 selEnd = BufEndOfLine(buf, cursorPos);
92 if (selEnd < buf->length)
93 selEnd++;
94 BufSelect(buf, selStart, selEnd);
95 isRect = False;
96 text = BufGetRange(buf, selStart, selEnd);
97 }
else if (isRect) {
98 cursorPos = TextGetCursorPos(window->lastFocus);
99 origLength = buf->length;
100 shiftRect(window, direction, byTab, selStart, selEnd, rectStart,
101 rectEnd);
102 TextSetCursorPos(window->lastFocus, (cursorPos < (selEnd+selStart)/
2) ?
103 selStart : cursorPos + (buf->length - origLength));
104 return;
105 }
else {
106 selStart = BufStartOfLine(buf, selStart);
107 if (selEnd !=
0 && BufGetCharacter(buf, selEnd-
1) !=
'\n') {
108 selEnd = BufEndOfLine(buf, selEnd);
109 if (selEnd < buf->length)
110 selEnd++;
111 }
112 BufSelect(buf, selStart, selEnd);
113 text = BufGetRange(buf, selStart, selEnd);
114 }
115
116
117 if (byTab) {
118 XtVaGetValues(window->textArea, textNemulateTabs, &emTabDist,
NULL);
119 shiftDist = emTabDist ==
0 ? buf->tabDist : emTabDist;
120 }
else
121 shiftDist =
1;
122 shiftedText = ShiftText(text, direction, buf->useTabs, buf->tabDist,
123 shiftDist, &shiftedLen);
124 NEditFree(text);
125 BufReplaceSelected(buf, shiftedText);
126 NEditFree(shiftedText);
127
128 newEndPos = selStart + shiftedLen;
129 BufSelect(buf, selStart, newEndPos);
130 }
131
132 static void shiftRect(WindowInfo *window,
int direction,
int byTab,
133 int selStart,
int selEnd,
int rectStart,
int rectEnd)
134 {
135 int offset, emTabDist;
136 textBuffer *tempBuf, *buf = window->buffer;
137 char *text;
138
139
140 selStart = BufStartOfLine(buf, selStart);
141 selEnd = BufEndOfLine(buf, selEnd);
142
143
144 if (byTab) {
145 XtVaGetValues(window->textArea, textNemulateTabs, &emTabDist,
NULL);
146 offset = emTabDist ==
0 ? buf->tabDist : emTabDist;
147 }
else
148 offset =
1;
149 offset *= direction ==
SHIFT_LEFT ? -
1 :
1;
150 if (rectStart + offset <
0)
151 offset = -rectStart;
152
153
154
155 tempBuf = BufCreate();
156 tempBuf->tabDist = buf->tabDist;
157 tempBuf->useTabs = buf->useTabs;
158 text = BufGetRange(buf, selStart, selEnd);
159 BufSetAll(tempBuf, text);
160 NEditFree(text);
161
162
163 text = BufGetTextInRect(buf, selStart, selEnd, rectStart, rectEnd);
164 BufRemoveRect(tempBuf,
0, selEnd-selStart, rectStart, rectEnd);
165 BufInsertCol(tempBuf, rectStart+offset,
0, text,
NULL,
NULL);
166 NEditFree(text);
167
168
169 BufReplace(buf, selStart, selEnd, BufAsString(tempBuf));
170 BufRectSelect(buf, selStart, selStart + tempBuf->length,
171 rectStart+offset, rectEnd+offset);
172 BufFree(tempBuf);
173 }
174
175 void UpcaseSelection(WindowInfo *window)
176 {
177 changeCase(window, True);
178 }
179
180 void DowncaseSelection(WindowInfo *window)
181 {
182 changeCase(window, False);
183 }
184
185
186
187
188
189
190 static void changeCase(WindowInfo *window,
int makeUpper)
191 {
192 textBuffer *buf = window->buffer;
193 char *text, *c;
194 int cursorPos, start, end, isRect, rectStart, rectEnd;
195
196 char *bak_locale =
NULL;
197 if(!XNEditDefaultCharsetIsUTF8()) {
198 bak_locale = setlocale(
LC_CTYPE,
NULL);
199 setlocale(
LC_CTYPE,
"C.UTF-8");
200 }
201
202
203 if (!BufGetSelectionPos(buf, &start, &end, &isRect, &rectStart, &rectEnd)) {
204 cursorPos = TextGetCursorPos(window->lastFocus);
205 if (cursorPos ==
0) {
206 XBell(TheDisplay,
0);
207 if(bak_locale) setlocale(
LC_CTYPE, bak_locale);
208 return;
209 }
210
211 int leftPos = BufLeftPos(buf, cursorPos);
212
213 wchar_t w = BufGetCharacterW(buf, leftPos);
214 wchar_t wc = makeUpper ? towupper(w) : towlower(w);
215 if(wc ==
0) wc = w;
216
217 char bufChar[
8];
218 int clen = wctomb(bufChar, wc);
219 bufChar[clen] =
0;
220
221 BufReplace(buf, leftPos, cursorPos, bufChar);
222 }
else {
223 Boolean modified = False;
224
225 text = BufGetSelectionText(buf);
226 size_t textlen = strlen(text);
227
228
229 size_t conv_alloc = textlen +
8;
230 size_t conv_len =
0;
231 char *converted = NEditMalloc(conv_alloc);
232
233 mbstate_t state;
234 memset(&state,
0,
sizeof(
mbstate_t));
235
236 int inc =
1;
237 size_t i =
0;
238 size_t cpos =
0;
239 char utf8[
8];
240 int append_len =
0;
241 for(c = text; *c !=
'\0'; c += inc) {
242 inc = Utf8CharLen((
unsigned char*)c);
243 if(i + inc > textlen) {
244 inc = textlen - i;
245 }
246
247
248
249
250 wchar_t w;
251 size_t nconverted = mbrtowc(&w, c, inc, &state);
252 if(nconverted >
0) {
253 wchar_t wc = makeUpper ? towupper(w) : towlower(w);
254 append_len = wctomb(utf8, wc);
255 if(wc != w) {
256 modified = True;
257 }
258 inc = nconverted;
259 }
else {
260 append_len = inc;
261 }
262
263 if(conv_alloc - cpos -
1 < append_len) {
264 conv_alloc +=
32;
265 converted = NEditRealloc(converted, conv_alloc);
266 }
267 memcpy(converted + cpos, utf8, append_len);
268 conv_len += append_len;
269
270 cpos += append_len;
271 i += inc;
272 }
273
274 converted[conv_len] =
'\0';
275
276 if (modified) {
277 BufReplaceSelected(buf, converted);
278 }
279
280 NEditFree(converted);
281 NEditFree(text);
282 if (isRect)
283 BufRectSelect(buf, start, end, rectStart, rectEnd);
284 else
285 BufSelect(buf, start, end);
286 }
287
288 if(bak_locale) setlocale(
LC_CTYPE, bak_locale);
289 }
290
291 void FillSelection(WindowInfo *window)
292 {
293 textBuffer *buf = window->buffer;
294 char *text, *filledText;
295 int left, right, nCols, len, isRect, rectStart, rectEnd;
296 int rightMargin, wrapMargin;
297 int insertPos = TextGetCursorPos(window->lastFocus);
298 int hasSelection = window->buffer->primary.selected;
299
300
301
302
303
304 if (!BufGetSelectionPos(buf, &left, &right, &isRect, &rectStart, &rectEnd)) {
305 left = findParagraphStart(buf, insertPos);
306 right = findParagraphEnd(buf, insertPos);
307 if (left == right) {
308 XBell(TheDisplay,
0);
309 return;
310 }
311 text = BufGetRange(buf, left, right);
312 }
else if (isRect) {
313 left = BufStartOfLine(buf, left);
314 right = BufEndOfLine(buf, right);
315 text = BufGetTextInRect(buf, left, right, rectStart,
INT_MAX);
316 }
else {
317 left = BufStartOfLine(buf, left);
318 if (right !=
0 && BufGetCharacter(buf, right-
1) !=
'\n') {
319 right = BufEndOfLine(buf, right);
320 if (right < buf->length)
321 right++;
322 }
323 BufSelect(buf, left, right);
324 text = BufGetRange(buf, left, right);
325 }
326
327
328
329 if (hasSelection && isRect) {
330 rightMargin = rectEnd - rectStart;
331 }
else
332 {
333 XtVaGetValues(window->textArea,
334 textNcolumns, &nCols,
335 textNwrapMargin, &wrapMargin,
336 NULL);
337 rightMargin = (wrapMargin ==
0 ? nCols : wrapMargin);
338 }
339
340
341 filledText = fillParagraphs(text, rightMargin, buf->tabDist, buf->useTabs,
342 buf->nullSubsChar, &len, False);
343 NEditFree(text);
344
345
346 if (hasSelection && isRect) {
347 BufReplaceRect(buf, left, right, rectStart,
INT_MAX, filledText);
348 BufRectSelect(buf, left,
349 BufEndOfLine(buf, BufCountForwardNLines(buf, left,
350 countLines(filledText)-
1)), rectStart, rectEnd);
351 }
else {
352 BufReplace(buf, left, right, filledText);
353 if (hasSelection)
354 BufSelect(buf, left, left + len);
355 }
356 NEditFree(filledText);
357
358
359
360 if (hasSelection && isRect)
361 TextSetCursorPos(window->lastFocus, buf->cursorPosHint);
362 else
363 TextSetCursorPos(window->lastFocus, insertPos < left ? left :
364 (insertPos > left + len ? left + len : insertPos));
365 }
366
367
368
369
370
371 char *ShiftText(
char *text,
int direction,
int tabsAllowed,
int tabDist,
372 int nChars,
int *newLen)
373 {
374 char *shiftedText, *shiftedLine;
375 char *textPtr, *lineStartPtr, *shiftedPtr;
376 int bufLen;
377
378
379
380
381
382
383 if (direction ==
SHIFT_RIGHT)
384 bufLen = strlen(text) + countLines(text) * nChars;
385 else
386 bufLen = strlen(text) + countLines(text) * tabDist;
387 shiftedText = (
char*)NEditMalloc(bufLen +
1);
388
389
390
391
392 lineStartPtr = text;
393 textPtr = text;
394 shiftedPtr = shiftedText;
395 while (
TRUE) {
396 if (*textPtr==
'\n' || *textPtr==
'\0') {
397 shiftedLine = (direction ==
SHIFT_RIGHT) ?
398 shiftLineRight(lineStartPtr, textPtr-lineStartPtr,
399 tabsAllowed, tabDist, nChars) :
400 shiftLineLeft(lineStartPtr, textPtr-lineStartPtr, tabDist,
401 nChars);
402 strcpy(shiftedPtr, shiftedLine);
403 shiftedPtr += strlen(shiftedLine);
404 NEditFree(shiftedLine);
405 if (*textPtr ==
'\0') {
406
407 *shiftedPtr =
'\0';
408 break;
409 }
else {
410
411 *shiftedPtr++ = *textPtr++;
412 }
413
414 lineStartPtr = textPtr;
415 }
else
416 textPtr++;
417 }
418 *newLen = shiftedPtr - shiftedText;
419 return shiftedText;
420 }
421
422 static char *shiftLineRight(
char *line,
int lineLen,
int tabsAllowed,
423 int tabDist,
int nChars)
424 {
425 char *lineOut;
426 char *lineInPtr, *lineOutPtr;
427 int whiteWidth, i;
428
429 lineInPtr = line;
430 lineOut = (
char*)NEditMalloc(lineLen + nChars +
1);
431 lineOutPtr = lineOut;
432 whiteWidth =
0;
433 while (
TRUE) {
434 if (*lineInPtr ==
'\0' || (lineInPtr - line) >= lineLen) {
435
436 *lineOut =
'\0';
437 return lineOut;
438 }
else if (*lineInPtr ==
' ') {
439
440 whiteWidth++;
441 *lineOutPtr++ = *lineInPtr++;
442 }
else if (*lineInPtr ==
'\t') {
443
444 whiteWidth = nextTab(whiteWidth, tabDist);
445 *lineOutPtr++ = *lineInPtr++;
446 }
else {
447
448 for (i=
0; i<nChars; i++) {
449 *lineOutPtr++ =
' ';
450 whiteWidth++;
451
452 if (tabsAllowed && atTabStop(whiteWidth, tabDist)) {
453 lineOutPtr -= tabDist;
454 *lineOutPtr++ =
'\t';
455 }
456 }
457
458 while (*lineInPtr!=
'\0' && (lineInPtr - line) < lineLen)
459 *lineOutPtr++ = *lineInPtr++;
460 *lineOutPtr =
'\0';
461 return lineOut;
462 }
463 }
464 }
465
466 static char *shiftLineLeft(
char *line,
int lineLen,
int tabDist,
int nChars)
467 {
468 char *lineOut;
469 int i, whiteWidth, lastWhiteWidth, whiteGoal;
470 char *lineInPtr, *lineOutPtr;
471
472 lineInPtr = line;
473 lineOut = (
char*)NEditMalloc(lineLen + tabDist +
1);
474 lineOutPtr = lineOut;
475 whiteWidth =
0;
476 lastWhiteWidth =
0;
477 while (
TRUE) {
478 if (*lineInPtr ==
'\0' || (lineInPtr - line) >= lineLen) {
479
480 *lineOut =
'\0';
481 return lineOut;
482 }
else if (*lineInPtr ==
' ') {
483
484 whiteWidth++;
485 *lineOutPtr++ = *lineInPtr++;
486 }
else if (*lineInPtr ==
'\t') {
487
488
489 lastWhiteWidth = whiteWidth;
490 whiteWidth = nextTab(whiteWidth, tabDist);
491 *lineOutPtr++ = *lineInPtr++;
492 }
else {
493
494 for (i=
1; i<=nChars; i++) {
495 if (lineOutPtr > lineOut) {
496 if (*(lineOutPtr-
1) ==
' ') {
497
498 lineOutPtr--;
499 }
else {
500
501
502 lineOutPtr--;
503 whiteGoal = whiteWidth - i;
504 whiteWidth = lastWhiteWidth;
505 while (whiteWidth < whiteGoal) {
506 *lineOutPtr++ =
' ';
507 whiteWidth++;
508 }
509 }
510 }
511 }
512
513 while (*lineInPtr!=
'\0' && (lineInPtr - line) < lineLen)
514 *lineOutPtr++ = *lineInPtr++;
515
516 *lineOutPtr =
'\0';
517 return lineOut;
518 }
519 }
520 }
521
522 static int atTabStop(
int pos,
int tabDist)
523 {
524 return (pos%tabDist ==
0);
525 }
526
527 static int nextTab(
int pos,
int tabDist)
528 {
529 return (pos/tabDist)*tabDist + tabDist;
530 }
531
532 static int countLines(
const char *text)
533 {
534 int count =
1;
535
536 while(*text !=
'\0') {
537 if (*text++ ==
'\n') {
538 count++;
539 }
540 }
541 return count;
542 }
543
544
545
546
547
548
549
550 static int findLeftMargin(
char *text,
int length,
int tabDist)
551 {
552 char *c;
553 int col =
0, leftMargin =
INT_MAX;
554 int inMargin = True;
555
556 for (c=text; *c!=
'\0' && c-text<length; c++) {
557 if (*c ==
'\t') {
558 col += BufCharWidth(
'\t', col, tabDist,
'\0');
559 }
else if (*c ==
' ') {
560 col++;
561 }
else if (*c ==
'\n') {
562 col =
0;
563 inMargin = True;
564 }
else {
565
566 if (col < leftMargin && inMargin)
567 leftMargin = col;
568 inMargin = False;
569 }
570 }
571
572
573 if (leftMargin ==
INT_MAX)
574 return 0;
575
576 return leftMargin;
577 }
578
579
580
581
582
583
584
585
586 static char *fillParagraphs(
char *text,
int rightMargin,
int tabDist,
587 int useTabs,
char nullSubsChar,
int *filledLen,
int alignWithFirst)
588 {
589 int paraStart, paraEnd, fillEnd;
590 char *c, ch, *secondLineStart, *paraText, *filledText;
591 int firstLineLen, firstLineIndent, leftMargin, len;
592 textBuffer *buf;
593
594
595 buf = BufCreate();
596 BufSetAll(buf, text);
597
598
599
600
601
602 paraStart =
0;
603 for (;;) {
604
605
606 while (paraStart < buf->length) {
607 ch = BufGetCharacter(buf, paraStart);
608 if (ch !=
' ' && ch !=
'\t' && ch !=
'\n')
609 break;
610 paraStart++;
611 }
612 if (paraStart >= buf->length)
613 break;
614 paraStart = BufStartOfLine(buf, paraStart);
615
616
617 paraEnd = findParagraphEnd(buf, paraStart);
618
619
620
621
622 fillEnd = alignWithFirst ? buf->length : paraEnd;
623
624
625
626 paraText = BufGetRange(buf, paraStart, fillEnd);
627
628
629
630 for (c=paraText ; *c!=
'\0' && *c!=
'\n'; c++);
631 firstLineLen = c - paraText;
632 secondLineStart = *c ==
'\0' ? paraText : c +
1;
633 firstLineIndent = findLeftMargin(paraText, firstLineLen, tabDist);
634 leftMargin = findLeftMargin(secondLineStart, paraEnd - paraStart -
635 (secondLineStart - paraText), tabDist);
636
637
638 filledText = fillParagraph(paraText, leftMargin, firstLineIndent,
639 rightMargin, tabDist, useTabs, nullSubsChar, &len);
640 NEditFree(paraText);
641
642
643 BufReplace(buf, paraStart, fillEnd, filledText);
644 NEditFree(filledText);
645
646
647 paraStart += len;
648 }
649
650
651 filledText = BufGetAll(buf);
652 *filledLen = buf->length;
653 BufFree(buf);
654 return filledText;
655 }
656
657
658
659
660
661
662
663
664 static char *fillParagraph(
char *text,
int leftMargin,
int firstLineIndent,
665 int rightMargin,
int tabDist,
int allowTabs,
char nullSubsChar,
666 int *filledLen)
667 {
668 char *cleanedText, *outText, *indentString, *leadIndentStr, *outPtr, *c, *b;
669 int col, cleanedLen, indentLen, leadIndentLen, nLines =
1;
670 int inWhitespace, inMargin;
671
672
673 cleanedText = (
char*)NEditMalloc(strlen(text)+
1);
674 outPtr = cleanedText;
675 inMargin = True;
676 for (c=text; *c!=
'\0'; c++) {
677 if (*c ==
'\t' || *c ==
' ') {
678 if (!inMargin)
679 *outPtr++ = *c;
680 }
else if (*c ==
'\n') {
681 if (inMargin) {
682
683
684 if (outPtr > cleanedText && *(outPtr-
1) ==
' ')
685 *(outPtr-
1) =
'\n';
686 *outPtr++ =
'\n';
687 nLines +=
2;
688 }
else
689 *outPtr++ =
' ';
690 inMargin = True;
691 }
else {
692 *outPtr++ = *c;
693 inMargin = False;
694 }
695 }
696 cleanedLen = outPtr - cleanedText;
697 *outPtr =
'\0';
698
699
700
701
702
703 col = firstLineIndent;
704 int inc =
1;
705 for (c=cleanedText; *c!=
'\0'; c+=inc) {
706 if (*c ==
'\n') {
707 col = leftMargin;
708 inc =
1;
709 }
else {
710 col += BufCharWidth(*c, col, tabDist, nullSubsChar);
711 inc = Utf8CharLen((
unsigned char*)c);
712 }
713 if (col-
1 > rightMargin) {
714 inWhitespace = True;
715 for (b=c; b>=cleanedText && *b!=
'\n'; b--) {
716 if (*b ==
'\t' || *b ==
' ') {
717 if (!inWhitespace) {
718 *b =
'\n';
719 c = b;
720 col = leftMargin;
721 nLines++;
722 break;
723 }
724 }
else
725 inWhitespace = False;
726 }
727 }
728 }
729 nLines++;
730
731
732 leadIndentStr = makeIndentString(firstLineIndent, tabDist,
733 allowTabs, &leadIndentLen);
734 indentString = makeIndentString(leftMargin, tabDist, allowTabs, &indentLen);
735
736
737 outText = (
char*)NEditMalloc(
sizeof(
char) * (cleanedLen + leadIndentLen +
738 indentLen * (nLines-
1) +
1));
739 outPtr = outText;
740
741
742 strncpy(outPtr, leadIndentStr, leadIndentLen);
743 outPtr += leadIndentLen;
744 for (c=cleanedText; *c!=
'\0'; c++) {
745 *outPtr++ = *c;
746 if (*c ==
'\n') {
747 strncpy(outPtr, indentString, indentLen);
748 outPtr += indentLen;
749 }
750 }
751
752
753 if (*(outPtr-
1) ==
' ')
754 *(outPtr-
1) =
'\n';
755 *outPtr =
'\0';
756
757
758 NEditFree(cleanedText);
759 NEditFree(leadIndentStr);
760 NEditFree(indentString);
761 *filledLen = outPtr - outText;
762 return outText;
763 }
764
765 static char *makeIndentString(
int indent,
int tabDist,
int allowTabs,
int *nChars)
766 {
767 char *indentString, *outPtr;
768 int i;
769
770 outPtr = indentString = (
char*)NEditMalloc(
sizeof(
char) * indent +
1);
771 if (allowTabs) {
772 for (i=
0; i<indent/tabDist; i++)
773 *outPtr++ =
'\t';
774 for (i=
0; i<indent%tabDist; i++)
775 *outPtr++ =
' ';
776 }
else {
777 for (i=
0; i<indent; i++)
778 *outPtr++ =
' ';
779 }
780 *outPtr =
'\0';
781 *nChars = outPtr - indentString;
782 return indentString;
783 }
784
785
786
787
788 static int findParagraphEnd(textBuffer *buf,
int startPos)
789 {
790 char c;
791 int pos;
792 static char whiteChars[] =
" \t";
793
794 pos = BufEndOfLine(buf, startPos)+
1;
795 while (pos < buf->length) {
796 c = BufGetCharacter(buf, pos);
797 if (c ==
'\n')
798 break;
799 if (strchr(whiteChars, c) !=
NULL)
800 pos++;
801 else
802 pos = BufEndOfLine(buf, pos)+
1;
803 }
804 return pos < buf->length ? pos : buf->length;
805 }
806 static int findParagraphStart(textBuffer *buf,
int startPos)
807 {
808 char c;
809 int pos, parStart;
810 static char whiteChars[] =
" \t";
811
812 if (startPos ==
0)
813 return 0;
814 parStart = BufStartOfLine(buf, startPos);
815 pos = parStart -
2;
816 while (pos >
0) {
817 c = BufGetCharacter(buf, pos);
818 if (c ==
'\n')
819 break;
820 if (strchr(whiteChars, c) !=
NULL)
821 pos--;
822 else {
823 parStart = BufStartOfLine(buf, pos);
824 pos = parStart -
2;
825 }
826 }
827 return parStart >
0 ? parStart :
0;
828 }
829