From f6a2bd488ca74881855f74f5302078526cfbd81c Mon Sep 17 00:00:00 2001 From: Jeffrey Armstrong Date: Sat, 8 Aug 2020 09:18:45 -0400 Subject: Initial work on favorites added. Probably flat-out wrong... --- ag_render.f90 | 21 ++++ favorites.f90 | 353 +++++++++++++++++++++++++++++++++++++++++++++++++++++ gemini-windows.prj | 11 +- main.F90 | 55 +++++++++ platform.F90 | 75 ++++++++++++ render.f90 | 13 +- 6 files changed, 520 insertions(+), 8 deletions(-) create mode 100644 favorites.f90 create mode 100644 platform.F90 diff --git a/ag_render.f90 b/ag_render.f90 index fc80295..383be04 100644 --- a/ag_render.f90 +++ b/ag_render.f90 @@ -43,6 +43,7 @@ implicit none integer, parameter::ag_render_event_scroll = 5 integer, parameter::ag_render_event_resize = 6 integer, parameter::ag_render_event_mousemove = 7 + integer, parameter::ag_render_event_favorite = 8 type :: link integer, dimension(4)::location @@ -55,6 +56,7 @@ implicit none integer::address_id integer::go_button_id integer::back_button_id + integer::fave_button_id integer::scroll_id integer::font_size @@ -153,6 +155,15 @@ contains end subroutine go_button_callback + subroutine fave_button_callback() + use appgraphics, only: stopidle + implicit none + + ag_render_event = ag_render_event_favorite + call stopidle() + + end subroutine fave_button_callback + subroutine mouse_button_callback(x, y) use appgraphics, only: stopidle implicit none @@ -264,6 +275,13 @@ contains call setbuttonposition(self%go_button_id, x, 2, 40, 20) end if + x = x + 50 + if(self%fave_button_id < 0) then + self%fave_button_id = createbutton(x, 2, 40, 20, "Wow!", fave_button_callback) + else + call setbuttonposition(self%fave_button_id, x, 2, 40, 20) + end if + ! Clears any drawing operations for controls quickly ignored = switch_to_thread() @@ -805,6 +823,9 @@ contains self%y = 0 ag_action = render_action_rewrap + + case(ag_render_event_favorite) + ag_action = render_action_favorite end select diff --git a/favorites.f90 b/favorites.f90 new file mode 100644 index 0000000..d1ba7d1 --- /dev/null +++ b/favorites.f90 @@ -0,0 +1,353 @@ +module favorite_handling +implicit none + + private + + public :: favorite, sort_added, sort_alpha, read_favorites, & + write_favorites, add_favorite, remove_favorite + + type :: favorite + + character(80)::name + character(1024)::link + integer::added + + end type favorite + +contains + + pure function string_compare(s1, s2) result(res) + implicit none + + character(*), intent(in)::s1, s2 + integer::res + + integer::n1, n2 + integer::i + + n1 = len_trim(s1) + n2 = len_trim(s2) + + res = 0 + do i = 1, min(n1, n2) + + if(s1(i:i) < s2(i:i)) then + res = -1 + exit + else if(s1(i:i) > s2(i:i)) then + res = 1 + exit + end if + + end do + + end function string_compare + + pure function string_location(array, minsearch) result(res) + implicit none + + character(*), dimension(:), intent(in)::array + logical, intent(in), optional::minsearch + integer::res + + logical::mymin + integer::i + + mymin = .false. + if(present(minsearch)) then + mymin = minsearch + end if + + res = 1 + do i = 2, size(array) + if(mymin .and. string_compare(array(res), array(i)) < 0) then + res = i + else if((.not. mymin) .and. string_compare(array(res), array(i)) > 0) then + res = i + end if + end do + + end function string_location + + subroutine sort_added(favorites, latest) + implicit none + + type(favorite), dimension(:), intent(inout)::favorites + logical, intent(in)::latest + + integer::i_loc + integer::i, n + + type(favorite)::swapper + + n = size(favorites) + do i=1, n-1 + + if(latest) then + i_loc = maxloc(favorites(i:n)%added, 1) + else + i_loc = minloc(favorites(i:n)%added, 1) + end if + + i_loc = i_loc + i - 1 + + if(i /= i_loc) then + swapper = favorites(i) + favorites(i) = favorites(i_loc) + favorites(i_loc) = swapper + end if + + end do + + end subroutine sort_added + + subroutine sort_alpha(favorites, descending) + implicit none + + type(favorite), dimension(:), intent(inout)::favorites + logical, intent(in)::descending + + integer::i_loc + integer::i, n + + type(favorite)::swapper + + n = size(favorites) + do i=1, n-1 + + if(descending) then + i_loc = string_location(favorites(i:n)%name) + else + i_loc = string_location(favorites(i:n)%name, minsearch=.true.) + end if + + i_loc = i_loc + i - 1 + + if(i /= i_loc) then + swapper = favorites(i) + favorites(i) = favorites(i_loc) + favorites(i_loc) = swapper + end if + + end do + + end subroutine sort_alpha + + function read_favorite(unit_number) result(res) + implicit none + + type(favorite)::res + integer, intent(in)::unit_number + + character::c + character(len=10)::text_date + integer::i, ios + + ! Leading spaces... + read(unit_number, '(A1)', advance='no') c + do while(c == ' ' .or. c == char(9)) + read(unit_number, '(A1)', advance='no') c + end do + + ! Link + res%link = " " + i = 1 + do while(c /= ' ' .and. c /= char(9)) + res%link(i:i) = c + read(unit_number, '(A1)', advance='no') c + end do + + ! Separating spaces... + do while(c == ' ' .or. c == char(9)) + read(unit_number, '(A1)', advance='no') c + end do + + ! Name... + res%name = " " + ios = 0 + do while(c /= ' ' .and. c /= char(9)) + res%name(i:i) = c + read(unit_number, '(A1)', advance='no', iostat=ios) c + end do + + ! The date should be at the end of the link + i = index(res%name, "(", .true.) + text_date = res%name(i+1:i+10) + do i = 5, 9 + text_date(i:i) = text_date(i+1:i+1) + end do + do i = 7, 8 + text_date(i:i) = text_date(i+1:i+1) + end do + read(text_date, '(I8)') res%added + + end function read_favorite + + function read_favorites(unit_number) result(faves) + implicit none + + integer, intent(in)::unit_number + type(favorite), dimension(:), allocatable::faves + + character(80)::temp + integer::n, i + + ! Title + read(unit_number, *) temp + + ! Blank + read(unit_number, *) temp + + ! Count + read(unit_number, *) n + + ! Blank + read(unit_number, *) temp + + allocate(faves(n)) + + do i = 1, n + read(unit_number, '(A2)', advance='no') temp + faves(i) = read_favorite(unit_number) + end do + + end function read_favorites + + subroutine write_favorite(unit_number, f) + implicit none + + integer, intent(in)::unit_number + type(favorite), intent(in)::f + + write(unit_number, *) "=> "//trim(f%link)//" "//f%name + + end subroutine write_favorite + + subroutine write_favorites(unit_number, faves) + implicit none + + integer, intent(in)::unit_number + type(favorite), dimension(:), intent(in)::faves + + integer::i + character(8)::n_text + + write(unit_number, *) "Favorites" + write(unit_number, *) + + write(n_text, '(I8)') size(faves) + + write(unit_number, *) trim(adjustl(n_text))//" Links Are Marked As Favorites" + write(unit_number, *) + + do i = 1, size(faves) + call write_favorite(unit_number, faves(i)) + end do + + end subroutine write_favorites + + pure function find_favorite(faves, link) + implicit none + + integer::find_favorite + type(favorite), dimension(:), allocatable, intent(in)::faves + character(*), intent(in)::link + + if(.not. allocated(faves)) then + find_favorite = -1 + else + do find_favorite = 1, size(faves) + if(trim(link) == trim(faves(find_favorite)%link)) then + exit + end if + end do + + if(find_favorite > size(faves)) then + find_favorite = -1 + end if + end if + + end function find_favorite + + subroutine add_favorite(faves, link, name) + implicit none + + type(favorite), dimension(:), intent(inout), allocatable::faves + character(*), intent(in)::link + character(*), intent(in)::name + character(8)::now + + integer::n + type(favorite), dimension(:), allocatable::holding + + n = -1 + + if(.not. allocated(faves)) then + + n = 1 + allocate(faves(1)) + + else if(find_favorite(faves, link) < 0) then + + n = size(faves) + allocate(holding(n)) + holding = faves + + deallocate(faves) + + allocate(faves(n+1)) + faves(1:n) = holding + + n = n + 1 + + end if + + if(n > 0) then + faves(n)%link = trim(link) + + call date_and_time(date=now) + faves(n)%name = trim(name)//" ("//now(1:4)//"-"//now(5:6)//"-"//now(7:8)//")" + read(now, '(I8)') faves(n)%added + end if + + end subroutine add_favorite + + subroutine remove_favorite(faves, link) + implicit none + + type(favorite), dimension(:), intent(inout), allocatable::faves + character(*), intent(in)::link + + integer::i, n + type(favorite), dimension(:), allocatable::holding + + i = find_favorite(faves, link) + if(i > 0) then + + if(size(faves) == 1) then + + deallocate(faves) + + else + + n = size(faves) + allocate(holding(n-1)) + if(i > 1) then + holding(1:i-1) = faves(1:i-1) + end if + if(i < n) then + holding(i:n-1) = faves(i+1:n) + end if + deallocate(faves) + + allocate(faves(n-1)) + faves = holding + deallocate(holding) + + end if + + end if + + end subroutine remove_favorite + +end module favorite_handling \ No newline at end of file diff --git a/gemini-windows.prj b/gemini-windows.prj index ad734ad..8e32881 100644 --- a/gemini-windows.prj +++ b/gemini-windows.prj @@ -46,6 +46,9 @@ },{ "filename":".\\escape.f90", "enabled":"1" + },{ + "filename":".\\favorites.f90", + "enabled":"1" },{ "filename":".\\files.f90", "enabled":"1" @@ -61,6 +64,9 @@ },{ "filename":".\\main.F90", "enabled":"1" + },{ + "filename":".\\platform.F90", + "enabled":"1" },{ "filename":".\\protocol.f90", "enabled":"1" @@ -111,12 +117,13 @@ }, "Build Dependencies":1, "Launch Options":{ + "Build Before Launch":"true", "Working Directory":"", "Launch Using MPI":"false", "Keep Console":"true", - "External Console":"false", + "Executable":"", "Command Line Arguments":"", - "Build Before Launch":"true" + "External Console":"false" }, "Build Options":{ "Makefile":"Makefile", diff --git a/main.F90 b/main.F90 index 7021195..fd618c3 100644 --- a/main.F90 +++ b/main.F90 @@ -42,6 +42,8 @@ use history use wsa_network, only: windows_network_startup => startup #endif +use favorite_handling + implicit none character(256)::initial_site @@ -69,6 +71,8 @@ implicit none type(line), pointer::first_line type(location), pointer::locations_visited + type(favorite), dimension(:), allocatable::faves + #ifdef WINDOWS call windows_network_startup() #endif @@ -101,6 +105,9 @@ implicit none redo_layout = .false. call r%initialize() + ! Load in any favorites + faves = load_favorites() + locations_visited => null() desired_url = initial_site current_url = " " @@ -231,6 +238,10 @@ implicit none loaded = .false. + case (render_action_favorite) + call add_favorite(faves, current_url, current_url) + call save_favorites(faves) + end select end do @@ -286,4 +297,48 @@ contains end subroutine update_status + function load_favorites() result(faves) + use platform, only: get_favorites_file + use favorite_handling, only: read_favorites, favorite + implicit none + + type(favorite), dimension(:), allocatable::faves + + character(260)::filename + integer::ios, loadunit + + call get_favorites_file(filename) + + open(newunit=loadunit, file=filename, status='old', action='read', iostat=ios) + if(ios == 0) then + + faves = read_favorites(loadunit) + close(loadunit) + + end if + + end function load_favorites + + subroutine save_favorites(faves) + use platform, only: get_favorites_file + use favorite_handling, only: write_favorites, favorite + implicit none + + type(favorite), dimension(:), allocatable::faves + + character(260)::filename + integer::ios, loadunit + + call get_favorites_file(filename) + + open(newunit=loadunit, file=filename, status='unknown', action='write', iostat=ios) + if(ios == 0) then + + call write_favorites(loadunit, faves) + close(loadunit) + + end if + + end subroutine save_favorites + end program gemini diff --git a/platform.F90 b/platform.F90 new file mode 100644 index 0000000..e10ca64 --- /dev/null +++ b/platform.F90 @@ -0,0 +1,75 @@ +module platform +implicit none + +#ifdef WINDOWS + character, parameter::dir_sep = '\' +#else + character, parameter::dir_sep = '/' +#endif + + character(*), parameter::favorites_file = "favorites.gmi" + +contains + + subroutine get_settings_directory(dir) + use iso_c_binding + implicit none + + character(*), intent(out)::dir +#ifdef WINDOWS + + interface + function SHGetFolderPath(hwnd, csidl, htoken, dwflags, path) bind(c, name="SHGetFolderPathA") + use iso_c_binding + type(c_ptr), value::hwnd + integer(kind=c_int), value::csidl + type(c_ptr), value::htoken + integer(kind=c_int32_t), value::dwflags + character(kind=c_char), dimension(260)::path + integer(kind=c_intptr_t)::SHGetFolderPath + end function SHGetFolderPath + end interface + + integer(kind=c_intptr_t), parameter::S_OK = 0 + integer(kind=c_int), parameter::CSIDL_APPDATA = 26 + + character(kind=c_char), dimension(260)::path + integer::i + + if(SHGetFolderPath(c_null_ptr, CSIDL_APPDATA, c_null_ptr, 0, path) == S_OK) then + dir = " " + i = 1 + do while(path(i) /= c_null_char .and. i < 260) + dir(i:i) = path(i) + i = i + 1 + end do + else + Print *, "Warning: Could not access CSIDL_APPDATA" + call get_environment_variable("HOME", value=dir) + end if + + if(dir(len_trim(dir):len_trim(dir)) /= dir_sep) then + dir = trim(dir)//dir_sep + end if + dir = trim(dir)//"LR-87" +#else + call get_environment_variable("HOME", value=dir) + if(dir(len_trim(dir):len_trim(dir)) /= dir_sep) then + dir = trim(dir)//dir_sep + end if + dir = trim(dir)//".lr87" +#endif + + end subroutine get_settings_directory + + subroutine get_favorites_file(filename) + implicit none + + character(*), intent(out)::filename + + call get_settings_directory(filename) + filename = trim(filename)//dir_sep//favorites_file + + end subroutine get_favorites_file + +end module platform \ No newline at end of file diff --git a/render.f90 b/render.f90 index 54f50e4..3cbb2bc 100644 --- a/render.f90 +++ b/render.f90 @@ -23,12 +23,13 @@ module render implicit none - integer, parameter::render_action_none = 1 - integer, parameter::render_action_goto = 2 - integer, parameter::render_action_layout = 3 - integer, parameter::render_action_back = 4 - integer, parameter::render_action_rewrap = 5 - integer, parameter::render_action_quit = 6 + integer, parameter::render_action_none = 1 + integer, parameter::render_action_goto = 2 + integer, parameter::render_action_layout = 3 + integer, parameter::render_action_back = 4 + integer, parameter::render_action_rewrap = 5 + integer, parameter::render_action_quit = 6 + integer, parameter::render_action_favorite = 7 integer, parameter::last_break = -1 -- cgit v1.2.3