~ubuntu-branches/debian/stretch/alpine/stretch

« back to all changes in this revision

Viewing changes to pico/word.c

  • Committer: Bazaar Package Importer
  • Author(s): Asheesh Laroia
  • Date: 2007-02-17 13:17:42 UTC
  • Revision ID: james.westby@ubuntu.com-20070217131742-99x5c6cpg1pbkdhw
Tags: upstream-0.82+dfsg
ImportĀ upstreamĀ versionĀ 0.82+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#if     !defined(lint) && !defined(DOS)
 
2
static char rcsid[] = "$Id: word.c 334 2006-12-19 01:26:30Z hubert@u.washington.edu $";
 
3
#endif
 
4
 
 
5
/*
 
6
 * ========================================================================
 
7
 * Copyright 2006 University of Washington
 
8
 *
 
9
 * Licensed under the Apache License, Version 2.0 (the "License");
 
10
 * you may not use this file except in compliance with the License.
 
11
 * You may obtain a copy of the License at
 
12
 *
 
13
 *     http://www.apache.org/licenses/LICENSE-2.0
 
14
 *
 
15
 * ========================================================================
 
16
 */
 
17
 
 
18
/*
 
19
 * Program:     Word at a time routines
 
20
 *
 
21
 * The routines in this file implement commands that work word at a time.
 
22
 * There are all sorts of word mode commands. If I do any sentence and/or
 
23
 * paragraph mode commands, they are likely to be put in this file.
 
24
 */
 
25
 
 
26
#include        "headers.h"
 
27
 
 
28
 
 
29
int fpnewline(UCS *quote);
 
30
 
 
31
 
 
32
/* Word wrap on n-spaces. Back-over whatever precedes the point on the current
 
33
 * line and stop on the first word-break or the beginning of the line. If we
 
34
 * reach the beginning of the line, jump back to the end of the word and start
 
35
 * a new line.  Otherwise, break the line at the word-break, eat it, and jump
 
36
 * back to the end of the word.
 
37
 * Returns TRUE on success, FALSE on errors.
 
38
 */
 
39
int
 
40
wrapword(void)
 
41
{
 
42
    register int cnt;                   /* size of word wrapped to next line */
 
43
    register int bp;                    /* index to wrap on */
 
44
    register int first = -1;
 
45
    int wid, ww;
 
46
 
 
47
    if(curwp->w_doto <= 0)              /* no line to wrap? */
 
48
      return(FALSE);
 
49
 
 
50
    wid = 0;
 
51
    for(bp = cnt = 0; cnt < llength(curwp->w_dotp) && !bp; cnt++){
 
52
        if(ucs4_isspace(lgetc(curwp->w_dotp, cnt).c)){
 
53
            first = 0;
 
54
            if(lgetc(curwp->w_dotp, cnt).c == TAB){
 
55
              ++wid;
 
56
              while(wid & 0x07)
 
57
                ++wid;
 
58
            }
 
59
            else
 
60
              ++wid;
 
61
        }
 
62
        else{
 
63
            ww = wcellwidth((UCS) lgetc(curwp->w_dotp, cnt).c);
 
64
            wid += (ww >= 0 ? ww : 1);
 
65
            if(!first)
 
66
              first = cnt;
 
67
        }
 
68
 
 
69
        if(first > 0 && wid > fillcol)
 
70
          bp = first;
 
71
    }
 
72
 
 
73
    if(!bp)
 
74
      return(FALSE);
 
75
 
 
76
    /* bp now points to the first character of the next line */
 
77
    cnt = curwp->w_doto - bp;
 
78
    curwp->w_doto = bp;
 
79
 
 
80
    if(!lnewline())                     /* break the line */
 
81
      return(FALSE);
 
82
 
 
83
    /*
 
84
     * if there's a line below, it doesn't start with whitespace 
 
85
     * and there's room for this line...
 
86
     */
 
87
    if(!(curbp->b_flag & BFWRAPOPEN)
 
88
       && lforw(curwp->w_dotp) != curbp->b_linep 
 
89
       && llength(lforw(curwp->w_dotp)) 
 
90
       && !ucs4_isspace(lgetc(lforw(curwp->w_dotp), 0).c)
 
91
       && (llength(curwp->w_dotp) + llength(lforw(curwp->w_dotp)) < fillcol)){
 
92
        gotoeol(0, 1);                  /* then pull text up from below */
 
93
        if(lgetc(curwp->w_dotp, curwp->w_doto - 1).c != ' ')
 
94
          linsert(1, ' ');
 
95
 
 
96
        forwdel(0, 1);
 
97
        gotobol(0, 1);
 
98
    }
 
99
 
 
100
    curbp->b_flag &= ~BFWRAPOPEN;       /* don't open new line next wrap */
 
101
                                        /* restore dot (account for NL)  */
 
102
    if(cnt && !forwchar(0, cnt < 0 ? cnt-1 : cnt))
 
103
      return(FALSE);
 
104
 
 
105
    return(TRUE);
 
106
}
 
