~ubuntu-branches/ubuntu/lucid/edbrowse/lucid

« back to all changes in this revision

Viewing changes to buffers.c

  • Committer: Bazaar Package Importer
  • Author(s): Kapil Hari Paranjape
  • Date: 2007-12-05 10:39:04 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20071205103904-zr3kzzu0ym6stg16
Tags: 3.3.1-1
* New upstream version (3.3.1).
  - Messages have been internationalised.
  - Supports LANG environment variable.
  - Includes man page.
* Incorporate upstream man page:
  - debian/rules: Add rule to install upstream man page.
  - debian/edbrowse.1: Not required. Removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
/* Static variables for this file. */
14
14
 
15
15
/* The valid edbrowse commands. */
16
 
static const char valid_cmd[] = "aAbBcdefghHijJklmMnpqrstuvwz=^<";
 
16
static const char valid_cmd[] = "aAbBcdefghHijJklmMnpqrstuvwXz=^<";
17
17
/* Commands that can be done in browse mode. */
18
 
static const char browse_cmd[] = "AbBdefghHijJklmMnpqsuvwz=^<";
 
18
static const char browse_cmd[] = "AbBdefghHijJklmMnpqsuvwXz=^<";
19
19
/* Commands for sql mode. */
20
 
static const char sql_cmd[] = "AadefghHiklmnpqrsvwz=^<";
 
20
static const char sql_cmd[] = "AadefghHiklmnpqrsvwXz=^<";
21
21
/* Commands for directory mode. */
22
 
static const char dir_cmd[] = "AdefghHklmnpqsvwz=^<";
 
22
static const char dir_cmd[] = "AdefghHklmnpqsvwXz=^<";
23
23
/* Commands that work at line number 0, in an empty file. */
24
24
static const char zero_cmd[] = "aAbefhHMqruw=^<";
25
25
/* Commands that expect a space afterward. */
26
26
static const char spaceplus_cmd[] = "befrw";
27
27
/* Commands that should have no text after them. */
28
 
static const char nofollow_cmd[] = "aAcdhHjlmnptu=";
 
28
static const char nofollow_cmd[] = "aAcdhHjlmnptuX=";
29
29
/* Commands that can be done after a g// global directive. */
30
 
static const char global_cmd[] = "dijJlmnpst";
 
30
static const char global_cmd[] = "dijJlmnpstX";
31
31
 
32
32
static struct ebWindow preWindow, undoWindow;
33
33
static int startRange, endRange;        /* as in 57,89p */
139
139
    pst p;                      /* the resulting copy of the string */
140
140
 
141
141
    if(!lw)
142
 
        errorPrint("@invalid session %d in fetchLineContext()", cx);
 
142
        i_printfExit(MSG_InvalidSession, cx);
143
143
    map = lw->map;
144
144
    dol = lw->dol;
145
145
    if(n <= 0 || n > dol)
146
 
        errorPrint("@invalid line number %d in fetchLineContext()", n);
 
146
        i_printfExit(MSG_InvalidLineNb, n);
147
147
 
148
148
    t = map + LNWIDTH * n;
149
149
    idx = atoi(t);
150
150
    if(!textLines[idx])
151
 
        errorPrint("@line %d->%d became null", n, idx);
 
151
        i_printfExit(MSG_LineNull, n, idx);
152
152
    if(show < 0)
153
153
        return textLines[idx];
154
154
    p = clonePstring(textLines[idx]);
170
170
    int i, ln, size;
171
171
    struct ebWindow *w;
172
172
    if(cx <= 0 || cx >= MAXSESSION || (w = sessionList[cx].lw) == 0) {
173
 
        setError("session %d is not active", cx);
 
173
        setError(MSG_SessionInactive, cx);
174
174
        return -1;
175
175
    }
176
176
    size = 0;
262
262
    printf("%s", dirSuffix(n));
263
263
    if(endMarks == 2 || endMarks && cmd == 'l')
264
264
        printf("$");
265
 
    printf("\n");
 
265
    nl();
266
266
 
267
267
    free(line);
268
268
}                               /* displayLine */
273
273
    if(cw->dot)
274
274
        displayLine(cw->dot);
275
275
    else
276
 
        printf("empty\n");
 
276
        i_puts(MSG_Empty);
277
277
}                               /* printDot */
278
278
 
279
279
/* Get a line from standard in.  Need not be a terminal.
305
305
    if(!fgets((char *)line, sizeof (line), stdin)) {
306
306
        if(intFlag)
307
307
            goto top;
308
 
        puts("EOF");
 
308
        i_puts(MSG_EOF);
309
309
        ebClose(1);
310
310
    }
311
311
    inInput = false;
403
403
    debugPrint(6, "freeWindowLines = %d", cnt);
404
404
}                               /* freeWindowLines */
405
405
 
 
406
/* quick sort compare */
 
407
static int
 
408
qscmp(const void *s, const void *t)
 
409
{
 
410
    return memcmp(s, t, 6);
 
411
}                               /* qscmp */
 
412
 
