From dbdfb68893a5b9677a9286beff8de3c1b02fff5d Mon Sep 17 00:00:00 2001 From: Jeffrey Armstrong Date: Tue, 1 Mar 2022 09:52:02 -0500 Subject: Slide notes are now extracted, and they can subsequently be output instead. Errors out if no notes are present. --- driver.f90 | 18 ++++++++---- fpoint.prj | 2 +- pptxml.f90 | 54 ++++++++++++++++++++++++++++++------ pptxzip.f90 | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 143 insertions(+), 23 deletions(-) diff --git a/driver.f90 b/driver.f90 index bcd8a25..2521407 100644 --- a/driver.f90 +++ b/driver.f90 @@ -27,7 +27,7 @@ implicit none type(pptxtracted)::presentation logical::verbose logical::notes - integer::i, j + integer::i, j, retcode character(len=:), pointer::filename, arg if(command_argument_count() < 1) then @@ -35,6 +35,7 @@ implicit none call exit(0) end if + retcode = 0 verbose = .false. notes = .false. filename => null() @@ -73,17 +74,22 @@ implicit none call maybe_print(verbose, "File opened at "//trim(presentation%directory)) call presentation%parse() - - write(*, '(A)') presentation%to_text() - + + if((.not. notes) .or. presentation%has_notes()) then + write(*, '(A)') presentation%to_text(notes_only=notes) + else + call maybe_print(verbose, "No slide notes found in "//filename) + retcode = 1 + end if + call presentation%close() else call maybe_print(verbose, "Failed on "//filename) - call exit(1) + retcode = 1 end if - call exit(0) + call exit(retcode) contains diff --git a/fpoint.prj b/fpoint.prj index 5d66372..038a8ed 100644 --- a/fpoint.prj +++ b/fpoint.prj @@ -61,7 +61,7 @@ "Launch Using MPI":"false", "Keep Console":"true", "External Console":"true", - "Command Line Arguments":"", + "Command Line Arguments":"-n \"Welcome to PowerPoint.pptx\"", "Build Before Launch":"true" }, "Build Options":{ diff --git a/pptxml.f90 b/pptxml.f90 index c785bb8..513703e 100644 --- a/pptxml.f90 +++ b/pptxml.f90 @@ -313,12 +313,14 @@ contains end subroutine parse_slide_sp - subroutine slide_load_filename(self, filename) + subroutine slide_load_filename(self, filename, title) use FoX_dom implicit none class(slide), intent(out)::self character(len=*), intent(in)::filename + character(len=*), intent(in), optional::title + character(len=:), pointer::filename_no_backslashes ! For parsing the title out @@ -369,11 +371,16 @@ contains return end if - self%title => find_slide_title(self%slide_dom) - if(.not. associated(self%title) .and. self%number > 0) then - allocate(character(len=16)::self%title) - write(self%title, '(I8)') self%number - self%title = "Slide "//trim(adjustl(self%title)) + if(present(title)) then + allocate(character(len=len_trim(title)) :: self%title) + self%title = title + else + self%title => find_slide_title(self%slide_dom) + if(.not. associated(self%title) .and. self%number > 0) then + allocate(character(len=16)::self%title) + write(self%title, '(I8)') self%number + self%title = "Slide "//trim(adjustl(self%title)) + end if end if call parse_slide_sp(self) @@ -520,10 +527,39 @@ contains class(text_element), intent(inout)::self type(Node), pointer::n - type(NodeList), pointer::rows + type(NodeList), pointer::rows, paras + character(len=:), pointer::one_para + integer::text_length, i + + text_length = 0 + paras => getElementsByTagNameNS(n, drawing_schema, "p") + do i = 1, getLength(paras) + rows => getElementsByTagNameNS(item(paras, i-1), drawing_schema, "r") + one_para => concatenated_text_in_rows(rows) + if(associated(one_para)) then + text_length = text_length + len_trim(one_para) + if(i /= getLength(paras)) then + text_length = text_length + len(new_line(' ')) + end if + end if + end do - rows => getElementsByTagNameNS(n, drawing_schema, "r") - self%text => concatenated_text_in_rows(rows) + allocate(character(len=text_length) :: self%text) + + text_length = 1 + paras => getElementsByTagNameNS(n, drawing_schema, "p") + do i = 1, getLength(paras) + rows => getElementsByTagNameNS(item(paras, i-1), drawing_schema, "r") + one_para => concatenated_text_in_rows(rows) + if(associated(one_para)) then + self%text(text_length:len(self%text)) = one_para + text_length = text_length + len_trim(one_para) + if(i /= getLength(paras)) then + self%text(text_length:len(self%text)) = new_line(' ') + text_length = text_length + len(new_line(' ')) + end if + end if + end do end subroutine text_element_from_node diff --git a/pptxzip.f90 b/pptxzip.f90 index d526125..1a11b1e 100644 --- a/pptxzip.f90 +++ b/pptxzip.f90 @@ -34,6 +34,9 @@ implicit none character(len=2048), dimension(:), pointer::note_paths type(slide), dimension(:), pointer::slides + + type(slide), dimension(:), pointer::notes + integer, dimension(:), pointer::slide_note_indices contains @@ -43,11 +46,27 @@ implicit none procedure :: to_text => pptx_to_text procedure :: slide_has_notes procedure :: slide_count + procedure :: get_notes => slide_get_notes + procedure :: has_notes => pptx_has_notes end type pptxtracted contains + function pptx_has_notes(self) + implicit none + + class(pptxtracted), intent(in)::self + logical::pptx_has_notes + + if(.not. associated(self%slide_note_indices)) then + pptx_has_notes = .false. + else + pptx_has_notes = (count(self%slide_note_indices > 0) > 0) + end if + + end function pptx_has_notes + function slide_has_notes(self, i) implicit none @@ -63,6 +82,28 @@ contains end function slide_has_notes + function slide_get_notes(self, i, success) + implicit none + + class(pptxtracted), intent(in)::self + integer, intent(in)::i + logical, intent(out), optional::success + type(slide)::slide_get_notes + + integer::j + + if(self%slide_has_notes(i)) then + j = self%slide_note_indices(i) + slide_get_notes = self%notes(j) + if(present(success)) then + success = .true. + end if + else if(present(success)) then + success = .false. + end if + + end function slide_get_notes + function slide_count(self) implicit none @@ -85,7 +126,7 @@ contains logical::res class(pptxtracted), intent(out)::self character(len=*), intent(in)::filename - integer::i, slidecount + integer::i, slidecount, j character(len=2048)::slidedir, slidecheck, notesdir character(len=4)::numtext logical::existence @@ -121,6 +162,10 @@ contains end do ! Now check for notes + allocate(self%slide_note_indices(slidecount)) + self%slide_note_indices = -1 + j = 1 + notesdir = self%directory call append_to_path(notesdir, 'ppt') call append_to_path(notesdir, 'notesSlides') @@ -132,11 +177,15 @@ contains inquire(file=self%note_paths(i), exist=existence) if(.not. existence) then self%note_paths(i) = " " + else + self%slide_note_indices(i) = j + j = j + 1 end if end do ! These should only be explicitly parsed self%slides => null() + self%notes => null() end function pptx_open @@ -162,39 +211,68 @@ contains implicit none class(pptxtracted), intent(inout)::self - integer::i + integer::i, j allocate(self%slides(self%slide_count())) + allocate(self%notes(count(self%slide_note_indices > 0))) do i = 1, self%slide_count() call self%slides(i)%load(self%slide_paths(i)) + if(self%slide_has_notes(i)) then + j = self%slide_note_indices(i) + call self%notes(j)%load(self%note_paths(i), title=self%slides(i)%title) + end if end do end subroutine pptx_parse - function pptx_to_text(self) result(t) + function pptx_to_text(self, notes_only) result(t) use fpoint_pptxml implicit none class(pptxtracted), intent(in)::self + logical, intent(in), optional::notes_only integer::text_length character(len=:), pointer::t, tmp integer::i + type(slide)::one_note + + logical::local_notes t => null() + local_notes = .false. + if(present(notes_only)) then + local_notes = notes_only + end if + if(self%slide_count() > 0 .and. associated(self%slides)) then text_length = 0 do i = 1, self%slide_count() - text_length = text_length + self%slides(i)%text_length() + if(local_notes .and. self%slide_has_notes(i)) then + one_note = self%get_notes(i) + text_length = text_length + one_note%text_length() + else if(.not. local_notes) then + text_length = text_length + self%slides(i)%text_length() + end if end do allocate(character(len=text_length) :: t) text_length = 1 do i = 1, self%slide_count() - tmp => self%slides(i)%to_text() - t(text_length:len(t)) = trim(tmp) - text_length = text_length + len_trim(tmp) + tmp => null() + if(local_notes .and. self%slide_has_notes(i)) then + one_note = self%get_notes(i) + tmp => one_note%to_text() + else if(.not. local_notes) then + tmp => self%slides(i)%to_text() + end if + + if(associated(tmp)) then + t(text_length:len(t)) = trim(tmp) + text_length = text_length + len_trim(tmp) + deallocate(tmp) + end if end do end if -- cgit v1.2.3