107
 
 
108
 
 
109
/*
 
110
 * Move the cursor backward by "n" words. All of the details of motion are
 
111
 * performed by the "backchar" and "forwchar" routines. Error if you try to
 
112
 * move beyond the buffers.
 
113
 */
 
114
int
 
115
backword(int f, int n)
 
116
{
 
117
        if (n < 0)
 
118
                return (forwword(f, -n));
 
119
        if (backchar(FALSE, 1) == FALSE)
 
120
                return (FALSE);
 
121
        while (n--) {
 
122
                while (inword() == FALSE) {
 
123
                        if (backchar(FALSE, 1) == FALSE)
 
124
                                return (FALSE);
 
125
                }
 
126
                while (inword() != FALSE) {
 
127
                        if (backchar(FALSE, 1) == FALSE)
 
128
                                return (FALSE);
 
129
                }
 
130
        }
 
131
        return (forwchar(FALSE, 1));
 
132
}
 
133
 
 
134
/*
 
135
 * Move the cursor forward by the specified number of words. All of the motion
 
136
 * is done by "forwchar". Error if you try and move beyond the buffer's end.
 
137
 */
 
138
int
 
139
forwword(int f, int n)
 
140
{
 
141
        if (n < 0)
 
142
                return (backword(f, -n));
 
143
        while (n--) {
 
144
#if     NFWORD
 
145
                while (inword() != FALSE) {
 
146
                        if (forwchar(FALSE, 1) == FALSE)
 
147
                                return (FALSE);
 
148
                }
 
149
#endif
 
150
                while (inword() == FALSE) {
 
151
                        if (forwchar(FALSE, 1) == FALSE)
 
152
                                return (FALSE);
 
153
                }
 
154
#if     NFWORD == 0
 
155
                while (inword() != FALSE) {
 
156
                        if (forwchar(FALSE, 1) == FALSE)
 
157
                                return (FALSE);
 
158
                }
 
159
#endif
 
160
        }
 
161
        return(TRUE);
 
162
}
 
163
 
 
164
int
 
165
ucs4_isalnum(UCS c)
 
166
{
 
167
    return((c && c <= 0x7f && isalnum((unsigned char) c))
 
168
           || (c >= 0xA0 && !SPECIAL_SPACE(c)));
 
169
}
 
170
 
 
171
int
 
172
ucs4_isalpha(UCS c)
 
173
{
 
174
    return((c && c <= 0x7f && isalpha((unsigned char) c))
 
175
           || (c >= 0xA0 && !SPECIAL_SPACE(c)));
 
176
}
 
177
 
 
178
int
 
179
ucs4_isspace(UCS c)
 
180
{
 
181
    return(c < 0xff && isspace((unsigned char) c) || SPECIAL_SPACE(c));
 
182
}
 
183
 
 
184
int
 
185
ucs4_ispunct(UCS c)
 
186
{
 
187
     return !ucs4_isalnum(c) && !ucs4_isspace(c);
 
188
}
 
189
 
 
190
#ifdef  MAYBELATER
 
