/*
MOVING:
              ^                   
              |                    
    <SHIFT> <- -> <SHIFT>
              |
              v
  
( click anywhere and cursor will go there )
   
<LEFT_ARROW>.............Go left one character
<RIGHT_ARROW>............Go right one character
<UP_ARROW>...............Go up one line
<DOWN_ARROW>.............Go down one line
<SHIFT><LEFT_ARROW>......Go to beginning of line 
<SHIFT><RIGHT_ARROW>.....Go to end of line
<RETURN>.................Splits current line
  
DONE_GENERAL
  
SELECTING:           with MOUSE                 with KEYBOARD
                  +---------------------+------------------------+
    chars         |  drag               |       <-- <CTRL> -->   |
    current line  |  double click       |       <CTRL> <RETURN>  |
    lines         |  click and drag     |       <CTRL> <RETURN>  |
    extending     |  <SHIFT> click      |       Any movement key |
    cancelling    |  click              |       <ESC>            |
                  +---------------------+------------------------+
DONE_SELECTING
*/

help.general = ''
do i = 2 while sourceline(i) ~= 'DONE_GENERAL'
    help.general = help.general || sourceline(i) || '0A'x
end

help.selecting = ''
do j = i + 1 while sourceline(j) ~= 'DONE_SELECTING'
    help.selecting = help.selecting || sourceline(j) || '0A'x
end

selected_name = ''

default_filename = "REXX:address_book.dat"

rx_tools_init = getclip( 'rx_tools_init' )
interpret rx_tools_init

a_screen = _send( 'screen', _OPEN, 2, HIRES + LACE, 'Address Book' )

edit_window = _send( 'rx_text_editor', _OPEN, 210, 20, 250, 175,
                                       ,"Address", my_port, a_screen )

call send edit_window, _SET_TAB_STOPS, '4'

interpret   first_menu"		'_Edit'"
interpret       item"           'copy',             xcopy,          'c'"
interpret       item"           'cut',              cut,            'x'"
interpret       item"           'paste',            paste,          'p'"
interpret       item"           'delete line',      delete_line,    'k'"

interpret   menu"            'HELP'"
interpret       item"           'general',          help,           '?'"
interpret       item"           'selecting',        help_selecting"


call send edit_window, _SET_MENU_STRIP, result

call send edit_window, _RX_BIND_KEY, _HELP, HELP

list_window = _send( 'rx_list_viewer', _OPEN, 10, 20, 200, 175,
									   ,"Name", my_port, a_screen )

call send list_window, _SET_CALLBACK, item_was_selected

interpret   first_menu"      'Project'"
interpret       item"           'open default',		open_def_file,	'o'"
interpret       item"           'open',				open_file"
interpret       item"           '_save',			save,			's'"
interpret       item"           '_save as',			save_as"
interpret       item"           'quit',				quit,			'q'"

interpret	menu"			'Edit'"
interpret		item"			'_modify',			modify,			'm'"
interpret		item"			'add',				add_item,		'a'"
interpret		item"			'_remove',			remove,			'r'"

call send list_window, _SET_MENU_STRIP, result

number_of_windows = 2

event_handler = getclip( 'rx_tools_event_handler' )
interpret event_handler

SAVE_AS: procedure expose addresses. opened_filename default_filename,
					      list_window edit_window selected_name foreach
	parse arg a_console
	
	a_file_req = _send( 'file_requester', _CREATE, a_console )
	full_file_name = send( a_file_req, _POST )
	call send a_file_req, _FREE
	if full_file_name ~= "" then
		call save_file full_file_name
	return

SAVE: procedure expose addresses. opened_filename default_filename,
					   list_window edit_window selected_name foreach
	if symbol( opened_filename ) = 'LIT' then
		do
		/* Ask user if he wants to overwrite the default file */
		call query_save
		end
	else
		do
		call save_file opened_filename
		end
	return

