From 568ecd439cbf0ea47d30a77f30c50e2eaaf20385 Mon Sep 17 00:00:00 2001 From: Toshio Sekiya Date: Mon, 11 Jan 2021 11:15:04 +0900 Subject: [PATCH] Latex and pdf file generation is supported. --- .gitignore | 1 + Rakefile | 74 ++++++++++++++++++++++++++++++++--- lib/lib_src2md.rb | 98 +++++++++++++++++++++++++++++++++++++++++++++-- sec1.md | 2 + sec10.md | 2 + sec11.md | 4 +- sec12.md | 12 +++++- sec13.md | 2 + sec14.md | 8 ++-- sec15.md | 2 + sec16.md | 2 + sec17.md | 2 + sec2.md | 2 + sec3.md | 2 + sec4.md | 2 + sec5.md | 2 + sec6.md | 2 + sec7.md | 6 ++- sec8.md | 2 + sec9.md | 2 + src/sec11.src.md | 6 +-- src/sec12.src.md | 10 ++++- src/sec14.src.md | 4 +- src/sec15.src.md | 8 ++-- src/sec16.src.md | 2 +- src/sec17.src.md | 2 +- src/sec2.src.md | 6 +-- src/sec3.src.md | 8 ++-- src/sec4.src.md | 2 +- src/sec5.src.md | 4 +- src/sec6.src.md | 2 +- src/sec7.src.md | 6 +-- src/sec9.src.md | 8 ++-- 33 files changed, 251 insertions(+), 46 deletions(-) diff --git a/.gitignore b/.gitignore index 52af3fe..bdb1e74 100755 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ insertfunc.rb pickoutfunc.rb src/img.rb +src/imgsize.rb src/toi.rb src/misc/a.out src/tfv/a.out diff --git a/Rakefile b/Rakefile index fec7b92..692b144 100644 --- a/Rakefile +++ b/Rakefile @@ -3,7 +3,6 @@ require 'rake/clean' require_relative 'lib/lib_sec_file.rb' require_relative 'lib/lib_src2md.rb' - srcfiles = [] FileList['src/*.src.md'].each do |file| srcfiles << Sec_file.new(file) @@ -15,6 +14,12 @@ mdfilenames = srcfiles.map {|srcfile| srcfile.to_md} htmlfilenames = srcfiles.map {|srcfile| "html/"+srcfile.to_html} texfilenames = srcfiles.map {|srcfile| "latex/"+srcfile.to_tex} +["html", "latex"].each do |d| + if ! Dir.exist?(d) + Dir.mkdir(d) + end +end + CLEAN.append(*mdfilenames) CLEAN << "Readme.md" @@ -72,6 +77,26 @@ You should be careful because there exists bugs, errors or mistakes. \n" + tail) IO.write("html/index.html",file_index) @@ -124,7 +149,12 @@ end 0.upto(srcfiles.size - 1) do |i| file "html/"+srcfiles[i].to_html => (srcfiles[i].c_files << srcfiles[i].path) do - src2md srcfiles[i].path, "html/"+srcfiles[i].to_md + src2md srcfiles[i].path, "html/"+srcfiles[i].to_md, -1 + buf = IO.readlines "html/"+srcfiles[i].to_md + buf.each do |line| + line.gsub!(/(\[[^\]]*\])\((sec\d+)\.md\)/,"\\1(\\2.html)") + end + IO.write "html/"+srcfiles[i].to_md, buf.join sh "pandoc -o html/#{srcfiles[i].to_html} html/#{srcfiles[i].to_md}" File.delete("html/#{srcfiles[i].to_md}") if srcfiles.size == 1 @@ -147,7 +177,41 @@ end end end +task pdf: "latex" do + sh "cd latex; pdflatex main.tex" + sh "cd latex; pdflatex main.tex" + sh "mv latex/main.pdf latex/gtk4_tutorial.pdf" +end + +task latex: texfilenames+["latex/main.tex"] + +file "latex/main.tex" do + 0.upto(srcfiles.size-1) do |i| + main += " \\input{#{srcfiles[i].to_tex}}\n" + end + main += "\\end{document}\n" + IO.write("latex/main.tex", main) + IO.write("latex/helper.tex", helper) +end + +0.upto(srcfiles.size - 1) do |i| + file "latex/"+srcfiles[i].to_tex => (srcfiles[i].c_files << srcfiles[i].path) do + src2md srcfiles[i].path, "latex/"+srcfiles[i].to_md, 80 + sh "pandoc -o latex/#{srcfiles[i].to_tex} latex/#{srcfiles[i].to_md}" + File.delete("latex/#{srcfiles[i].to_md}") + end +end + task :clean task :cleanhtml do - sh "rm html/*" + if Dir.exist?("html") && (! Dir.empty?("html")) + sh "rm html/*" + end end +task :cleanlatex do + if Dir.exist?("latex") && (! Dir.empty?("latex")) + sh "rm latex/*" + end +end +task cleanall: [:clean, :cleanhtml, :cleanlatex] + diff --git a/lib/lib_src2md.rb b/lib/lib_src2md.rb index 9f87d98..ef7f119 100644 --- a/lib/lib_src2md.rb +++ b/lib/lib_src2md.rb @@ -1,8 +1,61 @@ # lib_src2md.rb +require 'pathname' -def src2md srcmd, md +# The method 'src2md' convert .src.md file into .md file. +# The output .md file is fit for the final format, which is one of markdown, html and latex. +# - Links to relative URL are removed for latex. Otherwise, it remains. +# See "Hyperref and relative link" below for further explanation. +# - Width and height for images are removed for markdown and html. it remains for latex. +# ![sample](sample_image){width=10cm height=5cm} => ![sample](sample_image) for markdown and html + +# ---- Hyperref and relative link ---- +# Hyperref package makes internal link possible. +# The target of the link is made with '\hypertarget' command. +# And the link is made with '\hyperlink' command. +# For example, +# (sec11.tex) +# \hyperlink{tfeapplication.c}{Section 13} +# ... ... +# (sec13.tex) +# \hypertarget{tfeapplication.c}{% +# \section{tfeapplication.c}\label{tfeapplication.c}} +# If you click the text 'Section 13' in sec11.tex, then you can move to '13 tfeapplication.c', which is section 13 in sec13.tex. + +# The following lines are the original one in sec11.md and the result in sec11.tex, which is generated by pandoc. +# (sec11.md) +# All the source files are listed in [Section 13](sec13.tex). +# (sec11.tex) +# All the source files are listed in \href{sec13.tex}{Section 13}. +# Therefore, if you want to correct the link in sec11.tex, you need to do the followings. +# 1. Look at the first line of sec13.md and get the section heading (tfeapplication.c). +# 2. substitute "\hyperlink{tfeapplication.c}{Section 13}" for "\href{sec13.tex}{Section 13}". + +# The following lines are another conversion case by pandoc. +# (sec7.md) +# The source code of `tfe3.c` is stored in [src/tfe](../src/tfe) directory. +# (sec7.tex) +# The source code of \texttt{tfe3.c} is stored in \href{../src/tfe}{src/tfe} directory. +# The pdf file generated by pdflatex recognizes that the link 'href{../src/tfe}' points a pdf file '../src/tfe.pdf'. +# To avoid generating such incorrect links, it is good to remove the links from the original markdown file. + +# If the target is full URL, which means absolute URL begins with "http", no problem happens. + +# This Rakefile just remove the links if its target is relative URL. +# If you want to revive the link with relative URL, refer the description above. + +# ---- Folding verbatim lines ---- +# When C sourcefiles or subshell output are included, the lines are folded to fit in 'width'. +# Before they are folded, four space characters are prepended to the line. +# Therefore, 'width' must be at least five. +# Otherwise the lines are not folded. + +def src2md srcmd, md, width src_buf = IO.readlines srcmd src_dir = File.dirname srcmd + md_dir = File.dirname md +# type is 'the type of the target', which is one of "markdown", "html" and "latex". + type = md_dir == "." ? "markdown" : md_dir + md_buf = [] comflag = false src_buf.each do |line| @@ -55,16 +108,53 @@ def src2md srcmd, md end end end - width = tmp_buf.size.to_s.length + ln_width = tmp_buf.size.to_s.length n = 1 tmp_buf.each do |l| - md_buf << sprintf(" %#{width}d %s", n, l) + l = sprintf(" %#{ln_width}d %s", n, l) + md_buf << l n += 1 end else - md_buf << line.gsub(/(!\[[^\]]*\])\(..\/([^\)]*)\)/, "\\1(\\2)") + md_buf << change_rel_link(line, src_dir, File.dirname(md)) end end + tmp_buf = md_buf + md_buf = [] + tmp_buf.each do |line| + if line =~ /^ / && width.instance_of?(Integer) && width >= 5 + indent = line =~ /^( *\d+ +)/ ? " "*$1.length : " " + while line.instance_of?(String) && line.length > width + md_buf << line[0, width]+"\n" + line = line[width .. -1].gsub(/^/,indent) + end + elsif type == "latex" + line.gsub!(/(^|[^!])\[([^\]]*)\]\((?~http)\)/,"\\1\\2") # remove link + else # type == "markdown" or "html" + line.gsub!(/(!\[[^\]]*\]\([^\)]*\)) *{width *= *\d*(|\.\d*)cm *height *= *\d*(|\.\d*)cm}/,"\\1") + end + md_buf << line + end IO.write(md,md_buf.join) end +def change_rel_link line, src_dir, basedir + p_basedir = Pathname.new basedir + left = "" + right = line + while right =~ /(!?\[[^\]]*\])\((.*)\)/ + left = $` + right = $' + name = $1 + link = $2 + if name =~ /\[(S|s)ection (\d+)\]/ + link = "sec#{$2}.md" + elsif ! (link =~ /^(http|\/)/) + p_link = Pathname.new "#{src_dir}/#{link}" + link = p_link.relative_path_from(p_basedir).to_s + end + left += "#{name}(#{link})" + end + left + right +end + diff --git a/sec1.md b/sec1.md index 7828583..963570e 100644 --- a/sec1.md +++ b/sec1.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Next: [Section 2](sec2.md) + # Prerequisite and Licence ## Prerequisite @@ -51,4 +52,5 @@ as published by the Free Software Foundation; either version 3 of the License, o but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the [GNU General Public License](https://www.gnu.org/licenses/gpl-3.0.html) for more details. + Up: [Readme.md](Readme.md), Next: [Section 2](sec2.md) diff --git a/sec10.md b/sec10.md index a0669b1..80fc0a5 100644 --- a/sec10.md +++ b/sec10.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 9](sec9.md), Next: [Section 11](sec11.md) + # Signals ## Signals @@ -160,4 +161,5 @@ The following is extract from `tfetexties.c`. - "open-response" signal has one parameter. The fourth parameter is the parameter. + Up: [Readme.md](Readme.md), Prev: [Section 9](sec9.md), Next: [Section 11](sec11.md) diff --git a/sec11.md b/sec11.md index 2cac677..e005b2a 100644 --- a/sec11.md +++ b/sec11.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 10](sec10.md), Next: [Section 12](sec12.md) + # Functions in TfeTextView In this section I will explain each function in TfeTextView object. @@ -356,6 +357,7 @@ Otherwise, if the caller free the GFile object, `tv->file` is no more guaranteed ## Source file of tfetextview.c -All the source files are listed in [Section 13](https://github.com/ToshioCP/Gtk4-tutorial/blob/main/sec13.md). +All the source files are listed in [Section 14](sec14.md). + Up: [Readme.md](Readme.md), Prev: [Section 10](sec10.md), Next: [Section 12](sec12.md) diff --git a/sec12.md b/sec12.md index a9e0994..573b362 100644 --- a/sec12.md +++ b/sec12.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 11](sec11.md), Next: [Section 13](sec13.md) + # Functions with GtkNotebook GtkNotebook is a very important object in the text file editor `tfe`. @@ -26,7 +27,15 @@ The GFile `file` is copied and set in the TfeTextView object. - 4-5: `notebook_page_open` shows a file chooser dialog. Then, user chooses a file and the file is set into GtkTextBuffer. - 1-2: `notebook_page_save` saves the contents in GtkTextBuffer into the file, which has been set in the TfeTextView. -You probably find that the functions above are higher level functions of `tfe_text_view_new`, `tfe_text_view_new_with_file`, `tef_text_view_open` and `tfe_text_view_save` respectively. +You probably find that the functions above are higher level functions of + +- `tfe_text_view_new` +- `tfe_text_view_new_with_file` +- `tef_text_view_open` +- `tfe_text_view_save` + + respectively. + There are two layers. One of them is `tfe_text_view ...`, which is the lower level layer. The other is `note_book ...`, which is the higher level layer. @@ -208,4 +217,5 @@ Otherwise (file is NULL), assign untitled string to `filename`. - 16-17: Free `filename` and unref `file`. + Up: [Readme.md](Readme.md), Prev: [Section 11](sec11.md), Next: [Section 13](sec13.md) diff --git a/sec13.md b/sec13.md index ee95b22..5a64f1d 100644 --- a/sec13.md +++ b/sec13.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 12](sec12.md), Next: [Section 14](sec14.md) + # tfeapplication.c `tfeapplication.c` includes all the code other than `tfetxtview.c` and `tfenotebook.c`. @@ -267,4 +268,5 @@ First, get the top level window and call `gtk_window_destroy`. In this file, just the source file names are modified. + Up: [Readme.md](Readme.md), Prev: [Section 12](sec12.md), Next: [Section 14](sec14.md) diff --git a/sec14.md b/sec14.md index 91acfe9..cb01a17 100644 --- a/sec14.md +++ b/sec14.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 13](sec13.md), Next: [Section 15](sec15.md) + # tfe5 source files The followings are the source files of tfe5. @@ -219,7 +220,7 @@ The followings are the source files of tfe5. 116 } 117 -### tfenotebook.h +## tfenotebook.h 1 void 2 notebook_page_save(GtkNotebook *nb); @@ -608,7 +609,7 @@ The followings are the source files of tfe5. ## Total number of lines, words and charcters - $ wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfe.h tfe5/tfenotebook.c tfe5/tfenotebook.h tfe5/tfetextview.c tfe5/tfetextview.h tfe5/tfe.ui + $ LANG=C wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfe.h tfe5/tfenotebook.c tfe5/tfenotebook.h tfe5/tfetextview.c tfe5/tfetextview.h tfe5/tfe.ui 10 17 279 tfe5/meson.build 117 348 3576 tfe5/tfeapplication.c 6 9 153 tfe5/tfe.gresource.xml @@ -618,5 +619,6 @@ The followings are the source files of tfe5. 218 635 7769 tfe5/tfetextview.c 29 49 561 tfe5/tfetextview.h 64 105 2266 tfe5/tfe.ui - 576 1507 17864 合計 + 576 1507 17864 total + Up: [Readme.md](Readme.md), Prev: [Section 13](sec13.md), Next: [Section 15](sec15.md) diff --git a/sec15.md b/sec15.md index db95929..3066db2 100644 --- a/sec15.md +++ b/sec15.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 14](sec14.md), Next: [Section 16](sec16.md) + # Menu and action ## Menu @@ -213,4 +214,5 @@ The structure of the menu is shown in the diagram below. ![Screenshot of menu1](image/menu1_screenshot.png) + Up: [Readme.md](Readme.md), Prev: [Section 14](sec14.md), Next: [Section 16](sec16.md) diff --git a/sec16.md b/sec16.md index f261670..c958478 100644 --- a/sec16.md +++ b/sec16.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 15](sec15.md), Next: [Section 17](sec17.md) + # Stateful action Some actions have states. @@ -368,4 +369,5 @@ Other GtkLabel have no effect from this. The provider is added to GdkDisplay. - 90: Show the window. + Up: [Readme.md](Readme.md), Prev: [Section 15](sec15.md), Next: [Section 17](sec17.md) diff --git a/sec17.md b/sec17.md index b0565bf..22ab327 100644 --- a/sec17.md +++ b/sec17.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 16](sec16.md) + # Ui file for menu and action entries ## Ui file for menu @@ -336,4 +337,5 @@ meson.build 9 10 executable('menu3', sourcefiles, resources, dependencies: gtkdep) + Up: [Readme.md](Readme.md), Prev: [Section 16](sec16.md) diff --git a/sec2.md b/sec2.md index f47faef..0879cff 100644 --- a/sec2.md +++ b/sec2.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 1](sec1.md), Next: [Section 3](sec3.md) + # GtkApplication and GtkApplicationWindow ## GtkApplication @@ -282,4 +283,5 @@ The program sets the title and the default size of the window. Compile it and run `a.out`, then you will see a bigger window with its title "pr4". ![Screenshot of the window](image/screenshot_pr4.png) + Up: [Readme.md](Readme.md), Prev: [Section 1](sec1.md), Next: [Section 3](sec3.md) diff --git a/sec3.md b/sec3.md index 85bee55..b15031c 100644 --- a/sec3.md +++ b/sec3.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 2](sec2.md), Next: [Section 4](sec4.md) + # Widgets (1) ## GtkLabel, GtkButton and Gtkbox @@ -313,4 +314,5 @@ Then, these two buttons are appended to the box. The handler corresponds to `btn1` changes its label. The handler corresponds to `btn2` destroys the top-level window and the application quits. + Up: [Readme.md](Readme.md), Prev: [Section 2](sec2.md), Next: [Section 4](sec4.md) diff --git a/sec4.md b/sec4.md index 1cfbd2a..5ae2829 100644 --- a/sec4.md +++ b/sec4.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 3](sec3.md), Next: [Section 5](sec5.md) + # Widgets (2) ## GtkTextView, GtkTextbuffer and GtkScrolledWindow @@ -162,4 +163,5 @@ Now compile and run it. This time the window doesn't extend even if you type a lot of characters. It just scrolls. + Up: [Readme.md](Readme.md), Prev: [Section 3](sec3.md), Next: [Section 5](sec5.md) diff --git a/sec5.md b/sec5.md index a152588..cf76da9 100644 --- a/sec5.md +++ b/sec5.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 4](sec4.md), Next: [Section 6](sec6.md) + # Widgets (3) ## Open signal @@ -302,4 +303,5 @@ The numbers at the left of the following items are line numbers in the source co - 46: free the memory pointed by `filename` - 53-56: If at least one file was read, then the number of GtkNotebookPage is greater than zero. If it's true, then show the window. If it's false, then destroy the window. + Up: [Readme.md](Readme.md), Prev: [Section 4](sec4.md), Next: [Section 6](sec6.md) diff --git a/sec6.md b/sec6.md index 98a04e1..4536083 100644 --- a/sec6.md +++ b/sec6.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 5](sec5.md), Next: [Section 7](sec7.md) + # Define Child object ## Very simple editor @@ -347,4 +348,5 @@ It's not smart. We need more features like open, save, saveas, change font and so on. We will add them in the next section and after. + Up: [Readme.md](Readme.md), Prev: [Section 5](sec5.md), Next: [Section 7](sec7.md) diff --git a/sec7.md b/sec7.md index 9c6ad7c..9fed4e1 100644 --- a/sec7.md +++ b/sec7.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 6](sec6.md), Next: [Section 8](sec8.md) + # Ui file and GtkBuiler ## New, open and save button @@ -343,9 +344,9 @@ Only functions `on_open` are shown as follows. 47 gtk_window_destroy (GTK_WINDOW (win)); 48 } -The source code of `tfe3.c` is stored in [src/tfe](https://github.com/ToshioCP/Gtk4-tutorial/tree/main/src/tfe) directory. +The source code of `tfe3.c` is stored in [src/tfe](src/tfe) directory. If you want to see it, click the link above. -In the same way, you can get the source files below in the directory [src/tfe](https://github.com/ToshioCP/Gtk4-tutorial/tree/main/src/tfe). +In the same way, you can get the source files below in the directory [src/tfe](src/tfe). ### Using ui string @@ -450,4 +451,5 @@ Modify tfe3.c and save it as tfe3_r.c Then, compile and run it. The window appears and it is the same as the screenshot at the beginning of this page. + Up: [Readme.md](Readme.md), Prev: [Section 6](sec6.md), Next: [Section 8](sec8.md) diff --git a/sec8.md b/sec8.md index efe64a2..976cd7c 100644 --- a/sec8.md +++ b/sec8.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 7](sec7.md), Next: [Section 9](sec9.md) + # Build system ## What do we need to think about to manage big source files? @@ -423,4 +424,5 @@ I think meson and ninja is the best choice for the present. We divided a file into some categorized files and used a build tool. This method is used by many developers. + Up: [Readme.md](Readme.md), Prev: [Section 7](sec7.md), Next: [Section 9](sec9.md) diff --git a/sec9.md b/sec9.md index 6e73128..39ef110 100644 --- a/sec9.md +++ b/sec9.md @@ -1,4 +1,5 @@ Up: [Readme.md](Readme.md), Prev: [Section 8](sec8.md), Next: [Section 10](sec10.md) + # Instance and class This section and the following four sections are explanations about the next version of the text file editor (tfe). @@ -416,4 +417,5 @@ And `gobject` is a pointer to TfeTextView instance which is casted as a GObject After that, `dh3` calls `dh2`, and `dh2` calls `dh1`. Finally all the references are released. + Up: [Readme.md](Readme.md), Prev: [Section 8](sec8.md), Next: [Section 10](sec10.md) diff --git a/src/sec11.src.md b/src/sec11.src.md index b9d1984..3f0734d 100644 --- a/src/sec11.src.md +++ b/src/sec11.src.md @@ -108,7 +108,7 @@ The buttons are Cancel and Save. - 1-16: `saveas_dialog_response` signal handler. - 6-14: If the response is `GTK_RESPONSE_ACCEPT`, which is set to the argument when the user has clicked on Save button, then gets a pointer to the GFile object, set it to `tv->file`, turn on the modified bit of the GtkTextBuffer, emits "change-file" signal then call `tfe_text_view_save` to save the buffer to the file. -![Saveas process](../image/saveas.png) +![Saveas process](../image/saveas.png){width=10.7cm height=5.16cm} When you use GtkFileChooserDialog, you need to divide the program into two parts. They are a function which generates GtkFileChooserDialog and the signal handler. @@ -159,7 +159,7 @@ In Gtk3, `gtk_dialog_run` function is available. It simplifies the process. However, in Gtk4, `gtk_dialog_run`is unavailable any more. -![Caller and TfeTextView](../image/open.png) +![Caller and TfeTextView](../image/open.png){width=12.405cm height=9.225cm} 1. A caller get a pointer `tv` to TfeTextView by calling `tfe_text_view_new`. 2. The caller connects the handler (left bottom in the diagram) and the signal "open-response". @@ -179,5 +179,5 @@ Otherwise, if the caller free the GFile object, `tv->file` is no more guaranteed ## Source file of tfetextview.c -All the source files are listed in [Section 13](https://github.com/ToshioCP/Gtk4-tutorial/blob/main/sec13.md). +All the source files are listed in [Section 14](sec14.src.md). diff --git a/src/sec12.src.md b/src/sec12.src.md index 0be6065..0c10ab2 100644 --- a/src/sec12.src.md +++ b/src/sec12.src.md @@ -14,7 +14,15 @@ The GFile `file` is copied and set in the TfeTextView object. - 4-5: `notebook_page_open` shows a file chooser dialog. Then, user chooses a file and the file is set into GtkTextBuffer. - 1-2: `notebook_page_save` saves the contents in GtkTextBuffer into the file, which has been set in the TfeTextView. -You probably find that the functions above are higher level functions of `tfe_text_view_new`, `tfe_text_view_new_with_file`, `tef_text_view_open` and `tfe_text_view_save` respectively. +You probably find that the functions above are higher level functions of + +- `tfe_text_view_new` +- `tfe_text_view_new_with_file` +- `tef_text_view_open` +- `tfe_text_view_save` + + respectively. + There are two layers. One of them is `tfe_text_view ...`, which is the lower level layer. The other is `note_book ...`, which is the higher level layer. diff --git a/src/sec14.src.md b/src/sec14.src.md index 19ac0a9..2e6cb34 100644 --- a/src/sec14.src.md +++ b/src/sec14.src.md @@ -22,7 +22,7 @@ The followings are the source files of tfe5. @@@ tfe5/tfeapplication.c -### tfenotebook.h +## tfenotebook.h @@@ tfe5/tfenotebook.h @@ -41,5 +41,5 @@ The followings are the source files of tfe5. ## Total number of lines, words and charcters $$$ -wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfe.h tfe5/tfenotebook.c tfe5/tfenotebook.h tfe5/tfetextview.c tfe5/tfetextview.h tfe5/tfe.ui +LANG=C wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfe.h tfe5/tfenotebook.c tfe5/tfenotebook.h tfe5/tfetextview.c tfe5/tfetextview.h tfe5/tfe.ui $$$ diff --git a/src/sec15.src.md b/src/sec15.src.md index e21e5ed..67ea369 100644 --- a/src/sec15.src.md +++ b/src/sec15.src.md @@ -5,7 +5,7 @@ Users often use menus to tell the command to the computer. It is like this: -![Menu](../image/menu.png) +![Menu](../image/menu.png){width=5.985cm height=5.055cm} Now let's analyze the menu above. There are two types of object. @@ -18,7 +18,7 @@ They are called "menu". Menu is an ordered list of items. They are similar to arrays. -![Menu structure](../image/menu_structure.png) +![Menu structure](../image/menu_structure.png){width=10.23cm height=3.57cm} - Menubar is a menu which has three items, which are "File", "Edit" and "View". - The menu item labeled "Edit" has a link to the submenu which has two items. @@ -162,7 +162,7 @@ The structure of the menu is shown in the diagram below. - 30: Set GtkApplicationWindow to show the menubar. - 31: Show the window. -![menu and action](../image/menu1.png) +![menu and action](../image/menu1.png){width=12.555cm height=3.285cm} -![Screenshot of menu1](../image/menu1_screenshot.png) +![Screenshot of menu1](../image/menu1_screenshot.png){width=6.0cm height=5.115cm} diff --git a/src/sec16.src.md b/src/sec16.src.md index 7fcdf7d..d802296 100644 --- a/src/sec16.src.md +++ b/src/sec16.src.md @@ -197,7 +197,7 @@ It is the string "s" given at the generation time. The following code includes stateful actions above. This program has menus like this: -![menu2](../image/menu2.png) +![menu2](../image/menu2.png){width=6.03cm height=5.115cm} - Fullscreen menu toggles the size of the window between maximum and non-maximum. If the window is maximum size, which is called full screen, then a check mark is put before "fullscreen" label. diff --git a/src/sec17.src.md b/src/sec17.src.md index 683ba46..fc4088b 100644 --- a/src/sec17.src.md +++ b/src/sec17.src.md @@ -57,7 +57,7 @@ So, we usually prefer the former ui file style. The following is a screenshot of the sample program in this section. Its name is `menu3`. -![menu3](../image/menu3.png) +![menu3](../image/menu3.png){width=6.0cm height=5.055cm} The following is the ui file of the menu in `menu3`. diff --git a/src/sec2.src.md b/src/sec2.src.md index c4fbc4d..bdef097 100644 --- a/src/sec2.src.md +++ b/src/sec2.src.md @@ -163,7 +163,7 @@ And GtkWidget is a base object from which all the GUI objects derive. GtkWindow includes GtkWidget at the top of its object. -![GtkWindow and GtkWidget](../image/window_widget.png) +![GtkWindow and GtkWidget](../image/window_widget.png){width=9.0cm height=6.0cm} The function `gtk_window_new` is defined as follows. @@ -214,7 +214,7 @@ Save the program as `pr3.c` and compile and run it. A small window appears. -![Screenshot of the window](../image/screenshot_pr3.png) +![Screenshot of the window](../image/screenshot_pr3.png){width=3.3cm height=3.825cm} Click on the close button then the window disappears and the program finishes. @@ -235,4 +235,4 @@ So you don't need to call `gtk_window_set_application` any more. The program sets the title and the default size of the window. Compile it and run `a.out`, then you will see a bigger window with its title "pr4". -![Screenshot of the window](../image/screenshot_pr4.png) +![Screenshot of the window](../image/screenshot_pr4.png){width=6.3cm height=5.325cm} diff --git a/src/sec3.src.md b/src/sec3.src.md index 2890422..982b118 100644 --- a/src/sec3.src.md +++ b/src/sec3.src.md @@ -19,7 +19,7 @@ Then compile and run it. A window with a message "Hello." appears. -![Screenshot of the label](../image/screenshot_lb1.png) +![Screenshot of the label](../image/screenshot_lb1.png){width=6.3cm height=5.325cm} There's only a little change between `pr4.c` and `lb1.c`. Diff is a good program to know the difference between two files. @@ -69,7 +69,7 @@ The suffix cb means "call back". Name the program `lb2.c` and save it. Now compile and run it. -![Screenshot of the label](../image/screenshot_lb2.png) +![Screenshot of the label](../image/screenshot_lb2.png){width=11.205cm height=6.945cm} A window with the button appears. Click the button (it is a large button, you can click everywhere inside the window), then a string "Clicked." appears on the shell terminal. @@ -115,7 +115,7 @@ The following procedure shows the way to add two buttons in a window. After this, the Widgets are connected as following diagram. -![Parent-child relationship](../image/box.png) +![Parent-child relationship](../image/box.png){width=7.725cm height=2.055cm} Now, code it. @@ -135,7 +135,7 @@ The next function fills a box with children, giving them equal space. After that, two buttons `btn1` and `btn2` are generated and the signal handlers are set. Then, these two buttons are appended to the box. -![Screenshot of the box](../image/screenshot_lb4.png) +![Screenshot of the box](../image/screenshot_lb4.png){width=6.3cm height=5.325cm} The handler corresponds to `btn1` changes its label. The handler corresponds to `btn2` destroys the top-level window and the application quits. diff --git a/src/sec4.src.md b/src/sec4.src.md index 4dfa095..a6e70db 100644 --- a/src/sec4.src.md +++ b/src/sec4.src.md @@ -23,7 +23,7 @@ In line 30, `tv` is set to `win` as a child. Now compile and run it. -![GtkTextView](../image/screenshot_tfv1.png) +![GtkTextView](../image/screenshot_tfv1.png){width=6.3cm height=5.325cm} There's an I-beam pointer in the window. You can add or delete any characters on GtkTextview. diff --git a/src/sec5.src.md b/src/sec5.src.md index 14efcdb..8757630 100644 --- a/src/sec5.src.md +++ b/src/sec5.src.md @@ -95,7 +95,7 @@ Then compile and run it. $ comp tfv3 $ ./a.out tfv3.c -![File viewer](../image/screenshot_tfv3.png) +![File viewer](../image/screenshot_tfv3.png){width=6.3cm height=5.325cm} Now I want to explain the program `tfv3.c`. First, the function `main` changes in only two lines. @@ -142,7 +142,7 @@ If it fails, it outputs an error message and destroys the window. GtkNotebook is a container widget that contains multiple children with tabs in it. -![GtkNotebook](../image/screenshot_gtk_notebook.png) +![GtkNotebook](../image/screenshot_gtk_notebook.png){width=13.2cm height=5.325cm} Look at the screenshots above. The left one is a window at the startup. diff --git a/src/sec6.src.md b/src/sec6.src.md index 56b1f1c..4e47fde 100644 --- a/src/sec6.src.md +++ b/src/sec6.src.md @@ -39,7 +39,7 @@ What we are thinking about now is "child object". A child object includes its parent object. And a child object derives everything from the parent object. -![Child widget of GtkTwxtView](../image/child.png) +![Child widget of GtkTwxtView](../image/child.png){width=9.675cm height=4.89cm} We will define TfeTextView as a child object of GtkTextView. It has everything that GtkTextView has. diff --git a/src/sec7.src.md b/src/sec7.src.md index 18e60c7..85d065b 100644 --- a/src/sec7.src.md +++ b/src/sec7.src.md @@ -9,7 +9,7 @@ It is better to make "New", "Open", "Save" and "Close" buttons. This section describes how to put those buttons into the window. Signals and handlers will be explained later. -![Screenshot of the file editor](../image/screenshot_tfe2.png) +![Screenshot of the file editor](../image/screenshot_tfe2.png){width=9.3cm height=6.825cm} The screenshot above shows the layout. The function `on_open` in the source code `tfe2.c` is as follows. @@ -97,9 +97,9 @@ Only functions `on_open` are shown as follows. @@@ tfe/tfe3.c on_open -The source code of `tfe3.c` is stored in [src/tfe](https://github.com/ToshioCP/Gtk4-tutorial/tree/main/src/tfe) directory. +The source code of `tfe3.c` is stored in [src/tfe](tfe) directory. If you want to see it, click the link above. -In the same way, you can get the source files below in the directory [src/tfe](https://github.com/ToshioCP/Gtk4-tutorial/tree/main/src/tfe). +In the same way, you can get the source files below in the directory [src/tfe](tfe). ### Using ui string diff --git a/src/sec9.src.md b/src/sec9.src.md index 59e8126..279f9da 100644 --- a/src/sec9.src.md +++ b/src/sec9.src.md @@ -86,7 +86,7 @@ This is very important. It guarantees a child widget to derive all the features from ancestors. The structure of `TfeTextView` is like the following diagram. -![The structure of the instance TfeTextView](../image/TfeTextView.png) +![The structure of the instance TfeTextView](../image/TfeTextView.png){width=14.39cm height=2.16cm} ## Generate TfeTextView instance @@ -186,7 +186,7 @@ Override is rewriting ancestors' class methods in the descendent class.) TfeTextViewClass includes its ancsestors' class in it. It is illustrated in the following diagram. -![The structure of TfeTextView Class](../image/TfeTextViewClass.png) +![The structure of TfeTextView Class](../image/TfeTextViewClass.png){width=16.02cm height=8.34cm} ## Destruction of TfeTextView @@ -202,7 +202,7 @@ At this moment, no object refers C and the reference count of C is zero. This means C is no longer useful. Then C destructs itself and finally the memories allocated to C is freed. -![Reference count of B](../image/refcount.png) +![Reference count of B](../image/refcount.png){width=15.855cm height=2.475cm} The idea above is based on an assumption that an object refered by nothing has reference count of zero. When the reference count drops to zero, the object starts its destruction process. @@ -238,7 +238,7 @@ Look at the following diagram. There are four classes -- GObjectClass (GInitiallyUnownedClass), GtkWidgetClass, GtkTextViewClass and TfeTextViewClass. Each class has its own dispose handler -- `dh1`, `dh2`, `dh3` and `tfe_text_view_dispose`. -![dispose handers](../image/dispose_handler.png) +![dispose handers](../image/dispose_handler.png){width=14.925cm height=4.455cm} Now, look at the `tfe_text_view_dispose` program above. It first releases the reference to GFile object pointed by `tv->file`.