191
/*
 
192
 * Move the cursor forward by the specified number of words. As you move,
 
193
 * convert any characters to upper case. Error if you try and move beyond the
 
194
 * end of the buffer. Bound to "M-U".
 
195
 */
 
196
int
 
197
upperword(int f, int n)
 
198
{
 
199
        register int    c;
 
200
        CELL            ac;
 
201
 
 
202
        ac.a = 0;
 
203
        if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
 
204
                return(rdonly());       /* we are in read only mode     */
 
205
        if (n < 0)
 
206
                return (FALSE);
 
207
        while (n--) {
 
208
                while (inword() == FALSE) {
 
209
                        if (forwchar(FALSE, 1) == FALSE)
 
210
                                return (FALSE);
 
211
                }
 
212
                while (inword() != FALSE) {
 
213
                        c = lgetc(curwp->w_dotp, curwp->w_doto).c;
 
214
                        if (c>='a' && c<='z') {
 
215
                                ac.c = (c -= 'a'-'A');
 
216
                                lputc(curwp->w_dotp, curwp->w_doto, ac);
 
217
                                lchange(WFHARD);
 
218
                        }
 
219
                        if (forwchar(FALSE, 1) == FALSE)
 
220
                                return (FALSE);
 
221
                }
 
222
        }
 
223
        return (TRUE);
 
224
}
 
225
 
 
226
/*
 
227
 * Move the cursor forward by the specified number of words. As you move
 
228
 * convert characters to lower case. Error if you try and move over the end of
 
229
 * the buffer. Bound to "M-L".
 
230
 */
 
231
int
 
232
lowerword(int f, int n)
 
233
{
 
234
        register int    c;
 
235
        CELL            ac;
 
236
 
 
237
        ac.a = 0;
 
238
        if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
 
239
                return(rdonly());       /* we are in read only mode     */
 
240
        if (n < 0)
 
241
                return (FALSE);
 
242
        while (n--) {
 
243
                while (inword() == FALSE) {
 
244
                        if (forwchar(FALSE, 1) == FALSE)
 
245
                                return (FALSE);
 
246
                }
 
247
                while (inword() != FALSE) {
 
248
                        c = lgetc(curwp->w_dotp, curwp->w_doto).c;
 
249
                        if (c>='A' && c<='Z') {
 
250
                                ac.c (c += 'a'-'A');
 
251
                                lputc(curwp->w_dotp, curwp->w_doto, ac);
 
252
                                lchange(WFHARD);
 
253
                        }
 
254
                        if (forwchar(FALSE, 1) == FALSE)
 
255
                                return (FALSE);
 
256
                }
 
257
        }
 
258
        return (TRUE);
 
259
}
 
260
 
 
261
/*
 
262
 * Move the cursor forward by the specified number of words. As you move
 
263
 * convert the first character of the word to upper case, and subsequent
 
264
 * characters to lower case. Error if you try and move past the end of the
 
265
 * buffer. Bound to "M-C".
 
266
 */
 
267
int
 
268
capword(int f, int n)
 
269
{
 
270
        register int    c;
 
271
        CELL            ac;
 
272
 
 
273
        ac.a = 0;
 
274
        if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
 
275
                return(rdonly());       /* we are in read only mode     */
 
276
        if (n < 0)
 
277
                return (FALSE);
 
278
        while (n--) {
 
279
                while (inword() == FALSE) {
 
280
                        if (forwchar(FALSE, 1) == FALSE)
 
281
                                return (FALSE);
 
282
                }
 
283
                if (inword() != FALSE) {
 
284
                        c = lgetc(curwp->w_dotp, curwp->w_doto).c;
 
285
                        if (c>='a' && c<='z') {
 
286
                            ac.c = (c -= 'a'-'A');
 
287
                            lputc(curwp->w_dotp, curwp->w_doto, ac);
 
288
                            lchange(WFHARD);
 
289
                        }
 
290
                        if (forwchar(FALSE, 1) == FALSE)
 
291
                                return (FALSE);
 
292
                        while (inword() != FALSE) {
 
293
                                c = lgetc(curwp->w_dotp, curwp->w_doto).c;
 
294
                                if (c>='A' && c<='Z') {
 
295
                                    ac.c = (c += 'a'-'A');
 
296
                                    lputc(curwp->w_dotp, curwp->w_doto, ac);
 
297
                                    lchange(WFHARD);
 
298
                                }
 
299
                                if (forwchar(FALSE, 1) == FALSE)
 
300
                                        return (FALSE);
 
301
                        }
 
302
                }
 
303
        }
 
304
        return (TRUE);
 
305
}
 