SAVE_FILE: procedure expose addresses. opened_filename default_filename,
					   		list_window edit_window selected_name foreach
	parse arg filename

	if c2d( send( list_window, _GET_LINES ) ) = 0 then
		do
	    call _send 'notify', _CREATE, list_window, 10, 1,
	    		,"NO ADDRESSES", "There's nothing to save" || '0A 20'x
		return
		end

	if open( 'outstream', filename, 'W' ) then
		do
		opened_filename = filename
		call save_vars
		call close 'outstream'
		call send edit_window, _HAS_SYNCHED
		end
	else
		do
		    call _send 'notify', _CREATE, list_window, 10, 1,
		    		,"OPEN ERROR", "Couldn't open" filename || '0A 20'x
		end
	return

SAVE_VARS: procedure expose addresses. opened_filename default_filename,
					   		list_window edit_window selected_name foreach
	call synch_address
	collection = send( list_window, _GET_LINES )

	block = 'name = send( element, _GET_STRING );
			 writeln( "outstream", "#"name );
			 if addresses.name ~= "" & addresses.name ~= "0A"x then;
				do;
				writech( "outstream", addresses.name );
				end;'

	interpret foreach
	return				


OPEN_FILE: procedure expose addresses. opened_filename,
								default_filename list_window edit_window,
								selected_name pending_filename
	parse arg a_console
	
	a_file_req = _send( 'file_requester', _CREATE, a_console )
	full_file_name = send( a_file_req, _POST )
	call send a_file_req, _FREE
	if full_file_name ~= "" then
		call load_file full_file_name
	return

OPEN_DEF_FILE: procedure expose addresses. opened_filename,
								default_filename list_window edit_window,
								selected_name pending_filename
	call load_file default_filename
	return

LOAD_FILE: procedure expose addresses. opened_filename list_window,
							edit_window selected_name pending_filename
	parse arg filename

	if ~ exists( filename ) then
		do
		    call _send 'notify', _CREATE, list_window, 10, 1,
		    		,"NON EXISTENT",  filename "does not exist" || '0A 20'x
			return
		end

	if open( 'instream', filename, 'R' ) then
		do
			first_char_of_file = readch( 'instream', 1 )
			if first_char_of_file = '#' then
				do
				call seek 'instream', 0, 'B'
				if send( edit_window, _HAS_CHANGED2 ) then
					do
					pending_filename = filename
					call query_load
					call close 'instream'
					return
					end
				opened_filename = filename
				call load_vars
				call send list_window, _ON_MENU, 'save as'
				call send edit_window, _HAS_SYNCHED
				end
			else
				do
			    call _send 'notify', _CREATE, list_window, 10, 1, "WRONG TYPE",
			    		,filename "is not an address file" || '0A 20'x
				end
			call close 'instream'
		end
	else
		do
		    call _send 'notify', _CREATE, list_window, 10, 1,
		    		,"OPEN ERROR", "Couldn't open" filename || '0A 20'x
		end
	return

LOAD_VARS: procedure expose addresses. list_window edit_window,
							selected_name
	names = ''
	an_address = ''
	name = ''
	selected_name = ''
	drop addresses.
	do forever
		line = readln( 'instream' )
		if eof( 'instream' ) then
			leave
		if abbrev( line, '#', 1 ) then
			do
				if name ~= '' then
					addresses.name = an_address
				name = substr( line, 2 )
			    names = names || name || '0A'x
				an_address = ''
			end
		else
			do
				an_address = an_address || line || '0A'x
			end
	end
	if name ~= '' then
		addresses.name = an_address
	call send list_window, _ATTACH_LIST, names
	call send edit_window, _IMPORT_TEXT, ''
	return

MOD_STRING_GAD:
OK:
	display_string = 1
	return

CANCEL:
	display_string = 0
	return

MOD_REQ_SET: procedure
	parse arg from_window
	
	a_requester = send( from_window, _GET_REQUESTER )
	call send a_requester, _ACTIVATE_GADGET, MOD_STRING_GAD
	return


