  	subroutine dix_smg_sel_files(control)
	implicit none
c
c Select one of the files
c
	include 'dix_def.inc'
	record /control/ control	!:io: control block
c#
	record /file_info/ file
	pointer (p_file,file)
c
	character*(max_screen_width) line
	record /dyn_help/ help_des
c
	integer*4 ipos,k,dis_id,nk,iterm,dis_id1,scr_pos,view_size
	integer*4 p_nam,p_flg,p_siz,i_file,nold,istat,krow,kcol
c
	external dix_msg_filnotop
	external dix_msg_nofileleft
	external dix_int_cld
	integer*4 dix_main_get_files
	integer*4 dix_dcl_parse_table_int
	external lib$get_input
	integer*4 lib$get_input
c
	character*(*) context
	parameter (context = 'EDITFILES')
c
	include '($smgdef)'
c
	call smg$create_virtual_display(2,control.ncols,dis_id1)
	call sys$fao('Directory of !UL files',nk,line,%val(control.n_file))
	call smg$put_chars(dis_id1,line(1:nk),1,1)
c
c Create help page
c
	call help_init_std(control,help_des,'select files',20,15,context)
	call help_key(control,help_des,key_put,
     1         'inserts file(s) to list',context)
	call help_key(control,help_des,key_remove,
     1         'Remove this file',context)
	call help_key(control,help_des,key_exit,
     1         'Return to prev screen',context)
	call help_key(control,help_des,key_enter,
     1         'Return to prev screen and use current file',context)
	call help_key(control,help_des,key_select,
     1         'Set current file',context)
	call help_key(control,help_des,key_fileinfo,
     1         'View file',context)
	call dix_smg_stack_help(control,help_des)
c
c
	p_nam = len(dopointer)+1
	p_siz = control.ncols-10
	p_flg = p_siz-12
	line = ' '
	line(p_nam:) = 'Filename'
	line(p_flg:) = 'Flags'
	line(p_siz:) = '  FileSize'
c
	call smg$put_chars(dis_id1,line(1:control.ncols),2,1,,smg$m_underline)
	call smg$paste_virtual_display(dis_id1,control.paste_id,3,1)
c
c Create scroll window with data
c
	call smg$create_virtual_display(control.n_file,control.ncols,dis_id)
	view_size = min(control.n_file,control.nrows-5)
	call smg$create_viewport(dis_id,1,1,view_size,control.ncols)
c	
	p_file = control.top_file
	k = 1
	do while(p_file .ne. 0)
	  if(p_file .eq. control.cur_file) i_file = k
	  call lib$trim_filespec(file.fnam,line,p_flg-p_nam,nk)
	  call smg$put_chars(dis_id,line(1:nk),k,p_nam)
	  call sys$fao('!10UL',nk,line,%val(file.filesize))
	  call smg$put_chars(dis_id,line(1:nk),k,p_siz)
	  line = 'SEQ'
	  if(file.relative) line = 'REL'
	  if(file.indexed ) line = 'IDX'
	  nk = 3
	  if(file.fixed) then
	    line(nk+1:) = '/FIX'
	    nk = nk + 4
	  end if 
	  if(file.modify) then
	    line(nk+1:) = '/MOD'
	    nk = nk + 4
	  end if 
	  call smg$put_chars(dis_id,line(1:nk),k,p_flg)
	  k = k + 1
	  p_file = file.link.forw
	end do
c
	call smg$paste_virtual_display(dis_id,control.paste_id,5,1)
c
	call smg$put_chars(dis_id,dopointer,i_file,1)
	ipos = i_file
c
	scr_pos = 1
c
10	p_file = control.top_file
	ipos = max(1,min(ipos,control.n_file))
	do k=1,ipos-1
	  p_file = file.link.forw
	end do
c
c Make sure in display
c
	do while(ipos .lt. scr_pos)
	  scr_pos = scr_pos - 1
	  call smg$scroll_viewport(dis_id,smg$m_down,1)
	end do
c
	do while(ipos-scr_pos .ge. view_size)
	  scr_pos = scr_pos + 1
	  call smg$scroll_viewport(dis_id,smg$m_up,1)
	end do
c
	call smg$set_cursor_abs(dis_id,ipos,1)
	call dix_get_key(control,iterm,krow,kcol,context)
15	if(iterm .eq. key_mouse_left) then
	  ipos = krow - 5 +scr_pos	!display starts at 5
	  iterm = key_select
	elseif(iterm .eq. key_mouse_middle) then
	  krow = krow - 4	!display starts at 5
	  if(krow .lt. view_size/2) then
	    iterm = key_prev
	  else
	    iterm = key_next
	  endif
	elseif(iterm .eq. key_mouse_right .or. iterm .eq. key_menu) then
	  call dix_smg_select_menu(control,
     1              'Select,Display,Remove,Newfile',line,
     1              .false.,'Choises',0,0,.true.)
	  if(line(1:1) .eq. 'D') then
	    iterm = key_fileinfo
	  elseif(line(1:1) .eq. 'N') then
	    iterm = key_put
	  elseif(line(1:1) .eq. 'R') then
	    iterm = key_remove
	  elseif(line(1:1) .eq. 'S') then
	    krow = krow - 5 + scr_pos
	    if(krow .le. control.n_file) then
	      ipos = krow
	      iterm = key_enter
	    else
	      goto 10
	    endif
	  endif
	endif	
	if(iterm .eq. key_up) then
	  ipos = ipos-1
	elseif(iterm .eq. key_prev) then
	  ipos = ipos-10
	elseif(iterm .eq. key_next) then
	  ipos = ipos+10
	elseif(iterm .eq. key_top) then
	  ipos = 1
	elseif(iterm .eq. key_bot) then
	  ipos = control.n_file
	elseif(iterm .eq. key_right) then
	elseif(iterm .eq. key_left) then
	elseif(iterm .eq. key_down) then
	  ipos = ipos+1
	elseif(iterm .eq. key_fileinfo) then
c
	  call dix_smg_file_info_scr(control,file)
	elseif(iterm .eq. key_remove) then
c
c Close current file
c
	  if(control.n_file .eq. 1) then
	    call dix_message(control,dix_msg_nofileleft)
	  else
	    call smg$delete_line(dis_id,ipos)
	    call file_close(control,file)
	    call dix_util_link_out(file.link,control.top_file)
	    control.n_file = control.n_file - 1
	    call smg$change_virtual_display(dis_id,control.n_file)
	    view_size = min(control.n_file,control.nrows-5)
	    call smg$change_viewport(dis_id,,,view_size)
	    if(ipos .eq. i_file) then
	      i_file = max(1,i_file-1)
	      call smg$put_chars(dis_id,dopointer,i_file,1)
	    end if
	    if(ipos .gt. control.n_file) ipos =control.n_file
	  endif
	elseif(iterm .eq. key_put) then
	  line = ' '
	  call dix_smg_get_str(control,'filename',line(1:50),iterm)
	  if(line .ne. ' ') then
	    istat = dix_dcl_parse_table_int('OPEN '//line,
     1                             lib$get_input,.true.)
	    if(.not. istat) then
	      call dix_message(control,%val(istat))
	    else
	      nold = control.n_file
	      if(dix_main_get_files(control,'P1',' ',' ',
     1                       .false.,.true.)) then
	        call smg$change_virtual_display(dis_id,control.n_file)
	        view_size = min(control.n_file,control.nrows-5)
	        call smg$change_viewport(dis_id,,,view_size)
	        p_file = control.top_file
	        ipos = 1
	        do k=1,nold
	          p_file = file.link.forw
	          ipos = ipos + 1
	        end do
	        do k=nold+1,control.n_file
	          call lib$trim_filespec(file.fnam,line,70,nk)
	          call smg$put_chars(dis_id,line(1:nk),ipos,3)
	          call sys$fao('!10UL',nk,line,%val(file.filesize))
	          call smg$put_chars(dis_id,line(1:nk),ipos,p_siz)
	          line = 'SEQ'
	          if(file.relative) line = 'REL'
	          if(file.indexed ) line = 'IDX'
	          nk = 3
	          if(file.fixed) then
	            line(nk+1:) = '/FIX'
	            nk = nk + 4
	          end if 
	          if(file.modify) then
	            line(nk+1:) = '/MOD'
	            nk = nk + 4
	          end if 
	          call smg$put_chars(dis_id,line(1:nk),ipos,p_flg)
	          ipos = ipos + 1
	          p_file = file.link.forw
	        end do
	        call smg$put_chars(dis_id,unpointer,i_file,1)
	        i_file = nold + 1
	        call smg$put_chars(dis_id,dopointer,i_file,1)
	        ipos = i_file
	      end if    !we did open some files
	    end if      !parse want oke
	  end if	!user type a filename
	elseif(iterm .eq. key_select) then
	  call smg$put_chars(dis_id,unpointer,i_file,1)
	  i_file = ipos
	  call smg$put_chars(dis_id,dopointer,i_file,1)
	elseif(iterm .eq. key_exit) then
	  goto 90
	elseif(iterm .eq. key_enter) then
	  i_file = ipos
	  goto 90
	elseif(iterm .eq. key_help) then
	  call dix_smg_help(control,context)
	else
	  call dix_mes_invkey(control,context)
	end if
	goto 10
90	p_file = control.top_file
	do k=2,i_file
	  p_file = file.link.forw
	end do
	control.cur_file = p_file
	call smg$delete_virtual_display(dis_id)
	call smg$delete_virtual_display(dis_id1)
	call dix_smg_unstack_help(control)
	call help_exit(help_des)
	return
	end
	subroutine dix_smg_sel_dirs(control,file)
	implicit none
c
c Select desciptions
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	record /file_info/ file		!:io: file block
c#
	record /dyn_help/ help_des
c
	record /des_info/ des_info
	pointer (p_des_info,des_info)
c
	record /des_expanded/ des_expanded
	pointer (p_des_expanded,des_expanded)
c
	character*(max_screen_width) line
	character*(max_err_arg_length) err_arg
c
	character*(*) context
	parameter (context = 'SELDESCRIPTIONS')
c
	integer*4 ipos,k,dis_id,nk,iterm,n_des,i_des,dis_id1,l
	integer*4 scr_pos,view_size,p_nam,p_siz,n_old_des
	integer*4 istat,krow,kcol
c
	logical*4 dix_des_get_all
	logical*4 dix_edit_des
	integer*4 dix_util_get_len_fu
	external dix_msg_filnotop
	external dix_msg_notchanged
c
	include '($smgdef)'
c
c Create help text
c
	call help_init_std(control,help_des,'select descriptions',
     1                    20,15,context)
c
	call help_key(control,help_des,key_remove,
     1         'Remove description',context)
	call help_key(control,help_des,key_exit,
     1         'Return to previous screen',context)
	call help_key(control,help_des,key_editdes,
     1         'Edit description',context)
	call help_key(control,help_des,key_enter,
     1         'Return to prev screen and use current des',context)
	call help_key(control,help_des,key_select,
     1         'Set current description',context)
	call help_key(control,help_des,key_put,
     1         'Add new descriptions',context)
	call help_key(control,help_des,key_viewdes,
     1         'View des file',context)
	call dix_smg_stack_help(control,help_des)
c
c
	n_des = 0
	i_des = 0
	p_des_expanded = file.top_des
	do while(p_des_expanded .ne. 0)
	  n_des = n_des + 1
	  if(p_des_expanded .eq. file.cur_des) i_des = n_des
	  p_des_expanded = des_Expanded.link.forw
	end do
c
	call smg$create_virtual_display(2,control.ncols,dis_id1)
	p_nam = len(dopointer)+1
	p_siz = control.ncols-10
c
	line = ' '
	line(p_nam:) = 'Filename'
	line(p_siz:) = '  Filesize'
	call smg$put_chars(dis_id1,line(1:control.ncols),2,1,,smg$m_underline)
	call smg$paste_virtual_display(dis_id1,control.paste_id,3,1)
c
c Now the data
c
	view_size = min(control.nrows-5,n_des+1)
	call smg$create_virtual_display(n_des+1,control.ncols,dis_id)
	call smg$create_viewport(dis_id,1,1,view_size,control.ncols)
	p_des_expanded = file.top_des
	do k=1,n_des
	  p_des_info = des_expanded.p_des_info
	  call dix_des_display_width(control,des_info,line,nk,p_siz-p_nam)
	  call smg$put_chars(dis_id,line(1:nk),k,p_nam)	  
c
	  call sys$fao('!10UL',nk,line,
     1         %val(des_info.table_nor.count +
     1              des_info.table_vfc.count))
	  call smg$put_chars(dis_id,line(1:nk),k,p_siz)
c
	  p_des_expanded = des_expanded.link.forw
	end do
	call smg$paste_virtual_display(dis_id,control.paste_id,5,1)
c
	if(i_des .gt. 0) call smg$put_chars(dis_id,dopointer,i_des,1)
	ipos = i_des
c
	scr_pos = 1
c
	n_old_des = n_des-1	!to force display