406
413
/* Free any lines not used by the snapshot of the current session. */
407
414
void
408
415
freeUndoLines(const char *cmap)
409
416
{
410
417
    char *map = undoWindow.map;
411
 
    char *s;
412
 
    const char *t;
413
 
    int ln;
414
 
    int cnt = 0;
 
418
    char *cmap2;
 
419
    char *s, *t;
 
420
    int diff, ln, cnt = 0;
415
421
 
416
422
    if(!map) {
417
423
        debugPrint(6, "freeUndoLines = null");
425
431
        return;
426
432
    }
427
433
 
428
 
/* This is pretty efficient most of the time,
429
 
 * real inefficient sometimes. */
 
434
/* sort both arrays, run comm, and find out which lines are not needed any more,
 
435
then free them.
 
436
 * Use quick sort; some files are 100,000 lines long.
 
437
 * I have to copy the second array, so I can sort it.
 
438
 * The first I can sort in place, cause it's going to get thrown away. */
 
439
 
 
440
    cmap2 = cloneString(cmap);
 
441
    qsort(map + LNWIDTH, (strlen(map) / LNWIDTH) - 1, LNWIDTH, qscmp);
 
442
    qsort(cmap2 + LNWIDTH, (strlen(cmap2) / LNWIDTH) - 1, LNWIDTH, qscmp);
 
443
 
430
444
    s = map + LNWIDTH;
431
 
    t = cmap + LNWIDTH;
432
 
    for(; *s && *t; s += LNWIDTH, t += LNWIDTH)
433
 
        if(!memcmp(s, t, 6))
434
 
            *s = '*';
435
 
        else
436
 
            break;
437
 
 
438
 
    if(*s) {                    /* more to do */
439
 
        s = map + strlen(map);
440
 
        t = cmap + strlen(cmap);
441
 
        s -= LNWIDTH, t -= LNWIDTH;
442
 
        while(s > map && t > cmap) {
443
 
            if(!memcmp(s, t, 6))
444
 
                *s = '*';
445
 
            s -= LNWIDTH, t -= LNWIDTH;
446
 
        }
447
 
 
448
 
/* Ok, who's left? */
449
 
        for(s = map + LNWIDTH; *s; s += LNWIDTH) {
450
 
            if(*s == '*')
451
 
                continue;       /* in use */
452
 
            for(t = cmap + LNWIDTH; *t; t += LNWIDTH)
453
 
                if(!memcmp(s, t, 6))
454
 
                    break;
455
 
            if(*t)
456
 
                continue;       /* in use */
457
 
            ln = atoi(s);
458
 
            if(textLines[ln]) {
459
 
                free(textLines[ln]);
460
 
                textLines[ln] = 0;
461
 
                ++cnt;
462
 
            }
463
 
        }
464
 
    }
465
 
 
 
445
    t = cmap2 + LNWIDTH;
 
446
    while(*s && *t) {
 
447
        diff = memcmp(s, t, 6);
 
448
        if(!diff) {
 
449
            s += LNWIDTH;
 
450
            t += LNWIDTH;
 
451
            continue;
 
452
        }
 
453
        if(diff > 0) {
 
454
            t += LNWIDTH;
 
455
            continue;
 
456
        }
 
457
/* This line isn't being used any more. */
 
458
        ln = atoi(s);
 
459
        if(textLines[ln]) {
 
460
            free(textLines[ln]);
 
461
            textLines[ln] = 0;
 
462
            ++cnt;
 
463
        }
 
464
        s += LNWIDTH;
 
465
    }
 
466
 
 
467
    while(*s) {
 
468
        ln = atoi(s);
 
469
        if(textLines[ln]) {
 
470
            free(textLines[ln]);
 
471
            textLines[ln] = 0;
 
472
            ++cnt;
 
473
        }
 
474
        s += LNWIDTH;
 
475
    }
 
476
 
 
477
    free(cmap2);
466
478
    free(map);
467
479
    undoWindow.map = 0;
468
480
    debugPrint(6, "freeUndoLines = %d", cnt);
496
508
cxCompare(int cx)
497
509
{
498
510
    if(cx == 0) {
499
 
        setError("session 0 is invalid");
 
511
        setError(MSG_Session0);
500
512
        return false;
501
513
    }
502
514
    if(cx >= MAXSESSION) {
503
 
        setError("session %d is out of bounds, limit %d", cx, MAXSESSION - 1);
 
515
        setError(MSG_SessionHigh, cx, MAXSESSION - 1);
504
516
        return false;
505
517
    }
506
518
    if(cx != context)
507
519
        return true;            /* ok */
508
 
    setError("you are already in session %d", cx);
 
520
    setError(MSG_SessionCurrent, cx);
509
521
    return false;
510
522
}                               /*cxCompare */
511
523
 
514
526
cxActive(int cx)
515
527
{
516
528
    if(cx <= 0 || cx >= MAXSESSION)
517
 
        errorPrint("@session %d out of range in cxActive", cx);
 
529
        i_printfExit(MSG_SessionOutRange, cx);
518
530
    if(sessionList[cx].lw)
519
531
        return true;
520
 
    setError("session %d is not active", cx);
 
532
    setError(MSG_SessionInactive, cx);
521
533
    return false;
522
534
}                               /* cxActive */
523
535
 
526
538
{
527
539
    struct ebWindow *lw = createWindow();
528
540
    if(sessionList[cx].lw)
529
 
        errorPrint("@double init on session %d", cx);
 
541
        i_printfExit(MSG_DoubleInit, cx);
530
542
    sessionList[cx].fw = sessionList[cx].lw = lw;
531
543
}                               /* cxInit */
532
544
 
535
547
{
536
548
    struct ebWindow *w = sessionList[cx].lw;
537
549
    if(!w)
538
 
        errorPrint("@quitting a nonactive session %d", cx);
 
550
        i_printfExit(MSG_QuitNoActive, cx);
539
551
 
540
552
/* We might be trashing data, make sure that's ok. */
541
553
    if(w->changeMode &&
542
554
       !(w->dirMode | w->sqlMode) && lastq != cx && w->fileName &&
543
555
       !isURL(w->fileName)) {
544
556
        lastqq = cx;
545
 
        setError("expecting `w'");
 
557
        setError(MSG_ExpectW);
546
558
        if(cx != context)
547
 
            setError("expecting `w' on session %d", cx);
 
559
            setError(MSG_ExpectWX, cx);
548
560
        return false;
549
561
    }
550
562
 
601
613
    context = cx;
602
614
    if(interactive && debugLevel) {
603
615
        if(created)
604
 
            printf("new session\n");
 
616
            i_puts(MSG_SessionNew);
605
617
        else if(cw->fileName)
606
618
            puts(cw->fileName);
607
619
        else
608
 
            puts("no file");
 
620
            i_puts(MSG_NoFile);
609
621
    }
610
622
 
611
623
/* The next line is required when this function is called from main(),
633
645
{
634
646
    int need = textLinesCount + n;
635
647
    if(need > LNMAX) {
636
 
        setError
637
 
           ("Your limit of 1 million lines has been reached.\nSave your files, then exit and restart this program.");
 
648
        setError(MSG_LineLimit);
638
649
        return false;
639
650
    }
640
651
    if(need > textLinesMax) {
689
700
    int i, j;
690
701
    int nlines = end - start;
691
702
    if(nlines == 0)
692
 
        errorPrint("@empty new piece in addToMap()");
 
703
        i_printfExit(MSG_EmptyPiece);
693
704
    for(i = 0; i < 26; ++i) {
694
705
        int ln = cw->labels[i];
695
706
        if(ln <= destl)
737
748
        if(destl == cw->dol) {
738
749
            cw->nlMode = true;
739
750
            if(cmd != 'b' && !cw->binMode && !ismc)
740
 
                printf("no trailing newline\n");
 
751
                i_puts(MSG_NoTrailing);
741
752
        }
742
753
    }                           /* missing newline */
743
754
    start = end = textLinesCount;
838
849
{
839
850
    static char path[ABSPATH];
840
851
    if(strlen(cw->baseDirName) + strlen(f) > ABSPATH - 2) {
841
 
        setError("absolute path name too long, limit %d chars", ABSPATH);
 
852
        setError(MSG_PathNameLong, ABSPATH);
842
853
        return 0;
843
854
    }
844
855
    sprintf(path, "%s/%s", cw->baseDirName, f);
850
861
{
851
862
    int ln, cnt;
852
863
    if(!dirWrite) {
853
 
        setError
854
 
           ("directories are readonly, type dw to enable directory writes");
 
864
        setError(MSG_DirNoWrite);
855
865
        return false;
856
866
    }
857
867
    if(dirWrite == 1 && !recycleBin) {
858
 
        setError
859
 
           ("could not create .recycle under your home directory, to hold the deleted files");
 
868
        setError(MSG_NoRecycle);
860
869
        return false;
861
870
    }
862
871
    ln = startRange;
866
875
        file = (char *)fetchLine(ln, 0);
867
876
        t = strchr(file, '\n');
868
877
        if(!t)
869
 
            errorPrint("@no newline on directory entry %s", file);
 
878
            i_printfExit(MSG_NoNlOnDir, file);
870
879
        *t = 0;
871
880
        path = makeAbsPath(file);
872
881
        if(!path) {
876
885
        ftype = dirSuffix(ln);
877
886
        if(dirWrite == 2 || *ftype == '@') {
878
887
            if(unlink(path)) {
879
 
                setError("could not remove file %s", file);
 
888
                setError(MSG_NoRemove, file);
880
889
                free(file);
881
890
                return false;
882
891
            }
884
893
            char bin[ABSPATH];
885
894
            sprintf(bin, "%s/%s", recycleBin, file);
886
895
            if(rename(path, bin)) {
887
 
                setError
888
 
                   ("Could not move %s to the recycle bin, set dx mode to actually remove the file",
889
 
                   file);
 
896
                setError(MSG_NoMoveToTrash, file);
890
897
                free(file);
891
898
                return false;
892
899
            }
914
921
    int lowcut, highcut, diff, i;
915
922
 
916
923
    if(dl > sr && dl < er) {
917
 
        setError("destination lies inside the block to be moved or copied");
 
924
        setError(MSG_DestInBlock);
918
925
        return false;
919
926
    }
920
927
    if(cmd == 'm' && (dl == er || dl == sr)) {
921
928
        if(globSub)
922
 
            setError("no change");
 
929
            setError(MSG_NoChange);
923
930
        return false;
924
931
    }
925
932
 
986
993
    int j, size;
987
994
    pst newline, t;
988
995
    if(startRange == endRange) {
989
 
        setError("cannot join one line");
 
996
        setError(MSG_Join1);
990
997
        return false;
991
998
    }
992
999
    if(!linesComing(1))
1049
1056
    if(isSQL(filename)) {
1050
1057
        const char *t1, *t2;
1051
1058
        if(!cw->sqlMode) {
1052
 
            setError("cannot read from the database into another file");
 
1059
            setError(MSG_DBOtherFile);
1053
1060
            return false;
1054
1061
        }
1055
1062
        t1 = strchr(cw->fileName, ']');
1056
1063
        t2 = strchr(filename, ']');
1057
1064
        if(t1 - cw->fileName != t2 - filename ||
1058
1065
           memcmp(cw->fileName, filename, t2 - filename)) {
1059
 
            setError("cannot read different tables into the same session");
 
1066
            setError(MSG_DBOtherTable);
1060
1067
            return false;
1061
1068
        }
1062
1069
        rc = sqlReadRows(filename, &rbuf);
1079
1086
    if(memEqualCI(filename, "file://", 7))
1080
1087
        filename += 7;
1081
1088
    if(!*filename) {
1082
 
        setError("missing file name");
 
1089
        setError(MSG_MissingFileName);
1083
1090
        return false;
1084
1091
    }
1085
1092
 
1088
1095
        if(!domain)
1089
1096
            return false;       /* some kind of error */
1090
1097
        if(!*domain) {
1091
 
            setError("empty domain in url");
 
1098
            setError(MSG_DomainEmpty);
1092
1099
            return false;
1093
1100
        }
1094
1101
 
1130
1137
                return false;
1131
1138
            if(!cw->dol) {
1132
1139
                cw->dirMode = true;
1133
 
                printf("directory mode\n");
 
1140
                i_puts(MSG_DirMode);
1134
1141
            }
1135
1142
            if(start == end) {  /* empty directory */
1136
1143
                cw->dot = endRange;
1219
1226
        fileSize = j;
1220
1227
#endif
1221
1228
    } else if(binaryDetect & !cw->binMode) {
1222
 
        printf("binary data\n");
 
1229
        i_puts(MSG_BinaryData);
1223
1230
        cw->binMode = true;
1224
1231
    }
1225
1232
 
1239
1246
    if(memEqualCI(name, "file://", 7))
1240
1247
        name += 7;
1241
1248
    if(!*name) {
1242
 
        setError("missing file name");
 
1249
        setError(MSG_MissingFileName);
1243
1250
        return false;
1244
1251
    }
1245
1252
    if(isURL(name)) {
1246
 
        setError("cannot write to a url");
 
1253
        setError(MSG_NoWriteURL);
1247
1254
        return false;
1248
1255
    }
1249
1256
    if(isSQL(name)) {
1250
 
        setError("cannot write to a database table");
 
1257
        setError(MSG_WriteDB);
1251
1258
        return false;
1252
1259
    }
1253
1260
    if(!cw->dol) {
1254
 
        setError("cannot write an empty file");
 
1261
        setError(MSG_WriteEmpty);
1255
1262
        return false;
1256
1263
    }
1257
1264
/* mode should be TRUNC or APPEND */
1260
1267
        mode |= O_BINARY;
1261
1268
    fh = open(name, mode, 0666);
1262
1269
    if(fh < 0) {
1263
 
        setError("cannot create %s", name);
 
1270
        setError(MSG_NoCreate2, name);
1264
1271
        return false;
1265
1272
    }
1266
1273
    fileSize = 0;
1273
1280
                --len;
1274
1281
            if(write(fh, p, len) < len) {
1275
1282
              badwrite:
1276
 
                setError("cannot write to %s", name);
 
1283
                setError(MSG_NoWrite2, name);
1277
1284
                close(fh);
1278
1285
                return false;
1279
1286
            }
1346
1353
    }
1347
1354
    if(binaryDetect & !cw->binMode && lw->binMode) {
1348
1355
        cw->binMode = true;
1349
 
        printf("binary data\n");
 
1356
        i_puts(MSG_BinaryData);
1350
1357
    }
1351
1358
    return true;
1352
1359
}                               /* readContext */
1438
1445
    if(!linesize) {
1439
1446
/* interactive shell */
1440
1447
        if(!isInteractive) {
1441
 
            setError("session is not interactive");
 
1448
            setError(MSG_SessionBackground);
1442
1449
            return false;
1443
1450
        }
1444
1451
#ifdef DOSLIKE
1447
1454
        sprintf(subshell, "exec %s -i", sh);
1448
1455
        system(subshell);
1449
1456
#endif
1450
 
        printf("ok\n");
 
1457
        i_puts(MSG_OK);
1451
1458
        return true;
1452
1459
    }
1453
1460
 
1482
1489
                if(key == '+')
1483
1490
                    ++n;
1484
1491
                if(n > cw->dol || n == 0) {
1485
 
                    setError("line %c is out of range", key);
 
1492
                    setError(MSG_OutOfRange, key);
1486
1493
                    return false;
1487
1494
                }
1488
1495
              frombuf:
1494
1501
                    p = fetchLine(n, 1);
1495
1502
                    if(perl2c((char *)p)) {
1496
1503
                        free(p);
1497
 
                        setError("cannot embed nulls in a shell command");
 
1504
                        setError(MSG_ShellNull);
1498
1505
                        return false;
1499
1506
                    }
1500
1507
                    strcpy(s, (char *)p);
1507
1514
            if(islowerByte(key)) {
1508
1515
                n = cw->labels[key - 'a'];
1509
1516
                if(!n) {
1510
 
                    setError("label %c not set", key);
 
1517
                    setError(MSG_NoLabel, key);
1511
1518
                    return false;
1512
1519
                }
1513
1520
                goto frombuf;
1530
1537
 * even if the shell command failed.
1531
1538
 * Edbrowse succeeds if it is *able* to run the system command. */
1532
1539
    system(newline);
1533
 
    printf("ok\n");
 
1540
    i_puts(MSG_OK);
1534
1541
    free(newline);
1535
1542
    return true;
1536
1543
}                               /* shellEscape */
1568
1575
 
1569
1576
    *rexp = re;
1570
1577
    if(!strchr(valid_delim, delim)) {
1571
 
        setError("invalid delimiter");
 
1578
        setError(MSG_BadDelimit);
1572
1579
        return false;
1573
1580
    }
1574
1581
    start = line;
1578
1585
        if(isleft) {
1579
1586
            if(c == delim || c == 0) {
1580
1587
                if(!cw->lhs_yes) {
1581
 
                    setError("no remembered search string");
 
1588
                    setError(MSG_NoSearchString);
1582
1589
                    return false;
1583
1590
                }
1584
1591
                strcpy(re, cw->lhs);
1594
1601
            }
1595
1602
        } else if(c == '%' && (line[1] == delim || line[1] == 0)) {
1596
1603
            if(!cw->rhs_yes) {
1597
 
                setError("no remembered replacement string");
 
1604
                setError(MSG_NoReplaceString);
1598
1605
                return false;
1599
1606
            }
1600
1607
            strcpy(re, cw->rhs);
1605
1612
    /* ebmuck tricks */
1606
1613
    while(c = *line) {
1607
1614
        if(e >= re + MAXRE - 3) {
1608
 
            setError("regular expression too long");
 
1615
            setError(MSG_RexpLong);
1609
1616
            return false;
1610
1617
        }
1611
1618
        d = line[1];
1613
1620
        if(c == '\\') {
1614
1621
            line += 2;
1615
1622
            if(d == 0) {
1616
 
                setError("line ends in backslash");
 
1623
                setError(MSG_LineBackslash);
1617
1624
                return false;
1618
1625
            }
1619
1626
            ondeck = true;
1628
1635
                if(d == ')')
1629
1636
                    --paren;
1630
1637
                if(paren < 0) {
1631
 
                    setError("Unexpected closing )");
 
1638
                    setError(MSG_UnexpectedRight);
1632
1639
                    return false;
1633
1640
                }
1634
1641
                *e++ = d;
1661
1668
 
1662
1669
        if(c == '$' && !isleft && isdigitByte(d)) {
1663
1670
            if(d == '0' || isdigitByte(line[2])) {
1664
 
                setError("replacement string can only use $1 through $9");
 
1671
                setError(MSG_RexpDollar);
1665
1672
                return false;
1666
1673
            }
1667
1674
        }
1725
1732
            }
1726
1733
            if(!ondeck) {
1727
1734
                *e = 0;
1728
 
                setError("%s modifier has no preceding character", e - mod - 1);
 
1735
                setError(MSG_RexpModifier, e - mod - 1);
1729
1736
                return false;
1730
1737
            }
1731
1738
            ondeck = false;
1741
1748
 
1742
1749
    if(ebmuck) {
1743
1750
        if(cc) {
1744
 
            setError("no closing ]");
 
1751
            setError(MSG_NoBracket);
1745
1752
            return false;
1746
1753
        }
1747
1754
        if(paren) {
1748
 
            setError("no closing )");
 
1755
            setError(MSG_NoParen);
1749
1756
            return false;
1750
1757
        }
1751
1758
 
1789
1796
    } else if(first == '\'' && islowerByte(line[1])) {
1790
1797
        ln = cw->labels[line[1] - 'a'];
1791
1798
        if(!ln) {
1792
 
            setError("label %c not set", line[1]);
 
1799
            setError(MSG_NoLabel, line[1]);
1793
1800
            return false;
1794
1801
        }
1795
1802
        line += 2;
1800
1807
        char incr;              /* forward or back */
1801
1808
/* Don't look through an empty buffer. */
1802
1809
        if(cw->dol == 0) {
1803
 
            setError("empty buffer");
 
1810
            setError(MSG_EmptyBuffer);
1804
1811
            return false;
1805
1812
        }
1806
1813
        if(!regexpCheck(line, true, true, &re, &line))
1819
1826
            re_opt |= PCRE_CASELESS;
1820
1827
        re_cc = pcre_compile(re, re_opt, &re_error, &re_offset, 0);
1821
1828
        if(!re_cc) {
1822
 
            setError("error in regular expression, %s", re_error);
 
1829
            setError(MSG_RexpError, re_error);
1823
1830
            return false;
1824
1831
        }
1825
1832
/* We should probably study the pattern, if the file is large.
1840
1847
            free(subject);
1841
1848
            if(re_count < -1) {
1842
1849
                pcre_free(re_cc);
1843
 
                setError
1844
 
                   ("unexpected error while evaluating the regular expression at line %d",
1845
 
                   ln);
 
1850
                setError(MSG_RexpError2, ln);
1846
1851
                return (globSub = false);
1847
1852
            }
1848
1853
            if(re_count >= 0)
1849
1854
                break;
1850
1855
            if(ln == cw->dot) {
1851
1856
                pcre_free(re_cc);
1852
 
                setError("search string not found");
 
1857
                setError(MSG_NotFound);
1853
1858
                return false;
1854
1859
            }
1855
1860
        }                       /* loop over lines */
1868
1873
    }
1869
1874
 
1870
1875
    if(ln > cw->dol) {
1871
 
        setError("line number too large");
 
1876
        setError(MSG_LineHigh);
1872
1877
        return false;
1873
1878
    }
1874
1879
    if(ln < 0) {
1875
 
        setError("negative line number");
 
1880
        setError(MSG_LineLow);
1876
1881
        return false;
1877
1882
    }
1878
1883
 
1896
1901
    int i, origdot, yesdot, nodot;
1897
1902
 
1898
1903
    if(!delim) {
1899
 
        setError("no regular expression after %c", icmd);
 
1904
        setError(MSG_RexpMissing, icmd);
1900
1905
        return false;
1901
1906
    }
1902
1907
 
1903
1908
    if(!regexpCheck(line, true, true, &re, &line))
1904
1909
        return false;
1905
1910
    if(*line != delim) {
1906
 
        setError("missing delimiter");
 
1911
        setError(MSG_NoDelimit);
1907
1912
        return false;
1908
1913
    }
1909
1914
    ++line;
1921
1926
        re_opt |= PCRE_CASELESS;
1922
1927
    re_cc = pcre_compile(re, re_opt, &re_error, &re_offset, 0);
1923
1928
    if(!re_cc) {
1924
 
        setError("error in regular expression, %s", re_error);
 
1929
        setError(MSG_RexpError, re_error);
1925
1930
        return false;
1926
1931
    }
1927
1932
    for(i = startRange; i <= endRange; ++i) {
1932
1937
        free(subject);
1933
1938
        if(re_count < -1) {
1934
1939
            pcre_free(re_cc);
1935
 
            setError
1936
 
               ("unexpected error while evaluating the regular expression at line %d",
1937
 
               i);
 
1940
            setError(MSG_RexpError2, i);
1938
1941
            return false;
1939
1942
        }
1940
1943
        if(re_count < 0 && cmd == 'v' || re_count >= 0 && cmd == 'g') {
1945
1948
    pcre_free(re_cc);
1946
1949
 
1947
1950
    if(!gcnt) {
1948
 
        setError(cmd ==
1949
 
           'g' ? "no lines match the g pattern" :
1950
 
           "all lines match the v pattern");
 
1951
        setError((cmd == 'v') + MSG_NoMatchG);
1951
1952
        return false;
1952
1953
    }
1953
1954
 
1954
1955
/* apply the subcommand to every line with a star */
1955
1956
    globSub = true;
1956
 
    setError(0);
 
1957
    setError(-1);
1957
1958
    if(!*line)
1958
1959
        line = "p";
1959
1960
    origdot = cw->dot;
1997
1998
    } else {
1998
1999
        cw->dot = origdot;
1999
2000
        if(!errorMsg[0])
2000
 
            setError("none of the marked lines were successfully modified");
 
2001
            setError(MSG_NotModifiedG);
2001
2002
    }
2002
2003
    if(!errorMsg[0] && intFlag)
2003
 
        setError(opint);
 
2004
        setError(MSG_Interrupted);
2004
2005
    return (errorMsg[0] == 0);
2005
2006
}                               /* doGlobal */
2006
2007
 
2007
2008
static void
2008
 
fieldNumProblem(const char *desc, char c, int n, int nt, int nrt)
 
2009
fieldNumProblem(int desc, char c, int n, int nt, int nrt)
2009
2010
{
2010
2011
    if(!nrt) {
2011
 
        setError("no %s present", desc);
 
2012
        setError(MSG_NoInputFields + desc);
2012
2013
        return;
2013
2014
    }
2014
2015
    if(!n) {
2015
 
        setError("multiple %s present, please use %c1 through %c%d", desc, c, c,
2016
 
           nt);
 
2016
        setError(MSG_ManyInputFields + desc, c, c, nt);
2017
2017
        return;
2018
2018
    }
2019
2019
    if(nt > 1)
2020
 
        setError("%d is out of range, please use %c1 through %c%d", n, c, c,
2021
 
           nt);
 
2020
        setError(MSG_InputRange, n, c, c, nt);
2022
2021
    else
2023
 
        setError("%d is out of range, please use %c1, or simply %c", n, c, c);
 
2022
        setError(MSG_InputRange2, n, c, c);
2024
2023
}                               /* fieldNumProblem */
2025
2024
 
2026
2025
/* Perform a substitution on a given line.
2047
2046
/* find the next match */
2048
2047
        re_count = pcre_exec(re_cc, 0, line, len, offset, 0, re_vector, 33);
2049
2048
        if(re_count < -1) {
2050
 
            setError
2051
 
               ("unexpected error while evaluating the regular expression at line %d",
2052
 
               ln);
 
2049
            setError(MSG_RexpError2, ln);
2053
2050
            return -1;
2054
2051
        }
2055
2052
        if(re_count < 0)
2058
2055
        lastoffset = offset;
2059
2056
        offset = re_vector[1];  /* ready for next iteration */
2060
2057
        if(offset == lastoffset && (nth > 1 || global)) {
2061
 
            setError("cannot replace multiple instances of the empty string");
 
2058
            setError(MSG_ManyEmptyStrings);
2062
2059
            return -1;
2063
2060
        }
2064
2061
        if(!global &&instance != nth)
2082
2079
                goto longvar;
2083
2080
            memcpy(r, line + re_vector[0], span);
2084
2081
            r[span] = 0;
2085
 
            caseShift(r, rhs[0]);
 
2082
            i_caseShift((unsigned char *)r, rhs[0]);
2086
2083
            r += span;
2087
2084
            if(!global)
2088
2085
                break;
2188
2185
    return true;
2189
2186
 
2190
2187
  longvar:
2191
 
    setError("line exceeds %d bytes after substitution", REPLACELINELEN);
 
2188
    setError(MSG_SubLong, REPLACELINELEN);
2192
2189
    return -1;
2193
2190
}                               /* replaceText */
2194
2191
 
2228
2225
        if(isdigitByte(*line))
2229
2226
            whichField = strtol(line, (char **)&line, 10);
2230
2227
        if(!*line) {
2231
 
            setError("no regular expression after %c", icmd);
 
2228
            setError(MSG_RexpMissing2, icmd);
2232
2229
            return -1;
2233
2230
        }
2234
2231
 
2235
2232
        if(cw->dirMode && !dirWrite) {
2236
 
            setError
2237
 
               ("directories are readonly, type dw to enable directory writes");
 
2233
            setError(MSG_DirNoWrite);
2238
2234
            return -1;
2239
2235
        }
2240
2236
 
2242
2238
            return -1;
2243
2239
        strcpy(lhs, re);
2244
2240
        if(!*line) {
2245
 
            setError("missing delimiter");
 
2241
            setError(MSG_NoDelimit);
2246
2242
            return -1;
2247
2243
        }
2248
2244
        if(!regexpCheck(line, false, true, &re, &line))
2270
2266
                }
2271
2267
                if(isdigitByte(c)) {
2272
2268
                    if(nth) {
2273
 
                        setError("multiple numbers after the third delimiter");
 
2269
                        setError(MSG_SubNumbersMany);
2274
2270
                        return -1;
2275
2271
                    }
2276
2272
                    nth = strtol(line, (char **)&line, 10);
2277
2273
                    continue;
2278
2274
                }               /* number */
2279
 
                setError
2280
 
                   ("unexpected substitution suffix after the third delimiter");
 
2275
                setError(MSG_SubSuffixBad);
2281
2276
                return -1;
2282
2277
            }                   /* loop gathering suffix flags */
2283
2278
            if(g_mode && nth) {
2284
 
                setError
2285
 
                   ("cannot use both a numeric suffix and the `g' suffix simultaneously");
 
2279
                setError(MSG_SubNumberG);
2286
2280
                return -1;
2287
2281
            }
2288
2282
        }                       /* closing delimiter */
2294
2288
            re_opt |= PCRE_CASELESS;
2295
2289
        re_cc = pcre_compile(lhs, re_opt, &re_error, &re_offset, 0);
2296
2290
        if(!re_cc) {
2297
 
            setError("error in regular expression, %s", re_error);
 
2291
            setError(MSG_RexpError, re_error);
2298
2292
            return -1;
2299
2293
        }
2300
2294
    } else {
2303
2297
    }                           /* bl_mode or not */
2304
2298
 
2305
2299
    if(!globSub)
2306
 
        setError(0);
 
2300
        setError(-1);
2307
2301
 
2308
2302
    for(ln = startRange; ln <= endRange && !intFlag; ++ln) {
2309
2303
        char *p = (char *)fetchLine(ln, -1);
2312
2306
        if(bl_mode) {
2313
2307
            int newlen;
2314
2308
            if(!breakLine(p, len, &newlen)) {
2315
 
                setError
2316
 
                   ("sorry, cannot apply the bl command to lines longer than %d bytes",
2317
 
                   REPLACELINELEN);
 
2309
                setError(MSG_BreakLong, REPLACELINELEN);
2318
2310
                return -1;
2319
2311
            }
2320
2312
/* empty line is not allowed */
2334
2326
                char search[20];
2335
2327
                findInputField(p, 1, whichField, &total, &realtotal, &tagno);
2336
2328
                if(!tagno) {
2337
 
                    fieldNumProblem("input fields", 'i', whichField, total,
2338
 
                       realtotal);
 
2329
                    fieldNumProblem(0, 'i', whichField, total, realtotal);
2339
2330
                    continue;
2340
2331
                }
2341
2332
                sprintf(search, "%c%d<", InternalCodeChar, tagno);
2373
2364
 
2374
2365
        if(cw->sqlMode) {
2375
2366
            if(linecount) {
2376
 
                setError("replacement data contains newlines");
 
2367
                setError(MSG_ReplaceNewline);
2377
2368
                goto abort;
2378
2369
            }
2379
2370
            if(nullcount) {
2380
 
                setError("replacement data contains null characters");
 
2371
                setError(MSG_ReplaceNull);
2381
2372
                goto abort;
2382
2373
            }
2383
2374
            *replaceLineEnd = '\n';
2390
2381
/* move the file, then update the text */
2391
2382
            char src[ABSPATH], *dest;
2392
2383
            if(slashcount + nullcount + linecount) {
2393
 
                setError
2394
 
                   ("cannot embed slash, newline, or null in a directory name");
 
2384
                setError(MSG_DirNameBad);
2395
2385
                goto abort;
2396
2386
            }
2397
2387
            p[len - 1] = 0;     /* temporary */
2406
2396
                goto abort;
2407
2397
            if(!stringEqual(src, dest)) {
2408
2398
                if(fileTypeByName(dest, true)) {
2409
 
                    setError("destination file already exists");
 
2399
                    setError(MSG_DestFileExists);
2410
2400
                    goto abort;
2411
2401
                }
2412
2402
                if(rename(src, dest)) {
2413
 
                    setError("cannot rename file to %s", dest);
 
2403
                    setError(MSG_NoRename, dest);
2414
2404
                    goto abort;
2415
2405
                }
2416
2406
            }                   /* source and dest are different */
2418
2408
 
2419
2409
        if(cw->browseMode) {
2420
2410
            if(nullcount) {
2421
 
                setError("cannot embed nulls in an input field");
 
2411
                setError(MSG_InputNull2);
2422
2412
                goto abort;
2423
2413
            }
2424
2414
            if(linecount) {
2425
 
                setError("cannot embed newlines in an input field");
 
2415
                setError(MSG_InputNewline2);
2426
2416
                goto abort;
2427
2417
            }
2428
2418
            replaceLine[replaceLineLen] = 0;
2470
2460
        pcre_free(re_cc);
2471
2461
 
2472
2462
    if(intFlag) {
2473
 
        setError(opint);
 
2463
        setError(MSG_Interrupted);
2474
2464
        return -1;
2475
2465
    }
2476
2466
 
2477
2467
    if(!lastSubst) {
2478
2468
        if(!globSub) {
2479
2469
            if(!errorMsg[0])
2480
 
                setError(bl_mode ? "no changes" : "no match");
 
2470
                setError(bl_mode + MSG_NoMatch);
2481
2471
        }
2482
2472
        return false;
2483
2473
    }
2527
2517
        char *t = userAgents[line[2] - '0'];
2528
2518
        cmd = 'e';
2529
2519
        if(!t) {
2530
 
            setError("agent number %c is not defined", line[2]);
 
2520
            setError(MSG_NoAgent, line[2]);
2531
2521
            return false;
2532
2522
        }
2533
2523
        currentAgent = t;
2563
2553
                char cwdbuf[ABSPATH];
2564
2554
              pwd:
2565
2555
                if(!getcwd(cwdbuf, sizeof (cwdbuf))) {
2566
 
                    setError("could not %s directory",
2567
 
                       (c ? "print new" : "establish current"));
 
2556
                    setError(c ? MSG_CDGetError : MSG_CDSetError);
2568
2557
                    return false;
2569
2558
                }
2570
2559
                puts(cwdbuf);
2574
2563
                return false;
2575
2564
            if(!chdir(t))
2576
2565
                goto pwd;
2577
 
            setError("invalid directory");
 
2566
            setError(MSG_CDInvalid);
2578
2567
            return false;
2579
2568
        }
2580
2569
    }
2587
2576
            const char *suffix = 0;
2588
2577
            bool trailPercent = false;
2589
2578
            if(!cw->dol) {
2590
 
                setError("cannot play an empty buffer");
 
2579
                setError(MSG_AudioEmpty);
2591
2580
                return false;
2592
2581
            }
2593
2582
            if(cw->browseMode) {
2594
 
                setError("cannot play in browse mode");
 
2583
                setError(MSG_AudioBrowse);
2595
2584
                return false;
2596
2585
            }
2597
2586
            if(cw->dirMode) {
2598
 
                setError("cannot play in directory mode");
 
2587
                setError(MSG_AudioDir);
2599
2588
                return false;
2600
2589
            }
2601
2590
            if(cw->sqlMode) {
2602
 
                setError("cannot play in database mode");
 
2591
                setError(MSG_AudioDB);
2603
2592
                return false;
2604
2593
            }
2605
2594
            if(c == '.') {
2608
2597
                if(cw->fileName)
2609
2598
                    suffix = strrchr(cw->fileName, '.');
2610
2599
                if(!suffix) {
2611
 
                    setError
2612
 
                       ("file has no suffix, use mt.xxx to specify your own suffix");
 
2600
                    setError(MSG_NoSuffix);
2613
2601
                    return false;
2614
2602
                }
2615
2603
                ++suffix;
2616
2604
            }
2617
2605
            if(strlen(suffix) > 5) {
2618
 
                setError("suffix is limited to 5 characters");
 
2606
                setError(MSG_SuffixLong);
2619
2607
                return false;
2620
2608
            }
2621
2609
            mt = findMimeBySuffix(suffix);
2622
2610
            if(!mt) {
2623
 
                setError
2624
 
                   ("suffix .%s is not a recognized mime type, please check your config file.",
2625
 
                   suffix);
 
2611
                setError(MSG_SuffixBad, suffix);
2626
2612
                return false;
2627
2613
            }
2628
2614
            if(mt->program[strlen(mt->program) - 1] == '%')
2637
2623
    if(stringEqual(line, "rf")) {
2638
2624
        cmd = 'e';
2639
2625
        if(!cw->fileName) {
2640
 
            setError("no file name or url to refresh");
 
2626
            setError(MSG_NoRefresh);
2641
2627
            return false;
2642
2628
        }
2643
2629
        if(cw->browseMode)
2650
2636
 
2651
2637
    if(stringEqual(line, "sc")) {
2652
2638
        if(!cw->sqlMode) {
2653
 
            setError("not in database mode");
 
2639
            setError(MSG_NoDB);
2654
2640
            return false;
2655
2641
        }
2656
2642
        showColumns();
2661
2647
        bool ub = (line[0] == 'u');
2662
2648
        cmd = 'e';
2663
2649
        if(!cw->browseMode) {
2664
 
            setError("not in browse mode");
 
2650
            setError(MSG_NoBrowse);
2665
2651
            return false;
2666
2652
        }
2667
2653
        freeUndoLines(cw->map);
2709
2695
        allIPs();
2710
2696
        endhostent();
2711
2697
        if(!cw->iplist || cw->iplist[0] == -1) {
2712
 
            puts("none");
 
2698
            i_puts(MSG_None);
2713
2699
        } else {
2714
2700
            IP32bit ip;
2715
2701
            for(i = 0; (ip = cw->iplist[i]) != NULL_IP; ++i) {
2723
2709
        char *t;
2724
2710
        cmd = line[0];
2725
2711
        if(!cw->fileName) {
2726
 
            setError("no file name or url to refresh");
 
2712
            setError(MSG_NoRefresh);
2727
2713
            return false;
2728
2714
        }
2729
2715
        t = strrchr(cw->fileName, '/');
2730
2716
        if(!t) {
2731
 
            setError("file name does not contain /");
 
2717
            setError(MSG_NoSlash);
2732
2718
            return false;
2733
2719
        }
2734
2720
        ++t;
2735
2721
        if(!*t) {
2736
 
            setError("file name ends in /");
 
2722
            setError(MSG_YesSlash);
2737
2723
            return false;
2738
2724
        }
2739
2725
        sprintf(newline, "%c `%s", cmd, t);
2742
2728
 
2743
2729
    if(line[0] == 'f' && line[2] == 0 &&
2744
2730
       (line[1] == 'd' || line[1] == 'k' || line[1] == 't')) {
2745
 
        const char *s, *t;
 
2731
        const char *s;
 
2732
        int t;
2746
2733
        cmd = 'e';
2747
2734
        if(!cw->browseMode) {
2748
 
            setError("not in browse mode");
 
2735
            setError(MSG_NoBrowse);
2749
2736
            return false;
2750
2737
        }
2751
2738
        if(line[1] == 't')
2752
 
            s = cw->ft, t = "title";
 
2739
            s = cw->ft, t = MSG_NoTitle;
2753
2740
        if(line[1] == 'd')
2754
 
            s = cw->fd, t = "description";
 
2741
            s = cw->fd, t = MSG_NoDesc;
2755
2742
        if(line[1] == 'k')
2756
 
            s = cw->fk, t = "keywords";
 
2743
            s = cw->fk, t = MSG_NoKeywords;
2757
2744
        if(s)
2758
2745
            puts(s);
2759
2746
        else
2760
 
            printf("no %s\n", t);
 
2747
            i_puts(t);
2761
2748
        return true;
2762
2749
    }
2763
2750
 
2776
2763
/* send mail */
2777
2764
            return sendMailCurrent(account, dosig);
2778
2765
        } else {
2779
 
            setError("invalid characters after the sm command");
 
2766
            setError(MSG_SMBadChar);
2780
2767
            return false;
2781
2768
        }
2782
2769
    }
2784
2771
    if(stringEqual(line, "sg")) {
2785
2772
        searchStringsAll = true;
2786
2773
        if(helpMessagesOn)
2787
 
            puts("substitutions global");
 
2774
            i_puts(MSG_SubGlobal);
2788
2775
        return true;
2789
2776
    }
2790
2777
 
2791
2778
    if(stringEqual(line, "sl")) {
2792
2779
        searchStringsAll = false;
2793
2780
        if(helpMessagesOn)
2794
 
            puts("substitutions local");
 
2781
            i_puts(MSG_SubLocal);
2795
2782
        return true;
2796
2783
    }
2797
2784
 
2798
2785
    if(stringEqual(line, "ci")) {
2799
2786
        caseInsensitive = true;
2800
2787
        if(helpMessagesOn)
2801
 
            puts("case insensitive");
 
2788
            i_puts(MSG_CaseIns);
2802
2789
        return true;
2803
2790
    }
2804
2791
 
2805
2792
    if(stringEqual(line, "cs")) {
2806
2793
        caseInsensitive = false;
2807
2794
        if(helpMessagesOn)
2808
 
            puts("case sensitive");
 
2795
            i_puts(MSG_CaseSen);
2809
2796
        return true;
2810
2797
    }
2811
2798
 
2812
2799
    if(stringEqual(line, "dr")) {
2813
2800
        dirWrite = 0;
2814
2801
        if(helpMessagesOn)
2815
 
            puts("directories readonly");
 
2802
            i_puts(MSG_DirReadonly);
2816
2803
        return true;
2817
2804
    }
2818
2805
 
2819
2806
    if(stringEqual(line, "dw")) {
2820
2807
        dirWrite = 1;
2821
2808
        if(helpMessagesOn)
2822
 
            puts("directories writable");
 
2809
            i_puts(MSG_DirWritable);
2823
2810
        return true;
2824
2811
    }
2825
2812
 
2826
2813
    if(stringEqual(line, "dx")) {
2827
2814
        dirWrite = 2;
2828
2815
        if(helpMessagesOn)
2829
 
            puts("directories writable with delete");
 
2816
            i_puts(MSG_DirX);
2830
2817
        return true;
2831
2818
    }
2832
2819
 
2833
2820
    if(stringEqual(line, "hr")) {
2834
2821
        allowRedirection ^= 1;
2835
2822
        if(helpMessagesOn || debugLevel >= 1)
2836
 
            puts(allowRedirection ? "http redirection" : "no http redirection");
 
2823
            i_puts(allowRedirection + MSG_RedirectionOff);
2837
2824
        return true;
2838
2825
    }
2839
2826
 
2840
2827
    if(stringEqual(line, "sr")) {
2841
2828
        sendReferrer ^= 1;
2842
2829
        if(helpMessagesOn || debugLevel >= 1)
2843
 
            puts(sendReferrer ? "send referrer" : "do not send referrer");
 
2830
            i_puts(sendReferrer + MSG_RefererOff);
2844
2831
        return true;
2845
2832
    }
2846
2833
 
2847
2834
    if(stringEqual(line, "js")) {
2848
2835
        allowJS ^= 1;
2849
2836
        if(helpMessagesOn || debugLevel >= 1)
2850
 
            puts(allowJS ? "javascript enabled" : "javascript disabled");
 
2837
            i_puts(allowJS + MSG_JavaOff);
2851
2838
        return true;
2852
2839
    }
2853
2840
 
2854
2841
    if(stringEqual(line, "bd")) {
2855
2842
        binaryDetect ^= 1;
2856
2843
        if(helpMessagesOn || debugLevel >= 1)
2857
 
            puts(binaryDetect ? "watching for binary files" :
2858
 
               "treating binary like text");
 
2844
            i_puts(binaryDetect + MSG_BinaryIgnore);
2859
2845
        return true;
2860
2846
    }
2861
2847
 
2868
2854
            ftpMode = 'E';
2869
2855
        if(helpMessagesOn || debugLevel >= 1) {
2870
2856
            if(ftpMode == 'F')
2871
 
                puts("passive mode");
 
2857
                i_puts(MSG_PassiveMode);
2872
2858
            if(ftpMode == 'E')
2873
 
                puts("active mode");
 
2859
                i_puts(MSG_ActiveMode);
2874
2860
            if(ftpMode == 0)
2875
 
                puts("passive/active mode");
 
2861
                i_puts(MSG_PassActMode);
2876
2862
        }
2877
2863
        return true;
2878
2864
    }
2879
 
    /* fm */
 
2865
 
2880
2866
    if(stringEqual(line, "vs")) {
2881
2867
        verifyCertificates ^= 1;
2882
2868
        if(helpMessagesOn || debugLevel >= 1)
2883
 
            puts(verifyCertificates ? "verify ssl connections" :
2884
 
               "don't verify ssl connections (less secure)");
 
2869
            i_puts(verifyCertificates + MSG_CertifyOff);
2885
2870
        ssl_must_verify(verifyCertificates);
2886
2871
        return true;
2887
2872
    }
2889
2874
    if(stringEqual(line, "hf")) {
2890
2875
        showHiddenFiles ^= 1;
2891
2876
        if(helpMessagesOn || debugLevel >= 1)
2892
 
            puts(showHiddenFiles ? "show hidden files in directory mode" :
2893
 
               "don't show hidden files in directory mode");
 
2877
            i_puts(showHiddenFiles + MSG_HiddenOff);
2894
2878
        return true;
2895
2879
    }
2896
2880
 
2897
2881
    if(stringEqual(line, "tn")) {
2898
2882
        textAreaDosNewlines ^= 1;
2899
2883
        if(helpMessagesOn || debugLevel >= 1)
2900
 
            puts(textAreaDosNewlines ? "text areas use dos newlines" :
2901
 
               "text areas use unix newlines");
 
2884
            i_puts(textAreaDosNewlines + MSG_AreaUnix);
2902
2885
        return true;
2903
2886
    }
2904
2887
 
2905
2888
    if(stringEqual(line, "eo")) {
2906
2889
        endMarks = 0;
2907
2890
        if(helpMessagesOn)
2908
 
            puts("end markers off");
 
2891
            i_puts(MSG_MarkOff);
2909
2892
        return true;
2910
2893
    }
2911
2894
 
2912
2895
    if(stringEqual(line, "el")) {
2913
2896
        endMarks = 1;
2914
2897
        if(helpMessagesOn)
2915
 
            puts("end markers on listed lines");
 
2898
            i_puts(MSG_MarkList);
2916
2899
        return true;
2917
2900
    }
2918
2901
 
2919
2902
    if(stringEqual(line, "ep")) {
2920
2903
        endMarks = 2;
2921
2904
        if(helpMessagesOn)
2922
 
            puts("end markers on");
 
2905
            i_puts(MSG_MarkOn);
2923
2906
        return true;
2924
2907
    }
2925
2908
 
2974
2957
    char selected;
2975
2958
    static char openlist[] = "{([<`";
2976
2959
    static char closelist[] = "})]>'";
2977
 
    static char alllist[] = "{}()[]<>`'";
 
2960
    static const char alllist[] = "{}()[]<>`'";
2978
2961
    char *t;
2979
2962
    int level = 0;
2980
2963
    int i, direction, forward, backward;
2981
2964
 
2982
2965
    if(c = *line) {
2983
2966
        if(!strchr(alllist, c) || line[1]) {
2984
 
            setError("you must specify exactly one of %s after the B command",
2985
 
               alllist);
 
2967
            setError(MSG_BalanceChar, alllist);
2986
2968
            return false;
2987
2969
        }
2988
2970
        if(t = strchr(openlist, c)) {
2997
2979
        unbalanced(c, d, endRange, &backward, &forward);
2998
2980
        if(direction > 0) {
2999
2981
            if((level = forward) == 0) {
3000
 
                setError("line does not contain an open %c", c);
 
2982
                setError(MSG_BalanceNoOpen, c);
3001
2983
                return false;
3002
2984
            }
3003
2985
        } else {
3004
2986
            if((level = backward) == 0) {
3005
 
                setError("line does not contain an open %c", d);
 
2987
                setError(MSG_BalanceNoOpen, d);
3006
2988
                return false;
3007
2989
            }
3008
2990
        }
3014
2996
            d = closelist[i];
3015
2997
            unbalanced(c, d, endRange, &backward, &forward);
3016
2998
            if(backward && forward) {
3017
 
                setError
3018
 
                   ("both %c and %c are unbalanced on this line, try B%c or B%c",
3019
 
                   c, d, c, d);
 
2999
                setError(MSG_BalanceAmbig, c, d, c, d);
3020
3000
                return false;
3021
3001
            }
3022
3002
            level = backward + forward;
3028
3008
            break;
3029
3009
        }
3030
3010
        if(!level) {
3031
 
            setError
3032
 
               ("line does not contain an unbalanced brace, parenthesis, or bracket");
 
3011
            setError(MSG_BalanceNothing);
3033
3012
            return false;
3034
3013
        }
3035
3014
    }                           /* explicit character passed in, or look for one */
3049
3028
        level += (forward - backward) * direction;
3050
3029
    }                           /* loop over lines */
3051
3030
 
3052
 
    setError("cannot find the line that balances %c", selected);
 
3031
    setError(MSG_Unbalanced, selected);
3053
3032
    return false;
3054
3033
}                               /* balanceLine */
3055
3034
 
3065
3044
        return false;
3066
3045
    w = sessionList[cx].lw;
3067
3046
    if(w->browseMode) {
3068
 
        setError("session %d is currently in browse mode", cx);
 
3047
        setError(MSG_SessionBrowse, cx);
3069
3048
        return false;
3070
3049
    }
3071
3050
    if(w->dirMode) {
3072
 
        setError("session %d is currently in directory mode", cx);
 
3051
        setError(MSG_SessionDir, cx);
3073
3052
        return false;
3074
3053
    }
3075
3054
    if(cr)
3177
3156
    /* browse mode */
3178
3157
    if(!a_l) {                  /* nothing found yet */
3179
3158
        if(!cw->fileName) {
3180
 
            setError("no file name");
 
3159
            setError(MSG_NoFileName);
3181
3160
            return 0;
3182
3161
        }
3183
3162
        h = cloneString(cw->fileName);
3261
3240
        didRange = true;
3262
3241
        ++startRange, ++endRange;
3263
3242
        if(endRange > cw->dol) {
3264
 
            setError("end of buffer");
 
3243
            setError(MSG_EndBuffer);
3265
3244
            return false;
3266
3245
        }
3267
3246
    }
3283
3262
        didRange = true;
3284
3263
        endRange = startRange + 1;
3285
3264
        if(endRange > cw->dol) {
3286
 
            setError("no more lines to join");
 
3265
            setError(MSG_EndJoin);
3287
3266
            return false;
3288
3267
        }
3289
3268
    }
3315
3294
        }
3316
3295
    }
