unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
blob d763769a18a9ba9e4a15662e9292d6933b30d4df 95075 bytes (raw)
name: lisp/textmodes/reftex.el 	 # note: path name is non-authoritative(*)

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
 
;;; reftex.el --- minor mode for doing \label, \ref, \cite, \index in LaTeX
;; Copyright (C) 1997-2000, 2003-2019 Free Software Foundation, Inc.

;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
;; Keywords: tex

;; This file is part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; RefTeX is a minor mode with distinct support for \ref, \label, \cite,
;; and \index commands in (multi-file) LaTeX documents.
;; - A table of contents provides easy access to any part of a document.
;; - Labels are created semi-automatically.
;; - Definition context of labels is provided when creating a reference.
;; - Citations are simplified with efficient database lookup.
;; - Text phrases can be collected in a file, for later global indexing.
;; - The index preview buffer helps to check and edit index entries.
;;
;; There is an extensive Texinfo document describing RefTeX in detail.
;; One way to view this documentation is `M-x reftex-info RET'.
;;
;; The documentation in various formats is also available at
;;
;;     https://www.gnu.org/software/auctex/manual/reftex.index.html
;;
;; RefTeX is bundled with Emacs and available as a plug-in package for
;; XEmacs 21.x.  If you need to install it yourself, you can find a
;; distribution at
;;
;;    https://www.gnu.org/software/auctex/reftex.html
;;
;; RefTeX was written by Carsten Dominik <dominik@science.uva.nl> with
;; contributions from Stephen Eglen.  It is currently maintained by
;; the AUCTeX project.

;;; Code:

(eval-when-compile (require 'cl-lib))

;; Stuff that needs to be there when we use defcustom
(require 'custom)

(require 'easymenu)

(defvar reftex-tables-dirty t
  "Flag showing if tables need to be re-computed.")

(eval-and-compile
  (defun reftex-set-dirty (symbol value)
    (setq reftex-tables-dirty t)
    (set symbol value)))


;; Configuration variables
(require 'reftex-vars)


;;; Autoloads to ensure loading of support files when necessary
(require 'reftex-loaddefs)

;; We autoload tons of functions from these files, but some have
;; a single function that needs to be globally autoloaded.
;; The alternative is to use a Makefile rule + distinct autoload
;; cookie (eg ;;;###reftex-autoload) for internal autoloads,
;; as eg calendar/ does.  But that seemed like overkill for 4 functions.

;;;###autoload(autoload 'reftex-citation "reftex-cite" nil t)
;;;###autoload(autoload 'reftex-all-document-files "reftex-parse")
;;;###autoload(autoload 'reftex-isearch-minor-mode "reftex-global" nil t)
;;;###autoload(autoload 'reftex-index-phrases-mode "reftex-index" nil t)

;; Generated functions.
(autoload 'reftex-varioref-vref "reftex-ref"
  "Make a varioref reference." t)
(autoload 'reftex-fancyref-fref "reftex-ref"
  "Make a fancyref \\fref reference." t)
(autoload 'reftex-fancyref-Fref "reftex-ref"
  "Make a fancyref \\Fref reference." t)

;;; =========================================================================
;;;
;;; Define the formal stuff for a minor mode named RefTeX.
;;;

(defconst reftex-version emacs-version
  "Version string for RefTeX.")

(defvar reftex-mode-map
  (let ((map (make-sparse-keymap)))
    ;; The default bindings in the mode map.
    (define-key map "\C-c=" 'reftex-toc)
    (define-key map "\C-c-" 'reftex-toc-recenter)
    (define-key map "\C-c(" 'reftex-label)
    (define-key map "\C-c)" 'reftex-reference)
    (define-key map "\C-c[" 'reftex-citation)
    (define-key map "\C-c<" 'reftex-index)
    (define-key map "\C-c>" 'reftex-display-index)
    (define-key map "\C-c/" 'reftex-index-selection-or-word)
    (define-key map "\C-c\\" 'reftex-index-phrase-selection-or-word)
    (define-key map "\C-c|" 'reftex-index-visit-phrases-buffer)
    (define-key map "\C-c&" 'reftex-view-crossref)

    ;; Bind `reftex-mouse-view-crossref' only when the key is still free
    (if (featurep 'xemacs)
        (unless (key-binding [(shift button2)])
          (define-key map [(shift button2)] 'reftex-mouse-view-crossref))
      (unless (key-binding [(shift mouse-2)])
        (define-key map [(shift mouse-2)] 'reftex-mouse-view-crossref)))

    ;; For most of these commands there are already bindings in place.
    ;; Setting `reftex-extra-bindings' really is only there to spare users
    ;; the hassle of defining bindings in the user space themselves.  This
    ;; is why they violate the key binding recommendations.
    (when reftex-extra-bindings
      (define-key map "\C-ct" 'reftex-toc)
      (define-key map "\C-cl" 'reftex-label)
      (define-key map "\C-cr" 'reftex-reference)
      (define-key map "\C-cc" 'reftex-citation)
      (define-key map "\C-cv" 'reftex-view-crossref)
      (define-key map "\C-cg" 'reftex-grep-document)
      (define-key map "\C-cs" 'reftex-search-document))

    map)
  "Keymap for RefTeX mode.")

(defvar reftex-mode-menu nil)
(defvar reftex-syntax-table nil)
(defvar reftex-syntax-table-for-bib nil)

(defun reftex--prepare-syntax-tables ()
  (setq reftex-syntax-table (copy-syntax-table))
  (modify-syntax-entry ?\( "." reftex-syntax-table)
  (modify-syntax-entry ?\) "." reftex-syntax-table)

  (setq reftex-syntax-table-for-bib (copy-syntax-table))
  (modify-syntax-entry ?\' "." reftex-syntax-table-for-bib)
  (modify-syntax-entry ?\" "." reftex-syntax-table-for-bib)
  (modify-syntax-entry ?\[ "." reftex-syntax-table-for-bib)
  (modify-syntax-entry ?\] "." reftex-syntax-table-for-bib)
  (modify-syntax-entry ?\( "." reftex-syntax-table-for-bib)
  (modify-syntax-entry ?\) "." reftex-syntax-table-for-bib))

(unless (and reftex-syntax-table reftex-syntax-table-for-bib)
  (reftex--prepare-syntax-tables))

;; The following definitions are out of place, but I need them here
;; to make the compilation of reftex-mode not complain.
(defvar reftex-auto-view-crossref-timer nil
  "The timer used for auto-view-crossref.")
(defvar reftex-toc-auto-recenter-timer nil
  "The idle timer used to recenter the toc window.")

;;;###autoload
(defun turn-on-reftex ()
  "Turn on RefTeX mode."
  (reftex-mode t))

(put 'reftex-mode :included '(memq major-mode '(latex-mode tex-mode)))
(put 'reftex-mode :menu-tag "RefTeX Mode")
;;;###autoload
(define-minor-mode reftex-mode
  "Minor mode with distinct support for \\label, \\ref and \\cite in LaTeX.

\\<reftex-mode-map>A Table of Contents of the entire (multifile) document with browsing
capabilities is available with `\\[reftex-toc]'.

Labels can be created with `\\[reftex-label]' and referenced with `\\[reftex-reference]'.
When referencing, you get a menu with all labels of a given type and
context of the label definition.  The selected label is inserted as a
\\ref macro.

Citations can be made with `\\[reftex-citation]' which will use a regular expression
to pull out a *formatted* list of articles from your BibTeX
database.  The selected citation is inserted as a \\cite macro.

Index entries can be made with `\\[reftex-index-selection-or-word]' which indexes the word at point
or the current selection.  More general index entries are created with
`\\[reftex-index]'.  `\\[reftex-display-index]' displays the compiled index.

Most command have help available on the fly.  This help is accessed by
pressing `?' to any prompt mentioning this feature.

Extensive documentation about RefTeX is available in Info format.
You can view this information with `\\[reftex-info]'.

\\{reftex-mode-map}
Under X, these and other functions will also be available as `Ref' menu
on the menu bar.

------------------------------------------------------------------------------"
  :lighter " Ref" :keymap reftex-mode-map
  (if reftex-mode
      (progn
        ;; Mode was turned on
        (easy-menu-add reftex-mode-menu)
        (and reftex-plug-into-AUCTeX
             (reftex-plug-into-AUCTeX))
        (unless (get 'reftex-auto-view-crossref 'initialized)
          (and reftex-auto-view-crossref
               (reftex-toggle-auto-view-crossref))
          (put 'reftex-auto-view-crossref 'initialized t))
        (unless (get 'reftex-auto-recenter-toc 'initialized)
          (and (eq reftex-auto-recenter-toc t)
               (reftex-toggle-auto-toc-recenter))
          (put 'reftex-auto-recenter-toc 'initialized t))

        ;; Prepare the special syntax tables.
	(reftex--prepare-syntax-tables)

        (run-hooks 'reftex-mode-hook))
    ;; Mode was turned off
    (easy-menu-remove reftex-mode-menu)))

(defvar reftex-docstruct-symbol)
(defun reftex-kill-buffer-hook ()
  "Save RefTeX's parse file for this buffer if the information has changed."
  ;; Save the parsing information if it was modified.
  ;; This function should be installed in `kill-buffer-hook'.
  ;; We are careful to make sure nothing goes wrong in this function.
  (when (and (boundp 'reftex-mode)  reftex-mode
             (boundp 'reftex-save-parse-info)  reftex-save-parse-info
             (boundp 'reftex-docstruct-symbol)  reftex-docstruct-symbol
             (symbol-value reftex-docstruct-symbol)
             (get reftex-docstruct-symbol 'modified))
    ;; Write the file.
    (condition-case nil
        (reftex-access-parse-file 'write)
      (error nil))))

(defun reftex-kill-emacs-hook ()
  "Call `reftex-kill-buffer-hook' on all buffers."
  ;; This function should be installed in `kill-emacs-hook'.
  (save-excursion
    (mapcar (lambda (buf)
              (set-buffer buf)
              (reftex-kill-buffer-hook))
            (buffer-list))))

;;; =========================================================================
;;;
;;; Silence warnings about variables in other packages.
(defvar TeX-master)
(defvar LaTeX-section-hook)
(defvar LaTeX-label-function)
(defvar tex-main-file)
(defvar outline-minor-mode)
(defvar font-lock-mode)
(defvar font-lock-keywords)
(defvar font-lock-fontify-region-function)

;;; =========================================================================
;;;
;;; Multibuffer Variables
;;;
;; Technical notes: These work as follows: We keep just one list
;; of labels for each master file - this can save a lot of memory.
;; `reftex-master-index-list' is an alist which connects the true file name
;; of each master file with the symbols holding the information on that
;; document.  Each buffer has local variables which point to these symbols.

;; List of variables which handle the multifile stuff.
;; This list is used to tie, untie, and reset these symbols.
(defconst reftex-multifile-symbols
  '(reftex-docstruct-symbol))

;; Alist connecting master file names with the corresponding lisp symbols.
(defvar reftex-master-index-list nil)

;; Last index used for a master file.
(defvar reftex-multifile-index 0)

;; Variable holding the symbol with the label list of the document.
(defvar reftex-docstruct-symbol nil)
(make-variable-buffer-local 'reftex-docstruct-symbol)

(defun reftex-next-multifile-index ()
  ;; Return the next free index for multifile symbols.
  (cl-incf reftex-multifile-index))

(defun reftex-tie-multifile-symbols ()
  "Tie the buffer-local symbols to globals connected with the master file.
If the symbols for the current master file do not exist, they are created."
  (let* ((master (file-truename (reftex-TeX-master-file)))
         (index (assoc master reftex-master-index-list))
         (symlist reftex-multifile-symbols)
         symbol symname newflag)
    ;; Find the correct index.
    (if index
        ;; Symbols do exist
        (setq index (cdr index))
      ;; Get a new index and add info to the alist.
      (setq index (reftex-next-multifile-index)
            newflag t)
      (push (cons master index) reftex-master-index-list))

    ;; Get/create symbols and tie them.
    (while symlist
      (setq symbol (car symlist)
            symlist (cdr symlist)
            symname (symbol-name symbol))
      (set symbol (intern (concat symname "-" (int-to-string index))))
      (put (symbol-value symbol) :master-index index)
      ;; Initialize if new symbols.
      (when newflag
        (set (symbol-value symbol) nil)
        (put (symbol-value symbol) 'reftex-index-macros-style '(default))
	(put (symbol-value symbol) 'reftex-ref-style-list
	     reftex-ref-style-default-list)))

    ;; Return t if the symbols did already exist, nil when we've made them.
    (not newflag)))

(defun reftex-untie-multifile-symbols ()
  "Remove ties from multifile symbols, so that next use makes new ones."
  (let ((symlist reftex-multifile-symbols)
        (symbol nil))
    (while symlist
      (setq symbol  (car symlist)
            symlist (cdr symlist))
      (set symbol nil))))

(defun reftex-TeX-master-file ()
  ;; Return the name of the master file associated with the current buffer.
  ;; When AUCTeX is loaded, we will use it's more sophisticated method.
  ;; We also support the default TeX and LaTeX modes by checking for a
  ;; variable tex-main-file.
  (let
      ((master
        (cond
	 ;; Test if we're in a subfile using the subfiles document
	 ;; class, e.g., \documentclass[main.tex]{subfiles}.  It's
	 ;; argument is the main file, however it's not really the
	 ;; master file in `TeX-master-file' or `tex-main-file's
	 ;; sense.  It should be used for references but not for
	 ;; compilation, thus subfiles use a setting of
	 ;; `TeX-master'/`tex-main-file' being themselves.
	 ((save-excursion
            (goto-char (point-min))
            (re-search-forward
             "^[[:space:]]*\\\\documentclass\\[\\([^]]+\\)\\]{subfiles}"
             nil t))
          (match-string-no-properties 1))
         ;; AUCTeX is loaded.  Use its mechanism.
         ((fboundp 'TeX-master-file)
          (condition-case nil
              (TeX-master-file t)
            (error (buffer-file-name))))
         ;; Emacs LaTeX mode
         ((fboundp 'tex-main-file) (tex-main-file))
         ;; Check the `TeX-master' variable.
         ((boundp 'TeX-master)
          (cond
           ((eq TeX-master t)
            (buffer-file-name))
           ((eq TeX-master 'shared)
            (setq TeX-master (read-file-name "Master file: "
                                             nil nil t nil)))
           (TeX-master)
           (t
            (setq TeX-master (read-file-name "Master file: "
                                             nil nil t nil)))))
         ;; Check the `tex-main-file' variable.
         ((boundp 'tex-main-file)
          ;; This is the variable from the default TeX modes.
          (cond
           ((stringp tex-main-file)
            ;; ok, this must be it
            tex-main-file)
           (t
            ;; In this case, the buffer is its own master.
            (buffer-file-name))))
         ;; We know nothing about master file.  Assume this is a
         ;; master file.
         (t
          (buffer-file-name)))))
    (cond
     ((null master)
      (error "Need a filename for this buffer,  please save it first"))
     ((or (file-exists-p (concat master ".tex"))
          (reftex-get-buffer-visiting (concat master ".tex")))
      ;; Ahh, an extra .tex was missing...
      (setq master (concat master ".tex")))
     ((or (file-exists-p master)
          (reftex-get-buffer-visiting master))
      ;; We either see the file, or have a buffer on it.  OK.
      )
     (t
      ;; Use buffer file name.
      (setq master (buffer-file-name))))
    (expand-file-name master)))

(defun reftex-is-multi ()
  ;; Tell if this is a multifile document.  When not sure, say yes.
  (let ((entry (assq 'is-multi (symbol-value reftex-docstruct-symbol))))
    (if entry
        (nth 1 entry)
      t)))

(defun reftex-set-cite-format (value)
  "Set the document-local value of `reftex-cite-format'.
When such a value exists, it overwrites the setting given with
`reftex-cite-format'.  See the documentation of `reftex-cite-format'
for possible values.  This function should be used from AUCTeX style files."
  (unless reftex-docstruct-symbol
    (reftex-tie-multifile-symbols))
  (when (and reftex-docstruct-symbol
             (symbolp reftex-docstruct-symbol))
    (put reftex-docstruct-symbol 'reftex-cite-format value)))

(defun reftex-get-cite-format ()
  ;; Return the current citation format.  Either the document-local value in
  ;; reftex-cite-format-symbol, or the global value in reftex-cite-format.
  (if (and reftex-docstruct-symbol
           (symbolp reftex-docstruct-symbol)
           (get reftex-docstruct-symbol 'reftex-cite-format))
      (get reftex-docstruct-symbol 'reftex-cite-format)
    reftex-cite-format))

(defun reftex-add-index-macros (entry-list)
  "Add index macro descriptions to `reftex-index-macros-style'.
The format of ENTRY-LIST is exactly like `reftex-index-macros'.  See there
for details.
This function makes it possible to support RefTeX from AUCTeX style files.
The entries in ENTRY-LIST will be processed after the user settings in
`reftex-index-entries', and before the defaults.  Any changes made to
`reftex-index-macros-style' will raise a flag to the effect that
the label information is recompiled on next use."
  (unless reftex-docstruct-symbol
    (reftex-tie-multifile-symbols))
  (when (and reftex-docstruct-symbol
             (symbolp reftex-docstruct-symbol))
    (let ((list (get reftex-docstruct-symbol 'reftex-index-macros-style))
          entry changed)
      (while entry-list
        (setq entry (pop entry-list))
        ;; When it is a symbol, remove all other symbols
        (and (symbolp entry)
             (not (memq entry list))
             (setq list (reftex-remove-symbols-from-list list)))
        ;; Add to list unless already member
        (unless (member entry list)
          (setq reftex-tables-dirty t
                changed t)
          (push entry list)))
      (when changed
        (put reftex-docstruct-symbol 'reftex-index-macros-style list)))))

(defun reftex-ref-style-activate (style)
  "Activate the referencing style STYLE."
  (reftex-ref-style-toggle style 'activate))

(defun reftex-ref-style-toggle (style &optional action)
  "Activate or deactivate the referencing style STYLE.
With the optional argument ACTION a certain action can be forced.
The symbol `activate' will activate the style and `deactivate'
will deactivate it."
  (unless reftex-docstruct-symbol
    (reftex-tie-multifile-symbols))
  (when (and reftex-docstruct-symbol
             (symbolp reftex-docstruct-symbol))
    (let ((list (get reftex-docstruct-symbol 'reftex-ref-style-list))
          changed)
      (cond ((eq action 'activate)
	     (unless (member style list)
	       (setq reftex-tables-dirty t
		     changed t)
               (setq list (append list (list style)))))
	    ((eq action 'deactivate)
	     (when (member style list)
	       (setq reftex-tables-dirty t
		     changed t)
	       (setq list (delete style list))))
	    (t
	     (if (member style list)
		 (delete style list)
	       (setq list (append list (list style))))
	     (setq reftex-tables-dirty t
		   changed t)))
      (when changed
        (put reftex-docstruct-symbol 'reftex-ref-style-list list)))))

(defun reftex-ref-style-list ()
  "Return the list of referencing styles to be active at the moment."
  ;; Initialize the value of `reftex-ref-style-list' and tie it to the
  ;; docstruct symbol if necessary.
  (unless reftex-docstruct-symbol
    (reftex-tie-multifile-symbols))
  (if (and reftex-docstruct-symbol
           (symbolp reftex-docstruct-symbol)
           (get reftex-docstruct-symbol 'reftex-ref-style-list))
      (get reftex-docstruct-symbol 'reftex-ref-style-list)
    reftex-ref-style-default-list))

;;; =========================================================================
;;;
;;; Functions to compile the tables, reset the mode etc.

;; The following constants are derived from `reftex-label-alist'.

;; Prompt used for label type queries directed to the user.
(defvar reftex-type-query-prompt nil)

;; Help string for label type queries.
(defvar reftex-type-query-help nil)

;; Alist relating label type to reference format.
(defvar reftex-typekey-to-format-alist nil)

;; Alist relating label type to label prefix.
(defvar reftex-typekey-to-prefix-alist nil)

;; Alist relating environments or macros to label type and context regexp.
(defvar reftex-env-or-mac-alist nil)

;; List of special environment parser functions
(defvar reftex-special-env-parsers nil)

;; List of macros carrying a label.
(defvar reftex-label-mac-list nil)

;; List of environments carrying a label.
(defvar reftex-label-env-list nil)

;; List of all typekey letters in use.
(defvar reftex-typekey-list nil)

;; Alist relating magic words to a label type.
(defvar reftex-words-to-typekey-alist nil)
;; Alist relating label prefixes to a label type.
(defvar reftex-prefix-to-typekey-alist nil)

;; The last list-of-labels entry used in a reference.
(defvar reftex-last-used-reference (list nil nil nil nil))

;; Alist relating index macros to other info.
(defvar reftex-key-to-index-macro-alist nil)
;; Prompt for index macro queries
(defvar reftex-query-index-macro-prompt nil)
;; Help string for index macro queries
(defvar reftex-query-index-macro-help nil)

;; The message when follow-mode is suspended
(defvar reftex-no-follow-message
  "No follow-mode into unvisited file.  Press SPC to visit it.")
(defvar reftex-no-info-message
  "%s: info not available, use `\\[reftex-view-crossref]' to get it.")

;; Global variables used for communication between functions.
(defvar reftex-default-context-position nil)
(defvar reftex-location-start nil)
(defvar reftex-call-back-to-this-buffer nil)
(defvar reftex-select-return-marker (make-marker))
(defvar reftex-active-toc nil)
(defvar reftex-tex-path nil)
(defvar reftex-bib-path nil)
(defvar reftex-select-marked nil)
(defvar reftex-last-follow-point nil)
(defvar reftex-latex-syntax-table nil)
(defvar reftex-prefix nil)
(defvar reftex-section-levels-all nil)
(defvar reftex-buffers-with-changed-invisibility nil)
(defvar reftex-callback-fwd t)
(defvar reftex-last-toc-master nil
  "Stores the name of the tex file that `reftex-toc' was last run on.")
;; Marker for return point from recursive edit
(defvar reftex-recursive-edit-marker (make-marker))

;; List of buffers created temporarily for lookup, which should be killed.
(defvar reftex-buffers-to-kill nil)

;; Regexp to find anything.
(defvar reftex-section-regexp nil)
(defvar reftex-section-or-include-regexp nil)
(defvar reftex-index-macro-regexp nil)
(defvar reftex-index-level-re nil)
(defvar reftex-index-key-end-re nil)
(defvar reftex-find-index-entry-regexp-format nil)
(defvar reftex-everything-regexp nil)
(defvar reftex-everything-regexp-no-index nil)
(defvar reftex-index-re nil)
(defvar reftex-find-citation-regexp-format
  "\\\\\\([a-zA-Z]*cite[*a-zA-Z]*\\*?\\|bibentry\\)\\(\\[[^]]*\\]\\|{[^}]*}\\)*{\\([^}]*,\\)?\\(%s\\)[},]")
(defvar reftex-find-reference-format
  "\\\\\\(ref[a-zA-Z]*\\|[a-zA-Z]*ref\\(range\\)?\\)\\*?\\(\\[[^]]*\\]\\|{[^}]*}\\)*{\\(%s\\)}")
(defvar reftex-macros-with-labels nil)
(defvar reftex-macros-with-index nil)
(defvar reftex-index-macro-alist nil)
(defvar reftex-find-label-regexp-format nil)
(defvar reftex-find-label-regexp-format2 nil)

;; Constants for making RefTeX open to Texinfo hooking
(defvar reftex-section-pre-regexp "\\\\")
;; Including `\' as a character to be matched at the end of the regexp
;; will allow stuff like \begin{foo}\label{bar} to be matched.  This
;; will make the parser to advance one char too much.  Therefore
;; `reftex-parse-from-file' will step one char back if a section is
;; found.
(defvar reftex-section-post-regexp "\\*?\\(\\[[^]]*\\]\\)?[[{ \t\r\n\\]")
(defvar reftex-section-info-function 'reftex-section-info)

(defvar reftex-memory nil
  "Memorizes old variable values to indicate changes in these variables.")

;; A list of all variables in the cache.
;; The cache is used to save the compiled versions of some variables.
(defconst reftex-cache-variables
  '(reftex-memory ;; This MUST ALWAYS be the first!

    ;; Outline
    reftex-section-levels-all

    ;; Labels
    reftex-env-or-mac-alist
    reftex-special-env-parsers
    reftex-macros-with-labels
    reftex-label-mac-list
    reftex-label-env-list
    reftex-typekey-list
    reftex-typekey-to-format-alist
    reftex-typekey-to-prefix-alist
    reftex-words-to-typekey-alist
    reftex-prefix-to-typekey-alist
    reftex-type-query-prompt
    reftex-type-query-help

    ;; Index
    reftex-index-macro-alist
    reftex-macros-with-index
    reftex-query-index-macro-prompt
    reftex-query-index-macro-help
    reftex-key-to-index-macro-alist

    ;; Regular expressions
    reftex-section-regexp
    reftex-section-or-include-regexp
    reftex-index-re
    reftex-everything-regexp
    reftex-everything-regexp-no-index
    reftex-find-label-regexp-format
    reftex-find-label-regexp-format2
    reftex-find-index-entry-regexp-format
))

(defun reftex-ensure-compiled-variables ()
  ;; Recompile the label alist when necessary
  (let* ((mem reftex-memory)
         (cache (get reftex-docstruct-symbol 'reftex-cache))
         (cmem  (car cache))
         (alist reftex-label-alist)
         (levels (get reftex-docstruct-symbol 'reftex-section-levels))
         (style (get reftex-docstruct-symbol 'reftex-label-alist-style))
         (default reftex-default-label-alist-entries)
         (index reftex-index-macros)
         (istyle (get reftex-docstruct-symbol 'reftex-index-macros-style)))
    (cond
     (reftex-tables-dirty (reftex-compile-variables))
     ((and (eq alist   (nth 0 mem))
           (eq levels  (nth 1 mem))
           (eq style   (nth 2 mem))
           (eq default (nth 3 mem))
           (eq index   (nth 4 mem))
           (eq istyle  (nth 5 mem))))  ;; everything is OK
     ((and (eq alist   (nth 0 cmem))
           (eq levels  (nth 1 cmem))
           (eq style   (nth 2 cmem))
           (eq default (nth 2 cmem))
           (eq index   (nth 4 cmem))
           (eq istyle  (nth 5 cmem)))
      ;; restore the cache
      (message "Restoring cache")
      (mapcar (lambda (sym) (set sym (pop cache))) reftex-cache-variables))
     (t (reftex-compile-variables)))))

(defun reftex-reset-mode ()
  "Reset RefTeX Mode.
This will re-compile the configuration information and remove all
current scanning information and the parse file to enforce a rescan
on next use."
  (interactive)

  ;; Reset the file search path variables
  (dolist (prop '(status master-dir recursive-path rec-type))
    (put 'reftex-tex-path prop nil)
    (put 'reftex-bib-path prop nil))

  ;; Kill temporary buffers associated with RefTeX - just in case they
  ;; were not cleaned up properly
  (save-excursion
    (let ((buffer-list '("*RefTeX Help*" "*RefTeX Select*"
                         "*Duplicate Labels*" "*toc*" " *RefTeX-scratch*"))
          buf)
      (while (setq buf (pop buffer-list))
        (if (get-buffer buf)
            (kill-buffer buf))))
    (reftex-erase-all-selection-and-index-buffers))

  ;; Make sure the current document will be rescanned soon.
  (reftex-reset-scanning-information)

  ;; Remove any parse info file
  (reftex-access-parse-file 'kill)

  ;; Plug functions into AUCTeX if the user option says so.
  (and reftex-plug-into-AUCTeX
       (reftex-plug-into-AUCTeX))

  (reftex-compile-variables))

;;;###autoload
(defun reftex-reset-scanning-information ()
  "Reset the symbols containing information from buffer scanning.
This enforces rescanning the buffer on next use."
  (if (string= reftex-last-toc-master (reftex-TeX-master-file))
      (reftex-erase-buffer "*toc*"))
  (let ((symlist reftex-multifile-symbols)
        symbol)
    (while symlist
      (setq symbol (car symlist)
            symlist (cdr symlist))
      (if (and (symbolp (symbol-value symbol))
               (not (null (symbol-value symbol))))
          (set (symbol-value symbol) nil)))))

(defun reftex-erase-all-selection-and-index-buffers ()
  ;; Remove all selection buffers associated with current document.
  (mapc
   (lambda (type)
     (reftex-erase-buffer (reftex-make-selection-buffer-name type)))
   reftex-typekey-list)
  ;; Kill all index buffers
  (mapc
   (lambda (tag)
     (reftex-kill-buffer (reftex-make-index-buffer-name tag)))
   (cdr (assoc 'index-tags (symbol-value reftex-docstruct-symbol)))))

(defun reftex-compile-variables ()
  ;; Compile the information in reftex-label-alist & Co.

  (message "Compiling label environment definitions...")

  ;; Update AUCTeX style information
  (when (and (featurep 'tex-site) (fboundp 'TeX-update-style))
    (condition-case nil (TeX-update-style) (error nil)))

  ;; Record that we have done this, and what we have used.
  (setq reftex-tables-dirty nil)
  (setq reftex-memory
        (list reftex-label-alist
              (get reftex-docstruct-symbol 'reftex-section-levels)
              (get reftex-docstruct-symbol 'reftex-label-alist-style)
              reftex-default-label-alist-entries
              reftex-index-macros
              (get reftex-docstruct-symbol 'reftex-index-macros-style)))

  ;; Compile information in reftex-label-alist
  (let ((all (reftex-uniquify-by-car
              (reftex-splice-symbols-into-list
               (append reftex-label-alist
                       (get reftex-docstruct-symbol
                            'reftex-label-alist-style)
                       reftex-default-label-alist-entries)
               reftex-label-alist-builtin)
              '(nil)))
        (all-index (reftex-uniquify-by-car
                    (reftex-splice-symbols-into-list
                     (append reftex-index-macros
                             (get reftex-docstruct-symbol
                                  'reftex-index-macros-style)
                             '(default))
                     reftex-index-macros-builtin)))
        entry env-or-mac typekeychar typekey prefix context word
        fmt reffmt labelfmt wordlist qh-list macros-with-labels
        nargs nlabel opt-args cell sum i
        macro verify repeat nindex tag key toc-level toc-levels)

    (setq reftex-words-to-typekey-alist nil
          reftex-prefix-to-typekey-alist
          '(("sec:" . "s") ("cha:" . "s") ("chap:" . "s"))
          reftex-typekey-list nil
          reftex-typekey-to-format-alist nil
          reftex-typekey-to-prefix-alist nil
          reftex-env-or-mac-alist nil
          reftex-label-env-list nil
          reftex-label-mac-list nil)
    (while all
      (catch 'next-entry
        (setq entry (car all)
              env-or-mac (car entry)
              entry (cdr entry)
              all (cdr all))
        (if (null env-or-mac)
            (setq env-or-mac ""))
        (if (stringp (car entry))
            ;; This is before version 2.00 - convert entry to new format
            ;; This is just to keep old users happy
            (setq entry (cons (string-to-char (car entry))
                              (cons (concat (car entry) ":")
                                    (cdr entry)))))
        (setq typekeychar (nth 0 entry)
              typekey (if typekeychar (char-to-string typekeychar) nil)
              prefix (nth 1 entry)
              fmt (nth 2 entry)
              context (nth 3 entry)
              wordlist (nth 4 entry)
              toc-level (nth 5 entry))
        (if (stringp wordlist)
            ;; This is before version 2.04 - convert to new format
            (setq wordlist (nthcdr 4 entry)))

        (if (and (stringp fmt)
                 (string-match "@" fmt))
            ;; Special syntax for specifying a label format
            (setq fmt (split-string fmt "@+"))
          (setq fmt (list "\\label{%s}" fmt)))
        (setq labelfmt (car fmt)
              reffmt (nth 1 fmt))
        ;; Note a new typekey
        (if typekey
            (cl-pushnew typekey reftex-typekey-list :test #'equal))
        (if (and typekey prefix
                 (not (assoc prefix reftex-prefix-to-typekey-alist)))
            (cl-pushnew (cons prefix typekey) reftex-prefix-to-typekey-alist
                        :test #'equal))
        (if (and typekey prefix
                 (not (assoc typekey reftex-typekey-to-prefix-alist)))
            (cl-pushnew (cons typekey prefix) reftex-typekey-to-prefix-alist
                        :test #'equal))
        ;; Check if this is a macro or environment
        (cond
         ((symbolp env-or-mac)
          ;; A special parser function
          (unless (fboundp env-or-mac)
            (message "Warning: %s does not seem to be a valid function"
                     env-or-mac))
          (setq nargs nil nlabel nil opt-args nil)
          (cl-pushnew env-or-mac reftex-special-env-parsers)
          (setq env-or-mac (symbol-name env-or-mac)))
         ((string-match "\\`\\\\" env-or-mac)
          ;; It's a macro
          (let ((result (reftex-parse-args env-or-mac)))
            (setq env-or-mac (or (cl-first result) env-or-mac)
                  nargs (cl-second result)
                  nlabel (cl-third result)
                  opt-args (cl-fourth result))
            (if nlabel (cl-pushnew env-or-mac macros-with-labels :test #'equal)))
          (if typekey (cl-pushnew env-or-mac reftex-label-mac-list :test #'equal)))
         (t
          ;; It's an environment
          (setq nargs nil nlabel nil opt-args nil)
          (cond ((string= env-or-mac "any"))
                ((string= env-or-mac ""))
                ((string= env-or-mac "section"))
                (t
                 (cl-pushnew env-or-mac reftex-label-env-list :test #'equal)
                 (if toc-level
                     (let ((string (format "begin{%s}" env-or-mac)))
                       (or (assoc string toc-levels)
                           (push (cons string toc-level) toc-levels))))))))
        ;; Translate some special context cases
        (when (assq context reftex-default-context-regexps)
          (setq context
                (format
                 (cdr (assq context reftex-default-context-regexps))
                 (regexp-quote env-or-mac))))
        ;; See if this is the first format for this typekey
        (and reffmt
             (not (assoc typekey reftex-typekey-to-format-alist))
             (push (cons typekey reffmt) reftex-typekey-to-format-alist))
        ;; See if this is the first definition for this env-or-mac
        (and (not (string= env-or-mac "any"))
             (not (string= env-or-mac ""))
             (not (assoc env-or-mac reftex-env-or-mac-alist))
             (push (list env-or-mac typekey context labelfmt
                         nargs nlabel opt-args)
                   reftex-env-or-mac-alist))
        ;; Are the magic words regular expressions?  Quote normal words.
        (if (eq (car wordlist) 'regexp)
            (setq wordlist (cdr wordlist))
          (setq wordlist (mapcar 'regexp-quote wordlist)))
        ;; Remember the first association of each word.
        (while (stringp (setq word (pop wordlist)))
          (or (assoc word reftex-words-to-typekey-alist)
              (push (cons word typekey) reftex-words-to-typekey-alist)))
        (cond
         ((string= "" env-or-mac) nil)
         ((setq cell (assoc typekey qh-list))
          (push env-or-mac (cdr cell)))
         (typekey
          (push (list typekey env-or-mac) qh-list)))))

    (setq reftex-typekey-to-prefix-alist
          (nreverse reftex-typekey-to-prefix-alist))

    ;; Prepare the typekey query prompt and help string.
    (setq qh-list
          (sort qh-list
                (lambda (x1 x2)
                  (string< (downcase (car x1)) (downcase (car x2))))))
    (setq reftex-type-query-prompt
          (concat "Label type: ["
                  (mapconcat (lambda(x) (format "%s" (car x)))
                             qh-list "")
                  "]"))
    ;; In the help string, we need to wrap lines...
    (setq reftex-type-query-help
          (concat
           "SELECT A LABEL TYPE:\n--------------------\n"
           (mapconcat
            (lambda(x)
              (setq sum 0)
              (format " [%s]   %s"
                      (car x)
                      (mapconcat (lambda(env)
                                   (setq sum (+ sum (length env)))
                                   (if (< sum 60)
                                       env
                                     (setq sum 0)
                                     (concat "\n       " env)))
                                 (cdr x) " ")))
            qh-list "\n")))

    ;; Convert magic words to regular expressions.  We make regular expressions
    ;; which allow for some chars from the ref format to be in the buffer.
    ;; These characters will be seen and removed.
    (setq reftex-words-to-typekey-alist
          (mapcar
           (lambda (x)
             (setq word (car x)
                   typekey (cdr x)
                   fmt (cdr (assoc typekey reftex-typekey-to-format-alist)))
             (setq word (concat "\\W\\(" word "[ \t\n\r]*\\)\\("))
             (setq i 0)
             (while (and (< i 10)   ; maximum number of format chars allowed
                         (< i (length fmt))
                         (not (member (aref fmt i) '(?%))))
               (setq word (concat word "\\|" (regexp-quote
                                              (substring fmt 0 (1+ i)))))
               (cl-incf i))
             (cons (concat word "\\)\\=") typekey))
           (nreverse reftex-words-to-typekey-alist)))

    ;; Parse the index macros
    (setq reftex-index-macro-alist nil
          reftex-key-to-index-macro-alist nil
          reftex-macros-with-index nil)
    (while all-index
      (setq entry (car all-index)
            macro (car entry)
            tag (nth 1 entry)
            key (nth 2 entry)
            prefix (or (nth 3 entry) "")
            verify (nth 4 entry)
            ;; For repeat, we need to be compatible with older code
            ;; This information used to be given only for the default macro,
            ;; but later we required to have it for *every* index macro
            repeat (cond ((> (length entry) 5) (nth 5 entry))
                         ((and (eq key (car reftex-index-default-macro))
                               (> (length reftex-index-default-macro) 2))
                          ;; User has old setting - respect it
                          (nth 2 reftex-index-default-macro))
                         (t t))
            all-index (cdr all-index))
      (let ((result (reftex-parse-args macro)))
        (setq macro (or (cl-first result) macro)
              nargs (cl-second result)
              nindex (cl-third result)
              opt-args (cl-fourth result))
        (unless (member macro reftex-macros-with-index)
          ;;           0     1    2      3     4     5       6        7
          (push (list macro tag prefix verify nargs nindex opt-args repeat)
                reftex-index-macro-alist)
          (or (assoc key reftex-key-to-index-macro-alist)
              (push (list key macro) reftex-key-to-index-macro-alist))
          (push macro reftex-macros-with-index))))
    ;; Make the prompt and help string for index macros query
    (setq reftex-key-to-index-macro-alist
          (sort reftex-key-to-index-macro-alist
                (lambda (a b) (< (downcase (car a)) (downcase (car b))))))
    (setq reftex-query-index-macro-prompt
          (concat "Index macro: ["
                  (mapconcat (lambda (x) (char-to-string (car x)))
                             reftex-key-to-index-macro-alist "")
                  "]"))
    (setq i 0
          reftex-query-index-macro-help
          (concat
           "SELECT A MACRO:\n---------------\n"
           (mapconcat
            (lambda(x)
              (format "[%c] %-20.20s%s" (car x) (nth 1 x)
                      (if (= 0 (mod (cl-incf i) 3)) "\n" "")))
            reftex-key-to-index-macro-alist "")))

    ;; Make the full list of section levels
    (setq reftex-section-levels-all
          (append toc-levels
                  (get reftex-docstruct-symbol 'reftex-section-levels)
                  reftex-section-levels))

    ;; Calculate the regular expressions
    (let* (
;          (wbol "\\(\\`\\|[\n\r]\\)[ \t]*")
           (wbol "\\(^\\)%?[ \t]*") ; Need to keep the empty group because
                                    ; match numbers are hard coded
           (label-re (concat "\\(?:"
			     (mapconcat 'identity reftex-label-regexps "\\|")
			     "\\)"))
           (include-re (concat wbol
                               "\\\\\\("
                               (mapconcat 'identity
                                          reftex-include-file-commands "\\|")
                               "\\)[{ \t]+\\([^} \t\n\r]+\\)"))
           (section-re
            (concat wbol reftex-section-pre-regexp "\\("
                    (mapconcat (lambda (x) (regexp-quote (car x)))
                               reftex-section-levels-all "\\|")
                    "\\)" reftex-section-post-regexp))
           (appendix-re (concat wbol "\\(\\\\appendix\\)"))
           (macro-re
            (if macros-with-labels
                (concat "\\("
                        (mapconcat 'regexp-quote macros-with-labels "\\|")
                        "\\)[[{]")
              ""))
           (index-re
            (concat "\\("
                    (mapconcat 'regexp-quote reftex-macros-with-index "\\|")
                    "\\)[[{]"))
           (find-index-re-format
            (concat "\\("
                    (mapconcat 'regexp-quote reftex-macros-with-index "\\|")
                    "\\)\\([[{][^]}]*[]}]\\)*[[{]\\(%s\\)[]}]"))
           (find-label-re-format
            (concat "\\("
		    "label[[:space:]]*=[[:space:]]*"
		    "\\|"
                    (mapconcat 'regexp-quote (append '("\\label")
                                                     macros-with-labels) "\\|")
                    "\\)\\([[{][^]}]*[]}]\\)*[[{]\\(%s\\)[]}]"))
           (index-level-re
            (regexp-quote (nth 0 reftex-index-special-chars)))
           (index-key-end-re ;; ^]- not allowed
            (concat "[^" (nth 3 reftex-index-special-chars) "]"
                    "[" (nth 1 reftex-index-special-chars)
                    (nth 2 reftex-index-special-chars) "]"))
           )
      (setq reftex-section-regexp section-re
            reftex-section-or-include-regexp
            (concat section-re "\\|" include-re)
            reftex-everything-regexp
            (concat label-re "\\|" section-re "\\|" include-re
                    "\\|" appendix-re
                    "\\|" index-re
                    (if macros-with-labels "\\|" "") macro-re)
            reftex-everything-regexp-no-index
            (concat label-re "\\|" section-re "\\|" include-re
                    "\\|" appendix-re
                    "\\|" "\\(\\\\6\\\\3\\\\1\\)" ; This is unlikely to match
                    (if macros-with-labels "\\|" "") macro-re)
            reftex-index-re index-re
            reftex-index-level-re index-level-re
            reftex-index-key-end-re index-key-end-re
            reftex-macros-with-labels macros-with-labels
            reftex-find-index-entry-regexp-format find-index-re-format
            reftex-find-label-regexp-format find-label-re-format
            reftex-find-label-regexp-format2
            "\\([]} \t\n\r]\\)\\([[{]\\)\\(%s\\)[]}]")
      (message "Compiling label environment definitions...done")))
  (put reftex-docstruct-symbol 'reftex-cache
       (mapcar 'symbol-value reftex-cache-variables)))

(defun reftex-parse-args (macro)
  ;; Return a list of macro name, nargs, arg-nr which is label and a list of
  ;; optional argument indices.
  (if (string-match "[[{]\\*?[]}]" macro)
      (progn
        (let ((must-match (substring macro 0 (match-beginning 0)))
              (args (substring macro (match-beginning 0)))
              opt-list nlabel (cnt 0))
          (while (string-match "\\`[[{]\\(\\*\\)?[]}]" args)
            (cl-incf cnt)
            (when (eq ?\[ (string-to-char args))
              (push cnt opt-list))
            (when (and (match-end 1)
                       (not nlabel))
              (setq nlabel cnt))
            (setq args (substring args (match-end 0))))
          (list must-match cnt nlabel opt-list)))
    nil))

;;; =========================================================================
;;;
;;; Accessing the parse information

(defun reftex-access-scan-info (&optional rescan file)
  "Ensure access to the scanning info for the current file."
  ;; When the multifile symbols are not yet tied,
  ;; tie them.  When they are empty or RESCAN is non-nil, scan the document.
  ;; But, when RESCAN is -1, don't rescan even if docstruct is empty.
  ;; When FILE is non-nil, parse only from that file.

  ;; Error out in a buffer without a file.
  (if (and reftex-mode
	   (not (buffer-file-name)))
      (error "RefTeX works only in buffers visiting a file"))

  ;; Make sure we have the symbols tied
  (if (eq reftex-docstruct-symbol nil)
      ;; Symbols are not yet tied: Tie them.
      (reftex-tie-multifile-symbols))

  (reftex-ensure-compiled-variables)

  (when (or (null (symbol-value reftex-docstruct-symbol))
            (member rescan '(t 1 (4) (16))))
    ;; The docstruct will change: Remove selection buffers.
    (save-excursion
      (reftex-erase-buffer "*toc*")
      (reftex-erase-all-selection-and-index-buffers)))

  (if (and (null (symbol-value reftex-docstruct-symbol))
           (not (member rescan '(t 1 (4) (16))))
           reftex-save-parse-info)
      ;; Try to read the stuff from a file
      (reftex-access-parse-file 'read))

  (cond
   ((equal rescan -1))  ;; We are not allowed to scan.
   ((not (symbol-value reftex-docstruct-symbol))
    ;; Scan the whole document
    (reftex-do-parse 1 file))
   ((member rescan '(t 1 (4) (16)))
    ;; Scan whatever was required by the caller.
    (reftex-do-parse rescan file))))

(defun reftex-scanning-info-available-p ()
  "Is the scanning info about the current document available?"
  (unless reftex-docstruct-symbol
    (reftex-tie-multifile-symbols))
  (and (symbolp reftex-docstruct-symbol)
       (symbol-value reftex-docstruct-symbol)
       t))

(defun reftex-silence-toc-markers (list n)
  ;; Set all toc markers in the first N entries in list to nil
  (while (and list (> (cl-decf n) -1))
    (and (eq (car (car list)) 'toc)
         (markerp (nth 4 (car list)))
         (set-marker (nth 4 (car list)) nil))
    (pop list)))

(defun reftex-access-parse-file (action)
  "Perform ACTION on the parse file (the .rel file).
Valid actions are: readable, restore, read, kill, write."
  (let* ((list (symbol-value reftex-docstruct-symbol))
         (docstruct-symbol reftex-docstruct-symbol)
         (master (reftex-TeX-master-file))
         (enable-local-variables nil)
         (file (if (string-match "\\.[a-zA-Z]+\\'" master)
                   (concat (substring master 0 (match-beginning 0))
                           reftex-parse-file-extension)
                 (concat master reftex-parse-file-extension))))
    (cond
     ((eq action 'readable)
      (file-readable-p file))
     ((eq action 'restore)
      (put reftex-docstruct-symbol 'modified nil)
      (if (eq reftex-docstruct-symbol nil)
          ;; Symbols are not yet tied: Tie them.
          (reftex-tie-multifile-symbols))
      (if (file-exists-p file)
          ;; load the file and return t for success
          (condition-case nil
              (progn (load-file file) t)
            (error (set reftex-docstruct-symbol nil)
                   (error "Error while loading file %s" file)))
        ;; Throw an exception if the file does not exist
        (error "No restore file %s" file)))
     ((eq action 'read)
      (put reftex-docstruct-symbol 'modified nil)
      (if (file-exists-p file)
          ;; load the file and return t for success
          (condition-case nil
              (progn
                (load-file file)
                (reftex-check-parse-consistency)
                t)
            (error (message "Error while restoring file %s" file)
                   (set reftex-docstruct-symbol nil)
                   nil))
        ;; return nil for failure, but no exception
        nil))
     ((eq action 'kill)
      ;; Remove the file
      (when (and (file-exists-p file) (file-writable-p file))
        (message "Unlinking file %s" file)
        (delete-file file)))
     (t
      (put docstruct-symbol 'modified nil)
      (save-excursion
        (if (file-writable-p file)
            (with-temp-file file
              (message "Writing parse file %s" (abbreviate-file-name file))
              (insert (format ";; RefTeX parse info file\n"))
              (insert (format ";; File: %s\n" master))
              (insert (format ";; User: %s (%s)\n\n"
                              (user-login-name) (user-full-name)))
              (insert "(set reftex-docstruct-symbol '(\n\n")
              (let ((standard-output (current-buffer)))
                (mapc
                 (lambda (x)
                   (cond ((eq (car x) 'toc)
                          ;; A toc entry. Do not save the marker.
                          ;; Save the markers  position at position 8
                          (print (list 'toc "toc" (nth 2 x) (nth 3 x)
                                       nil (nth 5 x) (nth 6 x) (nth 7 x)
                                       (or (and (markerp (nth 4 x))
                                                (marker-position (nth 4 x)))
                                           (nth 8 x)))))
                         ((and (not (eq t reftex-support-index))
                               (eq (car x) 'index))
                          ;; Don't save index entries
                          )
                         (t (print x))))
                 list))
              (insert "))\n\n"))
          (error "Cannot write to file %s" file)))
      t))))

(defun reftex-check-parse-consistency ()
  ;; Check if parse file is consistent, throw an error if not.

  ;; Check if the master is the same: when moving a document, this will see it.
  (let* ((real-master (reftex-TeX-master-file))
         (parsed-master
          (nth 1 (assq 'bof (symbol-value reftex-docstruct-symbol)))))
    (unless (string= (file-truename real-master) (file-truename parsed-master))
      (message "Master file name in load file is different: %s versus %s"
               parsed-master real-master)
      (error "Master file name error")))

  ;; Check for the existence of all document files
;;;  (let* ((all (symbol-value reftex-docstruct-symbol)))
;;;    (while all
;;;      (when (and (eq (car (car all)) 'bof)
;;;              (not (file-regular-p (nth 1 (car all)))))
;;;     (message "File %s in saved parse info not available" (cdr (car all)))
;;;     (error "File not found"))
;;;      (setq all (cdr all))))
  )

(defun reftex-select-external-document (xr-alist xr-index)
  ;; Return index of an external document.
  (let* ((len (length xr-alist)) (highest (1- (+ ?0 len)))
         (prompt (format "[%c-%c] Select    TAB: Read prefix with completion"
                         ?0 highest))
         key prefix)
    (cond
     ((= len 1)
      (message "No external documents available")
      (ding) (sit-for 1) 0)
     ((= len 2)
      (- 1 xr-index))
     (t
      (save-excursion
        (let* ((length (apply 'max (mapcar
                                    (lambda(x) (length (car x))) xr-alist)))
               (fmt (format " [%%c]  %%-%ds  %%s\n" length))
               (n (1- ?0)))
          (setq key
                (reftex-select-with-char
                 prompt
                 (concat
                  "SELECT EXTERNAL DOCUMENT\n------------------------\n"
                  (mapconcat
                   (lambda (x)
                     (format fmt (cl-incf n) (or (car x) "")
                             (abbreviate-file-name (cdr x))))
                   xr-alist ""))
                 nil t))
          (cond
           ((and (>= key ?0) (<= key highest)) (- key ?0))
           ((= key ?\C-i)
            (setq prefix (completing-read "Prefix: " xr-alist nil t))
            (- len (length (memq (assoc prefix xr-alist) xr-alist))))
           (t (error "Invalid document selection [%c]" key)))))))))

;;; =========================================================================
;;;
;;; Finding files

(defun reftex-locate-file (file type master-dir &optional die)
  "Find FILE of type TYPE in MASTER-DIR or on the path associated with TYPE.
If the file does not have any of the valid extensions for TYPE,
try first the default extension and only then the naked file name.
When DIE is non-nil, throw an error if file not found."
  (let* ((rec-values (if reftex-search-unrecursed-path-first '(nil t) '(t)))
         (extensions (cdr (assoc type reftex-file-extensions)))
         (def-ext (car extensions))
         (ext-re (concat "\\("
                         (mapconcat 'regexp-quote extensions "\\|")
                         "\\)\\'"))
         (files (if (string-match ext-re file)
                    (cons file nil)
		  (if reftex-try-all-extensions
		      (append (mapcar (lambda (x) (concat file x))
				      extensions)
			      (list file))
		    (list (concat file def-ext) file))))
         path old-path file1 f fs)
    (cond
     ((file-name-absolute-p file)
      (while (setq f (pop files))
	(if (file-regular-p f)
	    (setq file1 f files nil))))
     ((and reftex-use-external-file-finders
           (assoc type reftex-external-file-finders))
      (setq file1 (reftex-find-file-externally file type master-dir)))
     (t
      (while (and (null file1) rec-values)
        (setq path (reftex-access-search-path
                    type (pop rec-values) master-dir file))
	(setq fs files)
	(while (and (null file1) (setq f (pop fs)))
	  (when (or (null old-path)
		    (not (eq old-path path)))
	    (setq old-path path
		  path (cons master-dir path))
	    (setq file1 (reftex-find-file-on-path f path master-dir)))))))
    (cond (file1 file1)
          (die (error "No such file: %s" file) nil)
          (t (message "No such file: %s (ignored)" file) nil))))

(defun reftex-find-file-externally (file type &optional master-dir)
  ;; Use external program to find FILE.
  ;; The program is taken from `reftex-external-file-finders'.
  ;; Interpret relative path definitions starting from MASTER-DIR.
  (let ((default-directory (or master-dir default-directory))
        (prg (cdr (assoc type reftex-external-file-finders)))
        out)
    (if (string-match "%f" prg)
        (setq prg (replace-match file t t prg)))
    (setq out (apply 'reftex-process-string (split-string prg)))
    (if (string-match "[ \t\n]+\\'" out)     ; chomp
        (setq out (replace-match "" nil nil out)))
    (cond ((equal out "") nil)
          ((file-regular-p out) (expand-file-name out master-dir))
          (t nil))))

(defun reftex-process-string (program &rest args)
  "Execute PROGRAM with arguments ARGS and return its STDOUT as a string."
  (let ((calling-dir default-directory))  ; remember default directory
    (with-output-to-string
      (with-current-buffer standard-output
        (let ((default-directory calling-dir)) ; set default directory
          (apply 'call-process program nil '(t nil) nil args))))))

(defun reftex-access-search-path (type &optional recurse master-dir file)
  ;; Access path from environment variables.  TYPE is either "tex" or "bib".
  ;; When RECURSE is t, expand path elements ending in `//' recursively.
  ;; Relative path elements are left as they are.  However, relative recursive
  ;; elements are expanded with MASTER-DIR as default directory.
  ;; The expanded path is cached for the next search.
  ;; FILE is just for the progress message.
  ;; Returns the derived path.
  (let* ((pathvar (intern (concat "reftex-" type "-path"))))
    (when (null (get pathvar 'status))
      ;; Get basic path
      (set pathvar
           (reftex-uniquify
            (reftex-parse-colon-path
             (mapconcat
              (lambda(x)
                (if (string-match "^!" x)
                    (apply 'reftex-process-string
                           (split-string (substring x 1)))
                  (or (getenv x) x)))
              ;; For consistency, the next line should look like this:
              ;;  (cdr (assoc type reftex-path-environment))
              ;; However, historically we have separate options for the
              ;; environment variables, so we have to do this:
              (symbol-value (intern (concat "reftex-" type
                                            "path-environment-variables")))
              path-separator))))
      (put pathvar 'status 'split)
      ;; Check if we have recursive elements
      (let ((path (symbol-value pathvar)) dir rec)
        (while (setq dir (pop path))
          (when (string= (substring dir -2) "//")
            (if (file-name-absolute-p dir)
                (setq rec (or rec 'absolute))
              (setq rec 'relative))))
        (put pathvar 'rec-type rec)))

    (if recurse
        ;; Return the recursive expansion of the path
        (cond
         ((not (get pathvar 'rec-type))
          ;; Path does not contain recursive elements - use simple path
          (symbol-value pathvar))
         ((or (not (get pathvar 'recursive-path))
              (and (eq (get pathvar 'rec-type) 'relative)
                   (not (equal master-dir (get pathvar 'master-dir)))))
          ;; Either: We don't have a recursive expansion yet.
          ;; or:     Relative recursive path elements need to be expanded
          ;;         relative to new default directory
          (message "Expanding search path to find %s file: %s ..." type file)
          (put pathvar 'recursive-path
               (reftex-expand-path (symbol-value pathvar) master-dir))
          (put pathvar 'master-dir master-dir)
          (get pathvar 'recursive-path))
         (t
          ;; Recursive path computed earlier is still OK.
          (get pathvar 'recursive-path)))
      ;; The simple path was requested
      (symbol-value pathvar))))

(defun reftex-find-file-on-path (file path &optional def-dir)
  ;; Find FILE along the directory list PATH.
  ;; DEF-DIR is the default directory for expanding relative path elements.
  (catch 'exit
    (when (file-name-absolute-p file)
      (if (file-regular-p file)
          (throw 'exit file)
        (throw 'exit nil)))
    (let* ((thepath path) file1 dir)
      (while (setq dir (pop thepath))
        (when (string= (substring dir -2) "//")
          (setq dir (substring dir 0 -1)))
        (setq file1 (expand-file-name file (expand-file-name dir def-dir)))
        (if (file-regular-p file1)
            (throw 'exit file1)))
      ;; No such file
      nil)))

(defun reftex-parse-colon-path (path)
  ;; Like parse-colon-parse, but // or /~ are left alone.
  ;; Trailing ! or !! will be converted into `//' (emTeX convention)
  (mapcar
   (lambda (dir)
     (if (string-match "\\(//+\\|/*!+\\)\\'" dir)
         (setq dir (replace-match "//" t t dir)))
     (file-name-as-directory dir))
   (delete "" (split-string path (concat path-separator "+")))))

(defun reftex-expand-path (path &optional default-dir)
  ;; Expand parts of path ending in `//' recursively into directory list.
  ;; Relative recursive path elements are expanded relative to DEFAULT-DIR.
  (let (path1 dir recursive)
    (while (setq dir (pop path))
      (if (setq recursive (string= (substring dir -2) "//"))
          (setq dir (substring dir 0 -1)))
      (if (and recursive
               (not (file-name-absolute-p dir)))
          (setq dir (expand-file-name dir default-dir)))
      (if recursive
          ;; Expand recursively
          (setq path1 (append (reftex-recursive-directory-list dir) path1))
        ;; Keep unchanged
        (push dir path1)))
    (nreverse path1)))

(defun reftex-recursive-directory-list (dir)
  ;; Return a list of all directories below DIR, including DIR itself
  (let ((path (list dir)) path1 file files)
    (while (setq dir (pop path))
      (when (file-directory-p dir)
        (setq files (nreverse (directory-files dir t "[^.]")))
        (while (setq file (pop files))
          (if (file-directory-p file)
              (push (file-name-as-directory file) path)))
        (push dir path1)))
    path1))

;;; =========================================================================
;;;
;;; Some generally useful functions

(defun reftex-typekey-check (typekey conf-variable &optional n)
  ;; Check if CONF-VARIABLE is true or contains TYPEKEY
  (and n (setq conf-variable (nth n conf-variable)))
  (or (eq conf-variable t)
      (and (stringp conf-variable)
           (let ((case-fold-search nil))
             (string-match (concat "[" conf-variable "]") typekey)))))

(defun reftex-check-recursive-edit ()
  ;; Check if we are already in a recursive edit.  Abort with helpful
  ;; message if so.
  (if (marker-position reftex-recursive-edit-marker)
      (error
       (substitute-command-keys
        "In unfinished selection process. Finish, or abort with \\[abort-recursive-edit]"))))

(defun reftex-in-comment ()
  "Return non-nil if point is in a comment."
  (save-excursion
    (save-match-data
      (let ((pos (point)))
	(beginning-of-line)
	(re-search-forward
	 (or comment-start-skip
	     ;; The parser may open files in fundamental mode if
	     ;; `reftex-initialize-temporary-buffers' is nil, so here
	     ;; is a default suitable for plain TeX and LaTeX.
	     "\\(\\(^\\|[^\\\n]\\)\\(\\\\\\\\\\)*\\)\\(%+[ \t]*\\)")
	 pos t)))))

(defun reftex-no-props (string)
  ;; Return STRING with all text properties removed
  (and (stringp string)
       (set-text-properties 0 (length string) nil string))
  string)

(defun reftex-match-string (n)
  ;; Match string without properties
  (when (match-beginning n)
    (buffer-substring-no-properties (match-beginning n) (match-end n))))

(defun reftex-region-active-p ()
  "Should we operate on an active region?"
  (if (fboundp 'use-region-p)
      (use-region-p)
    ;; For XEmacs.
    (region-active-p)))

(defun reftex-kill-buffer (buffer)
  ;; Kill buffer if it exists.
  (and (setq buffer (get-buffer buffer))
       (kill-buffer buffer)))

(defun reftex-erase-buffer (&optional buffer)
  ;; Erase BUFFER if it exists.  BUFFER defaults to current buffer.
  ;; This even erases read-only buffers.
  (cond
   ((null buffer)
    ;; erase current buffer
    (let ((buffer-read-only nil)) (erase-buffer)))
   ((setq buffer (get-buffer buffer))
    ;; buffer exists
    (with-current-buffer buffer
      (let ((inhibit-read-only t)) (erase-buffer))))))

(defun reftex-this-word (&optional class)
  ;; Grab the word around point.
  (setq class (or class "-a-zA-Z0-9:_/.*;|"))
  (save-excursion
    (buffer-substring-no-properties
     (progn (skip-chars-backward class) (point))
     (progn (skip-chars-forward  class) (point)))))

(defun reftex-number (n unit &optional ending)
  (if (and (integerp n) (stringp unit))
      (format "%d %s%s" n unit (if (= n 1) "" (or ending "s")))
    ""))

(defun reftex-all-assq (key list)
  ;; Return a list of all associations of KEY in LIST.  Comparison with eq.
  (let (rtn)
    (while (setq list (memq (assq key list) list))
      (push (car list) rtn)
      (pop list))
    (nreverse rtn)))

(defun reftex-all-assoc-string (key list)
  ;; Return a list of all associations of KEY in LIST.  Comparison with string=.
  (let (rtn)
    (while list
      (if (string= (car (car list)) key)
          (push (car list) rtn))
      (pop list))
    (nreverse rtn)))

(defun reftex-last-assoc-before-elt (key elt list &optional exclusive)
  ;; Find the last association of KEY in LIST before or at ELT
  ;; ELT is found in LIST with equal, not eq.
  ;; Returns nil when either KEY or elt are not found in LIST.
  ;; When EXCLUSIVE is non-nil, ELT cannot be the return value.
  ;; On success, returns the association.
  (let* ((elt (car (member elt list))) (ex (not exclusive)) ass last-ass)
    (while (and (setq ass (assoc key list))
                (setq list (memq ass list))
                (or ex (not (eq elt (car list))))
                (memq elt list))
      (setq last-ass ass
            list (cdr list)))
    last-ass))

(defun reftex-sublist-nth (list nth predicate &optional completion)
  ;; Make a list of the NTH elements of all members of LIST which
  ;; fulfill PREDICATE.
  ;; When COMPLETION is non-nil, make all elements of the resulting
  ;; list also a list, so that the result can be used for completion.
  (let (rtn)
    (while list
      (if (funcall predicate (car list))
          (push (if completion
                    (list (nth nth (car list)))
                  (nth nth (car list)))
                rtn))
      (setq list (cdr list)))
    (nreverse rtn)))

(defun reftex-make-selection-buffer-name (type &optional index)
  ;; Make unique name for a selection buffer.
  (format " *RefTeX[%s][%d]*"
          type (or index (get reftex-docstruct-symbol :master-index) 0)))

(defun reftex-make-index-buffer-name (tag &optional cnt)
  ;; Make unique name for an index buffer.
  (format "*Index[%s][%d]*"
          tag (or cnt (get reftex-docstruct-symbol :master-index) 0)))

(defun reftex-truncate (string ncols &optional ellipses padding)
  ;; Truncate STRING to NCOLS characters.
  ;; When PADDING is non-nil, and string is shorter than NCOLS, fill with
  ;; white space to NCOLS characters.  When ELLIPSES is non-nil and the
  ;; string needs to be truncated, replace last 3 characters by dots.
  (setq string
        (if (<= (length string) ncols)
            string
          (if ellipses
              (concat (substring string 0 (- ncols 3)) "...")
            (substring string 0 ncols))))
  (if padding
      (format (format "%%-%ds" ncols) string)
    string))

(defun reftex-nearest-match (regexp &optional max-length)
  ;; Find the nearest match of REGEXP.  Set the match data.
  ;; If POS is given, calculate distances relative to it.
  ;; Return nil if there is no match.
  (let ((pos (point))
        (dist (or max-length (length regexp)))
        match1 match2 match)
    (goto-char (min (+ pos dist) (point-max)))
    (when (re-search-backward regexp nil t)
      (setq match1 (match-data)))
    (goto-char (max (- pos dist) (point-min)))
    (when (re-search-forward regexp nil t)
      (setq match2 (match-data)))
    (goto-char pos)
    (setq match
          (cond
           ((not match1) match2)
           ((not match2) match1)
           ((< (abs (- pos (car match1))) (abs (- pos (car match2)))) match1)
           (t match2)))
    (if match (progn (set-match-data match) t) nil)))

(defun reftex-auto-mode-alist ()
  ;; Return an `auto-mode-alist' with only the .gz (etc) thingies.
  ;; Stolen from gnus nnheader.
  (let ((alist auto-mode-alist)
        out)
    (while alist
      (when (listp (cdr (car alist)))
        (push (car alist) out))
      (pop alist))
    (nreverse out)))

(defun reftex-window-height ()
  (if (fboundp 'window-displayed-height)
      (window-displayed-height)
    (window-height)))

(defun reftex-enlarge-to-fit (buf2 &optional keep-current)
  ;; Enlarge other window displaying buffer to show whole buffer if possible.
  ;; If KEEP-CURRENT in non-nil, current buffer must remain visible.
  (let* ((win1 (selected-window))
         (buf1 (current-buffer))
         (win2 (get-buffer-window buf2))) ;; Only on current frame.
    (when win2
      (select-window win2)
      (unless (and (pos-visible-in-window-p (point-min))
                   (pos-visible-in-window-p (point-max)))
        (enlarge-window (1+ (- (count-lines (point-min) (point-max))
                               (reftex-window-height))))))
    (cond
     ((window-live-p win1) (select-window win1))
     (keep-current
      ;; we must have the old buffer!
      (switch-to-buffer-other-window buf1)
      (shrink-window (- (window-height) window-min-height))))))

(defun reftex-select-with-char (prompt help-string &optional delay-time scroll)
  ;; Offer to select something with PROMPT and, after DELAY-TIME seconds,
  ;; also with HELP-STRING.
  ;; When SCROLL is non-nil, use SPC and DEL to scroll help window.
  (let ((char ?\?))
    (save-window-excursion
      (catch 'exit
        (message "%s   (?=Help)" prompt)
        (when (or (sit-for (or delay-time 0))
                  (= ?\? (setq char (read-char-exclusive))))
          (reftex-kill-buffer "*RefTeX Select*")
          (switch-to-buffer-other-window "*RefTeX Select*")
          (insert help-string)
          (goto-char 1)
          (unless (and (pos-visible-in-window-p (point-min))
                       (pos-visible-in-window-p (point-max)))
            (enlarge-window (1+ (- (count-lines (point-min) (point-max))
                                   (reftex-window-height)))))
          (setq truncate-lines t))
        (if (and (pos-visible-in-window-p (point-min))
                 (pos-visible-in-window-p (point-max)))
            nil
          (setq prompt (concat prompt (if scroll "   (SPC/DEL=Scroll)" ""))))
        (message "%s" prompt)
        (and (equal char ?\?) (setq char (read-char-exclusive)))
        (while t
          (cond ((equal char ?\C-g) (keyboard-quit))
                ((equal char ?\?))
                ((and scroll (equal char ?\ ))
                 (condition-case nil (scroll-up) (error nil))
                 (message "%s" prompt))
                ((and scroll (equal char ?\C-? ))
                 (condition-case nil (scroll-down) (error nil))
                 (message "%s" prompt))
                (t (message "")
		   (reftex-kill-buffer "*RefTeX Select*")
                   (throw 'exit char)))
          (setq char (read-char-exclusive)))))))


(defun reftex-make-regexp-allow-for-ctrl-m (string)
  ;; convert STRING into a regexp, allowing ^M for \n and vice versa
  (let ((start -2))
    (setq string (regexp-quote string))
    (while (setq start (string-match "[\n\r]" string (+ 3 start)))
      (setq string (replace-match "[\n\r]" nil t string)))
    string))

(defun reftex-get-buffer-visiting (file)
  ;; return a buffer visiting FILE
  (cond
   ((boundp 'find-file-compare-truenames) ; XEmacs
    (let ((find-file-compare-truenames t))
      (get-file-buffer file)))
   ((fboundp 'find-buffer-visiting)       ; Emacs
    (find-buffer-visiting file))
   (t (error "This should not happen (reftex-get-buffer-visiting)"))))

;; Define `current-message' for compatibility with XEmacs prior to 20.4
(defvar message-stack)
(if (and (featurep 'xemacs)
         (not (fboundp 'current-message)))
    (defun current-message (&optional _frame)
      (cdr (car message-stack))))

(defun reftex-visited-files (list)
  ;; Takes a list of filenames and returns the buffers of those already visited
  (delq nil (mapcar (lambda (x) (if (reftex-get-buffer-visiting x) x nil))
                    list)))

(defun reftex-get-file-buffer-force (file &optional mark-to-kill)
  ;; Return a buffer visiting file.  Make one, if necessary.
  ;; If neither such a buffer nor the file exist, return nil.
  ;; If MARK-TO-KILL is t and there is no live buffer, visit the file with
  ;; initializations according to `reftex-initialize-temporary-buffers',
  ;; and mark the buffer to be killed after use.

  (let ((buf (reftex-get-buffer-visiting file)))

    (cond (buf
           ;; We have it already as a buffer - just return it
           buf)

          ((file-readable-p file)
           ;; At least there is such a file and we can read it.

           (if (or (not mark-to-kill)
                   (eq t reftex-initialize-temporary-buffers))

               ;; Visit the file with full magic
               (setq buf (find-file-noselect file))

             ;; Else: Visit the file just briefly, without or
             ;;       with limited Magic

             ;; The magic goes away
             (cl-letf ((format-alist nil)
                       (auto-mode-alist (reftex-auto-mode-alist))
                       ((default-value 'major-mode) 'fundamental-mode)
                       (enable-local-variables nil)
                       (after-insert-file-functions nil))
               (setq buf (find-file-noselect file)))

             ;; Is there a hook to run?
             (when (listp reftex-initialize-temporary-buffers)
               (with-current-buffer buf
                 (run-hooks 'reftex-initialize-temporary-buffers))))

           ;; Let's see if we got a license to kill :-|
           (and mark-to-kill
                (cl-pushnew buf reftex-buffers-to-kill))

           ;; Return the new buffer
           buf)

          ;; If no such file exists, return nil
          (t nil))))

(defun reftex-kill-temporary-buffers (&optional buffer)
  ;; Kill all buffers in the list reftex-kill-temporary-buffers.
  (cond
   (buffer
    (when (member buffer reftex-buffers-to-kill)
      (kill-buffer buffer)
      (setq reftex-buffers-to-kill
            (delete buffer reftex-buffers-to-kill))))
   (t
    (while (setq buffer (pop reftex-buffers-to-kill))
      (when (bufferp buffer)
        (and (buffer-modified-p buffer)
             (y-or-n-p (format "Save file %s? "
                               (buffer-file-name buffer)))
             (with-current-buffer buffer
               (save-buffer)))
        (kill-buffer buffer))
      (pop reftex-buffers-to-kill)))))

(defun reftex-splice-symbols-into-list (list alist)
  ;; Splice the association in ALIST of any symbols in LIST into the list.
  ;; Return new list.
  (let (rtn tmp)
    (while list
      (while (and (not (null (car list)))  ;; keep list elements nil
                  (symbolp (car list)))
        (setq tmp (car list))
        (cond
         ((assoc tmp alist)
          (setq list (append (nth 2 (assoc tmp alist)) (cdr list))))
         (t
          (error "Cannot treat symbol %s in reftex-label-alist"
                 (symbol-name tmp)))))
      (push (pop list) rtn))
    (nreverse rtn)))

(defun reftex-remove-symbols-from-list (list)
  ;; Remove all symbols from list
  (let (rtn)
    (while list
      (unless (symbolp (car list))
        (push (car list) rtn))
      (setq list (cdr list)))
    (nreverse rtn)))

(defun reftex-uniquify (list &optional sort)
  ;; Return a list of all strings in LIST, but each only once, keeping order
  ;; unless SORT is set (faster!).
  (setq list (copy-sequence list))
  (if sort
      (progn
	(setq list (sort list 'string<))
	(let ((p list))
	  (while (cdr p)
	    (if (string= (car p) (car (cdr p)))
		(setcdr p (cdr (cdr p)))
	      (setq p (cdr p)))))
	list)
    (let ((p list) lst elt)
      ;; push all sublists into lst in reverse(!) order
      (while p
	(push p lst)
	(setq p (cdr p)))
      ;; sort all sublists
      (setq lst (sort lst (lambda (x1 x2) (string< (car x1) (car x2)))))
      (while (cdr lst)
	(setq elt (car (car lst)))
	;; for equal elements in the sorted sublist, replace the
	;; last(!) original list member with nil
	(when (string= elt (car (cadr lst)))
	  (setcar (pop lst) nil)
	  (while (and (cdr lst) (string= elt (car (cadr lst))))
	    (setcar (pop lst) nil)))
	(pop lst)))
    ;; weed out all nils and return.
    (delq nil list)))

(defun reftex-uniquify-by-car (alist &optional keep-list sort)
  ;; Return a list of all elements in ALIST, but each car only once.
  ;; Elements of KEEP-LIST are not removed even if duplicate.
  ;; The order is kept unless SORT is set (faster!).
  (setq keep-list (sort (copy-sequence keep-list) #'string<)
	alist (copy-sequence alist))
  (if sort
      (let (lst elt)
	(setq alist (sort alist (lambda(a b) (string< (car a) (car b)))))
	(setq lst alist)
	(while (cdr lst)
	  (setq elt (car (car lst)))
	  (when (string= elt (car (cadr lst)))
	    (while (and keep-list (string< (car keep-list) elt))
	      (pop keep-list))
	    (if (and keep-list (string= elt (car keep-list)))
		(progn
		  (pop lst)
		  (while (and (cdr lst)
			      (string= elt (car (cadr lst))))
		    (pop lst)))
	      (setcdr lst (cdr (cdr lst)))
	      (while (and (cdr lst)
			  (string= elt (car (cadr lst))))
		(setcdr lst (cdr (cdr lst))))))
	  (pop lst))
	alist)
    (let ((p alist) lst elt)
      (while p
	(push p lst)
	(setq p (cdr p)))
      (setq lst (sort lst (lambda(a b) (string< (car (car a))
						(car (car b))))))
      (while (cdr lst)
	(setq elt (car (car (car lst))))
	(when (string= elt (car (car (cadr lst))))
	  (while (and keep-list (string< (car keep-list) elt))
	    (pop keep-list))
	  (if (and keep-list (string= elt (car keep-list)))
	      (progn
		(pop lst)
		(while (and (cdr lst)
			    (string= elt (car (car (cadr lst)))))
		  (pop lst)))
	    (setcar (pop lst) nil)
	    (while (and (cdr lst)
			(string= elt (car (car (cadr lst)))))
	      (setcar (pop lst) nil))))
	(pop lst)))
    (delq nil alist)))

(defun reftex-remove-if (predicate list)
  "Nondestructively remove all items from LIST which satisfy PREDICATE."
  (let (result)
    (dolist (elt list (nreverse result))
      (unless (funcall predicate elt)
	(push elt result)))))

(defun reftex-abbreviate-title (string)
  (reftex-convert-string string "[-~ \t\n\r,;]" nil t t
                         5 40 nil 1 " " (nth 5 reftex-derive-label-parameters)))

(defun reftex-convert-string (string split-re invalid-re dot keep-fp
                                     nwords maxchar invalid abbrev sep
                                     ignore-words &optional downcase)
  "Convert a string (a sentence) to something shorter.
SPLIT-RE     is the regular expression used to split the string into words.
INVALID-RE   matches characters which are invalid in the final string.
DOT          t means add dots to abbreviated words.
KEEP-FP      t means to keep a final punctuation when applicable.
NWORDS       Number of words to use.
MAXCHAR      Maximum number of characters in the final string.
INVALID      nil: Throw away any words containing stuff matched with INVALID-RE.
             t:   Throw away only the matched part, not the whole word.
ABBREV       nil: Never abbreviate words.
             t:   Always abbreviate words (see `reftex-abbrev-parameters').
             not t and not nil: Abbreviate words if necessary to shorten
                                string below MAXCHAR.
SEP          String separating different words in the output string.
IGNORE-WORDS List of words which should be removed from the string."

  (let* ((words0 (split-string string (or split-re "[ \t\n\r]")))
         (reftex-label-illegal-re (or invalid-re "\000"))
         (abbrev-re (concat
                     "\\`\\("
                     (make-string (nth 0 reftex-abbrev-parameters) ?.)
                     "[" (nth 2 reftex-abbrev-parameters) "]*"
                     "\\)"
                     "[" (nth 3 reftex-abbrev-parameters) "]"
                     (make-string (1- (nth 1 reftex-abbrev-parameters)) ?.)))
         words word)

    ;; Remove words from the ignore list or with funny characters
    (while (setq word (pop words0))
      (if downcase (setq word (downcase word)))
      (cond
       ((member (downcase word) ignore-words))
       ((string-match reftex-label-illegal-re word)
        (when invalid
          (while (string-match reftex-label-illegal-re word)
            (setq word (replace-match "" nil nil word)))
          (push word words)))
       (t
        (push word words))))
    (setq words (nreverse words))

    ;; Restrict number of words
    (if (> (length words) nwords)
        (setcdr (nthcdr (1- nwords) words) nil))

    ;; First, try to use all words
    (setq string (mapconcat 'identity words sep))

    ;; Abbreviate words if enforced by user settings or string length
    (if (or (eq t abbrev)
            (and abbrev
                 (> (length string) maxchar)))
        (setq words
              (mapcar
               (lambda (w) (if (string-match abbrev-re w)
                               (if dot
                                   (concat (match-string 1 w) ".")
                                 (match-string 1 w))
                             w))
               words)
              string (mapconcat 'identity words sep)))

    ;; Shorten if still to long
    (setq string
          (if (> (length string) maxchar)
              (substring string 0 maxchar)
            string))

    ;; Delete the final punctuation, if any
    (if (and (not keep-fp) (string-match "\\s.+\\'" string))
        (setq string (replace-match "" nil nil string)))
    string))

(defun reftex-nicify-text (text)
  ;; Make TEXT nice for inclusion as context into label menu.
  ;; 1. remove line breaks and extra white space
  (while (string-match "[\n\r\t]\\|[ \t][ \t]+" text)
    (setq text (replace-match " " nil t text)))
  ;; 2. cut before the next `\end{' or `\item' or `\\'
  (if (string-match "\\(\\\\end{\\|\\\\item\\|\\\\\\\\\\).*" text)
      (setq text (replace-match "" nil t text)))
  ;; 3. kill the embedded label
  (if (string-match "\\\\label{[^}]*}" text)
      (setq text (replace-match "" nil t text)))
  ;; 4. remove leading garbage
  (if (string-match "\\`[ }]+" text)
      (setq text (replace-match "" nil t text)))
  ;; 5. limit length
  (cond
   ((> (length text) 100) (substring text 0 100))
   ((= (length text) 0) (make-string 1 ?\ ))
   (t text)))


;;; =========================================================================
;;;
;;; Fontification and Highlighting

(defun reftex-use-fonts ()
  ;; Return t if we can and want to use fonts.
  (and ; window-system
       reftex-use-fonts
       (featurep 'font-lock)))

(defun reftex-refontify ()
  ;; Return t if we need to refontify context
  (and (reftex-use-fonts)
       (or (eq t reftex-refontify-context)
           (and (eq 1 reftex-refontify-context)
                ;; Test of we use the font-lock version of x-symbol
                (and (featurep 'x-symbol-tex) (not (boundp 'x-symbol-mode)))))))

(defvar font-lock-defaults-computed)
(defun reftex-fontify-select-label-buffer (parent-buffer)
  ;; Fontify the `*RefTeX Select*' buffer.  Buffer is temporarily renamed to
  ;; start with none-SPC char, because Font-Lock otherwise refuses operation.
  (run-hook-with-args 'reftex-pre-refontification-functions
                      parent-buffer 'reftex-ref)
  (let* ((oldname (buffer-name))
         (newname (concat "Fontify-me-" oldname)))
    (unwind-protect
        (progn
          ;; Rename buffer temporarily to start w/o space (because of font-lock)
          (rename-buffer newname t)
          (cond
           ((fboundp 'font-lock-default-fontify-region)
            ;; Good: we have the indirection functions
            (set (make-local-variable 'font-lock-fontify-region-function)
                 'reftex-select-font-lock-fontify-region)
            (let ((major-mode 'latex-mode))
              (font-lock-mode 1)))
           ((fboundp 'font-lock-set-defaults-1)
            ;; Looks like the XEmacs font-lock stuff.
            ;; FIXME: this is still kind of a hack, but it works.
            (set (make-local-variable 'font-lock-keywords) nil)
            (let ((major-mode 'latex-mode)
                  (font-lock-defaults-computed nil))
              (font-lock-set-defaults-1)
              (reftex-select-font-lock-fontify-region (point-min) (point-max))))
           (t
            ;; Oops?
            (message "Sorry: cannot refontify RefTeX Select buffer."))))
      (rename-buffer oldname))))

(defun reftex-select-font-lock-fontify-region (beg end &optional _loudly)
  ;; Fontify a region, but only lines starting with a dot.
  (let ((func (if (fboundp 'font-lock-default-fontify-region)
                  'font-lock-default-fontify-region
                'font-lock-fontify-region))
        beg1 end1)
    (goto-char beg)
    (while (re-search-forward "^\\." end t)
      (setq beg1 (point) end1 (progn (skip-chars-forward "^\n") (point)))
      (funcall func beg1 end1 nil)
      (goto-char end1))))

(defun reftex-select-font-lock-unfontify (&rest _ignore) t)

(defun reftex-verified-face (&rest faces)
  ;; Return the first valid face in FACES, or nil if none is valid.
  ;; Also, when finding a nil element in FACES, return nil.  This
  ;; function is just a safety net to catch name changes of builtin
  ;; fonts. Currently it is only used for reftex-label-face.
  (let (face)
    (catch 'exit
      (while (setq face (pop faces))
        (if (featurep 'xemacs)
            (if (find-face face) (throw 'exit face))
          (if (facep face) (throw 'exit face)))))))

;; Highlighting uses overlays.  For XEmacs, we use extends.
(defalias 'reftex-make-overlay
  (if (featurep 'xemacs) 'make-extent 'make-overlay))
(defalias 'reftex-overlay-put
  (if (featurep 'xemacs) 'set-extent-property 'overlay-put))
(defalias 'reftex-move-overlay
  (if (featurep 'xemacs) 'set-extent-endpoints 'move-overlay))
(defalias 'reftex-delete-overlay
  (if (featurep 'xemacs) 'detach-extent 'delete-overlay))

;; We keep a vector with several different overlays to do our highlighting.
(defvar reftex-highlight-overlays [nil nil nil])

;; Initialize the overlays
(aset reftex-highlight-overlays 0 (reftex-make-overlay 1 1))
(reftex-overlay-put (aref reftex-highlight-overlays 0)
             'face 'highlight)
(aset reftex-highlight-overlays 1 (reftex-make-overlay 1 1))
(reftex-overlay-put (aref reftex-highlight-overlays 1)
             'face reftex-cursor-selected-face)
(aset reftex-highlight-overlays 2 (reftex-make-overlay 1 1))
(reftex-overlay-put (aref reftex-highlight-overlays 2)
             'face reftex-cursor-selected-face)

;; Two functions for activating and deactivation highlight overlays
(defun reftex-highlight (index begin end &optional buffer)
  "Highlight a region with overlay INDEX."
  (reftex-move-overlay (aref reftex-highlight-overlays index)
                begin end (or buffer (current-buffer))))
(defun reftex-unhighlight (index)
  "Detach overlay INDEX."
  (reftex-delete-overlay (aref reftex-highlight-overlays index)))

(defun reftex-highlight-shall-die ()
  ;; Function used in pre-command-hook to remove highlights.
  (remove-hook 'pre-command-hook 'reftex-highlight-shall-die)
  (reftex-unhighlight 0))

;;; =========================================================================
;;;
;;; Keybindings

(defvar bibtex-mode-map)

;; Bind `reftex-view-crossref-from-bibtex' in BibTeX mode map
(eval-after-load
 "bibtex"
 '(define-key bibtex-mode-map "\C-c&" 'reftex-view-crossref-from-bibtex))

;;; =========================================================================
;;;
;;; Menu

;; Define a menu for the menu bar if Emacs is running under X

(defvar reftex-isearch-minor-mode nil)
(make-variable-buffer-local 'reftex-isearch-minor-mode)

(easy-menu-define reftex-mode-menu reftex-mode-map
 "Menu used in RefTeX mode"
 `("Ref"
   ["Table of Contents"       reftex-toc t]
   ["Recenter TOC"            reftex-toc-recenter t]
   "--"
   ["\\label"                 reftex-label t]
   ["\\ref"                   reftex-reference t]
   ["\\cite"                  reftex-citation t]
   ("\\index"
    ["\\index"                    reftex-index t]
    ["\\index{THIS}"              reftex-index-selection-or-word t]
    "--"
    ["Add THIS to Index Phrases"  reftex-index-phrase-selection-or-word t]
    ["Visit Phrase Buffer"        reftex-index-visit-phrases-buffer t]
    ["Apply Phrases to Region"    reftex-index-phrases-apply-to-region t]
    "--"
    ["Display the Index"          reftex-display-index t])
   "--"
   ["View Crossref"           reftex-view-crossref t]
   "--"
   ("Parse Document"
    ["One File"               reftex-parse-one reftex-enable-partial-scans]
    ["Entire Document"        reftex-parse-all t]
    ["Save to File"           (reftex-access-parse-file 'write)
     (> (length (symbol-value reftex-docstruct-symbol)) 0)]
    ["Restore from File"      (reftex-access-parse-file 'restore) t])
   ("Global Actions"
    ["Search Whole Document"  reftex-search-document t]
    ["Search Again"           tags-loop-continue t]
    ["Replace in Document"    reftex-query-replace-document t]
    ["Grep on Document"       reftex-grep-document t]
    "--"
    ["Goto Label"             reftex-goto-label t]
    ["Find Duplicate Labels"  reftex-find-duplicate-labels t]
    ["Change Label and Refs"  reftex-change-label t]
    ["Renumber Simple Labels" reftex-renumber-simple-labels t]
    "--"
    ["Create BibTeX File"     reftex-create-bibtex-file t]
    "--"
    ["Create TAGS File"       reftex-create-tags-file t]
    "--"
    ["Save Document"          reftex-save-all-document-buffers t])
   "--"
   ("Options"
    "PARSER"
    ["Partial Scans"
     (setq reftex-enable-partial-scans (not reftex-enable-partial-scans))
     :style toggle :selected reftex-enable-partial-scans]
    ["Auto-Save Parse Info"
     (setq reftex-save-parse-info (not reftex-save-parse-info))
     :style toggle :selected reftex-save-parse-info]
    "--"
    "TOC RECENTER"
    ["Automatic Recenter" reftex-toggle-auto-toc-recenter
     :style toggle :selected reftex-toc-auto-recenter-timer]
    "--"
    "CROSSREF INFO"
    ["Automatic Info" reftex-toggle-auto-view-crossref
     :style toggle :selected reftex-auto-view-crossref-timer]
    ["...in Echo Area" (setq reftex-auto-view-crossref t)
     :style radio :selected (eq reftex-auto-view-crossref t)]
    ["...in Other Window" (setq reftex-auto-view-crossref 'window)
     :style radio :selected (eq reftex-auto-view-crossref 'window)]
    "--"
    "MISC"
    ["AUCTeX Interface" reftex-toggle-plug-into-AUCTeX
     :style toggle :selected reftex-plug-into-AUCTeX]
    ["isearch whole document" reftex-isearch-minor-mode
     :style toggle :selected reftex-isearch-minor-mode])
   ("Reference Style"
    ,@(let (list item)
	(dolist (elt reftex-ref-style-alist)
	  (setq elt (car elt)
		item (vector
		      elt
		      `(reftex-ref-style-toggle ,elt)
		      :style 'toggle
		      :selected `(member ,elt (reftex-ref-style-list))))
	  (unless (member item list)
            (setq list (append list (list item)))))
	list))
   ("Citation Style"
    ,@(mapcar
       (lambda (x)
         (vector
          (capitalize (symbol-name (car x)))
          (list 'reftex-set-cite-format (list 'quote (car x)))
          :style 'radio :selected
          (list 'eq (list 'reftex-get-cite-format) (list 'quote (car x)))))
       reftex-cite-format-builtin)
    "--"
    "Sort Database Matches"
    ["Not" (setq reftex-sort-bibtex-matches nil)
     :style radio :selected (eq reftex-sort-bibtex-matches nil)]
    ["by Author" (setq reftex-sort-bibtex-matches 'author)
     :style radio :selected (eq reftex-sort-bibtex-matches 'author)]
    ["by Year" (setq reftex-sort-bibtex-matches 'year)
     :style radio :selected (eq reftex-sort-bibtex-matches 'year)]
    ["by Year, reversed" (setq reftex-sort-bibtex-matches 'reverse-year)
     :style radio :selected (eq reftex-sort-bibtex-matches 'reverse-year)])
   ("Index Style"
    ,@(mapcar
       (lambda (x)
         (vector
          (capitalize (symbol-name (car x)))
          (list 'reftex-add-index-macros (list 'list (list 'quote (car x))))
          :style 'radio :selected
          (list 'memq (list 'quote (car x))
                (list 'get 'reftex-docstruct-symbol
                      (list 'quote 'reftex-index-macros-style)))))
       reftex-index-macros-builtin))
   "--"
    ["Reset RefTeX Mode"       reftex-reset-mode t]
   "--"
   ("Customize"
    ["Browse RefTeX Group" reftex-customize t]
    "--"
    ["Build Full Customize Menu" reftex-create-customize-menu
     (fboundp 'customize-menu-create)])
   ("Documentation"
    ["Info" reftex-info t]
    ["Commentary" reftex-show-commentary t])))

(defun reftex-customize ()
  "Call the customize function with reftex as argument."
  (interactive)
  (customize-browse 'reftex))

(defun reftex-create-customize-menu ()
  "Create a full customization menu for RefTeX, insert it into the menu."
  (interactive)
  (if (fboundp 'customize-menu-create)
      (progn
        (easy-menu-change
         '("Ref") "Customize"
         `(["Browse RefTeX group" reftex-customize t]
           "--"
           ,(customize-menu-create 'reftex)
           ["Set" Custom-set t]
           ["Save" Custom-save t]
           ["Reset to Current" Custom-reset-current t]
           ["Reset to Saved" Custom-reset-saved t]
           ["Reset to Standard Settings" Custom-reset-standard t]))
        (message "\"Ref\"-menu now contains full customization menu"))
    (error "Cannot expand menu (outdated version of cus-edit.el)")))


;;; Misc

(defun reftex-show-commentary ()
  "Use the finder to view the file documentation from `reftex.el'."
  (interactive)
  (finder-commentary "reftex.el"))

(defun reftex-info (&optional node)
  "Read documentation for RefTeX in the info system.
With optional NODE, go directly to that node."
  (interactive)
  (info (format "(reftex)%s" (or node ""))))

(defun reftex-report-bug ()
  "Report a bug in RefTeX.

Don't hesitate to report any problems or inaccurate documentation.

If you don't have setup sending mail from (X)Emacs, please copy the
output buffer into your mail program, as it gives us important
information about your RefTeX version and configuration."
  (interactive)
  (require 'reporter)
  (defvar reporter-prompt-for-summary-p)
  (let ((reporter-prompt-for-summary-p "Bug report subject: "))
    (reporter-submit-bug-report
     "bug-auctex@gnu.org, bug-gnu-emacs@gnu.org"
     reftex-version
     (list 'window-system
	   'reftex-plug-into-AUCTeX)
     nil nil
     "Remember to cover the basics, that is, what you expected to happen and
what in fact did happen.

Check if the bug is reproducible with an up-to-date version of
RefTeX available from https://www.gnu.org/software/auctex/.

If the bug is triggered by a specific \(La)TeX file, you should try
to produce a minimal sample file showing the problem and include it
in your report.

Your bug report will be posted to the AUCTeX bug reporting list.
------------------------------------------------------------------------")))

;;; Install the kill-buffer and kill-emacs hooks ------------------------------

(add-hook 'kill-buffer-hook 'reftex-kill-buffer-hook)
(unless noninteractive
  (add-hook 'kill-emacs-hook  'reftex-kill-emacs-hook))

;;; Run Hook ------------------------------------------------------------------

(run-hooks 'reftex-load-hook)

;;; That's it! ----------------------------------------------------------------

(setq reftex-tables-dirty t)  ; in case this file is evaluated by hand

(provide 'reftex)

;;; reftex.el ends here

debug log:

solving d763769a18 ...
found d763769a18 in https://git.savannah.gnu.org/cgit/emacs.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).