MOD_REQ_CLEAR: procedure expose display_string addresses. selected_name
	parse arg from_window


	a_requester = send( from_window, _GET_REQUESTER )
	parents_window = send( a_requester, _GET_PARENTS_WINDOW )
	a_gadget = send( a_requester, _FIND_GADGET, MOD_STRING_GAD )
	selected_item = send( parents_window, _GET_SELECTED_ITEM );

	changed_item = send( a_gadget, _RETRIEVE_STRING_FROM_GADGET )

	call send a_requester, _FREE

	if display_string & changed_item ~= '' & selected_item ~= changed_item then
		do
		compound_symbols_value = addresses.changed_item
		if compound_symbols_value = 'ADDRESSES.'changed_item then
			do
			addresses.changed_item = addresses.selected_name
			drop addresses.selected_name
			selected_name = changed_item
			call send parents_window, _DELETE_SELECTED_ITEM
			call send parents_window, _ADD_ITEM, changed_item
			call send parents_window, _ON_MENU, 'modify'
			call send parents_window, _ON_MENU, 'remove'
			end
		else
			do
		    call _send 'notify', _CREATE, parents_window, 10, 1,
		    		,"Duplicate entry", changed_item ' already exists' || '0A 20'x
			end
		end

	return

ADD_REQ_CLEAR: procedure expose display_string addresses. edit_window,
								selected_name foreach
	parse arg from_window

	a_requester = send( from_window, _GET_REQUESTER )
	parents_window = send( a_requester, _GET_PARENTS_WINDOW )
	a_gadget = send( a_requester, _FIND_GADGET, MOD_STRING_GAD )

	new_name = send( a_gadget, _RETRIEVE_STRING_FROM_GADGET )

	call send a_requester, _FREE

	if display_string & new_name ~= '' then
		do
		compound_symbols_value = addresses.new_name
		if compound_symbols_value = 'ADDRESSES.'new_name then
			do
			addresses.new_name = ''
			call send parents_window, _ADD_ITEM, new_name
			call item_was_selected parents_window
			call send edit_window, _ACTIVATE_WINDOW
			end
		else
			do
		    call _send 'notify', _CREATE, parents_window, 10, 1,
		    		,"Duplicate entry", new_name ' already exists' || '0A 20'x
			end
		end

	return

MODIFY: procedure
	parse arg from_window

	a_requester = ,
	_send( 'rx_requester', _CREATE, mod_req_set, mod_req_clear, from_window )

	call send a_requester, _ADD_END_STRING_GADGET, MOD_STRING_GAD, 20, 5, 261
	selected_item = send( from_window, _GET_SELECTED_ITEM )
	call send a_requester, _SET_DEFAULT_STRING2, MOD_STRING_GAD, selected_item
	call send a_requester, _ADD_END_HIT_GADGET, OK, 10, 30, 'ok'
	call send a_requester, _ADD_END_HIT_GADGET, CANCEL, -60, 30, 'cancel'
	call send a_requester, _POST_REQUESTER, 50, 40, 300, 50, 'edit selection'
	return

IGNORE:
	return

YES_X:
	do_it = 1
	return

NO_X:
	do_it = 0
	return

QC_CLEAR: procedure expose packet a_screen do_it,
						   addresses. opened_filename default_filename,
					   	   list_window edit_window selected_name foreach
	parse arg from_window

	a_requester = send( from_window, _GET_REQUESTER )
	call send a_requester, _FREE

	if do_it then
		do
		call save
		end
    call send edit_window, _DELETE
	call send list_window, _DELETE
	call send a_screen, _FREE
	call reply packet, 0
    exit 0
	return


QUERY_CLOSE: procedure
	parse arg from_window

	a_requester = ,
	_send( 'rx_requester', _CREATE, ignore, qc_clear, from_window )

	call send a_requester, _ADD_END_HIT_GADGET, YES_X, 10, 15, 'yes'
	call send a_requester, _ADD_END_HIT_GADGET, NO_X, -60, 15, 'no'
	call send a_requester, _POST_REQUESTER, 150, 20, 200, 35, 'Save changes?'
	return

QL_CLEAR: procedure expose edit_window selected_name pending_filename do_it,
						   addresses. opened_filename list_window
	parse arg from_window

	a_requester = send( from_window, _GET_REQUESTER )
	call send a_requester, _FREE

	if do_it then
		do
		call send edit_window, _HAS_SYNCHED
		call load_file pending_filename
		end
	return