3317
3296
    if(endRange < startRange) {
3318
 
        setError("bad range");
 
3297
        setError(MSG_BadRange);
3319
3298
        return false;
3320
3299
    }
3321
3300
 
3330
3309
/* Breakline is actually a substitution of lines. */
3331
3310
    if(stringEqual(line, "bl")) {
3332
3311
        if(cw->dirMode) {
3333
 
            setError("cannot break lines in directory mode");
 
3312
            setError(MSG_BreakDir);
3334
3313
            return false;
3335
3314
        }
3336
3315
        if(cw->sqlMode) {
3337
 
            setError("cannot break lines in database mode");
 
3316
            setError(MSG_BreakDB);
3338
3317
            return false;
3339
3318
        }
3340
3319
        if(cw->browseMode) {
3341
 
            setError("cannot break lines in browse mode");
 
3320
            setError(MSG_BreakBrowse);
3342
3321
            return false;
3343
3322
        }
3344
3323
        line = "s`bl";
3353
3332
    icmd = cmd;
3354
3333
 
3355
3334
    if(!strchr(valid_cmd, cmd)) {
3356
 
        setError("unknown command %c", cmd);
 
3335
        setError(MSG_UnknownCommand, cmd);
3357
3336
        return (globSub = false);
3358
3337
    }
3359
3338
 
3363
3342
        writeMode = O_APPEND, first = *++line;
3364
3343
 
3365
3344
    if(cw->dirMode && !strchr(dir_cmd, cmd)) {
3366
 
        setError("%c not available in directory mode", icmd);
 
3345
        setError(MSG_DirCommand, icmd);
3367
3346
        return (globSub = false);
3368
3347
    }
3369
3348
    if(cw->sqlMode && !strchr(sql_cmd, cmd)) {
3370
 
        setError("%c not available in database mode", icmd);
 
3349
        setError(MSG_BadRange, icmd);
3371
3350
        return (globSub = false);
3372
3351
    }
3373
3352
    if(cw->browseMode && !strchr(browse_cmd, cmd)) {
3374
 
        setError("%c not available in browse mode", icmd);
 
3353
        setError(MSG_BrowseCommand, icmd);
3375
3354
        return (globSub = false);
3376
3355
    }
3377
3356
    if(startRange == 0 && !strchr(zero_cmd, cmd)) {
3378
 
        setError("zero line number");
 
3357
        setError(MSG_AtLine0);
3379
3358
        return (globSub = false);
3380
3359
    }
3381
3360
    while(isspaceByte(first))
3385
3364
        while(isdigitByte(*s))
3386
3365
            ++s;
3387
3366
        if(*s) {
3388
 
            setError("no space after command");
 
3367
            setError(MSG_NoSpaceAfter);
3389
3368
            return (globSub = false);
3390
3369
        }
3391
3370
    }
