Updated shasums
[sgc2.git] / MainPage.praat
blob2bab2aa116ff2a5c0176dee1373e2bfbbccff222
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$' Apply
345         call convert_praat_to_latin1 'get_feedback_text.text$'
346         .applySelection$ = 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 variables
466                                 if index_regex(.showVariable$[.i], "[^0-9r]$") or index_regex(.showVariable$[.i], "[0-9]") <= 0 
467                                         .showVariable$[.i] = .pinyin$[.i]+"0"
468                                 endif
469                                 .tmp$ = replace_regex$(.showVariable$[.i], "^(.+)$", "\l\1", 0)
470                                 .tmp$ = replace_regex$(.tmp$, "\s", "_", 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                         
509                         .selectMenu$ = .toneText$
510                         if .numLessons > 0
511                                 .selectMenu$ = .selectMenu$ + " " + .partText$
512                         endif
513                         optionMenu: .selectMenu$, 1
514                                 option: .toneText$
515                                 option: "0"
516                                 option: "1"
517                                 option: "2"
518                                 option: "3"
519                                 option: "4"
520                         
521                         # Display Lesson text if available
522                         if .numLessons > 0
523                                 option: "---"
524                                 .j = 0
525                                 for .j to .numLessons
526                                         option: .partText$+": "+.lessonName$['.j']
527                                 endfor
528                         endif
529                 clicked = endPause ("'.cancelText$'", "'.clearText$'", "'.allText$'", "'.applySelection$'", "'.nextWord$'", "'.continueText$'", 6, 1)
530                 
531                 select sgc.currentWordlist
532                 if clicked = 2
533                         for .i to sgc.numberOfWords
534                                 Set string value: .i, "Show", "-"
535                         endfor
536                         .allShown = 0
537                 elsif clicked = 3
538                         for .i to sgc.numberOfWords
539                                 Set string value: .i, "Show", "+"
540                         endfor
541                         .allShown = 1
542                 elsif clicked != 1
543                         # Handle added word lists
544                         .tmp$ = replace_regex$(.wordlistText$, "^(.)", "\l\1", 0)
545                         .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
546                         .tmp$ = '.tmp$'$
547                         if .tmp$ <> "---" and sgc.allWordLists > 0
548                                 select sgc.currentWordlist
549                                 # Add current wordlist name as  a lesson name
550                                 .originalWordList = -1
551                                 .numRows = Get number of rows
552                                 for .w to .numRows
553                                         select sgc.currentWordlist
554                                         .currentLesson$ = Get value: .w, "Lesson"
555                                         if .currentLesson$ = "" or .currentLesson$ = "-"
556                                                 Set string value: .w, "Lesson", wordlist$
557                                         endif
558                                 endfor
559                                 
560                                 # Get and merge the selected list
561                                 # Enter words by hand
562                                 if .tmp$ = "*"+.manualEntryText$+"*"
563                                         .man_clicked = 3
564                                         .currentFilePath$ = .exampleText$
565                                         .manualText$ = .manualEntryText$
566                                         .manPinyin$ = .pinyinText$
567                                         .manCharacter$ = .characterText$
568                                         .manTranslation$ = .translationText$
569                                         .manSound$ = .currentFilePath$
570                                         .manLesson$ = .manualText$
571                                         while .man_clicked > 1
572                                                 beginPause: .manualEntryText$
573                                                         text: .pinyinText$, .manPinyin$
574                                                         text: .characterText$, .manCharacter$ 
575                                                         text: .translationText$, .manTranslation$ 
576                                                         text: .exampleText$, .manSound$
577                                                         text: .manualText$, .manualText$
578                                                 .man_clicked = endPause("'.cancelText$'", "'.exampleText$'", "'.continueText$'", 3, 1)
579                                                 if .man_clicked > 1
580                                                         .tmp$ = replace_regex$(.pinyinText$, "\s", "_", 0)
581                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
582                                                         if '.tmp$'$ <> .pinyinText$ 
583                                                                 .manPinyin$ = '.tmp$'$
584                                                         else
585                                                                 # Quit
586                                                                 .man_clicked = 0
587                                                         endif
589                                                         .tmp$ = replace_regex$(.characterText$, "\s", "_", 0)
590                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
591                                                         if '.tmp$'$ <> .characterText$ 
592                                                                 .manCharacter$ = '.tmp$'$
593                                                         else
594                                                                 .manCharacter$ = ""
595                                                         endif
596                                                         
597                                                         .tmp$ = replace_regex$(.translationText$, "\s", "_", 0)
598                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
599                                                         if '.tmp$'$ <> .translationText$ 
600                                                                 .manTranslation$ = '.tmp$'$
601                                                         else
602                                                                 .manTranslation$ = ""
603                                                         endif
604                                                         
605                                                         .tmp$ = replace_regex$(.exampleText$, "\s", "_", 0)
606                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
607                                                         if '.tmp$'$ <> .characterText$ and '.tmp$'$ <> ""
608                                                                 .manSound$ = '.tmp$'$
609                                                         endif
610                                                         
611                                                         .tmp$ = replace_regex$(.manualText$, "\s", "_", 0)
612                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
613                                                         .manLesson$ = '.tmp$'$
614                                                         
615                                                         if .man_clicked = 2
616                                                                 .manSound$ = chooseReadFile$(.exampleText$);
617                                                         elsif .man_clicked = 3
618                                                                 # Clean up input string
619                                                                 .manPinyin$ = replace_regex$(.manPinyin$, "^[^a-z]+", "", 0)
620                                                                 .manPinyin$ = replace_regex$(.manPinyin$, "[^\w']", "", 0)
621                                                                 
622                                                                 select sgc.currentWordlist
623                                                                 Append row
624                                                                 .numRows = Get number of rows
625                                                                 if .manPinyin$ <> ""
626                                                                         Set string value: .numRows, "Pinyin", .manPinyin$
627                                                                         Set string value: .numRows, "Character", .manCharacter$
628                                                                         Set string value: .numRows, "Translation", .manTranslation$
629                                                                         Set string value: .numRows, "Sound", .manSound$
630                                                                         Set string value: .numRows, "Lesson", .manLesson$
631                                                                         Set string value: .numRows, "Show", "+"
632                                                                 endif
633                                                                 .manualText$ = .manualEntryText$
634                                                                 .manPinyin$ = .pinyinText$
635                                                                 .manCharacter$ = .characterText$
636                                                                 .manTranslation$ = .translationText$
637                                                                 .manSound$ = .currentFilePath$
638                                                                 .manLesson$ = .manualText$                                                      
639                                                         endif
640                                                 endif
641                                         endwhile                                        
642                                 else
643                                         # Existing lessons
644                                         select sgc.allWordLists
645                                         .wordlistNum = Search column: "Name", .tmp$
646                                         if .wordlistNum > 0
647                                                 .wordlistPath$ = Get value: .wordlistNum, "Directory"
648                                                 .wordlistPath$ = replace_regex$(.wordlistPath$, "[ ]", "&", 0)
649                                                 call read_wordlist "'.tmp$'" '.wordlistPath$'
650                                                 .newList = read_wordlist.wordlistID
651                                                 call merge_into_wordlist '.newList' '.tmp$'
652                                                 select .newList
653                                                 Remove
654                                                 # Add wordlistname to Lesson column
655                                                 select sgc.allWordLists
656                                                 .numRows = Get number of rows
657                                                 if .numRows > 1
658                                                         Remove row: .wordlistNum
659                                                 else
660                                                         Set string value: 1, "Name", "---"
661                                                 endif
662                                         endif
663                                 endif
664                                 # Gather Lesson names
665                                 select sgc.currentWordlist
666                                 Sort rows... Lesson Pinyin
667                                 if .lessonCol > 0
668                                         sgc.numberOfWords = Get number of rows
669                                         .lessonList$ = tab$
670                                         .numLessons = 0
671                                         .lessonName$ = ""
672                                         for .i to sgc.numberOfWords
673                                                 .currentLesson$ = Get value: .i, "Lesson"
674                                                 .matchLesson$ = tab$+.currentLesson$+tab$
675                                                 if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
676                                                         .lessonList$ = .lessonList$ + .currentLesson$ + tab$
677                                                         .numLessons += 1
678                                                         .lessonName$['.numLessons'] = .currentLesson$
679                                                 endif
680                                                 .shown$ = Get value: .i, "Show"
681                                                 if .shown$ = "-"
682                                                         .allShown = 0
683                                                 endif
684                                         endfor
685                                 endif
686                         else                    
687                                 for .i from 0 to .max
688                                         .tmp$ = replace_regex$(.showVariable$['.i'], "^(.*)$", "\l\1", 0)
689                                         .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
690                                         
691                                         .showValue['.i'] = '.tmp$'
692                                         .showWord$['.i'] = "-"
693                                         if .showValue['.i'] <> 0
694                                                 .showWord$['.i'] = "+"
695                                         endif
696                                         Set string value: .currentWord+.i, "Show", .showWord$['.i']
697                                 endfor
698                         endif
699                         
700                         select sgc.currentWordlist
701                         .tmp$ = replace_regex$(.selectMenu$, "^(.)", "\l\1", 0)
702                         .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
703                         .toneSelected = '.tmp$' - 2
704                         if .toneSelected >= 0 and .toneSelected < 5
705                                 select sgc.currentWordlist
706                                 for .i to sgc.numberOfWords
707                                         .currentPinyin$ = Get value: .i, "Pinyin"
708                                         if index_regex(.currentPinyin$, "[0-9]") <= 0
709                                                 call pinyin2numbers '.currentPinyin$'
710                                                 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
711                                                 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
712                                         endif
713                                         .tmp$ = Get value: .i, "Show"
714                                         if .tmp$ <> "-" and index(.currentPinyin$, "'.toneSelected'") > 0
715                                                 Set string value: .i, "Show", "+"
716                                         else
717                                                 Set string value: .i, "Show", "-"
718                                                 .allShown = 0
719                                         endif
720                                 endfor
721                         elsif .toneSelected > 5
722                                 # .toneSelected = 5 is the Part text
723                                 .lessonSelected = .toneSelected - 5
724                                 if .lessonSelected > 0
725                                         .allShown = 1
726                                         .firstShown = -1
727                                         select sgc.currentWordlist
728                                         for .i to sgc.numberOfWords
729                                                 # Keep track of whether all are shown
730                                                 .shown$ = Get value: .i, "Show"
731                                                 if .shown$ = "-"
732                                                         .allShown = 0
733                                                 endif
734                                         endfor
736                                         for .i to sgc.numberOfWords
737                                                 # Lessons
738                                                 .currentLesson$ = Get value: .i, "Lesson"
739                                                 if .currentLesson$ = .lessonName$['.lessonSelected']
740                                                         Set string value: .i, "Show", "+"
741                                                 elsif .allShown = 1
742                                                         Set string value: .i, "Show", "-"
743                                                 endif
744                                         endfor
745                                         for .i to sgc.numberOfWords
746                                                 # Keep track of whether all are shown
747                                                 .shown$ = Get value: .i, "Show"
748                                                 if .firstShown <=0 and .shown$ <> "-"
749                                                         .firstShown = .i
750                                                 endif
751                                         endfor
752                                 endif
753                         endif
754                         
755                         if clicked = 4
756                                 if .currentWord <= 0
757                                         .currentWord = (sgc.numberOfWords div .numWordsPerScreen) * .numWordsPerScreen + 1
758                                 endif
759                         elsif clicked = 5
760                                 if .firstShown > 0
761                                         .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
762                                 endif
763                                 .currentWord += .numWordsPerScreen
764                                 if .currentWord > sgc.numberOfWords
765                                         .currentWord = 1
766                                 endif
767                         endif
768                 endif
769                 # Reset and go to the first selected word (can shuffle list)
770                 if clicked = 6
771                         sgc.currentWord = -1
772                         call next_word
773                         call init_window
774                 endif
775         endwhile
776         
777     # Implement Cancel
778     if clicked = 1
779                 select sgc.currentWordlist
780                 Remove
781                 select .tmpOriginalWordlist
782                 Copy: wordlist$
783                 sgc.currentWordlist = selected()
784         else
785                 # Set the values of the number of words shown   
786                 select sgc.currentWordlist
787                 .numWords = Get number of rows
788                 sgc.currentWordNum = 1
789                 sgc.numberOfDisplayedWords = 0
790                 sgc.currentWord = 0
791                 for .i to .numWords
792                         .show$ = Get value: .i, "Show"
793                         if .show$ = "+"
794                                 if sgc.currentWord < 1
795                                         sgc.currentWord = .i
796                                 endif
797                                 sgc.numberOfDisplayedWords += 1
798                         endif
799                 endfor
800         endif
801         select .tmpOriginalWordlist
802         Remove
804         label SELECTWORDSFAIL
805         
806     call Draw_button '.table$' '.label$' 0
807 endproc
809 ###############################################################
811 # Obligatory button Processing Routines
813 # These MUST be defined
815 ###############################################################
817 procedure processMainPageQuit .clickX .clickY .pressed$
818         call end_program
819 endproc
821 procedure processMainPageRefresh .clickX .clickY .pressed$
822         call clean_up_sound
823         call init_window
824 endproc
826 procedure processMainPageConfig .clickX .clickY .pressed$
827         call config_page
828 endproc
830 procedure processMainPageHelp .clickX .clickY .pressed$
831         call help_loop 'buttons$' init_window
832 endproc
834 procedure processMainPagePlay .clickX .clickY .pressed$
835         .table$ = "MainPage"
836         .label$ = "Play"
837         if recordedSound$ <> ""
838                 call play_sound 'sgc.recordedSound'
839                 mainPage.play = 0
840         endif
841         te.buttonPressValue = mainPage.play
842 endproc
844 procedure Set_Play_Button
845         mainPage.play = -1
846         if recordedSound$ <> ""
847                 mainPage.play = 0
848     endif       
849         call Draw_button MainPage Play 'mainPage.play'
850 endproc
852 procedure processMainPageRecord .clickX .clickY .pressed$
853         call count_syllables
854         .recordingTime = recordingTime
855         if count_syllables.number > 2
856                 .recordingTime = recordingTime + 1.0*ceiling((count_syllables.number - 2)/2)
857         endif
858     call record_sound '.recordingTime'
859     call recognizeTone
860         mainPage.play = 0
861         call Set_Play_Button
863     # Wipe screen
864     call wipeArea 'wipeContourArea$'
865    
866     call draw_tone_contour
867     # Write text (again)
868     call display_word_list_name
869     call display_text Black
870         call add_feedback_to_toneevaluation Feedback
871     call write_feedback Feedback
872         select Table Feedback
873         Remove
874         
875         # Do not exercise words that are going well (autoSelect)
876     if add_feedback_to_toneevaluation.result > 0
877                 if config.adaptiveLists > 0 and sgc.failedAttempts < 2
878                         # Deselect current word
879                         select sgc.currentWordlist
880                         .i = Search column: "Pinyin", sgc.pinyin$
881                         if .i > 0
882                                 Set string value: .i, "Show", "-"
883                         endif
884                 endif
885                 sgc.failedAttempts = 0
886     else
887                 sgc.failedAttempts += 1
888     endif
889 endproc
892 ###############################################################
894 # Miscelaneous supporting code
896 ###############################################################
898 # The example
899 procedure generate_example
900         select sgc.currentWordlist
901         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
902                 select sgc.currentWordlist
903                 .sound$ = Get value... 'sgc.currentWord' Sound
904                 call readPinyin 'sgc.currentWord'
905                 sgc.pinyin$ = readPinyin.pinyin$
906                 sgc.character$ = readPinyin.character$
907                 if .sound$ = "-" or .sound$ = ""
908                         .sound$ = sgc.pinyin$+".wav"
909                 endif
910                 if index_regex(.sound$, "^(/|~/|[A-Z]:\\)") > 0
911                         .soundFilePath$ = .sound$
912                 else
913                         .soundFilePath$ = localWordlistDir$+"/"+wordlistName$+"/"+.sound$
914                         .wordlistDirectory$ = ""
915                         if localWordlistDir$ <> "" and fileReadable("'localWordlistDir$'/'wordlistName$'")
916                                 .wordlistDirectory$ = "'localWordlistDir$'/'wordlistName$'"
917                         elsif sgc2wordlists$ <> "" and fileReadable("'sgc2wordlists$'/'wordlistName$'")
918                                 .wordlistDirectory$ = "'sgc2wordlists$'/'wordlistName$'"
919                         elsif globalwordlists$ <> "" and fileReadable("'globalwordlists$'/'wordlistName$'")
920                                 .wordlistDirectory$ = "'globalwordlists$'/'wordlistName$'"
921                         endif
922                         if .wordlistDirectory$ <> ""
923                                 .audioExampleList = Create Strings as file list... AudioList '.wordlistDirectory$'/'sgc.pinyin$'.*
924                                 .number_of_examples = Get number of strings
925                                 if .number_of_examples > 0
926                                         Randomize
927                                         .sound$ = Get string... 1
928                                         .soundFilePath$ = "'.wordlistDirectory$'/'.sound$'"
929                                 endif
930                                 Remove
931                         endif
932                 endif
933                 if fileReadable(.soundFilePath$) and config.useSoundExample
934                         .tmp = -1
935                         .tmp = nocheck Read from file... '.soundFilePath$'
936                         if .tmp != undefined and .tmp > 0
937                                 call play_sound '.tmp'
938                                 select .tmp
939                                 Remove
940                         endif
941                 elsif config.synthesis$ <> "" and config.synthesis$ <> "_DISABLED_"
942                         call synthesize_sound "'sgc.pinyin$'" "'sgc.character$'"
943                 else
944                         call humToneContour 'sgc.pinyin$' 'config.register'
945                         call reset_viewport
946                 endif
947         endif
948         demoShow()
949 endproc
951 # Draw a tone contour
952 procedure draw_tone_contour
953         select sgc.currentWordlist
954         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
955                 .sound$ = Get value... 'sgc.currentWord' Sound
956                 call readPinyin 'sgc.currentWord'
957                 sgc.pinyin$ = readPinyin.pinyin$
958                 sgc.character$ = readPinyin.character$
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                 sgc.character$ = readPinyin.character$
981                 call align_recordedSound 'sgc.pinyin$'
982         call sgc_ToneProt 'recordedSound$' 'sgc.pinyin$' 'config.register' '.strict' 'config.language$'
983         # sgc_ToneProt manipulates the sound given. Reconnect
984         select Sound 'recordedSound$'
985         sgc.recordedSound = selected("Sound")
986                 call reset_viewport
987         endif
988 endproc
990 procedure write_feedback .table$
991     select Table '.table$'
992     .line1$ = Get value... 1 Text
993     .line2$ = Get value... 2 Text
994     .label$ = Get value... 3 Text
996         # convert numbers to Pinyin if needed
997         if not config.displayNumbers
998                 call numbers2pinyin '.line1$'
999                 .line1$ = numbers2pinyin.pinyin$
1000         endif
1002     .color$ = "Red"
1003     if index(.line1$, "???") > 0
1004         .color$ = "Black"
1005     elsif .label$ = "Correct"
1006         .color$ = "Green"
1007         elsif config.strict$ = "'sgc.highestLevel'"
1008                 .line2$ = .line2$ + " *"
1009     endif
1011         .currentFeedbackFontSize = 14
1012         .maxHeight = 21 - 17
1013         call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
1014         .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
1015         
1016         call wipeArea 'wipeFeedbackArea$'
1017     call set_font_size '.currentFeedbackFontSize'
1018     demo '.color$'
1019     demo Text... 50 Centre 21 Bottom '.line1$'
1020     demo Text... 50 Centre 17 Bottom '.line2$'
1021         demoShow()
1022         demo 'defaultFont$'
1023     call set_font_size 'defaultFontSize'
1024 endproc
1026 # Text display
1027 procedure display_text .color$
1028         select sgc.currentWordlist
1029         if sgc.currentWord < 0 or sgc.currentWord > sgc.numberOfWords+1
1030                 call clean_up_sound
1031         if config.shuffleLists
1032                     Randomize rows
1033         endif
1034                 if sgc.currentWord < 0
1035                         sgc.currentWord = sgc.numberOfWords
1036                 else
1037                         sgc.currentWord = 1
1038                 endif
1039         endif
1040         
1041         .changeCJKstyle = 0
1042         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
1043                 .displayText$ = ""
1044                 call readDisplayPinyin 'sgc.currentWord'
1045                 .displayPinyin$ = readDisplayPinyin.pinyin$
1046                 .displayChar$ = Get value... 'sgc.currentWord' Character
1047                 .displayTrans$ = Get value... 'sgc.currentWord' Translation
1048                 if .displayPinyin$ <> "-" and (config.displayPinyin or sgc.writeAll)
1049                         if not config.displayNumbers
1050                                 call numbers2pinyin '.displayPinyin$'
1051                                 .displayPinyin$ = numbers2pinyin.pinyin$
1052                         endif
1053                         # Insert u umlaut
1054                         .displayPinyin$ = replace_regex$(.displayPinyin$, "v", "\\u\X22", 0)
1055                         .displayText$ = .displayText$ + .displayPinyin$
1056                 endif
1057                 if .displayChar$ <> "-" and (config.displayChar or sgc.writeAll)
1058                         .displayText$ = .displayText$ + "  "+ .displayChar$
1059                         .changeCJKstyle = 1
1060                 endif
1061                 if .displayTrans$ <> "-" and (config.displayTrans or sgc.writeAll)
1062                         .displayText$ = .displayText$ + "  \s{%%"+ .displayTrans$ + "%}"
1063                 endif
1064         elsif sgc.currentWord = 0 or sgc.currentWord = sgc.numberOfWords+1
1065                 call clean_up_sound
1066                 .displayText$ = "---"
1067         endif
1069         # Adapt font size
1070         call adjustFontSizeOnHeight 'defaultFont$' 24 15
1071         .currentFontSize = adjustFontSizeOnHeight.newFontSize
1072         call adjustFontSizeOnWidth 'defaultFont$' '.currentFontSize' 95 '.displayText$'
1073         .currentFontSize = adjustFontSizeOnWidth.newFontSize
1075         # Clear the writing area
1076         call wipeArea 'wipePinyinArea$'
1077         # Switch back to Chinese style CJK when in Japanese language mode
1078         if .changeCJKstyle and config.language$ = "JA"
1079                 CJK font style preferences: "Chinese"
1080         endif
1081         # Actually display text
1082         demo '.color$'
1083         call set_font_size '.currentFontSize'
1084         demo Text... 50 Centre 26 Bottom '.displayText$'
1085         demoShow()
1086         demo Black
1087         demo 'defaultFont$'
1088         call set_font_size 'defaultFontSize'
1089         if .changeCJKstyle and config.language$ = "JA"
1090                 if config.language$ = "JA"
1091                         CJK font style preferences: "Japanese"
1092                 elsif config.language$ = "ZH"
1093                         CJK font style preferences: "Chinese"
1094                 endif
1095         endif
1096         # Switch back to Japanese style CJK when in Japanese language mode
1097         if .changeCJKstyle and config.language$ = "JA"
1098                 CJK font style preferences: "Japanese"
1099         endif
1100 endproc
1102 procedure numbers2pinyin .numberstext$
1103         .intermediatePinyin$ = .numberstext$
1104         # Add a `-quote between vowels
1105         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])([aeuiov])", "\1\2'\3", 0)
1106         # Move numbers to the nucleus vowel
1107         # To the vowel
1108         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([^aeuiov0-9]*)([0-9])", "\1\3\2", 0)
1109         # Either a/e
1110         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([ae])([aeuiov]*)([0-9])", "\1\3\2", 0)
1111         # Or the Oo in /ou/
1112         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(ou)([0-9])", "o\2u", 0)
1113         # or the second vowel
1114         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([uiov][aeuiov])([uiov])([0-9])", "\1\3\2", 0)
1115         
1116         # Convert all tones to special characters
1117         # Tone 1
1118         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a1", "ā", 0)
1119         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e1", "ē", 0)
1120         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u1", "ū", 0)
1121         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i1", "ī", 0)
1122         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o1", "ō", 0)
1123         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v1", "ǖ", 0)
1124         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "1", "\\-^", 0)
1125         
1126         # Tone 2
1127         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v2", "ǘ", 0)
1128         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])2", "\\\1'", 0)
1129         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "2", "\\'^", 0)
1130         
1131         # Tone 3
1132         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a3", "ǎ", 0)
1133         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e3", "ě", 0)
1134         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u3", "ǔ", 0)
1135         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i3", "ǐ", 0)
1136         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o3", "ǒ", 0)
1137         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v3", "ǚ", 0)
1138         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "3", "\\N^", 0)
1140         # Tone 4
1141         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v4", "ǜ", 0)
1142         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])4", "\\\1`", 0)
1143         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "4", "\\`^", 0)
1144         
1145         # Tone 0
1146         # Remove tone 0 symbol completely
1147         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "", 0)
1148         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a0", "å", 0)
1149         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e0", "e̊", 0)
1150         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u0", "ů", 0)
1151         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i0", "i̊", 0)
1152         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o0", "o̊", 0)
1153         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v0", "ü̊", 0)
1154         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "\\0^", 0)
1155         
1156         # Pick best vowel symbols available in cases not caught before
1157         # Ugly clutch to get the 1, 3, 0 tone diacritics at least in the neighbourhood
1158         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i(\\[-N0]\^)", "i\\s{_ }\1", 0)
1159         # Insert u umlaut
1160         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v", "\\u\X22", 0)
1162         .pinyin$ = .intermediatePinyin$
1163 endproc
1165 # NEEDS WORK AND TESTING!!
1166 # Convert unicode Pinyin into tone numbers
1167 procedure pinyin2numbers .pinyin$
1168         .intermediatePinyin$ = .pinyin$
1169         # Convert all special characters to numbers
1170         # Tone 1
1171         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iā)([iaeouü]*)", "a\11", 0)
1172         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iē)([iaeouü]*)", "e\11", 0)
1173         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iū)([iaeouü]*)", "u\11", 0)
1174         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iī)([iaeouü]*)", "i\11", 0)
1175         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iō)([iaeouü]*)", "o\11", 0)
1176         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǖ)([iaeouü]*)", "v\11", 0)
1177         
1178         # Tone 2
1179         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iá)([iaeouü]*)", "a\12", 0)
1180         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ié)([iaeouü]*)", "e\12", 0)
1181         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iú)([iaeouü]*)", "u\12", 0)
1182         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ií)([iaeouü]*)", "i\12", 0)
1183         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ió)([iaeouü]*)", "o\12", 0)
1184         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǘ)([iaeouü]*)", "v\12", 0)
1185         
1186         # Tone 3
1187         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǎ)([iaeouü]*)", "a\13", 0)
1188         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iě)([iaeouü]*)", "e\13", 0)
1189         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǔ)([iaeouü]*)", "u\13", 0)
1190         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǐ)([iaeouü]*)", "i\13", 0)
1191         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǒ)([iaeouü]*)", "o\13", 0)
1192         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǚ)([iaeouü]*)", "v\13", 0)
1194         # Tone 4
1195         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ià)([iaeouü]*)", "a\14", 0)
1196         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iè)([iaeouü]*)", "e\14", 0)
1197         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iù)([iaeouü]*)", "u\14", 0)
1198         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iì)([iaeouü]*)", "i\14", 0)
1199         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iò)([iaeouü]*)", "o\14", 0)
1200         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǜ)([iaeouü]*)", "v\14", 0)
1201         
1202         # Tone 0
1203         # Add tone 0
1204         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iå)([iaeouü]*)", "a\10", 0)
1205         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e̊([iaeouü]*)", "e\10", 0)
1206         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iů)([iaeouü]*)", "u\10", 0)
1207         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i̊([iaeouü]*)", "i\10", 0)
1208         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o̊([iaeouü]*)", "o\10", 0)
1209         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ü̊([iaeouü]*)", "v\10", 0)
1211         # Syllables without a tone symbol are tone 0
1212         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov]+)([^0-9aeuiov]|\W|$)", "\10\2", 0)
1214         # Move numbers to the end of the syllable.
1215         # Syllables ending in n and start with g. Note that a syllable cannot start with an u or i
1216         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(n)(g[aeuiov])", "\1\3\2\4", 0)
1217         # Syllables ending in (ng?) followed by something that is not a valid vowel 
1218         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(ng?)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1219         # Syllables ending in r
1220         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(r)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1221         # Remove quotes etc
1222         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "[\\'\\`]", "", 0)
1223         
1224         .numberstext$ = .intermediatePinyin$
1225 endproc
1227 procedure readDisplayPinyin .currentWord
1228         select sgc.currentWordlist
1229         .pinyin$ = Get value... '.currentWord' Pinyin
1230         .character$ = Get value... '.currentWord' Character
1231         # Everything to lowercase
1233         if index_regex(.pinyin$, "[0-9]") <= 0
1234                 call pinyin2numbers '.pinyin$'
1235                 .pinyin$ = pinyin2numbers.numberstext$
1236         endif 
1237 endproc
1239 procedure readPinyin .currentWord
1240         call readDisplayPinyin '.currentWord'
1241         .character$ = readDisplayPinyin.character$
1242         .pinyin$ = replace_regex$(readDisplayPinyin.pinyin$, ".+", "\L&", 0)
1243         .pinyin$ = replace_regex$(.pinyin$, "[\\'\\` ]", "", 0)
1244         # Remove anything that is objectionable
1245         .pinyin$ = replace_regex$(.pinyin$, "[^\w']", "", 0)
1246 endproc
1248 # Includes
1249 include ToneProt/SGC_ToneProt.praat
1250 include ToneProt/DrawToneContour.praat
1251 include ToneProt/HumToneContour.praat
1252 include ToneProt/ToneRecognition.praat
1253 include ToneProt/ToneScript.praat
1254 include ToneProt/ToneRules.praat