QUERY_LOAD: procedure expose list_window

	a_requester = ,
	_send( 'rx_requester', _CREATE, ignore, ql_clear, list_window )

	call send a_requester, _ADD_END_HIT_GADGET, YES_X, 10, 15, 'ok'
	call send a_requester, _ADD_END_HIT_GADGET, NO_X, -60, 15, 'cancel'
	call send a_requester, _POST_REQUESTER, 100, 20, 250, 35, 'Overwrite unsaved data?'
	return

QS_CLEAR: procedure expose edit_window selected_name default_filename do_it,
						   addresses. opened_filename list_window foreach
	parse arg from_window

	a_requester = send( from_window, _GET_REQUESTER )
	call send a_requester, _FREE

	if do_it then
		do
		call save_file default_filename
		end
	return

QUERY_SAVE: procedure expose list_window

	a_requester = ,
	_send( 'rx_requester', _CREATE, ignore, qs_clear, list_window )

	call send a_requester, _ADD_END_HIT_GADGET, YES_X, 10, 15, 'ok'
	call send a_requester, _ADD_END_HIT_GADGET, NO_X, -60, 15, 'cancel'
	call send a_requester, _POST_REQUESTER, 100, 20, 250, 35, 'Overwrite default file?'
	return

ADD_ITEM: procedure
	parse arg from_window

	a_requester = ,
	_send( 'rx_requester', _CREATE, mod_req_set, add_req_clear, from_window )

	call send a_requester, _ADD_END_STRING_GADGET, MOD_STRING_GAD, 20, 5, 261
	call send a_requester, _ADD_END_HIT_GADGET, OK, 10, 30, 'ok'
	call send a_requester, _ADD_END_HIT_GADGET, CANCEL, -60, 30, 'cancel'
	call send a_requester, _POST_REQUESTER, 50, 40, 300, 50, 'add item'
	return

SYNCH_ADDRESS: procedure expose edit_window selected_name addresses. ,
								foreach
	if selected_name ~= '' then
		do
			an_address = ''
			collection = send( edit_window, _GET_LINES )
			block =	'an_address = an_address || send( element, _GET_STRING ) || "0A"x'
			interpret foreach
			addresses.selected_name = an_address
		end
	return


ITEM_WAS_SELECTED: procedure expose edit_window selected_name addresses. ,
									foreach
	parse arg a_window

	call send a_window, _ON_MENU, 'modify'
	call send a_window, _ON_MENU, 'remove'
	call send a_window, _ON_MENU, 'save'
	call send a_window, _ON_MENU, 'save as'
	call send edit_window, _ON_MENU, 'Edit'
	call synch_address
	selected_name = send( a_window, _GET_SELECTED_ITEM )
	call send edit_window, _IMPORT_TEXT, addresses.selected_name
	return

REMOVE: procedure expose selected_name addresses. edit_window
	parse arg a_window

	selected_name = send( a_window, _GET_SELECTED_ITEM )
	drop addresses.selected_name
	selected_name = ''
	call send edit_window, _IMPORT_TEXT, ''
	call send a_window, _DELETE_SELECTED_ITEM
	call send a_window, _OFF_MENU, 'modify'
	call send a_window, _OFF_MENU, 'remove'
	return

HELP: procedure expose help.
    parse arg from_window
    call _send 'notify', _CREATE, from_window, 10, 1, "HELP general", help.general
    return

HELP_SELECTING: procedure expose help.
    parse arg from_window
    call _send 'notify', _CREATE, from_window, 10, 1, "HELP selecting", help.selecting
    return


XCOPY: procedure
parse arg a_console
call send a_console, _COPY
return

CUT: procedure
parse arg a_console
call send a_console, _CUT
return

PASTE: procedure
parse arg a_console
call send a_console, _PASTE
return

DELETE_LINE: procedure
parse arg a_console
call send a_console, _DELETE_LINE
return

QUIT:
CLOSEWINDOW: procedure expose edit_window list_window packet a_screen
	parse arg from_window
	if send( edit_window, _HAS_CHANGED2 ) then
		do
		call query_close from_window
		return
		end
    call send edit_window, _DELETE
	call send list_window, _DELETE
	call send a_screen, _FREE
	call reply packet, 0
    exit 0