306
 
 
307
/*
 
308
 * Kill forward by "n" words. Remember the location of dot. Move forward by
 
309
 * the right number of words. Put dot back where it was and issue the kill
 
310
 * command for the right number of characters. Bound to "M-D".
 
311
 */
 
312
int
 
313
delfword(int f, int n)
 
314
{
 
315
        register long   size;
 
316
        register LINE   *dotp;
 
317
        register int    doto;
 
318
 
 
319
        if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
 
320
                return(rdonly());       /* we are in read only mode     */
 
321
        if (n < 0)
 
322
                return (FALSE);
 
323
        dotp = curwp->w_dotp;
 
324
        doto = curwp->w_doto;
 
325
        size = 0L;
 
326
        while (n--) {
 
327
#if     NFWORD
 
328
                while (inword() != FALSE) {
 
329
                        if (forwchar(FALSE,1) == FALSE)
 
330
                                return(FALSE);
 
331
                        ++size;
 
332
                }
 
333
#endif
 
334
                while (inword() == FALSE) {
 
335
                        if (forwchar(FALSE, 1) == FALSE)
 
336
                                return (FALSE);
 
337
                        ++size;
 
338
                }
 
339
#if     NFWORD == 0
 
340
                while (inword() != FALSE) {
 
341
                        if (forwchar(FALSE, 1) == FALSE)
 
342
                                return (FALSE);
 
343
                        ++size;
 
344
                }
 
345
#endif
 
346
        }
 
347
        curwp->w_dotp = dotp;
 
348
        curwp->w_doto = doto;
 
349
        return (ldelete(size, kinsert));
 
350
}
 
351
 
 
352
/*
 
353
 * Kill backwards by "n" words. Move backwards by the desired number of words,
 
354
 * counting the characters. When dot is finally moved to its resting place,
 
355
 * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
 
356
 */
 
357
int
 
358
delbword(int f, int n)
 
359
{
 
360
        register long   size;
 
361
 
 
362
        if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
 
363
                return(rdonly());       /* we are in read only mode     */
 
364
        if (n < 0)
 
365
                return (FALSE);
 
366
        if (backchar(FALSE, 1) == FALSE)
 
367
                return (FALSE);
 
368
        size = 0L;
 
369
        while (n--) {
 
370
                while (inword() == FALSE) {
 
371
                        if (backchar(FALSE, 1) == FALSE)
 
372
                                return (FALSE);
 
373
                        ++size;
 
374
                }
 
375
                while (inword() != FALSE) {
 
376
                        if (backchar(FALSE, 1) == FALSE)
 
377
                                return (FALSE);
 
378
                        ++size;
 
379
                }
 
380
        }
 
381
        if (forwchar(FALSE, 1) == FALSE)
 
382
                return (FALSE);
 
383
        return (ldelete(size, kinsert));
 
384
}
 
385
#endif  /* MAYBELATER */
 
386
 
 
387
/*
 
388
 * Return TRUE if the character at dot is a character that is considered to be
 
389
 * part of a word.
 
390
 */
 
391
int
 
392
inword(void)
 
