static boolean mefindusedblocksvisit (hdlheadrecord hnode, ptrvoid refcon) { /* if there's a script attached to hnode, note the database usage. */ ptrstring bsparent = (ptrstring) refcon; tymenuiteminfo item; bigstring bspath; if (megetmenuiteminfo (hnode, &item)) { /*something linked*/ opgetheadstring (hnode, bspath); pushchar (']', bspath); insertstring (BIGSTRING ("\x02" " ["), bspath); insertstring (bsparent, bspath); return (statsblockinuse (item.linkedscript.adrlink, bspath)); } return (true); /*keep visiting*/ } /*mefindusedblocksvisit*/
void TSC_source::cmd_paste() { QString str; StrChar ch; if (!pasteclipboard(str)) return; if (G_issel()) cmd_cutselblock(); undo_begin(); QString istr; for (int i=0; i<str.G_length(); i++) { ch=str[i]; if ((ch!=10)&&(ch!=13)) istr+=ch; if (ch==10) { if (istr.G_length()>0) { insertstring(istr); istr.clear(); } cmd_insertline(false); } } if (istr.G_length()>0) { insertstring(istr); istr.clear(); } undo_end(); }
/** * @relates texteditor * @brief Insert a newline at the cursor. **/ void texteditInsertNewline(texteditor * editor) { char * nextline; /* Copy everything after the cursor */ nextline = str_duplen(editor->curline->s + editor->pos, editor->linewidth); #if 0 nextline = (char*) malloc(editor->linewidth + 2); for (i = editor->pos, j = 0; i < strlen(editor->curline->s); i++, j++) nextline[j] = editor->curline->s[i]; tmpstr[j] = 0; #endif /* Truncate the current line */ editor->curline->s[editor->pos] = '\x0'; /* Insert nextline */ editor->text->cur = editor->curline; insertstring(editor->text, nextline); /* Advance to the new line */ editor->curline = editor->curline->next; editor->pos = 0; editor->updateflags |= TUD_EDITAREA; }
void TSC_source::cmd_insertline(bool autoindent, bool backup) { if (!G_canmodify()) return; if ((cursor_linenr<0)||(cursor_linenr>=G_linecount())) return; if (autoindent&&backup) undo_begin(); if (backup) addundo(new TSC_source_undoaction_insertline(this)); QString strl=*lines[cursor_linenr]; strl.substring(0,cursor_colnr-1); QString strr=*lines[cursor_linenr]; strr.substring(cursor_colnr,strr.G_length()); *lines[cursor_linenr]=strl; lines.insertbefore(cursor_linenr+1,new QString(strr)); cursor_linenr++;cursor_colnr=0; if (autoindent) { QString indent; for (int i=0; (i<G_line(cursor_linenr-1)->G_length())&&(G_line(cursor_linenr-1)->G_char(i)==' '); i++) indent+=' '; if (indent.G_length()>0) insertstring(indent,backup); } if (autoindent&&backup) undo_end(); modified=true; }
OSStatus pathtofsref ( bigstring bspath, FSRef *ref ) { /* 2009-08-30 aradke: mac-only helper function for converting from a pascal string (path) to an FSRef */ bigstring bs; CFStringRef csref; char str[256]; copystring(bspath, bs); // convert from colon-delimited to slash-delimited path stringswapall(':', '/', bs); insertstring ( BIGSTRING ( "\x09" "/Volumes/" ), bs ); // convert from Mac Roman to UTF-8 */ csref = CFStringCreateWithPascalString(kCFAllocatorDefault, bs, kCFStringEncodingMacRoman); CFStringGetCString(csref, str, sizeof(str), kCFStringEncodingUTF8); CFRelease(csref); // finally, pass our temporary copy of the string to the underlying system function return FSPathMakeRef((UInt8*) str, ref, NULL); } /*pathtofsref*/
static boolean findusedblocksvisit (hdlhashnode hnode, ptrvoid refcon) { /* 5.1.5b16: check fldontsave flag to avoid diving into guest databases, etc. */ ptrstring bsparent = (ptrstring) refcon; tyvaluerecord val = (**hnode).val; bigstring bspath; // if ((**hnode).fldontsave) //never gets saved in the database // return (true); gethashkey (hnode, bspath); if (bsparent != nil) { insertchar ('.', bspath); insertstring (bsparent, bspath); } if (val.valuetype == externalvaluetype) return (langexternalfindusedblocks ((hdlexternalvariable) val.data.externalvalue, bspath)); if (val.fldiskval) return (statsblockinuse (val.data.diskvalue, bspath)); return (true); /*continue traversal*/ } /*findusedblocksvisit*/
boolean aboutsetthreadstring (hdlprocessthread hp, boolean flin) { register hdlcancoonrecord hc = cancoonglobals; hdlthreadglobals hg = (hdlthreadglobals) hp; boolean fl = false; hdlwindowinfo hinfo; if (hc == nil) return (false); if (!aboutstatsshowing ()) return (false); if (!findaboutwindow (&hinfo) || !shellpushglobals ((**hinfo).macwindow)) return (false); if (flin) { numbertostring ((long) (**hg).idthread, bstheadinfo); if ((**hg).hprocess) { pushstring (BIGSTRING ("\x02" " ["), bstheadinfo); pushstring ((**(**hg).hprocess).bsname, bstheadinfo); pushchar (']', bstheadinfo); } } else insertstring (BIGSTRING ("\x06" "(out) "), bstheadinfo); if (aboutdata != nil) ccupdatestatistics (false); shellpopglobals (); return (fl); } /*aboutsetthreadstring*/
static void ccdrawabout (void) { /* 5.0b9 dmb: user Arial, but just for the frontier(tm) item */ Rect rabout = (**aboutdata).aboutarea; bigstring bs; /*draw the icon*/ { #ifdef WIN95VERSION short tmfont; fontgetnumber (BIGSTRING ("\x05" "Arial"), &tmfont); if (tmfont != 0) setglobalfontsizestyle (tmfont, 9, bold); else #endif setglobalfontsizestyle (geneva, 9, bold); rabout.top += max ((aboutrowsNoStats * aboutlineheight - abouticonsize) / 2, 0); rabout.left += abouticonsize; /*2005-01-12 aradke: shorter frontieritem, indent it too*/ movepento (rabout.left, rabout.top + abouticonsize + globalfontinfo.ascent); pendrawstring (aboutstrings [frontieritem]); #ifdef WIN95VERSION if (tmfont != 0) setglobalfontsizestyle (geneva, 9, bold); #endif //rabout.left += abouticonsize; /*2005-01-12 aradke*/ rabout.right = rabout.left + abouticonsize; rabout.bottom = rabout.top + abouticonsize; ccdrawfrontiericon (rabout, false); } ccdrawtextitem (copyright2item, nil, normal, leftjustified); ccdrawtextitem (copyrightitem, nil, normal, leftjustified); ccdrawurlitem (false); #if __powerc // ccdrawtextitem (isaitem, "\pPowerPC", normal); parsedialogstring (aboutstrings [isaitem], BIGSTRING ("\x07" "PowerPC"), nil, nil, nil, bs); #else parsedialogstring (aboutstrings [isaitem], BIGSTRING ("\x05" "680x0"), nil, nil, nil, bs); #endif // ccdrawmainwindowtext (isaitem, normal, bs, leftjustified); // ccdrawtextitem (frontieritem, nil, bold); ccdrawtextitem (sloganitem, nil, italic, leftjustified); filegetprogramversion (bs); #ifdef fltrialsize insertstring (BIGSTRING ("\x06" "Trial "), bs); #endif ccdrawmainwindowtext (versionitem, normal, bs, rightjustified); ccupdatestatistics (false); } /*ccdrawabout*/
static boolean newaboutwindow (boolean flbootsplash) { /* 5.0.2b20 dmb: don't reset window pos for negative values */ WindowPtr w; hdlwindowinfo hw; bigstring bstitle; Rect rzoom, rwindow; hdlaboutrecord hdata; short ixaboutconfig; if (!newclearhandle (sizeof (tyaboutrecord), (Handle *) &hdata)) return (false); shellfindcallbacks (idaboutconfig, &ixaboutconfig); if (flbootsplash) { globalsarray [ixaboutconfig].config.templateresnum = 131;//config.fldialog (**hdata).flbootsplash = true; } else globalsarray [ixaboutconfig].config.templateresnum = 129; //restore // get bigwindow setting with current root // (**hdata).flbigwindow = (cancoonglobals == nil) || (**cancoonglobals).flbigwindow; ccgetwindowrect (ixaboutinfo, &rwindow); // if (rwindow.top <= 0 || rwindow.left <= 0) // rwindow.top = -1; getsystemoriginrect (&rzoom); // getstringlist (aboutlistnumber, abouttitlestring, bstitle); copystring (aboutstrings [frontieritem], bstitle); if (!flbootsplash) insertstring (BIGSTRING ("\x06" "About "), bstitle); /* 2006-02-04 aradke: eliminated titleitem */ if (!newchildwindow (idaboutconfig, nil, &rwindow, &rzoom, bstitle, &w)) { disposehandle ((Handle) hdata); return (false); } #if TARGET_API_MAC_CARBON == 1 SetThemeWindowBackground (w, kThemeBrushModelessDialogBackgroundActive, false); #endif getwindowinfo (w, &hw); (**hw).hdata = (Handle) hdata; shellpushglobals (w); aboutwindowsetup (); aboutresetrects (hw); if (!flbootsplash) { aboutresizeafterfontchange (); aboutsetconfigminimum (); } shellpopglobals (); windowzoom (w); return (true); } /*newaboutwindow*/
int editbox(char *title, stringvector * sv, int editwidth, int flags, displaymethod * d) { int key; /* the key */ int i, j; /* general counters */ int done = 0; /* true when editing/viewing is done */ int updateflags; /* flags to determine what needs update */ stringnode *centerstr; /* str in center of dialog */ stringnode *loopstr; /* node pointer for use in looping */ int selChar = 0; /* vars only relating to editing */ int pos = 0; /* position in sv->cur->s */ char *tmpstr; /* temporary string for pushing */ char strbuf[80] = ""; /* general buffer */ static char savefilename[SAVEFILENAME_LEN] = "temp.zoc"; /* selection variables */ int selectFlag = 0; /* Status of the shift key */ int selPos = -1; /* Position of cursor when selection started; -1 when no selection */ int selLineOffset = 0; /* Offset of line where selection started; positive when below centerstr, negative when above */ /* statics */ static int insertflag = 1; /* nonzero when in insert mode */ static int wrapwidth = 42; /* where to wrap */ /* if there is no string, add one */ if (sv->cur == NULL || sv->first == NULL || sv->last == NULL) pushstring(sv, strcpy((char *) malloc(editwidth + 2), "")); if (sv->cur == NULL) return 0; centerstr = sv->cur; if (editwidth == EDITBOX_NOEDIT) { d->cursorgo(9, 13); /* Look for @title on first line */ if ((flags & EDITBOX_ZOCMODE) && sv->first != NULL && sv->first->s[0] == '@') { /* Display the first line as the title, not in the box itself */ if (sv->first->s[1] != '\x0') title = sv->first->s + 1; /* What's the harm? We're only looking. */ if (centerstr == sv->first) centerstr = centerstr->next; } } /* Check for NULL after advancing past @title, if we did so */ if (centerstr == NULL) return 0; drawscrollbox(d, 0, 0, 1); updateflags = U_ALL; while (!done) { if (editwidth) d->cursorgo(9 + pos, 13); /* If in select mode, center line should be updated no matter what */ if (selPos != -1) updateflags |= U_CENTER; if (updateflags & U_PANEL && editwidth) draweditpanel(insertflag, wrapwidth, flags & EDITBOX_ZOCMODE, d); sv->cur = centerstr; updateditbox(d, sv, updateflags, editwidth, flags, title, selPos == -1); updateflags = U_NONE; /* Draw highlighted text if applicable */ if (selPos != -1) { int startPos = 0, endPos = 0; if (selLineOffset > 0) { startPos = pos; endPos = strlen(centerstr->s); } else if (selLineOffset < 0) { startPos = 0; endPos = pos; } else { if (selPos > pos) { startPos = pos; endPos = selPos; } else { startPos = selPos; endPos = pos; } } for (j = startPos; j < endPos; j++) d->putch(9 + j, 13, centerstr->s[j], ZOC_HIGHLIGHT_COLOUR); if (selLineOffset != 0) { /* Draw meat lines */ if (selLineOffset > 0) { for (i = 1, loopstr = centerstr->next; i < selLineOffset && i < 8 && loopstr != NULL; i++, loopstr = loopstr->next) d->print_discrete(9, 13 + i, ZOC_HIGHLIGHT_COLOUR, loopstr->s); } else { for (i = -1, loopstr = centerstr->prev; i > selLineOffset && i > -8 && loopstr != NULL; i--, loopstr = loopstr->prev) d->print_discrete(9, 13 + i, ZOC_HIGHLIGHT_COLOUR, loopstr->s); } /* Draw farthest line from centerstr */ if (i < 8 && i > -8 && loopstr != NULL) { if (selLineOffset < 0) { startPos = selPos; endPos = strlen(loopstr->s); } else if (selLineOffset > 0) { startPos = 0; endPos = selPos; } for (j = startPos; j < endPos; j++) d->putch_discrete(9 + j, 13 + i, loopstr->s[j], ZOC_HIGHLIGHT_COLOUR); } } /* Update the display */ d->update(3, 4, 51, 19); } /* Get the key */ key = d->getch(); selectFlag = d->shift(); /* If we just started selecting, remember where we started */ if (selectFlag && selPos == -1) selPos = pos; /* Keys which work when editing and browsing */ switch (key) { case DKEY_UP: /* Up Arrow */ if (centerstr->prev != NULL && !(!editwidth && centerstr->prev == sv->first && sv->first->s[0] == '@')) { centerstr = centerstr->prev; if (pos > strlen(centerstr->s)) pos = strlen(centerstr->s); if (selectFlag) selLineOffset++; updateflags = U_EDITAREA; } break; case DKEY_DOWN: /* Down Arrow */ if (centerstr->next != NULL) { centerstr = centerstr->next; if (pos > strlen(centerstr->s)) pos = strlen(centerstr->s); if (selectFlag) selLineOffset--; updateflags = U_EDITAREA; } break; case DKEY_PAGEUP: /* Page Up */ for (i = 0; i < 7 && centerstr->prev != NULL && !(!editwidth && centerstr->prev == sv->first && sv->first->s[0] == '@'); i++) { centerstr = centerstr->prev; if (selectFlag) selLineOffset++; } if (pos > strlen(centerstr->s)) pos = strlen(centerstr->s); updateflags = U_EDITAREA; break; case DKEY_PAGEDOWN: /* Page Down */ for (i = 0; i < 7 && centerstr->next != NULL; i++) { centerstr = centerstr->next; if (selectFlag) selLineOffset--; } if (pos > strlen(centerstr->s)) pos = strlen(centerstr->s); updateflags = U_EDITAREA; break; case DKEY_CTRL_C: case DKEY_CTRL_X: /* Copy to register */ if (selPos != -1) { stringnode *selStart = centerstr, *selEnd = centerstr; int selStartPos, selEndPos; selectionBounds bounds; if (selLineOffset > 0) { /* Other end of selection is below current line, move end down to meet it. */ selStartPos = pos; selEndPos = selPos; for (i = 0; i < selLineOffset; i++) if (selEnd->next != NULL) selEnd = selEnd->next; } else if (selLineOffset < 0) { /* Other end of selection is above current line, move end up to meet it. */ selStartPos = selPos; selEndPos = pos; for (i = 0; i > selLineOffset; i--) if (selStart->prev != NULL) selStart = selStart->prev; } else { /* Selection is only on current line: selStartPos gets the lesser of selPos & pos */ if (selPos > pos) { selStartPos = pos; selEndPos = selPos; } else { selStartPos = selPos; selEndPos = pos; } } bounds.startLine = selStart; bounds.endLine = selEnd; bounds.startPos = selStartPos; bounds.endPos = selEndPos; regyank('\"', bounds); } break; case DKEY_ESC: if (editwidth > EDITBOX_NOEDIT) done = EDITBOX_OK; else done = EDITBOX_CANCEL; break; } /* Keys pertaining to browsing only */ if (editwidth == EDITBOX_NOEDIT) { switch (key) { case DKEY_ENTER: done = EDITBOX_OK; break; } /* If movement is enabled... */ if (flags & EDITBOX_MOVEMENT) { switch (key) { case DKEY_BACKSPACE: done = EDITBOX_BACK; break; case DKEY_RIGHT: done = EDITBOX_FORWARD; break; case DKEY_LEFT: done = EDITBOX_BACKWARD; break; case DKEY_F1: done = EDITBOX_HELP; break; } } } /* Keys pertaining to editing only */ if (editwidth > EDITBOX_NOEDIT) { /* We are edititing! Yea! Fun time! */ switch (key) { case DKEY_NONE: break; /********** Movement ***********/ case DKEY_LEFT: /* Left Arrow */ if (pos > 0) pos--; else { /* Move to end of previous line (or current line) */ if (centerstr->prev != NULL) { centerstr = centerstr->prev; updateflags = U_EDITAREA; } pos = strlen(centerstr->s); if (selectFlag) selLineOffset++; } break; case DKEY_RIGHT: /* Right Arrow */ if (pos < strlen(centerstr->s)) pos++; else { /* Move to begining of next line (or current line) */ if (centerstr->next != NULL) { centerstr = centerstr->next; updateflags = U_EDITAREA; } pos = 0; if (selectFlag) selLineOffset--; } break; case DKEY_HOME: /* Home */ pos = 0; break; case DKEY_END: /* End */ pos = strlen(centerstr->s); break; case DKEY_UP: case DKEY_DOWN: case DKEY_PAGEUP: case DKEY_PAGEDOWN: case DKEY_CTRL_C: /* Avoid inserting these keys */ break; /********** Insert & Delete ***********/ case DKEY_INSERT: /* Insert */ insertflag = !insertflag; updateflags = U_PANEL; break; case DKEY_DELETE: /* Delete */ if (pos < strlen(centerstr->s)) { for (i = pos; i < strlen(centerstr->s); i++) centerstr->s[i] = centerstr->s[i+1]; updateflags = U_CENTER; } else if (strlen(centerstr->s) == 0 && !(sv->first == sv->last)) { /* This string is empty: destroy */ sv->cur = centerstr; deletestring(sv); centerstr = sv->cur; pos = strlen(centerstr->s); updateflags = U_EDITAREA; } else if (centerstr->next != NULL) { if (strlen(centerstr->next->s) == 0) { /* Next string is empty: destroy */ sv->cur = centerstr->next; deletestring(sv); updateflags = U_BOTTOM; } else if (strlen(centerstr->s) + 1 < wrapwidth) { /* merge lines; wordwrap */ i = strlen(centerstr->s); if (centerstr->s[i-1] != ' ' && centerstr->next->s[0] != ' ') { /* add a space at the end */ centerstr->s[i] = ' '; centerstr->s[++i] = 0; } sv->cur = centerstr->next; tmpstr = removestring(sv); sv->cur = centerstr; pos = wordwrap(sv, tmpstr, i, -1, wrapwidth, editwidth); centerstr = sv->cur; free(tmpstr); updateflags = U_CENTER | U_BOTTOM | U_TOP; } } break; /****** ZOC Mode & Wordwrap settings **********/ case DKEY_ALT_Z: /* alt-z - toggle ZOC mode */ flags ^= EDITBOX_ZOCMODE; updateflags = U_PANEL | U_EDITAREA; break; case DKEY_ALT_MINUS: /* alt - */ if (wrapwidth > 10) wrapwidth--; else wrapwidth = editwidth; updateflags = U_PANEL; break; case DKEY_ALT_PLUS: /* alt + */ if (wrapwidth < editwidth) wrapwidth++; else wrapwidth = 10; updateflags = U_PANEL; break; /****** Help dialog ******/ case DKEY_F1: /* F1: help dialog */ /* Look for #command on current line for lookup in help */ i = pos; while (i > 0 && centerstr->s[i] != '#') i--; if (centerstr->s[i] == '#') { /* Copy the command onto tmpstr */ tmpstr = str_dup(centerstr->s + i + 1); for (i = 0; tmpstr[i] != ' ' && tmpstr[i] != '\0'; i++) ; tmpstr[i] = '\0'; if (zztoopFindCommand(tmpstr) == -1) { /* If it's not a valid command, don't bother looking for it */ tmpstr[0] = '\0'; } /* Display the help file with the command as the topic */ helpsectiontopic("langref", tmpstr, d); free(tmpstr); } else { /* Display the oop help file */ helpsectiontopic("langref", NULL, d); } updateflags = U_ALL; break; /********* ZZM Testing ********************/ case DKEY_CTRL_T: case DKEY_ALT_T: sv->cur = centerstr; testMusic(sv, key == DKEY_CTRL_T, editwidth, flags, d); updateflags = U_EDITAREA; break; /********* File access operations *********/ case DKEY_ALT_O: /* alt+o: open file */ case DKEY_ALT_I: /* alt+i: insert file */ { stringvector filetypelist; char* filename = NULL; initstringvector(&filetypelist); pushstring(&filetypelist, "*.zoc"); pushstring(&filetypelist, "*.txt"); pushstring(&filetypelist, "*.hlp"); pushstring(&filetypelist, "*.zzm"); pushstring(&filetypelist, "*.*"); if (editbox("Select A File Type", &filetypelist, 0, 1, d) == 27) { updateflags = U_EDITAREA | U_TITLE; break; } if (filetypelist.cur != NULL) filename = filedialog(".", filetypelist.cur->s + 2, (key == DKEY_ALT_O ? "Open ZZT Object Code (ZOC) File" : "Insert ZZT Object Code (ZOC) File"), FTYPE_ALL, d); if (filename != NULL && strlen(filename) != 0) { stringvector newsvector; newsvector = filetosvector(filename, wrapwidth, editwidth); if (newsvector.first != NULL) { if (key == DKEY_ALT_O) { strcpy(savefilename, filename); /* erase & replace sv */ deletestringvector(sv); *sv = newsvector; centerstr = sv->first; } else { /* insert newsvector before centerstr */ sv->cur = centerstr; if (sv->cur == sv->first) { /* first node */ sv->first = newsvector.first; sv->cur->prev = newsvector.last; newsvector.last->next = sv->cur; centerstr = newsvector.first; } else if (sv->cur->prev != NULL) { /* middle/end node */ newsvector.first->prev = sv->cur->prev; sv->cur->prev->next = newsvector.first; newsvector.last->next = sv->cur; sv->cur->prev = newsvector.last; centerstr = newsvector.first; } else { /* this code should be unreachable */ deletestringvector(&newsvector); } } /* esle alt-i */ } /* fi file selected */ } /* fi not empty */ free(filename); removestringvector(&filetypelist); } /* block */ updateflags = U_EDITAREA | U_TITLE | U_PANEL; break; case DKEY_ALT_S: /* alt-s: save to file */ { char* filename; filename = filenamedialog(savefilename, "", "Save Object Code As", 1, d); if (filename != NULL) { /* Save to the file */ svectortofile(sv, filename); /* Remember the file name */ strncpy(savefilename, filename, SAVEFILENAME_LEN - 1); savefilename[SAVEFILENAME_LEN - 1] = '\x0'; free(filename); } } updateflags = U_EDITAREA | U_PANEL | U_PANEL; break; case DKEY_ALT_M: /* alt-m: load .zzm music */ { char* filename; filename = filedialog(".", "zzm", "Choose ZZT Music (ZZM) File", FTYPE_ALL, d); if (filename != NULL) { stringvector zzmv; zzmv = filetosvector(filename, 80, 80); if (zzmv.first != NULL) { stringvector song; song = zzmpullsong(&zzmv, zzmpicksong(&zzmv, d)); if (song.first != NULL) { /* copy song into sv */ sv->cur = centerstr; for (song.cur = song.first; song.cur != NULL; song.cur = song.cur->next) { tmpstr = (char*) malloc(editwidth + 2); if (flags & EDITBOX_ZOCMODE) { strcpy(tmpstr, "#play "); strncat(tmpstr, song.cur->s, editwidth - 6); } else { strncpy(tmpstr, song.cur->s, editwidth); } preinsertstring(sv, tmpstr); } deletestringvector(&song); } deletestringvector(&zzmv); } } free(filename); } updateflags = U_EDITAREA | U_TITLE | U_PANEL; break; case DKEY_CTRL_R: /* ctrl-r: rip music */ { /* This is mostly worthless just now */ stringvector ripped; sv->cur = centerstr; ripped = zzmripsong(sv, 4); scrolldialog("Ripped Music", &ripped, d); deletestringvector(&ripped); updateflags = U_ALL; } break; /******** Cut operation *********/ case DKEY_CTRL_DELETE: /* ctrl-delete: clear selected text */ case DKEY_CTRL_X: /* ctrl-x: cut selected text */ sv->cur = centerstr; /* Destroy the meat of the selection */ if (selPos != -1) { int selStartPos, selEndPos, offset = selLineOffset; if (offset < 0) { /* Other end is above centerstr */ offset = -offset; selStartPos = selPos; selEndPos = pos; /* Move back to top of selection */ for (i = 0; i < offset; i++) { if (sv->cur->prev != NULL) sv->cur = sv->cur->prev; } /* Change centerstr to reflect the top of the selection */ centerstr = sv->cur; } else { selStartPos = pos; selEndPos = selPos; } if (offset == 0) { /* Only one line to work with */ int deltaPos; /* Reverse selStartPos and selEndPos if start is bigger */ if (selStartPos > selEndPos) { int swapPos = selStartPos; selStartPos = selEndPos; selEndPos = swapPos; } /* Remove everything between selStartPos and selEndPos */ deltaPos = selEndPos - selStartPos; for (i = selEndPos; i < strlen(centerstr->s); i++) { centerstr->s[i - deltaPos] = centerstr->s[i]; } centerstr->s[i - deltaPos] = '\0'; /* Move the cursor to the starting position of the cut */ pos = selStartPos; } else { /* Multiple lines were involved */ /* Remove lines following the first line of the block */ sv->cur = centerstr->next; for (i = 0; i + 1 < offset; i++) { deletestring(sv); } /* Remove the string at the end of the cut */ sv->cur = centerstr->next; tmpstr = removestring(sv); /* Remove first selEndPos chars from end string */ for (i = 0; i < (strlen(tmpstr) - selEndPos); i++) tmpstr[i] = tmpstr[i+selEndPos]; tmpstr[i] = 0; /* Truncate the string at the start of the cut */ sv->cur = centerstr; sv->cur->s[selStartPos] = '\0'; /* Wordwrap the end string onto this one */ /* The -1 tells wordwrap to track the cursor position at * the beginning of tmpstr. Negative tracking values should * be used only by wordwrap for internal purposes, but * necessity warrents in this case. vv */ pos = wordwrap(sv, tmpstr, selStartPos, -1, wrapwidth, editwidth); centerstr = sv->cur; /* Follow cursor */ /* tmpstr is our responsability */ free(tmpstr); } updateflags = U_EDITAREA; } break; case DKEY_CTRL_V: /* ctrl-v: paste register */ sv->cur = centerstr; pos = regput('\"', sv, pos, wrapwidth, editwidth); centerstr = sv->cur; updateflags = U_EDITAREA; break; case DKEY_TAB: /* Tab */ /* determine tab amount */ j = 4 - (pos % 4); if (strlen(centerstr->s) + j < (wrapwidth?wrapwidth:editwidth)) { /* insert if there is room */ for (i = strlen(centerstr->s) + j; i > pos; i--) centerstr->s[i] = centerstr->s[i-j]; for (i = 0; i < j; i++) centerstr->s[pos++] = ' '; updateflags = U_CENTER; } else { /* no room; wordwrap */ for (i = 0; i < j; i++) strbuf[i] = ' '; strbuf[i] = 0; sv->cur = centerstr; pos = wordwrap(sv, strbuf, pos, pos, wrapwidth, editwidth); centerstr = sv->cur; updateflags = U_EDITAREA; } break; case DKEY_ENTER: /* Enter */ tmpstr = (char*) malloc(editwidth + 2); for (i = pos, j = 0; i < strlen(centerstr->s); i++, j++) tmpstr[j] = centerstr->s[i]; centerstr->s[pos] = 0; tmpstr[j] = 0; sv->cur = centerstr; insertstring(sv, tmpstr); centerstr = centerstr->next; pos = 0; updateflags = U_EDITAREA; break; case DKEY_BACKSPACE: /* Backspace */ if (pos > 0) { for (i = pos - 1; i < strlen(centerstr->s); i++) centerstr->s[i] = centerstr->s[i+1]; pos--; updateflags = U_CENTER; } else if (centerstr->prev != NULL) { if (strlen(centerstr->s) == 0) { /* remove current line & move up & to eol */ sv->cur = centerstr; centerstr = centerstr->prev; pos = strlen(centerstr->s); deletestring(sv); updateflags = U_TOP | U_CENTER; } else if (strlen(centerstr->prev->s) == 0) { /* remove previous line */ sv->cur = centerstr->prev; deletestring(sv); /* update center too, in case @ line has moved to top now */ updateflags = U_TOP | U_CENTER; } else if (strlen(centerstr->prev->s) + 1 < wrapwidth) { /* merge lines; wordwrap */ i = strlen(centerstr->prev->s); if (centerstr->prev->s[i-1] != ' ' && centerstr->s[0] != ' ') { /* add a space at the end */ centerstr->prev->s[i] = ' '; centerstr->prev->s[i + 1] = 0; } sv->cur = centerstr->prev; tmpstr = removestring(sv); sv->cur = centerstr; pos = wordwrap(sv, tmpstr, 0, 0, wrapwidth, editwidth); centerstr = sv->cur; free(tmpstr); updateflags = U_EDITAREA; } } break; case DKEY_CTRL_Y: /* ctrl-y: delete line */ pos = 0; sv->cur = centerstr; if (centerstr->next != NULL) { centerstr = centerstr->next; deletestring(sv); updateflags = U_CENTER | U_BOTTOM; } else if (centerstr->prev != NULL) { centerstr = centerstr->prev; deletestring(sv); updateflags = U_TOP | U_CENTER; } else { centerstr->s[0] = 0; updateflags = U_CENTER; } break; case DKEY_ESC: /* escape when done */ done = EDITBOX_OK; break; case DKEY_CTRL_A: /* ctrl-a: insert ascii char/decimal-value */ strcpy(strbuf, centerstr->s); updateflags = U_EDITAREA; if (str_equ(strbuf, "#char", STREQU_UNCASE | STREQU_RFRONT)) { /* append dec value for ascii char */ sscanf(strbuf + 5, "%d", &selChar); key = charselect(d, selChar); if (key == -1) break; selChar = key; centerstr->s[5] = ' '; centerstr->s[6] = 0; /* change c to a string */ sprintf(strbuf, "%d", selChar); strcat(centerstr->s, strbuf); pos = strlen(centerstr->s); updateflags = U_EDITAREA; break; } else { /* ctrl-a: insert ascii char */ key = charselect(d, selChar); if (key == -1) break; else selChar = key; } /* no break; we just changed the key & want to insert it */ default: key = key & 0xFF; /* Clear all but the first 8 bits */ /* Normal/weird char for insert/replace */ if (insertflag) { /* insert */ if (strlen(centerstr->s) < (wrapwidth?wrapwidth:editwidth)) { /* insert if there is room */ for (i = strlen(centerstr->s) + 1; i > pos; i--) centerstr->s[i] = centerstr->s[i-1]; centerstr->s[pos++] = key; updateflags |= U_CENTER; } else if (wrapwidth) { /* no room; wordwrap */ strbuf[0] = key; strbuf[1] = 0; sv->cur = centerstr; pos = wordwrap(sv, strbuf, pos, pos, wrapwidth, editwidth); centerstr = sv->cur; updateflags = U_EDITAREA; } } else { /* easy replace */ if (centerstr->s[pos] == 0) { if (strlen(centerstr->s) < (wrapwidth?wrapwidth:editwidth)) { centerstr->s[pos+1] = 0; centerstr->s[pos++] = key; updateflags |= U_CENTER; } else if (wrapwidth) { /* no room; wordwrap */ strbuf[0] = key; strbuf[1] = 0; sv->cur = centerstr; pos = wordwrap(sv, strbuf, pos, pos, wrapwidth, editwidth); centerstr = sv->cur; updateflags = U_EDITAREA; } } else { centerstr->s[pos++] = key; updateflags |= U_CENTER; } } /* esle replace */ break; } } /* esle in editmode */ /* if the shift key is not still held down and we are selecting, * then stop select mode */ /* also stop if true ASCII key was pressed and selection is active */ if ((!selectFlag && selPos != -1) || (key < 0x7F && selPos != -1)) { selPos = -1; selLineOffset = 0; updateflags |= U_EDITAREA; } } /* elihw */ sv->cur = centerstr; return done; }
/* wordwrap * purpose: Inserts string into current string of svector, wordwrapping if * necessary. * args: sv: stringvector to manipulate * str: string to insert in sv->cur->s * inspos: where in sv to insert str * pos: cursor position in sv->cur->s to track; a negative value * indicates that -pos - 1 is position in str * wrapwidth: at what cursor position to wrap to next line * editwidth: maximum width of a line in sv * return: new location of pos. sv->cur is changed to reflect line on which * pos now resides. * * NOTE: str will not be modified nor free()d in any way. */ int wordwrap(stringvector * sv, char *str, int inspos, int pos, int wrapwidth, int editwidth) { int i, j, k; /* general counters */ char *longstr; /* Combination of sv->cur->s & str */ int longlen; /* Length of longstr */ int newpos; /* new position after insert */ char *newstr; /* new string for next line */ /* check for bad data */ if (sv->cur == NULL || sv->cur->s == NULL || wrapwidth > editwidth || editwidth < 2 || inspos > strlen(sv->cur->s)) return -1; /* first determine longlen and allocate longstr */ longlen = strlen(sv->cur->s) + strlen(str); longstr = (char *) malloc(longlen + 2); memset(longstr, 0, longlen + 2); /* fill longstr * * i: position in longstr * j: position in sv->cur->s * k: position in str */ /* fill from sv until inspos */ for (i = 0; i < inspos; i++) longstr[i] = sv->cur->s[i]; j = i; /* fill from str until end of str */ for (k = 0; str[k] != 0; k++, i++) longstr[i] = str[k]; /* fill from sv until end */ for (; i < longlen; i++, j++) longstr[i] = sv->cur->s[j]; /* cap longstr */ longstr[i] = 0; /* determine location of newpos */ if (pos >= inspos) newpos = pos + strlen(str); else if (pos < 0) newpos = inspos - pos - 1; if (longlen <= wrapwidth) { /* no need to wordwrap; we can just copy longstr over sv->cur->s */ strcpy(sv->cur->s, longstr); /* don't forget to free longstr before leaving */ free(longstr); return newpos; } /* we need to find the first space before wrapwidth * * i: position in longstr * j: position of last identified space */ j = -1; for (i = 0; i < wrapwidth; i++) if (longstr[i] == ' ') j = i; if (j == -1) { /* no space was found before wrap; reject insert */ /* longstr is no longer needed */ free(longstr); return pos; } /* make newpos the negative differance of location of space and newpos, * if it belongs on next line */ if (newpos > j) newpos = j - newpos; /* set newstr to location of string after the space & cap longstr at space */ newstr = longstr + j + 1; longstr[j] = 0; /* replace sv->cur->s with shortened longstr */ strcpy(sv->cur->s, longstr); /* finally: wrap onto next line or new line */ if (sv->cur->next == NULL || strlen(sv->cur->next->s) == 0 || sv->cur->next->s[0] == '#' || sv->cur->next->s[0] == '/' || sv->cur->next->s[0] == '?' || sv->cur->next->s[0] == ':' || sv->cur->next->s[0] == '!' || sv->cur->next->s[0] == '$' || sv->cur->next->s[0] == '\'' || sv->cur->next->s[0] == '@' || sv->cur->next->s[0] == ' ') { /* next line either does not exist, is blank, is a zoc command, * or is indented; so, we create a new, blank line to wordwrap onto */ char *newnode; newnode = (char *) malloc(editwidth + 2); newnode[0] = 0; insertstring(sv, newnode); } else { /* we can put text at the beginning of the next line; append a space * to end of newstr in preparation. */ i = strlen(newstr); newstr[i++] = ' '; newstr[i] = 0; } /* it is now okay to put text at the beginning of the next line */ /* recursively insert newstr at beginning of next line */ if (newpos < 0) { /* cursor should be tracked on next line */ sv->cur = sv->cur->next; newpos = wordwrap(sv, newstr, 0, newpos, wrapwidth, editwidth); } else { stringnode * nodeptr = sv->cur; sv->cur = sv->cur->next; wordwrap(sv, newstr, 0, 0, wrapwidth, editwidth); sv->cur = nodeptr; } free(longstr); return newpos; }