Added Replay expanded (debugging) to makefile
[sgc2.git] / MainPage.praat
blob0ebcb293b26ea71201a53a2381f5fee705559462
2 # SpeakGoodChinese 2.0
3
4 # Praat script handling buttons page
6 #     SpeakGoodChinese: MainPage.praat loads the code needed for the 
7 #     main, practice, page of SGC2 and the sound handling and recognition.
8 #     
9 #     Copyright (C) 2007-2010  R.J.J.H. van Son and 2010 the Netherlands Cancer Institute
10 #     The SpeakGoodChinese team are:
11 #     Guangqin Chen, Zhonyan Chen, Stefan de Koning, Eveline van Hagen, 
12 #     Rob van Son, Dennis Vierkant, David Weenink
13
14 #     This program is free software; you can redistribute it and/or modify
15 #     it under the terms of the GNU General Public License as published by
16 #     the Free Software Foundation; either version 2 of the License, or
17 #     (at your option) any later version.
18
19 #     This program is distributed in the hope that it will be useful,
20 #     but WITHOUT ANY WARRANTY; without even the implied warranty of
21 #     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 #     GNU General Public License for more details.
23
24 #     You should have received a copy of the GNU General Public License
25 #     along with this program; if not, write to the Free Software
26 #     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
27
28 # Includes at the bottom
30 ###############################################################
32 # Button Drawing Routines
34 ###############################################################
36 procedure DrawPrevious .color$ .x .y .size
37         demo '.color$'
38         .size *= 2/3
39         .fraction = 0
40         if sgc.numberOfDisplayedWords > 0
41                 .fraction = sgc.currentWordNum/sgc.numberOfDisplayedWords
42         endif
43         call drawProgressTriangle -1 .x .y .size .fraction '.color$' Green
44         .currentX = drawProgressTriangle.currentX
45         .endX = .currentX - 0.5
46         .lowY = .y - .size
47         .highY = .y + .size
48         .displayColor$ = .color$
49         if sgc.currentWordNum >= sgc.numberOfDisplayedWords
50                 .displayColor$ = "Green"
51         endif
52         demo Paint rectangle... '.displayColor$' '.currentX' '.endX' '.lowY' '.highY'
53 endproc
55 procedure DrawNext .color$ .x .y .size
56         demo '.color$'
57         .size *= 2/3
58         .fraction = 0
59         if sgc.numberOfDisplayedWords > 0
60                 .fraction = sgc.currentWordNum/sgc.numberOfDisplayedWords
61         endif
62         call drawProgressTriangle 1 .x .y .size .fraction '.color$' Green
63         .currentX = drawProgressTriangle.currentX
64         .endX = .currentX + 0.5
65         .lowY = .y - .size
66         .highY = .y + .size
67         .displayColor$ = .color$
68         if sgc.currentWordNum >= sgc.numberOfDisplayedWords
69                 .displayColor$ = "Green"
70         endif
71         demo Paint rectangle... '.displayColor$' '.currentX' '.endX' '.lowY' '.highY'
72 endproc
74 procedure DrawSelectWords .color$ .x .y .size
75         .currentFontSize = 48
76         .y -= .size/2 + 0.5
77         .maxHeight = 2*.size
78         call adjustFontSizeOnHeight 'defaultFont$' '.currentFontSize' '.maxHeight'
79         .currentFontSize = adjustFontSizeOnHeight.currentFontSize
80         call set_font_size '.currentFontSize'
81         demo Colour... '.color$'
82         demo Text... '.x' Centre '.y' Bottom \bu\bu\bu
83         call set_font_size 'defaultFontSize'
84 endproc
86 procedure DrawWordListUp .color$ .x .y .size
87     .xleft = .x - .size
88     .xright = .x + .size
89     .xmidleft = .x + 0.1
90     .xmidright = .x - 0.1
91     .ylow = .y
92     .yhigh = .y + .size
93         demo '.color$'
94         demo Line width... 3
95         demo Draw line... .xleft .ylow .xmidleft .yhigh
96         demo Draw line... .xright .ylow .xmidright .yhigh
97         demo Line width... 'defaultLineWidth'
98         demo Black
99 endproc
101 procedure DrawWordListDown .color$ .x .y .size
102     .xleft = .x - .size
103     .xright = .x + .size
104     .xmidleft = .x + 0.1
105     .xmidright = .x - 0.1
106     .yhigh = .y + .size
107     .ylow = .y
108         demo '.color$'
109         demo Line width... 3
110         demo Draw line... .xleft .yhigh .xmidleft .ylow
111         demo Draw line... .xright .yhigh .xmidright .ylow
112         demo Line width... 'defaultLineWidth'
113         demo Black
114 endproc
116 procedure drawTriangle .direction .x .y .size
117         # Make sure direction = +/- 1
118         if .direction = 0
119                 .direction = 1 
120         endif
121         .direction /= abs(.direction)
122         
123         .offset = 0.01
124         .currentHeight = .size
125         .currentX = .x - .direction*.size
126         
127         demo Line width... 2.0
129         while .currentHeight> 0
130                 .ystart = .y + .currentHeight
131                 .yend = .y - .currentHeight
132                 demo Draw line... .currentX .ystart .currentX .yend
133                 .currentHeight -= .offset *3/4
134                 .currentX += .direction*.offset * 1.5
135         endwhile
136         demo Line width... 'defaultLineWidth'
137 endproc
139 procedure drawProgressTriangle .direction .x .y .size .fraction .color1$ .color2$
140         # Make sure direction = +/- 1
141         if .direction = 0
142                 .direction = 1 
143         endif
144         .direction /= abs(.direction)
145         
146         .offset = 0.01
147         .currentHeight = .size
148         .startX = .x - .direction*.size
149         .currentX = .startX
150         
151         demo Line width... 2.0
153         while .currentHeight> 0
154                 # Implement progress bar in .color2$
155                 if .direction*(.currentX - .startX)/.size  <= 2*.fraction
156                         demo '.color2$'
157                 else
158                         demo '.color1$'
159                 endif
160                 
161                 .ystart = .y + .currentHeight
162                 .yend = .y - .currentHeight
163                 demo Draw line... .currentX .ystart .currentX .yend
164                 .currentHeight -= .offset *3/4
165                 .currentX += .direction*.offset * 1.5
166         endwhile
167         demo Line width... 'defaultLineWidth'
168         demo '.color1$'
169 endproc
171 ###############################################################
173 # Obligatory button Drawing Routines
175 # These MUST be defined
177 ###############################################################
179 procedure DrawRecord .color$ .x .y .size
180         .size /= 2
181     demo Paint circle... '.color$' '.x' '.y' '.size'
182 endproc
184 procedure DrawPlay .color$ .x .y .size
185         demo '.color$'
186         call drawTriangle 1 .x .y .size
187 endproc
189 procedure DrawQuit .color$ .x .y .size
190         demo Colour... '.color$'
191         .lineWidth = 0.5*.size**2
192         demo Line width... '.lineWidth'
193         .xstart = .x - .size
194         .ystart = .y + .size
195         .xend = .x + .size
196         .yend = .y - .size
197         demo Draw line... .xstart .ystart .xend .yend
198         .xstart = .x - .size
199         .ystart = .y - .size
200         .xend = .x + .size
201         .yend = .y + .size
202         demo Draw line... .xstart .ystart .xend .yend
203         demo Line width... 'defaultLineWidth'
204         demo Colour... Black
205 endproc
207 procedure DrawConfig .color$ .x .y .size
208         .size *= 1
209         .lineWidth = 0.4*.size
210         demo Arrow size... '.lineWidth'
211         .lineWidth = 0.4*.size**2
212         demo Line width... '.lineWidth'
213         .y += .size/2
214         .xstart = .x - .size
215         .xend = .x + .size
216         demo Draw arrow... .xstart .y .xend .y
217         demo Line width... 'defaultLineWidth'
218 endproc
220 procedure DrawRefresh .color$ .x .y .size
221         .lineWidth = 0.5*.size**2
222         .size /= 2
223         demo Line width... '.lineWidth'
224         demo Draw arc... '.x' '.y' '.size' 0 270
225         demo Line width... 'defaultLineWidth'
226 endproc
228 ###############################################################
230 # Button Processing Routines
232 ###############################################################
234 procedure processMainPageExample .clickX .clickY .pressed$
235         call generate_example
236 endproc
238 procedure processMainPagePrevious .clickX .clickY .pressed$
239         call clean_up_sound
240         call display_text Grey
241         call previous_word
242         # Draw the contour
243         call wipeArea 'wipeFeedbackArea$'
244         call init_window
245         call display_text Black
246         
247         sgc.failedAttempts = 0
248 endproc
250 procedure processMainPageNext .clickX .clickY .pressed$
251         call clean_up_sound
252         call display_text Grey
253         call next_word
254         call wipeArea 'wipeFeedbackArea$'
255         call init_window
256         # Draw the contour
257         call display_text Black
258 endproc
260 procedure processMainPageWordlistUp .clickX .clickY .pressed$
261         call wipeArea 'wipeFeedbackArea$'
262     call load_word_list "'localWordlistDir$'" -1
263         call init_window
264         call display_text Black
265 endproc
267 procedure processMainPageWordlistDown .clickX .clickY .pressed$
268         call wipeArea 'wipeFeedbackArea$'
269     call load_word_list "'localWordlistDir$'" 1
270         call init_window
271         call display_text Black
272 endproc
274 procedure processMainPageGRADE .clickX .clickY .pressed$
275         call setGrade '.pressed$'
276         # Redraw window
277         call init_window
278 endproc
280 procedure processMainPagePinYinArea .clickX .clickY .pressed$
281         # Redraw window
282         sgc.writeAll = 1
283         call display_text Red
284         sgc.writeAll = 0
285 endproc
287 # Select the words to practise. This is quite a complex piece of code
288 procedure processMainPageSelectWords .clickX .clickY .pressed$
289         .table$ = "MainPage"
290         .label$ = "SelectWords"
291     call Draw_button '.table$' '.label$' 1
293         # Get help text
294         call findLabel '.table$' '.label$'
295         .row = findLabel.row
296         select Table '.table$'
297         .helpText$ = Get value... '.row' Helptext
298         call convert_praat_to_latin1 '.helpText$'
299         .helpText$ = convert_praat_to_latin1.text$
300    
301     # Implement Cancel
302     select sgc.currentWordlist
303     .tmpOriginalWordlist = Copy: "Original_'wordlist$'"
305         # Remove current list from All wordlists table
306         select sgc.allWordLists
307         .rowNum = Search column: "Name", wordlistName$
308         if .rowNum > 0
309                 .numRows = Get number of rows
310                 if .numRows > 1
311                         Remove row: .rowNum
312                 else
313                         Set string value: 1, "Name", "---"
314                 endif
315         endif
316     
317     # Set current word
318         select sgc.currentWordlist
319         sgc.numberOfWords = Get number of rows
320     .currentWord = sgc.currentWord
321     if .currentWord <= 0 or .currentWord > sgc.numberOfWords or config.shuffleLists
322                 .currentWord = 1
323         endif
324     
325         # The texts
326         call get_feedback_text 'config.language$' AddWordlist
327         call convert_praat_to_latin1 'get_feedback_text.text$'
328         .wordlistText$ = convert_praat_to_latin1.text$
329         call get_feedback_text 'config.language$' Part
330         call convert_praat_to_latin1 'get_feedback_text.text$'
331         .partText$ = convert_praat_to_latin1.text$
332         call get_feedback_text 'config.language$' Tones
333         call convert_praat_to_latin1 'get_feedback_text.text$'
334         .toneText$ = convert_praat_to_latin1.text$
335         call get_feedback_text 'config.language$' Cancel
336         call convert_praat_to_latin1 'get_feedback_text.text$'
337         .cancelText$ = convert_praat_to_latin1.text$
338         call get_feedback_text 'config.language$' Clear
339         call convert_praat_to_latin1 'get_feedback_text.text$'
340         .clearText$ = convert_praat_to_latin1.text$
341         call get_feedback_text 'config.language$' All
342         call convert_praat_to_latin1 'get_feedback_text.text$'
343         .allText$ = convert_praat_to_latin1.text$
344         call get_feedback_text 'config.language$' Previous
345         call convert_praat_to_latin1 'get_feedback_text.text$'
346         .prevWord$ = convert_praat_to_latin1.text$
347         call get_feedback_text 'config.language$' Next
348         call convert_praat_to_latin1 'get_feedback_text.text$'
349         .nextWord$ = convert_praat_to_latin1.text$
350         call get_feedback_text 'config.language$' Continue
351         call convert_praat_to_latin1 'get_feedback_text.text$'
352         .continueText$ = convert_praat_to_latin1.text$
353         call get_feedback_text 'config.language$' Show
354         call convert_praat_to_latin1 'get_feedback_text.text$'
355         .showText$ = convert_praat_to_latin1.text$
357         call get_evaluation_text 'config.language$' Pinyin
358         .pinyinText$ = get_evaluation_text.text$
359         
360         call get_evaluation_text 'config.language$' Character
361         .characterText$ = get_evaluation_text.text$
362         
363         call get_evaluation_text 'config.language$' Example
364         .exampleText$ = get_evaluation_text.text$
365         
366         call get_evaluation_text 'config.language$' Translation
367         .translationText$ = get_evaluation_text.text$
368         
369         call get_evaluation_text 'config.language$' ManualEntry
370         .manualEntryText$ = get_evaluation_text.text$
371         
372         # Get lesson names
373         select sgc.currentWordlist
374         .lessonCol = Get column index: "Lesson"
375         if .lessonCol <= 0
376                 Append column: "Lesson"
377                 .lessonCol = Get column index: "Lesson"
378                 .numRows = Get number of rows
379                 for .w to .numRows
380                         Set string value: .w, "Lesson", "-"
381                 endfor
382         endif
383         .lessonList$ = tab$
384         .numLessons = 0
385         .lessonName$ = ""
386         # All shown keeps track whether all words are shown
387         # If so, selecting a lesson is preceded by a Clear All
388         .allShown = 0
389         # Sort words for consistent selection interface
390         if config.shuffleLists
391                 # Allow subdivision in lessons
392                 if .lessonCol > 0
393                         Sort rows... Lesson Pinyin
394                 else
395                         Sort rows... Pinyin
396                 endif
397         endif           
398         if .lessonCol > 0
399                 for .i to sgc.numberOfWords
400                         .currentLesson$ = Get value: .i, "Lesson"
401                         .matchLesson$ = tab$+.currentLesson$+tab$
402                         if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
403                                 .lessonList$ = .lessonList$ + .currentLesson$ + tab$
404                                 .numLessons += 1
405                                 .lessonName$['.numLessons'] = .currentLesson$
406                         endif
407                         .shown$ = Get value: .i, "Show"
408                         if .shown$ = "-"
409                                 .allShown = 0
410                         endif
411                 endfor
412         endif
413         
414         clicked = -1
415         .numWordsPerScreen = 15
416         while clicked <> 6 and clicked <> 1
417                 .lessonSelected = -1
418                 .toneSelected = -1
419                 .firstShown = -1
420                 
421                 select sgc.currentWordlist
422                 .lessonCol = Get column index: "Lesson"
423                 # Sort words for consistent selection interface
424         if config.shuffleLists
425                         # Allow subdivision in lessons
426                         if .numLessons > 1
427                                 Sort rows... Lesson Pinyin
428                         else
429                                 Sort rows... Pinyin
430                         endif
431         endif           
432                 .max = .numWordsPerScreen - 1
433                 if .currentWord + .max > sgc.numberOfWords
434                         .max = sgc.numberOfWords - .currentWord
435                 endif
436                 for .i from 0 to .numWordsPerScreen - 1
437                         if .i <= .max
438                                 .currentPinyin$ = Get value: .currentWord+.i, "Pinyin"
439                                 if index_regex(.currentPinyin$, "[0-9]") <= 0
440                                         call pinyin2numbers '.currentPinyin$'
441                                         .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
442                                         .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
443                                 endif
444                                 .pinyin$[.i] = .currentPinyin$
446                                 .character$[.i] = Get value: .currentWord+.i, "Character"
447                                 .lessonNum$[.i] = ""
448                                 if .numLessons > 1
449                                         .lessonNum$[.i] = Get value: .currentWord+.i, "Lesson"
450                                         .lessonNum$[.i] = " : " + .lessonNum$[.i]
451                                 endif
452                                 .showText$[.i] = .pinyin$['.i']
453                                 if .character$['.i'] <> "-"
454                                         .showText$[.i] = .pinyin$['.i']+" ("+.character$['.i']+.lessonNum$['.i']+")"
455                                 elsif .lessonNum$['.i'] <> ""
456                                         .showText$[.i] = .pinyin$['.i']+" ( -"+.lessonNum$['.i']+")"
457                                 endif
458                                 .showValueText$[.i] = Get value: .currentWord+.i, "Show"
459                                 if .showValueText$[.i] = "-"
460                                         .showValue[.i] = 0
461                                 else
462                                         .showValue[.i] = 1
463                                 endif
464                                 .showVariable$[.i] = .pinyin$[.i]
465                                 # This prevents some nasty attempts to use language elements as variabels
466                                 if index_regex(.showVariable$[.i], "[^0-9]$") 
467                                         .showVariable$[.i] = .pinyin$[.i]+"0"
468                                 endif
469                                 .tmp$ = replace_regex$(.showVariable$[.i], "^(.+)$", "\l\1", 0)
470                                 .tmp$ = replace_regex$(.tmp$, "[^\w]", "_", 0)
471                                 '.tmp$' = .showValue[.i]
472                         else
473                                 .showText$[.i] = "-"
474                                 .showValue[.i] = 0
475                         endif
476                 endfor
478                 # The user text input window (beginPause .... endPause)
479                 beginPause(.helpText$)
480                         if sgc.allWordLists > 0
481                                 select sgc.allWordLists
482                                 .numWordlists = Get number of rows
483                                 optionMenu: .wordlistText$, 1
484                                         option: "---"
485                                         for .w to .numWordlists
486                                                 select sgc.allWordLists
487                                                 .wordListName$ = Get value: .w, "Name"
488                                                 option: .wordListName$
489                                         endfor
490                                         option: "*"+.manualEntryText$+"*"
491                         endif
492                         
493                         boolean (.showText$[0], .showValue[0])
494                         boolean (.showText$[1], .showValue[1])
495                         boolean (.showText$[2], .showValue[2])
496                         boolean (.showText$[3], .showValue[3])
497                         boolean (.showText$[4], .showValue[4])
498                         boolean (.showText$[5], .showValue[5])
499                         boolean (.showText$[6], .showValue[6])
500                         boolean (.showText$[7], .showValue[7])
501                         boolean (.showText$[8], .showValue[8])
502                         boolean (.showText$[9], .showValue[9])
503                         boolean (.showText$[10], .showValue[10])
504                         boolean (.showText$[11], .showValue[11])
505                         boolean (.showText$[12], .showValue[12])
506                         boolean (.showText$[13], .showValue[13])
507                         boolean (.showText$[14], .showValue[14])
508                         if .numLessons > 0
509                                 optionMenu: .partText$, 1
510                                         option: "---"
511                                         .j = 0
512                                         for .j to .numLessons
513                                                 option: .lessonName$['.j']
514                                         endfor
515                         endif
516                         optionMenu: .toneText$, 1
517                                 option: "---"
518                                 option: "0"
519                                 option: "1"
520                                 option: "2"
521                                 option: "3"
522                                 option: "4"
523                 clicked = endPause ("'.cancelText$'", "'.clearText$'", "'.allText$'", "'.prevWord$'", "'.nextWord$'", "'.continueText$'", 6, 1)
524                 
525                 select sgc.currentWordlist
526                 if clicked = 2
527                         for .i to sgc.numberOfWords
528                                 Set string value: .i, "Show", "-"
529                         endfor
530                         .allShown = 0
531                 elsif clicked = 3
532                         for .i to sgc.numberOfWords
533                                 Set string value: .i, "Show", "+"
534                         endfor
535                         .allShown = 1
536                 elsif clicked != 1
537                         # Handle added word lists
538                         .wordlistText$ = replace_regex$(.wordlistText$, "^(.)", "\l\1", 0)
539                         .wordlistText$ = replace_regex$(.wordlistText$, "[^\w]", "_", 0)
540                         .tmp$ = '.wordlistText$'$
541                         if .tmp$ <> "---" and sgc.allWordLists > 0
542                                 select sgc.currentWordlist
543                                 # Add current wordlist name as  a lesson name
544                                 .originalWordList = -1
545                                 .numRows = Get number of rows
546                                 for .w to .numRows
547                                         select sgc.currentWordlist
548                                         .currentLesson$ = Get value: .w, "Lesson"
549                                         if .currentLesson$ = "" or .currentLesson$ = "-"
550                                                 Set string value: .w, "Lesson", wordlist$
551                                         endif
552                                 endfor
553                                 
554                                 # Get and merge the selected list
555                                 # Enter words by hand
556                                 if .tmp$ = "*"+.manualEntryText$+"*"
557                                         .man_clicked = 3
558                                         .currentFilePath$ = .exampleText$
559                                         .manualText$ = .manualEntryText$
560                                         .manPinyin$ = .pinyinText$
561                                         .manCharacter$ = .characterText$
562                                         .manTranslation$ = .translationText$
563                                         .manSound$ = .currentFilePath$
564                                         .manLesson$ = .manualText$
565                                         while .man_clicked > 1
566                                                 beginPause: .manualEntryText$
567                                                         text: .pinyinText$, .manPinyin$
568                                                         text: .characterText$, .manCharacter$ 
569                                                         text: .translationText$, .manTranslation$ 
570                                                         text: .exampleText$, .manSound$
571                                                         text: .manualText$, .manualText$
572                                                 .man_clicked = endPause("'.cancelText$'", "'.exampleText$'", "'.continueText$'", 3, 1)
573                                                 if .man_clicked > 1
574                                                         .tmp$ = replace_regex$(.pinyinText$, "[^\w]", "_", 0)
575                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
576                                                         if '.tmp$'$ <> .pinyinText$ 
577                                                                 .manPinyin$ = '.tmp$'$
578                                                         else
579                                                                 # Quit
580                                                                 .man_clicked = 0
581                                                         endif
583                                                         .tmp$ = replace_regex$(.characterText$, "[^\w]", "_", 0)
584                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
585                                                         if '.tmp$'$ <> .characterText$ 
586                                                                 .manCharacter$ = '.tmp$'$
587                                                         else
588                                                                 .manCharacter$ = ""
589                                                         endif
590                                                         
591                                                         .tmp$ = replace_regex$(.translationText$, "[^\w]", "_", 0)
592                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
593                                                         if '.tmp$'$ <> .translationText$ 
594                                                                 .manTranslation$ = '.tmp$'$
595                                                         else
596                                                                 .manTranslation$ = ""
597                                                         endif
598                                                         
599                                                         .tmp$ = replace_regex$(.exampleText$, "[^\w]", "_", 0)
600                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
601                                                         if '.tmp$'$ <> .characterText$ and '.tmp$'$ <> ""
602                                                                 .manSound$ = '.tmp$'$
603                                                         endif
604                                                         
605                                                         .tmp$ = replace_regex$(.manualText$, "[^\w]", "_", 0)
606                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
607                                                         .manLesson$ = '.tmp$'$
608                                                         
609                                                         if .man_clicked = 2
610                                                                 .manSound$ = chooseReadFile$(.exampleText$);
611                                                         elsif .man_clicked = 3
612                                                                 # Clean up input string
613                                                                 .manPinyin$ = replace_regex$(.manPinyin$, "^[^a-z]+", "", 0)
614                                                                 .manPinyin$ = replace_regex$(.manPinyin$, "[^\w']", "", 0)
615                                                                 
616                                                                 select sgc.currentWordlist
617                                                                 Append row
618                                                                 .numRows = Get number of rows
619                                                                 if .manPinyin$ <> ""
620                                                                         Set string value: .numRows, "Pinyin", .manPinyin$
621                                                                         Set string value: .numRows, "Character", .manCharacter$
622                                                                         Set string value: .numRows, "Translation", .manTranslation$
623                                                                         Set string value: .numRows, "Sound", .manSound$
624                                                                         Set string value: .numRows, "Lesson", .manLesson$
625                                                                         Set string value: .numRows, "Show", "+"
626                                                                 endif
627                                                                 .manualText$ = .manualEntryText$
628                                                                 .manPinyin$ = .pinyinText$
629                                                                 .manCharacter$ = .characterText$
630                                                                 .manTranslation$ = .translationText$
631                                                                 .manSound$ = .currentFilePath$
632                                                                 .manLesson$ = .manualText$                                                      
633                                                         endif
634                                                 endif
635                                         endwhile                                        
636                                 else
637                                         # Existing lessons
638                                         select sgc.allWordLists
639                                         .wordlistNum = Search column: "Name", .tmp$
640                                         if .wordlistNum > 0
641                                                 .wordlistPath$ = Get value: .wordlistNum, "Directory"
642                                                 .wordlistPath$ = replace_regex$(.wordlistPath$, "[ ]", "&", 0)
643                                                 call read_wordlist "'.tmp$'" '.wordlistPath$'
644                                                 .newList = read_wordlist.wordlistID
645                                                 call merge_into_wordlist '.newList' '.tmp$'
646                                                 select .newList
647                                                 Remove
648                                                 # Add wordlistname to Lesson column
649                                                 select sgc.allWordLists
650                                                 .numRows = Get number of rows
651                                                 if .numRows > 1
652                                                         Remove row: .wordlistNum
653                                                 else
654                                                         Set string value: 1, "Name", "---"
655                                                 endif
656                                         endif
657                                 endif
658                                 # Gather Lesson names
659                                 select sgc.currentWordlist
660                                 Sort rows... Lesson Pinyin
661                                 if .lessonCol > 0
662                                         sgc.numberOfWords = Get number of rows
663                                         .lessonList$ = tab$
664                                         .numLessons = 0
665                                         .lessonName$ = ""
666                                         for .i to sgc.numberOfWords
667                                                 .currentLesson$ = Get value: .i, "Lesson"
668                                                 .matchLesson$ = tab$+.currentLesson$+tab$
669                                                 if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
670                                                         .lessonList$ = .lessonList$ + .currentLesson$ + tab$
671                                                         .numLessons += 1
672                                                         .lessonName$['.numLessons'] = .currentLesson$
673                                                 endif
674                                                 .shown$ = Get value: .i, "Show"
675                                                 if .shown$ = "-"
676                                                         .allShown = 0
677                                                 endif
678                                         endfor
679                                 endif
680                         else                    
681                                 select sgc.currentWordlist
682                                 # Get selected Part BEFORE we do anything else
683                                 if .numLessons > 0
684                                         .tmp$ = replace_regex$(.partText$, "^(.)", "\l\1", 0)
685                                         .lessonSelected = '.tmp$' - 1
686                                 endif
687                                 if .lessonSelected > 0
688                                         .allShown = 1
689                                         .firstShown = -1
690                                         select sgc.currentWordlist
691                                         for .i to sgc.numberOfWords
692                                                 # Keep track of whether all are shown
693                                                 .shown$ = Get value: .i, "Show"
694                                                 if .shown$ = "-"
695                                                         .allShown = 0
696                                                 endif
697                                         endfor
699                                         for .i to sgc.numberOfWords
700                                                 # Lessons
701                                                 .currentLesson$ = Get value: .i, "Lesson"
702                                                 if .currentLesson$ = .lessonName$['.lessonSelected']
703                                                         Set string value: .i, "Show", "+"
704                                                 elsif .allShown = 1
705                                                         Set string value: .i, "Show", "-"
706                                                 endif
707                                         endfor
708                                         for .i to sgc.numberOfWords
709                                                 # Keep track of whether all are shown
710                                                 .shown$ = Get value: .i, "Show"
711                                                 if .firstShown <=0 and .shown$ <> "-"
712                                                         .firstShown = .i
713                                                 endif
714                                         endfor
715                                 else
716                                         for .i from 0 to .max
717                                                 .tmp$ = replace_regex$(.showVariable$['.i'], "^(.*)$", "\l\1", 0)
718                                                 .tmp$ = replace_regex$(.tmp$, "[^\w]", "_", 0)
719                                                 
720                                                 .showValue['.i'] = '.tmp$'
721                                                 .showWord$['.i'] = "-"
722                                                 if .showValue['.i'] <> 0
723                                                         .showWord$['.i'] = "+"
724                                                 endif
725                                                 Set string value: .currentWord+.i, "Show", .showWord$['.i']
726                                         endfor
727                                 endif
728                         endif
729                         
730                         select sgc.currentWordlist
731                         .tmp$ = replace_regex$(.toneText$, "^(.)", "\l\1", 0)
732                         .tmp$ = replace_regex$(.tmp$, "[^\w]", "_", 0)
733                         .toneSelected = '.tmp$' - 2
734                         if .toneSelected >= 0
735                                 select sgc.currentWordlist
736                                 for .i to sgc.numberOfWords
737                                         .currentPinyin$ = Get value: .i, "Pinyin"
738                                         if index_regex(.currentPinyin$, "[0-9]") <= 0
739                                                 call pinyin2numbers '.currentPinyin$'
740                                                 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
741                                                 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
742                                         endif
743                                         .tmp$ = Get value: .i, "Show"
744                                         if .tmp$ <> "-" and index(.currentPinyin$, "'.toneSelected'") > 0
745                                                 Set string value: .i, "Show", "+"
746                                         else
747                                                 Set string value: .i, "Show", "-"
748                                                 .allShown = 0
749                                         endif
750                                 endfor
751                         endif
752                         
753                         if clicked = 4
754                                 if .firstShown > 0
755                                         .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
756                                 elsif .toneSelected < 0
757                                         .currentWord -= .numWordsPerScreen
758                                 endif
759                                 if .currentWord <= 0
760                                         .currentWord = (sgc.numberOfWords div .numWordsPerScreen) * .numWordsPerScreen + 1
761                                 endif
762                         elsif clicked = 5
763                                 if .firstShown > 0
764                                         .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
765                                 elsif .toneSelected < 0
766                                         .currentWord += .numWordsPerScreen
767                                 endif
768                                 if .currentWord > sgc.numberOfWords
769                                         .currentWord = 1
770                                 endif
771                         endif
772                 endif
773                 # Reset and go to the first selected word (can shuffle list)
774                 if clicked = 6
775                         sgc.currentWord = -1
776                         call next_word
777                         call init_window
778                 endif
779         endwhile
780         
781     # Implement Cancel
782     if clicked = 1
783                 select sgc.currentWordlist
784                 Remove
785                 select .tmpOriginalWordlist
786                 Copy: wordlist$
787                 sgc.currentWordlist = selected()
788         else
789                 # Set the values of the number of words shown   
790                 select sgc.currentWordlist
791                 .numWords = Get number of rows
792                 sgc.currentWordNum = 1
793                 sgc.numberOfDisplayedWords = 0
794                 sgc.currentWord = 0
795                 for .i to .numWords
796                         .show$ = Get value: .i, "Show"
797                         if .show$ = "+"
798                                 if sgc.currentWord < 1
799                                         sgc.currentWord = .i
800                                 endif
801                                 sgc.numberOfDisplayedWords += 1
802                         endif
803                 endfor
804         endif
805         select .tmpOriginalWordlist
806         Remove
808     call Draw_button '.table$' '.label$' 0
809 endproc
811 ###############################################################
813 # Obligatory button Processing Routines
815 # These MUST be defined
817 ###############################################################
819 procedure processMainPageQuit .clickX .clickY .pressed$
820         call end_program
821 endproc
823 procedure processMainPageRefresh .clickX .clickY .pressed$
824         call clean_up_sound
825         call init_window
826 endproc
828 procedure processMainPageConfig .clickX .clickY .pressed$
829         call config_page
830 endproc
832 procedure processMainPageHelp .clickX .clickY .pressed$
833         call help_loop 'buttons$' init_window
834 endproc
836 procedure processMainPagePlay .clickX .clickY .pressed$
837         .table$ = "MainPage"
838         .label$ = "Play"
839         if recordedSound$ <> ""
840                 call play_sound 'sgc.recordedSound'
841                 mainPage.play = 0
842         endif
843         te.buttonPressValue = mainPage.play
844 endproc
846 procedure Set_Play_Button
847         mainPage.play = -1
848         if recordedSound$ <> ""
849                 mainPage.play = 0
850     endif       
851         call Draw_button MainPage Play 'mainPage.play'
852 endproc
854 procedure processMainPageRecord .clickX .clickY .pressed$
855         call count_syllables
856         .recordingTime = recordingTime
857         if count_syllables.number > 2
858                 .recordingTime = recordingTime + 1.0*ceiling((count_syllables.number - 2)/2)
859         endif
860     call record_sound '.recordingTime'
861     call recognizeTone
862         mainPage.play = 0
863         call Set_Play_Button
865     # Wipe screen
866     call wipeArea 'wipeContourArea$'
867    
868     call draw_tone_contour
869     # Write text (again)
870     call display_word_list_name
871     call display_text Black
872         call add_feedback_to_toneevaluation Feedback
873     call write_feedback Feedback
874         select Table Feedback
875         Remove
876         
877         # Do not exercise words that are going well (autoSelect)
878     if add_feedback_to_toneevaluation.result > 0
879                 if config.adaptiveLists > 0 and sgc.failedAttempts < 2
880                         # Deselect current word
881                         select sgc.currentWordlist
882                         .i = Search column: "Pinyin", sgc.pinyin$
883                         if .i > 0
884                                 Set string value: .i, "Show", "-"
885                         endif
886                 endif
887                 sgc.failedAttempts = 0
888     else
889                 sgc.failedAttempts += 1
890     endif
891 endproc
894 ###############################################################
896 # Miscelaneous supporting code
898 ###############################################################
900 # The example
901 procedure generate_example
902         select sgc.currentWordlist
903         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
904                 select sgc.currentWordlist
905                 .sound$ = Get value... 'sgc.currentWord' Sound
906                 call readPinyin 'sgc.currentWord'
907                 sgc.pinyin$ = readPinyin.pinyin$
908                 if .sound$ = "-" or .sound$ = ""
909                         .sound$ = sgc.pinyin$+".wav"
910                 endif
911                 if index_regex(.sound$, "^(/|~/|[A-Z]:\\)") > 0
912                         .soundFilePath$ = .sound$
913                 else
914                         .soundFilePath$ = localWordlistDir$+"/"+wordlistName$+"/"+.sound$
915                         .wordlistDirectory$ = ""
916                         if localWordlistDir$ <> "" and fileReadable("'localWordlistDir$'/'wordlistName$'")
917                                 .wordlistDirectory$ = "'localWordlistDir$'/'wordlistName$'"
918                         elsif sgc2wordlists$ <> "" and fileReadable("'sgc2wordlists$'/'wordlistName$'")
919                                 .wordlistDirectory$ = "'sgc2wordlists$'/'wordlistName$'"
920                         elsif globalwordlists$ <> "" and fileReadable("'globalwordlists$'/'wordlistName$'")
921                                 .wordlistDirectory$ = "'globalwordlists$'/'wordlistName$'"
922                         endif
923                         if .wordlistDirectory$ <> ""
924                                 .audioExampleList = Create Strings as file list... AudioList '.wordlistDirectory$'/'sgc.pinyin$'.*
925                                 .number_of_examples = Get number of strings
926                                 if .number_of_examples > 0
927                                         Randomize
928                                         .sound$ = Get string... 1
929                                         .soundFilePath$ = "'.wordlistDirectory$'/'.sound$'"
930                                 endif
931                                 Remove
932                         endif
933                 endif
934                 if fileReadable(.soundFilePath$) and config.useSoundExample
935                         .tmp = -1
936                         .tmp = nocheck Read from file... '.soundFilePath$'
937                         if .tmp != undefined and .tmp > 0
938                                 call play_sound '.tmp'
939                                 select .tmp
940                                 Remove
941                         endif
942                 elsif config.synthesis$ <> "" and config.synthesis$ <> "_DISABLED_"
943                         call synthesize_sound 'sgc.pinyin$'
944                 else
945                         call humToneContour 'sgc.pinyin$' 'config.register'
946                         call reset_viewport
947                 endif
948         endif
949         demoShow()
950 endproc
952 # Draw a tone contour
953 procedure draw_tone_contour
954         select sgc.currentWordlist
955         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
956                 .sound$ = Get value... 'sgc.currentWord' Sound
957                 call readPinyin 'sgc.currentWord'
958                 sgc.pinyin$ = readPinyin.pinyin$
959                 call drawToneContour 'sgc.pinyin$' 'config.register'
960                 call reset_viewport
961                 
962                 if te.recordedPitch > 0
963                         call drawSourceToneContour te.recordedPitch
964                 endif
965         endif
967 endproc
969 procedure recognizeTone
970         select sgc.currentWordlist
971         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
972                 .strict = 0
973                 if index_regex(config.strict$, "[^0-9]") <= 0
974                         .strict = ('config.strict$' >= sgc.highestLevel)
975                 endif
976                         
977                 .sound$ = Get value... 'sgc.currentWord' Sound
978                 call readPinyin 'sgc.currentWord'
979                 sgc.pinyin$ = readPinyin.pinyin$
980                 call align_recordedSound 'sgc.pinyin$'
981         call sgc_ToneProt 'recordedSound$' 'sgc.pinyin$' 'config.register' '.strict' 'config.language$'
982         # sgc_ToneProt manipulates the sound given. Reconnect
983         select Sound 'recordedSound$'
984         sgc.recordedSound = selected("Sound")
985                 call reset_viewport
986         endif
987 endproc
989 procedure write_feedback .table$
990     select Table '.table$'
991     .line1$ = Get value... 1 Text
992     .line2$ = Get value... 2 Text
993     .label$ = Get value... 3 Text
995         # convert numbers to Pinyin if needed
996         if not config.displayNumbers
997                 call numbers2pinyin '.line1$'
998                 .line1$ = numbers2pinyin.pinyin$
999         endif
1001     .color$ = "Red"
1002     if index(.line1$, "???") > 0
1003         .color$ = "Black"
1004     elsif .label$ = "Correct"
1005         .color$ = "Green"
1006         elsif config.strict$ = "'sgc.highestLevel'"
1007                 .line2$ = .line2$ + " *"
1008     endif
1010         .currentFeedbackFontSize = 14
1011         .maxHeight = 21 - 17
1012         call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
1013         .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
1014         
1015         call wipeArea 'wipeFeedbackArea$'
1016     call set_font_size '.currentFeedbackFontSize'
1017     demo '.color$'
1018     demo Text... 50 Centre 21 Bottom '.line1$'
1019     demo Text... 50 Centre 17 Bottom '.line2$'
1020         demoShow()
1021         demo 'defaultFont$'
1022     call set_font_size 'defaultFontSize'
1023 endproc
1025 # Text display
1026 procedure display_text .color$
1027         select sgc.currentWordlist
1028         if sgc.currentWord < 0 or sgc.currentWord > sgc.numberOfWords+1
1029                 call clean_up_sound
1030         if config.shuffleLists
1031                     Randomize rows
1032         endif
1033                 if sgc.currentWord < 0
1034                         sgc.currentWord = sgc.numberOfWords
1035                 else
1036                         sgc.currentWord = 1
1037                 endif
1038         endif
1039         
1040         .changeCJKstyle = 0
1041         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
1042                 .displayText$ = ""
1043                 call readDisplayPinyin 'sgc.currentWord'
1044                 .displayPinyin$ = readDisplayPinyin.pinyin$
1045                 .displayChar$ = Get value... 'sgc.currentWord' Character
1046                 .displayTrans$ = Get value... 'sgc.currentWord' Translation
1047                 if .displayPinyin$ <> "-" and (config.displayPinyin or sgc.writeAll)
1048                         if not config.displayNumbers
1049                                 call numbers2pinyin '.displayPinyin$'
1050                                 .displayPinyin$ = numbers2pinyin.pinyin$
1051                         endif
1052                         # Insert u umlaut
1053                         .displayPinyin$ = replace_regex$(.displayPinyin$, "v", "\\u\X22", 0)
1054                         .displayText$ = .displayText$ + .displayPinyin$
1055                 endif
1056                 if .displayChar$ <> "-" and (config.displayChar or sgc.writeAll)
1057                         .displayText$ = .displayText$ + "  "+ .displayChar$
1058                         .changeCJKstyle = 1
1059                 endif
1060                 if .displayTrans$ <> "-" and (config.displayTrans or sgc.writeAll)
1061                         .displayText$ = .displayText$ + "  \s{%%"+ .displayTrans$ + "%}"
1062                 endif
1063         elsif sgc.currentWord = 0 or sgc.currentWord = sgc.numberOfWords+1
1064                 call clean_up_sound
1065                 .displayText$ = "---"
1066         endif
1068         # Adapt font size
1069         call adjustFontSizeOnHeight 'defaultFont$' 24 15
1070         .currentFontSize = adjustFontSizeOnHeight.newFontSize
1071         call adjustFontSizeOnWidth 'defaultFont$' '.currentFontSize' 95 '.displayText$'
1072         .currentFontSize = adjustFontSizeOnWidth.newFontSize
1074         # Clear the writing area
1075         call wipeArea 'wipePinyinArea$'
1076         # Switch back to Chinese style CJK when in Japanese language mode
1077         if .changeCJKstyle and config.language$ = "JA"
1078                 CJK font style preferences: "Chinese"
1079         endif
1080         # Actually display text
1081         demo '.color$'
1082         call set_font_size '.currentFontSize'
1083         demo Text... 50 Centre 26 Bottom '.displayText$'
1084         demoShow()
1085         demo Black
1086         demo 'defaultFont$'
1087         call set_font_size 'defaultFontSize'
1088         if .changeCJKstyle and config.language$ = "JA"
1089                 if config.language$ = "JA"
1090                         CJK font style preferences: "Japanese"
1091                 elsif config.language$ = "ZH"
1092                         CJK font style preferences: "Chinese"
1093                 endif
1094         endif
1095         # Switch back to Japanese style CJK when in Japanese language mode
1096         if .changeCJKstyle and config.language$ = "JA"
1097                 CJK font style preferences: "Japanese"
1098         endif
1099 endproc
1101 procedure numbers2pinyin .numberstext$
1102         .intermediatePinyin$ = .numberstext$
1103         # Add a `-quote between vowels
1104         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])([aeuiov])", "\1\2'\3", 0)
1105         # Move numbers to the nucleus vowel
1106         # To the vowel
1107         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([^aeuiov0-9]*)([0-9])", "\1\3\2", 0)
1108         # Either a/e
1109         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([ae])([aeuiov]*)([0-9])", "\1\3\2", 0)
1110         # Or the Oo in /ou/
1111         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(ou)([0-9])", "o\2u", 0)
1112         # or the second vowel
1113         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([uiov][aeuiov])([uiov])([0-9])", "\1\3\2", 0)
1114         
1115         # Convert all tones to special characters
1116         # Tone 1
1117         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a1", "ā", 0)
1118         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e1", "ē", 0)
1119         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u1", "ū", 0)
1120         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i1", "ī", 0)
1121         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o1", "ō", 0)
1122         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v1", "ǖ", 0)
1123         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "1", "\\-^", 0)
1124         
1125         # Tone 2
1126         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v2", "ǘ", 0)
1127         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])2", "\\\1'", 0)
1128         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "2", "\\'^", 0)
1129         
1130         # Tone 3
1131         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a3", "ǎ", 0)
1132         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e3", "ě", 0)
1133         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u3", "ǔ", 0)
1134         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i3", "ǐ", 0)
1135         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o3", "ǒ", 0)
1136         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v3", "ǚ", 0)
1137         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "3", "\\N^", 0)
1139         # Tone 4
1140         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v4", "ǜ", 0)
1141         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])4", "\\\1`", 0)
1142         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "4", "\\`^", 0)
1143         
1144         # Tone 0
1145         # Remove tone 0 symbol completely
1146         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "", 0)
1147         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a0", "å", 0)
1148         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e0", "e̊", 0)
1149         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u0", "ů", 0)
1150         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i0", "i̊", 0)
1151         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o0", "o̊", 0)
1152         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v0", "ü̊", 0)
1153         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "\\0^", 0)
1154         
1155         # Pick best vowel symbols available in cases not caught before
1156         # Ugly clutch to get the 1, 3, 0 tone diacritics at least in the neighbourhood
1157         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i(\\[-N0]\^)", "i\\s{_ }\1", 0)
1158         # Insert u umlaut
1159         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v", "\\u\X22", 0)
1161         .pinyin$ = .intermediatePinyin$
1162 endproc
1164 # NEEDS WORK AND TESTING!!
1165 # Convert unicode Pinyin into tone numbers
1166 procedure pinyin2numbers .pinyin$
1167         .intermediatePinyin$ = .pinyin$
1168         # Convert all special characters to numbers
1169         # Tone 1
1170         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iā)([iaeouü]*)", "a\11", 0)
1171         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iē)([iaeouü]*)", "e\11", 0)
1172         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iū)([iaeouü]*)", "u\11", 0)
1173         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iī)([iaeouü]*)", "i\11", 0)
1174         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iō)([iaeouü]*)", "o\11", 0)
1175         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǖ)([iaeouü]*)", "v\11", 0)
1176         
1177         # Tone 2
1178         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iá)([iaeouü]*)", "a\12", 0)
1179         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ié)([iaeouü]*)", "e\12", 0)
1180         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iú)([iaeouü]*)", "u\12", 0)
1181         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ií)([iaeouü]*)", "i\12", 0)
1182         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ió)([iaeouü]*)", "o\12", 0)
1183         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǘ)([iaeouü]*)", "v\12", 0)
1184         
1185         # Tone 3
1186         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǎ)([iaeouü]*)", "a\13", 0)
1187         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iě)([iaeouü]*)", "e\13", 0)
1188         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǔ)([iaeouü]*)", "u\13", 0)
1189         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǐ)([iaeouü]*)", "i\13", 0)
1190         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǒ)([iaeouü]*)", "o\13", 0)
1191         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǚ)([iaeouü]*)", "v\13", 0)
1193         # Tone 4
1194         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ià)([iaeouü]*)", "a\14", 0)
1195         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iè)([iaeouü]*)", "e\14", 0)
1196         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iù)([iaeouü]*)", "u\14", 0)
1197         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iì)([iaeouü]*)", "i\14", 0)
1198         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iò)([iaeouü]*)", "o\14", 0)
1199         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǜ)([iaeouü]*)", "v\14", 0)
1200         
1201         # Tone 0
1202         # Add tone 0
1203         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iå)([iaeouü]*)", "a\10", 0)
1204         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e̊([iaeouü]*)", "e\10", 0)
1205         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iů)([iaeouü]*)", "u\10", 0)
1206         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i̊([iaeouü]*)", "i\10", 0)
1207         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o̊([iaeouü]*)", "o\10", 0)
1208         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ü̊([iaeouü]*)", "v\10", 0)
1210         # Syllables without a tone symbol are tone 0
1211         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov]+)([^0-9aeuiov]|\W|$)", "\10\2", 0)
1213         # Move numbers to the end of the syllable.
1214         # Syllables ending in n and start with g. Note that a syllable cannot start with an u or i
1215         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(n)(g[aeuiov])", "\1\3\2\4", 0)
1216         # Syllables ending in (ng?) followed by something that is not a valid vowel 
1217         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(ng?)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1218         # Syllables ending in r
1219         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(r)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1220         # Remove quotes etc
1221         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "[\\'\\`]", "", 0)
1222         
1223         .numberstext$ = .intermediatePinyin$
1224 endproc
1226 procedure readDisplayPinyin .currentWord
1227         select sgc.currentWordlist
1228         .pinyin$ = Get value... '.currentWord' Pinyin
1229         # Everything to lowercase
1231         if index_regex(.pinyin$, "[0-9]") <= 0
1232                 call pinyin2numbers '.pinyin$'
1233                 .pinyin$ = pinyin2numbers.numberstext$
1234         endif 
1235 endproc
1237 procedure readPinyin .currentWord
1238         call readDisplayPinyin '.currentWord'
1239         .pinyin$ = replace_regex$(readDisplayPinyin.pinyin$, ".+", "\L&", 0)
1240         .pinyin$ = replace_regex$(.pinyin$, "[\\'\\` ]", "", 0)
1241         # Remove anything that is objectionable
1242         .pinyin$ = replace_regex$(.pinyin$, "[^\w']", "", 0)
1243 endproc
1245 # Includes
1246 include ToneProt/SGC_ToneProt.praat
1247 include ToneProt/DrawToneContour.praat
1248 include ToneProt/HumToneContour.praat
1249 include ToneProt/ToneRecognition.praat
1250 include ToneProt/ToneScript.praat
1251 include ToneProt/ToneRules.praat