393
{
 
394
     if(curwp->w_doto < llength(curwp->w_dotp))
 
395
     {
 
396
         if(ucs4_isalnum(lgetc(curwp->w_dotp, curwp->w_doto).c))
 
397
         {
 
398
             return(TRUE);
 
399
         }
 
400
         else if(ucs4_ispunct(lgetc(curwp->w_dotp, curwp->w_doto).c))
 
401
         {
 
402
             if((curwp->w_doto > 1) &&
 
403
                 ucs4_isalnum(lgetc(curwp->w_dotp, curwp->w_doto - 1).c) &&
 
404
                 (curwp->w_doto + 1 < llength(curwp->w_dotp)) &&
 
405
                 ucs4_isalnum(lgetc(curwp->w_dotp, curwp->w_doto + 1).c))
 
406
             {
 
407
                 return(TRUE);
 
408
             }
 
409
         }
 
410
     }
 
411
 
 
412
     return(FALSE);
 
413
}
 
414
 
 
415
 
 
416
/*
 
417
 * Return number of quotes if whatever starts the line matches the quote string
 
418
 */
 
419
int
 
420
quote_match(UCS *q, LINE *l, UCS *buf, int buflen)
 
421
{
 
422
    register int i, n, j, qb;
 
423
 
 
424
    *buf = '\0';
 
425
    if(*q == '\0')
 
426
      return(1);
 
427
 
 
428
    qb = (ucs4_strlen(q) > 1 && q[ucs4_strlen(q)-1] == ' ') ? 1 : 0;
 
429
    for(n = 0, j = 0; ;){
 
430
        for(i = 0; j <= llength(l) && qb ? q[i+1] : q[i]; i++, j++)
 
431
          if(q[i] != lgetc(l, j).c)
 
432
            return(n);
 
433
 
 
434
        n++;
 
435
        if((!qb && q[i] == '\0') || (qb && q[i+1] == '\0')){
 
436
            if(ucs4_strlen(buf) + ucs4_strlen(q) + 1 < buflen){
 
437
                ucs4_strncat(buf, q, buflen-ucs4_strlen(q));
 
438
                buf[buflen-1] = '\0';
 
439
                if(qb && (j > llength(l) || lgetc(l, j).c != ' '))
 
440
                  buf[ucs4_strlen(buf)-1] = '\0';
 
441
            }
 
442
        }
 
443
        if(j > llength(l))
 
444
          return(n);
 
445
        else if(qb && lgetc(l, j).c == ' ')
 
446
          j++;
 
447
    }
 
448
    return(n);  /* never reached */
 
449
}
 
450
 
 
451
 
 
452
/* Justify the entire buffer instead of just a paragraph */
 
453
int
 
454
fillbuf(int f, int n)
 
455
{
 
456
    int i, lastflagsave;
 
457
    LINE *eobline;
 
458
    REGION region;
 
459
 
 
460
    if(curbp->b_mode&MDVIEW){           /* don't allow this command if  */
 
461
        return(rdonly());               /* we are in read only mode     */
 
462
    }
 
463
    else if (fillcol == 0) {            /* no fill column set */
 
464
        mlwrite_utf8("No fill column set", NULL);
 
465
        return(FALSE);
 
466
    }
 
467
 
 
468
    if((lastflag & CFFILL) && (lastflag & CFFLBF)){
 
469
        /* no use doing a full justify twice */
 
470
        thisflag |= (CFFLBF | CFFILL);
 
471
        return(TRUE);
 
472
    }
 
473
 
 
474
    /* record the pointer of the last line */
 
475
    if(gotoeob(FALSE, 1) == FALSE)
 
476
      return(FALSE);
 
477
 
 
478
    eobline = curwp->w_dotp;            /* last line of buffer */
 
479
    if(!llength(eobline))
 
480
      eobline = lback(eobline);
 
481
 
 
482
    /* and back to the beginning of the buffer */
 
483
    gotobob(FALSE, 1);
 
484
 
 
485
    thisflag |= CFFLBF; /* CFFILL also gets set in fillpara */
 
486
 
 
487
    if(!Pmaster)
 
488
      sgarbk = TRUE;
 
489
    
 
490
    curwp->w_flag |= WFMODE;
 
491
 
 
492
    /*
 
493
     * clear the kill buffer, that's where we'll store undo
 
494
     * information, we can't do the fill buffer because
 
495
     * fillpara relies on its contents
 
496
     */
 
497
    kdelete();
 
498
    curwp->w_doto = 0;
 
499
    getregion(&region, eobline, llength(eobline));
 
500
 
 
501
    /* Put full message in the kill buffer for undo */
 
502
    if(!ldelete(region.r_size, kinsert))
 
503
      return(FALSE);
 
504
 
 
505
    /* before yank'ing, clear lastflag so we don't just unjustify */
 
506
    lastflag &= ~(CFFLBF | CFFILL);
 
507
 
 
508
    /* Now in kill buffer, bring back text to use in fillpara */
 
509
    yank(FALSE, 1);
 
510
 
 
511
    gotobob(FALSE, 1);
 
512
 
 
513
    /* call fillpara until we're at the end of the buffer */
 
514
    while(curwp->w_dotp != curbp->b_linep)
 
515
      if(!(fillpara(FALSE, 1)))
 
516
        return(FALSE);
 
517
    
 
518
    return(TRUE);
 
519
}
 
