actions.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /* Copyright (C) 2005-2010 Valeriy Argunov (nporep AT mail DOT ru) */
  2. /*
  3. * This library is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU Lesser General Public License as published by
  5. * the Free Software Foundation; either version 2.1 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public License
  14. * along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. */
  17. #include "actions.h"
  18. #include "errors.h"
  19. #include "game.h"
  20. #include "locations.h"
  21. #include "statements.h"
  22. #include "text.h"
  23. QSPCurAct qspCurActions[QSP_MAXACTIONS];
  24. int qspCurActionsCount = 0;
  25. int qspCurSelAction = -1;
  26. QSP_BOOL qspIsActionsChanged = QSP_FALSE;
  27. QSP_BOOL qspCurIsShowActs = QSP_TRUE;
  28. static int qspActIndex(QSP_CHAR *);
  29. void qspClearActions(QSP_BOOL isFirst)
  30. {
  31. int i;
  32. if (!isFirst && qspCurActionsCount)
  33. {
  34. for (i = 0; i < qspCurActionsCount; ++i)
  35. {
  36. if (qspCurActions[i].Image) free(qspCurActions[i].Image);
  37. free(qspCurActions[i].Desc);
  38. qspFreePrepLines(qspCurActions[i].OnPressLines, qspCurActions[i].OnPressLinesCount);
  39. }
  40. qspIsActionsChanged = QSP_TRUE;
  41. }
  42. qspCurActionsCount = 0;
  43. qspCurSelAction = -1;
  44. }
  45. static int qspActIndex(QSP_CHAR *name)
  46. {
  47. int i, actNameLen, bufSize;
  48. QSP_CHAR *uName, *buf;
  49. if (!qspCurActionsCount) return -1;
  50. qspUpperStr(uName = qspGetNewText(name, -1));
  51. bufSize = 64;
  52. buf = (QSP_CHAR *)malloc(bufSize * sizeof(QSP_CHAR));
  53. for (i = 0; i < qspCurActionsCount; ++i)
  54. {
  55. actNameLen = qspStrLen(qspCurActions[i].Desc);
  56. if (actNameLen >= bufSize)
  57. {
  58. bufSize = actNameLen + 16;
  59. buf = (QSP_CHAR *)realloc(buf, bufSize * sizeof(QSP_CHAR));
  60. }
  61. qspStrCopy(buf, qspCurActions[i].Desc);
  62. qspUpperStr(buf);
  63. if (!qspStrsComp(buf, uName))
  64. {
  65. free(uName);
  66. free(buf);
  67. return i;
  68. }
  69. }
  70. free(uName);
  71. free(buf);
  72. return -1;
  73. }
  74. void qspAddAction(QSPVariant *args, int count, QSPLineOfCode *code, int start, int end, QSP_BOOL isManageLines)
  75. {
  76. QSPCurAct *act;
  77. QSP_CHAR *imgPath;
  78. if (qspActIndex(QSP_STR(args[0])) >= 0) return;
  79. if (qspCurActionsCount == QSP_MAXACTIONS)
  80. {
  81. qspSetError(QSP_ERR_CANTADDACTION);
  82. return;
  83. }
  84. if (count == 2 && qspIsAnyString(QSP_STR(args[1])))
  85. imgPath = qspGetPathAsIs(QSP_STR(args[1]));
  86. else
  87. imgPath = 0;
  88. act = qspCurActions + qspCurActionsCount++;
  89. act->Image = imgPath;
  90. act->Desc = qspGetNewText(QSP_STR(args[0]), -1);
  91. qspCopyPrepLines(&act->OnPressLines, code, start, end);
  92. act->OnPressLinesCount = end - start;
  93. act->Location = qspRealCurLoc;
  94. act->ActIndex = qspRealActIndex;
  95. act->StartLine = qspRealLine;
  96. act->IsManageLines = isManageLines;
  97. qspIsActionsChanged = QSP_TRUE;
  98. }
  99. void qspExecAction(int ind)
  100. {
  101. QSPCurAct *act;
  102. QSPLineOfCode *code;
  103. int count, oldLoc, oldActIndex, oldLine;
  104. oldLoc = qspRealCurLoc;
  105. oldActIndex = qspRealActIndex;
  106. oldLine = qspRealLine;
  107. act = qspCurActions + ind;
  108. qspRealCurLoc = act->Location;
  109. qspRealActIndex = act->ActIndex;
  110. count = act->OnPressLinesCount;
  111. qspCopyPrepLines(&code, act->OnPressLines, 0, count);
  112. if (act->IsManageLines)
  113. qspExecTopCodeWithLocals(code, count, act->StartLine + 1, QSP_FALSE);
  114. else
  115. {
  116. qspRealLine = act->StartLine;
  117. qspExecTopCodeWithLocals(code, count, 0, QSP_FALSE);
  118. }
  119. qspFreePrepLines(code, count);
  120. qspRealLine = oldLine;
  121. qspRealActIndex = oldActIndex;
  122. qspRealCurLoc = oldLoc;
  123. }
  124. QSP_CHAR *qspGetAllActionsAsCode()
  125. {
  126. int len = 0, count, i;
  127. QSP_CHAR *res, *temp;
  128. res = qspGetNewText(QSP_FMT(""), 0);
  129. for (i = 0; i < qspCurActionsCount; ++i)
  130. {
  131. len = qspAddText(&res, QSP_FMT("ACT '"), len, 5, QSP_FALSE);
  132. temp = qspReplaceText(qspCurActions[i].Desc, QSP_FMT("'"), QSP_FMT("''"));
  133. len = qspAddText(&res, temp, len, -1, QSP_FALSE);
  134. free(temp);
  135. if (qspCurActions[i].Image)
  136. {
  137. len = qspAddText(&res, QSP_FMT("','"), len, 3, QSP_FALSE);
  138. temp = qspReplaceText(qspCurActions[i].Image + qspQstPathLen, QSP_FMT("'"), QSP_FMT("''"));
  139. len = qspAddText(&res, temp, len, -1, QSP_FALSE);
  140. free(temp);
  141. }
  142. len = qspAddText(&res, QSP_FMT("':"), len, 2, QSP_FALSE);
  143. count = qspCurActions[i].OnPressLinesCount;
  144. if (count == 1 && qspIsAnyString(qspCurActions[i].OnPressLines->Str))
  145. len = qspAddText(&res, qspCurActions[i].OnPressLines->Str, len, -1, QSP_FALSE);
  146. else
  147. {
  148. if (count >= 2)
  149. {
  150. len = qspAddText(&res, QSP_STRSDELIM, len, QSP_LEN(QSP_STRSDELIM), QSP_FALSE);
  151. temp = qspJoinPrepLines(qspCurActions[i].OnPressLines, count, QSP_STRSDELIM);
  152. len = qspAddText(&res, temp, len, -1, QSP_FALSE);
  153. free(temp);
  154. }
  155. len = qspAddText(&res, QSP_STRSDELIM QSP_FMT("END"), len, QSP_LEN(QSP_STRSDELIM) + 3, QSP_FALSE);
  156. }
  157. len = qspAddText(&res, QSP_STRSDELIM, len, QSP_LEN(QSP_STRSDELIM), QSP_FALSE);
  158. }
  159. return res;
  160. }
  161. void qspStatementSinglelineAddAct(QSPLineOfCode *s, int statPos, int endPos)
  162. {
  163. QSPVariant args[2];
  164. QSPLineOfCode code;
  165. int i, oldRefreshCount, count, offset;
  166. QSP_CHAR ch, *pos = s->Str + s->Stats[statPos].EndPos;
  167. if (*pos != QSP_COLONDELIM[0])
  168. {
  169. qspSetError(QSP_ERR_COLONNOTFOUND);
  170. return;
  171. }
  172. if (statPos == endPos - 1)
  173. {
  174. qspSetError(QSP_ERR_CODENOTFOUND);
  175. return;
  176. }
  177. oldRefreshCount = qspRefreshCount;
  178. *pos = 0;
  179. count = qspGetStatArgs(s->Str + s->Stats[statPos].ParamPos, qspStatAct, args);
  180. *pos = QSP_COLONDELIM[0];
  181. if (qspRefreshCount != oldRefreshCount || qspErrorNum) return;
  182. ++statPos;
  183. code.Str = pos + 1;
  184. code.Label = qspGetLineLabel(code.Str);
  185. code.LineNum = 0;
  186. code.IsMultiline = QSP_FALSE;
  187. pos = s->Str + s->Stats[endPos - 1].EndPos;
  188. if (*pos == QSP_COLONDELIM[0]) ++pos;
  189. ch = *pos;
  190. *pos = 0;
  191. code.StatsCount = endPos - statPos;
  192. code.Stats = (QSPCachedStat *)malloc(code.StatsCount * sizeof(QSPCachedStat));
  193. offset = (int)(code.Str - s->Str);
  194. for (i = 0; i < code.StatsCount; ++i)
  195. {
  196. code.Stats[i].Stat = s->Stats[statPos].Stat;
  197. code.Stats[i].EndPos = s->Stats[statPos].EndPos - offset;
  198. code.Stats[i].ParamPos = s->Stats[statPos].ParamPos - offset;
  199. ++statPos;
  200. }
  201. qspAddAction(args, count, &code, 0, 1, QSP_FALSE);
  202. *pos = ch;
  203. qspFreeVariants(args, count);
  204. free(code.Stats);
  205. if (code.Label) free(code.Label);
  206. }
  207. void qspStatementMultilineAddAct(QSPLineOfCode *s, int endLine, int lineInd, QSP_BOOL isManageLines)
  208. {
  209. QSPVariant args[2];
  210. int count, oldRefreshCount;
  211. QSP_CHAR *pos;
  212. QSPLineOfCode *line = s + lineInd;
  213. pos = line->Str + line->Stats->EndPos;
  214. oldRefreshCount = qspRefreshCount;
  215. *pos = 0;
  216. count = qspGetStatArgs(line->Str + line->Stats->ParamPos, qspStatAct, args);
  217. *pos = QSP_COLONDELIM[0];
  218. if (qspRefreshCount != oldRefreshCount || qspErrorNum) return;
  219. qspAddAction(args, count, s, lineInd + 1, endLine, isManageLines);
  220. qspFreeVariants(args, count);
  221. }
  222. QSP_BOOL qspStatementDelAct(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  223. {
  224. int actInd = qspActIndex(QSP_STR(args[0]));
  225. if (actInd < 0) return QSP_FALSE;
  226. if (qspCurSelAction >= actInd) qspCurSelAction = -1;
  227. if (qspCurActions[actInd].Image) free(qspCurActions[actInd].Image);
  228. free(qspCurActions[actInd].Desc);
  229. qspFreePrepLines(qspCurActions[actInd].OnPressLines, qspCurActions[actInd].OnPressLinesCount);
  230. --qspCurActionsCount;
  231. while (actInd < qspCurActionsCount)
  232. {
  233. qspCurActions[actInd] = qspCurActions[actInd + 1];
  234. ++actInd;
  235. }
  236. qspIsActionsChanged = QSP_TRUE;
  237. return QSP_FALSE;
  238. }