-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathSOURCE.LST
1518 lines (927 loc) · 54.9 KB
/
SOURCE.LST
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
Notes on the Xvi Source Code
Chris Downey
John Downey
Xvi (pronounced _e_c_k_s-_v_e_e-_e_y_e) is a free, portable,
multi-window implementation of the popular UNIX|- editor
vi.
This document contains information on how to port xvi
to systems not currently supported. It also explains
how the xvi source code is arranged into modules, and
explains some of the data structures which are used, so
that modifications may be made if and when necessary to
the editor itself.
_1. _I_N_T_R_O_D_U_C_T_I_O_N
Xvi is intended to be portable to just about any system. This is
one of the central reasons for its existence; the authors wish to
be able to use the same editor everywhere.
The main body of the editor is (supposedly) fully portable,
relying only on standard facilities defined by the White Book,
and on a set of _p_r_i_m_i_t_i_v_e_s which are provided by a set of one or
more modules for each operating system. If ___S_T_D_C__ is defined,
certain ANSI C facilities will be used, but the editor will
compile with non-ANSI compilers.
Therefore, in order to port xvi to a new system, all that is
necessary is to provide the defined set of _p_r_i_m_i_t_i_v_e_s, and then
build the editor. Or at least, that's the idea; we have refined
the set of primitives as we port the editor to new environments,
and it's getting pretty easy now.
The rest of this document is divided into sections as follows:
_S_e_c_t_i_o_n _2: _S_y_s_t_e_m-_S_p_e_c_i_f_i_c _M_o_d_u_l_e_s
This section deals with the layout of source files and
makefiles which you will have to deal with when porting xvi.
_S_e_c_t_i_o_n _3: _P_r_i_m_i_t_i_v_e_s _P_r_o_v_i_d_e_d _b_y _x_v_i
Discusses what primitives are provided by the main body of
the editor source code for use by the system interface code.
_________________________
|- UNIX is a trademark of Bell Laboratories.
_2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2 _P_a_g_e _1
_2 _X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s
_S_e_c_t_i_o_n _4: _S_y_s_t_e_m _I_n_t_e_r_f_a_c_e
Explains the primitives which need to be provided in order
to make xvi work.
_S_e_c_t_i_o_n _5: _D_a_t_a _S_t_r_u_c_t_u_r_e_s
Details the internal data types used in the editor, and any
functions available for operating on those types.
_S_e_c_t_i_o_n _6: _S_o_u_r_c_e _F_i_l_e_s
Lists the source files comprising the editor, and explains
what functionality is provided by each one.
_2. _S_Y_S_T_E_M-_S_P_E_C_I_F_I_C _M_O_D_U_L_E_S
The system-specific code normally consists of three (or more)
files; a ".c" file, a ".h" file, and a makefile. For example:
_q_n_x._c
_q_n_x._h
_m_a_k_e_f_i_l_e._q_n_x
comprise the system-specific module for the QNX operating system.
In most cases, the system-specific code is divided into two or
more modules, where one (called the _s_y_s_t_e_m _i_n_t_e_r_f_a_c_e _m_o_d_u_l_e) is
concerned with general interactions with the operating system and
the other (called the _t_e_r_m_i_n_a_l _i_n_t_e_r_f_a_c_e _m_o_d_u_l_e) is designed for
a specific interface to a display and keyboard (and possibly, a
mouse).
For example, the generic UNIX implementation has _u_n_i_x._c and
_u_n_i_x._h for the system interface module, and _t_e_r_m_c_a_p._c and
_t_e_r_m_c_a_p._h for the terminal interface module; this should work
reasonably with any full-duplex terminal that can be described in
the _t_e_r_m_c_a_p database. On consoles with memory-mapped displays,
or systems with graphic user interfaces, however, it may be
possible to achieve faster display updating, and perhaps other
benefits, by replacing the _t_e_r_m_c_a_p module with another one that
makes better use of whatever facilities are available. For
instance, there is an experimental version for SunView, which
allows mouse input on Sun workstations running the SunView window
system.
On the other hand, the _t_e_r_m_c_a_p-specific routines might
conceivably be useful on some other operating systems (such as
VMS), so in general it seemed a good idea to make the _t_e_r_m_c_a_p-
specific routines a separate module.
The current MS-DOS implementation has a separate terminal
interface module, which is designed specifically for IBM PC
compatible computers. This is in the files
_P_a_g_e _2 _2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2
_X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s _3
_i_b_m_p_c__a._a_s_m
_i_b_m_p_c__c._c
_i_b_m_p_c._h
The first of these is written in assembly language because there
are not enough routines common to the various MS-DOS C compilers
which reliably access the display and keyboard at a low enough
level.
The hardware-independent system interface module for MS-DOS is in
_m_s_d_o_s__a._a_s_m
_m_s_d_o_s__c._c
_m_s_d_o_s._h
The first of these is written in assembly language for the same
reason as is _i_b_m_p_c__a._a_s_m.
Theoretically, different terminal interface modules could be
written for MS-DOS systems running on hardware which is not IBM-
compatible but, unfortunately, such systems seem to be virtually
extinct nowadays.
Sometimes more than one makefile is provided, as in the case of
UNIX, where different versions work in slightly different ways.
It is, of couse, not necessary to provide all - or any - of these
files for a particular implementation; this is just a convention.
The makefile(s) for each system determine what files are used in
the compilation of the editor.
The following porting modules are available at present:
_2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2 _P_a_g_e _3
_4 _X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s
________________________________________________________________
| System | Makefile | Source Files |
|________________________|_______________|_________________________|
| UNIX | | |
| BSD | makefile.bsd| unix.[ch] termcap.[ch]|
| System V |- | makefile.usg| unix.[ch] termcap.[ch]|
| AIX | makefile.aix| unix.[ch] termcap.[ch]|
| ULTRIX | makefile.ult| unix.[ch] termcap.[ch]|
| Xenix |- | makefile.xen| unix.[ch] termcap.[ch]|
| POSIX (e.g. BSDI) | makefile.pos| unix.[ch] termcap.[ch]|
| SunOS | makefile.sun| unix.[ch] termcap.[ch]|
| SunView | makefile.sv | unix.[ch] sunview.h |
| | | sunfront.c sunback.c |
| | | xvi.icn |
|________________________|_______________|_________________________|
| | | |
| MS-DOS | | msdos_c.c msdos.h |
| | | ibmpc_c.c ibmpc.h |
| Microsoft C 5.* | makefile.msc| 8086mm.inc ibmpc_a.asm|
| & MASM 5.* | | msdos_a.asm |
| | | |
| Microsoft Quick C | makefile.qc | 8086mm.inc ibmpc_a.asm|
| & MASM 5.* | | msdos_a.asm |
| Zortech C++ 2.* | makefile.zc2| 8086mm.inc ibmpc_a.asm|
| & MASM 5.* | | msdos_a.asm |
| | | |
| Zortech C++ 3.* | makefile.zc3| 8086mm.inc ibmpc_a.asm|
| & MASM 5.* | | msdos_a.asm |
| Zortech C++ 3.* | | |
| 386 protected mode | makefile.386| pc386.[ch] |
|________________________|_______________|_________________________|
| | | |
| OS/2 |- | | |
| Version 1, text mode| | |
| Microsoft C 5.1 | makefile.os2| os2vio.[ch] |
| & MASM 5.1 | | i286.asm |
|________________________|_______________|_________________________|
| QNX | | |
| Version 2/3 (CII) | makefile.qnx| qnx.[ch] |
| Version 4 (Watcom C)| makefile.qn4| unix.[ch] termcap.[ch]|
|________________________|_______________|_________________________|
| | | |
| TOS |- | | |
| Lattice C | makefile.tos| tos.[ch] tos.lnk |
|________________________|_______________|_________________________|
|- Versions marked with |- probably do not work, as systems have
not been recently available to the authors for testing.
_P_a_g_e _4 _2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2
_X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s _5
_3. _P_R_I_M_I_T_I_V_E_S _P_R_O_V_I_D_E_D _B_Y _X_V_I
_3._1. _G_e_n_e_r_a_l _D_e_f_i_n_i_t_i_o_n_s
The file _x_v_i._h should be included by all system-specific modules;
this file should also be edited so that a system-specific header
file (or files), as determined by a predefined keyword, will be
included.
For instance, under UNIX, the word _U_N_I_X is defined by passing the
-_D_U_N_I_X flag to the C compiler from the makefile, and _x_v_i._h
contains the following lines:
#_i_f_d_e_f _U_N_I_X
# _i_n_c_l_u_d_e "_u_n_i_x._h"
#_e_n_d_i_f
in order to obtain the UNIX-related definitions from that header
file.
Among the definitions in _x_v_i._h are the following:
bool_t
A Boolean type having values _T_R_U_E or _F_A_L_S_E.
const
volatile
These are defined out when ___S_T_D_C__ is not defined, so that
it is always safe to use them.
_x_v_i._h also includes various other header files which are needed.
The following system header files are always included:
_s_t_d_i_o._h
_c_t_y_p_e._h
_s_i_g_n_a_l._h
_s_t_r_i_n_g._h
These files are included if ___S_T_D_C__ is defined:
_s_t_d_d_e_f._h
_s_t_d_l_i_b._h
_l_i_m_i_t_s._h
and if ___S_T_D_C__ is not defined, _x_v_i._h will provide its own
definitions for the following:
_I_N_T__M_A_X
_I_N_T__M_I_N
_U_L_O_N_G__M_A_X
_F_I_L_E *_f_o_p_e_n();
_c_h_a_r *_m_a_l_l_o_c();
_c_h_a_r *_g_e_t_e_n_v();
_2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2 _P_a_g_e _5
_6 _X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s
Finally, one of the following header files will be included:
_s_t_d_a_r_g._h
_v_a_r_a_r_g_s._h
depending on whether ___S_T_D_C__ is defined or not. In order to
make coding of _v_a_r_a_r_g_s functions easier, a macro _V_A__S_T_A_R_T() is
defined, which takes the same arguments as the ANSI-style
_v_a__s_t_a_r_t(), but which is also available in non-ANSI environments
(e.g. BSD).
In order to make it possible to use ANSI-style prototypes for
function declarations, but still allow compilation under non-ANSI
environments, the following macro is provided:
#_i_f_d_e_f ___S_T_D_C__
# _d_e_f_i_n_e _P(_a_r_g_s) _a_r_g_s
#_e_l_s_e
# _d_e_f_i_n_e _P() ()
#_e_n_d_i_f
so that function declarations may be specified thus:
_e_x_t_e_r_n _F_I_L_E *_f_o_p_e_n _P((_c_o_n_s_t _c_h_a_r *, _c_o_n_s_t _c_h_a_r *));
Please use this facility when you provide declarations for your
system primitives, unless your system always uses an ANSI
compiler.
_3._2. _P_a_r_a_m_e_t_e_r_s
An important facility provided for use by system-specific modules
is access to the editor's parameter table. This is achieved by
means of some apparent functions, and a set of #_d_e_f_i_n_ed token
values. The functions are:
void set_param(int n, val)
This function sets the indicated parameter to the passed
value, which must be of an appropriate type. Parameter
values may be obtained by means of the following functions
(actually macros):
char *Ps(int n)
return value of string parameter
int Pn(int n)
return value of numeric parameter
bool_t Pb(int n)
return value of boolean parameter
char **Pl(int n)
return value of list parameter (a NULL-terminated array of
character pointers)
_P_a_g_e _6 _2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2
_X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s _7
int Pen(int n)
return numeric value (index) of enumerated parameter
char **Pes(int n)
return string value of enumerated parameter
In all cases, the int n argument is the index of the parameter in
the table; a set of #_d_e_f_i_n_es is provided, of the form:
_P__n_a_m_e
which map the parameter names into integral values. Thus, for
example, we might obtain the value of the _c_o_l_o_u_r parameter:
_c_o_l_o_u_r = _P_n(_P__c_o_l_o_u_r);
or set the value of the _h_e_l_p_f_i_l_e parameter:
_s_e_t__p_a_r_a_m(_P__h_e_l_p_f_i_l_e, "/_u_s_r/_l_i_b/_x_v_i/_h_e_l_p");
_4. _S_Y_S_T_E_M _I_N_T_E_R_F_A_C_E
_4._1. _I_n_t_r_o_d_u_c_t_i_o_n
There follows a list of the primitives which must be provided
either by the system interface module or by the underlying OS.
Note that it is perfectly acceptable to implement functions or
external variables as macros so long as they "look the same" as
the definitions below. As a guideline, anything which is (a) in
capitals, or (b) is a const variable, will be implemented as a
#_d_e_f_i_n_e for most systems.
When you want to actually do the port, it is highly recommended
that you copy the system-specific files for the system which
seems closest to your own, and modify those files, rather than
starting from scratch.
All the following symbols should be defined in the system
interface module, or by standard header files already included by
_x_v_i._h, or by other header files explicitly included by the
system-specific header file:
const unsigned int MAXPATHLEN
The maximum number of characters in a pathname.
const unsigned int MAXNAMLEN
The maximum number of characters in a filename.
int remove(char *filename)
Remove the named file as per ANSI.
_2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2 _P_a_g_e _7
_8 _X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s
int rename(char *old, char *new)
Rename the file old to new as per ANSI.
void sleep(unsigned int seconds)
Put the process to sleep for the given number of seconds.
const char * const DIRSEPS
The pathname separators supported for system calls (e.g.
"\\/" for MS-DOS).
FILE *fopenrb(char *file)
FILE *fopenwb(char *file)
Like the standard _f_o_p_e_n() library call, but they both open
files in "binary" mode (i.e. no conversion of cr/lf/crlf is
done), for reading and writing respectively.
bool_t exists(char *filename)
Returns _T_R_U_E if the named file exists.
bool_t can_write(char *filename)
Returns _T_R_U_E if the named file can be written, i.e. if a
fopenwb(filename) will succeed.
char *fexpand(char *filename)
Returns a filename-expanded version of the passed filename.
#define SETVBUF_AVAIL
const unsigned int READBUFSIZ
const unsigned int WRTBUFSIZ
If _S_E_T_V_B_U_F__A_V_A_I_L (or ___S_T_D_C__) is defined, these constant
values are used to set I/O buffer sizes (using the setvbuf()
function) for reading and writing files. Note that if
buffers of these sizes are unavailable at runtime, the
editor will try to allocate smaller buffers by iteratively
halving the buffer size until the allocation succeeds. It
is therefore acceptable for these values to be quite large.
char *tempfname(const char *filename)
Create a unique name for a temporary file, possibly using
filename as a base (this will be used by _d_o__p_r_e_s_e_r_v_e() to
create a backup file for the file named by _f_i_l_e_n_a_m_e). The
string returned must have been allocated using _m_a_l_l_o_c();
_N_U_L_L can be returned if there is no more memory available.
int call_system(char *command)
Invoke the given command in a subshell. This is used for
shell escapes from xvi. The command string may contain
metacharacters which are expected to be expanded by a
command interpreter, e.g. UNIX /_b_i_n/_s_h, MS-DOS _c_o_m_m_a_n_d._c_o_m.
Return value is 0 for success. In many environments, this
call may safely be #_d_e_f_i_n_ed as _s_y_s_t_e_m(_c_o_m_m_a_n_d).
_P_a_g_e _8 _2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2
_X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s _9
int call_shell(char *shell)
Invoke the named shell. This is used for the :_s_h_e_l_l
command. It may be mapped into _c_a_l_l__s_y_s_t_e_m(), but is
separate on some systems for efficiency reasons (i.e. not
invoking two shells to get one). Return value is 0 for
success.
bool_t
sys_pipe(char *cmd, int (*wf)(FILE *), long (*rf)(FILE *))
Used for the ! command. The first parameter is the command
to invoke, while the second and third are functions which
should be called with an open file pointer in order to write
out old, or read in new lines (respectively). Note that if
"real" pipes are not available, it is acceptable to
implement this function using temporary files, but the wf
function must obviously be called before rf.
void sys_exit(int code)
Exit with given exit status. This routine must not return.
The editor is considered "dead" once it has been called, and
no further calls to editor functions should be made.
void delay(void)
Delay for a short time, about a fifth of a second. This is
used for showing matching brackets when showmatch is set.
It is acceptable to just return if implementing this is not
easy.
_4._2. _S_c_r_e_e_n _C_o_n_t_r_o_l
An instance of the following structure must be defined in order
to allow screen output to take place:
_2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2 _P_a_g_e _9
_1_0 _X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s
_t_y_p_e_d_e_f _s_t_r_u_c_t _v_i_r_t_s_c_r {
_g_e_n_p_t_r *_p_v__w_i_n_d_o_w;
_i_n_t _p_v__r_o_w_s;
_i_n_t _p_v__c_o_l_s;
/* _p_u_b_l_i_c: */
_V_i_r_t_S_c_r *(*_v__n_e_w)(_V_i_r_t_S_c_r *);
_v_o_i_d (*_v__c_l_o_s_e)(_V_i_r_t_S_c_r *);
_i_n_t (*_v__r_o_w_s)(_V_i_r_t_S_c_r *);
_i_n_t (*_v__c_o_l_s)(_V_i_r_t_S_c_r *);
_v_o_i_d (*_v__c_l_e_a_r__a_l_l)(_V_i_r_t_S_c_r *);
_v_o_i_d (*_v__c_l_e_a_r__l_i_n_e)(_V_i_r_t_S_c_r *);
_v_o_i_d (*_v__g_o_t_o)(_V_i_r_t_S_c_r *, _i_n_t _r_o_w, _i_n_t _c_o_l);
_v_o_i_d (*_v__a_d_v_i_s_e)(_V_i_r_t_S_c_r *, _i_n_t _r_o_w, _i_n_t _c_o_l,
_i_n_t _i_n_d_e_x, _c_h_a_r *_s_t_r);
_v_o_i_d (*_v__w_r_i_t_e)(_V_i_r_t_S_c_r *, _i_n_t _r_o_w, _i_n_t _c_o_l, _c_h_a_r *_s_t_r);
_v_o_i_d (*_v__p_u_t_c)(_V_i_r_t_S_c_r *, _i_n_t _r_o_w, _i_n_t _c_o_l, _i_n_t _c_h);
_v_o_i_d (*_v__s_e_t__c_o_l_o_u_r)(_V_i_r_t_S_c_r *, _i_n_t _c_o_l_o_u_r);
_i_n_t (*_v__c_o_l_o_u_r__c_o_s_t)(_V_i_r_t_S_c_r *);
_v_o_i_d (*_v__f_l_u_s_h)(_V_i_r_t_S_c_r *);
_v_o_i_d (*_v__b_e_e_p)(_V_i_r_t_S_c_r *);
/* _o_p_t_i_o_n_a_l: _n_o_t _u_s_e_d _i_f _N_U_L_L */
_v_o_i_d (*_v__i_n_s_e_r_t)(_V_i_r_t_S_c_r *, _i_n_t _r_o_w, _i_n_t _c_o_l, _c_h_a_r *_s_t_r);
_i_n_t (*_v__s_c_r_o_l_l)(_V_i_r_t_S_c_r *, _i_n_t _s_t_a_r_t, _i_n_t _e_n_d, _i_n_t _n_l_i_n_e_s);
} _V_i_r_t_S_c_r;
The first three fields in this structure are "private", for use
only within the implementation of the "public" functions. The
remaining fields are all function pointers, and are described
below. Note that all functions have at least one parameter,
which is a pointer to the instance of the VirtScr in question.
This is always referred to as vs below. Note also that the top-
left-hand corner of the window is taken to be (0,0).
v_new(vs)
Obtain a new VirtScr, and return a pointer to it. This is
not used at present, and should return _N_U_L_L.
v_close(vs)
Close the window to which vs refers.
v_rows(vs)
Return the number of rows in vs.
_P_a_g_e _1_0 _2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2
_X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s _1_1
v_cols(vs)
Return the number of columns in vs.
v_clear_all(vs)
Clear the window completely.
v_clear_line(vs, int row, int col)
Clear the specified line, from the given column to the right
hand edge of the window, inclusive.
v_goto(vs, int row, int col)
Move the cursor to the specified row and column.
v_advise(vs, int row, int col, int index, char *str)
This function is called when the editor is about to produce
some output on the same line as the last output, but
separate from it by one or more characters. The destination
position is the coordinate pair (row, col + index), and str
contains the string of characters which are in the window
starting at position (row, col). Where there is a cost
incurred by moving the cursor to a specific screen position,
the terminal interface module may decide to write the
intervening characters to the screen rather than using a
specific "move cursor" sequence, in order to minimise the
number of characters written to the terminal.
Note that for many environments, the cost of re-positioning
the cursor is nil, and under these circumstances this
function need not do anything.
v_write(vs, int row, int col, char *str)
Write the specified string of characters into the window,
starting at the specified row and column. The parameters
will be such that the string will always fit into a single
line of the window, i.e. no line-wrapping is necessary;
however, it is quite possible for the string to end on the
last character of a line, and some implementations will need
to take special precautions to handle this correctly.
v_putc(vs, int row, int col, int ch)
This is like v_write but for a single character.
v_set_colour(vs, int colour)
Set the colour for all subsequent output (including clearing
of lines or the whole window) to the specified colour. The
meaning of the value is system-specific.
v_colour_cost(vs)
Return the number of extra characters which are taken up in
the window by a colour change. This is almost always 0, but
there exist some terminals for which it is not (see the "sg"
_t_e_r_m_c_a_p capability).
_2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2 _P_a_g_e _1_1
_1_2 _X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s
v_flush(vs)
Flush all screen output, and move the cursor on the screen
to the correct position. The screen need not actually be
updated until either this function is called, or
xvi_handle_event() returns.
v_beep(vs)
Beep. It is acceptable to flash the screen or window if no
audio facility is available.
v_insert(vs, int row, int col, char *str)
This function inserts the given string at the given
position, pushing any other characters on the same row to
the right. If such a facility is not available, the
function pointer should be set to _N_U_L_L.
v_scroll(vs, int start, int end, int nlines)
This function scrolls the set of lines between start and end
(inclusive) by nlines lines. If nlines is positive, _n_o_r_m_a_l
scrolling should be done, i.e. the lines should be moved
upwards with respect to the window. If nlines is negative,
scrolling should be in the reverse direction. The lines
which are left by the scrolling should be cleared. The
function should return non-zero if the scrolling was
successful, otherwise 0.
If scrolling is not available, the function pointer should
be set to _N_U_L_L.
_4._3. _P_a_r_a_m_e_t_e_r_s
Default values should be #_d_e_f_i_n_ed for certain parameters as
follows:
__________________________________________
| Parameter Name| Type | #define name |
|________________|__________|________________|
| syscolour | numeric| DEF_SYSCOLOUR|
| colour | numeric| DEF_COLOUR |
| statuscolour | numeric| DEF_STCOLOUR |
| roscolour | numeric| DEF_ROSCOLOUR|
| helpfile | string | HELPFILE |
|_f_o_r_m_a_t__________|__s_t_r_i_n_g___|__D_E_F___T_F_F________|
_4._4. _F_i_l_e _F_o_r_m_a_t_s
The functions in xvi which read and write text files are aware of
several different newline conventions (for example, "\n" on UNIX,
"\r\n" on MS-DOS, and so on), so that any version of the editor
can read and write any of the supported formats. The value of
the format parameter (which can be set to "unix", "msdos",
"macintosh", etc.) determines which format is currently being
used. If you are porting xvi to a system with a newline
convention which isn't one of those currently supported (see the
table called _t_f_t_a_b_l_e in _f_i_l_e_i_o._c) you may have to add a new entry
_P_a_g_e _1_2 _2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2
_X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s _1_3
to the table.
Unfortunately, the current design is not as general as it ought
to be. If you happen to be porting to VMS, or some other system
which doesn't use either a single character or a consecutive pair
of characters to represent a newline, you will have quite a lot
of work to do if you want to retain the facility for converting
between file formats within the editor.
In any case, your system interface module should define _D_E_F__T_F_F
to be the index of the entry in tftable which represents the
default format for your system. This is the value for
_P_e_n(_P__f_o_r_m_a_t) which will be compiled into the parameter table.
_4._5. _N_o_t_e_s _o_n _T_e_r_m_c_a_p _I_m_p_l_e_m_e_n_t_a_t_i_o_n
There exists a termcap implementation of the terminal interface,
currently only used for the UNIX port. This module could quite
easily be re-used for other systems if desired; the following
routines would need to be defined by the system module:
void foutch(int c)
Output a single character to the terminal. This must be
implemented as a function, not a macro, because it is passed
as a parameter into the _t_e_r_m_c_a_p library.
void moutch(int c)
Same as _f_o_u_t_c_h() except that it can be implemented as a
macro. This will be used by the _t_e_r_m_c_a_p interface module to
write characters to the screen.
void oflush(void)
Flush buffered output to the terminal.
_4._6. _E_n_t_e_r_i_n_g/_L_e_a_v_i_n_g _V_i_s_u_a_l _M_o_d_e
Some facility is commonly necessary for the system interface
module to be able to tell the terminal interface module to enter
or exit _v_i_s_u_a_l mode. This might mean changing the terminal state
between "raw" and "cooked" modes, or switching display pages. No
specific interface for this is defined, although the standard
UNIX and MS-DOS implementations do use such a facility, and the
interface functions for both systems are identically defined.
_4._7. _F_u_n_c_t_i_o_n _K_e_y_s/_M_o_u_s_e _H_a_n_d_l_i_n_g
Function key values are coded into a set of #_d_e_f_i_n_ed constants in
the file _a_s_c_i_i._h; e.g. the value _K__U_A_R_R_O_W might be given as input
when the keyboard up-arrow key has been pressed.
If the global variable _S_t_a_t_e is not equal to _N_O_R_M_A_L, all function
keys except for a backspace key are invalid input. If an invalid
key is pressed, the safest strategy may be to beep and wait for
another key to be pressed. _N_O_R_M_A_L is defined in _x_v_i._h.
_2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2 _P_a_g_e _1_3
_1_4 _X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s
Another facility which may be provided is handling mouse input on
systems where it is available. The strategy for interpreting
mouse input is controlled by the _m_o_u_s_e_c_l_i_c_k() function (in
_m_o_u_s_e._c); the idea is to make the strategy independent of any
specific device interface. If a mouse button is pressed before a
keyboard key is pressed, the following routine should be called:
_m_o_u_s_e_c_l_i_c_k(_i_n_t _r_o_w, _i_n_t _c_o_l_u_m_n);
where row and column are the current co-ordinates, counted in
character positions, of the mouse pointer within the screen or
editing window. If the mouse is moved while a button is held
down, the routine
_m_o_u_s_e_d_r_a_g(_i_n_t _s_t_a_r_t_r_o_w, _i_n_t _e_n_d_r_o_w, _i_n_t _s_t_a_r_t_c_o_l_u_m_n, _i_n_t _e_n_d_c_o_l_u_m_n);
should be called with co-ordinates describing the movement. If
the global variable _S_t_a_t_e is not equal to _N_O_R_M_A_L, mouse input can
be ignored altogether.
All this will be considerably tidied up at a later stage, when we
have proper _x_v_E_v_e_n_t types for function keys and mouse actions.
_4._8. _M_a_i_n
Finally, the system interface module must provide a main()
function. This function must call xvi_startup(vs, argc, argv,
env) at startup, with parameters as follows:
VirstScr *vs;
This is a pointer to the VirtScr structure for the first
window, or for the terminal screen.
int argc, char **argv;
These are as for a main() function.
char *env;
This is an environment string, normally the return value
from getenv("XVINIT"). If the concept of environment
variables does not exist, a string of the form
"source _f_i_l_e_n_a_m_e" may be passed instead, so as to allow
users to localise their usage of the editor.
The return value from xvi_startup() is a pointer, which will be
used in future to identify the window for input events. For now,
it should be stored in the VirtScr's pv_window field.
Having called xvi_startup(), input events may then be passed to
the editor by calling xvi_handle_event with a pointer to an
xvEvent structure as the sole argument. This structure is
defined as follows:
_P_a_g_e _1_4 _2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2
_X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s _1_5
_t_y_p_e_d_e_f _s_t_r_u_c_t _e_v_e_n_t {
_e_n_u_m {
_E_v__c_h_a_r,
_E_v__t_i_m_e_o_u_t
} _e_v__t_y_p_e;
_u_n_i_o_n {
/* _E_v__c_h_a_r: */
_i_n_t _e_v_u__i_n_c_h_a_r;
/* _E_v__t_i_m_e_o_u_t: */
} _e_v__u;
} _x_v_E_v_e_n_t;
#_d_e_f_i_n_e _e_v__i_n_c_h_a_r _e_v__u._e_v_u__i_n_c_h_a_r
The ev_type field is a tag which identifies the type of event
which has occurred. At present, only two events are supported:
an input character from the user, and a timeout. The union which
follows contains data associated with each event type; currently
only the type Ev_char requires data, as may be seen. The #_d_e_f_i_n_e
for ev_inchar is provided purely for convenience.
The return value from xvi_handle_event() is a long integer value
which is the time in milliseconds for which the editor is
prepared to wait for more input. If no input arrives within that
time, the function should be called again with an event of type
Ev_timeout. The timeout value returned may be 0L, indicating
that no timeout is necessary. It is very important that timeouts
should actually be implemented because they are needed for the
_p_r_e_s_e_r_v_e facility.
Currently, if a keyboard interrupt is received,
_x_v_i__h_a_n_d_l_e__e_v_e_n_t() need not be called (it should, in any case,
never be called from an asynchronous interrupt or signal handler)
but the global variable _k_b_d_i_n_t_r should be set to a non-zero
value.
_5. _D_A_T_A _S_T_R_U_C_T_U_R_E_S
Structures used in xvi are all typedef'd, and all begin with a
capital letter. They are defined in _x_v_i._h. The following data
structures are defined:
_5._1. _L_i_n_e
This structure is used to hold a single text line. It contains
forward and backward pointers which are connected together to
form a two-way linked list. It also contains a pointer to an
allocated text buffer, an integer recording the number of bytes
allocated for the text, and the line number (an unsigned long).
The text is null-terminated, and the space allocated for it may
_2_5_t_h _S_e_p_t_e_m_b_e_r _1_9_9_2 _P_a_g_e _1_5
_1_6 _X_v_i _S_o_u_r_c_e _C_o_d_e _N_o_t_e_s
be grown but is never shrunk. The maximum size of this space is
given by _M_A_X__L_I_N_E__L_E_N_G_T_H.
The line number is used when showing line numbers on screen, but