summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/COMMAND/TCMD1B.ASM
blob: 7a45e9d2bd1cbab85d4a0a95aa76ed9fc2f40218 (plain) (blame)
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
 page 80,132
;	SCCSID = @(#)tcmd1b.asm 1.1 85/05/14
;	SCCSID = @(#)tcmd1b.asm 1.1 85/05/14
TITLE	PART4 COMMAND Transient routines.

;	Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER

.xlist
.xcref
	INCLUDE DOSSYM.INC
	INCLUDE comseg.asm
	INCLUDE comsw.asm		;AC000;
	INCLUDE comequ.asm
	INCLUDE ioctl.inc		;AN000;
	INCLUDE ea.inc			;AN030;
.list
.cref


TRANDATA	SEGMENT PUBLIC BYTE	;AC000;
	EXTRN	badcpmes_ptr:word	;AC022;
	EXTRN	Extend_buf_ptr:word	;AC000;
	EXTRN	Extend_buf_sub:byte	;AN000;
	EXTRN	inornot_ptr:word
	EXTRN	msg_disp_class:byte	;AC000;
	EXTRN	parse_erase:byte	;AC000;
	EXTRN	parse_mrdir:byte	;AC000;
	EXTRN	parse_rename:byte	;AC000;
	EXTRN	parse_vol:byte		;AC000;
	EXTRN	PauseMes_ptr:word
	EXTRN	renerr_ptr:word
	EXTRN	slash_p_syn:word	;AC000;
	EXTRN	volmes_ptr:word 	;AC000;
	EXTRN	volmes_ptr_2:word	;AC000;
	EXTRN	volsermes_ptr:word	;AC000;
	EXTRN	xa_cp:byte		;AN030;
TRANDATA	ENDS

TRANSPACE	SEGMENT PUBLIC BYTE	;AC000;
	EXTRN	bytcnt:word
	EXTRN	charbuf:byte
	EXTRN	comsw:word
	EXTRN	cpyflag:byte		;AC000;
	EXTRN	curdrv:byte
	EXTRN	destinfo:byte
	EXTRN	destisdir:byte
	EXTRN	dirbuf:byte
	EXTRN	msg_numb:word		;AN022;
	EXTRN	one_char_val:byte
	EXTRN	parse1_addr:dword	;AN000;
	EXTRN	parse1_syn:word 	;AN000;
	EXTRN	srcbuf:byte		;AN000;
	EXTRN	string_ptr_2:word	;AN000;
	EXTRN	TPA:word
	EXTRN	vol_drv:byte
	EXTRN	vol_ioctl_buf:byte	;AC000;
	EXTRN	vol_label:byte		;AC000;
	EXTRN	vol_serial:dword	;AC000;
	EXTRN	xa_cp_out:byte		;AN030;
	EXTRN	xa_cp_length:word	;AN030;
	EXTRN	xa_list_attr:word	;AC030;
	EXTRN	zflag:byte
TRANSPACE	ENDS

TRANCODE	SEGMENT PUBLIC BYTE

ASSUME	CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING

;---------------

TRANSPACE	SEGMENT PUBLIC BYTE	;AC000;
	EXTRN	arg:byte		; the arg structure!
transpace   ends
;---------------

	EXTRN	cerror:near
	EXTRN	error_output:near
	EXTRN	notest2:near
	EXTRN	slashp_erase:near	;AN000;
	EXTRN	std_printf:near
	EXTRN	tcommand:near

	PUBLIC	badpath_err		;AN022;
	PUBLIC	crename
	PUBLIC	erase
	PUBLIC	extend_setup		;AN022;
	PUBLIC	Get_ext_error_number	;AN022;
	PUBLIC	Get_file_code_page_tag	;AN000;
	PUBLIC	pause
	PUBLIC	Set_ext_error_msg	;AN000;
	PUBLIC	set_file_code_page	;AN000;
	PUBLIC	typefil
	PUBLIC	volume


assume	ds:trangroup,es:trangroup

	break	Pause
assume	ds:trangroup,es:trangroup

PAUSE:
	mov	dx,offset trangroup:pausemes_ptr
	call	std_printf
	invoke	GetKeystroke
	invoke	crlf2
	return

	break	Erase

;****************************************************************
;*
;* ROUTINE:	DEL/ERASE - erase file(s)
;*
;* FUNCTION:	PARSE command line for file or path name and /P
;*		and invoke PATHCRUNCH.	If an error occurs, set
;*		up an error message and transfer control to CERROR.
;*		Otherwise, transfer control to NOTEST2 if /P not
;*		entered or SLASHP_ERASE if /P entered.
;*
;* INPUT:	command line at offset 81H
;*
;* OUTPUT:	if no error:
;*		FCB at 5ch set up with filename(s) entered
;*		Current directory set to entered directory
;*
;****************************************************************

assume	ds:trangroup,es:trangroup

ERASE:
	mov	si,81H				;AC000; get command line
	mov	comsw,0 			;AN000; clear switch indicator
	mov	di,offset trangroup:parse_erase ;AN000; Get adderss of PARSE_erase
	xor	cx,cx				;AN000; clear cx,dx

erase_scan:
	xor	dx,dx				;AN000;
	invoke	parse_with_msg			;AC018; call parser
	cmp	ax,end_of_line			;AN000; are we at end of line?
	jz	good_line			;AN000; yes - done parsing
	cmp	ax,result_no_error		;AC000; did we have an error?
	jnz	errj2				;AC000; yes exit

	cmp	parse1_syn,offset trangroup:slash_p_syn ;AN000; was /P entered?
	je	set_erase_prompt		;AN000; yes - go set prompt

;
; Must be filespec since no other matches occurred. move filename to srcbuf
;
	push	si				;AC000; save position in line
	lds	si,parse1_addr			;AC000; get address of filespec
	cmp	byte ptr[si+1],colon_char	;AC000; drive specified?
	jnz	Erase_drive_ok			;AC000; no - continue
	cmp	byte ptr[si+2],end_of_line_out	;AC000; was only drive entered?
	jnz	erase_drive_ok			;AC000; no - continue
	mov	ax,error_file_not_found 	;AN022; get message number in control block
	jmp	short extend_setup		;AC000; exit

erase_drive_ok:
	invoke	move_to_srcbuf			;AC000; move to srcbuf
	pop	si				;AC000; get position back
	jmp	short erase_scan		;AN000; continue parsing

set_erase_prompt:
	cmp	comsw,0 			;AN018; was /P already entered?
	jz	ok_to_set_erase_prompt		;AN018; no go set switch
	mov	ax,moreargs_ptr 		;AN018; set up too many arguments
	invoke	setup_parse_error_msg		;AN018; set up an error message
	jmp	short errj2			;AN018; exit

ok_to_set_erase_prompt: 			;AN018;
	inc	comsw				;AN000; indicate /p specified
	jmp	short erase_scan		;AN000; continue parsing

good_line:					;G  We know line is good
	invoke	pathcrunch
	jnc	checkdr
	mov	ax,[msg_numb]			;AN022; get message number
	cmp	ax,0				;AN022; was message flag set?
	jnz	extend_setup			;AN022; yes - print out message
	cmp	[destisdir],0			; No CHDIRs worked
	jnz	badpath_err			;AC022; see if they should have

checkdr:
	cmp	comsw,0 			;AN000; was /p specified
	jz	notest2j			;AN000; no - go to notest2
	jmp	slashp_erase			;AN000; yes - go to slashp_erase

notest2j:
	jmp	notest2

badpath_err:					;AN022; "Path not found" message
	mov	ax,error_path_not_found 	;AN022; set up error number

extend_setup:					;AN022;
	mov	msg_disp_class,ext_msg_class	;AN022; set up extended error msg class
	mov	dx,offset TranGroup:Extend_Buf_ptr ;AC022; get extended message pointer
	mov	Extend_Buf_ptr,ax		;AN022; get message number in control block
errj2:						;AC022; exit jump
	jmp	Cerror				;AN022;

	break	Rename

; ****************************************************************
; *
; * ROUTINE:	 CRENAME - rename file(s)
; *
; * FUNCTION:	 PARSE command line for one full filespec and one
; *		 filename.  Invoke PATHCRUNCH on the full filespec.
; *		 Make sure the second filespec only contains a
; *		 filename.  If both openands are valid, attempt
; *		 to rename the file.
; *
; * INPUT:	 command line at offset 81H
; *
; * OUTPUT:	 none
; *
; ****************************************************************

assume	ds:trangroup,es:trangroup

CRENAME:

	mov	si,81H				;AC000; Point to command line
	mov	di,offset trangroup:parse_rename;AN000; Get adderss of PARSE_RENAME
	xor	cx,cx				;AN000; clear cx,dx
	xor	dx,dx				;AN000;
	invoke	parse_with_msg			;AC018; call parser
	cmp	ax,result_no_error		;AC000; did we have an error?
	jz	crename_no_parse_error		;AC000; no - continue
	JMP	crename_parse_error		;AC000; Yes, fail. (need long jump)

;
;  Get first file name returned from parse into our buffer
;
crename_no_parse_error:
	push	si				;AN000; save position in line
	lds	si,parse1_addr			;AN000; get address of filespec
	invoke	move_to_srcbuf			;AN000; move to srcbuf
	pop	si				;AN000; restore position in line

	xor	dx,dx				;AN000; clear dx
	invoke	parse_with_msg			;AC018; call parser
	cmp	ax,result_no_error		;AN000; did we have an error?
	JNZ	crename_parse_error		;AN000; Yes, fail.

;
;  Check the second file name for drive letter colon
;
	push	si				;AN000; save position in line
	lds	si,parse1_addr			;AC000; get address of path

	mov	al,':'                          ;AC000;
	cmp	[si+1],al			;AC000; Does the 2nd parm have a drive spec?
	jnz	ren_no_drive			;AN000; Yes, error
	mov	msg_disp_class,parse_msg_class	;AN000; set up parse error msg class
	mov	dx,offset TranGroup:Extend_Buf_ptr  ;AC000; get extended message pointer
	mov	Extend_Buf_ptr,BadParm_ptr	;AN000; get "Invalid parameter" message number

	pop	si				;AN000;
crename_parse_error:				;AC022;
	jmp	short errj			;AC000;

;
;  Get second file name returned from parse into the fCB.  Save
;  character after file name so we can later check to make sure it
;  isn't a path character.
;

ren_no_drive:
	mov	di,FCB+10H			;AC000; set up to parse second file name
	mov	ax,(Parse_File_Descriptor SHL 8) OR 01H ;AC000;
	int	int_command			;AC000; do the function
	lodsb					;AC000; Load char after filename
	mov	one_char_val,al 		;AN000; save char after filename
	pop	si				;AN000; get line position back

;
; We have source and target.  See if any args beyond.
;

	mov	di,offset trangroup:parse_rename;AC000; get address of parse_rename
	invoke	parse_check_eol 		;AC000; are we at end of line?
	jnz	crename_parse_error		;AN000; no, fail.

	invoke	pathcrunch
	mov	dx,offset trangroup:badcpmes_ptr
	jz	errj2				; If 1st parm a dir, print error msg
	jnc	notest3
	mov	ax,[msg_numb]			;AN022; get message number
	cmp	ax,0				;AN022; was message flag set?
	jnz	extend_setup			;AN022; yes - print out message
	cmp	[destisdir],0			; No CHDIRs worked
	jz	notest3 			; see if they should have
	Jmp	badpath_err			;AC022; set up error

notest3:
	mov	al,one_char_val 		;AN000; move char into AX
	mov	dx,offset trangroup:inornot_ptr ; Load invalid fname error ptr
	invoke	pathchrcmp			; Is the char in al a path sep?
	jz	errj				; Yes, error - 2nd arg must be
						;  filename only.

	mov	ah,FCB_Rename
	mov	dx,FCB
	int	int_command
	cmp	al, 0FFH			; Did an error occur??
	jnz	renameok

	invoke	get_ext_error_number		;AN022; get extended error
	SaveReg <AX>				;AC022; Save results
	mov	al, 0FFH			; Restore original error state

renameok:
	push	ax
	invoke	restudir
	pop	ax
	inc	al
	retnz

	RestoreReg  <AX>			;AC022; get the error number back
	cmp	ax,error_file_not_found 	;AN022; error file not found?
	jz	use_renerr			;AN022; yes - use generic error message
	cmp	ax,error_access_denied		;AN022; error file not found?
	jz	use_renerr			;AN022; yes - use generic error message
	jmp	extend_setup			;AN022; need long jump - use extended error

use_renerr:
	mov	dx,offset trangroup:RenErr_ptr	;AC022;

ERRJ:
	jmp	Cerror

ret56:	ret

	break	Type

;****************************************************************
;*
;* ROUTINE:	TYPEFIL - Display the contents of a file to the
;*		standard output device
;*
;* SYNTAX:	TYPE filespec
;*
;* FUNCTION:	If a valid filespec is found, read the file until
;*		1Ah and display the contents to STDOUT.
;*
;* INPUT:	command line at offset 81H
;*
;* OUTPUT:	none
;*
;****************************************************************

assume	ds:trangroup,es:trangroup

TYPEFIL:
	mov	si,81H
	mov	di,offset trangroup:parse_mrdir ;AN000; Get adderss of PARSE_MRDIR
	xor	cx,cx				;AN000; clear cx,dx
	xor	dx,dx				;AN000;
	invoke	parse_with_msg			;AC018; call parser
	cmp	ax,result_no_error		;AC000; did we have an error?
	jnz	typefil_parse_error		;AN000; yes - issue error message

	push	si				;AC000; save position in line
	lds	si,parse1_addr			;AC000; get address of filespec
	invoke	move_to_srcbuf			;AC000; move to srcbuf
	pop	si				;AC000; get position back
	mov	di,offset trangroup:parse_mrdir ;AC000; get address of parse_mrdir
	invoke	parse_check_eol 		;AC000; are we at end of line?
	jz	gottarg 			;AC000; yes - continue

typefil_parse_error:				;AN000; no - set up error message and exit
	jmp	Cerror

gottarg:
	invoke	setpath
	test	[destinfo],00000010b		; Does the filespec contain wildcards
	jz	nowilds 			; No, continue processing
	mov	dx,offset trangroup:inornot_ptr ; Yes, report error
	jmp	Cerror
nowilds:
	mov	ax,ExtOpen SHL 8		;AC000; open the file
	mov	bx,read_open_mode		;AN000; get open mode for TYPE
	xor	cx,cx				;AN000; no special files
	mov	dx,read_open_flag		;AN000; set up open flags
	mov	di,-1				;AN030; no parm list
	mov	si,offset trangroup:srcbuf	;AN030; get file name
	int	int_command
	jnc	typecont			; If open worked, continue. Otherwise load

Typerr: 					;AN022;
	push	cs				;AN022; make sure we have local segment
	pop	ds				;AN022;
	invoke	set_ext_error_msg		;AN022;

Typerr2:					;AN022;
	mov	string_ptr_2,offset trangroup:srcbuf ;AC022; get address of failed string
	mov	Extend_buf_sub,one_subst	;AC022; put number of subst in control block
	jmp	cerror				;AC022; exit

typecont:
	mov	bx,ax				;AC000; get  Handle
	mov	cx,stdout			;AN000; set output to STDOUT
	call	set_file_code_page		;AN000; Set code page on output device
	jc	typerr2 			;AN022; exit if error

	mov	zflag,0 			; Reset ^Z flag
	mov	ds,[TPA]
	xor	dx,dx
ASSUME	DS:NOTHING

typelp:
	cmp	cs:[zflag],0			;AC050; Is the ^Z flag set?
	retnz					; Yes, return
	mov	cx,cs:[bytcnt]			;AC056; No, continue
	mov	ah,read
	int	int_command
	jc	typerr				;AN022; Exit if error
	mov	cx,ax
	jcxz	typelp_ret			;AC000; exit if nothing read
	push	ds
	pop	es				; Check to see if a ^Z was read.
assume es:nothing
	xor	di,di
	push	ax
	mov	al,1ah
	repnz	scasb
	pop	ax
	xchg	ax,cx
	cmp	ax,0
	jnz	foundz				; Yes, handle it
	cmp	byte ptr [di-1],1ah		; No, double check
	jnz	typecont2			; No ^Z, continue

foundz:
	sub	cx,ax				; Otherwise change cx so that only those
	dec	cx				;  bytes up to but NOT including the ^Z
	push	cs				;  will be typed.
	pop	es
assume es:trangroup
	not	zflag				; Turn on ^Z flag so that the routine

typecont2:					;  will quit after this write.
	push	bx
	mov	bx,1
	mov	ah,write
	int	int_command
	pop	bx
	jc	Error_outputj
	cmp	ax,cx
	jz	typelp
	dec	cx
	cmp	ax,cx
	retz					; One less byte OK (^Z)

Error_outputj:
	mov	bx,1
	mov	ax,IOCTL SHL 8
	int	int_command
	test	dl,devid_ISDEV
	retnz					; If device, no error message
	jmp	error_output

typelp_ret:
	ret

	break	Volume
assume	ds:trangroup,es:trangroup

;
; VOLUME command displays the volume ID on the specified drive
;
VOLUME:

	mov	si,81H
	mov	di,offset trangroup:parse_vol	;AN000; Get adderss of PARSE_VOL
	xor	cx,cx				;AN000; clear cx,dx
	xor	dx,dx				;AN000;
	invoke	parse_with_msg			;AC018; call parser
	cmp	ax,end_of_line			;AC000; are we at end of line?
	jz	OkVolArg			;AC000; Yes, display default volume ID
	cmp	ax,result_no_error		;AC000; did we have an error?
	jnz	BadVolArg			;AC000; Yes, fail.
;
; We have parsed off the drive.  See if there are any more chars left
;

	mov	di,offset trangroup:parse_vol	;AC000; get address of parse_vol
	xor	dx,dx				;AC000;
	invoke	parse_check_eol 		;AC000; call parser
	jz	OkVolArg			;AC000; yes, end of road
;
; The line was not interpretable.  Report an error.
;
badvolarg:
	jmp	Cerror
;
; Find the Volume ID on the disk.
;
PUBLIC	OkVolArg
OKVOLARG:
	invoke	crlf2
	mov	al,blank			;AN051; Print out a blank
	invoke	print_char			;AN051;   before volume message
	push	ds
	pop	es
;
; Volume IDs are only findable via extended FCBs or find_first with attributes
; of volume_id ONLY.
;

	mov	di,FCB-7			; Point to extended FCB beginning
	mov	al,-1				; Tag to indicate Extention
	stosb
	xor	ax,ax				; Zero padding to volume label
	stosw
	stosw
	stosb
	mov	al,attr_volume_ID		; Look for volume label
	stosb
	inc	di				; Skip drive byte; it is already set
	mov	cx,11				; fill in remainder of file
	mov	al,'?'
	rep	stosb
;
; Set up transfer address (destination of search first information)
;
	mov	dx,offset trangroup:dirbuf
	mov	ah,set_DMA
	int	int_command
;
; Do the search
;
	mov	dx,FCB-7
	mov	ah,Dir_Search_First
	int	int_command

;********************************
; Print volume ID info

	push	ax				;AC000; AX return from SEARCH_FIRST for VOL ID
	mov	al,DS:[FCB]			;AC000; get drive letter
	add	al,'@'
	cmp	al,'@'
	jnz	drvok
	mov	al,[curdrv]
	add	al,capital_A
drvok:
	mov	vol_drv,al			;AC000; get drive letter into argument
	pop	ax				;AC000; get return code back
	or	al,al				;AC000; volume label found?
	jz	Get_vol_name			;AC000; volume label exists - go get it
	mov	dx,offset trangroup:VolMes_ptr_2 ;AC000; set up no volume message
	jmp	short print_serial		;AC000; go print it

Get_vol_name:
	mov	di,offset trangroup:charbuf
	mov	dx,di
	mov	si,offset trangroup:dirbuf + 8	;AN000;  3/3/KK
	mov	cx,11				;AN000;  3/3/KK
	rep	movsb				;AN000;  3/3/KK

	xor	al,al				;AC000; store a zero to terminate the string
	stosb
	mov	dx,offset trangroup:VolMes_ptr	;AC000; set up message

PRINT_SERIAL:

;
; Attempt to get the volume serial number from the disk.  If an error
; occurs, do not print volume serial number.
;

	push	dx				;AN000; save message offset
	mov	ax,(GetSetMediaID SHL 8)	;AC036; Get the volume serial info
	mov	bl,DS:[FCB]			;AN000; get drive number from FCB
	mov	dx,offset trangroup:vol_ioctl_buf ;AN000;target buffer
	int	int_command			;AN000; do the call
	pop	dx				;AN000; get message offset back
	jc	printvol_end			;AN000; if error, just go print label
	call	std_printf			;AC000; go print volume message
	mov	al,blank			;AN051; Print out a blank
	invoke	print_char			;AN051;   before volume message
	mov	dx,offset trangroup:VolSerMes_ptr ;AN000; get serial number message

printvol_end:
	jmp	std_printf			;AC000; go print and exit

;****************************************************************
;*
;* ROUTINE:	Set file Code page
;*
;* FUNCTION:	Check CPSW status, if CPSW is on, get the file's
;*		code page and attempt to invoke it on the
;*		output device.
;*
;* INPUT:	file handle in BX - unless copyflg is set
;*		handle of output device in CX
;*
;* OUTPUT:	if carry set  (code page invoke failed)
;*		   ax = extended error
;*		otherwise
;*		   ax modified
;*
;*
;****************************************************************

Set_file_code_page proc near			;AN000;

	push	bx				;AN000; save registers
	push	di				;AN000;
	push	dx				;AN000;

	cmp	cpyflag,1			;AN000; were we called from COPY?
	jz	Already_have_cp 		;AN000; yes - already have code page
	call	get_file_code_page_tag		;AN000; get the file's code page
	jc	cp_set_error			;AN000; if error - just continue

already_have_cp:				;AN000; See what was returned.
	mov	ax,(file_times SHL 8)+set_XA	;AC030; set code page
	mov	di,offset trangroup:xa_cp_out	;AC030; offset of attr list
	mov	bx,cx				;AN000; get handle of output device
	int	int_command			;AN000;
	jnc	set_file_cp_end 		;AN000; all okay - return
cp_set_error:
	pop	dx				;AC030; we don't restore DX for error -
	call	Set_Ext_Error_msg		;AN000;    we return error message
	jmp	short set_file_cp_exit		;AC030; exit

set_file_cp_end:				;AN000; finished
	pop	dx				;AN000; restore registers

set_file_cp_exit:
	pop	di				;AN000;
	pop	bx				;AN000;

	ret					;AN000; return

Set_file_code_page endp 			;AN000;


;****************************************************************
;*
;* ROUTINE:	Get file Code page tag
;*
;* FUNCTION:	Get code page file attribute.
;*
;* INPUT:	file handle in BX
;*
;* OUTPUT:	if error - carry set
;*		otherwise - xa_list_attr set to file's code page
;*
;*		AX and DI modified
;*
;****************************************************************


Get_file_code_page_tag proc near		;AN000;

	push	cx				;AN030;
	push	si				;AN030;
	push	di				;AN030;
	mov	xa_list_attr,0			;AN030; initialize code page
	mov	ax,(file_times SHL 8)+get_XA	;AC030; get extended attributes
	mov	si,offset trangroup:xa_cp	;AN030; get xa request buffer
	mov	di,offset trangroup:xa_cp_out	;AC030; get xa output buffer
	mov	cx,xa_cp_length 		;AN030; length of buffer
	int	int_command			;AN000;
	pop	di				;AN030;
	pop	si				;AN030;
	pop	cx				;AN030;

	ret					;AN000; return

Get_file_code_page_tag endp			;AN000;


;****************************************************************
;*
;* ROUTINE:	Set_ext_error_msg
;*
;* FUNCTION:	Sets up extended error message for printing
;*
;* INPUT:	return from INT 21
;*
;* OUTPUT:	extended error message set up in extended error
;*		buffer.
;*
;****************************************************************

Set_ext_error_msg proc near			;AN000;

	call	get_ext_error_number		;AC022; get the extended error
	mov	msg_disp_class,ext_msg_class	;AN000; set up extended error msg class
	mov	dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
	mov	Extend_Buf_ptr,ax		;AN000; get message number in control block
	stc					;AN000; make sure carry is set

	ret					;AN000; return

Set_ext_error_msg endp				;AN000;

;****************************************************************
;*
;* ROUTINE:	Get_ext_error_number
;*
;* FUNCTION:	Does get extended error function call
;*
;* INPUT:	return from INT 21
;*
;* OUTPUT:	AX - extended error number
;*
;****************************************************************

Get_ext_error_number proc near			;AN022;

	SaveReg <BX,CX,DX,SI,DI,BP,ES,DS>	;AN022; save registers
	mov	ah,GetExtendedError		;AN022; get extended error
	xor	bx,bx				;AN022; clear BX
	int	int_command			;AN022;
	RestoreReg  <DS,ES,BP,DI,SI,DX,CX,BX>	;AN022; restore registers

	ret					;AN022; return

Get_ext_error_number endp			;AN022;

trancode    ends
	    end