520
 
 
521
 
 
522
/*
 
523
 * Fill the current paragraph according to the current fill column
 
524
 */
 
525
int
 
526
fillpara(int f, int n)
 
527
{
 
528
    int     i, j, c, qlen, word[NSTRING], same_word,
 
529
            spaces, word_len, word_ind, line_len, qn, ww;
 
530
    UCS     line_last;
 
531
    UCS    *qstr, qstr2[NSTRING];
 
532
    LINE   *eopline;
 
533
    REGION  region;
 
534
 
 
535
    if(curbp->b_mode&MDVIEW){           /* don't allow this command if  */
 
536
        return(rdonly());               /* we are in read only mode     */
 
537
    }
 
538
    else if (fillcol == 0) {            /* no fill column set */
 
539
        mlwrite_utf8("No fill column set", NULL);
 
540
        return(FALSE);
 
541
    }
 
542
    else if(curwp->w_dotp == curbp->b_linep) /* don't wrap! */
 
543
      return(FALSE);
 
544
 
 
545
    /* record the pointer to the line just past the EOP */
 
546
    if(gotoeop(FALSE, 1) == FALSE)
 
547
      return(FALSE);
 
548
 
 
549
    eopline = curwp->w_dotp;            /* first line of para */
 
550
 
 
551
    /* and back to the beginning of the paragraph */
 
552
    gotobop(FALSE, 1);
 
553
 
 
554
    /* determine if we're justifying quoted text or not */
 
555
    qstr = (glo_quote_str
 
556
            && quote_match(glo_quote_str, 
 
557
                           curwp->w_dotp, qstr2, NSTRING)
 
558
            && *qstr2) ? qstr2 : NULL;
 
559
    qlen = qstr ? ucs4_strlen(qstr) : 0;
 
560
 
 
561
    /* let yank() know that it may be restoring a paragraph */
 
562
    thisflag |= CFFILL;
 
563
 
 
564
    if(!Pmaster)
 
565
      sgarbk = TRUE;
 
566
    
 
567
    curwp->w_flag |= WFMODE;
 
568
 
 
569
    /* cut the paragraph into our fill buffer */
 
570
    fdelete();
 
571
    curwp->w_doto = 0;
 
572
    getregion(&region, eopline, llength(eopline));
 
573
    if(!ldelete(region.r_size, finsert))
 
574
      return(FALSE);
 
575
 
 
576
    /* Now insert it back wrapped */
 
577
    spaces = word_len = word_ind = line_len = same_word = 0;
 
578
 
 
579
    /* Beginning with leading quoting... */
 
580
    if(qstr){
 
581
        i = 0;
 
582
        while(qstr[i]){
 
583
          ww = wcellwidth(qstr[i]);
 
584
          line_len += (ww >= 0 ? ww : 1);
 
585
          linsert(1, qstr[i++]);
 
586
        }
 
587
 
 
588
        line_last = ' ';                        /* no word-flush space! */
 
589
    }
 
590
 
 
591
    /* ...and leading white space */
 
592
    for(i = qlen; (c = fremove(i)) == ' ' || c == TAB; i++){
 
593
        linsert(1, line_last = c);
 
594
        line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1);
 
595
    }
 