3392
3371
    if(globSub && !strchr(global_cmd, cmd)) {
3393
 
        setError("the %c command cannot be applied globally", icmd);
 
3372
        setError(MSG_GlobalCommand, icmd);
3394
3373
        return (globSub = false);
3395
3374
    }
3396
3375
 
3400
3379
            destLine = cw->dot;
3401
3380
        } else {
3402
3381
            if(!strchr(valid_laddr, first)) {
3403
 
                setError("invalid move/copy destination");
 
3382
                setError(MSG_BadDest);
3404
3383
                return (globSub = false);
3405
3384
            }
3406
3385
            if(!getRangePart(line, &destLine, &line))
3434
3413
        startRange = endRange + 1;
3435
3414
        endRange = startRange;
3436
3415
        if(startRange > cw->dol) {
3437
 
            setError("line number too large");
 
3416
            setError(MSG_LineHigh);
3438
3417
            return false;
3439
3418
        }
3440
3419
        cmd = 'p';
3453
3432
        linePending[0] = 0;
3454
3433
 
3455
3434
    if(first && strchr(nofollow_cmd, cmd)) {
3456
 
        setError("unexpected text after the %c command", icmd);
 
3435
        setError(MSG_TextAfter, icmd);
3457
3436
        return (globSub = false);
3458
3437
    }
3459
3438
 
3464
3443
    /* h */
3465
3444
    if(cmd == 'H') {
3466
3445
        if(helpMessagesOn ^= 1)
3467
 
            debugPrint(1, "help messages on");
3468
 
        return true;
3469
 
    }
3470
 
    /* H */
 
3446
            if(debugLevel >= 1)
 
3447
                i_puts(MSG_HelpOn);
 
3448
        return true;
 
3449
    }
 