c
10	ipos = max(1,min(ipos,n_des))
c
	if(n_old_des .ne. n_des) then
	  call sys$fao('Directory of !UL descriptions',nk,line,%val(n_des))
	  call smg$put_chars(dis_id1,line(1:nk),1,1)
	  n_old_des = n_des
	endif
c
	if(n_des .gt. 0) then
	  p_des_expanded = file.top_des
	  do k=1,i_des-1
	    p_des_expanded = des_expanded.link.forw
	  end do
	  p_des_info = des_expanded.p_des_info
	else
	  ipos = 1	!set cursor to first line
	endif
c
c Make sure in screen
c
	do while(ipos .lt. scr_pos)
	  scr_pos = scr_pos - 1
	  call smg$scroll_viewport(dis_id,smg$m_down,1)
	end do
	do while(ipos-scr_pos .ge. view_size)
	  scr_pos = scr_pos + 1
	  call smg$scroll_viewport(dis_id,smg$m_up,1)
	end do
c##
	call smg$set_cursor_abs(dis_id,ipos,1)
	call dix_get_key(control,iterm,krow,kcol,context)
c
15	if(iterm .eq. key_mouse_left) then
	  ipos = krow - 5 +scr_pos	!display starts at 5
	  iterm = key_Select
	elseif(iterm .eq. key_mouse_middle) then
	  krow = krow - 4	!display starts at 5
	  if(krow .lt. view_size/2) then
	    iterm = key_prev
	  else
	    iterm = key_next
	  endif
	elseif(iterm .eq. key_mouse_right .or. iterm .eq. key_menu) then
	  call dix_smg_select_menu(control,
     1              'Select,Display,Remove,NewDes',line,
     1              .false.,'Choises',0,0,.true.)
	  if(line(1:1) .eq. 'D') then
	    iterm = key_viewdes
	  elseif(line(1:1) .eq. 'N') then
	    iterm = key_put
	  elseif(line(1:1) .eq. 'R') then
	    iterm = key_remove
	  elseif(line(1:1) .eq. 'S') then
	    krow = krow - 5 + scr_pos
	    if(krow .le. control.n_file) then
	      ipos = krow
	      iterm = key_enter
	    else
	      goto 10
	    endif
	  endif
	endif	
	if(iterm .eq. key_up) then
	  if(ipos .gt. 1) ipos = ipos-1
	elseif(iterm .eq. key_down) then
	  if(ipos .lt. n_des) ipos = ipos+1
	elseif(iterm .eq. key_prev) then
	  ipos = max(1,ipos-10)
	elseif(iterm .eq. key_next) then
	  ipos = min(n_des,ipos+10)
	elseif(iterm .eq. key_top) then
	  ipos = 1
	elseif(iterm .eq. key_bot) then
	  ipos = n_des
	elseif(iterm .eq. key_left) then
	elseif(iterm .eq. key_right) then
	elseif(iterm .eq. key_viewdes) then
	  call dix_smg_view_des_file(control,des_info)
	elseif(iterm .eq. key_put) then
	  line = ' '
	  call dix_smg_get_str(control,'Description file',line(1:50),iterm)
	  if(line .ne. ' ') then
	    nk = dix_util_get_len_fu(line)
c
c Remember current last description
c
	    p_des_expanded = file.top_des
	    k = 0
	    do while(p_des_expanded .ne. 0)
	      k = p_des_expanded
	      p_des_expanded = des_expanded.link.forw
	    enddo
c
	    if(.not. dix_des_get_all(control,file,line(1:nk),
     1                               .false.,.false.)) then
	      call dix_message(control,dix_msg_filnotop,line(1:nk))
	      goto 10
	    endif
	    p_des_expanded = k
	    if(p_des_expanded .eq. 0) then
	      p_des_expanded = file.top_des
	    else
	      p_des_expanded = des_Expanded.link.forw
	    endif
	    do while(p_des_expanded .ne. 0) 
	      p_des_info = des_expanded.p_des_info
	      n_des = n_des + 1
	      call smg$change_virtual_display(dis_id,n_des+1)
	      view_size = min(control.nrows-5,n_des+1)
	      call smg$change_viewport(dis_id,1,1,view_size,control.ncols)
c
	      call sys$fao('!10UL',nk,line,
     1                   %val(des_info.table_nor.count + 
     1                        des_info.table_vfc.count))
	      call smg$put_chars(dis_id,line(1:nk),n_des,p_siz)
c
	      call dix_des_display_width(control,des_info,line,nk,p_siz-p_nam)
	      call smg$put_chars(dis_id,line(1:nk),n_des,p_nam)	  
	      p_des_expanded = des_expanded.link.forw
	    end do
	    call smg$put_chars(dis_id,unpointer,i_des,1)
 	    i_des = n_des
	    call smg$put_chars(dis_id,dopointer,i_des,1)
	    ipos  = n_des
	  end if
	elseif(iterm .eq. key_select) then
	  if(n_des .gt. 0) then
	    call smg$put_chars(dis_id,unpointer,i_des,1)
	    i_des = ipos
	    call smg$put_chars(dis_id,dopointer,i_des,1)
	  end if
	elseif(iterm .eq. key_remove) then
	  if(n_des .gt. 0) then
	    call smg$delete_line(dis_id,ipos,1)
c
c remove all tables from des
c
	    call dix_des_link_out(control,file,des_expanded)
	    n_des = n_des - 1
	    if(n_des .gt. 0) then
c
	      if(i_des .eq. ipos) then
	        call smg$put_chars(dis_id,unpointer,ipos,1)
	        i_des = max(1,ipos-1)
	        ipos = i_des
	        call smg$put_chars(dis_id,dopointer,ipos,1)
	      endif
	    endif
	    view_size = min(control.nrows-5,n_des+1)
	    call smg$change_virtual_display(dis_id,view_size)
	  end if
	elseif(iterm .eq. key_editdes) then
	  if(n_des .gt. 0) then
	    istat = dix_edit_des(control,file,des_info,' ',0,err_arg,
     1                           control.editor)
	    if(istat) then
	      call dix_des_display_width(control,des_info,
     1                      line,nk,p_siz-p_nam)
	      call smg$put_chars(dis_id,line(1:nk),ipos,p_nam)	  
	    else
	      l = dix_util_get_len_fu(err_arg)
	      call dix_message(control,istat,err_arg(1:l))
	    end if
	  endif
	elseif(iterm .eq. key_exit) then
	  goto 90
	elseif(iterm .eq. key_enter) then
	  if(n_des .gt. 0) i_des = ipos
	  goto 90
	elseif(iterm .eq. key_help) then
	  call dix_smg_help(control,context)
	else
	  call dix_mes_invkey(control,context)
	end if
	goto 10
90	if(n_des .eq. 0) then
	  p_des_expanded = 0
	else
	  p_des_expanded = file.top_des
	  do k=1,i_des-1
	    p_des_expanded = des_expanded.link.forw
	  end do
	endif
	file.cur_des = p_des_expanded
c
	call smg$delete_virtual_display(dis_id)
	call smg$delete_virtual_display(dis_id1)
	call dix_smg_unstack_help(control)
	call help_exit(help_des)
c
99	return
	end
	subroutine dix_smg_view_des_file(control,des_info)
	implicit none
c
c View description file
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	record /des_info/ des_info	!:i: description 
c#
	integer*4 lun_memtab,istat,nlin,nk
	character*(max_filename_length) fnam
c
	integer*4 memtab_open
	integer*4 dix_lbr_get_module
c                                  
	if(des_info.in_library .eq. des_in_file) then
	  istat = memtab_open(control,des_info.fnam(1:des_info.nk_fnam),
     1                        lun_memtab,nlin)
	else
          istat = dix_lbr_get_module(control,
     1            des_info.fnam(1:des_info.nk_fnam),
     1            lun_memtab,nlin,des_info.in_library)
	endif
	call dix_des_display(control,des_info,fnam,nk,.true.)
	if(istat) call dix_smg_view_memtab(control,lun_memtab,
     1              fnam(1:nk),18,.false.)
	call memtab_close(control,lun_memtab)
	return
	end
	subroutine dix_smg_view_file(control,lun_inp,header)
	implicit none
c
c View a file open on lun "lun_inp"
c  set header text to "header"
c
	include 'dix_def.inc'
	record /control/ control	!:io: control
	integer*4 lun_inp		!:i: lun on which file open
	character*(*) header		!:i: header text
c#
	integer*4 lun_memtab,nlines,istat
	integer*4 memtab_open_lun
c
c Copy to memtab
c
	rewind(lun_inp)
	istat = memtab_open_lun(control,lun_inp,lun_memtab,nlines)
c
c And display it
c
	if(istat) call dix_smg_view_memtab(control,lun_memtab,
     1                header,18,.false.)
	call memtab_close(control,lun_memtab)
	return
	end
	subroutine dix_smg_view_memtab(control,lun_memtab,
     1              header,view_size,check_bold)
	implicit none
c
c View a file open on LUN_MEMTAB
c  with header "header"
c
	include 'dix_def.inc'
	record /control/ control	!:i: control
	integer*4 lun_memtab             !:i: lun on which memtabfile open
	character*(*) header		!:i: header text
	integer*4 view_size		!:i: length of vieuw_port
	logical check_bold		!:i: check for first char :, => bold
c#
	character*(max_line_length) line,orgline
	integer*4 dis_id,nk,nlin,ipos,jpos,top_line,bpos,nk1
	integer*4 n_lines,width
	logical got_bold