596
 
 
597
    /* then digest the rest... */
 
598
    while((c = fremove(i++)) > 0){
 
599
        switch(c){
 
600
          case '\n' :
 
601
            i += qlen;                          /* skip next quote string */
 
602
            if(!spaces)
 
603
              spaces++;
 
604
            same_word = 0;
 
605
            break;
 
606
 
 
607
          case TAB :
 
608
          case ' ' :
 
609
            spaces++;
 
610
            same_word = 0;
 
611
            break;
 
612
 
 
613
          default :
 
614
            if(spaces){                         /* flush word? */
 
615
                if((line_len - qlen > 0)
 
616
                   && line_len + word_len + 1 > fillcol
 
617
                   && ((ucs4_isspace(line_last))
 
618
                       || (linsert(1, ' ')))
 
619
                   && (line_len = fpnewline(qstr)))
 
620
                  line_last = ' ';      /* no word-flush space! */
 
621
 
 
622
                if(word_len){                   /* word to write? */
 
623
                    if(line_len && !ucs4_isspace(line_last)){
 
624
                        linsert(1, ' ');        /* need padding? */
 
625
                        line_len++;
 
626
                    }
 
627
 
 
628
                    line_len += word_len;
 
629
                    for(j = 0; j < word_ind; j++)
 
630
                      linsert(1, line_last = word[j]);
 
631
 
 
632
                    if(spaces > 1 && strchr(".?!:;\")", line_last)){
 
633
                        linsert(2, line_last = ' ');
 
634
                        line_len += 2;
 
635
                    }
 
636
 
 
637
                    word_len = word_ind = 0;
 
638
                }
 
639
 
 
640
                spaces = 0;
 
641
            }
 
642
 
 
643
            if(word_ind + 1 >= NSTRING){
 
644
                /* Magic!  Fake that we output a wrapped word */
 
645
                if((line_len - qlen > 0) && !same_word++){
 
646
                    if(!ucs4_isspace(line_last))
 
647
                      linsert(1, ' ');
 
648
                    line_len = fpnewline(qstr);
 
649
                }
 
650
 
 
651
                line_len += word_len;
 
652
                for(j = 0; j < word_ind; j++)
 
653
                  linsert(1, word[j]);
 
654
 
 
655
                word_len = word_ind = 0;
 
656
                line_last = ' ';
 
657
            }
 
658
 
 
659
            word[word_ind++] = c;
 
660
            ww = wcellwidth(c);
 
661
            word_len += (ww >= 0 ? ww : 1);
 
662
 
 
663
            break;
 
664
        }
 
665
    }
 
666
 
 
667
    if(word_len){
 
668
        if((line_len - qlen > 0) && (line_len + word_len + 1 > fillcol)){
 
669
            if(!ucs4_isspace(line_last))
 
670
              linsert(1, ' ');
 
671
            (void) fpnewline(qstr);
 
672
        }
 
673
        else if(line_len && !ucs4_isspace(line_last))
 
674
          linsert(1, ' ');
 
675
 
 
676
        for(j = 0; j < word_ind; j++)
 
677
          linsert(1, word[j]);
 
678
    }
 
679
 
 
680
    /* Leave cursor on first char of first line after paragraph */
 
681
    curwp->w_dotp = lforw(curwp->w_dotp);
 
682
    curwp->w_doto = 0;
 
683
 
 
684
    return(TRUE);
 
685
}
 
686
 
 
687
 
 
688
/*
 
689
 * fpnewline - output a fill paragraph newline mindful of quote string
 
690
 */
 
691
int
 
692
fpnewline(UCS *quote)
 
693
{
 
694
    int len;
 
695
 
 
696
    lnewline();
 
697
    for(len = 0; quote && *quote; quote++){
 
698
        int ww;
 
699
 
 
700
        ww = wcellwidth(*quote);
 
701
        len += (ww >= 0 ? ww : 1);
 
702
        linsert(1, *quote);
 
703
    }
 
704
 
 
705
    return(len);
 
706
}