3450
 
 
3451
    if(cmd == 'X') {
 
3452
        cw->dot = endRange;
 
3453
        return true;
 
3454
    }
 
3455
 
3471
3456
    if(strchr("lpn", cmd)) {
3472
3457
        for(i = startRange; i <= endRange; ++i) {
3473
3458
            displayLine(i);
3477
3462
        }
3478
3463
        return true;
3479
3464
    }
3480
 
    /* lpn */
 
3465
 
3481
3466
    if(cmd == '=') {
3482
3467
        printf("%d\n", endRange);
3483
3468
        return true;
3491
3476
        struct ebWindow *uw = &undoWindow;
3492
3477
        char *swapmap;
3493
3478
        if(!cw->firstOpMode) {
3494
 
            setError("nothing to undo");
 
3479
            setError(MSG_NoUndo);
3495
3480
            return false;
3496
3481
        }
3497
3482
/* swap, so we can undo our undo, if need be */
3506
3491
    /* u */
3507
3492
    if(cmd == 'k') {
3508
3493
        if(!islowerByte(first) || line[1]) {
3509
 
            setError("please enter k[a-z]");
 
3494
            setError(MSG_EnterKAZ);
3510
3495
            return false;
3511
3496
        }
3512
3497
        if(startRange < endRange) {
3513
 
            setError("cannot label an entire range");
 
3498
            setError(MSG_RangeLabel);
3514
3499
            return false;
3515
3500
        }
3516
3501
        cw->labels[first - 'a'] = endRange;
3522
3507
    if(!postSpace) {
3523
3508
        cx = stringIsNum(line);
3524
3509
        if(!cx) {
3525
 
            setError("%s 0 is invalid", cmd == '^' ? "backing up" : "session");
 
3510
            setError((cmd == '^') ? MSG_Backup0 : MSG_Session0);
3526
3511
            return false;
3527
3512
        }
3528
3513
        if(cx < 0)
3538
3523
        } else {
3539
3524
            cx = context;
3540
3525
            if(first) {
3541
 
                setError("unexpected text after the q command");
 
3526
                setError(MSG_QAfter);
3542
3527
                return false;
3543
3528
            }
3544
3529
        }
3567
3552
            if(!cxActive(cx))
3568
3553
                return false;
3569
3554
            s = sessionList[cx].lw->fileName;
3570
 
            printf("%s", s ? s : "no file");
 
3555
            if(s)
 
3556
                printf("%s", s);
 
3557
            else
 
3558
                i_printf(MSG_NoFile);
3571
3559
            if(sessionList[cx].lw->binMode)
3572
 
                printf(" [binary]");
3573
 
            printf("\n");
 
3560
                i_printf(MSG_BinaryBrackets);
 
3561
            nl();
3574
3562
            return true;
3575
3563
        }                       /* another session */
3576
3564
        if(first) {
3577
3565
            if(cw->dirMode) {
3578
 
                setError("cannot change the name of a directory");
 
3566
                setError(MSG_DirRename);
3579
3567
                return false;
3580
3568
            }
3581
3569
            if(cw->sqlMode) {
3582
 
                setError("cannot change the name of a table");
 
3570
                setError(MSG_TableRename);
3583
3571
                return false;
3584
3572
            }
3585
3573
            nzFree(cw->fileName);
3586
3574
            cw->fileName = cloneString(line);
3587
3575
        }
3588
3576
        s = cw->fileName;
3589
 
        printf("%s", s ? s : "no file");
 
3577
        if(s)
 
3578
            printf("%s", s);
 
3579
        else
 
3580
            i_printf(MSG_NoFile);
3590
3581
        if(cw->binMode)
3591
 
            printf(" [binary]");
3592
 
        printf("\n");
 
3582
            i_printf(MSG_BinaryBrackets);
 
3583
        nl();
3593
3584
        return true;
3594
3585
    }