c
	character*(*) bold_seq,norm_seq
        parameter (bold_seq = ESCAPE//'[1;7m')        !bold/reverse
        parameter (norm_seq = ESCAPE//'[m')
c
	logical memtab_read
c
	include '($smgdef)'
c
c Create display
c
	call memtab_get_nlines(lun_memtab,n_lines)
	call memtab_get_max_width(lun_memtab,width)
	width = max(70,min(width,len(line)))
	call smg$create_virtual_display(n_lines,width,dis_id)
	call smg$create_viewport(dis_id,1,1,view_size,
     1              min(width,control.ncols))
	nk1 = min(len(header),width-5)
	call smg$label_border(dis_id,'File:'//header(1:nk1))
c
	call memtab_rewind(lun_memtab)
	nlin = 0
	do while(memtab_read(lun_memtab,nk,line))
	  nlin = nlin + 1
	  orgline = ' '
	  bpos = 1
	  got_bold = .false.
	  if(check_bold) then
	    if(line(1:1) .eq. ':') then
	      orgline(1:1) = 'B'
	      orgline(nk-1:nk-1) = 'X'
	      bpos = 2
	      got_bold = .true.
	    endif
	  else
c
c 
c
10	    ipos = index(line,bold_seq)
	    if(ipos .ne. 0) then
	      jpos = index(line,norm_seq)
	      if(jpos .gt. ipos) then
	        line = line(1:ipos-1)//line(ipos+len(bold_seq):jpos-1)//
     1               line(jpos+len(norm_seq):nk)
	        jpos = jpos - len(bold_seq)-1
	        orgline(ipos:ipos) = 'B'
	        orgline(jpos:jpos) = 'X'
	        nk = nk - len(norm_seq) - len(bold_seq)
	        got_bold = .true.
	        goto 10
	      end if
	    endif
	  endif
	  call smg$put_chars(dis_id,line(bpos:nk),nlin,1)
	  if(got_bold) then
20	    ipos = index(orgline,'B')
	    jpos = index(orgline,'X')
	    if(ipos .ne. 0) then
	      orgline(ipos:ipos) = ' '
	      orgline(jpos:jpos) = ' '
	      call smg$change_rendition(dis_id,nlin,ipos,1,
     1               jpos-ipos+1,smg$m_bold .or. smg$m_reverse)
	      goto 20
	    end if
	  end if
	end do
c
	top_line = max(2,(control.nrows - view_size)/2)
	call smg$paste_virtual_display(dis_id,control.paste_id,top_line,1)
	call  dix_smg_show(control,dis_id,1,'View file')
	call smg$delete_virtual_display(dis_id)
	return
	end

	function dix_smg_find_string(control,dis_id,nk_se,sear_string,
     1                    row,col,nlines,forward)
	implicit none
c
c Find a string in display
c
	include 'dix_def.inc'
	record /control/ control
c
	integer*4 dis_id		!:i: display id
	integer*4 nk_se			!:i: length of search
	character*(*) sear_string	!:i: search string
	integer*4 row			!:o: row found
	integer*4 col			!:o: col found
	integer*4 nlines		!:o: #lines found
	logical*4 forward		!:i: forward search
	logical*4 dix_smg_find_string	!:f: function result
c#
c
	external dix_msg_seanotf
	logical*4 dix_smg_find_string1
c
	if(nk_se .eq. 0) then
	  call dix_smg_get_sear_string(control,
     1        sear_string,nk_se,forward)
	end if
c
	if(nk_se .eq. 0) then
	  dix_smg_find_string =.false.
	else
c
	  dix_smg_find_string = dix_smg_find_string1(
     1                    dis_id,nk_se,sear_string,
     1                    row,col,nlines,forward)
	endif
	if(.not. dix_smg_find_string) then
	  call dix_message(control,dix_msg_seanotf)
	endif
	return
	end
	subroutine dix_smg_get_sear_string(control,
     1       sear_string,nk_se,forward)
	implicit none
c
	include 'dix_def.inc'
	record /control/ control
	character*(*) sear_string
	integer*4 nk_se
	logical*4 forward
c
	integer*4 lent,d_id,iterm
c
	sear_string = ' '
 	lent = len(sear_string)
	call smg$create_virtual_display(3,lent+7,d_id)
	call smg$paste_virtual_display(d_id,control.paste_id,10,
     1               control.ncols-10-lent)
	call smg$label_border(d_id,'Search string')
	call smg$put_chars(d_id,'Search:',1,1)
	iterm = 0
	call dix_smg_get_string(control,d_id,1,9,lent,sear_string,0,iterm,
     1                 nk_se,.false.)
	if(iterm .eq. key_set_forw ) forward = .true.
	if(iterm .eq. key_set_backw) forward = .false.
	call smg$delete_virtual_display(d_id)
	return
	end
	function dix_smg_find_string1(dis_id,
     1                    nk_se,sear_string,
     1                    row,col,nlines,forward)
	implicit none
c
c Find a string in display
c
	include 'dix_def.inc'
c
	integer*4 dis_id		!:i: display id
	integer*4 nk_se			!:i: length of search
	character*(*) sear_string	!:i: search string
	integer*4 row			!:o: row found
	integer*4 col			!:o: col found
	integer*4 nlines		!:o: #lines found
	logical*4 forward		!:i: forward search
	logical*4 dix_smg_find_string1	!:f: function result
c#
	include '($smgdef)'
c
	character*(max_short_line_length) sear_up
c
	integer*4 yp,jpos
	character*(max_screen_width) regel
	external dix_msg_seanotf
c
	yp = row
c
	dix_smg_find_string1 =.true.
c
	call str$upcase(sear_up,sear_string)
	if(.not. forward) call dix_smg_rever(sear_up(1:nk_se))
c
10	call smg$read_from_display(dis_id,regel,,yp)
	call str$upcase(regel,regel)
	if(.not. forward) call dix_smg_rever(regel)
	if(yp .eq. row) then
c
c search on current line
c
	  if(forward) then
	    jpos = col
	    col = index(regel(col+1:),sear_up(1:nk_se))
	    if(col .ne. 0) col = col+jpos
	  else
c	    if(col .eq. 1) then
c	      col = 0
c	    end if
c	    if(col .eq. 0) col = len(regel)+1
	    jpos = col
	    col = index(regel(len(regel)-col+2:),sear_up(1:nk_se))
	    if(col .ne. 0) col = jpos-col-nk_se+1
	  end if
	else
c
c On non current line we can search all positions
c
	  col = index(regel,sear_up(1:nk_se))
	  if(col .ne.0 .and. .not. forward) col = len(regel)-col+1-nk_se+1
	end if	
	if(col .ne. 0) then
	  row= yp
	  goto 90
	end if
c
c Not found, so try next line
c
	if(forward) then
	  yp = yp+1
	  if(yp .gt. nlines) goto 80
	else
	  yp = yp-1
	  if(yp .eq. 0) goto 80
	end if
	goto 10
c
80	dix_smg_find_string1 =.false.
90	return
	end

	subroutine dix_smg_rever(text)
	implicit none
c
c Reverse a string
c
	character*(*) text		!:io: text line
c#
	character hulp
	integer*4 ipos_e,ipos_b
c
	ipos_e = len(text)
	ipos_b = 1
	do while(ipos_b .lt. ipos_e)
	  hulp = text(ipos_b:ipos_b)
	  text(ipos_b:ipos_b) = text(ipos_e:ipos_e)
	  text(ipos_e:ipos_e) = hulp
	  ipos_b = ipos_b + 1
	  ipos_e = ipos_e - 1
	end do
	return
	end

	function dix_smg_question(control,message,default)
	implicit none
c
c Ask a question via SMG
c
	include 'dix_def.inc'
	include '($smgdef)'
c
	record /control/ control	!:i: control block
	character*(*) message		!:i: the message
	logical default			!:i: default true of false
	logical*4 dix_smg_question	!:f: function result
c
	character*(*) context
	parameter (context = 'YESNO')
c
c#
        character kar
	character dix_util_upcase_kar
c
	integer*4 iterm,dis_id,linenr,krow,kcol,ypos,npos
	external dix_msg_yesnomes
c
	call smg$create_virtual_display(1,max(25,len(message)+10),dis_id)
	call smg$label_border(dis_id,'Questions-answers')
	linenr = max(1,control.nrows - 2 - control.nlin_dis_err)
	call smg$paste_virtual_display(dis_id,control.paste_id,linenr,1)
9	if(default) then
	  ypos = len(message) + 3
	  npos = len(message) + 6
	  call smg$put_chars(dis_id,message//' [y]/n:  ',1,1)
	else
	  ypos = len(message) + 2
	  npos = len(message) + 5
	  call smg$put_chars(dis_id,message//' y/[n]:  ',1,1)
	endif
10	call dix_get_key(control,iterm,krow,kcol,context)
	if(iterm .eq. key_help) then
	  call dix_message(control,dix_msg_yesnomes)
	  goto 10
	end if
c
	if(iterm .eq. key_mouse_left) then
	  kar = ' '
	  if(krow .eq. linenr) then
	    if(kcol .eq. ypos) kar = 'Y'
	    if(kcol .eq. npos) kar = 'N'
	  endif
	elseif(iterm .eq. key_enter) then
	  kar = 'N'
	  if(default) kar = 'Y'
	else
	  kar = dix_util_upcase_kar(char(iterm))
	endif
	if(kar .ne. 'Y' .and. kar .ne. 'N')goto 9
c
	dix_smg_question= kar .eq. 'Y'
	call smg$delete_virtual_display(dis_id)
	return
	end

	subroutine dix_smg_out_of_band(control)
	implicit none
c
c Set up an out of band ast
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	include '($smgdef)'
c#
	integer*4 iterm
	external dix_smg_out_of_band_ast
c
	iterm = 2**smg$k_trm_ctrlc 
c
	call smg$set_out_of_band_asts(control.paste_id,iterm,
     1            dix_smg_out_of_band_ast,control)
	return
	end
c
	subroutine dix_smg_out_of_band_ast(param)
	implicit none
c
c the ast for the out of band
c
	include 'dix_def.inc'
c
	structure /hulp/
	  integer*4 p_id
	  integer*4 arg
	  byte kar
	  byte hulp(3)
	end structure
	record /hulp/ param
c#
	record /control/ control
	pointer (p_control,control)
c
	if(param.kar .eq. 3) then
	  p_control = param.arg
	  control.control_c_seen = .true.
	end if
	return
	end

	function dix_smg_get_int(control,message,val,minval,maxval)
	implicit none
c
c Get an integer from the user
c
	include 'dix_def.inc'
c
	record /control/ control	!:i: control block
	character*(*) message		!:i: the message
	integer*4 val			!:o: value returned
	integer*4 minval		!:i: min value allowed
	integer*4 maxval		!:i: max value allowed
	logical*4 dix_smg_get_int	!:f: return value
c#
c
	integer*4 iterm,dis_id,col,nkar,k
	character*(max_short_line_length) line
	include '($smgdef)'
c
	external dix_msg_illval
c
	dix_smg_get_int = .false.
	call smg$create_virtual_display(1,40,dis_id)
	call smg$label_border(dis_id,'Number input')
	call smg$paste_virtual_display(dis_id,control.paste_id,
     1           control.nrows-1,1)
10	write(line,1010) message,minval,maxval,val
1010	format('Give ',a,'(',i5,'-',i5,') : ',i5)
	call smg$put_chars(dis_id,line,1,1)
	col = index(line,':')+2
	k = 0
	call sys$fao('!UL       ',nkar,line,%val(val))
	call smg$put_chars(dis_id,line(1:nkar),1,col)
c
	iterm = 0
	call dix_smg_get_string(control,dis_id,1,col,7,line,0,
     1              iterm,nkar,.false.)
	if(iterm .eq. key_exit) goto 90
	read(line(1:7),2000,err=30) k
2000	format(bn,i7)
	if(k .ge. minval .and. k .le. maxval) then
	  val = k
	  dix_smg_get_int = .true.
	  goto 90
	end if
30	call dix_message(control,dix_msg_illval)
	goto 10
90	call smg$delete_virtual_display(dis_id)
	return
	end

	subroutine dix_smg_get_str(control,message,text,iterm)
	implicit none
c
c Get a string from the user
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	character*(*) message		!:i: intro message
	character*(*) text		!:o: the string
	integer*4 iterm			!:o: the terminator
c#
cc Common for screen display
c
	integer*4 dis_id,col,nkar
	include '($smgdef)'
c
	call smg$create_virtual_display(1,60,dis_id)
	call smg$label_border(dis_id,'Enter '//message)
	call smg$paste_virtual_display(dis_id,control.paste_id,
     1                  control.nrows-1,1)
	call smg$put_chars(dis_id,message//' :',1,1)
	col = len(message)+3
	iterm = 0
	call dix_smg_get_string(control,dis_id,1,col,len(text),text,0,iterm,
     1              nkar,.false.)
	call smg$delete_virtual_display(dis_id)
	return
	end

	subroutine dix_smg_file_info_scr(control,file) 
	implicit none
c
c Display file info on screen
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	record /file_info/ file		!:i: file block
c#
	include '($smgdef)'
c
	integer*4 nk,mem_lun,nlines
c
	call memtab_init(control,mem_lun,'File View')
	control.linenr = 0
c
	call dix_rms_file_info_scr(control,mem_lun,file) 
c
	call memtab_get_nlines(mem_lun,nlines)
c
	nk = max(60,file.nk_fnam)
	call dix_smg_view_memtab(control,mem_lun,
     1              file.fnam(1:nk),15,.true.)
	call memtab_close(control,mem_lun)
	return
	end

	subroutine dix_smg_show(control,dis_id,beg_lin,topic)
 	implicit none
c
c Show a display id to the user
c
	include 'dix_def.inc'
	record /control /control
	integer*4 dis_id		!:i: display id
	integer*4 beg_lin		!:i: start row for display
	character*(*) topic		!:i: topic (header line)
c#
	include '($smgdef)'
c
	record /dyn_help/ help_des
 	integer*4 iterm,res_lin
	integer*4 dix_smg_show_int
c
	character*(*) context
	parameter (context = 'VIEW')
c         
c Create help_text
c
	call help_init_std(control,help_des,topic,20,15,context)
	call help_key(control,help_des,key_find,
     1              'find text in display',context)
	call help_key(control,help_des,key_set_forw,
     1               'Set forward',context)
	call help_key(control,help_des,key_set_backw,
     1                'Set backward',context)
c
	call dix_smg_stack_help(control,help_des)
	call smg$set_cursor_abs(dis_id,beg_lin,1)
c
c Now show the text
c
10	iterm = dix_smg_show_int(control,dis_id,res_lin,context,
     1                           .true.)
	if(iterm .eq. key_help) then
c
c Display help
c
	  call dix_smg_help(control,context)
	  goto 10
	endif
	call dix_smg_unstack_help(control)
	call help_exit(help_des)
	return
	end
c
	function dix_smg_show_int(control,dis_id,res_lin,context,
     1                            allow_mouse)
 	implicit none
c
c  Show display to user
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	integer*4 dis_id		!:i: display id
	integer*4 res_lin		!:o: result line number
	character*(*) context		!:i: context (screen) 
	logical*4 allow_mouse		!:i: allow mouse click
	integer*4 dix_SMG_show_int	!:f: function result
c#
	include '($smgdef)'
c
	logical*4 bold_set,forward
	integer*4 nk_se,bcol,brow,iterm !,nk
	integer*4 view_size,view_width,nlines,width
	character*(max_short_line_length) sear
	character*(max_line_length) line
	common /save_12/ nk_se,forward,bold_set,sear
	data nk_se/0/,forward/.true./
	logical*4 dix_smg_find_string
c
	logical*4 pf1_flag
	integer*4 scr_pos,row,scr_col,col,kcol,krow
	integer*4 paste_row,paste_col,k
	integer*4 smg$cursor_row
	integer*4 smg$cursor_column
c
	external dix_msg_general
c
	call smg$get_pasting_info(dis_id,control.paste_id,k,
     1                            paste_row,paste_col)
	call smg$get_display_attr(dis_id,nlines,width)
	call smg$get_viewport_char(dis_id,scr_pos,scr_col,
     1         view_size,view_width)
	row = smg$cursor_row(dis_id)
	col = smg$cursor_column(dis_id)
c
10	pf1_flag = .false.
11	row = min(nlines,max(row,1))
	if(col .lt. 1)      col = 1
	if(col-1 + view_width .gt. width) col = width - view_width +1
	do while(row .lt. scr_pos)
	  scr_pos = scr_pos - 1
	  call smg$scroll_viewport(dis_id,smg$m_down,1)
	end do
c
	do while(row-scr_pos .ge. view_size)
	  scr_pos = scr_pos + 1
	  call smg$scroll_viewport(dis_id,smg$m_up,1)
	end do
c
	if(col .lt. scr_col) then
	  call smg$scroll_viewport(dis_id,smg$m_right,scr_col-col)
	elseif(col .gt. scr_col) then
	  call smg$scroll_viewport(dis_id,smg$m_left,col-scr_col)
	endif
	scr_col = col
c
	call smg$set_cursor_abs(dis_id,row,col)

	call dix_get_key(control,iterm,krow,kcol,context)
	if(bold_set) then
c
c Clear the search 
c
	  call smg$change_rendition(dis_id,brow,bcol,1,nk_se,0)
	  bold_set = .false.
	end if
c
	if(iterm .eq. key_mouse_left) then
	  row = krow - paste_row + 1
	  goto 10
	elseif(iterm .eq. key_mouse_middle) then
c
c Now we divide the screen in 4 parts
c   separated by a diagonal cross
c  middle top = prev
c  middle bot = next
c  middle left = left
c  middle right = right
c
c	  call sys$fao('Krow=!UL, KCOL=!UL, PR,C = !UL,!UL',nk,line,
c     1         %val(krow),%val(kcol),%val(paste_row),%val(paste_col))
c	  call dix_message(control,dix_msg_general,line(1:nk))
	  krow = krow - paste_row + 1	!in window
	  kcol = kcol - paste_col + 1
	  if(krow .ge. 1 .and. krow .le. view_size/4) then
	    iterm = key_prev
	  elseif(krow .ge. 3*view_size/4 .and. krow .le. view_size)then
	    iterm = key_next
	  elseif(kcol .ge. 1 .and. kcol .le. view_width/4) then
	    iterm = key_left
	  elseif(kcol .ge. 3*view_width/4 .and. krow.le.view_width)then
	    iterm = key_right
	  else
	    goto 10
	  endif	
	elseif(iterm .eq. key_mouse_right .or. iterm .eq. key_menu) then
	  if(allow_mouse) then
	    call dix_smg_select_menu(control,
     1              'Return',line,
     1              .false.,'Choises',0,0,.true.)
	  else
	    krow = row
	    line = 'RETURN'
	  endif
	  if(line(1:1) .eq. 'R') then
	    krow = krow - paste_row + 1	!in window
	    if(krow .ge. 1 .and. krow .le. view_size) then
	      row = krow
	      iterm = key_enter
	    else
	      goto 10
	    endif
	  endif
	endif
c
	if(iterm .eq. key_up) then
	  row = row - 1
	elseif(iterm .eq. key_prev) then
	  row = row - view_size+2
	elseif(iterm .eq. key_down) then
	  row = row + 1
	elseif(iterm .eq. key_next) then
	  row = row+view_size-2
	elseif(iterm .eq. key_top) then
	  row = 1
	elseif(iterm .eq. key_left) then
	  col = col - 1
	elseif(iterm .eq. key_right) then
	  col = col + 1
	elseif(iterm .eq. key_bot) then
	  row = nlines
	elseif(iterm .eq. key_find .or. iterm .eq. key_find1) then
	  if(iterm .eq. key_find1) nk_se = 0
	  bcol = col
	  brow = row
	  if(dix_smg_find_string(control,dis_id,nk_se,sear,brow,bcol,
     1           nlines,forward)) then
	    bold_set = .true.
	    call smg$change_rendition(dis_id,brow,bcol,1,nk_se,,smg$m_bold)
	    row = brow	
	    col = bcol
	  end if
	elseif(iterm .eq. key_set_forw) then
	  forward = .true.
	elseif(iterm .eq. key_set_backw) then
	  forward = .false.
	elseif(iterm .eq. key_help) then
	  goto 90		!return help key
	elseif(iterm .eq. key_exit .or. iterm .eq. key_enter) then
	  res_lin = row 
	  goto 90
	else
	  call dix_mes_invkey(control,context)
	end if
	goto 10
90	dix_smg_show_int = iterm
	return
	end	

	subroutine dix_smg_help(control,context)
	implicit none
c
c Display help
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	character*(*) context
c#
	integer*4 view_size,view_width
	parameter (view_size=15,view_width=70)
c
	integer*4 idx,iterm,orig_row,orig_col,dis_id1,res_lin,istat
	integer*4 width,height,nrow_h,ncol_h
	integer*4 dix_help
c
	integer*4 dix_smg_show_int
c
c	character*(*) context
c	parameter (context = 'HELP')
c
	include '($smgdef)'
c
	idx = control.help_depth
c 
c Save the phys cursor
c
	call dix_smg_getset_phys_cursor(control,.false.,orig_row,orig_col)
c
c Compute the #lines and width of the help text
c and fill display
c
10	call dix_smg_help_1(control,
     1               control.help_stack(idx).stack,nrow_h,ncol_h,
     1               control.help_stack(idx).dis_id,context)
c
c Clip the viewport to somthing reasonble
c
	height = min(nrow_h,view_size,control.nrows)
	width  = min(ncol_h,view_width,control.ncols)
c
c Create viewport
c
	call smg$create_viewport(
     1               control.help_stack(idx).dis_id,1,1,height,width)
c
c Past it on the screen
c
	call smg$paste_virtual_display(
     1               control.help_stack(idx).dis_id,
     1               control.paste_id,
     1               max(1,control.nrows- height-idx),
     1               max(1,control.ncols- width -idx))
c
c And look at it
c
12	iterm = dix_smg_show_int(control,
     1               control.help_stack(idx).dis_id,res_lin,
     1               context,.false.)
c
c interpret what the user wants
c
	if(iterm .eq. key_help) then
c
c Deeper help, if level=1 display the help file
c
	  if(idx .eq. 1)  then
	    call smg$create_virtual_display(control.nrows,
     1               control.ncols,dis_id1)
	    call smg$paste_virtual_display(dis_id1,control.paste_id,1,1)
	    istat = dix_help('DIX')
	    call smg$delete_virtual_display(dis_id1)
	    if(.not. istat) call dix_message(control,%val(istat))
	    goto 12
	  else
c
c Else display the deeper level
c
	    idx = idx-1
	  end if
	  goto 10
	elseif(iterm .eq. key_enter) then
c
c Skip this help level , return to upper help
c
	  call smg$delete_virtual_display(control.help_stack(idx).dis_id)
	  idx = idx + 1
	  if(idx .le. control.help_depth) goto 12
	endif
c
c Skip all levels
c
	do while(idx .le. control.help_depth)
	  call smg$delete_virtual_display(control.help_stack(idx).dis_id)
	  idx = idx + 1
	end do
c
c And restore phys cursor
c
	call dix_smg_getset_phys_cursor(control,.true.,orig_row,orig_col)
	return
	end
	subroutine dix_smg_help_1(control,lines,nlines,nk,dis_id,context)
	implicit none
c
c Display a help topic fro the stack
c
	include 'dix_def.inc'
	record /control/ control	!:i: display id
	character*(*) lines		!:i: #lines 
	integer*4 nlines		!:i: #lines
	integer*4 nk			!:i: length of line
	integer*4 dis_id		!:i: display id
	character*(*) context		!:i: context for keys
c#
	integer*4 k,nk_h1,nk_h2,nk_h3,nk_h4
	include '($smgdef)'
	character*(max_screen_width) line,help1,help2,help3,help4
c
	integer*4 ibpos,iepos,video,iline
c
	call keydefs_get_map(key_enter,control,nk,line,context)
	call sys$fao('Type !AS to return to previous screen',
     1                nk_h1,help1,line(1:nk))
c
	call keydefs_get_map(key_left,control,nk,line,context)
	call sys$fao('Use !AS,',nk_h2,help2,line(1:nk))
c
	call keydefs_get_map(key_right,control,nk,line,context)
	call sys$fao('!AS,',k,help2(nk_h2+1:),line(1:nk))
	nk_h2 = nk_h2 + k
c
	call keydefs_get_map(key_up,control,nk,line,context)
	call sys$fao('!AS,',k,help2(nk_h2+1:),line(1:nk))
	nk_h2 = nk_h2 + k
c
	call keydefs_get_map(key_down,control,nk,line,context)
	call sys$fao('!AS to move around in this screen',
     1           k,help2(nk_h2+1:),line(1:nk))
	nk_h2 = nk_h2 + k
c
	call sys$fao('S+K means Type Shift+the key together ',
     1                nk_h3,help3)
	call sys$fao('PF1-K means Type PF1 first and then the key',
     1                nk_h4,help4)
c
	ibpos  = 1
	nlines = 0			
	nk     = max(nk_h1,nk_H2,nk_h3,nk_h4)	!minimal the help line
c
	do while(ibpos .lt. len(lines))
	  iepos = index(lines(ibpos:),';')
	  if(iepos .eq. 0) then
	    iepos = len(lines)
	  else
	    iepos = ibpos + iepos - 2
	  end if
	  if(iepos-ibpos+1 .gt. nk) nk = iepos-ibpos+1
	  nlines = nlines + 1
	  ibpos = iepos + 2
	end do
c
c Now we know the #lines and the width, create the display
c
	call smg$create_virtual_display(nlines+3,nk,dis_id)
c
c Print the 3 header lines
c
	video = smg$m_bold
	call smg$put_chars(dis_id,help1(1:nk_h1),1,1,,video)
	call smg$put_chars(dis_id,help2(1:nk_h2),2,1,,video)
	call smg$put_chars(dis_id,help3(1:nk_h3),3,1,,video)
	call smg$put_chars(dis_id,help4(1:nk_h4),4,1,,video)
c
	ibpos = 1
	iline = 5
c
	do k=1,nlines
	  iepos = index(lines(ibpos:),';')
	  if(iepos .eq. 0) then
	    iepos = len(lines)
	  else
	    iepos = ibpos + iepos - 2
	  end if
	  if(k .eq. 1) then
c
c The first entry is the header
c
	    call smg$label_border(dis_id,'Help on '//lines(ibpos:iepos))
	  else
	    video = 0
	    if(lines(ibpos:ibpos) .eq. ':') then
	      video = smg$m_bold
	      ibpos = ibpos + 1
	    end if
	    call smg$put_chars(dis_id,lines(ibpos:iepos),iline,1,,video)
	    iline = iline + 1
	  endif
	  ibpos = iepos + 2
	end do	 
c
	call smg$set_cursor_abs(dis_id,1,1)
c
90	return
	end
	function dix_smg_get_string_multi(control,d_id,d_id_offset,
     1                              row_inp,
     1                              col_inp,nlin,view_ncols,
     1                              string,video_inp,iterm,nkar,
     1                              col1,col2,col_offset,
     1                              disp_ncols,row_offset,view_nrows)
c
	implicit none		
c
c Get a line from the user with a string over more than one line 
c
	include 'dix_def.inc'
        record /control/ control
	integer*4 d_id		!:i: display id to read from
	integer*4 d_id_offset	!:i: display id of the offset
	integer*4 row_inp	!:i: row
	integer*4 col_inp	!:i: col of string
	integer*4 nlin 		!:io: #lines on screen
	integer*4 view_ncols		!:i: width of display
	character*(*) string	!:io: result string
	integer*4 video_inp	!:i: video mode
	integer*4 iterm		!:io: teminator
	integer*4 nkar		!:io: string length
	integer*4 col1		!:i: col for separator1
	integer*4 col2		!:i: col for separator2
	integer*4 col_offset	!:io: column offset
	integer*4 disp_ncols	!:io: #cols of the display
	integer*4 row_offset	!:io: row - offset of row display
	integer*4 view_nrows    !:i: view size
	logical*4 dix_smg_get_string_multi		!:i: true if changed
c#
	include '($smgdef)'
c
	logical*4 dix_util_kar_in_ran
	logical*4 dix_con_kar_to_hex
c	character dix_util_kar_conv
c
	external dix_msg_illhexchar
	external dix_msg_nomorel
	external dix_msg_onfirst
	external dix_msg_endfield
	external dix_msg_strfull
	external dix_msg_hexmode1
	external dix_msg_hexmode2
	external dix_msg_stafield
	external dix_msg_kardisp
	external dix_msg_clear
c
	integer*4 ipos,k,l,video,col,row,ibpos,iepos,dpos,m
	integer*4 nlin_needed,nk,kcol,krow,paste_row,paste_col
	integer*4 view_row,view_col
	logical*4 insert
	character*(max_command_length) vid_line,line,wvid_line
c
	character*(*) context
	parameter (context = 'EDITMULTIPLE')
c
	integer*4 max_pos
	record /dyn_help/ help_des
c
c Build help text
c
	call smg$get_pasting_info(d_id,control.paste_id,k,
     1                            paste_row,paste_col)
	call smg$get_viewport_char(d_id,view_row,view_col)
	call help_init_std(control,help_des,'get string',20,19,context)
	call help_key(control,help_des,key_swap_dis,
     1            'HEX info about char',context)
	call dix_smg_stack_help(control,help_des)
c
	video = video_inp .or. smg$m_underline
	max_pos = len(string)
c
c
c string is equal to text on screen
c nlin   is equal to #lines on screen
c nkar   is #chars in text
c
5	if(iterm .eq. key_enter .or. iterm .eq. key_right) iterm = 0
	ibpos = 1
	row = row_inp
	do while(ibpos .le. nkar) 
	  iepos = nkar
	  if(.not. control.wide_display) then
	    iepos = min(iepos,ibpos+view_ncols-1)
	  endif
c 
c Remember old video
c
	  call smg$read_from_display(d_id,line,,row,wvid_line)
	  vid_line(ibpos:iepos) = wvid_line(col_inp:)
c
	  call smg$change_rendition(d_id,row,col_inp,1,iepos-ibpos+1,video)
c
c See if some chars were displayed with anything else but normal
c   (for unprintable chars the reverse attribute is set)
c
	  do k=1,iepos-ibpos+1
	    l = ichar(vid_line(k:k))
	    if(l .ne. 0) then
c
c Set the extra attribute
c
	      call smg$change_rendition(d_id,row,col_inp+k-1,1,1,video .or. l)
	    endif
	  enddo
	  row = row+1
	  ibpos= iepos+1
	end do
c
	if(iterm .lt. 0) then
	  iterm = key_right
	end if
c
	ipos = 1
	insert = (control.input_flags .and. input_flag_insert) .ne. 0
10	if(ipos .gt. nkar) ipos = nkar+1
	if(ipos .lt. 1) ipos = 1
c
20	if(control.wide_display) then
	  row = row_inp 
	  col = col_inp + ipos-1
c
c Now make sure col is on screen
c 
	  do while(col .lt. col_offset) 
	    col_offset = col_offset - 1
	    call smg$scroll_viewport(d_id,smg$m_right,1)
	  end do
c
	  do while(col .ge. col_offset+view_ncols) 
	    col_offset = col_offset + 1
	    call smg$scroll_viewport(d_id,smg$m_left,1)
	  end do
c
	else
	  row = row_inp + (ipos-1)/view_ncols
	  col = col_inp + mod(ipos-1,view_ncols)
	endif
c
c See if row in screen
c
	if (row .lt. row_offset) then
	  k = row_offset - row
	  call smg$scroll_viewport(d_id,smg$m_down,k)
	  call smg$scroll_viewport(d_id_offset,smg$m_down,k)
	  row_offset = row_offset - k
	endif
c
	if (row .ge. row_offset+view_nrows) then
	  k = row - row_offset-view_nrows + 1
	  call smg$scroll_viewport(d_id,smg$m_up,k)
	  call smg$scroll_viewport(d_id_offset,smg$m_up,k)
	  row_offset = row_offset + k
	endif

	call smg$set_cursor_abs(d_id,row,col)
	if(iterm .eq. 0) call dix_get_key(control,iterm,krow,kcol,context)
c
	if(iterm .eq. key_mouse_left) then
	  krow = krow - paste_row + view_row
	  kcol = kcol - paste_col + view_col
	  if(krow .ge. row_inp .and. krow .lt. row_inp+nlin .and.
     1       kcol .ge. col_inp .and. kcol .lt. col_inp+view_ncols) then
	    krow = krow - row_inp
	    kcol = kcol - col_inp + 1
	    ipos = krow*view_ncols + kcol
	  endif
	  goto 50
	elseif(iterm .eq. key_mouse_middle) then
c
c Ignore middle mouse
c
	  goto 50
	elseif(iterm .eq. key_mouse_right .or. iterm .eq. key_menu) then
	  nk = 0
	  call sys$fao('Begin,End,Erase,Accept',nk,line)
	  if(insert) then
	    call dix_append(nk,line,',Overstrike')
	  else
	    call dix_append(nk,line,',Insert')
	  endif
	  call dix_smg_select_menu(control,line(1:nk),line,
     1             .false.,'Choises',0,0,.true.)
	  if(line(1:1) .eq. 'A') then
	    iterm = key_enter
	  elseif(line(1:1) .eq. 'B') then
	    iterm = key_first
	  elseif(line(1:2) .eq. 'EN') then
	    iterm = key_last
	  elseif(line(1:2) .eq. 'ER') then
	    iterm = key_erase
	  elseif(line(1:1) .eq. 'I') then
	    iterm = key_toggle
	  elseif(line(1:1) .eq. 'O') then
	    iterm = key_toggle
	  else
	    goto 50
	  endif
	endif
c
	if(iterm .eq. key_toggle) then
	  insert = .not. insert
	elseif(iterm .eq. key_last) then
	  ipos = nkar+1
	elseif(iterm .eq. key_first) then
	  ipos = 1
	elseif(iterm .eq. key_down) then
	  if(row-row_inp .le. nlin-2) then
	    ipos = ipos + view_ncols
	  else
	    call dix_message(control,dix_msg_nomorel)
	  end if
	elseif(iterm .eq. key_help) then
	  call dix_smg_help(control,context)
	elseif(iterm .eq. key_up) then
	  if(row .gt. row_inp) then
	    ipos = ipos - view_ncols
	  else
	    call dix_message(control,dix_msg_onfirst)
	  end if
	elseif(iterm .eq. key_right) then
	  if(ipos .le. nkar) then
	    ipos = ipos + 1
	  else
	    call dix_message(control,dix_msg_endfield)
	  end if
	elseif(iterm .eq. key_left) then
	  if(ipos .gt. 1) then
	    ipos = ipos - 1
	  else
	    call dix_message(control,dix_msg_stafield)
	  end if
	elseif(iterm .eq. key_erase) then
	  string = ' '
	  nkar = 0
	  ipos = 1
	  dpos = 1
	  goto 60
	elseif(iterm .eq. key_delete) then
	  if(ipos .gt. 1) then
	    dix_smg_get_string_multi = .true.
	    string(ipos-1:nkar) = string(ipos:nkar)//' '
	    vid_line(ipos-1:nkar) = vid_line(ipos:nkar)//char(0)
	    nkar = nkar - 1
	    ipos = ipos-1
	    dpos = ipos
	    goto 60
	  else
	    call dix_message(control,dix_msg_stafield)
	  end if
	elseif(iterm .eq. key_enter .or. 
     1         iterm .eq. key_set_forw   .or.
     1         iterm .eq. key_Set_backw   .or.
     1         iterm .eq. key_exit) then
	  goto 90
	elseif(iterm .eq. key_swap_dis) then
	  call dix_message(control,dix_msg_kardisp,
     1            %val(ipos),
     1            %val(ichar(string(ipos:ipos))),
     1            %val(ichar(string(ipos:ipos))),
     1            %val(ichar(string(ipos:ipos))))
	elseif(dix_util_kar_in_ran(iterm) .or. iterm .eq. key_swap_num) then
	  if(iterm .eq. key_swap_num) then
	    call dix_message(control,dix_msg_hexmode1)
	    call smg$set_cursor_abs(d_id,row,col)
	    call smg$read_keystroke(control.keyboard_id,iterm)
	    if(.not. dix_con_kar_to_hex(char(iterm),k)) goto 55
c
	    call dix_message(control,dix_msg_clear)
	    call dix_message(control,dix_msg_hexmode2)
	    call smg$set_cursor_abs(d_id,row,col)
	    call smg$read_keystroke(control.keyboard_id,iterm)
	    if(.not. dix_con_kar_to_hex(char(iterm),l)) goto 55
	    iterm = k*16+l
	    call dix_message(control,dix_msg_clear)
	  end if
	  if(ipos .le. max_pos) then
	    dix_smg_get_string_multi = .true.
	    if(insert) then
	      if(nkar .eq. max_pos) then
	        call dix_message(control,dix_msg_strfull)
	        goto 50
	      else
	        nkar = nkar + 1
	        string(ipos:nkar)   = char(iterm)//string(ipos:max_pos-1)
	        vid_line(ipos:nkar) = char(0)//vid_line(ipos:max_pos-1)
	      end if
	    else
	      string(ipos:ipos) = char(iterm)
	      vid_line(ipos:ipos) = char(0)
	      if(ipos .gt. nkar) nkar = ipos
	    end if
	    dpos = ipos
	    ipos = ipos + 1
	    goto 60
	  else
	    call dix_message(control,dix_msg_strfull)
	  end if
	else
	  call dix_mes_invkey(control,context)
	end if
50	iterm = 0
	goto 10
55	call dix_message(control,dix_msg_illhexchar)
	iterm = 0
	goto 10
c
c Redisplay data from dpos upto nkar
c
60	if(control.wide_display) then
c
c single line display
c make sure the display is wide enough for the new length
c
	  if(nkar .gt. disp_ncols) then
	    disp_ncols = nkar
	    call smg$change_virtual_display(d_id,,disp_ncols)
	  endif
	else
c
c Multi line display
c
	  nlin_needed = max(1,(nkar+view_ncols-1)/view_ncols)
c
	  if(nlin .gt. nlin_needed) then
c
c Delete one more line
c
	    call smg$delete_line(d_id,row_inp+nlin_needed,nlin-nlin_needed)
	    call smg$get_display_attr(d_id,k)
	    call smg$change_virtual_display(d_id,k-nlin+nlin_needed)
c
	    call smg$delete_line(d_id_offset,row_inp+nlin_needed,
     1                       nlin-nlin_needed)
	    call smg$get_display_attr(d_id_offset,k)
	    call smg$change_virtual_display(d_id_offset,k-nlin+nlin_needed)
c
	  elseif(nlin .lt. nlin_needed) then
c
c Delete one more line
c
	    call smg$get_display_attr(d_id,k)
	    call smg$change_virtual_display(d_id,k+nlin_needed-nlin)
	    call smg$change_virtual_display(d_id_offset,k+nlin_needed-nlin)
c
c Make room for a lot of lines
c
	    line = ' '
	    do k=nlin+1,nlin_needed
	      call smg$insert_line(d_id,row_inp+nlin,line,smg$m_down)	!insert here
	      call smg$insert_line(d_id_offset,row_inp+nlin,line,smg$m_down)	!insert here
	      if(col1 .ne. 0) then
	        call smg$draw_char(d_id_offset,smg$m_up,row_inp+k-1,col1)
	      endif
	      if(col2 .ne. 0) then
	        call smg$draw_char(d_id_offset,smg$m_up,row_inp+k-1,col2)
	      endif
	    end do
c
c And blank them out
c
	  end if
	  nlin = nlin_needed
	  do k=1,nlin
	    ibpos = (k-1)*view_ncols+1
	    iepos = k*view_ncols
	    if(ibpos .le. nkar .and. iepos .ge. dpos) then
	      if(iepos .gt. nkar) iepos = nkar
	      nk = iepos-ibpos+1
	      line = string(ibpos:iepos)
c
	      call smg$put_chars(d_id,line(1:nk),row_inp+k-1,col_inp,,video)
	      do l=ibpos,iepos
	        m = ichar(vid_line(l:l))
	        if(m .ne. 0) then
	          call smg$change_rendition(d_id,row_inp+k-1,col_inp+l-1,1,1,
     1              video .or. m)
	        endif
	      end do
	    end if
	  end do
c
c if nkar<view_ncols*nlin display nkar+1 as space
c
          if(nkar .lt. nlin*view_ncols) then
	    row = nkar/view_ncols+row_inp
	    col = mod(nkar,view_ncols)+col_inp
            call smg$erase_line(d_id,row,col)
	  end if	
	endif
	goto 50
90	continue
	call dix_smg_unstack_help(control)
	call help_exit(help_des)
	return
	end		

	function dix_smg_get_string(control,d_id,row_inp,col_inp,lent,
     1                    string,video_inp,iterm,nkar,at_end)
c
c Get a string from the user
c
	implicit none		
	include 'dix_def.inc'
	record /control/ control
	integer*4 d_id		!:i: display id to read from
	integer*4 row_inp	!:i: row
	integer*4 col_inp	!:i: col of string
	character*(*) string	!:o: result string
	integer*4 lent		!:i: max string length
	integer*4 video_inp	!:i: video mode
	integer*4 iterm		!:io: teminator
	integer*4 nkar		!:o: string length
	logical at_end		!:i: goto end of string
	logical*4 dix_smg_get_string		!:i: true if changed
c#
	include '($smgdef)'
c
	logical*4 dix_util_kar_in_ran
	logical*4 dix_con_kar_to_hex
c
	character*(*) context
	parameter (context = 'EDITLINE')
c
	integer*4 ipos,k,l,video,col,row,string_len,kcol,krow
	integer*4 string_pos,paste_row,paste_col,nk,view_row,view_col
	logical*4 insert
	character*(max_screen_width) line
c
	external dix_msg_illhexchar
	external dix_msg_endfield
	external dix_msg_strfull
	external dix_msg_hexmode1
	external dix_msg_hexmode2
	external dix_msg_stafield
	external dix_msg_kardisp
	external dix_msg_clear
c
	integer*4 max_pos
	record /dyn_help/ help_des
c
c Build help text
c
	call smg$get_pasting_info(d_id,control.paste_id,k,
     1                            paste_row,paste_col)
	call smg$get_viewport_char(d_id,view_row,view_col)
c
	call help_init_std(control,help_des,'get string',20,19,context)
	call help_key(control,help_des,key_enter,
     1               'All done',context)
	call help_key(control,help_des,key_swap_dis,
     1               'Display in HEX',context)
	call dix_smg_stack_help(control,help_des)
c
	video = video_inp .or. smg$m_underline
	string_len = min(len(line),len(string),lent)
	max_pos    = string_len+1
c
	dix_smg_get_string = .false.
	call smg$read_from_display(d_id,line,,row_inp)
	if(at_end) then
c
c Cursor is at end of string
c
	  string = line(max(1,col_inp-string_len+1):col_inp)
	  string_pos = col_inp - string_len + 1
	else
c
c Cursor is at the beginning
c
	  string = line(col_inp:min(len(line),col_inp+string_len-1))
	  string_pos = col_inp
	endif
c
c Get max length
c
	do nkar=string_len,1,-1
	  if(string(nkar:nkar) .ne. ' ') goto 5
	end do
	nkar = 0
5	if(iterm .eq. key_enter .or.iterm .eq. key_right) iterm = 0
c
	if(iterm .lt. 0) then
	  iterm = key_right
	end if
c
	if(at_end) then
	  insert = (control.input_flags .and. input_flag_insert) .ne. 0
	  ipos = string_len+1
	else
	  insert = .false.
	  ipos = 1
	endif
	call smg$change_rendition(d_id,row_inp,string_pos,1,nkar,video)
10	if(ipos .gt. max_pos) ipos = max_pos
	if(ipos .lt. 1) ipos = 1
c
20	row = row_inp
	col = string_pos + ipos-1
	call smg$set_cursor_abs(d_id,row,col)
	if(iterm .eq. 0) call dix_get_key(control,iterm,krow,kcol,context)
c
	if(iterm .eq. key_mouse_left) then
	  krow = krow - paste_row + view_row
	  kcol = kcol - paste_col + view_col
	  if(krow .eq. row_inp .and.
     1       kcol .ge. col_inp .and. kcol .lt. col_inp+lent) then
	    kcol = kcol - col_inp + 1
	    ipos = kcol
	  endif
	  goto 50
	elseif(iterm .eq. key_mouse_middle) then
c
c Ignore middle mouse
c
	  goto 50
	elseif(iterm .eq. key_mouse_right .or. iterm .eq. key_menu) then
	  nk = 0
	  call sys$fao('Begin,End,Erase,Accept',nk,line)
	  if(insert) then
	    call dix_append(nk,line,',Overstrike')
	  else
	    call dix_append(nk,line,',Insert')
	  endif
	  call dix_smg_select_menu(control,line(1:nk),line,
     1                .false.,'Choises',0,0,.true.)
	  if(line(1:1) .eq. 'A') then
	    iterm = key_enter
	  elseif(line(1:1) .eq. 'B') then
	    iterm = key_first
	  elseif(line(1:2) .eq. 'EN') then
	    iterm = key_last
	  elseif(line(1:2) .eq. 'ER') then
	    iterm = key_erase
	  elseif(line(1:1) .eq. 'I') then
	    iterm = key_toggle
	  elseif(line(1:1) .eq. 'O') then
	    iterm = key_toggle
	  else
	    goto 50
	  endif
	endif
c
	if(iterm .eq. key_toggle) then
	  insert = .not. insert
	elseif(iterm .eq. key_last) then
	  ipos = nkar
	elseif(iterm .eq. key_first) then
	  ipos = 1
	elseif(iterm .eq. key_help) then
	  call dix_smg_help(control,context)
	elseif(iterm .eq. key_right) then
	  if(ipos .lt. max_pos) then
	    ipos = ipos + 1
	  else
	    call dix_message(control,dix_msg_endfield)
	  end if
	elseif(iterm .eq. key_left) then
	  if(ipos .gt. 1) then
	    ipos = ipos - 1
	  else
	    call dix_message(control,dix_msg_stafield)
	  end if
	elseif(iterm .eq. key_erase) then
	  string = ' '
	  call smg$put_chars(d_id,string,row_inp,string_pos,,video)
	  nkar = 0
	  ipos = 1
	elseif(iterm .eq. key_delete) then
	  if(ipos .gt. 1) then
	    dix_smg_get_string = .true.
	    if(at_end) then
	      string(1:string_len) = ' '//string(1:ipos-2)//
     1                                    string(ipos:string_len)
	    else
	      string(1:string_len) = string(1:ipos-2)//
     1                               string(ipos:string_len)
	      ipos = ipos - 1
	    endif
	    goto 52
	  else
	    call dix_message(control,dix_msg_stafield)
	  end if
	elseif(iterm .eq. key_enter .or. 
     1         iterm .eq. key_set_forw .or.
     1         iterm .eq. key_set_backw   .or.
     1         iterm .eq. key_exit) then
	  goto 90
	elseif(iterm .eq. key_swap_dis) then
	  call dix_message(control,dix_msg_kardisp,
     1            %val(ipos),
     1            %val(ichar(string(ipos:ipos))),
     1            %val(ichar(string(ipos:ipos))),
     1            %val(ichar(string(ipos:ipos))))
	elseif(dix_util_kar_in_ran(iterm) .or. iterm .eq.key_swap_num) then
	  if(iterm .eq. key_Swap_num) then
	    call dix_message(control,dix_msg_hexmode1)
	    call smg$read_keystroke(control.keyboard_id,iterm)
	    if(.not. dix_con_kar_to_hex(char(iterm),k)) goto 55
	    call dix_message(control,dix_msg_clear)
	    call dix_message(control,dix_msg_hexmode2)
	    call smg$read_keystroke(control.keyboard_id,l)
	    if(.not. dix_con_kar_to_hex(char(iterm),l)) goto 55
	    iterm = k*16+l
	    call dix_message(control,dix_msg_clear)
	  end if
	  if(ipos .le. max_pos) then
	    dix_smg_get_string = .true.
	    if(insert) then
	      if(string(1:1) .ne. ' ') then
	        call dix_message(control,dix_msg_strfull)
	        goto 50
	      else
	        string(1:string_len) = string(2:ipos-1)//char(iterm)//
     1                         string(ipos:string_len)
	      end if
	    else
	      if(ipos .gt. string_len) then
	        call dix_message(control,dix_msg_strfull)
	        goto 50
	      else
	        string(ipos:ipos) = char(iterm)
	      endif
	    end if
	    if(ipos .lt. max_pos) ipos = ipos + 1
	    goto 52
	  else
	    call dix_message(control,dix_msg_endfield)
	  end if
	else
	  call dix_mes_invkey(control,context)
	end if
50	iterm = 0
	goto 10
c
c Stirng changed, check for length
c
52	do k=string_len,1,-1
	  if(string(k:k) .ne. ' ') goto 341
	end do
	k = 0
341	nkar = k
	call smg$put_chars(d_id,string(1:nkar),row_inp,string_pos,,video)
	call smg$put_chars(d_id,string(nkar+1:string_len),
     1                  row_inp,string_pos+nkar)
	
	goto 50
c
55	call dix_message(control,dix_msg_illhexchar)
	goto 50
c
90	continue
        call smg$put_chars(d_id,string(1:nkar),
     1                         row_inp,string_pos,,video_inp)
	call dix_smg_unstack_help(control)
	call help_exit(help_des)
	return
	end		
	function dix_smg_get_string_1(control,d_id,row_inp,col_inp,lent,
     1                    string,video_inp,iterm,nkar,at_end)
c
c Get a string from the user
c
	implicit none		
	include 'dix_def.inc'
	record /control/ control
	integer*4 d_id		!:i: display id to read from
	integer*4 row_inp	!:i: row
	integer*4 col_inp	!:i: col of string
	character*(*) string	!:o: result string
	integer*4 lent		!:i: max string length
	integer*4 video_inp	!:i: video mode
	integer*4 iterm		!:io: teminator
	integer*4 nkar		!:o: string length
	logical at_end		!:i: goto end of string
	logical*4 dix_smg_get_string_1		!:i: true if changed
c#
	include '($smgdef)'
c
	logical*4 dix_util_kar_in_ran
	logical*4 dix_con_kar_to_hex
c
	integer*4 ipos,k,l,video,col,row,string_len,kcol,krow
	integer*4 paste_row,paste_col,nk,view_row,view_col
	logical*4 insert
	character*(max_screen_width) line
c
	external dix_msg_illhexchar
	external dix_msg_endfield
	external dix_msg_strfull
	external dix_msg_hexmode1
	external dix_msg_hexmode2
	external dix_msg_stafield
	external dix_msg_kardisp
	external dix_msg_clear
c
	integer*4 dix_util_get_len_fu
c
	integer*4 max_pos
	record /dyn_help/ help_des
c
	character*(*) context
	parameter (context='GETSTRING')

c
c Build help text
c
	call smg$get_pasting_info(d_id,control.paste_id,k,
     1                            paste_row,paste_col)
	call smg$get_viewport_char(d_id,view_row,view_col)
	call help_init_std(control,help_des,'get string',20,19,context)
	call help_key(control,help_des,key_do,
     1               'All done',context)
	call help_key(control,help_des,key_select,
     1               'Toggle Begin/Current',context)
	call dix_smg_stack_help(control,help_des)
c
	video = video_inp .or. smg$m_underline
	string_len = min(len(line),len(string),lent)
	max_pos    = string_len+1
c
	dix_smg_get_string_1 = .false.
	call smg$read_from_display(d_id,line,,row_inp)
c
	string = line(col_inp:min(len(line),col_inp+string_len-1))
c
c Get max length
c
	nkar = dix_util_get_len_fu(string(1:string_len))
c
	if(at_end) then
	  insert = (control.input_flags .and. input_flag_insert) .ne. 0
	  ipos = string_len+1
	else
	  insert = .false.
	  ipos = 1
	endif
c
	call smg$change_rendition(d_id,row_inp,col_inp,1,nkar,video)
10	if(ipos .gt. max_pos) ipos = max_pos
	if(ipos .lt. 1) ipos = 1
c
20	row = row_inp
	col = col_inp + ipos-1
	call smg$set_cursor_abs(d_id,row,col)
	call dix_get_key(control,iterm,krow,kcol,context)
c
c
	if(iterm .eq. key_mouse_left) then
	  krow = krow - paste_row + view_row
	  kcol = kcol - paste_col + view_col
	  if(krow .eq. row_inp .and.
     1       kcol .ge. col_inp .and. kcol .lt. col_inp+lent) then
	    kcol = kcol - col_inp + 1
	    ipos = kcol
	  endif
	  goto 50
	elseif(iterm .eq. key_mouse_middle) then
c
c Ignore middle mouse
c
	  goto 50
	elseif(iterm .eq. key_mouse_right .or. iterm .eq. key_menu) then
	  nk = 0
	  call sys$fao('Begin,End,Erase,Accept',nk,line)
	  if(insert) then
	    call dix_append(nk,line,',Overstrike')
	  else
	    call dix_append(nk,line,',Insert')
	  endif
	  call dix_smg_select_menu(control,line(1:nk),line,
     1                .false.,'Choises',0,0,.true.)
	  if(line(1:1) .eq. 'A') then
	    iterm = key_enter
	  elseif(line(1:1) .eq. 'B') then
	    iterm = key_first
	  elseif(line(1:2) .eq. 'EN') then
	    iterm = key_last
	  elseif(line(1:2) .eq. 'ER') then
	    iterm = key_erase
	  elseif(line(1:1) .eq. 'I') then
	    iterm = key_toggle
	  elseif(line(1:1) .eq. 'O') then
	    iterm = key_toggle
	  else
	    goto 50
	  endif
	endif
c
	if(iterm .eq. key_toggle) then
	  insert = .not. insert
	elseif(iterm .eq. key_last) then
	  ipos = nkar
	elseif(iterm .eq. key_first) then
	  ipos = 1
	elseif(iterm .eq. key_help) then
	  call dix_smg_help(control,context)
	elseif(iterm .eq. key_right) then
	  if(ipos .lt. max_pos) then
	    ipos = ipos + 1
	  else
	    call dix_message(control,dix_msg_endfield)
	  end if
	elseif(iterm .eq. key_left) then
	  if(ipos .gt. 1) then
	    ipos = ipos - 1
	  else
	    call dix_message(control,dix_msg_stafield)
	  end if
	elseif(iterm .eq. key_erase) then
	  string = ' '
	  call smg$put_chars(d_id,string,row_inp,col_inp,,video)
	  nkar = 0
	  ipos = 1
	elseif(iterm .eq. key_delete) then
	  if(ipos .gt. 1) then
	    dix_smg_get_string_1 = .true.
	    string(1:string_len) = string(1:ipos-2)//
     1                               string(ipos:string_len)
	    ipos = ipos - 1
	    goto 52
	  else
	    call dix_message(control,dix_msg_stafield)
	  end if
	elseif(iterm .eq. key_enter  .or. 
     1         iterm .eq. key_remove .or.
     1         iterm .eq. key_put    .or.
     1         iterm .eq. key_do     .or.
     1         iterm .eq. key_down   .or.
     1         iterm .eq. key_up     .or.
     1         iterm .eq. key_prev   .or.
     1         iterm .eq. key_next   .or.
     1         iterm .eq. key_next_window.or.
     1         iterm .eq. key_prev_window.or.
     1         iterm .eq. key_select .or.
     1         iterm .eq. key_exit) then
	  goto 90
	elseif(iterm .eq. key_swap_dis) then
	  call dix_message(control,dix_msg_kardisp,
     1            %val(ipos),
     1            %val(ichar(string(ipos:ipos))),
     1            %val(ichar(string(ipos:ipos))),
     1            %val(ichar(string(ipos:ipos))))
	elseif(dix_util_kar_in_ran(iterm) .or. iterm .eq.key_swap_num) then
	  if(iterm .eq. key_Swap_num) then
	    call dix_message(control,dix_msg_hexmode1)
	    call smg$read_keystroke(control.keyboard_id,iterm)
	    if(.not. dix_con_kar_to_hex(char(iterm),k)) goto 55
	    call dix_message(control,dix_msg_clear)
	    call dix_message(control,dix_msg_hexmode2)
	    call smg$read_keystroke(control.keyboard_id,l)
	    if(.not. dix_con_kar_to_hex(char(iterm),l)) goto 55
	    iterm = k*16+l
	    call dix_message(control,dix_msg_clear)
	  end if
	  if(ipos .le. max_pos) then
	    dix_smg_get_string_1 = .true.
	    if(insert) then
	      if(string(1:1) .ne. ' ') then
	        call dix_message(control,dix_msg_strfull)
	        goto 50
	      else
	        string(1:string_len) = string(2:ipos-1)//char(iterm)//
     1                         string(ipos:string_len)
	      end if
	    else
	      if(ipos .gt. string_len) then
	        call dix_message(control,dix_msg_strfull)
	        goto 50
	      else
	        string(ipos:ipos) = char(iterm)
	      endif
	    end if
	    if(ipos .lt. max_pos) ipos = ipos + 1
	    goto 52
	  else
	    call dix_message(control,dix_msg_endfield)
	  end if
	else
	  call dix_mes_invkey(control,context)
	end if
50	iterm = 0
	goto 10
c
c Stirng changed, check for length
c
52	do k=string_len,1,-1
	  if(string(k:k) .ne. ' ') goto 341
	end do
	k = 0
341	nkar = k
	call smg$put_chars(d_id,string(1:nkar),row_inp,col_inp,,video)
	call smg$put_chars(d_id,string(nkar+1:string_len),
     1                  row_inp,col_inp+nkar)
	
	goto 50
c
55	call dix_message(control,dix_msg_illhexchar)
	goto 50
c
90	continue
        call smg$put_chars(d_id,string(1:nkar),
     1                         row_inp,col_inp,,video_inp)
	call dix_smg_unstack_help(control)
	call help_exit(help_des)
	return
	end		

	function dix_smg_select_field(control,data,size,bits,fldnam,
     1                                reverse,modify,readonly)
	implicit none
c
c Display a list  and let the user choose one
c
	include 'dix_def.inc'
c
	record /control/ control
 	integer*4 data(*)		!:io: the data
	integer*4 size                  !:i: the datasize in bits
	logical*4 bits			!:i: allow multiple bits set
	character*(*) fldnam		!:i: fieldnames
	logical*4 reverse		!:i: Bits reversed?         
	logical*4 modify		!:i: modify mode?
	logical*4 readonly		!:i: readonly field
	logical*4 dix_smg_select_field
c#
	include '($smgdef)'
c
	integer*4 ncol,width,k,dis_id,iterm,nf,r,c,nrow,ipos,val,kcol,krow
	integer*4 temp_data(2),max_w,r_old,c_old,kpos,tel,nf_tot
	character*(max_symbol_name_length) field1
c
	integer*4 max_bits
	parameter (max_bits=64)
	integer*4 indices(max_bits)
c
	logical*4 str$element
	logical dix_dump_in_modify
	integer*4 dix_util_get_len
c
	logical test_bit,bit_set,do_incr
	character kar
	integer*4 all_bits(2),nk
	character*(max_line_length) line
	record /dyn_help/ help_des
c
	character*(*) context
	parameter (context = 'SELFIELD')
	character*(*) label
	parameter (label = 'Selecting')
c
c Build help text
c
	call help_init_std(control,help_des,'Select fields',20,11,context)
	if(bits) then
	  call help_key(control,help_des,key_remove,
     1                'Clear all bits',context)
	  call help_key(control,help_des,key_put,
     1                'Set all bits',context)
	endif
	call help_key(control,help_des,key_exit,
     1                'Disregard changes',context)
	call help_key(control,help_des,key_enter,
     1                'Activate this field',context)
	call help_key(control,help_des,key_do,
     1                'Accept this value(s)',context)
	call dix_smg_stack_help(control,help_des)
c
c compute #names
c
	dix_smg_select_field = .false.
	nf = 0
	max_w  = 0 
	nf_tot = 0
	do while(str$element(field1,nf_tot,',',fldnam)) 
	  ipos = dix_util_get_len(field1)
	  if(ipos .gt. max_w) max_w = ipos
	  if(ipos .ne. 0) nf = nf+1	!alleen niet lege velden
	  nf_tot = nf_tot + 1
	end do
c
c We have nf fields
c compute #columns to display
c
	nrow = min(nf,control.nrows-3)
	ncol = (nf+nrow-1)/nrow
	width = min(max_w+2,control.ncols/ncol)
c
	temp_data(1) = data(1)
	temp_data(2) = 0
	if(size .gt. 32) temp_data(2) = data(2)
c
c Compute width of each field
c
	k = max(len(label)+1,width*ncol)
	call smg$create_virtual_display(nrow,k,dis_id)
	call smg$label_border(dis_id,label)
c
	call smg$paste_virtual_display(dis_id,control.paste_id,2,
     1           control.ncols-width*ncol)
c
c
5	tel = 0
	all_bits(1) = 0
	all_bits(2) = 0
	do k=0,nf_tot-1
	  call str$element(field1,k,',',fldnam)
	  r = mod((tel),nrow)+1
	  c = tel/nrow*width+1
	  if(bits) then
	    bit_set = test_bit(k,temp_data)
	    if(reverse) bit_set = .not. bit_set
	    kar = ' '
	    if(bit_set) kar = '*'
	    if(field1 .ne. ' ') then
	      call set_bit(k,all_bits)
	      tel = tel + 1
	      call  smg$put_chars(dis_id,kar//field1(1:width-2),r,c)
	      indices(tel) = k		!remember bit position
	    endif
	  else
	    ipos = index(field1,'=')
	    if(ipos .gt. 1) then
	      read(field1(1:ipos-1),'(bn,i10)') val
	    else
	      val = k
	    endif
	    kar = ' '
	    if(val .eq. temp_data(1)) then
	      kar = '*'
	      r_old = r
	      c_old = c
            endif
	    tel = tel + 1
	    call  smg$put_chars(dis_id,kar//field1(1:width-2),r,c)
	  endif
	end do
c
	ipos = 0
c
50	if(ipos .lt. 0) ipos = 0
	if(ipos .ge. nf) ipos = nf-1
	r = mod(ipos,nrow)+1
	c = ipos/nrow*width+1
c
	call str$element(field1,ipos,',',fldnam)
c
51	call smg$set_cursor_abs(dis_id,r,c)
	call dix_get_key(control,iterm,krow,kcol,context)
	do_incr = .true.
c
	if(iterm .eq. key_mouse_left) then
	  iterm = 0
	  krow = krow - 1	!pasted at row 2
	  kcol = kcol - control.ncols+width*ncol
	  if(krow .ge. 1 .and. krow .le. nrow .and.
     1       kcol .ge. 1 .and. kcol .le. width*ncol) then
	    kcol = (kcol-1) /width
	    k = kcol*nrow + krow -1
	    if(k .lt. nf) then
	      ipos = k
	      iterm = key_enter
	      do_incr = .false.
	    endif
	  endif
	  if(iterm .eq. 0) goto 50	   
	elseif(iterm .eq. key_mouse_middle) then
	  goto 51	!ignore middle mouse
	elseif(iterm .eq. key_mouse_right .or. iterm .eq. key_menu) then
	  nk = 0
	  call sys$fao('Accept,Abort,ClearAll,SetAll,Toggle',nk,line)
	  call dix_smg_select_menu(control,line(1:nk),line,
     1                .false.,'Choises',0,0,.true.)
	  if(line(1:1) .eq. 'AC') then
	    iterm = key_do
	  elseif(line(1:1) .eq. 'AB') then
	    iterm = key_abort
	  elseif(line(1:1) .eq. 'C') then
	    iterm = key_remove
	  elseif(line(1:1) .eq. 'S') then
	    iterm = key_put
	  elseif(line(1:1) .eq. 'T') then
	    iterm = key_enter
	  else
	    goto 51
	  endif
	endif
c
	if(iterm .eq. key_enter) then
	  r = mod(ipos,nrow)+1
	  c = ipos/nrow*width+1
	  if(.not. dix_dump_in_modify(control,modify,readonly)) goto 50
	  if(bits) then
	    kpos = indices(ipos+1)
	    kar = ' '
	    if(test_bit(kpos,temp_data)) then
	      call clear_bit(kpos,temp_data)
	      bit_set = .false.
 	      if(reverse) kar = '*'
	    else
	      call set_bit(kpos,temp_data)
	      bit_set = .true.
	      if(.not. reverse) kar = '*'
	    endif 
	    call smg$put_chars(dis_id,kar,r,c)	      
	    if(do_incr) ipos = ipos + 1
	  else
c
c Number case, 
c
	    k = index(field1,'=')
	    if(k .eq. 0) then
	      temp_data(1) = ipos
	    else
	      read(field1(1:k-1),'(bn,i10)') temp_data(1)
	    end if
	    call smg$put_chars(dis_id,' ',r_old,c_old)
	    call smg$put_chars(dis_id,'*',r,c)
	    r_old = r
	    c_old = c
	  endif
	elseif(iterm .eq. key_help) then
	  call dix_smg_help(control,context)
	elseif(iterm .eq. key_do) then
	   goto 90
	elseif(iterm .eq. key_exit) then
	   goto 95
	elseif(iterm .eq. key_down) then
	  ipos = ipos +1
	elseif(iterm .eq. key_up) then
	  ipos = ipos -1
	elseif(iterm .eq. key_put .or. iterm .eq. key_remove) then
	  if(.not. dix_dump_in_modify(control,modify,readonly)) goto 50
	  if(bits) then
	    do k=0,nf-1
	      kpos = indices(k+1)
	      if(test_bit(kpos,all_bits)) then
c
c The bit was in the original setting
c
	        if(iterm .eq. key_put) then
c
c All bits to be active
c
	          kar = '*'
	          if(reverse) then
c
cWe want the reverse option
c
	            call clear_bit(kpos,temp_data)
	          else
	            call set_bit(kpos,temp_data)
	          endif
	        else
c
c Alll bits to be passive
c
	          kar = ' '
	          if(reverse) then
c
cWe want the reverse option
c
	            call set_bit(kpos,temp_data)
	          else
	            call clear_bit(kpos,temp_data)
	          endif
	        endif
	        r = mod(k,nrow)+1
	        c = k/nrow*width+1
	        call smg$put_chars(dis_id,kar,r,c)	      
	      endif
	    end do
	  else
	    call dix_mes_invkey(control,context)
	  endif
	elseif(iterm .eq. key_left) then
	  ipos = ipos - nrow
	  if(ipos .lt. 0) then
	    ipos = ipos + ncol*nrow - 1
	  endif
	elseif(iterm .eq. key_top) then
	  ipos = 0
	elseif(iterm .eq. key_bot) then
	  ipos = nf
	elseif(iterm .eq. key_prev) then
	  ipos = ipos - 10
	elseif(iterm .eq. key_next) then
	  ipos = ipos + 10
	elseif(iterm .eq. key_right) then
	  ipos = ipos + nrow
	  if(ipos .ge. nf) then
	    ipos = ipos - ncol*nrow + 1
	  endif
	else
	  call dix_mes_invkey(control,context)
	end if
	goto 50
90	call dix_util_insert_bits(temp_data,0,size,data)
 	dix_smg_select_field = .true.
95	call smg$delete_virtual_display(dis_id)
	call dix_smg_unstack_help(control)
	call help_exit(help_des)
	return
	end
	subroutine dix_smg_getset_phys_cursor(control,setit,row,col)
	implicit none
c
c Get or set physical cursor
c
	include 'dix_def.inc'
	record /control/ control
	logical*4 setit		!if true the set, else get
	integer*4 row      	!:o: row
	integer*4 col		!:o: column
c#
	include '($smgdef)'
	record /smg$r_attribute_info_block/ smgrec
c
	if(setit) then
	  call smg$set_physical_cursor(control.paste_id,row,col)
	else
	  call smg$get_pasteboard_attributes(control.paste_id,
     1              smgrec,sizeof(smgrec))
	  row = smgrec.smg$w_phys_cursor_row
	  col = smgrec.smg$w_phys_cursor_col
	end if
	return
	end
	function dix_get_key(control,dix_key,row,col,context)
	implicit none
c
c Get a key hit from the user
c
	include 'dix_def.inc'
	record /control/ control
	integer*4 dix_key		!:o the key read
	integer*4 row			!:o: row when mouse click
	integer*4 col			!:o: col when mouse click
	character*(*) context		!:i: the context (screen) 
	logical dix_get_key		!:f: status of smg$read_key
c#
c
	integer*4 istat
	integer*4 keydefs_get_key
	external dix_msg_disontop
	external dix_msg_clear
	external dix_msg_illstate
c
	call dix_message(control,dix_msg_disontop)	!set display on top
10	istat = keydefs_get_key(control.key_table,
     1           control.keyboard_id,dix_key,control,
     1           row,col,context)
	if(.not. istat) dix_key = key_exit
	call dix_message(control,dix_msg_clear)
	if(dix_key .eq. key_repaint) then
	  call smg$repaint_screen(control.paste_id)
	  goto 10
	end if
c
c Toggle mouse usage
c
	if(dix_key .eq. key_mouse_toggle) then
	  control.use_mouse = .not. control.use_mouse
	  goto 10
	endif
c
	if(dix_key .eq. 0) then
	  call dix_message(control,dix_msg_illstate)
	  goto 10
	endif
	dix_get_key = istat
	return
	end
	subroutine dix_mes_invkey(control,context)
	implicit none
c
c give a message for help
c
	include 'dix_def.inc'	
	record /control/ control	!:i: control block
	character*(*) context		!:i: screen context
c#
	integer*4 nk
	character*(max_line_length) line
	external dix_msg_typhelp
c
	call keydefs_get_map(key_help,control,nk,line,context)
c
	call dix_message(control,dix_msg_typhelp,line(1:nk))
	return
	end
	function dix_smg_select_menu(control,lines,sel_line,horizontal,
     1                                 topic,row_w,col_w,add_ignore)
	implicit none
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	character*(*) lines		!:i: possible options
	character*(*) sel_line		!:o: selected line
	logical*4 horizontal		!:i: force horizontal display
	character*(*) topic		!:i: menu header (border name)
	integer*4 row_w			!:i: row wanted (0=auto)
	integer*4 col_w			!:i: col wanted (0=auto)
	logical*4 add_ignore		!:i: add ignore item?
	integer*4 dix_smg_select_menu	!:f: function result
c
	include '($smgdef)'
c
c
	integer*4 nit,k,nrow,ncol,dis_menu,istat,old_row,old_col
	integer*4 row,col,row_incr,col_incr,paste_row,paste_col,nk_bold
	integer*4 maxw,nk,ipos,iterm,krow,kcol,dis_ptr,col_arrow
c
	character*(max_short_line_length) item
	character*(max_screen_width) line
	character*(*) ignore_item
	parameter (ignore_item = 'Ignore')
c
	integer*4 dix_util_get_len_fu
	integer*4 dix_get_key
	integer*4 str$element
c
	record /dyn_help/ help_des
c
	character*(*) context
	parameter (context = 'MENU')
c
	call help_init_std(control,help_des,'select menu',
     1                     20,15,context)
c
	call help_init_std(control,help_des,'select files',20,15,context)
	call help_key(control,help_des,key_put,
     1         'inserts file(s) to list',context)
	call help_key(control,help_des,key_exit,
     1         'Return to prev screen and ignore',context)
	call help_key(control,help_des,key_enter,
     1         'Return to prev screen and select',context)
	call dix_smg_stack_help(control,help_des)
c
	nit = 0
	if(add_ignore) then
	  maxw = len(ignore_item)
	else
	  maxw = 0
	endif
	do while(str$element(item,nit,',',lines))
	  nit = nit + 1
	  nk = dix_util_get_len_fu(item)
	  if(nk .gt. maxw) maxw = nk	  
	end do
c
c Add ignore item
c
	if(add_ignore) nit = nit + 1
c
c Maxw is the max number of chars needed for one item
c  add 2 to seperate the columns
c
	maxw = maxw + 2	
	if(row_w .eq. 0) then
	  paste_row = 4
	else
	  paste_row = row_w
	endif
	if(col_w .eq. 0) then
	  paste_col = 2
	else
	  paste_col = col_w
	endif
	dis_ptr = 0
c
c Blank out the rest
c
	if(horizontal) then
c
c Horizontal display, try to display horizontal
c see how many fit on a screen width 
c
	  k    = (control.ncols-paste_col-2)/maxw	!need some space for box
	  nrow = (nit+k-1)/k		!should be one?
	  ncol = (nit+nrow-1)/nrow	!just to be sure
c
c Now compute #columns (each row maximal max_vert items)
c
	else
c
c We want a vertical display, see hom many fit
c
	  k = control.nrows-paste_row+1	!#rows left
	  ncol = (nit+k-1)/k		!should be one
	  nrow = (nit+ncol-1)/ncol	!just to be sure
	  if(ncol .gt. 1) then			!would be multiple col
c
c Would be more than 1 col
c
	    if(row_w .ne. 0) then
c 
c User wanted explicit row
c
	      paste_row = max(4,control.nrows-nit+1) !now map from bottom
	      k = control.nrows-paste_row +1	!#rows left
	      ncol = (nit+k-1)/k		!should be one
	      nrow = (nit+ncol-1)/ncol	!just to be sure
c
	    endif
	  endif
c
c If we have a topic, we need an arrow to point to the
c  original place
c
	  if(topic .ne. ' ' ) then
c
c See if we have room at the right
c
	    call smg$create_virtual_display(nrow,2,dis_ptr)
	    if(col_w .lt. control.ncols - ncol*maxw-5) then
c
c Does fit at the right
c
	      col_arrow = paste_col+1
	      paste_col = paste_col+4
	    else
c
c Must be at the left
c
	      col_arrow = paste_col-2
	      paste_col = paste_col-3 - ncol*maxw
	    endif
	  endif
	endif
c
	call smg$create_virtual_display(nrow,ncol*maxw,dis_menu)
	if(topic .ne. ' ') call smg$label_border(dis_menu,topic)
c
	row = 1
	col = 1
	do k=1,nit
	  if(k .eq. nit .and. add_ignore) then
	    item = Ignore_item
	  else
	    call str$element(item,k-1,',',lines)
	  endif
	  call smg$put_chars(dis_menu,item,row,col)
	  if(horizontal) then
	    col = col + maxw
	    if(col .gt. ncol*maxw) then
	      row = row + 1
	      col = 1
	    endif
	  else
	    row = row + 1
	    if(row .gt. nrow) then
	      col = col + maxw
	      row = 1
	    endif
	  endif
	enddo
c
	if(horizontal) then
	  row_incr = ncol
	  col_incr = 1
	else
	  row_incr = 1
	  col_incr = nrow
	endif
c
	call smg$paste_virtual_display(dis_menu,control.paste_id,
     1                                 paste_row,paste_col)
	if(dis_ptr .ne. 0) then
	  if(col_arrow .lt. paste_col) then
	    call smg$put_chars(dis_ptr,'<-',row_w-paste_row+1,1)
	  else
	    call smg$put_chars(dis_ptr,'->',row_w-paste_row+1,1)
	  endif
	  call smg$paste_virtual_display(dis_ptr,control.paste_id,
     1                                 paste_row,col_arrow)
	endif
c
	old_row = 0
	old_col = 0
	ipos = 1
10	ipos = max(1,min(ipos,nit))
	row = mod(ipos-1,nrow) + 1
	col = (ipos-1)/nrow
	col = maxw*col + 1
	call smg$set_cursor_abs(dis_menu,row,col)
c
c  Unhighlight the previous
c
	if(old_row .ne. 0) call smg$change_rendition(dis_menu,
     1        old_row,old_col,1,nk_bold,0)
	call smg$read_from_display(dis_menu,line,,row)
	line = line(col:)
	nk_bold = index(line,' ')-1
	call smg$change_rendition(dis_menu,row,col,1,nk_bold,
     1                           smg$m_reverse)
	old_row = row
	old_col = col
c
	istat = dix_get_key(control,iterm,krow,kcol,'MENU')
	if(.not. istat) goto 90
c
	if(iterm .eq. key_mouse_left .or. 
     1     iterm .eq. key_mouse_right) then
	  krow = krow - paste_row  	 !0..nrow-1
	  kcol = (kcol - paste_col)/maxw !0..ncol-1
	  if(kcol .ge. 0 .and. kcol .lt. nrow) then
	    if(kcol .ge. 0 .and. kcol .lt. ncol) then
	      if(horizontal) then
	        k = kcol+1 + krow*ncol
	      else
	        k = kcol*nrow + krow + 1
	      endif
	      if(ipos .le. nit) then
	        ipos = k
	        if(iterm .eq. key_mouse_right) goto 90
	      endif
	    endif
	  endif
	  goto 10
	elseif(iterm .eq. key_mouse_middle) then
	  goto 10		!ignore
	endif
c
	if(iterm .eq. key_up) then
	  ipos = ipos - row_incr
	elseif(iterm .eq. key_down) then
	  ipos = ipos + row_incr
	elseif(iterm .eq. key_left) then
	  ipos = ipos - col_incr
	elseif(iterm .eq. key_right) then
	  ipos = ipos + col_incr
	elseif(iterm .eq. key_next) then
	  ipos = ipos + nit/2
	elseif(iterm .eq. key_prev) then
	  ipos = ipos - nit/2
	elseif(iterm .eq. key_top) then
	  ipos = 1
	elseif(iterm .eq. key_bot) then
	  ipos = nit
	elseif(iterm .eq. key_enter) then
	  goto 90
	elseif(iterm .eq. key_abort) then
	  ipos = nit
	  goto 90
	elseif(iterm .eq. key_help) then
	  call dix_smg_help(control,context)
	else
	  call dix_mes_invkey(control,context)
	endif
	goto 10
90 	call smg$delete_virtual_display(dis_menu)
 	if(dis_ptr .ne. 0) call smg$delete_virtual_display(dis_ptr)
	if(istat) then
	  if(ipos .eq. nit .and. add_ignore) then
	    sel_line = ' '		!ignore item
	  else
	    call str$element(item,ipos-1,',',lines)
	    call str$upcase(sel_line,item)
	  endif
	else
	  sel_line = ' '
	endif
c
c And return status
c
	call dix_smg_unstack_help(control)
	dix_smg_select_menu = istat
	return
	end
	subroutine dix_smg_set_scroll(dis_id,dis_id_offset,screen,
     1                                height,width)
	implicit none
c
c Make sure cursor is in displayed window
c  adapt the viewport if necessary
c
c	
	include 'dix_screen_def.inc'
	include '($smgdef)'
	integer*4 dis_id		!:i: display id
	integer*4 dis_id_offset         !:i: associate display (only vertical)
	record /screen_data/ screen     !:i: display data
	integer*4 height		!:i: override height if >0
	integer*4 width                 !:i: override width  if >0
c
	integer*4 k,limit
        integer*4 max_smooth_scroll
        parameter (max_smooth_scroll=20)
c
c Make sure the row is on the screen
c row must be in thhe screen
c
	if(screen.row .lt. 1) screen.row = 1
        do while(screen.row .lt. screen.row_offset)
          k = screen.row_offset-screen.row
          if(k .lt. max_smooth_scroll) k = 1
          screen.row_offset = screen.row_offset-k
          call smg$scroll_viewport(dis_id,smg$m_down,k)
          if(dis_id_offset .ne. 0) then
            call smg$scroll_viewport(dis_id_offset,smg$m_down,k)
          endif
        end do
c
c Now the lower part
c  row must be in the range
c  screen.row_offset..screen.row_offset + height-1
c   if height <=0 , height = screen.view_nrows
c  
	limit = height
	if(limit .le. 0) limit = screen.view_nrows
c
	k =max(screen.view_nrows,screen.nlines) -screen.view_nrows+limit
	if(screen.row .gt. k) screen.row = k
c
        do while(screen.row .gt. screen.row_offset+limit-1)
          k = screen.row - screen.row_offset -limit + 1
          if(k .lt. max_smooth_scroll) k = 1
          screen.row_offset = screen.row_offset+k
          call smg$scroll_viewport(dis_id,smg$m_up,k)
          if(dis_id_offset .ne. 0) then
            call smg$scroll_viewport(dis_id_offset,smg$m_up,k)
          endif
        end do
c
c  Now the column
c  col must be >= col_offset
c
	if(screen.col .lt. 0) screen.col = 1
c
        do while(screen.col .lt. screen.col_offset)
          k = screen.col_offset-screen.col
          if(k .lt. max_smooth_scroll) k = 1
          screen.col_offset = screen.col_offset-k
          call smg$scroll_viewport(dis_id,smg$m_right,k)
        end do
c
c And now the right side
c  col must be in the range
c  screen.col_offset..screen.col_offset + width-1
c   if width <=0 , width = screen.view_ncols
c
	limit = width
	if(limit .le. 0) limit = screen.view_ncols
c
	k =max(screen.view_ncols,screen.ncols) -screen.view_ncols+limit
	if(screen.col .gt. k) screen.col = k
c
        do while(screen.col .gt. screen.col_offset+limit-1)
          k = screen.col - screen.col_offset -limit + 1
          if(k .lt. max_smooth_scroll) k = 1
          screen.col_offset = screen.col_offset+k
          call smg$scroll_viewport(dis_id,smg$m_left,k)
        end do
c
	return
	end