3595
 
    /* f */
 
3586
 
3596
3587
    if(cmd == 'w') {
3597
3588
        if(cx) {                /* write to another buffer */
3598
3589
            if(writeMode == O_APPEND) {
3599
 
                setError("cannot append to another buffer");
 
3590
                setError(MSG_BufferAppend);
3600
3591
                return false;
3601
3592
            }
3602
3593
            return writeContext(cx);
3604
3595
        if(!first)
3605
3596
            line = cw->fileName;
3606
3597
        if(!line) {
3607
 
            setError("no file specified");
 
3598
            setError(MSG_NoFileSpecified);
3608
3599
            return false;
3609
3600
        }
3610
3601
        if(cw->dirMode && stringEqual(line, cw->fileName)) {
3611
 
            setError
3612
 
               ("cannot write to the directory; files are modified as you go");
 
3602
            setError(MSG_NoDirWrite);
3613
3603
            return false;
3614
3604
        }
3615
3605
        if(cw->sqlMode && stringEqual(line, cw->fileName)) {
3616
 
            setError
3617
 
               ("cannot write to the database; rows are modified as you go");
 
3606
            setError(MSG_NoDBWrite);
3618
3607
            return false;
3619
3608
        }
3620
3609
        return writeFile(line, writeMode);
3622
3611
    /* w */
3623
3612
    if(cmd == '^') {            /* back key, pop the stack */
3624
3613
        if(first && !cx) {
3625
 
            setError("unexpected text after the ^ command");
 
3614
            setError(MSG_ArrowAfter);
3626
3615
            return false;
3627
3616
        }
3628
3617
        if(!cx)
3630
3619
        while(cx) {
3631
3620
            struct ebWindow *prev = cw->prev;
3632
3621
            if(!prev) {
3633
 
                setError("no previous text");
 
3622
                setError(MSG_NoPrevious);
3634
3623
                return false;
3635
3624
            }
3636
3625
            saveSubstitutionStrings();
3646
3635
 
3647
3636
    if(cmd == 'M') {            /* move this to another session */
3648
3637
        if(first && !cx) {
3649
 
            setError("unexpected text after the M command");
 
3638
            setError(MSG_MAfter);
3650
3639
            return false;
3651
3640
        }
3652
3641
        if(!first) {
3653
 
            setError("destination session not specified");
 
3642
            setError(MSG_NoDestSession);
3654
3643
            return false;
3655
3644
        }
3656
3645
        if(!cw->prev) {
3657
 
            setError("no previous text, cannot back up");
 
3646
            setError(MSG_NoBackup);
3658
3647
            return false;
3659
3648
        }
3660
3649
        if(!cxCompare(cx))
3701
3690
    if(cmd == 'g' && cw->dirMode && !first) {
3702
3691
        char *p, *dirline, *endline;
3703
3692
        if(endRange > startRange) {
3704
 
            setError("cannot apply the g command to a range");
 
3693
            setError(MSG_RangeG);
3705
3694
            return false;
3706
3695
        }
3707
3696
        p = (char *)fetchLine(endRange, -1);
3726
3715
            return true;
3727
3716
        }
3728
3717
        if(!first) {
3729
 
            printf("session %d\n", context);
 
3718
            i_printf(MSG_SessionX, context);
3730
3719
            return true;
3731
3720
        }
3732
3721
/* more e to come */
3743
3732
            j = strtol(line, (char **)&s, 10);
3744
3733
        if(j >= 0 && !*s) {
3745
3734
            if(cw->sqlMode) {
3746
 
                setError("g not available in database mode");
 
3735
                setError(MSG_DBG);
3747
3736
                return false;
3748
3737
            }
3749
3738
            jsh = jsgo = nogo = false;
3750
3739
            jsdead = cw->jsdead;
3751
3740
            if(!cw->jsc)
3752
3741
                jsdead = true;
 
3742
            click = dclick = over = false;
3753
3743
            cmd = 'b';
3754
3744
            if(endRange > startRange) {
3755
 
                setError("cannot apply the g command to a range");
 
3745
                setError(MSG_RangeG);
3756
3746
                return false;
3757
3747
            }
3758
3748
            p = (char *)fetchLine(endRange, -1);
3760
3750
            findField(p, 0, j, &n, 0, &tagno, &h, &ev);
3761
3751
            debugPrint(5, "findField returns %d, %s", tagno, h);
3762
3752
            if(!h) {
3763
 
                fieldNumProblem("links", 'g', j, n, n);
 
3753
                fieldNumProblem(1, 'g', j, n, n);
3764
3754
                return false;
3765
3755
            }
3766
3756
            jsh = memEqualCI(h, "javascript:", 11);
3778
3768
            debugPrint(5, "click %d dclick %d over %d", click, dclick, over);
3779
3769
            if(jsgo & jsdead) {
3780
3770
                if(nogo)
3781
 
                    puts("javascript is disabled, no action taken");
 
3771
                    i_puts(MSG_NJNoAction);
3782
3772
                else
3783
 
                    puts("javascript is disabled, going straight to the url");
 
3773
                    i_puts(MSG_NJGoing);
3784
3774
                jsgo = jsh = false;
3785
3775
            }
3786
3776
            line = allocatedLine = h;
3787
3777
            first = *line;
3788
 
            setError(0);
 
3778
            setError(-1);
3789
3779
            rc = false;
3790
3780
            if(jsgo) {
3791
3781
                jSyncup();
3848
3838
        c = *s;
3849
3839
        if(c && (strchr(valid_delim, c) || cmd == 'i' && strchr("*<?=", c))) {
3850
3840
            if(!cw->browseMode && (cmd == 'i' || cx)) {
3851
 
                setError("not in browse mode");
 
3841
                setError(MSG_NoBrowse);
3852
3842
                return false;
3853
3843
            }
3854
3844
            if(endRange > startRange && cmd == 'i') {
3855
 
                setError("cannot apply the i%c command to a range", c);
 
3845
                setError(MSG_RangeI, c);
3856
3846
                return false;
3857
3847
            }
3858
3848
            if(cmd == 'i' && strchr("?=<*", c)) {
3872
3862
                findInputField(p, j, cx, &n, &realtotal, &tagno);
3873
3863
                debugPrint(5, "findField returns %d.%d", n, tagno);
3874
3864
                if(!tagno) {
3875
 
                    fieldNumProblem((c == '*' ? "buttons" : "input fields"),
3876
 
                       'i', cx, n, realtotal);
 
3865
                    fieldNumProblem((c == '*' ? 2 : 0), 'i', cx, n, realtotal);
3877
3866
                    return false;
3878
3867
                }
3879
3868
                if(scmd == '?') {
3883
3872
                if(c == '<') {
3884
3873
                    bool fromfile = false;
3885
3874
                    if(globSub) {
3886
 
                        setError("cannot use i< in a global command");
 
3875
                        setError(MSG_IG);
3887
3876
                        return (globSub = false);
3888
3877
                    }
3889
3878
                    skipWhite(&line);
3890
3879
                    if(!*line) {
3891
 
                        setError("no file specified");
 
3880
                        setError(MSG_NoFileSpecified);
3892
3881
                        return false;
3893
3882
                    }
3894
3883
                    n = stringIsNum(line);
3899
3888
                            return false;
3900
3889
                        dol = sessionList[n].lw->dol;
3901
3890
                        if(!dol) {
3902
 
                            setError("buffer %d is empty", n);
 
3891
                            setError(MSG_BufferXEmpty, n);
3903
3892
                            return false;
3904
3893
                        }
3905
3894
                        if(dol > 1) {
3906
 
                            setError("buffer %d contains more than one line",
3907
 
                               n);
 
3895
                            setError(MSG_BufferXLines, n);
3908
3896
                            return false;
3909
3897
                        }
3910
3898
                        p = (char *)fetchLineContext(1, 1, n);
3921
3909
                            return false;
3922
3910
                        fd = open(line, O_RDONLY | O_TEXT);
3923
3911
                        if(fd < 0) {
3924
 
                            setError("cannot open %s", line);
 
3912
                            setError(MSG_NoOpen, line);
3925
3913
                            return false;
3926
3914
                        }
3927
3915
                        n = read(fd, newline, sizeof (newline));
3928
3916
                        close(fd);
3929
3917
                        if(n < 0) {
3930
 
                            setError("cannot read from %s", line);
 
3918
                            setError(MSG_NoRead, line);
3931
3919
                            return false;
3932
3920
                        }
3933
3921
                    }
3934
3922
                    for(j = 0; j < n; ++j) {
3935
3923
                        if(newline[j] == 0) {
3936
 
                            setError("input text contains nulls", line);
 
3924
                            setError(MSG_InputNull, line);
3937
3925
                            return false;
3938
3926
                        }
3939
3927
                        if(newline[j] == '\r' && !fromfile &&
3940
3928
                           j < n - 1 && newline[j + 1] != '\n') {
3941
 
                            setError
3942
 
                               ("line contains an embeded carriage return");
 
3929
                            setError(MSG_InputCR);
3943
3930
                            return false;
3944
3931
                        }
3945
3932
                        if(newline[j] == '\r' || newline[j] == '\n')
3946
3933
                            break;
3947
3934
                    }
3948
3935
                    if(j == sizeof (newline)) {
3949
 
                        setError("first line of %s is too long", line);
 
3936
                        setError(MSG_FirstLineLong, line);
3950
3937
                        return false;
3951
3938
                    }
3952
3939
                    newline[j] = 0;
3969
3956
            } else
3970
3957
                cmd = 's';
3971
3958
        } else {
3972
 
            setError("unexpected text after the %c command", icmd);
 
3959
            setError(MSG_TextAfter, icmd);
3973
3960
            return false;
3974
3961
        }
3975
3962
    }
3978
3965
    if(cmd == 'e' || cmd == 'b' && first && first != '#') {
3979
3966
        if(cw->fileName && !noStack && sameURL(line, cw->fileName)) {
3980
3967
            if(stringEqual(line, cw->fileName)) {
3981
 
                setError
3982
 
                   ("file is currently in buffer - please use the rf command to refresh");
 
3968
                setError(MSG_AlreadyInBuffer);
3983
3969
                return false;
3984
3970
            }
3985
3971
/* Same url, but a different #section */
4030
4016
            nzFree(subj);
4031
4017
            nzFree(body);
4032
4018
            if(j)
4033
 
                printf
4034
 
                   ("SendMail link.  Compose your mail, type sm to send, then ^ to get back.\n");
 
4019
                i_puts(MSG_MailHowto);
4035
4020
        } else {
4036
4021
            cw->fileName = cloneString(line);
4037
4022
            if(isSQL(line))
4084
4069
    if(cmd == 'b') {
4085
4070
        if(!cw->browseMode) {
4086
4071
            if(cw->binMode) {
4087
 
                setError("cannot browse a binary file");
 
4072
                setError(MSG_BrowseBinary);
4088
4073
                return false;
4089
4074
            }
4090
4075
            if(!cw->dol) {
4091
 
                setError("cannot browse an empty file");
 
4076
                setError(MSG_BrowseEmpty);
4092
4077
                return false;
4093
4078
            }
4094
4079
            if(fileSize >= 0) {
4097
4082
            }
4098
4083
            if(!browseCurrentBuffer()) {
4099
4084
                if(icmd == 'b') {
4100
 
                    setError("this doesn't look like browsable text");
 
4085
                    setError(MSG_Unbrowsable);
4101
4086
                    return false;
4102
4087
                }
4103
4088
                return true;
4104
4089
            }
4105
4090
        } else if(!first) {
4106
 
            setError("already browsing");
 
4091
            setError(MSG_BrowseAlready);
4107
4092
            return false;
4108
4093
        }
4109
4094
 
4125
4110
                icmd = cmd = 'b';
4126
4111
                first = *line;
4127
4112
                if(intFlag) {
4128
 
                    puts("redirection interrupted by user");
 
4113
                    i_puts(MSG_RedirectionInterrupted);
4129
4114
                    return true;
4130
4115
                }
4131
4116
                goto rebrowse;
4156
4141
                return true;
4157
4142
            }
4158
4143
        }
4159
 
        setError("label %s not found", s);
 
4144
        setError(MSG_NoLable2, s);
4160
4145
        return false;
4161
4146
    }
4162
4147
    /* b */
4194
4179
            return rc;
4195
4180
        }
4196
4181
        if(cw->browseMode) {
4197
 
            setError("i not available in browse mode");
 
4182
            setError(MSG_BrowseI);
4198
4183
            return false;
4199
4184
        }
4200
4185
        cmd = 'a';
4209
4194
 
4210
4195
    if(cmd == 'a') {
4211
4196
        if(inscript) {
4212
 
            setError("cannot run an insert command from an edbrowse function");
 
4197
            setError(MSG_InsertFunction);
4213
4198
            return false;
4214
4199
        }
4215
4200
        if(cw->sqlMode) {
4280
4265
                }
4281
4266
                if(j > 1) {
4282
4267
                  notwhere:
4283
 
                    setError("cannot read text into a database session");
 
4268
                    setError(MSG_readText);
4284
4269
                    return false;
4285
4270
                }
4286
4271
              sqlwhere:
4293
4278
                fileSize = -1;
4294
4279
            return j;
4295
4280
        }
4296
 
        setError("no file specified");
 
4281
        setError(MSG_NoFileSpecified);
4297
4282
        return false;
4298
4283
    }
4299
4284
 
4308
4293
        return j;
4309
4294
    }
4310
4295
    /* s */
4311
 
    setError("command %c not yet implemented", icmd);
 
4296
    setError(MSG_CNYI, icmd);
4312
4297
    return (globSub = false);
4313
4298
}                               /* runCommand */
4314
4299
 
4366
4351
            if(!sessionList[cx].lw)
4367
4352
                break;
4368
4353
        if(cx == MAXSESSION) {
4369
 
            debugPrint(0,
4370
 
               "warning: no buffers available to handle the ancillary window");
 
4354
            i_puts(MSG_NoBufferExtraWindow);
4371
4355
            return 0;
4372
4356
        }
4373
4357
    }
4384
4368
    if(textlen) {
4385
4369
        rc = addTextToBuffer((pst) text, textlen, 0);
4386
4370
        if(!rc)
4387
 
            debugPrint(0,
4388
 
               "warning: could not preload <buffer %d> with its initial text",
4389
 
               cx);
 
4371
            i_printf(MSG_BufferPreload, cx);
4390
4372
        if(autobrowse) {
4391
4373
/* This is html; we need to render it.
4392
4374
 * I'm disabling javascript in this window.
4472
4454
            do_ip = false;
4473
4455
        if(passMail)
4474
4456
            do_ip = false;
4475
 
        if(memEqualCI(newbuf, "<html>\n", 7)) {
 
4457
        if(memEqualCI(newbuf, "<html>\n", 7) && allowRedirection) {
4476
4458
/* double browse, mail then html */
4477
4459
            bmode = 2;
4478
4460
            rawbuf = newbuf;
4563
4545
        s = strchr(s, '<') + 1;
4564
4546
        t = strstr(s, "\2000>");
4565
4547
        if(!t)
4566
 
            errorPrint("@no closing > at line %d", ln);
 
4548
            i_printfExit(MSG_NoClosingLine, ln);
4567
4549
        *ln_p = ln;
4568
4550
        *p_p = p;
4569
4551
        *s_p = s;
4605
4587
        if(notify == 1)
4606
4588
            displayLine(ln);
4607
4589
        if(notify == 2)
4608
 
            printf("line %d has been updated\n", ln);
 
4590
            i_printf(MSG_LineUpdated, ln);
4609
4591
        cw->firstOpMode = undoable = true;
4610
4592
        return;
4611
4593
    }
4612
4594
 
4613
4595
    if(required)
4614
 
        errorPrint("fieldInBuffer could not find tag %d newtext %s", tagno,
4615
 
           newtext);
 
4596
        i_printfExit(MSG_NoTagFound, tagno, newtext);
4616
4597
}                               /* updateFieldInBuffer */
4617
4598
 
4618
4599
/* This is the inverse of the above function, fetch instead of update. */